MDeX-2.1.1
v2.1.1
热修: 修复了部分文档编辑区与预览区滚动不同步的问题——编辑器滞后于预览区若干段落,且越往文档后部越明显。
Hotfix: Fixed out-of-sync scrolling between the editor and preview in some documents — the editor lagged behind the preview by several paragraphs, with the issue worsening toward the end of the document.
修复 / Fixes
-
修复编辑↔预览块级对齐错位
问题根因:srcBlockOffsets(预览区每个块对应的源码偏移量)原先是通过按空行\n\n切分源码来定义「块」的,这与marked解析器的实际顶层块划分逻辑不一致。
具体而言,marked会将「标题紧跟列表/段落(中间无空行)」的情况拆分为heading+list两个顶层元素,或将loose list(松散列表)及其续文段落合并为一个list token。这种逻辑差异导致按空行切分得到的块数与marked解析出的实际块数不匹配。错位后果:
renderIntoPreview随后使用children[i] ↔ srcBlockOffsets[i]的方式按下标一一对应分配data-src-offset。一旦出现块数分歧,后续所有偏移量即开始产生单调错位。在一份包含大量「标题紧跟列表」与「列表续文段落」的测试文档中,66 个预览块里有 58 个标注了错误的偏移量。这导致syncAnchors的中线映射将编辑器和预览锚定到了不同的段落,表现为编辑器持续滞后于预览,且越往后偏移越严重。解决方案: 改用
marked.lexer的顶层 token 在源码中按顺序定位每个块的起始偏移。这使得源码映射与预览的顶层元素严格同源、一一对应,从而彻底消除了错位。测试: 附带了
tools/check-align.js(块切分对比工具)与tools/test-align-e2e.mjs(真实浏览器端到端对齐回归测试)。
Fixed Edit↔Preview block-alignment drift
Root Cause:srcBlockOffsets(each preview block's corresponding source offset) was originally derived by splitting the source on blank lines (\n\n). This method did not align withmarked's actual top-level block parsing logic. Specifically,markedsplits "a heading immediately followed by a list/paragraph (no blank line)" into two separate top-level elements (heading+list), while merging loose lists and their continuation paragraphs into a singlelist token. Consequently, the block count obtained by splitting on blank lines differed frommarked's parsed output.Impact:
renderIntoPreviewthen assigneddata-src-offsetby pairingchildren[i]withsrcBlockOffsets[i]based on index. From the first point of divergence, all subsequent offsets began to drift monotonically. In a test document full of "heading-then-list" and "list-continuation" patterns, 58 out of 66 preview blocks were assigned incorrect offsets. This causedsyncAnchorsto map the editor and preview to different paragraphs, manifesting as the editor consistently lagging behind the preview, with the error worsening toward the end.Fix: The offset of each block is now located sequentially using
marked.lexer's top-level tokens. This ensures the source mapping is strictly co-sourced with the preview's top-level elements in a one-to-one correspondence, eliminating the drift.Tests: Added
tools/check-align.js(block-split diff utility) andtools/test-align-e2e.mjs(real-browser end-to-end alignment regression test). -
版本号升级至 2.1.1。 / Version bumped to 2.1.1.
重构 / Refactor
-
app.js 拆分(内部重构,无功能变化)
改动内容: 将 17 种语言的界面文案(I18N,共 491 行)抽离至src/i18n.js;将帮助文档数据(HELP_STRINGS及其依赖项SK/sc/CITE_HELP_*,共 1090 行)抽离至src/help.js。此举使src/app.js从 6580 行缩减至 5006 行(−24%)。实现细节:
app.js内部通过const X = window.X重新引用这些模块(下游 6 处引用零改动)。build-html.mjs现改为拼接i18n + help + app并内联至同一个<script>标签中,保持了单文件离线产物的特性,且无需引入打包器。验证: 经过四层验证确保功能正常:
- 构建成功;
npm test通过 (20/20);- 真实浏览器对齐端到端测试通过(66 个块,0 错位);
- 运行时确认
window.I18N/window.HELP_DATA数据完整,UI 文案与帮助文档显示正常。
**app.js split (internal refactor, no behavior change)** **Changes:** Extracted the 17-language UI strings (`I18N`, 491 lines) into `src/i18n.js` and the help-document data (`HELP_STRINGS` plus dependencies `SK`/`sc`/`CITE_HELP_*`, 1090 lines) into `src/help.js`. This reduced `src/app.js` from 6580 to 5006 lines (−24%).Implementation:
app.jsreimports these modules viaconst X = window.X(zero downstream edits required).build-html.mjsnow concatenatesi18n + help + appinto a single inlined<script>tag, preserving the self-contained offline build without a bundler.Verification: Verified through four layers:
- Build succeeds;
npm testpasses (20/20);- Real-browser alignment e2e test passes (66 blocks, 0 drift);
- Runtime confirmation that
window.I18N/window.HELP_DATAare fully populated, and UI labels/help docs render correctly.