mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Updated markdown preview to update on diff-basis
Uses vdom system to diff and update the current markdown preview view instead of requiring a full HTML replace change. This should provide better performance, expecially where dynamically loaded content such as iframes were in use. Closes #3454
This commit is contained in:
parent
3fe666f36a
commit
e00d88f45d
14
package-lock.json
generated
14
package-lock.json
generated
@ -10,6 +10,7 @@
|
||||
"dropzone": "^5.9.3",
|
||||
"markdown-it": "^13.0.1",
|
||||
"markdown-it-task-lists": "^2.1.1",
|
||||
"snabbdom": "^3.5.0",
|
||||
"sortablejs": "^1.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -1600,6 +1601,14 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/snabbdom": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.5.0.tgz",
|
||||
"integrity": "sha512-Ff5BKG18KrrPuskHJlA9aujPHqEabItaDl96l7ZZndF4zt5AYSczz7ZjjgQAX5IBd5cd25lw9NfgX21yVUJ+9g==",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sortablejs": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||
@ -2972,6 +2981,11 @@
|
||||
"object-inspect": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"snabbdom": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.5.0.tgz",
|
||||
"integrity": "sha512-Ff5BKG18KrrPuskHJlA9aujPHqEabItaDl96l7ZZndF4zt5AYSczz7ZjjgQAX5IBd5cd25lw9NfgX21yVUJ+9g=="
|
||||
},
|
||||
"sortablejs": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||
|
@ -28,6 +28,7 @@
|
||||
"dropzone": "^5.9.3",
|
||||
"markdown-it": "^13.0.1",
|
||||
"markdown-it-task-lists": "^2.1.1",
|
||||
"snabbdom": "^3.5.0",
|
||||
"sortablejs": "^1.15.0"
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import MarkdownIt from "markdown-it";
|
||||
import mdTasksLists from 'markdown-it-task-lists';
|
||||
import Clipboard from "../services/clipboard";
|
||||
import {debounce} from "../services/util";
|
||||
|
||||
import {patchDomFromHtmlString} from "../services/vdom";
|
||||
import DrawIO from "../services/drawio";
|
||||
|
||||
class MarkdownEditor {
|
||||
@ -127,18 +127,31 @@ class MarkdownEditor {
|
||||
updateAndRender() {
|
||||
const content = this.cm.getValue();
|
||||
this.input.value = content;
|
||||
|
||||
const html = this.markdown.render(content);
|
||||
window.$events.emit('editor-html-change', html);
|
||||
window.$events.emit('editor-markdown-change', content);
|
||||
|
||||
// Set body content
|
||||
const target = this.getDisplayTarget();
|
||||
this.displayDoc.body.className = 'page-content';
|
||||
this.displayDoc.body.innerHTML = html;
|
||||
patchDomFromHtmlString(target, html);
|
||||
|
||||
// Copy styles from page head and set custom styles for editor
|
||||
this.loadStylesIntoDisplay();
|
||||
}
|
||||
|
||||
getDisplayTarget() {
|
||||
const body = this.displayDoc.body;
|
||||
|
||||
if (body.children.length === 0) {
|
||||
const wrap = document.createElement('div');
|
||||
this.displayDoc.body.append(wrap);
|
||||
}
|
||||
|
||||
return body.children[0];
|
||||
}
|
||||
|
||||
loadStylesIntoDisplay() {
|
||||
if (this.displayStylesLoaded) return;
|
||||
this.displayDoc.documentElement.classList.add('markdown-editor-display');
|
||||
|
31
resources/js/services/vdom.js
Normal file
31
resources/js/services/vdom.js
Normal file
@ -0,0 +1,31 @@
|
||||
import {
|
||||
init,
|
||||
attributesModule,
|
||||
toVNode
|
||||
} from "snabbdom";
|
||||
|
||||
let patcher;
|
||||
|
||||
/**
|
||||
* @returns {Function}
|
||||
*/
|
||||
function getPatcher() {
|
||||
if (patcher) return patcher;
|
||||
|
||||
|
||||
patcher = init([
|
||||
attributesModule,
|
||||
]);
|
||||
|
||||
return patcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} domTarget
|
||||
* @param {String} html
|
||||
*/
|
||||
export function patchDomFromHtmlString(domTarget, html) {
|
||||
const contentDom = document.createElement('div');
|
||||
contentDom.innerHTML = html;
|
||||
getPatcher()(toVNode(domTarget), toVNode(contentDom));
|
||||
}
|
Loading…
Reference in New Issue
Block a user