dev(tools): add license header adder thingy

This commit is contained in:
KernelDeimos 2024-07-10 00:40:37 -04:00
parent c76af1ab21
commit 67139ef91b
8 changed files with 1334 additions and 28 deletions

1
addlicense.yml Normal file
View File

@ -0,0 +1 @@
header: doc/license_header.txt

455
package-lock.json generated
View File

@ -1024,6 +1024,102 @@
"url": "https://github.com/sponsors/nzakas"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"license": "ISC",
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"license": "MIT"
},
"node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@isaacs/cliui/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
@ -6021,6 +6117,10 @@
"node": ">=14"
}
},
"node_modules/comment-parser": {
"resolved": "tools/comment-parser",
"link": true
},
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
@ -6183,6 +6283,15 @@
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
"license": "ISC"
},
"node_modules/console-table-printer": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/console-table-printer/-/console-table-printer-2.12.1.tgz",
"integrity": "sha512-wKGOQRRvdnd89pCeH96e2Fn4wkbenSP6LMHfjfyNLMbGuHEFbMqQNuxXqd0oXG9caIOQ1FTvc5Uijp9/4jujnQ==",
"license": "MIT",
"dependencies": {
"simple-wcswidth": "^1.0.1"
}
},
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@ -6327,7 +6436,6 @@
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true,
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@ -6617,6 +6725,12 @@
"node": ">=0.3.1"
}
},
"node_modules/diff-match-patch": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz",
"integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==",
"license": "Apache-2.0"
},
"node_modules/diff3": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz",
@ -6707,6 +6821,12 @@
"url": "https://dotenvx.com"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"license": "MIT"
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
@ -8001,6 +8121,10 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/google-license": {
"resolved": "tools/google-license",
"link": true
},
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
@ -8682,8 +8806,7 @@
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"node_modules/isobject": {
"version": "3.0.1",
@ -8889,6 +9012,24 @@
"node": ">=8"
}
},
"node_modules/jackspeak": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz",
"integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/jest-worker": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
@ -8973,6 +9114,15 @@
"integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==",
"license": "BSD-3-Clause"
},
"node_modules/js-levenshtein": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
"integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/js-parse-and-output": {
"resolved": "experiments/js-parse-and-output",
"link": true
@ -9458,6 +9608,10 @@
"decamelize": "^1.2.0"
}
},
"node_modules/license-headers": {
"resolved": "tools/license-headers",
"link": true
},
"node_modules/load-bmfont": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz",
@ -10760,6 +10914,12 @@
"node": ">=8"
}
},
"node_modules/package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
"integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
"license": "BlueOak-1.0.0"
},
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
@ -10855,7 +11015,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -10865,6 +11024,40 @@
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/path-scurry": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz",
"integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==",
"license": "ISC",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/path-scurry/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
@ -11965,7 +12158,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"dependencies": {
"shebang-regex": "^3.0.0"
},
@ -11977,7 +12169,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -12116,6 +12307,12 @@
"node": ">=10"
}
},
"node_modules/simple-wcswidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-wcswidth/-/simple-wcswidth-1.0.1.tgz",
"integrity": "sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg==",
"license": "MIT"
},
"node_modules/sinon": {
"version": "15.2.0",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-15.2.0.tgz",
@ -12435,6 +12632,21 @@
"node": ">=8"
}
},
"node_modules/string-width-cjs": {
"name": "string-width",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@ -12446,6 +12658,19 @@
"node": ">=8"
}
},
"node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-bom": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
@ -13383,7 +13608,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"dependencies": {
"isexe": "^2.0.0"
},
@ -13525,6 +13749,24 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs": {
"name": "wrap-ansi",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@ -13638,6 +13880,18 @@
"dev": true,
"license": "ISC"
},
"node_modules/yaml": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz",
"integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
@ -14213,9 +14467,196 @@
"version": "1.0.0",
"license": "AGPL-3.0-only"
},
"tools/comment-parser": {
"version": "1.0.0",
"license": "AGPL-3.0-only",
"devDependencies": {
"chai": "^5.1.1"
}
},
"tools/comment-parser/node_modules/assertion-error": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
"integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
}
},
"tools/comment-parser/node_modules/chai": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz",
"integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==",
"dev": true,
"license": "MIT",
"dependencies": {
"assertion-error": "^2.0.1",
"check-error": "^2.1.1",
"deep-eql": "^5.0.1",
"loupe": "^3.1.0",
"pathval": "^2.0.0"
},
"engines": {
"node": ">=12"
}
},
"tools/comment-parser/node_modules/check-error": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
"integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 16"
}
},
"tools/comment-parser/node_modules/deep-eql": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
"integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"tools/comment-parser/node_modules/loupe": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz",
"integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==",
"dev": true,
"license": "MIT",
"dependencies": {
"get-func-name": "^2.0.1"
}
},
"tools/comment-parser/node_modules/pathval": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
"integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.16"
}
},
"tools/file-walker": {
"version": "1.0.0",
"license": "AGPL-3.0-only"
},
"tools/google-license": {
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"commander": "^12.1.0",
"glob": "^11.0.0",
"handlebars": "^4.7.8"
}
},
"tools/google-license/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"tools/google-license/node_modules/commander": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"tools/google-license/node_modules/foreground-child": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz",
"integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==",
"license": "ISC",
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"tools/google-license/node_modules/glob": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
"integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^4.0.1",
"minimatch": "^10.0.0",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"tools/google-license/node_modules/minimatch": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"tools/google-license/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"tools/google-license/node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"license": "ISC",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"tools/license-headers": {
"version": "1.0.0",
"license": "AGPL-3.0-only",
"dependencies": {
"console-table-printer": "^2.12.1",
"dedent": "^1.5.3",
"diff-match-patch": "^1.0.5",
"js-levenshtein": "^1.1.6",
"yaml": "^2.4.5"
}
}
}
}

