Skip to content
3 changes: 3 additions & 0 deletions jgclark.NoteHelpers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ Templates should normally end with a linefeed character (`\n`).

## History

### v0.9.2, 13.6.2021
- change: write text offscreen and ask user if they want to open newly created file

### v0.9.0, 12.6.2021
- [add]: **/nns** command to add a new note from selection (and leave link to it in its place) (@dwertheimer)

Expand Down
116 changes: 92 additions & 24 deletions jgclark.NoteHelpers/noteHelpers.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// @flow
// @ flow
//--------------------------------------------------------------------------------------------------------------------
// Note Helpers plugin for NotePlan
// Jonathan Clark & Eduard Metzger
// /nns by @dwertheimer
// v0.9.0, 1.6.2021
// v0.9.2, 1.6.2021
//--------------------------------------------------------------------------------------------------------------------

// Globals
Expand Down Expand Up @@ -65,15 +65,22 @@ async function showMessage(message, confirmTitle = 'OK') {
return await CommandBar.showOptions([confirmTitle], message)
}

// Show feedback Yes/No Question via Command Bar (@dwertheimer)
async function showMessageYesNo(message, choicesArray = ['Yes', 'No']) {
const answer = await CommandBar.showOptions(choicesArray, message)
return choicesArray[answer.index]
}

// Find a unique note title/filename so backlinks can work properly (@dwertheimer)
function getUniqueNoteTitle(title) {
let i = 0,
res = []
res = [],
newTitle = title
while (++i === 1 || res.length > 0) {
newtitle = i === 1 ? title : `${title} ${i}`
res = DataStore.projectNoteByTitle(newtitle,true,false)
newTitle = i === 1 ? title : `${title} ${i}`
res = DataStore.projectNoteByTitle(newTitle, true, false)
}
return newtitle
return newTitle
}

//------------------------------------------------------------------
Expand Down Expand Up @@ -194,29 +201,64 @@ function setTitleFromYAML() {
}
globalThis.setTitleFromYAML = setTitleFromYAML

// Start Testing/debugging here
async function noteOpener(fullPath, desc, useProjNoteByFilename = true) {
console.log(
`\tAbout to open filename: "${fullPath}" (${desc}) using ${
useProjNoteByFilename ? 'projectNoteByFilename' : 'noteByFilename'
}`,
)
const newNote = (await useProjNoteByFilename)
? DataStore.projectNoteByFilename(fullPath)
: DataStore.noteByFilename(fullPath, 'Notes')
if (newNote) {
console.log(`\t\tWorked! ${fullPath} (${desc} version) `)
} else {
console.log(
`\t\tDidn't work! ${
useProjNoteByFilename ? 'projectNoteByFilename' : 'noteByFilename'
} returned ${newNote}`,
)
}
return newNote
}

//------------------------------------------------------------------
// @dwertheimer based on @jgclark's newNote
// Create new note from currently selected text
// and (optionally) leave backlink to it where selection was
async function newNoteFromSelection() {
const { selectedLinesText, selectedText } = Editor
console.log('\nnewNoteFromSelection (running):')
const version = `0.9.2`
console.log(`Running v${version}`)
const { selectedLinesText, selectedText, selectedParagraphs } = Editor
console.log(
`\nnewNoteFromSelection (running v${version}) ${selectedParagraphs.length} selected:`,
)
let currentFolder = ''

if (selectedLinesText.length && selectedText !== '') {
// Get title for this note
const stripHashes = /^\s*(#)* *(.*)/
const firstLineArray = stripHashes.exec(selectedLinesText[0])
const strippedFirstLine =
firstLineArray.length === 3 ? firstLineArray[2] : ''
console.log(
`\t1st Para Type = ${selectedParagraphs[0].type} = "${selectedParagraphs[0].content}"`,
)
// const stripHashes = /^\s*(#)* *(.*)/
// const firstLineArray = stripHashes.exec(selectedLinesText[0])
// const strippedFirstLine =
// firstLineArray.length === 3 ? firstLineArray[2] : ''

const isTextContent =
['title', 'text', 'empty'].indexOf(selectedParagraphs[0].type) >= 0
const strippedFirstLine = selectedParagraphs[0].content
let title = await CommandBar.showInput(
'Title of new note ([enter] to use text below)',
strippedFirstLine,
)
// If user just hit [enter], then use the first line as suggested
if (!title) {
title = strippedFirstLine
selectedLinesText.shift()
if (isTextContent) {
selectedLinesText.shift()
}
}
const movedText = selectedLinesText.join('\n')
const uniqueTitle = getUniqueNoteTitle(title)
Expand All @@ -235,30 +277,56 @@ async function newNoteFromSelection() {
// no Folders so go to root
currentFolder = '/'
}
console.log(`\tcurrentFolder=${currentFolder}`)

if (title) {
// Create new note in the specific folder
const origFile = Editor.note.title || Editor.note.filename // Calendar notes have no title
// const origFileType = Editor.note.type //either "Notes" or "Calendar"
console.log(`\torigFile:${origFile}`)
const filename = (await DataStore.newNote(title, currentFolder)) ?? ''
console.log(`\tnewNote returned Filename:${filename}`)

const fullPath = `${
currentFolder !== '/' ? `${currentFolder}/` : ''
}${filename}`

const filename = DataStore.newNote(title, currentFolder) ?? ''
// This question needs to be here after newNote and before noteOpener
// to force a cache refresh after newNote. This API bug will eventually be fixed.
const iblq = await CommandBar.showOptions(
['Yes', 'No'],
'Insert link to new file where selection was?',
)
const insertBackLink = iblq.index === 0
if (Editor.replaceSelectionWithText) {
// for compatibility, make sure the function exists

const newNote = await noteOpener(fullPath, 'no leading slash')

if (newNote) {
console.log(`\tnewNote=${newNote}\n\t${newNote.title}`)
console.log(`\tcontent=${newNote.content}`)

const insertBackLink = iblq.index === 0
if (Editor.replaceSelectionWithText) {
// for compatibility, make sure the function exists
if (insertBackLink) {
Editor.replaceSelectionWithText(`[[${title}]]`)
} else {
Editor.replaceSelectionWithText(``)
}
}

newNote.appendParagraph(movedText, 'empty')
if (insertBackLink) {
Editor.replaceSelectionWithText(`[[${title}]]`)
} else {
Editor.replaceSelectionWithText(``)
newNote.appendParagraph(`^^^ Moved from [[${origFile}]]:`, 'text')
}
if (
(await showMessageYesNo('New Note created. Open it now?')) === 'Yes'
) {
await Editor.openNoteByFilename(fullPath)
}
} else {
console.log(`\tCould not open file: "${fullPath}"`)
showMessage(`\tCould not open file ${fullPath}`)
}
await Editor.openNoteByFilename(filename)
if (insertBackLink)
Editor.note.appendParagraph(`From [[${origFile}]]:`, 'empty')
Editor.note.appendParagraph(movedText, 'empty')
} else {
console.log('\tError: undefined or empty title')
}
Expand Down
2 changes: 1 addition & 1 deletion jgclark.NoteHelpers/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"plugin.icon": "",
"plugin.author": "Jonathan Clark & Eduard Metzger",
"plugin.url": "https://github.com/NotePlan/plugins/tree/main/jgclark.NoteHelpers/",
"plugin.version": "0.9.0",
"plugin.version": "0.9.2",
"plugin.changelog": "See plugin README.md",
"plugin.dependencies": [],
"plugin.script": "noteHelpers.js",
Expand Down