From 254cb9146521945eaa36ce5959ab13ba9c9d9260 Mon Sep 17 00:00:00 2001 From: David Dreher Date: Thu, 7 Feb 2019 17:20:00 +0100 Subject: [PATCH] Fix for #2782: CodeEditor.handleChange will now update the toc if available when a headline was modified --- browser/components/CodeEditor.js | 35 +++++++++++++++++++++++++++ browser/lib/markdown-toc-generator.js | 17 +++++++------ 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index f19fc3f1d..76c7be669 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -22,6 +22,7 @@ const buildEditorContextMenu = require('browser/lib/contextMenuBuilder') import TurndownService from 'turndown' import {languageMaps} from '../lib/CMLanguageList' import snippetManager from '../lib/SnippetManager' +import {generateInEditor, tocExistsInEditor} from 'browser/lib/markdown-toc-generator' CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js' @@ -614,6 +615,34 @@ export default class CodeEditor extends React.Component { handleChange (editor, changeObject) { spellcheck.handleChange(editor, changeObject) + // The current note contains an toc. We'll check for changes on headlines. + // origin is undefined when markdownTocGenerator replace the old tod + if (tocExistsInEditor(editor) && changeObject.origin !== undefined) { + let requireTocUpdate + + // Check if one of the changed lines contains a headline + for (let line = 0; line < changeObject.text.length; line++) { + if (this.linePossibleContainsHeadline(editor.getLine(changeObject.from.line + line))) { + requireTocUpdate = true + break + } + } + + if (!requireTocUpdate) { + // Check if one of the removed lines contains a headline + for (let line = 0; line < changeObject.removed.length; line++) { + if (this.linePossibleContainsHeadline(changeObject.removed[line])) { + requireTocUpdate = true + break + } + } + } + + if (requireTocUpdate) { + generateInEditor(editor) + } + } + this.updateHighlight(editor, changeObject) this.value = editor.getValue() @@ -622,6 +651,12 @@ export default class CodeEditor extends React.Component { } } + linePossibleContainsHeadline (currentLine) { + // We can't check if the line start with # because when some write text before + // the # we also need to update the toc + return currentLine.includes('# ') + } + incrementLines (start, linesAdded, linesRemoved, editor) { const highlightedLines = editor.options.linesHighlighted diff --git a/browser/lib/markdown-toc-generator.js b/browser/lib/markdown-toc-generator.js index af1c833f4..8f027247b 100644 --- a/browser/lib/markdown-toc-generator.js +++ b/browser/lib/markdown-toc-generator.js @@ -28,6 +28,8 @@ function linkify (token) { const TOC_MARKER_START = '' const TOC_MARKER_END = '' +const tocRegex = new RegExp(`${TOC_MARKER_START}[\\s\\S]*?${TOC_MARKER_END}`) + /** * Takes care of proper updating given editor with TOC. * If TOC doesn't exit in the editor, it's inserted at current caret position. @@ -35,12 +37,6 @@ const TOC_MARKER_END = '' * @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()) - } - function updateExistingToc () { const toc = generate(editor.getValue()) const search = editor.getSearchCursor(tocRegex) @@ -54,13 +50,17 @@ export function generateInEditor (editor) { editor.replaceRange(wrapTocWithEol(toc, editor), editor.getCursor()) } - if (tocExistsInEditor()) { + if (tocExistsInEditor(editor)) { updateExistingToc() } else { addTocAtCursorPosition() } } +export function tocExistsInEditor (editor) { + return tocRegex.test(editor.getValue()) +} + /** * Generates MD TOC based on MD document passed as string. * @param markdownText MD document @@ -94,5 +94,6 @@ function wrapTocWithEol (toc, editor) { export default { generate, - generateInEditor + generateInEditor, + tocExistsInEditor }