@@ -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
42177function 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