View File

@ -0,0 +1,345 @@
const lib = {};
lib.dedent_lines = lines => {
// If any lines are just spaces, remove the spaces
for ( let i=0 ; i < lines.length ; i++ ) {
if ( /^\s+$/.test(lines[i]) ) lines[i] = '';
}
// Remove leading and trailing blanks
while ( lines[0] === '' ) lines.shift();
while ( lines[lines.length-1] === '' ) lines.pop();
let min_indent = Number.MAX_SAFE_INTEGER;
for ( let i=0 ; i < lines.length ; i++ ) {
if ( lines[i] === '' ) continue;
let n_spaces = 0;
for ( let j=0 ; j < lines[i].length ; j++ ) {
if ( lines[i][j] === ' ' ) n_spaces++;
else break;
}
if ( n_spaces < min_indent ) min_indent = n_spaces;
}
for ( let i=0 ; i < lines.length ; i++ ) {
if ( lines[i] === '' ) continue;
lines[i] = lines[i].slice(min_indent);
}
};
const StringStream = (str, { state_ } = {}) => {
const state = state_ ?? { pos: 0 };
return {
skip_whitespace () {
while ( /^\s/.test(str[state.pos]) ) state.pos++;
},
// INCOMPLETE: only handles single chars
skip_matching (items) {
while ( items.some(item => {
return str[state.pos] === item;
}) ) state.pos++;
},
fwd (amount) {
state.pos += amount ?? 1;
},
fork () {
return StringStream(str, { state_: { pos: state.pos } });
},
async get_pos () {
return state.pos;
},
async get_char () {
return str[state.pos];
},
async matches (re_or_lit) {
if ( re_or_lit instanceof RegExp ) {
const re = re_or_lit;
return re.test(str.slice(state.pos));
}
const lit = re_or_lit;
return lit === str.slice(state.pos, state.pos + lit.length);
},
async get_until (re_or_lit) {
let index;
if ( re_or_lit instanceof RegExp ) {
const re = re_or_lit;
const result = re.exec(str.slice(state.pos));
if ( ! result ) return;
index = state.pos + result.index;
} else {
const lit = re_or_lit;
const ind = str.slice(state.pos).indexOf(lit);
// TODO: parser warnings?
if ( ind === -1 ) return;
index = state.pos + ind;
}
const start_pos = state.pos;
state.pos = index;
return str.slice(start_pos, index);
},
async debug () {
const l1 = str.length;
const l2 = str.length - state.pos;
const clean = s => s.replace(/\n/, '{LF}');
return `[stream : "${
clean(str.slice(0, Math.min(6, l1)))
}"... |${state.pos}| ..."${
clean(str.slice(state.pos, state.pos + Math.min(6, l2)))
}"]`
}
};
};
const LinesCommentParser = ({
prefix
}) => {
return {
parse: async (stream) => {
stream.skip_whitespace();
const lines = [];
while ( await stream.matches(prefix) ) {
const line = await stream.get_until('\n');
if ( ! line ) return;
lines.push(line);
stream.fwd();
stream.skip_matching([' ', '\t']);
if ( await stream.get_char() === '\n' ){
stream.fwd();
break;
}
stream.skip_whitespace();
}
if ( lines.length === 0 ) return;
for ( let i=0 ; i < lines.length ; i++ ) {
lines[i] = lines[i].slice(prefix.length);
}
lib.dedent_lines(lines);
return {
lines,
};
}
};
};
const BlockCommentParser = ({
start,
end,
ignore_line_prefix,
}) => {
return {
parse: async (stream) => {
stream.skip_whitespace();
stream.debug('starting at', await stream.debug())
if ( ! stream.matches(start) ) return;
stream.fwd(start.length);
const contents = await stream.get_until(end);
if ( ! contents ) return;
stream.fwd(end.length);
// console.log('ending at', await stream.debug())
const lines = contents.split('\n');
// === Formatting Time! === //
// Special case: remove the last '*' after '/**'
if ( lines[0].trim() === ignore_line_prefix ) {
lines.shift();
}
// First dedent pass
lib.dedent_lines(lines);
// If all the lines start with asterisks, remove
let allofem = true;
for ( let i=0 ; i < lines.length ; i++ ) {
if ( lines[i] === '' ) continue;
if ( ! lines[i].startsWith(ignore_line_prefix) ) {
allofem = false;
break
}
}
if ( allofem ) {
for ( let i=0 ; i < lines.length ; i++ ) {
if ( lines[i] === '' ) continue;
lines[i] = lines[i].slice(ignore_line_prefix.length);
}
// Second dedent pass
lib.dedent_lines(lines);
}
return { lines };
}
};
};
const LinesCommentWriter = ({ prefix }) => {
return {
write: (lines) => {
lib.dedent_lines(lines);
for ( let i=0 ; i < lines.length ; i++ ) {
lines[i] = prefix + lines[i];
}
return lines.join('\n') + '\n';
}
};
};
const BlockCommentWriter = ({ start, end, prefix }) => {
return {
write: (lines) => {
lib.dedent_lines(lines);
for ( let i=0 ; i < lines.length ; i++ ) {
lines[i] = prefix + lines[i];
}
let s = start + '\n';
s += lines.join('\n') + '\n';
s += end + '\n';
return s;
}
};
};
const CommentParser = () => {
const registry_ = {
object: {
parsers: {
lines: LinesCommentParser,
block: BlockCommentParser,
},
writers: {
lines: LinesCommentWriter,
block: BlockCommentWriter,
},
},
data: {
extensions: {
js: 'javascript',
cjs: 'javascript',
mjs: 'javascript',
},
languages: {
javascript: {
parsers: [
['lines', {
prefix: '// ',
}],
['block', {
start: '/*',
end: '*/',
ignore_line_prefix: '*',
}],
],
writers: {
lines: ['lines', {
prefix: '//'
}],
block: ['block', {
start: '/*',
end: '*/',
prefix: ' * ',
}]
},
}
},
}
};
const get_language_by_filename = ({ filename }) => {
const { language } = (({ filename }) => {
const { language_id } = (({ filename }) => {
const { extension } = (({ filename }) => {
const components = ('' + filename).split('.');
const extension = components[components.length - 1];
return { extension };
})({ filename });
const language_id = registry_.data.extensions[extension];
if ( ! language_id ) {
throw new Error(`unrecognized language id: ` +
language_id);
}
return { language_id };
})({ filename });
const language = registry_.data.languages[language_id];
return { language };
})({ filename });
if ( ! language ) {
// TODO: use strutil quot here
throw new Error(`unrecognized language: ${language}`)
}
return { language };
}
const supports = ({ filename }) => {
try {
get_language_by_filename({ filename });
} catch (e) {
return false;
}
return true;
};
const extract_top_comments = async ({ filename, source }) => {
const { language } = get_language_by_filename({ filename });
// TODO: registry has `data` and `object`...
// ... maybe add `virt` (virtual), which will
// behave in the way the above code is written.
const inst_ = spec => registry_.object.parsers[spec[0]](spec[1]);
let ss = StringStream(source);
const results = [];
for (;;) {
let comment;
for ( let parser of language.parsers ) {
const parser_name = parser[0];
parser = inst_(parser);
const ss_ = ss.fork();
const start_pos = await ss_.get_pos();
comment = await parser.parse(ss_);
const end_pos = await ss_.get_pos();
if ( comment ) {
ss = ss_;
comment.type = parser_name;
comment.range = [start_pos, end_pos];
break;
}
}
if ( ! comment ) break;
results.push(comment);
}
return results;
}
const output_comment = ({ filename, style, text }) => {
const { language } = get_language_by_filename({ filename });
const inst_ = spec => registry_.object.writers[spec[0]](spec[1]);
let writer = language.writers[style];
writer = inst_(writer);
const lines = text.split('\n');
const s = writer.write(lines);
return s;
}
return {
supports,
extract_top_comments,
output_comment,
};
};
module.exports = {
StringStream,
LinesCommentParser,
BlockCommentParser,
CommentParser,
};

