如何记录 NodeJS 原生 (V8) 模块?
How do I document NodeJS native (V8) modules?
我开发了一个本地 NodeJS 模块(使用 NAN 助手)。现在我想知道记录它的最佳方式是什么。
模块导出的方法仅存在于 C++ 源代码中,但是我希望导出 Javascript 文档。
我必须创建一个简单的文档生成器来扫描源代码中类似 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)
...
编辑:我发现另一种我认为更好的方法:
JSDoc 所需要的只是能够将 doclet 附加到某些东西上,因此您实际上可以这样做(如果您忽略 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),否则它无法自动推断它。
原答案
虽然我承认 none 看起来特别优雅,但我知道有几种方法。
在您 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
};
如果您想将 class 和 re-assemble 分开,您也可以用这种方式记录 class 的成员,但是越深入它就会变得有点笨拙。
我知道的另一种方法是在原生 JS 中包装每个 class 方法,这带来了(几乎可以忽略不计的)性能损失:
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 classes 使内容更容易在视觉上理解:)
您也可以尝试使用 @typedef 指令来定义事物,因为关于 typedef 的 doclet 可以与其描述的对象分开,但我不认为 typedef 可以记录方法或 classes 通常,它们仅用于数据对象。
最后我选择了一个不太优雅的解决方案。我已经创建了一个单独的 JavaScript 文件,其中只有我的本地 API.
导出的方法
这个文件看起来像这样:
/** @namespace AwesomeLibrary
*
* @description API overview
*/
AwesomeLibrary = {
/**
* @param {string} param Input parameter
* @return combobulates {@link param}
*/
combobulate: function (param) {}
}
然后我使用 JsDoc 生成项目的文档并将此 JavaScript 文件作为输入而不是我的本机代码传递。最后,我将文档与我的模块的二进制分发包捆绑在一起。
这个解决方案并不理想,因为文档和源代码必须单独维护,但它具有零开销和(相当)干净的文件的优点。我还禁用了 JsDoc 中的源代码生成,因为这显然毫无用处,只会显示空存根。
我开发了一个本地 NodeJS 模块(使用 NAN 助手)。现在我想知道记录它的最佳方式是什么。
模块导出的方法仅存在于 C++ 源代码中,但是我希望导出 Javascript 文档。
我必须创建一个简单的文档生成器来扫描源代码中类似 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)
...
编辑:我发现另一种我认为更好的方法:
JSDoc 所需要的只是能够将 doclet 附加到某些东西上,因此您实际上可以这样做(如果您忽略 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),否则它无法自动推断它。
原答案
虽然我承认 none 看起来特别优雅,但我知道有几种方法。
在您 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
};
如果您想将 class 和 re-assemble 分开,您也可以用这种方式记录 class 的成员,但是越深入它就会变得有点笨拙。
我知道的另一种方法是在原生 JS 中包装每个 class 方法,这带来了(几乎可以忽略不计的)性能损失:
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 classes 使内容更容易在视觉上理解:)
您也可以尝试使用 @typedef 指令来定义事物,因为关于 typedef 的 doclet 可以与其描述的对象分开,但我不认为 typedef 可以记录方法或 classes 通常,它们仅用于数据对象。
最后我选择了一个不太优雅的解决方案。我已经创建了一个单独的 JavaScript 文件,其中只有我的本地 API.
导出的方法这个文件看起来像这样:
/** @namespace AwesomeLibrary
*
* @description API overview
*/
AwesomeLibrary = {
/**
* @param {string} param Input parameter
* @return combobulates {@link param}
*/
combobulate: function (param) {}
}
然后我使用 JsDoc 生成项目的文档并将此 JavaScript 文件作为输入而不是我的本机代码传递。最后,我将文档与我的模块的二进制分发包捆绑在一起。
这个解决方案并不理想,因为文档和源代码必须单独维护,但它具有零开销和(相当)干净的文件的优点。我还禁用了 JsDoc 中的源代码生成,因为这显然毫无用处,只会显示空存根。