Skip to content

refactor: rewrite template as vanilla JS + esbuild (drop React)#29

Merged
jamliaoo merged 7 commits into
mainfrom
template-html-adapter
Jun 30, 2026
Merged

refactor: rewrite template as vanilla JS + esbuild (drop React)#29
jamliaoo merged 7 commits into
mainfrom
template-html-adapter

Conversation

@jamliaoo

Copy link
Copy Markdown
Contributor

Summary / 動機

Template 職責是「載入內容、靜態渲染」,沒有複雜的互動所以不需要 React(react/react-dom/react-scripts/@craco/craco/react-helmet/@headlessui/@heroicons/sweetalert2…)。改用 @coseeing/see-mark/html 後,可完全脫離 React,build 也更單純。

移除:React 全家桶、craco、helmet、headlessui、heroicons、sweetalert2、prop-types、testing-library。
新增esbuild;保留 tailwindcss/postcss/autoprefixer(透過 Node API 編譯);@coseeing/see-mark@^1.11.0

📌 給 reviewer:diff 很大,但只有 6 個檔

這個 PR 的 diff 絕大部分是雜訊

  • package-lock.json 刪除(~39k 行)— 因為 see-mark 改用本地路徑開發;發佈 1.11.0 後會重生並補一個 commit
  • 拔除 React 相關檔案(App.jsContent.jsHelmet.jslib/link.jslib/context/config.js、舊 Alert.js/InternalLink.js 等)

真正的新程式碼只有這些,請聚焦:

  • src/main.js — 入口:讀 window.contentConfig、設 title/meta/theme、呼叫 renderToHtml、把結果包進 .markdown > [data-remove-styles] > div
  • src/components/alert.jssrc/components/internal-link.js — 兩個 vanilla 覆寫元件(取代舊 React 版)
  • scripts/pipeline.mjs / build.mjs / dev.mjs — esbuild + postcss/tailwind 建置
  • public/index.html — 改為 classic <script>(content-config.js 先載、main.js 後載)

為何需要 alert / internal-link 覆寫

設計分界:SeeMark 的 default components 只保證語意與無障礙正確,視覺保持中性;外觀由 consumer 覆寫帶入(React adapter 同樣如此——main 分支的 Content.js 本來就覆寫這兩個元件,本 PR 是 1:1 移植,不是新增客製)。

