diff --git a/web/include/vditor-adapter.js b/web/include/vditor-adapter.js index e493d12..f7788a7 100644 --- a/web/include/vditor-adapter.js +++ b/web/include/vditor-adapter.js @@ -13,6 +13,7 @@ var DEFAULT_CDN = global.HUSTOJ_VDITOR_CDN || getLocalCdnBase(); global.HUSTOJ_VDITOR_CDN = DEFAULT_CDN; var assetsPromise = null; + var aceAssetsPromise = null; var styleInjected = false; function getLocalCdnBase() { @@ -25,6 +26,16 @@ return scriptSrc.replace(/\/vditor-adapter\.js(?:[?#].*)?$/, '/vditor'); } + function getLocalAceBase() { + var scriptSrc = currentScriptRef && currentScriptRef.src; + + if (!scriptSrc) { + return 'ace'; + } + + return scriptSrc.replace(/\/include\/vditor-adapter\.js(?:[?#].*)?$/, '/ace'); + } + function injectAdapterStyle() { var style; @@ -39,6 +50,14 @@ '.hustoj-vditor-hidden{display:none !important;}', '.hustoj-vditor-wrapper{width:100%;margin:0 0 12px;}', '.hustoj-vditor-code{--hustoj-vditor-font-size:18px;text-align:left;}', + '.hustoj-vditor-code.ace_editor{position:relative;border:1px solid #d4d4d5;border-radius:6px;line-height:1.5;}', + '.hustoj-vditor-code .ace_scroller,', + '.hustoj-vditor-code .ace_gutter,', + '.hustoj-vditor-code .ace_content{font-family:Consolas,Monaco,"Courier New",monospace !important;font-size:var(--hustoj-vditor-font-size) !important;line-height:1.5 !important;}', + '.hustoj-vditor-code .ace_gutter{background:#f8f8f8;color:#8a8a8a;}', + '.hustoj-vditor-dark.ace_editor{background:#272822;border-color:#4a4a4a;}', + '.hustoj-vditor-dark .ace_gutter{background:#2f3129;color:#bcbcbc;}', + '.hustoj-vditor-dark .ace_print-margin{background:#3a3d34;}', '.hustoj-vditor-preview{--hustoj-diagram-font-family:"Microsoft YaHei","PingFang SC","Hiragino Sans GB","Noto Sans CJK SC","Source Han Sans SC","WenQuanYi Micro Hei",Arial,sans-serif;--hustoj-diagram-font-size:14px;}', '.hustoj-vditor-code .vditor-toolbar{display:none !important;}', '.hustoj-vditor-code .vditor-reset,', @@ -147,6 +166,56 @@ return assetsPromise; } + function ensureAceAssets(options) { + var aceBase = (options && options.aceBase) || getLocalAceBase(); + + injectAdapterStyle(); + + if (global.ace) { + if (global.ace.config && typeof global.ace.config.set === 'function') { + global.ace.config.set('basePath', aceBase); + } + return Promise.resolve(global.ace); + } + + if (aceAssetsPromise) { + return aceAssetsPromise; + } + + aceAssetsPromise = new Promise(function (resolve, reject) { + var aceScriptSrc = aceBase + '/ace.js'; + var existing = documentRef.querySelector('script[data-hustoj-ace-js="' + aceScriptSrc + '"]'); + var finish = function () { + if (global.ace && global.ace.config && typeof global.ace.config.set === 'function') { + global.ace.config.set('basePath', aceBase); + } + resolve(global.ace); + }; + + if (existing) { + if (global.ace) { + finish(); + } else { + existing.addEventListener('load', finish, { once: true }); + existing.addEventListener('error', reject, { once: true }); + } + return; + } + + var script = documentRef.createElement('script'); + script.src = aceScriptSrc; + script.async = true; + script.setAttribute('data-hustoj-ace-js', aceScriptSrc); + script.onload = finish; + script.onerror = function () { + reject(new Error('Failed to load ' + aceScriptSrc)); + }; + documentRef.head.appendChild(script); + }); + + return aceAssetsPromise; + } + function resolveElement(target) { if (!target) { return null; @@ -621,15 +690,16 @@ } function createCodeEditor(options) { - return ensureAssets(options).then(function () { + return ensureAceAssets(options).then(function () { var container = resolveElement(options.container); var hiddenField = resolveElement(options.hiddenField); var sourceField = resolveElement(options.sourceField); var initialValue = options.initialValue; var adapter = null; - var vditor = null; + var aceEditor = null; var session = null; var state; + var aceBase = (options && options.aceBase) || getLocalAceBase(); if (!container) { throw new Error('Vditor code editor container not found'); @@ -649,25 +719,33 @@ container.classList.add('hustoj-vditor-code'); container.style.setProperty('--hustoj-vditor-font-size', state.fontSize + 'px'); container.classList.toggle('hustoj-vditor-dark', aceThemeToVditorTheme(state.theme) === 'dark'); + container.style.width = options.width || '100%'; + if (typeof options.height === 'string') { + container.style.height = options.height; + } else { + container.style.height = (options.height || computeHeight(container, 420)) + 'px'; + } if (sourceField && sourceField !== container) { sourceField.classList.add('hustoj-vditor-hidden'); } - container.textContent = ''; + container.textContent = initialValue || ''; function applyTheme() { var editorTheme = aceThemeToVditorTheme(state.theme); - var contentTheme = aceThemeToContentTheme(state.theme); container.classList.toggle('hustoj-vditor-dark', editorTheme === 'dark'); - if (vditor && typeof vditor.setTheme === 'function') { - vditor.setTheme(editorTheme, contentTheme, 'github'); + if (aceEditor) { + aceEditor.setTheme(state.theme); } } function applyFontSize() { container.style.setProperty('--hustoj-vditor-font-size', state.fontSize + 'px'); + if (aceEditor) { + aceEditor.setFontSize(state.fontSize); + } } function syncSourceValue(value) { @@ -685,6 +763,9 @@ session = { setMode: function (modeName) { state.mode = normalizeMode(modeName); + if (aceEditor) { + aceEditor.session.setMode(modeName || 'text'); + } }, getValue: function () { return adapter.getValue(); @@ -695,110 +776,105 @@ }; return new Promise(function (resolve) { - vditor = new global.Vditor(container, { - cdn: options.cdn || DEFAULT_CDN, - cache: { enable: false }, - mode: options.editorMode || 'sv', - lang: options.lang || 'zh_CN', - value: initialValue || '', - icon: options.icon || 'ant', - theme: aceThemeToVditorTheme(state.theme), - width: options.width || '100%', - minHeight: options.minHeight || computeHeight(container, 420), - height: options.height || computeHeight(container, 420), - toolbar: options.toolbar || [], - toolbarConfig: options.toolbarConfig || { hide: true, pin: false }, - resize: options.resize || { enable: false }, - outline: options.outline || { enable: false }, - counter: options.counter || { enable: false }, - preview: options.preview || { - mode: 'editor', - delay: 0, - actions: [], - markdown: { - sanitize: false, - autoSpace: false, - codeBlockPreview: false, - mathBlockPreview: false, - fixTermTypo: false - } - }, - input: function (value) { - syncSourceValue(value); - }, - blur: function (value) { - syncSourceValue(value); - }, - after: function () { - adapter = { - getValue: function () { - return vditor.getValue(); - }, - setValue: function (value) { - var nextValue = typeof value === 'undefined' ? '' : String(value); - vditor.setValue(nextValue, true); - syncSourceValue(nextValue); - return nextValue; - }, - getSession: function () { - return session; - }, - session: session, - setTheme: function (themeName) { - state.theme = themeName || state.theme; - applyTheme(); - }, - getTheme: function () { - return state.theme; - }, - setOptions: function (editorOptions) { - if (!editorOptions) { - return; - } - if (editorOptions.fontSize) { - this.setFontSize(editorOptions.fontSize); - } - if (typeof editorOptions.readOnly !== 'undefined') { - this.setReadOnly(editorOptions.readOnly); - } - }, - setOption: function (name, value) { - if (name === 'wrap') { - state.wrap = value !== 'off'; - } - }, - resize: function () { - applyFontSize(); - }, - getFontSize: function () { - return String(state.fontSize); - }, - setFontSize: function (fontSize) { - state.fontSize = parseInt(fontSize, 10) || state.fontSize; - applyFontSize(); - }, - setReadOnly: function (readOnly) { - if (readOnly) { - vditor.disabled(); - } else { - vditor.enable(); - } - }, - focus: function () { - vditor.focus(); - }, - _vditor: vditor - }; + if (global.ace && global.ace.config && typeof global.ace.config.set === 'function') { + global.ace.config.set('basePath', aceBase); + } - applyTheme(); - applyFontSize(); - if (options.readOnly) { - adapter.setReadOnly(true); - } - syncSourceValue(vditor.getValue()); - resolve(adapter); - } + aceEditor = global.ace.edit(container); + aceEditor.$blockScrolling = Infinity; + aceEditor.setValue(initialValue || '', -1); + aceEditor.session.setUseWorker(false); + aceEditor.session.setUseWrapMode(true); + aceEditor.renderer.setShowPrintMargin(false); + aceEditor.setHighlightActiveLine(true); + aceEditor.setOptions({ + showFoldWidgets: false, + tabSize: 4, + useSoftTabs: true, + behavioursEnabled: false, + wrapBehavioursEnabled: false, + fontSize: state.fontSize }); + + if (state.mode) { + aceEditor.session.setMode('ace/mode/' + state.mode); + } + + aceEditor.session.on('change', function () { + syncSourceValue(aceEditor.getValue()); + }); + aceEditor.on('blur', function () { + syncSourceValue(aceEditor.getValue()); + }); + + adapter = { + getValue: function () { + return aceEditor.getValue(); + }, + setValue: function (value) { + var nextValue = typeof value === 'undefined' ? '' : String(value); + aceEditor.setValue(nextValue, -1); + syncSourceValue(nextValue); + return nextValue; + }, + getSession: function () { + return aceEditor.getSession(); + }, + session: aceEditor.getSession(), + setTheme: function (themeName) { + state.theme = themeName || state.theme; + applyTheme(); + }, + getTheme: function () { + return state.theme; + }, + setOptions: function (editorOptions) { + if (!editorOptions) { + return; + } + if (editorOptions.fontSize) { + this.setFontSize(editorOptions.fontSize); + } + if (typeof editorOptions.readOnly !== 'undefined') { + this.setReadOnly(editorOptions.readOnly); + } + aceEditor.setOptions(editorOptions); + }, + setOption: function (name, value) { + if (name === 'wrap') { + state.wrap = value !== 'off'; + aceEditor.session.setUseWrapMode(state.wrap); + return; + } + aceEditor.setOption(name, value); + }, + resize: function () { + aceEditor.resize(); + applyFontSize(); + }, + getFontSize: function () { + return String(state.fontSize); + }, + setFontSize: function (fontSize) { + state.fontSize = parseInt(fontSize, 10) || state.fontSize; + applyFontSize(); + }, + setReadOnly: function (readOnly) { + aceEditor.setReadOnly(!!readOnly); + }, + focus: function () { + aceEditor.focus(); + }, + _ace: aceEditor + }; + + applyTheme(); + applyFontSize(); + if (options.readOnly) { + adapter.setReadOnly(true); + } + syncSourceValue(aceEditor.getValue()); + resolve(adapter); }); }); } diff --git a/web/include/vditor/dist/index.js b/web/include/vditor/dist/index.js index eccd8de..45a8829 100644 --- a/web/include/vditor/dist/index.js +++ b/web/include/vditor/dist/index.js @@ -2818,13 +2818,6 @@ var plantumlRenderAdapter = { /* harmony import */ var _util_function__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(446); var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { -var FLOWCHART_DIAGRAM_FONT_FAMILY = '"Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Source Han Sans SC", "WenQuanYi Micro Hei", Arial, sans-serif'; -var FLOWCHART_DIAGRAM_OPTIONS = { - "font-family": FLOWCHART_DIAGRAM_FONT_FAMILY, - "font-size": 14, - "font-weight": "normal" -}; - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } @@ -2994,6 +2987,11 @@ var codeRender = function (element, option) { var flowchartRender = function (element, cdn) { if (cdn === void 0) { cdn = _constants__WEBPACK_IMPORTED_MODULE_0__/* .Constants.CDN */ .g.CDN; } + var flowchartDiagramOptions = { + "font-family": '"Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Source Han Sans SC", "WenQuanYi Micro Hei", Arial, sans-serif', + "font-size": 14, + "font-weight": "normal" + }; var flowchartElements = _adapterRender__WEBPACK_IMPORTED_MODULE_1__.flowchartRenderAdapter.getElements(element); if (flowchartElements.length === 0) { return; @@ -3005,7 +3003,7 @@ var flowchartRender = function (element, cdn) { } var flowchartObj = flowchart.parse(_adapterRender__WEBPACK_IMPORTED_MODULE_1__.flowchartRenderAdapter.getCode(item)); item.innerHTML = ""; - flowchartObj.drawSVG(item, FLOWCHART_DIAGRAM_OPTIONS); + flowchartObj.drawSVG(item, flowchartDiagramOptions); item.setAttribute("data-processed", "true"); }); }); @@ -3548,6 +3546,10 @@ var mermaidRender = function (element, cdn, theme) { fontFamily: mermaidFontFamily, fontSize: "14px", startOnLoad: false, + themeVariables: { + fontFamily: mermaidFontFamily, + fontSize: "14px" + }, flowchart: { htmlLabels: false, useMaxWidth: !0 diff --git a/web/include/vditor/src/ts/markdown/mermaidRender.ts b/web/include/vditor/src/ts/markdown/mermaidRender.ts index 8ab543e..caa698a 100644 --- a/web/include/vditor/src/ts/markdown/mermaidRender.ts +++ b/web/include/vditor/src/ts/markdown/mermaidRender.ts @@ -23,6 +23,10 @@ export const mermaidRender = (element: HTMLElement, cdn = Constants.CDN, theme: fontFamily: MERMAID_FONT_FAMILY, fontSize: MERMAID_FONT_SIZE, startOnLoad: false, + themeVariables: { + fontFamily: MERMAID_FONT_FAMILY, + fontSize: MERMAID_FONT_SIZE, + }, flowchart: { htmlLabels: false, useMaxWidth: !0