refactor: rewrite template as vanilla JS + esbuild (drop React)#29
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 後會重生並補一個 commitApp.js、Content.js、Helmet.js、lib/link.js、lib/context/config.js、舊Alert.js/InternalLink.js等)真正的新程式碼只有這些,請聚焦:
src/main.js— 入口:讀window.contentConfig、設 title/meta/theme、呼叫renderToHtml、把結果包進.markdown > [data-remove-styles] > divsrc/components/alert.js、src/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 移植,不是新增客製)。/html內建)<div role="region">+ 純文字 variant 名 + 英文back連結,無視覺class="underline"text-[#58B2DC]兩個只有覆寫版才有的細節:
octiconclass 有功能意義——index.css的[data-remove-styles] svg:not(.octicon) { all: revert }靠它放行 icon 樣式href不帶#前綴——照搬 React 版既有行為,本 PR 不順手「修正」拿掉覆寫仍可渲染,但 alert 退化為無 icon、無色彩的素樣式——對舊版匯出是視覺迴歸。
⚙️ 為何用 esbuild 而非 Vite/CRA(重要)
原計畫用 Vite,但 bundle 含
mathjax-full,其 asciimath legacy 有三個硬性限制,逐一淘汰掉其他方案:global→ 需define: { global: 'globalThis' }arguments.callee→ strict mode 會 throw;ESM 一律 strict 且無法關閉(Vite 的<script type="module">出局),Rollup 的 iife 也預設加"use strict",即使設strict: false仍會錯誤處理 mathjax 全域(MathJax is not defined)—— Vite 的 production build 底層是 Rollup,一起出局<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 注入流程不受影響。已知行為(非迴歸)
lib/link.js的彈窗功能本就是 dead code(linkHandler從未被呼叫),一併移除,功能面零損失(詳見 umbrella issue 的元件互動性表)。驗證
npm run build/npm run build-zip— 正常產出;bundle 內無 React runtimemerge 後
依
@coseeing/see-mark@1.11.0重生package-lock.json(補 commit)、npm run build-zip產出新 ZIP 供 Access8MathWeb PR 使用。