From 9bf721c574dfddafc946a67b76d5ccd31dc2fba8 Mon Sep 17 00:00:00 2001 From: Gary Moore Date: Mon, 17 Oct 2022 02:38:11 +0100 Subject: [PATCH] feat: working timer implementation with events --- .editorconfig | 11 + jest.config.cjs | 2 +- package.json | 9 +- pnpm-lock.yaml | 329 ++++++++++++++++++ rollup.config.js | 106 +++--- schema.json | 8 +- src/Component.svelte | 15 +- src/lib/Timer.svelte | 105 ++++++ src/lib/components/TimerInput.svelte | 74 ++++ .../utils/__tests__/splitInput.test.ts | 22 ++ src/lib/components/utils/chunk.ts | 48 +++ src/lib/components/utils/splitInput.ts | 15 + src/lib/types/Time.ts | 7 + .../utils/__tests__/longTimeToSecs.test.ts | 29 ++ .../utils/__tests__/secsToLongTime.test.ts | 20 ++ src/lib/utils/longTimeToSecs.ts | 7 + src/lib/utils/secsToLongTime.ts | 11 + tsconfig.json | 6 + 18 files changed, 768 insertions(+), 56 deletions(-) create mode 100644 .editorconfig create mode 100644 src/lib/Timer.svelte create mode 100644 src/lib/components/TimerInput.svelte create mode 100644 src/lib/components/utils/__tests__/splitInput.test.ts create mode 100644 src/lib/components/utils/chunk.ts create mode 100644 src/lib/components/utils/splitInput.ts create mode 100644 src/lib/types/Time.ts create mode 100644 src/lib/utils/__tests__/longTimeToSecs.test.ts create mode 100644 src/lib/utils/__tests__/secsToLongTime.test.ts create mode 100644 src/lib/utils/longTimeToSecs.ts create mode 100644 src/lib/utils/secsToLongTime.ts create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4f217a9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +[*] +end_of_line = lf +insert_final_newline = true + +[*.{js,ts,jsx,tsx,svelte}] +indent_style = space +indent_size = 2 + +[package.json] +indent_style = space +indent_size = 2 diff --git a/jest.config.cjs b/jest.config.cjs index 421302d..d59c8a7 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -4,7 +4,7 @@ module.exports = { coverageDirectory: 'coverage', coverageProvider: 'v8', testEnvironment: 'jsdom', - moduleFileExtensions: ['js', 'svelte'], + moduleFileExtensions: ['js', 'ts', 'svelte'], transform: { '^.+\\.(t|j)sx?$': ['@swc/jest'], '^.+\\.svelte$': 'svelte-jester', diff --git a/package.json b/package.json index a60c470..f3fe63e 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,13 @@ "devDependencies": { "@rollup/plugin-commonjs": "^18.0.0", "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-typescript": "^8.5.0", "@swc/core": "^1.3.4", "@swc/jest": "^0.2.23", "@testing-library/jest-dom": "^5.16.5", "@testing-library/svelte": "^3.2.1", + "@tsconfig/svelte": "^3.0.0", + "@types/jest": "^29.1.2", "jest": "^29.1.2", "jest-environment-jsdom": "^29.1.2", "npm-run-all": "^4.1.5", @@ -35,7 +38,11 @@ "rollup-plugin-svelte": "^7.1.0", "rollup-plugin-svg": "^2.0.0", "rollup-plugin-terser": "^7.0.2", + "svelte-check": "^2.9.1", "svelte-jester": "^2.3.2", - "tar": "^6.1.11" + "svelte-preprocess": "^4.10.7", + "tar": "^6.1.11", + "tslib": "^2.4.0", + "typescript": "^4.8.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8de853c..07b71e0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,10 +4,13 @@ specifiers: '@crownframework/svelte-error-boundary': ^1.0.3 '@rollup/plugin-commonjs': ^18.0.0 '@rollup/plugin-node-resolve': ^11.2.1 + '@rollup/plugin-typescript': ^8.5.0 '@swc/core': ^1.3.4 '@swc/jest': ^0.2.23 '@testing-library/jest-dom': ^5.16.5 '@testing-library/svelte': ^3.2.1 + '@tsconfig/svelte': ^3.0.0 + '@types/jest': ^29.1.2 jest: ^29.1.2 jest-environment-jsdom: ^29.1.2 npm-run-all: ^4.1.5 @@ -23,8 +26,12 @@ specifiers: rollup-plugin-svg: ^2.0.0 rollup-plugin-terser: ^7.0.2 svelte: ^3.49.0 + svelte-check: ^2.9.1 svelte-jester: ^2.3.2 + svelte-preprocess: ^4.10.7 tar: ^6.1.11 + tslib: ^2.4.0 + typescript: ^4.8.4 dependencies: '@crownframework/svelte-error-boundary': 1.0.3 @@ -33,10 +40,13 @@ dependencies: devDependencies: '@rollup/plugin-commonjs': 18.1.0_rollup@2.79.1 '@rollup/plugin-node-resolve': 11.2.1_rollup@2.79.1 + '@rollup/plugin-typescript': 8.5.0_hafrwlgfjmvsm7253l3bfjzhnq '@swc/core': 1.3.6 '@swc/jest': 0.2.23_@swc+core@1.3.6 '@testing-library/jest-dom': 5.16.5 '@testing-library/svelte': 3.2.2_svelte@3.50.1 + '@tsconfig/svelte': 3.0.0 + '@types/jest': 29.1.2 jest: 29.1.2 jest-environment-jsdom: 29.1.2 npm-run-all: 4.1.5 @@ -51,8 +61,12 @@ devDependencies: rollup-plugin-svelte: 7.1.0_3j3zasnyq6cqs3hqscflv4du7a rollup-plugin-svg: 2.0.0 rollup-plugin-terser: 7.0.2_rollup@2.79.1 + svelte-check: 2.9.1_r763xggw3my2ousygwguxmp6ru svelte-jester: 2.3.2_jest@29.1.2+svelte@3.50.1 + svelte-preprocess: 4.10.7_3qrjncjggkfjiva57qa6ctvjlq tar: 6.1.11 + tslib: 2.4.0 + typescript: 4.8.4 packages: @@ -703,6 +717,27 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: true + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk/1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.13.0 + dev: true + /@rollup/plugin-commonjs/18.1.0_rollup@2.79.1: resolution: {integrity: sha512-h3e6T9rUxVMAQswpDIobfUHn/doMzM9sgkMrsMWCFLmB84PSoC8mV8tOloAJjSRwdqhXBqstlX2BwBpHJvbhxg==} engines: {node: '>= 8.0.0'} @@ -745,6 +780,24 @@ packages: rollup: 2.79.1 dev: true + /@rollup/plugin-typescript/8.5.0_hafrwlgfjmvsm7253l3bfjzhnq: + resolution: {integrity: sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ==} + engines: {node: '>=8.0.0'} + peerDependencies: + rollup: ^2.14.0 + tslib: '*' + typescript: '>=3.7.0' + peerDependenciesMeta: + tslib: + optional: true + dependencies: + '@rollup/pluginutils': 3.1.0_rollup@2.79.1 + resolve: 1.22.1 + rollup: 2.79.1 + tslib: 2.4.0 + typescript: 4.8.4 + dev: true + /@rollup/pluginutils/3.1.0_rollup@2.79.1: resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} engines: {node: '>= 8.0.0'} @@ -995,6 +1048,10 @@ packages: engines: {node: '>=10.13.0'} dev: true + /@tsconfig/svelte/3.0.0: + resolution: {integrity: sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==} + dev: true + /@types/aria-query/4.2.2: resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==} dev: true @@ -1081,12 +1138,22 @@ packages: resolution: {integrity: sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==} dev: true + /@types/pug/2.0.6: + resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==} + dev: true + /@types/resolve/1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: '@types/node': 18.8.3 dev: true + /@types/sass/1.43.1: + resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} + dependencies: + '@types/node': 18.8.3 + dev: true + /@types/stack-utils/2.0.1: resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} dev: true @@ -1278,6 +1345,11 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true + /binary-extensions/2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + /boolbase/1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true @@ -1313,6 +1385,10 @@ packages: node-int64: 0.4.0 dev: true + /buffer-crc32/0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + dev: true + /buffer-from/1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true @@ -1387,6 +1463,21 @@ packages: engines: {node: '>=10'} dev: true + /chokidar/3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.2 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + /chownr/2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} @@ -1673,6 +1764,11 @@ packages: engines: {node: '>=0.4.0'} dev: true + /detect-indent/6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: true + /detect-newline/3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -1788,6 +1884,10 @@ packages: is-symbol: 1.0.4 dev: true + /es6-promise/3.3.1: + resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + dev: true + /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -1883,6 +1983,17 @@ packages: jest-util: 29.1.2 dev: true + /fast-glob/3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + /fast-json-stable-stringify/2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: true @@ -1891,6 +2002,12 @@ packages: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true + /fastq/1.13.0: + resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + dependencies: + reusify: 1.0.4 + dev: true + /fb-watchman/2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} dependencies: @@ -2000,6 +2117,13 @@ packages: get-intrinsic: 1.1.3 dev: true + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + /glob/7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: @@ -2127,6 +2251,14 @@ packages: import-from: 3.0.0 dev: true + /import-fresh/3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + /import-from/3.0.0: resolution: {integrity: sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==} engines: {node: '>=8'} @@ -2183,6 +2315,13 @@ packages: has-bigints: 1.0.2 dev: true + /is-binary-path/2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + /is-boolean-object/1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} @@ -2209,6 +2348,11 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-extglob/2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + /is-fullwidth-code-point/3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -2219,6 +2363,13 @@ packages: engines: {node: '>=6'} dev: true + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + /is-module/1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} dev: true @@ -3000,6 +3151,11 @@ packages: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + /micromatch/4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} @@ -3036,6 +3192,10 @@ packages: brace-expansion: 1.1.11 dev: true + /minimist/1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + dev: true + /minipass/3.3.4: resolution: {integrity: sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==} engines: {node: '>=8'} @@ -3051,12 +3211,24 @@ packages: yallist: 4.0.0 dev: true + /mkdirp/0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.6 + dev: true + /mkdirp/1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} hasBin: true dev: true + /mri/1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: true + /ms/2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true @@ -3225,6 +3397,13 @@ packages: engines: {node: '>=6'} dev: true + /parent-module/1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + /parse-json/4.0.0: resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} engines: {node: '>=4'} @@ -3759,6 +3938,10 @@ packages: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} dev: true + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + /randombytes/2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -3782,6 +3965,13 @@ packages: path-type: 3.0.0 dev: true + /readdirp/3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + /redent/3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -3823,6 +4013,11 @@ packages: resolve-from: 5.0.0 dev: true + /resolve-from/4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + /resolve-from/5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} @@ -3842,6 +4037,18 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf/2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + /rollup-plugin-copy2/0.3.1_rollup@2.79.1: resolution: {integrity: sha512-v7Gakvj4HIFAFR4AMpyFg5ofuqZaV0Y9lAC9BNntCI7OZ1+N4cPmH/ZdepnPyrT3bsCycKhgnJKeRYMxHypU7w==} peerDependencies: @@ -3943,6 +4150,19 @@ packages: fsevents: 2.3.2 dev: true + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /sade/1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + dependencies: + mri: 1.2.0 + dev: true + /safe-buffer/5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} dev: true @@ -3967,6 +4187,15 @@ packages: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: true + /sander/0.5.1: + resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} + dependencies: + es6-promise: 3.3.1 + graceful-fs: 4.2.10 + mkdirp: 0.5.6 + rimraf: 2.7.1 + dev: true + /saxes/6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -4047,6 +4276,16 @@ packages: engines: {node: '>=8'} dev: true + /sorcery/0.10.0: + resolution: {integrity: sha512-R5ocFmKZQFfSTstfOtHjJuAwbpGyf9qjQa1egyhvXSbM7emjrtLXtGdZsDJDABC85YBfVvrOiGWKSYXPKdvP1g==} + hasBin: true + dependencies: + buffer-crc32: 0.2.13 + minimist: 1.2.6 + sander: 0.5.1 + sourcemap-codec: 1.4.8 + dev: true + /source-map-js/1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} @@ -4242,6 +4481,34 @@ packages: engines: {node: '>= 0.4'} dev: true + /svelte-check/2.9.1_r763xggw3my2ousygwguxmp6ru: + resolution: {integrity: sha512-+BFPsj6irZ+t2pVSVo//2Ic1mI3A52xCwbkSTVhTqYZqgawcyZd9pYZoEac3fIWbEeTyCb5X82ORKI/gjn+P7A==} + hasBin: true + peerDependencies: + svelte: ^3.24.0 + dependencies: + '@jridgewell/trace-mapping': 0.3.16 + chokidar: 3.5.3 + fast-glob: 3.2.12 + import-fresh: 3.3.0 + picocolors: 1.0.0 + sade: 1.8.1 + svelte: 3.50.1 + svelte-preprocess: 4.10.7_3qrjncjggkfjiva57qa6ctvjlq + typescript: 4.8.4 + transitivePeerDependencies: + - '@babel/core' + - coffeescript + - less + - node-sass + - postcss + - postcss-load-config + - pug + - sass + - stylus + - sugarss + dev: true + /svelte-jester/2.3.2_jest@29.1.2+svelte@3.50.1: resolution: {integrity: sha512-JtxSz4FWAaCRBXbPsh4LcDs4Ua7zdXgLC0TZvT1R56hRV0dymmNP+abw67DTPF7sQPyNxWsOKd0Sl7Q8SnP8kg==} engines: {node: '>=14'} @@ -4253,6 +4520,58 @@ packages: svelte: 3.50.1 dev: true + /svelte-preprocess/4.10.7_3qrjncjggkfjiva57qa6ctvjlq: + resolution: {integrity: sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==} + engines: {node: '>= 9.11.2'} + requiresBuild: true + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 || ^4.0.0 + node-sass: '*' + postcss: ^7 || ^8 + postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 + pug: ^3.0.0 + sass: ^1.26.8 + stylus: ^0.55.0 + sugarss: ^2.0.0 + svelte: ^3.23.0 + typescript: ^3.9.5 || ^4.0.0 + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + node-sass: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + dependencies: + '@types/pug': 2.0.6 + '@types/sass': 1.43.1 + detect-indent: 6.1.0 + magic-string: 0.25.9 + postcss: 8.4.17 + sorcery: 0.10.0 + strip-indent: 3.0.0 + svelte: 3.50.1 + typescript: 4.8.4 + dev: true + /svelte/3.50.1: resolution: {integrity: sha512-bS4odcsdj5D5jEg6riZuMg5NKelzPtmsCbD9RG+8umU03TeNkdWnP6pqbCm0s8UQNBkqk29w/Bdubn3C+HWSwA==} engines: {node: '>= 8'} @@ -4348,6 +4667,10 @@ packages: punycode: 2.1.1 dev: true + /tslib/2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + dev: true + /type-check/0.3.2: resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} engines: {node: '>= 0.8.0'} @@ -4365,6 +4688,12 @@ packages: engines: {node: '>=10'} dev: true + /typescript/4.8.4: + resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + /unbox-primitive/1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: diff --git a/rollup.config.js b/rollup.config.js index 35401a6..530b513 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,113 +1,117 @@ -import commonjs from "@rollup/plugin-commonjs" -import resolve from "@rollup/plugin-node-resolve" -import svelte from "rollup-plugin-svelte" -import { terser } from "rollup-plugin-terser" -import postcss from "rollup-plugin-postcss" -import svg from "rollup-plugin-svg" -import json from "rollup-plugin-json" -import nodePolyfills from "rollup-plugin-polyfill-node" -import copy from "rollup-plugin-copy2" -import tar from "tar" -import fs from "fs" -import pkg from "./package.json" -import crypto from "crypto" +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import svelte from 'rollup-plugin-svelte'; +import { terser } from 'rollup-plugin-terser'; +import postcss from 'rollup-plugin-postcss'; +import svg from 'rollup-plugin-svg'; +import json from 'rollup-plugin-json'; +import nodePolyfills from 'rollup-plugin-polyfill-node'; +import copy from 'rollup-plugin-copy2'; +import tar from 'tar'; +import fs from 'fs'; +import pkg from './package.json'; +import crypto from 'crypto'; +import autoPreprocess from 'svelte-preprocess'; +import typescript from '@rollup/plugin-typescript'; const ignoredWarnings = [ - "unused-export-let", - "css-unused-selector", - "module-script-reactive-declaration", - "a11y-no-onchange", -] + 'unused-export-let', + 'css-unused-selector', + 'module-script-reactive-declaration', + 'a11y-no-onchange', +]; // Custom plugin to clean the dist folder before building const clean = () => ({ buildStart() { - const dist = "./dist/" + const dist = './dist/'; if (fs.existsSync(dist)) { fs.readdirSync(dist).forEach(path => { - if (path.endsWith(".tar.gz")) { - fs.unlinkSync(dist + path) + if (path.endsWith('.tar.gz')) { + fs.unlinkSync(dist + path); } - }) + }); } }, -}) +}); // Custom plugin to hash the JS bundle and write it in the schema const hash = () => ({ writeBundle() { // Generate JS hash - const fileBuffer = fs.readFileSync("dist/plugin.min.js") - const hashSum = crypto.createHash("sha1") - hashSum.update(fileBuffer) - const hex = hashSum.digest("hex") + const fileBuffer = fs.readFileSync('dist/plugin.min.js'); + const hashSum = crypto.createHash('sha1'); + hashSum.update(fileBuffer); + const hex = hashSum.digest('hex'); // Read and parse existing schema from dist folder - const schema = JSON.parse(fs.readFileSync("./dist/schema.json", "utf8")) + const schema = JSON.parse(fs.readFileSync('./dist/schema.json', 'utf8')); // Write updated schema to dist folder, pretty printed as JSON again const newSchema = { ...schema, hash: hex, version: pkg.version, - } - fs.writeFileSync("./dist/schema.json", JSON.stringify(newSchema, null, 2)) + }; + fs.writeFileSync('./dist/schema.json', JSON.stringify(newSchema, null, 2)); }, -}) +}); // Custom plugin to bundle up our files after building const bundle = () => ({ async writeBundle() { - const bundleName = `${pkg.name}-${pkg.version}.tar.gz` + const bundleName = `${pkg.name}-${pkg.version}.tar.gz`; return tar - .c({ gzip: true, cwd: "dist" }, [ - "plugin.min.js", - "schema.json", - "package.json", - ]) - .pipe(fs.createWriteStream(`dist/${bundleName}`)) + .c({ gzip: true, cwd: 'dist' }, [ + 'plugin.min.js', + 'schema.json', + 'package.json', + ]) + .pipe(fs.createWriteStream(`dist/${bundleName}`)); }, -}) +}); export default { - input: "index.js", + input: 'index.js', output: { - sourcemap: process.env.ROLLUP_WATCH ? "inline" : false, - format: "iife", - file: "dist/plugin.min.js", - name: "plugin", + sourcemap: process.env.ROLLUP_WATCH ? 'inline' : false, + format: 'iife', + file: 'dist/plugin.min.js', + name: 'plugin', globals: { - svelte: "svelte", - "svelte/internal": "svelte_internal", + svelte: 'svelte', + 'svelte/internal': 'svelte_internal', }, }, - external: ["svelte", "svelte/internal"], + external: ['svelte', 'svelte/internal'], plugins: [ clean(), svelte({ + preprocess: autoPreprocess(), emitCss: true, onwarn: (warning, handler) => { // Ignore some warnings if (!ignoredWarnings.includes(warning.code)) { - handler(warning) + handler(warning); } }, }), + typescript(), postcss(), commonjs(), nodePolyfills(), resolve({ preferBuiltins: true, browser: true, - skip: ["svelte", "svelte/internal"], + skip: ['svelte', 'svelte/internal'], }), svg(), json(), terser(), copy({ - assets: ["schema.json", "package.json"], + assets: ['schema.json', 'package.json'], }), hash(), bundle(), ], -} +}; diff --git a/schema.json b/schema.json index a01d7f4..4fffe96 100644 --- a/schema.json +++ b/schema.json @@ -6,6 +6,12 @@ "friendlyName": "bb-timer", "description": "A kinda cool timer thing", "icon": "Text", - "settings": [] + "settings": [ + { + "type": "event", + "key": "timeout", + "label": "On Timeout" + } + ] } } diff --git a/src/Component.svelte b/src/Component.svelte index 3e9bea7..9a622fc 100644 --- a/src/Component.svelte +++ b/src/Component.svelte @@ -1,10 +1,21 @@ -
-

Not implemented

+
+ + diff --git a/src/lib/Timer.svelte b/src/lib/Timer.svelte new file mode 100644 index 0000000..b4de947 --- /dev/null +++ b/src/lib/Timer.svelte @@ -0,0 +1,105 @@ + + +
+
+ +
+ +
+ + +
+
+ + diff --git a/src/lib/components/TimerInput.svelte b/src/lib/components/TimerInput.svelte new file mode 100644 index 0000000..ee68243 --- /dev/null +++ b/src/lib/components/TimerInput.svelte @@ -0,0 +1,74 @@ + + +
+
+
{time.hour}
+
h
+
+ +
+
{time.minute}
+
m
+
+ +
+
{time.second}
+
s
+
+
+ + diff --git a/src/lib/components/utils/__tests__/splitInput.test.ts b/src/lib/components/utils/__tests__/splitInput.test.ts new file mode 100644 index 0000000..908a65c --- /dev/null +++ b/src/lib/components/utils/__tests__/splitInput.test.ts @@ -0,0 +1,22 @@ +import splitInput from '../splitInput'; +import type {Time} from "../../../types/Time"; + +interface TestData { + text: string; + expected: Time; +} + +describe.each` + text | expected + ${'12'} | ${{ hour: '0', minute: '0', second: '12' }} + ${'123'} | ${{ hour: '0', minute: '1', second: '23' }} + ${'1232'} | ${{ hour: '0', minute: '12', second: '32' }} + ${'12323'} | ${{ hour: '1', minute: '23', second: '23' }} + ${'123456'} | ${{ hour: '12', minute: '34', second: '56' }} + ${'999999'} | ${{ hour: '99', minute: '99', second: '99' }} + ${'12321232'} | ${{ hour: '32', minute: '12', second: '32' }} +`('splitInput($text)', ({ text, expected }: TestData) => { + it(`should equal hour: ${expected.hour}, minute: ${expected.minute}, second: ${expected.second}`, () => { + expect(splitInput(text)).toEqual(expected); + }); +}); diff --git a/src/lib/components/utils/chunk.ts b/src/lib/components/utils/chunk.ts new file mode 100644 index 0000000..f2b1de0 --- /dev/null +++ b/src/lib/components/utils/chunk.ts @@ -0,0 +1,48 @@ +// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. +// This module is browser compatible. + +/** + * Splits the given array into chunks of the given size and returns them + * + * Example: + * + * ```ts + * import { chunk } from "https://deno.land/std@$STD_VERSION/collections/chunk.ts"; + * import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; + * + * const words = [ 'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consetetur', 'sadipscing' ] + * const chunks = chunk(words, 3) + * + * assertEquals(chunks, [ + * [ 'lorem', 'ipsum', 'dolor' ], + * [ 'sit', 'amet', 'consetetur' ], + * [ 'sadipscing' ], + * ]) + * ``` + */ +function chunk(array: readonly T[], size: number): T[][] { + if (size <= 0 || !Number.isInteger(size)) { + throw new Error( + `Expected size to be an integer greater than 0 but found ${size}`, + ); + } + + if (array.length === 0) { + return []; + } + + const ret = Array.from({ length: Math.ceil(array.length / size) }); + let readIndex = 0; + let writeIndex = 0; + + while (readIndex < array.length) { + ret[writeIndex] = array.slice(readIndex, readIndex + size); + + writeIndex += 1; + readIndex += size; + } + + return ret; +} + +export default chunk; diff --git a/src/lib/components/utils/splitInput.ts b/src/lib/components/utils/splitInput.ts new file mode 100644 index 0000000..39d0ccb --- /dev/null +++ b/src/lib/components/utils/splitInput.ts @@ -0,0 +1,15 @@ +import chunk from './chunk'; +import type { Time } from '../../types/Time'; + +const splitInput = (text: string): Time => { + const [second, minute, hour] = chunk([...text].reverse(), 2).map(charArray => + charArray.reverse().join('') + ); + return { + hour: hour ?? '0', + minute: minute ?? '0', + second: second ?? '0', + }; +}; + +export default splitInput; diff --git a/src/lib/types/Time.ts b/src/lib/types/Time.ts new file mode 100644 index 0000000..12c52ef --- /dev/null +++ b/src/lib/types/Time.ts @@ -0,0 +1,7 @@ +interface Time { + hour: string; + minute: string; + second: string; +} + +export type { Time }; diff --git a/src/lib/utils/__tests__/longTimeToSecs.test.ts b/src/lib/utils/__tests__/longTimeToSecs.test.ts new file mode 100644 index 0000000..5b38706 --- /dev/null +++ b/src/lib/utils/__tests__/longTimeToSecs.test.ts @@ -0,0 +1,29 @@ +import longTimeToSecs from '../longTimeToSecs'; + +interface TestData { + hrs: number; + mins: number; + secs: number; + expected: number; +} + +describe.each` + hrs | mins | secs | expected + ${0} | ${0} | ${0} | ${0} + ${0} | ${0} | ${1} | ${1} + ${0} | ${1} | ${0} | ${60} + ${1} | ${0} | ${0} | ${3600} + ${1} | ${1} | ${0} | ${3660} + ${1} | ${1} | ${1} | ${3661} + ${12} | ${3} | ${14} | ${43_394} + ${1} | ${132} | ${49} | ${11_569} + ${0} | ${420} | ${69} | ${25_269} + ${123} | ${123} | ${123} | ${450_303} +`( + 'longTimeToSecs($hrs, $mins, $secs)', + ({ hrs, mins, secs, expected }: TestData) => { + it(`should equal ${expected}`, () => { + expect(longTimeToSecs(hrs, mins, secs)).toEqual(expected); + }); + } +); diff --git a/src/lib/utils/__tests__/secsToLongTime.test.ts b/src/lib/utils/__tests__/secsToLongTime.test.ts new file mode 100644 index 0000000..945f919 --- /dev/null +++ b/src/lib/utils/__tests__/secsToLongTime.test.ts @@ -0,0 +1,20 @@ +import secsToLongTime from '../secsToLongTime'; + +interface TestData { + secs: number; + expected: string; +} + +describe.each` + secs | expected + ${123212} | ${{ hour: '34', minute: '13', second: '32' }} + ${321} | ${{ hour: '0', minute: '5', second: '21' }} + ${12} | ${{ hour: '0', minute: '0', second: '12' }} + ${1232} | ${{ hour: '0', minute: '20', second: '32' }} + ${0} | ${{ hour: '0', minute: '0', second: '0' }} + ${999999} | ${{ hour: '277', minute: '46', second: '39' }} +`('secsToLongTime($secs)', ({ secs, expected }: TestData) => { + it(`should equal ${expected}`, () => { + expect(secsToLongTime(secs)).toEqual(expected); + }); +}); diff --git a/src/lib/utils/longTimeToSecs.ts b/src/lib/utils/longTimeToSecs.ts new file mode 100644 index 0000000..048063b --- /dev/null +++ b/src/lib/utils/longTimeToSecs.ts @@ -0,0 +1,7 @@ +const longTimeToSecs = ( + hours: number, + minutes: number, + seconds: number +): number => (hours ?? 0) * 60 * 60 + (minutes ?? 0) * 60 + (seconds ?? 0); + +export default longTimeToSecs; diff --git a/src/lib/utils/secsToLongTime.ts b/src/lib/utils/secsToLongTime.ts new file mode 100644 index 0000000..576a36b --- /dev/null +++ b/src/lib/utils/secsToLongTime.ts @@ -0,0 +1,11 @@ +import type { Time } from '../types/Time'; + +function secsToLongTime(secs: number): Time { + return { + hour: Math.floor(secs / 3600).toString(10), + minute: Math.floor((secs % 3600) / 60).toString(10), + second: Math.floor((secs % 3600) % 60).toString(10), + }; +} + +export default secsToLongTime; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a0d607a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + + "include": ["src/**/*", "src/node_modules"], + "exclude": ["node_modules/*", "__sapper__/*", "public/*"], +}