冒險書
你正在將一份文件轉變為一段旅程。讀者將一步步穿越一個根據使用者選擇的主題所繪製的插圖故事,而故事中每個標記的詞語都可以點擊,以查看它所代表的真實事物:來自原始文件的實際命令、規則、決策或事實。輸出結果是一個獨立的 .html 檔案,無需任何依賴即可離線運作。
引擎(導航、彈出抽屜、知識庫、進度地圖、視差效果、鍵盤操作、行動版佈局、減少動畫模式)已內建於 assets/template.html 中。scripts/build_book.py 負責將你的內容組裝到該模板中。你的工作是負責創意且忠實於原文的部分:故事、寓意、散文、彈出內容以及場景美術。
三個參考文件承載著這項技藝:references/story.md(結構 — 每次都要閱讀)、references/themes.md(每個主題的語氣和寓意)以及 references/scenes.md(繪圖)。
需要避免的兩種失敗情況是字數過多以及其下沒有故事:一本只為文件章節換上主題服裝,卻將真實事實淹沒在氣氛中的書。少一些文字,一條清晰的旅程。
工作流程
- 閱讀整個原始文件。 注意其標題、事件發生的順序、讀者之後應該能夠做什麼,以及任何容易出錯的事實(確切的命令、名稱、數字、規則)。這些事實正是彈出功能要保護的對象。
- 確定主題和寓意。 採用使用者給定的主題;如果沒有,選擇一個適合該材料的主題,並說明你選擇了哪一個。閱讀
references/themes.md中相應的章節,了解其語氣、主題、英雄原型和階段命名模式。然後為自己寫一個簡短的對應表:原始文件中的每個真實概念及其主題化的對應物(VPN = 面紗,資料庫 = 偉大的馴服野獸,CI 管線 = 試煉場)。在整本書中保持每個對應關係穩定。讀者只學習一次寓意;如果面紗在第四章變成了迷霧,這本書就失去了教導作用。 - 塑造故事。 在規劃任何內容之前,先閱讀
references/story.md並為這本書填寫其故事主軸:英雄必須達到的目標、引導他們到達那裡的「因為那樣」的連鎖反應、他們在接近尾聲時犯下的錯誤,以及這本書結束時的畫面。一份文件是一系列章節的列表;一本書是一連串的因果後果,將前者轉化為後者是全部的工作。不要因為原始文件看起來像一個簡單的清單就跳過這一步——那些正是會變成投影片秀的類型。 - 規劃階段。 目標是 5 到 9 個,每個階段一個節拍,對應到故事主軸上(一個抵達階段、三到六個升級的中間階段、一個出錯的階段、一個收穫成果的階段)。每個階段通常對應原始文件的一個章節:合併那些內容太薄弱、無法承載一個節拍的章節,並拆分那些需要超過約 120 字敘述的章節。按讀者需要知識的順序來安排階段,這通常就是文件的順序。為每個階段賦予一個符合主題語氣的標題,以及一個
source:標題,以便讀者可以從階段內部展開原始章節。 - 在一個工作資料夾中編寫內容檔案(
book.json、stages/NN-name.md、scenes/*.svg)。格式如下。 - 刪減,然後執行檢查清單。 根據「書寫故事」一節重新閱讀每個階段,刪除大約三分之一的文字;初稿幾乎總是所需長度的兩倍,而你刪除的每一句話都會使標記的詞語更容易被看到。然後執行
references/story.md末尾的檢查清單,並修正失敗的部分。這兩件事都在你構建之前完成;它們都不是可選的潤飾步驟。 - 構建並閱讀警告。 修正每一個「沒有找到 id 為... 的彈出內容」、「未找到標題」和覆蓋範圍的警告。重新構建,直到報告乾淨,或者每個剩餘的警告都是故意的。
- 驗證並交付。 開啟檔案(在 macOS 上使用
open <file>.html),或至少在可用時使用 headless Chrome 對其進行截圖。告訴使用者檔案的位置、如何瀏覽(方向鍵、點擊地圖、點擊發光的文字),以及你使用了哪個主題。
內容格式
book.json(路徑相對於 JSON 檔案):
{
"title": "尋找傳送門的任務",
"subtitle": "一位騎士在 AGENTS.md 中的旅程",
"theme": "knight",
"source": "../AGENTS.md",
"cover": { "eyebrow": "互動式冒險", "scene": "scenes/cover.svg", "blurb": "cover.md" },
"stages": [ "stages/01-gates.md", "stages/02-forge.md" ],
"ending": { "scene": "scenes/ending.svg", "blurb": "ending.md",
"recap": [ "在進行任何其他操作之前,先穿過[[面紗|vpn]]", "每個套件都帶有 `@internal/` 旗標" ] }
}
每個階段都是一個 Markdown 檔案:
---
id: gates
title: 城堡的大門
chapter: 第一章
source: 本地開發環境設定
scene: scenes/01-gates.svg
---
迷霧籠罩著通往城堡的道路。一名衛兵擋住了去路:除非你已經穿過[[面紗|vpn]],否則任何人都不得進入……
## popout: vpn
title: VPN
在進行任何其他操作之前,你必須先連上公司 VPN,因為內部套件註冊表和服務只能從內部網路訪問。
構建腳本會強制執行或警告的規則:
- 每個散文欄位都是 Markdown。每個場景都是內聯 SVG,以
.svg檔案的路徑給出。 [[顯示文字|id]]標記一個彈出連結;[[docker]]使用文字本身作為 id。每個 id 需要在同一階段中有一個## popout: id區塊(或在book.json中有一個書本層級的popouts陣列)。- 前言中的
source:指定原始文件中的一個標題。腳本會逐字提取該章節,並在「原始捲軸」按鈕背後顯示它。一個彈出區塊也可以帶有source: <heading>,將其相關章節附加在其說明下方——但它必須位於彈出內容的標題行中,緊接在## popout: id下方,與title:一起,而不是在說明之後。如果放錯位置,它會被靜默地視為散文,而該章節將不會被覆蓋。 - 主題是一個預設名稱(
knight、space、pirate、noir、expedition、deepsea)或一個物件{ "extends": "knight", "colors": {...}, "fonts": {...}, "vocabulary": {...} }。預設主題位於assets/themes.json;複製一個作為自創主題的起點。
構建:
python3 <skill-dir>/scripts/build_book.py --content work/book.json --out <name>.html
書寫故事
第二人稱、現在式、每個階段一個場景和一個節拍。「你」就是英雄。一個階段不是對一個地點的描述;而是發生在某處的一件事。你到達,你遇到一個人或一個問題,你做一件事,然後你帶著改變或更好的裝備離開。如果一個階段歸結為「你在某個地方,那裡很有氣氛」,那麼它還沒有節拍:在原始文件的章節中找到一個——讀者必須做的事、他們不能犯的錯、所做的決定——並圍繞它構建場景。
堅持你規劃好的形狀。 references/story.md 是結構的權威:開頭就陳述目標,階段之間用「因此」和「但是」而非「然後」來連接,中間階段逐步升級,接近尾聲時有一個真正的錯誤,一個重複出現的主題或攜帶的物品……