(function (global) { 'use strict'; var documentRef = global.document; if (!documentRef) { return; } var currentScriptRef = documentRef.currentScript || (function () { var scripts = documentRef.getElementsByTagName('script'); return scripts.length > 0 ? scripts[scripts.length - 1] : null; })(); 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() { var scriptSrc = currentScriptRef && currentScriptRef.src; if (!scriptSrc) { return 'include/vditor'; } 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 getLocalSarasaFontUrl() { var scriptSrc = currentScriptRef && currentScriptRef.src; if (!scriptSrc) { return 'template/syzoj/fonts/SarasaMonoSC-Regular.ttf'; } return scriptSrc.replace(/\/include\/vditor-adapter\.js(?:[?#].*)?$/, '/template/syzoj/fonts/SarasaMonoSC-Regular.ttf'); } function injectAdapterStyle() { var sarasaFontUrl = getLocalSarasaFontUrl(); var style; if (styleInjected) { return; } style = documentRef.createElement('style'); style.type = 'text/css'; style.setAttribute('data-hustoj-vditor', 'adapter-style'); style.textContent = [ '@font-face{font-family:"Sarasa Mono SC Local";src:local("等距更纱黑体 SC"),local("Sarasa Mono SC"),url("' + sarasaFontUrl + '") format("truetype");font-weight:400;font-style:normal;font-display:swap;}', '.hustoj-vditor-hidden{display:none !important;}', '.hustoj-vditor-wrapper{width:100%;margin:0 0 12px;}', '.hustoj-vditor-wrapper,.hustoj-vditor-preview,.hustoj-vditor-markdown,.hustoj-vditor-code{--hustoj-vditor-font-family:"Sarasa Mono SC Local","等距更纱黑体 SC","Sarasa Mono SC","Sarasa Fixed SC","Sarasa Gothic SC",Consolas,"Cascadia Mono","JetBrains Mono","Courier New",monospace;--hustoj-vditor-font-size:24px;--hustoj-vditor-preview-code-font-size:24px;}', '.hustoj-vditor-markdown,.hustoj-vditor-markdown .vditor,.hustoj-vditor-markdown .vditor-content,.hustoj-vditor-markdown .vditor-ir,.hustoj-vditor-markdown .vditor-sv,.hustoj-vditor-markdown .vditor-reset,.hustoj-vditor-markdown .vditor-wysiwyg,.hustoj-vditor-markdown .vditor-sv__preview{text-align:left !important;}', '.hustoj-vditor-markdown .vditor{margin-left:0 !important;margin-right:auto !important;}', '.hustoj-vditor-markdown .vditor-toolbar{justify-content:flex-start;}', '.hustoj-vditor-markdown .vditor-content,.hustoj-vditor-markdown .vditor-reset,.hustoj-vditor-markdown .vditor-reset *,.hustoj-vditor-markdown textarea{font-family:var(--hustoj-vditor-font-family) !important;}', '.hustoj-vditor-code{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:var(--hustoj-vditor-font-family) !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,', '.hustoj-vditor-code .vditor-content,', '.hustoj-vditor-code .vditor,', '.hustoj-vditor-code textarea{text-align:left !important;font-family:var(--hustoj-vditor-font-family) !important;font-size:var(--hustoj-vditor-font-size) !important;line-height:1.5 !important;}', '.hustoj-vditor-code .vditor-sv,', '.hustoj-vditor-code .vditor-ir{min-height:100%;}', '.hustoj-vditor-dark .vditor{background:#272822;border-color:#4a4a4a;}', '.hustoj-vditor-dark .vditor-reset,', '.hustoj-vditor-dark .vditor-content,', '.hustoj-vditor-dark textarea{color:#f8f8f2 !important;background:#272822 !important;}', '.hustoj-vditor-dark .vditor-toolbar svg{fill:#f8f8f2;}', '.hustoj-vditor-mail .vditor-toolbar{border-bottom:1px solid #ddd;}', '.hustoj-vditor-mail .vditor{height:100%;min-height:180px;}', '.hustoj-vditor-preview .vditor-reset pre{position:relative;margin:16px 0;padding:16px 18px;border:1px solid #cfd7e6;border-radius:12px;background:linear-gradient(180deg,#f9fbff 0%,#f3f7ff 100%);box-shadow:0 8px 20px rgba(15,23,42,0.06);}', '.hustoj-vditor-preview .vditor-reset pre code{display:block;font-family:var(--hustoj-vditor-font-family) !important;font-size:var(--hustoj-vditor-preview-code-font-size) !important;line-height:1.7;}', '.hustoj-vditor-preview .vditor-reset pre div.vditor-copy{display:block !important;opacity:1 !important;visibility:visible !important;position:absolute;top:12px;right:12px;z-index:2;}', '.hustoj-vditor-preview .vditor-copy span{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border:1px solid #c8d3e6;border-radius:999px;background:rgba(255,255,255,0.96);box-shadow:0 4px 12px rgba(15,23,42,0.08);font-size:12px;font-weight:600;color:#2f4f7f;position:static !important;}', '.hustoj-vditor-preview .vditor-copy span::after{content:attr(aria-label);}', '.hustoj-vditor-preview .vditor-copy svg{width:14px !important;height:14px !important;color:currentColor;}', '.hustoj-vditor-preview .hustoj-vditor-sample-heading{display:flex;align-items:center;margin:24px 0 0;padding:12px 16px;border:1px solid #d6dde8;border-bottom:0;border-radius:14px 14px 0 0;background:#eef4ff;color:#274061;font-size:1.05em;font-weight:700;line-height:1.4;}', '.hustoj-vditor-preview .vditor-reset pre.hustoj-vditor-sample-box{margin-top:0;border-top-left-radius:0;border-top-right-radius:0;border-top-color:#d6dde8;padding-top:52px;}', '.hustoj-vditor-preview .vditor-reset .language-mermaid,', '.hustoj-vditor-preview .vditor-reset .language-flowchart{margin:18px 0;padding:14px;border:1px solid #d7dce5;border-radius:12px;background:#fff;overflow:auto;text-align:center;}', '.hustoj-vditor-preview .vditor-reset .language-mermaid svg,', '.hustoj-vditor-preview .vditor-reset .language-flowchart svg{display:block;max-width:100%;height:auto !important;overflow:visible;}', '.hustoj-vditor-preview .vditor-reset .language-mermaid foreignObject,', '.hustoj-vditor-preview .vditor-reset .language-flowchart foreignObject,', '.hustoj-vditor-preview .vditor-reset .language-mermaid .label,', '.hustoj-vditor-preview .vditor-reset .language-flowchart .label{overflow:visible;}', '.hustoj-vditor-preview .vditor-reset .language-mermaid .label div,', '.hustoj-vditor-preview .vditor-reset .language-flowchart .label div,', '.hustoj-vditor-preview .vditor-reset .language-mermaid .edgeLabel,', '.hustoj-vditor-preview .vditor-reset .language-flowchart .edgeLabel{font-family:var(--hustoj-diagram-font-family) !important;font-size:var(--hustoj-diagram-font-size) !important;white-space:normal !important;line-height:1.4 !important;}', '.hustoj-vditor-preview .vditor-reset .language-mermaid .nodeLabel,', '.hustoj-vditor-preview .vditor-reset .language-flowchart .nodeLabel,', '.hustoj-vditor-preview .vditor-reset .language-mermaid .nodeLabel *,', '.hustoj-vditor-preview .vditor-reset .language-flowchart .nodeLabel *,', '.hustoj-vditor-preview .vditor-reset .language-mermaid svg text,', '.hustoj-vditor-preview .vditor-reset .language-mermaid svg tspan,', '.hustoj-vditor-preview .vditor-reset .language-flowchart svg text,', '.hustoj-vditor-preview .vditor-reset .language-flowchart svg tspan{font-family:var(--hustoj-diagram-font-family) !important;font-size:var(--hustoj-diagram-font-size) !important;font-variant-ligatures:none;text-rendering:geometricPrecision;}', '.hustoj-vditor-preview .vditor-reset .language-mermaid .nodeLabel p,', '.hustoj-vditor-preview .vditor-reset .language-flowchart .nodeLabel p{margin:0;line-height:1.4 !important;}' ].join(''); documentRef.head.appendChild(style); styleInjected = true; } function ensureStyleTag(href) { var existing = documentRef.querySelector('link[data-hustoj-vditor-css="' + href + '"]'); if (existing) { return; } var link = documentRef.createElement('link'); link.rel = 'stylesheet'; link.href = href; link.setAttribute('data-hustoj-vditor-css', href); documentRef.head.appendChild(link); } function ensureScript(src) { return new Promise(function (resolve, reject) { var existing = documentRef.querySelector('script[data-hustoj-vditor-js="' + src + '"]'); if (existing) { if (global.Vditor) { resolve(global.Vditor); } else { existing.addEventListener('load', function () { resolve(global.Vditor); }, { once: true }); existing.addEventListener('error', reject, { once: true }); } return; } var script = documentRef.createElement('script'); script.src = src; script.async = true; script.setAttribute('data-hustoj-vditor-js', src); script.onload = function () { resolve(global.Vditor); }; script.onerror = function () { reject(new Error('Failed to load ' + src)); }; documentRef.head.appendChild(script); }); } function ensureAssets(options) { var cdn = (options && options.cdn) || DEFAULT_CDN; global.HUSTOJ_VDITOR_CDN = cdn; if (global.Vditor) { injectAdapterStyle(); return Promise.resolve(global.Vditor); } if (assetsPromise) { return assetsPromise; } ensureStyleTag(cdn + '/dist/index.css'); injectAdapterStyle(); assetsPromise = ensureScript(cdn + '/dist/index.js').then(function () { return global.Vditor; }); 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 languageToolsSrc = aceBase + '/ext-language_tools.js'; var existing = documentRef.querySelector('script[data-hustoj-ace-js="' + aceScriptSrc + '"]'); var loadLanguageTools = function () { var languageTools = documentRef.querySelector('script[data-hustoj-ace-js="' + languageToolsSrc + '"]'); var done = function () { finish(); }; if (languageTools) { languageTools.addEventListener('load', done, { once: true }); languageTools.addEventListener('error', done, { once: true }); return; } languageTools = documentRef.createElement('script'); languageTools.src = languageToolsSrc; languageTools.async = true; languageTools.setAttribute('data-hustoj-ace-js', languageToolsSrc); languageTools.onload = done; languageTools.onerror = done; documentRef.head.appendChild(languageTools); }; 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) { loadLanguageTools(); } else { existing.addEventListener('load', loadLanguageTools, { 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 = loadLanguageTools; script.onerror = function () { reject(new Error('Failed to load ' + aceScriptSrc)); }; documentRef.head.appendChild(script); }); return aceAssetsPromise; } function resolveElement(target) { if (!target) { return null; } if (typeof target === 'string') { return documentRef.getElementById(target) || documentRef.querySelector(target); } return target; } function getElementValue(element) { if (!element) { return ''; } if (typeof element.value === 'string') { return element.value; } return element.textContent || ''; } function computeHeight(element, fallbackHeight) { var computed; var rows; var height; if (element && global.getComputedStyle) { computed = global.getComputedStyle(element); height = parseInt(computed.height, 10); if (!height) { height = parseInt(computed.minHeight, 10); } } if (!height && element) { rows = parseInt(element.getAttribute('rows'), 10); if (rows) { height = Math.max(rows * 24, fallbackHeight || 320); } } return height || fallbackHeight || 360; } function aceThemeToVditorTheme(themeName) { if (!themeName) { return 'classic'; } if (themeName.indexOf('monokai') !== -1 || themeName.indexOf('dark') !== -1) { return 'dark'; } return 'classic'; } function aceThemeToContentTheme(themeName) { return aceThemeToVditorTheme(themeName) === 'dark' ? 'dark' : 'light'; } function normalizeMode(modeName) { if (!modeName) { return ''; } return String(modeName).replace(/^ace\/mode\//, ''); } function dispatchNativeEvent(element, eventName) { var eventObject; if (!element || typeof Event === 'undefined') { return; } eventObject = new Event(eventName, { bubbles: true }); element.dispatchEvent(eventObject); } function syncFieldValue(field, value, onChange) { if (!field) { if (typeof onChange === 'function') { onChange(value, null); } if (typeof global.sync === 'function') { global.sync(); } return; } field.value = value; dispatchNativeEvent(field, 'input'); dispatchNativeEvent(field, 'change'); if (typeof onChange === 'function') { onChange(value, field); } if (typeof global.sync === 'function') { global.sync(); } } function decodeHtmlEntities(text) { var textarea = documentRef.createElement('textarea'); textarea.innerHTML = typeof text === 'string' ? text : ''; return textarea.value; } function toElementArray(target) { var resolved; if (!target) { return []; } if (typeof target === 'string') { return Array.prototype.slice.call(documentRef.querySelectorAll(target)); } if (target.nodeType === 1) { return [target]; } if (typeof target.length === 'number') { return Array.prototype.slice.call(target).map(function (item) { return resolveElement(item); }).filter(function (item) { return !!item; }); } resolved = resolveElement(target); return resolved ? [resolved] : []; } function mergeObjects(target, source) { var key; if (!source) { return target; } for (key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } return target; } function getMarkdownSource(element, options) { var rawSource; var source; if (!element) { return ''; } if (!options.refreshSource && typeof element._hustojVditorSource === 'string') { return element._hustojVditorSource; } if (typeof options.getSource === 'function') { rawSource = options.getSource(element); } else if (options.useTextContent) { rawSource = element.textContent || ''; } else { rawSource = element.innerHTML || ''; } source = String(rawSource || ''); if (options.decodeEntities !== false) { source = decodeHtmlEntities(source); } element._hustojVditorSource = source; return source; } function buildPreviewOptions(options, afterRender) { var previewOptions = { cdn: options.cdn || DEFAULT_CDN, mode: options.mode || 'light', anchor: typeof options.anchor === 'undefined' ? 0 : options.anchor, speech: { enable: false }, hljs: { style: options.codeTheme || 'github' }, markdown: { autoSpace: false, fixTermTypo: false, toc: false, codeBlockPreview: true, mathBlockPreview: true, sanitize: false }, math: { inlineDigit: true }, after: afterRender }; if (options.previewOptions) { mergeObjects(previewOptions, options.previewOptions); if (options.previewOptions.speech) { previewOptions.speech = mergeObjects(previewOptions.speech, options.previewOptions.speech); } if (options.previewOptions.hljs) { previewOptions.hljs = mergeObjects(previewOptions.hljs, options.previewOptions.hljs); } if (options.previewOptions.markdown) { previewOptions.markdown = mergeObjects(previewOptions.markdown, options.previewOptions.markdown); } if (options.previewOptions.math) { previewOptions.math = mergeObjects(previewOptions.math, options.previewOptions.math); } } previewOptions.after = afterRender; return previewOptions; } function decorateRenderedPreview(element) { if (!element || !element.classList) { return; } element.classList.add('hustoj-vditor-preview'); decorateSampleBlocks(element); Array.prototype.forEach.call( element.querySelectorAll('.language-mermaid, .language-flowchart'), function (diagramContainer) { Array.prototype.forEach.call(diagramContainer.querySelectorAll('svg'), function (svgElement) { svgElement.style.maxWidth = '100%'; svgElement.style.height = 'auto'; svgElement.style.overflow = 'visible'; }); Array.prototype.forEach.call( diagramContainer.querySelectorAll('foreignObject, .label, .label div, .edgeLabel, .nodeLabel, .nodeLabel p'), function (node) { if (node.tagName === 'FOREIGNOBJECT') { node.style.overflow = 'visible'; } if (node.tagName === 'DIV' || node.tagName === 'SPAN') { node.style.whiteSpace = 'normal'; } if (node.tagName === 'P') { node.style.margin = '0'; node.style.lineHeight = '1.4'; } if (node.classList && node.classList.contains('nodeLabel')) { node.style.lineHeight = '1.4'; } } ); } ); } function normalizeHeadingText(text) { return String(text || '').replace(/\s+/g, ' ').trim(); } function parseSampleHeading(text) { var normalized = normalizeHeadingText(text).replace(/[::]+$/, ''); var match = normalized.match(/^(?:(?:样例|示例|sample|example)\s*)?(输入|输出|input|output)\s*([0-9]+)?$/i); var kind; if (!match) { return null; } kind = match[1].toLowerCase(); if (kind === '输入' || kind === 'input') { kind = 'input'; } else { kind = 'output'; } return { kind: kind, index: match[2] || '' }; } function getSiblingCodeBlock(heading) { var sibling = heading ? heading.nextElementSibling : null; while (sibling && sibling.tagName === 'P' && !normalizeHeadingText(sibling.textContent)) { sibling = sibling.nextElementSibling; } if (!sibling || sibling.tagName !== 'PRE') { return null; } return sibling; } function decorateSampleBlocks(element) { Array.prototype.forEach.call(element.querySelectorAll('h1, h2, h3, h4, h5, h6'), function (heading) { var sampleMeta = parseSampleHeading(heading.textContent); var codeBlock; if (!sampleMeta) { return; } codeBlock = getSiblingCodeBlock(heading); if (!codeBlock) { return; } heading.classList.add('hustoj-vditor-sample-heading'); heading.setAttribute('data-hustoj-sample-kind', sampleMeta.kind); if (sampleMeta.index) { heading.setAttribute('data-hustoj-sample-index', sampleMeta.index); } codeBlock.classList.add('hustoj-vditor-sample-box'); codeBlock.setAttribute('data-hustoj-sample-kind', sampleMeta.kind); if (sampleMeta.index) { codeBlock.setAttribute('data-hustoj-sample-index', sampleMeta.index); } }); } function renderMarkdownBlocks(target, options) { var renderOptions = options || {}; return ensureAssets(renderOptions).then(function () { var elements = toElementArray(target); var tasks = []; elements.forEach(function (element) { var source = getMarkdownSource(element, renderOptions); if (!source && !renderOptions.renderEmpty) { return; } tasks.push(new Promise(function (resolve, reject) { var previewOptions = buildPreviewOptions(renderOptions, function () { decorateRenderedPreview(element); if (typeof renderOptions.afterEach === 'function') { renderOptions.afterEach(element, source); } resolve(element); }); try { global.Vditor.preview(element, source, previewOptions); } catch (error) { reject(error); } })); }); return Promise.all(tasks).then(function (result) { if (typeof renderOptions.afterAll === 'function') { renderOptions.afterAll(result); } return result; }); }); } function editorUploadFormatter(files, responseText) { var payload; var fileName = 'upload'; var result; try { payload = JSON.parse(responseText); } catch (error) { return JSON.stringify({ msg: '上传返回解析失败', code: 1, data: { errFiles: [fileName], succMap: {} } }); } if (files && files.length > 0 && files[0] && files[0].name) { fileName = files[0].name; } if (typeof payload.code !== 'undefined' && payload.data) { return responseText; } if (payload.error === 0 && payload.url) { result = { msg: '', code: 0, data: { errFiles: [], succMap: {} } }; result.data.succMap[fileName] = payload.url; return JSON.stringify(result); } return JSON.stringify({ msg: payload.message || payload.msg || '上传失败', code: 1, data: { errFiles: [fileName], succMap: {} } }); } function buildUploadOptions(options) { if (!options || !options.uploadUrl) { return undefined; } return { url: options.uploadUrl, max: options.uploadMax || 400 * 1024 * 1024, multiple: false, fieldName: options.fieldName || 'imgFile', accept: options.accept || '*/*', format: function (files, responseText) { return editorUploadFormatter(files, responseText); } }; } function getDefaultMarkdownToolbar() { return [ 'emoji', 'headings', 'bold', 'italic', 'strike', '|', 'line', 'quote', 'list', 'ordered-list', 'check', '|', 'link', 'upload', 'table', 'code', 'inline-code', '|', 'undo', 'redo', 'fullscreen', 'outline' ]; } function getDefaultMailToolbar() { return [ 'emoji', 'headings', 'bold', 'italic', 'strike', '|', 'link', 'upload', 'code', 'inline-code', '|', 'undo', 'redo', '|', 'fullscreen' ]; } function createTextareaEditor(textarea, options) { var wrapper = documentRef.createElement('div'); var height = computeHeight(textarea, options.height || 360); var vditor; wrapper.className = 'hustoj-vditor-wrapper hustoj-vditor-markdown'; textarea.classList.add('hustoj-vditor-hidden'); textarea.parentNode.insertBefore(wrapper, textarea.nextSibling); return new Promise(function (resolve) { vditor = new global.Vditor(wrapper, { cdn: options.cdn || DEFAULT_CDN, cache: { enable: false }, mode: options.mode || 'sv', value: textarea.value || '', lang: options.lang || 'zh_CN', theme: options.theme || 'classic', icon: options.icon || 'ant', width: options.width || '100%', minHeight: options.minHeight || Math.min(height, 320), height: options.height || height, toolbar: options.toolbar || getDefaultMarkdownToolbar(), toolbarConfig: options.toolbarConfig || { pin: true }, resize: options.resize || { enable: true, position: 'bottom' }, outline: options.outline || { enable: false }, preview: options.preview || { mode: 'both', delay: 0, actions: [], markdown: { sanitize: false, autoSpace: false, codeBlockPreview: true, mathBlockPreview: true, fixTermTypo: false } }, upload: buildUploadOptions(options), ctrlEnter: function (value) { var form; syncFieldValue(textarea, value, options.onChange); if (!options.ctrlEnterFormName) { return; } form = documentRef.querySelector('form[name="' + options.ctrlEnterFormName + '"]'); if (form) { form.submit(); } }, input: function (value) { syncFieldValue(textarea, value, options.onChange); }, blur: function (value) { syncFieldValue(textarea, value, options.onChange); }, after: function () { syncFieldValue(textarea, vditor.getValue(), options.onChange); resolve(vditor); } }); }); } function createCodeEditor(options) { 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 aceEditor = null; var session = null; var state; var aceBase = (options && options.aceBase) || getLocalAceBase(); if (!container) { throw new Error('Vditor code editor container not found'); } if (typeof initialValue === 'undefined') { initialValue = getElementValue(sourceField || container); } state = { theme: options.theme || 'ace/theme/chrome', fontSize: parseInt(options.fontSize, 10) || 24, mode: normalizeMode(options.mode || ''), wrap: true }; 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 = initialValue || ''; function applyTheme() { var editorTheme = aceThemeToVditorTheme(state.theme); container.classList.toggle('hustoj-vditor-dark', editorTheme === 'dark'); 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) { if (sourceField && sourceField !== container && typeof sourceField.value === 'string') { sourceField.value = value; } if (hiddenField && typeof hiddenField.value === 'string') { hiddenField.value = value; } if (typeof options.onChange === 'function') { options.onChange(value); } } session = { setMode: function (modeName) { state.mode = normalizeMode(modeName); if (aceEditor) { aceEditor.session.setMode(modeName || 'text'); } }, getValue: function () { return adapter.getValue(); }, setValue: function (value) { adapter.setValue(value); } }; return new Promise(function (resolve) { if (global.ace && global.ace.config && typeof global.ace.config.set === 'function') { global.ace.config.set('basePath', aceBase); } 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); }); }); } function createDeferredCodeEditor(options) { var initialElement = resolveElement(options && (options.sourceField || options.container)); var proxy = { _impl: null, _theme: (options && options.theme) || 'ace/theme/chrome', _fontSize: parseInt(options && options.fontSize, 10) || 18, _value: typeof options !== 'undefined' && typeof options.initialValue !== 'undefined' ? options.initialValue : getElementValue(initialElement), _mode: normalizeMode(options && options.mode), _options: null, _readOnly: typeof options !== 'undefined' ? options.readOnly : undefined, _wrap: 'free' }; function getProxySession() { return { setMode: function (modeName) { proxy._mode = normalizeMode(modeName); if (proxy._impl) { proxy._impl.getSession().setMode(modeName); } }, getValue: function () { return proxy.getValue(); }, setValue: function (value) { proxy.setValue(value); } }; } proxy.getValue = function () { if (proxy._impl) { return proxy._impl.getValue(); } if (typeof proxy._value !== 'undefined' && proxy._value !== null && proxy._value !== '') { return proxy._value; } return getElementValue(resolveElement(options && (options.sourceField || options.container))); }; proxy.setValue = function (value) { proxy._value = value; if (proxy._impl) { return proxy._impl.setValue(value); } return value; }; proxy.getSession = function () { return getProxySession(); }; proxy.session = getProxySession(); proxy.setTheme = function (themeName) { proxy._theme = themeName || proxy._theme; if (proxy._impl) { proxy._impl.setTheme(proxy._theme); } }; proxy.getTheme = function () { if (proxy._impl) { return proxy._impl.getTheme(); } return proxy._theme; }; proxy.setOptions = function (editorOptions) { proxy._options = editorOptions; if (editorOptions && editorOptions.fontSize) { proxy._fontSize = parseInt(editorOptions.fontSize, 10) || proxy._fontSize; } if (proxy._impl) { proxy._impl.setOptions(editorOptions); } }; proxy.setOption = function (name, value) { if (name === 'wrap') { proxy._wrap = value; } if (proxy._impl) { proxy._impl.setOption(name, value); } }; proxy.resize = function () { if (proxy._impl) { proxy._impl.resize(); } }; proxy.getFontSize = function () { if (proxy._impl) { return proxy._impl.getFontSize(); } return String(proxy._fontSize); }; proxy.setFontSize = function (fontSize) { proxy._fontSize = parseInt(fontSize, 10) || proxy._fontSize; if (proxy._impl) { proxy._impl.setFontSize(proxy._fontSize); } }; proxy.setReadOnly = function (readOnly) { proxy._readOnly = readOnly; if (proxy._impl) { proxy._impl.setReadOnly(readOnly); } }; proxy.focus = function () { if (proxy._impl) { proxy._impl.focus(); } }; createCodeEditor(options || {}).then(function (instance) { proxy._impl = instance; instance.setTheme(proxy._theme); instance.setFontSize(proxy._fontSize); if (proxy._options) { instance.setOptions(proxy._options); } if (proxy._mode) { instance.getSession().setMode('ace/mode/' + proxy._mode); } if (typeof proxy._readOnly !== 'undefined') { instance.setReadOnly(proxy._readOnly); } instance.setOption('wrap', proxy._wrap); if (typeof proxy._value !== 'undefined' && proxy._value !== null) { instance.setValue(proxy._value); } }).catch(function (error) { console.error('Failed to initialize deferred Vditor code editor.', error); }); return proxy; } function createRichTextEditor(options) { return ensureAssets(options).then(function () { var container = resolveElement(options.container); var hiddenField = resolveElement(options.hiddenField); var initialValue = options.initialValue || ''; var vditor = null; var adapter = null; if (!container) { throw new Error('Vditor rich editor container not found'); } container.classList.add('hustoj-vditor-mail'); container.textContent = ''; function syncHtml() { var html = vditor.getHTML(); if (hiddenField && typeof hiddenField.value === 'string') { hiddenField.value = html; } if (typeof options.onChange === 'function') { options.onChange(html); } } return new Promise(function (resolve) { vditor = new global.Vditor(container, { cdn: options.cdn || DEFAULT_CDN, cache: { enable: false }, mode: options.mode || 'wysiwyg', lang: options.lang || 'zh_CN', value: initialValue, theme: options.theme || 'classic', icon: options.icon || 'ant', width: options.width || '100%', minHeight: options.minHeight || computeHeight(container, 200), height: options.height || computeHeight(container, 200), toolbar: options.toolbar || getDefaultMailToolbar(), toolbarConfig: options.toolbarConfig || { pin: true }, preview: options.preview || { mode: 'editor', delay: 0, actions: [], markdown: { sanitize: false, autoSpace: false, fixTermTypo: false } }, upload: buildUploadOptions(options), input: syncHtml, blur: syncHtml, after: function () { adapter = { getHTML: function () { return vditor.getHTML(); }, getValue: function () { return vditor.getValue(); }, setValue: function (value) { vditor.setValue(value || '', true); syncHtml(); }, focus: function () { vditor.focus(); }, txt: { html: function () { return vditor.getHTML(); } }, _vditor: vditor }; syncHtml(); resolve(adapter); } }); }); }); } function initTextareaVditors(options) { return ensureAssets(options).then(function () { var selector = (options && options.selector) || 'textarea.vditor-editor'; var textareas = documentRef.querySelectorAll(selector); var tasks = []; Array.prototype.forEach.call(textareas, function (textarea) { tasks.push(createTextareaEditor(textarea, options || {})); }); return Promise.all(tasks); }); } global.HustOJVditor = { ensureAssets: ensureAssets, initTextareaVditors: initTextareaVditors, createCodeEditor: createCodeEditor, createDeferredCodeEditor: createDeferredCodeEditor, createRichTextEditor: createRichTextEditor, renderMarkdownBlocks: renderMarkdownBlocks, aceThemeToVditorTheme: aceThemeToVditorTheme, decodeHtmlEntities: decodeHtmlEntities, editorUploadFormatter: editorUploadFormatter }; })(window);