跳转到主要内容

支持在JSDoc文档的JS代码上使用Sphinx

项目描述

为什么

当你编写一个JavaScript库时,你如何向人们解释它?如果它是一个用户熟悉的领域的较小项目,JSDoc的字母表顺序的例程列表可能就足够了。但在一个较大的项目中,穿插散文与您的API文档很有用,而无需复制和粘贴内容。

sphinx-js 允许您在 JS 项目中使用业界领先的 Sphinx 文档工具。它提供了一系列指令,模仿了以 Python 为中心的 autodoc 指令,用于将 JSDoc 格式的文档拉入 reStructuredText 页面。而且,因为您可以在代码中继续使用 JSDoc,您将与您的其他 JS 工具(如 Google 的 Closure Compiler)保持兼容。

sphinx-js 还与 TypeScript 兼容,使用 TypeDoc 工具代替 JSDoc,并输出所有预期的类型信息。

设置

  1. 安装 JSDoc(如果您正在编写 TypeScript,则安装 TypeDoc)。该工具必须在您的 $PATH 上,因此您可能希望全局安装它

    npm install -g jsdoc

    …或者…

    npm install -g typedoc

    已知 JSDoc 3.6.3 和 4.0.0 以及 TypeDoc 0.15.0 可以正常工作。

  2. 安装 sphinx-js,这将作为依赖项拉入 Sphinx 本身

    pip install sphinx-js
  3. 通过运行 sphinx-quickstart 并回答它的问题,在您的项目中创建一个文档文件夹

    cd my-project
    sphinx-quickstart
    
      Please enter values for the following settings (just press Enter to
      accept a default value, if one is given in brackets).
    
      Selected root path: .
    
      You have two options for placing the build directory for Sphinx output.
      Either, you use a directory "_build" within the root path, or you separate
      "source" and "build" directories within the root path.
      > Separate source and build directories (y/n) [n]:
    
      The project name will occur in several places in the built documentation.
      > Project name: My Project
      > Author name(s): Fred Fredson
      > Project release []: 1.0
    
      If the documents are to be written in a language other than English,
      you can select a language here by its language code. Sphinx will then
      translate text that it generates into that language.
    
      For a list of supported codes, see
      https://sphinx-doc.cn/en/master/usage/configuration.html#confval-language.
      > Project language [en]:
  4. 在生成的 Sphinx conf.py 文件中,通过将其添加到 extensions 来启用 sphinx_js

    extensions = ['sphinx_js']
  5. 如果您要记录 TypeScript,请将 js_language = 'typescript' 也添加到 conf.py 中。

  6. 如果您的 JS 源代码不在项目的根目录,请在 conf.py 中单独添加 js_source_path = '../somewhere/else'。您的 JS 源代码树根应该位于该设置所指的位置,相对于 conf.py 文件。默认值 ../ 适用于在项目根目录中存在 docs 文件夹且源代码直接位于根目录的情况。

  7. 如果您有特殊的 JSDoc 或 TypeDoc 配置,请将 jsdoc_config_path = '../conf.json'(例如)也添加到 conf.py 中。

  8. 如果您只记录 JS 或 TS 以及没有其他语言(如 C),则可以在 conf.py 中将您的“主域”设置为 JS

    primary_domain = 'js'

    (即使您正在编写 TypeScript,域也是 js。)然后您可以在下面的指令中省略所有的“js:”前缀。

使用

简而言之,在 Sphinx 项目中,使用以下指令来拉入您的 JSDoc 文档,然后告诉 Sphinx 在您的文档目录中运行 make html 以渲染所有内容。如果您从未使用过 Sphinx 或编写过 reStructuredText,这里是其 教程的下一部分。为了快速入门,只需将内容添加到 index.rst,直到您证明一切正常。

autofunction

首先,使用标准 JSDoc 格式记录您的 JS 代码

/**
 * 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 - Types or not: either works.
 * @throws {PartyError|Hearty} Multiple types work fine.
 * @returns {Number} Types and descriptions are both supported.
 */
function linkDensity(node) {
    const length = node.flavors.get('paragraphish').inlineLength;
    const lengthWithoutLinks = inlineTextLength(node.element,
                                                element => element.tagName !== 'A');
    return (length - lengthWithoutLinks) / length;
}

然后,使用 sphinx-js 指令引用您的文档。我们的指令与 Sphinx 的标准 autodoc 指令非常相似。您可以仅指定函数的名称…

.. js:autofunction:: someFunction

…那么,一个格式良好的文档块将显示在您的文档中。

您还可以添加自己的显式参数列表,如果您想注明可选参数的话

