跪拜 Guibai
← All articles
Frontend

Motie Turns Markdown Into WeChat-Ready HTML With Inline Styles, Not Preview Polish

By Dragon_xjy ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

WeChat’s editor is a lossy paste target, and Motie’s inline-style pipeline is a useful pattern for any tool that ships formatted HTML across platform boundaries: verify against the real paste destination, not the preview. The concrete fixes show that copy/paste fidelity, not visual polish, is where Markdown-to-publisher tools live or die.

Summary

Motie is a static web page that takes Markdown, runs it through Marked and DOMPurify, and emits inline-styled HTML used for preview, rich-text copy, and file export. The same HTML goes to the clipboard, so formatting survives leaving the page as long as the target editor respects element-level styles. Marked, DOMPurify, highlight.js, and Lucide are bundled with the page, so opening it requires no CDN requests.

One round of real use showed where preview-only thinking fails. Code blocks using just `white-space: pre-wrap` lost line structure in WeChat, so Motie now writes explicit `<br>` tags, non-breaking spaces, and two-column tabs. Task-list checkmarks were split into separate paragraphs, so `☑`/`☐` are embedded in the same paragraph as the item text. Bare reference URLs no longer render as “URL: URL”, and existing `[1]`/`[2]` numbering is preserved. A regression sample document lets every future change be checked against the same article.

UI work removed a nested iframe that created double vertical scrollbars, then hid scrollbars while keeping wheel, touch, and keyboard scrolling. Images can be pasted at the cursor or dragged in as PNG/JPG/WebP/GIF, with per-image replacement by local file or full URL, though local images live only in page memory. Version 1.1.0 passes 44 local tests, but the project’s own checklist treats real WeChat draft paste and mobile preview as the final acceptance step, because tool-side success doesn’t equal the target platform accepting images and styles.

Takeaways
— Motie is a static web page: paste Markdown, inspect the preview, copy, and paste into the WeChat Official Account editor; it does not handle login, asset upload, or publishing.
— The conversion pipeline is Markdown → Marked parsing → DOMPurify sanitization → code/image/list/reference-link handling → inline styles → preview/copy/export.
— The same inline-styled HTML feeds preview, rich-text copy, and export so styling does not depend on the page’s own CSS classes.
— Marked, DOMPurify, highlight.js, and Lucide are bundled locally; the page makes no CDN requests.
— Code blocks preserve line breaks with explicit <br> tags, spaces with non-breaking spaces, and tabs as two columns; `white-space: pre-wrap` alone is not reliable in WeChat.
— Task-list markers `☑`/`☐` are placed in the same paragraph as the item text; for already split content, only the marker and first sentence are merged.
— Bare reference URLs no longer duplicate as “URL: URL”, and existing `[1]`/`[2]` numbering is preserved.
— Double scrollbars in the preview were fixed by removing the nested iframe and letting the outer canvas scroll; the scrollbar is hidden but wheel, touch, and keyboard scrolling still work.
— Preview widths cap at 375px for mobile and 680px for desktop, shrinking when the panel is narrow.
— Images can be pasted at the cursor or added as PNG/JPG/WebP/GIF and replaced per image with a local file or full HTTP/HTTPS URL; local images remain only in page memory and are not bundled with Markdown drafts.
— Version 1.1.0 reports 44 passing local tests (26 conversion, 18 UI logic) and returned HTTP 200 on GitHub Pages when checked on October 22, 2026.
— The editor has 200ms debounce, so immediate copy triggers a conversion refresh before the clipboard reads the current body.
— Tests use jsdom and a clipboard stub; final acceptance requires pasting into a real WeChat draft and checking the mobile preview.
Conclusions

Preview panes are structurally the wrong place to debug copy/paste tools: every significant bug in this round appeared only after pasting into WeChat, because the target editor reinterprets the HTML. A regression corpus built from one real article catches more than a larger suite of synthetic cases.

Bundling dependencies into the page is a quiet reliability decision: a static file that makes no CDN requests will keep converting Markdown even when the network or a third-party CDN misbehaves.

The 200ms debounce test is the kind of UI timing detail that unit suites usually miss; a copy button that reads stale content after immediate input is exactly the failure users hit and developers don’t.

Turning “make it look nicer” into concrete checks like “no scrollbar but full text readable” is what makes AI-assisted iteration reviewable. Without that translation, neither a human nor a model has a way to know whether a change landed.

Concepts & terms
Inline styles
CSS rules written directly on each element through style attributes. Motie uses them so formatting survives when HTML is copied into editors that ignore <style> blocks or external stylesheets.
DOMPurify
A JavaScript library that sanitizes HTML by removing executable or dangerous content. Motie runs Marked’s output through it before generating rich text.
Anti-leech
A server policy that rejects image requests based on the referrer header, so an image that loads in Motie may show as broken after pasting into WeChat’s editor.
Debounce
A timing technique that waits until input pauses before running a handler. Motie’s editor waits 200ms after the last keystroke, so a copy action must flush pending conversion before reading the current content.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