View File

@ -0,0 +1,15 @@
{
"name": "comment-parser",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "AGPL-3.0-only",
"description": "",
"devDependencies": {
"chai": "^5.1.1"
}
}

View File

@ -0,0 +1,127 @@
const {
StringStream,
LinesCommentParser,
BlockCommentParser,
CommentParser
} = require('../main');
const assert = async (label, fn) => {
if ( ! await fn() ) {
// TODO: strutil quot
throw new Error(`assert: '${label}' failed`)
}
};
describe('parsers', () => {
describe('lines-comment-parser', () => {
it ('basic test', async () => {
const parser = LinesCommentParser({ prefix: '//' });
let lines;
const ss = StringStream(`
// first line of first block
// second line of first block
// first line of second block
function () {}
`);
const results = [];
for (;;) {
comment = await parser.parse(ss);
if ( ! comment ) break;
results.push(comment.lines);
}
console.log('results?', results);
})
})
describe('block-comment-parser', () => {
it ('basic test', async () => {
const parser = BlockCommentParser({
start: '/*',
end: '*/',
ignore_line_prefix: '*',
});
let lines;
const ss = StringStream(`
/*
First block
comment
*/
/*
* second block
* comment
*/
/**
* third block
* comment
*/
function () {}
`);
const results = [];
for (;;) {
comment = await parser.parse(ss);
if ( ! comment ) break;
results.push(comment.lines);
}
console.log('results?', results);
})
it ('doesn\'t return anything for line comments', async () => {
const parser = BlockCommentParser({
start: '/*',
end: '*/',
ignore_line_prefix: '*',
});
let lines;
const ss = StringStream(`
// this comment should not be parsed
// by the block comment parser
function () {}
`);
const results = [];
for (;;) {
comment = await parser.parse(ss);
if ( ! comment ) break;
results.push(comment.lines);
}
console.log('results?', results);
})
})
describe('extract_top_comments', () => {
it ('basic test', async () => {
const parser = CommentParser();
const filename = 'test.js';
const source = `
// First lines comment
// second line of lines comment
/*
First block comment
second line of block comment
*/
`;
const results = await parser.extract_top_comments({
filename,
source,
});
console.log('results?', results);
})
})
describe('StringStream', () => {
describe('fork', () => {
it('works', async () => {
const ss = StringStream('asdf');
const ss_ = ss.fork();
ss_.fwd();
await assert('fwd worked', async () => {
return await ss_.get_char() === 's';
});
await assert('upstream state is same', async () => {
return await ss.get_char() === 'a';
});
})
})
})
});

