mirror of
https://github.com/HeyPuter/puter
synced 2024-11-14 14:03:42 +00:00
dev(tools): add license header adder thingy
This commit is contained in:
parent
c76af1ab21
commit
67139ef91b
1
addlicense.yml
Normal file
1
addlicense.yml
Normal file
@ -0,0 +1 @@
|
||||
header: doc/license_header.txt
|
455
package-lock.json
generated
455
package-lock.json
generated
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
345
tools/comment-parser/main.js
Normal file
345
tools/comment-parser/main.js
Normal 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,
|
||||
};
|
15
tools/comment-parser/package.json
Normal file
15
tools/comment-parser/package.json
Normal 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"
|
||||
}
|
||||
}
|
127
tools/comment-parser/test/test.js
Normal file
127
tools/comment-parser/test/test.js
Normal 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';
|
||||
});
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
@ -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,
|
||||
};
|
||||
|
356
tools/license-headers/main.js
Normal file
356
tools/license-headers/main.js
Normal 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();
|
||||
}
|
19
tools/license-headers/package.json
Normal file
19
tools/license-headers/package.json
Normal 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"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user