[譯] sphinx-js 介紹 - Javascript 專案的文件工具

很長一段時間在 javascript 專案,文件的部分並沒有什麼好用的工具。JSDoc 大概是這個領域中唯一的競爭者,並且其設計中有些非常不錯的地方:

jsdoc 本質上是程式碼中的註解,通過特定格式的註解搭配指令工具協助我們產生文件,另外也有許多 IDE 使用它來支援提示說明的功能。

  • 明確定義用於描述的結構像是 @constructor, @param 等標籤非常清楚。
  • 像是 Closure COmpiler 這類工具在編譯過程中處理該定義的標籤。

雖然許多編譯工具支援解析這種註解結構但輸出的僅僅只是一個列表針對 functino 或片段程式碼說明的整理而已。根據產出的說明,新的使用者大概可以快速理解整個輪廓和參數的用法。這對小型的函式庫或 API 來說非常實用了。但對於大型專案包含著複雜的概念時就不是這邊方便了。如果我們想要在這些擷取自註解的文件上作點組織編排,加上解釋和介紹,編寫整個段落的說明並附上連結等等,jsdoc 就顯得不夠出色了。

Python 的開發者們長期以來一直習慣使用 Sphinx 來作為它們的專案文件工具,同時這個工具支援許多語言也可以根據需求匯出不同格式的文件,它所支援的索引功能,搜尋,引用參考更顯出這個工具的強大。

甚至有人使用它撰寫了一本書,通過搭配一些套件例如:圖表、Youtube 影片等等都可以產生。不過台的 javascript 版本一直不支援從程式碼擷取文件說明的功能。

現在,sphinx-js 支援了這個功能,給 javascript 開發者一個兩全其美的方案。

sphinx-js 一樣採用標準 jsdoc 的註解格式,您不需要在程式中在加入其他髒髒的東西。事實上它解析的部分仍然是交給 jsdoc 處理。我們只需要在專案的根目錄中初始化 docs 目錄,接著就可以使用 reStructuredText 來撰寫組織文件了,那麼我們該怎麼組織文件呢?我們可以使用 sphinx-js 提供的語法,參考 autodoc 的範例。大致上使用起來像下面這個範例:

1
.. autofunction:: linkDensity

然後 sphinx 就會自動去找到該 function:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* Return the ratio of the inline text length of the links in an element to
* the inline text length of the entire element.
*
* @param {Node} node - The node whose density to measure
* @throws {EldritchHorrorError|BoredomError} If the expected laws of the
* universe change, raise EldritchHorrorError. If we're getting bored of
* said laws, raise BoredomError.
* @returns {Number} A ratio of link length to overall text length: 0..1
*/
function linkDensity(node) {
...
}

接著產生文件

當我們想要追加一些比較長得範例時,我們就可以體會到 sphinx 的彈性了,不需要在 linkDensity 上面的註解加東西。而是在 reStructuredText 檔案。

1
2
3
4
.. autofunction:: linkDensity

Anything you type here will be appended to the function's description right
after its return value. It's a great place for lengthy examples!

另外針對 ECMAScript 2015 不管時構造函數還是新的 class 語法糖都可以使用 @class 標記,它會自動遍歷類別成員產生文件。您也可以控制其順序、把 private 的類別成員關閉顯示、所有 sphinx 在 python 支援的功能都可以使用。

比起已經非常成熟的 python 慣例 sphinx-js 還支援了參考的用法以避免在同一個 js 物件實例同名碰撞的情況。例如 一個物件有一個靜態方法 foo同時又有一個物件實例方法 foo 這個時候就可以使用 jsdoc 的 namepaths。舉例來說:

  • object#foo 是物件實例的方法
  • object.foo 是靜態方法
  • object~foo 是內部成員或函數

由於 jsdoc 仍然負責處理分析註解的任務,所以我們可以利用其相對理解 js 的優勢。因為 js 語言巢狀的特性使得它可以變得非常複雜,誰會希望自己編寫寫下面這樣的完整路徑

1
some/file.Class#InstanceMethod.staticMethod~innerMember

幸好,sphinx-js 會自動索引採用 suffix tree 的演算法,簡單說就是會由後面判斷回來,所以我們可以直接就用 innerMember 就好,那如果有另外一個物件也有一個同樣名稱的 innerMember 呢?那我們就往前加一層 staticMethod~innerMember 以此類推直到兩者都成為唯一值。這讓我們可以不用總是寫完整路徑。

使用非常成熟的 sphinx 搭配 jsdoc 的優勢:sphinx-js 成為了一個非常傑出的文件工具,給我們一個新的方式來組織大型 js 專案的文件。如果您已經躍躍欲試的話可以先參考sphinx-js 入門,如果您需要參考一些範例可以看看Fathom 文件 - Rule and Ruleset Reference

資源

[譯] sphinx-js 介紹 - Javascript 專案的文件工具

https://andyyou.github.io/2017/08/01/sphinxjs/

作者

andyyou(YOU,ZONGYAN)

發表於

2017-08-01

更新於

2023-12-05

許可協議