View File

@ -20,6 +20,19 @@ const fs = require('fs');
const fsp = fs.promises;
const path_ = require('path');
const EXCLUDE_LISTS = {
NOT_SOURCE: [
/^\.git/,
/^volatile\//,
/^node_modules\//,
/\/node_modules$/,
/^node_modules$/,
/package-lock\.json/,
/src\/backend\/src\/public\/assets/,
/^src\/gui\/src\/lib/
]
};
const hl_readdir = async path => {
const names = await fs.promises.readdir(path);
const entries = [];
@ -130,15 +143,7 @@ const blame = async (path) => {
const walk_test = async () => {
// console.log(await hl_readdir('.'));
for await ( const value of walk({
excludes: [
/^\.git/,
/^volatile\//,
/^node_modules\//,
/\/node_modules$/,
/^node_modules$/,
/package-lock\.json/,
/^src\/gui\/dist/,
]
excludes: EXCLUDE_LISTS.NOT_SOURCE,
}, '.') ) {
if ( ! value.is_dir ) continue;
console.log('value', value.path);
@ -170,16 +175,7 @@ git blame parsing.
const walk_and_blame = async () => {
// console.log(await hl_readdir('.'));
for await ( const value of walk({
excludes: [
/^\.git/,
/^volatile\//,
/^node_modules\//,
/\/node_modules$/,
/^node_modules$/,
/package-lock\.json/,
/src\/backend\/src\/public\/assets/,
/^src\/gui\/src\/lib/
]
excludes: EXCLUDE_LISTS.NOT_SOURCE,
}, '.') ) {
if ( value.is_dir ) continue;
console.log('value', value.path);
@ -194,6 +190,12 @@ const walk_and_blame = async () => {
console.log('AUTHORS', authors);
}
const main = walk_and_blame;
if ( require.main === module ) {
const main = walk_and_blame;
main();
}
main();
module.exports = {
walk,
EXCLUDE_LISTS,
};

View File

@ -0,0 +1,356 @@
const levenshtein = require('js-levenshtein');
const DiffMatchPatch = require('diff-match-patch');
const dmp = new DiffMatchPatch();
const dedent = require('dedent');
const { walk, EXCLUDE_LISTS } = require('file-walker');
const { CommentParser } = require('../comment-parser/main');
const fs = require('fs');
const path_ = require('path');
const CompareFn = ({ header1, header2, distance_only = false }) => {
// Calculate Levenshtein distance
const distance = levenshtein(header1, header2);
// console.log(`Levenshtein distance: ${distance}`);
if ( distance_only ) return { distance };
// Generate diffs using diff-match-patch
const diffs = dmp.diff_main(header1, header2);
dmp.diff_cleanupSemantic(diffs);
let term_diff = '';
// Manually format diffs for terminal display
diffs.forEach(([type, text]) => {
switch (type) {
case DiffMatchPatch.DIFF_INSERT:
term_diff += `\x1b[32m${text}\x1b[0m`; // Green for insertions
break;
case DiffMatchPatch.DIFF_DELETE:
term_diff += `\x1b[31m${text}\x1b[0m`; // Red for deletions
break;
case DiffMatchPatch.DIFF_EQUAL:
term_diff += text; // No color for equal parts
break;
}
});
return {
distance,
term_diff,
};
}
const LicenseChecker = ({
comment_parser,
desired_header,
}) => {
const supports = ({ filename }) => {
return comment_parser.supports({ filename });
};
const compare = async ({ filename, source }) => {
const headers = await comment_parser.extract_top_comments(
{ filename, source });
const headers_lines = headers.map(h => h.lines);
if ( headers.length < 1 ) {
return {
has_header: false,
};
}
// console.log('headers', headers);
let top = 0;
let bottom = 0;
let current_distance = Number.MAX_SAFE_INTEGER;
// "wah"
for ( let i=1 ; i <= headers.length ; i++ ) {
const combined = headers_lines.slice(top, i).flat();
const combined_txt = combined.join('\n');
const { distance } =
CompareFn({
header1: desired_header,
header2: combined_txt,
distance_only: true,
});
if ( distance < current_distance ) {
current_distance = distance;
bottom = i;
} else {
break;
}
}
// "woop"
for ( let i=1 ; i < headers.length ; i++ ) {
const combined = headers_lines.slice(i, bottom).flat();
const combined_txt = combined.join('\n');
const { distance } =
CompareFn({
header1: desired_header,
header2: combined_txt,
distance_only: true,
});
if ( distance < current_distance ) {
current_distance = distance;
top = i;
} else {
break;
}
}
const combined = headers_lines.slice(top, bottom).flat();
const combined_txt = combined.join('\n');
const diff_info = CompareFn({
header1: desired_header,
header2: combined_txt,
})
diff_info.range = [
headers[top].range[0],
headers[bottom-1].range[1],
];
diff_info.has_header = true;
return diff_info;
};
return {
compare,
supports,
};
};
const license_check_test = async ({ options }) => {
const comment_parser = CommentParser();
const license_checker = LicenseChecker({
comment_parser,
desired_header: fs.readFileSync(
path_.join(__dirname, '../../doc/license_header.txt'),
'utf-8',
),
});
const walk_iterator = walk({
excludes: EXCLUDE_LISTS.NOT_SOURCE,
}, path_.join(__dirname, '../..'));
for await ( const value of walk_iterator ) {
if ( value.is_dir ) continue;
if ( value.name !== 'dev-console-ui-utils.js' ) continue;
console.log(value.path);
const source = fs.readFileSync(value.path, 'utf-8');
const diff_info = await license_checker.compare({
filename: value.name,
source,
})
if ( diff_info ) {
process.stdout.write('\x1B[36;1m=======\x1B[0m\n');
process.stdout.write(diff_info.term_diff);
process.stdout.write('\n\x1B[36;1m=======\x1B[0m\n');
// console.log('headers', headers);
} else {
console.log('NO COMMENT');
}
console.log('RANGE', diff_info.range)
const new_comment = comment_parser.output_comment({
filename: value.name,
style: 'block',
text: 'some text\nto display'
});
console.log('NEW COMMENT?', new_comment);
}
};
const cmd_check_fn = async () => {
const comment_parser = CommentParser();
const license_checker = LicenseChecker({
comment_parser,
desired_header: fs.readFileSync(
path_.join(__dirname, '../../doc/license_header.txt'),
'utf-8',
),
});
const counts = {
ok: 0,
missing: 0,
conflict: 0,
error: 0,
unsupported: 0,
};
const walk_iterator = walk({
excludes: EXCLUDE_LISTS.NOT_SOURCE,
}, path_.join(__dirname, '../..'));
for await ( const value of walk_iterator ) {
if ( value.is_dir ) continue;
process.stdout.write(value.path + ' ... ');
if ( ! license_checker.supports({ filename: value.name }) ) {
process.stdout.write(`\x1B[37;1mUNSUPPORTED\x1B[0m\n`);
counts.unsupported++;
continue;
}
const source = fs.readFileSync(value.path, 'utf-8');
const diff_info = await license_checker.compare({
filename: value.name,
source,
})
if ( ! diff_info ) {
counts.error++;
continue;
}
if ( ! diff_info.has_header ) {
counts.missing++;
process.stdout.write(`\x1B[33;1mMISSING\x1B[0m\n`);
continue;
}
if ( diff_info ) {
if ( diff_info.distance !== 0 ) {
counts.conflict++;
process.stdout.write(`\x1B[31;1mCONFLICT\x1B[0m\n`);
} else {
counts.ok++;
process.stdout.write(`\x1B[32;1mOK\x1B[0m\n`);
}
} else {
console.log('NO COMMENT');
}
}
const { Table } = require('console-table-printer');
const t = new Table({
columns: [
{
title: 'License Header',
name: 'situation', alignment: 'left', color: 'white_bold' },
{
title: 'Number of Files',
name: 'count', alignment: 'right' },
],
colorMap: {
green: '\x1B[32;1m',
yellow: '\x1B[33;1m',
red: '\x1B[31;1m',
}
});
console.log('');
if ( counts.error > 0 ) {
console.log(`\x1B[31;1mTHERE WERE SOME ERRORS!\x1B[0m`);
console.log('check the log above for the stack trace');
console.log('');
t.addRow({ situation: 'error', count: counts.error },
{ color: 'red' });
}
console.log(dedent(`
\x1B[31;1mAny text below is mostly lies!\x1B[0m
This tool is still being developed and most of what's
described is "the plan" rather than a thing that will
actually happen.
\x1B[31;1m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\x1B[0m
`));
if ( counts.conflict ) {
console.log(dedent(`
\x1B[37;1mIt looks like you have some conflicts!\x1B[0m
Run the following command to update license headers:
\x1B[36;1maddlicense sync\x1B[0m
This will begin an interactive license update.
Any time the license doesn't quite match you will
be given the option to replace it or skip the file.
\x1B[90mSee \`addlicense help sync\` for other options.\x1B[0m
You will also be able to choose
"remember for headers matching this one"
if you know the same issue will come up later.
`));
} else if ( counts.missing ) {
console.log(dedent(`
\x1B[37;1mSome missing license headers!\x1B[0m
Run the following command to add the missing license headers:
\x1B[36;1maddlicense sync\x1B[0m
`));
} else {
console.log(dedent(`
\x1B[37;1mNo action to perform!\x1B[0m
Run the following command to do absolutely nothing:
\x1B[36;1maddlicense sync\x1B[0m
`));
}
console.log('');
t.addRow({ situation: 'ok', count: counts.ok },
{ color: 'green' });
t.addRow({ situation: 'missing', count: counts.missing },
{ color: 'yellow' });
t.addRow({ situation: 'conflict', count: counts.conflict },
{ color: 'red' });
t.addRow({ situation: 'unsupported', count: counts.unsupported });
t.printTable();
};
const main = async () => {
const { program } = require('commander');
const helptext = dedent(`
Usage: usage text
`);
const run_command = async ({ cmd, cmd_fn }) => {
const options = {
program: program.opts(),
command: cmd.opts(),
};
console.log('options', options);
if ( ! fs.existsSync(options.program.config) ) {
// TODO: configuration wizard
fs.writeFileSync(options.program.config, '');
}
await cmd_fn({ options });
};
program
.name('addlicense')
.option('-c, --config', 'configuration file', 'addlicense.yml')
.addHelpText('before', helptext)
;
const cmd_check = program.command('check')
.description('check license headers')
.option('-n, --non-interactive', 'disable prompting')
.action(() => {
run_command({ cmd: cmd_check, cmd_fn: cmd_check_fn });
})
const cmd_sync = program.command('sync')
.description('synchronize files with license header rules')
.option('-n, --non-interactive', 'disable prompting')
.action(() => {
console.log('called sync');
console.log(program.opts());
console.log(cmd_sync.opts());
})
program.parse(process.argv);
};
if ( require.main === module ) {
main();
}

View File

@ -0,0 +1,19 @@
{
"name": "license-headers",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "AGPL-3.0-only",
"description": "",
"dependencies": {
"console-table-printer": "^2.12.1",
"dedent": "^1.5.3",
"diff-match-patch": "^1.0.5",
"js-levenshtein": "^1.1.6",
"yaml": "^2.4.5"
}
}