1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 09:46:22 +00:00

Create Markdown TOC at current cursor position

If there is no TOC in the current document, it's created at current
cursor position. Subsequent generation calls update TOC at existing
position.

Add additional tests with CodeMirror editor mock.
This commit is contained in:
Maciek
2018-08-26 00:34:35 +02:00
parent ede733888d
commit 1bb841d5c5
5 changed files with 496 additions and 207 deletions

View File

@@ -6,6 +6,8 @@ import toc from 'markdown-toc'
import diacritics from 'diacritics-map'
import stripColor from 'strip-color'
const EOL = require('os').EOL
/**
* @caseSensitiveSlugify Custom slugify function
* Same implementation that the original used by markdown-toc (node_modules/markdown-toc/lib/utils.js),
@@ -17,6 +19,7 @@ function caseSensitiveSlugify (str) {
return diacritics[ch] || ch
})
}
function getTitle (str) {
if (/^\[[^\]]+\]\(/.test(str)) {
var m = /^\[([^\]]+)\]/.exec(str)
@@ -24,6 +27,7 @@ function caseSensitiveSlugify (str) {
}
return str
}
str = getTitle(str)
str = stripColor(str)
// str = str.toLowerCase() //let's be case sensitive
@@ -38,15 +42,59 @@ function caseSensitiveSlugify (str) {
return str
}
export function generate (currentValue, updateCallback) {
const TOC_MARKER = '<!-- toc -->'
if (!currentValue.includes(TOC_MARKER)) {
currentValue = TOC_MARKER + currentValue
const TOC_MARKER_START = '<!-- toc -->'
const TOC_MARKER_END = '<!-- tocstop -->'
/**
* Takes care of proper updating given editor with TOC.
* If TOC doesn't exit in the editor, it's inserted at current caret position.
* Otherwise,TOC is updated in place.
* @param editor CodeMirror editor to be updated with TOC
*/
export function generateInEditor (editor) {
const tocRegex = new RegExp(`${TOC_MARKER_START}[\\s\\S]*?${TOC_MARKER_END}`)
function tocExistsInEditor () {
return tocRegex.test(editor.getValue())
}
updateCallback(toc.insert(currentValue, {slugify: caseSensitiveSlugify}))
function updateExistingToc () {
const toc = generate(editor.getValue())
const search = editor.getSearchCursor(tocRegex)
while (search.findNext()) {
search.replace(toc)
}
}
function addTocAtCursorPosition () {
const toc = generate(editor.getRange(editor.getCursor(), {line: Infinity}))
editor.replaceRange(wrapTocWithEol(toc, editor), editor.getCursor())
}
if (tocExistsInEditor()) {
updateExistingToc()
} else {
addTocAtCursorPosition()
}
}
/**
* Generates MD TOC based on MD document passed as string.
* @param markdownText MD document
* @returns generatedTOC String containing generated TOC
*/
export function generate (markdownText) {
const generatedToc = toc(markdownText, {slugify: caseSensitiveSlugify})
return TOC_MARKER_START + EOL + EOL + generatedToc.content + EOL + EOL + TOC_MARKER_END
}
function wrapTocWithEol (toc, editor) {
const leftWrap = editor.getCursor().ch === 0 ? '' : EOL
const rightWrap = editor.getLine(editor.getCursor().line).length === editor.getCursor().ch ? '' : EOL
return leftWrap + toc + rightWrap
}
export default {
generate
generate,
generateInEditor
}