我如何向包添加注释。Json用于NPM安装?

我有一个简单的包裹。json文件,我想添加一个评论。有办法做到这一点吗,或者有什么hack可以做到这一点吗?

{
"name": "My Project",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "3.x",
"mongoose": "3.x"
},
"devDependencies" :  {
"should": "*"
/* "mocha": "*" not needed as should be globally installed */
}
}

上面的示例注释在npm崩溃时不起作用。我还尝试了// style注释。

191944 次浏览

这个问题最近在Node.js邮件列表上讨论过。

根据创建npm的Isaac Schlueter的说法:

... “/ /”;Key将永远不会被NPM用于任何目的,并保留评论…如果你想使用多行注释,你可以使用一个数组,或者多个"//"钥匙。

当使用你常用的工具(npm, yarn等)时,多个"//"密钥将被删除。这生存:

{ "//": [
"first line",
"second line" ] }

这将不复存在:

{ "//": "this is the first line of a comment",
"//": "this is the second line of the comment" }

免责声明:你可能不应该使用这个黑客。请看下面的评论。


下面是另一个在JSON中添加注释的技巧。自:

{"a": 1, "a": 2}

等于

{"a": 2}

你可以这样做:

{
"devDependencies": "'mocha' not needed as should be globally installed",
"devDependencies" :  {
"should": "*"
}
}

您总是可以滥用重复的键会被覆盖的事实。这就是我刚才写的:

