{"id":13395047,"url":"https://github.com/tj/dox","last_synced_at":"2025-05-15T10:06:45.746Z","repository":{"id":501717,"uuid":"736638","full_name":"tj/dox","owner":"tj","description":"JavaScript documentation generator for node using markdown and jsdoc","archived":false,"fork":false,"pushed_at":"2022-09-07T14:50:30.000Z","size":837,"stargazers_count":2154,"open_issues_count":19,"forks_count":194,"subscribers_count":38,"default_branch":"master","last_synced_at":"2025-04-14T16:57:14.152Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tj.png","metadata":{"files":{"readme":"Readme.md","changelog":"History.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-06-23T22:54:55.000Z","updated_at":"2025-03-23T05:41:55.000Z","dependencies_parsed_at":"2022-07-15T00:16:13.290Z","dependency_job_id":null,"html_url":"https://github.com/tj/dox","commit_stats":null,"previous_names":["visionmedia/dox"],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tj%2Fdox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tj%2Fdox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tj%2Fdox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tj%2Fdox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tj","download_url":"https://codeload.github.com/tj/dox/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254319720,"owners_count":22051073,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T17:01:40.343Z","updated_at":"2025-05-15T10:06:40.721Z","avatar_url":"https://github.com/tj.png","language":"JavaScript","readme":"# Dox\n\n[![Tests](https://github.com/tj/dox/actions/workflows/test.workflow.yml/badge.svg)](https://github.com/tj/dox/actions/workflows/test.workflow.yml)\n\nDox is a JavaScript documentation generator written with [node](http://nodejs.org). Dox no longer generates an opinionated structure or style for your docs, it simply gives you a JSON representation, allowing you to use _markdown_ and _JSDoc_-style tags.\n\n## Installation\n\nInstall from npm:\n\n```sh\nnpm install -g dox\n```\n\n## Usage Examples\n\n`dox(1)` operates over stdio:\n\n```sh\n$ dox \u003c utils.js\n...JSON...\n```\n\nto inspect the generated data you can use the `--debug` flag, which is easier to read than the JSON output:\n\n```sh\ndox --debug \u003c utils.js\n```\n\n[utils.js](./doc_examples/utils.js):\n\n```js\n/**\n * Escape the given `html`.\n *\n * @example\n *     utils.escape('\u003cscript\u003e\u003c/script\u003e')\n *     // =\u003e '\u0026lt;script\u0026gt;\u0026lt;/script\u0026gt;'\n *\n * @param {String} html string to be escaped\n * @return {String} escaped html\n * @api public\n */\n\nexports.escape = function(html){\n  return String(html)\n    .replace(/\u0026(?!\\w+;)/g, '\u0026amp;')\n    .replace(/\u003c/g, '\u0026lt;')\n    .replace(/\u003e/g, '\u0026gt;');\n};\n```\n\noutput:\n\n```json\n[\n  {\n    \"tags\": [\n      {\n        \"type\": \"param\",\n        \"string\": \"{String} html\",\n        \"name\": \"html\",\n        \"description\": \"\",\n        \"types\": [\n          \"String\"\n        ],\n        \"typesDescription\": \"\u003ccode\u003eString\u003c/code\u003e\",\n        \"optional\": false,\n        \"nullable\": false,\n        \"nonNullable\": false,\n        \"variable\": false,\n        \"html\": \"\u003cp\u003e{String} html\u003c/p\u003e\"\n      },\n      {\n        \"type\": \"return\",\n        \"string\": \"{String}\",\n        \"types\": [\n          \"String\"\n        ],\n        \"typesDescription\": \"\u003ccode\u003eString\u003c/code\u003e\",\n        \"optional\": false,\n        \"nullable\": false,\n        \"nonNullable\": false,\n        \"variable\": false,\n        \"description\": \"\",\n        \"html\": \"\u003cp\u003e{String}\u003c/p\u003e\"\n      },\n      {\n        \"type\": \"api\",\n        \"string\": \"private\",\n        \"visibility\": \"private\",\n        \"html\": \"\u003cp\u003eprivate\u003c/p\u003e\"\n      }\n    ],\n    \"description\": {\n      \"full\": \"\u003cp\u003eEscape the given \u003ccode\u003ehtml\u003c/code\u003e.\u003c/p\u003e\",\n      \"summary\": \"\u003cp\u003eEscape the given \u003ccode\u003ehtml\u003c/code\u003e.\u003c/p\u003e\",\n      \"body\": \"\"\n    },\n    \"isPrivate\": true,\n    \"isConstructor\": false,\n    \"isClass\": false,\n    \"isEvent\": false,\n    \"ignore\": false,\n    \"line\": 2,\n    \"codeStart\": 10,\n    \"code\": \"exports.escape = function(html){\\n  return String(html)\\n    .replace(/\u0026(?!\\\\w+;)/g, '\u0026amp;')\\n    .replace(/\u003c/g, '\u0026lt;')\\n    .replace(/\u003e/g, '\u0026gt;');\\n};\",\n    \"ctx\": {\n      \"type\": \"method\",\n      \"receiver\": \"exports\",\n      \"name\": \"escape\",\n      \"string\": \"exports.escape()\"\n    }\n  }\n]\n```\n\nThis output can then be passed to a template for rendering. Look below at the \"Properties\" section for details.\n\n## Usage\n\n```txt\n\nUsage: dox [options]\n\n  Options:\n\n    -h, --help                     output usage information\n    -V, --version                  output the version number\n    -r, --raw                      output \"raw\" comments, leaving the markdown intact\n    -a, --api                      output markdown readme documentation\n    -s, --skipPrefixes [prefixes]  skip comments prefixed with these prefixes, separated by commas\n    -d, --debug                    output parsed comments for debugging\n    -S, --skipSingleStar           set to false to ignore `/* ... */` comments\n\n  Examples:\n\n    # stdin\n    $ dox \u003e myfile.json\n\n    # operates over stdio\n    $ dox \u003c myfile.js \u003e myfile.json\n\n```\n\n### Programmatic Usage\n\n```js\nvar dox = require('dox'),\n    code = \"...\";\n\nvar obj = dox.parseComments(code);\n\n// [{ tags:[ ... ], description, ... }, { ... }, ...]\n```\n\n## Properties\n\nA \"comment\" is comprised of the following detailed properties:\n\n  - tags\n  - description\n  - isPrivate\n  - isEvent\n  - isConstructor\n  - line\n  - ignore\n  - code\n  - ctx\n\n### Description\n\nA dox description is comprised of three parts, the \"full\" description,\nthe \"summary\", and the \"body\". The following example has only a \"summary\",\nas it consists of a single paragraph only, therefore the \"full\" property has\nonly this value as well.\n\n[write1.js](./doc_examples/write1.js):\n\n```js\n/**\n * Output the given `str` to _stdout_.\n */\n\nexports.write = function(str) {\n  process.stdout.write(str);\n};\n```\n\nyields:\n\n```json\n[\n  {\n    \"description\": {\n      \"full\": \"\u003cp\u003eOutput the given \u003ccode\u003estr\u003c/code\u003e to \u003cem\u003estdout\u003c/em\u003e.\u003c/p\u003e\",\n      \"summary\": \"\u003cp\u003eOutput the given \u003ccode\u003estr\u003c/code\u003e to \u003cem\u003estdout\u003c/em\u003e.\u003c/p\u003e\",\n      \"body\": \"\"\n    },\n    // ... other tags\n  }\n]\n```\n\nLarge descriptions might look something like the following, where the \"summary\" is still the first paragraph, the remaining description becomes the \"body\". Keep in mind this _is_ markdown, so you can indent code, use lists, links, etc. Dox also augments markdown, allowing \"Some Title:\\n\" to form a header.\n\n[write2.js](./doc_examples/write2.js):\n\n```js\n/**\n * Output the given `str` to _stdout_\n * or the stream specified by `options`.\n *\n * Options:\n *\n *   - `stream` defaulting to _stdout_\n *\n * Examples:\n *\n *     mymodule.write('foo')\n *     mymodule.write('foo', { stream: process.stderr })\n *\n */\n\nexports.write = function(str, options) {\n  options = options || {};\n  (options.stream || process.stdout).write(str);\n};\n```\n\nyields:\n\n```json\n[\n  {\n    \"description\": {\n      \"full\": \"\u003cp\u003eOutput the given \u003ccode\u003estr\u003c/code\u003e to \u003cem\u003estdout\u003c/em\u003e\u003cbr /\u003e\\nor the stream specified by \u003ccode\u003eoptions\u003c/code\u003e.\u003c/p\u003e\\n\u003cp\u003eOptions:\u003c/p\u003e\\n\u003cul\u003e\\n\u003cli\u003e\u003ccode\u003estream\u003c/code\u003e defaulting to \u003cem\u003estdout\u003c/em\u003e\u003c/li\u003e\\n\u003c/ul\u003e\\n\u003cp\u003eExamples:\u003c/p\u003e\\n\u003cpre\u003e\u003ccode\u003emymodule.write('foo')\\nmymodule.write('foo', { stream: process.stderr })\\n\u003c/code\u003e\u003c/pre\u003e\",\n      \"summary\": \"\u003cp\u003eOutput the given \u003ccode\u003estr\u003c/code\u003e to \u003cem\u003estdout\u003c/em\u003e\u003cbr /\u003e\\nor the stream specified by \u003ccode\u003eoptions\u003c/code\u003e.\u003c/p\u003e\",\n      \"body\": \"\u003cp\u003eOptions:\u003c/p\u003e\\n\u003cul\u003e\\n\u003cli\u003e\u003ccode\u003estream\u003c/code\u003e defaulting to \u003cem\u003estdout\u003c/em\u003e\u003c/li\u003e\\n\u003c/ul\u003e\\n\u003cp\u003eExamples:\u003c/p\u003e\\n\u003cpre\u003e\u003ccode\u003emymodule.write('foo')\\nmymodule.write('foo', { stream: process.stderr })\\n\u003c/code\u003e\u003c/pre\u003e\"\n    },\n    // ... other tags\n  }\n]\n```\n\n### Tags\n\nDox also supports JSdoc-style tags. Currently only __@api__ is special-cased, providing the `comment.isPrivate` boolean so you may omit \"private\" utilities etc.\n\n[write_tags.js](./doc_examples/write_tags.js):\n\n```js\n/**\n * Output the given `str` to _stdout_\n * or the stream specified by `options`.\n *\n * @param {String} str\n * @param {{stream: Writable}} options\n * @return {Object} exports for chaining\n */\n\nexports.write = function(str, options) {\n  options = options || {};\n  (options.stream || process.stdout).write(str);\n  return this;\n};\n```\n\nyields:\n\n```json\n[\n  {\n    \"tags\": [\n      {\n        \"type\": \"param\",\n        \"string\": \"{String} str\",\n        \"name\": \"str\",\n        \"description\": \"\",\n        \"types\": [\n          \"String\"\n        ],\n        \"typesDescription\": \"\u003ccode\u003eString\u003c/code\u003e\",\n        \"optional\": false,\n        \"nullable\": false,\n        \"nonNullable\": false,\n        \"variable\": false,\n        \"html\": \"\u003cp\u003e{String} str\u003c/p\u003e\"\n      },\n      {\n        \"type\": \"param\",\n        \"string\": \"{{stream: Writable}} options\",\n        \"name\": \"options\",\n        \"description\": \"\",\n        \"types\": [\n          {\n            \"stream\": [\n              \"Writable\"\n            ]\n          }\n        ],\n        \"typesDescription\": \"{stream: \u003ccode\u003eWritable\u003c/code\u003e}\",\n        \"optional\": false,\n        \"nullable\": false,\n        \"nonNullable\": false,\n        \"variable\": false,\n        \"html\": \"\u003cp\u003e{{stream: Writable}} options\u003c/p\u003e\"\n      },\n      {\n        \"type\": \"return\",\n        \"string\": \"{Object} exports for chaining\",\n        \"types\": [\n          \"Object\"\n        ],\n        \"typesDescription\": \"\u003ccode\u003eObject\u003c/code\u003e\",\n        \"optional\": false,\n        \"nullable\": false,\n        \"nonNullable\": false,\n        \"variable\": false,\n        \"description\": \"\u003cp\u003eexports for chaining\u003c/p\u003e\"\n      }\n    ],\n    // ... other tags\n  }\n]\n```\n\n#### Complex jsdoc tags\n\ndox supports all jsdoc type strings specified in the [jsdoc documentation](http://usejsdoc.org/tags-type.html). You can\nspecify complex object types including optional flag `=`, nullable `?`, non-nullable `!` and variable arguments `...`.\n\nAdditionally you can use `typesDescription` which contains formatted HTML for displaying complex types.\n\n[generatePersonInfo.js](./doc_examples/generatePersonInfo.js):\n\n```js\n/**\n * Generates a person information string based on input.\n *\n * @param {string | {name: string, age: number | date}} name Name or person object\n * @param {{separator: string} =} options An options object\n * @return {string} The constructed information string\n */\n\nexports.generatePersonInfo = function(name, options) {\n  var str = '';\n  var separator = options \u0026\u0026 options.separator ? options.separator : ' ';\n\n  if(typeof name === 'object') {\n    str = [name.name, '(', name.age, ')'].join(separator);\n  } else {\n    str = name;\n  }\n};\n```\n\nyields:\n\n```json\n[\n  {\n    \"tags\": [\n      {\n        \"type\": \"param\",\n        \"string\": \"{string | {name: string, age: number | date}} name Name or person object\",\n        \"name\": \"name\",\n        \"description\": \"\u003cp\u003eName or person object\u003c/p\u003e\",\n        \"types\": [\n          \"string\",\n          {\n            \"name\": [\n              \"string\"\n            ],\n            \"age\": [\n              \"number\",\n              \"date\"\n            ]\n          }\n        ],\n        \"typesDescription\": \"\u003ccode\u003estring\u003c/code\u003e | {name: \u003ccode\u003estring\u003c/code\u003e, age: \u003ccode\u003enumber\u003c/code\u003e | \u003ccode\u003edate\u003c/code\u003e}\",\n        \"optional\": false,\n        \"nullable\": false,\n        \"nonNullable\": false,\n        \"variable\": false\n      },\n      {\n        \"type\": \"param\",\n        \"string\": \"{{separator: string} =} options An options object\",\n        \"name\": \"options\",\n        \"description\": \"\u003cp\u003eAn options object\u003c/p\u003e\",\n        \"types\": [\n          {\n            \"separator\": [\n              \"string\"\n            ]\n          }\n        ],\n        \"typesDescription\": \"{separator: \u003ccode\u003estring\u003c/code\u003e|\u003ccode\u003eundefined\u003c/code\u003e}\",\n        \"optional\": true,\n        \"nullable\": false,\n        \"nonNullable\": false,\n        \"variable\": false\n      },\n      {\n        \"type\": \"return\",\n        \"string\": \"{string} The constructed information string\",\n        \"types\": [\n          \"string\"\n        ],\n        \"typesDescription\": \"\u003ccode\u003estring\u003c/code\u003e\",\n        \"optional\": false,\n        \"nullable\": false,\n        \"nonNullable\": false,\n        \"variable\": false,\n        \"description\": \"\u003cp\u003eThe constructed information string\u003c/p\u003e\"\n      }\n    ],\n    // ... other tags\n  }\n]\n```\n\n### Code\n\nThe `.code` property is the code following the comment block, in our previous examples:\n\n```js\nexports.write = function(str, options) {\n  options = options || {};\n  (options.stream || process.stdout).write(str);\n  return this;\n};\n```\n\n### Ctx\n\nThe `.ctx` object indicates the context of the code block, is it a method, a function, a variable etc. Below are some examples:\n\n[ctx.js](./doc_examples/ctx.js):\n\n```js\n/** */\nexports.generate = function(str, options) {};\n```\n\nyields:\n\n```json\n[\n  {\n    // ... other tags\n    \"ctx\": {\n      \"type\": \"method\",\n      \"receiver\": \"exports\",\n      \"name\": \"generate\",\n      \"string\": \"exports.generate()\"\n    }\n  }\n]\n```\n\n```js\n/** */\nvar foo = 'bar';\n```\n\nyields:\n\n```json\n[\n  {\n    // ... other tags\n    \"ctx\": {\n      \"type\": \"declaration\",\n      \"name\": \"foo\",\n      \"value\": \"'bar'\",\n      \"string\": \"foo\"\n    }\n  }\n]\n```\n\n```js\n/** */\nfunction User() {}\n```\n\nyields:\n\n```json\n[\n  {\n    // ... other tags\n    \"ctx\": {\n      \"type\": \"function\",\n      \"name\": \"User\",\n      \"string\": \"User()\"\n    }\n  }\n]\n```\n\n### Extending Context Matching\n\nContext matching in dox is done by performing pattern matching against the code following a\ncomment block. `dox.contextPatternMatchers` is an array of all pattern matching functions,\nwhich dox will iterate over until one of them returns a result. If none return a result,\nthen the comment block does not receive a `ctx` value.\n\nThis array is exposed to allow for extension of unsupported context patterns by adding more\nfunctions.  Each function is passed the code following the comment block and (if detected)\nthe parent context if the block.\n\n```js\ndox.contextPatternMatchers.push(function (str, parentContext) {\n  // return a context object if found\n  // return false otherwise\n});\n```\n\n### Ignore\n\nComments and their associated bodies of code may be flagged with \"!\" to be considered worth ignoring, these are typically things like file comments containing copyright etc, however you of course can output them in your templates if you want.\n\n```js\n/**\n * Not ignored.\n */\n```\n\nvs\n\n```js\n/*!\n * Ignored.\n */\n```\n\nYou may use `-S`, `--skipSingleStar` or `{skipSingleStar: true}` to ignore `/* ... */` comments.\n\n### Running tests\n\nInstall dev dependencies and execute `make test`:\n\n```sh\nnpm install -d\nmake test\n```\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk \u0026lt;tj@vision-media.ca\u0026gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","funding_links":[],"categories":["JavaScript","Documentation","others","Documentation [🔝](#readme)","Packages","Uncategorized","文档","包"],"sub_categories":["Runner","Documentation","Uncategorized","运行器","运行器e2e测试"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftj%2Fdox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftj%2Fdox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftj%2Fdox/lists"}