容質(zhì)量檢查流水線:從錯別字到失效鏈接的全面校驗)
前陣子我在整理自己博客后臺時翻到一篇半年前閱讀量還不錯的舊文發(fā)現(xiàn)里面躺著一個前期完全沒注意到的錯別字還有一個早就失效的外部鏈接。那種感覺很難形容就像精心布置的客廳里墻角偏偏有一塊沒擦干凈的污漬。也就是從那天開始我給自己立了個小目標(biāo)所有內(nèi)容在發(fā)布之前都必須達(dá)到 impeccable 的狀態(tài)。這個詞源于拉丁語原意是“無可指摘、沒有瑕疵”放在內(nèi)容創(chuàng)作里指的不是文采有多驚艷而是“沒有低級錯誤、邏輯通順、結(jié)構(gòu)一致、鏈接和引用都站得住腳”。這篇文章就記錄我是怎么把“無可挑剔”從一個感覺拆成具體可執(zhí)行的檢查流程并搭建了一套內(nèi)容質(zhì)量流水線。不管你是寫博客、做技術(shù)文檔還是日常發(fā)布運營文案這套思路都能直接套用。1. 項目立項為什么把“無可挑剔”當(dāng)成工程問題大部分內(nèi)容創(chuàng)作者都有過這樣的體驗發(fā)布之前檢查了三遍發(fā)布之后第二天再看還是發(fā)現(xiàn)某個地方不順暢。問題不在于你不夠認(rèn)真而在于“認(rèn)真檢查”本身是不可量化的。只要沒有明確規(guī)則每一次校對都是在憑感覺碰運氣。所以我當(dāng)時的第一反應(yīng)不是繼續(xù)逼自己多讀幾遍而是把“impeccable”當(dāng)成一個工程目標(biāo)去拆解。1.1 所謂 impeccable到底指什么如果只說“高質(zhì)量”“無瑕疵”這句話等于沒說。因為每個人對質(zhì)量的理解不一樣作者覺得把話說通順就夠了編輯可能會盯著標(biāo)點符號和術(shù)語一致性讀者關(guān)心的則是信息是否準(zhǔn)確、引用是否可靠。為了讓全家人都在同一張桌子上吃飯我先把“impeccable”拆成了四個可驗證的層次。第一層是拼寫與語法。錯別字、漏字、主謂不一致、標(biāo)點誤用這些是最容易被讀者察覺的問題也是拉低信任感的頭號殺手。第二層是風(fēng)格與可讀性。句子是否太長、被動語態(tài)是否過多、重點是否被埋在冗長表達(dá)里。第三層是結(jié)構(gòu)與格式一致性。標(biāo)題層級是否合理、代碼塊是否規(guī)范、列表是否統(tǒng)一、配圖是否都有說明。第四層是事實與鏈接可靠性。引用的數(shù)據(jù)是否真實存在、外鏈?zhǔn)欠襁€活著、內(nèi)部錨點是否跳到了正確位置。這四個層次可以對應(yīng)到不同的工具和檢查手段。剛開始我列了一個簡單對照表后面所有選型都圍繞這張表展開。層次核心檢查內(nèi)容典型問題主要工具拼寫與語法錯別字、語法、標(biāo)點“的地得”混淆、英文單詞拼錯LanguageTool、編輯器拼寫檢查風(fēng)格與可讀性句子長度、被動語態(tài)、用詞長句堆砌、語氣生硬Hemingway、Vale結(jié)構(gòu)與格式Markdown規(guī)范、標(biāo)題層級標(biāo)題跳級、代碼塊缺語言標(biāo)注markdownlint、prettier事實與鏈接外鏈有效性、內(nèi)部錨點、數(shù)據(jù)來源鏈接404、引用數(shù)字失真lychee、自定義腳本1.2 為什么肉眼檢查靠不住人眼對自家文字有一種“慣性忽略”。這是因為我大腦里裝的不是文章本身而是“我想表達(dá)的意思”所以閱讀時總會自動修正那些明顯的錯誤。加上寫作時的注意力集中在組織語言上校對屬于第二任務(wù)大腦根本沒有切換到糾錯模式。我拿自己做了一次小樣本對比一篇大約1500字的文章認(rèn)認(rèn)真真讀一遍找出錯別字和格式問題用時接近十分鐘結(jié)果后來用工具跑一遍仍然能查出兩處術(shù)語不一致和一個失效外鏈。不是說人工校對沒用而是純靠人眼做不到穩(wěn)定復(fù)用狀態(tài)好時能抓出很多問題狀態(tài)差時基本白看。工具的作用不是替代作者而是充當(dāng)一條兜底線把所有機械的、可枚舉的檢查點交給程序處理讓作者把精力留給真正需要判斷力的地方。2. 工具選型給文字裝上質(zhì)檢儀說實話市面上能用的文字檢查工具很多但沒有任何一個能覆蓋全部四個層次。我的選型原則很簡單優(yōu)先選能本地運行、規(guī)則可配置、跟主流編輯器與 CI 能順利集成的工具。這樣不依賴網(wǎng)絡(luò)服務(wù)也不容易被商業(yè)產(chǎn)品的封閉格式綁架。目前我保留的主力工具就四個LanguageTool、Vale、markdownlint、lychee。2.1 拼寫與語法層LanguageToolLanguageTool 是開源項目支持中文、英文、德文、法文等二十多種語言而且本地部署也很方便。它既可以作為桌面客戶端使用也可以在 VS Code 里以插件形式跑甚至能通過 HTTP API 接入到自建流程中。我個人最喜歡的一點是它把“拼寫錯誤”和“語法問題”分開報告方便我配置不同嚴(yán)重級別。實際使用中我發(fā)現(xiàn)它對英文語法的識別已經(jīng)相當(dāng)能打比如冠詞缺失、主謂不一致、時態(tài)誤用這些常見問題都能抓到。中文也能識別一部分錯別字和搭配問題但準(zhǔn)確率不如英文版本誤報率也會偏高。所以我在配置里會把中文檢查的嚴(yán)重級別調(diào)低一些只保留“明確錯誤”級別。Grammarly 我也試過體驗很流暢尤其是瀏覽器插件幾乎是無感存在。但它的致命問題有兩個一個是文檔長期存在云端對內(nèi)容隱私敏感的場景不友好另一個是對中文幾乎無能為力。如果你只寫英文Grammarly 值得考慮但如果你和我一樣是中英文混寫LanguageTool 是更踏實的底座。2.2 風(fēng)格與可讀性Hemingway 和 ValeHemingway Editor 是一個風(fēng)格檢查工具核心邏輯就是“讓句子更短、更直接”。它會把過長的句子標(biāo)成黃色把特別拗口的句子標(biāo)成紅色還會統(tǒng)計被動語態(tài)、副詞、復(fù)雜詞數(shù)量。它很直觀適合用來做內(nèi)容修改的輔助閱讀。但說實話Hemingway 更適合英文內(nèi)容中文支持基本為零所以我通常只把它用在英文版本地化前的內(nèi)容判斷階段。Vale 則完全不同它是一個基于規(guī)則的文本檢查引擎不對語言本身做判斷而是根據(jù)你寫的規(guī)則去掃描文本。只要你能用 JSON 或 YAML 定義規(guī)則Vale 就能嚴(yán)格按規(guī)則執(zhí)行。比如我可以規(guī)定“凡是產(chǎn)品名稱出現(xiàn)時必須使用統(tǒng)一寫法”“禁止使用‘非常’這種弱化表達(dá)”“每個標(biāo)題長度不能超過40個字”。這就是它最強的地方把團隊的風(fēng)格規(guī)范變成機器能執(zhí)行的檢查項。Vale 的安裝很簡單在項目目錄放一個.vale.ini配置文件里面定義樣式規(guī)則包路徑和目標(biāo)文件后綴。啟動時它會自動讀取配置并掃描指定目錄下的 Markdown 或 HTML 文件。后面我會展示一個最小可用配置初學(xué)者照抄也能跑起來。2.3 結(jié)構(gòu)與鏈接完整性markdownlint 和 lychee很多人寫 Markdown 容易忽略格式問題標(biāo)題跳級了、列表縮進不一致、代碼塊沒寫語言類型、圖片缺少替代文本。這些問題不會影響發(fā)布結(jié)果但是會嚴(yán)重影響文檔質(zhì)量和后續(xù)維護體驗。markdownlint 就是為了治理這類問題存在的它遵循一套行業(yè)通用的 Markdown 規(guī)范校驗規(guī)則非常細(xì)。檢查鏈接是否有效用的是 lychee。它能遞歸抓取文本里的所有外鏈發(fā)出 HTTP 請求確認(rèn)目標(biāo)是否返回 200。這個工具是我在一次舊文排查中被刺激之后才加進工作流的——那篇文章里有一個鏈接指向的頁面早就變成 404 了但發(fā)布時完全沒人發(fā)現(xiàn)。加上 lychee 之后每次提交前跑一遍就能把這種低級問題直接擋在門外。3. 核心流程落地一條可復(fù)用的內(nèi)容校驗流水線工具選好了接下來就是把它們組織成一條穩(wěn)定可執(zhí)行的流程。我的原則是“三個階段、三道防線”寫作階段靠編輯器實時提醒提交階段靠 Git 鉤子強制校驗協(xié)作階段靠 CI 統(tǒng)一跑全量檢查。每一道防線目標(biāo)不同互相之間不沖突也不重復(fù)。3.1 本地寫作階段讓編輯器實時提醒在寫作階段我最看重反饋速度。只有在錯誤出現(xiàn)的那一刻就把它標(biāo)出來作者才來得及一邊寫一邊修。如果等寫完整篇文章才去跑一次檢查很多人會面對一堆錯漏直接擺爛。我用 VS Code 作為主力編輯器配了三個插件LanguageTool 插件、markdownlint 插件、Prettier。LanguageTool 負(fù)責(zé)語法和錯別字markdownlint 負(fù)責(zé)格式警告Prettier 負(fù)責(zé)格式統(tǒng)一。保存文件時自動格式化能解決掉一大半標(biāo)點、空格、縮進的問題。需要注意一點不要把插件的警告級別全部拉滿。剛開始我把 markdownlint 的所有規(guī)則都開了結(jié)果編輯器滿屏都是黃色波浪線反而看不清重點。后來我調(diào)整策略只保留高價值的規(guī)則比如標(biāo)題層級、代碼塊語言標(biāo)注、列表縮進那些關(guān)于空行數(shù)量、行寬限制的規(guī)則直接關(guān)掉。工具是輔助不是用來制造焦慮的。3.2 提交階段用 Git 鉤子擋住低級錯誤編輯器實時提醒只能解決“作者愿意看提示”的場景。要是趕稿時昏了頭完全可能忽略所有警告直接提交。這時候需要一道更加剛性的門禁提交時自動跑檢查失敗就不允許提交。我用 pre-commit 框架來管理 Git 鉤子。只要在.pre-commit-config.yaml里聲明要跑的檢查工具每次執(zhí)行g(shù)it commit時它就會自動運行。路徑很簡單repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - repo: https://github.com/igorshubovych/markdownlint-cli rev: v0.41.0 hooks: - id: markdownlint args: [--config, .markdownlint.json] - repo: https://github.com/lycheeverse/lychee rev: v0.15.1 hooks: - id: lychee args: [--config, .lychee.toml]注意pre-commit 鉤子只檢查本次提交涉及的文件不會全量掃描整個倉庫。這樣設(shè)計是對的提交階段要快、要輕只攔截當(dāng)前改動可能引入的問題。把全量檢查放在 CI 階段才合理。3.3 CI 階段全量校驗合并到主分支前本地鉤子只對做過了配置的人生效。如果團隊協(xié)作其他成員可能沒有安裝 pre-commit或者干脆用不同編輯器那很多問題到了合并請求階段才會暴露。所以我在 CI 里再增加一道全量校驗由服務(wù)器統(tǒng)一執(zhí)行。假設(shè)你正在用 GitHub可以在.github/workflows/quality.yml里配置這樣一個任務(wù)name: content-quality on: pull_request: branches: [main] jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - name: Run markdownlint uses: DavidAnson/markdownlint-cli2-actionv15 with: globs: docs/**/*.md - name: Run Vale run: | curl -L --output vale.deb \ https://github.com/errata-ai/vale/releases/download/v3.2.0/vale_3.2.0_Linux_64-bit.deb sudo dpkg -i vale.deb vale sync vale docs/ --minAlertLevelerror - name: Check links run: lychee --config .lychee.toml docs/README.md docs/guide/*.mdCI 階段一般比較慢因為要拉依賴、裝工具、跑全量掃描但它在發(fā)布線路上可以接受。更重要的是它讓質(zhì)量門禁和具體某臺電腦無關(guān)任何人在任何環(huán)境提交代碼最終都要通過同一套標(biāo)準(zhǔn)。4. 實操過程中踩過的坑與排查記錄任何流程優(yōu)化真正有價值的往往不是順利跑通的那一刻而是后續(xù)維護中不斷涌現(xiàn)的坑。我在這套內(nèi)容質(zhì)量流水線跑了大半年中間至少推翻過三次配置也收到過來自同事的多次吐槽。這里挑幾個最具有代表性的問題聊聊。4.1 誤報太多導(dǎo)致檢查形同虛設(shè)流水線剛上線的時候我?guī)缀醢?LanguageTool 的所有規(guī)則都打開了。結(jié)果第一次全量掃描出現(xiàn)了一千多處警告其中一半以上是無傷大雅的風(fēng)格建議比如“這個詞可以換一個更正式的同義詞”“這個句子可以考慮拆分”。等到需要人工處理這些問題時幾乎沒人愿意碰那堆報告檢查就慢慢流于形式。后來我明白了質(zhì)量檢查工具最怕的不是跑出來的問題太多而是問題里泥沙俱下導(dǎo)致真正嚴(yán)重的問題被淹沒。解決辦法很簡單收縮規(guī)則集寧缺毋濫。我把 LanguageTool 的嚴(yán)重級別調(diào)到只保留錯誤級別關(guān)掉了大部分風(fēng)格類建議markdownlint 也只保留不過關(guān)會被讀者一眼發(fā)現(xiàn)的規(guī)則。第一次全量掃描的警告數(shù)從上千條降到幾十條這個數(shù)量才是人可以也愿意處理的。4.2 中英文混排怎么處理我的博客和技術(shù)文檔基本都是中英文混合的內(nèi)容遇到的問題很典型LanguageTool 會把英文單詞“impeccable”當(dāng)成拼寫錯誤因為它默認(rèn)中文文檔里不該出現(xiàn)英文同時它又把“VS Code”這種專有名詞拆開檢查導(dǎo)致誤報。Vale 的默認(rèn)規(guī)則對中文也幾乎是白紙一張很多英文風(fēng)格建議在中文本地化語境下根本不適用。我的解決方式是分語言配置。LanguageTool 里開啟“多語言自動檢測”讓它識別當(dāng)前句子的主語言而不是用單一語言規(guī)則去套所有內(nèi)容。Vale 這邊則完全放棄默認(rèn)的英文風(fēng)格包只保留我手工編寫的、針對文檔場景的自定義規(guī)則。另外中英文之間加空格的問題我直接交給 Prettier 解決保存時統(tǒng)一在中英文之間插入空格避免標(biāo)題和段落里出現(xiàn)排版參差不齊的情況。4.3 規(guī)則配置的“最少夠用”原則這條經(jīng)驗是從誤報問題延伸出來的。很多工具給足了規(guī)則集新手容易陷入一種錯覺規(guī)則開得越多質(zhì)量就越有保障。實際操作中規(guī)則越多意味著誤報越多、噪音越大、維護成本越高最終大概率會被人悄悄跳過。我后來給自己定了一條鐵律每條規(guī)則都必須能回答“它到底預(yù)防了什么事故”。如果一條規(guī)則在三個月內(nèi)都沒有命中過我會直接刪掉如果一條規(guī)則出現(xiàn)超過五次誤報我會調(diào)整它的觸發(fā)條件。做好記錄很重要我每次調(diào)整規(guī)則都會隨手在配置目錄里留下備注說明改動原因。這里也分享一個小技巧當(dāng)某篇需要特殊處理的文檔出現(xiàn)例外情況時不要直接關(guān)掉工具而是用行內(nèi)注釋比如 markdownlint 支持!-- markdownlint-disable MD024 --Vale 支持!-- vale off --。這樣既保證了極少數(shù)的合理例外又不會讓整個文檔失去檢查覆蓋。5. 從“措辭正確”到“內(nèi)容可信”拼寫、語法、格式、鏈接這些都屬于“可枚舉的問題”工具可以解決得很徹底。但 impeccable 還有一個層次是工具不太好覆蓋的那就是內(nèi)容本身是否可信可靠。尤其在今天大量內(nèi)容都由 AI 參與生成表面順滑的文字背后可能藏著根本沒有依據(jù)的數(shù)據(jù)這個問題變得比以往更突出。5.1 給 AI 生成內(nèi)容單獨加一道核查工序我現(xiàn)在的工作流里有一個專門針對 AI 初稿的額外階段。AI 生成的文本往往沒有拼寫錯誤語法也很漂亮但它會在最關(guān)鍵的地方一本正經(jīng)地編造事實。比如它可能給出一個看起來很真實的數(shù)據(jù)引用但那個數(shù)據(jù)根本沒有出處也可能把某個產(chǎn)品的發(fā)布時間說錯到完全對不上。所以凡是 AI 參與生成或輔助的內(nèi)容我會強制要求做到三件事第一所有主張、數(shù)據(jù)、結(jié)論必須能追到原文鏈接或可核對的來源第二涉及具體數(shù)量、日期、名稱的信息單獨建立一份清單逐項人工驗證第三用 lychee 把所有引用鏈接跑一遍確認(rèn)不是發(fā)布時才知道鏈接失效。這一步無法自動化替代但能通過流程把它變成強制動作而不是可選項。5.2 建立“發(fā)布前清單”把最后一道門留給人工具能檢查的只是形式層真正判斷“內(nèi)容有沒有價值”這件事只能由人來做。我在流程末尾放了一份發(fā)布前清單每次內(nèi)容準(zhǔn)備上線前都會逐項過一遍觀點是否清晰邏輯是否完整有沒有未驗證的數(shù)據(jù)目標(biāo)讀者讀完后能帶走什么這些動作不依賴任何工具但它恰好是保證內(nèi)容不至于淪為“語法正確卻沒有靈魂”的關(guān)鍵。我目前的建議是工具負(fù)責(zé)處理“看起來對不對”人負(fù)責(zé)處理“讀起來有沒有用”。兩者配合才更接近真正意義上的 impeccable。這套內(nèi)容質(zhì)量流水線從搭起來到現(xiàn)在幫我擋掉的至少包括幾十個錯別字、十幾個失效外鏈還有無數(shù)個格式不規(guī)范。更重要的是它讓“認(rèn)真校對”這件事不再是隨狀態(tài)起伏的主觀動作而變成一個穩(wěn)定執(zhí)行的標(biāo)準(zhǔn)流程。如果你也經(jīng)常發(fā)布內(nèi)容我的建議是先別追求一步到位挑一個最容易讓你感覺“丟臉”的檢查項加進流程哪怕最開始只有一個工具也比沒有強。