数字公式优化
This commit is contained in:
@@ -3,6 +3,9 @@ import Vue from 'vue';
|
||||
import katex from 'katex';
|
||||
import JSZip from 'jszip';
|
||||
import mammoth from "mammoth";
|
||||
import { MathfieldElement } from 'mathlive';
|
||||
import 'mathlive/dist/mathlive-static.css';
|
||||
import 'mathlive/dist/mathlive-fonts.css';
|
||||
import { importWordDocumentWithMath as parseWordDocumentWithMath, parseHtmlToLatex as convertHtmlToLatex } from '@/utils/wordMathImport';
|
||||
import api from '../../api/index.js';
|
||||
import Common from '@/components/common/common'
|
||||
@@ -26,6 +29,499 @@ const replaceNegativeSign = function (text) {
|
||||
return text;
|
||||
};
|
||||
|
||||
let activeInlineMathOverlay = null;
|
||||
|
||||
function escapeLatexForWmathAttr(latex) {
|
||||
return String(latex || '')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/</g, '<');
|
||||
}
|
||||
|
||||
function buildStoredLatex(rawLatex) {
|
||||
const t = String(rawLatex || '').trim();
|
||||
if (!t) return '';
|
||||
if (/^\$\$[\s\S]+\$\$$/.test(t)) return t;
|
||||
if (/^\$[\s\S]+\$$/.test(t)) return `$$${t.replace(/^\$|\$$/g, '')}$$`;
|
||||
return `$$${t}$$`;
|
||||
}
|
||||
|
||||
function resolveWmathWrapMode(latex) {
|
||||
const t = String(latex || '')
|
||||
.trim()
|
||||
.replace(/^\$\$/, '')
|
||||
.replace(/\$\$$/, '');
|
||||
if (!t) return 'block';
|
||||
if (/^\\begin\{/.test(t) || /\n\s*\n/.test(t)) return 'block';
|
||||
if (/\\frac|\\dfrac|\\tfrac|\\sum|\\int|\\prod|\\lim|\\sqrt\{|\\displaystyle/.test(t)) {
|
||||
return 'block';
|
||||
}
|
||||
return 'inline';
|
||||
}
|
||||
|
||||
function createWmathElementHtml(rawLatex, uid, wrapMode) {
|
||||
const storedLatex = buildStoredLatex(rawLatex);
|
||||
const safeLatex = escapeLatexForWmathAttr(storedLatex);
|
||||
const mode = normalizeWmathWrapMode(wrapMode);
|
||||
return (
|
||||
'<wmath contenteditable="false" data-id="' +
|
||||
uid +
|
||||
'" data-latex="' +
|
||||
safeLatex +
|
||||
'" data-wrap="' +
|
||||
mode +
|
||||
'">' +
|
||||
storedLatex +
|
||||
'</wmath>'
|
||||
);
|
||||
}
|
||||
|
||||
function parseLatexFromWmath(wmathElement) {
|
||||
const raw = (wmathElement && wmathElement.getAttribute('data-latex')) || '';
|
||||
return raw
|
||||
.replace(/^\$\$/, '')
|
||||
.replace(/\$\$$/, '')
|
||||
.replace(/^\$/, '')
|
||||
.replace(/\$$/, '')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function getEventElementTarget(target) {
|
||||
if (!target) return null;
|
||||
if (target.nodeType === 3) return target.parentNode;
|
||||
if (target.nodeType === 9) return null;
|
||||
return target;
|
||||
}
|
||||
|
||||
function findWmathAncestor(node, root) {
|
||||
let el = getEventElementTarget(node);
|
||||
while (el && el !== root) {
|
||||
if (el.nodeType === 1 && el.nodeName && el.nodeName.toLowerCase() === 'wmath') {
|
||||
return el;
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function stripMceSelectedAttr(html) {
|
||||
return String(html || '').replace(/\s*data-mce-selected="[^"]*"/gi, '');
|
||||
}
|
||||
|
||||
function normalizeWmathWrapMode(wrap) {
|
||||
return wrap === 'inline' ? 'inline' : 'block';
|
||||
}
|
||||
|
||||
function getOppositeWrapLabel(wrapMode) {
|
||||
const target = wrapMode === 'inline' ? 'Text above and below' : 'Inline with text';
|
||||
return 'Change to ' + target;
|
||||
}
|
||||
|
||||
function clearEditorMathSelection(ed) {
|
||||
if (!ed || !ed.getBody) return;
|
||||
const body = ed.getBody();
|
||||
if (!body) return;
|
||||
body.querySelectorAll('[data-mce-selected]').forEach((el) => {
|
||||
el.removeAttribute('data-mce-selected');
|
||||
});
|
||||
try {
|
||||
ed.selection.collapse(false);
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function closeWmathContextMenu() {
|
||||
const menu = document.getElementById('tinymce-wmath-context-menu');
|
||||
if (menu) menu.remove();
|
||||
}
|
||||
|
||||
function copyTextToClipboard(text, onSuccess) {
|
||||
const value = String(text || '').trim();
|
||||
if (!value) return;
|
||||
const done = typeof onSuccess === 'function' ? onSuccess : () => {};
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(value).then(done).catch(() => {
|
||||
const ta = document.createElement('textarea');
|
||||
ta.value = value;
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(ta);
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
const ta = document.createElement('textarea');
|
||||
ta.value = value;
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(ta);
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
function showWmathContextMenu(ed, wmathElement, event) {
|
||||
if (!wmathElement || !event) return;
|
||||
if (document.getElementById('tinymce-inline-math-overlay')) return;
|
||||
|
||||
closeWmathContextMenu();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const latex = parseLatexFromWmath(wmathElement);
|
||||
const wrapMode = wmathElement.getAttribute('data-wrap') || 'block';
|
||||
const uid = wmathElement.getAttribute('data-id') || 'wmath-' + Math.random().toString(36).substr(2, 9);
|
||||
const wrapLabel = getOppositeWrapLabel(wrapMode);
|
||||
const nextWrap = wrapMode === 'inline' ? 'block' : 'inline';
|
||||
|
||||
const menu = document.createElement('div');
|
||||
menu.id = 'tinymce-wmath-context-menu';
|
||||
menu.className = 'tinymce-wmath-context-menu';
|
||||
menu.innerHTML =
|
||||
'<button type="button" class="tinymce-wmath-context-item" data-action="copy">Copy LaTeX code</button>' +
|
||||
'<button type="button" class="tinymce-wmath-context-item" data-action="wrap">' +
|
||||
wrapLabel +
|
||||
'</button>';
|
||||
|
||||
menu.style.left = Math.min(event.clientX, window.innerWidth - 220) + 'px';
|
||||
menu.style.top = Math.min(event.clientY, window.innerHeight - 100) + 'px';
|
||||
document.body.appendChild(menu);
|
||||
|
||||
const onMenuAction = (e) => {
|
||||
const item = e.target.closest('[data-action]');
|
||||
if (!item || !menu.contains(item)) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const action = item.getAttribute('data-action');
|
||||
if (action === 'copy') {
|
||||
copyTextToClipboard(latex);
|
||||
} else if (action === 'wrap' && latex) {
|
||||
ed.dom.setOuterHTML(wmathElement, createWmathElementHtml(latex, uid, nextWrap));
|
||||
setTimeout(() => {
|
||||
if (typeof window.renderMathJax === 'function') {
|
||||
window.renderMathJax(ed.id);
|
||||
}
|
||||
clearEditorMathSelection(ed);
|
||||
}, 10);
|
||||
}
|
||||
closeWmathContextMenu();
|
||||
document.removeEventListener('mousedown', onOutside, true);
|
||||
};
|
||||
|
||||
const onOutside = (e) => {
|
||||
if (menu.contains(e.target)) return;
|
||||
closeWmathContextMenu();
|
||||
document.removeEventListener('mousedown', onOutside, true);
|
||||
};
|
||||
|
||||
menu.addEventListener('mousedown', (e) => e.stopPropagation());
|
||||
menu.addEventListener('click', onMenuAction);
|
||||
setTimeout(() => document.addEventListener('mousedown', onOutside, true), 0);
|
||||
}
|
||||
|
||||
function openInlineMathEditor(ed, options) {
|
||||
try {
|
||||
openInlineMathEditorCore(ed, options);
|
||||
} catch (err) {
|
||||
console.error('openInlineMathEditor failed:', err);
|
||||
closeInlineMathOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function openInlineMathEditorCore(ed, options) {
|
||||
const opts = options || {};
|
||||
const mode = opts.mode === 'edit' ? 'edit' : 'insert';
|
||||
const wmathElement = opts.wmathElement || null;
|
||||
|
||||
closeInlineMathOverlay();
|
||||
|
||||
const iframe = ed.iframeElement;
|
||||
const iframeDoc = ed.getDoc();
|
||||
if (!iframe || !iframeDoc) return;
|
||||
|
||||
const placeholderId = 'math-ph-' + Date.now();
|
||||
let uid = 'wmath-' + Math.random().toString(36).substr(2, 9);
|
||||
let initialLatex = '';
|
||||
let originalWmathHtml = null;
|
||||
let preservedWrapMode = null;
|
||||
let currentWrapMode = 'block';
|
||||
|
||||
let anchorRect = null;
|
||||
|
||||
if (mode === 'edit' && wmathElement) {
|
||||
uid = wmathElement.getAttribute('data-id') || uid;
|
||||
initialLatex = parseLatexFromWmath(wmathElement);
|
||||
preservedWrapMode = wmathElement.getAttribute('data-wrap') || null;
|
||||
originalWmathHtml = stripMceSelectedAttr(wmathElement.outerHTML);
|
||||
anchorRect = wmathElement.getBoundingClientRect();
|
||||
const phWidth = Math.max(Math.round(anchorRect.width), 4);
|
||||
const phHeight = Math.max(Math.round(anchorRect.height), 4);
|
||||
ed.dom.setOuterHTML(
|
||||
wmathElement,
|
||||
`<span id="${placeholderId}" class="math-placeholder" style="display:inline-block;min-width:${phWidth}px;min-height:${phHeight}px;vertical-align:middle;">​</span>`
|
||||
);
|
||||
} else {
|
||||
ed.insertContent(
|
||||
`<span id="${placeholderId}" class="math-placeholder" style="display:inline-block;min-width:4px;">​</span>`
|
||||
);
|
||||
}
|
||||
|
||||
const placeholder = ed.dom.get(placeholderId);
|
||||
if (!placeholder) return;
|
||||
|
||||
currentWrapMode = normalizeWmathWrapMode(preservedWrapMode);
|
||||
|
||||
const phRect = placeholder.getBoundingClientRect();
|
||||
const iframeRect = iframe.getBoundingClientRect();
|
||||
const anchor = anchorRect || phRect;
|
||||
const overlayTop = iframeRect.top + anchor.top;
|
||||
const overlayLeft = iframeRect.left + anchor.left;
|
||||
const overlayMinWidth = Math.min(Math.max(anchor.width, phRect.width, 360), 560);
|
||||
|
||||
let overlay = document.getElementById('tinymce-inline-math-overlay');
|
||||
if (!overlay) {
|
||||
overlay = document.createElement('div');
|
||||
overlay.id = 'tinymce-inline-math-overlay';
|
||||
overlay.className = 'tinymce-inline-math-overlay';
|
||||
document.body.appendChild(overlay);
|
||||
}
|
||||
|
||||
overlay.style.display = 'block';
|
||||
overlay.style.top = overlayTop + 'px';
|
||||
overlay.style.left = overlayLeft + 'px';
|
||||
overlay.style.minWidth = overlayMinWidth + 'px';
|
||||
|
||||
overlay.innerHTML = `
|
||||
<div class="tinymce-inline-math-panel">
|
||||
<div class="tinymce-inline-math-field-wrap"></div>
|
||||
<div class="tinymce-inline-math-footer">
|
||||
<div class="tinymce-inline-math-tools">
|
||||
<button type="button" class="tinymce-inline-math-copy">Copy LaTeX code</button>
|
||||
<span class="tinymce-inline-math-tool-divider"></span>
|
||||
<button type="button" class="tinymce-inline-math-wrap-toggle"></button>
|
||||
</div>
|
||||
<div class="tinymce-inline-math-actions">
|
||||
<button type="button" class="tinymce-inline-math-cancel">Cancel</button>
|
||||
<button type="button" class="tinymce-inline-math-confirm">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const fieldWrap = overlay.querySelector('.tinymce-inline-math-field-wrap');
|
||||
const confirmBtn = overlay.querySelector('.tinymce-inline-math-confirm');
|
||||
const cancelBtn = overlay.querySelector('.tinymce-inline-math-cancel');
|
||||
const copyBtn = overlay.querySelector('.tinymce-inline-math-copy');
|
||||
const wrapToggleBtn = overlay.querySelector('.tinymce-inline-math-wrap-toggle');
|
||||
|
||||
const updateWrapToggleLabel = () => {
|
||||
wrapToggleBtn.textContent = getOppositeWrapLabel(currentWrapMode);
|
||||
};
|
||||
updateWrapToggleLabel();
|
||||
|
||||
wrapToggleBtn.addEventListener('mousedown', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
wrapToggleBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
currentWrapMode = currentWrapMode === 'inline' ? 'block' : 'inline';
|
||||
updateWrapToggleLabel();
|
||||
});
|
||||
|
||||
copyBtn.addEventListener('mousedown', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
const mf = new MathfieldElement();
|
||||
fieldWrap.appendChild(mf);
|
||||
|
||||
copyBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
copyTextToClipboard(mf.value, () => {
|
||||
copyBtn.textContent = 'Copied!';
|
||||
copyBtn.classList.add('is-copied');
|
||||
setTimeout(() => {
|
||||
copyBtn.textContent = 'Copy LaTeX code';
|
||||
copyBtn.classList.remove('is-copied');
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
let mfInitialized = false;
|
||||
const initMathfield = () => {
|
||||
if (mfInitialized) return;
|
||||
mfInitialized = true;
|
||||
mf.virtualKeyboardMode = 'onfocus';
|
||||
mf.placeholder = 'Type formula here.';
|
||||
mf.menuItems = [];
|
||||
try {
|
||||
if (initialLatex) {
|
||||
mf.value = initialLatex;
|
||||
}
|
||||
} catch (valueErr) {
|
||||
console.warn('Mathfield set value failed:', valueErr);
|
||||
}
|
||||
requestAnimationFrame(() => {
|
||||
mf.focus();
|
||||
});
|
||||
};
|
||||
|
||||
mf.addEventListener('mount', initMathfield, { once: true });
|
||||
mf.addEventListener('contextmenu', (e) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
setTimeout(initMathfield, 0);
|
||||
|
||||
let finalized = false;
|
||||
let ignoreOutsideClick = true;
|
||||
const openedAt = Date.now();
|
||||
|
||||
const cleanupOutsideListeners = () => {
|
||||
document.removeEventListener('mousedown', onDocMouseDown, true);
|
||||
iframeDoc.removeEventListener('mousedown', onIframeMouseDown, true);
|
||||
mf.removeEventListener('blur', onMfBlur);
|
||||
};
|
||||
|
||||
const canCancelOutside = () => !ignoreOutsideClick && Date.now() - openedAt > 400;
|
||||
|
||||
const finalize = (save) => {
|
||||
if (finalized) return;
|
||||
finalized = true;
|
||||
cleanupOutsideListeners();
|
||||
|
||||
const latex = (mf.value || '').trim();
|
||||
closeInlineMathOverlay();
|
||||
|
||||
const ph = ed.dom.get(placeholderId);
|
||||
if (!ph) return;
|
||||
|
||||
const afterUpdate = () => {
|
||||
setTimeout(() => {
|
||||
if (typeof window.renderMathJax === 'function') {
|
||||
window.renderMathJax(ed.id);
|
||||
}
|
||||
clearEditorMathSelection(ed);
|
||||
}, 10);
|
||||
};
|
||||
|
||||
if (save && latex) {
|
||||
ed.dom.setOuterHTML(ph, createWmathElementHtml(latex, uid, currentWrapMode));
|
||||
afterUpdate();
|
||||
} else if (mode === 'edit' && originalWmathHtml) {
|
||||
ed.dom.setOuterHTML(ph, originalWmathHtml);
|
||||
afterUpdate();
|
||||
} else {
|
||||
ed.dom.remove(ph);
|
||||
clearEditorMathSelection(ed);
|
||||
}
|
||||
};
|
||||
|
||||
const onDocMouseDown = (e) => {
|
||||
if (!canCancelOutside()) return;
|
||||
if (overlay.contains(e.target)) return;
|
||||
if (isMathliveUiTarget(e.target)) return;
|
||||
finalize(false);
|
||||
};
|
||||
|
||||
const onIframeMouseDown = (e) => {
|
||||
if (!canCancelOutside()) return;
|
||||
if (overlay.contains(e.target)) return;
|
||||
if (isMathliveUiTarget(e.target)) return;
|
||||
finalize(false);
|
||||
};
|
||||
|
||||
const onMfBlur = () => {
|
||||
setTimeout(() => {
|
||||
if (finalized) return;
|
||||
if (!canCancelOutside()) return;
|
||||
const activeEl = document.activeElement;
|
||||
const iframeActiveEl = iframeDoc.activeElement;
|
||||
if (overlay.contains(activeEl)) return;
|
||||
if (isMathliveUiTarget(activeEl) || isMathliveUiTarget(iframeActiveEl)) return;
|
||||
finalize(false);
|
||||
}, 150);
|
||||
};
|
||||
|
||||
confirmBtn.addEventListener('mousedown', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
confirmBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
finalize(true);
|
||||
});
|
||||
|
||||
cancelBtn.addEventListener('mousedown', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
cancelBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
finalize(false);
|
||||
});
|
||||
|
||||
activeInlineMathOverlay = {
|
||||
overlay,
|
||||
iframeDoc,
|
||||
mf,
|
||||
finalize,
|
||||
cleanupOutsideListeners
|
||||
};
|
||||
|
||||
mf.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
e.preventDefault();
|
||||
finalize(false);
|
||||
}
|
||||
});
|
||||
mf.addEventListener('blur', onMfBlur);
|
||||
|
||||
setTimeout(() => {
|
||||
ignoreOutsideClick = false;
|
||||
document.addEventListener('mousedown', onDocMouseDown, true);
|
||||
iframeDoc.addEventListener('mousedown', onIframeMouseDown, true);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function insertInlineMathWithMathlive(ed) {
|
||||
openInlineMathEditor(ed, { mode: 'insert' });
|
||||
}
|
||||
|
||||
function editInlineMathWithMathlive(ed, wmathElement) {
|
||||
if (!wmathElement) return;
|
||||
if (activeInlineMathOverlay) return;
|
||||
openInlineMathEditor(ed, { mode: 'edit', wmathElement });
|
||||
}
|
||||
|
||||
function isMathliveUiTarget(target) {
|
||||
if (!target || !target.closest) return false;
|
||||
return !!(
|
||||
target.closest('#tinymce-inline-math-overlay') ||
|
||||
target.closest('.ML__keyboard') ||
|
||||
target.closest('.ML__virtual-keyboard') ||
|
||||
target.closest('.MLK__plate') ||
|
||||
target.closest('math-field')
|
||||
);
|
||||
}
|
||||
|
||||
function closeInlineMathOverlay() {
|
||||
if (!activeInlineMathOverlay) return;
|
||||
const { overlay, cleanupOutsideListeners } = activeInlineMathOverlay;
|
||||
if (typeof cleanupOutsideListeners === 'function') {
|
||||
cleanupOutsideListeners();
|
||||
}
|
||||
overlay.style.display = 'none';
|
||||
overlay.innerHTML = '';
|
||||
activeInlineMathOverlay = null;
|
||||
}
|
||||
|
||||
|
||||
// 首字母大写的方法
|
||||
// const capitalizeFirstLetter = function (text) {
|
||||
@@ -1837,6 +2333,19 @@ str = str.replace(regex, function (match, content, offset, fullString) {
|
||||
},
|
||||
|
||||
|
||||
insertInlineMathWithMathlive(ed) {
|
||||
openInlineMathEditor(ed, { mode: 'insert' });
|
||||
},
|
||||
editInlineMathWithMathlive(ed, wmathElement) {
|
||||
if (!wmathElement) return;
|
||||
openInlineMathEditor(ed, { mode: 'edit', wmathElement });
|
||||
},
|
||||
findWmathFromTarget(target, root) {
|
||||
return findWmathAncestor(target, root);
|
||||
},
|
||||
openWmathContextMenu(ed, wmathElement, event) {
|
||||
showWmathContextMenu(ed, wmathElement, event);
|
||||
},
|
||||
initEditorButton(vueInstance, ed) {
|
||||
|
||||
ed.ui.registry.addMenuButton('customDropdown', {
|
||||
@@ -2189,28 +2698,37 @@ str = str.replace(regex, function (match, content, offset, fullString) {
|
||||
let latexEditorBookmark = null; // 用于记录插入点
|
||||
let activeEditorId = null; // 当前激活的编辑器 ID
|
||||
|
||||
// 在编辑器工具栏中添加 "LateX" 按钮
|
||||
// // 在编辑器工具栏中添加 "LateX" 按钮
|
||||
// ed.ui.registry.addButton('LateX', {
|
||||
// text: 'LateX', // 按钮文本
|
||||
// onAction: function () {
|
||||
// // 1. 获取当前光标位置
|
||||
// const latexEditorBookmark = ed.selection.getBookmark(2); // 获取光标位置
|
||||
// const editorId = ed.id; // 保存当前编辑器 ID
|
||||
|
||||
// // 2. 生成一个随机的 ID,用于 wmath 标签
|
||||
// const uid = 'wmath-' + Math.random().toString(36).substr(2, 9);
|
||||
|
||||
// // 3. 创建一个 <wmath> 标签并插入到光标处
|
||||
// const wmathHtml = `<wmath contenteditable="false" data-id="${uid}" data-latex="" data-wrap="block"></wmath>`;
|
||||
// ed.insertContent(wmathHtml); // 在光标位置插入 wmath 标签
|
||||
|
||||
// // 4. 打开公式编辑器窗口,并传递光标位置、编辑器 ID 和 wmathId
|
||||
// const url = `/LateX?editorId=${editorId}&wmathId=${uid}`;
|
||||
// // vueInstance.openLatexEditor({
|
||||
// // editorId:editorId,
|
||||
// // wmathId:uid,
|
||||
// // });
|
||||
// window.open(url, '_blank', 'width=1000,height=800,scrollbars=no,resizable=no');
|
||||
// }
|
||||
// });
|
||||
|
||||
// 行内公式编辑(MathLive),类似 Word「在此处键入公式」
|
||||
ed.ui.registry.addButton('LateX', {
|
||||
text: 'LateX', // 按钮文本
|
||||
text: 'LateX',
|
||||
tooltip: 'Type formula here',
|
||||
onAction: function () {
|
||||
// 1. 获取当前光标位置
|
||||
const latexEditorBookmark = ed.selection.getBookmark(2); // 获取光标位置
|
||||
const editorId = ed.id; // 保存当前编辑器 ID
|
||||
|
||||
// 2. 生成一个随机的 ID,用于 wmath 标签
|
||||
const uid = 'wmath-' + Math.random().toString(36).substr(2, 9);
|
||||
|
||||
// 3. 创建一个 <wmath> 标签并插入到光标处
|
||||
const wmathHtml = `<wmath contenteditable="false" data-id="${uid}" data-latex="" data-wrap="block"></wmath>`;
|
||||
ed.insertContent(wmathHtml); // 在光标位置插入 wmath 标签
|
||||
|
||||
// 4. 打开公式编辑器窗口,并传递光标位置、编辑器 ID 和 wmathId
|
||||
const url = `/LateX?editorId=${editorId}&wmathId=${uid}`;
|
||||
// vueInstance.openLatexEditor({
|
||||
// editorId:editorId,
|
||||
// wmathId:uid,
|
||||
// });
|
||||
window.open(url, '_blank', 'width=1000,height=800,scrollbars=no,resizable=no');
|
||||
insertInlineMathWithMathlive(ed);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user