.. js:autofunction:: someFunction(foo, bar[, baz])

参数属性和解构参数也工作得很好,使用 标准的 JSDoc 语法

/**
 * Export an image from the given canvas and save it to the disk.
 *
 * @param {Object} options Output options
 * @param {string} options.format The output format (``jpeg``,  ``png``, or
 *     ``webp``)
 * @param {number} options.quality The output quality when format is
 *     ``jpeg`` or ``webp`` (from ``0.00`` to ``1.00``)
 */
function saveCanvas({ format, quality }) {
    // ...
}

提取默认参数值也正常工作。这些行为如预期,但有几点需要注意

/**
 * You must declare the params, even if you have nothing else to say, so
 * JSDoc will extract the default values.
 *
 * @param [num]
 * @param [str]
 * @param [bool]
 * @param [nil]
 */
function defaultsDocumentedInCode(num=5, str="true", bool=true, nil=null) {}

/**
 * JSDoc guesses types for things like "42". If you have a string-typed
 * default value that looks like a number or boolean, you'll need to
 * specify its type explicitly. Conversely, if you have a more complex
 * value like an arrow function, specify a non-string type on it so it
 * isn't interpreted as a string. Finally, if you have a disjoint type like
 * {string|Array} specify string first if you want your default to be
 * interpreted as a string.
 *
 * @param {function} [func=() => 5]
 * @param [str=some string]
 * @param {string} [strNum=42]
 * @param {string|Array} [strBool=true]
 * @param [num=5]
 * @param [nil=null]
 */
function defaultsDocumentedInDoclet(func, strNum, strBool, num, nil) {}

您甚至可以添加额外的内容。如果您这样做,它将出现在任何提取的文档下方

.. js:autofunction:: someFunction

    Here are some things that will appear...

    * Below
    * The
    * Extracted
    * Docs

    Enjoy!

js:autofunction 拥有一个选项,即 :short-name:,对于实现细节不希望暴露的链式API来说,这个选项非常有用。当你在类方法中使用它时,包含的类在文档中不会被提及,函数将在索引中显示其简称,并且交叉引用也必须使用简称(:func:`someFunction`)。

.. js:autofunction:: someClass#someFunction
   :short-name:

autofunction 还可以用于使用 @callback 标签 定义的回调。

虽然实验性地支持将 autofunction 用于文档化 @typedef 标签,但结果将被格式化为函数样式,并且 @property 标签将误导性地归入“参数”标题下。不过,这总比没有好,直到我们能够正确地处理它。

autoclass

我们提供了一个 js:autoclass 指令,它通过拼接类的注释和构造函数注释来文档化类。它共享了 js:autofunction 的所有功能,甚至可以使用相同的 :short-name: 标志,这对于内部类来说非常有用。使用它的最简单方法是调用它的 :members: 选项,这将自动文档化你类中所有的公共方法和属性。

.. js:autoclass:: SomeEs6Class(constructor, args, if, you[, wish])
   :members:

你可以通过以下方式添加私有成员…

.. js:autoclass:: SomeEs6Class
   :members:
   :private-members:

隐私由 JSDoc 的 @private 标签或 TypeScript 的 private 关键字确定。

使用 :exclude-members: 标签通过名称排除某些成员。

.. js:autoclass:: SomeEs6Class
   :members:
   :exclude-members: Foo, bar, baz

或者明确列出你想要列出的成员。我们将尊重你的排序。

.. js:autoclass:: SomeEs6Class
   :members: Qux, qum

在明确列出成员时,你可以包括 * 来包含所有未提及的成员。这有助于控制某些元素的排序,而不必包含详尽的列表。

.. js:autoclass:: SomeEs6Class
   :members: importMethod, *, uncommonlyUsedMethod

最后,如果你想要完全控制,可以通过嵌入 js:autofunctionjs:autoattribute 逐个拉取你的类成员。

.. js:autoclass:: SomeEs6Class

   .. js:autofunction:: SomeEs6Class#someMethod

   Additional content can go here and appears below the in-code comments,
   allowing you to intersperse long prose passages and examples that you
   don't want in your code.

autoattribute

这对于文档化公共属性很有用。

class Fnode {
    constructor(element) {
        /**
         * The raw DOM element this wrapper describes
         */
        this.element = element;
    }
}

然后,在文档中…

.. autoclass:: Fnode

   .. autoattribute:: Fnode#element

这也是文档化 ES6 风格的 getter 和 setter 的方法,因为它省略了函数后面的 ()。假设的实践是通常的 JSDoc:只文档化你的 getter/setter 对中的一方。

class Bing {
    /** The bong of the bing */
    get bong() {
        return this._bong;
    }

