├── .editorconfig ├── .eslintrc.yaml ├── .gitattributes ├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── .ignore ├── .npmrc ├── LICENSE ├── Makefile ├── README.md ├── fixtures ├── actions.yaml ├── dual │ ├── package.json │ └── pyproject.toml ├── github │ ├── updates-commits.json │ └── updates-tags.json ├── npm-1500 │ └── package.json ├── npm-empty │ └── package.json ├── npm-test │ └── package.json ├── npm │ ├── @babel%2fpreset-env.json │ ├── gulp-sourcemaps.json │ ├── html-webpack-plugin.json │ ├── jpeg-buffer-orientation.json │ ├── noty.json │ ├── preset-env │ ├── prismjs.json │ ├── react.json │ ├── styled-components.json │ ├── svgstore.json │ ├── typescript.json │ └── updates.json ├── poetry │ └── pyproject.toml └── pypi │ ├── PyYAML.json │ └── djlint.json ├── index.test.ts ├── index.ts ├── package-lock.json ├── package.json ├── screenshot.png ├── snapshots └── index.test.ts.snap ├── tsconfig.json ├── updates.config.js ├── vite.config.ts └── vitest.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | tab_width = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [Makefile] 13 | indent_style = tab 14 | -------------------------------------------------------------------------------- /.eslintrc.yaml: -------------------------------------------------------------------------------- 1 | root: true 2 | reportUnusedDisableDirectives: true 3 | extends: 4 | - silverwind 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | *.snap linguist-generated 3 | fixtures/** linguist-generated 4 | vendor/** linguist-vendored 5 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | test: 6 | strategy: 7 | fail-fast: false 8 | matrix: 9 | js: [[node, 18], [node, 20], [node, 22], [bun, latest]] 10 | os: [ubuntu-latest, macos-latest, windows-latest] 11 | runs-on: ${{matrix.os}} 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v4 15 | with: 16 | node-version: ${{matrix.js[1]}} 17 | if: ${{matrix.js[0] == 'node'}} 18 | - uses: oven-sh/setup-bun@v2 19 | with: 20 | bun-version: ${{matrix.js[1]}} 21 | no-cache: true 22 | if: ${{matrix.js[0] == 'bun'}} 23 | - run: make lint test 24 | if: ${{matrix.js[0] == 'node'}} 25 | - run: bun install && bunx vite build && make hashbang && chmod +x dist/index.js && bun test 26 | if: ${{matrix.js[0] == 'bun'}} 27 | env: 28 | BUN: "true" 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode 2 | /dist 3 | /node_modules 4 | /npm-debug.log* 5 | /yarn-error.log 6 | /yarn.lock 7 | /bun.lockb 8 | /__snapshots__ 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /.ignore: -------------------------------------------------------------------------------- 1 | fixtures 2 | dist 3 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | audit=false 2 | fund=false 3 | package-lock=true 4 | save-exact=true 5 | update-notifier=false 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) silverwind 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SOURCE_FILES := index.ts 2 | DIST_FILES := dist/index.js 3 | 4 | ifeq ($(shell sed --version 2>/dev/null | grep -q GNU && echo gnu),gnu) 5 | SED_INPLACE := sed -i 6 | else 7 | SED_INPLACE := sed -i '' 8 | endif 9 | 10 | node_modules: package-lock.json 11 | npm install --no-save 12 | @touch node_modules 13 | 14 | .PHONY: deps 15 | deps: node_modules 16 | 17 | .PHONY: lint 18 | lint: node_modules 19 | npx eslint --ext js,jsx,ts,tsx --color . 20 | npx tsc 21 | 22 | .PHONY: lint-fix 23 | lint-fix: node_modules 24 | npx eslint --ext js,jsx,ts,tsx --color . --fix 25 | npx tsc 26 | 27 | .PHONY: test 28 | test: node_modules build 29 | npx vitest 30 | 31 | .PHONY: test-update 32 | test-update: node_modules build 33 | npx vitest -u 34 | 35 | .PHONY: hashbang 36 | hashbang: 37 | @$(SED_INPLACE) "1s/.*/\#\!\/usr\/bin\/env node/" dist/index.js 38 | 39 | .PHONY: build 40 | build: node_modules $(DIST_FILES) 41 | 42 | $(DIST_FILES): $(SOURCE_FILES) package-lock.json vite.config.ts 43 | npx vite build 44 | @$(MAKE) --no-print-directory hashbang 45 | chmod +x $(DIST_FILES) 46 | 47 | .PHONY: publish 48 | publish: node_modules 49 | git push -u --tags origin master 50 | npm publish 51 | 52 | .PHONY: update 53 | update: node_modules 54 | npx updates -cu 55 | rm -rf node_modules package-lock.json 56 | npm install 57 | @touch node_modules 58 | 59 | .PHONY: path 60 | patch: node_modules lint test build 61 | npx versions patch package.json package-lock.json 62 | @$(MAKE) --no-print-directory publish 63 | 64 | .PHONY: minor 65 | minor: node_modules lint test build 66 | npx versions minor package.json package-lock.json 67 | @$(MAKE) --no-print-directory publish 68 | 69 | .PHONY: major 70 | major: node_modules lint test build 71 | npx versions major package.json package-lock.json 72 | @$(MAKE) --no-print-directory publish 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # updates 2 | [![](https://img.shields.io/npm/v/updates.svg?style=flat)](https://www.npmjs.org/package/updates) [![](https://img.shields.io/npm/dm/updates.svg)](https://www.npmjs.org/package/updates) [![](https://packagephobia.com/badge?p=updates)](https://packagephobia.com/result?p=updates) 3 | 4 | ![](./screenshot.png) 5 | 6 | `updates` is a CLI tool which checks for dependency updates. It is typically able to complete in less than a second. Supported dependencies are: 7 | 8 | - npm via `package.json` 9 | - poetry via `pyproject.toml` 10 | - go via `go.mod` (checking only currently, disabled by default when directory is used) 11 | 12 | # Usage 13 | 14 | With Node.js: 15 | 16 | ```bash 17 | # check for updates 18 | npx updates 19 | 20 | # update package.json and install new dependencies 21 | npx updates -u && npm i 22 | ``` 23 | 24 | With Bun: 25 | 26 | ```bash 27 | # check for updates 28 | bunx updates 29 | 30 | # update package.json and install new dependencies 31 | bunx updates -u && bun i 32 | ``` 33 | 34 | ## Options 35 | 36 | See `--help`. Options that take multiple arguments can take them either via comma-separated value or by specifying the option multiple times. 37 | 38 | If an option has a optional `pkg` argument but none is given, the option will be applied to all packages instead. 39 | 40 | All `pkg` options support glob matching via [picomatch](https://github.com/micromatch/picomatch) or regex (on CLI, wrap the regex in slashes, e.g. `'/^foo/'`). 41 | 42 | ## Notes 43 | 44 | The module uses global `fetch` under the hood. In Node.js HTTP proxies from environment are [not supported](https://github.com/nodejs/undici/issues/1650), but it's still possible to enable `updates` to use them by installing the `undici` dependency into your project. 45 | 46 | ## Config File 47 | 48 | The config file is used to configure certain options of the module. It be placed as `updates.config.{js,ts,mjs,mts}` or `config/updates.config.{js,ts,mjs,mts}`, relative to `package.json` / `pyproject.toml` / `go.mod`. 49 | 50 | For typescript to work in Node 22.6.0 and above, set `NODE_OPTIONS="--experimental-strip-types"` in your environment. 51 | 52 | ```ts 53 | export default { 54 | exclude: [ 55 | "semver", 56 | "@vitejs/*", 57 | /^react(-dom)?$/, 58 | ], 59 | }; 60 | ``` 61 | 62 | ### Config Options 63 | 64 | - `include` *Array[String|Regexp]*: Array of dependencies to include 65 | - `exclude` *Array[String|Regexp]*: Array of dependencies to exclude 66 | - `types` *Array[String]*: Array of dependency types 67 | - `registry` *String*: URL to npm registry 68 | 69 | CLI arguments have precedence over options in the config file, except for `include` and `exclude` options which are merged. 70 | 71 | © [silverwind](https://github.com/silverwind), distributed under BSD licence 72 | -------------------------------------------------------------------------------- /fixtures/actions.yaml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | ci: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | - uses: actions/setup-node@v1 10 | - uses: tj-actions/changed-files@87697c0dca7dd44e37a2b79a79489332556ff1f3 # v37.6.0 11 | -------------------------------------------------------------------------------- /fixtures/dual/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "gulp-sourcemaps": "2.0.0", 4 | "prismjs": "1.0.0", 5 | "svgstore": "^3.0.0", 6 | "html-webpack-plugin": "4.0.0-alpha.2", 7 | "noty": "3.1.0", 8 | "jpeg-buffer-orientation": "0.0.0", 9 | "styled-components": "2.5.0-1", 10 | "@babel/preset-env": "7.0.0", 11 | "updates": "https://github.com/silverwind/updates/tarball/6941e05", 12 | "ipaddr.js": "https://github.com/silverwind/ipaddr.js/tarball/ipv6_cidrs_take2", 13 | "react": "18.0" 14 | }, 15 | "devDependencies": { 16 | "updates": "file:." 17 | }, 18 | "peerDependencies": { 19 | "@babel/preset-env": "~6.0.0", 20 | "svgstore": "^1.0.0 || ^2.0.0" 21 | }, 22 | "resolutions": { 23 | "versions/updates": "^1.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /fixtures/dual/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "" 3 | version = "0.0.0" 4 | description = "" 5 | authors = [] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.8" 9 | 10 | [tool.poetry.group.dev.dependencies] 11 | djlint = "1.30.0" 12 | PyYAML = "6.0" 13 | -------------------------------------------------------------------------------- /fixtures/github/updates-tags.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ref": "refs/tags/v0.1.0", 4 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYwLjEuMA==", 5 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v0.1.0", 6 | "object": { 7 | "sha": "14adf18eef21bcf2c4b3354480f104324ecf40f3", 8 | "type": "tag", 9 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/14adf18eef21bcf2c4b3354480f104324ecf40f3" 10 | } 11 | }, 12 | { 13 | "ref": "refs/tags/v1.0.0", 14 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjAuMA==", 15 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.0.0", 16 | "object": { 17 | "sha": "b4670e6eea514c310b056c24fceda7b68265af62", 18 | "type": "tag", 19 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/b4670e6eea514c310b056c24fceda7b68265af62" 20 | } 21 | }, 22 | { 23 | "ref": "refs/tags/v1.0.1", 24 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjAuMQ==", 25 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.0.1", 26 | "object": { 27 | "sha": "16b12fd661e53eda7e8857c6711957f017d6ac37", 28 | "type": "tag", 29 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/16b12fd661e53eda7e8857c6711957f017d6ac37" 30 | } 31 | }, 32 | { 33 | "ref": "refs/tags/v1.0.2", 34 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjAuMg==", 35 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.0.2", 36 | "object": { 37 | "sha": "d13f0750a588bbc219e4161df6895dacaaa185ab", 38 | "type": "tag", 39 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/d13f0750a588bbc219e4161df6895dacaaa185ab" 40 | } 41 | }, 42 | { 43 | "ref": "refs/tags/v1.0.3", 44 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjAuMw==", 45 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.0.3", 46 | "object": { 47 | "sha": "1e87ec5becd0ffeebb76a6c47dc60a77199073b5", 48 | "type": "tag", 49 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/1e87ec5becd0ffeebb76a6c47dc60a77199073b5" 50 | } 51 | }, 52 | { 53 | "ref": "refs/tags/v1.0.4", 54 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjAuNA==", 55 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.0.4", 56 | "object": { 57 | "sha": "d1cd948f9ab610f9427d0af88da1454655fb8f30", 58 | "type": "tag", 59 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/d1cd948f9ab610f9427d0af88da1454655fb8f30" 60 | } 61 | }, 62 | { 63 | "ref": "refs/tags/v1.0.5", 64 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjAuNQ==", 65 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.0.5", 66 | "object": { 67 | "sha": "e64b813be93131b2e14b258a6a6c50cb05493304", 68 | "type": "tag", 69 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/e64b813be93131b2e14b258a6a6c50cb05493304" 70 | } 71 | }, 72 | { 73 | "ref": "refs/tags/v1.0.6", 74 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjAuNg==", 75 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.0.6", 76 | "object": { 77 | "sha": "45e81b625bdf8feda5a18fe074aa61c57cde43b5", 78 | "type": "tag", 79 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/45e81b625bdf8feda5a18fe074aa61c57cde43b5" 80 | } 81 | }, 82 | { 83 | "ref": "refs/tags/v1.1.0", 84 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjEuMA==", 85 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.1.0", 86 | "object": { 87 | "sha": "023bb9ebdc952cb6c16e30a2f00380581981e2ad", 88 | "type": "tag", 89 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/023bb9ebdc952cb6c16e30a2f00380581981e2ad" 90 | } 91 | }, 92 | { 93 | "ref": "refs/tags/v1.1.1", 94 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjEuMQ==", 95 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.1.1", 96 | "object": { 97 | "sha": "da1cfb83ba8020d52ca8e3f5595be58cac98bbdf", 98 | "type": "tag", 99 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/da1cfb83ba8020d52ca8e3f5595be58cac98bbdf" 100 | } 101 | }, 102 | { 103 | "ref": "refs/tags/v1.1.2", 104 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjEuMg==", 105 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.1.2", 106 | "object": { 107 | "sha": "f22e67e5172d20b28116769c96e471ee85bd5399", 108 | "type": "tag", 109 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/f22e67e5172d20b28116769c96e471ee85bd5399" 110 | } 111 | }, 112 | { 113 | "ref": "refs/tags/v1.1.3", 114 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjEuMw==", 115 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.1.3", 116 | "object": { 117 | "sha": "a167270102264d0efd7c0282822580c6b4fd87a4", 118 | "type": "tag", 119 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/a167270102264d0efd7c0282822580c6b4fd87a4" 120 | } 121 | }, 122 | { 123 | "ref": "refs/tags/v1.2.0", 124 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjIuMA==", 125 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.2.0", 126 | "object": { 127 | "sha": "7ada41d9428c2b5fafa1518324b3f901cf7258f0", 128 | "type": "tag", 129 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/7ada41d9428c2b5fafa1518324b3f901cf7258f0" 130 | } 131 | }, 132 | { 133 | "ref": "refs/tags/v1.2.1", 134 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjIuMQ==", 135 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.2.1", 136 | "object": { 137 | "sha": "ce7d5441e294f31c488fb36e9adb63172622ea33", 138 | "type": "tag", 139 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/ce7d5441e294f31c488fb36e9adb63172622ea33" 140 | } 141 | }, 142 | { 143 | "ref": "refs/tags/v1.2.2", 144 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjIuMg==", 145 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.2.2", 146 | "object": { 147 | "sha": "2c16b1a8b10d953e66c98f0495be2a4e219e65f4", 148 | "type": "tag", 149 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/2c16b1a8b10d953e66c98f0495be2a4e219e65f4" 150 | } 151 | }, 152 | { 153 | "ref": "refs/tags/v1.2.3", 154 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjIuMw==", 155 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.2.3", 156 | "object": { 157 | "sha": "6d5f983ff09b3348a235f0889ddb89a15679a4e0", 158 | "type": "tag", 159 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/6d5f983ff09b3348a235f0889ddb89a15679a4e0" 160 | } 161 | }, 162 | { 163 | "ref": "refs/tags/v1.2.4", 164 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjIuNA==", 165 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.2.4", 166 | "object": { 167 | "sha": "80d63de374dee180e1cc83c74d4817022a127631", 168 | "type": "tag", 169 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/80d63de374dee180e1cc83c74d4817022a127631" 170 | } 171 | }, 172 | { 173 | "ref": "refs/tags/v1.2.5", 174 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjIuNQ==", 175 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.2.5", 176 | "object": { 177 | "sha": "d99ff9dd7fee8552fbc402eb8933aa8d7042c9f5", 178 | "type": "tag", 179 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/d99ff9dd7fee8552fbc402eb8933aa8d7042c9f5" 180 | } 181 | }, 182 | { 183 | "ref": "refs/tags/v1.2.6", 184 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjIuNg==", 185 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.2.6", 186 | "object": { 187 | "sha": "671bac0eb4ffa23f765ad47ed2c4df150e4a5010", 188 | "type": "tag", 189 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/671bac0eb4ffa23f765ad47ed2c4df150e4a5010" 190 | } 191 | }, 192 | { 193 | "ref": "refs/tags/v1.3.0", 194 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjMuMA==", 195 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.3.0", 196 | "object": { 197 | "sha": "7f0608b95f211cfda610102773c64e9461534db7", 198 | "type": "tag", 199 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/7f0608b95f211cfda610102773c64e9461534db7" 200 | } 201 | }, 202 | { 203 | "ref": "refs/tags/v1.3.1", 204 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjMuMQ==", 205 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.3.1", 206 | "object": { 207 | "sha": "371c84da03f12687ff8fb687cc1eb9289ae59425", 208 | "type": "tag", 209 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/371c84da03f12687ff8fb687cc1eb9289ae59425" 210 | } 211 | }, 212 | { 213 | "ref": "refs/tags/v1.4.0", 214 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjQuMA==", 215 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.4.0", 216 | "object": { 217 | "sha": "79568dd7a9494b31e3792e0afb1a62e2142ba742", 218 | "type": "tag", 219 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/79568dd7a9494b31e3792e0afb1a62e2142ba742" 220 | } 221 | }, 222 | { 223 | "ref": "refs/tags/v1.4.1", 224 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjQuMQ==", 225 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.4.1", 226 | "object": { 227 | "sha": "29656ef972be09efa3e873d3d530b7b2f77f4b98", 228 | "type": "tag", 229 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/29656ef972be09efa3e873d3d530b7b2f77f4b98" 230 | } 231 | }, 232 | { 233 | "ref": "refs/tags/v1.5.0", 234 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjUuMA==", 235 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.5.0", 236 | "object": { 237 | "sha": "ee9591ddd5921286a5ff8b9cad41c8e711e446ec", 238 | "type": "tag", 239 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/ee9591ddd5921286a5ff8b9cad41c8e711e446ec" 240 | } 241 | }, 242 | { 243 | "ref": "refs/tags/v1.5.1", 244 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjUuMQ==", 245 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.5.1", 246 | "object": { 247 | "sha": "0006ad0f6338202b8f32fc6e07154011c685ccbf", 248 | "type": "tag", 249 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/0006ad0f6338202b8f32fc6e07154011c685ccbf" 250 | } 251 | }, 252 | { 253 | "ref": "refs/tags/v1.5.2", 254 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYxLjUuMg==", 255 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v1.5.2", 256 | "object": { 257 | "sha": "55252104f961e82c98b2d05dac9cb3a77017c0d6", 258 | "type": "tag", 259 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/55252104f961e82c98b2d05dac9cb3a77017c0d6" 260 | } 261 | }, 262 | { 263 | "ref": "refs/tags/v2.0.0", 264 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjAuMA==", 265 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.0.0", 266 | "object": { 267 | "sha": "a0948f49721133e82a25f4cb4f3dca800956f76f", 268 | "type": "tag", 269 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/a0948f49721133e82a25f4cb4f3dca800956f76f" 270 | } 271 | }, 272 | { 273 | "ref": "refs/tags/v2.0.1", 274 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjAuMQ==", 275 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.0.1", 276 | "object": { 277 | "sha": "0f7d20f98307b7453a933d3c960a6bb0c12a730c", 278 | "type": "tag", 279 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/0f7d20f98307b7453a933d3c960a6bb0c12a730c" 280 | } 281 | }, 282 | { 283 | "ref": "refs/tags/v2.0.2", 284 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjAuMg==", 285 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.0.2", 286 | "object": { 287 | "sha": "db85c355f57e0f58dd506e0cf6e0d148a800ffd2", 288 | "type": "tag", 289 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/db85c355f57e0f58dd506e0cf6e0d148a800ffd2" 290 | } 291 | }, 292 | { 293 | "ref": "refs/tags/v2.0.3", 294 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjAuMw==", 295 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.0.3", 296 | "object": { 297 | "sha": "e6a0568f6f0f6812739faf8eb1fe2978036f6afd", 298 | "type": "tag", 299 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/e6a0568f6f0f6812739faf8eb1fe2978036f6afd" 300 | } 301 | }, 302 | { 303 | "ref": "refs/tags/v2.1.0", 304 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjEuMA==", 305 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.1.0", 306 | "object": { 307 | "sha": "b5d4180b9712df6bfdeba20ad3886aff915a5def", 308 | "type": "tag", 309 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/b5d4180b9712df6bfdeba20ad3886aff915a5def" 310 | } 311 | }, 312 | { 313 | "ref": "refs/tags/v2.2.0", 314 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjIuMA==", 315 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.2.0", 316 | "object": { 317 | "sha": "37a624efa141441990e4f0aa8da4db2708e2fb67", 318 | "type": "tag", 319 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/37a624efa141441990e4f0aa8da4db2708e2fb67" 320 | } 321 | }, 322 | { 323 | "ref": "refs/tags/v2.2.1", 324 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjIuMQ==", 325 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.2.1", 326 | "object": { 327 | "sha": "8a678aee40e58a2fb6fe599084ff60618947ef56", 328 | "type": "tag", 329 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/8a678aee40e58a2fb6fe599084ff60618947ef56" 330 | } 331 | }, 332 | { 333 | "ref": "refs/tags/v2.3.0", 334 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjMuMA==", 335 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.3.0", 336 | "object": { 337 | "sha": "16f283b9899ccdb85cdbf6a8b071ae277892585a", 338 | "type": "tag", 339 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/16f283b9899ccdb85cdbf6a8b071ae277892585a" 340 | } 341 | }, 342 | { 343 | "ref": "refs/tags/v2.3.1", 344 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjMuMQ==", 345 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.3.1", 346 | "object": { 347 | "sha": "9bb1c70afd3b4617067160fb560d634e9859a1dc", 348 | "type": "tag", 349 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/9bb1c70afd3b4617067160fb560d634e9859a1dc" 350 | } 351 | }, 352 | { 353 | "ref": "refs/tags/v2.4.0", 354 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjQuMA==", 355 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.4.0", 356 | "object": { 357 | "sha": "ed4bed94f51ebd6e9e6a6150b91d9e06d1245ca4", 358 | "type": "tag", 359 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/ed4bed94f51ebd6e9e6a6150b91d9e06d1245ca4" 360 | } 361 | }, 362 | { 363 | "ref": "refs/tags/v2.4.1", 364 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjQuMQ==", 365 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.4.1", 366 | "object": { 367 | "sha": "fa1a2b7a8b806ca8ed0051d516e228251b7efe20", 368 | "type": "tag", 369 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/fa1a2b7a8b806ca8ed0051d516e228251b7efe20" 370 | } 371 | }, 372 | { 373 | "ref": "refs/tags/v2.5.0", 374 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjUuMA==", 375 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.5.0", 376 | "object": { 377 | "sha": "b3715fb0c1af28279bc3e14e07af7e0d07dabd97", 378 | "type": "tag", 379 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/b3715fb0c1af28279bc3e14e07af7e0d07dabd97" 380 | } 381 | }, 382 | { 383 | "ref": "refs/tags/v2.5.1", 384 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjUuMQ==", 385 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.5.1", 386 | "object": { 387 | "sha": "c95e75e54585525b9c760606adecea674d6a6419", 388 | "type": "tag", 389 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/c95e75e54585525b9c760606adecea674d6a6419" 390 | } 391 | }, 392 | { 393 | "ref": "refs/tags/v2.6.0", 394 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjYuMA==", 395 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.6.0", 396 | "object": { 397 | "sha": "fbdca273e9056ea8f3b80d79212948681ec77148", 398 | "type": "tag", 399 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/fbdca273e9056ea8f3b80d79212948681ec77148" 400 | } 401 | }, 402 | { 403 | "ref": "refs/tags/v2.7.0", 404 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjcuMA==", 405 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.7.0", 406 | "object": { 407 | "sha": "5880fc211f20f605926d0bb56fbbb10dd4e32807", 408 | "type": "tag", 409 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/5880fc211f20f605926d0bb56fbbb10dd4e32807" 410 | } 411 | }, 412 | { 413 | "ref": "refs/tags/v2.7.1", 414 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjcuMQ==", 415 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.7.1", 416 | "object": { 417 | "sha": "4ccbfc399f822935b1385c592953c9d2345d7ff9", 418 | "type": "tag", 419 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/4ccbfc399f822935b1385c592953c9d2345d7ff9" 420 | } 421 | }, 422 | { 423 | "ref": "refs/tags/v2.7.2", 424 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjcuMg==", 425 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.7.2", 426 | "object": { 427 | "sha": "57d6fcb88dfe15e751a348b7bb494ca49b9d58a5", 428 | "type": "tag", 429 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/57d6fcb88dfe15e751a348b7bb494ca49b9d58a5" 430 | } 431 | }, 432 | { 433 | "ref": "refs/tags/v2.7.3", 434 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYyLjcuMw==", 435 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v2.7.3", 436 | "object": { 437 | "sha": "1158cdc59823f18f61de5f424fee0ce53e539d8e", 438 | "type": "tag", 439 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/1158cdc59823f18f61de5f424fee0ce53e539d8e" 440 | } 441 | }, 442 | { 443 | "ref": "refs/tags/v3.0.0", 444 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYzLjAuMA==", 445 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v3.0.0", 446 | "object": { 447 | "sha": "aa4d862f5a7348eddaf2387bcc77255c1b17c2d1", 448 | "type": "tag", 449 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/aa4d862f5a7348eddaf2387bcc77255c1b17c2d1" 450 | } 451 | }, 452 | { 453 | "ref": "refs/tags/v3.0.1", 454 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYzLjAuMQ==", 455 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v3.0.1", 456 | "object": { 457 | "sha": "742977336937425a7ff0cd83d32d6900240296e4", 458 | "type": "tag", 459 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/742977336937425a7ff0cd83d32d6900240296e4" 460 | } 461 | }, 462 | { 463 | "ref": "refs/tags/v3.1.0", 464 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYzLjEuMA==", 465 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v3.1.0", 466 | "object": { 467 | "sha": "c1ca3197e125e0a7df346abd949d69b9d9d3c0d9", 468 | "type": "tag", 469 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/c1ca3197e125e0a7df346abd949d69b9d9d3c0d9" 470 | } 471 | }, 472 | { 473 | "ref": "refs/tags/v3.2.0", 474 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYzLjIuMA==", 475 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v3.2.0", 476 | "object": { 477 | "sha": "00e87f9a7d54252bfac1a4ba98b02d03c6cd815b", 478 | "type": "tag", 479 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/00e87f9a7d54252bfac1a4ba98b02d03c6cd815b" 480 | } 481 | }, 482 | { 483 | "ref": "refs/tags/v3.2.1", 484 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYzLjIuMQ==", 485 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v3.2.1", 486 | "object": { 487 | "sha": "a132b656deb18eba83924125d34af139dbbe67eb", 488 | "type": "tag", 489 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/a132b656deb18eba83924125d34af139dbbe67eb" 490 | } 491 | }, 492 | { 493 | "ref": "refs/tags/v3.2.2", 494 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYzLjIuMg==", 495 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v3.2.2", 496 | "object": { 497 | "sha": "543a16bddabee4e1d5220588b93f9bcc45aba642", 498 | "type": "tag", 499 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/543a16bddabee4e1d5220588b93f9bcc45aba642" 500 | } 501 | }, 502 | { 503 | "ref": "refs/tags/v3.2.3", 504 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnYzLjIuMw==", 505 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v3.2.3", 506 | "object": { 507 | "sha": "33fa41757e3ecef7af6df5f4b2d38162312f07f9", 508 | "type": "tag", 509 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/33fa41757e3ecef7af6df5f4b2d38162312f07f9" 510 | } 511 | }, 512 | { 513 | "ref": "refs/tags/v4.0.0", 514 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjAuMA==", 515 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.0.0", 516 | "object": { 517 | "sha": "0389902ed4e1f61535d4c80f05485d51a3b3787b", 518 | "type": "tag", 519 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/0389902ed4e1f61535d4c80f05485d51a3b3787b" 520 | } 521 | }, 522 | { 523 | "ref": "refs/tags/v4.0.1", 524 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjAuMQ==", 525 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.0.1", 526 | "object": { 527 | "sha": "8d8879cf64ec5748f7a4305df9530a5f160cc792", 528 | "type": "tag", 529 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/8d8879cf64ec5748f7a4305df9530a5f160cc792" 530 | } 531 | }, 532 | { 533 | "ref": "refs/tags/v4.1.0", 534 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjEuMA==", 535 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.1.0", 536 | "object": { 537 | "sha": "a321da1f4829e52bad1f46b1654d92fce1acc51a", 538 | "type": "tag", 539 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/a321da1f4829e52bad1f46b1654d92fce1acc51a" 540 | } 541 | }, 542 | { 543 | "ref": "refs/tags/v4.1.1", 544 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjEuMQ==", 545 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.1.1", 546 | "object": { 547 | "sha": "7d4f90aad1dccedeaad0f5ff48096a0a86c2cd2d", 548 | "type": "tag", 549 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/7d4f90aad1dccedeaad0f5ff48096a0a86c2cd2d" 550 | } 551 | }, 552 | { 553 | "ref": "refs/tags/v4.1.2", 554 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjEuMg==", 555 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.1.2", 556 | "object": { 557 | "sha": "2e4313657ad241d5572d3613e62970612c1bde43", 558 | "type": "tag", 559 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/2e4313657ad241d5572d3613e62970612c1bde43" 560 | } 561 | }, 562 | { 563 | "ref": "refs/tags/v4.1.3", 564 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjEuMw==", 565 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.1.3", 566 | "object": { 567 | "sha": "d8ae74c4d1f2fd8a339092fb0cdc8453711f5c3a", 568 | "type": "tag", 569 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/d8ae74c4d1f2fd8a339092fb0cdc8453711f5c3a" 570 | } 571 | }, 572 | { 573 | "ref": "refs/tags/v4.1.4", 574 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjEuNA==", 575 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.1.4", 576 | "object": { 577 | "sha": "2e15b8898af4610b2bb3fc284ed696507a80b35e", 578 | "type": "tag", 579 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/2e15b8898af4610b2bb3fc284ed696507a80b35e" 580 | } 581 | }, 582 | { 583 | "ref": "refs/tags/v4.2.0", 584 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjIuMA==", 585 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.2.0", 586 | "object": { 587 | "sha": "0f1d4df3852f5e79c5875a76b890d7daed0aa89c", 588 | "type": "tag", 589 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/0f1d4df3852f5e79c5875a76b890d7daed0aa89c" 590 | } 591 | }, 592 | { 593 | "ref": "refs/tags/v4.2.1", 594 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjIuMQ==", 595 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.2.1", 596 | "object": { 597 | "sha": "65a30f022cb3eefc2fc21fa93ba0864d0e980815", 598 | "type": "tag", 599 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/65a30f022cb3eefc2fc21fa93ba0864d0e980815" 600 | } 601 | }, 602 | { 603 | "ref": "refs/tags/v4.2.2", 604 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjIuMg==", 605 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.2.2", 606 | "object": { 607 | "sha": "0a4dd54ab1568cbfb578a1418429890b57f67954", 608 | "type": "tag", 609 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/0a4dd54ab1568cbfb578a1418429890b57f67954" 610 | } 611 | }, 612 | { 613 | "ref": "refs/tags/v4.2.3", 614 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjIuMw==", 615 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.2.3", 616 | "object": { 617 | "sha": "35f77505075bcbe2eb68f3fc1017db9d15080f4b", 618 | "type": "tag", 619 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/35f77505075bcbe2eb68f3fc1017db9d15080f4b" 620 | } 621 | }, 622 | { 623 | "ref": "refs/tags/v4.3.0", 624 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjMuMA==", 625 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.3.0", 626 | "object": { 627 | "sha": "14623619ee3552531013d503fe30207be28ff85c", 628 | "type": "tag", 629 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/14623619ee3552531013d503fe30207be28ff85c" 630 | } 631 | }, 632 | { 633 | "ref": "refs/tags/v4.4.0", 634 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjQuMA==", 635 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.4.0", 636 | "object": { 637 | "sha": "6d6f902c1bd431ab171df06a9bb9e8cf9e4e9e1f", 638 | "type": "tag", 639 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/6d6f902c1bd431ab171df06a9bb9e8cf9e4e9e1f" 640 | } 641 | }, 642 | { 643 | "ref": "refs/tags/v4.4.1", 644 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjQuMQ==", 645 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.4.1", 646 | "object": { 647 | "sha": "40704267a4e5032762d7679927b150b853815c79", 648 | "type": "tag", 649 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/40704267a4e5032762d7679927b150b853815c79" 650 | } 651 | }, 652 | { 653 | "ref": "refs/tags/v4.5.0", 654 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjUuMA==", 655 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.5.0", 656 | "object": { 657 | "sha": "7ec217e5a3ee7a54799739b52ab7c9103d1f0474", 658 | "type": "tag", 659 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/7ec217e5a3ee7a54799739b52ab7c9103d1f0474" 660 | } 661 | }, 662 | { 663 | "ref": "refs/tags/v4.5.1", 664 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjUuMQ==", 665 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.5.1", 666 | "object": { 667 | "sha": "73f869d92f3c3fbce30c58c03cc253f80586ac9e", 668 | "type": "tag", 669 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/73f869d92f3c3fbce30c58c03cc253f80586ac9e" 670 | } 671 | }, 672 | { 673 | "ref": "refs/tags/v4.5.2", 674 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjUuMg==", 675 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.5.2", 676 | "object": { 677 | "sha": "48d25d000a7d30a0a8e3f2aaa363ae85ad9108f1", 678 | "type": "tag", 679 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/48d25d000a7d30a0a8e3f2aaa363ae85ad9108f1" 680 | } 681 | }, 682 | { 683 | "ref": "refs/tags/v4.6.0", 684 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY0LjYuMA==", 685 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v4.6.0", 686 | "object": { 687 | "sha": "19ab3a04f20126b9922c93e044226e2093f6f251", 688 | "type": "tag", 689 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/19ab3a04f20126b9922c93e044226e2093f6f251" 690 | } 691 | }, 692 | { 693 | "ref": "refs/tags/v5.0.0", 694 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjAuMA==", 695 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.0.0", 696 | "object": { 697 | "sha": "ef2238453eb861bd409e682fed7ea10ab75b0f60", 698 | "type": "tag", 699 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/ef2238453eb861bd409e682fed7ea10ab75b0f60" 700 | } 701 | }, 702 | { 703 | "ref": "refs/tags/v5.0.1", 704 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjAuMQ==", 705 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.0.1", 706 | "object": { 707 | "sha": "bd1a6a6d28dfbb65959b637096f1ef4ca8d070d0", 708 | "type": "tag", 709 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/bd1a6a6d28dfbb65959b637096f1ef4ca8d070d0" 710 | } 711 | }, 712 | { 713 | "ref": "refs/tags/v5.1.0", 714 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjEuMA==", 715 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.1.0", 716 | "object": { 717 | "sha": "5bb4acb28cc175bfe5010651b2bce519680c889c", 718 | "type": "tag", 719 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/5bb4acb28cc175bfe5010651b2bce519680c889c" 720 | } 721 | }, 722 | { 723 | "ref": "refs/tags/v5.1.1", 724 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjEuMQ==", 725 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.1.1", 726 | "object": { 727 | "sha": "0c89c3a4b5268d817c1b9f1705b0def3d6d013c9", 728 | "type": "tag", 729 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/0c89c3a4b5268d817c1b9f1705b0def3d6d013c9" 730 | } 731 | }, 732 | { 733 | "ref": "refs/tags/v5.1.2", 734 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjEuMg==", 735 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.1.2", 736 | "object": { 737 | "sha": "e5394c829f94ae83497b59f2c80b536eadcd4d2b", 738 | "type": "tag", 739 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/e5394c829f94ae83497b59f2c80b536eadcd4d2b" 740 | } 741 | }, 742 | { 743 | "ref": "refs/tags/v5.2.0", 744 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjIuMA==", 745 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.2.0", 746 | "object": { 747 | "sha": "aee43723ea10a2667b09059d44f692c6884f914b", 748 | "type": "tag", 749 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/aee43723ea10a2667b09059d44f692c6884f914b" 750 | } 751 | }, 752 | { 753 | "ref": "refs/tags/v5.2.1", 754 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjIuMQ==", 755 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.2.1", 756 | "object": { 757 | "sha": "a22c23d84ce46590c7ee5efd0b862237685e837b", 758 | "type": "tag", 759 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/a22c23d84ce46590c7ee5efd0b862237685e837b" 760 | } 761 | }, 762 | { 763 | "ref": "refs/tags/v5.2.2", 764 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjIuMg==", 765 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.2.2", 766 | "object": { 767 | "sha": "a1660ea0021d1b8234e233b4577f849abe5000f8", 768 | "type": "tag", 769 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/a1660ea0021d1b8234e233b4577f849abe5000f8" 770 | } 771 | }, 772 | { 773 | "ref": "refs/tags/v5.3.0", 774 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjMuMA==", 775 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.3.0", 776 | "object": { 777 | "sha": "d22efab7a025579d55b3ff55585441601991c351", 778 | "type": "tag", 779 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/d22efab7a025579d55b3ff55585441601991c351" 780 | } 781 | }, 782 | { 783 | "ref": "refs/tags/v5.3.1", 784 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjMuMQ==", 785 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.3.1", 786 | "object": { 787 | "sha": "b639897773f390a5e1bf7f35856645e2b099045d", 788 | "type": "tag", 789 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/b639897773f390a5e1bf7f35856645e2b099045d" 790 | } 791 | }, 792 | { 793 | "ref": "refs/tags/v5.4.0", 794 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjQuMA==", 795 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.4.0", 796 | "object": { 797 | "sha": "4fbf1440c9a6fc2cb14d678cfec7656374a467ab", 798 | "type": "tag", 799 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/4fbf1440c9a6fc2cb14d678cfec7656374a467ab" 800 | } 801 | }, 802 | { 803 | "ref": "refs/tags/v5.4.1", 804 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjQuMQ==", 805 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.4.1", 806 | "object": { 807 | "sha": "17138e24fd74d4e3120401e2b9515249d46150e0", 808 | "type": "tag", 809 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/17138e24fd74d4e3120401e2b9515249d46150e0" 810 | } 811 | }, 812 | { 813 | "ref": "refs/tags/v5.4.2", 814 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjQuMg==", 815 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.4.2", 816 | "object": { 817 | "sha": "68026aa56d4f0c26aae68b18717da0d4248a43db", 818 | "type": "tag", 819 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/68026aa56d4f0c26aae68b18717da0d4248a43db" 820 | } 821 | }, 822 | { 823 | "ref": "refs/tags/v5.4.3", 824 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY1LjQuMw==", 825 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v5.4.3", 826 | "object": { 827 | "sha": "c25d3945b422e14a03c570e256587f9e4c3f034b", 828 | "type": "tag", 829 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/c25d3945b422e14a03c570e256587f9e4c3f034b" 830 | } 831 | }, 832 | { 833 | "ref": "refs/tags/v6.0.0", 834 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY2LjAuMA==", 835 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v6.0.0", 836 | "object": { 837 | "sha": "bc01fefb8a5ac2e4f68c9cbf6e65d0eb2340d46b", 838 | "type": "tag", 839 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/bc01fefb8a5ac2e4f68c9cbf6e65d0eb2340d46b" 840 | } 841 | }, 842 | { 843 | "ref": "refs/tags/v6.0.1", 844 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY2LjAuMQ==", 845 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v6.0.1", 846 | "object": { 847 | "sha": "0eac8ecabe9710f21af8cd727d08c7e085809967", 848 | "type": "tag", 849 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/0eac8ecabe9710f21af8cd727d08c7e085809967" 850 | } 851 | }, 852 | { 853 | "ref": "refs/tags/v6.0.2", 854 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY2LjAuMg==", 855 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v6.0.2", 856 | "object": { 857 | "sha": "48befd7c1a8a40c0217e5f7b2a87fd75b7ce51de", 858 | "type": "tag", 859 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/48befd7c1a8a40c0217e5f7b2a87fd75b7ce51de" 860 | } 861 | }, 862 | { 863 | "ref": "refs/tags/v6.0.3", 864 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY2LjAuMw==", 865 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v6.0.3", 866 | "object": { 867 | "sha": "79874403346eb7d708eeb4414ae49a7600f2a877", 868 | "type": "tag", 869 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/79874403346eb7d708eeb4414ae49a7600f2a877" 870 | } 871 | }, 872 | { 873 | "ref": "refs/tags/v6.1.0", 874 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY2LjEuMA==", 875 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v6.1.0", 876 | "object": { 877 | "sha": "6e7e63020c4ab97c297be26334ac2918e5a2f785", 878 | "type": "tag", 879 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/6e7e63020c4ab97c297be26334ac2918e5a2f785" 880 | } 881 | }, 882 | { 883 | "ref": "refs/tags/v6.2.0", 884 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY2LjIuMA==", 885 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v6.2.0", 886 | "object": { 887 | "sha": "22424d2698ea7cbe27346e7330ca117b9600bf89", 888 | "type": "tag", 889 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/22424d2698ea7cbe27346e7330ca117b9600bf89" 890 | } 891 | }, 892 | { 893 | "ref": "refs/tags/v6.2.1", 894 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY2LjIuMQ==", 895 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v6.2.1", 896 | "object": { 897 | "sha": "97ba410a0f16ec0264421792f2d90c2dbd2b5e03", 898 | "type": "tag", 899 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/97ba410a0f16ec0264421792f2d90c2dbd2b5e03" 900 | } 901 | }, 902 | { 903 | "ref": "refs/tags/v8.0.1", 904 | "node_id": "MDM6UmVmMTEyOTIxNjI2OnY4LjAuMQ==", 905 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/v8.0.1", 906 | "object": { 907 | "sha": "c893762b7f01b5dae55e0a6c0d47d19cd37e5902", 908 | "type": "tag", 909 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/c893762b7f01b5dae55e0a6c0d47d19cd37e5902" 910 | } 911 | }, 912 | { 913 | "ref": "refs/tags/6.2.2", 914 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjYuMi4y", 915 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/6.2.2", 916 | "object": { 917 | "sha": "9914d6a36509c4248b2879770c29e716e35b3329", 918 | "type": "tag", 919 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/9914d6a36509c4248b2879770c29e716e35b3329" 920 | } 921 | }, 922 | { 923 | "ref": "refs/tags/6.2.3", 924 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjYuMi4z", 925 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/6.2.3", 926 | "object": { 927 | "sha": "f5a766927df6a10bdc2c5c013f067d715f5bb1de", 928 | "type": "tag", 929 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/f5a766927df6a10bdc2c5c013f067d715f5bb1de" 930 | } 931 | }, 932 | { 933 | "ref": "refs/tags/6.2.4", 934 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjYuMi40", 935 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/6.2.4", 936 | "object": { 937 | "sha": "01aa5a01d8e54d8ed21edea5bfb511c0128cd8cc", 938 | "type": "tag", 939 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/01aa5a01d8e54d8ed21edea5bfb511c0128cd8cc" 940 | } 941 | }, 942 | { 943 | "ref": "refs/tags/6.3.0", 944 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjYuMy4w", 945 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/6.3.0", 946 | "object": { 947 | "sha": "3fbaa022ae90b916af8fc2e15c16de0a840151d1", 948 | "type": "tag", 949 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/3fbaa022ae90b916af8fc2e15c16de0a840151d1" 950 | } 951 | }, 952 | { 953 | "ref": "refs/tags/7.0.0", 954 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjcuMC4w", 955 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/7.0.0", 956 | "object": { 957 | "sha": "eb56ceb3eb397bb023913a606f474f8ebd5442ea", 958 | "type": "tag", 959 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/eb56ceb3eb397bb023913a606f474f8ebd5442ea" 960 | } 961 | }, 962 | { 963 | "ref": "refs/tags/7.1.0", 964 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjcuMS4w", 965 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/7.1.0", 966 | "object": { 967 | "sha": "1dc6e3bc4e1e82fa7dc2281047a438bcb6ef877b", 968 | "type": "tag", 969 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/1dc6e3bc4e1e82fa7dc2281047a438bcb6ef877b" 970 | } 971 | }, 972 | { 973 | "ref": "refs/tags/7.1.1", 974 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjcuMS4x", 975 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/7.1.1", 976 | "object": { 977 | "sha": "a178127eca53d3939fe07d1047ee8684212359b2", 978 | "type": "tag", 979 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/a178127eca53d3939fe07d1047ee8684212359b2" 980 | } 981 | }, 982 | { 983 | "ref": "refs/tags/7.1.2", 984 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjcuMS4y", 985 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/7.1.2", 986 | "object": { 987 | "sha": "82b32037bba0305a88080f9d9b3bb5179187e4fe", 988 | "type": "tag", 989 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/82b32037bba0305a88080f9d9b3bb5179187e4fe" 990 | } 991 | }, 992 | { 993 | "ref": "refs/tags/7.2.0", 994 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjcuMi4w", 995 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/7.2.0", 996 | "object": { 997 | "sha": "a550cb0666827abf337fe98c0bebc19233759cb4", 998 | "type": "tag", 999 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/a550cb0666827abf337fe98c0bebc19233759cb4" 1000 | } 1001 | }, 1002 | { 1003 | "ref": "refs/tags/7.2.1", 1004 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjcuMi4x", 1005 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/7.2.1", 1006 | "object": { 1007 | "sha": "34e07a3b662d4aa6be50b568a7d55fcf29e73305", 1008 | "type": "tag", 1009 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/34e07a3b662d4aa6be50b568a7d55fcf29e73305" 1010 | } 1011 | }, 1012 | { 1013 | "ref": "refs/tags/8.0.0", 1014 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMC4w", 1015 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.0.0", 1016 | "object": { 1017 | "sha": "21ac50797390d5c546bfb77207e83d47bdd2ec12", 1018 | "type": "tag", 1019 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/21ac50797390d5c546bfb77207e83d47bdd2ec12" 1020 | } 1021 | }, 1022 | { 1023 | "ref": "refs/tags/8.0.1", 1024 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMC4x", 1025 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.0.1", 1026 | "object": { 1027 | "sha": "60441ae5c4dadcda4b62f08ca4f5326f5ce836d4", 1028 | "type": "tag", 1029 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/60441ae5c4dadcda4b62f08ca4f5326f5ce836d4" 1030 | } 1031 | }, 1032 | { 1033 | "ref": "refs/tags/8.0.2", 1034 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMC4y", 1035 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.0.2", 1036 | "object": { 1037 | "sha": "5f65a20e78db20e6af189080bd8a59db3948b0fb", 1038 | "type": "tag", 1039 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/5f65a20e78db20e6af189080bd8a59db3948b0fb" 1040 | } 1041 | }, 1042 | { 1043 | "ref": "refs/tags/8.0.3", 1044 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMC4z", 1045 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.0.3", 1046 | "object": { 1047 | "sha": "adc817629709be733690143f21901479ffbf23c4", 1048 | "type": "tag", 1049 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/adc817629709be733690143f21901479ffbf23c4" 1050 | } 1051 | }, 1052 | { 1053 | "ref": "refs/tags/8.1.0", 1054 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMS4w", 1055 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.1.0", 1056 | "object": { 1057 | "sha": "3605ccaef48a61e741651c3795caa58073b7a286", 1058 | "type": "tag", 1059 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/3605ccaef48a61e741651c3795caa58073b7a286" 1060 | } 1061 | }, 1062 | { 1063 | "ref": "refs/tags/8.1.1", 1064 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMS4x", 1065 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.1.1", 1066 | "object": { 1067 | "sha": "be73694424c1c51d7b6755849733eb6f7babe5c2", 1068 | "type": "tag", 1069 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/be73694424c1c51d7b6755849733eb6f7babe5c2" 1070 | } 1071 | }, 1072 | { 1073 | "ref": "refs/tags/8.1.2", 1074 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMS4y", 1075 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.1.2", 1076 | "object": { 1077 | "sha": "f26b0c514e2b13522e81ec58974539f7e761aae9", 1078 | "type": "tag", 1079 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/f26b0c514e2b13522e81ec58974539f7e761aae9" 1080 | } 1081 | }, 1082 | { 1083 | "ref": "refs/tags/8.1.3", 1084 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMS4z", 1085 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.1.3", 1086 | "object": { 1087 | "sha": "96b11225b3697427cf8fbdda9b53a9652061ba36", 1088 | "type": "tag", 1089 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/96b11225b3697427cf8fbdda9b53a9652061ba36" 1090 | } 1091 | }, 1092 | { 1093 | "ref": "refs/tags/8.1.4", 1094 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMS40", 1095 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.1.4", 1096 | "object": { 1097 | "sha": "3f228b779e10f6d55b9ff579d45f5968e6b50cd9", 1098 | "type": "tag", 1099 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/3f228b779e10f6d55b9ff579d45f5968e6b50cd9" 1100 | } 1101 | }, 1102 | { 1103 | "ref": "refs/tags/8.1.5", 1104 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMS41", 1105 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.1.5", 1106 | "object": { 1107 | "sha": "64adc974334806aa30a95c67e0423f80fc4e98d9", 1108 | "type": "tag", 1109 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/64adc974334806aa30a95c67e0423f80fc4e98d9" 1110 | } 1111 | }, 1112 | { 1113 | "ref": "refs/tags/8.2.0", 1114 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMi4w", 1115 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.2.0", 1116 | "object": { 1117 | "sha": "e7c28ee7e5fef2d10d568c2cc18c2807fae3e756", 1118 | "type": "tag", 1119 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/e7c28ee7e5fef2d10d568c2cc18c2807fae3e756" 1120 | } 1121 | }, 1122 | { 1123 | "ref": "refs/tags/8.2.1", 1124 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMi4x", 1125 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.2.1", 1126 | "object": { 1127 | "sha": "dab27ee9cd5335617d0808e71885d8a69b87535e", 1128 | "type": "tag", 1129 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/dab27ee9cd5335617d0808e71885d8a69b87535e" 1130 | } 1131 | }, 1132 | { 1133 | "ref": "refs/tags/8.3.0", 1134 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguMy4w", 1135 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.3.0", 1136 | "object": { 1137 | "sha": "2888a292c08dea4790449b9ff150116aa8783916", 1138 | "type": "tag", 1139 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/2888a292c08dea4790449b9ff150116aa8783916" 1140 | } 1141 | }, 1142 | { 1143 | "ref": "refs/tags/8.4.0", 1144 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguNC4w", 1145 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.4.0", 1146 | "object": { 1147 | "sha": "02c8bc9509fc66a8f44f42548968b0349b1b5cac", 1148 | "type": "tag", 1149 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/02c8bc9509fc66a8f44f42548968b0349b1b5cac" 1150 | } 1151 | }, 1152 | { 1153 | "ref": "refs/tags/8.4.1", 1154 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguNC4x", 1155 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.4.1", 1156 | "object": { 1157 | "sha": "46f230f6ee59269c2229e44bec84a4e5fbba4661", 1158 | "type": "tag", 1159 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/46f230f6ee59269c2229e44bec84a4e5fbba4661" 1160 | } 1161 | }, 1162 | { 1163 | "ref": "refs/tags/8.4.2", 1164 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguNC4y", 1165 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.4.2", 1166 | "object": { 1167 | "sha": "864f62e2c67c78b478b90fc11fb3bc3e7ea4427e", 1168 | "type": "tag", 1169 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/864f62e2c67c78b478b90fc11fb3bc3e7ea4427e" 1170 | } 1171 | }, 1172 | { 1173 | "ref": "refs/tags/8.5.0", 1174 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguNS4w", 1175 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.5.0", 1176 | "object": { 1177 | "sha": "8223c627ade53fa10cb2c7cd75636d059d757164", 1178 | "type": "tag", 1179 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/8223c627ade53fa10cb2c7cd75636d059d757164" 1180 | } 1181 | }, 1182 | { 1183 | "ref": "refs/tags/8.5.1", 1184 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguNS4x", 1185 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.5.1", 1186 | "object": { 1187 | "sha": "6bc5ac82e04375612a3ed753c636816e83507058", 1188 | "type": "tag", 1189 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/6bc5ac82e04375612a3ed753c636816e83507058" 1190 | } 1191 | }, 1192 | { 1193 | "ref": "refs/tags/8.5.2", 1194 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguNS4y", 1195 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.5.2", 1196 | "object": { 1197 | "sha": "6b6646f8e36c9bf4f361cf9b311c3f791132d3f9", 1198 | "type": "tag", 1199 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/6b6646f8e36c9bf4f361cf9b311c3f791132d3f9" 1200 | } 1201 | }, 1202 | { 1203 | "ref": "refs/tags/8.5.3", 1204 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjguNS4z", 1205 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/8.5.3", 1206 | "object": { 1207 | "sha": "d2194b68eec6af613f84239d3f92de25d4619016", 1208 | "type": "tag", 1209 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/d2194b68eec6af613f84239d3f92de25d4619016" 1210 | } 1211 | }, 1212 | { 1213 | "ref": "refs/tags/9.0.0", 1214 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjkuMC4w", 1215 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/9.0.0", 1216 | "object": { 1217 | "sha": "bbbbe99b1cb6ddf86207acf398cab6f8b83ccce7", 1218 | "type": "tag", 1219 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/bbbbe99b1cb6ddf86207acf398cab6f8b83ccce7" 1220 | } 1221 | }, 1222 | { 1223 | "ref": "refs/tags/9.0.1", 1224 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjkuMC4x", 1225 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/9.0.1", 1226 | "object": { 1227 | "sha": "53fc8475866317255e73a94cd81605450a37c756", 1228 | "type": "tag", 1229 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/53fc8475866317255e73a94cd81605450a37c756" 1230 | } 1231 | }, 1232 | { 1233 | "ref": "refs/tags/9.1.0", 1234 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjkuMS4w", 1235 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/9.1.0", 1236 | "object": { 1237 | "sha": "0bec39eb1c56f2131785ad36d7c06cc6599512b8", 1238 | "type": "tag", 1239 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/0bec39eb1c56f2131785ad36d7c06cc6599512b8" 1240 | } 1241 | }, 1242 | { 1243 | "ref": "refs/tags/9.2.0", 1244 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjkuMi4w", 1245 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/9.2.0", 1246 | "object": { 1247 | "sha": "61e167f43d7ee082c1872e4244dcf21b394d1ed2", 1248 | "type": "tag", 1249 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/61e167f43d7ee082c1872e4244dcf21b394d1ed2" 1250 | } 1251 | }, 1252 | { 1253 | "ref": "refs/tags/9.3.0", 1254 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjkuMy4w", 1255 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/9.3.0", 1256 | "object": { 1257 | "sha": "bca931c7e578596739b99b5acbf4c61cf4eeb5a7", 1258 | "type": "tag", 1259 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/bca931c7e578596739b99b5acbf4c61cf4eeb5a7" 1260 | } 1261 | }, 1262 | { 1263 | "ref": "refs/tags/9.3.1", 1264 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjkuMy4x", 1265 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/9.3.1", 1266 | "object": { 1267 | "sha": "b6c8f431350ad90943fb9ca2767849949837ed0f", 1268 | "type": "tag", 1269 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/b6c8f431350ad90943fb9ca2767849949837ed0f" 1270 | } 1271 | }, 1272 | { 1273 | "ref": "refs/tags/9.3.2", 1274 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjkuMy4y", 1275 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/9.3.2", 1276 | "object": { 1277 | "sha": "4c89c3e9cb6530bfc7cdd2bca5a8907e08426e4c", 1278 | "type": "tag", 1279 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/4c89c3e9cb6530bfc7cdd2bca5a8907e08426e4c" 1280 | } 1281 | }, 1282 | { 1283 | "ref": "refs/tags/9.3.3", 1284 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjkuMy4z", 1285 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/9.3.3", 1286 | "object": { 1287 | "sha": "6e3a924962b6b6f85f7eab63e692d586046ee648", 1288 | "type": "tag", 1289 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/6e3a924962b6b6f85f7eab63e692d586046ee648" 1290 | } 1291 | }, 1292 | { 1293 | "ref": "refs/tags/10.0.0", 1294 | "node_id": "MDM6UmVmMTEyOTIxNjI2OjEwLjAuMA==", 1295 | "url": "https://api.github.com/repos/silverwind/updates/git/refs/tags/10.0.0", 1296 | "object": { 1297 | "sha": "0fe3fc04943a8d3ebe4dda5683715129304e6f44", 1298 | "type": "tag", 1299 | "url": "https://api.github.com/repos/silverwind/updates/git/tags/0fe3fc04943a8d3ebe4dda5683715129304e6f44" 1300 | } 1301 | } 1302 | ] 1303 | -------------------------------------------------------------------------------- /fixtures/npm-empty/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /fixtures/npm-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "gulp-sourcemaps": "2.0.0", 4 | "prismjs": "1.0.0", 5 | "svgstore": "^3.0.0", 6 | "html-webpack-plugin": "4.0.0-alpha.2", 7 | "noty": "3.1.0", 8 | "jpeg-buffer-orientation": "0.0.0", 9 | "styled-components": "2.5.0-1", 10 | "@babel/preset-env": "7.0.0", 11 | "updates": "https://github.com/silverwind/updates/tarball/6941e05", 12 | "ipaddr.js": "https://github.com/silverwind/ipaddr.js/tarball/ipv6_cidrs_take2", 13 | "react": "18.0" 14 | }, 15 | "devDependencies": { 16 | "updates": "file:." 17 | }, 18 | "peerDependencies": { 19 | "@babel/preset-env": "~6.0.0", 20 | "svgstore": "^1.0.0 || ^2.0.0", 21 | "typescript": "^4" 22 | }, 23 | "resolutions": { 24 | "versions/updates": "^1.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fixtures/npm/jpeg-buffer-orientation.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "jpeg-buffer-orientation", 3 | "_rev": "6-951f1bfbf15efe1c07aef84f8148892d", 4 | "name": "jpeg-buffer-orientation", 5 | "dist-tags": { "latest": "2.0.3" }, 6 | "versions": { 7 | "0.0.0": { 8 | "name": "jpeg-buffer-orientation", 9 | "version": "0.0.0", 10 | "description": "get orientation from a jpeg buffer", 11 | "main": "lib/index.js", 12 | "module": "lib/index.mjs", 13 | "browser": "lib/index.min.js", 14 | "unpkg": "lib/index.min.js", 15 | "jsdelivr": "lib/index.min.js", 16 | "repository": { 17 | "type": "git", 18 | "url": "git+ssh://git@github.com/fisker/jpeg-buffer-orientation.git" 19 | }, 20 | "author": { "name": "fisker", "email": "lionkay@gmail.com" }, 21 | "license": "MIT", 22 | "scripts": { 23 | "build": "npm-run-all build:*", 24 | "build:js": "rollup --config", 25 | "dist": "npm-run-all dist:*", 26 | "dist:npm": "np --yolo --no-yarn", 27 | "clean": "rimraf lib", 28 | "test-coverage": "jest --coverage", 29 | "lint": "npm-run-all lint:*", 30 | "lint:js": "eslint src/**/*.js --fix", 31 | "release": "run-s clean lint build test dist", 32 | "test": "jest" 33 | }, 34 | "config": { 35 | "commitizen": { 36 | "path": "./node_modules/cz-conventional-changelog-emoji" 37 | } 38 | }, 39 | "publishConfig": { "registry": "https://registry.npmjs.org/" }, 40 | "devDependencies": { 41 | "@babel/core": "^7.3.4", 42 | "@babel/preset-env": "^7.3.4", 43 | "@commitlint/cli": "^7.5.2", 44 | "@commitlint/config-conventional": "^7.5.0", 45 | "@xwtec/eslint-config": "^3.7.0", 46 | "babel-jest": "^24.5.0", 47 | "cz-conventional-changelog-emoji": "^0.1.0", 48 | "eslint": "^5.15.2", 49 | "husky": "^1.3.1", 50 | "jest": "^24.5.0", 51 | "lint-staged": "^8.1.5", 52 | "markdownlint-cli": "^0.14.0", 53 | "np": "^4.0.2", 54 | "npm-run-all": "^4.1.5", 55 | "prettier": "^1.16.4", 56 | "rimraf": "^2.6.3", 57 | "rollup": "^1.6.0", 58 | "rollup-plugin-babel": "^4.3.2", 59 | "rollup-plugin-commonjs": "^9.2.1", 60 | "rollup-plugin-filesize": "^6.0.1", 61 | "rollup-plugin-node-resolve": "^4.0.1", 62 | "rollup-plugin-terser": "^4.0.4" 63 | }, 64 | "bugs": { 65 | "url": "https://github.com/fisker/jpeg-buffer-orientation/issues" 66 | }, 67 | "homepage": "https://github.com/fisker/jpeg-buffer-orientation#readme", 68 | "_id": "jpeg-buffer-orientation@0.0.0", 69 | "_npmVersion": "6.4.1", 70 | "_nodeVersion": "10.15.1", 71 | "_npmUser": { "name": "fisker", "email": "lionkay@gmail.com" }, 72 | "dist": { 73 | "integrity": "sha512-l+K6X8I+7L4PyH3exEjI8eaoJaMVlBSOB0gQCS+9Vb8ZPHO2vek2eDC0GwrVMpMCAtywBRlVvo1IF8Jf8IPrDA==", 74 | "shasum": "3361a6c860be95c95fea4488e96f7cd3c47340a9", 75 | "tarball": "https://registry.npmjs.org/jpeg-buffer-orientation/-/jpeg-buffer-orientation-0.0.0.tgz", 76 | "fileCount": 1, 77 | "unpackedSize": 1726, 78 | "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJckdAzCRA9TVsSAnZWagAAyhwQAIREmZ0xP7mEd+2r4NN1\n4AlLcuA5Ac6TvDCS5En/RaX2iE9Djcr7lZlOpDt/G1yQcU8x0Q+C9WSxuWCl\nKtpKBdjuMXy7Z9QsnaCfcdv5ogLAr9TAFELTR4Oljzf/CQVyJDX687LVKfNc\nn/HaS83E0Z/lv3RxpzP8XEpNLk265Ogqb8rXQxcjYMfcBNonWs3pSGuhbef7\nRjhB3qq3R9Q1FWalB8NHlF+licXU/g8CJIJrZ/uMK+YsrBS62F1RBoqTxo/2\npNoiBNIp0VSDDpERJittwWi4rlE2s2WQIZGWYop16kvgGhanlucK1aqCFuRn\n64w4ZnO4JcRxxcSTAyXdqogprH4ATOMA2de3IIvMvovsuocNEQOgbn8+J6li\n8Dm4gws+WE4AMACyXFbw6a1UGYd+g/UQGDYykn8xVVPuQ785B3/x9lcAkb83\nmjZ9cVOwWkPuhoyeYd1Ty/LRzJI0wKIEQWvFONdnLXrfbDnMjYC+5uzr5W5r\nxnOSeOKGL1jU5NZPA2k7JHADWekFaP4FE9v4WTeQwjBKIfAK2QoEcwLYyD8i\noUWpxnI4iyvxU8guH8lWL+B0fSQqqAWrSrBoWmcfcPtb2hRheK6kW3KBPZwn\nLsXqGNO2zjBV927rVP7+1mfD4HOBB9cR9jteupOdkrh4lKoAKPWlqR4jxE6Z\now7c\r\n=x3NH\r\n-----END PGP SIGNATURE-----\r\n" 79 | }, 80 | "maintainers": [{ "name": "fisker", "email": "lionkay@gmail.com" }], 81 | "directories": {}, 82 | "_npmOperationalInternal": { 83 | "host": "s3://npm-registry-packages", 84 | "tmp": "tmp/jpeg-buffer-orientation_0.0.0_1553059891151_0.6286552659517253" 85 | }, 86 | "_hasShrinkwrap": false 87 | }, 88 | "1.0.0": { 89 | "name": "jpeg-buffer-orientation", 90 | "version": "1.0.0", 91 | "description": "get orientation from a jpeg buffer", 92 | "main": "lib/index.common.js", 93 | "module": "lib/index.min.mjs", 94 | "browser": "lib/index.min.js", 95 | "unpkg": "lib/index.min.js", 96 | "jsdelivr": "lib/index.min.js", 97 | "repository": { 98 | "type": "git", 99 | "url": "git+ssh://git@github.com/fisker/jpeg-buffer-orientation.git" 100 | }, 101 | "author": { "name": "fisker", "email": "lionkay@gmail.com" }, 102 | "license": "MIT", 103 | "scripts": { 104 | "build": "npm-run-all build:*", 105 | "build:js": "rollup --config", 106 | "docs": "npm-run-all docs:*", 107 | "docs:js": "cpy lib docs/lib", 108 | "docs:image": "cpy __tests__/fixture docs/images", 109 | "docs:html": "cpy src/index.html docs", 110 | "prettier": "prettier --write", 111 | "dist": "npm-run-all dist:*", 112 | "dist:npm": "np --yolo --no-yarn", 113 | "clean": "rimraf lib docs", 114 | "test-coverage": "jest --coverage", 115 | "lint": "npm-run-all lint:*", 116 | "lint:js": "eslint src/**/*.js --fix", 117 | "release": "run-s clean lint build test docs dist", 118 | "test": "jest" 119 | }, 120 | "config": { 121 | "commitizen": { 122 | "path": "./node_modules/cz-conventional-changelog-emoji" 123 | } 124 | }, 125 | "publishConfig": { "registry": "https://registry.npmjs.org/" }, 126 | "devDependencies": { 127 | "@babel/core": "^7.3.4", 128 | "@babel/preset-env": "^7.3.4", 129 | "@commitlint/cli": "^7.5.2", 130 | "@commitlint/config-conventional": "^7.5.0", 131 | "@xwtec/eslint-config": "^3.7.0", 132 | "babel-jest": "^24.5.0", 133 | "cpy-cli": "^2.0.0", 134 | "cz-conventional-changelog-emoji": "^0.1.0", 135 | "eslint": "^5.15.2", 136 | "husky": "^1.3.1", 137 | "jest": "^24.5.0", 138 | "lint-staged": "^8.1.5", 139 | "markdownlint-cli": "^0.14.0", 140 | "np": "^4.0.2", 141 | "npm-run-all": "^4.1.5", 142 | "prettier": "^1.16.4", 143 | "rimraf": "^2.6.3", 144 | "rollup": "^1.6.0", 145 | "rollup-plugin-babel": "^4.3.2", 146 | "rollup-plugin-filesize": "^6.0.1", 147 | "rollup-plugin-prettier": "^0.6.0", 148 | "rollup-plugin-terser": "^4.0.4" 149 | }, 150 | "gitHead": "7c8f6029180cfd4ac22ac01f09694456acdedf29", 151 | "bugs": { 152 | "url": "https://github.com/fisker/jpeg-buffer-orientation/issues" 153 | }, 154 | "homepage": "https://github.com/fisker/jpeg-buffer-orientation#readme", 155 | "_id": "jpeg-buffer-orientation@1.0.0", 156 | "_npmVersion": "6.4.1", 157 | "_nodeVersion": "10.15.1", 158 | "_npmUser": { "name": "fisker", "email": "lionkay@gmail.com" }, 159 | "dist": { 160 | "integrity": "sha512-Rtqsi3QzdZ4Z+WaACSlgKwpHqAHCVOlNfPeA8MwBWN40d+AUUGVavBO6GVCpCTfn4HO1548WKOz8+WKK4CzThQ==", 161 | "shasum": "644af85e85e1a914c3535701b17e5982b4345882", 162 | "tarball": "https://registry.npmjs.org/jpeg-buffer-orientation/-/jpeg-buffer-orientation-1.0.0.tgz", 163 | "fileCount": 12, 164 | "unpackedSize": 53180, 165 | "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcke1qCRA9TVsSAnZWagAAetgP+wUE+TTsFLLiXh2O49r0\n9eO7K7xCe7jACd8TtGr9KkQlaN52qm8FjySwo+cW/CUpGpMGNrxt3iy/gK8e\nhckhZH6jv+0bsBmXaaZ0i0rApPS+DHnldCOeCcH546cm009kpBIj9sSNk8Y4\nROnpqWt+epggThF7q4ogwv2rVYtDuBUPyVnnmdZQx+DtyAt4lFliDhMcqjDt\nv1A6sC0uX4gNd8IlwKcybIxp2wChgfsMwsojmInEyscIcAcH8n1S+wQptLu2\n4ercNCKhZrqt9C8Zz69p/RMJf8kGAhC23JuW6F/4v1SpfQsxOeGG7v6hupTj\nFHvSRmIXK3mIltWIv8v+G+BMEAARDp1PZF7TURxStVEPjd/zHLP/cvi3sIYw\nGTEbdVbsvxUM5nHUtesVpCKAZgfoA3rl8xoGsC/x9fYYAQHWkYRqqlNlhVxh\n6mH6VogdIG8T3VVVlxlde3dHbM7zmCC5dF00ztMjrJisd6Cx7Pj/y5qg/5KQ\ngeg+Ytcf7YMMB7AQ/9V3RvPgQcoue/gdGng93nsHgib8csbDihUmct7yaFNQ\nFCuoinLU5DR+qZjLGy7bcYSIn7zXM6CN1MCdDbkz52sD2eG3zfz9mJyPBrey\nGCECLoh9rQSu3Zon85M4dfdwKQwtT0qtCxOhHHJH/Lo0nSV0XBEDWkn+qnc1\nqqsY\r\n=HfFE\r\n-----END PGP SIGNATURE-----\r\n" 166 | }, 167 | "maintainers": [{ "name": "fisker", "email": "lionkay@gmail.com" }], 168 | "directories": {}, 169 | "_npmOperationalInternal": { 170 | "host": "s3://npm-registry-packages", 171 | "tmp": "tmp/jpeg-buffer-orientation_1.0.0_1553067369550_0.22923552775192269" 172 | }, 173 | "_hasShrinkwrap": false 174 | }, 175 | "1.0.1": { 176 | "name": "jpeg-buffer-orientation", 177 | "version": "1.0.1", 178 | "description": "get orientation from a jpeg buffer", 179 | "main": "lib/index.common.js", 180 | "module": "lib/index.min.mjs", 181 | "browser": "lib/index.min.js", 182 | "unpkg": "lib/index.min.js", 183 | "jsdelivr": "lib/index.min.js", 184 | "repository": { 185 | "type": "git", 186 | "url": "git+ssh://git@github.com/fisker/jpeg-buffer-orientation.git" 187 | }, 188 | "author": { 189 | "name": "fisker Cheung", 190 | "email": "lionkay@gmail.com", 191 | "url": "https://www.fiskercheung.com/" 192 | }, 193 | "license": "MIT", 194 | "scripts": { 195 | "build": "run-p build:*", 196 | "build:js": "rollup --config", 197 | "docs": "run-p docs:*", 198 | "docs:js": "cpy lib docs/lib", 199 | "docs:image": "cpy __tests__/fixture docs/images", 200 | "docs:html": "cpy src/index.html docs", 201 | "prettier": "prettier **/*.{css,html,js,json,less,md,scss,ts,vue,yaml,yml} --write", 202 | "dist": "run-p dist:*", 203 | "dist:npm": "np --yolo --no-yarn", 204 | "clean": "rimraf lib docs", 205 | "test-coverage": "jest --coverage", 206 | "lint": "run-p lint:*", 207 | "lint:eslint": "eslint **/*.{js,mjs,vue} --fix", 208 | "lint:markdown": "markdownlint **/*.md --ignore \"**/node_modules/**\"", 209 | "release": "run-s clean lint build test docs dist", 210 | "test": "jest" 211 | }, 212 | "config": { 213 | "commitizen": { 214 | "path": "./node_modules/cz-conventional-changelog-emoji" 215 | } 216 | }, 217 | "publishConfig": { 218 | "registry": "https://registry.npmjs.org/", 219 | "access": "public" 220 | }, 221 | "devDependencies": { 222 | "@babel/core": "^7.4.5", 223 | "@babel/preset-env": "^7.4.5", 224 | "@commitlint/cli": "^7.6.1", 225 | "@fisker/commitlint-config": "^1.0.8", 226 | "@fisker/eslint-config": "^1.0.14", 227 | "@fisker/eslint-config-jest": "^1.0.2", 228 | "@fisker/husky-config": "^1.1.0", 229 | "@fisker/lint-staged-config": "^1.0.4", 230 | "@fisker/prettier-config": "^1.0.17", 231 | "babel-jest": "^24.8.0", 232 | "cpy-cli": "^2.0.0", 233 | "cz-conventional-changelog-emoji": "^0.1.0", 234 | "eslint": "^5.16.0", 235 | "husky": "^2.3.0", 236 | "jest": "^24.8.0", 237 | "lint-staged": "^8.1.7", 238 | "markdownlint-cli": "^0.16.0", 239 | "npm-run-all": "^4.1.5", 240 | "prettier": "^1.17.1", 241 | "rimraf": "^2.6.3", 242 | "rollup": "^1.12.3", 243 | "rollup-plugin-babel": "^4.3.2", 244 | "rollup-plugin-filesize": "^6.0.1", 245 | "rollup-plugin-prettier": "^0.6.0", 246 | "rollup-plugin-terser": "^5.0.0" 247 | }, 248 | "sideEffects": false, 249 | "gitHead": "ad2936ba2ec94e468607180980184127b6393129", 250 | "bugs": { 251 | "url": "https://github.com/fisker/jpeg-buffer-orientation/issues" 252 | }, 253 | "homepage": "https://github.com/fisker/jpeg-buffer-orientation#readme", 254 | "_id": "jpeg-buffer-orientation@1.0.1", 255 | "_npmVersion": "6.4.1", 256 | "_nodeVersion": "10.15.3", 257 | "_npmUser": { "name": "fisker", "email": "lionkay@gmail.com" }, 258 | "dist": { 259 | "integrity": "sha512-6HqbecO5TQLHn0mS+FcdlAa44T2oC7fNxmFtwCZ4+DHWxvEDbPc2VHajsttxECATCEWmak83rkO5RG18fNke3Q==", 260 | "shasum": "b6e2cc85cb16171f7787e68ac8957fde3c4ba7c1", 261 | "tarball": "https://registry.npmjs.org/jpeg-buffer-orientation/-/jpeg-buffer-orientation-1.0.1.tgz", 262 | "fileCount": 13, 263 | "unpackedSize": 58042, 264 | "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc5mHZCRA9TVsSAnZWagAA6CwP/jyig/OowXYAZJ66uThG\nRQjaN6fgCextNJNibjnew5L9jBZuH4g4wfZMpAFWaSOhVvefeiQJlcQeXu6G\nyi/bwaHePlW6zaf/4wZAf82s2DO0TIPWB6NoaK4GuDhk2MP+diw+JoANE+Np\nRENTPq4x7cZjBnhBJXjoR7OOyl+ASgzhn7iMe3ytqyO+LDNWhDOi+ZFr+9+R\nhcInAbZBFGqLdZxp3V43y5Tw1IN020lepWBrPPbXDlHpDstVoq7OlBlvFCXH\nhrKP2ahNNwGXc7d3Ru81026AwVh05wF92+ElCPB6Gftj5UergcEm5ThkBi4B\nX6dRmjSfp5i41y/kbVreenlh2Kvqvbr6JeZz2VKURj3lzrb4aySHh67h5MmX\nISoUJEHZQIn/ZaJZtv+6dKZH+/BT+Z29ZievAvJ2JKuC7JWXynyR48aM48JW\n7NpHQ1d4IviQ52QZeVAKcQ3pV3dg18e2lmm4iOSn+6QvPR0JiEoROc51vptL\ncSR+ttKWF31V6PHaRVs2bWLgWE62SjaGXx2e4A4SPRJR57+HINRvVU0YFiLm\nngrYIADy3vChuE4MKt1aSQd0FW39wFbwG6p1KuvMQnAeFexxO6C9j2fsakQX\nlsvehrW4hIDNE2Uq0NGb1++n/oZKlsT0RoKjz9uq/FScs6myTXE3mVWJi97e\nRvi6\r\n=NA7u\r\n-----END PGP SIGNATURE-----\r\n" 265 | }, 266 | "maintainers": [{ "name": "fisker", "email": "lionkay@gmail.com" }], 267 | "directories": {}, 268 | "_npmOperationalInternal": { 269 | "host": "s3://npm-registry-packages", 270 | "tmp": "tmp/jpeg-buffer-orientation_1.0.1_1558602201058_0.8499780717859713" 271 | }, 272 | "_hasShrinkwrap": false 273 | }, 274 | "2.0.0": { 275 | "name": "jpeg-buffer-orientation", 276 | "version": "2.0.0", 277 | "description": "get orientation from a jpeg buffer", 278 | "main": "lib/index.common.js", 279 | "module": "lib/index.min.mjs", 280 | "browser": "lib/index.min.js", 281 | "unpkg": "lib/index.min.js", 282 | "jsdelivr": "lib/index.min.js", 283 | "repository": { 284 | "type": "git", 285 | "url": "git+ssh://git@github.com/fisker/jpeg-buffer-orientation.git" 286 | }, 287 | "author": { 288 | "name": "fisker Cheung", 289 | "email": "lionkay@gmail.com", 290 | "url": "https://www.fiskercheung.com/" 291 | }, 292 | "license": "MIT", 293 | "scripts": { 294 | "build": "run-p build:*", 295 | "build:js": "rollup --config", 296 | "docs": "run-p docs:*", 297 | "docs:js": "cpy lib docs/lib", 298 | "docs:image": "cpy __tests__/fixture docs/images", 299 | "docs:html": "cpy src/index.html docs", 300 | "dist": "run-p dist:*", 301 | "dist:npm": "np --yolo --no-yarn", 302 | "clean": "rimraf lib docs", 303 | "test-coverage": "jest --coverage", 304 | "lint": "run-p lint:*", 305 | "lint:eslint": "eslint **/*.{js,mjs,vue}", 306 | "lint:markdown": "markdownlint **/*.md --ignore \"**/node_modules/**\"", 307 | "release": "run-s clean lint build test docs format dist", 308 | "test": "jest", 309 | "format": "run-p format:*", 310 | "format:eslint": "yarn lint:eslint --fix", 311 | "format:prettier": "prettier **/*.{css,html,js,json,less,md,scss,ts,vue,yaml,yml} --write" 312 | }, 313 | "config": { 314 | "commitizen": { 315 | "path": "./node_modules/cz-conventional-changelog-emoji" 316 | } 317 | }, 318 | "publishConfig": { 319 | "registry": "https://registry.npmjs.org/", 320 | "access": "public" 321 | }, 322 | "devDependencies": { 323 | "@babel/core": "^7.4.5", 324 | "@babel/preset-env": "^7.4.5", 325 | "@commitlint/cli": "^8.0.0", 326 | "@fisker/commitlint-config": "^1.1.0", 327 | "@fisker/eslint-config": "^1.2.5", 328 | "@fisker/eslint-config-jest": "^1.1.0", 329 | "@fisker/husky-config": "^1.1.0", 330 | "@fisker/lint-staged-config": "^1.0.4", 331 | "@fisker/prettier-config": "^1.0.17", 332 | "babel-jest": "^24.8.0", 333 | "cpy-cli": "^2.0.0", 334 | "cz-conventional-changelog-emoji": "^0.1.0", 335 | "eslint": "^6.0.1", 336 | "husky": "^3.0.0", 337 | "jest": "^24.8.0", 338 | "lint-staged": "^9.0.2", 339 | "markdownlint-cli": "^0.17.0", 340 | "npm-run-all": "^4.1.5", 341 | "prettier": "^1.18.2", 342 | "rimraf": "^2.6.3", 343 | "rollup": "^1.16.4", 344 | "rollup-plugin-babel": "^4.3.3", 345 | "rollup-plugin-filesize": "^6.1.1", 346 | "rollup-plugin-prettier": "^0.6.0", 347 | "rollup-plugin-terser": "^5.1.0" 348 | }, 349 | "sideEffects": false, 350 | "gitHead": "ee58378e15d96ed2acbb5fe134d34ef370c45e2b", 351 | "bugs": { 352 | "url": "https://github.com/fisker/jpeg-buffer-orientation/issues" 353 | }, 354 | "homepage": "https://github.com/fisker/jpeg-buffer-orientation#readme", 355 | "_id": "jpeg-buffer-orientation@2.0.0", 356 | "_nodeVersion": "10.16.0", 357 | "_npmVersion": "6.9.0", 358 | "dist": { 359 | "integrity": "sha512-kWcDqvQVMAOiQt0aw4wjm32+YTC+/nsIb3ziBdqtWvuYFKNgw+7InyeI9Zlsb/pzKMwXsDcaOamgCDjD9oX7NA==", 360 | "shasum": "7b36f5750a2703db8852a54ec63a79207d41582d", 361 | "tarball": "https://registry.npmjs.org/jpeg-buffer-orientation/-/jpeg-buffer-orientation-2.0.0.tgz", 362 | "fileCount": 13, 363 | "unpackedSize": 57482, 364 | "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdHXQOCRA9TVsSAnZWagAA92kP/AhzAERKOgVvqhJa7/LQ\nqNC1GJuSLB+koagdYSYEnqfVBcDXnIKCXxAM+XucdthphQjIT/YZxyWMpwVO\nnoGTcBYaMIhRVrkNp5u12qwCp/l/waSp8AkpYxR39EgRpJ/iv5T18hDkeAkv\nlyGL5kvkbMmW905Uk09e7QGLLXKgQcwU45Xx/0EddLJLKkAs/3/NtIoMRxWq\nEii/Zx1+1ZhbnE2BVadNWnwOptbgHjPAQtoBGITU5Jd6jdEIzjCZuPmi2LN4\nSTN+s4moqwjqo7H6SMabxsDmcqJVyvrDg5GwEb9pxxL9npVvh016YLjKJxa9\nYRHerNunt886SUA1FdXJGl3s6Xha+CRiqB6BWBMq6Y+yxE2Yf150MQNd10i7\nQDNO723PyunowGYG4Zs/sva38Wl7jIuYJ9vRoG2TCTzrQFbH4Puj5g/F4OPG\nXunL8NRJKyX1o9q1TLxS401GcI1g8eVWleXGcgb7yEn4X6DLy9/xn12sOEOk\nHne9yfDKsWeYXUBSCr1K0nJK3REz05mFEHQ2aVE95DNIPtVOD7WguCiKjkEf\nvPyV/MOfk+QorYoam9fd+yHffjzJQMN+9TLJ9AYRcGRbB32TfIEt8/yADh7L\nF5d19PYbCfXopWrFukQK/WYV44njO96uCet/Uuj/1cN4+VtENVm0zeulJpfH\npmp1\r\n=6riB\r\n-----END PGP SIGNATURE-----\r\n" 365 | }, 366 | "maintainers": [{ "name": "fisker", "email": "lionkay@gmail.com" }], 367 | "_npmUser": { "name": "fisker", "email": "lionkay@gmail.com" }, 368 | "directories": {}, 369 | "_npmOperationalInternal": { 370 | "host": "s3://npm-registry-packages", 371 | "tmp": "tmp/jpeg-buffer-orientation_2.0.0_1562211341556_0.6252401222436288" 372 | }, 373 | "_hasShrinkwrap": false 374 | }, 375 | "2.0.1": { 376 | "name": "jpeg-buffer-orientation", 377 | "version": "2.0.1", 378 | "description": "get orientation from a jpeg buffer", 379 | "main": "lib/index.common.js", 380 | "module": "lib/index.min.mjs", 381 | "browser": "lib/index.min.js", 382 | "unpkg": "lib/index.min.js", 383 | "jsdelivr": "lib/index.min.js", 384 | "repository": { 385 | "type": "git", 386 | "url": "git+ssh://git@github.com/fisker/jpeg-buffer-orientation.git" 387 | }, 388 | "author": { 389 | "name": "fisker Cheung", 390 | "email": "lionkay@gmail.com", 391 | "url": "https://www.fiskercheung.com/" 392 | }, 393 | "license": "MIT", 394 | "scripts": { 395 | "build": "run-p build:*", 396 | "build:js": "rollup --config", 397 | "clean": "rimraf lib docs", 398 | "dist": "run-p dist:*", 399 | "dist:npm": "np --yolo --no-yarn", 400 | "docs": "run-p docs:*", 401 | "docs:html": "cpy src/index.html docs", 402 | "docs:image": "cpy __tests__/fixture docs/images", 403 | "docs:js": "cpy lib docs/lib", 404 | "format": "run-p format:*", 405 | "format:eslint": "yarn lint:eslint --fix", 406 | "format:prettier": "prettier \"**/*.{css,html,js,json,less,md,scss,ts,vue,yaml,yml}\" --write", 407 | "lint": "run-p lint:*", 408 | "lint:eslint": "eslint \"**/*.{js,mjs,vue}\"", 409 | "lint:markdown": "markdownlint \"**/*.md\" --ignore \"**/node_modules/**\"", 410 | "lint:prettier": "prettier \"**/*.{css,html,js,json,less,md,scss,ts,vue,yaml,yml}\" --check", 411 | "release": "run-s clean lint build test docs format dist", 412 | "test": "jest", 413 | "test-coverage": "jest --coverage" 414 | }, 415 | "config": { 416 | "commitizen": { "path": "./node_modules/cz-conventional-changelog" } 417 | }, 418 | "publishConfig": { 419 | "registry": "https://registry.npmjs.org/", 420 | "access": "public" 421 | }, 422 | "devDependencies": { 423 | "@babel/core": "7.5.5", 424 | "@babel/preset-env": "7.5.5", 425 | "@commitlint/cli": "8.1.0", 426 | "@fisker/commitlint-config": "1.1.2", 427 | "@fisker/eslint-config": "1.2.8", 428 | "@fisker/eslint-config-jest": "1.1.4", 429 | "@fisker/husky-config": "1.1.1", 430 | "@fisker/lint-staged-config": "1.0.5", 431 | "@fisker/prettier-config": "1.0.18", 432 | "@fisker/stylelint-config": "1.1.7", 433 | "babel-jest": "24.8.0", 434 | "cpy-cli": "2.0.0", 435 | "cz-conventional-changelog": "3.0.2", 436 | "eslint": "6.1.0", 437 | "husky": "3.0.2", 438 | "jest": "24.8.0", 439 | "lint-staged": "9.2.1", 440 | "markdownlint-cli": "0.17.0", 441 | "npm-run-all": "4.1.5", 442 | "prettier": "1.18.2", 443 | "rimraf": "2.6.3", 444 | "rollup": "1.17.0", 445 | "rollup-plugin-babel": "4.3.3", 446 | "rollup-plugin-filesize": "6.1.1", 447 | "rollup-plugin-prettier": "0.6.0", 448 | "rollup-plugin-terser": "5.1.1" 449 | }, 450 | "sideEffects": false, 451 | "gitHead": "6e430511b7a3b28193612718723bceca8b0f63bc", 452 | "bugs": { 453 | "url": "https://github.com/fisker/jpeg-buffer-orientation/issues" 454 | }, 455 | "homepage": "https://github.com/fisker/jpeg-buffer-orientation#readme", 456 | "_id": "jpeg-buffer-orientation@2.0.1", 457 | "_nodeVersion": "10.16.0", 458 | "_npmVersion": "6.9.0", 459 | "dist": { 460 | "integrity": "sha512-IJnFZo+qTlZPt28gztDoBaLRY+3wcsIHKxki0vNgD3apZLC0Km8OVk8gJE4CtZJv6T7gx2bOWVWK5TkeJpHz6A==", 461 | "shasum": "b8f1351ee70754c39b92e3c7179cc90fbb40c741", 462 | "tarball": "https://registry.npmjs.org/jpeg-buffer-orientation/-/jpeg-buffer-orientation-2.0.1.tgz", 463 | "fileCount": 13, 464 | "unpackedSize": 57596, 465 | "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQXtvCRA9TVsSAnZWagAACB0P/1kUKymbKIvVFm9YvVqZ\nCgIlabOLxEXEflS0i5fAm4vuSlglOc4dv+FEGW28Pf4H6aJ0Er8zg+cDRqCC\nV57zDoNllxmCzwiYCPYR42mVpn3mKttlERZSaaQh9IK+4titHDrtFiDQW6wI\nd7A1eloTVN1GOrjFUZV5mLr8yQHZFNnmvNKyEr4lUhS0lgDcZApnIQpVjA96\nZPORibdoWjjt5jfGKvJOo7YRGHdjUJ3dPOZvC0IMCyop786k9SncRadxu/uV\n/6iNCZ3YI5bGKNMuHh5f3ayxWR4tsSRUyMGYx3+xuAiLTqQoXcdZs+h155yE\n0MbQbRSQwKwKIgnHs64xTAvAfMQlZ/yOvRe2Aq3TZIWxPJMNbouEXWVDvR68\nlB8hmZq1NqwhdiLuKBURFblLWeiknKLWTYuR+e6NMBdbqh6u6Vx+LC+u+zrM\nKsqWJs/GT0vBj0e7AgTrwdLbgL2c9wNernAOLUQ7YDb0RVn5CIiqSyuZD4Wn\nIu983eNQa0RSskYg53UVg3s6nD6O0bF4ceoHntdc+G+Bdt1MkJth5bcPNtY6\nQsxb0v0Yq6Uob9W6WXayxg8eGcYnRG7lU40BuPYrLYbvDF6YxkJd/sUNOThX\nIEdkiiA8ngWAyOMxiEnwquh0bqmYD4OSf9rAnLRhiioVymb6GTVH2IEYsAg8\nru0r\r\n=Q658\r\n-----END PGP SIGNATURE-----\r\n" 466 | }, 467 | "maintainers": [{ "name": "fisker", "email": "lionkay@gmail.com" }], 468 | "_npmUser": { "name": "fisker", "email": "lionkay@gmail.com" }, 469 | "directories": {}, 470 | "_npmOperationalInternal": { 471 | "host": "s3://npm-registry-packages", 472 | "tmp": "tmp/jpeg-buffer-orientation_2.0.1_1564572526461_0.7117217355647429" 473 | }, 474 | "_hasShrinkwrap": false 475 | }, 476 | "2.0.2": { 477 | "name": "jpeg-buffer-orientation", 478 | "version": "2.0.2", 479 | "description": "get orientation from a jpeg buffer", 480 | "main": "lib/index.common.js", 481 | "module": "lib/index.min.mjs", 482 | "browser": "lib/index.min.js", 483 | "unpkg": "lib/index.min.js", 484 | "jsdelivr": "lib/index.min.js", 485 | "repository": { 486 | "type": "git", 487 | "url": "git+ssh://git@github.com/fisker/jpeg-buffer-orientation.git" 488 | }, 489 | "author": { 490 | "name": "fisker Cheung", 491 | "email": "lionkay@gmail.com", 492 | "url": "https://www.fiskercheung.com/" 493 | }, 494 | "license": "MIT", 495 | "scripts": { 496 | "build": "run-p build:*", 497 | "build:js": "rollup --config", 498 | "clean": "rimraf lib docs", 499 | "dist": "run-p dist:*", 500 | "dist:npm": "np --yolo --no-yarn", 501 | "docs": "run-p docs:*", 502 | "docs:html": "cpy src/index.html docs", 503 | "docs:image": "cpy __tests__/fixture docs/images", 504 | "docs:js": "cpy lib docs/lib", 505 | "format": "run-p format:*", 506 | "format:eslint": "yarn lint:eslint --fix", 507 | "format:prettier": "prettier \"**/*.{css,html,js,json,less,md,scss,ts,vue,yaml,yml}\" --write", 508 | "lint": "run-p lint:*", 509 | "lint:eslint": "eslint \"**/*.{js,mjs,vue}\"", 510 | "lint:markdown": "markdownlint \"**/*.md\" --ignore \"**/node_modules/**\"", 511 | "lint:prettier": "prettier \"**/*.{css,html,js,json,less,md,scss,ts,vue,yaml,yml}\" --check", 512 | "release": "run-s clean lint build test docs format dist", 513 | "test": "jest", 514 | "test-coverage": "jest --coverage" 515 | }, 516 | "config": { 517 | "commitizen": { "path": "./node_modules/cz-conventional-changelog" } 518 | }, 519 | "publishConfig": { 520 | "registry": "https://registry.npmjs.org/", 521 | "access": "public" 522 | }, 523 | "devDependencies": { 524 | "@babel/core": "7.6.4", 525 | "@babel/preset-env": "7.6.3", 526 | "@commitlint/cli": "8.2.0", 527 | "@fisker/commitlint-config": "1.1.3", 528 | "@fisker/eslint-config": "1.3.4", 529 | "@fisker/eslint-config-jest": "1.1.12", 530 | "@fisker/husky-config": "1.1.3", 531 | "@fisker/lint-staged-config": "1.0.6", 532 | "@fisker/prettier-config": "1.0.21", 533 | "babel-jest": "24.9.0", 534 | "cpy-cli": "2.0.0", 535 | "cz-conventional-changelog": "3.0.2", 536 | "eslint": "6.5.1", 537 | "husky": "3.0.9", 538 | "jest": "24.9.0", 539 | "lint-staged": "9.4.2", 540 | "markdownlint-cli": "0.19.0", 541 | "npm-run-all": "4.1.5", 542 | "nyc": "14.1.1", 543 | "prettier": "1.18.2", 544 | "rimraf": "3.0.0", 545 | "rollup": "1.25.2", 546 | "rollup-plugin-babel": "4.3.3", 547 | "rollup-plugin-filesize": "6.2.1", 548 | "rollup-plugin-prettier": "0.6.0", 549 | "rollup-plugin-terser": "5.1.2" 550 | }, 551 | "sideEffects": false, 552 | "gitHead": "906a353d85a51842a2b4b2fde244e0670e61ef94", 553 | "bugs": { 554 | "url": "https://github.com/fisker/jpeg-buffer-orientation/issues" 555 | }, 556 | "homepage": "https://github.com/fisker/jpeg-buffer-orientation#readme", 557 | "_id": "jpeg-buffer-orientation@2.0.2", 558 | "_nodeVersion": "10.16.3", 559 | "_npmVersion": "6.9.0", 560 | "dist": { 561 | "integrity": "sha512-ps1FhBCsK16dXNpsFTEbQk359XIYtJ4b66+jhwDSR4+X/Hae1dIPq5337aKo3aasPoV/0m2tOao4Hxeaae8MJA==", 562 | "shasum": "28c8baadb3f9dc1ff48fef97753d27443e240294", 563 | "tarball": "https://registry.npmjs.org/jpeg-buffer-orientation/-/jpeg-buffer-orientation-2.0.2.tgz", 564 | "fileCount": 13, 565 | "unpackedSize": 58999, 566 | "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdsBeJCRA9TVsSAnZWagAA9dIP/A8LqjM3aPYseuXrGReU\nSSfvHRjLhLlTqnYsl5Z3oAKJTTtqskFJDWBlp1cGqhiM+GdAxSlrziCZNc6u\n6HRAwrCPFMlzrOGZG8iXCOQGn+KtOoOkxeUTjUIugAm2P3/G/OmhflXoW64C\n71Igqae1gtG1u8cFLXM/gvXxVYLbxcAdBF72H4vB9bPhAxfOaJO2ljk/nW0z\nWmGs1IXqp9cyphyiPUukHvEr1YOxGbjGubHEZOPttaOZ01xA3sRpJqm7B0Bx\nQlIhpC5cfcYGiAFY520MvxJwIyDUqPXWgk1yVT9dpHxEUG1Z0j04A/ZZV9B0\nPJxjRI4hqFCElFjLoqq/zBJmf0UCbwJdFJnZHWxIUzJuitLemfyYuNfwcvuP\nkprGeI5Aa4EyHAOCfxIfhcJRjQu3cA+99Dm5Ql3ywQqqsGmMDx6MkOCHgJmo\n0tD8mPt/pZVjWnvmtV0dOnu6Me6VYNwKamWV/qqV4hYzFVhCvoXQRmk1VQ5w\n/896bJbPs3qksbX2nKIMV2XYirRs9PeQUU2ZHiJJrrRc56W9ee10Z7dbOMku\nYsmJIedeMs0hXpvP4jC4Mgx6O5FX8KmXqI8+hegI5dhBTr9PxKUA5ZdV+IIj\nnEEUQEWoSq2bc4iFz/MFLkT5qw3a2oISaK9hyRW+XTAPWp2Ktm2hC91R0Ny9\nCjSV\r\n=jenZ\r\n-----END PGP SIGNATURE-----\r\n" 567 | }, 568 | "maintainers": [{ "name": "fisker", "email": "lionkay@gmail.com" }], 569 | "_npmUser": { "name": "fisker", "email": "lionkay@gmail.com" }, 570 | "directories": {}, 571 | "_npmOperationalInternal": { 572 | "host": "s3://npm-registry-packages", 573 | "tmp": "tmp/jpeg-buffer-orientation_2.0.2_1571821449502_0.004977468991351097" 574 | }, 575 | "_hasShrinkwrap": false 576 | }, 577 | "2.0.3": { 578 | "name": "jpeg-buffer-orientation", 579 | "version": "2.0.3", 580 | "description": "get orientation from a jpeg buffer", 581 | "repository": { 582 | "type": "git", 583 | "url": "git+ssh://git@github.com/fisker/jpeg-buffer-orientation.git" 584 | }, 585 | "license": "MIT", 586 | "author": { 587 | "name": "fisker Cheung", 588 | "email": "lionkay@gmail.com", 589 | "url": "https://www.fiskercheung.com/" 590 | }, 591 | "sideEffects": false, 592 | "main": "dist/index.common.js", 593 | "jsdelivr": "dist/index.min.js", 594 | "unpkg": "dist/index.min.js", 595 | "module": "dist/index.min.mjs", 596 | "browser": "dist/index.min.js", 597 | "scripts": { 598 | "build": "run-p build:*", 599 | "build:js": "rollup --config", 600 | "clean": "run-p clean:*", 601 | "clean:dist": "del-cli dist docs", 602 | "dist": "run-p dist:*", 603 | "dist:npm": "np --yolo --no-yarn", 604 | "docs": "run-p docs:*", 605 | "docs:html": "cpy src/index.html docs", 606 | "docs:image": "cpy __tests__/fixture docs/images", 607 | "docs:js": "cpy dist docs/dist", 608 | "format": "run-p format:*", 609 | "format:eslint": "yarn lint:eslint --fix", 610 | "format:markdown": "yarn lint:markdown --fix", 611 | "format:package-json": "sort-package-json \"package.json\" \"packages/*/package.json\"", 612 | "format:prettier": "yarn lint:prettier --write", 613 | "lint": "run-p lint:*", 614 | "lint:eslint": "eslint \"**/*.{js,mjs,vue}\"", 615 | "lint:markdown": "markdownlint \"**/*.md\" --ignore \"**/node_modules/**\"", 616 | "lint:package-json": "yarn run format:package-json --check", 617 | "lint:prettier": "prettier \"**/*.{css,html,js,json,less,md,scss,ts,vue,yaml,yml}\" --check", 618 | "release": "run-s clean lint build test docs format dist", 619 | "test": "jest", 620 | "test-coverage": "jest --coverage" 621 | }, 622 | "config": { 623 | "commitizen": { "path": "./node_modules/cz-conventional-changelog" } 624 | }, 625 | "devDependencies": { 626 | "@babel/core": "7.7.4", 627 | "@babel/preset-env": "7.7.4", 628 | "@commitlint/cli": "8.2.0", 629 | "@fisker/commitlint-config": "1.1.4", 630 | "@fisker/eslint-config": "1.5.1", 631 | "@fisker/eslint-config-jest": "1.2.1", 632 | "@fisker/husky-config": "1.1.5", 633 | "@fisker/lint-staged-config": "1.0.8", 634 | "@fisker/prettier-config": "1.0.24", 635 | "babel-jest": "24.9.0", 636 | "cpy-cli": "2.0.0", 637 | "cz-conventional-changelog": "3.0.2", 638 | "del-cli": "3.0.0", 639 | "eslint": "6.7.2", 640 | "husky": "3.1.0", 641 | "jest": "24.9.0", 642 | "lint-staged": "9.5.0", 643 | "markdownlint-cli": "0.19.0", 644 | "npm-run-all": "4.1.5", 645 | "nyc": "14.1.1", 646 | "prettier": "1.19.1", 647 | "rollup": "1.27.8", 648 | "rollup-plugin-babel": "4.3.3", 649 | "rollup-plugin-filesize": "6.2.1", 650 | "rollup-plugin-prettier": "0.6.0", 651 | "rollup-plugin-terser": "5.1.2", 652 | "sort-package-json": "1.30.0" 653 | }, 654 | "publishConfig": { 655 | "access": "public", 656 | "registry": "https://registry.npmjs.org/" 657 | }, 658 | "gitHead": "f5819df4eb6ebccc968d371931b31554ade5d436", 659 | "bugs": { 660 | "url": "https://github.com/fisker/jpeg-buffer-orientation/issues" 661 | }, 662 | "homepage": "https://github.com/fisker/jpeg-buffer-orientation#readme", 663 | "_id": "jpeg-buffer-orientation@2.0.3", 664 | "_nodeVersion": "10.16.2", 665 | "_npmVersion": "6.9.0", 666 | "dist": { 667 | "integrity": "sha512-lHjA3pL9Z3CcHgwnTMUg10OBNzHLcOuTTn/kro1p8bJLf61Kc0F8eJ47IJvOPWmdo2NgyJK5CoM68LCD3K32Yg==", 668 | "shasum": "4af45cbb82dfe0767e9a8d5ac9101e856c3919d5", 669 | "tarball": "https://registry.npmjs.org/jpeg-buffer-orientation/-/jpeg-buffer-orientation-2.0.3.tgz", 670 | "fileCount": 13, 671 | "unpackedSize": 59245, 672 | "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd5pXZCRA9TVsSAnZWagAA32MP+wTg26qr54KeHUJdDPZ4\nO9049lxvIS5cGUpOEW1dKxL965jYISP15K1Jj9WDf2CZWoOMOFDj7Z2fZ9kg\n4j4tPyrHeBsmcOIwBXAgheyepFkyNb7FiTNxAXlvUQzMuI0lNsk7dvuTQ33X\nWz/TcovMlupsENM3mvVRDLYy3ThIdi5wezrjahwqdS6o9MBlXDzVv3Gbu7Wn\nc4w5kI9YgzSRRCbZjbOnBYYM09xMFcgGeER5w/OuUuzDYJA9KzK1S+VnlUq2\nKtcxS8e8mW85rGvg00wTVhsi6zV6Od36N1ajVKB+dStzCyCzydyQuMfSpDIa\ni+X1zeyYRiifKl5BMehIH2c+CQuKwcVGtl1Gz0ZqnRYenz2/qMzJeyc+hIhD\nsZmax5M0A3nUaEsPYG4I6E8RAdtH5CwhasrYJ3JC1rOmTlgSWFNfzEApdKC4\nFBnEXC2uGD91r/z/9RkvRHGD+HB65qpN5RjEGAMT7iElHfMDi10F0UfiZ1Lq\nSERrTy/rV+zq5CDF2ZWRz/dbZw4DH00uFYYBjKzm7Rq9Whq3e8tJvC6vhIvh\nFD4EGrNKmRS8C6IBApm9vWfg91ls5G0lAxz796q11doFFuG5Rz0oAbGM9TKa\ndIdf3OkhCkeuWpzE4eHUNM2R9o8Rb9Cm5pAAIEHHjg2/TOGu528KJKAqHD9O\ni5XC\r\n=BEKD\r\n-----END PGP SIGNATURE-----\r\n" 673 | }, 674 | "maintainers": [{ "name": "fisker", "email": "lionkay@gmail.com" }], 675 | "_npmUser": { "name": "fisker", "email": "lionkay@gmail.com" }, 676 | "directories": {}, 677 | "_npmOperationalInternal": { 678 | "host": "s3://npm-registry-packages", 679 | "tmp": "tmp/jpeg-buffer-orientation_2.0.3_1575392728778_0.023808633142333724" 680 | }, 681 | "_hasShrinkwrap": false 682 | } 683 | }, 684 | "time": { 685 | "created": "2019-03-20T05:31:31.150Z", 686 | "0.0.0": "2019-03-20T05:31:31.255Z", 687 | "modified": "2019-12-03T17:05:32.836Z", 688 | "1.0.0": "2019-03-20T07:36:09.665Z", 689 | "1.0.1": "2019-05-23T09:03:21.205Z", 690 | "2.0.0": "2019-07-04T03:35:41.727Z", 691 | "2.0.1": "2019-07-31T11:28:46.602Z", 692 | "2.0.2": "2019-10-23T09:04:09.659Z", 693 | "2.0.3": "2019-12-03T17:05:28.947Z" 694 | }, 695 | "maintainers": [{ "name": "fisker", "email": "lionkay@gmail.com" }], 696 | "description": "get orientation from a jpeg buffer", 697 | "homepage": "https://github.com/fisker/jpeg-buffer-orientation#readme", 698 | "repository": { 699 | "type": "git", 700 | "url": "git+ssh://git@github.com/fisker/jpeg-buffer-orientation.git" 701 | }, 702 | "author": { 703 | "name": "fisker Cheung", 704 | "email": "lionkay@gmail.com", 705 | "url": "https://www.fiskercheung.com/" 706 | }, 707 | "bugs": { "url": "https://github.com/fisker/jpeg-buffer-orientation/issues" }, 708 | "license": "MIT", 709 | "readme": "# jpeg-buffer-orientation\n\n[![gzip size](http://img.badgesize.io/https://unpkg.com/jpeg-buffer-orientation/dist/index.min.mjs?compression=gzip&style=flat-square)](http://img.badgesize.io/https://unpkg.com/jpeg-buffer-orientation/dist/index.min.mjs)\n\n[![Travis](https://img.shields.io/travis/fisker/jpeg-buffer-orientation.svg?style=flat-square)](https://travis-ci.org/fisker/jpeg-buffer-orientation)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f1c92423809b450e871e4812581f8fe6)](https://app.codacy.com/app/fisker/jpeg-buffer-orientation?utm_source=github.com&utm_medium=referral&utm_content=fisker/jpeg-buffer-orientation&utm_campaign=Badge_Grade_Settings)\n[![Coveralls github](https://img.shields.io/coveralls/github/fisker/jpeg-buffer-orientation.svg?style=flat-square)](https://coveralls.io/github/fisker/jpeg-buffer-orientation)\n\n[![devDependencies](https://img.shields.io/david/dev/fisker/jpeg-buffer-orientation.svg?style=flat-square)](https://david-dm.org/fisker/jpeg-buffer-orientation)\n[![Issues](http://img.shields.io/github/issues/fisker/jpeg-buffer-orientation.svg?style=flat-square)](https://github.com/fisker/jpeg-buffer-orientation/issues)\n[![Issues](https://img.shields.io/github/issues-pr/fisker/jpeg-buffer-orientation.svg?style=flat-square)](https://github.com/fisker/jpeg-buffer-orientation/pulls)\n[![GitHub last commit](https://img.shields.io/github/last-commit/fisker/jpeg-buffer-orientation.svg?style=flat-square)](https://github.com/fisker/jpeg-buffer-orientation/commits)\n[![GitHub Release Date](https://img.shields.io/github/release-date/fisker/jpeg-buffer-orientation.svg?style=flat-square)](https://github.com/fisker/jpeg-buffer-orientation/releases)\n\n[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n[![MIT license](https://img.shields.io/github/license/fisker/jpeg-buffer-orientation.svg?style=flat-square)](http://opensource.org/licenses/MIT)\n\n> get orientation from a jpeg buffer\n\n## Install\n\n```sh\nyarn add --dev jpeg-buffer-orientation\n```\n\n## Usage\n\nin browser\n\n```html\n\n```\n\n[demo](https://fisker.github.com/jpeg-buffer-orientation)\n\nin browser (legacy)\n\n```html\n\n\n```\n\nin node\n\n```js\nimport getOrientation from 'jpeg-buffer-orientation'\n\nconst myJPEGFile = 'path/to/a/jpeg/file'\nconst {buffer} = readFileSync(myJPEGFile)\nconst orientation = getOrientation(buffer)\nconsole.log('orientation', orientation)\n```\n\n## API\n\ngetOrientation(buffer)\n\n- buffer\n\n type: `ArrayBuffer`\n\n- @returns\n\n type: `Number|undefined`\n\n## FYI\n\nthis package is design for use in browser, not optimized for node.\n\n1. accept `Buffer` instead of `ArrayBuffer` should be easier to use.\n2. instead of reading the whole image, just reading head maybe better.\n\n## License\n\nMIT © [fisker Cheung](https://github.com/fisker)\n", 710 | "readmeFilename": "readme.md" 711 | } 712 | -------------------------------------------------------------------------------- /fixtures/npm/svgstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "svgstore", 3 | "_rev": "14-5f646a9496caeee910226d7dfc2fd445", 4 | "name": "svgstore", 5 | "description": "Combines mulitple svg files into one.", 6 | "dist-tags": { "latest": "3.0.0-2", "next": "3.0.0-0" }, 7 | "versions": { 8 | "1.0.0": { 9 | "name": "svgstore", 10 | "version": "1.0.0", 11 | "description": "Combines mulitple svg files into one.", 12 | "main": "src/svgstore.js", 13 | "scripts": { 14 | "coveralls": "nyc report -r text-lcov | coveralls", 15 | "pretest": "xo src/*.js test/*.js", 16 | "test": "nyc ava -v", 17 | "posttest": "nyc report -r lcov", 18 | "watch": "chokidar '{src,test}/**/*.js' -c 'npm test'" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/shannonmoeller/svgstore.git" 23 | }, 24 | "keywords": [ 25 | "concat", 26 | "join", 27 | "merge", 28 | "pack", 29 | "path", 30 | "sprite", 31 | "svg", 32 | "svgs", 33 | "svgstore", 34 | "symbol", 35 | "symbols" 36 | ], 37 | "author": { 38 | "name": "Shannon Moeller", 39 | "email": "me@shannonmoeller.com", 40 | "url": "http://shannonmoeller.com" 41 | }, 42 | "license": "MIT", 43 | "bugs": { "url": "https://github.com/shannonmoeller/svgstore/issues" }, 44 | "homepage": "https://github.com/shannonmoeller/svgstore", 45 | "dependencies": { "cheerio": "^0.20.0" }, 46 | "devDependencies": { 47 | "ava": "^0.12.0", 48 | "chokidar-cli": "^1.2.0", 49 | "coveralls": "^2.11.6", 50 | "nyc": "^6.0.0", 51 | "xo": "^0.12.1" 52 | }, 53 | "engines": { "node": ">= 0.12" }, 54 | "gitHead": "23ad86240e00ba80d3ddbc2607ead4916978450a", 55 | "_id": "svgstore@1.0.0", 56 | "_shasum": "92dd8bd140a80e457a642305297e0ab73f1fd5f3", 57 | "_from": ".", 58 | "_npmVersion": "3.6.0", 59 | "_nodeVersion": "5.6.0", 60 | "_npmUser": { 61 | "name": "shannonmoeller", 62 | "email": "me@shannonmoeller.com" 63 | }, 64 | "dist": { 65 | "shasum": "92dd8bd140a80e457a642305297e0ab73f1fd5f3", 66 | "tarball": "https://registry.npmjs.org/svgstore/-/svgstore-1.0.0.tgz" 67 | }, 68 | "maintainers": [ 69 | { "name": "shannonmoeller", "email": "me@shannonmoeller.com" } 70 | ], 71 | "_npmOperationalInternal": { 72 | "host": "packages-12-west.internal.npmjs.com", 73 | "tmp": "tmp/svgstore-1.0.0.tgz_1457558098823_0.10486977710388601" 74 | }, 75 | "directories": {} 76 | }, 77 | "1.1.0": { 78 | "name": "svgstore", 79 | "version": "1.1.0", 80 | "description": "Combines mulitple svg files into one.", 81 | "main": "src/svgstore.js", 82 | "scripts": { 83 | "coveralls": "nyc report -r text-lcov | coveralls", 84 | "test": "xo src/*.js test/*.js; nyc ava -v", 85 | "posttest": "nyc report -r lcov", 86 | "watch": "chokidar '{src,test}/**/*.js' -c 'npm test'" 87 | }, 88 | "repository": { 89 | "type": "git", 90 | "url": "git+https://github.com/shannonmoeller/svgstore.git" 91 | }, 92 | "keywords": [ 93 | "concat", 94 | "join", 95 | "merge", 96 | "pack", 97 | "path", 98 | "sprite", 99 | "svg", 100 | "svgs", 101 | "svgstore", 102 | "symbol", 103 | "symbols" 104 | ], 105 | "author": { 106 | "name": "Shannon Moeller", 107 | "email": "me@shannonmoeller.com", 108 | "url": "http://shannonmoeller.com" 109 | }, 110 | "license": "MIT", 111 | "bugs": { "url": "https://github.com/shannonmoeller/svgstore/issues" }, 112 | "homepage": "https://github.com/shannonmoeller/svgstore", 113 | "dependencies": { "cheerio": "^0.20.0", "object-assign": "^4.1.0" }, 114 | "devDependencies": { 115 | "ava": "0.15.2", 116 | "chokidar-cli": "^1.2.0", 117 | "coveralls": "^2.11.6", 118 | "nyc": "^7.0.0", 119 | "xo": "^0.16" 120 | }, 121 | "engines": { "node": ">= 0.12" }, 122 | "gitHead": "7d5bc7cef614b698d57279a5a0b3a33a58bfb264", 123 | "_id": "svgstore@1.1.0", 124 | "_shasum": "a3fb5d731bcc24a70a0bb5303e34dad40500044e", 125 | "_from": ".", 126 | "_npmVersion": "3.10.3", 127 | "_nodeVersion": "6.3.1", 128 | "_npmUser": { 129 | "name": "shannonmoeller", 130 | "email": "me@shannonmoeller.com" 131 | }, 132 | "dist": { 133 | "shasum": "a3fb5d731bcc24a70a0bb5303e34dad40500044e", 134 | "tarball": "https://registry.npmjs.org/svgstore/-/svgstore-1.1.0.tgz" 135 | }, 136 | "maintainers": [ 137 | { "name": "bsipple", "email": "bsipple57@gmail.com" }, 138 | { "name": "shannonmoeller", "email": "me@shannonmoeller.com" } 139 | ], 140 | "_npmOperationalInternal": { 141 | "host": "packages-12-west.internal.npmjs.com", 142 | "tmp": "tmp/svgstore-1.1.0.tgz_1470660692409_0.16017176560126245" 143 | }, 144 | "directories": {} 145 | }, 146 | "2.0.0": { 147 | "name": "svgstore", 148 | "version": "2.0.0", 149 | "description": "Combines mulitple svg files into one.", 150 | "main": "src/svgstore.js", 151 | "scripts": { 152 | "coveralls": "nyc report -r text-lcov | coveralls", 153 | "pretest": "xo src/*.js test/*.js", 154 | "test": "nyc ava -v", 155 | "posttest": "nyc report -r lcov", 156 | "watch": "chokidar '{src,test}/**/*.js' -d 1000 -c 'npm test'" 157 | }, 158 | "repository": { 159 | "type": "git", 160 | "url": "git+https://github.com/svgstore/svgstore.git" 161 | }, 162 | "keywords": [ 163 | "concat", 164 | "join", 165 | "merge", 166 | "pack", 167 | "path", 168 | "sprite", 169 | "svg", 170 | "svgs", 171 | "svgstore", 172 | "symbol", 173 | "symbols" 174 | ], 175 | "author": { 176 | "name": "Shannon Moeller", 177 | "email": "me@shannonmoeller.com", 178 | "url": "http://shannonmoeller.com" 179 | }, 180 | "maintainers": [ 181 | { "name": "bsipple", "email": "bsipple57@gmail.com" }, 182 | { "name": "shannonmoeller", "email": "me@shannonmoeller.com" } 183 | ], 184 | "license": "MIT", 185 | "bugs": { "url": "https://github.com/svgstore/svgstore/issues" }, 186 | "homepage": "https://github.com/svgstore/svgstore", 187 | "dependencies": { "cheerio": "^0.22.0", "object-assign": "^4.1.0" }, 188 | "devDependencies": { 189 | "ava": "0.16.0", 190 | "chokidar-cli": "^1.2.0", 191 | "coveralls": "^2.11.12", 192 | "nyc": "^8.1.0", 193 | "xo": "^0.16" 194 | }, 195 | "engines": { "node": ">= 0.12" }, 196 | "gitHead": "be4bc5189764deefb77f9db3e98e65ff2ff1eecd", 197 | "_id": "svgstore@2.0.0", 198 | "_shasum": "72d96baf74389a9eb41937fd037f6d18e9c8a395", 199 | "_from": ".", 200 | "_npmVersion": "3.10.8", 201 | "_nodeVersion": "6.9.1", 202 | "_npmUser": { 203 | "name": "shannonmoeller", 204 | "email": "me@shannonmoeller.com" 205 | }, 206 | "dist": { 207 | "shasum": "72d96baf74389a9eb41937fd037f6d18e9c8a395", 208 | "tarball": "https://registry.npmjs.org/svgstore/-/svgstore-2.0.0.tgz" 209 | }, 210 | "_npmOperationalInternal": { 211 | "host": "packages-12-west.internal.npmjs.com", 212 | "tmp": "tmp/svgstore-2.0.0.tgz_1481291505877_0.01739357877522707" 213 | }, 214 | "directories": {} 215 | }, 216 | "2.0.1": { 217 | "name": "svgstore", 218 | "version": "2.0.1", 219 | "description": "Combines mulitple svg files into one.", 220 | "main": "src/svgstore.js", 221 | "scripts": { 222 | "coveralls": "nyc report -r text-lcov | coveralls", 223 | "pretest": "xo src/*.js test/*.js", 224 | "test": "nyc ava -v", 225 | "posttest": "nyc report -r lcov", 226 | "watch": "chokidar '{src,test}/**/*.js' -d 1000 -c 'npm test'" 227 | }, 228 | "repository": { 229 | "type": "git", 230 | "url": "git+https://github.com/svgstore/svgstore.git" 231 | }, 232 | "keywords": [ 233 | "concat", 234 | "join", 235 | "merge", 236 | "pack", 237 | "path", 238 | "sprite", 239 | "svg", 240 | "svgs", 241 | "svgstore", 242 | "symbol", 243 | "symbols" 244 | ], 245 | "author": { 246 | "name": "Shannon Moeller", 247 | "email": "me@shannonmoeller.com", 248 | "url": "http://shannonmoeller.com" 249 | }, 250 | "maintainers": [ 251 | { "name": "bsipple", "email": "bsipple57@gmail.com" }, 252 | { "name": "shannonmoeller", "email": "me@shannonmoeller.com" } 253 | ], 254 | "license": "MIT", 255 | "bugs": { "url": "https://github.com/svgstore/svgstore/issues" }, 256 | "homepage": "https://github.com/svgstore/svgstore", 257 | "dependencies": { "cheerio": "^0.22.0", "object-assign": "^4.1.0" }, 258 | "devDependencies": { 259 | "ava": "0.16.0", 260 | "chokidar-cli": "^1.2.0", 261 | "coveralls": "^2.11.12", 262 | "nyc": "^8.1.0", 263 | "xo": "^0.16" 264 | }, 265 | "engines": { "node": ">= 0.12" }, 266 | "gitHead": "2173923027049d4c12f0e09c2458c1798c1686b9", 267 | "_id": "svgstore@2.0.1", 268 | "_shasum": "610bc9aaf00e44b8087907e7b626feb2d1291575", 269 | "_from": ".", 270 | "_npmVersion": "3.10.8", 271 | "_nodeVersion": "6.9.1", 272 | "_npmUser": { 273 | "name": "shannonmoeller", 274 | "email": "me@shannonmoeller.com" 275 | }, 276 | "dist": { 277 | "shasum": "610bc9aaf00e44b8087907e7b626feb2d1291575", 278 | "tarball": "https://registry.npmjs.org/svgstore/-/svgstore-2.0.1.tgz" 279 | }, 280 | "_npmOperationalInternal": { 281 | "host": "packages-18-east.internal.npmjs.com", 282 | "tmp": "tmp/svgstore-2.0.1.tgz_1481292207125_0.2159856262151152" 283 | }, 284 | "directories": {} 285 | }, 286 | "2.0.2": { 287 | "name": "svgstore", 288 | "version": "2.0.2", 289 | "description": "Combines mulitple svg files into one.", 290 | "main": "src/svgstore.js", 291 | "scripts": { 292 | "coveralls": "nyc report -r text-lcov | coveralls", 293 | "pretest": "xo src/*.js test/*.js", 294 | "test": "nyc ava -v", 295 | "posttest": "nyc report -r lcov", 296 | "watch": "chokidar '{src,test}/**/*.js' -d 1000 -c 'npm test'" 297 | }, 298 | "repository": { 299 | "type": "git", 300 | "url": "git+https://github.com/svgstore/svgstore.git" 301 | }, 302 | "keywords": [ 303 | "concat", 304 | "join", 305 | "merge", 306 | "pack", 307 | "path", 308 | "sprite", 309 | "svg", 310 | "svgs", 311 | "svgstore", 312 | "symbol", 313 | "symbols" 314 | ], 315 | "author": { 316 | "name": "Shannon Moeller", 317 | "email": "me@shannonmoeller.com", 318 | "url": "http://shannonmoeller.com" 319 | }, 320 | "maintainers": [ 321 | { "name": "bsipple", "email": "bsipple57@gmail.com" }, 322 | { "name": "shannonmoeller", "email": "me@shannonmoeller.com" } 323 | ], 324 | "license": "MIT", 325 | "bugs": { "url": "https://github.com/svgstore/svgstore/issues" }, 326 | "homepage": "https://github.com/svgstore/svgstore", 327 | "dependencies": { "cheerio": "^0.22.0", "object-assign": "^4.1.0" }, 328 | "devDependencies": { 329 | "ava": "0.16.0", 330 | "chokidar-cli": "^1.2.0", 331 | "coveralls": "^2.11.12", 332 | "nyc": "^8.1.0", 333 | "xo": "^0.16" 334 | }, 335 | "engines": { "node": ">= 0.12" }, 336 | "gitHead": "eb87eefe81e6fad000ac717b31e1f4fe2aaac6a3", 337 | "_id": "svgstore@2.0.2", 338 | "_shasum": "18954ed1e571c389061ecdd3738baa41e4016cac", 339 | "_from": ".", 340 | "_npmVersion": "3.10.8", 341 | "_nodeVersion": "6.9.1", 342 | "_npmUser": { 343 | "name": "shannonmoeller", 344 | "email": "me@shannonmoeller.com" 345 | }, 346 | "dist": { 347 | "shasum": "18954ed1e571c389061ecdd3738baa41e4016cac", 348 | "tarball": "https://registry.npmjs.org/svgstore/-/svgstore-2.0.2.tgz" 349 | }, 350 | "_npmOperationalInternal": { 351 | "host": "packages-12-west.internal.npmjs.com", 352 | "tmp": "tmp/svgstore-2.0.2.tgz_1481307664151_0.29293247195892036" 353 | }, 354 | "directories": {} 355 | }, 356 | "2.0.3": { 357 | "name": "svgstore", 358 | "version": "2.0.3", 359 | "description": "Combines mulitple svg files into one.", 360 | "main": "src/svgstore.js", 361 | "scripts": { 362 | "coveralls": "nyc report -r text-lcov | coveralls", 363 | "pretest": "xo src/*.js test/*.js", 364 | "test": "nyc ava -v", 365 | "posttest": "nyc report -r lcov", 366 | "watch": "chokidar '{src,test}/**/*.js' -d 1000 -c 'npm test'" 367 | }, 368 | "repository": { 369 | "type": "git", 370 | "url": "git+https://github.com/svgstore/svgstore.git" 371 | }, 372 | "keywords": [ 373 | "concat", 374 | "join", 375 | "merge", 376 | "pack", 377 | "path", 378 | "sprite", 379 | "svg", 380 | "svgs", 381 | "svgstore", 382 | "symbol", 383 | "symbols" 384 | ], 385 | "author": { 386 | "name": "Shannon Moeller", 387 | "email": "me@shannonmoeller.com", 388 | "url": "http://shannonmoeller.com" 389 | }, 390 | "maintainers": [ 391 | { "name": "bsipple", "email": "bsipple57@gmail.com" }, 392 | { "name": "shannonmoeller", "email": "me@shannonmoeller.com" } 393 | ], 394 | "license": "MIT", 395 | "bugs": { "url": "https://github.com/svgstore/svgstore/issues" }, 396 | "homepage": "https://github.com/svgstore/svgstore", 397 | "dependencies": { "cheerio": "^0.22.0", "object-assign": "^4.1.0" }, 398 | "devDependencies": { 399 | "ava": "0.16.0", 400 | "chokidar-cli": "^1.2.0", 401 | "coveralls": "^2.11.12", 402 | "nyc": "^8.1.0", 403 | "xo": "^0.16" 404 | }, 405 | "engines": { "node": ">= 0.12" }, 406 | "gitHead": "5bfed8ae5f90b51be29673a90e3a4846b39b3400", 407 | "_id": "svgstore@2.0.3", 408 | "_npmVersion": "5.6.0", 409 | "_nodeVersion": "8.9.4", 410 | "_npmUser": { 411 | "name": "shannonmoeller", 412 | "email": "me@shannonmoeller.com" 413 | }, 414 | "dist": { 415 | "integrity": "sha512-K5GcfdH/lZbLyQv2Vi9pDAKUXBLZAn7eRoPGCzV+7gk7Fv/LOB1gLsNfevNSrcapX/q45M8x0XMct9ZjWRFImQ==", 416 | "shasum": "63b3945c02062c3f7710f98ca17a3ea37a5f0e1d", 417 | "tarball": "https://registry.npmjs.org/svgstore/-/svgstore-2.0.3.tgz" 418 | }, 419 | "_npmOperationalInternal": { 420 | "host": "s3://npm-registry-packages", 421 | "tmp": "tmp/svgstore-2.0.3.tgz_1517247314326_0.7908548447303474" 422 | }, 423 | "directories": {} 424 | }, 425 | "3.0.0-0": { 426 | "name": "svgstore", 427 | "version": "3.0.0-0", 428 | "description": "Combines mulitple svg files into one.", 429 | "main": "src/svgstore.js", 430 | "scripts": { 431 | "coveralls": "nyc report -r text-lcov | coveralls", 432 | "pretest": "xo src/*.js test/*.js", 433 | "test": "nyc ava -v", 434 | "posttest": "nyc report -r lcov", 435 | "watch": "chokidar '{src,test}/**/*.js' -d 1000 -c 'npm test'" 436 | }, 437 | "repository": { 438 | "type": "git", 439 | "url": "git+https://github.com/svgstore/svgstore.git" 440 | }, 441 | "keywords": [ 442 | "concat", 443 | "join", 444 | "merge", 445 | "pack", 446 | "path", 447 | "sprite", 448 | "svg", 449 | "svgs", 450 | "svgstore", 451 | "symbol", 452 | "symbols" 453 | ], 454 | "author": { 455 | "name": "Shannon Moeller", 456 | "email": "me@shannonmoeller.com", 457 | "url": "http://shannonmoeller.com" 458 | }, 459 | "maintainers": [ 460 | { "name": "bsipple", "email": "bsipple57@gmail.com" }, 461 | { "name": "shannonmoeller", "email": "me@shannonmoeller.com" } 462 | ], 463 | "license": "MIT", 464 | "bugs": { "url": "https://github.com/svgstore/svgstore/issues" }, 465 | "homepage": "https://github.com/svgstore/svgstore", 466 | "dependencies": { "cheerio": "^0.22.0", "object-assign": "^4.1.0" }, 467 | "devDependencies": { 468 | "ava": "0.16.0", 469 | "chokidar-cli": "^1.2.0", 470 | "coveralls": "^2.11.12", 471 | "nyc": "^8.1.0", 472 | "xo": "^0.16" 473 | }, 474 | "engines": { "node": ">= 0.12" }, 475 | "readme": "# svgstore\n\n[![NPM version][npm-img]][npm-url] [![Downloads][downloads-img]][npm-url] [![Build Status][travis-img]][travis-url] [![Coverage Status][coveralls-img]][coveralls-url]\n\nCombines multiple SVG files into one using `` elements which you may [`` in your markup](https://css-tricks.com/svg-sprites-use-better-icon-fonts/). Heavily inspired by [`grunt-svgstore`](https://github.com/FWeinb/grunt-svgstore) and [`gulp-svgstore`](https://github.com/w0rm/gulp-svgstore), this is a standalone module that may be [used in any asset pipeline](#future-goals).\n\n## Install\n\n $ npm install --save svgstore\n\n## Usage\n\n```js\nvar svgstore = require('svgstore');\nvar fs = require('fs');\n\nvar sprites = svgstore()\n .add('unicorn', fs.readFileSync('./unicorn.svg', 'utf8'))\n .add('rainbow', fs.readFileSync('./rainbow.svg', 'utf8'));\n\nfs.writeFileSync('./sprites.svg', sprites);\n```\n\nThe resulting file may be consumed in markup as external content.\n\n```html\n\n \n \n\n```\n\nSee the [examples directory](https://github.com/shannonmoeller/svgstore/tree/master/docs/examples) for more detail.\n\n## API\n\n### svgstore([options]): SvgStore\n\n- `options` `{Object}`: [Options for converting SVGs to symbols](#svgstore-options)\n\nCreates a container SVG sprites document.\n\n### .element\n\nThe current [cheerio](https://github.com/cheeriojs/cheerio) instance.\n\n### .add(id, svg [, options]): SvgStore\n\n- `id` `{String}` Unique `id` for this SVG file.\n- `svg` `{String}` Raw source of the SVG file.\n- `options` `{Object}` Same as the [options of `svgstore()`](#svgstore-options), but will only apply to this SVG file's ``.\n\nAppends a file to the sprite with the given `id`.\n\n### .toString([options]): String\n\n- `options` `{Object}`\n - `inline` `{Boolean}` (default: `false`) Don't output ``, `DOCTYPE`, and the `xmlns` attribute.\n\nOutputs sprite as a string of XML.\n\n## Options\n\n- `cleanDefs` `{Boolean|Array}` (default: `false`) Remove `style` attributes from SVG definitions, or a list of attributes to remove.\n- `cleanSymbols` `{Boolean|Array}` (default: `false`) Remove `style` attributes from SVG objects, or a list of attributes to remove.\n- `svgAttrs` `{Boolean|Object}` (default: `false`) A map of attributes to set on the root `` element. If you set an attribute's value to null, you remove that attribute. Values may be functions like jQuery.\n- `symbolAttrs` `{Boolean|Object}` (default: `false`) A map of attributes to set on each `` element. If you set an attribute's value to null, you remove that attribute. Values may be functions like jQuery.\n- `copyAttrs` `{Boolean|Array}` (default: `false`) Attributes to have `svgstore` attempt to copy to the newly created `` tag from it's source `` tag. The `viewBox`, `aria-labelledby`, and `role` attributes are always copied.\n- `renameDefs` `{Boolean}` (default: `false`) Rename `defs` content ids to make them inherit files' names so that it would help to avoid defs with same ids in the output file.\n\n## Contributing\n\nStandards for this project, including tests, code coverage, and semantics are enforced with a build tool. Pull requests must include passing tests with 100% code coverage and no linting errors.\n\n### Test\n\n $ npm test\n\n## Future Goals\n\nThe svgstore organization began after it was noticed that the common [build task of converting an `` into a `` tag](https://css-tricks.com/svg-symbol-good-choice-icons/) was being implemented in a similar manner by many different projects across the JavaScript ecosystem.\n\nThe long-term goal for this project, in particular, is to provide a single standalone module that can be plugged in to any asset pipeline, thus allowing pipeline tools to focus on providing clean APIs and interfaces related to their build process integration, rather than implementing/duplicating SVG conversion logic directly.\n\n#### Current build tools using `svgstore`:\n\n* [broccoli-svgstore][broccoli-svgstore]\n* [svgstore-cli][svgstore-cli]\n\n----\n\nMIT © [Shannon Moeller](http://shannonmoeller.com)\n\n[coveralls-img]: http://img.shields.io/coveralls/svgstore/svgstore/master.svg?style=flat-square\n[coveralls-url]: https://coveralls.io/r/svgstore/svgstore\n[downloads-img]: http://img.shields.io/npm/dm/svgstore.svg?style=flat-square\n[npm-img]: http://img.shields.io/npm/v/svgstore.svg?style=flat-square\n[npm-url]: https://npmjs.org/package/svgstore\n[travis-img]: http://img.shields.io/travis/svgstore/svgstore.svg?style=flat-square\n[travis-url]: https://travis-ci.org/svgstore/svgstore\n[broccoli-svgstore]: https://github.com/svgstore/broccoli-svgstore\n[svgstore-cli]: https://github.com/svgstore/svgstore-cli\n", 476 | "readmeFilename": "readme.md", 477 | "gitHead": "2d02e7b12efd2d709d9e33451695f90444c2dddc", 478 | "_id": "svgstore@3.0.0-0", 479 | "_npmVersion": "5.6.0", 480 | "_nodeVersion": "8.11.4", 481 | "_npmUser": { 482 | "name": "shannonmoeller", 483 | "email": "me@shannonmoeller.com" 484 | }, 485 | "dist": { 486 | "integrity": "sha512-hr0V7ZdfvseD+tu66ZB6X5h+eY+5LKMP1lFDR7dVEAnQbgEYBUh/4nM/uN6mIFjzZARsjpq5YsP7bTHIc2H3+w==", 487 | "shasum": "a84965d425ebdf95daf1c52c11407b7018fc79d7", 488 | "tarball": "https://registry.npmjs.org/svgstore/-/svgstore-3.0.0-0.tgz", 489 | "fileCount": 19, 490 | "unpackedSize": 37628, 491 | "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrOQKCRA9TVsSAnZWagAAm/QP/ijk4YOr37u/faH1SqPD\nFKfHYmWSzc7bsQolAdiEp8Cvaj/IlZi9xMaFV0w1uVhQJVqUT3RRYnI8DnTu\nhiqtQWpDXI/BqLOVsLZORSfYjSLe26iXxZ2r9NbACzoiisGk5N+vpkZCmRo/\ndOf/D9mnr+RVUo8OYvF2RHdLsG7XUkIiEMZxBHzCkinD6H5b5JQi4Zy8Bp4R\nRZxIL0uLhvCXuyMfkjTpWy2sK8Wdq3zhrvRcBWxt4/x+6brpbZUrswWqH+Cw\nuuJ23VJ1tJ0/5u3I8kGDSCGJUIqZ6za0UoD7I5zfepPCVgURSehukDn6bQJ1\nZbEg4D8AEe8uFrogiQ87Bhk1GNhXkS40c7/6Ml9RB6WD8RsWAmM1EBiEB7hh\n4xZtF52WU65H0NMQ8U+jCmw4HYkKGEDJLQ01nJFDNoD/gVmUqUrhpMkrgXsM\nm70KFGOfAzCK6Tnip9HejWAcMQ7YBSNNawpnMUgKsHfVEFqKrLKT0EAer0DY\nzUyfrthg8ea4jDOHUivccMbDH1JS2OYBBCTtpl7TGHFXaUxvs8/QHnYxi64U\nS8TX7/JQQLr2xCDUanceGOG5H9gyF0XWLZW44BKqxO9Vg7g1Rhff/KUaXRBn\nJNHNFbdpR8EwMCIWS1d66gEBMLED5GbzunbBly430v8/DxNGFK6ppwDVaTaO\nOaws\r\n=JGm8\r\n-----END PGP SIGNATURE-----\r\n" 492 | }, 493 | "directories": {}, 494 | "_npmOperationalInternal": { 495 | "host": "s3://npm-registry-packages", 496 | "tmp": "tmp/svgstore_3.0.0-0_1538057225624_0.3026307519576523" 497 | }, 498 | "_hasShrinkwrap": false 499 | }, 500 | "3.0.0-1": { 501 | "name": "svgstore", 502 | "version": "3.0.0-1", 503 | "description": "Combines mulitple svg files into one.", 504 | "main": "src/svgstore.js", 505 | "scripts": { 506 | "coveralls": "nyc report -r text-lcov | coveralls", 507 | "test": "nyc ava -v", 508 | "posttest": "nyc report -r lcov", 509 | "watch": "chokidar '{src,test}/**/*.js' -d 1000 -c 'npm test'" 510 | }, 511 | "repository": { 512 | "type": "git", 513 | "url": "git+https://github.com/svgstore/svgstore.git" 514 | }, 515 | "keywords": [ 516 | "concat", 517 | "join", 518 | "merge", 519 | "pack", 520 | "path", 521 | "sprite", 522 | "svg", 523 | "svgs", 524 | "svgstore", 525 | "symbol", 526 | "symbols" 527 | ], 528 | "author": { 529 | "name": "Shannon Moeller", 530 | "email": "me@shannonmoeller.com", 531 | "url": "http://shannonmoeller.com" 532 | }, 533 | "maintainers": [ 534 | { "name": "bsipple", "email": "bsipple57@gmail.com" }, 535 | { "name": "shannonmoeller", "email": "me@shannonmoeller.com" } 536 | ], 537 | "license": "MIT", 538 | "bugs": { "url": "https://github.com/svgstore/svgstore/issues" }, 539 | "homepage": "https://github.com/svgstore/svgstore", 540 | "dependencies": { "cheerio": "^0.22.0", "object-assign": "^4.1.1" }, 541 | "devDependencies": { 542 | "ava": "0.25.0", 543 | "chokidar-cli": "^1.2.1", 544 | "coveralls": "^3.0.2", 545 | "nyc": "^13.0.1" 546 | }, 547 | "engines": { "node": ">= 0.12" }, 548 | "gitHead": "58af91df39d24ded147232684d41ec5ce7a9b7a4", 549 | "_id": "svgstore@3.0.0-1", 550 | "_npmVersion": "5.6.0", 551 | "_nodeVersion": "8.11.4", 552 | "_npmUser": { 553 | "name": "shannonmoeller", 554 | "email": "me@shannonmoeller.com" 555 | }, 556 | "dist": { 557 | "integrity": "sha512-8Xic3EybQ8GaTXu7sH4MA7t1MEYuFASwFRMuz9amYf/BoVhCV+r8eCw/+ttWemFPIYEJJC8ZuJkEP7YU4J8ZZQ==", 558 | "shasum": "9a138f8b7ae768157e5fb359da7dcdf8495b713d", 559 | "tarball": "https://registry.npmjs.org/svgstore/-/svgstore-3.0.0-1.tgz", 560 | "fileCount": 19, 561 | "unpackedSize": 37568, 562 | "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrOVVCRA9TVsSAnZWagAAl5QP/RqVImxD4JQ/V8SpsQF3\nMxZCVKK0J1DIbgDD1v152BiNbwFi9y/sfABn0S9Nf+fQpLwnZ9Jiw+88r7V1\nGtEG1+QBjOc+f+Ni4kwBNnF7udu4jZc/KzaN/u0fmlxjCtqxtw/Mh9Z7t8Ym\n4MF8LPDv79T9pB5JKNKTErGOXvje6G+8DWVxsFjP3SG4I95Be6GBBc6EUntp\nOhGyh+ahsbqS0hzGUTFdLtanv8RHFsXOIBt2O4x8NiMsYj4g51KS3T3v8kXQ\nSgBnAPUuFizT7ds2Gji2NgZrDMXHXaXE8/JeaEGRbxaOVebgTpULJYhDqniX\nqL/otFkPmpS9llPz3d06Or1r8yYf1ughs47M58pSX+5qh3vsmM0yoUPbyPGH\n9ymxYaukDlSLz8J4TOabp12N6Em5E1mrUjg2itjf7MbPTtLnGos2YHCXrSo8\nb7qv8VcyYWV3WNjb1+cMnIh2HoFFp5X4HXLLHroYYQbAWrg7qtB9B0fkXfiJ\n7JKWo/MqpVacO2RQqpwlJ+Q+f6h/SeI60Y99A8eW/e+Jp6b3rVviirXtIjWe\npusWSugYAz8oYR9eAXCeo76qEeurfjIyOUIsOrmuSfQ/2dJ2L6QaU4cm3GOK\nIz96RgFLraMCvprSU6Z8QNcEFTZ3osuB7O7dddnwMR8cdo8WXUOqCxJ8jLNA\nCx9J\r\n=LgUh\r\n-----END PGP SIGNATURE-----\r\n" 563 | }, 564 | "directories": {}, 565 | "_npmOperationalInternal": { 566 | "host": "s3://npm-registry-packages", 567 | "tmp": "tmp/svgstore_3.0.0-1_1538057557028_0.6947879244514266" 568 | }, 569 | "_hasShrinkwrap": false 570 | }, 571 | "3.0.0-2": { 572 | "name": "svgstore", 573 | "version": "3.0.0-2", 574 | "description": "Combines mulitple svg files into one.", 575 | "main": "src/svgstore.js", 576 | "scripts": { 577 | "coveralls": "nyc report -r text-lcov | coveralls", 578 | "test": "nyc ava -v", 579 | "posttest": "nyc report -r lcov", 580 | "watch": "chokidar '{src,test}/**/*.js' -d 1000 -c 'npm test'" 581 | }, 582 | "repository": { 583 | "type": "git", 584 | "url": "git+https://github.com/svgstore/svgstore.git" 585 | }, 586 | "keywords": [ 587 | "concat", 588 | "join", 589 | "merge", 590 | "pack", 591 | "path", 592 | "sprite", 593 | "svg", 594 | "svgs", 595 | "svgstore", 596 | "symbol", 597 | "symbols" 598 | ], 599 | "author": { 600 | "name": "Shannon Moeller", 601 | "email": "me@shannonmoeller.com", 602 | "url": "http://shannonmoeller.com" 603 | }, 604 | "maintainers": [ 605 | { "name": "bsipple", "email": "bsipple57@gmail.com" }, 606 | { "name": "shannonmoeller", "email": "me@shannonmoeller.com" } 607 | ], 608 | "license": "MIT", 609 | "bugs": { "url": "https://github.com/svgstore/svgstore/issues" }, 610 | "homepage": "https://github.com/svgstore/svgstore", 611 | "dependencies": { "cheerio": "^0.22.0", "object-assign": "^4.1.1" }, 612 | "devDependencies": { 613 | "ava": "0.25.0", 614 | "chokidar-cli": "^1.2.1", 615 | "coveralls": "^3.0.2", 616 | "nyc": "^13.0.1" 617 | }, 618 | "engines": { "node": ">= 0.12" }, 619 | "gitHead": "8505ce5966bc33f5de8d966b0003ad48816534e2", 620 | "_id": "svgstore@3.0.0-2", 621 | "_npmVersion": "5.6.0", 622 | "_nodeVersion": "8.11.4", 623 | "_npmUser": { 624 | "name": "shannonmoeller", 625 | "email": "me@shannonmoeller.com" 626 | }, 627 | "dist": { 628 | "integrity": "sha512-qiR9MvGgCWLuuspa9wFkafE1BrwrtsoFwhsWHt6zFK7vq3TcYKPCKFOVDBa0rAflF7/GI3SFIE+h38l8vFCFgQ==", 629 | "shasum": "0b936d60c5205d5b68efba673a4589f1384620ef", 630 | "tarball": "https://registry.npmjs.org/svgstore/-/svgstore-3.0.0-2.tgz", 631 | "fileCount": 19, 632 | "unpackedSize": 37568, 633 | "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrOXECRA9TVsSAnZWagAAobkP/jjXmWcjGP6E3nr4RA8h\nCQMW08EwphlBVo073uWi/2xTIkq7dB+Ml2ssf4a3Kd9A1EBxQhCmajMu4vhB\nfDZsw/3T5R47FFrksmJ3axKrs5RmN2ymHRGIBXJAV91GJJAeDq+02iZHisq6\nXhjeF3GHXjacWbRcx+TdKQru4ZhRjJctRGyVevAiwLF1QdDnGUOIVuSbb4/z\nnU9YjurvdPMykvtyKFZ+IRlFyTEr9rbj76rH81O0hnfAwi1+Kttvm1sfh9kO\n0AJfKx92zCHAMxZGZ+jW7JTapY+xkgTJw2nDP2O3FLQPqUBG06WDIcAakdfP\ntVCbQrrZ8TqEoS7ze6hXXiMrRxBBBgv0/0v1ctoafqc0wGvAvXHq3PXMuf6K\nx5L0D+kiv3xud//1NBB/w2DDwnyTnwCblX7A7BZ0qJDYm/YNERXoZZdIGlnp\nY8VTfCHE0ChrOEli0ZeduMYun7/fDkdIj2iBSVDJ01qs6mY04+WmpJvRt4Ih\n3DL3u1nTIaYjkq4PBa3TOh8htxNb4vZJVLEXQmDkJQI1RJ+tE4BLzgq4b3NZ\n7E/4fiucZZfWWXmYrxE5DrWKeqeXX6yfBdn6dBWvtlTU8M3Xd9FNcxNPq1ep\nRE4mK5SIZ9sWYDaX6D2yns1c276TAcxj2sRHsGe5cV70z5At1AF67zyoJvGs\naf87\r\n=1Wn5\r\n-----END PGP SIGNATURE-----\r\n" 634 | }, 635 | "directories": {}, 636 | "_npmOperationalInternal": { 637 | "host": "s3://npm-registry-packages", 638 | "tmp": "tmp/svgstore_3.0.0-2_1538057667386_0.4167043390452414" 639 | }, 640 | "_hasShrinkwrap": false 641 | } 642 | }, 643 | "readme": "# svgstore\n\n[![NPM version][npm-img]][npm-url] [![Downloads][downloads-img]][npm-url] [![Build Status][travis-img]][travis-url] [![Coverage Status][coveralls-img]][coveralls-url]\n\nCombines multiple SVG files into one using `` elements which you may [`` in your markup](https://css-tricks.com/svg-sprites-use-better-icon-fonts/). Heavily inspired by [`grunt-svgstore`](https://github.com/FWeinb/grunt-svgstore) and [`gulp-svgstore`](https://github.com/w0rm/gulp-svgstore), this is a standalone module that may be [used in any asset pipeline](#future-goals).\n\n## Install\n\n $ npm install --save svgstore\n\n## Usage\n\n```js\nvar svgstore = require('svgstore');\nvar fs = require('fs');\n\nvar sprites = svgstore()\n .add('unicorn', fs.readFileSync('./unicorn.svg', 'utf8'))\n .add('rainbow', fs.readFileSync('./rainbow.svg', 'utf8'));\n\nfs.writeFileSync('./sprites.svg', sprites);\n```\n\nThe resulting file may be consumed in markup as external content.\n\n```html\n\n \n \n\n```\n\nSee the [examples directory](https://github.com/shannonmoeller/svgstore/tree/master/docs/examples) for more detail.\n\n## API\n\n### svgstore([options]): SvgStore\n\n- `options` `{Object}`: [Options for converting SVGs to symbols](#svgstore-options)\n\nCreates a container SVG sprites document.\n\n### .element\n\nThe current [cheerio](https://github.com/cheeriojs/cheerio) instance.\n\n### .add(id, svg [, options]): SvgStore\n\n- `id` `{String}` Unique `id` for this SVG file.\n- `svg` `{String}` Raw source of the SVG file.\n- `options` `{Object}` Same as the [options of `svgstore()`](#svgstore-options), but will only apply to this SVG file's ``.\n\nAppends a file to the sprite with the given `id`.\n\n### .toString([options]): String\n\n- `options` `{Object}`\n - `inline` `{Boolean}` (default: `false`) Don't output ``, `DOCTYPE`, and the `xmlns` attribute.\n\nOutputs sprite as a string of XML.\n\n## Options\n\n- `cleanDefs` `{Boolean|Array}` (default: `false`) Remove `style` attributes from SVG definitions, or a list of attributes to remove.\n- `cleanSymbols` `{Boolean|Array}` (default: `false`) Remove `style` attributes from SVG objects, or a list of attributes to remove.\n- `svgAttrs` `{Boolean|Object}` (default: `false`) A map of attributes to set on the root `` element. If you set an attribute's value to null, you remove that attribute. Values may be functions like jQuery.\n- `symbolAttrs` `{Boolean|Object}` (default: `false`) A map of attributes to set on each `` element. If you set an attribute's value to null, you remove that attribute. Values may be functions like jQuery.\n- `copyAttrs` `{Boolean|Array}` (default: `false`) Attributes to have `svgstore` attempt to copy to the newly created `` tag from it's source `` tag. The `viewBox`, `aria-labelledby`, and `role` attributes are always copied.\n- `renameDefs` `{Boolean}` (default: `false`) Rename `defs` content ids to make them inherit files' names so that it would help to avoid defs with same ids in the output file.\n\n## Contributing\n\nStandards for this project, including tests, code coverage, and semantics are enforced with a build tool. Pull requests must include passing tests with 100% code coverage and no linting errors.\n\n### Test\n\n $ npm test\n\n## Future Goals\n\nThe svgstore organization began after it was noticed that the common [build task of converting an `` into a `` tag](https://css-tricks.com/svg-symbol-good-choice-icons/) was being implemented in a similar manner by many different projects across the JavaScript ecosystem.\n\nThe long-term goal for this project, in particular, is to provide a single standalone module that can be plugged in to any asset pipeline, thus allowing pipeline tools to focus on providing clean APIs and interfaces related to their build process integration, rather than implementing/duplicating SVG conversion logic directly.\n\n#### Current build tools using `svgstore`:\n\n* [broccoli-svgstore][broccoli-svgstore]\n* [svgstore-cli][svgstore-cli]\n\n----\n\nMIT © [Shannon Moeller](http://shannonmoeller.com)\n\n[coveralls-img]: http://img.shields.io/coveralls/svgstore/svgstore/master.svg?style=flat-square\n[coveralls-url]: https://coveralls.io/r/svgstore/svgstore\n[downloads-img]: http://img.shields.io/npm/dm/svgstore.svg?style=flat-square\n[npm-img]: http://img.shields.io/npm/v/svgstore.svg?style=flat-square\n[npm-url]: https://npmjs.org/package/svgstore\n[travis-img]: http://img.shields.io/travis/svgstore/svgstore.svg?style=flat-square\n[travis-url]: https://travis-ci.org/svgstore/svgstore\n[broccoli-svgstore]: https://github.com/svgstore/broccoli-svgstore\n[svgstore-cli]: https://github.com/svgstore/svgstore-cli\n", 644 | "maintainers": [ 645 | { "name": "bsipple", "email": "bsipple57@gmail.com" }, 646 | { "name": "shannonmoeller", "email": "me@shannonmoeller.com" } 647 | ], 648 | "time": { 649 | "modified": "2019-01-05T14:14:17.113Z", 650 | "created": "2016-03-09T21:15:01.151Z", 651 | "1.0.0": "2016-03-09T21:15:01.151Z", 652 | "1.1.0": "2016-08-08T12:51:33.960Z", 653 | "2.0.0": "2016-12-09T13:51:48.339Z", 654 | "2.0.1": "2016-12-09T14:03:27.815Z", 655 | "2.0.2": "2016-12-09T18:21:06.150Z", 656 | "2.0.3": "2018-01-29T17:35:15.538Z", 657 | "3.0.0-0": "2018-09-27T14:07:05.725Z", 658 | "3.0.0-1": "2018-09-27T14:12:37.242Z", 659 | "3.0.0-2": "2018-09-27T14:14:27.548Z" 660 | }, 661 | "homepage": "https://github.com/svgstore/svgstore", 662 | "keywords": [ 663 | "concat", 664 | "join", 665 | "merge", 666 | "pack", 667 | "path", 668 | "sprite", 669 | "svg", 670 | "svgs", 671 | "svgstore", 672 | "symbol", 673 | "symbols" 674 | ], 675 | "repository": { 676 | "type": "git", 677 | "url": "git+https://github.com/svgstore/svgstore.git" 678 | }, 679 | "author": { 680 | "name": "Shannon Moeller", 681 | "email": "me@shannonmoeller.com", 682 | "url": "http://shannonmoeller.com" 683 | }, 684 | "bugs": { "url": "https://github.com/svgstore/svgstore/issues" }, 685 | "license": "MIT", 686 | "readmeFilename": "readme.md", 687 | "users": { "revlis": true, "shanewholloway": true } 688 | } 689 | -------------------------------------------------------------------------------- /fixtures/poetry/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "" 3 | version = "0.0.0" 4 | description = "" 5 | authors = [] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.8" 9 | 10 | [tool.poetry.group.dev.dependencies] 11 | djlint = "1.30.0" 12 | PyYAML = "6.0" 13 | -------------------------------------------------------------------------------- /index.test.ts: -------------------------------------------------------------------------------- 1 | import spawn from "nano-spawn"; 2 | import restana from "restana"; 3 | import {join, dirname} from "node:path"; 4 | import {readFileSync, mkdtempSync} from "node:fs"; 5 | import {writeFile, readFile, rm} from "node:fs/promises"; 6 | import {fileURLToPath} from "node:url"; 7 | import {tmpdir} from "node:os"; 8 | import {env} from "node:process"; 9 | import type {Server} from "node:http"; 10 | import type {Service, Protocol} from "restana"; 11 | 12 | const testFile = fileURLToPath(new URL("fixtures/npm-test/package.json", import.meta.url)); 13 | const emptyFile = fileURLToPath(new URL("fixtures/npm-empty/package.json", import.meta.url)); 14 | const poetryFile = fileURLToPath(new URL("fixtures/poetry/pyproject.toml", import.meta.url)); 15 | const dualFile = fileURLToPath(new URL("fixtures/dual", import.meta.url)); 16 | 17 | const testPkg = JSON.parse(readFileSync(testFile, "utf8")); 18 | const testDir = mkdtempSync(join(tmpdir(), "updates-")); 19 | const script = fileURLToPath(new URL("dist/index.js", import.meta.url)); 20 | 21 | const dependencyTypes = [ 22 | "dependencies", 23 | "devDependencies", 24 | "peerDependencies", 25 | "optionalDependencies", 26 | "resolutions", 27 | ]; 28 | 29 | const testPackages: Set = new Set(); 30 | for (const dependencyType of dependencyTypes) { 31 | for (const name of Object.keys(testPkg[dependencyType] || [])) { 32 | testPackages.add(name); 33 | } 34 | } 35 | 36 | const pyTestPackages = new Set(["djlint", "PyYAML"]); 37 | 38 | function makeUrl(server: Server) { 39 | const {port}: any = server.address(); 40 | return Object.assign(new URL("http://localhost"), {port}).toString(); 41 | } 42 | 43 | function defaultRoute(req: any, res: any) { 44 | console.error(`default handler hit for ${req.url}`); 45 | res.send(404); 46 | } 47 | 48 | function resolutionsBasePackage(name: string) { 49 | const packages = name.match(/(@[^/]+\/)?([^/]+)/g) || []; 50 | return packages[packages.length - 1]; 51 | } 52 | 53 | let npmServer: Service | Server; 54 | let githubServer: Service | Server; 55 | let pypiServer: Service | Server; 56 | 57 | let githubUrl: string; 58 | let pypiUrl: string; 59 | let npmUrl: string; 60 | 61 | beforeAll(async () => { 62 | let commits, tags; 63 | 64 | [npmServer, githubServer, pypiServer, commits, tags] = await Promise.all([ 65 | restana({defaultRoute}), 66 | restana({defaultRoute}), 67 | restana({defaultRoute}), 68 | readFile(fileURLToPath(new URL("fixtures/github/updates-commits.json", import.meta.url))), 69 | readFile(fileURLToPath(new URL("fixtures/github/updates-tags.json", import.meta.url))), 70 | ]); 71 | 72 | for (const pkgName of testPackages) { 73 | const name = testPkg.resolutions[pkgName] ? resolutionsBasePackage(pkgName) : pkgName; 74 | const urlName = name.replace(/\//g, "%2f"); 75 | // can not use file URLs because node stupidely throws on "%2f" in paths. 76 | const path = join(dirname(fileURLToPath(import.meta.url)), `fixtures/npm/${urlName}.json`); 77 | npmServer.get(`/${urlName}`, async (_, res) => res.send(await readFile(path))); 78 | } 79 | 80 | for (const pkgName of pyTestPackages) { 81 | const path = join(dirname(fileURLToPath(import.meta.url)), `fixtures/pypi/${pkgName}.json`); 82 | pypiServer.get(`/pypi/${pkgName}/json`, async (_, res) => res.send(await readFile(path))); 83 | } 84 | 85 | githubServer.get("/repos/silverwind/updates/commits", (_, res) => res.send(commits)); 86 | githubServer.get("/repos/silverwind/updates/git/refs/tags", (_, res) => res.send(tags)); 87 | 88 | [githubServer, pypiServer, npmServer] = await Promise.all([ 89 | githubServer.start(0), 90 | pypiServer.start(0), 91 | npmServer.start(0), 92 | ]); 93 | 94 | githubUrl = makeUrl(githubServer); 95 | npmUrl = makeUrl(npmServer); 96 | pypiUrl = makeUrl(pypiServer); 97 | 98 | await writeFile(join(testDir, ".npmrc"), `registry=${npmUrl}`); // Fake registry 99 | await writeFile(join(testDir, "package.json"), JSON.stringify(testPkg, null, 2)); // Copy fixture 100 | }); 101 | 102 | afterAll(async () => { 103 | await Promise.all([ 104 | rm(testDir, {recursive: true}), 105 | npmServer?.close(), 106 | githubServer?.close(), 107 | ]); 108 | }); 109 | 110 | function makeTest(args: string) { 111 | return async () => { 112 | const argsArr = [ 113 | ...args.split(/\s+/), "-c", 114 | "--githubapi", githubUrl, 115 | "--pypiapi", pypiUrl, 116 | ]; 117 | const {stdout} = await spawn(process.execPath, [script, ...argsArr], {cwd: testDir}); 118 | const {results} = JSON.parse(stdout); 119 | 120 | // Parse results, with custom validation for the dynamic "age" property 121 | for (const mode of Object.keys(results || {})) { 122 | for (const dependencyType of [ 123 | ...dependencyTypes, 124 | "tool.poetry.dependencies", 125 | "tool.poetry.dev-dependencies", 126 | "tool.poetry.test-dependencies", 127 | "tool.poetry.group.dev.dependencies", 128 | "tool.poetry.group.test.dependencies", 129 | ]) { 130 | for (const name of Object.keys(results?.[mode]?.[dependencyType] || {})) { 131 | delete results[mode][dependencyType][name].age; 132 | } 133 | } 134 | } 135 | 136 | expect(results).toMatchSnapshot(); 137 | }; 138 | } 139 | 140 | test("simple", async () => { 141 | const {stdout, stderr} = await spawn(process.execPath, [ 142 | script, 143 | "-C", 144 | "--githubapi", githubUrl, 145 | "--pypiapi", pypiUrl, 146 | "--registry", npmUrl, 147 | "-f", testFile, 148 | ]); 149 | expect(stderr).toEqual(""); 150 | expect(stdout).toContain("prismjs"); 151 | expect(stdout).toContain("https://github.com/silverwind/updates"); 152 | }); 153 | 154 | test("empty", async () => { 155 | const {stdout, stderr} = await spawn(process.execPath, [ 156 | script, 157 | "-C", 158 | "--githubapi", githubUrl, 159 | "--pypiapi", pypiUrl, 160 | "-f", emptyFile, 161 | ]); 162 | expect(stderr).toEqual(""); 163 | expect(stdout).toContain("No dependencies"); 164 | }); 165 | 166 | if (env.CI && !env.BUN) { 167 | test("global", async () => { 168 | await spawn("npm", ["i", "-g", "."]); 169 | const {stdout, stderr} = await spawn("updates", [ 170 | "-C", 171 | "--githubapi", githubUrl, 172 | "--pypiapi", pypiUrl, 173 | "-f", testFile, 174 | ]); 175 | expect(stderr).toEqual(""); 176 | expect(stdout).toContain("prismjs"); 177 | expect(stdout).toContain("https://github.com/silverwind/updates"); 178 | }); 179 | } 180 | 181 | test("latest", makeTest("-j")); 182 | test("greatest", makeTest("-j -g")); 183 | test("prerelease", makeTest("-j -g -p")); 184 | test("release", makeTest("-j -R")); 185 | test("patch", makeTest("-j -P")); 186 | test("include", makeTest("-j -i noty")); 187 | test("include 2", makeTest("-j -i noty -i noty,noty")); 188 | test("include 3", makeTest("-j -i /^noty/")); 189 | test("exclude", makeTest("-j -e gulp-sourcemaps,prismjs,svgstore,html-webpack-plugin,noty,jpeg-buffer-orientation,styled-components,@babel/preset-env,versions/updates,react")); 190 | test("exclude 2", makeTest("-j -e gulp-sourcemaps -i /react/")); 191 | test("exclude 3", makeTest("-j -i gulp*")); 192 | test("exclude 4", makeTest("-j -i /^gulp/ -P gulp*")); 193 | test("pypi", makeTest(`-j -f ${poetryFile}`)); 194 | test("dual", makeTest(`-j -f ${dualFile}`)); 195 | test("dual 2", makeTest(`-j -f ${dualFile} -i noty`)); 196 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S node --experimental-strip-types --no-warnings 2 | import minimist from "minimist"; 3 | import registryAuthToken from "registry-auth-token"; 4 | import rc from "rc"; 5 | import {parse, coerce, diff, gt, gte, lt, neq, valid, validRange} from "semver"; 6 | import {cwd, stdout, argv, env, exit} from "node:process"; 7 | import {join, dirname, basename, resolve} from "node:path"; 8 | import {lstatSync, readFileSync, truncateSync, writeFileSync, accessSync} from "node:fs"; 9 | import {stripVTControlCharacters} from "node:util"; 10 | import {timerel} from "timerel"; 11 | import supportsColor from "supports-color"; 12 | import {magenta, red, green, disableColor} from "glowie"; 13 | import pAll from "p-all"; 14 | import picomatch from "picomatch"; 15 | import pkg from "./package.json" with {type: "json"}; 16 | import {execFileSync} from "node:child_process"; 17 | import type {AuthOptions} from "registry-auth-token"; 18 | import type {AgentOptions} from "node:https"; 19 | import type {TimerelAnyDate} from "timerel"; 20 | 21 | export type Config = { 22 | include?: Array; 23 | exclude?: Array; 24 | types?: Array; 25 | registry?: string; 26 | } 27 | 28 | type Npmrc = { 29 | registry?: string, 30 | ca?: string, 31 | cafile?: string, 32 | cert?: string, 33 | certfile?: string, 34 | key?: string, 35 | keyfile?: string, 36 | [other: string]: any, 37 | } 38 | 39 | type Dep = { 40 | "old": string, 41 | "new": string, 42 | "oldPrint"?: string, 43 | "newPrint"?: string, 44 | "oldOriginal"?: string, 45 | "info"?: string, 46 | "age"?: string, 47 | } 48 | 49 | type Deps = { 50 | [name: string]: Dep, 51 | } 52 | 53 | type DepsByMode = { 54 | [mode: string]: Deps, 55 | } 56 | 57 | type Output = { 58 | results: { 59 | [mode: string]: { 60 | [type: string]: Deps, 61 | } 62 | } 63 | } 64 | 65 | type FindVersionOpts = { 66 | range: string, 67 | semvers: Set, 68 | usePre: boolean, 69 | useRel: boolean, 70 | useGreatest: boolean, 71 | } 72 | 73 | type FindNewVersionOpts = { 74 | mode: string, 75 | range: string, 76 | usePre: boolean, 77 | useRel: boolean, 78 | useGreatest: boolean, 79 | semvers: Set, 80 | } 81 | 82 | // regexes for url dependencies. does only github and only hash or exact semver 83 | // https://regex101.com/r/gCZzfK/2 84 | const stripRe = /^.*?:\/\/(.*?@)?(github\.com[:/])/i; 85 | const partsRe = /^([^/]+)\/([^/#]+)?.*?\/([0-9a-f]+|v?[0-9]+\.[0-9]+\.[0-9]+)$/i; 86 | const hashRe = /^[0-9a-f]{7,}$/i; 87 | const versionRe = /[0-9]+(\.[0-9]+)?(\.[0-9]+)?/g; 88 | const esc = (str: string) => str.replace(/[|\\{}()[\]^$+*?.-]/g, "\\$&"); 89 | const normalizeUrl = (url: string) => url.endsWith("/") ? url.substring(0, url.length - 1) : url; 90 | const packageVersion = pkg.version || "0.0.0"; 91 | const sep = "\0"; 92 | 93 | const modeByFileName = { 94 | "package.json": "npm", 95 | "pyproject.toml": "pypi", 96 | "go.mod": "go", 97 | }; 98 | 99 | const args = minimist(argv.slice(2), { 100 | boolean: [ 101 | "E", "error-on-outdated", 102 | "U", "error-on-unchanged", 103 | "h", "help", 104 | "j", "json", 105 | "n", "no-color", 106 | "u", "update", 107 | "v", "version", 108 | "V", "verbose", 109 | ], 110 | string: [ 111 | "d", "allow-downgrade", 112 | "f", "file", 113 | "g", "greatest", 114 | "m", "minor", 115 | "M", "modes", 116 | "P", "patch", 117 | "p", "prerelease", 118 | "R", "release", 119 | "r", "registry", 120 | "t", "types", 121 | "githubapi", // undocumented, only for tests 122 | "pypiapi", // undocumented, only for tests 123 | "goproxy", // undocumented, only for tests 124 | ], 125 | alias: { 126 | d: "allow-downgrade", 127 | E: "error-on-outdated", 128 | U: "error-on-unchanged", 129 | e: "exclude", 130 | f: "file", 131 | g: "greatest", 132 | h: "help", 133 | i: "include", 134 | j: "json", 135 | m: "minor", 136 | M: "modes", 137 | n: "no-color", 138 | P: "patch", 139 | p: "prerelease", 140 | r: "registry", 141 | R: "release", 142 | s: "semver", 143 | S: "sockets", 144 | t: "types", 145 | u: "update", 146 | v: "version", 147 | V: "verbose", 148 | }, 149 | }); 150 | 151 | if (args["no-color"] || !supportsColor.stdout) disableColor(); 152 | 153 | type PackageArg = Set | boolean; 154 | 155 | const greatest = argSetToRegexes(parseMixedArg(args.greatest)) as PackageArg; 156 | const prerelease = argSetToRegexes(parseMixedArg(args.prerelease)) as PackageArg; 157 | const release = argSetToRegexes(parseMixedArg(args.release)) as PackageArg; 158 | const patch = argSetToRegexes(parseMixedArg(args.patch)) as PackageArg; 159 | const minor = argSetToRegexes(parseMixedArg(args.minor)) as PackageArg; 160 | const allowDowngrade = parseMixedArg(args["allow-downgrade"]) as PackageArg; 161 | const enabledModes = parseMixedArg(args.modes) as Set || new Set(["npm", "pypi"]); 162 | const githubApiUrl = args.githubapi ? normalizeUrl(args.githubapi) : "https://api.github.com"; 163 | const pypiApiUrl = args.pypiapi ? normalizeUrl(args.pypiapi) : "https://pypi.org"; 164 | const defaultGoProxy = "https://proxy.golang.org"; 165 | const goProxies = args.goproxy ? normalizeUrl(args.goproxy) : makeGoProxies(); 166 | const stripV = (str: string) => str.replace(/^v/, ""); 167 | 168 | function matchesAny(str: string, set: PackageArg) { 169 | for (const re of (set instanceof Set ? set : [])) { 170 | if (re.test(str)) return true; 171 | } 172 | return false; 173 | } 174 | 175 | function registryUrl(scope: string, npmrc: Npmrc) { 176 | const url = npmrc[`${scope}:registry`] || npmrc.registry; 177 | return url.endsWith("/") ? url : `${url}/`; 178 | } 179 | 180 | function makeGoProxies(): string[] { 181 | if (env.GOPROXY) { 182 | return env.GOPROXY.split(/[,|]/).map(s => s.trim()).filter(s => (Boolean(s) && s !== "direct")); 183 | } else { 184 | return [defaultGoProxy]; 185 | } 186 | } 187 | 188 | function getProperty(obj: Record, path: string) { 189 | return path.split(".").reduce((obj: Record, prop: string) => obj?.[prop] ?? null, obj); 190 | } 191 | 192 | function commaSeparatedToArray(str: string) { 193 | return str.split(",").filter(Boolean); 194 | } 195 | 196 | function findUpSync(filename: string, dir: string): string | null { 197 | const path = join(dir, filename); 198 | try { accessSync(path); return path; } catch {} 199 | const parent = dirname(dir); 200 | return parent === dir ? null : findUpSync(filename, parent); 201 | } 202 | 203 | function getAuthAndRegistry(name: string, registry: string, authTokenOpts: AuthOptions, npmrc: Npmrc) { 204 | if (!name.startsWith("@")) { 205 | return {auth: registryAuthToken(registry, authTokenOpts), registry}; 206 | } else { 207 | const scope = (/@[a-z0-9][\w-.]+/.exec(name) || [""])[0]; 208 | const url = normalizeUrl(registryUrl(scope, npmrc)); 209 | if (url !== registry) { 210 | try { 211 | const newAuth = registryAuthToken(url, authTokenOpts); 212 | if (newAuth?.token) return {auth: newAuth, registry: url}; 213 | } catch {} 214 | } 215 | return {auth: registryAuthToken(registry, authTokenOpts), registry}; 216 | } 217 | } 218 | 219 | function getFetchOpts(agentOpts: AgentOptions, authType?: string, authToken?: string) { 220 | return { 221 | ...(Object.keys(agentOpts).length && {agentOpts}), 222 | headers: { 223 | "user-agent": `updates/${packageVersion}`, 224 | ...(authToken && {Authorization: `${authType} ${authToken}`}), 225 | } 226 | }; 227 | } 228 | 229 | async function doFetch(url: string, opts: RequestInit) { 230 | if (args.verbose) console.error(`${magenta("fetch")} ${url}`); 231 | const res = await fetch(url, opts); 232 | if (args.verbose) console.error(`${res.ok ? green(res.status) : red(res.status)} ${url}`); 233 | return res; 234 | } 235 | 236 | async function fetchNpmInfo(name: string, type: string, originalRegistry: string, agentOpts: AgentOptions, authTokenOpts: AuthOptions, npmrc: Npmrc) { 237 | const {auth, registry} = getAuthAndRegistry(name, originalRegistry, authTokenOpts, npmrc); 238 | const packageName = type === "resolutions" ? basename(name) : name; 239 | const url = `${registry}/${packageName.replace(/\//g, "%2f")}`; 240 | 241 | const res = await doFetch(url, getFetchOpts(agentOpts, auth?.type, auth?.token)); 242 | if (res?.ok) { 243 | return [await res.json(), type, registry, name]; 244 | } else { 245 | if (res?.status && res?.statusText) { 246 | throw new Error(`Received ${res.status} ${res.statusText} from ${url}`); 247 | } else { 248 | throw new Error(`Unable to fetch ${name} from ${registry}`); 249 | } 250 | } 251 | } 252 | 253 | async function fetchPypiInfo(name: string, type: string, agentOpts: AgentOptions) { 254 | const url = `${pypiApiUrl}/pypi/${name}/json`; 255 | 256 | const res = await doFetch(url, getFetchOpts(agentOpts)); 257 | if (res?.ok) { 258 | return [await res.json(), type, null, name]; 259 | } else { 260 | if (res?.status && res?.statusText) { 261 | throw new Error(`Received ${res.status} ${res.statusText} from ${url}`); 262 | } else { 263 | throw new Error(`Unable to fetch ${name} from ${pypiApiUrl}`); 264 | } 265 | } 266 | } 267 | 268 | function splitPlainText(str: string): string[] { 269 | return str.split(/\r?\n/).map(s => s.trim()).filter(Boolean); 270 | } 271 | 272 | async function fetchGoVersionInfo(modulePath: string, version: string, agentOpts: AgentOptions, proxies: string[]) { 273 | const proxyUrl = proxies.shift(); 274 | if (!proxyUrl) { 275 | throw new Error("No more go proxies available"); 276 | } 277 | 278 | const url = `${proxyUrl}/${modulePath.toLowerCase()}/${version === "latest" ? "@latest" : `@v/${version}.info`}`; 279 | const res = await doFetch(url, getFetchOpts(agentOpts)); 280 | 281 | if ([404, 410].includes(res.status) && proxies.length) { 282 | return fetchGoVersionInfo(modulePath, version, agentOpts, proxies); 283 | } 284 | 285 | if (res?.ok) { 286 | return res.json(); 287 | } else { 288 | if (res?.status && res?.statusText) { 289 | throw new Error(`Received ${res.status} ${res.statusText} from ${url}`); 290 | } else { 291 | throw new Error(`Unable to fetch ${modulePath} from ${proxyUrl}`); 292 | } 293 | } 294 | } 295 | 296 | type PackageRepository = string | { 297 | type: string, 298 | url: string, 299 | directory: string, 300 | } 301 | 302 | function resolvePackageJsonUrl(url: string) { 303 | url = url.replace("git@", "").replace(/.+?\/\//, "https://").replace(/\.git$/, ""); 304 | if (/^[a-z]+:[a-z0-9-]\/[a-z0-9-]$/.test(url)) { // foo:user/repo 305 | return url.replace(/^(.+?):/, (_, p1) => `https://${p1}.com/`); 306 | } else if (/^[a-z0-9-]\/[a-z0-9-]$/.test(url)) { // user/repo 307 | return `https://github.com/${url}`; 308 | } else { 309 | return url; 310 | } 311 | } 312 | 313 | function getSubDir(url: string) { 314 | if (url.startsWith("https://bitbucket.org")) { 315 | return "src/HEAD"; 316 | } else { 317 | return "tree/HEAD"; 318 | } 319 | } 320 | 321 | function getInfoUrl({repository, homepage, info}: {repository: PackageRepository, homepage: string, info: Record}, registry: string, name: string): string { 322 | if (info) { // pypi 323 | repository = 324 | info.project_urls.repository || 325 | info.project_urls.Repository || 326 | info.project_urls.repo || 327 | info.project_urls.Repo || 328 | info.project_urls.source || 329 | info.project_urls.Source || 330 | info.project_urls["source code"] || 331 | info.project_urls["Source code"] || 332 | info.project_urls["Source Code"] || 333 | info.project_urls.homepage || 334 | info.project_urls.Homepage || 335 | `https://pypi.org/project/${name}/`; 336 | } 337 | 338 | let infoUrl = ""; 339 | if (registry === "https://npm.pkg.github.com") { 340 | return `https://github.com/${name.replace(/^@/, "")}`; 341 | } else if (repository) { 342 | const url = typeof repository === "string" ? repository : repository.url; 343 | infoUrl = resolvePackageJsonUrl(url); 344 | if (infoUrl && typeof repository !== "string" && repository.directory) { 345 | infoUrl = `${infoUrl}/${getSubDir(infoUrl)}/${repository.directory}`; 346 | } 347 | } 348 | 349 | return infoUrl || homepage || ""; 350 | } 351 | 352 | function finishWithMessage(message: string) { 353 | console.info(args.json ? JSON.stringify({message}) : message); 354 | doExit(); 355 | } 356 | 357 | function doExit(err?: Error | void) { 358 | if (err) { 359 | const error = err.stack ?? err.message; 360 | console.info(args.json ? JSON.stringify({error}) : red(error)); 361 | } 362 | process.exit(err ? 1 : 0); 363 | } 364 | 365 | function outputDeps(deps: DepsByMode = {}) { 366 | for (const mode of Object.keys(deps)) { 367 | for (const value of Object.values(deps[mode])) { 368 | if (typeof value.oldPrint === "string") { 369 | value.old = value.oldPrint; 370 | delete value.oldPrint; 371 | } 372 | if (typeof value.newPrint === "string") { 373 | value.new = value.newPrint; 374 | delete value.newPrint; 375 | } 376 | if (typeof value.oldOriginal === "string") { 377 | value.old = value.oldOriginal; 378 | delete value.oldOriginal; 379 | } 380 | } 381 | } 382 | 383 | let num = 0; 384 | for (const mode of Object.keys(deps)) { 385 | num += Object.keys(deps[mode]).length; 386 | } 387 | 388 | if (args.json) { 389 | const output: Output = {results: {}}; 390 | for (const mode of Object.keys(deps)) { 391 | for (const [key, value] of Object.entries(deps[mode])) { 392 | const [type, name] = key.split(sep); 393 | if (!output.results[mode]) output.results[mode] = {}; 394 | if (!output.results[mode][type]) output.results[mode][type] = {}; 395 | output.results[mode][type][name] = value; 396 | } 397 | } 398 | console.info(JSON.stringify(output)); 399 | } else if (num) { 400 | console.info(formatDeps(deps)); 401 | } 402 | 403 | if (args["error-on-outdated"]) { 404 | return num ? 2 : 0; 405 | } else if (args["error-on-unchanged"]) { 406 | return num ? 0 : 2; 407 | } else { 408 | return 0; 409 | } 410 | } 411 | 412 | // preserve file metadata on windows 413 | async function write(file: string, content: string) { 414 | const {platform} = await import("node:os"); 415 | const isWindows = platform() === "win32"; 416 | if (isWindows) truncateSync(file, 0); 417 | writeFileSync(file, content, isWindows ? {flag: "r+"} : undefined); 418 | } 419 | 420 | function highlightDiff(a: string, b: string, colorFn: (str: string) => string) { 421 | if (a === b) return a; 422 | const aParts = a.split(/\./); 423 | const bParts = b.split(/\./); 424 | const versionPartRe = /^[0-9a-zA-Z-.]+$/; 425 | 426 | let res = ""; 427 | for (let i = 0; i < aParts.length; i++) { 428 | if (aParts[i] !== bParts[i]) { 429 | if (versionPartRe.test(aParts[i])) { 430 | res += colorFn(aParts.slice(i).join(".")); 431 | } else { 432 | res += aParts[i].split("").map(char => { 433 | return versionPartRe.test(char) ? colorFn(char) : char; 434 | }).join("") + colorFn(`.${aParts.slice(i + 1).join(".")}`.replace(/\.$/, "")); 435 | } 436 | break; 437 | } else { 438 | res += `${aParts[i]}.`; 439 | } 440 | } 441 | return res.replace(/\.$/, ""); 442 | } 443 | 444 | const ansiLen = (str: string): number => stripVTControlCharacters(str).length; 445 | 446 | function textTable(rows: string[][], hsep = " "): string { 447 | let ret = ""; 448 | const colSizes = new Array(rows[0].length).fill(0); 449 | for (const row of rows) { 450 | for (const [colIndex, col] of row.entries()) { 451 | const len = ansiLen(col); 452 | if (len > colSizes[colIndex]) { 453 | colSizes[colIndex] = len; 454 | } 455 | } 456 | } 457 | for (const [rowIndex, row] of rows.entries()) { 458 | for (const [colIndex, col] of row.entries()) { 459 | if (colIndex > 0) ret += hsep; 460 | const space = " ".repeat(colSizes[colIndex] - ansiLen(col)); 461 | ret += col + (colIndex === row.length - 1 ? "" : space); 462 | } 463 | if (rowIndex < rows.length - 1) ret += "\n"; 464 | } 465 | return ret; 466 | } 467 | 468 | function shortenGoName(moduleName: string) { 469 | if (/\/v[0-9]$/.test(moduleName)) { 470 | moduleName = dirname(moduleName); 471 | } 472 | return moduleName; 473 | } 474 | 475 | function formatDeps(deps: DepsByMode) { 476 | const arr = [["NAME", "OLD", "NEW", "AGE", "INFO"]]; 477 | const seen = new Set(); 478 | 479 | for (const mode of Object.keys(deps)) { 480 | for (const [key, data] of Object.entries(deps[mode])) { 481 | const name = key.split(sep)[1]; 482 | const id = `${mode}|${name}`; 483 | if (seen.has(id)) continue; 484 | seen.add(id); 485 | arr.push([ 486 | mode === "go" ? shortenGoName(name) : name, 487 | highlightDiff(data.old, data.new, red), 488 | highlightDiff(data.new, data.old, green), 489 | data.age || "", 490 | data.info || "", 491 | ]); 492 | } 493 | } 494 | 495 | return textTable(arr); 496 | } 497 | 498 | function updatePackageJson(pkgStr: string, deps: Deps) { 499 | let newPkgStr = pkgStr; 500 | for (const key of Object.keys(deps)) { 501 | const name = key.split(sep)[1]; 502 | const old = deps[key].oldOriginal || deps[key].old; 503 | const re = new RegExp(`"${esc(name)}": *"${esc(old)}"`, "g"); 504 | newPkgStr = newPkgStr.replace(re, `"${name}": "${deps[key].new}"`); 505 | } 506 | return newPkgStr; 507 | } 508 | 509 | function updateProjectToml(pkgStr: string, deps: Deps) { 510 | let newPkgStr = pkgStr; 511 | for (const key of Object.keys(deps)) { 512 | const name = key.split(sep)[1]; 513 | const old = deps[key].oldOriginal || deps[key].old; 514 | const re = new RegExp(`${esc(name)} *= *"${esc(old)}"`, "g"); 515 | newPkgStr = newPkgStr.replace(re, `${name} = "${deps[key].new}"`); 516 | } 517 | return newPkgStr; 518 | } 519 | 520 | function updateRange(oldRange: string, newVersion: string, oldOriginal?: string) { 521 | let newRange = oldRange.replace(/[0-9]+\.[0-9]+\.[0-9]+(-.+)?/g, newVersion); 522 | 523 | // if old version is a range like ^5 or ~5, retain number of version parts in new range 524 | if (oldOriginal && oldOriginal !== oldRange && /^[\^~]/.test(newRange)) { 525 | const oldParts = oldOriginal.substring(1).split("."); 526 | const newParts = newRange.substring(1).split("."); 527 | if (oldParts.length !== newParts.length) { 528 | newRange = `${newRange[0]}${newParts.slice(0, oldParts.length).join(".")}`; 529 | } 530 | } 531 | 532 | return newRange; 533 | } 534 | 535 | function isVersionPrerelease(version: string) { 536 | const parsed = parse(version); 537 | if (!parsed) return false; 538 | return Boolean(parsed.prerelease.length); 539 | } 540 | 541 | function isRangePrerelease(range: string) { 542 | // can not use coerce here because it ignores prerelease tags 543 | return /[0-9]+\.[0-9]+\.[0-9]+-.+/.test(range); 544 | } 545 | 546 | function rangeToVersion(range: string) { 547 | try { 548 | return coerce(range)?.version ?? ""; 549 | } catch { 550 | return ""; 551 | } 552 | } 553 | 554 | function findVersion(data: any, versions: string[], {range, semvers, usePre, useRel, useGreatest}: FindVersionOpts) { 555 | let tempVersion = rangeToVersion(range); 556 | let tempDate = 0; 557 | usePre = isRangePrerelease(range) || usePre; 558 | 559 | if (usePre) { 560 | semvers.add("prerelease"); 561 | if (semvers.has("patch")) semvers.add("prepatch"); 562 | if (semvers.has("minor")) semvers.add("preminor"); 563 | if (semvers.has("major")) semvers.add("premajor"); 564 | } 565 | 566 | for (const version of versions) { 567 | const parsed = parse(version); 568 | if (!parsed || !tempVersion || parsed.prerelease.length && (!usePre || useRel)) continue; 569 | 570 | const d = diff(tempVersion, parsed.version); 571 | if (!d || !semvers.has(d)) continue; 572 | 573 | // some registries like github don't have data.time available, fall back to greatest on them 574 | if (useGreatest || !("time" in data)) { 575 | if (gte(rangeToVersion(parsed?.version), tempVersion)) { 576 | tempVersion = parsed.version; 577 | } 578 | } else { 579 | const date = (new Date(data.time[version])).getTime(); 580 | if (date >= 0 && date > tempDate) { 581 | tempVersion = parsed.version; 582 | tempDate = date; 583 | } 584 | } 585 | } 586 | 587 | return tempVersion || null; 588 | } 589 | 590 | function findNewVersion(data: any, {mode, range, useGreatest, useRel, usePre, semvers}: FindNewVersionOpts): string | null { 591 | if (mode === "go") { 592 | if (gt(stripV(data.Version), stripV(range))) { 593 | return data.Version; 594 | } else { 595 | return null; 596 | } 597 | } 598 | if (range === "*") return null; // ignore wildcard 599 | if (range.includes("||")) return null; // ignore or-chains 600 | 601 | let versions: string[] = []; 602 | if (mode === "pypi") { 603 | versions = Object.keys(data.releases).filter((version: string) => valid(version)); 604 | } else if (mode === "npm") { 605 | versions = Object.keys(data.versions).filter((version: string) => valid(version)); 606 | } 607 | const version = findVersion(data, versions, {range, semvers, usePre, useRel, useGreatest}); 608 | if (!version) return null; 609 | 610 | if (useGreatest) { 611 | return version; 612 | } else { 613 | let latestTag = ""; 614 | let originalLatestTag = ""; 615 | if (mode === "pypi") { 616 | originalLatestTag = data.info.version; // may not be a 3-part semver 617 | latestTag = rangeToVersion(data.info.version); // add .0 to 6.0 so semver eats it 618 | } else { 619 | latestTag = data["dist-tags"].latest; 620 | } 621 | 622 | const oldVersion = rangeToVersion(range); 623 | const oldIsPre = isRangePrerelease(range); 624 | const newIsPre = isVersionPrerelease(version); 625 | const latestIsPre = isVersionPrerelease(latestTag); 626 | const isGreater = gt(version, oldVersion); 627 | 628 | // update to new prerelease 629 | if (!useRel && usePre || (oldIsPre && newIsPre)) { 630 | return version; 631 | } 632 | 633 | // downgrade from prerelease to release on --release-only 634 | if (useRel && !isGreater && oldIsPre && !newIsPre) { 635 | return version; 636 | } 637 | 638 | // update from prerelease to release 639 | if (oldIsPre && !newIsPre && isGreater) { 640 | return version; 641 | } 642 | 643 | // do not downgrade from prerelease to release 644 | if (oldIsPre && !newIsPre && !isGreater) { 645 | return null; 646 | } 647 | 648 | // check if latestTag is allowed by semvers 649 | const d = diff(oldVersion, latestTag); 650 | if (d && d !== "prerelease" && !semvers.has(d.replace(/^pre/, ""))) { 651 | return version; 652 | } 653 | 654 | // prevent upgrading to prerelease with --release-only 655 | if (useRel && isVersionPrerelease(latestTag)) { 656 | return version; 657 | } 658 | 659 | // prevent downgrade to older version except with --allow-downgrade 660 | if (lt(latestTag, oldVersion) && !latestIsPre) { 661 | if (allowDowngrade === true || matchesAny(data.name, allowDowngrade)) { 662 | return latestTag; 663 | } else { 664 | return null; 665 | } 666 | } 667 | 668 | // in all other cases, return latest dist-tag 669 | return originalLatestTag || latestTag; 670 | } 671 | } 672 | 673 | function fetchGitHub(url: string) { 674 | const opts: RequestInit = {}; 675 | const token = env.UPDATES_GITHUB_API_TOKEN || env.GITHUB_API_TOKEN || env.GH_TOKEN || env.HOMEBREW_GITHUB_API_TOKEN; 676 | if (token) { 677 | opts.headers = {Authorization: `Bearer ${token}`}; 678 | } 679 | return doFetch(url, opts); 680 | } 681 | 682 | async function getLastestCommit(user: string, repo: string): Promise<{hash: string, commit: Record}> { 683 | const url = `${githubApiUrl}/repos/${user}/${repo}/commits`; 684 | const res = await fetchGitHub(url); 685 | if (!res?.ok) return {hash: "", commit: {}}; 686 | const data = await res.json(); 687 | const {sha: hash, commit} = data[0]; 688 | return {hash, commit}; 689 | } 690 | 691 | // return list of tags sorted old to new 692 | // TODO: newDate support, semver matching 693 | async function getTags(user: string, repo: string): Promise { 694 | const res = await fetchGitHub(`${githubApiUrl}/repos/${user}/${repo}/git/refs/tags`); 695 | if (!res?.ok) return []; 696 | const data = await res.json(); 697 | const tags = data.map((entry: {ref: string}) => entry.ref.replace(/^refs\/tags\//, "")); 698 | return tags; 699 | } 700 | 701 | function selectTag(tags: string[], oldRef: string, useGreatest: boolean) { 702 | const oldRefBare = stripV(oldRef); 703 | if (!valid(oldRefBare)) return; 704 | 705 | if (!useGreatest) { 706 | const lastTag = tags.at(-1); 707 | if (!lastTag) return; 708 | const lastTagBare = stripV(lastTag); 709 | if (!valid(lastTagBare)) return; 710 | 711 | if (neq(oldRefBare, lastTagBare)) { 712 | return lastTag; 713 | } 714 | } else { 715 | let greatestTag = oldRef; 716 | let greatestTagBare = stripV(oldRef); 717 | 718 | for (const tag of tags) { 719 | const tagBare = stripV(tag); 720 | if (!valid(tagBare)) continue; 721 | if (!greatestTag || gt(tagBare, greatestTagBare)) { 722 | greatestTag = tag; 723 | greatestTagBare = tagBare; 724 | } 725 | } 726 | if (neq(oldRefBare, greatestTagBare)) { 727 | return greatestTag; 728 | } 729 | } 730 | } 731 | 732 | type CheckResult = { 733 | key: string, 734 | newRange: string, 735 | user: string, 736 | repo: string, 737 | oldRef: string, 738 | newRef: string, 739 | newDate?: string, 740 | newTag?: string, 741 | }; 742 | 743 | async function checkUrlDep(key: string, dep: Dep, useGreatest: boolean): Promise { 744 | const stripped = dep.old.replace(stripRe, ""); 745 | const [_, user, repo, oldRef] = partsRe.exec(stripped) || []; 746 | if (!user || !repo || !oldRef) return; 747 | 748 | if (hashRe.test(oldRef)) { 749 | const {hash, commit} = await getLastestCommit(user, repo); 750 | if (!hash) return; 751 | 752 | const newDate = commit?.committer?.date ?? commit?.author?.date; 753 | const newRef = hash.substring(0, oldRef.length); 754 | if (oldRef !== newRef) { 755 | const newRange = dep.old.replace(oldRef, newRef); 756 | return {key, newRange, user, repo, oldRef, newRef, newDate}; 757 | } 758 | } else { 759 | const tags = await getTags(user, repo); 760 | const newTag = selectTag(tags, oldRef, useGreatest); 761 | if (newTag) { 762 | return {key, newRange: newTag, user, repo, oldRef, newRef: newTag}; 763 | } 764 | } 765 | } 766 | 767 | // turn "v1.3.2-0.20230802210424-5b0b94c5c0d3" into "v1.3.2" 768 | function shortenGoVersion(version: string) { 769 | return version.replace(/-.*/, ""); 770 | } 771 | 772 | function normalizeRange(range: string) { 773 | const versionMatches = range.match(versionRe); 774 | if (versionMatches?.length !== 1) return range; 775 | return range.replace(versionRe, rangeToVersion(versionMatches[0])); 776 | } 777 | 778 | function parseMixedArg(arg: any) { 779 | if (arg === undefined) { 780 | return false; 781 | } else if (arg === "") { 782 | return true; 783 | } else if (typeof arg === "string") { 784 | return arg.includes(",") ? new Set(commaSeparatedToArray(arg)) : new Set([arg]); 785 | } else if (Array.isArray(arg)) { 786 | return new Set(arg); 787 | } else { 788 | return false; 789 | } 790 | } 791 | 792 | function extractCerts(str: string): string[] { 793 | return Array.from(str.matchAll(/(----BEGIN CERT[^]+?IFICATE----)/g), (m: string[]) => m[0]); 794 | } 795 | 796 | function extractKey(str: string): string[] { 797 | return Array.from(str.matchAll(/(----BEGIN [^]+?PRIVATE KEY----)/g), (m: string[]) => m[0]); 798 | } 799 | 800 | async function appendRoots(certs: string[] = []) { 801 | return [...(await import("node:tls")).rootCertificates, ...certs]; 802 | } 803 | 804 | // convert arg from cli or config to regex 805 | function argToRegex(arg: string | RegExp, cli: boolean) { 806 | if (cli && typeof arg === "string") { 807 | return /\/.+\//.test(arg) ? new RegExp(arg.slice(1, -1)) : picomatch.makeRe(arg); 808 | } else { 809 | return arg instanceof RegExp ? arg : picomatch.makeRe(arg); 810 | } 811 | } 812 | 813 | // parse cli arg into regex set 814 | function argSetToRegexes(arg: any) { 815 | if (arg instanceof Set) { 816 | const ret = new Set(); 817 | for (const entry of arg) { 818 | ret.add(argToRegex(entry, true)); 819 | } 820 | return ret; 821 | } 822 | return arg; 823 | } 824 | 825 | // parse include/exclude into a Set of regexes 826 | function matchersToRegexSet(cliArgs: string[], configArgs: Array): Set { 827 | const ret = new Set(); 828 | for (const arg of cliArgs || []) { 829 | ret.add(argToRegex(arg, true)); 830 | } 831 | for (const arg of configArgs || []) { 832 | ret.add(argToRegex(arg, false)); 833 | } 834 | return ret as Set; 835 | } 836 | 837 | function canInclude(name: string, mode: string, include: Set, exclude: Set) { 838 | if (mode === "pypi" && name === "python") return false; 839 | if (!include.size && !exclude.size) return true; 840 | for (const re of exclude) { 841 | if (re.test(name)) return false; 842 | } 843 | for (const re of include) { 844 | if (re.test(name)) return true; 845 | } 846 | return include.size ? false : true; 847 | } 848 | 849 | function resolveFiles(filesArg: Set): [Set, Set] { 850 | const resolvedFiles = new Set(); 851 | const explicitFiles = new Set(); 852 | 853 | if (filesArg) { // check passed files 854 | for (const file of filesArg) { 855 | let stat; 856 | try { 857 | stat = lstatSync(file); 858 | } catch (err) { 859 | throw new Error(`Unable to open ${file}: ${(err as Error).message}`); 860 | } 861 | 862 | if (stat?.isFile()) { 863 | const resolved = resolve(file); 864 | resolvedFiles.add(resolved); 865 | explicitFiles.add(resolved); 866 | } else if (stat?.isDirectory()) { 867 | for (const filename of Object.keys(modeByFileName)) { 868 | const f = join(file, filename); 869 | let stat; 870 | try { 871 | stat = lstatSync(f); 872 | } catch {} 873 | if (stat?.isFile()) { 874 | resolvedFiles.add(resolve(f)); 875 | } 876 | } 877 | } else { 878 | throw new Error(`${file} is neither a file nor directory`); 879 | } 880 | } 881 | } else { // search for files 882 | for (const filename of Object.keys(modeByFileName)) { 883 | const file = findUpSync(filename, cwd()); 884 | if (file) resolvedFiles.add(resolve(file)); 885 | } 886 | } 887 | return [resolvedFiles, explicitFiles]; 888 | } 889 | 890 | async function loadConfig(rootDir: string): Promise { 891 | const filenames: string[] = []; 892 | for (const prefix of ["", ".config/"]) { 893 | for (const ext of ["js", "ts", "mjs", "mts"]) { 894 | filenames.push(`${prefix}updates${prefix ? "" : ".config"}.${ext}`); 895 | } 896 | } 897 | let config: Config = {}; 898 | try { 899 | ({default: config} = await Promise.any(filenames.map(str => { 900 | return import(join(rootDir, ...str.split("/"))); 901 | }))); 902 | } catch {} 903 | return config; 904 | } 905 | 906 | async function main() { 907 | for (const stream of [process.stdout, process.stderr]) { 908 | // @ts-expect-error 909 | stream?._handle?.setBlocking?.(true); 910 | } 911 | 912 | const maxSockets = 96; 913 | const concurrency = typeof args.sockets === "number" ? args.sockets : maxSockets; 914 | const {help, version, file: filesArg, types, update} = args; 915 | 916 | if (help) { 917 | stdout.write(`usage: updates [options] 918 | 919 | Options: 920 | -u, --update Update versions and write package file 921 | -f, --file File or directory to use, defaults to current directory 922 | -i, --include Include only given packages 923 | -e, --exclude Exclude given packages 924 | -p, --prerelease [] Consider prerelease versions 925 | -R, --release [] Only use release versions, may downgrade 926 | -g, --greatest [] Prefer greatest over latest version 927 | -t, --types Check only given dependency types 928 | -P, --patch [] Consider only up to semver-patch 929 | -m, --minor [] Consider only up to semver-minor 930 | -d, --allow-downgrade [] Allow version downgrades when using latest version 931 | -E, --error-on-outdated Exit with code 2 when updates are available and 0 when not 932 | -U, --error-on-unchanged Exit with code 0 when updates are available and 2 when not 933 | -r, --registry Override npm registry URL 934 | -S, --sockets Maximum number of parallel HTTP sockets opened. Default: ${maxSockets} 935 | -M, --modes Which modes to enable. Either npm,pypi,go. Default: npm,pypi 936 | -j, --json Output a JSON object 937 | -n, --no-color Disable color output 938 | -v, --version Print the version 939 | -V, --verbose Print verbose output to stderr 940 | -h, --help Print this help 941 | 942 | Examples: 943 | $ updates 944 | $ updates -u 945 | $ updates -e '@vitejs/*' 946 | $ updates -e '/^react-(dom)?/' 947 | $ updates -f package.json 948 | $ updates -f pyproject.toml 949 | `); 950 | exit(0); 951 | } 952 | 953 | if (version) { 954 | console.info(packageVersion); 955 | exit(0); 956 | } 957 | 958 | // output vars 959 | const deps: DepsByMode = {}; 960 | const maybeUrlDeps: DepsByMode = {}; 961 | const pkgStrs: Record = {}; 962 | const filePerMode: Record = {}; 963 | let numDependencies = 0; 964 | 965 | const [files, explicitFiles] = resolveFiles(parseMixedArg(filesArg) as Set); 966 | 967 | for (const file of files) { 968 | const projectDir = dirname(resolve(file)); 969 | const filename = basename(file) as keyof typeof modeByFileName; 970 | const mode = modeByFileName[filename]; 971 | if (!enabledModes.has(mode) && !explicitFiles.has(file)) continue; 972 | filePerMode[mode] = file; 973 | if (!deps[mode]) deps[mode] = {}; 974 | 975 | const config = await loadConfig(projectDir); 976 | let includeCli: string[] = []; 977 | let excludeCli: string[] = []; 978 | if (args.include && args.include !== true) { // cli 979 | includeCli = (Array.isArray(args.include) ? args.include : [args.include]) 980 | .flatMap(item => commaSeparatedToArray(item)); 981 | } 982 | if (args.exclude && args.exclude !== true) { 983 | excludeCli = (Array.isArray(args.exclude) ? args.exclude : [args.exclude]) 984 | .flatMap(item => commaSeparatedToArray(item)); 985 | } 986 | const include = matchersToRegexSet(includeCli, config?.include ?? []); 987 | const exclude = matchersToRegexSet(excludeCli, config?.exclude ?? []); 988 | 989 | const agentOpts: AgentOptions = {}; 990 | const npmrc: Npmrc = rc("npm", {registry: "https://registry.npmjs.org"}) || {}; 991 | const authTokenOpts = {npmrc, recursive: true}; 992 | if (mode === "npm") { 993 | // TODO: support these per-scope 994 | if (npmrc["strict-ssl"] === false) { 995 | agentOpts.rejectUnauthorized = false; 996 | } 997 | for (const opt of ["cert", "ca", "key"] as const) { 998 | const extract = (opt === "key") ? extractKey : extractCerts; 999 | let strs: string[] = []; 1000 | if (npmrc[opt]) { 1001 | strs = (Array.isArray(npmrc[opt]) ? npmrc[opt] : [npmrc[opt]]).flatMap(str => extract(str)); 1002 | } 1003 | if (npmrc[`${opt}file`]) { 1004 | strs = Array.from(extract(readFileSync(npmrc[`opt${file}`], "utf8"))); 1005 | } 1006 | if (strs.length) { 1007 | agentOpts[opt] = opt === "ca" ? await appendRoots(strs) : strs; 1008 | } 1009 | } 1010 | } 1011 | 1012 | let dependencyTypes: string[] = []; 1013 | if (types) { 1014 | dependencyTypes = Array.isArray(types) ? types : commaSeparatedToArray(types); 1015 | } else if ("types" in config && Array.isArray(config.types)) { 1016 | dependencyTypes = config.types; 1017 | } else { 1018 | if (mode === "npm") { 1019 | dependencyTypes = [ 1020 | "dependencies", 1021 | "devDependencies", 1022 | "optionalDependencies", 1023 | "peerDependencies", 1024 | "resolutions", 1025 | ]; 1026 | } else if (mode === "pypi") { 1027 | dependencyTypes = [ 1028 | "tool.poetry.dependencies", 1029 | "tool.poetry.dev-dependencies", 1030 | "tool.poetry.test-dependencies", 1031 | "tool.poetry.group.dev.dependencies", 1032 | "tool.poetry.group.test.dependencies", 1033 | ]; 1034 | } else if (mode === "go") { 1035 | dependencyTypes = [ 1036 | "deps", 1037 | ]; 1038 | } 1039 | } 1040 | 1041 | let pkg: Record = {}; 1042 | if (mode === "go") { 1043 | pkgStrs[mode] = execFileSync("go", [ 1044 | "list", "-m", "-f", "{{if not .Indirect}}{{.Path}}@{{.Version}}{{end}}", "all", 1045 | ], {stdio: "pipe", encoding: "utf8", cwd: projectDir}); 1046 | } else { 1047 | try { 1048 | pkgStrs[mode] = readFileSync(file, "utf8"); 1049 | } catch (err) { 1050 | throw new Error(`Unable to open ${file}: ${(err as Error).message}`); 1051 | } 1052 | } 1053 | 1054 | try { 1055 | if (mode === "npm") { 1056 | pkg = JSON.parse(pkgStrs[mode]); 1057 | } else if (mode === "pypi") { 1058 | pkg = (await import("smol-toml")).parse(pkgStrs[mode]); 1059 | } else { 1060 | pkg.deps = {}; 1061 | for (const modulePathAndVersion of splitPlainText(pkgStrs[mode])) { 1062 | const [modulePath, version] = modulePathAndVersion.split("@"); 1063 | if (version) { // current module has no version 1064 | pkg.deps[modulePath] = version; 1065 | } 1066 | } 1067 | } 1068 | } catch (err) { 1069 | throw new Error(`Error parsing ${file}: ${(err as Error).message}`); 1070 | } 1071 | 1072 | for (const depType of dependencyTypes) { 1073 | let obj: Record; 1074 | if (mode === "npm" || mode === "go") { 1075 | obj = pkg[depType] || {}; 1076 | } else { 1077 | obj = getProperty(pkg, depType) || {}; 1078 | } 1079 | 1080 | for (const [name, value] of Object.entries(obj)) { 1081 | if (mode !== "go" && validRange(value) && canInclude(name, mode, include, exclude)) { 1082 | // @ts-expect-error 1083 | deps[mode][`${depType}${sep}${name}`] = { 1084 | old: normalizeRange(value), 1085 | oldOriginal: value, 1086 | } as Partial; 1087 | } else if (mode === "npm" && canInclude(name, mode, include, exclude)) { 1088 | // @ts-expect-error 1089 | maybeUrlDeps[`${depType}${sep}${name}`] = { 1090 | old: value, 1091 | } as Partial; 1092 | } else if (mode === "go") { 1093 | // @ts-expect-error 1094 | deps[mode][`${depType}${sep}${name}`] = { 1095 | old: shortenGoVersion(value), 1096 | oldOriginal: value, 1097 | } as Partial; 1098 | } 1099 | } 1100 | } 1101 | 1102 | numDependencies += Object.keys(deps[mode]).length + Object.keys(maybeUrlDeps).length; 1103 | if (!numDependencies) continue; 1104 | 1105 | let registry: string; 1106 | if (mode === "npm") { 1107 | registry = normalizeUrl(args.registry || config.registry || npmrc.registry); 1108 | } 1109 | 1110 | const entries = await pAll(Object.keys(deps[mode]).map(key => async () => { 1111 | const [type, name] = key.split(sep); 1112 | if (mode === "npm") { 1113 | return fetchNpmInfo(name, type, registry, agentOpts, authTokenOpts, npmrc); 1114 | } else if (mode === "pypi") { 1115 | return fetchPypiInfo(name, type, agentOpts); 1116 | } else { 1117 | const proxies = Array.from(goProxies); 1118 | const data: Record = await fetchGoVersionInfo(name, "latest", agentOpts, proxies); 1119 | return [data, "deps", null, name]; 1120 | } 1121 | }), {concurrency}); 1122 | 1123 | for (const [data, type, registry, name] of entries) { 1124 | if (data?.error) throw new Error(data.error); 1125 | 1126 | const useGreatest = typeof greatest === "boolean" ? greatest : matchesAny(data.name, greatest); 1127 | const usePre = typeof prerelease === "boolean" ? prerelease : matchesAny(data.name, prerelease); 1128 | const useRel = typeof release === "boolean" ? release : matchesAny(data.name, release); 1129 | 1130 | let semvers; 1131 | if (patch === true || matchesAny(data.name, patch)) { 1132 | semvers = new Set(["patch"]); 1133 | } else if (minor === true || matchesAny(data.name, minor)) { 1134 | semvers = new Set(["patch", "minor"]); 1135 | } else { 1136 | semvers = new Set(["patch", "minor", "major"]); 1137 | } 1138 | 1139 | const key = `${type}${sep}${name}`; 1140 | const oldRange = deps[mode][key].old; 1141 | const oldOriginal = deps[mode][key].oldOriginal; 1142 | const newVersion = findNewVersion(data, { 1143 | usePre, useRel, useGreatest, semvers, range: oldRange, mode, 1144 | }); 1145 | 1146 | let newRange: string = ""; 1147 | if (mode === "go" && newVersion) { 1148 | newRange = newVersion; 1149 | } else if (newVersion) { 1150 | newRange = updateRange(oldRange, newVersion, oldOriginal); 1151 | } 1152 | 1153 | if (!newVersion || oldOriginal && (oldOriginal === newRange)) { 1154 | delete deps[mode][key]; 1155 | } else { 1156 | deps[mode][key].new = newRange; 1157 | 1158 | if (mode === "npm") { 1159 | deps[mode][key].info = getInfoUrl(data?.versions?.[newVersion], registry, data.name); 1160 | } else if (mode === "pypi") { 1161 | deps[mode][key].info = getInfoUrl(data, registry, data.info.name); 1162 | } else { 1163 | deps[mode][key].info = data?.Origin?.URL ?? `https://${name}`; 1164 | } 1165 | 1166 | let date: TimerelAnyDate = ""; 1167 | if (mode === "npm" && data.time?.[newVersion]) { // npm 1168 | date = data.time[newVersion]; 1169 | } else if (mode === "pypi" && data.releases?.[newVersion]?.[0]?.upload_time_iso_8601) { 1170 | date = data.releases[newVersion][0].upload_time_iso_8601; 1171 | } else if (mode === "go" && data.Time) { 1172 | date = data.Time; 1173 | } 1174 | if (date) { 1175 | deps[mode][key].age = timerel(date, {noAffix: true}); 1176 | } 1177 | } 1178 | } 1179 | 1180 | if (Object.keys(maybeUrlDeps).length) { 1181 | const results = await pAll(Object.entries(maybeUrlDeps).map(([key, dep]) => () => { 1182 | const name = key.split(sep)[1]; 1183 | const useGreatest = typeof greatest === "boolean" ? greatest : matchesAny(name, greatest); 1184 | // @ts-expect-error 1185 | return checkUrlDep(key, dep, useGreatest); 1186 | }), {concurrency}); 1187 | 1188 | for (const res of (results || []).filter(Boolean)) { 1189 | const {key, newRange, user, repo, oldRef, newRef, newDate} = res as CheckResult; 1190 | deps[mode][key] = { 1191 | // @ts-expect-error 1192 | old: maybeUrlDeps[key].old, 1193 | new: newRange, 1194 | oldPrint: hashRe.test(oldRef) ? oldRef.substring(0, 7) : oldRef, 1195 | newPrint: hashRe.test(newRef) ? newRef.substring(0, 7) : newRef, 1196 | info: `https://github.com/${user}/${repo}`, 1197 | ...(newDate ? {age: timerel(newDate, {noAffix: true})} : {}), 1198 | }; 1199 | } 1200 | } 1201 | } 1202 | 1203 | if (numDependencies === 0) { 1204 | finishWithMessage("No dependencies found, nothing to do."); 1205 | doExit(); 1206 | } 1207 | 1208 | let numEntries = 0; 1209 | for (const mode of Object.keys(deps)) { 1210 | numEntries += Object.keys(deps[mode]).length; 1211 | } 1212 | 1213 | if (!numEntries) { 1214 | finishWithMessage("All dependencies are up to date."); 1215 | doExit(); 1216 | } 1217 | 1218 | const exitCode = outputDeps(deps); 1219 | 1220 | if (update) { 1221 | for (const mode of Object.keys(deps)) { 1222 | if (!Object.keys(deps[mode]).length) continue; 1223 | try { 1224 | const fn = (mode === "npm") ? updatePackageJson : updateProjectToml; 1225 | await write(filePerMode[mode], fn(pkgStrs[mode], deps[mode])); 1226 | } catch (err) { 1227 | throw new Error(`Error writing ${basename(filePerMode[mode])}: ${(err as Error).message}`); 1228 | } 1229 | 1230 | // TODO: json 1231 | console.info(green(`✨ ${basename(filePerMode[mode])} updated`)); 1232 | } 1233 | } 1234 | 1235 | process.exit(exitCode); 1236 | } 1237 | 1238 | main().catch(doExit).then(doExit); 1239 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "updates", 3 | "version": "16.4.2", 4 | "description": "Flexible npm and poetry dependency update tool", 5 | "author": "silverwind", 6 | "repository": "silverwind/updates", 7 | "license": "BSD-2-Clause", 8 | "bin": "dist/index.js", 9 | "types": "dist/index.d.ts", 10 | "type": "module", 11 | "files": [ 12 | "dist" 13 | ], 14 | "engines": { 15 | "node": ">=18" 16 | }, 17 | "devDependencies": { 18 | "@types/minimist": "1.2.5", 19 | "@types/node": "22.13.4", 20 | "@types/picomatch": "3.0.2", 21 | "@types/rc": "1.2.4", 22 | "@types/registry-auth-token": "4.2.4", 23 | "@types/semver": "7.5.8", 24 | "eslint": "8.57.0", 25 | "eslint-config-silverwind": "99.0.0", 26 | "glowie": "1.3.2", 27 | "minimist": "1.2.8", 28 | "nano-spawn": "0.2.0", 29 | "p-all": "5.0.0", 30 | "picomatch": "4.0.2", 31 | "rc": "1.2.8", 32 | "registry-auth-token": "4.2.2", 33 | "restana": "5.0.0", 34 | "semver": "7.3.8", 35 | "smol-toml": "1.3.1", 36 | "supports-color": "10.0.0", 37 | "timerel": "5.8.1", 38 | "typescript": "5.7.3", 39 | "typescript-config-silverwind": "7.0.0", 40 | "versions": "12.1.3", 41 | "vite": "6.1.0", 42 | "vite-config-silverwind": "4.0.0", 43 | "vite-plugin-dts": "3.9.1", 44 | "vitest": "3.0.5", 45 | "vitest-config-silverwind": "10.0.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silverwind/updates/85132c1ba67bddd1c19c688e0e6fb125242703f5/screenshot.png -------------------------------------------------------------------------------- /snapshots/index.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`dual 1`] = ` 4 | { 5 | "npm": { 6 | "dependencies": { 7 | "@babel/preset-env": { 8 | "info": "https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env", 9 | "new": "7.11.5", 10 | "old": "7.0.0", 11 | }, 12 | "gulp-sourcemaps": { 13 | "info": "https://github.com/gulp-sourcemaps/gulp-sourcemaps", 14 | "new": "2.6.5", 15 | "old": "2.0.0", 16 | }, 17 | "html-webpack-plugin": { 18 | "info": "https://github.com/jantimon/html-webpack-plugin", 19 | "new": "4.0.0-beta.11", 20 | "old": "4.0.0-alpha.2", 21 | }, 22 | "jpeg-buffer-orientation": { 23 | "info": "https://github.com/fisker/jpeg-buffer-orientation", 24 | "new": "2.0.3", 25 | "old": "0.0.0", 26 | }, 27 | "noty": { 28 | "info": "https://github.com/needim/noty", 29 | "new": "3.2.0-beta", 30 | "old": "3.1.0", 31 | }, 32 | "prismjs": { 33 | "info": "https://github.com/LeaVerou/prism", 34 | "new": "1.17.1", 35 | "old": "1.0.0", 36 | }, 37 | "react": { 38 | "info": "https://github.com/facebook/react/tree/HEAD/packages/react", 39 | "new": "18.2.0", 40 | "old": "18.0", 41 | }, 42 | "styled-components": { 43 | "info": "https://github.com/styled-components/styled-components", 44 | "new": "5.0.0-rc.2", 45 | "old": "2.5.0-1", 46 | }, 47 | "svgstore": { 48 | "info": "https://github.com/svgstore/svgstore", 49 | "new": "^3.0.0-2", 50 | "old": "^3.0.0", 51 | }, 52 | "updates": { 53 | "info": "https://github.com/silverwind/updates", 54 | "new": "537ccb7", 55 | "old": "6941e05", 56 | }, 57 | }, 58 | "peerDependencies": { 59 | "@babel/preset-env": { 60 | "info": "https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env", 61 | "new": "~7.11.5", 62 | "old": "~6.0.0", 63 | }, 64 | }, 65 | "resolutions": { 66 | "versions/updates": { 67 | "info": "https://github.com/silverwind/updates", 68 | "new": "^10.0.0", 69 | "old": "^1.0.0", 70 | }, 71 | }, 72 | }, 73 | "pypi": { 74 | "dependencies": { 75 | "updates": { 76 | "info": "https://github.com/silverwind/updates", 77 | "new": "537ccb7", 78 | "old": "6941e05", 79 | }, 80 | }, 81 | "tool.poetry.group.dev.dependencies": { 82 | "djlint": { 83 | "info": "https://github.com/Riverside-Healthcare/djlint", 84 | "new": "1.31.0", 85 | "old": "1.30.0", 86 | }, 87 | }, 88 | }, 89 | } 90 | `; 91 | 92 | exports[`dual 2 1`] = ` 93 | { 94 | "npm": { 95 | "dependencies": { 96 | "noty": { 97 | "info": "https://github.com/needim/noty", 98 | "new": "3.2.0-beta", 99 | "old": "3.1.0", 100 | }, 101 | }, 102 | }, 103 | } 104 | `; 105 | 106 | exports[`exclude 1`] = ` 107 | { 108 | "npm": { 109 | "dependencies": { 110 | "updates": { 111 | "info": "https://github.com/silverwind/updates", 112 | "new": "537ccb7", 113 | "old": "6941e05", 114 | }, 115 | }, 116 | "peerDependencies": { 117 | "typescript": { 118 | "info": "https://github.com/Microsoft/TypeScript", 119 | "new": "^5", 120 | "old": "^4", 121 | }, 122 | }, 123 | }, 124 | } 125 | `; 126 | 127 | exports[`exclude 2 1`] = ` 128 | { 129 | "npm": { 130 | "dependencies": { 131 | "react": { 132 | "info": "https://github.com/facebook/react/tree/HEAD/packages/react", 133 | "new": "18.2.0", 134 | "old": "18.0", 135 | }, 136 | }, 137 | }, 138 | } 139 | `; 140 | 141 | exports[`exclude 3 1`] = ` 142 | { 143 | "npm": { 144 | "dependencies": { 145 | "gulp-sourcemaps": { 146 | "info": "https://github.com/gulp-sourcemaps/gulp-sourcemaps", 147 | "new": "2.6.5", 148 | "old": "2.0.0", 149 | }, 150 | }, 151 | }, 152 | } 153 | `; 154 | 155 | exports[`exclude 4 1`] = ` 156 | { 157 | "npm": { 158 | "dependencies": { 159 | "gulp-sourcemaps": { 160 | "info": "https://github.com/floridoo/gulp-sourcemaps", 161 | "new": "2.0.1", 162 | "old": "2.0.0", 163 | }, 164 | }, 165 | }, 166 | } 167 | `; 168 | 169 | exports[`greatest 1`] = ` 170 | { 171 | "npm": { 172 | "dependencies": { 173 | "@babel/preset-env": { 174 | "info": "https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env", 175 | "new": "7.11.5", 176 | "old": "7.0.0", 177 | }, 178 | "gulp-sourcemaps": { 179 | "info": "https://github.com/gulp-sourcemaps/gulp-sourcemaps", 180 | "new": "2.6.5", 181 | "old": "2.0.0", 182 | }, 183 | "html-webpack-plugin": { 184 | "info": "https://github.com/jantimon/html-webpack-plugin", 185 | "new": "4.0.0-beta.11", 186 | "old": "4.0.0-alpha.2", 187 | }, 188 | "jpeg-buffer-orientation": { 189 | "info": "https://github.com/fisker/jpeg-buffer-orientation", 190 | "new": "2.0.3", 191 | "old": "0.0.0", 192 | }, 193 | "noty": { 194 | "info": "https://github.com/needim/noty", 195 | "new": "3.1.4", 196 | "old": "3.1.0", 197 | }, 198 | "prismjs": { 199 | "info": "https://github.com/LeaVerou/prism", 200 | "new": "1.17.1", 201 | "old": "1.0.0", 202 | }, 203 | "react": { 204 | "info": "https://github.com/facebook/react/tree/HEAD/packages/react", 205 | "new": "18.2.0", 206 | "old": "18.0", 207 | }, 208 | "styled-components": { 209 | "info": "https://github.com/styled-components/styled-components", 210 | "new": "5.0.0-rc.2", 211 | "old": "2.5.0-1", 212 | }, 213 | "updates": { 214 | "info": "https://github.com/silverwind/updates", 215 | "new": "537ccb7", 216 | "old": "6941e05", 217 | }, 218 | }, 219 | "peerDependencies": { 220 | "@babel/preset-env": { 221 | "info": "https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env", 222 | "new": "~7.11.5", 223 | "old": "~6.0.0", 224 | }, 225 | "typescript": { 226 | "info": "https://github.com/Microsoft/TypeScript", 227 | "new": "^5", 228 | "old": "^4", 229 | }, 230 | }, 231 | "resolutions": { 232 | "versions/updates": { 233 | "info": "https://github.com/silverwind/updates", 234 | "new": "^10.0.0", 235 | "old": "^1.0.0", 236 | }, 237 | }, 238 | }, 239 | } 240 | `; 241 | 242 | exports[`include 1`] = ` 243 | { 244 | "npm": { 245 | "dependencies": { 246 | "noty": { 247 | "info": "https://github.com/needim/noty", 248 | "new": "3.2.0-beta", 249 | "old": "3.1.0", 250 | }, 251 | }, 252 | }, 253 | } 254 | `; 255 | 256 | exports[`include 2 1`] = ` 257 | { 258 | "npm": { 259 | "dependencies": { 260 | "noty": { 261 | "info": "https://github.com/needim/noty", 262 | "new": "3.2.0-beta", 263 | "old": "3.1.0", 264 | }, 265 | }, 266 | }, 267 | } 268 | `; 269 | 270 | exports[`include 3 1`] = ` 271 | { 272 | "npm": { 273 | "dependencies": { 274 | "noty": { 275 | "info": "https://github.com/needim/noty", 276 | "new": "3.2.0-beta", 277 | "old": "3.1.0", 278 | }, 279 | }, 280 | }, 281 | } 282 | `; 283 | 284 | exports[`latest 1`] = ` 285 | { 286 | "npm": { 287 | "dependencies": { 288 | "@babel/preset-env": { 289 | "info": "https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env", 290 | "new": "7.11.5", 291 | "old": "7.0.0", 292 | }, 293 | "gulp-sourcemaps": { 294 | "info": "https://github.com/gulp-sourcemaps/gulp-sourcemaps", 295 | "new": "2.6.5", 296 | "old": "2.0.0", 297 | }, 298 | "html-webpack-plugin": { 299 | "info": "https://github.com/jantimon/html-webpack-plugin", 300 | "new": "4.0.0-beta.11", 301 | "old": "4.0.0-alpha.2", 302 | }, 303 | "jpeg-buffer-orientation": { 304 | "info": "https://github.com/fisker/jpeg-buffer-orientation", 305 | "new": "2.0.3", 306 | "old": "0.0.0", 307 | }, 308 | "noty": { 309 | "info": "https://github.com/needim/noty", 310 | "new": "3.2.0-beta", 311 | "old": "3.1.0", 312 | }, 313 | "prismjs": { 314 | "info": "https://github.com/LeaVerou/prism", 315 | "new": "1.17.1", 316 | "old": "1.0.0", 317 | }, 318 | "react": { 319 | "info": "https://github.com/facebook/react/tree/HEAD/packages/react", 320 | "new": "18.2.0", 321 | "old": "18.0", 322 | }, 323 | "styled-components": { 324 | "info": "https://github.com/styled-components/styled-components", 325 | "new": "5.0.0-rc.2", 326 | "old": "2.5.0-1", 327 | }, 328 | "svgstore": { 329 | "info": "https://github.com/svgstore/svgstore", 330 | "new": "^3.0.0-2", 331 | "old": "^3.0.0", 332 | }, 333 | "updates": { 334 | "info": "https://github.com/silverwind/updates", 335 | "new": "537ccb7", 336 | "old": "6941e05", 337 | }, 338 | }, 339 | "peerDependencies": { 340 | "@babel/preset-env": { 341 | "info": "https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env", 342 | "new": "~7.11.5", 343 | "old": "~6.0.0", 344 | }, 345 | "typescript": { 346 | "info": "https://github.com/Microsoft/TypeScript", 347 | "new": "^5", 348 | "old": "^4", 349 | }, 350 | }, 351 | "resolutions": { 352 | "versions/updates": { 353 | "info": "https://github.com/silverwind/updates", 354 | "new": "^10.0.0", 355 | "old": "^1.0.0", 356 | }, 357 | }, 358 | }, 359 | } 360 | `; 361 | 362 | exports[`patch 1`] = ` 363 | { 364 | "npm": { 365 | "dependencies": { 366 | "gulp-sourcemaps": { 367 | "info": "https://github.com/floridoo/gulp-sourcemaps", 368 | "new": "2.0.1", 369 | "old": "2.0.0", 370 | }, 371 | "html-webpack-plugin": { 372 | "info": "https://github.com/jantimon/html-webpack-plugin", 373 | "new": "4.0.0-beta.11", 374 | "old": "4.0.0-alpha.2", 375 | }, 376 | "noty": { 377 | "info": "https://github.com/needim/noty", 378 | "new": "3.1.4", 379 | "old": "3.1.0", 380 | }, 381 | "react": { 382 | "info": "https://github.com/facebook/react/tree/HEAD/packages/react", 383 | "new": "18.0.0", 384 | "old": "18.0", 385 | }, 386 | "svgstore": { 387 | "info": "https://github.com/svgstore/svgstore", 388 | "new": "^3.0.0-2", 389 | "old": "^3.0.0", 390 | }, 391 | "updates": { 392 | "info": "https://github.com/silverwind/updates", 393 | "new": "537ccb7", 394 | "old": "6941e05", 395 | }, 396 | }, 397 | "resolutions": { 398 | "versions/updates": { 399 | "info": "https://github.com/silverwind/updates", 400 | "new": "^1.0.6", 401 | "old": "^1.0.0", 402 | }, 403 | }, 404 | }, 405 | } 406 | `; 407 | 408 | exports[`prerelease 1`] = ` 409 | { 410 | "npm": { 411 | "dependencies": { 412 | "@babel/preset-env": { 413 | "info": "https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env", 414 | "new": "7.11.5", 415 | "old": "7.0.0", 416 | }, 417 | "gulp-sourcemaps": { 418 | "info": "https://github.com/gulp-sourcemaps/gulp-sourcemaps", 419 | "new": "2.6.5", 420 | "old": "2.0.0", 421 | }, 422 | "html-webpack-plugin": { 423 | "info": "https://github.com/jantimon/html-webpack-plugin", 424 | "new": "4.0.0-beta.11", 425 | "old": "4.0.0-alpha.2", 426 | }, 427 | "jpeg-buffer-orientation": { 428 | "info": "https://github.com/fisker/jpeg-buffer-orientation", 429 | "new": "2.0.3", 430 | "old": "0.0.0", 431 | }, 432 | "noty": { 433 | "info": "https://github.com/needim/noty", 434 | "new": "3.2.0-beta", 435 | "old": "3.1.0", 436 | }, 437 | "prismjs": { 438 | "info": "https://github.com/LeaVerou/prism", 439 | "new": "1.17.1", 440 | "old": "1.0.0", 441 | }, 442 | "react": { 443 | "info": "https://github.com/facebook/react/tree/HEAD/packages/react", 444 | "new": "18.3.0-next-d1e35c703-20221110", 445 | "old": "18.0", 446 | }, 447 | "styled-components": { 448 | "info": "https://github.com/styled-components/styled-components", 449 | "new": "5.0.0-rc.2", 450 | "old": "2.5.0-1", 451 | }, 452 | "svgstore": { 453 | "info": "https://github.com/svgstore/svgstore", 454 | "new": "^3.0.0-2", 455 | "old": "^3.0.0", 456 | }, 457 | "updates": { 458 | "info": "https://github.com/silverwind/updates", 459 | "new": "537ccb7", 460 | "old": "6941e05", 461 | }, 462 | }, 463 | "peerDependencies": { 464 | "@babel/preset-env": { 465 | "info": "https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env", 466 | "new": "~7.11.5", 467 | "old": "~6.0.0", 468 | }, 469 | "typescript": { 470 | "info": "https://github.com/Microsoft/TypeScript", 471 | "new": "^5", 472 | "old": "^4", 473 | }, 474 | }, 475 | "resolutions": { 476 | "versions/updates": { 477 | "info": "https://github.com/silverwind/updates", 478 | "new": "^10.0.0", 479 | "old": "^1.0.0", 480 | }, 481 | }, 482 | }, 483 | } 484 | `; 485 | 486 | exports[`pypi 1`] = ` 487 | { 488 | "pypi": { 489 | "tool.poetry.group.dev.dependencies": { 490 | "djlint": { 491 | "info": "https://github.com/Riverside-Healthcare/djlint", 492 | "new": "1.31.0", 493 | "old": "1.30.0", 494 | }, 495 | }, 496 | }, 497 | } 498 | `; 499 | 500 | exports[`release 1`] = ` 501 | { 502 | "npm": { 503 | "dependencies": { 504 | "@babel/preset-env": { 505 | "info": "https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env", 506 | "new": "7.11.5", 507 | "old": "7.0.0", 508 | }, 509 | "gulp-sourcemaps": { 510 | "info": "https://github.com/gulp-sourcemaps/gulp-sourcemaps", 511 | "new": "2.6.5", 512 | "old": "2.0.0", 513 | }, 514 | "html-webpack-plugin": { 515 | "info": "https://github.com/jantimon/html-webpack-plugin", 516 | "new": "3.2.0", 517 | "old": "4.0.0-alpha.2", 518 | }, 519 | "jpeg-buffer-orientation": { 520 | "info": "https://github.com/fisker/jpeg-buffer-orientation", 521 | "new": "2.0.3", 522 | "old": "0.0.0", 523 | }, 524 | "noty": { 525 | "info": "https://github.com/needim/noty", 526 | "new": "3.1.4", 527 | "old": "3.1.0", 528 | }, 529 | "prismjs": { 530 | "info": "https://github.com/LeaVerou/prism", 531 | "new": "1.17.1", 532 | "old": "1.0.0", 533 | }, 534 | "react": { 535 | "info": "https://github.com/facebook/react/tree/HEAD/packages/react", 536 | "new": "18.2.0", 537 | "old": "18.0", 538 | }, 539 | "styled-components": { 540 | "info": "https://github.com/styled-components/styled-components", 541 | "new": "4.4.1", 542 | "old": "2.5.0-1", 543 | }, 544 | "svgstore": { 545 | "info": "https://github.com/svgstore/svgstore", 546 | "new": "^2.0.3", 547 | "old": "^3.0.0", 548 | }, 549 | "updates": { 550 | "info": "https://github.com/silverwind/updates", 551 | "new": "537ccb7", 552 | "old": "6941e05", 553 | }, 554 | }, 555 | "peerDependencies": { 556 | "@babel/preset-env": { 557 | "info": "https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env", 558 | "new": "~7.11.5", 559 | "old": "~6.0.0", 560 | }, 561 | "typescript": { 562 | "info": "https://github.com/Microsoft/TypeScript", 563 | "new": "^5", 564 | "old": "^4", 565 | }, 566 | }, 567 | "resolutions": { 568 | "versions/updates": { 569 | "info": "https://github.com/silverwind/updates", 570 | "new": "^10.0.0", 571 | "old": "^1.0.0", 572 | }, 573 | }, 574 | }, 575 | } 576 | `; 577 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "typescript-config-silverwind", 3 | "compilerOptions": { 4 | "strict": true, 5 | "types": [ 6 | "jest-extended", 7 | "vite/client", 8 | "vitest/globals", 9 | ], 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /updates.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | exclude: [ 3 | "eslint", 4 | "registry-auth-token", 5 | "semver", 6 | "vite-plugin-dts", // https://github.com/qmhc/vite-plugin-dts/issues/363 7 | ], 8 | }; 9 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import {defineConfig} from "vite"; 2 | import {nodeCli} from "vite-config-silverwind"; 3 | import dts from "vite-plugin-dts"; 4 | 5 | export default defineConfig(nodeCli({ 6 | url: import.meta.url, 7 | build: { 8 | target: "node18", 9 | }, 10 | plugins: [ 11 | dts({include: "index.ts"}), 12 | ], 13 | })); 14 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import {defineConfig} from "vitest/config"; 2 | import {backend} from "vitest-config-silverwind"; 3 | 4 | export default defineConfig(backend({ 5 | url: import.meta.url, 6 | })); 7 | --------------------------------------------------------------------------------