From 29cfd177787695357e8f6fd9f32a6e5c46739b25 Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 4 Mar 2024 21:34:17 +0100 Subject: [PATCH] Create lint exemptions --- apps/{.eslintrc.json => .eslintrc.js} | 15 +- apps/lint_exemptions.js | 578 ++++++++++++++++++++++++++ bin/exempt-lint.mjs | 66 +++ bin/sync-lint-exemptions.mjs | 46 ++ package.json | 4 +- 5 files changed, 705 insertions(+), 4 deletions(-) rename apps/{.eslintrc.json => .eslintrc.js} (93%) create mode 100644 apps/lint_exemptions.js create mode 100755 bin/exempt-lint.mjs create mode 100755 bin/sync-lint-exemptions.mjs diff --git a/apps/.eslintrc.json b/apps/.eslintrc.js similarity index 93% rename from apps/.eslintrc.json rename to apps/.eslintrc.js index bda2025f6..31aa7bfe2 100644 --- a/apps/.eslintrc.json +++ b/apps/.eslintrc.js @@ -1,9 +1,14 @@ -{ +const lintExemptions = require("./lint_exemptions.js"); + +module.exports = { "env": { // TODO: "espruino": false // TODO: "banglejs": false }, "extends": "eslint:recommended", + "plugins": [ + + ], "globals": { // Methods and Fields at https://banglejs.com/reference "Array": "readonly", @@ -157,5 +162,11 @@ "no-unused-vars": ["warn", { "args": "none" } ], "no-useless-escape": "off", "no-control-regex" : "off" - } + }, + overrides: [ + ...Object.entries(lintExemptions).map(([filePath, {rules}]) => ({ + files: [filePath], + rules: Object.fromEntries(rules.map(rule => [rule, "off"])), + })), + ], } diff --git a/apps/lint_exemptions.js b/apps/lint_exemptions.js new file mode 100644 index 000000000..24531d576 --- /dev/null +++ b/apps/lint_exemptions.js @@ -0,0 +1,578 @@ +module.exports = { + "xxlmessage/app.js": { + "hash": "14a9ea1fbcf0e1053df1a77d7ee7acd543f1ed63e26ecf220468c3813f93de4f", + "rules": [ + "no-unused-vars" + ] + }, + "waternet/app.js": { + "hash": "a03fbfc731811f8cc9ea8c96781ff7fe46532c5f9e628b317892069e43b97012", + "rules": [ + "no-unused-vars" + ] + }, + "tabata/tabata.js": { + "hash": "bba68fd35b57afe00adb054d598d8bde74cf2c9cb1d1d7ae27c17e13899383ee", + "rules": [ + "no-unused-vars" + ] + }, + "speedalt2/GPS Adv Sports II.js": { + "hash": "1b0dff5c4ebe0c8042dec9456f809ebaada379357188b8a18dc17a144ee8c071", + "rules": [ + "no-unused-vars" + ] + }, + "timerclk/alarm.alert.js": { + "hash": "2d422f738c044dcf0d6a43712c672dccc0ad4f2d0a877ee11f0a96ec3d939714", + "rules": [ + "no-unused-vars" + ] + }, + "spacew/prep/split.js": { + "hash": "06f25475a3765417e42dc7638ee500b546d3ce75ac28b39b8b836c0aee2ea2cb", + "rules": [ + "no-unused-vars" + ] + }, + "spacew/bench.js": { + "hash": "428a741d8dfba625cb1d2958dab3b6c7b0ca05f582b00e06ec9f7f495658beb6", + "rules": [ + "no-unused-vars" + ] + }, + "spacew/app.js": { + "hash": "6467f44962655f10a649226a2ea180a3662308146d2f19d15903a16ae081d282", + "rules": [ + "no-unused-vars" + ] + }, + "smclock/app.js": { + "hash": "8f338b03c24738793d62b7a2c4d0c2b41ab0538394adc6f3d977776b68ee3287", + "rules": [ + "no-unused-vars" + ] + }, + "sleepphasealarm/app.js": { + "hash": "d234fea5d711ae5a149879e53b28bc9002860c6b6a75285e1fc04093fe400a88", + "rules": [ + "no-unused-vars" + ] + }, + "sleeplog/settings.js": { + "hash": "bd5e3e1382321df6682ef1cb718b0e15ab355422bef77278eb086f213f643021", + "rules": [ + "no-unused-vars" + ] + }, + "showimg/app.js": { + "hash": "98975f1cdec81d982d1ee8ca23e38f6851c12c2ccf57c4503c449d20f747e9cf", + "rules": [ + "no-unused-vars" + ] + }, + "sensible/sensible.js": { + "hash": "4b8b4417c352d7a86f39653c812356c36e56770e44051d645c522f986e98abfe", + "rules": [ + "no-unused-vars" + ] + }, + "rpnsci/app.js": { + "hash": "e5bf536babe9b30e7f40b03826d7052aec98f806a7ab3b80b10438e9bf2cc61b", + "rules": [ + "no-unused-vars" + ] + }, + "recorder/app.js": { + "hash": "64c838b63a756a712555ae54d0bae89f0373ce317c289f7b19a583d3f91d473b", + "rules": [ + "no-unused-vars" + ] + }, + "podadrem/app.js": { + "hash": "8d02fced6187142b7943c63ddefd874700d0a8731d49121de06d211959db58c4", + "rules": [ + "no-unused-vars" + ] + }, + "openstmap/imagefilter.js": { + "hash": "8a71e9a0ecfa94150379c41a5a915cfdac39f8b2e485e5cc1ce4629e85293acd", + "rules": [ + "no-unused-vars" + ] + }, + "mtnclock/app.js": { + "hash": "c48e3ed1a605e6a131e5947718e26cc9481c6eeab36c5670bb74f0c58cb96cd8", + "rules": [ + "no-unused-vars" + ] + }, + "mmonday/manic-monday.js": { + "hash": "2eff38d4d1cde2b9f17800a554da58300a6250de3e014995a6958a11bcb5b76a", + "rules": [ + "no-unused-vars" + ] + }, + "mixdiganclock/mixdiganclock.app.js": { + "hash": "97beda5daa3b6e60f27dcad1230dd49a9c3b3e81cf55d644496c797fbef1256f", + "rules": [ + "no-unused-vars" + ] + }, + "locale/locales.js": { + "hash": "c89110fccb76824508aab0ed8374eb06843a9173262fd3a93cf3a67b098ee5a3", + "rules": [ + "no-unused-vars" + ] + }, + "legoremote/app.js": { + "hash": "af12068cd1b84369aa8416a82e9335298f6a4b69b56aa7bc70b9eb0d91e6d78e", + "rules": [ + "no-unused-vars" + ] + }, + "lightswitch/settings.js": { + "hash": "340a664f7f82fbffcb108bfceded78dbbe162717d4e4dda0f08452ca79fa3881", + "rules": [ + "no-unused-vars" + ] + }, + "kbtouch/lib.js": { + "hash": "725b41b792a0f9879257e61cc5c2ba30df777c21137bd2d2e324ab83be7b8012", + "rules": [ + "no-unused-vars" + ] + }, + "jbm8b_IT/app.js": { + "hash": "52df7b9bcac876176d66cbb65f7015cb0b5933ba585a6e3f6b93766bbe19fb11", + "rules": [ + "no-unused-vars" + ] + }, + "jbm8b/app.js": { + "hash": "7ec45c7d21590f8fa9167f4953fa6da40190d0f287f436dac7a2c4b62d82d429", + "rules": [ + "no-unused-vars" + ] + }, + "wristlight/app.js": { + "hash": "422b63acf557ac81beb0f0d08d85a8988a004752e74b50a08e23c97293351d0b", + "rules": [ + "no-unused-vars" + ] + }, + "widhrm/widget.js": { + "hash": "9c5fd63130c579a015f5600862ec1a5032387a41e058950c739c9875bc81c6bf", + "rules": [ + "no-unused-vars" + ] + }, + "waypoints/waypoints.app.js": { + "hash": "ff02639eb8f81784c942093d57d254295e2c78918adb4bcffdf0d0284ebfac55", + "rules": [ + "no-unused-vars" + ] + }, + "timerclk/timer.js": { + "hash": "f44702e61ad833b53fb28d222ff0fbd77d0307c6eb69c5ecebb8626a1cb20ed4", + "rules": [ + "no-unused-vars" + ] + }, + "timerclk/stopwatch.js": { + "hash": "92838c03923e162c0e9ab4f37ca0220a1fee61ed16cba1d38c79d7bdd0e18765", + "rules": [ + "no-unused-vars" + ] + }, + "timerclk/alarm.js": { + "hash": "6f521742cc6a6d6f215e499084a596ffc3494d1e1f950b204368c051a18773de", + "rules": [ + "no-unused-vars" + ] + }, + "speedalt2/app.js": { + "hash": "8cf396b8c2b3a449635274d537ac12dda88a829fd32336e6c2c0cd85e7f56b2d", + "rules": [ + "no-unused-vars" + ] + }, + "skyspy/skyspy.app.js": { + "hash": "49a727a4c052e8c6322a502750ca036b0d58896f476b1cffebe9c53e426c8bcc", + "rules": [ + "no-unused-vars" + ] + }, + "sixths/sixths.app.js": { + "hash": "b4572a529b31a5edcbd6ca5843b91c54abcbf75b2a28e90bd33751f7d6a3ebcd", + "rules": [ + "no-unused-vars" + ] + }, + "scribble/app.js": { + "hash": "6d13abd27bab8009a6bdabe1df2df394bc14aac20c68f67e8f8b085fa6b427cd", + "rules": [ + "no-unused-vars" + ] + }, + "promenu/boot.js": { + "hash": "8b0ed99c61c877348365d9ec50f904744f4694c5e2c0a93200e998955034ed0f", + "rules": [ + "no-unused-vars" + ] + }, + "promenu/bootb2.js": { + "hash": "558ab22819c2bc83ebf97c960c4fa494fccccbc894f1582f28972dbf8f563170", + "rules": [ + "no-unused-vars" + ] + }, + "poweroff/settings.js": { + "hash": "c197afe72c612a4b3825a3a12a628d0f4ed83823da3f28885bbf473037a02506", + "rules": [ + "no-unused-vars" + ] + }, + "oxofocus/app.js": { + "hash": "cd29309373974ef038725e26d8a2ff2634a437c89cdffc3b12defd65a948db75", + "rules": [ + "no-unused-vars" + ] + }, + "orloj/app.js": { + "hash": "9240830a097ba545fdbdb06305817234e30238bf2fbb8fbb47af83897cd588a9", + "rules": [ + "no-unused-vars" + ] + }, + "nixie/m_vatch.js": { + "hash": "36a7fa956f99d5815cd6bac570d2b86833d1d37474d7eef0bb21892bdf6723a8", + "rules": [ + "no-unused-vars" + ] + }, + "moonphase/app.js": { + "hash": "0e78c9ec9e7ab04f22f1838fcf033691024c8734de23f8d8dd51d6f11c30a2f2", + "rules": [ + "no-unused-vars" + ] + }, + "lcars/lcars.app.js": { + "hash": "a305f73ee4e77b6534746ea79e699f700fd3db305f2b0289ef081d8869e1faf1", + "rules": [ + "no-unused-vars" + ] + }, + "widagps/widget.js": { + "hash": "a58cdc481962575ef0aa0bfaedcc1f9de3ce966218c5b16168d8ed8b4b9672b8", + "rules": [ + "no-unused-vars" + ] + }, + "sleeplog/lib.js": { + "hash": "5210446eb507f62897782735e7d56a2e84ea5f9dba557ef67a977f53065f3461", + "rules": [ + "no-unused-vars" + ] + }, + "sleeplog/app.js": { + "hash": "336da552e4b04677447cf76a253b40bc259a597ea11d455121933f93afe99794", + "rules": [ + "no-unused-vars" + ] + }, + "recorder/widget.js": { + "hash": "b48698bab90fc4f38f880b6663eda108b8d31ce929ba1d32d815aa4ec8c74bca", + "rules": [ + "no-unused-vars" + ] + }, + "qmsched/app.js": { + "hash": "4b7dbabed6c252021531d6b0449c16a3adc2e405f2ddda33ca0a65f5fa42c663", + "rules": [ + "no-unused-vars" + ] + }, + "runplus/app.js": { + "hash": "fabec449552d17ceb5d510aa058e420757f3caba11999efbe6ebf2ac1a81eb32", + "rules": [ + "no-unused-vars" + ] + }, + "powermanager/boot.js": { + "hash": "662d9d29a80a4f2c2855097b4073a099604f4f6d444c13a33304346c788cc5cb", + "rules": [ + "no-unused-vars" + ] + }, + "ohmcalc/app.js": { + "hash": "ac1ac172c9c4f9c4faf9bc2ce8ad7dd51ecd9a5c38f28a107d39f0c86a836899", + "rules": [ + "no-unused-vars" + ] + }, + "nightwatch/nightwatch.app.js": { + "hash": "9366528bc5bb229cd08e68000a4deebaa27036a18ac5215dce7c38ffa9d69b31", + "rules": [ + "no-unused-vars" + ] + }, + "messagelist/app.js": { + "hash": "a76b5cc3ddcdbd60a9979972f274a717a901ea65e108545b13d415740a71b4e0", + "rules": [ + "no-unused-vars" + ] + }, + "imageclock/app.js": { + "hash": "198ad2d18b41ba30e3ee2545372c84ba443cec7d6f9ce4e9ca494defc9476a8e", + "rules": [ + "no-unused-vars" + ] + }, + "hworldclock/app.js": { + "hash": "e4c34cc76e242541156006952a2cf05427feb0fbe70ae55a1afb9bd0e1d5fae1", + "rules": [ + "no-unused-vars" + ] + }, + "homework/app.js": { + "hash": "f367470e50c9105ee1f48c3193c605293338c35bd1ae1488467404270a20747c", + "rules": [ + "no-unused-vars" + ] + }, + "hidmsicswipe/hidmsicswipe.js": { + "hash": "8c8c2058315c6debaec71b65b1409ebf5725233c72dbcc2ac921bec0d238fd4f", + "rules": [ + "no-unused-vars" + ] + }, + "hidcam/app.js": { + "hash": "29a9e8add8daa19ec5c12bf6b372fe4e59c2b07be30e305e9d75dac55995dffd", + "rules": [ + "no-unused-vars" + ] + }, + "gpstrek/app.js": { + "hash": "9c941a29790dd642579478bf4b19a2afd5473a782d07fafd2c8113b2d7392bec", + "rules": [ + "no-unused-vars" + ] + }, + "gpstouch/gpstouch.app.js": { + "hash": "3492b202c866d6d619298456a48dd8501c4b34f5cce84698e92c62acaf3b8ce4", + "rules": [ + "no-unused-vars" + ] + }, + "gpspoilog/app.js": { + "hash": "38c72e56a4929102f5748ed5e5415a63a31bfd3bf6d853527a10d71a268bc294", + "rules": [ + "no-unused-vars" + ] + }, + "gpsrec/app.js": { + "hash": "4d842608edea63975c7da9db6be2746af8849ea2dcc9135fc7d77e5806701f60", + "rules": [ + "no-unused-vars" + ] + }, + "golfview/maptools.js": { + "hash": "2c3bdb849dce1710863693f2370f7fb32070a7c3bec915d8d2ef8106fda937d8", + "rules": [ + "no-unused-vars" + ] + }, + "golfview/golfview.js": { + "hash": "76d8a7743122a63bd82c8e95c234229261829b465a4bc998cdc9e45860ec7fc4", + "rules": [ + "no-unused-vars" + ] + }, + "golfscore/app.js": { + "hash": "2df86a3f159b72229011f6276ef023c764837b39552b852f1caa431450a06f3a", + "rules": [ + "no-unused-vars" + ] + }, + "geissclk/clock.js": { + "hash": "2e547f904f17995668e351a9031bc4701ddaff71cba4f88ca28d51a4dd4f6154", + "rules": [ + "no-unused-vars" + ] + }, + "gbmusic/app.js": { + "hash": "c36e9ccf6813264000732cf8aae5b16bb63afafb3bdc81f6f98d670c008b3416", + "rules": [ + "no-unused-vars" + ] + }, + "gbdebug/app.js": { + "hash": "5372409dd09a1b165b009afc7dc9af24d4be223ffc6507a3f6e1cbb694a3eeec", + "rules": [ + "no-unused-vars" + ] + }, + "gallery/app.js": { + "hash": "81b119cc61c9d1ae76071f7ef05580f4f93ac60bf97fbdfe418463817e045402", + "rules": [ + "no-unused-vars" + ] + }, + "football/app.js": { + "hash": "a24c293073557c259cffbf4f1340b6c9111832b7230b3e36072f32335ce4047b", + "rules": [ + "no-unused-vars" + ] + }, + "fd6fdetect/app.js": { + "hash": "5fb67c4e3699ed30815b6e316ce669f1b8479aa312bf4d8348e30cdf0a29409f", + "rules": [ + "no-unused-vars" + ] + }, + "dotmatrixclock/app.js": { + "hash": "ad51c66072f5dd799826e1b3b69c6febb6ab93c93b2eb2245b4035c36b496063", + "rules": [ + "no-unused-vars" + ] + }, + "dragboard/lib.js": { + "hash": "e3cbf03054134e9b8e570f02ea5cf0d3e784c8f47d68c85eaa2c5b005291b668", + "rules": [ + "no-unused-vars" + ] + }, + "doztime/app-bangle2.js": { + "hash": "81592fe1bc6537f80d7dbe7b2e8145924d2400f98ea780c68dd5bd9694376c8a", + "rules": [ + "no-unused-vars" + ] + }, + "doztime/app-bangle1.js": { + "hash": "ba263e0ff80cb0ab1df9fe19e62a4972bb8646ea709af8bc41206e9a6395d539", + "rules": [ + "no-unused-vars" + ] + }, + "devstopwatch/app.js": { + "hash": "bb75693cc6ed2ffef0d227a40b53079e06d1ebcc7c2d9eed671b5401a8e06433", + "rules": [ + "no-unused-vars" + ] + }, + "coretemp/settings.js": { + "hash": "b5aa84ecab587b444028b4491b2c2e8f3b2303aa33745265ab629c6ff5141cfb", + "rules": [ + "no-unused-vars" + ] + }, + "coretemp/boot.js": { + "hash": "02ee3a04d7dc485367394a91e570affd712ab919bbb155bdafc00e534d3bcd4a", + "rules": [ + "no-unused-vars" + ] + }, + "configurable_clock/app.js": { + "hash": "09d1d02b63abc4ecea5e00a7372de7150ccfe67c2502ff5d298ec7b8e29c353b", + "rules": [ + "no-unused-vars" + ] + }, + "chronowid/widget.js": { + "hash": "1056a77f508708a6667e7ae3d201add1d747a1ea4eeab2b3b8afce24a97f1e65", + "rules": [ + "no-unused-vars" + ] + }, + "cliclockJS2Enhanced/app.js": { + "hash": "056b4eeddbabbcf0f94db83d188e55dc0008bccb3913af76e31236e74a780aa1", + "rules": [ + "no-unused-vars" + ] + }, + "chrono/chrono.js": { + "hash": "62a4fe13d32528af5107e8008197510115134d749851f8ecfe062c7190b4fc5e", + "rules": [ + "no-unused-vars" + ] + }, + "chess/engine.js": { + "hash": "5ab335ed76f39b69e5b3436325229d8b3bd2c20a5da6d32bcb7c194f79c9f89c", + "rules": [ + "no-unused-vars" + ] + }, + "carcrazy/app.js": { + "hash": "82b9b291ad6e2efcb689e5bb7f48a5ba1a3b59f740a5ab4634006f3d413cee7e", + "rules": [ + "no-unused-vars" + ] + }, + "animclk/create_images.js": { + "hash": "05a222b265effe46b2c7a9cc0822c6c4cd86335d5d3a0cecce5fdd15d5e09b9f", + "rules": [ + "no-unused-vars" + ] + }, + "calculator/app.js": { + "hash": "fcb7c7b6c4ec5ce0f425d2a690baab8da235a12e685fe2680cbd4cf2cfdef0b0", + "rules": [ + "no-unused-vars" + ] + }, + "bthrm/bthrm.js": { + "hash": "0ad6b3150200efa959096d239a136865fc0ee1df0c50ebaae76693c07df7a02e", + "rules": [ + "no-unused-vars" + ] + }, + "bowserWF/app.js": { + "hash": "ec1e9fabf53e16dc91b19d305616ae0dfd879c32c3b1116da97928ebb8d2eb56", + "rules": [ + "no-unused-vars" + ] + }, + "blackjack/blackjack.app.js": { + "hash": "392382463c90b11b31818e974c3198ed4ec4ed681c9668b4a39865ab055d68ad", + "rules": [ + "no-unused-vars" + ] + }, + "blackjack/appb2.js": { + "hash": "d2e866a297811dfec4cba834c996e1e085421820673a038a9a9e9d438e4fabf9", + "rules": [ + "no-unused-vars" + ] + }, + "astral/app.js": { + "hash": "a210269f0d57eb496a3b75cfc4550676f9d7e85a697c77e18f41bf02549179e3", + "rules": [ + "no-unused-vars" + ] + }, + "ballmaze/app.js": { + "hash": "cd493a329063e879f44ead211cbecb4ca25da2d5c40b65ba05d6e9b2b91ff8a5", + "rules": [ + "no-unused-vars" + ] + }, + "astrocalc/astrocalc-app.js": { + "hash": "00e29864b2bfeec7f11bd8509181b26f7916c25dd4a777abfe1fbd555822983d", + "rules": [ + "no-unused-vars" + ] + }, + "a_dndtoggle/a_dndtoggle.app.js": { + "hash": "8ba115261df8ddb14bf7d16a300a114a1e59ace4da478657968390b62ba53cbb", + "rules": [ + "no-unused-vars" + ] + }, + "HRV/app.js": { + "hash": "265b4b0272c43126670b5026079711354cee0a211096bcd2c18139b7a3ee774a", + "rules": [ + "no-unused-vars" + ] + } +}; diff --git a/bin/exempt-lint.mjs b/bin/exempt-lint.mjs new file mode 100755 index 000000000..f2ca64fc8 --- /dev/null +++ b/bin/exempt-lint.mjs @@ -0,0 +1,66 @@ +#!/usr/bin/env node + +/** + * @file + * You can use this script to exempt an app file from a specific eslint rule. + * + * This should only be used to exempt existing apps when a new lint rule is added. + * You are not allowed to exempt your new app from existing lint rules. + * + * Run it like this: + * node bin/exempt-lint.mjs LINTRULE FILEPATH + * + * Example command: + * node bin/exempt-lint.mjs no-unused-vars ./apps/_example_app/app.js + */ + +import fs from "node:fs/promises"; + +const lintRule = process.argv[2]; +if(!lintRule){ + throw new Error("First argument needs to be a lint rule, something like 'no-unused-vars'"); +} + +const filePathInput = process.argv[3]; +const filePathMatch = filePathInput?.match(/^(?:.*?\/apps\/|apps\/|\/)?(?.*\.js)$/ui); +const filePath = filePathMatch?.groups?.path; +if(!filePath){ + throw new Error("Second argument needs to be a file path that looks something like './apps/_example_app/app.js'"); +} + + +const exemptionsFilePath = "../apps/lint_exemptions.js"; + +const exemptions = (await import(exemptionsFilePath)).default; + +const fileContents = await fs.readFile("apps/" + filePath, "utf8"); + + +const exemption = exemptions[filePath] || {}; +exemption.hash = await hashContents(fileContents); +const rules = new Set(exemption.rules || []); +rules.add(lintRule); +exemption.rules = [...rules]; +exemptions[filePath] = exemption; + + + +const output = `module.exports = ${JSON.stringify(exemptions, undefined, 2)};\n`; +await fs.writeFile("bin/" + exemptionsFilePath, output); + +console.log(`✔️ '${filePath}' is now exempt from the rule '${lintRule}'`); + + + +/** + * https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string + */ +async function hashContents(message) { + const msgUint8 = new TextEncoder().encode(message); // encode as (utf-8) Uint8Array + const hashBuffer = await crypto.subtle.digest("SHA-256", msgUint8); // hash the message + const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array + const hashHex = hashArray + .map((b) => b.toString(16).padStart(2, "0")) + .join(""); // convert bytes to hex string + return hashHex; +} diff --git a/bin/sync-lint-exemptions.mjs b/bin/sync-lint-exemptions.mjs new file mode 100755 index 000000000..ee024ac84 --- /dev/null +++ b/bin/sync-lint-exemptions.mjs @@ -0,0 +1,46 @@ +#!/usr/bin/env node + +/** + * @file + * Run this to ensure that the lint exemptions are all valid. + * If any of the exempt app files have been changed, this script will remove the exemption for that file. + * + * Run it like this: + * node bin/sync-lint-exemptions.mjs + */ + +import fs from "node:fs/promises"; + +const exemptionsFilePath = "../apps/lint_exemptions.js"; + +const exemptions = (await import(exemptionsFilePath)).default; + +for(const filePath of Object.keys(exemptions)){ + const fileContents = await fs.readFile("apps/" + filePath, "utf8"); + const currentHash = await hashContents(fileContents); + if(exemptions[filePath].hash !== currentHash){ + delete exemptions[filePath]; + console.log(`! Removed lint exemptions for '${filePath}' because it has been edited`); + } +} + + +const output = `module.exports = ${JSON.stringify(exemptions, undefined, 2)};\n`; +await fs.writeFile("bin/" + exemptionsFilePath, output); + +console.log(`✔️ Synchronized all lint exemptions\n`); + + + +/** + * https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string + */ +async function hashContents(message) { + const msgUint8 = new TextEncoder().encode(message); // encode as (utf-8) Uint8Array + const hashBuffer = await crypto.subtle.digest("SHA-256", msgUint8); // hash the message + const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array + const hashHex = hashArray + .map((b) => b.toString(16).padStart(2, "0")) + .join(""); // convert bytes to hex string + return hashHex; +} diff --git a/package.json b/package.json index 36734e920..3689750a6 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ "npm-watch": "^0.11.0" }, "scripts": { - "lint-apps": "eslint ./apps --ext .js", - "test": "node bin/sanitycheck.js && eslint ./apps --ext .js && eslint ./modules --ext .js", + "lint-apps": "node bin/sync-lint-exemptions.mjs && eslint ./apps --ext .js", + "test": "node bin/sanitycheck.js && npm run lint-apps && eslint ./modules --ext .js", "update-local-apps": "./bin/create_apps_json.sh apps.local.json", "local": "npm-watch & npx http-server -a localhost -c-1", "start": "npx http-server -c-1"