"dependencies": {
"grunt": "...",
"grunt-cli": "...",


"api-easy": "# Here is the pull request: https://github.com/...",
"api-easy": "git://..."


"grunt-vows": "...",
"vows": "..."
}
然而,不清楚JSON是否允许复制键(参见 # EYZ0。它似乎与npm一起工作,所以我冒这个险

推荐的hack是使用"//"键(从Nodejs邮件列表键)。当我测试它时,它不能处理“依赖”部分。此外,文章中的例子使用了多个"//"键,这意味着npm不会拒绝具有重复键的JSON文件。换句话说,上面的hack应该总是好的。

重复密钥的一个令人讨厌的缺点是,npm install --save无声地消除了所有重复密钥。不幸的是,它很容易被忽视,你善意的评论也消失了。

"//"黑客似乎仍然是最安全的。然而,多行注释也将被npm install --save删除。

以下是我对package.json / bower.json内的评论的看法:

我有文件package.json.js,其中包含一个脚本,导出实际的package.json。运行脚本会覆盖旧的package.json,并告诉我它所做的更改,完美地帮助您跟踪npm所做的自动更改。这样,我甚至可以通过编程方式定义我想要使用的包。

最新的Grunt任务在这里: # EYZ0 < / p >

我有一个有趣的黑客想法。

创建一个npm包名,作为package.json文件中dependenciesdevDependencies块的注释分隔符,例如x----x----x

{
"name": "app-name",
"dependencies": {
"x----x----x": "this is the first line of a comment",
"babel-cli": "6.x.x",
"babel-core": "6.x.x",
"x----x----x": "this is the second line of a comment",
"knex": "^0.11.1",
"mocha": "1.20.1",
"x----x----x": "*"
}
}

请注意:你必须添加一个有效版本的最后注释分隔行,就像代码块中的*

到目前为止,大多数“黑客”;这里建议不要滥用JSON。但是,为什么不滥用底层脚本语言呢?

最初的反应是把描述放在右边,使用# add comments here来包装它;然而,这并不适用于Windows,因为标志(例如,npm run myframework -- --myframework-flags)将被忽略。我改变了我的响应,使其适用于所有平台,并增加了一些缩进的可读性。

{
"scripts": {
"help": "       echo 'Display help information (this screen)';          npm run",
"myframework": "echo 'Run myframework binary';                          myframework",
"develop": "    echo 'Run in development mode (with terminal output)';  npm run myframework"
"start": "      echo 'Start myFramework as a daemon';                   myframework start",
"stop":  "      echo 'Stop the myFramework daemon';                     myframework stop"
"test": "echo \"Error: no test specified\" && exit 1"
}
}

这将:

  1. 不会破坏JSON的遵从性(或者至少这不是一种黑客行为,你的IDE不会因为你做了奇怪、危险的事情而给你警告)
  2. 跨平台工作(在macOS和Windows上进行了测试,假设在Linux上也能正常工作)
  3. 不会妨碍运行npm run myframework -- --help
  4. 将在运行npm run时输出有意义的信息(这是用于获取可用脚本信息的实际命令)
  5. 提供一个更明确的帮助命令(以防一些开发人员不知道npm run显示这样的输出)
  6. 在运行命令本身时将显示两个命令而且的描述
  7. 当只打开package.json(使用less或您最喜欢的IDE)时,有点可读
NPS(节点包脚本)为我解决了这个问题。它允许你把NPM脚本放到一个单独的JavaScript文件中,在那里你可以添加大量的注释和任何其他你需要的JavaScript逻辑。 # EYZ0 < / p >

示例package-scripts.js从我的一个项目

module.exports = {
scripts: {
// makes sure e2e webdrivers are up to date
postinstall: 'nps webdriver-update',


// run the webpack dev server and open it in browser on port 7000
server: 'webpack-dev-server --inline --progress --port 7000 --open',


// start webpack dev server with full reload on each change
default: 'nps server',


// start webpack dev server with hot module replacement
hmr: 'nps server -- --hot',


// generates icon font via a gulp task
iconFont: 'gulp default --gulpfile src/deps/build-scripts/gulp-icon-font.js',


// No longer used
// copyFonts: 'copyfiles -f src/app/glb/font/webfonts/**/* dist/1-0-0/font'
}
}

我只是做了一个本地安装npm install nps -save-dev,并把它放在我的package.json脚本。

"scripts": {
"start": "nps",
"test": "nps test"
}

在浪费了一个小时的复杂和俗套的解决方案之后,我在package.json中找到了注释我庞大的依赖项部分的简单而有效的解决方案。就像这样:

{
"name": "package name",
"version": "1.0",
"description": "package description",
"scripts": {
"start": "npm install && node server.js"
},
"scriptsComments": {
"start": "Runs development build on a local server configured by server.js"
},
"dependencies": {
"ajv": "^5.2.2"
},
"dependenciesComments": {
"ajv": "JSON-Schema Validator for validation of API data"
}
}

当以同样的方式排序时,现在我可以很容易地在Git提交差异中或在编辑器中跟踪这些依赖项/注释对,同时使用文件package.json

不需要使用额外的工具,只需要简单有效的JSON。

我最终得到了这样的scripts:

  "scripts": {
"//-1a": "---------------------------------------------------------------",
"//-1b": "---------------------- from node_modules ----------------------",
"//-1c": "---------------------------------------------------------------",
"ng": "ng",
"prettier": "prettier",
"tslint": "tslint",
"//-2a": "---------------------------------------------------------------",
"//-2b": "--------------------------- backend ---------------------------",
"//-2c": "---------------------------------------------------------------",
"back:start": "node backend/index.js",
"back:start:watch": "nodemon",
"back:build:prod": "tsc -p backend/tsconfig.json",
"back:serve:prod": "NODE_ENV=production node backend/dist/main.js",
"back:lint:check": "tslint -c ./backend/tslint.json './backend/src/**/*.ts'",
"back:lint:fix": "yarn run back:lint:check --fix",
"back:check": "yarn run back:lint:check && yarn run back:prettier:check",
"back:check:fix": "yarn run back:lint:fix; yarn run back:prettier:fix",
"back:prettier:base-files": "yarn run prettier './backend/**/*.ts'",
"back:prettier:fix": "yarn run back:prettier:base-files --write",
"back:prettier:check": "yarn run back:prettier:base-files -l",
"back:test": "ts-node --project backend/tsconfig.json node_modules/jasmine/bin/jasmine ./backend/**/*spec.ts",
"back:test:watch": "watch 'yarn run back:test' backend",
"back:test:coverage": "echo TODO",
"//-3a": "---------------------------------------------------------------",
"//-3b": "-------------------------- frontend ---------------------------",
"//-3c": "---------------------------------------------------------------",
"front:start": "yarn run ng serve",
"front:test": "yarn run ng test",
"front:test:ci": "yarn run front:test --single-run --progress=false",
"front:e2e": "yarn run ng e2e",
"front:e2e:ci": "yarn run ng e2e --prod --progress=false",
"front:build:prod": "yarn run ng build --prod --e=prod --no-sourcemap --build-optimizer",
"front:lint:check": "yarn run ng lint --type-check",
"front:lint:fix": "yarn run front:lint:check --fix",
"front:check": "yarn run front:lint:check && yarn run front:prettier:check",
"front:check:fix": "yarn run front:lint:fix; yarn run front:prettier:fix",
"front:prettier:base-files": "yarn run prettier \"./frontend/{e2e,src}/**/*.{scss,ts}\"",
"front:prettier:fix": "yarn run front:prettier:base-files --write",
"front:prettier:check": "yarn run front:prettier:base-files -l",
"front:postbuild": "gulp compress",
"//-4a": "---------------------------------------------------------------",
"//-4b": "--------------------------- cypress ---------------------------",
"//-4c": "---------------------------------------------------------------",
"cy:open": "cypress open",
"cy:headless": "cypress run",
"cy:prettier:base-files": "yarn run prettier \"./cypress/**/*.{js,ts}\"",
"cy:prettier:fix": "yarn run front:prettier:base-files --write",
"cy:prettier:check": "yarn run front:prettier:base-files -l",
"//-5a": "---------------------------------------------------------------",
"//-5b": "--------------------------- common ----------------------------",
"//-5c": "---------------------------------------------------------------",
"all:check": "yarn run back:check && yarn run front:check && yarn run cy:prettier:check",
"all:check:fix": "yarn run back:check:fix && yarn run front:check:fix && yarn run cy:prettier:fix",
"//-6a": "---------------------------------------------------------------",
"//-6b": "--------------------------- hooks -----------------------------",
"//-6c": "---------------------------------------------------------------",
"precommit": "lint-staged",
"prepush": "yarn run back:lint:check && yarn run front:lint:check"
},

我在这里的目的不是澄清一行,只是在后台、前端、所有等脚本之间使用某种分隔符。

我不太喜欢1a、1b、1c、2a……但钥匙是不同的,我没有任何问题,像这样。

我对JSON中没有注释的沮丧之处的看法。我创建了新节点,以它们所引用的节点命名,但以下划线作为前缀。这是不完美的,但功能。

{
"name": "myapp",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-scripts": "1.1.4"
},
"scripts": {
"__start": [
"a note about how the start script works"
],
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"__proxy": [
"A note about how proxy works",
"multilines are easy enough to add"
],
"proxy": "http://server.whatever.com:8000"
}

由于重复的注释键被删除运行包。json工具(npm, yarn等),我开始使用散列版本,允许更好地阅读多行和键,如:

"//": {
"alpaca": "we use the bootstrap version",
"eonasdan-bootstrap-datetimepicker": "instead of bootstrap-datetimepicker",
"moment-with-locales": "is part of moment"
},

这是“有效的”根据我的IDE作为根键,但在dependencies它抱怨期望字符串值。

我一直在这样做:

{
...
"scripts": {
"about": "echo 'Say something about this project'",
"about:clean": "echo 'Say something about the clean script'",
"clean": "do something",
"about:build": "echo 'Say something about building it'",
"build": "do something",
"about:watch": "echo 'Say something about how watch works'",
"watch": "do something",
}
...
}

这样,我既可以读到“伪评论”;在脚本本身,而且也运行如下内容,在终端中看到一些帮助:

npm run about
npm run about:watch

如果使用yarn就更好了。

yarn about:clean
此外,正如@Dakota Jang在评论中指出的那样,你可以使用//something这样的键来更清楚地表明这是一个评论。
像这样:< / p >
{
...
"scripts": {
"//clean": "echo 'Say something about the clean script'",
"clean": "do something",
"//build": "echo 'Say something about building it'",
"build": "do something",
"//watch": "echo 'Say something about how watch works'",
"watch": "do something",
}
...
}

然后运行:

npm run //build
# or
yarn //build

你的终端中会有一个辅助输出,和一个&;comment&;在你的包裹里。Json也是。

正如这个答案所解释的,//键是保留的,所以它可以常规地用于注释。//注释的问题是它不实用,因为它不能被多次使用。重复的键删除package.json自动更新:

"//": "this comment about dependencies stays",
"dependencies": {}
"//": "this comment disappears",
"devDependencies": {}

另一个问题是,//注释不能在dependenciesdevDependencies中使用,因为它被视为常规依赖:

"dependencies": {
"//": "comment"
}

npm犯错!代码EINVALIDPACKAGENAME

< p > npm犯错!无效的包名&;//&;:name只能包含url友好的 字符< / p >

在NPM中工作的一个变通方法,而不是Yarn,是使用一个非字符串值:

"dependencies": {
"foo": ["unused package"],
}

一个在NPM和Yarn中工作的变通方法是作为语义版本控制的一部分添加的注释:

"dependencies": {
"bar": "^2",
"foo": "^2 || should be removed in 1.x release"
}

注意,如果OR之前的第一部分不匹配,则可以解析来自注释的版本,例如1.x

需要注释但没有安装的包,应该移动到另一个键,例如dependencies //:

"dependencies //": {
"baz": "unused package",
}

另一个黑客

我创建了一个脚本来读取文件package.json作为一个句柄模板的上下文。

代码如下,以防有人发现这种方法有用:

const templateData = require('../package.json');
const Handlebars = require('handlebars');
const fs = require('fs-extra');
const outputPath = __dirname + '/../package-json-comments.md';
const srcTemplatePath = __dirname + '/package-json-comments/package-json-comments.hbs';


Handlebars.registerHelper('objlist', function() {
// The first argument is an object, and the list is a set of keys for that obj
const obj = arguments[0];
const list = Array.prototype.slice.call(arguments, 1).slice(0,-1);


const mdList = list.map(function(k) {
return '* ' + k + ': ' + obj[k];
});


return new Handlebars.SafeString(mdList.join("\n"));
});


fs.readFile(srcTemplatePath, 'utf8', function(err, srcTemplate){
if (err) throw err;
const template = Handlebars.compile(srcTemplate);
const content = template(templateData);


fs.writeFile(outputPath, content, function(err) {
if (err) throw err;
});
});

handlebars模板文件package-json-comments.hbs

### Dependency Comments
For package: \{\{ name }}: \{\{version}}


#### Current Core Packages
should be safe to update
\{\{{objlist dependencies
"@material-ui/core"
"@material-ui/icons"
"@material-ui/styles"
}}}


#### Lagging Core Packages
breaks current code if updated
\{\{{objlist dependencies
"amazon-cognito-identity-js"
}}}


#### Major version change
Not tested yet
\{\{{objlist dependencies
"react-dev-utils"
"react-redux"
"react-router"
"redux-localstorage-simple"


}}}

受这个帖子的启发,下面是我们正在使用:

{
"//dependencies": {
"crypto-exchange": "Unified exchange API"
},
"dependencies": {
"crypto-exchange": "^2.3.3"
},
"//devDependencies": {
"chai": "Assertions",
"mocha": "Unit testing framwork",
"sinon": "Spies, Stubs, Mocks",
"supertest": "Test requests"
},
"devDependencies": {
"chai": "^4.1.2",
"mocha": "^4.0.1",
"sinon": "^4.1.3",
"supertest": "^3.0.0"
}
}

因为大多数开发人员都熟悉基于标记/注释的文档,所以我开始使用的约定是类似的。来尝尝:

{
"@comment dependencies": [
"These are the comments for the `dependencies` section.",
"The name of the section being commented is included in the key after the `@comment` 'annotation'/'tag' to ensure the keys are unique.",
"That is, using just \"@comment\" would not be sufficient to keep keys unique if you need to add another comment at the same level.",
"Because JSON doesn't allow a multi-line string or understand a line continuation operator/character, just use an array for each line of the comment.",
"Since this is embedded in JSON, the keys should be unique.",
"Otherwise JSON validators, such as ones built into IDEs, will complain.",
"Or some tools, such as running `npm install something --save`, will rewrite the `package.json` file but with duplicate keys removed.",
"",
"@package react - Using an `@package` 'annotation` could be how you add comments specific to particular packages."
],
"dependencies": {
...
},
"@comment scripts": {
"build": "This comment is about the build script.",
"start": [
"This comment is about the `start` script.",
"It is wrapped in an array to allow line formatting.",
"When using npm, as opposed to yarn, to run the script, be sure to add ` -- ` before adding the options.",
"",
"@option {number} --port - The port the server should listen on."
],
"test": "This comment is about the test script.",
},
"scripts": {
"build": "...",
"start": "...",
"test": "..."
}
}

注意:对于dependenciesdevDependencies等部分,注释注释不能直接添加到配置对象中各个包依赖项的上方,因为npm期望键是npm包的名称。因此才有了@comment dependencies

我喜欢向JSON添加注释的注释/标记样式方式,因为@符号从普通声明中脱颖而出。

年长的建议

以下是我之前的建议。它为脚本内嵌注释,但我已经意识到这些注释显示为“命令”;在一些工具中(在VS Code >探险家在NPM脚本部分)。最新的建议没有受到这个问题的影响,但是脚本注释不再位于同一位置。

{
"@comment dependencies": [
...
],
"dependencies": {
...
},
"scripts": {
"@comment build": "This comment is about the build script.",
"build": "...",


"@comment start": [
"This comment is about the `start` script.",
"It is wrapped in an array to allow line formatting.",
"When using npm, as opposed to yarn, to run the script, be sure to add ` -- ` before adding the options.",
"",
"@option {number} --port - The port the server should listen on."
],
"start": "...",


"@comment test": "This comment is about the test script.",
"test": "..."
}
}

注意:在某些情况下,例如在"scripts"对象中,一些编辑器/ ide可能会抱怨数组。在脚本上下文中,VS Code期望值为字符串——而不是数组。

用于npm的包。我发现了两种方法(在阅读这段对话后):

  "devDependencies": {
"del-comment": [
"some-text"
],
"del": "^5.1.0 ! inner comment",
"envify-comment": [
"some-text"
],
"envify": "4.1.0 ! inner comment"
}

但更新或重新安装的软件包与“;——save"或者"——save-dev,像"^4.1.0 !comment"在相应的地方会被删除。所有这些都将打破npm审计。

总结一下这些答案:

  1. 添加一个名为//的包含评论字符串的单一的顶级字段。这是可行的,但它很糟糕,因为你不能把评论放在他们正在评论的东西附近。

  2. 添加多个顶级字段 //,例如//dependencies包含一个注释字符串。这样更好,但仍然只允许您做顶级注释。不能注释单个依赖项。

  3. 添加echo命令到scripts。这是可行的,但它很糟糕,因为你只能在scripts中使用它。

这些解决方案的可读性也都不是很好。它们增加了大量的视觉干扰,ide不会用语法将它们作为注释突出显示。

我认为唯一合理的解决方案是从另一个文件生成package.json。最简单的方法是将JSON编写为JavaScript,并使用Node.js将其写入package.json。将这个文件保存为package.json.mjschmod +x,然后您可以运行它来生成package.json

#!/usr/bin/env node


import { writeFileSync } from "fs";


const config = {
// TODO: Think of better name.
name: "foo",
dependencies: {
// Bar 2.0 does not work due to bug 12345.
bar: "^1.2.0",
},
// Look at these beautify comments. Perfectly syntax highlighted, you
// can put them anywhere and there no risk of some tool removing them.
};


writeFileSync("package.json", JSON.stringify({
"//": "This file is \x40generated from package.json.mjs; do not edit.",
...config
}, null, 2));

它使用//键警告人们不要编辑它。\x40generated是故意的。它变成了package.json中的@generated,这意味着一些代码审查系统将默认崩溃该文件。

这是构建系统中的一个额外步骤,但它胜过这里的所有其他hack。

我喜欢这个:

  "scripts": {
"⏬⏬⏬ Jenkins Build - in this order ⏬⏬⏬                                                                                                  ": "",
"purge": "lerna run something",
"clean:test": "lerna exec --ignore nanana"
}

在命令名中有额外的空格,所以在Visual Studio Code的NPM脚本插件中你有更好的外观。

我做了一些你们可能会喜欢的事情:

这个//在名字里面意味着它是我的注释:

  "//":"Main and typings are used till ES5",
"//main": "build/index",
"//typings": "build/index",

除了Global //注释(或注释数组)之外,您还可以使用Semver管分离器对特定依赖项进行注释。

# EYZ0

“脚本”中的命令;是bash代码-我们可以注释bash:

"dedup": "yarn-deduplicate && yarn # TODO remove this on yarn/npm v2 because integrated"

奖励:当你运行它-你会看到评论:yarn deduplication comment

从刚刚发布的pnpm 7.17.1开始,你可以切换到pnpm进行包管理,移动你的包。Json来打包。Json5和包中的注释。Json5是允许的,并将由pnpm保存。但是请注意,对于作为包发布以在npm注册表上使用(例如),一个包。json5将不能被其他包管理器识别,我怀疑注册表的所有处理都不能识别。所以你必须转换这个包。Json5到一个包中。Json。另一方面,对于“顶级应用程序”;不太可能作为包包含在其他项目中,一个包。Json5似乎工作得很好,只要您坚持使用PNPM作为包管理器。