如何记录NodeJS本机(V8)模块?

时间:2015-11-30 09:04:11

标签: javascript node.js documentation v8

我开发了一个原生的NodeJS模块(使用NAN助手)。现在我想知道记录它的最佳方法是什么。

模块导出的方法仅存在于C ++源代码中,但我希望导出Javascript文档。

3 个答案:

答案 0 :(得分:1)

编辑:我发现另一种我认为更好的方式:

所有JSDoc需要的是能够将doclet附加到SOMETHING,所以你实际上可以这样做(如果你忽略了关于期望赋值或调用而不是表达式的JSHint警告):

var nativeStuff = require('some/native/stuff');

/**
 * My Cool Class
 * @class
 */
nativeStuff.MyCoolClass;

/**
 * My Cool Method
 * @function
 * @param {String} [name] The argument
 */
nativeStuff.MyCoolClass.prototype.CoolMethod;

/**
 * Some Other Value
 * @type {String}
 */
nativeStuff.someStringValue;

module.exports = nativeStuff;

这样做的好处是可以使用IDE(至少是WebStorm),而不需要您复制或代理对象本身。请注意,您必须明确告诉它每个条目的字段类型(使用@function或@class或@type),因为它不能自动推断它。

原始答案

我知道有几种方法,但我承认没有一种方式特别优雅。

在小型适配器文件中,require()代码的本机部分并将其作为模块提供,您可以单独分配每个组件并以这种方式记录它们:

var nativeStuff = require('some/native/stuff');

// If your module only has one thing
/**
 * My Cool Class
 * @class MyCoolClass
 */
module.exports = nativeStuff;

// If it has several things
module.exports = {
    /**
     * My cool class
     * @class
     */
    MyCoolClass: nativeStuff.MyCoolClass,

    /**
     * My Other Cool Member
     */
    OtherCoolMember: nativeStuff.OtherCoolMember
};

如果你想要拆开课程并重新组装课程,你也可以用这种方式记录课程成员,但是你越深入就会变得有点笨拙。

我知道的另一种方法是将每个类方法包装在本机JS中,这会带来(几乎可以忽略不计)性能影响:

var nativeStuff = require('some/native/stuff');

/**
 * My Cool Class
 */
class MyCoolClass {

    constructor() {
        this._nativeObj = new nativeStuff.MyCoolClass();
    }

    /**
     * Some Cool Method
     * @param {String} [name] My name
     */
    coolMethod(name) {
        return this._nativeObj(name);
    }
}

module.exports = MyCoolClass;

(请注意,这也适用于较旧的JS版本,但ES6类使视觉上的内容更易于理解:)

您也可以尝试使用@typedef指令来定义事物,因为关于typedef的doclet可以与它描述的对象分开,但我不认为typedef可以记录方法或一般来说,它们只适用于数据对象。

答案 1 :(得分:0)

我必须创建一个简单的文档生成器,以类似Javadoc的方式扫描源代码中的注释:https://github.com/aspectron/gendoc

Here是此类文档的一部分,如下所示:

/**
@module crypto
**/

/**
@class Hash
Hash generator
@function Hash(algorithm)
@param algorithm {String}
Constructor. Initiaize hash generator with specified algorithm, see #getHashes
Throws exception on unknown algorithm
**/
v8pp::class_<hash_generator> hash_class(bindings.isolate(), v8pp::v8_args_ctor);
hash_class
    /**
    @function reset([algorithm])
    @param [algorithm] {String}
    @return {Hash}
    Reset hash generator to initial state optionaly changing generator algorithm.
    Throws exception on unknown algorithm.
    **/
    .set("reset", &hash_generator::reset_v8)
...

答案 2 :(得分:0)

最后,我选择了一个不太优雅的解决方案。我创建了一个单独的JavaScript文件,该文件只包含由我的本机API导出的方法。

此文件如下所示:

/** @namespace AwesomeLibrary
 * 
 * @description API overview
 */

AwesomeLibrary = {
  /**
   * @param {string} param Input parameter
   * @return combobulates {@link param}
   */
  combobulate: function (param) {}  
}

然后我使用JsDoc生成项目的文档,并将此JavaScript文件作为输入而不是我的本机代码传递。最后,我将文档与我的模块的二进制发行版捆绑在一起。

此解决方案并不理想,因为文档和源代码必须单独维护,但它具有零开销和(相当)干净文件的优点。我也禁用了JsDoc中的源代码生成,因为这显然是无用的,只显示空的存根。