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
6 changes: 3 additions & 3 deletions helpers/NPFrontMatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -770,9 +770,9 @@ export function getSanitizedFmParts(noteText: string, removeTemplateTagsInFM?: b
// logError(`Frontmatter getAttributes error. COULD NOT SANITIZE CONTENT: "${error.message}". Returning empty values for this note: "${JSON.stringify(noteText)}"`)

// Add debug logging to understand why fm library failed
logDebug(pluginJson, `getSanitizedFmParts: fm library failed with error: ${error.message}`)
logDebug(pluginJson, `getSanitizedFmParts: Original text: ${noteText.substring(0, 200)}...`)
logDebug(pluginJson, `getSanitizedFmParts: Sanitized text: ${sanitizedText.substring(0, 200)}...`)
// logDebug(pluginJson, `getSanitizedFmParts: fm library failed with error: ${error.message}`)
// logDebug(pluginJson, `getSanitizedFmParts: Original text: ${noteText.substring(0, 200)}...`)
// logDebug(pluginJson, `getSanitizedFmParts: Sanitized text: ${sanitizedText.substring(0, 200)}...`)

// When fm library fails, we need to manually extract the body and attributes
// Check if the text has frontmatter structure (starts with --- and has another ---)
Expand Down
7 changes: 5 additions & 2 deletions helpers/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { logDebug } from './dev'
import { showMessageYesNo, showMessage } from './userInput'
import { getFolderFromFilename } from '@helpers/folders'

/**
* Run Editor.save() if active Editor is dirty and needs saving
Expand Down Expand Up @@ -37,13 +38,15 @@ export async function checkAndProcessFolderAndNewNoteTitle(templateNote: TNote,
const isEditorEmpty = editorIsEmpty()
const theFolder = frontmatterAttributes?.folder?.trim() || ''
const newNoteTitle = frontmatterAttributes?.newNoteTitle?.trim() || ''
logDebug(`checkAndProcessFolderAndNewNoteTitle starting: templateNote:"${templateNote?.title || ''}", frontmatterAttributes:${JSON.stringify(frontmatterAttributes)}`)
if (theFolder.length > 0 || newNoteTitle.length > 0) {
if (isEditorEmpty) {
logDebug(`insertNoteTemplate: template has folder attribute, so moving empty note to trash and creating a new note in the folder`)
logDebug(`insertNoteTemplate: template has folder:"${theFolder}", newNoteTitle:"${newNoteTitle}", so moving empty note to trash and creating a new note in the folder`)
// invoke the template with the folder attribute
const emptyNoteFilename = Editor.filename
const templateTitle = templateNote?.title
const argsArray = [templateTitle, theFolder, newNoteTitle]
const folderToUse = theFolder.length > 0 ? theFolder : getFolderFromFilename(Editor.filename)
const argsArray = [templateTitle, folderToUse === '/' ? '' : folderToUse, newNoteTitle, frontmatterAttributes]
await DataStore.invokePluginCommandByName('templateNew', 'np.Templating', argsArray)
// move the empty note to the trash
await DataStore.moveNote(emptyNoteFilename, '@Trash')
Expand Down
4 changes: 4 additions & 0 deletions np.MeetingNotes/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

See Plugin [README](https://github.com/NotePlan/plugins/blob/main/np.MeetingNotes/README.md) for details on available commands and use case.

## [2.0.1] - 2025-08-02 @dwertheimer

- Add override when inserting a template into a blank note but template has folder or newNoteTitle attribute

## [2.0.0] - 2025-05-13 @dwertheimer

- Add <current> to append/prepend frontmatter tag
Expand Down
2 changes: 1 addition & 1 deletion np.MeetingNotes/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"noteplan.minAppVersion": "3.5.0",
"plugin.id": "np.MeetingNotes",
"plugin.name": "✍️ Meeting Notes",
"plugin.version": "2.0.0",
"plugin.version": "2.0.1",
"plugin.description": "Create Meeting Notes from events using templates.",
"plugin.author": "NotePlan",
"plugin.dependencies": [],
Expand Down
8 changes: 7 additions & 1 deletion np.MeetingNotes/src/NPMeetingNotes.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ import { checkAndProcessFolderAndNewNoteTitle } from '@helpers/editor'
* @param {Date} dailyNoteDate -> (optional) Date of the daily note, if not set the current editor will be used
*/
export async function insertNoteTemplate(origFileName: string, dailyNoteDate: Date, timeframe: string, shouldReplaceContent: boolean = false): Promise<void> {
logDebug(pluginJson, 'insertNoteTemplate')
logDebug(
pluginJson,
`insertNoteTemplate starting: origFileName:"${origFileName}", dailyNoteDate:"${dailyNoteDate?.toLocaleDateString() || ''}", timeframe:"${
timeframe || ''
}", shouldReplaceContent:"${String(shouldReplaceContent)}"`,
)
const templateFilename = await chooseTemplateIfNeeded(origFileName, false)
if (!templateFilename) {
return
Expand All @@ -44,6 +49,7 @@ export async function insertNoteTemplate(origFileName: string, dailyNoteDate: Da
const { frontmatterBody: templateBody, frontmatterAttributes } = await DataStore.invokePluginCommandByName('renderFrontmatter', 'np.Templating', [templateContent])

// Check if the template wants the note to be created in a folder (or with a new title) and if so, move the empty note to the trash and create a new note in the folder
logDebug(pluginJson, `insertNoteTemplate: about to checkAndProcessFolderAndNewNoteTitle`)
if (templateNote && (await checkAndProcessFolderAndNewNoteTitle(templateNote, frontmatterAttributes))) return

logDebug(pluginJson, `render() template with frontmatterAttributes: [${Object.keys(frontmatterAttributes).join(', ')}]`)
Expand Down
3 changes: 3 additions & 0 deletions np.Templating/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

See Plugin [Documentation](https://noteplan.co/templates/docs) for details on available commands and use case.

## [2.0.12] 2025-08-02 @dwertheimer
- Fix templateNew to handle blank meeting note edge case

## [2.0.11] 2025-07-31 @dwertheimer
- Fix getFolder to handle <select XXX> and to honor folder attribute in quick-note templates

Expand Down
4 changes: 4 additions & 0 deletions np.Templating/lib/rendering/templateProcessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ import { log, logError, logDebug, logWarn, clo } from '@helpers/dev'
export function logProgress(stepDescription: string, templateData: string, sessionData?: Object, userOptions?: Object): void {
const verbose = Boolean(sessionData && sessionData.verboseLog)
logDebug(`🔄 TEMPLATE PROCESSOR: ${stepDescription}${verbose ? ' (verboseLog)' : ''}`)
if (!templateData) {
logDebug(`🔄 TEMPLATE PROCESSOR PROBLEM FYI: logProgress called with empty templateData`)
return
}

// Only log template data if verbose mode is on or if it's a key step
const isStart = stepDescription.includes('START')
Expand Down
13 changes: 8 additions & 5 deletions np.Templating/lib/support/modules/FrontmatterModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default class FrontmatterModule {

isFrontmatterTemplate(templateData: string): boolean {
// First check if the template has the frontmatter structure (starts with --- and has another ---)
if (!templateData.startsWith('---')) return false
const lines = templateData.split('\n')
if (lines.length >= 2 && lines[0].trim() === '---') {
// Find the second --- separator
Expand All @@ -30,12 +31,14 @@ export default class FrontmatterModule {
}
}
}

// Fallback to the original method for edge cases
const parts = getSanitizedFmParts(templateData)
const hasAttributes = parts?.attributes && Object.keys(parts.attributes).length > 0
logDebug(pluginJson, `FrontmatterModule.isFrontmatterTemplate: Fallback check - hasAttributes=${String(hasAttributes)}`)
return hasAttributes
// dbw note 2025-08-02: I can't imagine why this would ever be needed, so commenting out for now
// FIXME: remove this in the future if no edge cases are discovered
// const parts = getSanitizedFmParts(templateData)
// const hasAttributes = parts?.attributes && Object.keys(parts.attributes).length > 0
// logDebug(pluginJson, `FrontmatterModule.isFrontmatterTemplate: Fallback check - hasAttributes=${String(hasAttributes)} templateData:"${templateData}"`)
// return hasAttributes
return false
}

getFrontmatterBlock(templateData: string): string {
Expand Down
4 changes: 2 additions & 2 deletions np.Templating/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"noteplan.minAppVersion": "3.9.10",
"plugin.id": "np.Templating",
"plugin.name": "📒 Templating",
"plugin.version": "2.0.11",
"plugin.lastUpdateInfo": "2.0.11: fix getFolder to handle <select XXX> and to honor folder attribute in quick-note templates",
"plugin.version": "2.0.12",
"plugin.lastUpdateInfo": "2.0.12: fix templateNew to handle blank meeting note edge case",
"plugin.description": "Templating Plugin for NotePlan",
"plugin.author": "Mike Erickson ( codedungeon)",
"plugin.dependencies": [],
Expand Down
33 changes: 28 additions & 5 deletions np.Templating/src/Templating.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export async function templateInsert(templateName: string = ''): Promise<void> {
const { frontmatterBody, frontmatterAttributes } = await NPTemplating.renderFrontmatter(templateData)

// Check if the template wants the note to be created in a folder (or with a new title) and if so, move the empty note to the trash and create a new note in the folder
logDebug(pluginJson, `templateInsert: about to checkAndProcessFolderAndNewNoteTitle`)
if (templateNote && (await checkAndProcessFolderAndNewNoteTitle(templateNote, frontmatterAttributes))) return

// $FlowIgnore
Expand Down Expand Up @@ -169,6 +170,7 @@ export async function templateAppend(templateName: string = ''): Promise<void> {
let { frontmatterBody, frontmatterAttributes } = await NPTemplating.renderFrontmatter(templateData)

// Check if the template wants the note to be created in a folder (or with a new title) and if so, move the empty note to the trash and create a new note in the folder
logDebug(pluginJson, `templateAppend: about to checkAndProcessFolderAndNewNoteTitle`)
if (templateNote && (await checkAndProcessFolderAndNewNoteTitle(templateNote, frontmatterAttributes))) return

// Create frontmatter object that includes BOTH the attributes AND the methods
Expand Down Expand Up @@ -287,13 +289,34 @@ export async function templateNew(templateTitle: string = '', _folder?: string,
const templateAttributes = await NPTemplating.getTemplateAttributes(templateData)

let folder = _folder ?? ''
let frontmatterBody, frontmatterAttributes
logDebug(
pluginJson,
`templateNew: before renderFrontmatter:\n\targs:${JSON.stringify(Object.keys(typeof args === 'string' ? {} : args))}\n\ttemplateAttributes:${JSON.stringify(
Object.keys(templateAttributes),
)}`,
)
// In the case we have been passed rendered arguments (e.g. from the /insert button that rendered the frontmatter already)
// if every property in templateAttributes is in args, then we can use args to render the template
const argsKeys = typeof args === 'object' ? Object.keys(args) : []
const templateAttributesKeys = Object.keys(templateAttributes)
logDebug(pluginJson, `templateNew: argsKeys:${JSON.stringify(argsKeys)}\ntemplateAttributesKeys:${JSON.stringify(templateAttributesKeys)}`)
const allArgsKeysAreInTemplateAttributes = templateAttributesKeys.length && argsKeys.length && templateAttributesKeys.every((key) => argsKeys.includes(key))
if (allArgsKeysAreInTemplateAttributes) {
//FIXMME: it is going down this path but the frontmatterBody is empty
frontmatterAttributes = typeof args === 'object' ? args : {}
frontmatterBody = new FrontmatterModule().body(templateData)
logDebug(pluginJson, `templateNew: after skipping renderFrontmatter:\nfrontmatterBody:"${frontmatterBody}"\nfrontmatterAttributes:${JSON.stringify(frontmatterAttributes)}`)
} else {
logDebug(pluginJson, `templateNew: about to renderFrontmatter`)
const { frontmatterBody: fBody, frontmatterAttributes: fAttributes } = await NPTemplating.renderFrontmatter(templateData, args)
frontmatterBody = fBody
frontmatterAttributes = { ...fAttributes, ...(typeof args === 'object' ? args : {}) }
}
logDebug(pluginJson, `templateNew: after renderFrontmatter:\nfrontMatterBody:"${frontmatterBody}"\nfrontMatterAttributes:${JSON.stringify(frontmatterAttributes, null, 2)}`)

let { frontmatterBody, frontmatterAttributes } = await NPTemplating.renderFrontmatter(templateData, args)
frontmatterAttributes = { ...frontmatterAttributes, ...(typeof args === 'object' ? args : {}) }

// select/choose is by default not closed because it could contain a folder name
// select/choose is by default not closed with > because it could contain a folder name
if (/<select|<choose|<current>/i.test(folder) || (!folder && frontmatterAttributes?.folder && frontmatterAttributes.folder.length > 0)) {
// dbw note: I'm not sure I understand the second part of this condition, but it's always been that way, so not changing it
folder = await NPTemplating.getFolder(frontmatterAttributes.folder, 'Select Destination Folder')
}

Expand Down
Loading