    set bong(newBong) {
        this._bong = newBong * 2;
    }
}

然后,在文档中…

.. autoattribute:: Bing#bong

使用路径名避免歧义

如果你在不同文件中有同名的对象,请使用路径名来区分它们。这里有一个特别长的例子

.. js:autofunction:: ./some/dir/some/file.SomeClass#someInstanceMethod.staticMethod~innerMember

你可能已经认识到了来自 JSDoc 名称路径 的分隔符 #.~;在这里它们工作方式相同。

为了简洁,你可以使用任何唯一的后缀,只要它由完整的路径段组成。假设它们在源树中是唯一的,它们都将与上述内容等效。

innerMember
staticMethod~innerMember
SomeClass#someInstanceMethod.staticMethod~innerMember
some/file.SomeClass#someInstanceMethod.staticMethod~innerMember

注意事项

  • 我们使用简单的文件路径,而不是 JSDoc 的 module: 前缀或 TypeDoc 的 external:module: 之一。

  • 我们独家使用简单的反斜杠转义,而不是在路径中途切换转义方案;JSDoc 本身 也在朝这个方向发展。需要转义的字符是 #.~(/,尽管你不需要在开头的 ./../ 中转义点。一个极其糟糕的路径可能是一个…

    some/path\ with\ spaces/file.topLevelObject#instanceMember.staticMember\(with\(parens
  • 相对路径相对于配置中指定的 js_source_path。不允许绝对路径。

