03 / 真實套件案例 / 閱讀約 7 分鐘
slugify:為什麼 URL 裡還有「!」?
「Déjà Vu!」 變成了「deja-vu!」,但你想要的是「deja-vu」。用 REA 分析這個 JavaScript 套件,找到控制標點的設定,再驗證結果。
本頁內容
直接看答案
lower: true 只會把大寫字母改成小寫。再加上 strict: true 就能同時移除標點。這是需要開啟的選項,並非庫本身的錯誤。
slugify("Déjà Vu!", { lower: true, strict: true })
// → "deja-vu"01. 我們想要的 URL
slug 是 URL 末尾便於閱讀的一段,例如 deja-vu (完整 URL 為 example.com/posts/deja-vu)。本範例使用真實的 slugify 1.6.6 npm 發行版本。下方結果來自在本機執行該版本。
試試下方標題,再開啟 移除標點符號 看看差別。
還有「!」?請開啟 移除標點符號。
{ lower: true, strict: false }在瀏覽器本機執行,不上傳任何內容。REA 的使用見文字教學。
下面是同樣的 JavaScript 比較:
slugify("Déjà Vu!")
// → "Deja-Vu!"
slugify("Déjà Vu!", { lower: true })
// → "deja-vu!"重音符號消失了,感嘆號卻還在。我們用 REA 定位套件入口檔案,讀取過濾程式碼,並查明哪個選項會移除感嘆號。你可以按下方步驟重現。
02. 下載套件,用 REA 分析
我們下載了固定版本的 npm tarball,解壓時沒有安裝或執行套件。以下準備指令需要 shell 中有 tar:
mkdir rea-slugify-case
cd rea-slugify-case
npm pack [email protected]
tar -xzf slugify-1.6.6.tgz隨後,我們對解壓後的 package 目錄執行 REA 的 JavaScript 應用程式分析器:
如果更習慣使用 AI 程式開發代理,請替換路徑並貼上這段提示詞:
使用 REA 分析 /absolute/path/to/rea-slugify-case/package。我用 slugify 生成文章 URL。為什麼 slugify('Déjà Vu!', { lower: true }) 會保留感嘆號?找到入口檔案,展示允許保留它的程式碼,並指出移除它的選項。不要修改套件。也可以直接在終端機收集分析結果:
npx -y [email protected] analyze-javascript-application ./package --json > analysis.jsonREA 將套件識別為 slugify,版本為 1.6.6,入口為 ./slugify.js。報告紀錄了三個相關檔案,解析失敗數為零;同時將整體圖覆蓋範圍標記為 partial(部分覆蓋),我們在釋出的摘要中保留了這一點。
這是可讀的 JavaScript 發行包。REA 提供了檔案清單和分析上下文,隨後透過原始碼檢查和直接驗證確認行為,未涉及原生程式碼反編譯。
03. 找到移除標點的選項
在發行套件的 slugify.js中,第 33–42 行完成字串正規化、語言或字元對映替換,以及字元過濾。預設過濾規則明確允許感嘆號。
// remove not allowed characters
.replace(options.remove || /[^\w\s$*_+~.()'"!\-:@]+/g, '')
}, '');
if (options.strict) {
slug = slug.replace(/[^A-Za-z0-9\s]/g, '');
}strict 分支隨後執行,移除字母、數字和空白以外的字元。小寫轉換是第 57–58 行的獨立操作。由此可以提出一個可測試的預測:
slugify("Déjà Vu!", { lower: true, strict: true })
// should return "deja-vu"同一檔案也解釋了為什麼多個空格合併成一個分隔符,為什麼 & 變成 and,以及為什麼德語設定會改變 Ä 變為 AE。
04. 在真實套件上執行驗證
我們對未經修改的 1.6.6 版本執行了八項斷言,包括最初的問題和幾個相關行為。
原始套件 · Node.js 22.23.1 · macOS arm64
| 輸入 | 選項 | 實際結果 |
|---|---|---|
| Déjà Vu! | 預設 | Deja-Vu! |
| Déjà Vu! | lower | deja-vu! |
| Déjà Vu! | lower + strict | deja-vu |
| hello world(兩側有空格) | 預設 | hello-world |
| Rock & Roll | 預設 | Rock-and-Roll |
| Äpfel | 德語設定 + lower | aepfel |
| 空字串 | 預設 | 空字串 |
| 42(數字) | 預設 | 丟擲「string argument expected」錯誤 |
檢視已紀錄的驗證結果,或使用上方互動示範。示範在瀏覽器中執行同一固定版本的套件。
05. 我們測試了什麼
對於這個版本和這些輸入,原始碼與實際輸出一致。如果想得到 deja-vu,請同時使用 lower: true 和 strict: true。
注意驗證範圍。 八項驗證不能覆蓋所有 Unicode 或語言設定行為。REA 的關係圖並不完整;圖中缺少某個關係,並不能證明關係不存在。我們沒有重建原生二進位檔案,也沒有恢復無法取得的原始碼。
發行套件中的原始碼可讀,因此直接檢查原始碼也是可行方法。這個案例示範完整的分析習慣:確認分析物件,檢查一條規則,再對照原始實作驗證結論。
06. 下載並執行這個範例
下載小型重現資料包,其中包含固定版本的依賴、全部八項斷言,以及收集 REA 證據的步驟。
npm install --ignore-scripts
node verify.mjs斷言指令碼會列印每項結果,任一驗證失敗時以錯誤退出。只有到這一步,Node.js 才會執行 npm 套件;此前 REA 的靜態分析不會執行它。
試試另一篇教學查明應用程式把匯出檔案儲存在哪裡。