Skip to content

Commit e88749d

Browse files
author
cloudQuant
committed
fix ueditor markdown
1 parent adef9aa commit e88749d

1 file changed

Lines changed: 285 additions & 5 deletions

File tree

woniunote/resource/ueditor/dialogs/contentimport/contentimport.js

Lines changed: 285 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,189 @@ function processWord(file) {
3131
reader.readAsArrayBuffer(file);
3232
}
3333

34-
function processMarkdown( markdown ){
35-
var converter = new showdown.Converter();
36-
var html = converter.makeHtml(markdown);
34+
function processMarkdown(markdown) {
35+
// 第一步:处理代码块,保护它们不被当作公式处理
36+
var codeBlocks = [];
37+
var codeBlockIndex = 0;
38+
var processedMarkdown = markdown;
39+
40+
// 先提取代码块避免其中的$ 符号被当作数学公式处理
41+
processedMarkdown = processedMarkdown.replace(/```([\s\S]*?)```/g, function(match) {
42+
var placeholder = "__CODE_" + codeBlockIndex + "__";
43+
codeBlocks.push({placeholder: placeholder, content: match});
44+
codeBlockIndex++;
45+
return placeholder;
46+
});
47+
48+
// 第二步:使用Showdown转换markdown为HTML
49+
var converter = new showdown.Converter({
50+
tables: true, // 启用表格支持
51+
strikethrough: true, // 启用删除线
52+
tasklists: true, // 支持任务列表
53+
simpleLineBreaks: true, // 简单换行
54+
emoji: true, // 支持emoji
55+
literalMidWordUnderscores: true, // 支持单词内的下划线
56+
parseImgDimensions: true // 支持图片尺寸
57+
});
58+
59+
// 页面上的MathJax配置支持$ $也支持\( \)格式,所以我们先将所有公式转换为$ $格式
60+
// 这样处理我们可以让Showdown正常处理Markdown,而公式部分不会被讨匀
61+
62+
// 处理原生的\[ ... \]格式的公式(可能跨多行)
63+
processedMarkdown = processedMarkdown.replace(/\\\[([\s\S]*?)\\\]/g, function(match, formula) {
64+
return '$$' + formula + '$$';
65+
});
66+
67+
// 将方括号内的LaTeX公式转换为$$..$$格式
68+
// 注意这里的正则使用[\s\S]*?来匹配包括换行在内的任意字符
69+
processedMarkdown = processedMarkdown.replace(/\[([\s\S]*?)\]/g, function(match, formula) {
70+
// 只有当括号中的内容包含公式特性的内容才进行转换
71+
if (formula.indexOf('\\beta') !== -1 ||
72+
formula.indexOf('\\frac') !== -1 ||
73+
formula.indexOf('_') !== -1 ||
74+
formula.indexOf('^') !== -1 ||
75+
formula.indexOf('\\epsilon') !== -1 ||
76+
formula.indexOf('\\left') !== -1 ||
77+
formula.indexOf('\\right') !== -1 ||
78+
formula.indexOf('\\cdots') !== -1) {
79+
return '$$' + formula + '$$';
80+
}
81+
return match; // 如果不是公式,保持原样
82+
});
83+
84+
// 转换Markdown为HTML
85+
var html = converter.makeHtml(processedMarkdown);
86+
87+
// 第三步:将代码块放回到HTML中
88+
codeBlocks.forEach(function(block) {
89+
html = html.replace(block.placeholder, block.content);
90+
});
91+
92+
// 第四步:添加MathJax配置,与网站现有配置保持一致
93+
var mathjaxConfig = '<script type="text/javascript">\n' +
94+
'window.MathJax = {\n' +
95+
' tex: {\n' +
96+
' inlineMath: [["$", "$"], ["\\\\(", "\\\\)"]],\n' +
97+
' displayMath: [["$$", "$$"], ["\\\\[", "\\\\]"]],\n' +
98+
' processEscapes: true,\n' +
99+
' processEnvironments: true\n' +
100+
' },\n' +
101+
' options: {\n' +
102+
' ignoreHtmlClass: "tex2jax_ignore",\n' +
103+
' processHtmlClass: "tex2jax_process"\n' +
104+
' },\n' +
105+
' startup: {\n' +
106+
' ready: function() {\n' +
107+
' MathJax.startup.defaultReady();\n' +
108+
' }\n' +
109+
' }\n' +
110+
'};\n' +
111+
'</script>\n';
112+
113+
// 添加MathJax脚本支持,使用与网站相同的版本和渲染器
114+
var mathjaxSupport = mathjaxConfig +
115+
'<script type="text/javascript" id="MathJax-script" async ' +
116+
'src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>';
117+
118+
// 添加表格样式
119+
var styles = '<style>\n' +
120+
'table {border-collapse: collapse; width: 100%; margin: 10px 0;}\n' +
121+
'table, th, td {border: 1px solid #ddd;}\n' +
122+
'th, td {padding: 8px; text-align: left;}\n' +
123+
'th {background-color: #f2f2f2;}\n' +
124+
'</style>\n';
125+
126+
// 特别为网站添加的公式处理脚本
127+
var specialMathJaxScript = '<script>\n' +
128+
'setTimeout(function() {\n' +
129+
' // 获取文章内容元素\n' +
130+
' const contentElement = document.getElementById(\'content\');\n' +
131+
' if (!contentElement) return;\n' +
132+
' \n' +
133+
' // 获取HTML内容\n' +
134+
' let html = contentElement.innerHTML;\n' +
135+
' \n' +
136+
' // 使用正则表达式处理多行公式\n' +
137+
' // 注意这里的s标志可以匹配多行内容\n' +
138+
' html = html.replace(/\\[([\\s\\S]*?)\\]/gs, function(match, formula) {\n' +
139+
' // 只有当括号中的内容包含公式特性的内容才进行转换\n' +
140+
' if (formula.indexOf(\'\\\\beta\') !== -1 || \n' +
141+
' formula.indexOf(\'\\\\frac\') !== -1 || \n' +
142+
' formula.indexOf(\'_\') !== -1 || \n' +
143+
' formula.indexOf(\'^\') !== -1 || \n' +
144+
' formula.indexOf(\'\\\\epsilon\') !== -1 ||\n' +
145+
' formula.indexOf(\'\\\\left\') !== -1 ||\n' +
146+
' formula.indexOf(\'\\\\right\') !== -1 ||\n' +
147+
' formula.indexOf(\'\\\\cdots\') !== -1) {\n' +
148+
' return \'$$\' + formula + \'$$\';\n' +
149+
' }\n' +
150+
' return match; // 如果不是公式,保持原样\n' +
151+
' });\n' +
152+
' \n' +
153+
' // 更新内容\n' +
154+
' contentElement.innerHTML = html;\n' +
155+
' \n' +
156+
' // 重新渲染数学公式\n' +
157+
' MathJax && MathJax.typeset && MathJax.typeset();\n' +
158+
'}, 500);\n' +
159+
'</script>';
160+
161+
html = styles + html + mathjaxSupport + specialMathJaxScript;
162+
37163
$('.file-tip').html('转换成功');
38164
contentImport.data.result = html;
39165
$('.file-result').html(html).show();
166+
167+
// 初始化MathJax渲染
168+
if (window.MathJax) {
169+
try {
170+
window.MathJax.typesetPromise && window.MathJax.typesetPromise();
171+
} catch(e) {
172+
console.error('MathJax渲染失败:', e);
173+
}
174+
}
40175
}
41176

42177
function processMarkdownFile(file) {
43178
$('.file-tip').html('正在转换Markdown文件,请稍后...');
44179
$('.file-result').html('').hide();
45180
var reader = new FileReader();
46181
reader.onload = function (loadEvent) {
47-
processMarkdown( loadEvent.target.result );
182+
// 加载MathJax脚本以支持数学公式
183+
if (!window.MathJax) {
184+
// 加载MathJax配置和脚本
185+
var configScript = document.createElement('script');
186+
configScript.type = 'text/javascript';
187+
configScript.text = 'window.MathJax = {' +
188+
'tex: {' +
189+
' inlineMath: [["\\\\(", "\\\\)"]],' +
190+
' displayMath: [["\\\\[", "\\\\]"]],' +
191+
' processEscapes: true,' +
192+
' processEnvironments: true,' +
193+
' macros: {' +
194+
' beta: "\\\\beta",' +
195+
' epsilon: "\\\\epsilon",' +
196+
' hat: ["\\\\hat{#1}", 1]' +
197+
' }' +
198+
'},' +
199+
'options: {' +
200+
' ignoreHtmlClass: "tex2jax_ignore",' +
201+
' processHtmlClass: "tex2jax_process"' +
202+
'},' +
203+
'startup: {' +
204+
' ready: function() {' +
205+
' MathJax.startup.defaultReady();' +
206+
' }' +
207+
'}' +
208+
'};';
209+
document.head.appendChild(configScript);
210+
211+
$.getScript('https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js', function() {
212+
processMarkdown(loadEvent.target.result);
213+
});
214+
} else {
215+
processMarkdown(loadEvent.target.result);
216+
}
48217
};
49218
reader.onerror = function (loadEvent) {
50219
$('.file-tip').html('Markdown文件转换失败:' + loadEvent);
@@ -82,9 +251,120 @@ function addOkListener() {
82251
alert('请先上传文件识别内容');
83252
return false;
84253
}
254+
255+
// 内容已经包含样式,直接插入
256+
var content = contentImport.data.result;
257+
258+
// 检查是否已包含MathJax,如果不包含则添加
259+
if (content.indexOf('MathJax-script') === -1) {
260+
// 添加MathJax配置和脚本,使用与网站相同的配置
261+
var mathjaxConfig = '<script type="text/javascript">\n' +
262+
'window.MathJax = {\n' +
263+
' tex: {\n' +
264+
' inlineMath: [["$", "$"], ["\\\\(", "\\\\)"]],\n' +
265+
' displayMath: [["$$", "$$"], ["\\\\[", "\\\\]"]],\n' +
266+
' processEscapes: true,\n' +
267+
' processEnvironments: true\n' +
268+
' },\n' +
269+
' options: {\n' +
270+
' ignoreHtmlClass: "tex2jax_ignore",\n' +
271+
' processHtmlClass: "tex2jax_process"\n' +
272+
' },\n' +
273+
' startup: {\n' +
274+
' ready: function() {\n' +
275+
' MathJax.startup.defaultReady();\n' +
276+
' }\n' +
277+
' }\n' +
278+
'};\n' +
279+
'</script>\n';
280+
281+
var mathjaxScript = '<script type="text/javascript" id="MathJax-script" async ' +
282+
'src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>';
283+
// 特别为网站添加的公式处理脚本,处理方括号内的公式
284+
var specialMathJaxScript = '<script>\n' +
285+
'setTimeout(function() {\n' +
286+
' var contentElement = document.getElementById(\'content\');\n' +
287+
' if (!contentElement) {\n' +
288+
' contentElement = document.querySelector(\'.ueditor-content\');\n' +
289+
' }\n' +
290+
' if (!contentElement) return;\n' +
291+
' \n' +
292+
' let html = contentElement.innerHTML;\n' +
293+
' \n' +
294+
' // 使用正则表达式处理多行公式\n' +
295+
' // 注意这里的s标志可以匹配多行内容\n' +
296+
' html = html.replace(/\\[([\\s\\S]*?)\\]/gs, function(match, formula) {\n' +
297+
' // 只有当括号中的内容包含公式特性的内容才进行转换\n' +
298+
' if (formula.indexOf(\'\\\\beta\') !== -1 || \n' +
299+
' formula.indexOf(\'\\\\frac\') !== -1 || \n' +
300+
' formula.indexOf(\'_\') !== -1 || \n' +
301+
' formula.indexOf(\'^\') !== -1 || \n' +
302+
' formula.indexOf(\'\\\\epsilon\') !== -1 ||\n' +
303+
' formula.indexOf(\'\\\\left\') !== -1 ||\n' +
304+
' formula.indexOf(\'\\\\right\') !== -1 ||\n' +
305+
' formula.indexOf(\'\\\\cdots\') !== -1) {\n' +
306+
' return \'$$\' + formula + \'$$\';\n' +
307+
' }\n' +
308+
' return match; // 如果不是公式,保持原样\n' +
309+
' });\n' +
310+
' \n' +
311+
' contentElement.innerHTML = html;\n' +
312+
' \n' +
313+
' MathJax && MathJax.typeset && MathJax.typeset();\n' +
314+
'}, 500);\n' +
315+
'</script>';
316+
317+
content = mathjaxConfig + content + mathjaxScript + specialMathJaxScript;
318+
}
319+
85320
editor.fireEvent('saveScene');
86-
editor.execCommand("inserthtml", contentImport.data.result);
321+
editor.execCommand("inserthtml", content);
87322
editor.fireEvent('saveScene');
323+
324+
// 重新初始化MathJax渲染,以确保公式正确显示
325+
if (window.MathJax) {
326+
setTimeout(function() {
327+
try {
328+
// MathJax 3.x
329+
if (window.MathJax && window.MathJax.typeset) {
330+
window.MathJax.typeset();
331+
332+
// 额外处理方括号中的公式
333+
var contentElement = document.getElementById('content');
334+
if (!contentElement) {
335+
contentElement = document.querySelector('.ueditor-content');
336+
}
337+
if (contentElement) {
338+
var html = contentElement.innerHTML;
339+
// 使用正则表达式处理多行公式
340+
html = html.replace(/\[([\s\S]*?)\]/gs, function(match, formula) {
341+
// 只有当括号中的内容包含公式特性的内容才进行转换
342+
if (formula.indexOf('\\beta') !== -1 ||
343+
formula.indexOf('\\frac') !== -1 ||
344+
formula.indexOf('_') !== -1 ||
345+
formula.indexOf('^') !== -1 ||
346+
formula.indexOf('\\epsilon') !== -1 ||
347+
formula.indexOf('\\left') !== -1 ||
348+
formula.indexOf('\\right') !== -1 ||
349+
formula.indexOf('\\cdots') !== -1) {
350+
return '$$' + formula + '$$';
351+
}
352+
return match; // 如果不是公式,保持原样
353+
});
354+
contentElement.innerHTML = html;
355+
window.MathJax.typeset();
356+
}
357+
console.log('MathJax渲染成功');
358+
}
359+
// MathJax 2.x
360+
else if (window.MathJax && window.MathJax.Hub) {
361+
window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub]);
362+
}
363+
} catch(e) {
364+
console.error('MathJax初始化或渲染失败:', e);
365+
}
366+
}, 1000); // 增加延时确保内容已加载
367+
}
88368
};
89369
dialog.oncancel = function () {
90370
};

0 commit comments

Comments
 (0)