跳轉到

D-20260704-01|主題系統三件套(token+manifest+fallback)

背景與驅動力

使用者提案:樣式 / 圖檔 / 圖示 /LOGO/ 音樂與程式碼脫鉤——程式碼只保證流程與功能(只認 token 名與資產 key),外觀交給主題;個人選單選主題、主題可分類、逐主題累積歷史(社群討論與分辨的單位)。討論兩輪定案落 spec,新立 canon 主題系統.md 與 impl 程式架構/themes.md

考慮過的選項

  • 分類做成程式側 enum:分類現階段無法確定、日後必須可變更,寫死程式即每次調整都是程式變更——否決。
  • 主題資產共用混放 / 跨主題引用:磁碟混放、垃圾檔無從機器驗證——否決,共用一律靠 fallback。
  • 主題 id 兩案皆否決:純語意名(先到先得 +review 仲裁命名)使搶名有利可圖、純 UUID(自產免仲裁)可讀性歸零——收斂混合案。
  • token+manifest+fallback 三件套(採納)。

決定

  • 三件套模型:token(CSS custom properties+ 資產 key)+manifest(theme.json:id、內嵌多語系 name、category、authors、version、tokens、assets)+fallback(主題只放要覆蓋的、缺項 runtime 落 default;default=fallback 骨幹、CI 驗完備、SW install 預快取,其他主題 lazy 首載不含)。
  • 分類 = 資料非程式 enumcategories.json 註冊表(id+i18nKey、顯示名走字典四語系);起始僅 basic,累積後 PR 加分類 + 改各主題 category 欄——演化 = 純資料 patch、零程式變更。
  • 資產依主題隔離themes/<id>/ 自包含、磁碟零混放、禁跨主題引用;validate 雙向查(引用檔案存在 + 資料夾檔案全被引用)。
  • 主題 id= 混合案 <slug>-<6 位自產隨機尾碼>default 為唯一免尾碼保留 id;slug 不獨占、搶名無意義);id 不可改,僅授權 / 法律下架時登錄 themes/retired-ids.json 永久退役、CI 拒重用。
  • 鐵則:只換皮、不換語意 / 佈局;gameplay 資訊視覺保留 token THEME_RESERVED_TOKENS 不可覆蓋(CI+runtime 雙防);品牌錨點(OG/manifest icons)固定;主題屬純 client 資源 =patch 發版、不上鏈不影響配對;主題與 i18n 正交。

附帶決策

音樂面採播放槽模型(2026-07-05 同脈絡定案):槽位名錄非檔案清單、有檔才播(槽空 = 靜音非錯誤)、default 名錄必列全但值可空;三態語意(路徑 / 省略 = 落 default/null= 明確靜音);保留 SFX 槽 THEME_RESERVED_SFX 恆取 default;轉場常數 BGM_CROSSFADE_MS=1000。同輪砍除場地綁定音樂與玩家自訂 BGM。細節見 程式架構/audio-system.md

AudioContext 的使用者授權與即時執行狀態分離:首次手勢取得本 session 的 unlocked 能力,後續 pointerdown 或回 visible 可對已解鎖、再次 suspended 的 SFX/world context 做 state-aware、 single-flight resume;running/closed 不動,失敗留待下一手勢。此恢復不得重播 BGM。

後果與影響

外觀演化與程式發版脫鉤,社群主題走 PR(validate、review 含資產授權聲明、patch 隨版發);BGM 主題化承接音樂方向懸案。樣式(皮膚)面架構其後由 D-20260723-01 修訂為受控 CSS Style API;token 治理由 D-20260708-10 細化為兩層。