Sometimes I copy material from one note into another, or within a note. Because of its new place in the note, the headers need to be changed. E.g., in one place a sequence of headers might be:
A
A1
A2
B
B1
But once I copy this into a new section of note beginning
Lists starting with capital letters
I now need to “demote” everything:
Lists starting with capital letters
A
A1
A2
B
B1
Proposed solution
I would be great to be able to do this with a single hotkey rather than changign each heading manually.
Hi @JAndrews2, this is a very fair feature request IMHO. Just like we can tab and shift+tab outlines, we should be able to do the same with headings.
While we are waiting for an official feature like this, I wrote a little script to do it in the meantime. I’m just beginning to learn some javascript, so this was a fun exercise.
Script to promote/demote all headings in selection
<%*
const direction = 1;
// 1: Promote headings (make them bigger)
// -1: Demote headings (make smaller)
const editor = app.workspace.activeLeaf.view.editor;
let selection = editor.getSelection();
if (selection=="") {
// if there is no selection, set it to the current line instead
let l = editor.getCursor().line;
editor.setSelection({line: l, ch: 0}, {line: l, ch: 99});
selection = editor.getSelection();
}
/* Because this script is being called from Templater, the selection is automatically replaced with the text of this script before being executed and consumed. The next three lines reset the selection to what it was before execution. For some reason a timer of 0ms is sufficient for that. */
let cAnchor = editor.getCursor('anchor');
let cHead = editor.getCursor('head');
setTimeout(() => editor.setSelection(cAnchor, cHead), 0);
if (direction == 1)
editor.replaceSelection(selection.replace(/^#(#+) /gm, "$1 "));
else if (direction == -1)
editor.replaceSelection(selection.replace(/^#+ /gm, "#$&"));
%>
Create two new files in your template folder (specified in Templater settings)
Copy and paste the above script into each of the two files, and changeconst direction to -1 in only one of them (that will be your “demote”)
Enable those templates in “Hotkeys for templates” settings
Assign hotkeys to the command via Obsidian settings > Hotkeys
You could also set these up as macro choices in QuickAdd. A little more complicated with QuickAdd, but then you could avoid the strange setTimeout(... 0) that I don't fully understand.
And if someone can improve my code, all the better!
Demo
Sorry my custom css may make it a little harder to see what’s going on.
Hi @scwunch, I have been following the instructions you have given above, so I installed the two plugins, pasted the script into the two files in the template folder, and they looked jammed without all the line breaks, but I went ahead and run the templates anyway, but it only replaced whatever selection of text with the actual content of that template(which is the script itself). Is there any setting I need to toggle for the template to run as commands?
Basically, the plugin allows us to apply customized regex to highlighted text. This is convenient for some tasks.
Here are the steps to promote/demote all selected headers.
Install the plugin
Copy below code to clipboard
Click “Import patterns from clipboard” in Apply Patterns's option page.
Then enjoy the solution
highlight any text range
trigger “Apply Patterns: Apply patterns to selection”, you will see two commands “refactor: increase heading level” and “refactor: decrease heading level”
Brilliant! Just what the doctor ordered. Hopefully it gets baked in the core, one fine day. (He said, with an already-overflowing plate and a mouthful of food.)
Another solution is to place multiple cursors (alt+click) on each header, go to the beginning of the line using the keyboard key Home and hit # to demote, or hit Delete to promote!
You can also create the multiple cursors with more ease using Advanced Cursors (Obsidian Store, GitHub).
and another another solution: use the plugin obsidian-linter:
in my case I head many H5s under one H4 which I had to change to a H3 (and with it all the belonging H5s).
I only had to change the H4 to H3 and the linter automatically changed all lower H5s to H4s.