Как добавить комментарии к package.json для установки npm?

У меня есть простой файл package.json, и я хочу добавить комментарий. Есть ли способ сделать это, или есть какие-то хаки, чтобы сделать эту работу?

{
  "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. Я также попробовал//комментарии стиля.

Ответ 1

Это недавно обсуждалось в списке рассылки node.js.

По словам Исаака Шлютера, который создал npm:

... ключ "//" никогда не будет использоваться npm для каких-либо целей и зарезервирован для комментариев... Если вы хотите использовать многострочный комментарий, вы можете использовать либо массив, либо несколько "//" ключи.

При использовании ваших обычных инструментов (npm, yarn и т.д.) Будет удалено несколько ключей "//". Это выживает:

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

Это не выживет

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

Ответ 2

Вот еще один взлом для добавления комментариев в JSON. Так как:

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

Является эквивалентным

{"a": 2}

Вы можете сделать что-то вроде:

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

Ответ 3

Потратив час на сложные и хакерские решения, я нашел простое и правильное решение для комментирования моего громоздкого раздела зависимостей в 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 commit diffs, либо в редакторе при работе с package.json.

И никаких дополнительных инструментов, только простой и действительный JSON.

Надеюсь, это кому-нибудь поможет.

Ответ 4

Вы всегда можете злоупотреблять тем, что дублированные ключи перезаписываются. Это то, что я только что написал:

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

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

  "grunt-vows": "...",
  "vows": "..."
}

Однако неясно, разрешает ли JSON дублировать ключи (см. Синтаксис JSON позволяет дублировать ключи в объекте?. Кажется, он работает с npm, поэтому я рискну.

Рекомендуется использовать ключи "//" (из списка рассылки nodejs). Когда я тестировал его, он не работал с разделами "зависимости". Кроме того, пример в посте использует несколько ключей "//", что означает, что npm не отклоняет файлы JSON с дублированными ключами. Другими словами, взломать выше всегда должно быть хорошо.

Обновление: один досадный недостаток взлома дублированных ключей заключается в том, что npm install --save удаляет все дубликаты. К сожалению, это очень легко пропустить, и ваши комментарии из лучших побуждений пропали.

Взлом "//" по-прежнему самый безопасный, как кажется. Однако многострочные комментарии также будут удалены npm install --save.

Ответ 5

NPS (Node Package Scripts) решил эту проблему для меня. Позволяет поместить ваши сценарии NPM в отдельный файл JS, куда вы можете добавить множество комментариев и любую другую логику JS, которая вам нужна. https://www.npmjs.com/package/nps

Пример 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"
}

Ответ 6

Много интересных идей.

То, что я делал, это:

{
  ...
  "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

Мои 2цента за это обсуждение :)

Ответ 7

У меня есть забавная идея взлома.

Создайте имя пакета npm в качестве разделителя комментариев для блока dependencies и devDependencies в package.json, например 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": "*"
    }
}

ПРИМЕЧАНИЕ. Должен добавить последнюю разделитель комментариев с допустимой версией, например * в блоке.

Ответ 8

До сих пор большинство "хаков" здесь предлагают злоупотреблять 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"
  }
}

Это будет:

  • Не нарушайте соответствие JSON (или, по крайней мере, его не взломать, и ваша среда IDE не даст вам предупреждений о том, что вы делаете странные, опасные вещи).
  • Работает кросс-платформа (протестирована на macOS и Windows, предполагая, что она будет работать отлично в Linux)
  • Не мешает запустить npm run myframework -- --help
  • Будет выводить значимую информацию при запуске npm run (которая является фактической командой для запуска, чтобы получить информацию о доступных сценариях)
  • Представляет более явную команду справки (в случае, если некоторые разработчики не знают, что npm run представляет такой вывод)
  • Покажет обе команды И его описание при запуске самой команды
  • Несколько читается при открытии package.json (используя less или вашу любимую среду IDE)

Ответ 9

Здесь мои комментарии в package.json/bower.json:

У меня package.json.js, который содержит script, который экспортирует фактический package.json. Запуск script перезаписывает старый package.json и сообщает мне, какие изменения он внес, идеально подходит для отслеживания автоматических изменений npm. Таким образом, я могу даже программно определить, какие пакеты я хочу использовать.

Последняя задача: https://gist.github.com/MarZab/72fa6b85bc9e71de5991

Ответ 10

Вдохновленный этой темой, вот что мы используем:

{
  "//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"
  }
}

Ответ 11

Я закончил с такими 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"
  },

Мое намерение здесь состоит не в том, чтобы уточнить одну строку, просто чтобы иметь какие-то разделители между моими сценариями для backend, frontend, all и т.д.

Я не большой поклонник 1a, 1b, 1c, 2a,... но ключи разные, и у меня вообще нет таких проблем.

Ответ 12

Поскольку дублирующие ключи комментариев удаляются с помощью инструментов package.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 жалуется на ожидание строкового значения.

Ответ 13

Как объясняется в этом ответе, ключ // был зарезервирован, поэтому его можно использовать для комментариев. Проблема с // комментарием состоит в том, что он не может использоваться в dependencies и devDependencies как обычная зависимость со строкой в качестве ограничения версии:

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

вызывает ошибку,

нпм ERR! код EINVALIDPACKAGENAME

нпм ERR! Неверное имя пакета "//": имя может содержать только дружественные к URL символы

Хотя ключи с нестроковыми значениями считаются недействительными зависимостями и эффективно игнорируются:

"dependencies": {
  "//": ["comment"]
}

Сама зависимость может быть закомментирована таким же образом:

"dependencies": {
  "foo": ["*", "is not needed now"],
}

Поскольку зависимости сортируются, когда package.json изменяется NPM, нецелесообразно размещать комментарий над зависимостью, на которую он ссылается:

"dependencies": {
  "bar": "*",
  "//": ["should be removed in 1.x release"]
  "foo": "*",
}

Ключ комментария должен быть назван соответствующим образом, если он ссылается на конкретную строку, поэтому он не будет перемещен:

"dependencies": {
  "bar": "*",
  "foo": "*",
  "foo //": ["should be removed in 1.x release"]
}

Комментарий, применимый к конкретной зависимости, может быть добавлен как часть semver:

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

Обратите внимание, что если первая часть перед OR не совпадает, комментарий может быть проанализирован, например, 1.x

Эти обходные пути совместимы со всеми текущими версиями NPM (6 и ниже).

Ответ 14

Еще один взлом. Я создал скрипт для чтения 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() {
  // first arg is object, 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;
  });
});

файл шаблона руля 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"

}}}

Ответ 15

Поскольку большинство разработчиков знакомы с документацией на основе тегов/аннотаций, соглашение, которое я начал использовать, аналогично. Вот вкус:

{
  "@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 does not 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 IDE's, 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": {
    ...
  },
  "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": "..."
  }
}

Примечание. Для разделов dependencies, devDependencies и т.д. комментарии к комментариям не могут быть добавлены непосредственно над зависимостями отдельных пакетов внутри объекта конфигурации, поскольку npm ожидает, что ключ будет именем Пакет Npm. Отсюда и причина @comment dependencies.

Примечание. В определенных контекстах, например, в объекте scripts, некоторые редакторы /IDE могут жаловаться на массив. В контексте сценариев VS Code ожидает строку для значения, а не массив.

Мне нравится способ добавления комментариев к JSON в стиле аннотаций/тегов, потому что символ @ выделяется из обычных объявлений.

Ответ 16

Мой взгляд на разочарование без комментариев в 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"
}