SeeMark default(/html 內建) Template 覆寫
alert <div role="region"> + 純文字 variant 名 + 英文 back 連結,無視覺 GitHub 風格:5 種 variant 的 Octicon SVG icon、各自文字/邊框色、中文「返回」backlink
internalLink class="underline" 加上品牌藍 text-[#58B2DC]

兩個只有覆寫版才有的細節:

  • icon 的 octicon class 有功能意義——index.css[data-remove-styles] svg:not(.octicon) { all: revert } 靠它放行 icon 樣式
  • alert backlink 的 href 不帶 # 前綴——照搬 React 版既有行為,本 PR 不順手「修正」

拿掉覆寫仍可渲染,但 alert 退化為無 icon、無色彩的素樣式——對舊版匯出是視覺迴歸。

⚙️ 為何用 esbuild 而非 Vite/CRA(重要)

原計畫用 Vite,但 bundle 含 mathjax-full,其 asciimath legacy 有三個硬性限制,逐一淘汰掉其他方案:

  1. 引用 Node 的 global → 需 define: { global: 'globalThis' }
  2. arguments.calleestrict mode 會 throw;ESM 一律 strict 且無法關閉(Vite 的 <script type="module"> 出局),Rollup 的 iife 也預設加 "use strict",即使設 strict: false 仍會錯誤處理 mathjax 全域(MathJax is not defined)—— Vite 的 production build 底層是 Rollup,一起出局
  3. 匯出網站需支援雙擊(file://)開啟,而 <script type="module"> 在 file:// 被 Chrome CORS 擋 → 必須是 classic script,任何 ESM 輸出方案都不行

→ 需求收斂成「非 strict 的 iife + classic script + 支援 global define」,採 esbuild iife 一次解決三個問題。輸出結構(build/index.html + build/static/{js,css})與舊 CRA 一致,Access8MathWeb 的 ZIP 注入流程不受影響。

bundle size:JS 約 2.1MB(gzip ~720KB),大宗是 mathjax;拔 React 省的是 React/ReactDOM 那部分。真正收益是「脫離 React 生態 + 更簡單的 build」。

已知行為(非迴歸)

  • media modal:舊版 lib/link.js 的彈窗功能本就是 dead code(linkHandler 從未被呼叫),一併移除,功能面零損失(詳見 umbrella issue 的元件互動性表)。
  • 連結樣式:外部連結維持與舊 React 匯出一致(純文字)——連結著色 CSS 僅存在於 Access8MathWeb app 的預覽區,從未在 Template 內。

驗證

  • npm run build / npm run build-zip — 正常產出;bundle 內無 React runtime
  • 真實瀏覽器 smoke test(詳見 umbrella issue):匯出站台全語法元件正確渲染、a11y(math sr-only/aria-hidden)正常、file:// 雙擊可開

merge 後

@coseeing/see-mark@1.11.0 重生 package-lock.json(補 commit)、npm run build-zip 產出新 ZIP 供 Access8MathWeb PR 使用。

jamliaoo added 7 commits June 13, 2026 12:24
Phase 1C: the exported-website template no longer needs React. It renders a
single static document, so it now uses @coseeing/see-mark/html (the new HTML
adapter) + plain DOM, dropping react, react-dom, react-scripts/craco,
react-helmet, @headlessui, @heroicons, sweetalert2, prop-types, and the
testing stack.

Entry is src/main.js: read window.contentConfig, set title/meta/theme, call
renderToHtml() with the Alert and InternalLink custom components (rewritten as
(props, childrenHtml) => htmlString), and assign the sanitized result to
the see-mark 1.11 payload keys (display/target), fixing a latent mismatch with
the old text/id keys.

Build uses esbuild (not Vite/Rollup): mathjax-full's asciimath legacy code
needs a NON-STRICT, classic-script bundle with a `global` shim. esbuild's iife
output provides exactly that; Rollup (Vite) emits "use strict" and mishandles
mathjax's global, and ESM module scripts also fail to load over file://.
The esbuild bundle is a classic script, so the exported site works both over
http and by opening index.html directly (file://). Tailwind CSS is compiled
via the postcss + tailwindcss + autoprefixer Node APIs in scripts/build.mjs.

Output layout (build/index.html + build/static/{js,css}) and scripts/pack.sh
are unchanged, so Access8MathWeb's ZIP injection keeps working. Verified in a
real browser (agent-browser) over both http and file://: headings, all five
alert variants with icons, latex + asciimath math (MathML + SVG), images,
internal links, and theming all render correctly.

package-lock.json is removed; it will be regenerated once see-mark 1.11.0 is
published (this branch can't resolve ^1.11.0 from the registry until then).
/simplify pass: build.mjs and dev.mjs duplicated the whole CSS +
esbuild + copy-public pipeline (clean dirs, postcss/tailwind compile,
iife esbuild config with the `global` shim, public copy). Move the
shared parts into scripts/pipeline.mjs so dev and prod stay in lockstep
instead of being hand-synced; each script keeps only its own delta
(build = one-shot minified Promise.all, dev = watch + serve).

Output structure and behavior unchanged.
see-mark folded the /html/utils subpath into /html (one entry per
adapter); same named exports, new path.
@jamliaoo jamliaoo marked this pull request as ready for review June 29, 2026 15:13
@jamliaoo jamliaoo requested a review from wendyyuchensun June 29, 2026 15:55

@wendyyuchensun wendyyuchensun left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try, thanks.

@jamliaoo jamliaoo merged commit 136bb9d into main Jun 30, 2026
1 check passed
@jamliaoo jamliaoo deleted the template-html-adapter branch June 30, 2026 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants