Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import joplin from "api";
import { NewNote } from "./parser";
import { NewNote, NOTE_ID_PLACEHOLDER } from "./parser";
import { getSelectedFolder } from "./utils/folders";
import { applyTagToNote, getAnyTagWithTitle } from "./utils/tags";
import { ApplyTagsWhileInsertingSetting } from "./settings";
Expand All @@ -10,15 +10,22 @@ export enum TemplateAction {
InsertText = "insertText"
}


const performInsertTextAction = async (template: NewNote) => {
await joplin.commands.execute("insertText", template.body);
// When inserting into an existing note, resolve {{ note_id }} to the
// currently selected note's ID, since there is no "new note" being created.
const currentNote = await joplin.workspace.selectedNote();
const body = template.body.includes(NOTE_ID_PLACEHOLDER)
? template.body.split(NOTE_ID_PLACEHOLDER).join(currentNote.id)
: template.body;

await joplin.commands.execute("insertText", body);

const applyTags = await ApplyTagsWhileInsertingSetting.get()
if (applyTags) {
const noteId = (await joplin.workspace.selectedNote()).id;
for (const tag of template.tags) {
const tagId = (await getAnyTagWithTitle(tag)).id;
await applyTagToNote(tagId, noteId);
await applyTagToNote(tagId, currentNote.id);
}
}
}
Expand All @@ -32,13 +39,21 @@ const performNewNoteAction = async (template: NewNote, isTodo: 0 | 1) => {
}

const note = await joplin.data.post(["notes"], null, notePayload);

// Post-process: replace the note_id placeholder with the actual note ID
if (template.body.includes(NOTE_ID_PLACEHOLDER)) {
const updatedBody = template.body.split(NOTE_ID_PLACEHOLDER).join(note.id);
await joplin.data.put(["notes", note.id], null, { body: updatedBody });
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This replaces the placeholder in the body, but note_id is also available in the title/tags context (via getDefaultContext() in parser.ts). So if someone writes template_title: "Note {{ note_id }}", the title ends up as "Note __JOPLIN_TEMPLATE_NOTE_ID__" and never gets corrected.

Either extend this put to also update the title, or scope note_id so it's only injected into the body context (parser.ts:275) rather than the shared getDefaultContext().

}

await joplin.commands.execute("openNote", note.id);
for (const tag of template.tags) {
const tagId = (await getAnyTagWithTitle(tag)).id;
await applyTagToNote(tagId, note.id);
}
}


export const performAction = async (action: TemplateAction, template: NewNote): Promise<void> => {
switch (action) {
case TemplateAction.InsertText:
Expand Down
16 changes: 15 additions & 1 deletion src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import { CustomVariable } from "./variables/types/base";
import { setTemplateVariablesView } from "./views/templateVariables";
import { HelperFactory } from "./helpers";

// Unique placeholder that Handlebars will output for {{ note_id }}.
// actions.ts replaces this with the real note ID after the note is created.
export const NOTE_ID_PLACEHOLDER = "__JOPLIN_TEMPLATE_NOTE_ID__";

// Can't use import for this library because the types in the library
// are declared incorrectly which result in typescript errors.
// Reference -> https://github.com/jxson/front-matter/issues/76
Expand Down Expand Up @@ -281,9 +285,19 @@ export class Parser {
const templateBody = processedTemplate.body;
const compiledTemplate = Handlebars.compile(templateBody);

// note_id is intentionally excluded from the shared context above
// because it is only meaningful in the note body (it resolves to a
// placeholder that actions.ts swaps for the real ID after creation).
// Including it in the title/tags context would leave the placeholder
// string unreplaced there.
const bodyContext = {
...context,
note_id: NOTE_ID_PLACEHOLDER
};

return {
...newNoteMeta,
body: compiledTemplate(context)
body: compiledTemplate(bodyContext)
};
} catch (err) {
console.error("Error in parsing template.", err);
Expand Down
Loading