1. 从Word到WordPress一条让公式头秃的粘贴路1.1 我当初是怎么被这个场景逼疯的先交代一下背景。我的站点是教育题库类型作者每天要在Word里用MathType 7编辑几十道试题然后发布到WordPress后台。这个流程听起来很常规但真正操作起来第一批作者用了不到两天就来拍桌子了公式粘贴到古腾堡编辑器后要么变成一团乱码要么变成一张模糊的小图片更恶心的情况是整个公式直接消失后台HTML里只剩一堆object和embed标签。这个问题说白了就是Word和MathType使用的是桌面端的对象嵌入体系而WordPress的区块编辑器处理的是HTML、Markdown和普通图片。两边在“公式”这件事上根本说不到一块去。我自己研究了一个多星期才把整条链路彻底打通——从Word里复制MathType公式粘贴到WordPress后台自动转成可编辑的公式源文件同时上传生成为清晰可缩放的显示图并且让公式源在MathType桌面端还能二次打开修改。这篇文章就把整个方案完整拆开讲。适合看这篇文章的人大概是这么几类教育网站/题库站点的站长被Word公式和WordPress兼容性坑过的技术运营以及想在Gutenberg编辑器里做自定义粘贴增强的开发者。如果你只是想临时往文章里插一个公式截图那用不着折腾下面的方案但如果你有几十上百个作者每天在传公式题这个方案的投入产出比是值得的。1.2 直接粘贴之后后台到底存了些什么我在一开始几乎是无头苍蝇。先做了个实验在Word里用MathType输入了一个求根公式复制然后粘贴到WordPress后台的Gutenberg编辑器存草稿再去看代码视图。结果是公式被存成了一个img标签图片链接指向了一个WMF转出来的PNG缩放一下边缘全是锯齿。更麻烦的是如果这个Word文档最开始是用WPS做的或者MathType版本比较老粘贴出来的东西可能连img都没有直接就是一段嵌入式的OLE二进制乱码被夹在HTML里。再做一个实验从MathType编辑器窗口本身复制公式粘贴到WordPress得到的是HTML源码里包含了一段MathML片段math标签。但这个MathML存在文章HTML里Google能抓到作者后续想改就抓瞎了——你不可能让每个编辑都在后台源代码里对着math标签改公式。如果切换到经典编辑器TinyMCE情况更微妙它会把MathML转成一个img加alt属性等于彻底丢失了可编辑信息。这个实验让我意识到一个关键问题公式粘贴的“格式”不是单一的剪贴板里带了多种格式最后落成什么取决于接收方优先解析哪一种。而默认情况下Web编辑器优先解析HTML里的图片和富文本结构MathML被当成生僻标签给过滤或者降级处理了。1.3 目标定义这条链路要打通成什么样经过这几轮踩雷我给自己定的目标是这样的作者在MathType编辑器或者Word里的MathType公式对象复制公式粘到WordPress后台系统自动完成以下流程。拦截粘贴识别出剪贴板中的数学公式内容MathML优先LaTeX兜底。前端实时渲染出公式预览作者能确认自己贴对了。公式源MathML/LaTeX作为独立资源上传到服务器并注册进媒体库方便后续查找。同时生成一张SVG格式的显示图嵌入到文章正文中保证清晰度和加载速度。文章保存后点击这张显示图可以反查并下载对应的公式源文件拿到MathType桌面端打开继续修改。这套流程的核心不是把公式做成图片扔上去而是让“粘贴公式”这件事同时具备两个属性读者看到的是高质量显示图作者和MathType拿到的是可编辑源文件。后面的内容全部围绕这个目标展开。2. 解开剪贴板MathType公式复制时到底带了几层皮2.1 剪贴板里的数据金字塔要真正解决问题必须先搞清楚公式复制那一刻剪贴板里都装了什么。我用一个剪贴板查看工具把MathType公式复制后的内容扒了一遍发现它不是一个单纯的“图片”或“文字”而是一个多格式的数据包。大致结构如下。数据格式内容说明用在哪HTML包含MathML片段的富文本信息最适合Web端提取RTF富文本格式内嵌了MTEF对象和OLE引用桌面端Word/WPS使用纯文本通常是一段LaTeX代码或空格乱码LaTeX兜底方案EMF/WMF矢量图公式的矢量图形表示显示图片源Bitmap位图屏幕分辨率位图快速预览这就像一个金字塔不同的接收方会从里面挑自己认识的层级去读。Word拿到RTF/MTEF能继续编辑浏览器拿到HTML/MathML理论上能渲染图片查看器拿到Bitmap/EMF只能显示。问题在于绝大多数Web编辑器对MathML的支持极其有限古腾堡编辑器虽然不会主动删掉MathML标签但它会当成普通HTML块来管理不会渲染成公式。TinyMCE更狠直接把它简化成图片。所以方案的第一步是在粘贴事件到达编辑器默认处理逻辑之前把剪贴板里的MathML或LaTeX抢出来。2.2 关键开关MathType的Cut and Copy Preferences这里有一个非常容易被忽略的设置项我强烈建议每个用这套方案的人先检查一下。在MathType编辑器的“Preferences”偏好设置菜单里有一个“Cut and Copy Preferences”选项里面可以设置复制公式时额外携带哪些格式。勾选“Include MathML”包含MathML复制公式时剪贴板里才会有完整的MathML源码。勾选“Include TeX”包含LaTeX剪贴板的纯文本区域才会写入LaTeX代码。默认情况下从MathType编辑器窗口复制公式是带MathML的但从Word正文里直接复制公式对象时MathML常常不在剪贴板里因为它走的是OLE/RTF通道。我后来测试过很多版本包括MathType 7.4和7.8结论是要让方案稳定运行必须引导作者在MathType编辑器窗口里复制公式而不是在Word正文里右键复制。这不是我们前端代码能完全兜住的需要在操作指引里写清楚。另外如果用户复制的是纯图片公式比如网页上截的公式图剪贴板里就只有图片没有任何MathML或LaTeX。这种情况不要强行处理直接按普通图片上传走反而更合理。方案只对“携带公式语义”的粘贴行为生效。2.3 为什么MathML才是Web端的“MathType格式”题目的“MathType格式上传”这几个字很多人第一反应是要生成.mtef或者.eq这种MathType私有二进制文件。我一开始也这么想结果研究一圈发现这条路在Web端根本走不通。MTEFMathType Equation Format是MathType专有的二进制格式通常封装在RTF或OLE对象里结构复杂官方从来没有公开完整的解析规范。在浏览器端要从剪贴板的RTF流里解析出MTEF再转成可用的数据工程量极大而且极其脆弱不同版本的MathType生成的MTEF细节还有差异。真正可行的方向是MathML。MathType桌面端从很早版本开始就支持直接把MathML粘贴进去并转为可编辑公式MathType 7对MathML 3的支持已经很成熟。所以Web端把公式保存成MathML文件上传后在运营同学需要改题时下载这个.mml文件用MathType打开照样是原生可编辑的公式。这才是Web场景下对“MathType格式”的正确转译。LaTeX作为第二方案也有价值。部分作者习惯用LaTeX写题或者从其他平台复制LaTeX公式MathType同样能导入LaTeX所以前端解析时LaTeX可以作为兜底。3. 方案选型官方Web集成还是自研粘贴解析管道3.1 MathType官方Web集成做了什么在动手自研之前我认真评估过MathType官方提供的Web集成方案。它面向CKEditor、TinyMCE、/数学编辑器等场景基本思路是在编辑器里嵌入一个MathType公式编辑窗口用户在里面输入或粘贴公式它帮你生成MathML然后用MathJax渲染显示。官方方案的优点是用户能直接弹窗编辑公式对键盘输入和手写识别的支持很好公式输入体验接近桌面端。但具体到我的场景有几个无法接受的问题。它是按编辑器插件形式设计的接入后在博客前台展示的是一个整体式数学编辑器这和“粘贴现有公式”这个场景是错位的。官方集成需要购买商用授权免费版有站点限制和功能阉割。古腾堡编辑器没有官方现成的块集成是要写自定义块去包一层成本并不低。它生成的内容和管理后台媒体库是隔离的公式源文件不会自动上传成附件后续想统一管理、批量导出都会很麻烦。如果只是想在WordPress里做一个“在线数学编辑器弹窗”官方方案依然值得买。但我的需求是打通“Word已有公式→粘贴→归档→可再编辑”这条链路官方方案本质上是在造新公式不适合存量工作流。3.2 自研管道的取舍与适用边界自研方案的核心思路是不改变作者“复制—粘贴”的习惯在后端和前端之间加一层解析与上传逻辑。你能拿到剪贴板里原始的所有格式自己决定保留什么、丢弃什么、存储什么。自研的优点是显而易见的完全可控不依赖第三方授权能深度配合WordPress的附件机制可以按自己的数据结构存MathML源和显示图后续想加OCR反解、批量迁移、数据导出都方便。缺点也很真实前端要处理剪贴板事件和浏览器差异后端要处理REST API和附件注册整个链路比写一个普通插件复杂不少。另外如果粘贴的是Word文档里嵌入的MathType对象经过我的实测稳定拿到MathML的前提是MathType复制设置正确且从编辑器窗口复制。这个限制需要在作者端做操作培训技术代码并不能百分之百兜住所有输入场景。我最终选定的是自研方案。明确边界如下只处理带MathML或LaTeX语义的公式粘贴纯图片粘贴走原生上传不兼容的情况给用户明确提示而不是静默失败。3.3 我最终选定的技术栈技术选型上我尽量选成熟稳定、文档完善、WordPress社区常见的组件避免引入冷门依赖。环节选型理由前端编辑器Gutenberg古腾堡WordPress默认编辑器长期演进方向粘贴拦截原生paste事件不需要框架捕获阶段拦截MathML解析DOMParser XMLSerializer浏览器原生API零依赖LaTeX兜底text/plain直接读取剪贴板纯文本区域公式渲染MathJax 3前端预览兼容MathML和LaTeX社区生态成熟后端接口WordPress REST API自定义路由权限校验、响应规范、上传链路直接复用附件存储自定义上传目录 attachment meta显示图和公式源成对挂载这套组合还有个好处服务器上不需要装额外工具MySQL存储MathML文本足够。SVG生成我选择在后端做而不是依赖前端MathJax把SVG传到服务器主要是为了给服务器留一个统一处理的空间后续如果要加水印、压缩、格式转换都方便。4. 核心实现CtrlV之后的数据流转全链路4.1 前端拦截粘贴事件的正确姿势先看前端。直接在Gutenberg的编辑器内容区域绑定paste监听是不够的因为古腾堡自己有一套粘贴处理逻辑可能会先把内容变成HTML块。正确的做法是在document上以捕获阶段监听paste事件检查剪贴板里是否存在MathML片段如果存在才拦截处理。document.addEventListener(paste, function (event) { const cd event.clipboardData || window.clipboardData; if (!cd) return; const html cd.getData(text/html); // 快速判断是否包含 MathML if (html html.indexOf(math) ! -1) { event.preventDefault(); event.stopImmediatePropagation(); handleMathPaste(cd, event.target); } else if (cd.files cd.files.length) { // 纯图片粘贴走默认上传即可 return; } }, true);这里两个细节很重要。第一必须用捕获阶段true如果只在冒泡阶段监听古腾堡可能已经把粘贴内容处理掉了。第二检测到MathML后preventDefault和stopImmediatePropagation要同时调用前者阻止默认行为后者确保Gutenberg内部的粘贴监听器不会把它当成普通HTML块插入。4.2 MathML提取与LaTeX兜底解析从text/html里提取MathML不能直接当字符串截取因为不同环境下MathML可能带命名空间前缀比如m:math标签属性顺序也可能不同。最稳的方式是交给浏览器的DOMParser解析成XML文档再用XMLSerializer序列化回来。function extractMathML(htmlString) { const parser new DOMParser(); const doc parser.parseFromString(htmlString, application/xhtmlxml); const nsResolver doc.getElementsByTagNameNS ? doc.getElementsByTagNameNS(http://www.w3.org/1998/Math/MathML, math) : doc.getElementsByTagName(math); if (nsResolver nsResolver.length 0) { return new XMLSerializer().serializeToString(nsResolver[0]); } return null; }注意parseFromString的第二个参数必须用application/xhtmlxml如果用text/html部分浏览器会把MathML标签当成普通HTML节点序列化时会丢失命名空间后面MathJax渲染和MathType识别都会出问题。如果HTML里没有MathML就检查纯文本区域是否包含LaTeX。这里不做复杂判断只需要判断字符串里是否包含LaTeX特征字符如\frac、^、_等命令片段同时排除普通正文文本。function extractLatex(text) { if (!text) return null; const latexPattern /\\[a-zA-Z]|[$]$|\^|_/; if (latexPattern.test(text)) { return text.trim(); } return null; }提取到MathML或LaTeX之后先在后台显示一行预览这个预览用MathJax实时渲染。作者看到预览确认无误点击“插入公式”前端才把数据发给后端。4.3 MathJax渲染预览与显示图生成前端预览我用的MathJax 3直接以组件方式引入把MathML字符串丢给MathJax.typesetPromise()就能渲染没什么坑。重点说一下后端生成显示图这件事。后端生成SVG我选择用MathJax的Node包mathjax-full。在PHP端调用Node脚本有点别扭所以我单独做了一个CLI脚本接收MathML文本输出SVG文件路径。const { mathjax } require(mathjax-full/js/mathjax.js); const { TeX } require(mathjax-full/js/input/tex.js); const { MathML } require(mathjax-full/js/input/mathml.js); const { SVG } require(mathjax-full/js/output/svg.js); const { liteAdaptor } require(mathjax-full/js/adaptors/liteAdaptor.js); const { RegisterHTMLHandler } require(mathjax-full/js/handlers/html.js); const adaptor liteAdaptor(); RegisterHTMLHandler(adaptor); const mml new MathML(); const tex new TeX(); const svg new SVG({ fontCache: local }); const html mathjax.document(, { InputJax: [tex, mml], OutputJax: svg }); function mmlToSvg(mmlString) { const node html.convert(mmlString, { display: true, em: 16, ex: 8, containerWidth: 1000 }); return adaptor.innerHTML(node); } const input process.argv[2]; process.stdout.write(mmlToSvg(input));这个脚本一次只处理一个公式WordPress后端点一次请求执行一次。虽然效率不算高但胜在稳定不会因为并发把内存打爆。如果你公式量很大可以改成常驻Node服务或批量任务我这边单日公式量在几百个量级CLI完全够用。4.4 WordPress侧REST接收与文件挂载后端我注册了一个自定义REST路由接收前端POST上来的公式数据。数据结构简单粗暴{ content: math xmlns\...\.../math, format: mathml, post_id: 123 }收到数据后做三件事把公式源写入自定义上传目录uploads/math/用MathJax脚本生成SVG显示图把SVG注册为媒体库附件并把MathML存为该附件的post_meta字段。add_action(rest_api_init, function () { register_rest_route(math-upload/v1, /formula, [ methods WP_REST_Server::CREATABLE, callback handle_formula_upload, permission_callback function () { return current_user_can(edit_posts); } ]); }); function handle_formula_upload(WP_REST_Request $request) { $content $request-get_param(content); $format $request-get_param(format); $postId intval($request-get_param(post_id)); if (empty($content)) { return new WP_Error(empty_formula, 公式内容为空, [status 400]); } $uploadDir wp_upload_dir(); $mathDir $uploadDir[basedir] . /math; if (!file_exists($mathDir)) { wp_mkdir_p($mathDir); } $fileName eq- . md5($content . time()) . . . ($format latex ? tex : mml); $filePath $mathDir . / . $fileName; file_put_contents($filePath, $content); // 生成SVG显示图 $svgContent exec(node . __DIR__ . /mathjax-cli.js . escapeshellarg($content), $svgOutput, $returnCode); $svgFileName eq- . md5($content . time()) . .svg; file_put_contents($mathDir . / . $svgFileName, implode(\n, $svgOutput)); // 注册媒体库附件 $attachmentId wp_insert_attachment([ post_mime_type image/svgxml, post_title $fileName, post_status inherit, ], $mathDir . / . $svgFileName, $postId); update_post_meta($attachmentId, _math_source_file, $fileName); update_post_meta($attachmentId, _math_source_format, $format); return rest_ensure_response([ attachment_id $attachmentId, url $uploadDir[basedir] . /math/ . $svgFileName, ]); }先别急着抄这段代码有几处明显是示意性的你要根据自己环境调整比如exec执行Node脚本的安全性和超时问题。我实际项目里是把MathJax转换做成了HTTP微服务PHP端wp_remote_post调用这样不会阻塞主进程。另外SVG文件要允许WordPress上传得在upload_mimes过滤器中加上svg|svgz否则媒体库不识别。5. 踩坑实录这些细节不处理方案直接废掉5.1 Gutenberg的粘贴处理器会提前截胡我第一次实现时把监听器绑在编辑器DOM节点上结果粘贴公式后页面直接插入了一段混乱的HTML块公式既没渲染成显示图MathML也丢了。调试了半天才定位到原因Gutenberg使用了自己的paste处理器在事件冒泡阶段就会读取剪贴板并转换成块的属性。解决办法就是前面说的捕获阶段监听stopImmediatePropagation。但还有一个隐藏坑Gutenberg的块编辑区域是动态渲染的某些情况下事件绑定到的目标元素会被React替换掉。我在实际项目里用到的方案是不绑定到特定编辑器DOM而是监听document然后从事件源判断是否处于编辑器可编辑区域内。如果你的站点同时开着经典编辑器插件还要区分处理经典编辑器走TinyMCE自己的粘贴拦截逻辑和古腾堡完全不同。5.2 MathML命名空间与标签序列化的浏览器差异这个坑花了我一个下午。用text/html解析粘贴的HTML片段Chrome会把MathML里的标签渲染成HTMLUnknownElement序列化时命名空间xmlnshttp://www.w3.org/1998/Math/MathML丢失标签变成小写无前缀的math、mrow、mi等。前端用MathJax渲染还能识别但保存到文件里再用MathType打开就报格式错误。解决方式是必须用application/xhtmlxml解析再用XMLSerializer.serializeToString()序列化。还有一个Firefox特有的小问题Firefox对MathML的序列化会在math标签上自动添加xmlns属性这本身没问题但如果你在字符串处理时用了可能破坏XML结构的方法比如正则替换要特别小心属性值的闭合。我后来干脆统一用DOMParserXMLSerializer组合不在前端字符串层面做任何标签替换问题彻底消失。5.3 别把RTF里的MTEF对象当作解析入口写方案过程中我尝试了一条最激进的路直接从剪贴板的RTF二进制流转成MathML。查了很多资料也翻了一些开源项目的代码最终确认这是一个吃力不讨好的方向。RTF里的MTEF对象存在多种变体MathType 6.x和7.x生成的字节结构不同Word在写入RTF时还可能做压缩和转义实际解析成功的概率低到离谱。所以我的最终方案做了明确的用户引导要求作者在MathType编辑器窗口内复制公式而不是在Word正文里直接复制。因为从MathType编辑器复制剪贴板才会稳定携带MathML。从Word正文复制带的是OLE对象MathML经常缺失。如果作者真的在Word正文里复制了前端拿不到MathML会弹出一个提示引导他改从MathType窗口复制。这相当于在方案边界上做了软约束比硬解析RTF靠谱一百倍。5.4 显示图与可编辑源必须成对存储最开始我的实现是前端拿到MathML直接渲染成SVG字符串和MathML一起POST到后端后端存两段文本。听起来没问题但用了一段时间后发现文章里公式图对应的MathML源找不到了。原因是文章的显示图和公式源之间没有任何关联SVG作为附件存在媒体库MathML只是文章HTML里的一个隐藏标签。如果运营同学发现某道题公式错了在媒体库里找到SVG图片但不知道源文件在哪个.mml文件里也没法拿回MathType改。这时候成对存储的价值就体现出来了。现在的做法是每次粘贴生成公式源文件.mml或.tex和显示图文件.svgSVG注册成附件_math_source_file和_math_source_format写到附件meta里。运营在媒体库看到SVG点编辑就能看到公式源文件名下载附件时也能通过meta找到对应源文件。前端显示图上加一个隐藏链接后台编辑状态下点击可以下载MathML源文件双击直接用MathType打开。5.5 权限校验与REST Nonce还有一个很容易踩的坑REST权限。WordPress REST API对未登录用户默认返回rest_cookie_invalid错误但即便登录了直接调wp_remote_post也会遇到nonce校验失败的问题。通用做法是在前端页面上输出wpApiSettings.nonce所有REST请求都要带X-WP-Nonce头并且路由的permission_callback要判断current_user_can(edit_posts)。如果你用了前端模板或自定义登录方式还要额外处理Cookie认证的兼容性。我这个方案里虽然用户已经登录了后台但前端请求毕竟发生在编辑器页面必须确保每次请求头里都携带有效的nonce。fetch(/wp-json/math-upload/v1/formula, { method: POST, headers: { Content-Type: application/json, X-WP-Nonce: wpApiSettings.nonce }, credentials: same-origin, body: JSON.stringify({ content: mathmlString, format: mathml, post_id: currentPostId }) });如果你在控制台测试时发现401先检查wpApiSettings是否在页面中正确输出。没有输出的话在wp_enqueue_scripts里用wp_localize_script传过去。6. 从能用到好用历史公式迁移与MathType再编辑闭环6.1 存量公式图片如何批量反解方案跑通之后我遇到的第一个现实问题是站点里已经有两千多道题的公式是以图片形式存在的有的是PNG截图有的是MathType通过另存为生成的GIF。总不能全部手动重贴一遍。我的做法是分两步走。第一步写一个批量扫描脚本遍历历史文章的HTML找出所有img标签判断alt或title里是否包含公式特征比如MathType导出图片会在alt里写公式的MathML文本或者有特定的class。如果有直接提取出来走新的上传逻辑。第二步对于完全没有任何语义标注的纯公式图用OCR方案批量识别识别成MathML后重新生成SVG并替换。OCR这块我用的是现成API准确率在复杂公式上大概百分之八十到九十识别失败的公式保留原图并在后台标记为“待人工处理”。迁移脚本最核心的原则是不要在迁移过程中删除原图先新老并存人工确认没问题后再批量清理。我在跑迁移脚本时发现有些老文章里的公式图即使识别错了也比直接把原图删掉强毕竟损失可控。6.2 从WordPress里的mml再回到MathType桌面端这套方案最让我满意的地方是“闭环”公式源保存为.mml文件后不只是存档用的它真的能回到MathType桌面端继续编辑。操作流程是这样的在媒体库里找到对应公式的附件记录下载_math_source_file指向的.mml文件在桌面端MathType里按CtrlO打开。MathType 7.x打开标准MathML文件完全没问题编辑完成后在MathType窗口复制公式再粘回WordPress后台前端又会走一遍拦截–解析–上传的流程生成新的公式源和显示图。旧版本SVG和旧公式源会自动保留不会覆盖历史记录。我实测过一个稍微复杂的定积分公式从MathType打开.mml、修改上标、重新复制粘贴整个过程能控制在十几秒内。这比让作者在Word里找原始文档、改完再导出图片、重新上传的流程要顺畅太多了。这里再强调一下MathType版本问题。MathType 6.x打开MathML文件偶尔会弹兼容性提示MathType 7.x则几乎没有问题。如果运营那边还是老版本建议升级这属于配套工具链的必要投入。6.3 我给同类站点的建议清单最后整理一下我这段时间落地这套方案后的建议按优先级排的。先在2-3个测试作者账号上跑一周确认粘贴流程稳定后再全员开放避免上线当天被作者投诉淹没。前端粘贴失败时一定要有明确提示比如“未识别到公式请从MathType窗口复制”。静默失败是体验黑洞。显示图建议用SVG而不用PNG公式放大不模糊且文件体积小很多。但老IE版本不支持SVG如果读者端有老浏览器需要做兼容降级。REST上传接口务必做频率限制不然有人恶意刷接口uploads/math目录会被垃圾文件塞满。MathML源文件也是敏感数据建议定期备份uploads/math目录因为一旦源文件丢失公式就只能以图片形式存在了。媒体库里SVG附件的缩略图在部分主题下可能不显示这是WordPress默认不生成SVG缩略图导致的可以装一个SVG支持插件或者手动在附件meta里补一张PNG预览图。如果站点开启了CDNSVG文件记得设置正确的Content-Type: image/svgxml否则部分CDN会把它当纯文本输出导致公式直接显示成XML源码。我这套方案在正式环境跑了三个多月累计处理了一万多个公式失败率大概是百分之三左右绝大多数失败都来自同一个原因作者没有从MathType编辑器窗口复制而是从Word正文直接复制导致缺少MathML。后来我在编辑器顶部加了一条黄色提示条失败率就降到百分之零点五以下了。所以这种链路型方案技术实现是一方面操作引导对稳定性的影响往往被低估。如果你也在折腾类似的需求不妨先花一晚上把MathType的复制设置和作者操作习惯统一好再写代码会省很多事。
