mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 01:36: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:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -267,8 +267,8 @@ class MarkdownNoteDetail extends React.Component {
|
||||
}
|
||||
|
||||
handleGenerateToc () {
|
||||
markdownToc.generate(this.refs.content.value,
|
||||
(modifiedValue) => this.refs.content.refs.code.setValue(modifiedValue))
|
||||
const editor = this.refs.content.refs.code.editor
|
||||
markdownToc.generateInEditor(editor)
|
||||
}
|
||||
|
||||
handleFocus (e) {
|
||||
|
||||
@@ -100,9 +100,8 @@ class SnippetNoteDetail extends React.Component {
|
||||
handleGenerateToc () {
|
||||
const currentMode = this.state.note.snippets[this.state.snippetIndex].mode
|
||||
if (currentMode.includes('Markdown')) {
|
||||
const currentValue = this.refs['code-' + this.state.snippetIndex].value
|
||||
const currentEditor = this.refs['code-' + this.state.snippetIndex].refs.code.editor
|
||||
markdownToc.generate(currentValue, (modifiedValue) => currentEditor.setValue(modifiedValue))
|
||||
markdownToc.generateInEditor(currentEditor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user