在幕后,sphinx-js会将所有分隔符更改为点,以便...

  • Sphinx的“缩短”语法工作::func:`~InwardRhs.atMost` 打印为仅仅是 atMost()。(目前,你应该始终使用点而不是其他名称路径分隔符:#~。)

  • Sphinx索引更具信息性,说明方法属于其类。

通过设置主要域名来节省键盘敲击次数

为了节省一些键盘敲击,您可以在 conf.py 中设置 primary_domain = 'js',然后说(例如)autofunction 而不是 js:autofunction

配置参考

js_language

根据您使用的语言使用“javascript”或“typescript”。默认为“javascript”。

js_source_path

要扫描的目录列表(非递归)以查找 JS 或 TS 源文件,相对于 Sphinx 的 conf.py 文件。如果只有一个,则可以是一个字符串。如果有多个,则必须指定 root_for_relative_js_paths。默认为“../”。

jsdoc_config_path

到 JSDoc 配置文件的 conf.py 相关路径,如果您想指定自己的 JSDoc 选项,例如递归和自定义文件名匹配,这很有用。如果使用 TypeDoc,您也可以指向 tsconfig.json 文件。

root_for_relative_js_paths

相关的 JS 实体路径相对于此路径解析。如果只有一个项,则默认为 js_source_path

jsdoc_cache

JSDoc 输出将缓存的文件的路径。如果省略,每次 Sphinx 运行时都会运行 JSDoc。如果您有大量的源文件,则可能有助于配置此值。但请注意:如果您的源代码更改,则不会自动刷新缓存;您必须手动删除它。

示例

使用大多数 sphinx-js 功能的好例子是 Fathom 文档。一个特别有趣的部分是 https://mozilla.github.io/fathom/ruleset.html。单击“查看页面源代码”链接以查看原始指令。

ReadTheDocs 是 Sphinx 文档的官方托管平台,现在作为可选的测试版支持 sphinx-js。将以下内容放在您存储库根目录下的 .readthedocs.yml 文件中

requirements_file: docs/requirements.txt
build:
  image: latest

然后,在 docs/requirements.txt 中放置您想要的 sphinx-js 版本。例如...

sphinx-js==3.1.2

或者,如果您愿意,Fathom 存储库包含一个 Travis CI 配置 和一个 部署脚本,用于使用 sphinx-js 构建文档并将它们发布到 GitHub Pages。您可以自由借用它们。

注意事项

  • 我们不了解内联 JSDoc 结构,如 {@link foo};您现在必须使用 Sphinx 风格的等效项,例如 :js:func:`foo`(或者如果您在 conf.py 中设置了 primary_domain = 'js',则简单地为 :func:`foo`)。

  • 到目前为止,我们理解和转换了JSDoc块标签 @param@returns@throws@example(不包括可选的 <caption>)、@deprecated@see 及其同义词。其他标签将消失在虚空中。

测试

使用tox运行测试,这将还会安装JSDoc和TypeDoc的指定版本

pip install tox
tox

版本历史

3.2.2:(2023年9月20日)
  • 移除对Sphinx的版本上限要求。(#227)

  • 停止支持Python 3.7。(#228)

感谢Will Kahn-Greene!

3.2.1:(2022年12月16日)
  • 修复对静态函数的xrefs。(#178)

  • 添加对jsdoc 4.0.0的支持。(#215)

感谢xsjad0和Will Kahn-Greene!

3.2.0:(2022年12月13日)
  • 在静态方法前添加“static”。

  • 固定Jinja2和markupsafe版本。(#190)

  • 跟踪依赖项;不读取所有文档。这提高了增量更新的速度。(#194)

  • 支持Python 3.10和3.11。(#186)

  • 支持Sphinx >= 4.1.0。(#209)

  • 修复对 js_source_path 配置项的类型警告。(#182)

感谢Stefan ‘hr’ Berder、David Huggins-Daines、Nick Alexander、mariusschenzle、Erik Rose、lonnen和Will Kahn-Greene!

3.1.2:(2021年4月15日)
  • 移除对 docutils 的声明依赖,以解决pip的贪婪依赖解析器对Sphinx最新版本的处理方式。当pip安装sphinx-js时失败,因为pip首先看到了我们的“任何版本的docutils”声明(贪婪解析到最新版本,0.17),但后来遇到了Sphinx的似乎新的 <0.17 约束并放弃。当pip的 --use-feature=2020-resolver 成为默认时,我们可以撤销这个操作。

3.1.1:(2021年3月23日)
  • 重写后缀树的大部分内容,该树用于路径查找。这修复了几个崩溃问题。

3.1:(2020年9月10日)
  • 重新设计语言分析。现在在JSDoc-和TypeDoc生成的JSON与渲染器之间有一个良好的文档记录的中间表示形式。这应该会大大加快合并PR的速度。

  • 重写TypeScript分析引擎的大部分内容,以便将其馈入新的IR。

    • 如果代码库中包含任何重载函数,TypeScript分析以前会崩溃。现在不再发生这种情况;我们现在任意使用每个重载函数的第一个函数签名。

    • 添加对TS类中的静态属性的支持。

    • 支持TS中的可变参数。

    • 支持TS中的交叉类型(foo & bar)。

    • 从类和接口中删除“导出自”模块链接。函数从未有过。让我们看看我们是否会错过它们。

    • TS对象的路径名现在不再在文件路径段后面使用 ~;现在它们使用 .,就像JS一样。

    • 更一般地说,TS路径名现在与JS路径名一样。在文件名前不再有 external: 前缀,在命名空间名称前不再有 module: 前缀。

    • TS分析器不再关心当前工作目录是什么。

    • 测试现在只断言它们关心的事情,而不是变得脆弱到禁止任何更改。

  • 不再显示在参数列表中的完全无用的参数,既没有描述也没有类型信息。

  • 除非手动使用 :members: 排序,否则类属性现在列在方法之前。

3.0.1:(2020年8月10日)
  • 当在对象路径上遇到 ../ 前缀时不再崩溃。这可能在设置 root_for_relative_js_paths 在JS代码内部时在后台发生。

3.0:(2020年7月14日)
  • 与Sphinx 3兼容,该版本需要Python 3。

  • 停止对Python 2的支持。

  • 使sphinx-js不在意当前工作目录是什么,除了TypeScript分析器,它需要进一步的工作。

  • 正确转义RST返回类型。

2.8:(2019年9月16日)
  • 正确显示泛型TypeScript类型。将字段放在方法之前。(Paul Grau)

  • 在TypeScript类顶部合并构造函数和类文档。(Sebastian Weigand)

  • 将pytest作为测试运行器。(Sebastian Weigand)

  • 为大型代码库添加JSDoc输出的可选缓存。(Patrick Browne)

  • 修复TypeScript中联合类型的显示。(Sebastian Weigand)

  • 修复从typedoc 0.14.0开始出现的解析破坏。(Paul Grau)

  • 修复TypeScript中的一个数据输入崩溃。(Cristiano Santos)

2.7.1:(2018年11月16日)
  • 修复在Windows上有时会发生UTF-8崩溃的问题。#67。

  • 始终使用conf.py的目录作为JSDoc的工作目录。#78。(Thomas Khyn)

2.7:(2018年8月2日)
  • 添加实验性TypeScript支持。(Wim Yedema)

2.6:(2018年7月26日)
  • 添加对@deprecated@see的支持。(David Li)

  • 优雅地通知并记录JS可变参数。(David Li)

  • 向代码库添加lint工具。

2.5:(2018年4月20日)
  • 使用文档化的@params来帮助填写函数的形式参数列表。这使我们不会错过使用解构的参数。(flozz)

  • 改进JSDoc缺失时的错误报告。

  • 将提取的默认值添加到生成的形式参数列表中。(flozz和erikrose)

2.4:(2018年3月21日)
  • 支持@example标签。(lidavidm)

  • 在Windows下工作。在此之前,我们几乎找不到任何文档。(flozz)

  • 正确展开多行JSDoc标签,即使它们有Windows行结束符。(Wim Yedema)

  • 停止对Python 3.3的支持,因为Sphinx也已经停止支持。

  • 修复在Sphinx >=1.7.1下使用recommonmark(用于Markdown支持)时的构建时崩溃。(jamrizzi)

2.3.1:(2018年1月11日)
  • 在Windows上找到jsdoc命令,其中它有一个不同的名称。然后修复进程通信,使其不会挂起。

2.3:(2017年11月1日)
  • 添加在autoclass :members:选项中说出“*”的能力,这意味着“和我没有明确列出的一切成员”。

2.2:(2017年10月10日)
  • 添加对@callback标签的autofunction支持。(krassowski)

  • 添加对@typedef标签的实验性autofunction支持。(krassowski)

  • 当JSDoc找不到任何JS文件时,添加一个友好的错误信息。

  • 更紧密地锁定six,以确保python_2_unicode_compatible肯定可用。

2.1:(2017年8月30日)
  • 允许在js_source_path中使用多个文件夹。这对于逐步迁移大型项目非常有用,一次一个文件夹,到JSDoc。引入root_for_relative_js_paths以保持相对路径在多个源路径面前不模糊。

  • 聚合PathTaken错误,并一次性报告它们。这意味着您在清理大型项目时不必重复运行JSDoc。

  • 修复一个bytes vs. strings问题,该问题在Python 3之前的版本中崩溃。(jhkennedy)

  • 容忍具有除“ .js”之外扩展名的JS文件。在此之前,当与自定义JSDoc配置结合使用时,会生成不正确的对象路径名,从而导致虚假的“没有为对象找到JSDoc文档……”错误。

2.0.1:(2017年7月13日)
  • 在加载大型的JSDoc输出时,通过先将其写入临时文件来修复虚假的语法错误。(jhkennedy)

2.0版本:(2017年5月4日)
  • 处理模糊的对象路径。具有相同JSDoc长名的符号(例如在不同文件中称为“foo”的两个顶级事物)将不再互相影响。引入一个明确的路径约定来引用对象。添加一个真正的解析器来解析它们,而不是我们之前使用的肮脏技巧。向后兼容性略有降低,因为模糊引用现在是一个致命错误,而不是静默地引用JSDoc偶然遇到的最后一个定义。

  • 将所有内容索引到后缀树中,以便可以使用任何唯一的路径后缀来引用一个对象。

  • 使用真实解析器的其他副作用

    • 停止支持“-”作为名称路径分隔符。

    • 不再将名称路径中的转义分隔符错误地转换为点。

    • 否则正确处理路径和转义。例如,我们现在可以处理包含“(”的符号。

  • 修复尝试收集标记为@class的普通旧对象的构造函数参数时的KeyError。

1.5.2版本:(2017年3月22日)
  • 修复在警告指定的长名找不到时的崩溃问题。

1.5.1版本:(2017年3月20日)
  • 当未显式指定顺序时,按字母顺序对:members:进行排序。

1.5版本:(2017年3月17日)
  • autoclass添加:members:选项。

  • 添加与其对应的:private-members::exclude-members:选项。

  • 进行重大重构,以允许指令类相互通信。

1.4版本:(2017年3月10日)
  • 添加jsdoc_config_path选项。

1.3.1版本:(2017年3月6日)
  • 容忍在源代码中包装的@args和其他信息字段行。

  • 在Sphinx生成的警告和错误中引用源注释的文件和行。

1.3版本:(2017年2月21日)
  • 添加autoattribute指令。

1.2版本:(2017年2月14日)
  • 始终执行完整重建;当JS代码已更改但RST文件未更改时,不要留下页面过时。

  • 使Python 3兼容。

  • 添加基本的autoclass指令。

1.1版本:(2017年2月13日)
  • 添加:short-name:选项。

1.0版本:(2017年2月7日)
  • 初始发布,仅包含js:autofunction

项目详情


下载文件

下载适用于您的平台的文件。如果您不确定要选择哪个,请了解有关安装软件包的更多信息。

源代码分发

sphinx-js-3.2.2.tar.gz (73.0 kB 查看哈希值)

上传时间 源代码

构建版本

sphinx_js-3.2.2-py2.py3-none-any.whl (86.4 kB 查看哈希值)

上传时间 Python 2 Python 3

支持