From fd73020e56803363ee0d6f192d827ca3f5ef370b Mon Sep 17 00:00:00 2001 From: Cosmin Popovici Date: Mon, 15 Jul 2024 21:08:49 +0300 Subject: [PATCH] fix: git conflicts --- .editorconfig | 18 +- .github/dependabot.yml | 1 - .github/workflows/nodejs.yml | 8 +- CHANGELOG.md | 730 ++ bin/maizzle | 4 +- biome.json | 8 +- package-lock.json | 10686 ++++++---------- package.json | 118 +- src/commands/build.js | 263 +- src/commands/serve.js | 199 +- src/functions/plaintext.js | 5 - src/functions/render.js | 5 - src/generators/config.js | 52 - src/generators/output/index.js | 4 - src/generators/output/to-disk.js | 254 - src/generators/output/to-string.js | 73 - src/generators/plaintext.js | 283 +- src/generators/postcss.js | 23 - src/generators/posthtml/index.js | 75 - src/generators/render.js | 128 + src/generators/tailwindcss.js | 157 - src/index.js | 58 +- .../posthtml/defaultComponentsConfig.js | 10 +- .../posthtml/defaultConfig.js | 2 +- src/posthtml/index.js | 74 + src/posthtml/plugins/expandLinkTag.js | 36 + src/server/client.js | 181 + src/server/index.js | 383 + src/server/routes/hmr.js | 24 + src/server/routes/index.js | 38 + src/server/views/error.html | 83 + src/server/views/index.html | 24 + src/server/websockets.js | 27 + src/transformers/addAttributes.js | 30 + src/transformers/attributeToStyle.js | 66 +- src/transformers/baseUrl.js | 83 +- src/transformers/comb.js | 51 + src/transformers/core.js | 20 + src/transformers/extraAttributes.js | 33 - src/transformers/filters/defaultFilters.js | 161 +- src/transformers/filters/index.js | 92 +- src/transformers/index.js | 331 +- src/transformers/inline.js | 240 + src/transformers/inlineCss.js | 42 - src/transformers/markdown.js | 27 +- src/transformers/minify.js | 37 +- src/transformers/posthtmlMso.js | 21 +- src/transformers/prettify.js | 31 +- src/transformers/preventWidows.js | 60 +- src/transformers/removeAttributes.js | 38 +- .../removeInlineBackgroundColor.js | 57 - src/transformers/removeInlineSizes.js | 45 - src/transformers/removeInlinedSelectors.js | 100 - src/transformers/removeUnusedCss.js | 48 - src/transformers/replaceStrings.js | 39 +- src/transformers/safeClassNames.js | 48 +- src/transformers/shorthandCss.js | 22 + src/transformers/shorthandInlineCSS.js | 26 - src/transformers/sixHex.js | 34 +- src/transformers/urlParameters.js | 34 +- src/transformers/useAttributeSizes.js | 65 + src/utils/getConfigByFilePath.js | 124 + src/utils/helpers.js | 13 - src/utils/node.js | 68 + src/utils/string.js | 117 + test/build.test.js | 224 + test/config.test.js | 39 + .../expected/{transformers => }/base-url.html | 0 test/expected/build/beforeCreate.html | 1 + .../components/backwards-compatibility.html | 6 - test/expected/components/kitchen-sink.html | 73 - test/expected/{transformers => }/filters.html | 10 + test/expected/transformers/prettify.html | 23 - .../fixtures/{transformers => }/base-url.html | 0 test/fixtures/basic.html | 9 - test/fixtures/build/beforeCreate.html | 1 + test/fixtures/build/expandLinkTag.html | 4 + .../empty.html => fixtures/build/image.png} | 0 .../components/backwards-compatibility.html | 19 - test/fixtures/components/kitchen-sink.html | 124 - test/fixtures/{transformers => }/filters.html | 10 + test/fixtures/transformers/prettify.html | 31 - test/plaintext.test.js | 132 + test/posthtml.test.js | 14 + test/render.test.js | 71 + test/server.test.js | 74 + test/stubs/assets/foo.bar | 1 - test/stubs/assets2/foo1.bar | 1 - test/stubs/assets2/foo2.bar | 1 - test/stubs/breaking/bad.html | 5 - test/stubs/components/bare.html | 8 - test/stubs/components/component.html | 12 - test/stubs/components/text.html | 6 - test/stubs/config/config.js | 11 +- test/stubs/config/config.maizzle-ci.js | 10 - test/stubs/config/maizzle.config.local.js | 3 + .../stubs/config/maizzle.config.maizzle-ci.js | 3 + test/stubs/config/maizzle.config.test.js | 11 - test/stubs/data.json | 14 - test/stubs/events/before-create.html | 1 - test/stubs/layouts/layout.html | 13 - test/stubs/layouts/legacy.html | 1 - test/stubs/layouts/template-legacy.html | 5 - test/stubs/main.css | 5 - test/stubs/plaintext/front-matter.html | 9 - test/stubs/plaintext/plaintext.html | 5 - test/stubs/post.css | 6 - test/stubs/static/plain.txt | 1 + test/stubs/style.css | 3 + test/stubs/tailwind/add-important.html | 6 - test/stubs/tailwind/content-source.html | 1 - test/stubs/tailwind/tailwind.css | 3 - test/stubs/template-legacy.html | 10 - test/stubs/templates/1.html | 1 - test/stubs/templates/2.html | 1 - test/stubs/templates/2.test | 1 - test/stubs/templates/nested/3.html | 1 - test/test-config.js | 24 - test/test-misc.js | 8 - test/test-postcss.js | 8 - test/test-posthtml.js | 126 - test/test-serve.js | 57 - test/test-tailwindcss.js | 206 - test/test-todisk.js | 660 - test/test-tostring.js | 165 - test/test-transformers.js | 664 - test/transformers.test.js | 573 + test/utils.test.js | 125 + test/websockets.test.js | 38 + tsconfig.json | 22 - types/baseUrl.d.ts | 79 - types/build.d.ts | 174 +- types/components.d.ts | 242 +- types/config.d.ts | 696 +- types/css/inline.d.ts | 234 + types/css/purge.d.ts | 125 + types/events.d.ts | 110 +- types/fetch.d.ts | 143 - types/index.d.ts | 264 +- types/inlineCss.d.ts | 207 - types/layouts.d.ts | 39 - types/markdown.d.ts | 38 +- types/minify.d.ts | 242 +- types/plaintext.d.ts | 98 +- types/posthtml.d.ts | 239 +- types/removeUnusedCss.d.ts | 115 - types/render.d.ts | 117 - types/tailwind.d.ts | 22 - types/templates.d.ts | 181 - types/urlParameters.d.ts | 41 +- types/widowWords.d.ts | 16 +- vite.config.js | 8 + 152 files changed, 10178 insertions(+), 13189 deletions(-) create mode 100644 CHANGELOG.md delete mode 100644 src/functions/plaintext.js delete mode 100644 src/functions/render.js delete mode 100644 src/generators/config.js delete mode 100644 src/generators/output/index.js delete mode 100644 src/generators/output/to-disk.js delete mode 100644 src/generators/output/to-string.js delete mode 100644 src/generators/postcss.js delete mode 100644 src/generators/posthtml/index.js create mode 100644 src/generators/render.js delete mode 100644 src/generators/tailwindcss.js rename src/{generators => }/posthtml/defaultComponentsConfig.js (50%) rename src/{generators => }/posthtml/defaultConfig.js (77%) create mode 100644 src/posthtml/index.js create mode 100644 src/posthtml/plugins/expandLinkTag.js create mode 100644 src/server/client.js create mode 100644 src/server/index.js create mode 100644 src/server/routes/hmr.js create mode 100644 src/server/routes/index.js create mode 100644 src/server/views/error.html create mode 100644 src/server/views/index.html create mode 100644 src/server/websockets.js create mode 100644 src/transformers/addAttributes.js create mode 100644 src/transformers/comb.js create mode 100644 src/transformers/core.js delete mode 100644 src/transformers/extraAttributes.js create mode 100644 src/transformers/inline.js delete mode 100644 src/transformers/inlineCss.js delete mode 100644 src/transformers/removeInlineBackgroundColor.js delete mode 100644 src/transformers/removeInlineSizes.js delete mode 100644 src/transformers/removeInlinedSelectors.js delete mode 100644 src/transformers/removeUnusedCss.js create mode 100644 src/transformers/shorthandCss.js delete mode 100644 src/transformers/shorthandInlineCSS.js create mode 100644 src/transformers/useAttributeSizes.js create mode 100644 src/utils/getConfigByFilePath.js delete mode 100644 src/utils/helpers.js create mode 100644 src/utils/node.js create mode 100644 src/utils/string.js create mode 100644 test/build.test.js create mode 100644 test/config.test.js rename test/expected/{transformers => }/base-url.html (100%) create mode 100644 test/expected/build/beforeCreate.html delete mode 100644 test/expected/components/backwards-compatibility.html delete mode 100644 test/expected/components/kitchen-sink.html rename test/expected/{transformers => }/filters.html (88%) delete mode 100644 test/expected/transformers/prettify.html rename test/fixtures/{transformers => }/base-url.html (100%) delete mode 100644 test/fixtures/basic.html create mode 100644 test/fixtures/build/beforeCreate.html create mode 100644 test/fixtures/build/expandLinkTag.html rename test/{stubs/empty/empty.html => fixtures/build/image.png} (100%) delete mode 100644 test/fixtures/components/backwards-compatibility.html delete mode 100644 test/fixtures/components/kitchen-sink.html rename test/fixtures/{transformers => }/filters.html (89%) delete mode 100644 test/fixtures/transformers/prettify.html create mode 100644 test/plaintext.test.js create mode 100644 test/posthtml.test.js create mode 100644 test/render.test.js create mode 100644 test/server.test.js delete mode 100644 test/stubs/assets/foo.bar delete mode 100644 test/stubs/assets2/foo1.bar delete mode 100644 test/stubs/assets2/foo2.bar delete mode 100644 test/stubs/breaking/bad.html delete mode 100644 test/stubs/components/bare.html delete mode 100644 test/stubs/components/component.html delete mode 100644 test/stubs/components/text.html delete mode 100644 test/stubs/config/config.maizzle-ci.js create mode 100644 test/stubs/config/maizzle.config.local.js create mode 100644 test/stubs/config/maizzle.config.maizzle-ci.js delete mode 100644 test/stubs/config/maizzle.config.test.js delete mode 100644 test/stubs/data.json delete mode 100644 test/stubs/events/before-create.html delete mode 100644 test/stubs/layouts/layout.html delete mode 100644 test/stubs/layouts/legacy.html delete mode 100644 test/stubs/layouts/template-legacy.html delete mode 100644 test/stubs/main.css delete mode 100644 test/stubs/plaintext/front-matter.html delete mode 100644 test/stubs/plaintext/plaintext.html delete mode 100644 test/stubs/post.css create mode 100644 test/stubs/static/plain.txt create mode 100644 test/stubs/style.css delete mode 100644 test/stubs/tailwind/add-important.html delete mode 100644 test/stubs/tailwind/content-source.html delete mode 100644 test/stubs/tailwind/tailwind.css delete mode 100644 test/stubs/template-legacy.html delete mode 100644 test/stubs/templates/1.html delete mode 100644 test/stubs/templates/2.html delete mode 100644 test/stubs/templates/2.test delete mode 100644 test/stubs/templates/nested/3.html delete mode 100644 test/test-config.js delete mode 100644 test/test-misc.js delete mode 100644 test/test-postcss.js delete mode 100644 test/test-posthtml.js delete mode 100644 test/test-serve.js delete mode 100644 test/test-tailwindcss.js delete mode 100644 test/test-todisk.js delete mode 100644 test/test-tostring.js delete mode 100644 test/test-transformers.js create mode 100644 test/transformers.test.js create mode 100644 test/utils.test.js create mode 100644 test/websockets.test.js delete mode 100644 tsconfig.json delete mode 100644 types/baseUrl.d.ts create mode 100644 types/css/inline.d.ts create mode 100644 types/css/purge.d.ts delete mode 100644 types/fetch.d.ts delete mode 100644 types/inlineCss.d.ts delete mode 100644 types/layouts.d.ts delete mode 100644 types/removeUnusedCss.d.ts delete mode 100644 types/tailwind.d.ts delete mode 100644 types/templates.d.ts create mode 100644 vite.config.js diff --git a/.editorconfig b/.editorconfig index c6c8b362..d03e4647 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,9 +1,9 @@ -root = true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e0c861d0..196f69dc 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,4 +5,3 @@ updates: schedule: interval: "daily" target-branch: "master" - open-pull-requests-limit: 10 diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 28ca080a..fedbb793 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -15,15 +15,15 @@ jobs: strategy: matrix: - node-version: [14, 16, 18] + node-version: [18, 20, 22] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - - run: npm install + - run: npm ci - run: npm test env: CI: true diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..64d41981 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,730 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [5.0.0] - 2024-??-?? + +These are notes for the release, not the actual release notes. + +### New Features + +- files: ['test/fixtures/**/*.html', '!test/fixtures/build/beforeCreate.html'], -> document how to negate file paths +- template sources (build.files) can no longer be a function, only an array of globs; show how to use a function to generate these globs in the docs, because we now have top level await (ie fetch from some api maybe?) +- note: binary files alongside templates in build.files globs will only be copied if the glob covers all files, i.e. `**/*.*` and not `**/*.html` or `**/file.html` + +### Added + +### Changed + +- event payloads can now be destructured into {html, config, render} +- returning HTML from events is now optional, if missing the original HTML will be used + +### Fixed + +- fixed an issue with identical file names in different root folders when using multiple template sources + For example, if you had `source: ['foo', 'src/templates'],` and a `index.html` in each, the one in `src/templates` would overwrite the first one in the build output, because the directory structure was not being preserved correctly. + +### Removed + +- removed `inlineCSS.preferBgColorAttribute` + + +## [2.5.0] - 2020-11-06 + +### Added + +- Use Tailwind CSS inside `` conditional tags (#349) +- Define top-level data objects in your config (#350) + +### Changed + +- default to Tailwind's PurgeCSS extractor + +### Fixed + +- always remove the `` tag from the HTML version + +## [2.4.1] - 2020-10-31 + +- the plaintext generator now accepts `options`, if you need to configure string-strip-html. + +## [2.4.0] - 2020-10-30 + +### Added + +- new plaintext method d95846a +- use purging from tailwind config if set f440db8 + +### Fixed + +- disable decodeEntities by default 1cb15d4 + +### Changed + +- always set NODE_ENV to production if not developing locally 8e420a4 + +## [2.3.4] - 2020-10-29 + +### Fixed + +- fix: disable decodeEntities in all transformers 8af4342 + +## [2.3.3] - 2020-10-29 + +### Fixed + +- Fixed an issue with entities being decoded into symbols (#348) +- Fixed an issue where `{{ }}` curly braces for expressions were being output as `{{ }` because of a loose regex when using `mergeLonghand` (#347) + +## [2.3.2] - 2020-10-29 + +### Fixed + +- Fix issue where parser would break `<%= =>` tags (#346) +- Fix issue with mergeLongHand always enabled + +## [2.3.1] - 2020-10-23 + +### Fixed + +- fix: beforeCreate event in serve method c368555 +- fix: events in serve method 3d01f3a + +### Changed + +- refactor: cli message when compiling a template 05f234c +- chore: update package keywords 17555d6 +- chore: update package description 28c417e +- refactor(tests): use default import for path module 943d0c0 + +## [2.3.0] - 2020-10-01 + +### Added + +- Maizzle now uses `bs-html-injector` to 'hot reload' your changes without reloading the browser page + +### Changed + +- Much faster local development: maizzle serve now only re-compiles the template that was changed/edited + +### Fixed + +- Browsersync will now correctly watch the file you have specified in `build.tailwind.config` in your `config.js` +- fix: local dev tailwind compilation 09fffc7 + +## [2.2.0] - 2020-09-28 + +### Changed + +- updated to the latest PurgeCSS version, so you can now use the new `safelist` and `blocklist` options +- minifier now works out of the box just by enabling it, no need to set `removeLineBreaks: true` (fixes #307) + + +## [2.1.2] - 2020-09-11 + +### Fixed + +- fix(todisk): report correct number of templates parsed bd2f1e7 + +## [2.1.1] - 2020-09-11 + +### Fixed + +- fix(generators): read plaintext option correctly from template config 9705f2e + +## [2.1.0] - 2020-09-08 + +### Added + +- Maizzle now sets `process.env.NODE_ENV` to your current build `env` value + +## [2.0.1] - 2020-09-07 + +### Changed + +- build(tailwind): add purge layers future flag bcebc54 + +## [2.0.0] - 2020-09-01 + +### Added + +- support for multiple destination directories +- support multiple template sources +- exposed `html` in `beforeRender` + +### Changed + +- new `build.templates` config +- `toString` now returns object +- build(deps): bump posthtml-expressions from 1.4.6 to 1.4.7 51d65c8 +- build(deps): bump tailwindcss from 1.7.5 to 1.7.6 257cb0c +- build(deps): bump tailwindcss from 1.7.3 to 1.7.5 87448ac + +### Fixed + +- fix(todisk): show correct number of templates built 73e079f +- fix(todisk): return array of all files d281396 +- fix: plaintext and todisk generators 5c3c06a + +## [1.4.3] - 2020-08-28 + +### Fixed + +- fix(tailwind): remove css-mqpacker postcss plugin 3dba076 + +### Changed + +- ci: add node 14 7079ea7 +- docs: update github ci shield url 5137193 +- build(deps): bump string-strip-html from 5.0.0 to 5.0.1 8a0ca9e +- build(deps): [security] bump dot-prop from 4.2.0 to 4.2.1 94c742e + +## [1.4.2] - 2020-08-24 + +### Fixed + +- fixed #269 by updating posthtml-expressions to v1.4.6, and also updates some of the dependencies + +## [1.4.1] - 2020-08-20 + +### Changed + +- build(deps): bump tailwindcss to 1.7.3 1ac6611 +- revert(posthtml): evaluate expressions first ccc9bcc + +## [1.4.0] - 2020-08-20 + +### Added + +#### Tailwind CSS v1.7.0 + +- Layouts: templating has been improved and you can now do more stuff with layouts/extending +- Expressions: you can now use expressions inside the `src=""` attribute when extending a layout +- Added support for using custom tag names instead of `<extends>` +- Use custom slot/fill tag names, instead of the `<block>` tag + +## [1.3.1] - 2020-08-05 + +### Changed + +- test(tailwind): fix failing tests c75c95e +- build(deps): bump tailwindcss from 1.5.2 to 1.6.2 35acb14 +- build(deps-dev): bump ava from 3.11.0 to 3.11.1 48a7c7d + +## [1.3.0] - 2020-07-27 + +### Added + +#### Pass config object to serve() + +### Changed + +- build(deps): bump posthtml-url-parameters from 1.0.3 to 1.0.4 95f894f +- build(deps): bump tailwindcss from 1.4.6 to 1.5.2 478decc +- build(deps-dev): bump ava from 3.10.1 to 3.11.0 9b77d6c +- build(deps): bump browser-sync from 2.26.7 to 2.26.12 6587b85 +- build(deps): bump ora from 4.0.4 to 4.0.5 0689100 +- build(deps): [security] bump lodash from 4.17.14 to 4.17.19 c67b973 +- build(deps-dev): bump np from 6.3.1 to 6.3.2 fa908d1 +- build(deps): bump postcss-nested from 4.2.2 to 4.2.3 8f0e7b3 +- build(deps): bump juice from 6.0.0 to 7.0.0 a9bc488 + +## [1.2.1] - 2020-07-08 + +### Changed + +- build(deps-dev): bump np from 6.3.0 to 6.3.1 f2ad173 +- build(deps): bump posthtml-modules from 0.6.1 to 0.6.2 39cc7b2 +- build(deps): bump posthtml-expressions from 1.4.4 to 1.4.5 89ff144 +- build(deps-dev): bump ava from 3.10.0 to 3.10.1 bbfb50f +- build(deps-dev): bump np from 6.2.5 to 6.3.0 22fd4e6 +- build(deps-dev): bump xo from 0.32.0 to 0.32.1 d8fe3aa +- build(deps): bump postcss-nested from 4.2.1 to 4.2.2 853889f +- build(deps): bump html-crush from 1.9.36 to 2.0.0 2d66fd7 +- build(deps-dev): bump ava from 3.9.0 to 3.10.0 60937c6 + +## [1.2.0] - 2020-07-02 + +### Added +- feat: support all browsersync options 00f4196 + +### Fixed + +- skip inexistent asset paths ded92b2 +- external engine variables break urlParameters #213 (fixed in posthtml/posthtml-url-parameters#3) +- `<raw>` tag not working inside `<if>` condition (fixed in posthtml/posthtml-expressions#87) +- escape custom delimiters when ignoring expressions (fixed in posthtml/posthtml-expressions#91) +- correctly output nested components (fixed in posthtml/posthtml-modules#44) + +## [1.1.1] - 2020-05-29 + +### Fixed + +- fix(posthtml): don't pass expressions plugin to modules 95cd4ba (fixes #194) + +## [1.1.0] - 2020-05-28 + +### Added + +- Added support for multiple asset paths +- Support disabling the `safeClassNames` transformer + +### Changed + +- Use PostHTML for `extraAttributes` too (replacing `cheerio`) + +## [1.0.9] - 2020-05-23 + +### Changed + +- build: update dependencies 828e397 +- build(deps): bump front-matter from 3.1.0 to 3.2.1 21ba57a +- build(deps): bump email-comb from 3.9.14 to 3.9.16 21935ea +- build(deps): bump string-strip-html from 4.4.3 to 4.4.5 c6249a3 +- build(deps): bump postcss from 7.0.29 to 7.0.30 7bd7f37 +- build(deps): bump posthtml-expressions from 1.4.0 to 1.4.1 737b0ec +- build(deps): bump html-crush from 1.9.31 to 1.9.33 a0ec0cd + +## [1.0.8] - 2020-05-11 + +### Fixed + +- fix(posthtml): use expressions plugin last 211d64e +- fix(tailwind): prepend passed css string to css from existing file aad35d1 + +### Changed + +- test: add tests for helpers d0b1281 +- test(tostring): add inheritance test 0792e13 +- revert(posthtml): remove initial option from modules plugin 9a2abc8 +- refactor(tailwind): use a single function for css compilation 9c329cd + +## [1.0.7] - 2020-05-08 + +### Changed + +- chore: bump posthtml-safe-class-names 8f40131 +- build(deps): bump postcss from 7.0.28 to 7.0.29 1446d9a +- build(deps): bump posthtml-mso from 1.0.0 to 1.0.1 cd5dad2 +- build(deps): bump tailwindcss from 1.4.0 to 1.4.4 4ddd93c +- build(deps): bump postcss from 7.0.27 to 7.0.28 90518bb +- build(deps-dev): bump np from 6.2.2 to 6.2.3 e92835a + +## [1.0.6] - 2020-05-03 + +### Fixed + +- fix(tailwind): pick up config changes when watching files 0885127 + +## [1.0.5] - 2020-05-01 + +### Fixed + +- fix(generators): use initial option with modules plugin 7dab46d + +## [1.0.4] - 2020-05-01 + +### Fixed + +- fix(transformers): add extra attribute only if it doesn't exist 0610c62 + +## [1.0.3] - 2020-04-30 + +### Added + +- feat(tailwind): allow omitting config file path 1548434 + +## [1.0.2] - 2020-04-30 + +### Added + +- feat(tailwind): use target and purge options when compiling from string c642836 +- feat(tailwind): use purge options from tailwind config e756cdd +- feat(tailwind): use ie11 as default target 0de0e73 + +### Changed + +- chore: bump tailwindcss version to 1.4 d9fe4b6 + +## [1.0.1] - 2020-04-30 + +### Fixed + +- fix(todisk): remove plaintext tags only when generating plaintext 6031701 + +## [1.0.0] - 2020-04-28 + +### Changed + +- [BREAKING] Use PostHTML instead of Nunjucks +- [BREAKING] New `config.js` structure +- [BREAKING] Requires Node 10 or later + +### Added + +- PostHTML templating (see [layouts](https://v1.maizzle.com/docs/layouts/), [templates](https://v1.maizzle.com/docs/templates/), [tags](https://v1.maizzle.com/docs/tags/)) +- New `<plaintext>` tag ([docs](https://v1.maizzle.com/docs/plaintext/)) +- New `<outlook>` tags ([docs](https://v1.maizzle.com/docs/tags/#outlook)) +- New `<fetch>` tag ([docs](https://v1.maizzle.com/docs/tags/#fetch)) +- New transformer: `removeAttributes` ([docs](https://v1.maizzle.com/docs/code-cleanup/#removeattributes)) +- Customizable safe class names ([docs](https://v1.maizzle.com/docs/code-cleanup/#safeclassnames)) +- Default Browsersync paths 38664a5 +- Default PurgeCSS sources db3c3c9 +- Default extra attributes b36201c +- Merge inline CSS longhand to shorthand e4d3672 +- Use `removeStyleTags` in CSS inliner options 48fda1c +- CLI: interactive prompt for scaffolding commands ([docs](https://v1.maizzle.com/docs/commands/#scaffolding)) +- CLI: short commands for project scaffolding ([docs](https://v1.maizzle.com/docs/commands/#new)) + +### Fixed + +- `maizzle serve` now works properly with multiple template paths 844a195 +- Node.js: you can just pass in a string when using `render()`, no option is required +- Build error handling now lets you know which file failed to compile ([customizable](https://v1.maizzle.com/docs/build-config/#build-errors)) +- Better minification (now using `html-crush`) 094d03b +- Better Markdown (now using `markdown-it`) 7d12277 + +### Removed + +- Removed `afterConfig` event +- CLI: removed the need for `bootstrap.js` in project root maizzle/cli@30087b8 + +## [0.9.1] - 2020-03-18 + +### Fixed + +- [security] bump acorn from 7.1.0 to 7.1.1 2fbb4bf + +### Changed + +- update ESLint fc9a806 +- bump query-string from 6.11.0 to 6.11.1 2af6427 +- bump email-comb from 3.9.3 to 3.9.4 1fdeb11 +- bump string-strip-html from 4.3.16 to 4.3.17 5356a1b +- bump nunjucks from 3.2.0 to 3.2.1 0324913 + +## [0.9.0] - 2020-03-05 + +### Added + +- Added new markdown parser +- Transform Contents transformer +- Support dots in utility class names + +### Changed + +- Use `<style postcss>` instead of `<style tailwind>` for Tailwind CSS + +## [0.8.0] - 2020-02-29 + +### Added + +- add `beforeCreate` event 9ef368f +- support async functions in `afterBuild` event 4f4829c + +### Changed + +- rename config variables. 9650e2d +- bump @fullhuman/postcss-purgecss from 2.0.5 to 2.1.0 d0e52cd +- bump postcss from 7.0.26 to 7.0.27 2903e2c +- bump np from 5.2.1 to 6.2.0 9d21f44 +- bump email-comb from 3.9.0 to 3.9.3 060be57 +- bump eslint-plugin-import from 2.20.0 to 2.20.1 cc13487 +- bump query-string from 6.10.1 to 6.11.0 ff30eba +- bump string-strip-html from 4.3.15 to 4.3.16 f87c461 + +## [0.7.4] - 2020-02-12 + +### Fixed + +- don't rewrite class names when developing locally 1cbe8fd +- fix Nunjucks inheritance 4d5efce + +### Changed + +- include `ui` browser sync option ab0b7c8 + +## [0.7.3] - 2020-02-07 + +### Changed + +- bump tailwindcss from 1.1.4 to 1.2.0 ab15ec7 + +## [0.7.2] - 2020-02-04 + +### Added + +- allow using `local` as environment name in config file 45b5ccd + +## [0.7.1] - 2020-02-01 + +### Added + +- add support for `%` in default PurgeCSS extractor dc8e0ab + +### Changed + +- replace `%` with `pc` in output HTML class names 4b90d7a + +### Fixed + +- update Tailwind separator replacer regex fcad256 + +## [0.7.0] - 2020-01-30 + +### Added + +- add afterBuild hook 4e12a6f + +### Fixed + +- ensure parent object exists for `afterBuild` event 5b9fd9f + +### Changed + +- update FUNDING.yml 5cf30f0 +- update FUNDING.yml 1750962 +- update dependencies 49a2faa + +## [0.6.4] - 2019-12-23 + +### Fixed + +- pass env config in posthtml-content transformer 78f9b2c + +## [0.6.3] - 2019-12-23 + +### Fixed + +- fix purgeCSS when using multiple template sources 8a00ec6 +- make use of layout in render() method, too fd9474c + +### Changed + +- simplify special character replacement regexes d204ad7 +- don't ensure and read layout when compiling CSS eaae1c9 + +## [0.6.2] - 2019-12-20 + +### Added + +- allow customizing purgeCSS `content` when building strings 4f127bd + +## [0.6.1] - 2019-12-19 + +### Fixed + +- make sure Nunjucks config exists before using it. 23ab1a1 + +## [0.6.0] - 2019-12-19 + +### Added + +- support compiling templates from multiple sources. f627869 +- allow configuring Nunjucks tags. 6beb37a +- allow configuring Nunjucks base path. c7f89c8 +- add support for lifecycle hooks in config. bf91c8d +- allow customizing purgeCSS' defaultExtractor. d8f8380 + +### Changed + +- update escaped character CSS class replacements. dfa1add + +## [0.5.3] - 2019-12-17 + +### Changed + +- prefer const for layout variable 5241e61 +- also generate Tailwind components by default f3453a0 +- update regex for escaped character class replace 61fd671 + +## [0.5.2] - 2019-12-12 + +### Fixed + +- fix layout handling in `render()` method bed6dd5 +- rework template inheritance 8bdb8dd + +## [0.5.1] - 2019-12-12 + +### Changed + +- roll back template inheritance 335a886 + +## [0.5.0] - 2019-12-12 + +### Added + +- Added Lifecycle hooks +- Add support for `:` or `/` in CSS class names +- Added support for preventing widow words through the `prevent-widows` attribute + +### Fixed + +- Template inheritance + +### Changed + +- throw error if Tailwind config is not an object cf46651 +- compile Tailwind only if needed 0f663d6 +- copy assets to output dir as a final step 0ed5198 +- start using ESLint 9b5d03a + +## [0.4.4] - 2019-12-02 + +### Changed + +- updated dependencies + +## [0.4.3] - 2019-09-17 + +### Fixed + +- bump email-comb from 3.7.1 to 3.8.0 ba0d2b7 +- remove console.log f88c50e + +## [0.4.2] - 2019-09-11 + +### Fixed + +- update email-comb to 3.7.1 c55023c + +## [0.4.1] - 2019-09-10 + +### Added + +- add `replaceStrings` transformer 1779ddb + +### Changed + +- pass through minifier only if explicitly enabled 37f8f06 + +## [0.4.0] - 2019-09-10 + +### Fixed + +- use Nunjucks extends in `render()` 05a5389 + +### Changed + +- make `opts.tailwind.css` optional in `render()` 15898cf +- bump posthtml from 0.11.4 to 0.11.6 ee9fccf +- bump color-shorthand-hex-to-six-digit from 2.10.37 to 2.10.40 5eb3035 +- bump query-string from 6.8.2 to 6.8.3 780ebd5 +- bump email-comb from 3.5.1 to 3.6.1 f5fd1c5 +- bump string-strip-html from 4.0.29 to 4.1.1 bbf1b33 + +## [0.3.3] - 2019-08-28 + +### Changed + +- [security] bump set-value from 2.0.0 to 2.0.1 5da7c27 +- [security] bump mixin-deep from 1.3.1 to 1.3.2 af7f0c4 +- bump query-string from 6.8.1 to 6.8.2 d8eba9e +- bump color-shorthand-hex-to-six-digit from 2.10.35 to 2.10.37 9e63ac0 +- bump email-comb from 3.4.8 to 3.5.1 1e5bf71 +- bump tailwindcss from 1.0.6 to 1.1.2 13c8832 +- bump string-strip-html from 4.0.27 to 4.0.29 227514a + +## [0.3.2] - 2019-08-16 + +### Changed + +- better media query sorting 99d1aa5 + +## [0.3.1] - 2019-08-13 + +### Fixed + +- specify env when getting config in serve method acbeb91 + +## [0.3.0] - 2019-08-01 + +### Added + +- allow using array for `build.templates.filetypes` ab361d2 +- support falsy values for `baseImageURL`. 3412db5 + +### Changed + +- dependency & security updates + +### Fixed + +- throw error if building `env` with missing config. 5ca5230 +- don't add `baseImageURL` to empty attributes. a5e7e4a + +### Removed + +- remove fix for Tailwind CSS escaped characters. 9d0a870 + +## [0.2.4] - 2019-07-01 + +### Changed + +- bump np from 4.0.2 to 5.0.3 4e0840c +- bump fs-extra from 8.0.1 to 8.1.0 58f932d +- bump color-shorthand-hex-to-six-digit from 2.10.26 to 2.10.27 822b4bf +- bump marked from 0.6.2 to 0.6.3 f477c37 +- bump query-string from 6.4.0 to 6.8.1 5bde4c4 + +## [0.2.3] - 2019-06-24 + +### Changed + +- updated dependencies + +## [0.2.2] - 2019-06-12 + +### Fixed + +- update baseImageURL replacement regex efd7463 + +### Changed + +- parse template file path only when needed 8c79708 + +## [0.2.1] - 2019-06-12 + +### Fixed + +- check if assets source path exists before copying. b5c163e + +## [0.2.0] - 2019-06-10 + +### Changed + +- parse Browsersync open option c9c9fe3 +- updated dependencies 0befafb + +## [0.1.5] - 2019-06-04 + +### Changed + +- update email-comb f4c0d56 +- update dependencies.d969560 + +## [0.1.4] - 2019-05-22 + +### Changed + +- Update TailwindCSS to stable release. 0f78e7e + +## [0.1.3] - 2019-04-03 + +### Fixed + +- Fixes a race condition while developing locally + +## [0.1.2] - 2019-04-01 + +## Added + +- Exposes environment name to templates. Use `env` in a template to get the current build environment name + +## [0.1.1] - 2019-03-28 + +First release! 🎉 diff --git a/bin/maizzle b/bin/maizzle index d607b3e8..80c09cbe 100644 --- a/bin/maizzle +++ b/bin/maizzle @@ -1,3 +1,5 @@ #!/usr/bin/env node -require('@maizzle/cli') +import bootstrap from '@maizzle/cli' + +await bootstrap() diff --git a/biome.json b/biome.json index c914aa4e..4a9e5b2e 100644 --- a/biome.json +++ b/biome.json @@ -7,12 +7,12 @@ "enabled": true, "rules": { "recommended": true, - "performance": { - "noAccumulatingSpread": "off" + "complexity": { + "noForEach": "off" }, "style": { - "noParameterAssign": "off", - "useTemplate": "off" + "useTemplate": "off", + "noParameterAssign": "off" } } } diff --git a/package-lock.json b/package-lock.json index ab2ea2a8..2056b450 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,63 +1,70 @@ { "name": "@maizzle/framework", - "version": "4.8.8", + "version": "5.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@maizzle/framework", - "version": "4.8.8", + "version": "5.0.0", "license": "MIT", "dependencies": { - "@maizzle/cli": "^1.5.1", - "autoprefixer": "^10.4.14", - "browser-sync": "^3.0.2", - "color-shorthand-hex-to-six-digit": "^3.0.2", - "email-comb": "^5.3.1", + "@csstools/css-calc": "^1.2.2", + "@maizzle/cli": "next", + "cheerio": "^1.0.0-rc.12", + "chokidar": "^3.6.0", + "cli-table3": "^0.6.5", + "color-shorthand-hex-to-six-digit": "^5.0.16", + "defu": "^6.1.4", + "email-comb": "^7.0.21", + "express": "^4.19.2", "fast-glob": "^3.3.2", - "front-matter": "^4.0.0", - "fs-extra": "^11.2.0", - "html-crush": "^4.0.0", - "is-url-superb": "^5.0.0", + "gray-matter": "^4.0.3", + "html-crush": "^6.0.18", + "is-url-superb": "^6.1.0", + "istextorbinary": "^9.5.0", "juice": "^10.0.0", - "lodash": "^4.17.20", - "ora": "^5.1.0", - "postcss": "^8.4.21", - "postcss-import": "^15.0.0", - "postcss-merge-longhand": "^6.0.0", + "lodash-es": "^4.17.21", + "morphdom": "^2.7.2", + "ora": "^8.0.1", + "pathe": "^1.1.2", + "postcss": "^8.4.38", + "postcss-custom-properties": "^13.3.10", + "postcss-import": "^16.1.0", + "postcss-safe-parser": "^7.0.0", "posthtml": "^0.16.6", "posthtml-attrs-parser": "^1.1.0", - "posthtml-base-url": "^2.0.2", + "posthtml-base-url": "^3.1.2", "posthtml-component": "^1.1.0", - "posthtml-content": "^2.1.0", - "posthtml-extend": "^0.6.0", - "posthtml-extra-attributes": "^2.0.0", - "posthtml-fetch": "^3.0.0", - "posthtml-markdownit": "^3.1.0", - "posthtml-match-helper": "^1.0.3", - "posthtml-mso": "^3.1.0", + "posthtml-content": "^2.0.1", + "posthtml-extra-attributes": "^3.0.0", + "posthtml-markdownit": "^3.0.1", + "posthtml-mso": "^3.0.0", + "posthtml-parser": "^0.12.0", + "posthtml-postcss": "^1.0.0", "posthtml-postcss-merge-longhand": "^3.1.0", - "posthtml-safe-class-names": "^3.0.0", - "posthtml-url-parameters": "^2.0.0", + "posthtml-render": "^3.0.0", + "posthtml-safe-class-names": "^4.0.2", + "posthtml-url-parameters": "^3.0.0", "pretty": "^2.0.0", - "query-string": "^7.1.3", - "string-remove-widows": "^2.1.0", - "string-strip-html": "^8.2.0", - "tailwindcss": "^3.2.7" + "string-remove-widows": "^4.0.22", + "string-strip-html": "^13.4.8", + "tailwindcss": "^3.4.4", + "ws": "^8.17.0" }, "bin": { "maizzle": "bin/maizzle" }, "devDependencies": { "@biomejs/biome": "^1.8.3", - "@types/browser-sync": "^2.29.0", - "@types/js-beautify": "^1.14.0", - "@types/markdown-it": "^14.0.0", - "ava": "^5.2.0", - "c8": "^10.0.0" + "@types/js-beautify": "^1.14.3", + "@types/markdown-it": "^14.1.1", + "@vitest/coverage-v8": "^2.0.1", + "supertest": "^7.0.0", + "vitest": "^2.0.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/@alloc/quick-lru": { @@ -71,97 +78,58 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "dev": true, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { + "node_modules/@babel/helper-validator-identifier": { "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "dev": true, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" + "node_modules/@babel/parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=4" + "node": ">=6.0.0" } }, - "node_modules/@babel/runtime": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", - "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", + "node_modules/@babel/types": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", + "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "dev": true, "dependencies": { - "regenerator-runtime": "^0.14.0" + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" @@ -328,4677 +296,2050 @@ "node": ">=14.21.3" } }, - "node_modules/@inquirer/figures": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.3.tgz", - "integrity": "sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==", - "engines": { - "node": ">=18" + "node_modules/@clack/core": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-0.3.4.tgz", + "integrity": "sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==", + "dependencies": { + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" } }, - "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==", + "node_modules/@clack/prompts": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-0.7.0.tgz", + "integrity": "sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==", + "bundleDependencies": [ + "is-unicode-supported" + ], "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" + "@clack/core": "^0.3.3", + "is-unicode-supported": "*", + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" } }, - "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==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, + "node_modules/@clack/prompts/node_modules/is-unicode-supported": { + "version": "1.3.0", + "inBundle": true, + "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true, "engines": { - "node": ">=8" + "node": ">=0.1.90" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, + "node_modules/@csstools/cascade-layer-name-parser": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.13.tgz", + "integrity": "sha512-MX0yLTwtZzr82sQ0zOjqimpZbzjMaK/h2pmlrLK7DCzlmiZLYFpoO94WmN1akRVo6ll/TdpHb53vihHLUMyvng==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=6.0.0" + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.7.1", + "@csstools/css-tokenizer": "^2.4.1" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@csstools/css-calc": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-1.2.4.tgz", + "integrity": "sha512-tfOuvUQeo7Hz+FcuOd3LfXVp+342pnWUJ7D2y8NUpu1Ww6xnTbHLpz018/y6rtbHifJ3iIEf9ttxXd8KG7nL0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=6.0.0" + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.7.1", + "@csstools/css-tokenizer": "^2.4.1" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.7.1.tgz", + "integrity": "sha512-2SJS42gxmACHgikc1WGesXLIT8d/q2l0UFM7TaEeIzdFCE/FPMtTiizcPGGJtlPo2xuQzY09OhrLTzRxqJqwGw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@maizzle/cli": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@maizzle/cli/-/cli-1.5.9.tgz", - "integrity": "sha512-M6t6t59QXGgcICyDf41PNGfg5xshgsNqjWH7MRdUcSm+RkyQwQQbml/Lqh+8NwLsKFjFHnE/T8pXsl5gWduLmw==", - "dependencies": { - "chalk": "^4.1.0", - "commander": "^11.0.0", - "execa": "^5.0.0", - "fs-extra": "^11.2.0", - "import-cwd": "^3.0.0", - "inquirer": "^8.0.0", - "np": "*", - "ora": "^5.1.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "maizzle": "bin/maizzle" + "node": "^14 || ^16 || >=18" }, - "engines": { - "node": ">=14.0.0" + "peerDependencies": { + "@csstools/css-tokenizer": "^2.4.1" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.4.1.tgz", + "integrity": "sha512-eQ9DIktFJBhGjioABJRtUucoWR2mwllurfnM8LuNGAqX3ViZXaUchqk+1s7jjtkFiT9ySdACsFEA3etErkALUg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">= 8" + "node": "^14 || ^16 || >=18" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@csstools/utilities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-1.0.0.tgz", + "integrity": "sha512-tAgvZQe/t2mlvpNosA4+CkMiZ2azISW5WPAcdSalZlEjQvUfghHxfQcrCiK/7/CrfAWVxyM88kGFYO82heIGDg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">= 8" + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/@one-ini/wasm": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", - "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=14" + "node": ">=12" } }, - "node_modules/@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=12.22.0" + "node": ">=12" } }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dependencies": { - "graceful-fs": "4.2.10" - }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=12.22.0" + "node": ">=12" } }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/@pnpm/npm-conf": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", - "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", - "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" - }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { "node": ">=12" } }, - "node_modules/@samverschueren/stream-to-observable": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", - "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", - "dependencies": { - "any-observable": "^0.3.0" - }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6" - }, - "peerDependenciesMeta": { - "rxjs": { - "optional": true - }, - "zen-observable": { - "optional": true - } + "node": ">=12" } }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "node": ">=12" } }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/@types/browser-sync": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/@types/browser-sync/-/browser-sync-2.29.0.tgz", - "integrity": "sha512-d2V8FDX/LbDCSm343N2VChzDxvll0h76I8oSigYpdLgPDmcdcR6fywTggKBkUiDM3qAbHOq7NZvepj/HJM5e2g==", + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@types/micromatch": "^2", - "@types/node": "*", - "@types/serve-static": "*", - "chokidar": "^3.0.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, - "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", - "dependencies": { - "@types/node": "*" + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "node_modules/@types/js-beautify": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/@types/js-beautify/-/js-beautify-1.14.3.tgz", - "integrity": "sha512-FMbQHz+qd9DoGvgLHxeqqVPaNRffpIu5ZjozwV8hf9JAGpIOzuAf4wGbRSo8LNITHqGjmmVjaMggTT5P4v4IHg==", - "dev": true - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dependencies": { - "@types/node": "*" + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", - "dev": true - }, - "node_modules/@types/markdown-it": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", - "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "@types/linkify-it": "^5", - "@types/mdurl": "^2" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", - "dev": true - }, - "node_modules/@types/micromatch": { - "version": "2.3.35", - "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-2.3.35.tgz", - "integrity": "sha512-J749bHo/Zu56w0G0NI/IGHLQPiSsjx//0zJhfEVAN95K/xM5C8ZDmhkXtU3qns0sBOao7HuQzr8XV1/2o5LbXA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "@types/parse-glob": "*" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.14.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz", - "integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==", - "dependencies": { - "undici-types": "~5.26.4" + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" - }, - "node_modules/@types/parse-glob": { - "version": "3.0.32", - "resolved": "https://registry.npmjs.org/@types/parse-glob/-/parse-glob-3.0.32.tgz", - "integrity": "sha512-n4xmml2WKR12XeQprN8L/sfiVPa8FHS3k+fxp4kSr/PA2GsGUgFND+bvISJxM0y5QdvzNEGjEVU3eIrcKks/pA==", - "dev": true - }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dependencies": { - "@types/node": "*" + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">= 0.6" + "node": ">=12" } }, - "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], "dev": true, - "bin": { - "acorn": "bin/acorn" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.4.0" + "node": ">=12" } }, - "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "acorn": "^8.11.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.4.0" + "node": ">=12" } }, - "node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", - "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" - }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "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==", "dependencies": { - "string-width": "^4.1.0" + "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/ansi-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "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==" + }, + "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==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/ansi-align/node_modules/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==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { - "node": ">=6" + "node": ">=6.0.0" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "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==", - "engines": { - "node": ">=12" + "node_modules/@maizzle/cli": { + "version": "2.0.0-alpha.1", + "resolved": "https://registry.npmjs.org/@maizzle/cli/-/cli-2.0.0-alpha.1.tgz", + "integrity": "sha512-HGt1rFzMFfNtuaqGwXxONSAwTfimpSRb7whTzY3P38vUlt5dcFctC7m3NnAMgHnXd0Qv/HlNLqX2+/mDp1AjCw==", + "dependencies": { + "@clack/prompts": "^0.7.0", + "commander": "^12.1.0", + "create-maizzle": "^0.3.0", + "import-from-esm": "^1.3.4", + "ora": "^8.0.1", + "pathe": "^1.1.2", + "picocolors": "^1.0.1" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "bin": { + "maizzle": "bin/maizzle.mjs" } }, - "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==", - "engines": { - "node": ">=12" + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">= 8" } }, - "node_modules/any-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "engines": { - "node": ">=6" + "node": ">= 8" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { "node": ">= 8" } }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", - "dev": true, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arrayiffy-if-string": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/arrayiffy-if-string/-/arrayiffy-if-string-3.14.0.tgz", - "integrity": "sha512-pQQDnM+wOBvgElVGB8//y16IpZEsi3mU3jkjvhJCm3J7zSvRPlm/8Wl76gE1O9vnU1CWcz2u5JfsOLtD7yvuLw==", - "dependencies": { - "@babel/runtime": "^7.14.0" + "node": ">=14" } }, - "node_modules/arrgv": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", - "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", + "integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==", + "cpu": [ + "arm" + ], "dev": true, - "engines": { - "node": ">=8.0.0" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/arrify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", - "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz", + "integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==", + "cpu": [ + "arm64" + ], "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dependencies": { - "lodash": "^4.17.14" - } + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz", + "integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/async-each-series": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz", - "integrity": "sha512-p4jj6Fws4Iy2m0iCmI2am2ZNZCgbdgE+P8F/8csmn2vx7ixXrO2zGcuNsD46X5uZSVecmkEy/M06X2vG8KD6dQ==", - "engines": { - "node": ">=0.8.0" - } + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz", + "integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/autoprefixer": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", - "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz", + "integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==", + "cpu": [ + "arm" ], - "dependencies": { - "browserslist": "^4.23.0", - "caniuse-lite": "^1.0.30001599", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/ava": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ava/-/ava-5.3.1.tgz", - "integrity": "sha512-Scv9a4gMOXB6+ni4toLuhAm9KYWEjsgBglJl+kMGI5+IVDt120CCDZyB5HNU9DjmLI2t4I0GbnxGLmmRfGTJGg==", + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz", + "integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "acorn": "^8.8.2", - "acorn-walk": "^8.2.0", - "ansi-styles": "^6.2.1", - "arrgv": "^1.0.2", - "arrify": "^3.0.0", - "callsites": "^4.0.0", - "cbor": "^8.1.0", - "chalk": "^5.2.0", - "chokidar": "^3.5.3", - "chunkd": "^2.0.1", - "ci-info": "^3.8.0", - "ci-parallel-vars": "^1.0.1", - "clean-yaml-object": "^0.1.0", - "cli-truncate": "^3.1.0", - "code-excerpt": "^4.0.0", - "common-path-prefix": "^3.0.0", - "concordance": "^5.0.4", - "currently-unhandled": "^0.4.1", - "debug": "^4.3.4", - "emittery": "^1.0.1", - "figures": "^5.0.0", - "globby": "^13.1.4", - "ignore-by-default": "^2.1.0", - "indent-string": "^5.0.0", - "is-error": "^2.2.2", - "is-plain-object": "^5.0.0", - "is-promise": "^4.0.0", - "matcher": "^5.0.0", - "mem": "^9.0.2", - "ms": "^2.1.3", - "p-event": "^5.0.1", - "p-map": "^5.5.0", - "picomatch": "^2.3.1", - "pkg-conf": "^4.0.0", - "plur": "^5.1.0", - "pretty-ms": "^8.0.0", - "resolve-cwd": "^3.0.0", - "stack-utils": "^2.0.6", - "strip-ansi": "^7.0.1", - "supertap": "^3.0.1", - "temp-dir": "^3.0.0", - "write-file-atomic": "^5.0.1", - "yargs": "^17.7.2" - }, - "bin": { - "ava": "entrypoints/cli.mjs" - }, - "engines": { - "node": ">=14.19 <15 || >=16.15 <17 || >=18" - }, - "peerDependencies": { - "@ava/typescript": "*" - }, - "peerDependenciesMeta": { - "@ava/typescript": { - "optional": true - } - } - }, - "node_modules/ava/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/blueimp-md5": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", - "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/boxen": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", - "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^7.0.1", - "chalk": "^5.2.0", - "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/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==", - "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/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-sync": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-3.0.2.tgz", - "integrity": "sha512-PC9c7aWJFVR4IFySrJxOqLwB9ENn3/TaXCXtAa0SzLwocLN3qMjN+IatbjvtCX92BjNXsY6YWg9Eb7F3Wy255g==", - "dependencies": { - "browser-sync-client": "^3.0.2", - "browser-sync-ui": "^3.0.2", - "bs-recipes": "1.3.4", - "chalk": "4.1.2", - "chokidar": "^3.5.1", - "connect": "3.6.6", - "connect-history-api-fallback": "^1", - "dev-ip": "^1.0.1", - "easy-extender": "^2.3.4", - "eazy-logger": "^4.0.1", - "etag": "^1.8.1", - "fresh": "^0.5.2", - "fs-extra": "3.0.1", - "http-proxy": "^1.18.1", - "immutable": "^3", - "micromatch": "^4.0.2", - "opn": "5.3.0", - "portscanner": "2.2.0", - "raw-body": "^2.3.2", - "resp-modifier": "6.0.2", - "rx": "4.1.0", - "send": "0.16.2", - "serve-index": "1.9.1", - "serve-static": "1.13.2", - "server-destroy": "1.0.1", - "socket.io": "^4.4.1", - "ua-parser-js": "^1.0.33", - "yargs": "^17.3.1" - }, - "bin": { - "browser-sync": "dist/bin.js" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/browser-sync-client": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-3.0.2.tgz", - "integrity": "sha512-tBWdfn9L0wd2Pjuz/NWHtNEKthVb1Y67vg8/qyGNtCqetNz5lkDkFnrsx5UhPNPYUO8vci50IWC/BhYaQskDiQ==", - "dependencies": { - "etag": "1.8.1", - "fresh": "0.5.2", - "mitt": "^1.1.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/browser-sync-ui": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-3.0.2.tgz", - "integrity": "sha512-V3FwWAI+abVbFLTyJjXJlCMBwjc3GXf/BPGfwO2fMFACWbIGW9/4SrBOFYEOOtqzCjQE0Di+U3VIb7eES4omNA==", - "dependencies": { - "async-each-series": "0.1.1", - "chalk": "4.1.2", - "connect-history-api-fallback": "^1", - "immutable": "^3", - "server-destroy": "1.0.1", - "socket.io-client": "^4.4.1", - "stream-throttle": "^0.1.3" - } - }, - "node_modules/browser-sync/node_modules/fs-extra": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", - "integrity": "sha512-V3Z3WZWVUYd8hoCL5xfXJCaHWYzmtwW5XWYSlLgERi8PWd8bx1kUHUk8L1BT57e49oKnDDD180mjfrHc1yA9rg==", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^3.0.0", - "universalify": "^0.1.0" - } - }, - "node_modules/browser-sync/node_modules/jsonfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", - "integrity": "sha512-oBko6ZHlubVB5mRFkur5vgYR1UyqX+S6Y/oCfLhqNdcc2fYFlDpIoNc7AfKS1KOGcnNAkvsr0grLck9ANM815w==", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/browser-sync/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/browserslist": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", - "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001629", - "electron-to-chromium": "^1.4.796", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.16" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs-recipes": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz", - "integrity": "sha512-BXvDkqhDNxXEjeGM8LFkSbR+jzmP/CYpCiVKYn+soB1dDldeU15EBNDkwVXndKuX35wnNUaPd0qSoQEAkmQtMw==" - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dependencies": { - "run-applescript": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/c8": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.2.tgz", - "integrity": "sha512-Qr6rj76eSshu5CgRYvktW0uM0CFY0yi4Fd5D0duDXO6sYinyopmftUiJVuzBQxQcwQLor7JWDVRP+dUfCmzgJw==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^3.1.1", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.1.6", - "test-exclude": "^7.0.1", - "v8-to-istanbul": "^9.0.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "monocart-coverage-reports": "^2" - }, - "peerDependenciesMeta": { - "monocart-coverage-reports": { - "optional": true - } - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/callsites": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.1.0.tgz", - "integrity": "sha512-aBMbD1Xxay75ViYezwT40aQONfr+pSXTHwNKvIXhXD6+LY3F1dLIcceoC5OZKBVHbXcysz1hL9D2w0JJIMXpUw==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001638", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001638.tgz", - "integrity": "sha512-5SuJUJ7cZnhPpeLHaH0c/HPAnAHZvS6ElWyHK9GSIbVOQABLzowiI2pjmpvZ1WEbkyz46iFd4UXlOHR5SqgfMQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/cbor": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", - "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", - "dev": true, - "dependencies": { - "nofilter": "^3.1.0" - }, - "engines": { - "node": ">=12.19" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk-template": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.0.tgz", - "integrity": "sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==", - "dependencies": { - "chalk": "^5.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/chalk/chalk-template?sponsor=1" - } - }, - "node_modules/chalk-template/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/chalk/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chunkd": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", - "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", - "dev": true - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/ci-parallel-vars": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz", - "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", - "dev": true - }, - "node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clean-yaml-object": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", - "integrity": "sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cliui/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/cliui/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/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==", - "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/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/code-excerpt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", - "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", - "dev": true, - "dependencies": { - "convert-to-spaces": "^2.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/color-shorthand-hex-to-six-digit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/color-shorthand-hex-to-six-digit/-/color-shorthand-hex-to-six-digit-3.1.0.tgz", - "integrity": "sha512-Mqd0b5KwDuvbQET6UsP82K4w27pWA3I7qzyoDiM7gI+6nb222d0+dUy6rlzr28YbVJkpY1dnF5yclhfG055kZg==", - "dependencies": { - "@babel/runtime": "^7.14.0", - "hex-color-regex": "^1.1.0", - "lodash.clonedeep": "^4.5.0", - "lodash.isplainobject": "^4.0.6" - } - }, - "node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", - "engines": { - "node": ">=16" - } - }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/concordance": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", - "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", - "dev": true, - "dependencies": { - "date-time": "^3.1.0", - "esutils": "^2.0.3", - "fast-diff": "^1.2.0", - "js-string-escape": "^1.0.1", - "lodash": "^4.17.15", - "md5-hex": "^3.0.1", - "semver": "^7.3.2", - "well-known-symbols": "^2.0.0" - }, - "engines": { - "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" - } - }, - "node_modules/condense-newlines": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/condense-newlines/-/condense-newlines-0.2.1.tgz", - "integrity": "sha512-P7X+QL9Hb9B/c8HI5BFFKmjgBu2XpQuF98WZ9XkO+dBGgk5XgwiQz7o1SmpglNWId3581UcS0SFAWfoIhMHPfg==", - "dependencies": { - "extend-shallow": "^2.0.1", - "is-whitespace": "^0.3.0", - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/config-chain/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/configstore": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", - "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", - "dependencies": { - "dot-prop": "^6.0.1", - "graceful-fs": "^4.2.6", - "unique-string": "^3.0.0", - "write-file-atomic": "^3.0.3", - "xdg-basedir": "^5.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/yeoman/configstore?sponsor=1" - } - }, - "node_modules/configstore/node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha512-OO7axMmPpu/2XuX1+2Yrg0ddju31B6xLZMWkJ5rYBu4YRmRVlOjvlY6kw2FJKiAzyxGwnrDUAG4s1Pf0sbBMCQ==", - "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", - "utils-merge": "1.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/convert-to-spaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", - "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", - "dependencies": { - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/crypto-random-string/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", - "dev": true, - "dependencies": { - "array-find-index": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" - }, - "node_modules/date-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", - "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", - "dev": true, - "dependencies": { - "time-zone": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/del/-/del-7.1.0.tgz", - "integrity": "sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==", - "dependencies": { - "globby": "^13.1.2", - "graceful-fs": "^4.2.10", - "is-glob": "^4.0.3", - "is-path-cwd": "^3.0.0", - "is-path-inside": "^4.0.0", - "p-map": "^5.5.0", - "rimraf": "^3.0.2", - "slash": "^4.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" - }, - "node_modules/dev-ip": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", - "integrity": "sha512-LmVkry/oDShEgSZPNgqCIp2/TlqtExeGmymru3uCELnfyjY11IzpAproLYs+1X88fXO6DBoYP3ul2Xo2yz2j6A==", - "bin": { - "dev-ip": "lib/dev-ip.js" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-prop": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", - "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "node_modules/easy-extender": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", - "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==", - "dependencies": { - "lodash": "^4.17.10" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/eazy-logger": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-4.0.1.tgz", - "integrity": "sha512-2GSFtnnC6U4IEKhEI7+PvdxrmjJ04mdsj3wHZTFiw0tUtG4HCWzTr13ZYTk8XOGnA1xQMaDljoBOYlk3D/MMSw==", - "dependencies": { - "chalk": "4.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/editorconfig": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", - "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", - "dependencies": { - "@one-ini/wasm": "0.1.1", - "commander": "^10.0.0", - "minimatch": "9.0.1", - "semver": "^7.5.3" - }, - "bin": { - "editorconfig": "bin/editorconfig" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/editorconfig/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "engines": { - "node": ">=14" - } - }, - "node_modules/editorconfig/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/electron-to-chromium": { - "version": "1.4.814", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.814.tgz", - "integrity": "sha512-GVulpHjFu1Y9ZvikvbArHmAhZXtm3wHlpjTMcXNGKl4IQ4jMQjlnz8yMQYYqdLHKi/jEL2+CBC2akWVCoIGUdw==" - }, - "node_modules/elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/email-comb": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/email-comb/-/email-comb-5.3.1.tgz", - "integrity": "sha512-0rFhgyrRRw6BGWc5Iakf6HI1LGQbmzqFzoMTwq1SGby6PehTTAxqns1y5lBf9HSTY02kC1sqqq8cq+fI4Wx+Sg==" - }, - "node_modules/emittery": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-1.0.3.tgz", - "integrity": "sha512-tJdCJitoy2lrC2ldJcqN4vkqJ00lT+tOWNT1hBJjO/3FDMJa5TTIiYGCKGkn/WfCyOzUMObeohbVTj00fhiLiA==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "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==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", - "dependencies": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/engine.io-client": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", - "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1", - "xmlhttprequest-ssl": "~2.0.0" - } - }, - "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-goat": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", - "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit-hook": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-4.0.0.tgz", - "integrity": "sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fclone": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", - "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==" - }, - "node_modules/figures": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", - "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha512-ejnvM9ZXYzp6PUPUyQBMBf0Co5VX2gr5H2VQe2Ui2jWXNlxv+PYZo8wpAymJNJdLsG1R4p+M4aynF8KuoUEwRw==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up-simple": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", - "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "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==", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/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==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "engines": { - "node": ">= 14.17" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/front-matter": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", - "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", - "dependencies": { - "js-yaml": "^3.13.1" - } - }, - "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/github-url-from-git": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/github-url-from-git/-/github-url-from-git-1.5.0.tgz", - "integrity": "sha512-WWOec4aRI7YAykQ9+BHmzjyNlkfJFG8QLXnDTsLz/kZefq7qkzdfo4p6fkYYMIq1aj+gZcQs/1HQhQh3DPPxlQ==" - }, - "node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/global-directory": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", - "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", - "dependencies": { - "ini": "4.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-dirs/node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hex-color-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", - "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" - }, - "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/html-crush": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/html-crush/-/html-crush-4.2.0.tgz", - "integrity": "sha512-z+8zsmaf6iHX1UN6t5mFxnlvweBh1eSws0NI2RjrMv9NX2gGubjcUPIaU6sdrypiBvU0S/Hjqr5aEcJ55fndPA==", - "dependencies": { - "@babel/runtime": "^7.14.0", - "ranges-apply": "^5.1.0", - "ranges-push": "^5.1.0", - "string-left-right": "^4.1.0", - "string-match-left-right": "^7.1.0", - "string-range-expander": "^2.1.0", - "test-mixer": "^2.1.0" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", - "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", - "dev": true, - "engines": { - "node": ">=10 <11 || >=12 <13 || >=14" - } - }, - "node_modules/ignore-walk": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", - "integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==", - "dependencies": { - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/immutable": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", - "integrity": "sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/import-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", - "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==", - "dependencies": { - "import-from": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/import-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", - "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-lazy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/index-to-position": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-0.1.2.tgz", - "integrity": "sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/inline-style-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", - "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" - }, - "node_modules/inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^6.0.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/inquirer-autosubmit-prompt": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/inquirer-autosubmit-prompt/-/inquirer-autosubmit-prompt-0.2.0.tgz", - "integrity": "sha512-mzNrusCk5L6kSzlN0Ioddn8yzrhYNLli+Sn2ZxMuLechMYAzakiFCIULxsxlQb5YKzthLGfrFACcWoAvM7p04Q==", - "dependencies": { - "chalk": "^2.4.1", - "inquirer": "^6.2.1", - "rxjs": "^6.3.3" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/inquirer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", - "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", - "dependencies": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==" - }, - "node_modules/inquirer-autosubmit-prompt/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/inquirer-autosubmit-prompt/node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" - } + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz", + "integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/inquirer-autosubmit-prompt/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz", + "integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/inquirer-autosubmit-prompt/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz", + "integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/inquirer-autosubmit-prompt/node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "engines": { - "node": ">=4" - } + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz", + "integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/inquirer-autosubmit-prompt/node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz", + "integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/inquirer-autosubmit-prompt/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz", + "integrity": "sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/inquirer-autosubmit-prompt/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.1.tgz", + "integrity": "sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/inquirer-autosubmit-prompt/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz", + "integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/inquirer/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz", + "integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/inquirer/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz", + "integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/inquirer/node_modules/escape-string-regexp": { + "node_modules/@types/estree": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true }, - "node_modules/inquirer/node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/@types/js-beautify": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@types/js-beautify/-/js-beautify-1.14.3.tgz", + "integrity": "sha512-FMbQHz+qd9DoGvgLHxeqqVPaNRffpIu5ZjozwV8hf9JAGpIOzuAf4wGbRSo8LNITHqGjmmVjaMggTT5P4v4IHg==", + "dev": true }, - "node_modules/inquirer/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true }, - "node_modules/inquirer/node_modules/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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } + "node_modules/@types/lodash": { + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", + "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==" }, - "node_modules/inquirer/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "@types/lodash": "*" } }, - "node_modules/irregular-plurals": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", - "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", + "node_modules/@types/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" + "@types/linkify-it": "^5", + "@types/mdurl": "^2" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true }, - "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "node_modules/@vitest/coverage-v8": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.0.3.tgz", + "integrity": "sha512-53d+6jXFdYbasXBmsL6qaGIfcY5eBQq0sP57AjdasOcSiGNj4qxkkpDKIitUNfjxcfAfUfQ8BD0OR2fSey64+g==", + "dev": true, "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.5", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.10", + "magicast": "^0.3.4", + "std-env": "^3.7.0", + "strip-literal": "^2.1.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^1.2.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "2.0.3" } }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node_modules/@vitest/expect": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.3.tgz", + "integrity": "sha512-X6AepoOYePM0lDNUPsGXTxgXZAl3EXd0GYe/MZyVE4HzkUqyUVC6S3PrY5mClDJ6/7/7vALLMV3+xD/Ko60Hqg==", + "dev": true, + "dependencies": { + "@vitest/spy": "2.0.3", + "@vitest/utils": "2.0.3", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/is-error": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", - "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==", - "dev": true - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" + "node_modules/@vitest/pretty-format": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.3.tgz", + "integrity": "sha512-URM4GLsB2xD37nnTyvf6kfObFafxmycCL8un3OC9gaCs5cti2u+5rJdIflZ2fUJUen4NbvF6jCufwViAFLvz1g==", + "dev": true, + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" + "node_modules/@vitest/runner": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.0.3.tgz", + "integrity": "sha512-EmSP4mcjYhAcuBWwqgpjR3FYVeiA4ROzRunqKltWjBfLNs1tnMLtF+qtgd5ClTwkDP6/DGlKJTNa6WxNK0bNYQ==", + "dev": true, + "dependencies": { + "@vitest/utils": "2.0.3", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "node_modules/@vitest/snapshot": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.0.3.tgz", + "integrity": "sha512-6OyA6v65Oe3tTzoSuRPcU6kh9m+mPL1vQ2jDlPdn9IQoUxl8rXhBnfICNOC+vwxWY684Vt5UPgtcA2aPFBb6wg==", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "@vitest/pretty-format": "2.0.3", + "magic-string": "^0.30.10", + "pathe": "^1.1.2" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/@vitest/spy": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.3.tgz", + "integrity": "sha512-sfqyAw/ypOXlaj4S+w8689qKM1OyPOqnonqOc9T91DsoHbfN5mU7FdifWWv3MtQFf0lEUstEwR9L/q/M390C+A==", + "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "tinyspy": "^3.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/is-in-ci": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-0.1.0.tgz", - "integrity": "sha512-d9PXLEY0v1iJ64xLiQMJ51J128EYHAaOR4yZqQi8aHGfw6KgifM3/Viw1oZZ1GCVmb3gBuyhLyHj0HgR2DhSXQ==", - "bin": { - "is-in-ci": "cli.js" - }, - "engines": { - "node": ">=18" + "node_modules/@vitest/utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.3.tgz", + "integrity": "sha512-c/UdELMuHitQbbc/EVctlBaxoYAwQPQdSNwv7z/vHyBKy2edYZaFgptE27BRueZB7eW8po+cllotMNTDpL3HWg==", + "dev": true, + "dependencies": { + "@vitest/pretty-format": "2.0.3", + "estree-walker": "^3.0.3", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "is-docker": "^3.0.0" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "bin": { - "is-inside-container": "cli.js" + "acorn": "bin/acorn" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.4.0" } }, - "node_modules/is-installed-globally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-1.0.0.tgz", - "integrity": "sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==", - "dependencies": { - "global-directory": "^4.0.1", - "is-path-inside": "^4.0.0" - }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "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==", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/is-json": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", - "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==" - }, - "node_modules/is-npm": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", - "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "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==", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, "engines": { - "node": ">=0.12.0" + "node": ">= 8" } }, - "node_modules/is-number-like": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", - "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dependencies": { - "lodash.isfinite": "^3.3.2" + "sprintf-js": "~1.0.2" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "engines": { - "node": ">=8" - } + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "node_modules/is-observable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", - "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "node_modules/array-pull-all-with-glob": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/array-pull-all-with-glob/-/array-pull-all-with-glob-7.0.10.tgz", + "integrity": "sha512-v3rBOs7EP3Ad+D61v8sC98TWg7tiVTbxXLN+UDHOcL3fIt3ZH9YsmMSzlZ6arEUVuSHyDRh6SMnR0BR2wX6M0A==", "dependencies": { - "symbol-observable": "^1.1.0" + "matcher": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=14.18.0" } }, - "node_modules/is-observable/node_modules/symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "node_modules/arrayiffy-if-string": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/arrayiffy-if-string/-/arrayiffy-if-string-5.0.8.tgz", + "integrity": "sha512-v2zOhx1Xc2qhN5FBQP8RZ/TPkXIi2xBnb/EnPMKen+W46JkGsl6pg1RTHtEBaIG+DxkWaf1OZ7MOV96Fz2Jy6w==", "engines": { - "node": ">=0.10.0" + "node": ">=14.18.0" } }, - "node_modules/is-path-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-3.0.0.tgz", - "integrity": "sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==", + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "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, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=12" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-path-inside": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", - "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "node_modules/binaryextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", + "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", + "dependencies": { + "editions": "^6.21.0" + }, "engines": { - "node": ">=12" + "node": ">=4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://bevry.me/fund" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } }, - "node_modules/is-scoped": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-3.0.0.tgz", - "integrity": "sha512-ezxLUq30kiTvP0w/5n9tj4qTOKlrA07Oty1hwTQ+lcqw11x6uc8sp7VRb2OVGRzKfCHZ2A22T5Zsau/Q2Akb0g==", + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "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==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "scoped-regex": "^3.0.0" + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" }, - "engines": { - "node": ">=12" + "bin": { + "browserslist": "cli.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" - }, - "node_modules/is-url-superb": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-5.0.0.tgz", - "integrity": "sha512-jGkG59ra7/JlcV8ap3dsc0M79IgpuFU/obfsSf6X5D0z1NVvFTFuzt4ob7nfBTZEPbTwjGXVKNQDfWfPghapKQ==", + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-whitespace": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-whitespace/-/is-whitespace-0.3.0.tgz", - "integrity": "sha512-RydPhl4S6JwAyj0JJjshWJEFG6hNye3pZFBRZaTUfZFwGHxzppNaNOVgQuS/E/SlhrApuMXrpnK1EEIXfdo3Dg==", + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "node_modules/caniuse-lite": { + "version": "1.0.30001642", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", + "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "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, "dependencies": { - "is-inside-container": "^1.0.0" + "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": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/issue-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/issue-regex/-/issue-regex-4.1.0.tgz", - "integrity": "sha512-X3HBmm7+Th+l4/kMtqwcHHgELD0Lfl0Ina6S3+grr+mKmTxsrM84NAO1UuRPIxIbGLIl3TCEu45S1kdu21HYbQ==", + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "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, "engines": { - "node": ">=8" + "node": ">= 16" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" }, "engines": { - "node": ">=10" + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/jackspeak": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", - "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">=14" + "node": ">= 8.10.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://paulmillr.com/funding/" }, "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "bin": { - "jiti": "bin/jiti.js" + "fsevents": "~2.3.2" } }, - "node_modules/js-beautify": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz", - "integrity": "sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==", + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", "dependencies": { - "config-chain": "^1.1.13", - "editorconfig": "^1.0.4", - "glob": "^10.3.3", - "js-cookie": "^3.0.5", - "nopt": "^7.2.0" - }, - "bin": { - "css-beautify": "js/bin/css-beautify.js", - "html-beautify": "js/bin/html-beautify.js", - "js-beautify": "js/bin/js-beautify.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", - "engines": { - "node": ">=14" - } - }, - "node_modules/js-string-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", - "dev": true, - "engines": { - "node": ">= 0.8" + "consola": "^3.2.3" } }, - "node_modules/js-tokens": { + "node_modules/cli-cursor": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "restore-cursor": "^4.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "engines": { + "node": ">=6" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/juice": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/juice/-/juice-10.0.0.tgz", - "integrity": "sha512-9f68xmhGrnIi6DBkiiP3rUrQN33SEuaKu1+njX6VgMP+jwZAsnT33WIzlrWICL9matkhYu3OyrqSUP55YTIdGg==", + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dependencies": { - "cheerio": "^1.0.0-rc.12", - "commander": "^6.1.0", - "mensch": "^0.3.4", - "slick": "^1.12.2", - "web-resource-inliner": "^6.0.1" - }, - "bin": { - "juice": "bin/juice" + "string-width": "^4.2.0" }, "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/juice/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "engines": { - "node": ">= 6" + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/codsen-utils": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/codsen-utils/-/codsen-utils-1.6.4.tgz", + "integrity": "sha512-PDyvQ5f2PValmqZZIJATimcokDt4JjIev8cKbZgEOoZm+U1IJDYuLeTcxZPQdep99R/X0RIlQ6ReQgPOVnPbNw==", "dependencies": { - "json-buffer": "3.0.1" + "rfdc": "^1.3.1" + }, + "engines": { + "node": ">=14.18.0" } }, - "node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "is-buffer": "^1.1.5" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/ky": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ky/-/ky-1.4.0.tgz", - "integrity": "sha512-tPhhoGUiEiU/WXR4rt8klIoLdnTtyu+9jVKHd/wauEjYud32jyn63mzKWQweaQrHWxBQtYoVtdcEnYX1LosnFQ==", - "engines": { - "node": ">=18" + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-shorthand-hex-to-six-digit": { + "version": "5.0.16", + "resolved": "https://registry.npmjs.org/color-shorthand-hex-to-six-digit/-/color-shorthand-hex-to-six-digit-5.0.16.tgz", + "integrity": "sha512-feDk6pY/BqYmVV/ZJNB9XJ6CzO0RzE4ZcZ8OHpny273C8LatYQIJA3yUQP+oZ9e/F8BjIqsmppvWPMy6VI7ZSQ==", + "dependencies": { + "codsen-utils": "^1.6.4", + "hex-color-regex": "^1.1.0", + "rfdc": "^1.3.1" }, - "funding": { - "url": "https://github.com/sindresorhus/ky?sponsor=1" + "engines": { + "node": ">=14.18.0" } }, - "node_modules/latest-version": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", - "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { - "package-json": "^8.1.0" + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/limiter": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", - "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dependencies": { - "uc.micro": "^2.0.0" + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", - "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "node_modules/condense-newlines": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/condense-newlines/-/condense-newlines-0.2.1.tgz", + "integrity": "sha512-P7X+QL9Hb9B/c8HI5BFFKmjgBu2XpQuF98WZ9XkO+dBGgk5XgwiQz7o1SmpglNWId3581UcS0SFAWfoIhMHPfg==", "dependencies": { - "@samverschueren/stream-to-observable": "^0.3.0", - "is-observable": "^1.1.0", - "is-promise": "^2.1.0", - "is-stream": "^1.1.0", - "listr-silent-renderer": "^1.1.1", - "listr-update-renderer": "^0.5.0", - "listr-verbose-renderer": "^0.5.0", - "p-map": "^2.0.0", - "rxjs": "^6.3.3" + "extend-shallow": "^2.0.1", + "is-whitespace": "^0.3.0", + "kind-of": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/listr-input": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/listr-input/-/listr-input-0.2.1.tgz", - "integrity": "sha512-oa8iVG870qJq+OuuMK3DjGqFcwsK1SDu+kULp9kEq09TY231aideIZenr3lFOQdASpAr6asuyJBbX62/a3IIhg==", + "node_modules/condense-newlines/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "dependencies": { - "inquirer": "^7.0.0", - "inquirer-autosubmit-prompt": "^0.2.0", - "rxjs": "^6.5.3", - "through": "^2.3.8" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/listr-input/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==" }, - "node_modules/listr-input/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } }, - "node_modules/listr-input/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", "engines": { - "node": ">=0.8.0" + "node": "^14.18.0 || >=16.10.0" } }, - "node_modules/listr-input/node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "escape-string-regexp": "^1.0.5" + "safe-buffer": "5.2.1" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/listr-input/node_modules/inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { - "node": ">=8.0.0" + "node": ">= 0.6" } }, - "node_modules/listr-input/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/listr-input/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, + "node_modules/create-maizzle": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/create-maizzle/-/create-maizzle-0.3.0.tgz", + "integrity": "sha512-QLp6FCpGqGil6ktA/MQPdkd7DeRJLg5FCM7V5+QluBlDYf/bdvw+Vcyc6J0qkCdNhELIJ026tj3YZTdgbT29mw==", "dependencies": { - "tslib": "^1.9.0" + "@clack/prompts": "^0.7.0", + "degit": "^2.8.4", + "nypm": "^0.3.6", + "picocolors": "^1.0.0" }, - "engines": { - "npm": ">=2.0.0" + "bin": { + "create-maizzle": "bin/create-maizzle.mjs" } }, - "node_modules/listr-input/node_modules/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==", + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/listr-input/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "dependencies": { - "ansi-regex": "^5.0.1" + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "engines": { - "node": ">=8" + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/listr-input/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" }, - "node_modules/listr-silent-renderer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, "engines": { "node": ">=4" } }, - "node_modules/listr-update-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", - "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^2.3.0", - "strip-ansi": "^3.0.1" + "ms": "2.1.2" }, "engines": { - "node": ">=6" + "node": ">=6.0" }, - "peerDependencies": { - "listr": "^0.14.2" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/listr-update-renderer/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "node_modules/decode-uri-component": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", + "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==", "engines": { - "node": ">=0.10.0" + "node": ">=14.16" } }, - "node_modules/listr-update-renderer/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "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, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/listr-update-renderer/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/listr-update-renderer/node_modules/cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==", - "dependencies": { - "slice-ansi": "0.0.4", - "string-width": "^1.0.1" + "node": ">= 0.4" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/listr-update-renderer/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==" }, - "node_modules/listr-update-renderer/node_modules/figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", - "dependencies": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "node_modules/degit": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/degit/-/degit-2.8.4.tgz", + "integrity": "sha512-vqYuzmSA5I50J882jd+AbAhQtgK6bdKUJIex1JNfEUPENCgYsxugzKVZlFyMwV4i06MmnV47/Iqi5Io86zf3Ng==", + "bin": { + "degit": "degit" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/listr-update-renderer/node_modules/indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", - "engines": { - "node": ">=4" + "node": ">=8.0.0" } }, - "node_modules/listr-update-renderer/node_modules/is-fullwidth-code-point": { + "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", - "dependencies": { - "number-is-nan": "^1.0.0" - }, + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.4.0" } }, - "node_modules/listr-update-renderer/node_modules/log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ==", - "dependencies": { - "chalk": "^1.0.0" - }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/listr-update-renderer/node_modules/slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/listr-update-renderer/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "asap": "^2.0.0", + "wrappy": "1" } }, - "node_modules/listr-update-renderer/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dependencies": { - "ansi-regex": "^2.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/listr-update-renderer/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "engines": { - "node": ">=0.8.0" - } + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] }, - "node_modules/listr-verbose-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", - "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dependencies": { - "chalk": "^2.4.1", - "cli-cursor": "^2.1.0", - "date-fns": "^1.27.2", - "figures": "^2.0.0" + "domelementtype": "^2.3.0" }, "engines": { - "node": ">=4" + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/listr-verbose-renderer/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "dependencies": { - "color-convert": "^1.9.0" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/listr-verbose-renderer/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/editions": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.21.0.tgz", + "integrity": "sha512-ofkXJtn7z0urokN62DI3SBo/5xAtF0rR7tn+S/bSYV79Ka8pTajIIl+fFQ1q88DQEImymmo97M4azY3WX/nUdg==", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "version-range": "^4.13.0" }, "engines": { "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" } }, - "node_modules/listr-verbose-renderer/node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", "dependencies": { - "restore-cursor": "^2.0.0" + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" }, "engines": { - "node": ">=4" + "node": ">=14" } }, - "node_modules/listr-verbose-renderer/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/editorconfig/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "engines": { - "node": ">=0.8.0" + "node": ">=14" } }, - "node_modules/listr-verbose-renderer/node_modules/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.827", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", + "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==" + }, + "node_modules/email-comb": { + "version": "7.0.21", + "resolved": "https://registry.npmjs.org/email-comb/-/email-comb-7.0.21.tgz", + "integrity": "sha512-7Kb9XkAYdegTCNqi1O4VUg/vQtlr/nEnXzH9xD60+QtrvFc23mApMizmHHIeo0aCmXKWmx0MbTVVhpUuKWs8CQ==", "dependencies": { - "escape-string-regexp": "^1.0.5" + "array-pull-all-with-glob": "^7.0.10", + "codsen-utils": "^1.6.4", + "html-crush": "^6.0.19", + "matcher": "^5.0.0", + "ranges-apply": "^7.0.16", + "ranges-push": "^7.0.15", + "regex-empty-conditional-comments": "^3.0.7", + "string-extract-class-names": "^8.0.18", + "string-left-right": "^6.0.17", + "string-match-left-right": "^9.0.19", + "string-range-expander": "^4.0.14", + "string-uglify": "^3.0.11" }, "engines": { - "node": ">=4" + "node": ">=14.18.0" } }, - "node_modules/listr-verbose-renderer/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/listr-verbose-renderer/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/listr-verbose-renderer/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "dependencies": { - "mimic-fn": "^1.0.0" - }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "engines": { - "node": ">=4" - } - }, - "node_modules/listr-verbose-renderer/node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "node": ">=0.12" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/listr-verbose-renderer/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dependencies": { - "has-flag": "^3.0.0" + "get-intrinsic": "^1.2.4" }, "engines": { - "node": ">=4" - } - }, - "node_modules/listr/node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "node_modules/listr/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/listr/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/listr/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dependencies": { - "tslib": "^1.9.0" + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "npm": ">=2.0.0" + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, - "node_modules/listr/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", - "dev": true, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, + "node_modules/escape-goat": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz", + "integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==", "engines": { "node": ">=10" }, @@ -5006,410 +2347,384 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" - }, - "node_modules/lodash.intersection": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.intersection/-/lodash.intersection-4.4.0.tgz", - "integrity": "sha512-N+L0cCfnqMv6mxXtSPeKt+IavbOBBSiAEkKyLasZ8BVcP9YXQgxLO12oPR8OyURwKV8l5vJKiE1M8aS70heuMg==" - }, - "node_modules/lodash.isfinite": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", - "integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" - }, - "node_modules/lodash.pull": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.pull/-/lodash.pull-4.1.0.tgz", - "integrity": "sha512-EM7CVTzXfkTyusQdN7mgGPh2ZfkKfQ5lA9U+X7NNDeEgKEaO65dB5Kh8+Ppap0X1wQOndPjKP/VVTis7hFvkzg==" - }, - "node_modules/lodash.zip": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", - "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==" + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, - "node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", - "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" - }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "engines": { - "node": ">=18" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==", - "dependencies": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { "node": ">=4" } }, - "node_modules/log-update/node_modules/ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "engines": { - "node": ">=4" + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" } }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { - "node": ">=4" + "node": ">= 0.6" } }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dependencies": { - "restore-cursor": "^2.0.0" + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "engines": { - "node": ">=4" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/log-update/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, "engines": { - "node": ">=4" + "node": ">= 0.10.0" } }, - "node_modules/log-update/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" + "ms": "2.0.0" } }, - "node_modules/log-update/node_modules/restore-cursor": { + "node_modules/express/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "is-extendable": "^0.1.0" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/log-update/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=4" + "node": ">=8.6.0" } }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" + "reusify": "^1.0.4" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==", + "node_modules/fclone": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", + "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" + "to-regex-range": "^5.0.1" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "engines": { "node": ">=8" } }, - "node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, + "node_modules/filter-obj": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", + "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { - "p-defer": "^1.0.0" + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" + "ms": "2.0.0" } }, - "node_modules/markdown-it/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/matcher": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", - "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", - "dev": true, + "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==", "dependencies": { - "escape-string-regexp": "^5.0.0" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/md5-hex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", - "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, "dependencies": { - "blueimp-md5": "^2.10.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" - }, - "node_modules/mem": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/mem/-/mem-9.0.2.tgz", - "integrity": "sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A==", + "node_modules/formidable": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", + "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==", "dev": true, "dependencies": { - "map-age-cleaner": "^0.1.3", - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12.20" + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0" }, "funding": { - "url": "https://github.com/sindresorhus/mem?sponsor=1" + "url": "https://ko-fi.com/tunnckoCore/commissions" } }, - "node_modules/mensch": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.4.tgz", - "integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==" - }, - "node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { - "node": ">= 8" + "node": ">= 0.6" } }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8.6" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "bin": { - "mime": "cli.js" + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": "*" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "engines": { - "node": ">=18" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "engines": { - "node": ">=4" + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { - "node": ">=4" + "node": ">= 6" } }, - "node_modules/minimatch": { + "node_modules/glob/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", @@ -5423,351 +2738,279 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mitt": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", - "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==" - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=6.0" } }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/new-github-release-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", - "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "type-fest": "^2.5.1" + "es-define-property": "^1.0.0" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/new-github-release-url/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "engines": { - "node": ">=12.20" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { - "whatwg-url": "^5.0.0" + "function-bind": "^1.1.2" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "node_modules/hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" }, - "node_modules/nofilter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", - "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", "dev": true, "engines": { - "node": ">=12.19" + "node": ">=8" } }, - "node_modules/nopt": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", - "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "node_modules/html-crush": { + "version": "6.0.19", + "resolved": "https://registry.npmjs.org/html-crush/-/html-crush-6.0.19.tgz", + "integrity": "sha512-H44ysZgliZnmOAkfFbo4jLZx3AAuSOfysZMBsR0bgTatI6P20MZ/yXPzD2XOUg0OZOtI71rF+0JQBsOUKeHP3g==", "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" + "codsen-utils": "^1.6.4", + "ranges-apply": "^7.0.16", + "ranges-push": "^7.0.15", + "string-left-right": "^6.0.17", + "string-match-left-right": "^9.0.19", + "string-range-expander": "^4.0.14", + "test-mixer": "^4.1.14" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=14.18.0" } }, - "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", - "dependencies": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=16.17.0" } }, - "node_modules/np": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/np/-/np-10.0.6.tgz", - "integrity": "sha512-173uUvFDmHtme1ra3JDMjYzqa94XHJAHoNae6lCA4mJWMIz073x9FE2O8SHMMjKXlHetRdOXufLUjdimRxXR3A==", + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dependencies": { - "chalk": "^5.3.0", - "chalk-template": "^1.1.0", - "cosmiconfig": "^8.3.6", - "del": "^7.1.0", - "escape-goat": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "execa": "^8.0.1", - "exit-hook": "^4.0.0", - "github-url-from-git": "^1.5.0", - "hosted-git-info": "^7.0.1", - "ignore-walk": "^6.0.4", - "import-local": "^3.1.0", - "inquirer": "^9.2.15", - "is-installed-globally": "^1.0.0", - "is-interactive": "^2.0.0", - "is-scoped": "^3.0.0", - "issue-regex": "^4.1.0", - "listr": "^0.14.3", - "listr-input": "^0.2.1", - "log-symbols": "^6.0.0", - "meow": "^13.2.0", - "new-github-release-url": "^2.0.0", - "npm-name": "^8.0.0", - "onetime": "^7.0.0", - "open": "^10.0.4", - "p-memoize": "^7.1.1", - "p-timeout": "^6.1.2", - "path-exists": "^5.0.0", - "pkg-dir": "^8.0.0", - "read-package-up": "^11.0.0", - "read-pkg": "^9.0.1", - "rxjs": "^7.8.1", - "semver": "^7.6.0", - "symbol-observable": "^4.0.0", - "terminal-link": "^3.0.0", - "update-notifier": "^7.0.0" - }, - "bin": { - "np": "source/cli.js" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "git": ">=2.11.0", - "node": ">=18", - "npm": ">=9", - "pnpm": ">=8", - "yarn": ">=1.7.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/np?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/np/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/import-from-esm": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-1.3.4.tgz", + "integrity": "sha512-7EyUlPFC0HOlBDpUFGfYstsU7XHxZJKAAMzCT8wZ0hMW7b+hG51LIKTDcsgtz8Pu6YC0HqRVbX+rVUtsGMUKvg==", + "dependencies": { + "debug": "^4.3.4", + "import-meta-resolve": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=16.20" } }, - "node_modules/np/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/np/node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "engines": { - "node": ">= 12" - } + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/np/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "node_modules/np/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, + "node_modules/inline-style-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">= 0.10" } }, - "node_modules/np/node_modules/execa/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dependencies": { - "mimic-fn": "^4.0.0" + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/np/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-core-module": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "dependencies": { + "hasown": "^2.0.2" + }, "engines": { - "node": ">=16" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/np/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "engines": { - "node": ">=16.17.0" + "node": ">=0.10.0" } }, - "node_modules/np/node_modules/inquirer": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.1.tgz", - "integrity": "sha512-A5IdVr1I04XqPlwrGgTJMKmzRg5ropqNpSeqo0vj1ZmluSCNSFaPZz4eazdPrhVcZfej7fCEYvD2NYa1KjkTJA==", - "dependencies": { - "@inquirer/figures": "^1.0.3", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "external-editor": "^3.1.0", - "mute-stream": "1.0.0", - "ora": "^5.4.1", - "picocolors": "^1.0.1", - "run-async": "^3.0.0", - "rxjs": "^7.8.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0" - }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/np/node_modules/is-fullwidth-code-point": { + "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", @@ -5775,32 +3018,45 @@ "node": ">=8" } }, - "node_modules/np/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/np/node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "node_modules/is-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", + "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=0.12.0" } }, - "node_modules/np/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dependencies": { - "path-key": "^4.0.0" - }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -5808,13 +3064,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/np/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dependencies": { - "mimic-function": "^5.0.0" - }, + "node_modules/is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", "engines": { "node": ">=18" }, @@ -5822,18 +3075,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/np/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/np/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "node_modules/is-url-superb": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-6.1.0.tgz", + "integrity": "sha512-LXdhGlYqUPdvEyIhWPEEwYYK3yrUiPcBjmFGlZNv1u5GtIL5qQRf7ddDyPNAvsMFqdzS923FROpTQU97tLe3JQ==", "engines": { "node": ">=12" }, @@ -5841,670 +3086,740 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/np/node_modules/run-async": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", - "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "node_modules/is-whitespace": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-whitespace/-/is-whitespace-0.3.0.tgz", + "integrity": "sha512-RydPhl4S6JwAyj0JJjshWJEFG6hNye3pZFBRZaTUfZFwGHxzppNaNOVgQuS/E/SlhrApuMXrpnK1EEIXfdo3Dg==", "engines": { - "node": ">=0.12.0" + "node": ">=0.10.0" } }, - "node_modules/np/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==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, "engines": { - "node": ">=14" + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=10" } }, - "node_modules/np/node_modules/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==", + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/np/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/np/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "node_modules/istextorbinary": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", + "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "dependencies": { + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" + }, "engines": { - "node": ">=12" + "node": ">=4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://bevry.me/fund" } }, - "node_modules/npm-name": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/npm-name/-/npm-name-8.0.0.tgz", - "integrity": "sha512-DIuCGcKYYhASAZW6Xh/tiaGMko8IHOHe0n3zOA7SzTi0Yvy00x8L7sa5yNiZ75Ny58O/KeRtNouy8Ut6gPbKiw==", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dependencies": { - "is-scoped": "^3.0.0", - "is-url-superb": "^6.1.0", - "ky": "^1.2.0", - "lodash.zip": "^4.2.0", - "org-regex": "^1.0.0", - "p-map": "^7.0.1", - "registry-auth-token": "^5.0.2", - "registry-url": "^6.0.1", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": ">=18" + "@isaacs/cliui": "^8.0.2" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/npm-name/node_modules/is-url-superb": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-6.1.0.tgz", - "integrity": "sha512-LXdhGlYqUPdvEyIhWPEEwYYK3yrUiPcBjmFGlZNv1u5GtIL5qQRf7ddDyPNAvsMFqdzS923FROpTQU97tLe3JQ==", - "engines": { - "node": ">=12" + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-beautify": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz", + "integrity": "sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==", + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.3.3", + "js-cookie": "^3.0.5", + "nopt": "^7.2.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" } }, - "node_modules/npm-name/node_modules/p-map": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.2.tgz", - "integrity": "sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==", + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", "engines": { - "node": ">=18" + "node": ">=14" + } + }, + "node_modules/js-tokens": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", + "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/juice": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/juice/-/juice-10.0.0.tgz", + "integrity": "sha512-9f68xmhGrnIi6DBkiiP3rUrQN33SEuaKu1+njX6VgMP+jwZAsnT33WIzlrWICL9matkhYu3OyrqSUP55YTIdGg==", "dependencies": { - "path-key": "^3.0.0" + "cheerio": "^1.0.0-rc.12", + "commander": "^6.1.0", + "mensch": "^0.3.4", + "slick": "^1.12.2", + "web-resource-inliner": "^6.0.1" + }, + "bin": { + "juice": "bin/juice" }, "engines": { - "node": ">=8" + "node": ">=10.0.0" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "node_modules/juice/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "engines": { + "node": ">= 6" } }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "engines": { "node": ">=0.10.0" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "engines": { - "node": ">=0.10.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/object-boolean-combinations": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-boolean-combinations/-/object-boolean-combinations-4.1.0.tgz", - "integrity": "sha512-AkiONPtYhPo7B2X/0sohAlFsIBCFr9HElIe34edEFJIk5XSYc/N/06SJyQWeq6L/gFuvnUTa0/TnrqE0Ge3ncA==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dependencies": { - "@babel/runtime": "^7.14.0", - "lodash.clonedeep": "^4.5.0", - "lodash.intersection": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.pull": "^4.1.0" + "uc.micro": "^2.0.0" } }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "engines": { - "node": ">= 6" - } + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dependencies": { - "mimic-fn": "^2.1.0" + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/onetime/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/magicast": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", + "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.24.4", + "@babel/types": "^7.24.0", + "source-map-js": "^1.2.0" } }, - "node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/opn": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", - "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dependencies": { - "is-wsl": "^1.1.0" + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, - "engines": { - "node": ">=4" + "bin": { + "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/opn/node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", - "engines": { - "node": ">=4" - } + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/matcher": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", + "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "escape-string-regexp": "^5.0.0" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/ora/node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "node_modules/mensch": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.4.tgz", + "integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==" + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/ora/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/ora/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8.6" } }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/org-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/org-regex/-/org-regex-1.0.0.tgz", - "integrity": "sha512-7bqkxkEJwzJQUAlyYniqEZ3Ilzjh0yoa62c7gL6Ijxj5bEpPL+8IE1Z0PFj0ywjjXQcdrwR51g9MIcLezR0hKQ==", + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", - "dev": true, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "engines": { "node": ">=4" } }, - "node_modules/p-event": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-5.0.1.tgz", - "integrity": "sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==", - "dev": true, + "node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dependencies": { - "p-timeout": "^5.0.2" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/p-event/node_modules/p-timeout": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", - "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", - "dev": true, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, + "node_modules/mlly": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", + "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, + "node_modules/morphdom": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/morphdom/-/morphdom-2.7.3.tgz", + "integrity": "sha512-rvGK92GxSuPEZLY8D/JH07cG3BxyA+/F0Bxg32OoGAEFFhGWA3OqVpqPZlOgZTCR52clXrmz+z2pYSJ6gOig1w==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "dependencies": { - "p-limit": "^3.0.2" + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/p-map": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", - "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", - "dependencies": { - "aggregate-error": "^4.0.0" - }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/p-memoize": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/p-memoize/-/p-memoize-7.1.1.tgz", - "integrity": "sha512-DZ/bONJILHkQ721hSr/E9wMz5Am/OTJ9P6LhLFo2Tu+jL8044tgc9LwHO8g4PiaYePnlVVRAJcKmgy8J9MVFrA==", + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { - "mimic-fn": "^4.0.0", - "type-fest": "^3.0.0" + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">=14.16" + "node": "4.x || >=6.0.0" }, - "funding": { - "url": "https://github.com/sindresorhus/p-memoize?sponsor=1" - } - }, - "node_modules/p-memoize/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "engines": { - "node": ">=14.16" + "peerDependencies": { + "encoding": "^0.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/p-timeout": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", - "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", - "engines": { - "node": ">=14.16" + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "dependencies": { + "abbrev": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/package-json": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", - "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dependencies": { - "got": "^12.1.0", - "registry-auth-token": "^5.0.1", - "registry-url": "^6.0.0", - "semver": "^7.3.7" + "path-key": "^4.0.0" }, "engines": { - "node": ">=14.16" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "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==" - }, - "node_modules/package-json/node_modules/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "engines": { - "node": ">=14.16" + "node": ">=12" }, "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/package-json/node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dependencies": { - "defer-to-connect": "^2.0.1" + "boolbase": "^1.0.0" }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/package-json/node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "engines": { - "node": ">=14.16" + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/package-json/node_modules/cacheable-request": { - "version": "10.2.14", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "node_modules/nypm": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.9.tgz", + "integrity": "sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==", "dependencies": { - "@types/http-cache-semantics": "^4.0.2", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.3", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" + "citty": "^0.1.6", + "consola": "^3.2.3", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + }, + "bin": { + "nypm": "dist/cli.mjs" }, "engines": { - "node": ">=14.16" + "node": "^14.16.0 || >=16.10.0" } }, - "node_modules/package-json/node_modules/got": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", - "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/package-json/node_modules/http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "node_modules/object-boolean-combinations": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/object-boolean-combinations/-/object-boolean-combinations-6.1.5.tgz", + "integrity": "sha512-SO/w6lYb3XoMZ8qo+6PsOgVUpixc5qUEvZg2m7a4LFG6T1FOKbMAHBPrYs3DcIpkbSAFbf7Zug/4peT/lYz31Q==", "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" + "codsen-utils": "^1.6.4", + "rfdc": "^1.3.1" }, "engines": { - "node": ">=10.19.0" + "node": ">=14.18.0" } }, - "node_modules/package-json/node_modules/lowercase-keys": { + "node_modules/object-hash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/package-json/node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/package-json/node_modules/normalize-url": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", - "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", - "engines": { - "node": ">=14.16" + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 0.8" } }, - "node_modules/package-json/node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "engines": { - "node": ">=12.20" + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" } }, - "node_modules/package-json/node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dependencies": { - "lowercase-keys": "^3.0.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/ora": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz", + "integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==", "dependencies": { - "callsites": "^3.0.0" + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parent-module/node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-ms": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-3.0.0.tgz", - "integrity": "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "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==" }, "node_modules/parse5": { "version": "7.1.2", @@ -6526,31 +3841,15 @@ "parse5": "^7.0.0" }, "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, "node_modules/path-key": { @@ -6581,12 +3880,23 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, "engines": { - "node": ">=8" + "node": ">= 14.16" } }, "node_modules/picocolors": { @@ -6621,144 +3931,14 @@ "node": ">= 6" } }, - "node_modules/pkg-conf": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-4.0.0.tgz", - "integrity": "sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==", - "dev": true, - "dependencies": { - "find-up": "^6.0.0", - "load-json-file": "^7.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/pkg-conf/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-8.0.0.tgz", - "integrity": "sha512-4peoBq4Wks0riS0z8741NVv+/8IiTvqnZAr8QGgtdifrtpdXbNw/FxRS1l6NFqm4EMzuS0EDqNNx4XGaz8cuyQ==", - "dependencies": { - "find-up-simple": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/plur": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", - "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", - "dev": true, - "dependencies": { - "irregular-plurals": "^3.3.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/portscanner": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", - "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", + "node_modules/pkg-types": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.3.tgz", + "integrity": "sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==", "dependencies": { - "async": "^2.6.0", - "is-number-like": "^1.0.3" - }, - "engines": { - "node": ">=0.4", - "npm": ">=1.0.0" + "confbox": "^0.1.7", + "mlly": "^1.7.1", + "pathe": "^1.1.2" } }, "node_modules/postcss": { @@ -6788,17 +3968,45 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-custom-properties": { + "version": "13.3.12", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.3.12.tgz", + "integrity": "sha512-oPn/OVqONB2ZLNqN185LDyaVByELAA/u3l2CS2TS16x2j2XsmV4kd8U49+TMxmUsEU9d8fB/I10E6U7kB0L1BA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/cascade-layer-name-parser": "^1.0.13", + "@csstools/css-parser-algorithms": "^2.7.1", + "@csstools/css-tokenizer": "^2.4.1", + "@csstools/utilities": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", + "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" }, "peerDependencies": { "postcss": "^8.0.0" @@ -6823,9 +4031,9 @@ } }, "node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", "funding": [ { "type": "opencollective", @@ -6837,46 +4045,42 @@ } ], "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" + "lilconfig": "^3.1.1" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { + "jiti": ">=1.21.0", "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { + "jiti": { + "optional": true + }, "postcss": { "optional": true }, - "ts-node": { + "tsx": { + "optional": true + }, + "yaml": { "optional": true } } }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, "node_modules/postcss-merge-longhand": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz", - "integrity": "sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-7.0.2.tgz", + "integrity": "sha512-06vrW6ZWi9qeP7KMS9fsa9QW56+tIMW55KYqF7X3Ccn+NI2pIgPV6gFfvXTMQ05H90Y5DvnCDPZ2IuHa30PMUg==", "dependencies": { "postcss-value-parser": "^4.2.0", - "stylehacks": "^6.1.1" + "stylehacks": "^7.0.2" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" @@ -6926,9 +4130,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", - "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", + "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -6963,17 +4167,22 @@ } }, "node_modules/posthtml-base-url": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/posthtml-base-url/-/posthtml-base-url-2.0.2.tgz", - "integrity": "sha512-4kHKNZe+zYfr4uz3HeoVRei7XvuSu9tgqgYYr2hZpQw8s/RUV3J6wHdmL4B4ZQmOvN9DnbEeaRYrUyn9x5kpXg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/posthtml-base-url/-/posthtml-base-url-3.1.2.tgz", + "integrity": "sha512-HJln2LRk2lTFgjo3pVNkU2ZCYi5BN20cwiApargxA6MtG/viDmxH70kktys7bMTFi6uIHMo8o45o1UhmWe0VRQ==", "dependencies": { - "is-url-superb": "^5.0.0", - "lodash.merge": "^4.6.2", - "postcss": "^8.4.6", - "srcset": "^4.0.0" + "defu": "^6.1.4", + "is-url-superb": "^6.1.0", + "pathe": "^1.1.2", + "postcss": "^8.4.35", + "postcss-safe-parser": "^7.0.0", + "srcset": "^5.0.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=18" + }, + "peerDependencies": { + "posthtml": "^0.16.6" } }, "node_modules/posthtml-component": { @@ -6993,24 +4202,6 @@ "node": ">=10" } }, - "node_modules/posthtml-component/node_modules/htmlparser2": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", - "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.1.0", - "entities": "^4.5.0" - } - }, "node_modules/posthtml-component/node_modules/posthtml-attrs-parser": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/posthtml-attrs-parser/-/posthtml-attrs-parser-0.1.2.tgz", @@ -7019,17 +4210,6 @@ "node": ">=16.0.0" } }, - "node_modules/posthtml-component/node_modules/posthtml-parser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.12.0.tgz", - "integrity": "sha512-OzpgZVxgSP85jSPeMysDh2PUWpr1V0DzrulCyEV5Kr5FBrwIpUI7S8xS3vVeEscaYhzBBnHjIroftzHI4IxKBA==", - "dependencies": { - "htmlparser2": "^9.0.0" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/posthtml-content": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/posthtml-content/-/posthtml-content-2.1.0.tgz", @@ -7141,46 +4321,27 @@ "node": ">=12" } }, - "node_modules/posthtml-extend": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/posthtml-extend/-/posthtml-extend-0.6.5.tgz", - "integrity": "sha512-4GUJaGViVfzthUHDUNxdb4Et4VeRNIJ+v3bz0Zsa7UZney6xcqBOtWsE71P31TbZ3g94LAZfQb+HOQZLXZKyCQ==", - "dependencies": { - "deepmerge": "^4.2.2", - "posthtml": "^0.16.5", - "posthtml-expressions": "^1.10.0", - "posthtml-parser": "^0.11.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/posthtml-extra-attributes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/posthtml-extra-attributes/-/posthtml-extra-attributes-2.0.0.tgz", - "integrity": "sha512-hsgcYtvu9v1zGTtUE+KPFLueiz72gdZiKD9CRlTCQXB2f9sDYPqWLacbzm21DVrD6cpQ4aemZLZjkectehS2hQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/posthtml-extra-attributes/-/posthtml-extra-attributes-3.1.0.tgz", + "integrity": "sha512-7zLEzb6eIE/h3UL+nX6RKRTHVQJ3vs2jH4z/VgOByPVBpq5kvlKlz8dMmrAGAXX24G5Ut7gKpSZuQhSqSO0iOA==", "dependencies": { "lodash.omit": "^4.5.0", - "posthtml-match-helper": "^1.0.1" + "posthtml-match-helper": "^2.0.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/posthtml-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/posthtml-fetch/-/posthtml-fetch-3.0.0.tgz", - "integrity": "sha512-YwvmC8Ze3JOPsC3l368TKkTnwGXERKeA4wcdMhHi4bamEszRPESYvjzIIpRFNzao/r4BtKEN6X5dRoc8RNRDnA==", - "dependencies": { - "got": "^11.8.0", - "is-url": "^1.2.4", - "lodash.merge": "^4.6.2", - "posthtml": "^0.16.4", - "posthtml-expressions": "^1.6.2", - "posthtml-match-helper": "^1.0.1" - }, + "node_modules/posthtml-extra-attributes/node_modules/posthtml-match-helper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/posthtml-match-helper/-/posthtml-match-helper-2.0.2.tgz", + "integrity": "sha512-ehnazjlSwcGa3P2LlFYmTmcnaembTSt9dLWIRRDVHDPidf6InWAr9leKeeLvUXgnU32g6BrFS64Je+c2Ld+l9g==", "engines": { - "node": ">=14.0.0" + "node": ">=18" + }, + "peerDependencies": { + "posthtml": "^0.16.6" } }, "node_modules/posthtml-markdownit": { @@ -7198,7 +4359,37 @@ "node": ">=18" } }, - "node_modules/posthtml-markdownit/node_modules/htmlparser2": { + "node_modules/posthtml-match-helper": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/posthtml-match-helper/-/posthtml-match-helper-1.0.4.tgz", + "integrity": "sha512-Tj9orTIBxHdnraCxoEGjoizsFsTGvukzwcuhOjYQGmDG6gTlaRbMrGgi1J+FwKTN8hsCQENHYY0Deqs9a89BVg==", + "peerDependencies": { + "posthtml": ">=0.5.0" + } + }, + "node_modules/posthtml-mso": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/posthtml-mso/-/posthtml-mso-3.1.0.tgz", + "integrity": "sha512-L2vgoWHLmbl5h/1qYD2I/cQ6X0hfOEpJWmMZcUxIwnrBS3QBIpI6W4W+DQXGQoRVk2OQkN3nIWO5rlOCkludOA==", + "dependencies": { + "posthtml": "^0.16.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/posthtml-parser": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.12.0.tgz", + "integrity": "sha512-OzpgZVxgSP85jSPeMysDh2PUWpr1V0DzrulCyEV5Kr5FBrwIpUI7S8xS3vVeEscaYhzBBnHjIroftzHI4IxKBA==", + "dependencies": { + "htmlparser2": "^9.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/posthtml-parser/node_modules/htmlparser2": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", @@ -7216,48 +4407,84 @@ "entities": "^4.5.0" } }, - "node_modules/posthtml-markdownit/node_modules/posthtml-parser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.12.0.tgz", - "integrity": "sha512-OzpgZVxgSP85jSPeMysDh2PUWpr1V0DzrulCyEV5Kr5FBrwIpUI7S8xS3vVeEscaYhzBBnHjIroftzHI4IxKBA==", + "node_modules/posthtml-postcss": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/posthtml-postcss/-/posthtml-postcss-1.0.2.tgz", + "integrity": "sha512-TOjR9wXMftkJIazb5VjpgbqRkEggb/i+2BbPze9GWpK6M7DouAEWwnR3dX9UDnTWqk5NWDVEannwaIpl3wKCaQ==", + "dependencies": { + "postcss": "^8.4.35", + "postcss-load-config": "^6.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/posthtml-postcss-merge-longhand": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/posthtml-postcss-merge-longhand/-/posthtml-postcss-merge-longhand-3.1.2.tgz", + "integrity": "sha512-Tt+Fugp9099JZijL6sDKPLqgpB+sAhMs0wLxD0XYjQO0I1Zpb98hzAeKlZSh1IAStg2GWNuBdCPGDel4crxwvg==", "dependencies": { - "htmlparser2": "^9.0.0" + "postcss": "^8.1.10", + "postcss-merge-longhand": "^7.0.0", + "postcss-safe-parser": "^7.0.0", + "posthtml": "^0.16.4" }, "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/posthtml-match-helper": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/posthtml-match-helper/-/posthtml-match-helper-1.0.4.tgz", - "integrity": "sha512-Tj9orTIBxHdnraCxoEGjoizsFsTGvukzwcuhOjYQGmDG6gTlaRbMrGgi1J+FwKTN8hsCQENHYY0Deqs9a89BVg==", - "peerDependencies": { - "posthtml": ">=0.5.0" + "node_modules/posthtml-render": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", + "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", + "dependencies": { + "is-json": "^2.0.1" + }, + "engines": { + "node": ">=12" } }, - "node_modules/posthtml-mso": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/posthtml-mso/-/posthtml-mso-3.1.0.tgz", - "integrity": "sha512-L2vgoWHLmbl5h/1qYD2I/cQ6X0hfOEpJWmMZcUxIwnrBS3QBIpI6W4W+DQXGQoRVk2OQkN3nIWO5rlOCkludOA==", + "node_modules/posthtml-safe-class-names": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/posthtml-safe-class-names/-/posthtml-safe-class-names-4.1.0.tgz", + "integrity": "sha512-+eBDQw8LtxMAkTqwDjRT4doBm0pkU10/cx2X63LzFKix4an7w7p7uCcZszz3i3HKvzoSjbuE2iROiFx2h7Fn/A==", "dependencies": { + "css.escape": "^1.5.1", + "postcss": "^8.4.32", + "postcss-safe-parser": "^7.0.0", + "postcss-selector-parser": "^6.0.15", "posthtml": "^0.16.6" }, "engines": { "node": ">=18" } }, - "node_modules/posthtml-parser": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", - "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", + "node_modules/posthtml-url-parameters": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/posthtml-url-parameters/-/posthtml-url-parameters-3.1.0.tgz", + "integrity": "sha512-oyAhXgGQsn30m7AjGHO/W+UzGvpv8p8zGJxDCzMetvHT1vLS/ha1RhvJeOgMWc1Ee26hU+Vhg/FvTvw9pBBmHA==", "dependencies": { - "htmlparser2": "^7.1.1" + "is-url-superb": "^6.1.0", + "posthtml": "^0.16.6", + "posthtml-match-helper": "^2.0.0", + "query-string": "^9.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/posthtml-url-parameters/node_modules/posthtml-match-helper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/posthtml-match-helper/-/posthtml-match-helper-2.0.2.tgz", + "integrity": "sha512-ehnazjlSwcGa3P2LlFYmTmcnaembTSt9dLWIRRDVHDPidf6InWAr9leKeeLvUXgnU32g6BrFS64Je+c2Ld+l9g==", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "posthtml": "^0.16.6" } }, - "node_modules/posthtml-parser/node_modules/dom-serializer": { + "node_modules/posthtml/node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", @@ -7270,7 +4497,7 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/posthtml-parser/node_modules/dom-serializer/node_modules/entities": { + "node_modules/posthtml/node_modules/dom-serializer/node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", @@ -7278,7 +4505,7 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/posthtml-parser/node_modules/domhandler": { + "node_modules/posthtml/node_modules/domhandler": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", @@ -7292,7 +4519,7 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/posthtml-parser/node_modules/domutils": { + "node_modules/posthtml/node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", @@ -7305,7 +4532,7 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/posthtml-parser/node_modules/entities": { + "node_modules/posthtml/node_modules/entities": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", @@ -7316,7 +4543,7 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/posthtml-parser/node_modules/htmlparser2": { + "node_modules/posthtml/node_modules/htmlparser2": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", @@ -7334,105 +4561,17 @@ "entities": "^3.0.1" } }, - "node_modules/posthtml-postcss-merge-longhand": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/posthtml-postcss-merge-longhand/-/posthtml-postcss-merge-longhand-3.1.2.tgz", - "integrity": "sha512-Tt+Fugp9099JZijL6sDKPLqgpB+sAhMs0wLxD0XYjQO0I1Zpb98hzAeKlZSh1IAStg2GWNuBdCPGDel4crxwvg==", - "dependencies": { - "postcss": "^8.1.10", - "postcss-merge-longhand": "^7.0.0", - "postcss-safe-parser": "^7.0.0", - "posthtml": "^0.16.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/posthtml-postcss-merge-longhand/node_modules/postcss-merge-longhand": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-7.0.2.tgz", - "integrity": "sha512-06vrW6ZWi9qeP7KMS9fsa9QW56+tIMW55KYqF7X3Ccn+NI2pIgPV6gFfvXTMQ05H90Y5DvnCDPZ2IuHa30PMUg==", - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^7.0.2" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/posthtml-postcss-merge-longhand/node_modules/stylehacks": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.2.tgz", - "integrity": "sha512-HdkWZS9b4gbgYTdMg4gJLmm7biAUug1qTqXjS+u8X+/pUd+9Px1E+520GnOW3rST9MNsVOVpsJG+mPHNosxjOQ==", - "dependencies": { - "browserslist": "^4.23.1", - "postcss-selector-parser": "^6.1.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/posthtml-render": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", - "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", + "node_modules/posthtml/node_modules/posthtml-parser": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", + "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", "dependencies": { - "is-json": "^2.0.1" + "htmlparser2": "^7.1.1" }, "engines": { "node": ">=12" } }, - "node_modules/posthtml-safe-class-names": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/posthtml-safe-class-names/-/posthtml-safe-class-names-3.0.0.tgz", - "integrity": "sha512-3UepR+RKVp6ZDYmWp/XcdTxDjcdY5DNFQoTvprBYOVLKCUbPZNSIGvaYlPm1TnRvnxb9PVRIhYi6FF0DOtE+JA==", - "dependencies": { - "css.escape": "^1.5.1", - "postcss": "^8.1.10", - "postcss-safe-parser": "^6.0.0", - "postcss-selector-parser": "^6.0.4", - "posthtml": "^0.16.4" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/posthtml-safe-class-names/node_modules/postcss-safe-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", - "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.3.3" - } - }, - "node_modules/posthtml-url-parameters": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/posthtml-url-parameters/-/posthtml-url-parameters-2.1.0.tgz", - "integrity": "sha512-3keKK6HZ4TZ3wQ97Qz27T4O8C5nnC+ZTVVhLrwL7eHVmW5/zV8iR9nQPwM0Bwth6SVPGwx8S8tlgRRyE/Gy/iQ==", - "dependencies": { - "is-url-superb": "^5.0.0", - "posthtml": "^0.16.6", - "posthtml-match-helper": "^1.0.3", - "query-string": "7.1.3" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/pretty": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pretty/-/pretty-2.0.0.tgz", @@ -7446,33 +4585,21 @@ "node": ">=0.10.0" } }, - "node_modules/pretty-ms": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-8.0.0.tgz", - "integrity": "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==", - "dev": true, - "dependencies": { - "parse-ms": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/punycode.js": { @@ -7483,32 +4610,31 @@ "node": ">=6" } }, - "node_modules/pupa": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", - "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dependencies": { - "escape-goat": "^4.0.0" + "side-channel": "^1.0.4" }, "engines": { - "node": ">=12.20" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/query-string": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", - "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.0.0.tgz", + "integrity": "sha512-4EWwcRGsO2H+yzq6ddHcVqkCQ2EFUSfDMEjF8ryp8ReymyZhIuaFRGLomeOQLkrzacMHoyky2HW0Qe30UbzkKw==", "dependencies": { - "decode-uri-component": "^0.2.2", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" + "decode-uri-component": "^0.4.1", + "filter-obj": "^5.1.0", + "split-on-first": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7533,17 +4659,6 @@ } ] }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -7553,223 +4668,92 @@ } }, "node_modules/ranges-apply": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ranges-apply/-/ranges-apply-5.1.0.tgz", - "integrity": "sha512-VF3a0XUuYS/BQHv2RaIyX1K7S1hbfrs64hkGKgPVk0Y7p4XFwSucjTTttrBqmkcmB/PZx5ISTZdxErRZi/89aQ==", - "dependencies": { - "@babel/runtime": "^7.14.0", - "ranges-merge": "^7.1.0" - } - }, - "node_modules/ranges-merge": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/ranges-merge/-/ranges-merge-7.1.0.tgz", - "integrity": "sha512-coTHcyAEIhoEdsBs9f5f+q0rmy7UHvS/5nfuXzuj5oLX/l/tbqM5uxRb6eh8WMdetXia3lK67ZO4tarH4ieulQ==", - "dependencies": { - "@babel/runtime": "^7.14.0", - "ranges-push": "^5.1.0", - "ranges-sort": "^4.1.0" - } - }, - "node_modules/ranges-push": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ranges-push/-/ranges-push-5.1.0.tgz", - "integrity": "sha512-vqGcaGq7GWV1zBa9w83E+dzYkOvE9/3pIRUPvLf12c+mGQCf1nesrkBI7Ob8taN2CC9V1HDSJx0KAQl0SgZftA==", - "dependencies": { - "@babel/runtime": "^7.14.0", - "ranges-merge": "^7.1.0", - "string-collapse-leading-whitespace": "^5.1.0", - "string-trim-spaces-only": "^3.1.0" - } - }, - "node_modules/ranges-sort": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ranges-sort/-/ranges-sort-4.1.0.tgz", - "integrity": "sha512-GOQgk6UtsrfKFeYa53YLiBVnLINwYmOk5l2QZG1csZpT6GdImUwooh+/cRrp7b+fYawZX/rnyA3Ul+pdgQBIzA==", - "dependencies": { - "@babel/runtime": "^7.14.0" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/read-package-up": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", - "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", - "dependencies": { - "find-up-simple": "^1.0.0", - "read-pkg": "^9.0.0", - "type-fest": "^4.6.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-package-up/node_modules/type-fest": { - "version": "4.20.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.20.1.tgz", - "integrity": "sha512-R6wDsVsoS9xYOpy8vgeBlqpdOyzJ12HNfQhC/aAKWM3YoCV9TtunJzh/QpkMgeDhkoynDcw5f1y+qF9yc/HHyg==", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", - "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", - "dependencies": { - "@types/normalize-package-data": "^2.4.3", - "normalize-package-data": "^6.0.0", - "parse-json": "^8.0.0", - "type-fest": "^4.6.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/parse-json": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.1.0.tgz", - "integrity": "sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==", + "version": "7.0.16", + "resolved": "https://registry.npmjs.org/ranges-apply/-/ranges-apply-7.0.16.tgz", + "integrity": "sha512-4rGJHOyA7qatiMDg3vcETkc/TVBPU86/xZRTXff6o7a2neYLmj0EXUUAlhLVuiWAzTPHDPHOQxtk8EDrIF4ohg==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "index-to-position": "^0.1.2", - "type-fest": "^4.7.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "4.20.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.20.1.tgz", - "integrity": "sha512-R6wDsVsoS9xYOpy8vgeBlqpdOyzJ12HNfQhC/aAKWM3YoCV9TtunJzh/QpkMgeDhkoynDcw5f1y+qF9yc/HHyg==", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "ranges-merge": "^9.0.15", + "tiny-invariant": "^1.3.3" + }, + "engines": { + "node": ">=14.18.0" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/ranges-merge": { + "version": "9.0.15", + "resolved": "https://registry.npmjs.org/ranges-merge/-/ranges-merge-9.0.15.tgz", + "integrity": "sha512-hvt4hx0FKIaVfjd1oKx0poL57ljxdL2KHC6bXBrAdsx2iCsH+x7nO/5J0k2veM/isnOcFZKp0ZKkiCjCtzy74Q==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "ranges-push": "^7.0.15", + "ranges-sort": "^6.0.11" }, "engines": { - "node": ">= 6" + "node": ">=14.18.0" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/ranges-push": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/ranges-push/-/ranges-push-7.0.15.tgz", + "integrity": "sha512-gXpBYQ5Umf3uG6jkJnw5ddok2Xfo5p22rAJBLrqzNKa7qkj3q5AOCoxfRPXEHUVaJutfXc9K9eGXdIzdyQKPkw==", "dependencies": { - "picomatch": "^2.2.1" + "codsen-utils": "^1.6.4", + "ranges-sort": "^6.0.11", + "string-collapse-leading-whitespace": "^7.0.7", + "string-trim-spaces-only": "^5.0.10" }, "engines": { - "node": ">=8.10.0" + "node": ">=14.18.0" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + "node_modules/ranges-sort": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/ranges-sort/-/ranges-sort-6.0.11.tgz", + "integrity": "sha512-fhNEG0vGi7bESitNNqNBAfYPdl2efB+1paFlI8BQDCNkruERKuuhG8LkQClDIVqUJLkrmKuOSPQ3xZHqVnVo3Q==", + "engines": { + "node": ">=14.18.0" + } }, - "node_modules/registry-auth-token": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", - "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { - "@pnpm/npm-conf": "^2.1.0" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=14" + "node": ">= 0.8" } }, - "node_modules/registry-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", - "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dependencies": { - "rc": "1.2.8" + "picomatch": "^2.2.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8.10.0" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/regex-empty-conditional-comments": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/regex-empty-conditional-comments/-/regex-empty-conditional-comments-3.0.7.tgz", + "integrity": "sha512-TkjH8FOKIqxfx/zEwus9SVHm7+tyLghPAfb1wiG1h9YMuyUqSWg9kWI+oQxLVUKL6VJOMZVsVJAoQItQrXnnYw==", "engines": { - "node": ">=0.10.0" + "node": ">=14.18.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -7786,97 +4770,47 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dependencies": { - "resolve-from": "^5.0.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/resp-modifier": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz", - "integrity": "sha512-U1+0kWC/+4ncRFYqQWTx/3qkfE6a4B/h3XXgmXypfa0SPZ3t7cbbaFk297PjQS/yov24R18h6OZe6iZwj3NSLw==", - "dependencies": { - "debug": "^2.2.0", - "minimatch": "^3.0.2" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/resp-modifier/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resp-modifier/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" } }, - "node_modules/resp-modifier/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dependencies": { - "brace-expansion": "^1.1.7" + "mimic-fn": "^2.1.0" }, "engines": { - "node": "*" - } - }, - "node_modules/resp-modifier/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dependencies": { - "lowercase-keys": "^2.0.0" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/reusify": { "version": "1.0.4", @@ -7887,78 +4821,44 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/rollup": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz", + "integrity": "sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==", + "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" + "@types/estree": "1.0.5" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" + "bin": { + "rollup": "dist/bin/rollup" }, "engines": { - "node": "*" - } - }, - "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", - "engines": { - "node": ">=18" + "node": ">=18.0.0", + "npm": ">=8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "engines": { - "node": ">=0.12.0" + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.1", + "@rollup/rollup-android-arm64": "4.18.1", + "@rollup/rollup-darwin-arm64": "4.18.1", + "@rollup/rollup-darwin-x64": "4.18.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.1", + "@rollup/rollup-linux-arm-musleabihf": "4.18.1", + "@rollup/rollup-linux-arm64-gnu": "4.18.1", + "@rollup/rollup-linux-arm64-musl": "4.18.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.1", + "@rollup/rollup-linux-riscv64-gnu": "4.18.1", + "@rollup/rollup-linux-s390x-gnu": "4.18.1", + "@rollup/rollup-linux-x64-gnu": "4.18.1", + "@rollup/rollup-linux-x64-musl": "4.18.1", + "@rollup/rollup-win32-arm64-msvc": "4.18.1", + "@rollup/rollup-win32-ia32-msvc": "4.18.1", + "@rollup/rollup-win32-x64-msvc": "4.18.1", + "fsevents": "~2.3.2" } }, "node_modules/run-parallel": { @@ -7983,19 +4883,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha512-CiaiuN6gapkdl+cZUr67W6I8jquN4lkak3vtIsIWCl4XIPP8ffsoyN6/+PuGXnQy8Cu8W2y9Xxh31Rq4M6wUug==" - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -8020,15 +4907,16 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/scoped-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-3.0.0.tgz", - "integrity": "sha512-yEsN6TuxZhZ1Tl9iB81frTNS292m0I/IG7+w8lTvfcJQP2x3vnpOoevjBoE3Np5A6KnZM2+RtVenihj9t6NiYg==", - "engines": { - "node": ">=12" + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=4" } }, "node_modules/semver": { @@ -8042,38 +4930,24 @@ "node": ">=10" } }, - "node_modules/semver-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", - "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" @@ -8087,166 +4961,45 @@ "ms": "2.0.0" } }, - "node_modules/send/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/send/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/send/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "node_modules/send/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/send/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "node_modules/send/node_modules/statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "node_modules/serve-index/node_modules/ms": { + "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "engines": { - "node": ">= 0.6" - } + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" + "parseurl": "~1.3.3", + "send": "0.18.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/server-destroy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", - "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==" + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -8272,38 +5025,45 @@ "node": ">=8" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "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==", "engines": { - "node": ">=12" + "node": ">=14" }, "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, "node_modules/slick": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/slick/-/slick-1.12.2.tgz", @@ -8312,58 +5072,6 @@ "node": "*" } }, - "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", - "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.3.2", - "engine.io": "~6.5.2", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", - "dependencies": { - "debug": "~4.3.4", - "ws": "~8.17.1" - } - }, - "node_modules/socket.io-client": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", - "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.2", - "engine.io-client": "~6.5.2", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -8372,40 +5080,15 @@ "node": ">=0.10.0" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", - "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==" - }, "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", + "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/sprintf-js": { @@ -8414,168 +5097,169 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/srcset": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", - "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-5.0.1.tgz", + "integrity": "sha512-/P1UYbGfJVlxZag7aABNRrulEXAwCSDo7fklafOQrantuPTDmYgijJMks2zusPCVzgW9+4P69mq7w6pYuZpgxw==", "engines": { - "node": ">=12" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true }, "node_modules/statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha512-wuTCPGlJONk/a1kqZ4fQM2+908lC7fa7nPYpTC1EhnvqLX/IICbeP1OZGDtA374trpSq68YubKUMo8oRhN46yg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stream-throttle": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", - "integrity": "sha512-889+B9vN9dq7/vLbGyuHeZ6/ctf5sNuGWsDy89uNxkFTAgzy0eK7+w5fL3KLNRTkLle7EgZGvHUphZW0Q26MnQ==", - "dependencies": { - "commander": "^2.2.0", - "limiter": "^1.0.5" - }, - "bin": { - "throttleproxy": "bin/throttleproxy.js" - }, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">= 0.10.0" + "node": ">= 0.8" } }, - "node_modules/stream-throttle/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", "engines": { - "node": ">=4" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string-character-is-astral-surrogate": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/string-character-is-astral-surrogate/-/string-character-is-astral-surrogate-1.13.0.tgz", - "integrity": "sha512-tKRG2qaGiV2ntUur32sfeAypqTvMUtl+8spEYSJzDsee4lKGMFxQmdHIyCw/uiWWQSve+DQmde2japDYZlQpLA==", - "dependencies": { - "@babel/runtime": "^7.14.0" + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/string-character-is-astral-surrogate/-/string-character-is-astral-surrogate-3.0.9.tgz", + "integrity": "sha512-JAJh6v5WyBsgywv+p9js+wGAayVvTl7XQNM5ahCURTFyt9+wY8Z5iqEe2VILkyqQ3XZS57onxSvhwk6cNvf18w==", + "engines": { + "node": ">=14.18.0" } }, "node_modules/string-collapse-leading-whitespace": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/string-collapse-leading-whitespace/-/string-collapse-leading-whitespace-5.1.0.tgz", - "integrity": "sha512-mYz9/Kb5uvRB4DZj46zILwI4y9lD9JsvXG9Xb7zjbwm0I/R40G7oFfMsqJ28l2d7gWMTLJL569NfJQVLQbnHCw==", + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/string-collapse-leading-whitespace/-/string-collapse-leading-whitespace-7.0.7.tgz", + "integrity": "sha512-jF9eynJoE6ezTCdYI8Qb02/ij/DlU9ItG93Dty4SWfJeLFrotOr+wH9IRiWHTqO3mjCyqBWEiU3uSTIbxYbAEQ==", + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/string-extract-class-names": { + "version": "8.0.18", + "resolved": "https://registry.npmjs.org/string-extract-class-names/-/string-extract-class-names-8.0.18.tgz", + "integrity": "sha512-Ib8Pe5oeAmtR5M/vHk/Ci9fYLVE1EORlgTB6WTcMI7trIxjAm1DOQ63nTa79WrfsgFovbqH5omB+M9PFEBcb6Q==", "dependencies": { - "@babel/runtime": "^7.14.0" + "string-left-right": "^6.0.17" + }, + "engines": { + "node": ">=14.18.0" } }, "node_modules/string-left-right": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/string-left-right/-/string-left-right-4.1.0.tgz", - "integrity": "sha512-ic/WvfNVUygWWsgg8akzSzp2NuttfhrdbH7QmSnda5b5RFmT9aCEDiS/M+gmTJwtFy7+b/2AXU4Z6vejcePQqQ==", + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/string-left-right/-/string-left-right-6.0.17.tgz", + "integrity": "sha512-nuyIV4D4ivnwT64E0TudmCRg52NfkumuEUilyoOrHb/Z2wEOF5I+9SI6P+veFKqWKZfGpAs6OqKe4nAjujARyw==", "dependencies": { - "@babel/runtime": "^7.14.0", - "lodash.clonedeep": "^4.5.0", - "lodash.isplainobject": "^4.0.6" + "codsen-utils": "^1.6.4", + "rfdc": "^1.3.1" + }, + "engines": { + "node": ">=14.18.0" } }, "node_modules/string-match-left-right": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-match-left-right/-/string-match-left-right-7.1.0.tgz", - "integrity": "sha512-PSyXWesECKYnTJy6xaXAz/2AiyIjrga2hhMN8QbSNGwsnxcpWxt5pMpc7JQIzPkkEwDwip8PdIuU110xKuBevg==", + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/string-match-left-right/-/string-match-left-right-9.0.19.tgz", + "integrity": "sha512-SDp6gtyCZBg+icFiKdugIldylOchJ8o5p1vMoyjH7FHAjn7wAsXhO/L0N82tVx8ab2C1Tgw6RaJLxP1AXkXNhQ==", "dependencies": { - "@babel/runtime": "^7.14.0", - "arrayiffy-if-string": "^3.14.0", - "lodash.isplainobject": "^4.0.6", - "string-character-is-astral-surrogate": "^1.13.0" + "arrayiffy-if-string": "^5.0.8", + "codsen-utils": "^1.6.4", + "string-character-is-astral-surrogate": "^3.0.9" + }, + "engines": { + "node": ">=14.18.0" } }, "node_modules/string-range-expander": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string-range-expander/-/string-range-expander-2.1.0.tgz", - "integrity": "sha512-y/lRS0l1vfqAfj/msJ3APzf9IXCB7CZ6PrZFEPkXcLjau2vFrZ7ML1skKVItMYy16wGO87rv+28KtTYIAQoAYw==", + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/string-range-expander/-/string-range-expander-4.0.14.tgz", + "integrity": "sha512-rVnlXd202FvDSZqJEhRpu0EGRKGtdapEgWDFC350QRFukL2MbZxadGAA31kOKadXmGZIcvFfGjKpWv/ZehsjDA==", "dependencies": { - "@babel/runtime": "^7.14.0" + "codsen-utils": "^1.6.4" + }, + "engines": { + "node": ">=14.18.0" } }, "node_modules/string-remove-widows": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string-remove-widows/-/string-remove-widows-2.1.0.tgz", - "integrity": "sha512-GoBqfTvkc1uKeazfS/+hjLSi81IBDPmPPVBowk5x39Z+VvrvHLjJZFoYJbwe0JlPg1Mc4rX3Ak+5zPqAexWu5Q==", + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/string-remove-widows/-/string-remove-widows-4.0.22.tgz", + "integrity": "sha512-ZTJ4NLi7Y0r64fH2TWRebSDAEdH1QE7V4vA0RpChEUTio4Lw0Z3U/fXX3QrfWPxNqZTbBWppdT1FKe9Og+6xVw==", "dependencies": { - "@babel/runtime": "^7.14.0", - "ranges-apply": "^5.1.0", - "ranges-push": "^5.1.0", - "string-left-right": "^4.1.0", - "string-match-left-right": "^7.1.0" + "codsen-utils": "^1.6.4", + "ranges-apply": "^7.0.16", + "ranges-push": "^7.0.15", + "string-left-right": "^6.0.17", + "string-match-left-right": "^9.0.19" + }, + "engines": { + "node": ">=14.18.0" } }, "node_modules/string-strip-html": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/string-strip-html/-/string-strip-html-8.5.0.tgz", - "integrity": "sha512-5ICsK1B1j0A3AF1d45m0sqQCcmi1Q+t1QpF+b794LO5FTHV+ITkGR5C+UCDJQZgs5LMuRruqr6j48PxQVIurJQ==", + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/string-strip-html/-/string-strip-html-13.4.8.tgz", + "integrity": "sha512-vlcRAtx5DN6zXGUx3EYGFg0/JOQWM65mqLgDaBHviQPP+ovUFzqZ30iQ+674JHWr9wNgnzFGxx9TGipPZMnZXg==", + "dependencies": { + "@types/lodash-es": "^4.17.12", + "codsen-utils": "^1.6.4", + "html-entities": "^2.5.2", + "lodash-es": "^4.17.21", + "ranges-apply": "^7.0.16", + "ranges-push": "^7.0.15", + "string-left-right": "^6.0.17" + }, "engines": { - "node": ">=14" + "node": ">=14.18.0" } }, "node_modules/string-trim-spaces-only": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-trim-spaces-only/-/string-trim-spaces-only-3.1.0.tgz", - "integrity": "sha512-AW7RSi3+QtE6wR+4m/kmwlyy39neBbCIzrzzu1/RGzNRiPKQOeB3rGzr4ubg4UIQgYtr2w0PrxhKPXgyqJ0vaQ==", - "dependencies": { - "@babel/runtime": "^7.14.0" + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/string-trim-spaces-only/-/string-trim-spaces-only-5.0.10.tgz", + "integrity": "sha512-MhmjE5jNqb1Ylo+BARPRlsdChGLrnPpAUWrT1VOxo9WhWwKVUU6CbZTfjwKaQPYTGS/wsX/4Zek88FM2rEb5iA==", + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/string-uglify": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/string-uglify/-/string-uglify-3.0.11.tgz", + "integrity": "sha512-EOGHYwf8JBA6hzHvLxeUo3/JzW8gFKcXKwr7pRkwoM2qJkzJhxNlOpf8uGJujkgwKBvuh3ztBvQxCa0qLXCoeg==", + "engines": { + "node": ">=14.18.0" } }, "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==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/string-width-cjs": { @@ -8600,20 +5284,26 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { + "node_modules/string-width/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", @@ -8658,20 +5348,35 @@ "node": ">=8" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", + "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", + "dev": true, + "dependencies": { + "js-tokens": "^9.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" } }, "node_modules/style-to-object": { @@ -8683,15 +5388,15 @@ } }, "node_modules/stylehacks": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.1.1.tgz", - "integrity": "sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.2.tgz", + "integrity": "sha512-HdkWZS9b4gbgYTdMg4gJLmm7biAUug1qTqXjS+u8X+/pUd+9Px1E+520GnOW3rST9MNsVOVpsJG+mPHNosxjOQ==", "dependencies": { - "browserslist": "^4.23.0", - "postcss-selector-parser": "^6.0.16" + "browserslist": "^4.23.1", + "postcss-selector-parser": "^6.1.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" @@ -8726,39 +5431,58 @@ "node": ">= 6" } }, - "node_modules/supertap": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", - "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", + "node_modules/superagent": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", + "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", "dev": true, "dependencies": { - "indent-string": "^5.0.0", - "js-yaml": "^3.14.1", - "serialize-error": "^7.0.1", - "strip-ansi": "^7.0.1" + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^3.5.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14.18.0" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/supertest": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz", + "integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==", + "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "methods": "^1.1.2", + "superagent": "^9.0.1" }, "engines": { - "node": ">=8" + "node": ">=14.18.0" } }, - "node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" @@ -8775,14 +5499,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "engines": { - "node": ">=0.10" - } - }, "node_modules/tailwindcss": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", @@ -8830,53 +5546,73 @@ "node": ">=10.13.0" } }, - "node_modules/temp-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", - "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", - "dev": true, + "node_modules/tailwindcss/node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "engines": { - "node": ">=14.16" + "node": ">=10" } }, - "node_modules/terminal-link": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-3.0.0.tgz", - "integrity": "sha512-flFL3m4wuixmf6IfhFJd1YPiLiMuxEc8uHRM1buzIeZPm22Au2pDqBJQgdo7n1WfPU1ONFGv7YDwpFBmHGF6lg==", + "node_modules/tailwindcss/node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "dependencies": { - "ansi-escapes": "^5.0.0", - "supports-hyperlinks": "^2.2.0" + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" }, "engines": { - "node": ">=12" + "node": ">=14.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "postcss": "^8.0.0" } }, - "node_modules/terminal-link/node_modules/ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "type-fest": "^1.0.2" + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" }, "engines": { - "node": ">=12" + "node": ">= 14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/terminal-link/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "node_modules/tailwindcss/node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/test-exclude": { @@ -8893,14 +5629,45 @@ "node": ">=18" } }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/test-mixer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/test-mixer/-/test-mixer-2.1.0.tgz", - "integrity": "sha512-b258NzCyFOZlCNUiPubygccoTt0AAYeJQgFVV5BMQfzFxkSKJuWauehCOmocxM56+2P+Wv1uIIXac90M8KyJLA==", + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/test-mixer/-/test-mixer-4.1.14.tgz", + "integrity": "sha512-wbfQV/wjsGAgK1i9wGcnhOrj6mPsbI7Ylw0XNC73UxEViRUoq1CO0zJ4Dvuqi5nhJH09JB1SF+6a/HITr8mxVQ==", + "dependencies": { + "object-boolean-combinations": "^6.1.5", + "rfdc": "^1.3.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", "dependencies": { - "@babel/runtime": "^7.14.0", - "lodash.clonedeep": "^4.5.0", - "object-boolean-combinations": "^4.1.0" + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" } }, "node_modules/thenify": { @@ -8922,29 +5689,51 @@ "node": ">=0.8" } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, + "node_modules/tinybench": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", + "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==", + "dev": true }, - "node_modules/time-zone": { + "node_modules/tinypool": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", - "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.0.tgz", + "integrity": "sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==", "dev": true, "engines": { - "node": ">=4" + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.0.tgz", + "integrity": "sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, "engines": { - "node": ">=0.6.0" + "node": ">=4" } }, "node_modules/to-regex-range": { @@ -8976,50 +5765,16 @@ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, - "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/ua-parser-js": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz", - "integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, "engines": { - "node": "*" + "node": ">= 0.6" } }, "node_modules/uc.micro": { @@ -9027,43 +5782,10 @@ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "dependencies": { - "crypto-random-string": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" - } + "node_modules/ufo": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==" }, "node_modules/unpipe": { "version": "1.0.0", @@ -9074,9 +5796,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "funding": [ { "type": "opencollective", @@ -9102,65 +5824,6 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/update-notifier": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-7.0.0.tgz", - "integrity": "sha512-Hv25Bh+eAbOLlsjJreVPOs4vd51rrtCrmhyOJtbpAojro34jS4KQaEp4/EvlHJX7jSO42VvEFpkastVyXyIsdQ==", - "dependencies": { - "boxen": "^7.1.1", - "chalk": "^5.3.0", - "configstore": "^6.0.0", - "import-lazy": "^4.0.0", - "is-in-ci": "^0.1.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^6.0.0", - "latest-version": "^7.0.0", - "pupa": "^3.1.0", - "semver": "^7.5.4", - "semver-diff": "^4.0.0", - "xdg-basedir": "^5.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/update-notifier/node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -9174,20 +5837,6 @@ "node": ">= 0.4.0" } }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, "node_modules/valid-data-url": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz", @@ -9196,23 +5845,6 @@ "node": ">=10" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -9221,12 +5853,156 @@ "node": ">= 0.8" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "node_modules/version-range": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.14.0.tgz", + "integrity": "sha512-gjb0ARm9qlcBAonU4zPwkl9ecKkas+tC2CGwFfptTCWWIVTWY1YUbT2zZKsOAF1jR/tNxxyLwwG0cb42XlYcTg==", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/vite": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz", + "integrity": "sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.39", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.0.3.tgz", + "integrity": "sha512-14jzwMx7XTcMB+9BhGQyoEAmSl0eOr3nrnn+Z12WNERtOvLN+d2scbRUvyni05rT3997Bg+rZb47NyP4IQPKXg==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.5", + "pathe": "^1.1.2", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.0.3.tgz", + "integrity": "sha512-o3HRvU93q6qZK4rI2JrhKyZMMuxg/JRt30E6qeQs6ueaiz5hr1cPj+Sk2kATgQzMMqsa2DiNI0TIK++1ULx8Jw==", + "dev": true, "dependencies": { - "defaults": "^1.0.3" + "@ampproject/remapping": "^2.3.0", + "@vitest/expect": "2.0.3", + "@vitest/pretty-format": "^2.0.3", + "@vitest/runner": "2.0.3", + "@vitest/snapshot": "2.0.3", + "@vitest/spy": "2.0.3", + "@vitest/utils": "2.0.3", + "chai": "^5.1.1", + "debug": "^4.3.5", + "execa": "^8.0.1", + "magic-string": "^0.30.10", + "pathe": "^1.1.2", + "std-env": "^3.7.0", + "tinybench": "^2.8.0", + "tinypool": "^1.0.0", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.0.3", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.0.3", + "@vitest/ui": "2.0.3", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, "node_modules/web-resource-inliner": { @@ -9321,17 +6097,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/web-resource-inliner/node_modules/escape-goat": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz", - "integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/web-resource-inliner/node_modules/htmlparser2": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz", @@ -9362,15 +6127,6 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, - "node_modules/well-known-symbols": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", - "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -9394,31 +6150,36 @@ "node": ">= 8" } }, - "node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, "dependencies": { - "string-width": "^5.0.1" + "siginfo": "^2.0.0", + "stackback": "0.0.2" }, - "engines": { - "node": ">=12" + "bin": { + "why-is-node-running": "cli.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrap-ansi-cjs": { @@ -9460,48 +6221,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -9513,115 +6232,37 @@ "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/wrap-ansi/node_modules/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==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" + "node": ">=12" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/write-file-atomic/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==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "engines": { "node": ">=10.0.0" }, @@ -9638,33 +6279,6 @@ } } }, - "node_modules/xdg-basedir": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", - "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/xmlhttprequest-ssl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", - "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, "node_modules/yaml": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", @@ -9675,88 +6289,6 @@ "engines": { "node": ">= 14" } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } } } } diff --git a/package.json b/package.json index e043d365..f1a70c2e 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,32 @@ { "name": "@maizzle/framework", - "version": "4.8.8", + "version": "5.0.0-beta.0", "description": "Maizzle is a framework that helps you quickly build HTML emails with Tailwind CSS.", "license": "MIT", - "main": "src/index.js", - "types": "types/index.d.ts", + "type": "module", + "exports": { + ".": { + "import": "./src/index.js", + "types": "./types/index.d.ts" + } + }, "bin": { "maizzle": "bin/maizzle" }, + "files": [ + "bin", + "src", + "types" + ], + "publishConfig": { + "access": "public" + }, + "scripts": { + "dev": "vitest", + "lint": "biome lint ./src ./test", + "pretest": "npm run lint", + "test": "vitest run --coverage" + }, "repository": { "type": "git", "url": "https://github.com/maizzle/framework.git" @@ -27,70 +46,59 @@ "email-boilerplate", "html-emails" ], - "publishConfig": { - "access": "public" - }, - "scripts": { - "lint": "biome lint ./src ./test", - "pretest": "npm run lint", - "test": "c8 ava" - }, - "files": [ - "src", - "types", - "bin" - ], "dependencies": { - "@maizzle/cli": "^1.5.1", - "autoprefixer": "^10.4.14", - "browser-sync": "^3.0.2", - "color-shorthand-hex-to-six-digit": "^3.0.2", - "email-comb": "^5.3.1", + "@csstools/css-calc": "^1.2.2", + "@maizzle/cli": "next", + "cheerio": "^1.0.0-rc.12", + "chokidar": "^3.6.0", + "cli-table3": "^0.6.5", + "color-shorthand-hex-to-six-digit": "^5.0.16", + "defu": "^6.1.4", + "email-comb": "^7.0.21", + "express": "^4.19.2", "fast-glob": "^3.3.2", - "front-matter": "^4.0.0", - "fs-extra": "^11.2.0", - "html-crush": "^4.0.0", - "is-url-superb": "^5.0.0", + "gray-matter": "^4.0.3", + "html-crush": "^6.0.18", + "is-url-superb": "^6.1.0", + "istextorbinary": "^9.5.0", "juice": "^10.0.0", - "lodash": "^4.17.20", - "ora": "^5.1.0", - "postcss": "^8.4.21", - "postcss-import": "^15.0.0", - "postcss-merge-longhand": "^6.0.0", + "lodash-es": "^4.17.21", + "morphdom": "^2.7.2", + "ora": "^8.0.1", + "pathe": "^1.1.2", + "postcss": "^8.4.38", + "postcss-custom-properties": "^13.3.10", + "postcss-import": "^16.1.0", + "postcss-safe-parser": "^7.0.0", "posthtml": "^0.16.6", "posthtml-attrs-parser": "^1.1.0", - "posthtml-base-url": "^2.0.2", + "posthtml-base-url": "^3.1.2", "posthtml-component": "^1.1.0", - "posthtml-content": "^2.1.0", - "posthtml-extend": "^0.6.0", - "posthtml-extra-attributes": "^2.0.0", - "posthtml-fetch": "^3.0.0", - "posthtml-markdownit": "^3.1.0", - "posthtml-match-helper": "^1.0.3", - "posthtml-mso": "^3.1.0", + "posthtml-content": "^2.0.1", + "posthtml-extra-attributes": "^3.0.0", + "posthtml-markdownit": "^3.0.1", + "posthtml-mso": "^3.0.0", + "posthtml-parser": "^0.12.0", + "posthtml-postcss": "^1.0.0", "posthtml-postcss-merge-longhand": "^3.1.0", - "posthtml-safe-class-names": "^3.0.0", - "posthtml-url-parameters": "^2.0.0", + "posthtml-render": "^3.0.0", + "posthtml-safe-class-names": "^4.0.2", + "posthtml-url-parameters": "^3.0.0", "pretty": "^2.0.0", - "query-string": "^7.1.3", - "string-remove-widows": "^2.1.0", - "string-strip-html": "^8.2.0", - "tailwindcss": "^3.2.7" + "string-remove-widows": "^4.0.22", + "string-strip-html": "^13.4.8", + "tailwindcss": "^3.4.4", + "ws": "^8.17.0" }, "devDependencies": { "@biomejs/biome": "^1.8.3", - "@types/browser-sync": "^2.29.0", - "@types/js-beautify": "^1.14.0", - "@types/markdown-it": "^14.0.0", - "ava": "^5.2.0", - "c8": "^10.0.0" + "@types/js-beautify": "^1.14.3", + "@types/markdown-it": "^14.1.1", + "@vitest/coverage-v8": "^2.0.1", + "supertest": "^7.0.0", + "vitest": "^2.0.1" }, "engines": { - "node": ">=14.0.0" - }, - "ava": { - "files": [ - "test/**/test*.js" - ] + "node": ">=18.0.0" } } diff --git a/src/commands/build.js b/src/commands/build.js index 906e40a5..3cf7ea74 100644 --- a/src/commands/build.js +++ b/src/commands/build.js @@ -1,27 +1,252 @@ -const ora = require('ora') -const {get} = require('lodash') -const Output = require('../generators/output') -const {clearConsole} = require('../utils/helpers') +import { + readFile, + writeFile, + copyFile, + lstat, + mkdir, + rm +} from 'node:fs/promises' +import path from 'pathe' +import fg from 'fast-glob' +import { defu as merge } from 'defu' -const build = async (env = 'local', config = {}) => { - const start = new Date() - const spinner = ora('Building emails...').start() +import get from 'lodash/get.js' +import isEmpty from 'lodash-es/isEmpty.js' +import { isBinary } from 'istextorbinary' - const {files, parsed} = await Output.toDisk(env, spinner, config) +import ora from 'ora' +import pico from 'picocolors' +import cliTable from 'cli-table3' - const elapsedSeconds = (Date.now() - start) / 1000 +import { render } from '../generators/render.js' +import { formatTime } from '../utils/string.js' +import { getColorizedFileSize } from '../utils/node.js' +import { readFileConfig } from '../utils/getConfigByFilePath.js' +import { + generatePlaintext, + handlePlaintextTags, + writePlaintextFile +} from '../generators/plaintext.js' - if (get(config, 'build.command') === 'serve') { - if (get(config, 'build.console.clear')) { - clearConsole() +/** + * Compile templates and output to the build directory. + * Returns a promise containing an object with files output and the config object. + * + * @param {object|string} config - The Maizzle config object, or path to a config file. + * @returns {Promise<object>} The build output, containing the files and config. + */ +export default async (config = {}) => { + const spinner = ora() + + try { + const startTime = Date.now() + + // Compute config + config = await readFileConfig(config).catch(() => { throw new Error('Could not compute config') }) + + /** + * Support customizing the spinner + */ + const spinnerConfig = get(config, 'build.spinner') + + if (spinnerConfig === false) { + // Show only 'Building...' text + spinner.isEnabled = false + } else { + spinner.spinner = get(config, 'build.spinner', 'circleHalves') } - spinner.succeed(`Re-built ${parsed.length} templates in ${elapsedSeconds}s`) - } else { - spinner.succeed(`Built ${parsed.length} templates in ${elapsedSeconds}s`) - } + spinner.start('Building...') - return {files} -} + // Run beforeCreate event + if (typeof config.beforeCreate === 'function') { + await config.beforeCreate({ config }) + } + + const buildOutputPath = get(config, 'build.output.path', 'build_local') + + // Remove output directory + await rm(buildOutputPath, { recursive: true, force: true }) + + const table = new cliTable({ + head: ['File name', 'File size', 'Build time'].map(item => pico.bold(item)), + }) + + // Determine paths of templates to build + const userFilePaths = get(config, 'build.content', 'src/templates/**/*.html') + const templateFolders = Array.isArray(userFilePaths) ? userFilePaths : [userFilePaths] + const templatePaths = await fg.glob([...new Set(templateFolders)]) + + // If there are no templates to build, throw error + if (templatePaths.length === 0) { + throw new Error(`No templates found in ${pico.inverse(templateFolders)}`) + } + + const baseDirs = templateFolders.filter(p => !p.startsWith('!')).map(p => { + const parts = p.split('/') + // remove the glob part (e.g., **/*.html): + return parts.filter(part => !part.includes('*')).join('/') + }) + + /** + * Check for binary files + * + * We store paths to binary files in a separate array, because we don't want + * to render them. These files will be treated as static files and will + * be copied directly to the output directory, just like the + * `build.static` folders. + */ + const binaryPaths = await fg.glob([...new Set(baseDirs.map(base => `${base}/**/*.*`))]) + .then(paths => paths.filter(file => isBinary(file))) + + /** + * Render templates + * + * Render each template and write the output to the output directory, + * preserving the relative path. + */ + for await (const templatePath of templatePaths) { + const templateBuildStartTime = Date.now() + + // Determine the base directory the template belongs to + const baseDir = baseDirs.find(base => templatePath.startsWith(base)) + + // Compute the relative path + const relativePath = path.relative(baseDir, templatePath) + + /** + * Add the current template path to the config + * + * Can be used in events like `beforeRender` to determine + * which template file is being rendered. + */ + config.build.current = { + path: path.parse(templatePath), + baseDir, + relativePath, + } + + const html = await readFile(templatePath, 'utf8') + + const rendered = await render(html, config) + + /** + * Generate plaintext + * + * We do this first so that we can remove the <plaintext> + * tags from the markup before outputting the file. + */ + const plaintextConfig = get(rendered.config, 'plaintext') + + if (Boolean(plaintextConfig) || !isEmpty(plaintextConfig)) { + const posthtmlOptions = get(rendered.config, 'posthtml.options', {}) + + const plaintext = await generatePlaintext(rendered.html, merge(plaintextConfig, posthtmlOptions)) + rendered.html = await handlePlaintextTags(rendered.html, posthtmlOptions) + await writePlaintextFile(plaintext, rendered.config) + .catch(error => { + throw new Error(`Error writing plaintext file: ${error}`) + }) + } + + /** + * Determine output path, creating directories if needed + * + * Prioritize `permalink` path from Front Matter, + * fallback to the current template path. + * + * We do this before generating plaintext, so that + * any paths will already have been created. + */ + const outputPathFromConfig = get(rendered.config, 'permalink', path.join(buildOutputPath, relativePath)) + const parsedOutputPath = path.parse(outputPathFromConfig) + const extension = get(rendered.config, 'build.output.extension', parsedOutputPath.ext.slice(1)) + const outputPath = `${parsedOutputPath.dir}/${parsedOutputPath.name}.${extension}` -module.exports = build + const pathExists = await lstat(path.dirname(outputPath)).catch(() => false) + + if (!pathExists) { + await mkdir(path.dirname(outputPath), { recursive: true }) + } + + /** + * Write the rendered HTML to disk, creating directories if needed + */ + await writeFile(outputPath, rendered.html) + + /** + * Add file to CLI table for build summary logging + */ + if (config.build.summary) { + table.push([ + path.relative(get(rendered.config, 'build.output.path'), outputPath), + getColorizedFileSize(rendered.html), + formatTime(Date.now() - templateBuildStartTime) + ]) + } + } + + /** + * Copy static files + * + * Copy binary files that are alongside templates as well as + * files from `build.static`, to the output directory. + * + * TODO: support an array of objects with source and destination, i.e. static: [{ source: 'src/assets', destination: 'assets' }, ...] + */ + + // Copy binary files that are alongside templates + for await (const binaryPath of binaryPaths) { + const relativePath = path.relative(get(config, 'build.current.baseDir'), binaryPath) + const outputPath = path.join(get(config, 'build.output.path'), get(config, 'build.static.destination'), relativePath) + + await mkdir(path.dirname(outputPath), { recursive: true }) + await copyFile(binaryPath, outputPath) + } + + // Copy files from `build.static` + const staticSourcePaths = await fg.glob([...new Set(get(config, 'build.static.source', []))]) + .then(paths => paths.filter(file => isBinary(file))) + + if (!isEmpty(staticSourcePaths)) { + for await (const staticPath of staticSourcePaths) { + const relativePath = path.relative(get(config, 'build.current.baseDir'), staticPath) + const outputPath = path.join(get(config, 'build.output.path'), get(config, 'build.static.destination'), relativePath) + + await mkdir(path.dirname(outputPath), { recursive: true }) + await copyFile(staticPath, outputPath) + } + } + + const compiledFiles = await fg.glob(path.join(config.build.output.path, '**/*')) + + /** + * Run `afterBuild` event + */ + if (typeof config.afterBuild === 'function') { + await config.afterBuild({ files: compiledFiles, config, render }) + } + + /** + * Log a build summary if enabled in the config + * + * Need to first clear the spinner + */ + + spinner.clear() + + if (config.build.summary) { + console.log(table.toString() + '\n') + } + + spinner.succeed(`Build completed in ${formatTime(Date.now() - startTime)}`) + + return { + files: compiledFiles, + config + } + } catch (error) { + spinner.fail('Build failed') + throw error + } +} diff --git a/src/commands/serve.js b/src/commands/serve.js index bffe01a6..2ac5bbbf 100644 --- a/src/commands/serve.js +++ b/src/commands/serve.js @@ -1,198 +1,3 @@ -const ora = require('ora') -const fs = require('fs-extra') -const path = require('node:path') +import server from '../server/index.js' -const Config = require('../generators/config') -const buildToFile = require('../commands/build') -const renderToString = require('../functions/render') - -const {get, merge, isObject} = require('lodash') -const {clearConsole} = require('../utils/helpers') - -/** - * Initialize Browsersync on-demand - * https://github.com/maizzle/framework/issues/605 - */ -const browsersync = () => { - if (!global.cachedBrowserSync) { - const bs = require('browser-sync') - global.cachedBrowserSync = bs.create() - } - - return global.cachedBrowserSync -} - -const getConfig = async (env = 'local', config = {}) => merge( - config, - await Config.getMerged(env) -) - -const serve = async (env = 'local', config = {}) => { - config = await getConfig(env, merge(config, { - build: { - command: 'serve' - } - })) - - const spinner = ora() - - // Build all emails first - await buildToFile(env, config) - - // Set some paths to watch - let templates = get(config, 'build.templates') - templates = Array.isArray(templates) ? templates : [templates] - - const templatePaths = [...new Set(templates.map(config => `${get(config, 'source', 'src')}/**`))] - const tailwindConfig = get(config, 'build.tailwind.config', 'tailwind.config.js') - const globalPaths = [ - 'src/**', - ...new Set(get(config, 'build.browsersync.watch', [])) - ] - - if (typeof tailwindConfig === 'string') { - globalPaths.push(tailwindConfig) - } - - // Watch for Template file changes - browsersync() - .watch(templatePaths) - .on('change', async file => { - config = await getConfig(env, config) - - if (config.events && typeof config.events.beforeCreate === 'function') { - await config.events.beforeCreate(config) - } - - // Don't render if file type is not configured - // eslint-disable-next-line - const filetypes = templates.reduce((acc, template) => { - return [...acc, ...get(template, 'filetypes', ['html'])] - }, []) - - if (!filetypes.includes(path.extname(file).slice(1))) { - return - } - - // Clear console if enabled - if (get(config, 'build.console.clear')) { - clearConsole() - } - - // Start the spinner - const start = new Date() - spinner.start('Building email...') - - // Render the template - renderToString( - await fs.readFile(file.replace(/\\/g, '/'), 'utf8'), - { - maizzle: merge( - config, - { - build: { - current: { - path: path.parse(file) - } - } - } - ), - ...config.events - } - ) - .then(async ({html, config}) => { - // Write the file to disk - let source = '' - let dest = '' - let ext = '' - - if (Array.isArray(config.build.templates)) { - const match = config.build.templates.find(template => path.parse(file).dir.includes(path.normalize(template.source))) - source = path.normalize(get(match, 'source')) - dest = path.normalize(get(match, 'destination.path', 'build_local')) - ext = get(match, 'destination.ext', 'html') - } else if (isObject(config.build.templates)) { - source = path.normalize(get(config, 'build.templates.source')) - dest = path.normalize(get(config, 'build.templates.destination.path', 'build_local')) - ext = get(config, 'build.templates.destination.ext', 'html') - } - - const fileDir = path.parse(file).dir.replace(source, '') - const finalDestination = path.join(dest, fileDir, `${path.parse(file).name}.${ext}`) - - await fs.outputFile(config.permalink || finalDestination, html) - }) - .then(() => { - browsersync().reload() - spinner.succeed(`Compiled in ${(Date.now() - start) / 1000}s [${file}]`) - }) - .catch(error => { - throw error - }) - }) - - // Watch for changes in all other files - browsersync() - .watch(globalPaths, {ignored: templatePaths}) - .on('change', () => buildToFile(env, config) - .then(() => browsersync().reload()) - .catch(error => { - throw error - }) - ) - .on('unlink', () => buildToFile(env, config) - .then(() => browsersync().reload()) - .catch(error => { - throw error - }) - ) - - // Watch for changes in config files - browsersync() - .watch('{maizzle.config*,config*}.{js,cjs}') - .on('change', async file => { - const fileName = path.parse(file).base - const match = fileName.match(/\.?config\.(.+?)\./) - - const parsedEnv = match ? match[1] : env || 'local' - - Config - .getMerged(parsedEnv) - .then(config => buildToFile(parsedEnv, config) - .then(() => browsersync().reload()) - .catch(error => { - throw error - }) - ) - }) - - // Browsersync options - const baseDir = templates.map(t => t.destination.path) - - // Initialize Browsersync - browsersync() - .init( - merge( - { - notify: false, - open: false, - port: 3000, - server: { - baseDir, - directory: true - }, - tunnel: false, - ui: {port: 3001}, - logFileChanges: false, - watchOptions: { - awaitWriteFinish: { - stabilityThreshold: 150, - pollInterval: 25 - } - } - }, - get(config, 'build.browsersync', {}) - ), () => {}) -} - -module.exports = serve +export default server diff --git a/src/functions/plaintext.js b/src/functions/plaintext.js deleted file mode 100644 index 75c9ee19..00000000 --- a/src/functions/plaintext.js +++ /dev/null @@ -1,5 +0,0 @@ -const Plaintext = require('../generators/plaintext') - -const toPlaintext = async (html, config = {}) => Plaintext.generate(html, false, config) - -module.exports = toPlaintext diff --git a/src/functions/render.js b/src/functions/render.js deleted file mode 100644 index e46b3025..00000000 --- a/src/functions/render.js +++ /dev/null @@ -1,5 +0,0 @@ -const Output = require('../generators/output') - -const render = async (html, options) => Output.toString(html, options) - -module.exports = render diff --git a/src/generators/config.js b/src/generators/config.js deleted file mode 100644 index e73d4945..00000000 --- a/src/generators/config.js +++ /dev/null @@ -1,52 +0,0 @@ -const path = require('node:path') -const {merge} = require('lodash') -const {requireUncached} = require('../utils/helpers') - -const baseConfigFileNames = [ - './maizzle.config.js', - './maizzle.config.cjs', - './maizzle.config.local.js', - './maizzle.config.local.cjs', - './config.js', - './config.cjs', - './config.local.js', - './config.local.cjs' -] - -module.exports = { - getMerged: async (env = 'local') => { - if (typeof env !== 'string') { - throw new TypeError(`env name must be a string, received ${typeof env}(${env})`) - } - - let baseConfig = {env} - let envConfig = {env} - - const cwd = ['maizzle-ci', 'test'].includes(env) ? './test/stubs/config' : process.cwd() - - for (const module of baseConfigFileNames) { - try { - baseConfig = merge(baseConfig, requireUncached(path.resolve(cwd, module))) - } catch {} - } - - if (env !== 'local') { - let loaded = false - const modulesToTry = [`./maizzle.config.${env}.js`, `./maizzle.config.${env}.cjs`, `./config.${env}.js`, `./config.${env}.cjs`] - - for (const module of modulesToTry) { - try { - envConfig = merge(envConfig, requireUncached(path.resolve(cwd, module))) - loaded = true - break - } catch {} - } - - if (!loaded) { - throw new Error(`Failed to load config file for \`${env}\` environment, do you have one of these files in your project root?\n\n${modulesToTry.join('\n')}`) - } - } - - return merge(baseConfig, envConfig) - } -} diff --git a/src/generators/output/index.js b/src/generators/output/index.js deleted file mode 100644 index 95ff5675..00000000 --- a/src/generators/output/index.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - toDisk: require('./to-disk'), - toString: require('./to-string') -} diff --git a/src/generators/output/to-disk.js b/src/generators/output/to-disk.js deleted file mode 100644 index 4147f8a3..00000000 --- a/src/generators/output/to-disk.js +++ /dev/null @@ -1,254 +0,0 @@ -const fs = require('fs-extra') -const path = require('node:path') -const {glob} = require('fast-glob') -const {get, merge, isEmpty} = require('lodash') - -const Config = require('../config') -const Plaintext = require('../plaintext') -const Tailwind = require('../tailwindcss') - -const render = require('./to-string') - -module.exports = async (env, spinner, config) => { - process.env.NODE_ENV = env || 'local' - - if (isEmpty(config)) { - config = await Config.getMerged(env).catch(error => { - spinner.fail('Build failed') - throw error - }) - } - - const buildTemplates = get(config, 'build.templates') - const templatesConfig = Array.isArray(buildTemplates) ? buildTemplates : [buildTemplates] - - const parsed = [] - let files = [] - - const css = (typeof get(config, 'build.tailwind.compiled') === 'string') - ? config.build.tailwind.compiled - : await Tailwind.compile({config}) - - // Parse each template config object - for await (const templateConfig of templatesConfig) { - if (!templateConfig) { - const configFileName = env === 'local' ? 'config.js' : `config.${env}.js` - throw new Error(`No template sources defined in \`build.templates\`, check your ${configFileName} file`) - } - - const outputDir = get(templateConfig, 'destination.path', `build_${env}`) - - await fs.remove(outputDir) - - /** - * Get all files in the template config's source directory - * Supports `source` defined as: - * - string - * - array of strings - * - function that returns either of the above - * - * */ - const templateSource = [] - const templateTypeErrorMessage = 'Invalid template source: expected string or array of strings, got ' - - if (typeof templateConfig.source === 'function') { - const sources = templateConfig.source(config) - - if (Array.isArray(sources)) { - templateSource.push(...sources) - } else if (typeof sources === 'string') { - templateSource.push(sources) - } else { - throw new TypeError(templateTypeErrorMessage + typeof sources) - } - } else { - if (Array.isArray(templateConfig.source)) { - templateSource.push(...templateConfig.source) - } else if (typeof templateConfig.source === 'string') { - templateSource.push(templateConfig.source) - } else { - throw new TypeError(templateTypeErrorMessage + typeof templateConfig.source) - } - } - - // Create a pipe-delimited list of allowed extensions - // We only compile these, the rest are copied as-is - const fileTypes = get(templateConfig, 'filetypes', 'html') - const extensionsList = Array.isArray(fileTypes) - ? fileTypes.join(',') - : fileTypes.split('|').join(',') - - // List of files that won't be copied to the output directory - const omitted = Array.isArray(templateConfig.omit) - ? templateConfig.omit - : [get(templateConfig, 'omit', '')] - - // Parse each template source - for await (const source of templateSource) { - /** - * Copy single-file sources correctly - * If `src` is a file, `dest` cannot be a directory - * https://github.com/jprichardson/node-fs-extra/issues/323 - */ - const out = fs.lstatSync(source).isFile() - ? `${outputDir}/${path.basename(source)}` - : outputDir - - await fs - .copy(source, out, {filter: file => { - // Do not copy omitted files - return !omitted - .filter(Boolean) - .some(omit => path.normalize(file).includes(path.normalize(omit))) - }}) - .then(async () => { - const extensions = extensionsList.includes(',') - ? `{${extensionsList}}` - : extensionsList - const allSourceFiles = await glob(`${outputDir}/**/*.${extensions}`) - - const skipped = Array.isArray(templateConfig.skip) ? - templateConfig.skip : - [get(templateConfig, 'skip', '')] - - const templates = allSourceFiles.filter(template => { - return !skipped.includes(template.replace(`${outputDir}/`, '')) - }) - - if (templates.length === 0) { - spinner.warn(`Error: no files with the .${extensions} extension found in ${templateConfig.source}`) - return - } - - if (config.events && typeof config.events.beforeCreate === 'function') { - await config.events.beforeCreate(config) - } - - for await (const file of templates) { - config.build.current = { - path: path.parse(file) - } - - const html = await fs.readFile(file, 'utf8') - - try { - const compiled = await render(html, { - useFileConfig: true, - maizzle: { - ...config, - env - }, - tailwind: { - compiled: css - }, - ...config.events - }) - - const destination = get(compiled, 'config.permalink', file) - - /** - * Generate plaintext - * - * We do this first so that we can remove the <plaintext> - * tags from the markup before outputting the file. - */ - - // Check if plaintext: true globally, fallback to template's front matter - const plaintextConfig = get(templateConfig, 'plaintext', get(compiled.config, 'plaintext', false)) - const plaintextPath = get(plaintextConfig, 'destination.path', destination) - - if (Boolean(plaintextConfig) || !isEmpty(plaintextConfig)) { - await Plaintext - .generate( - compiled.html, - plaintextPath, - merge(plaintextConfig, {filepath: file}) - ) - .then(async ({html, plaintext, destination}) => { - compiled.html = html - await fs.outputFile(destination, plaintext) - }) - } - - /** - * Output file - */ - const parts = path.parse(destination) - const extension = get(templateConfig, 'destination.extension', 'html') - const finalDestination = `${parts.dir}/${parts.name}.${extension}` - - await fs.outputFile(finalDestination, compiled.html) - - /** - * Remove original file if its path is different - * from the final destination path. - * - * This ensures non-HTML files do not pollute - * the build destination folder. - */ - if (finalDestination !== file) { - await fs.remove(file) - } - - // Keep track of handled files - files.push(file) - parsed.push(file) - } catch (error) { - switch (config.build.fail) { - case 'silent': - spinner.warn(`Failed to compile template: ${path.basename(file)}`) - break - case 'verbose': - spinner.warn(`Failed to compile template: ${path.basename(file)}`) - console.error(error) - break - default: - spinner.fail(`Failed to compile template: ${path.basename(file)}`) - throw error - } - } - } - - const assets = Array.isArray(get(templateConfig, 'assets')) - ? get(templateConfig, 'assets') - : [{source: '', destination: 'assets', ...get(templateConfig, 'assets')}] - - for await (const asset of assets) { - if (Array.isArray(asset.source)) { - for await (const source of asset.source) { - if (fs.existsSync(source)) { - await fs - .copy(source, path.join(templateConfig.destination.path, asset.destination)) - .catch(error => spinner.warn(error.message)) - } - } - } else { - if (fs.existsSync(asset.source)) { - await fs - .copy(asset.source, path.join(templateConfig.destination.path, asset.destination)) - .catch(error => spinner.warn(error.message)) - } - } - } - - await glob(path.join(templateConfig.destination.path, '/**').replace(/\\/g, '/')) - .then(contents => { - files = [...new Set([...files, ...contents])] - }) - }) - .catch(error => { - throw error - }) - } - } - - if (config.events && typeof config.events.afterBuild === 'function') { - await config.events.afterBuild(files, config) - } - - return { - files, - parsed, - css - } -} diff --git a/src/generators/output/to-string.js b/src/generators/output/to-string.js deleted file mode 100644 index c5ae868f..00000000 --- a/src/generators/output/to-string.js +++ /dev/null @@ -1,73 +0,0 @@ -const fm = require('front-matter') -const Config = require('../config') -const {get, merge} = require('lodash') -const posthtml = require('../posthtml') -const Tailwind = require('../tailwindcss') -const Transformers = require('../../transformers') - -module.exports = async (html, options) => { - process.env.NODE_ENV = get(options, 'maizzle.env', 'local') - - if (typeof html !== 'string') { - throw new TypeError(`first argument must be an HTML string, received ${html}`) - } - - if (html.length === 0) { - throw new RangeError('received empty string') - } - - const fileConfig = get(options, 'useFileConfig') - ? await Config.getMerged(process.env.NODE_ENV) - : {} - - let config = merge(fileConfig, get(options, 'maizzle', {})) - - const {frontmatter} = fm(html) - - html = `---\n${frontmatter}\n---\n\n${fm(html).body}` - - config = merge({applyTransformers: true}, config, fm(html).attributes) - - if (typeof get(options, 'tailwind.compiled') === 'string') { - config.css = options.tailwind.compiled - } else { - config.css = await Tailwind.compile({ - css: get(options, 'tailwind.css', ''), - html, - config: merge(config, { - build: { - tailwind: { - config: get(options, 'tailwind.config') - } - } - }) - }) - } - - if (options && typeof options.beforeRender === 'function') { - html = await options.beforeRender(html, config) - } - - html = await posthtml(html, config) - - while (Object.keys(fm(html).attributes).length > 0) { - html = fm(html).body - } - - if (options && typeof options.afterRender === 'function') { - html = await options.afterRender(html, config) - } - - if (config.applyTransformers) { - html = await Transformers.process(html, config) - } - - if (options && typeof options.afterTransformers === 'function') { - html = await options.afterTransformers(html, config) - } - - return { - html, - config - } -} diff --git a/src/generators/plaintext.js b/src/generators/plaintext.js index 8896e355..95f7747d 100644 --- a/src/generators/plaintext.js +++ b/src/generators/plaintext.js @@ -1,118 +1,219 @@ -const path = require('node:path') -const posthtml = require('posthtml') -const {get, merge} = require('lodash') -const {stripHtml} = require('string-strip-html') -const defaultConfig = require('./posthtml/defaultConfig') - -const self = { - removeCustomTags: (tag, html, config = {}) => { - const posthtmlOptions = get(config, 'build.posthtml.options', {}) - - const posthtmlPlugin = () => tree => { - const process = node => { - if (!node.tag) { - return node - } - - if (node.tag === tag) { - return { - tag: false, - content: [''] - } - } - - if (Array.isArray(tag) && tag.includes(node.tag)) { - return { - tag: false, - content: [''] - } - } +import path from 'pathe' +import posthtml from 'posthtml' +import get from 'lodash-es/get.js' +import { defu as merge } from 'defu' +import { stripHtml } from 'string-strip-html' +import defaultConfig from '../posthtml/defaultConfig.js' +import { writeFile, lstat, mkdir } from 'node:fs/promises' + +/** + * Removes HTML tags from a given HTML string based on + * a specified tag name or an array of tag names. + * + * @param {Object} options - The options object. + * @param {string|string[]} [options.tag='not-plaintext'] - The tag name or an array of tag names to remove from the HTML. + * @param {string} [options.html=''] - The HTML string from which to remove the tags. + * @param {Object} [options.config={}] - PostHTML options. + * @returns {string} - The HTML string with the specified tags removed. + */ +const removeTags = ({ tag = 'not-plaintext', html = '', config = {} }) => { + /** + * If the HTML string is empty, return it as is + */ + if (!html) { + return html + } + const posthtmlPlugin = () => tree => { + const process = node => { + if (!node.tag) { return node } - return tree.walk(process) - } - - return posthtml([posthtmlPlugin()]).process(html, {...posthtmlOptions, sync: true}).html - }, - handleCustomTags: (html, config = {}) => { - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - - const posthtmlPlugin = () => tree => { - const process = node => { - if (node.tag === 'plaintext') { - return { - tag: false, - content: [''] - } - } - - if (node.tag === 'not-plaintext') { - return { - tag: false, - content: tree.render(node.content) - } + /** + * If the tag is a string and it matches the node tag, remove it + */ + if (node.tag === tag) { + return { + tag: false, + content: [''] } - - return node } - return tree.walk(process) + return node } - return posthtml([posthtmlPlugin()]).process(html, {...posthtmlOptions, sync: true}).html - }, - generate: async (html, destination, config = {}) => { - const configDestinationPath = get(config, 'destination.path') - const extension = get(config, 'destination.extension', 'txt') + return tree.walk(process) + } - const strippedHTML = self.removeCustomTags('not-plaintext', html, config) + const posthtmlOptions = merge(defaultConfig, config) - const plaintext = stripHtml(strippedHTML, { - dumpLinkHrefsNearby: { - enabled: true - }, - stripTogetherWithTheirContents: ['script', 'style', 'xml'], - ...config - }).result + return posthtml([posthtmlPlugin()]).process(html, { ...posthtmlOptions }).then(res => res.html) +} - html = self.handleCustomTags(html, config) +/** + * Handles custom <plaintext> tags and replaces their content based on the tag name. + * + * @param {Object} options - The options object. + * @param {string} [options.html=''] - The HTML string containing custom tags to be processed. + * @param {Object} [options.config={}] - PostHTML options. + * @returns {string} - The modified HTML string after processing custom tags. + */ +export async function handlePlaintextTags(html = '', config = {}) { + /** + * If the HTML string is empty, return early + */ + if (!html) { + return html + } - // If we set plaintext.destination.path in config/fm - if (configDestinationPath) { + const posthtmlPlugin = () => tree => { + const process = node => { /** - * Using a file path will generate a single plaintext file, - * no matter how many templates there are. - * - * It will be based on the last-processed template. + * Remove <plaintext> tags and their content from the HTML */ - if (path.extname(configDestinationPath)) { - destination = configDestinationPath - - return {html, plaintext, destination} + if (node.tag === 'plaintext') { + return { + tag: false, + content: [''] + } } /** - * Using a directory-like path for plaintext.destination.path + * Replace <not-plaintext> tags with their content */ - destination = path.join(configDestinationPath, path.basename(config.filepath, path.extname(config.filepath)) + '.' + extension) + if (node.tag === 'not-plaintext') { + return { + tag: false, + content: tree.render(node.content) + } + } - return {html, plaintext, destination} + return node } - /** - * Use template's `permalink` Front Matter key, - * fall back to the original `destination`. - */ - destination = get(config, 'permalink', destination) + return tree.walk(process) + } + + const posthtmlOptions = merge(defaultConfig, config) + + return posthtml([posthtmlPlugin()]).process(html, { ...posthtmlOptions }).then(res => res.html) +} + +/** + * Generate a plaintext representation from the provided HTML. + * + * @param {Object} options - The options object. + * @param {string} [options.html=''] - The HTML string to convert to plaintext. + * @param {Object} [options.config={}] - Configuration object. + * @returns {Promise<string>|void} - The generated plaintext as a string. + */ +export async function generatePlaintext(html = '', config = {}) { + const { posthtml: posthtmlOptions, ...stripOptions } = config + + /** + * Remove <not-plaintext> tags and their content from the HTML. + * `config` is an object containing PostHTML options. + */ + html = await removeTags({ tag: 'not-plaintext', html, config: posthtmlOptions }) + + /** + * Return the plaintext representation from the stripped HTML. + * The `dumpLinkHrefsNearby` option is enabled by default. + */ + return stripHtml( + html, + merge( + stripOptions, + { + dumpLinkHrefsNearby: { + enabled: true, + }, + }, + ) + ).result +} + +export async function writePlaintextFile(plaintext = '', templateConfig = {}) { + if (!plaintext) { + throw new Error('Missing plaintext content.') + } + + if (typeof plaintext !== 'string') { + throw new Error('Plaintext content must be a string.') + } - if (typeof destination === 'string') { - destination = path.join(path.dirname(destination), path.basename(destination, path.extname(destination)) + '.' + extension) + /** + * Get plaintext output path config, i.e `config.plaintext.destination.path` + * + * Fall back to template's build output path and extension, for example: + * `config.build.output.path` + */ + const plaintextConfig = get(templateConfig, 'plaintext') + let plaintextOutputPath = get(plaintextConfig, 'output.path', get(templateConfig, 'build.output.path')) + const plaintextExtension = get(plaintextConfig, 'output.extension', 'txt') + + /** + * If `plaintext: true` (either from Front Matter or from config) + */ + if (plaintextConfig === true) { + // If the template has a `permalink` key set in the FM + if (typeof templateConfig.permalink === 'string') { + // Output plaintext at the `permalink` path + plaintextOutputPath = templateConfig.permalink + } else { + // Output plaintext at the same directory as the HTML file + plaintextOutputPath = path.join( + get(templateConfig, 'build.output.path'), + get(templateConfig, 'build.current.relativePath') + ) } + } - return {html, plaintext, destination} + /** + * If `plaintext: path/to/file.ext` in the FM + * Can't work if set in config.js as file path, because it would be the same for all templates + * We check later if it's a dir path, won't work if it's a file path + */ + if (typeof plaintextConfig === 'string') { + plaintextOutputPath = plaintextConfig } -} -module.exports = self + // No need to handle if it's an object, since we already set it to that initially + + /** + * If `plaintextOutputPath` is a file path, output file there + */ + if (path.extname(plaintextOutputPath)) { + // Ensure the target directory exists + await lstat(path.dirname(plaintextOutputPath)).catch(async () => { + await mkdir(path.dirname(plaintextOutputPath), { recursive: true }) + }) + + // Ensure correct extension is used + plaintextOutputPath = path.join( + path.dirname(plaintextOutputPath), + path.basename(plaintextOutputPath, path.extname(plaintextOutputPath)) + '.' + plaintextExtension + ) + + return writeFile(plaintextOutputPath, plaintext) + } + + /** + * If `plaintextOutputPath` is a directory path, output file there, using the template's name + */ + const templateFileName = get(templateConfig, 'build.current.path.name') + + plaintextOutputPath = path.join( + plaintextOutputPath, + get(templateConfig, 'build.current.path.dir'), + templateFileName + '.' + plaintextExtension + ) + + // Ensure the target directory exists + await lstat(path.dirname(plaintextOutputPath)).catch(async () => { + await mkdir(path.dirname(plaintextOutputPath), { recursive: true }) + }) + + return writeFile(plaintextOutputPath, plaintext) +} diff --git a/src/generators/postcss.js b/src/generators/postcss.js deleted file mode 100644 index 416de6c1..00000000 --- a/src/generators/postcss.js +++ /dev/null @@ -1,23 +0,0 @@ -const {get} = require('lodash') -const postcss = require('postcss') -const postcssImport = require('postcss-import') -const postcssNested = require('tailwindcss/nesting') -const mergeLonghand = require('postcss-merge-longhand') - -module.exports = { - process: async (css = '', maizzleConfig = {}) => { - return postcss([ - postcssImport(), - postcssNested(), - get(maizzleConfig, 'shorthandCSS', get(maizzleConfig, 'shorthandInlineCSS')) === true ? - mergeLonghand() : - () => {}, - ...get(maizzleConfig, 'build.postcss.plugins', []) - ]) - .process(css, {from: undefined}) - .then(result => result.css) - .catch(error => { - throw new SyntaxError(error) - }) - } -} diff --git a/src/generators/posthtml/index.js b/src/generators/posthtml/index.js deleted file mode 100644 index 62e2c2a8..00000000 --- a/src/generators/posthtml/index.js +++ /dev/null @@ -1,75 +0,0 @@ -const fm = require('front-matter') -const posthtml = require('posthtml') -const fetch = require('posthtml-fetch') -const layouts = require('posthtml-extend') -const {get, merge, omit} = require('lodash') -const components = require('posthtml-component') -const defaultPosthtmlConfig = require('./defaultConfig') -const defaultComponentsConfig = require('./defaultComponentsConfig') - -module.exports = async (html, config) => { - const posthtmlOptions = merge(defaultPosthtmlConfig, get(config, 'build.posthtml.options', {})) - const posthtmlPlugins = get(config, 'build.posthtml.plugins', []) - - const componentsUserOptions = get(config, 'build.components', {}) - - const expressionsOptions = merge( - { - loopTags: ['each', 'for'], - strictMode: false - }, - get(componentsUserOptions, 'expressions', {}), - get(config, 'build.posthtml.expressions', {}) - ) - - const locals = merge( - get(expressionsOptions, 'locals', {}), - get(config, 'locals', {}), - {page: config} - ) - - const fetchPlugin = fetch( - merge( - { - expressions: merge(expressionsOptions, {locals}) - }, - get(config, 'build.posthtml.fetch', {}) - ) - ) - - const componentsOptions = merge( - { - ...defaultComponentsConfig, - folders: [ - ...get(componentsUserOptions, 'folders', []), - ...defaultComponentsConfig.folders - ], - expressions: merge(expressionsOptions, {locals}) - }, - { - root: componentsUserOptions.root || './' - }, - /** - * We omit `folders`, `root` and `expressions` in order to prevent duplicate - * array values, as they are already added above - */ - omit(componentsUserOptions, ['folders', 'root', 'expressions']) - ) - - return posthtml([ - fetchPlugin, - layouts( - merge( - { - strict: false, - expressions: merge(expressionsOptions, {locals}) - }, - get(config, 'build.layouts', {}) - ) - ), - components(componentsOptions), - ...posthtmlPlugins - ]) - .process(html, {...posthtmlOptions}) - .then(result => fm(result.html).body) -} diff --git a/src/generators/render.js b/src/generators/render.js new file mode 100644 index 00000000..abf7f01f --- /dev/null +++ b/src/generators/render.js @@ -0,0 +1,128 @@ +import { parse } from 'pathe' +import posthtml from 'posthtml' +import { cwd } from 'node:process' +import { defu as merge } from 'defu' +import expressions from 'posthtml-expressions' +import { parseFrontMatter } from '../utils/node.js' +import { process as compilePostHTML } from '../posthtml/index.js' +import { run as useTransformers } from '../transformers/index.js' + +export async function render(html = '', config = {}) { + if (typeof html !== 'string') { + throw new TypeError(`first argument must be a string, received ${html}`) + } + + if (html.length === 0) { + throw new RangeError('received empty string') + } + + /** + * Parse front matter + * + * Parse expressions in front matter and add to config + * This could be handled by components() but plugins aren't working with it currently + */ + let { content, matter } = parseFrontMatter(html) + + /** + * Compute template config + * + * Merge it with front matter data and set the `cwd` for Tailwind. + */ + const { data: matterData } = await posthtml( + [ + expressions({ + strictMode: false, + missingLocal: '{local}', + locals: { + page: config + } + }) + ] + ) + .process(matter) + .then(({ html }) => parseFrontMatter(`---${html}\n---`)) + + const templateConfig = merge(matterData, config) + + /** + * Used for PostCSS `from` to make `@config` work in Tailwind + * + * @todo use only when in Node environment + */ + templateConfig.cwd = parse(cwd()).base + + /** + * Run `beforeRender` event + * + * @param {Object} options + * @param {string} options.html - The HTML to be transformed + * @param {Object} options.config - The current template config + * @param {function} options.render - The render function + * @returns {string} - The transformed HTML, or the original one if nothing was returned + */ + if (typeof templateConfig.beforeRender === 'function') { + content = await templateConfig.beforeRender(({ + html: content, + config: templateConfig, + render + })) ?? content + } + + // Compile PostHTML + const compiled = await compilePostHTML(content, templateConfig) + + /** + * Run `afterRender` event + * + * @param {Object} options + * @param {string} options.html - The HTML to be transformed + * @param {Object} options.config - The current template config + * @param {function} options.render - The render function + * @returns {string} - The transformed HTML, or the original one if nothing was returned + */ + if (typeof templateConfig.afterRender === 'function') { + compiled.html = await templateConfig.afterRender(({ + html: compiled.html, + config: templateConfig, + render + })) ?? compiled.html + } + + // Run Transformers + /** + * Run Transformers + * + * Runs only if `useTransformers` is not explicitly disabled in the config. + * + * @param {string} html - The HTML to be transformed + * @param {Object} config - The current template config + * @returns {string} - The transformed HTML + */ + if (templateConfig.useTransformers !== false) { + compiled.html = await useTransformers(compiled.html, templateConfig).then(({ html }) => html) + } + + // Run `afterTransformers` event + /** + * Run `afterTransformers` event + * + * @param {Object} options + * @param {string} options.html - The HTML to be transformed + * @param {Object} options.config - The current template config + * @param {function} options.render - The render function + * @returns {string} - The transformed HTML, or the original one if nothing was returned + */ + if (typeof templateConfig.afterTransformers === 'function') { + compiled.html = await templateConfig.afterTransformers(({ + html: compiled.html, + config: templateConfig, + render + })) ?? compiled.html + } + + return { + config: templateConfig, + html: compiled.html, + } +} diff --git a/src/generators/tailwindcss.js b/src/generators/tailwindcss.js deleted file mode 100644 index e98034b4..00000000 --- a/src/generators/tailwindcss.js +++ /dev/null @@ -1,157 +0,0 @@ -const fs = require('fs-extra') -const path = require('node:path') -const postcss = require('postcss') -const tailwindcss = require('tailwindcss') -const postcssImport = require('postcss-import') -const {get, merge, isObject, isEmpty} = require('lodash') -const postcssNested = require('tailwindcss/nesting') -const {requireUncached} = require('../utils/helpers') -const mergeLonghand = require('postcss-merge-longhand') -const defaultComponentsConfig = require('./posthtml/defaultComponentsConfig') - -const addImportantPlugin = () => { - return { - postcssPlugin: 'add-important', - Rule(rule) { - const shouldAddImportant = get(rule, 'raws.tailwind.layer') === 'variants' - || get(rule, 'parent.type') === 'atrule' - - if (shouldAddImportant) { - rule.walkDecls(decl => { - decl.important = true - }) - } - } - } -} - -module.exports = { - compile: async ({css = '', html = '', config = {}}) => { - // Compute the Tailwind config to use - const userConfig = config => { - const tailwindUserConfig = get(config, 'build.tailwind.config', 'tailwind.config.js') - - // If a custom config object was passed, use that - if (isObject(tailwindUserConfig) && !isEmpty(tailwindUserConfig)) { - return tailwindUserConfig - } - - /** - * Try loading a fresh tailwind.config.js, with fallback to an empty object. - * This will use the default Tailwind config (with rem units etc) - */ - try { - return requireUncached(path.resolve(process.cwd(), tailwindUserConfig)) - } catch { - return {} - } - } - - // Merge user's Tailwind config on top of a 'base' config - const layoutsRoot = get(config, 'build.layouts.root') - const componentsRoot = get(config, 'build.components.root', defaultComponentsConfig.root) - - const layoutsPath = typeof layoutsRoot === 'string' && layoutsRoot ? - `${layoutsRoot}/**/*.*`.replace(/\/\//g, '/') : - 'src/layouts/**/*.*' - - const componentsPath = defaultComponentsConfig.folders.map(folder => { - return path - .join(componentsRoot, folder, `**/*.${defaultComponentsConfig.fileExtension}`) - .replace(/\\/g, '/') - .replace(/\/\//g, '/') - }) - - const tailwindConfig = merge({ - content: { - files: [ - ...componentsPath, - layoutsPath - ] - } - }, userConfig(config)) - - // If `content` is an array, add it to `content.files` - if (Array.isArray(tailwindConfig.content)) { - tailwindConfig.content = { - files: [ - ...componentsPath, - layoutsPath, - ...tailwindConfig.content - ] - } - } - - // Add raw HTML if using API - if (html) { - tailwindConfig.content.files.push({raw: html, extension: 'html'}) - } - - // Include all `build.templates.source` paths when scanning for selectors to preserve - const buildTemplates = get(config, 'build.templates') - - if (buildTemplates) { - const templateObjects = Array.isArray(buildTemplates) ? buildTemplates : [buildTemplates] - const configFileTypes = get(buildTemplates, 'filetypes', ['html']) - const fileTypes = Array.isArray(configFileTypes) ? configFileTypes : configFileTypes.split('|') - const fileTypesPattern = fileTypes.length > 1 ? `{${fileTypes.join(',')}}` : fileTypes[0] - - for (const template of templateObjects) { - const source = get(template, 'source') - - if (typeof source === 'function') { - const sources = source(config) - - if (Array.isArray(sources)) { - sources.map(s => tailwindConfig.content.files.push(`${s}/**/*.${fileTypesPattern}`)) - } else if (typeof sources === 'string') { - tailwindConfig.content.files.push(sources) - } - } - - // Support single-file sources i.e. src/templates/index.html - else if (typeof source === 'string' && Boolean(path.extname(source))) { - tailwindConfig.content.files.push(source) - } - - // Default behavior - directory sources as a string - else { - tailwindConfig.content.files.push(`${source}/**/*.${fileTypesPattern}`) - } - } - } - - // Filter out any duplicate content paths - tailwindConfig.content.files = [...new Set(tailwindConfig.content.files)] - - const userFilePath = get(config, 'build.tailwind.css', path.join(process.cwd(), 'src/css/tailwind.css')) - const userFileExists = await fs.pathExists(userFilePath) - - const toProcess = [ - postcssNested(), - tailwindcss(tailwindConfig), - get(tailwindConfig, 'important') === false ? () => {} : addImportantPlugin(), - get(config, 'shorthandCSS', get(config, 'shorthandInlineCSS')) === true ? - mergeLonghand() : - () => {}, - ...get(config, 'build.postcss.plugins', []) - ] - - if (userFileExists) { - css = await fs.readFile(path.resolve(userFilePath), 'utf8') + css - - toProcess.unshift( - postcssImport({path: path.dirname(userFilePath)}) - ) - } else { - css = `@tailwind components; @tailwind utilities; ${css}` - } - - return postcss([...toProcess]) - .process(css, {from: userFileExists ? userFilePath : undefined}) - .then(result => result.css) - .catch(error => { - throw new SyntaxError(error) - }) - } -} diff --git a/src/index.js b/src/index.js index 62f741b4..15478f5b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,17 +1,49 @@ -const serve = require('./commands/serve') -const toFile = require('./commands/build') -const render = require('./functions/render') -const transformers = require('./transformers') -const PostCSS = require('./generators/postcss') -const toPlaintext = require('./functions/plaintext') -const TailwindCSS = require('./generators/tailwindcss') +import serve from './server/index.js' +import build from './commands/build.js' +import { render } from './generators/render.js' -module.exports = { +import { addAttributes } from './transformers/addAttributes.js' +import { attributeToStyle } from './transformers/attributeToStyle.js' +import { addBaseUrl } from './transformers/baseUrl.js' +import { comb } from './transformers/comb.js' +import { filters } from './transformers/filters/index.js' +import { inline } from './transformers/inline.js' +import { markdown } from './transformers/markdown.js' +import { minify } from './transformers/minify.js' +import { useMso } from './transformers/posthtmlMso.js' +import { prettify } from './transformers/prettify.js' +import { removeAttributes } from './transformers/removeAttributes.js' +import { replaceStrings } from './transformers/replaceStrings.js' +import { safeClassNames } from './transformers/safeClassNames.js' +import { shorthandCSS } from './transformers/shorthandCss.js' +import { sixHEX } from './transformers/sixHex.js' +import { addURLParams } from './transformers/urlParameters.js' +import { useAttributeSizes } from './transformers/useAttributeSizes.js' +import { preventWidows } from './transformers/preventWidows.js' +import { generatePlaintext } from './generators/plaintext.js' + +export { + build, serve, render, - build: toFile, - ...transformers, - postcss: PostCSS, - plaintext: toPlaintext, - tailwindcss: TailwindCSS + addAttributes, + attributeToStyle, + addBaseUrl, + comb as removeUnusedCSS, + comb as purgeCSS, + filters, + inline as inlineCSS, + markdown, + minify, + useMso, + prettify, + removeAttributes, + replaceStrings, + safeClassNames, + shorthandCSS, + sixHEX, + addURLParams, + useAttributeSizes, + preventWidows, + generatePlaintext, } diff --git a/src/generators/posthtml/defaultComponentsConfig.js b/src/posthtml/defaultComponentsConfig.js similarity index 50% rename from src/generators/posthtml/defaultComponentsConfig.js rename to src/posthtml/defaultComponentsConfig.js index 722841da..5028da20 100644 --- a/src/generators/posthtml/defaultComponentsConfig.js +++ b/src/posthtml/defaultComponentsConfig.js @@ -1,9 +1,11 @@ -module.exports = { +export default { root: './', folders: ['src/components', 'src/layouts', 'src/templates'], fileExtension: 'html', tag: 'component', - attribute: 'src', - yield: 'content', - propsAttribute: 'locals' + expressions: { + loopTags: ['each', 'for'], + missingLocal: '{local}', + strictMode: false, + }, } diff --git a/src/generators/posthtml/defaultConfig.js b/src/posthtml/defaultConfig.js similarity index 77% rename from src/generators/posthtml/defaultConfig.js rename to src/posthtml/defaultConfig.js index f1c6e778..81e0ab9f 100644 --- a/src/generators/posthtml/defaultConfig.js +++ b/src/posthtml/defaultConfig.js @@ -1,4 +1,4 @@ -module.exports = { +export default { recognizeNoValueAttribute: true, recognizeSelfClosing: true } diff --git a/src/posthtml/index.js b/src/posthtml/index.js new file mode 100644 index 00000000..9df5f2d8 --- /dev/null +++ b/src/posthtml/index.js @@ -0,0 +1,74 @@ +import get from 'lodash-es/get.js' +import { defu as merge } from 'defu' + +// PostHTML +import posthtml from 'posthtml' +import components from 'posthtml-component' +import posthtmlPostcss from 'posthtml-postcss' +import defaultPosthtmlConfig from './defaultConfig.js' +import expandLinkTag from './plugins/expandLinkTag.js' + +// PostCSS +import tailwindcss from 'tailwindcss' +import postcssImport from 'postcss-import' +import postcssSafeParser from 'postcss-safe-parser' +import customProperties from 'postcss-custom-properties' + +import defaultComponentsConfig from './defaultComponentsConfig.js' + +export async function process(html = '', config = {}) { + const postcssPlugin = posthtmlPostcss( + [ + postcssImport(), + tailwindcss(get(config, 'css.tailwind', {})), + get(config, 'css.inline.resolveCSSVariables', true) && customProperties(), + ...get(config, 'postcss.plugins', []), + ], + merge( + get(config, 'postcss.options', {}), + { + from: config.cwd || './', + parser: postcssSafeParser + } + ) + ) + + const posthtmlOptions = merge(get(config, 'posthtml.options', {}), defaultPosthtmlConfig) + + const componentsUserOptions = get(config, 'components', {}) + + const expressionsOptions = merge( + get(config, 'build.expressions', get(config, 'posthtml.expressions', {})), + get(componentsUserOptions, 'expressions', {}), + ) + + const locals = merge( + get(config, 'locals', {}), + get(expressionsOptions, 'locals', {}), + { page: config }, + ) + + return posthtml([ + ...get(config, 'posthtml.plugins.before', []), + expandLinkTag, + postcssPlugin, + components( + merge({ + expressions: { + locals, + } + }, defaultComponentsConfig) + ), + expandLinkTag, + postcssPlugin, + ...get(config, 'posthtml.plugins.after', get(config, 'posthtml.plugins', [])) + ]) + .process(html, posthtmlOptions) + .then(result => ({ + config, + html: result.html, + })) + .catch(error => { + throw error + }) +} diff --git a/src/posthtml/plugins/expandLinkTag.js b/src/posthtml/plugins/expandLinkTag.js new file mode 100644 index 00000000..957c10e2 --- /dev/null +++ b/src/posthtml/plugins/expandLinkTag.js @@ -0,0 +1,36 @@ +import fs from 'node:fs' + +const targets = new Set(['expand', 'inline']) + +// TODO: refactor to a Promise so we can use async readFile +const plugin = (() => tree => { + const process = node => { + /** + * Don't expand link tags that are not explicitly marked as such + */ + if (node.attrs && ![...targets].some(attr => attr in node.attrs)) { + for (const attr of targets) { + node.attrs[attr] = false + } + + return node + } + + if ( + node.tag === 'link' + && node.attrs + && node.attrs.href + && node.attrs.rel === 'stylesheet' + ) { + node.content = [fs.readFileSync(node.attrs.href, 'utf8')] + node.tag = 'style' + node.attrs = {} + } + + return node + } + + return tree.walk(process) +})() + +export default plugin diff --git a/src/server/client.js b/src/server/client.js new file mode 100644 index 00000000..6367bbe0 --- /dev/null +++ b/src/server/client.js @@ -0,0 +1,181 @@ +// biome-ignore lint: need it globally +var lastKnownScrollPosition = 0 + +function connectWebSocket() { + if (!('WebSocket' in window)) { + return + } + + const { hostname, port } = window.location + const socket = new WebSocket(`ws://${hostname}:${port}`) + + /** + * Synchronized scrolling + * Sends the scroll position to the server + */ + function handleScroll() { + socket.send(JSON.stringify({ + type: 'scroll', + position: window.scrollY + })) + } + + function scrollHandler() { + lastKnownScrollPosition = window.scrollY + requestAnimationFrame(handleScroll) + } + + window.addEventListener('scroll', scrollHandler) + + socket.addEventListener('message', async event => { + const data = JSON.parse(event.data) + + if (data.type === 'scroll' && data.scrollSync === true) { + window.scrollTo(0, data.position) + } + + if (data.type === 'change') { + if (data.hmr === true) { + // Use morphdom to update the existing DOM with the new content + morphdom(document.documentElement, data.content, { + childrenOnly: true, + onBeforeElUpdated(fromEl, toEl) { + // Speed-up trick from morphdom docs - https://dom.spec.whatwg.org/#concept-node-equals + if (fromEl.isEqualNode(toEl)) { + return false + } + + return true + }, + onElUpdated(el) { + // Handle broken images updates, like incorrect file paths + if (el.tagName === 'IMG' && !el.complete) { + const img = new Image() + img.src = el.src + el.src = '' + + img.onload = () => { + el.src = img.src + } + } + }, + }) + } else { + // Reload the page + window.location.reload() + } + + /** + * Fix for attributes not being updated on <html> tag + * Borrowed from https://github.com/11ty/eleventy-dev-server/ + */ + const parser = new DOMParser() + const parsed = parser.parseFromString(data.content, 'text/html') + const parsedDoc = parsed.documentElement + const newAttrs = parsedDoc.getAttributeNames() + const docEl = document.documentElement + + // Remove old attributes + const removedAttrs = docEl.getAttributeNames().filter(name => !newAttrs.includes(name)) + for (const attr of removedAttrs) { + docEl.removeAttribute(attr) + } + + // Add new attributes + for (const attr of newAttrs) { + docEl.setAttribute(attr, parsedDoc.getAttribute(attr)) + } + } + + if (['add', 'unlink'].includes(data.type)) { + if (data.hmr === true) { + const randomNumber = Math.floor(Math.random() * 10 ** 16).toString().padStart(16, '0') + + /** + * Cache busting for images + * + * Appends a `?v=` cache-busting parameter to image sources + * every time a file is added or removed. This forces the + * browser to re-download the image and immediately + * reflect the changes through HMR. + */ + + // For all elements with `src` attributes + const srcElements = document.querySelectorAll('[src]') + + srcElements.forEach(el => { + // Update the value of 'v' parameter if it already exists + if (el.src.includes('?')) { + el.src = el.src.replace(/([?&])v=[^&]*/, `$1v=${randomNumber}`) + } else { + // Add 'v' parameter + el.src += `?v=${randomNumber}` + } + }) + + // For `background` attributes + const htmlBgElements = document.querySelectorAll('[background]') + + htmlBgElements.forEach(el => { + const bgValue = el.getAttribute('background') + if (bgValue) { + // Update the value of 'v' parameter if it already exists + if (bgValue.includes('?')) { + el.setAttribute('background', bgValue.replace(/([?&])v=[^&]*/, `$1v=${randomNumber}`)) + } else { + // Add 'v' parameter + el.setAttribute('background', `${bgValue}?v=${randomNumber}`) + } + } + }) + + // For inline CSS `background` properties + const styleElements = document.querySelectorAll('[style]') + + styleElements.forEach(el => { + const styleAttribute = el.getAttribute('style') + if (styleAttribute) { + const urlPattern = /(url\(["']?)(.*?)(["']?\))/g + // Replace URLs in style attribute with cache-busting parameter + const updatedStyleAttribute = styleAttribute.replace(urlPattern, (match, p1, p2, p3) => { + // Update the value of 'v' parameter if it already exists + if (p2.includes('?')) { + return `${p1}${p2.replace(/([?&])v=[^&]*/, `$1v=${randomNumber}`)}${p3}` + } + + // Add 'v' parameter + return `${p1}${p2}?v=${randomNumber}${p3}` + }) + + // Update style attribute + el.setAttribute('style', updatedStyleAttribute) + } + }) + } else { + // Reload the page + window.location.reload() + } + } + }) + + socket.addEventListener('close', () => { + window.removeEventListener('scroll', scrollHandler) + + // debug only: + console.log('WebSocket connection closed. Reconnecting...') + + // Reconnect after a short delay + setTimeout(() => { + connectWebSocket() + }, 1000) + }) + + // Handle connection opened + socket.addEventListener('open', event => { + console.log('WebSocket connection opened') + }) + + return socket +} + +connectWebSocket() diff --git a/src/server/index.js b/src/server/index.js new file mode 100644 index 00000000..9be36bc9 --- /dev/null +++ b/src/server/index.js @@ -0,0 +1,383 @@ +import path from 'pathe' +import fs from 'node:fs/promises' +import { createServer } from 'node:http' +import { cwd, exit } from 'node:process' + +import { fileURLToPath } from 'node:url' +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +import ora from 'ora' +import fg from 'fast-glob' +import express from 'express' +import pico from 'picocolors' +import get from 'lodash-es/get.js' +import * as chokidar from 'chokidar' +import { isBinary } from 'istextorbinary' + +import WebSocket, { WebSocketServer } from 'ws' +import { initWebSockets } from './websockets.js' + +import { + getLocalIP, + getColorizedFileSize, +} from '../utils/node.js' +import { injectScript, formatTime } from '../utils/string.js' + +import { render } from '../generators/render.js' +import { readFileConfig } from '../utils/getConfigByFilePath.js' +import defaultComponentsConfig from '../posthtml/defaultComponentsConfig.js' + +// Routes +import hmrRoute from './routes/hmr.js' +import indexRoute from './routes/index.js' + +const app = express() +const wss = new WebSocketServer({ noServer: true }) + +// Register routes +app.use(indexRoute) +app.use(hmrRoute) + +let viewing = '' +const spinner = ora() + +export default async (config = {}) => { + // Read the Maizzle config file + config = await readFileConfig(config).catch(() => { throw new Error('Could not compute config') }) + + /** + * Dev server settings + */ + const shouldScroll = get(config, 'server.scrollSync', false) + const useHmr = get(config, 'server.hmr', true) + + // Add static assets root prefix so user doesn't have to + if (!config.baseURL) { + config.baseURL = '/' + } + + /** + * Initialize WebSocket server + * Used to send messages between the server and the browser + */ + initWebSockets(wss, { scrollSync: shouldScroll, hmr: useHmr }) + + // Get a list of all template paths + const templateFolders = Array.isArray(get(config, 'build.content')) + ? config.build.content + : [config.build.content] + + const templatePaths = await fg.glob([...new Set(templateFolders)]) + + // Set the template paths on the app, we use them in the index view + app.request.templatePaths = templatePaths + + /** + * Create route pattern + * Only allow files with the following extensions + */ + const extensions = [ + ...new Set(templatePaths + .filter(p => !isBinary(p)) // exclude binary files from routes + .map(p => path.extname(p).slice(1).toLowerCase()) + ) + ].join('|') + + const routePattern = Array.isArray(templateFolders) + ? `*/:file.(${extensions})` + : `:file.(${extensions})` + + /** + * Loop over the source folders and create route for each file + */ + templatePaths.forEach(() => { + app.get(routePattern, async (req, res, next) => { + // Run beforeCreate event + if (typeof config.beforeCreate === 'function') { + config.beforeCreate(config) + } + + try { + const filePath = templatePaths.find(t => t.endsWith(req.url.slice(1))) + + // Set the file being viewed + viewing = filePath + + // Read the file + const fileContent = await fs.readFile(filePath, 'utf8') + + // Set a `dev` flag on the config + config._dev = true + + // Render the file with PostHTML + let { html } = await render(fileContent, config) + + /** + * Inject HMR script + */ + html = injectScript(html, '<script src="/hmr.js"></script>') + + res.send(html) + } catch (error) { + spinner.fail(`Failed to render template: ${req.url}\n`) + next(error) + } + }) + }) + + // Error-handling middleware + app.use(async (error, req, res, next) => { // eslint-disable-line + console.error(error) + + const view = await fs.readFile(path.join(__dirname, 'views', 'error.html'), 'utf8') + const { html } = await render(view, { + method: req.method, + url: req.url, + error + }) + + res.status(500).send(html) + }) + + /** + * Components watcher + * + * Watches for changes in the configured Templates and Components paths + */ + chokidar + .watch([...templatePaths, ...get(config, 'components.folders', defaultComponentsConfig.folders) ]) + .on('change', async () => { + // Not viewing a component in the browser, no need to rebuild + if (!viewing) { + return + } + + try { + const startTime = Date.now() + spinner.start('Building...') + + // beforeCreate event + if (typeof config.beforeCreate === 'function') { + await config.beforeCreate(config) + } + + // Read the file + const fileContent = await fs.readFile(viewing, 'utf8') + + // Set a `dev` flag on the config + config._dev = true + + // Render the file with PostHTML + let { html } = await render(fileContent, config) + + // Update console message + const shouldReportFileSize = get(config, 'server.reportFileSize', false) + + spinner.succeed( + `Done in ${formatTime(Date.now() - startTime)}` + + `${pico.gray(` [${path.relative(cwd(), viewing)}]`)}` + + `${ shouldReportFileSize ? ' · ' + getColorizedFileSize(html) : ''}` + ) + + /** + * Inject HMR script + */ + html = injectScript(html, '<script src="/hmr.js"></script>') + + // Notify connected websocket clients about the change + wss.clients.forEach(client => { + if (client.readyState === WebSocket.OPEN) { + client.send(JSON.stringify({ + type: 'change', + content: html, + scrollSync: get(config, 'server.scrollSync', false), + hmr: get(config, 'server.hmr', true), + })) + } + }) + } catch (error) { + spinner.fail('Failed to render template.') + throw error + } + }) + + /** + * Global watcher + * + * Watch for changes in the config file, Tailwind CSS config, and CSS files + */ + const globalWatchedPaths = new Set([ + 'config*.js', + 'maizzle.config*.js', + 'tailwind*.config.js', + '**/*.css', + ...get(config, 'server.watch', []) + ]) + + async function globalPathsHandler(file, eventType) { + // Not viewing a component in the browser, no need to rebuild + if (!viewing) { + spinner.info(`file ${eventType}: ${file}`) + return + } + + try { + const startTime = Date.now() + spinner.start('Building...') + + // Read the Maizzle config file + config = await readFileConfig() + + // Add static assets root prefix so user doesn't have to + if (!config.baseURL) { + config.baseURL = '/' + } + + // Run beforeCreate event + if (typeof config.beforeCreate === 'function') { + await config.beforeCreate(config) + } + + // Read the file + const filePath = templatePaths.find(t => t.endsWith(viewing)) + const fileContent = await fs.readFile(path.normalize(filePath), 'utf8') + + // Set a `dev` flag on the config + config._dev = true + + // Render the file with PostHTML + let { html } = await render(fileContent, config) + + // Update console message + const shouldReportFileSize = get(config, 'server.reportFileSize', false) + + spinner.succeed( + `Done in ${formatTime(Date.now() - startTime)}` + + `${pico.gray(` [${path.relative(cwd(), filePath)}]`)}` + + `${ shouldReportFileSize ? ' · ' + getColorizedFileSize(html) : ''}` + ) + + /** + * Inject HMR script + */ + html = injectScript(html, '<script src="/hmr.js"></script>') + + // Notify connected websocket clients about the change + wss.clients.forEach(client => { + if (client.readyState === WebSocket.OPEN) { + client.send(JSON.stringify({ + type: eventType, + content: html, + scrollSync: get(config, 'server.scrollSync', false), + hmr: get(config, 'server.hmr', true), + })) + } + }) + } catch (error) { + spinner.fail('Failed to render template.') + throw error + } + } + + chokidar + .watch([...globalWatchedPaths], { + ignored: [ + 'node_modules', + get(config, 'build.output.path', 'build_production'), + ], + ignoreInitial: true, + }) + .on('change', async file => await globalPathsHandler(file, 'change')) + .on('add', async file => await globalPathsHandler(file, 'add')) + .on('unlink', async file => await globalPathsHandler(file, 'unlink')) + + /** + * Serve all folders in the cwd as static files + * + * TODO: change to include build.assets or build.static, which may be outside cwd + */ + const srcFoldersList = await fg.glob( + [ + '**/*/', + ...get(config, 'build.static.source', []) + ], { + onlyFiles: false, + ignore: [ + 'node_modules', + get(config, 'build.output.path', 'build_*'), + ] + }) + + srcFoldersList.forEach(folder => { + app.use(express.static(path.join(config.cwd, folder))) + }) + + /** + * Start the server + */ + let retryCount = 0 + const port = get(config, 'server.port', 3000) + const maxRetries = get(config, 'server.maxRetries', 10) + + function startServer(port) { + const serverStartTime = Date.now() + spinner.start('Starting server...') + + const server = createServer(app) + + /** + * Handle WebSocket upgrades + * Attaches the WebSocket server to the Express server. + */ + server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, ws => { + wss.emit('connection', ws, request) + }) + }) + + server.listen(port, async () => { + const { version } = JSON.parse( + await fs.readFile( + new URL('../../package.json', import.meta.url) + ) + ) + + spinner.stopAndPersist({ + text: `${pico.bgBlue(` Maizzle v${version} `)} ready in ${pico.bold(Date.now() - serverStartTime)} ms` + + '\n\n' + + ` → Local: http://localhost:${port}` + + '\n' + + ` → Network: http://${getLocalIP()}:${port}\n` + }) + }) + + server.on('error', error => { + try { + if (error.code === 'EADDRINUSE') { + server.close() + retryPort() + } + } catch (error) { + spinner.fail(error.message) + exit(1) + } + }) + + return server + } + + function retryPort() { + retryCount++ + + if (retryCount <= maxRetries) { + const nextPort = port + retryCount + startServer(nextPort) + } else { + spinner.fail(`Exceeded maximum number of retries (${maxRetries}). Unable to find a free port.`) + + exit(1) + } + } + + startServer(port) +} diff --git a/src/server/routes/hmr.js b/src/server/routes/hmr.js new file mode 100644 index 00000000..dfce12dd --- /dev/null +++ b/src/server/routes/hmr.js @@ -0,0 +1,24 @@ +import express from 'express' +const router = express.Router() +import fs from 'node:fs/promises' +import { dirname, join } from 'pathe' +import { fileURLToPath } from 'node:url' + +const __dirname = dirname(fileURLToPath(import.meta.url)) + +router.get('/hmr.js', async (req, res) => { + const morphdomScript = await fs.readFile( + join(__dirname, '../../../node_modules/morphdom/dist/morphdom-umd.js'), + 'utf8' + ) + + const clientScript = await fs.readFile( + join(__dirname, '../client.js'), + 'utf8' + ) + + res.setHeader('Content-Type', 'application/javascript') + res.send(morphdomScript + clientScript) +}) + +export default router diff --git a/src/server/routes/index.js b/src/server/routes/index.js new file mode 100644 index 00000000..096b3fa0 --- /dev/null +++ b/src/server/routes/index.js @@ -0,0 +1,38 @@ +import path from 'pathe' +import express from 'express' +const route = express.Router() +import posthtml from 'posthtml' +import fs from 'node:fs/promises' +import { fileURLToPath } from 'node:url' +import expressions from 'posthtml-expressions' +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +route.get(['/', '/index.html'], async (req, res) => { + const view = await fs.readFile(path.join(__dirname, '../views', 'index.html'), 'utf8') + + // Group by `dir` + const groupedByDir = {} + + req.templatePaths + .map(t => path.parse(t)) + .forEach(file => { + if (!groupedByDir[file.dir]) { + groupedByDir[file.dir] = [] + } + + file.href = [file.dir.replace(file.root, ''), file.base].join('/') + groupedByDir[file.dir].push(file) + }) + + const { html } = await posthtml() + .use(expressions({ + locals: { + templates: groupedByDir + } + })) + .process(view) + + res.send(html) +}) + +export default route diff --git a/src/server/views/error.html b/src/server/views/error.html new file mode 100644 index 00000000..52c2cc4f --- /dev/null +++ b/src/server/views/error.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Error</title> + <style> + body { + font-family: Helvetica, Arial, sans-serif; + margin: 0; + padding: 0; + box-sizing: border-box; + } + + .container { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + position: relative; + z-index: 1; + padding: 24px; + } + + .stack-trace-wrapper { + width: 100%; + max-width: 90ch; + margin-top: 2.25rem; + } + + .stack-trace { + overflow-x: auto; + padding: 24px; + border-radius: 4px; + text-align: left; + font-size: 1rem; + box-shadow: 0px 0px 30px rgba(0, 0, 0, 0.1); + border-left: 4px solid #FB7185; + background-color: rgba(248, 250, 252, 0.7); + backdrop-filter: blur(4px); + font-family: 'Courier New', Courier, monospace; + } + </style> +</head> +<body> + <div class="container"> + <h1 style="font-size: 3rem; color: #0F172A; margin: 2.25rem 0"> + <span style="color: #4f46e5">Oops!</span> + Something went wrong. + </h1> + + <p style="margin: 0 0 2.25rem; font-size: 1.25rem; line-height: 1.5; color: #64748B;"> + {{ page.error.message }} + </p> + + <span style="padding: 2px 12px; font-size: 1rem; line-height: 1.5; color: #fff; background-color: #64748B; border-radius: 8px;"> + {{ page.method }} + </span> + + <p style="margin: 1rem 0 0; font-size: 1rem; line-height: 1.5; font-weight: 600; color: #334155;"> + {{ page.url }} + </p> + + <if condition="page.error.code"> + <p style="margin: 1rem 0 0; font-size: 1rem; line-height: 1.5; font-weight: 600; color: #334155;"> + {{ page.error.code }} + </p> + </if> + + <div class="stack-trace-wrapper"> + <div class="stack-trace"> + <each loop="line, index in page.error.stack.split('\n')"> + <p>{{{ line }}}</p> + </each> + </div> + </div> + </div> + + <div style="position: fixed; bottom: 0; right: 0; pointer-events: none; user-select: none;"> + <svg width="883" height="536" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="a" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="1100" height="536"><path fill="#D9D9D9" d="M0 .955h1100V536H0z"/></mask><g mask="url(#a)" stroke="#94A3B8" stroke-miterlimit="10"><path d="M1056.93 92.587c0-50.03-43.95-90.587-98.168-90.587-54.22 0-98.174 40.557-98.174 90.587v483.125c0 50.029 43.954 90.586 98.174 90.586 54.218 0 98.168-40.557 98.168-90.586V92.587ZM646.241 92.587C646.241 42.556 602.287 2 548.067 2c-54.219 0-98.173 40.557-98.173 90.587v483.125c0 50.029 43.954 90.586 98.173 90.586 54.22 0 98.174-40.557 98.174-90.586V92.587Z"/><path d="M1036.18 148.383c33.41-39.402 25.88-96.336-16.82-127.164C976.657-9.61 914.955-2.66 881.544 36.742L471.586 520.215c-33.411 39.402-25.879 96.336 16.824 127.164 42.702 30.829 104.404 23.879 137.815-15.523l409.955-483.473ZM625.093 148.396c33.411-39.403 25.878-96.336-16.824-127.164C565.567-9.597 503.865-2.647 470.454 36.755L60.495 520.228c-33.41 39.402-25.878 96.336 16.825 127.164 42.702 30.829 104.404 23.879 137.815-15.523l409.958-483.473Z"/></g></svg> + </div> +</body> +</html> diff --git a/src/server/views/index.html b/src/server/views/index.html new file mode 100644 index 00000000..ece3e4f3 --- /dev/null +++ b/src/server/views/index.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Maizzle | Templates</title> +</head> +<body> + <each loop="items, index in templates"> + <div> + <h2>{{ index }}</h2> + <ul> + <each loop="item in items"> + <li> + <a href="{{ item.href }}"> + {{ item.base }} + </a> + </li> + </each> + </ul> + </div> + </each> +</body> +</html> diff --git a/src/server/websockets.js b/src/server/websockets.js new file mode 100644 index 00000000..2494f56f --- /dev/null +++ b/src/server/websockets.js @@ -0,0 +1,27 @@ +import WebSocket from 'ws' + +export function initWebSockets(wss, options = {}) { + options.shouldScroll = options.shouldScroll || false + options.useHmr = options.useHmr || true + + wss.on('connection', ws => { + // Handle incoming messages from the client + ws.on('message', message => { + const parsedMessage = JSON.parse(message) + + /** + * Broadcast message back to all connected clients + * We use it to send the scroll position back so other clients can follow + */ + wss.clients.forEach(client => { + if (client.readyState === WebSocket.OPEN) { + client.send(JSON.stringify({ + ...parsedMessage, + scrollSync: options.shouldScroll, + hmr: options.useHmr + })) + } + }) + }) + }) +} diff --git a/src/transformers/addAttributes.js b/src/transformers/addAttributes.js new file mode 100644 index 00000000..3e0d8f95 --- /dev/null +++ b/src/transformers/addAttributes.js @@ -0,0 +1,30 @@ +import posthtml from 'posthtml' +import { defu as merge } from 'defu' +import posthtmlConfig from '../posthtml/defaultConfig.js' +import addAttributesPlugin from 'posthtml-extra-attributes' + +export default function posthtmlPlugin(attributes = {}) { + const defaultAttributes = { + table: { + cellpadding: 0, + cellspacing: 0, + role: 'none' + }, + img: { + alt: '' + } + } + + // User-defined attributes take precedence + attributes = merge(attributes, defaultAttributes) + + return addAttributesPlugin({ attributes }) +} + +export async function addAttributes(html = '', attributes = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(attributes) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) +} diff --git a/src/transformers/attributeToStyle.js b/src/transformers/attributeToStyle.js index 58039bc9..0a892165 100644 --- a/src/transformers/attributeToStyle.js +++ b/src/transformers/attributeToStyle.js @@ -1,44 +1,28 @@ -const { - get, - merge, - forEach, - intersection, - keys, - isEmpty -} = require('lodash') -const posthtml = require('posthtml') -const parseAttrs = require('posthtml-attrs-parser') -const defaultConfig = require('../generators/posthtml/defaultConfig') - -module.exports = async (html, config = {}, direct = false) => { - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - const attributes = get(config, 'inlineCSS.attributeToStyle', false) - - if (typeof attributes === 'boolean' && attributes) { - return posthtml([attributesToStyle()]).process(html, posthtmlOptions).then(result => result.html) +import posthtml from 'posthtml' +import get from 'lodash-es/get.js' +import { defu as merge } from 'defu' +import keys from 'lodash-es/keys.js' +import forEach from 'lodash-es/forEach.js' +import parseAttrs from 'posthtml-attrs-parser' +import intersection from 'lodash-es/intersection.js' +import posthtmlConfig from '../posthtml/defaultConfig.js' + +const posthtmlPlugin = (attributes = []) => tree => { + if (!Array.isArray(attributes)) { + return tree } - if (Array.isArray(attributes) && !isEmpty(attributes)) { - return posthtml([attributesToStyle({attributes})]).process(html, posthtmlOptions).then(result => result.html) + if (attributes.length === 0) { + return tree } - if (direct) { - return posthtml([ - attributesToStyle({ - attributes: Array.isArray(config) ? config : [] - }) - ]).process(html, posthtmlOptions).then(result => result.html) - } - - return html -} - -const attributesToStyle = (options = {}) => tree => { - options.attributes = options.attributes || ['width', 'height', 'bgcolor', 'background', 'align', 'valign'] - const process = node => { + if (!node.attrs) { + return node + } + const nodeAttributes = parseAttrs(node.attrs) - const matches = intersection(keys(nodeAttributes), options.attributes) + const matches = intersection(keys(nodeAttributes), attributes) const nodeStyle = get(node.attrs, 'style') const cssToInline = [] @@ -87,7 +71,7 @@ const attributesToStyle = (options = {}) => tree => { } }) - nodeAttributes.style = nodeStyle ? `${nodeStyle} ${cssToInline.join('; ')}` : `${cssToInline.join('; ')}` + nodeAttributes.style = nodeStyle ? `${nodeStyle.split(';').join(';')} ${cssToInline.join('; ')}` : `${cssToInline.join('; ')}` node.attrs = nodeAttributes.compose() @@ -96,3 +80,13 @@ const attributesToStyle = (options = {}) => tree => { return tree.walk(process) } + +export default posthtmlPlugin + +export async function attributeToStyle(html = '', attributes = [], posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(attributes) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) +} diff --git a/src/transformers/baseUrl.js b/src/transformers/baseUrl.js index f4184db5..d185807b 100644 --- a/src/transformers/baseUrl.js +++ b/src/transformers/baseUrl.js @@ -1,48 +1,77 @@ -const posthtml = require('posthtml') -const isUrl = require('is-url-superb') -const baseUrl = require('posthtml-base-url') -const {get, merge, isObject, isEmpty} = require('lodash') -const defaultConfig = require('../generators/posthtml/defaultConfig') +import posthtml from 'posthtml' +import isUrl from 'is-url-superb' +import get from 'lodash-es/get.js' +import { defu as merge } from 'defu' +import baseUrl from 'posthtml-base-url' +import { render } from 'posthtml-render' +import isEmpty from 'lodash-es/isEmpty.js' +import isObject from 'lodash-es/isObject.js' +import { parser as parse } from 'posthtml-parser' +import posthtmlConfig from '../posthtml/defaultConfig.js' -module.exports = async (html, config = {}, direct = false) => { - const url = direct ? config : get(config, 'baseURL', get(config, 'baseUrl')) - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - - // Handle `baseUrl` as a string +const posthtmlPlugin = url => tree => { + // Handle `baseURL` as a string if (typeof url === 'string' && url.length > 0) { - html = rewriteVMLs(html, url) + const html = rewriteVMLs(render(tree), url) - return posthtml([ - baseUrl({url, allTags: true, styleTag: true, inlineCss: true}) - ]) - .process(html, posthtmlOptions) - .then(result => result.html) + return baseUrl({ + url, + allTags: true, + styleTag: true, + inlineCss: true + })(parse(html, posthtmlConfig)) } // Handle `baseURL` as an object if (isObject(url) && !isEmpty(url)) { - html = rewriteVMLs(html, get(url, 'url', '')) + const html = rewriteVMLs(render(tree), get(url, 'url', '')) + const { + styleTag = true, + inlineCss = true, + allTags, + tags, + url: baseURL, + ...posthtmlOptions + } = url - return posthtml([ - baseUrl(merge({styleTag: true, inlineCss: true}, url)) - ]) - .process(html, posthtmlOptions) - .then(result => result.html) + return baseUrl({ + styleTag, + inlineCss, + allTags, + tags, + url: baseURL, + })(parse(html, merge(posthtmlConfig, posthtmlOptions))) } - return html + return tree +} + +export default posthtmlPlugin + +export async function addBaseUrl(html = '', options = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(options) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) } /** + * Handle VML + * * VML backgrounds must be handled with regex because * they're inside HTML comments. + * + * @param {string} html The HTML content + * @param {string} url The base URL to prepend + * @returns {string} The modified HTML */ const rewriteVMLs = (html, url) => { // Handle <v:image> const vImageMatches = html.match(/<v:image[^>]+src="?([^"\s]+)"/g) if (vImageMatches) { - for (const match of vImageMatches) { + vImageMatches.forEach(match => { const vImage = match.match(/<v:image[^>]+src="?([^"\s]+)"/) const vImageSrc = vImage[1] @@ -51,14 +80,14 @@ const rewriteVMLs = (html, url) => { const vImageReplace = vImage[0].replace(vImageSrc, vImageSrcUrl) html = html.replace(vImage[0], vImageReplace) } - } + }) } // Handle <v:fill> const vFillMatches = html.match(/<v:fill[^>]+src="?([^"\s]+)"/g) if (vFillMatches) { - for (const match of vFillMatches) { + vFillMatches.forEach(match => { const vFill = match.match(/<v:fill[^>]+src="?([^"\s]+)"/) const vFillSrc = vFill[1] @@ -67,7 +96,7 @@ const rewriteVMLs = (html, url) => { const vFillReplace = vFill[0].replace(vFillSrc, vFillSrcUrl) html = html.replace(vFill[0], vFillReplace) } - } + }) } return html diff --git a/src/transformers/comb.js b/src/transformers/comb.js new file mode 100644 index 00000000..4814b3c4 --- /dev/null +++ b/src/transformers/comb.js @@ -0,0 +1,51 @@ +import posthtml from 'posthtml' +import get from 'lodash-es/get.js' +import { defu as merge } from 'defu' +import { render } from 'posthtml-render' +import { comb as emailComb } from 'email-comb' +import { parser as parse } from 'posthtml-parser' +import posthtmlConfig from '../posthtml/defaultConfig.js' + +const posthtmlPlugin = options => tree => { + const defaultSafelist = [ + '*body*', // Gmail + '.gmail*', // Gmail + '.apple*', // Apple Mail + '.ios*', // Mail on iOS + '.ox-*', // Open-Xchange + '.outlook*', // Outlook.com + '[data-ogs*', // Outlook.com + '.bloop_container', // Airmail + '.Singleton', // Apple Mail 10 + '.unused', // Notes 8 + '.moz-text-html', // Thunderbird + '.mail-detail-content', // Comcast, Libero webmail + '*edo*', // Edison (all) + '#*', // Freenet uses #msgBody + '.lang*' // Fenced code blocks + ] + + const defaultOptions = { + backend: [ + { heads: '{{', tails: '}}' }, + { heads: '{%', tails: '%}' }, + ], + whitelist: [...defaultSafelist, ...get(options, 'whitelist', [])] + } + + options = merge(options, defaultOptions) + + const { result: html } = emailComb(render(tree), options) + + return parse(html) +} + +export default posthtmlPlugin + +export async function comb(html = '', options = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(options) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) +} diff --git a/src/transformers/core.js b/src/transformers/core.js new file mode 100644 index 00000000..b83ac2f0 --- /dev/null +++ b/src/transformers/core.js @@ -0,0 +1,20 @@ +const posthtmlPlugin = (config = {}) => tree => { + const process = node => { + /** + * Remove plaintext tags when developing locally + */ + if ( + config._dev + && node.tag === 'plaintext' + ) { + node.tag = false + node.content = [''] + } + + return node + } + + return tree.walk(process) +} + +export default posthtmlPlugin diff --git a/src/transformers/extraAttributes.js b/src/transformers/extraAttributes.js deleted file mode 100644 index 2fc8f2ab..00000000 --- a/src/transformers/extraAttributes.js +++ /dev/null @@ -1,33 +0,0 @@ -const posthtml = require('posthtml') -const {get, merge, isObject} = require('lodash') -const addAttributes = require('posthtml-extra-attributes') -const defaultConfig = require('../generators/posthtml/defaultConfig') - -module.exports = async (html, config = {}, direct = false) => { - if (get(config, 'extraAttributes') === false) { - return html - } - - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - - let attributes = { - table: { - cellpadding: 0, - cellspacing: 0, - role: 'none' - }, - img: { - alt: '' - } - } - - attributes = direct - ? {...attributes, ...config} - : ( - isObject(config.extraAttributes) - ? {...attributes, ...config.extraAttributes} - : attributes - ) - - return posthtml([addAttributes({attributes})]).process(html, posthtmlOptions).then(result => result.html) -} diff --git a/src/transformers/filters/defaultFilters.js b/src/transformers/filters/defaultFilters.js index 4da288a9..6edd974c 100644 --- a/src/transformers/filters/defaultFilters.js +++ b/src/transformers/filters/defaultFilters.js @@ -1,3 +1,11 @@ +const append = (content, attribute) => content + attribute + +const capitalize = content => content.charAt(0).toUpperCase() + content.slice(1) + +const ceil = content => Math.ceil(Number.parseFloat(content)) + +const divide = (content, attribute) => Number.parseFloat(content) / Number.parseFloat(attribute) + const escapeMap = { '&': '&amp;', '<': '&lt;', @@ -5,32 +13,27 @@ const escapeMap = { '"': '&#34;', '\'': '&#39;' } - -const unescapeMap = { - '&amp;': '&', - '&lt;': '<', - '&gt;': '>', - '&#34;': '"', - '&#39;': '\'' -} -// biome-ignore lint: not shadowing -const unescape = string => string.replace(/&(amp|lt|gt|#34|#39);/g, m => unescapeMap[m]) - -const append = (content, attribute) => content + attribute -const capitalize = content => content.charAt(0).toUpperCase() + content.slice(1) -const ceil = content => Math.ceil(Number.parseFloat(content)) -const divide = (content, attribute) => Number.parseFloat(content) / Number.parseFloat(attribute) -// biome-ignore lint: not shadowing +// biome-ignore lint: not confusing const escape = content => content.replace(/["&'<>]/g, m => escapeMap[m]) + const escapeOnce = content => escape(unescape(content)) + const floor = content => Math.floor(Number.parseFloat(content)) + const lowercase = content => content.toLowerCase() + const lstrip = content => content.replace(/^\s+/, '') + const minus = (content, attribute) => Number.parseFloat(content) - Number.parseFloat(attribute) + const modulo = (content, attribute) => Number.parseFloat(content) % Number.parseFloat(attribute) + const multiply = (content, attribute) => Number.parseFloat(content) * Number.parseFloat(attribute) + const newlineToBr = content => content.replace(/\n/g, '<br>') + const plus = (content, attribute) => Number.parseFloat(content) + Number.parseFloat(attribute) + const prepend = (content, attribute) => attribute + content const remove = (content, attribute) => { @@ -39,6 +42,7 @@ const remove = (content, attribute) => { } const removeFirst = (content, attribute) => content.replace(attribute, '') + const replace = (content, attribute) => { const [search, replace] = attribute.split('|') const regex = new RegExp(search, 'g') @@ -51,77 +55,92 @@ const replaceFirst = (content, attribute) => { } const round = content => Math.round(Number.parseFloat(content)) + const rstrip = content => content.replace(/\s+$/, '') + const uppercase = content => content.toUpperCase() + const size = content => content.length + const slice = (content, attribute) => { - try { - const [start, end] = attribute.split(',') - return content.slice(start, end) - } catch { + const [start, end] = attribute.split(',') + + if (!end && !start) { + return content + } + + if (!end) { return content.slice(attribute) } + + return content.slice(start, end) } const stripNewlines = content => content.replace(/\n/g, '') + const trim = content => content.trim() + const truncate = (content, attribute) => { - try { - const [length, omission] = attribute.split(',') - return content.length > Number.parseInt(length, 10) ? - content.slice(0, length) + (omission || '...') : - content - } catch { - const length = Number.parseInt(attribute, 10) - return content.length > length ? content.slice(0, length) + '...' : content - } + const [length, omission] = attribute.split(',') + + return content && content.length > Number.parseInt(length, 10) + ? content.slice(0, length) + (omission || '...') + : content // content is shorter than length required to truncate } const truncateWords = (content, attribute) => { - try { - const [length, omission] = attribute.split(',') - return content.split(' ').slice(0, Number.parseInt(length, 10)).join(' ') + (omission || '...') - } catch { - const length = Number.parseInt(attribute, 10) - return content.split(' ').slice(0, length).join(' ') + '...' - } + const [length, omission] = attribute.split(',') + + return content.split(' ') + .slice(0, Number.parseInt(length, 10)) + .join(' ') + (omission || '...') +} + +const unescapeMap = { + '&amp;': '&', + '&lt;': '<', + '&gt;': '>', + '&#34;': '"', + '&#39;': '\'' } +// biome-ignore lint: not confusing +const unescape = string => string.replace(/&(amp|lt|gt|#34|#39);/g, m => unescapeMap[m]) -// eslint-disable-next-line const urlDecode = content => content.split('+').map(decodeURIComponent).join(' ') -// eslint-disable-next-line + const urlEncode = content => content.split(' ').map(encodeURIComponent).join('+') -exports.append = append -exports.capitalize = capitalize -exports.ceil = ceil -exports['divide-by'] = divide -exports.divide = divide -exports.escape = escape -exports['escape-once'] = escapeOnce -exports.floor = floor -exports.lowercase = lowercase -exports.lstrip = lstrip -exports.minus = minus -exports.modulo = modulo -exports.multiply = multiply -exports['newline-to-br'] = newlineToBr -exports.plus = plus -exports.prepend = prepend -exports.remove = remove -exports['remove-first'] = removeFirst -exports.replace = replace -exports['replace-first'] = replaceFirst -exports.round = round -exports.rstrip = rstrip -exports.uppercase = uppercase -exports.size = size -exports.slice = slice -exports.strip = trim -exports['strip-newlines'] = stripNewlines -exports.times = multiply -exports.trim = trim -exports.truncate = truncate -exports['truncate-words'] = truncateWords -exports['url-decode'] = urlDecode -exports['url-encode'] = urlEncode +export const filters = { + append, + capitalize, + ceil, + 'divide-by': divide, + escape, + 'escape-once': escapeOnce, + floor, + lowercase, + lstrip, + minus, + modulo, + multiply, + 'newline-to-br': newlineToBr, + plus, + prepend, + remove, + 'remove-first': removeFirst, + replace, + 'replace-first': replaceFirst, + round, + rstrip, + uppercase, + size, + slice, + 'strip-newlines': stripNewlines, + times: multiply, + trim, + truncate, + 'truncate-words': truncateWords, + 'url-decode': urlDecode, + 'url-encode': urlEncode, + unescape +} diff --git a/src/transformers/filters/index.js b/src/transformers/filters/index.js index 5305f096..f2f9a2f6 100644 --- a/src/transformers/filters/index.js +++ b/src/transformers/filters/index.js @@ -1,83 +1,19 @@ -const posthtml = require('posthtml') -const {get, merge, omit, has} = require('lodash') -const defaultFilters = require('./defaultFilters') -const PostCSS = require('../../generators/postcss') -const posthtmlContent = require('posthtml-content') -const Tailwind = require('../../generators/tailwindcss') -const safeClassNames = require('posthtml-safe-class-names') -const defaultConfig = require('../../generators/posthtml/defaultConfig') +import posthtml from 'posthtml' +import { defu as merge } from 'defu' +import posthtmlContent from 'posthtml-content' +import posthtmlConfig from '../../posthtml/defaultConfig.js' +import { filters as defaultFilters } from './defaultFilters.js' -module.exports = async (html, config = {}, direct = false) => { - if (get(config, 'filters') === false) { - return html - } +export default function posthtmlPlugin(filters = {}) { + filters = merge(defaultFilters, filters) - const filters = direct ? - merge(defaultFilters, config) : - merge(defaultFilters, get(config, 'filters', {})) - - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - - /** - * Compile CSS in <style {post|tailwind}css> tags - */ - const maizzleConfig = omit(config, ['build.tailwind.css', 'css']) - - filters.postcss = css => PostCSS.process(css, maizzleConfig) - filters.tailwindcss = css => Tailwind.compile({ - css, - html, - config: merge({ - build: { - tailwind: { - config: get(config, 'build.tailwind.config', 'tailwind.config.js') - } - } - }, maizzleConfig) - }) - - const posthtmlPlugins = [ - styleDataEmbed(), - posthtmlContent(filters) - ] - - /** - * Run `safeClassNames` in filters only when not when developing locally and - * `safeClassNames` is not explicitly disabled (set to `false`). - */ - if (get(config, 'env') !== 'local' && get(config, 'safeClassNames') !== false) { - posthtmlPlugins.push(safeClassNames({ - replacements: { - '{': '{', - '}': '}' - } - })) - } - - return posthtml(posthtmlPlugins) - .process(html, posthtmlOptions) - .then(result => result.html) + return posthtmlContent(filters) } -/** - * Prevent CSS inlining - * - * Add a `data-embed` attribute to <style> tags that we want to preserve. - * Can be used for HTML email client targeting hacks. - */ -const styleDataEmbed = () => tree => { - const process = node => { - if ( - node.tag === 'style' - && node.attrs - && (has(node.attrs, 'preserve') || has(node.attrs, 'embed'))) { - node.attrs = {...node.attrs, 'data-embed': true} - node.attrs.preserve = false - node.attrs.embed = false - } - - return node - } - - return tree.walk(process) +export async function filters(html = '', filters = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(filters) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) } diff --git a/src/transformers/index.js b/src/transformers/index.js index 9422370b..40060767 100644 --- a/src/transformers/index.js +++ b/src/transformers/index.js @@ -1,64 +1,269 @@ -const minify = require('./minify') -const filters = require('./filters') -const inline = require('./inlineCss') -const markdown = require('./markdown') -const prettify = require('./prettify') -const ensureSixHEX = require('./sixHex') -const applyBaseUrl = require('./baseUrl') -const posthtmlMSO = require('./posthtmlMso') -const addURLParams = require('./urlParameters') -const preventWidows = require('./preventWidows') -const replaceStrings = require('./replaceStrings') -const safeClassNames = require('./safeClassNames') -const removeUnusedCSS = require('./removeUnusedCss') -const removeAttributes = require('./removeAttributes') -const attributeToStyle = require('./attributeToStyle') -const removeInlineSizes = require('./removeInlineSizes') -const applyExtraAttributes = require('./extraAttributes') -const shorthandInlineCSS = require('./shorthandInlineCSS') -const removeInlinedClasses = require('./removeInlinedSelectors') -const removeInlineBgColor = require('./removeInlineBackgroundColor') - -exports.process = async (html, config) => { - html = await safeClassNames(html, config) - html = await filters(html, config) - html = await markdown(html, config) - html = await preventWidows(html, config) - html = await attributeToStyle(html, config) - html = await inline(html, config) - html = await removeUnusedCSS(html, config) - html = await removeAttributes(html, config) - html = await shorthandInlineCSS(html, config) - html = await removeInlineSizes(html, config) - html = await removeInlineBgColor(html, config) - html = await applyExtraAttributes(html, config) - html = await applyBaseUrl(html, config) - html = await addURLParams(html, config) - html = await ensureSixHEX(html, config) - html = await posthtmlMSO(html, config) - html = await prettify(html, config) - html = await minify(html, config) - html = await replaceStrings(html, config) - - return html -} +import posthtml from 'posthtml' +import get from 'lodash-es/get.js' +import { defu as merge } from 'defu' + +import comb from './comb.js' +import sixHex from './sixHex.js' +import minify from './minify.js' +import baseUrl from './baseUrl.js' +import inlineCSS from './inline.js' +import prettify from './prettify.js' +import filters from './filters/index.js' +import markdown from 'posthtml-markdownit' +import posthtmlMso from './posthtmlMso.js' +import shorthandCss from './shorthandCss.js' +import preventWidows from './preventWidows.js' +import addAttributes from './addAttributes.js' +import urlParameters from './urlParameters.js' +import safeClassNames from './safeClassNames.js' +import replaceStrings from './replaceStrings.js' +import attributeToStyle from './attributeToStyle.js' +import removeAttributes from './removeAttributes.js' + +import coreTransformers from './core.js' + +import defaultPosthtmlConfig from '../posthtml/defaultConfig.js' + +/** + * Use Maizzle Transformers on an HTML string. + * + * Only Transformers that are enabled in the `config` will be used. + * + * @param {string} html The HTML content + * @param {object} config The Maizzle config object + * @returns {Promise<{ original: string, config: object, html: string }>} + * A Promise resolving to an object containing the original HTML, modified HTML, and the config + */ +export async function run(html = '', config = {}) { + const posthtmlPlugins = [] + + const posthtmlConfig = merge( + get(config, 'posthtml.options', {}), + defaultPosthtmlConfig + ) + + /** + * 1. Core transformers + * + * Transformers that are always enabled + * + */ + posthtmlPlugins.push(coreTransformers(config)) + + /** + * 2. Safe class names + * + * Rewrite Tailwind CSS class names to email-safe alternatives, + * unless explicitly disabled + */ + if (get(config, 'css.safeClassNames') !== false) { + posthtmlPlugins.push( + safeClassNames(get(config, 'css.safeClassNames', {})) + ) + } + + /** + * 3. Filters + * + * Apply filters to HTML. + * Filters are always applied, unless explicitly disabled. + */ + if (get(config, 'filters') !== false) { + posthtmlPlugins.push( + filters(get(config, 'filters', {})) + ) + } + + /** + * 4. Markdown + * + * Convert Markdown to HTML with Markdown-it, unless explicitly disabled + */ + if (get(config, 'markdown') !== false) { + posthtmlPlugins.push( + markdown(get(config, 'markdown', {})) + ) + } + + /** + * 5. Prevent widow words + * Always runs, unless explicitly disabled + */ + if (get(config, 'widowWords') !== false) { + posthtmlPlugins.push( + preventWidows(get(config, 'widowWords', {})) + ) + } + + /** + * 6. Attribute to `style` + * + * Duplicate HTML attributes to inline CSS. + */ + if (get(config, 'css.inline.attributeToStyle')) { + posthtmlPlugins.push( + attributeToStyle(get(config, 'css.inline.attributeToStyle', [])) + ) + } + + /** + * 7. Inline CSS + * + * Inline CSS into HTML + */ + if (get(config, 'css.inline')) { + posthtmlPlugins.push(inlineCSS( + merge( + get(config, 'css.inline', {}), + { + removeInlinedSelectors: true, + } + ) + )) + } -exports.minify = (html, config) => minify(html, config, true) -exports.inlineCSS = (html, config) => inline(html, config, true) -exports.markdown = (html, config) => markdown(html, config, true) -exports.prettify = (html, config) => prettify(html, config, true) -exports.ensureSixHEX = (html, config) => ensureSixHEX(html, config) -exports.withFilters = (html, config) => filters(html, config, true) -exports.addURLParams = (html, config) => addURLParams(html, config, true) -exports.preventWidows = (html, config) => preventWidows(html, config) -exports.replaceStrings = (html, config) => replaceStrings(html, config, true) -exports.safeClassNames = (html, config) => safeClassNames(html, config, true) -exports.removeUnusedCSS = (html, config) => removeUnusedCSS(html, config, true) -exports.removeAttributes = (html, config) => removeAttributes(html, config, true) -exports.attributeToStyle = (html, config) => attributeToStyle(html, config, true) -exports.removeInlineSizes = (html, config) => removeInlineSizes(html, config, true) -exports.applyBaseUrl = (html, config) => applyBaseUrl(html, config, true) -exports.removeInlinedClasses = (html, config) => removeInlinedClasses(html, config) -exports.shorthandInlineCSS = (html, config) => shorthandInlineCSS(html, config, true) -exports.removeInlineBgColor = (html, config) => removeInlineBgColor(html, config, true) -exports.applyExtraAttributes = (html, config) => applyExtraAttributes(html, config, true) + /** + * 8. Purge CSS + * + * Remove unused CSS, uglify classes etc. + */ + if (get(config, 'css.purge')) { + posthtmlPlugins.push(comb(config.css.purge)) + } + + /** + * 9. Remove attributes + * + * Remove attributes from HTML tags + * If `undefined`, removes empty `style` and `class` attributes + */ + if (get(config, 'attributes.remove') !== false) { + posthtmlPlugins.push( + removeAttributes( + get(config, 'attributes.remove', []), + posthtmlConfig + ) + ) + } + + /** + * 10. Shorthand CSS + * + * Convert longhand CSS properties to shorthand in `style` attributes + */ + if (get(config, 'css.shorthand')) { + posthtmlPlugins.push( + shorthandCss(get(config, 'css.shorthand', {})) + ) + } + + /** + * 11. Add attributes + * + * Add attributes to HTML tags + */ + if (get(config, 'attributes.add') !== false) { + posthtmlPlugins.push( + addAttributes(get(config, 'attributes.add', {})) + ) + } + + /** + * 12. Base URL + * + * Add a base URL to relative paths + */ + if (get(config, 'baseURL', get(config, 'baseUrl'))) { + posthtmlPlugins.push( + baseUrl(get(config, 'baseURL', get(config, 'baseUrl', {}))) + ) + } else { + /** + * Set baseURL to `build.static.destination` if it's not already set + */ + const destination = get(config, 'build.static.destination', '') + if (destination && !config._dev) { + posthtmlPlugins.push( + baseUrl({ + url: destination, + allTags: true, + styleTag: true, + inlineCss: true, + }) + ) + } + } + + /** + * 13. URL parameters + * + * Add parameters to URLs + */ + if (get(config, 'urlParameters')) { + posthtmlPlugins.push( + urlParameters(get(config, 'urlParameters', {})) + ) + } + + /** + * 14. Six-digit HEX + * + * Convert three-digit HEX colors to six-digit + * Always runs, unless explicitly disabled + */ + if (get(config, 'css.sixHex') !== false) { + posthtmlPlugins.push( + sixHex() + ) + } + + /** + * 15. PostHTML MSO + * + * Simplify writing MSO conditionals for Outlook + */ + if (get(config, 'outlook') !== false) { + posthtmlPlugins.push( + posthtmlMso(get(config, 'outlook', {})) + ) + } + + /** + * 16. Prettify + * + * Pretty-print HTML using js-beautify + */ + if (get(config, 'prettify')) { + posthtmlPlugins.push( + prettify(get(config, 'prettify', {})) + ) + } + + /** + * 17. Minify + * + * Minify HTML using html-crush + */ + if (get(config, 'minify')) { + posthtmlPlugins.push( + minify(get(config, 'minify', {})) + ) + } + + /** + * 18. Replace strings + * + * Replace strings through regular expressions + */ + if (get(config, 'replaceStrings')) { + posthtmlPlugins.push( + replaceStrings(get(config, 'replaceStrings', {})) + ) + } + + return posthtml(posthtmlPlugins) + .process(html, posthtmlConfig) + .then(result => ({ + html: result.html, + })) +} diff --git a/src/transformers/inline.js b/src/transformers/inline.js new file mode 100644 index 00000000..d2f5a5d9 --- /dev/null +++ b/src/transformers/inline.js @@ -0,0 +1,240 @@ +import juice from 'juice' +import postcss from 'postcss' +import get from 'lodash-es/get.js' +import has from 'lodash-es/has.js' +import remove from 'lodash-es/remove.js' +import { render } from 'posthtml-render' +import { calc } from '@csstools/css-calc' +import isEmpty from 'lodash-es/isEmpty.js' +import * as cheerio from 'cheerio/lib/slim' +import safeParser from 'postcss-safe-parser' +import isObject from 'lodash-es/isObject.js' +import { parser as parse } from 'posthtml-parser' +import { useAttributeSizes } from './useAttributeSizes.js' + +const posthtmlPlugin = (options = {}) => tree => { + return inline(render(tree), options).then(html => parse(html)) +} + +export default posthtmlPlugin + +export async function inline(html = '', options = {}) { + // Exit early if no HTML is passed + if (typeof html !== 'string' || html === '') { + return html + } + + const removeStyleTags = get(options, 'removeStyleTags', false) + const css = get(options, 'customCSS', false) + + options.resolveCSSVariables = get(options, 'resolveCSSVariables', true) + options.removeInlinedSelectors = get(options, 'removeInlinedSelectors', true) + options.resolveCalc = get(options, 'resolveCalc', true) + options.preferUnitlessValues = get(options, 'preferUnitlessValues', true) + + juice.styleToAttribute = get(options, 'styleToAttribute', {}) + juice.applyWidthAttributes = get(options, 'applyWidthAttributes', true) + juice.applyHeightAttributes = get(options, 'applyHeightAttributes', true) + juice.excludedProperties.push(...get(options, 'excludedProperties', [])) + juice.widthElements = get(options, 'widthElements', ['img', 'video']).map(i => i.toUpperCase()) + juice.heightElements = get(options, 'heightElements', ['img', 'video']).map(i => i.toUpperCase()) + + if (isObject(options.codeBlocks) && !isEmpty(options.codeBlocks)) { + Object.entries(options.codeBlocks).forEach(([k, v]) => { + juice.codeBlocks[k] = v + }) + } + + const $ = cheerio.load(html, { decodeEntities: false, _useHtmlParser2: true }) + + // Add a `data-embed` attribute to style tags that have the embed attribute + $('style[embed]').each((i, el) => { + $(el).attr('data-embed', '') + }) + + /** + * Inline the CSS + * + * If customCSS is passed, inline that CSS specifically + * Otherwise, use Juice's default inlining + */ + $.root().html( + css + ? juice.inlineContent($.html(), css, { removeStyleTags, ...options }) + : juice($.html(), { removeStyleTags, ...options }) + ) + + /** + * Prefer attribute sizes + * + * Prefer HTML `width` and `height` attributes over inline CSS. + * Useful for retina images in MSO Outlook, where CSS sizes + * aren't respected and will render the image in its + * natural size. + */ + if (options.useAttributeSizes) { + $.root().html( + await useAttributeSizes(html, { + width: juice.widthElements, + height: juice.heightElements, + }) + ) + } + + /** + * Remove inlined selectors from the HTML + */ + // For each style tag + $('style:not([embed])').each((i, el) => { + // Parse the CSS + const { root } = postcss() + .process( + $(el).html(), + { + from: undefined, + parser: safeParser + } + ) + + const preservedClasses = new Set() + const selectors = new Set() + + // Preserve selectors in at rules + root.walkAtRules(rule => { + if (['media', 'supports'].includes(rule.name)) { + rule.walkRules(rule => { + preservedClasses.add(rule.selector) + }) + } + }) + + // For each rule in the CSS block we're parsing + root.walkRules(rule => { + // Keep track of declarations in the rule + const declarations = new Set() + + rule.walkDecls(decl => { + // Resolve calc() values to static values + if (options.resolveCalc) { + decl.value = decl.value.includes('calc(') ? calc(decl.value) : decl.value + } + + declarations.add(decl) + }) + + /** + * Remove duplicate declarations + * + * Only do so if the `resolveCSSVariables` option is enabled, + * otherwise we'll end up removing all declarations that use CSS variables + */ + if (options.resolveCSSVariables) { + Array.from(declarations) + /** + * Consider only declarations with a value that includes any of the other declarations' property + * So a decl like color(var(--text-color)) will be removed if there's a decl with a property of --text-color + * */ + .filter(decl => + Array.from(declarations).some(otherDecl => decl.value.includes(otherDecl.prop)) + || decl.prop.startsWith('--') + ) + .map(decl => decl.remove()) + } + + const { selector } = rule + + selectors.add({ + name: selector, + prop: get(rule.nodes[0], 'prop') + }) + + // Preserve pseudo selectors + // TODO: revisit pseudos list + if ([':hover', ':active', ':focus', ':visited', ':link', ':before', ':after'].some(i => selector.includes(i))) { + preservedClasses.add(selector) + } + + if (options.removeInlinedSelectors) { + // Remove the rule in the <style> tag as long as it's not a preserved class + if (!preservedClasses.has(selector)) { + rule.remove() + } + + // Update the <style> tag contents + $(el).html(root.toString()) + } + }) + + // Loop over selectors that we found in the <style> tags + selectors.forEach(({ name, prop }) => { + const elements = $(name).get() + + // If the property is excluded from inlining, skip + if (!juice.excludedProperties.includes(prop)) { + // Find the selector in the HTML + elements.forEach((el) => { + // Get a `property|value` list from the inline style attribute + const styleAttr = $(el).attr('style') + let inlineStyles = {} + + if (styleAttr) { + inlineStyles = styleAttr.split(';').reduce((acc, i) => { + let [property, value] = i.split(':').map(i => i.trim()) + + if (value && options.resolveCalc) { + value = value.includes('calc') ? calc(value) : value + } + + if (value && options.preferUnitlessValues) { + value = value.replace( + /\b0(px|rem|em|%|vh|vw|vmin|vmax|in|cm|mm|pt|pc|ex|ch)\b/g, + '0' + ) + } + + if (property) { + acc[property] = value + } + + return acc + }, {}) + + // Update the element's style attribute with the new value + $(el).attr( + 'style', + Object.entries(inlineStyles).map(([property, value]) => `${property}: ${value}`).join('; ') + ) + } + + // Get the classes from the element's class attribute + const classes = $(el).attr('class') + + if (options.removeInlinedSelectors && classes) { + const classList = classes.split(' ') + + // If the class has been inlined in the style attribute... + if (has(inlineStyles, prop)) { + // Try to remove the classes that have been inlined + if (![...preservedClasses].some(item => item.endsWith(name) || item.startsWith(name))) { + remove(classList, classToRemove => name.includes(classToRemove)) + } + + // Update the class list on the element with the new classes + if (classList.length > 0) { + $(el).attr('class', classList.join(' ')) + } else { + $(el).removeAttr('class') + } + } + } + }) + } + }) + }) + + $('style[embed]').each((i, el) => { + $(el).removeAttr('embed') + }) + + return $.html() +} diff --git a/src/transformers/inlineCss.js b/src/transformers/inlineCss.js deleted file mode 100644 index 7a30ea20..00000000 --- a/src/transformers/inlineCss.js +++ /dev/null @@ -1,42 +0,0 @@ -const juice = require('juice') -const {get, isObject, isEmpty} = require('lodash') - -module.exports = async (html, config = {}, direct = false) => { - if (get(config, 'inlineCSS') === false) { - return html - } - - const options = direct ? config : get(config, 'inlineCSS', {}) - // Default `removeStyleTags` to false so we can preserve - // CSS selectors that are not present in the HTML - const removeStyleTags = get(options, 'removeStyleTags', false) - const css = get(config, 'customCSS', false) - - if (get(config, 'inlineCSS') === true || !isEmpty(options)) { - options.applyAttributesTableElements = true - juice.styleToAttribute = get(options, 'styleToAttribute', {}) - - juice.widthElements = get(options, 'applyWidthAttributes', []).map(i => i.toUpperCase()) - juice.heightElements = get(options, 'applyHeightAttributes', []).map(i => i.toUpperCase()) - - juice.excludedProperties = ['--tw-shadow'] - - if (!isEmpty(options.excludedProperties)) { - juice.excludedProperties.push(...get(options, 'excludedProperties', [])) - } - - if (isObject(options.codeBlocks) && !isEmpty(options.codeBlocks)) { - for (const [k, v] of Object.entries(options.codeBlocks)) { - juice.codeBlocks[k] = v - } - } - - html = css ? - juice.inlineContent(html, css, {removeStyleTags, ...options}) : - juice(html, {removeStyleTags, ...options}) - - return html - } - - return html -} diff --git a/src/transformers/markdown.js b/src/transformers/markdown.js index 43397e02..6dd7c558 100644 --- a/src/transformers/markdown.js +++ b/src/transformers/markdown.js @@ -1,20 +1,19 @@ -const posthtml = require('posthtml') -const {get, merge} = require('lodash') -const markdown = require('posthtml-markdownit') -const defaultConfig = require('../generators/posthtml/defaultConfig') +import posthtml from 'posthtml' +import { defu as merge } from 'defu' +import md from 'posthtml-markdownit' +import posthtmlConfig from '../posthtml/defaultConfig.js' -module.exports = async (html, config = {}, direct = false) => { - if (get(config, 'markdown') === false) { - return html - } - - const userMarkdownOptions = direct ? config : get(config, 'markdown', {}) - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - const markdownOptions = merge({markdownit: {html: true}}, userMarkdownOptions) +export async function markdown(html = '', options = {}, posthtmlOptions = {}) { + /** + * Automatically wrap in <md> tag, unless manual mode is enabled + * With manual mode, user must wrap the markdown content in a <md> tag + * https://github.com/posthtml/posthtml-markdownit#usage + */ + html = options.manual ? html : `<md>${html}</md>` return posthtml([ - markdown({...markdownOptions}) + md(options) ]) - .process(html, posthtmlOptions) + .process(html, merge(posthtmlOptions, posthtmlConfig)) .then(result => result.html) } diff --git a/src/transformers/minify.js b/src/transformers/minify.js index 374f6f1c..10429bde 100644 --- a/src/transformers/minify.js +++ b/src/transformers/minify.js @@ -1,21 +1,26 @@ -const {crush} = require('html-crush') -const {get, isEmpty} = require('lodash') +import posthtml from 'posthtml' +import { crush } from 'html-crush' +import { defu as merge } from 'defu' +import { render } from 'posthtml-render' +import { parser as parse } from 'posthtml-parser' +import posthtmlConfig from '../posthtml/defaultConfig.js' -module.exports = async (html, config = {}, direct = false) => { - if (get(config, 'minify') === false) { - return html - } - - config = direct ? { - lineLengthLimit: 500, - removeIndentations: true, +const posthtmlPlugin = (options = {}) => tree => { + options = merge(options, { removeLineBreaks: true, - ...config - } : get(config, 'minify', {}) + }) + + const { result: html } = crush(render(tree), options) + + return parse(html) +} - if (!isEmpty(config)) { - html = crush(html, {removeLineBreaks: true, ...config}).result - } +export default posthtmlPlugin - return html +export async function minify(html = '', options = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(options) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) } diff --git a/src/transformers/posthtmlMso.js b/src/transformers/posthtmlMso.js index f7b589f1..36ec11da 100644 --- a/src/transformers/posthtmlMso.js +++ b/src/transformers/posthtmlMso.js @@ -1,11 +1,16 @@ -const posthtml = require('posthtml') -const {get, merge} = require('lodash') -const outlook = require('posthtml-mso') -const defaultConfig = require('../generators/posthtml/defaultConfig') +import posthtml from 'posthtml' +import { defu as merge } from 'defu' +import posthtmlMso from 'posthtml-mso' +import posthtmlConfig from '../posthtml/defaultConfig.js' -module.exports = async (html, config) => { - const outlookOptions = get(config, 'build.posthtml.outlook', {}) - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) +export default function posthtmlPlugin(options = {}) { + return posthtmlMso(options) +} - return posthtml([outlook({...outlookOptions})]).process(html, posthtmlOptions).then(result => result.html) +export async function useMso(html = '', options = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(options) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) } diff --git a/src/transformers/prettify.js b/src/transformers/prettify.js index 71061798..6e99c65e 100644 --- a/src/transformers/prettify.js +++ b/src/transformers/prettify.js @@ -1,8 +1,10 @@ -/* eslint-disable camelcase */ -const pretty = require('pretty') -const {get, merge, isEmpty, isObject} = require('lodash') +import pretty from 'pretty' +import posthtml from 'posthtml' +import { defu as merge } from 'defu' +import { render } from 'posthtml-render' +import posthtmlConfig from '../posthtml/defaultConfig.js' -module.exports = async (html, config = {}, direct = false) => { +const posthtmlPlugin = (options = {}) => tree => { const defaultConfig = { space_around_combinator: true, // Preserve space around CSS selector combinators newline_between_rules: false, // Remove empty lines between CSS rules @@ -10,18 +12,17 @@ module.exports = async (html, config = {}, direct = false) => { extra_liners: [] // Don't add extra new line before any tag } - config = direct ? config : get(config, 'prettify') + const config = merge(options, defaultConfig) - // Don't prettify if not explicitly enabled in config - if (!config || (isObject(config) && isEmpty(config))) { - return html - } - - if (typeof config === 'boolean' && config) { - return pretty(html, defaultConfig) - } + return pretty(render(tree), config) +} - config = merge(defaultConfig, config) +export default posthtmlPlugin - return pretty(html, config) +export async function prettify(html = '', options = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(options) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) } diff --git a/src/transformers/preventWidows.js b/src/transformers/preventWidows.js index 91dacbf6..30034514 100644 --- a/src/transformers/preventWidows.js +++ b/src/transformers/preventWidows.js @@ -1,22 +1,13 @@ -const posthtml = require('posthtml') -const {get, merge, isEmpty} = require('lodash') -const {removeWidows} = require('string-remove-widows') -const defaultConfig = require('../generators/posthtml/defaultConfig') +import posthtml from 'posthtml' +import { defu as merge } from 'defu' +import { removeWidows } from 'string-remove-widows' +import posthtmlConfig from '../posthtml/defaultConfig.js' -module.exports = async (html, config = {}) => { - if (isEmpty(config)) { - return removeWidows(html).res - } - - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - - return posthtml([removeWidowsPlugin(config)]).process(html, posthtmlOptions).then(result => result.html) -} - -const removeWidowsPlugin = options => tree => { - const {attrName = 'prevent-widows', ...removeWidowsOptions} = get(options, 'widowWords', options) - - removeWidowsOptions.minWordCount = removeWidowsOptions.minWordCount || 3 +const posthtmlPlugin = (options = {}) => tree => { + options = merge(options, { + minWordCount: 3, + attrName: 'prevent-widows' + }) // Ignore defaults const mappings = [ @@ -58,22 +49,19 @@ const removeWidowsPlugin = options => tree => { } ] - if (Array.isArray(removeWidowsOptions.ignore)) { - for (const pair of removeWidowsOptions.ignore) { - mappings.push(pair) - } + if (Array.isArray(options.ignore)) { + options.ignore.forEach(pair => mappings.push(pair)) } - if (typeof removeWidowsOptions.ignore !== 'string') { - removeWidowsOptions.ignore = mappings + if (typeof options.ignore !== 'string') { + options.ignore = mappings } const process = node => { - if (node.attrs && Object.keys(node.attrs).includes(attrName)) { - const widowsRemovedString = removeWidows(tree.render(node.content), removeWidowsOptions).res - + if (node.attrs && Object.keys(node.attrs).includes(options.attrName)) { + const widowsRemovedString = removeWidows(tree.render(node.content), options).res node.content = tree.render(tree.parser(widowsRemovedString)) - node.attrs[attrName] = false + delete node.attrs[options.attrName] } return node @@ -81,3 +69,19 @@ const removeWidowsPlugin = options => tree => { return tree.walk(process) } + +export default posthtmlPlugin + +export async function preventWidows(html = '', options = {}, posthtmlOptions = {}) { + // Apply only to elements that contain the `prevent-widows` attribute + if (options.withAttributes) { + return posthtml([ + posthtmlPlugin(options) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) + } + + // Apply to all elements + return removeWidows(html, options).res +} diff --git a/src/transformers/removeAttributes.js b/src/transformers/removeAttributes.js index ec1914c5..fab16a73 100644 --- a/src/transformers/removeAttributes.js +++ b/src/transformers/removeAttributes.js @@ -1,19 +1,7 @@ -const posthtml = require('posthtml') -const {get, merge} = require('lodash') -const defaultConfig = require('../generators/posthtml/defaultConfig') - -module.exports = async (html, config = {}, direct = false) => { - const attributes = direct ? (Array.isArray(config) ? [...config] : []) : get(config, 'removeAttributes', []) - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - - attributes.push('style', 'class') - - html = await posthtml([ - removeAttributes(attributes, posthtmlOptions) - ]).process(html, posthtmlOptions).then(result => result.html) - - return html -} +import posthtml from 'posthtml' +import get from 'lodash-es/get.js' +import { defu as merge } from 'defu' +import posthtmlConfig from '../posthtml/defaultConfig.js' /** * Remove empty attributes with PostHTML @@ -26,7 +14,9 @@ module.exports = async (html, config = {}, direct = false) => { * * Condition 3: same as 2, but for regular expressions */ -const removeAttributes = (attributes = {}, posthtmlOptions = {}) => tree => { +const posthtmlPlugin = (attributes = [], posthtmlOptions = {}) => tree => { + attributes.push('style', 'class') + const process = node => { const normalizedAttrs = attributes.map(attribute => { return { @@ -36,7 +26,7 @@ const removeAttributes = (attributes = {}, posthtmlOptions = {}) => tree => { }) if (node.attrs) { - for (const attr of normalizedAttrs) { + normalizedAttrs.forEach(attr => { const targetAttrValue = get(node.attrs, attr.name) if ( @@ -46,7 +36,7 @@ const removeAttributes = (attributes = {}, posthtmlOptions = {}) => tree => { ) { node.attrs[attr.name] = false } - } + }) } return node @@ -54,3 +44,13 @@ const removeAttributes = (attributes = {}, posthtmlOptions = {}) => tree => { return tree.walk(process) } + +export default posthtmlPlugin + +export async function removeAttributes(html = '', attributes = [], posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(attributes, merge(posthtmlOptions, posthtmlConfig)) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) +} diff --git a/src/transformers/removeInlineBackgroundColor.js b/src/transformers/removeInlineBackgroundColor.js deleted file mode 100644 index 76e0130f..00000000 --- a/src/transformers/removeInlineBackgroundColor.js +++ /dev/null @@ -1,57 +0,0 @@ -const posthtml = require('posthtml') -const {get, merge, isEmpty} = require('lodash') -const parseAttrs = require('posthtml-attrs-parser') -const {toStyleString} = require('../utils/helpers') -const defaultConfig = require('../generators/posthtml/defaultConfig') - -module.exports = async (html, config = {}, direct = false) => { - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - - if (isEmpty(config)) { - return posthtml([removeInlineBGColor()]).process(html, posthtmlOptions).then(result => result.html) - } - - if (get(config, 'inlineCSS.preferBgColorAttribute') === true) { - return posthtml([removeInlineBGColor()]).process(html, posthtmlOptions).then(result => result.html) - } - - const tags = direct ? (Array.isArray(config) ? config : false) : get(config, 'inlineCSS.preferBgColorAttribute', false) - - if (Array.isArray(tags)) { - return posthtml([removeInlineBGColor({tags})]).process(html, posthtmlOptions).then(result => result.html) - } - - return html -} - -const removeInlineBGColor = (options = {}) => tree => { - options.tags = options.tags || ['body', 'marquee', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr'] - - const process = node => { - if (!options.tags.includes(node.tag)) { - return node - } - - const attrs = parseAttrs(node.attrs, { - rules: { - bgcolor: { - delimiter: /\s+/, - glue: ' ' - } - } - }) - - if (attrs.style?.['background-color']) { - node.attrs.bgcolor = attrs.style['background-color'] - - // biome-ignore lint: assigning value will output the attribute - delete attrs.style['background-color'] - - node.attrs.style = toStyleString(attrs.style) - } - - return node - } - - return tree.walk(process) -} diff --git a/src/transformers/removeInlineSizes.js b/src/transformers/removeInlineSizes.js deleted file mode 100644 index 46118688..00000000 --- a/src/transformers/removeInlineSizes.js +++ /dev/null @@ -1,45 +0,0 @@ -const posthtml = require('posthtml') -const {get, merge, isEmpty} = require('lodash') -const parseAttrs = require('posthtml-attrs-parser') -const {toStyleString} = require('../utils/helpers') -const defaultConfig = require('../generators/posthtml/defaultConfig') - -module.exports = async (html, config = {}, direct = false) => { - const settings = direct ? config : get(config, 'inlineCSS.keepOnlyAttributeSizes', {}) - - if (!isEmpty(settings)) { - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - - return posthtml([removeInlineSizes(settings)]).process(html, posthtmlOptions).then(result => result.html) - } - - return html -} - -const removeInlineSizes = (mappings = {}) => tree => { - const process = node => { - // biome-ignore lint: yes - Object.entries(mappings).forEach(([attribute, tags]) => { - tags = Object.values(tags).map(tag => tag.toLowerCase()) - - if (!tags.includes(node.tag)) { - return node - } - - const attrs = parseAttrs(node.attrs) - - // biome-ignore lint: yes - tags.forEach(() => { - if (get(node, 'attrs.style')) { - delete attrs.style[attribute] - - node.attrs.style = toStyleString(attrs.style) - } - }) - }) - - return node - } - - return tree.walk(process) -} diff --git a/src/transformers/removeInlinedSelectors.js b/src/transformers/removeInlinedSelectors.js deleted file mode 100644 index b9ce97cc..00000000 --- a/src/transformers/removeInlinedSelectors.js +++ /dev/null @@ -1,100 +0,0 @@ -const postcss = require('postcss') -const posthtml = require('posthtml') -const {get, merge, has, remove} = require('lodash') -const parseAttrs = require('posthtml-attrs-parser') -const matchHelper = require('posthtml-match-helper') -const defaultConfig = require('../generators/posthtml/defaultConfig') - -module.exports = async (html, config = {}) => { - if (get(config, 'removeInlinedSelectors') === false) { - return html - } - - const options = { - posthtml: merge(defaultConfig, get(config, 'build.posthtml.options', {})), - removeUnusedCSS: config - } - - return posthtml([plugin(options)]).process(html, options.posthtml).then(result => result.html) -} - -const plugin = (options = {}) => tree => { - const process = node => { - // For each style tag... - if (node.tag === 'style') { - const {root} = postcss().process(node.content) - const preservedClasses = [] - - // Preserve selectors in at rules - root.walkAtRules(rule => { - if (['media', 'supports'].includes(rule.name)) { - rule.walkRules(rule => { - preservedClasses.push(rule.selector) - }) - } - }) - - root.walkRules(rule => { - const {selector} = rule - const prop = get(rule.nodes[0], 'prop') - - // Preserve pseudo selectors - if (selector.includes(':')) { - preservedClasses.push(selector) - } - - try { - const safelist = get(options.removeUnusedCSS, 'whitelist', []) - - // If we find the selector in the HTML... - tree.match(matchHelper(selector), n => { - // If the selector is safelisted, preserve it - if (safelist.some(item => item.endsWith(selector) || item.startsWith(selector))) { - preservedClasses.push(selector) - return n - } - - const parsedAttrs = parseAttrs(n.attrs) - const classAttr = get(parsedAttrs, 'class', []) - const styleAttr = get(parsedAttrs, 'style', {}) - - // If the class is in the style attribute (inlined), remove it - if (has(styleAttr, prop)) { - // Remove the class as long as it's not a preserved class - if (!preservedClasses.some(item => item.endsWith(selector) || item.startsWith(selector))) { - remove(classAttr, classToRemove => selector.includes(classToRemove)) - } - - // Remove the rule in the <style> tag - if (rule.parent.type !== 'atrule') { - rule.remove() - } - } - - n.attrs = parsedAttrs.compose() - - // Fix issue with .compose() automatically quoting attributes with no values - for (const [name, value] of Object.entries(n.attrs)) { - if (value === '' && get(options.posthtml, 'recognizeNoValueAttribute') === true) { - n.attrs[name] = true - } - } - - return n - }) - } catch {} - }) - - node.content = root.toString().trim() - - // Remove <style> tag if it ends up empty after processing - if (node.content.length === 0) { - node.tag = false - } - } - - return node - } - - return tree.walk(process) -} diff --git a/src/transformers/removeUnusedCss.js b/src/transformers/removeUnusedCss.js deleted file mode 100644 index 9de85ce2..00000000 --- a/src/transformers/removeUnusedCss.js +++ /dev/null @@ -1,48 +0,0 @@ -const {comb} = require('email-comb') -const {get, merge, isEmpty, isObject} = require('lodash') -const removeInlinedClasses = require('./removeInlinedSelectors') - -module.exports = async (html, config = {}, direct = false) => { - config = direct ? config : get(config, 'removeUnusedCSS') - - // Don't purge CSS if `removeUnusedCSS` is not set - if (!config || (isObject(config) && isEmpty(config))) { - return html - } - - const safelist = [ - '*body*', // Gmail - '.gmail*', // Gmail - '.apple*', // Apple Mail - '.ios*', // Mail on iOS - '.ox-*', // Open-Xchange - '.outlook*', // Outlook.com - '[data-ogs*', // Outlook.com - '.bloop_container', // Airmail - '.Singleton', // Apple Mail 10 - '.unused', // Notes 8 - '.moz-text-html', // Thunderbird - '.mail-detail-content', // Comcast, Libero webmail - '*edo*', // Edison (all) - '#*', // Freenet uses #msgBody - '.lang*' // Fenced code blocks - ] - - const defaultOptions = { - backend: [ - {heads: '{{', tails: '}}'}, - {heads: '{%', tails: '%}'} - ], - whitelist: get(config, 'whitelist', safelist) - } - - const options = merge(defaultOptions, config) - - /** - * Remove possibly inlined selectors, as long as we're not calling - * this function directly, i.e. Maizzle.removeUnusedCSS() - * */ - html = direct ? html : await removeInlinedClasses(html, options) - - return comb(html, options).result -} diff --git a/src/transformers/replaceStrings.js b/src/transformers/replaceStrings.js index e671a9ea..d968d651 100644 --- a/src/transformers/replaceStrings.js +++ b/src/transformers/replaceStrings.js @@ -1,14 +1,35 @@ -const {get, isEmpty} = require('lodash') - -module.exports = async (html, config = {}, direct = false) => { - const replacements = direct ? config : get(config, 'replaceStrings', {}) +import posthtml from 'posthtml' +import { defu as merge } from 'defu' +import { render } from 'posthtml-render' +import isEmpty from 'lodash-es/isEmpty.js' +import { parser as parse } from 'posthtml-parser' +import posthtmlConfig from '../posthtml/defaultConfig.js' +const posthtmlPlugin = (replacements = {}) => tree => { if (!isEmpty(replacements)) { - for (const [k, v] of Object.entries(replacements)) { - const regex = new RegExp(k, 'gi') - html = html.replace(regex, v) - } + const regexes = Object.entries(replacements).map(([k, v]) => [new RegExp(k, 'gi'), v]) + const patterns = new RegExp(Object.keys(replacements).join('|'), 'gi') + + return parse( + render(tree).replace(patterns, matched => { + for (const [regex, replacement] of regexes) { + if (regex.test(matched)) { + return replacement + } + } + }) + ) } - return html + return tree +} + +export default posthtmlPlugin + +export async function replaceStrings(html = '', replacements = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(replacements) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) } diff --git a/src/transformers/safeClassNames.js b/src/transformers/safeClassNames.js index 3019316e..7596cd7f 100644 --- a/src/transformers/safeClassNames.js +++ b/src/transformers/safeClassNames.js @@ -1,29 +1,29 @@ -const posthtml = require('posthtml') -const {get, merge, isEmpty} = require('lodash') -const safeClassNames = require('posthtml-safe-class-names') -const defaultConfig = require('../generators/posthtml/defaultConfig') +import posthtml from 'posthtml' +import { defu as merge } from 'defu' +import posthtmlConfig from '../posthtml/defaultConfig.js' +import posthtmlSafeClassNames from 'posthtml-safe-class-names' -module.exports = async (html, config = {}, direct = false) => { - /* - * Don't run when: - * - `config` is falsy or empty - * - developing locally and `safeClassNames` is not explicitly `true` - * - `safeClassNames` is explicitly `false` - */ - if ( - !config - || isEmpty(config) - || (get(config, 'env') === 'local' && get(config, 'safeClassNames') !== true) - || get(config, 'safeClassNames') === false - ) { - return html +export default function posthtmlPlugin(options = {}) { + // If options is boolean, convert to object + if (typeof options === 'boolean') { + options = {} } - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - const replacements = direct ? config : get(config, 'safeClassNames', { - '{': '{', - '}': '}' - }) + // Default options + options = merge({ + replacements: { + '{': '{', + '}': '}' + } + }, options) - return posthtml([safeClassNames({replacements})]).process(html, posthtmlOptions).then(result => result.html) + return posthtmlSafeClassNames(options) +} + +export async function safeClassNames(html = '', options = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(options) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) } diff --git a/src/transformers/shorthandCss.js b/src/transformers/shorthandCss.js new file mode 100644 index 00000000..f56a4a4d --- /dev/null +++ b/src/transformers/shorthandCss.js @@ -0,0 +1,22 @@ +import posthtml from 'posthtml' +import { defu as merge } from 'defu' +import posthtmlConfig from '../posthtml/defaultConfig.js' +import posthtmlMergeLonghand from 'posthtml-postcss-merge-longhand' + +export default function posthtmlPlugin(options = {}) { + if (Array.isArray(options.tags)) { + return posthtmlMergeLonghand({ + tags: options.tags, + }) + } + + return posthtmlMergeLonghand() +} + +export async function shorthandCSS(html = '', options = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(options) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) +} diff --git a/src/transformers/shorthandInlineCSS.js b/src/transformers/shorthandInlineCSS.js deleted file mode 100644 index 45fbb254..00000000 --- a/src/transformers/shorthandInlineCSS.js +++ /dev/null @@ -1,26 +0,0 @@ -const posthtml = require('posthtml') -const {get, merge, isObject, isEmpty} = require('lodash') -const mergeInlineLonghand = require('posthtml-postcss-merge-longhand') -const defaultConfig = require('../generators/posthtml/defaultConfig') - -module.exports = async (html, config, direct = false) => { - config = direct ? - (isObject(config) ? config : true) : - get(config, 'shorthandCSS', get(config, 'shorthandInlineCSS', [])) - - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - - if (typeof config === 'boolean' && config) { - html = await posthtml([mergeInlineLonghand()]) - .process(html, posthtmlOptions) - .then(result => result.html) - } - - if (isObject(config) && !isEmpty(config)) { - html = await posthtml([mergeInlineLonghand(config)]) - .process(html, posthtmlOptions) - .then(result => result.html) - } - - return html -} diff --git a/src/transformers/sixHex.js b/src/transformers/sixHex.js index 558ee37c..ba19a2af 100644 --- a/src/transformers/sixHex.js +++ b/src/transformers/sixHex.js @@ -1,28 +1,18 @@ -const posthtml = require('posthtml') -const {get, merge} = require('lodash') -const {conv} = require('color-shorthand-hex-to-six-digit') -const defaultConfig = require('../generators/posthtml/defaultConfig') +import posthtml from 'posthtml' +import { defu as merge } from 'defu' +import { conv } from 'color-shorthand-hex-to-six-digit' +import posthtmlConfig from '../posthtml/defaultConfig.js' -module.exports = async (html, config = {}) => { - if (get(config, 'sixHex') === false) { - return html - } - - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - - return posthtml([sixHex()]).process(html, posthtmlOptions).then(result => result.html) -} - -const sixHex = () => tree => { +const posthtmlPlugin = () => tree => { const targets = new Set(['bgcolor', 'color']) const process = node => { if (node.attrs) { - for (const [name, value] of Object.entries(node.attrs)) { + Object.entries(node.attrs).forEach(([name, value]) => { if (targets.has(name) && node.attrs[name]) { node.attrs[name] = conv(value) } - } + }) } return node @@ -30,3 +20,13 @@ const sixHex = () => tree => { return tree.walk(process) } + +export default posthtmlPlugin + +export async function sixHEX(html = '', posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin() + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) +} diff --git a/src/transformers/urlParameters.js b/src/transformers/urlParameters.js index 56e16291..60fc98c0 100644 --- a/src/transformers/urlParameters.js +++ b/src/transformers/urlParameters.js @@ -1,20 +1,22 @@ -const posthtml = require('posthtml') -const {get, merge, isEmpty} = require('lodash') -const urlParams = require('posthtml-url-parameters') -const defaultConfig = require('../generators/posthtml/defaultConfig') +import posthtml from 'posthtml' +import get from 'lodash-es/get.js' +import { defu as merge } from 'defu' +import urlParameters from 'posthtml-url-parameters' +import posthtmlConfig from '../posthtml/defaultConfig.js' -module.exports = async (html, config = {}, direct = false) => { - const urlParameters = direct ? config : get(config, 'urlParameters', {}) +export default function posthtmlPlugin(options = {}) { + const { _options, ...parameters } = options + const tags = get(_options, 'tags', ['a']) + const strict = get(_options, 'strict', true) + const qs = get(_options, 'qs', { encode: false }) - if (!isEmpty(urlParameters)) { - const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {})) - const {_options, ...parameters} = urlParameters - const tags = get(_options, 'tags', ['a']) - const strict = get(_options, 'strict', true) - const qs = get(_options, 'qs', {encode: false}) - - return posthtml([urlParams({parameters, tags, qs, strict})]).process(html, posthtmlOptions).then(result => result.html) - } + return urlParameters({ parameters, tags, qs, strict }) +} - return html +export async function addURLParams(html = '', options = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(options) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) } diff --git a/src/transformers/useAttributeSizes.js b/src/transformers/useAttributeSizes.js new file mode 100644 index 00000000..43477577 --- /dev/null +++ b/src/transformers/useAttributeSizes.js @@ -0,0 +1,65 @@ +import postcss from 'postcss' +import posthtml from 'posthtml' +import get from 'lodash-es/get.js' +import { defu as merge } from 'defu' +import posthtmlConfig from '../posthtml/defaultConfig.js' + +const posthtmlPlugin = (mappings = {}) => tree => { + if (!Object.keys(mappings).length) { + return tree + } + + // Normalize tags in mappings by lowercasing them + for (const key in mappings) { + if (Array.isArray(mappings[key])) { + mappings[key] = mappings[key].map(value => value.toLowerCase()) + } + } + + const process = node => { + // Check if the node is defined in mappings + if ( + get(mappings, 'width', []).includes(node.tag) + || get(mappings, 'height', []).includes(node.tag) + ) { + // Check if the node has an inline CSS property equal to one of the keys in mappings + if (node.attrs.style) { + const { root } = postcss().process(`${node.attrs.style}`, { from: undefined }) + + root.walkDecls(decl => { + if (mappings.width.includes(node.tag) && decl.prop === 'width') { + // Set its value as an attribute on the node; the attribute name is the key in mappings + node.attrs.width = decl.value.replace('px', '') + // Remove the inline CSS property from the declaration + decl.remove() + } + + if (mappings.height.includes(node.tag) && decl.prop === 'height') { + // Set its value as an attribute on the node; the attribute name is the key in mappings + node.attrs.height = decl.value.replace('px', '') + // Remove the inline CSS property from the declaration + decl.remove() + } + }) + + // Set the remaining inline CSS as the `style` attribute on the node + // If there are no remaining declarations, remove the `style` attribute + node.attrs.style = root.toString().trim() || false + } + } + + return node + } + + return tree.walk(process) +} + +export default posthtmlPlugin + +export async function useAttributeSizes(html = '', mappings = {}, posthtmlOptions = {}) { + return posthtml([ + posthtmlPlugin(mappings) + ]) + .process(html, merge(posthtmlOptions, posthtmlConfig)) + .then(result => result.html) +} diff --git a/src/utils/getConfigByFilePath.js b/src/utils/getConfigByFilePath.js new file mode 100644 index 00000000..41b43101 --- /dev/null +++ b/src/utils/getConfigByFilePath.js @@ -0,0 +1,124 @@ +import { resolve } from 'pathe' +import get from 'lodash/get.js' +import { defu as merge } from 'defu' +import { lstat } from 'node:fs/promises' +import isEmpty from 'lodash-es/isEmpty.js' + +/** + * Compute the Maizzle config object. + * + * If a config file path is provided, that file will be read + * instead of trying to merge the base and environment configs. + * + * If an environment is provided, the config object will be + * computed based on a base config and the resolved + * environment config. + * + * @param {string} env - The environment name to use. + * @param {string} path - The path to the config file to use. + * @returns {Promise<object>} The computed config object. + */ +export async function readFileConfig(config) { + try { + /** + * If `config` is string, try to read and return + * the config object from it. + */ + if (typeof config === 'string' && config) { + const { default: resolvedConfig } = await import(`file://${resolve(config)}?d=${Date.now()}`) + .catch(() => { throw new Error('Could not read config file') }) + + return merge(resolvedConfig, { env: config }) + } + + /** + * Otherwise, default to the Environment config approach, + * where we check for config files that follow a + * specific naming convention. + * + * First, we check for a base config file, in this order: + */ + const baseConfigFileNames = [ + './maizzle.config.js', + './maizzle.config.local.js', + './config.js', + './config.local.js', + './maizzle.config.cjs', + './maizzle.config.local.cjs', + './config.cjs', + './config.local.cjs', + ] + + const env = get(config, 'env', 'local') + let baseConfig = merge({ env }, config) + let envConfig = merge({ env }, config) + + const cwd = env === 'maizzle-ci' ? './test/stubs/config' : process.cwd() + + // We load the first base config found + for (const module of baseConfigFileNames) { + // Check if the file exists, go to next one if not + const configFileExists = await lstat(resolve(cwd, module)).catch(() => false) + + if (!configFileExists) { + continue + } + + // Load the config file + try { + const { default: baseConfigFile } = await import(`file://${resolve(cwd, module)}?d=${Date.now()}`) + + // Use the first base config found + if (!isEmpty(baseConfigFile)) { + baseConfig = merge(baseConfigFile, baseConfig) + break + } + } catch (error) { + break + } + + } + + // Then, we load and compute the first Environment config found + if (env !== 'local') { + let loaded = false + const modulesToTry = [ + `./maizzle.config.${env}.js`, + `./config.${env}.js`, + `./maizzle.config.${env}.cjs`, + `./config.${env}.cjs`, + ] + + for (const module of modulesToTry) { + // Check if the file exists, go to next one if not + const configFileExists = await lstat(resolve(cwd, module)).catch(() => false) + + if (!configFileExists) { + continue + } + + // Load the config file + try { + const { default: envConfigFile } = await import(`file://${resolve(cwd, module)}?d=${Date.now()}`) + + // If it's not an empty object, merge it with the base config + if (!isEmpty(envConfigFile)) { + envConfig = merge(envConfigFile, envConfig) + loaded = true + break + } + } catch (error) { + break + } + } + + if (!loaded) { + throw new Error(`Failed to load the \`${env}\` environment config, do you have one of these files in your project root?\n\n${modulesToTry.join('\n')}`) + } + } + + return merge(envConfig, baseConfig) + } catch (error) { + throw new Error('Could not compute config') + } +} diff --git a/src/utils/helpers.js b/src/utils/helpers.js deleted file mode 100644 index 85684da0..00000000 --- a/src/utils/helpers.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - requireUncached: module => { - try { - delete require.cache[require.resolve(module)] - return require(module) - } catch { - throw new Error(`could not load ${module}`) - } - }, - // https://github.com/lukeed/console-clear - clearConsole: () => process.stdout.write('\x1B[H\x1B[2J'), - toStyleString: (object = {}) => Object.entries(object).map(([k, v]) => `${k}: ${v}`).join('; ') -} diff --git a/src/utils/node.js b/src/utils/node.js new file mode 100644 index 00000000..f93f28b4 --- /dev/null +++ b/src/utils/node.js @@ -0,0 +1,68 @@ +import os from 'node:os' +import gm from 'gray-matter' +import pico from 'picocolors' +import { humanFileSize } from './string.js' + +// Return a local IP address +export function getLocalIP() { + const interfaces = os.networkInterfaces() + + for (const iface in interfaces) { + const ifaceInfo = interfaces[iface] + + for (const alias of ifaceInfo) { + if (alias.family === 'IPv4' && !alias.internal) { + return alias.address + } + } + } + + return '127.0.0.1' // Default to localhost if no suitable IP is found +} + +/** + * Return the file size of a string + * + * @param {string} string The HTML string to calculate the file size of + * @returns {number} The file size in bytes, a floating-point number + * */ +export function getFileSize(string) { + const blob = new Blob([string], { type: 'text/html' }) + + return blob.size.toFixed(2) +} + +/** + * Color-code a formatted file size string depending on the size + * + * 0-49 KB: green + * 50-102 KB: yellow + * >102 KB: red + * + * @param {string} string The HTML string to calculate the file size of + * @returns {string} The formatted, color-coded file size + * */ +export function getColorizedFileSize(string) { + const size = getFileSize(string) + const formattedSize = humanFileSize(size) + + if (size / 1024 < 50) { + return formattedSize + } + + if (size / 1024 < 102) { + return pico.yellow(formattedSize) + } + + return pico.red(formattedSize) +} + +export function parseFrontMatter(html) { + /** + * Need to pass empty options object to gray-matter + * in order to disable caching. + * https://github.com/jonschlinkert/gray-matter/issues/43 + */ + const { content, data, matter, stringify } = gm(html, {}) + return { content, data, matter, stringify } +} diff --git a/src/utils/string.js b/src/utils/string.js new file mode 100644 index 00000000..1481eeb4 --- /dev/null +++ b/src/utils/string.js @@ -0,0 +1,117 @@ +/** + * Inject a script into HTML by "prepending" it to the first available closing + * tag from a list of candidates. + * + * @param {string} html The HTML content + * @param {string} script The script to inject + * @returns {string} The modified HTML + */ +export function injectScript(html = '', script = '') { + if (html.includes('</head>')) { + return html.replace('</head>', `${script}</head>`) + } + + if (html.includes('</title>')) { + return html.replace('</title>', `</title>${script}`) + } + + if (html.includes('</body>')) { + return html.replace('</body>', `${script}</body>`) + } + + if (html.includes('</html>')) { + return html.replace('</html>', `${script}</html>`) + } + + if (html.includes('<!doctype html>')) { + return html.replace('<!doctype html>', `<!doctype html>${script}`) + } + + return script + html +} + +/** + * Find the common prefix among an array of strings. + * + * @param {string[]} strings Array of strings + * @returns {string} Common prefix + * @throws {TypeError} If the input is not an array + */ +export function findCommonPrefix(strings) { + // Must be an array + if (!Array.isArray(strings)) { + throw new TypeError('findCommonPrefix expects an array') + } + + const sortedStrings = strings.slice().sort() + const first = sortedStrings[0] + const last = sortedStrings[sortedStrings.length - 1] + let i = 0 + + while (i < first.length && first.charAt(i) === last.charAt(i)) { + i++ + } + + return first.substring(0, i) +} + +export function formatMs(milliseconds) { + const date = new Date(milliseconds); + + const hours = date.getUTCHours(); + const minutes = date.getUTCMinutes(); + const seconds = date.getUTCSeconds(); + const formattedTime = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; + + return formattedTime; +} + +/** + * Format milliseconds as human-readable text. + * + * @param {number} ms Number of milliseconds. + * @returns {string} Formatted string. + */ +export function formatTime(ms) { + if (ms < 1000) { + return `${ms} ms` + } + + if (ms < 60000) { // Less than 1 minute + const seconds = ms / 1000 + return `${seconds.toFixed(2)} s` + } + + const minutes = ms / 60000 + return `${minutes.toFixed(2)} min` +} + +/** + * Format bytes as human-readable text. + * + * @param {number} bytes Number of bytes. + * @param {boolean} si True to use metric (SI) units, aka powers of 1000. False to use + * binary (IEC), aka powers of 1024. + * @param {number} dp Number of decimal places to display. + * + * @return {string} Formatted string. + */ +export function humanFileSize(bytes, si=false, dp=2) { + const threshold = si ? 1000 : 1024 + + if (Math.abs(bytes) < threshold) { + return bytes + ' B' + } + + const units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] + let u = -1 + const r = 10**dp + + do { + bytes /= threshold + ++u + } while (Math.round(Math.abs(bytes) * r) / r >= threshold && u < units.length - 1) + + + return bytes.toFixed(dp) + ' ' + units[u] +} diff --git a/test/build.test.js b/test/build.test.js new file mode 100644 index 00000000..c603441c --- /dev/null +++ b/test/build.test.js @@ -0,0 +1,224 @@ +import path from 'pathe' +import fg from 'fast-glob' +import build from '../src/commands/build.js' +import { rm, readFile } from 'node:fs/promises' +import { describe, expect, test, beforeEach, afterEach, afterAll, vi } from 'vitest' + +describe.concurrent('Build', () => { + beforeEach(async context => { + context.folder = '_temp_' + Math.random().toString(36).slice(2, 9) + }) + + afterEach(async context => { + if (context.folder) { + await rm(context.folder, { recursive: true }).catch(() => {}) + context.folder = undefined + } + }) + + test('Throws if no config found', async () => { + await expect(() => build({})).rejects.toThrow() + }) + + test('Throws if no templates found', async () => { + await expect(() => build({ foo: 'bar' })).rejects.toThrow('No templates found in') + }) + + test('Throws if build.files is invalid', async () => { + await expect(() => build({ + build: { + content: true + } + })).rejects.toThrow() + }) + + test('Runs `beforeCreate` event', async ctx => { + await build( + { + build: { + content: 'test/fixtures/**/beforeCreate.html', + output: { + path: ctx.folder + } + }, + css: { + tailwind: { + content: ['test/fixtures/build/**/*.html'] + } + }, + async beforeCreate({ config }) { + config.foo = '`beforeCreate` with build()' + expect(config).toBeInstanceOf(Object) + } + } + ) + + const files = await fg.glob(`${ctx.folder}/**/*.html`) + const fileContents = await readFile(files[0], 'utf8') + + expect(fileContents).toContain('`beforeCreate` with build()') + }) + + test('Runs `afterBuild` event', async ctx => { + await build( + { + build: { + content: 'test/fixtures/**/beforeCreate.html', + output: { + path: ctx.folder + } + }, + css: { + tailwind: { + content: ['test/fixtures/build/**/*.html'] + } + }, + async afterBuild({ files, config, render }) { + ctx.afterBuild = files + expect(config).toBeInstanceOf(Object) + expect(files).toBeInstanceOf(Array) + expect(render).toBeInstanceOf(Function) + } + } + ) + + expect(ctx.afterBuild).toContain(`${ctx.folder}/test/fixtures/build/beforeCreate.html`) + }) + + test('Outputs files', async ctx => { + ctx.arrayGlobFiles = await build( + { + build: { + content: ['test/fixtures/**/*.html', '!test/fixtures/filters.html', '!test/fixtures/build/expandLinkTag.html'], + output: { + path: ctx.folder, + extension: 'blade.php' + } + }, + css: { + tailwind: { + content: ['test/fixtures/build/**/*.html'] + } + } + } + ).then(({ files }) => files) + + ctx.stringGlobFiles = await build( + { + build: { + content: 'test/fixtures/**/*.html', + output: { + path: path.join(ctx.folder, 'str'), + } + }, + css: { + tailwind: { + content: ['test/fixtures/build/**/*.html'] + } + } + } + ).then(({ files }) => files) + + expect(ctx.arrayGlobFiles.length).toBe(3) + expect(ctx.arrayGlobFiles).toContain(`${ctx.folder}/build/beforeCreate.blade.php`) + + expect(ctx.stringGlobFiles.length).toBe(5) + expect(ctx.stringGlobFiles).toContain(`${ctx.folder}/str/filters.html`) + }) + + test('Logs build report', async ctx => { + const consoleMock = vi.spyOn(console, 'log').mockImplementation(() => undefined) + + afterAll(() => { + consoleMock.mockReset() + }) + + await build( + { + build: { + content: 'test/fixtures/build/**/*.html', + output: { + path: ctx.folder + }, + summary: true + }, + css: { + tailwind: { + content: ['test/fixtures/build/**/*.html'] + } + } + } + ) + + expect(consoleMock).toHaveBeenCalledOnce() + }) + + test('Copies static files to output directory', async ctx => { + ctx.files = await build( + { + build: { + content: 'test/fixtures/build/*.html', + output: { + path: ctx.folder + }, + static: { + source: ['test/stubs/static/*'], + } + }, + css: { + tailwind: { + content: ['test/fixtures/build/**/*.html'] + } + }, + } + ).then(({ files }) => files) + + expect(ctx.files.length).toBe(3) + expect(ctx.files).toContain(`${ctx.folder}/image.png`) + }) + + test('Generates plaintext file', async ctx => { + ctx.files = await build( + { + build: { + content: 'test/fixtures/**/beforeCreate.html', + output: { + path: ctx.folder + }, + }, + plaintext: true, + css: { + tailwind: { + content: ['test/fixtures/build/**/*.html'] + } + }, + } + ).then(({ files }) => files) + + expect(ctx.files).toContain(`${ctx.folder}/test/fixtures/build/beforeCreate.txt`) + }) + + test('Expands <link> tags', async ctx => { + ctx.files = await build( + { + build: { + content: ['test/fixtures/**/expandLinkTag.html'], + output: { + path: ctx.folder + }, + }, + css: { + tailwind: { + content: ['test/fixtures/build/**/*.html'] + } + }, + } + ).then(({ files }) => files) + + const fileContents = await readFile(ctx.files[0], 'utf8') + + expect(fileContents).toContain('display: none') + expect(fileContents).not.toContain('expand') + expect(fileContents).toContain('link') + }) +}) diff --git a/test/config.test.js b/test/config.test.js new file mode 100644 index 00000000..0a9122a9 --- /dev/null +++ b/test/config.test.js @@ -0,0 +1,39 @@ +import { describe, expect, test, vi } from 'vitest' +import { readFileConfig } from '../src/utils/getConfigByFilePath' + +vi.mock('module', () => ({ + async import(path) { + // Simulate file not found or error condition + if (path.includes('config.invalid.js')) { + throw new Error('File not found') + } + + // Simulate a successful import for other paths + return { default: { foo: 'bar' } } + }, +})) + +describe.concurrent('Config', () => { + test('Throws if it cannot load the config', async () => { + await expect(readFileConfig('config.invalid.js')) + .rejects.toThrow('Could not compute config') + + await expect(readFileConfig({ env: 'invalid' })) + .rejects.toThrow('Could not compute config') + }) + + test('Returns the resolved config', async () => { + const config = await readFileConfig('test/stubs/config/config.js') + + expect(config).toHaveProperty('foo', 'bar') + }) + + test('Uses the correct environment config', async () => { + const config = await readFileConfig({ env: 'maizzle-ci' }) + + expect(config) + .toHaveProperty('env', 'maizzle-ci') + .toHaveProperty('local', true) + .toHaveProperty('foo', 'bar') + }) +}) diff --git a/test/expected/transformers/base-url.html b/test/expected/base-url.html similarity index 100% rename from test/expected/transformers/base-url.html rename to test/expected/base-url.html diff --git a/test/expected/build/beforeCreate.html b/test/expected/build/beforeCreate.html new file mode 100644 index 00000000..d3844795 --- /dev/null +++ b/test/expected/build/beforeCreate.html @@ -0,0 +1 @@ +`beforeCreate` with build() diff --git a/test/expected/components/backwards-compatibility.html b/test/expected/components/backwards-compatibility.html deleted file mode 100644 index 34299e70..00000000 --- a/test/expected/components/backwards-compatibility.html +++ /dev/null @@ -1,6 +0,0 @@ -<p class="flex">Variable from attribute: Example</p> -<p>Variable from locals attribute: bar</p> -<p class="hidden">Variable from page: maizzle-ci</p> -<p class="flex">Variable from attribute: Nested component</p> -<p>Variable from locals attribute: bar (nested)</p> -<p>Variable from page (nested): maizzle-ci</p> diff --git a/test/expected/components/kitchen-sink.html b/test/expected/components/kitchen-sink.html deleted file mode 100644 index aea4cd0e..00000000 --- a/test/expected/components/kitchen-sink.html +++ /dev/null @@ -1,73 +0,0 @@ -{{ test }} -The Website Weekly Newsletter -bar -{% capture email_title %}Hey {{customer.first_name}} {{ customer.last_name}}, {% endcapture %} -<!DOCTYPE html> -<html lang="en" xmlns:v="urn:schemas-microsoft-com:vml"> -<head> - <style> - </style> -</head> -<body class="bg-red-500"> - <h1>H1 in fill:template</h1> - - <!-- Expressions --> - Compiled: maizzle-ci - Ignored: {{ page.env }} - Inside component: maizzle-ci - Inside component (ignored): {{ page.env }} - Inside nested component: maizzle-ci - Inside nested component (ignored): {{ page.env }} - - <!-- Component slots --> - Slot header - - <!-- Markdown --> - <h3>Heading</h3> - <pre><code class="language-js">console.log('Hello world!') -</code></pre> - <h3>Markdown in component</h3> - - <!-- Passing props to component --> - Environment: maizzle-ci - Environment (ignore expression): {{ page.env }} - - <!-- Nesting components, with props --> - Parent - Childish - - <!-- <fetch> tag --> - <ul> - <li> - Leanne Graham - </li> - <li> - Ervin Howell - </li> - <li> - Clementine Bauch (last item) - </li> - </ul> - - <!-- <outlook> tag --> - - <!--[if mso]>in outlook<![endif]--> - - <!-- Conditionals --> - <p>Using Maizzle programmatically</p> - - <!-- Loops --> - {{ i }} is <i>1</i> - {{ i }} is <i>2 (last)</i> - - <!-- Switch --> - page.foo is bar - - <!-- Scope --> - Author: John - Editor: Jane - - <!-- Raw --> - Expression should be ignored: {{ foo }} -</body> -</html> diff --git a/test/expected/transformers/filters.html b/test/expected/filters.html similarity index 88% rename from test/expected/transformers/filters.html rename to test/expected/filters.html index ac2a0846..6f01d220 100644 --- a/test/expected/transformers/filters.html +++ b/test/expected/filters.html @@ -62,6 +62,8 @@ <div>est</div> <!-- Slice with endIndex --> <div>tes</div> +<!-- Slice with invalid attribute --> +<div>test</div> <!-- Truncate --> <div>Ground control to...</div> @@ -69,12 +71,20 @@ <div>Ground control to</div> <!-- Truncate with custom ellipsis --> <div>Ground control to no one</div> +<!-- Truncate error --> +<div>undefined</div> <!-- Truncate words --> <div>Ground control...</div> <!-- Truncate words with custom ellipsis --> <div>Ground control over and out</div> +<!-- Custom: underscore-case --> +<div>t_e_s_t</div> + +<!-- Unescape --> +<div>"&'<></div> + <!-- URL decode --> <div>'Stop!' said Fred</div> <!-- URL encode --> diff --git a/test/expected/transformers/prettify.html b/test/expected/transformers/prettify.html deleted file mode 100644 index 07c3991f..00000000 --- a/test/expected/transformers/prettify.html +++ /dev/null @@ -1,23 +0,0 @@ -<!doctype html> -<html> - <head> - <meta charset="utf-8"> - <link href="style.css" rel="stylesheet"> - </head> - <body> - <br> - <br> - <img src="image.png"> - <img src="image.png"> - <hr class="my-4"> - <hr class="my-4"> - <div style="font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif; line-height: 1;"> - <!--[if mso]> - <v:rect stroke="f" fillcolor="none" style="width: 600px" xmlns:v="urn:schemas-microsoft-com:vml"> - <v:fill type="frame" src="https://via.placeholder.com/600x400" /> - <v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text: true"><div><![endif]--> - <img src="image.png"> - <!--[if mso]></div></v:textbox></v:rect><![endif]--> - </div> - </body> -</html> diff --git a/test/fixtures/transformers/base-url.html b/test/fixtures/base-url.html similarity index 100% rename from test/fixtures/transformers/base-url.html rename to test/fixtures/base-url.html diff --git a/test/fixtures/basic.html b/test/fixtures/basic.html deleted file mode 100644 index ebd5b3b7..00000000 --- a/test/fixtures/basic.html +++ /dev/null @@ -1,9 +0,0 @@ -<!doctype html> -<html> -<head> - <title>test></title> -</head> -<body> - <div>test</div> -</body> -</html> diff --git a/test/fixtures/build/beforeCreate.html b/test/fixtures/build/beforeCreate.html new file mode 100644 index 00000000..e4b8fddc --- /dev/null +++ b/test/fixtures/build/beforeCreate.html @@ -0,0 +1 @@ +{{ page.foo }} diff --git a/test/fixtures/build/expandLinkTag.html b/test/fixtures/build/expandLinkTag.html new file mode 100644 index 00000000..cd21736d --- /dev/null +++ b/test/fixtures/build/expandLinkTag.html @@ -0,0 +1,4 @@ +<link rel="stylesheet" href="test/stubs/foo.css"> +<link rel="stylesheet" href="test/stubs/style.css" expand> + +<div class="hidden">test</div> diff --git a/test/stubs/empty/empty.html b/test/fixtures/build/image.png similarity index 100% rename from test/stubs/empty/empty.html rename to test/fixtures/build/image.png diff --git a/test/fixtures/components/backwards-compatibility.html b/test/fixtures/components/backwards-compatibility.html deleted file mode 100644 index 3f6c19d4..00000000 --- a/test/fixtures/components/backwards-compatibility.html +++ /dev/null @@ -1,19 +0,0 @@ -<component - src="test/stubs/components/component.html" - text="Example" - locals='{ - "foo": "bar" - }' -> -<p class="hidden">Variable from page: [[ page.env ]]</p> - -<component - src="test/stubs/components/component.html" - text="Nested component" - locals='{ - "foo": "bar (nested)" - }' -> -<p>Variable from page (nested): [[ page.env ]]</p> - </component> -</component> diff --git a/test/fixtures/components/kitchen-sink.html b/test/fixtures/components/kitchen-sink.html deleted file mode 100644 index dbb5970d..00000000 --- a/test/fixtures/components/kitchen-sink.html +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: "The Website Weekly Newsletter" -roles: - author: - name: "John" - editor: - name: "Jane" ---- - -@{{ test }} - -{{ page.title }} - -{{ page.foo }} - -<raw> - {% capture email_title %}Hey {{customer.first_name}} {{ customer.last_name}}, {% endcapture %} -</raw> - -<x-layout> - <fill:template> - <h1>H1 in fill:template</h1> - - <!-- Expressions --> - Compiled: {{ page.env }} - Ignored: @{{ page.env }} - <x-bare> - Inside component: {{ page.env }} - Inside component (ignored): @{{ page.env }} - - <x-bare> - Inside nested component: {{ page.env }} - Inside nested component (ignored): @{{ page.env }} - </x-bare> - </x-bare> - - <!-- Component slots --> - <x-bare> - <slot:header>Slot header</slot:header> - </x-bare> - - <!-- Markdown --> - <md> - ### Heading - - ```js - console.log('Hello world!') - ``` - </md> - - <x-bare> - <md> - ### Markdown in component - </md> - </x-bare> - - <!-- Passing props to component --> - <x-text text="{{ page.env }}">Environment: </x-text> - <x-text text="@{{ page.env }}">Environment (ignore expression): </x-text> - - <!-- Nesting components, with props --> - <x-bare aware:text="ish"> - Parent - <x-text>Child</x-text> - </x-bare> - - <!-- <fetch> tag --> - <x-bare> - <fetch url="test/stubs/data.json"> - <ul> - <each loop="user in response"> - <li> - <x-bare>{{ user.name + (loop.last ? ' (last item)' : '') }}</x-bare> - </li> - </each> - </ul> - </fetch> - </x-bare> - - <!-- <outlook> tag --> - <x-bare> - <outlook>in outlook</outlook> - </x-bare> - - <!-- Conditionals --> - <x-bare> - <if condition="page.env === 'maizzle-ci'"> - <p>Using Maizzle programmatically</p> - </if> - </x-bare> - - <!-- Loops --> - <x-bare> - <each loop="i in [1, 2]"> - @{{ i }} is <i>{{ i }}{{ loop.last ? ' (last)' : '' }}</i> - </each> - </x-bare> - - <!-- Switch --> - <switch expression="page.foo"> - <case n="'bar'"> - page.foo is {{ page.foo }} - </case> - <default> - default - page.foo is {{ page.foo }} - </default> - </switch> - - <!-- Scope --> - <x-bare> - <scope with="page.roles"> - Author: {{ author.name }} - Editor: {{ editor.name }} - </scope> - </x-bare> - - <!-- Raw --> - <x-bare> - <raw> - Expression should be ignored: {{ foo }} - </raw> - </x-bare> - </fill:template> -</x-layout> diff --git a/test/fixtures/transformers/filters.html b/test/fixtures/filters.html similarity index 89% rename from test/fixtures/transformers/filters.html rename to test/fixtures/filters.html index 193c71d8..c46b8300 100644 --- a/test/fixtures/transformers/filters.html +++ b/test/fixtures/filters.html @@ -68,6 +68,8 @@ <div slice="1">test</div> <!-- Slice with endIndex --> <div slice="0,-1">test</div> +<!-- Slice with invalid attribute --> +<div slice="">test</div> <!-- Truncate --> <div truncate="17">Ground control to Major Tom.</div> @@ -75,12 +77,20 @@ <div truncate="17">Ground control to</div> <!-- Truncate with custom ellipsis --> <div truncate="17, no one">Ground control to Major Tom.</div> +<!-- Truncate error --> +<div truncate=""></div> <!-- Truncate words --> <div truncate-words="2">Ground control to Major Tom.</div> <!-- Truncate words with custom ellipsis --> <div truncate-words="2, over and out">Ground control to Major Tom.</div> +<!-- Custom: underscore-case --> +<div underscore-case>test</div> + +<!-- Unescape --> +<div unescape>&#34;&amp;&#39;&lt;&gt;</div> + <!-- URL decode --> <div url-decode>%27Stop%21%27+said+Fred</div> <!-- URL encode --> diff --git a/test/fixtures/transformers/prettify.html b/test/fixtures/transformers/prettify.html deleted file mode 100644 index fbc232df..00000000 --- a/test/fixtures/transformers/prettify.html +++ /dev/null @@ -1,31 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <meta charset="utf-8" /> - <link href="style.css" rel="stylesheet" /> -</head> -<body> - <br /> - <br/> - <img src="image.png" /> - <img src="image.png"/> - <hr class="my-4" /> - <hr class="my-4"/> - <div - style=" - font-family: - ui-sans-serif, - system-ui, - -apple-system, - &quot;Segoe UI&quot;, - sans-serif; - line-height: 1; "> - <!--[if mso]> - <v:rect stroke="f" fillcolor="none" style="width: 600px" xmlns:v="urn:schemas-microsoft-com:vml"> - <v:fill type="frame" src="https://via.placeholder.com/600x400" /> - <v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text: true"><div><![endif]--> - <img src="image.png" /> - <!--[if mso]></div></v:textbox></v:rect><![endif]--> - </div> -</body> -</html> diff --git a/test/plaintext.test.js b/test/plaintext.test.js new file mode 100644 index 00000000..fafbf4a7 --- /dev/null +++ b/test/plaintext.test.js @@ -0,0 +1,132 @@ +import { + beforeEach, + afterEach, + describe, + expect, + test } from 'vitest' +import { + generatePlaintext, + handlePlaintextTags, + writePlaintextFile +} from '../src/generators/plaintext.js' +import { rm, readdir, readFile } from 'node:fs/promises' + +const minify = html => html.replaceAll(/[\s\n]+/g, '') + +describe.concurrent('Plaintext', () => { + beforeEach(async context => { + context.folder = '_temp_' + Math.random().toString(36).slice(2, 9) + }) + + afterEach(async context => { + if (context.folder) { + await rm(context.folder, { recursive: true }).catch(() => {}) + context.folder = undefined + } + }) + + test('Throws is plaintext content is not provided', async () => { + await expect(writePlaintextFile(undefined)).rejects.toThrow('Missing plaintext content.') + }) + + test('Throws is plaintext content is not a string', async () => { + await expect(writePlaintextFile(true)).rejects.toThrow('Plaintext content must be a string.') + }) + + test('Does not generate plaintext if no HTML is provided', async () => { + expect(await generatePlaintext()).toBe('') + }) + + test('Generates plaintext', async () => { + const html = ` + <div>Show in HTML</div> + <plaintext>Show in plaintext</plaintext> + <not-plaintext> + <p>Do not show <a href="url">this</a> in plaintext.</p> + </not-plaintext> + ` + + const expected = 'Show in HTML\nShow in plaintext' + + const result = await generatePlaintext(html) + + expect(result).toBe(expected) + }) + + test('Generates plaintext (with options)', async () => { + const html = ` + <div>Show in HTML &amp; plaintext &check;</div> + <plaintext>Show <a href="https://example.com">this</a> in plaintext</plaintext> + <not-plaintext> + <p>Do not show this in plaintext.</p> + </not-plaintext> + ` + + const expected = 'Show in HTML & plaintext ✓\nShow this [https://example.com] in plaintext' + + const result = await generatePlaintext( + html, + { + dumpLinkHrefsNearby: { + wrapHeads: '[', + wrapTails: ']' + }, + posthtml: { + decodeEntities: true + } + }, + ) + + expect(result).toBe(expected) + }) + + test('Outputs plaintext files', async ctx => { + const withOptions = await writePlaintextFile('test', { + plaintext: `${ctx.folder}/plaintext.txt` + }) + + const withOptionsFiles = await readdir(ctx.folder) + const withOptionsFileContents = await readFile(`${ctx.folder}/plaintext.txt`, 'utf8') + + // Successful file write fulfills the promise with `undefined` + expect(withOptions).toBe(undefined) + expect(withOptionsFiles).toContain('plaintext.txt') + expect(withOptionsFileContents).toBe('test') + + const withPermalink = await writePlaintextFile('with permalink', { + plaintext: true , + permalink: `${ctx.folder}/plaintext2.txt` + }) + + const withPermalinkFiles = await readdir(ctx.folder) + const withPermalinkFileContents = await readFile(`${ctx.folder}/plaintext2.txt`, 'utf8') + + // Successful file write fulfills the promise with `undefined` + expect(withPermalink).toBe(undefined) + expect(withPermalinkFiles).toContain('plaintext2.txt') + expect(withPermalinkFileContents).toBe('with permalink') + }) + + test('Handles custom <plaintext> tags', async () => { + const html = ` + <p>This should exist in the returned HTML.</p> + <plaintext>This should be removed from the returned HTML</plaintext> + <not-plaintext> + <p>This should also exist in the returned HTML.</p> + </not-plaintext> + ` + + const expected = ` + <p>This should exist in the returned HTML.</p> + <p>This should also exist in the returned HTML.</p> + ` + + const result = await handlePlaintextTags(html) + + expect(minify(result)).toBe(minify(expected)) + }) + + test('Returns original input if it is empty', async () => { + expect(await handlePlaintextTags('')).toBe('') + }) +}) diff --git a/test/posthtml.test.js b/test/posthtml.test.js new file mode 100644 index 00000000..0a5c1f0b --- /dev/null +++ b/test/posthtml.test.js @@ -0,0 +1,14 @@ +import { describe, expect, test } from 'vitest' +import { process as posthtml } from '../src/posthtml/index.js' + +describe.concurrent('PostHTML', () => { + test('Throws on PostHTML processing error', async () => { + await expect(posthtml('test', { + posthtml: { + plugins: [ + () => { throw new Error('TestError') } + ] + } + })).rejects.toThrow('TestError') + }) +}) diff --git a/test/render.test.js b/test/render.test.js new file mode 100644 index 00000000..1edb731c --- /dev/null +++ b/test/render.test.js @@ -0,0 +1,71 @@ +import { describe, expect, test } from 'vitest' +import { render } from '../src/generators/render.js' + +describe.concurrent('Render', () => { + test('Throws if first argument is not a string', async () => { + const html = true + + await expect(render(html)).rejects.toThrow('first argument must be a string') + }) + + test('Throws if first argument is an empty string', async () => { + const html = '' + + await expect(render(html)).rejects.toThrow('received empty string') + }) + + test('Uses data from config if available', async () => { + const source = '<div class="inline">{{ page.mail }}</div>' + + const { html } = await render(source, { + mail: 'puzzle' + }) + + expect(html).toBe('<div class="inline">puzzle</div>') + }) + + test('Runs the `beforeRender` event', async () => { + const { html } = await render('<div class="inline">{{ page.foo }}</div>', { + beforeRender({ config }) { + config.foo = 'bar' + } + }) + + expect(html).toBe('<div class="inline">bar</div>') + }) + + test('Runs the `afterRender` event', async () => { + const { html } = await render('<div class="inline">foo</div>', { + afterRender({ config }) { + config.replaceStrings = { + foo: 'bar' + } + } + }) + + expect(html).toBe('<div class="inline">bar</div>') + }) + + test('Runs the `afterTransformers` event', async () => { + const { html: withHtmlReturned } = await render('<div class="inline">foo</div>', { + replaceStrings: { + foo: 'bar' + }, + afterTransformers({ html }) { + return html.replace('bar', 'baz') + } + }) + + const { html: nothingReturned } = await render('<div class="inline">foo</div>', { + replaceStrings: { + foo: 'bar' + }, + afterTransformers({ html }) { + html.replace('bar', 'baz') + } + }) + + expect(withHtmlReturned).toBe('<div class="inline">baz</div>') + expect(nothingReturned).toBe('<div class="inline">bar</div>') + }) +}) diff --git a/test/server.test.js b/test/server.test.js new file mode 100644 index 00000000..f46eda8b --- /dev/null +++ b/test/server.test.js @@ -0,0 +1,74 @@ +import request from 'supertest' +import serve from '../src/commands/serve.js' +import { describe, expect, test, beforeAll } from 'vitest' + +const init = async () => { + await serve({ + build: { + content: 'test/fixtures/build/**/*.html', + static: { + source: 'test/fixtures/build/**/*.png', + } + }, + components: { + folders: ['test/stubs/templates'] + }, + beforeCreate(config) { + config.hello = 'world' + }, + server: { + maxRetries: 1 + } + }) +} + +beforeAll(async () => { + await init() +}) + +describe.concurrent('Server', () => { + test('Starts server', async () => { + const res = await request('http://localhost:3000').get('/') + + expect(res.status).toBe(200) + expect(res.text).toContain('<title>Maizzle | Templates</title>') + + // Test if the server serves static files from `build.static.source` + const imageRes = await request('http://localhost:3000').get('/image.png') + expect(imageRes.status).toBe(200) + }) + + test('Retries for a different port', async () => { + await init() + + const res = await request('http://localhost:3001').get('/') + + expect(res.status).toBe(200) + }) + + test('Throws if it cannot render a template', async () => { + const res = await request('http://localhost:3000').get('/error.html') + + expect(res.status).toBe(500) + }) + + test('Serves scripts', async () => { + const hmr = await request('http://localhost:3000').get('/hmr.js') + + expect(hmr.status).toBe(200) + }) + + test('Lists grouped templates', async () => { + const res = await request('http://localhost:3000').get('/') + + expect(res.status).toBe(200) + expect(res.text).toContain('<h2>test/fixtures/build</h2>') + }) + + test('Renders template', async () => { + const res = await request('http://localhost:3000').get('/expandLinkTag.html') + + expect(res.status).toBe(200) + expect(res.text).toContain('<style>.hidden {') + }) +}) diff --git a/test/stubs/assets/foo.bar b/test/stubs/assets/foo.bar deleted file mode 100644 index 5f5bdb43..00000000 --- a/test/stubs/assets/foo.bar +++ /dev/null @@ -1 +0,0 @@ -Some asset file... diff --git a/test/stubs/assets2/foo1.bar b/test/stubs/assets2/foo1.bar deleted file mode 100644 index 5f5bdb43..00000000 --- a/test/stubs/assets2/foo1.bar +++ /dev/null @@ -1 +0,0 @@ -Some asset file... diff --git a/test/stubs/assets2/foo2.bar b/test/stubs/assets2/foo2.bar deleted file mode 100644 index 5f5bdb43..00000000 --- a/test/stubs/assets2/foo2.bar +++ /dev/null @@ -1 +0,0 @@ -Some asset file... diff --git a/test/stubs/breaking/bad.html b/test/stubs/breaking/bad.html deleted file mode 100644 index b5ae15c2..00000000 --- a/test/stubs/breaking/bad.html +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: [THIS] should break the build ---- - -<div class="inline">{{ page.title }}</div> diff --git a/test/stubs/components/bare.html b/test/stubs/components/bare.html deleted file mode 100644 index 448489ae..00000000 --- a/test/stubs/components/bare.html +++ /dev/null @@ -1,8 +0,0 @@ -<script props> - module.exports = { - text: props.text || 'default text' - } -</script> -<slot:header></slot:header> -<slot:aw></slot:aw> -<content></content> diff --git a/test/stubs/components/component.html b/test/stubs/components/component.html deleted file mode 100644 index 35ef8748..00000000 --- a/test/stubs/components/component.html +++ /dev/null @@ -1,12 +0,0 @@ -<script props> - module.export = { - text: props.text || 'default text', - foo: props.foo || 'default foo' - } -</script> - -<p class="flex">Variable from attribute: [[ text ]]</p> - -<p>Variable from locals attribute: [[ foo ]]</p> - -<content></content> diff --git a/test/stubs/components/text.html b/test/stubs/components/text.html deleted file mode 100644 index ee363a01..00000000 --- a/test/stubs/components/text.html +++ /dev/null @@ -1,6 +0,0 @@ -<script props> - module.exports = { - text: props.text || 'default text' - } -</script> -<content></content>{{ text }} diff --git a/test/stubs/config/config.js b/test/stubs/config/config.js index 32acacf9..92b33d29 100644 --- a/test/stubs/config/config.js +++ b/test/stubs/config/config.js @@ -1,10 +1,3 @@ -module.exports = { - build: { - templates: { - source: '../templates', - destination: { - path: 'build_local' - } - } - } +export default { + foo: 'bar' } diff --git a/test/stubs/config/config.maizzle-ci.js b/test/stubs/config/config.maizzle-ci.js deleted file mode 100644 index 1d7aa2ac..00000000 --- a/test/stubs/config/config.maizzle-ci.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - build: { - templates: { - source: '../templates', - destination: { - path: 'build_production' - } - } - } -} diff --git a/test/stubs/config/maizzle.config.local.js b/test/stubs/config/maizzle.config.local.js new file mode 100644 index 00000000..cc24bc4c --- /dev/null +++ b/test/stubs/config/maizzle.config.local.js @@ -0,0 +1,3 @@ +export default { + local: true +} diff --git a/test/stubs/config/maizzle.config.maizzle-ci.js b/test/stubs/config/maizzle.config.maizzle-ci.js new file mode 100644 index 00000000..92b33d29 --- /dev/null +++ b/test/stubs/config/maizzle.config.maizzle-ci.js @@ -0,0 +1,3 @@ +export default { + foo: 'bar' +} diff --git a/test/stubs/config/maizzle.config.test.js b/test/stubs/config/maizzle.config.test.js deleted file mode 100644 index bf4b41a7..00000000 --- a/test/stubs/config/maizzle.config.test.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - file: 'maizzle.config.test.js', - build: { - templates: { - source: '../templates', - destination: { - path: 'build_test' - } - } - } -} diff --git a/test/stubs/data.json b/test/stubs/data.json deleted file mode 100644 index 818816a2..00000000 --- a/test/stubs/data.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "id": 1, - "name": "Leanne Graham" - }, - { - "id": 2, - "name": "Ervin Howell" - }, - { - "id": 3, - "name": "Clementine Bauch" - } -] diff --git a/test/stubs/events/before-create.html b/test/stubs/events/before-create.html deleted file mode 100644 index 783ed96c..00000000 --- a/test/stubs/events/before-create.html +++ /dev/null @@ -1 +0,0 @@ -<div class="inline">Foo is {{ page.foo }}</div> diff --git a/test/stubs/layouts/layout.html b/test/stubs/layouts/layout.html deleted file mode 100644 index fdf4bcd7..00000000 --- a/test/stubs/layouts/layout.html +++ /dev/null @@ -1,13 +0,0 @@ -<!DOCTYPE {{{ page.doctype || 'html' }}}> -<html lang="{{ page.language || 'en' }}" xmlns:v="urn:schemas-microsoft-com:vml"> - <head> - <stack name="styles" /> - <style> - {{{ page.css }}} - </style> - </head> - - <body class="{{ page.bodyClass ?? 'bg-red-500' }}"> - <slot:template /> - </body> -</html> diff --git a/test/stubs/layouts/legacy.html b/test/stubs/layouts/legacy.html deleted file mode 100644 index ba93c90b..00000000 --- a/test/stubs/layouts/legacy.html +++ /dev/null @@ -1 +0,0 @@ -<block name="template"></block> diff --git a/test/stubs/layouts/template-legacy.html b/test/stubs/layouts/template-legacy.html deleted file mode 100644 index c356e91e..00000000 --- a/test/stubs/layouts/template-legacy.html +++ /dev/null @@ -1,5 +0,0 @@ ---- -template: base ---- - -<block name="template"></block> diff --git a/test/stubs/main.css b/test/stubs/main.css deleted file mode 100644 index 58b3c792..00000000 --- a/test/stubs/main.css +++ /dev/null @@ -1,5 +0,0 @@ -@import "tailwindcss/utilities"; - -.foo { - color: red; -} diff --git a/test/stubs/plaintext/front-matter.html b/test/stubs/plaintext/front-matter.html deleted file mode 100644 index 1677da2b..00000000 --- a/test/stubs/plaintext/front-matter.html +++ /dev/null @@ -1,9 +0,0 @@ ---- -plaintext: true ---- - -<div>Show in HTML</div> -<plaintext>Show in plaintext</plaintext> -<not-plaintext> - <table><tr><td>Remove from plaintext</td></tr></table> -</not-plaintext> diff --git a/test/stubs/plaintext/plaintext.html b/test/stubs/plaintext/plaintext.html deleted file mode 100644 index 3452ac92..00000000 --- a/test/stubs/plaintext/plaintext.html +++ /dev/null @@ -1,5 +0,0 @@ -<div>Show in HTML</div> -<plaintext>Show in plaintext</plaintext> -<not-plaintext> - <p>Do not show <a href="url">this</a> in plaintext.</p> -</not-plaintext> diff --git a/test/stubs/post.css b/test/stubs/post.css deleted file mode 100644 index 1cfd42fe..00000000 --- a/test/stubs/post.css +++ /dev/null @@ -1,6 +0,0 @@ -div { - margin-top: 1px; - margin-right: 2px; - margin-bottom: 3px; - margin-left: 4px; -} diff --git a/test/stubs/static/plain.txt b/test/stubs/static/plain.txt new file mode 100644 index 00000000..8e27be7d --- /dev/null +++ b/test/stubs/static/plain.txt @@ -0,0 +1 @@ +text diff --git a/test/stubs/style.css b/test/stubs/style.css new file mode 100644 index 00000000..f4d336fd --- /dev/null +++ b/test/stubs/style.css @@ -0,0 +1,3 @@ +.hidden { + display: none; +} diff --git a/test/stubs/tailwind/add-important.html b/test/stubs/tailwind/add-important.html deleted file mode 100644 index e999a4a7..00000000 --- a/test/stubs/tailwind/add-important.html +++ /dev/null @@ -1,6 +0,0 @@ -sm:block -hover:sm:flex -hover:opacity-50 -[&_p]:mt-4 -[@media(any-hover:hover){&:hover}]:uppercase -[border:0] diff --git a/test/stubs/tailwind/content-source.html b/test/stubs/tailwind/content-source.html deleted file mode 100644 index b734912b..00000000 --- a/test/stubs/tailwind/content-source.html +++ /dev/null @@ -1 +0,0 @@ -<div class="hidden"></div> diff --git a/test/stubs/tailwind/tailwind.css b/test/stubs/tailwind/tailwind.css deleted file mode 100644 index 5a7d3471..00000000 --- a/test/stubs/tailwind/tailwind.css +++ /dev/null @@ -1,3 +0,0 @@ -.example { - @apply hidden; -} diff --git a/test/stubs/template-legacy.html b/test/stubs/template-legacy.html deleted file mode 100644 index 54a33d5e..00000000 --- a/test/stubs/template-legacy.html +++ /dev/null @@ -1,10 +0,0 @@ ---- -template: first ---- - -<extends src="test/stubs/layouts/template-legacy.html"> - <block name="template"> - Parent - <block name="button">Child in first.html</block> - </block> -</extends> diff --git a/test/stubs/templates/1.html b/test/stubs/templates/1.html deleted file mode 100644 index d21b6f66..00000000 --- a/test/stubs/templates/1.html +++ /dev/null @@ -1 +0,0 @@ -<div class="inline">html</div> diff --git a/test/stubs/templates/2.html b/test/stubs/templates/2.html deleted file mode 100644 index 5353a77a..00000000 --- a/test/stubs/templates/2.html +++ /dev/null @@ -1 +0,0 @@ -<div class="inline">html modified</div> \ No newline at end of file diff --git a/test/stubs/templates/2.test b/test/stubs/templates/2.test deleted file mode 100644 index 30d74d25..00000000 --- a/test/stubs/templates/2.test +++ /dev/null @@ -1 +0,0 @@ -test \ No newline at end of file diff --git a/test/stubs/templates/nested/3.html b/test/stubs/templates/nested/3.html deleted file mode 100644 index 1d49a0df..00000000 --- a/test/stubs/templates/nested/3.html +++ /dev/null @@ -1 +0,0 @@ -<div class="inline">nested template</div> diff --git a/test/test-config.js b/test/test-config.js deleted file mode 100644 index 26d984d9..00000000 --- a/test/test-config.js +++ /dev/null @@ -1,24 +0,0 @@ -const test = require('ava') -const Config = require('../src/generators/config') - -test('returns the merged config', async t => { - const config = await Config.getMerged('maizzle-ci') - t.is(config.env, 'maizzle-ci') -}) - -test('throws if env name is not a string', async t => { - await t.throwsAsync(async () => { - await Config.getMerged(false) - }, {instanceOf: TypeError, message: 'env name must be a string, received boolean(false)'}) -}) - -test('throws if a config could not be loaded for the specified environment', async t => { - await t.throwsAsync(async () => { - await Config.getMerged('fake') - }, {instanceOf: Error, message: 'Failed to load config file for \`fake\` environment, do you have one of these files in your project root?\n\n./maizzle.config.fake.js\n./maizzle.config.fake.cjs\n./config.fake.js\n./config.fake.cjs'}) -}) - -test('supports maizzle.config.js file names', async t => { - const config = await Config.getMerged('test') - t.is(config.file, 'maizzle.config.test.js') -}) diff --git a/test/test-misc.js b/test/test-misc.js deleted file mode 100644 index d628e132..00000000 --- a/test/test-misc.js +++ /dev/null @@ -1,8 +0,0 @@ -const test = require('ava') -const path = require('node:path') -const h = require('../src/utils/helpers') - -test('requires an uncached module', t => { - const helpers = h.requireUncached(path.resolve(process.cwd(), 'src/utils/helpers')) - t.is(typeof helpers.requireUncached, 'function') -}) diff --git a/test/test-postcss.js b/test/test-postcss.js deleted file mode 100644 index 353b9394..00000000 --- a/test/test-postcss.js +++ /dev/null @@ -1,8 +0,0 @@ -const test = require('ava') -const PostCSS = require('../src/generators/postcss') - -test('throws on processing error', async t => { - await t.throwsAsync(async () => { - await PostCSS.process(null, {}) - }, {instanceOf: SyntaxError}) -}) diff --git a/test/test-posthtml.js b/test/test-posthtml.js deleted file mode 100644 index f114e2ee..00000000 --- a/test/test-posthtml.js +++ /dev/null @@ -1,126 +0,0 @@ -const test = require('ava') -const {render, prettify} = require('../src') - -const path = require('node:path') -const fs = require('node:fs') - -const readFile = (dir, filename) => fs.promises - .readFile(path.join(__dirname, dir, `${filename}.html`), 'utf8') - .then(html => html.trim()) - -const fixture = file => readFile('fixtures', file) -const expected = file => readFile('expected', file) - -const renderString = (string, options = {}) => render(string, options).then(({html}) => html) - -test('layouts (legacy)', async t => { - const source = `--- -greeting: Hello ---- - -<extends src="test/stubs/layouts/legacy.html"> - <block name="template"> - Front matter variable: {{ page.greeting }} - </block> -</extends>` - - const html = await renderString(source, { - maizzle: { - greeting: 'Hello' - } - }) - - t.is(html.trim(), 'Front matter variable: Hello') -}) - -test('inheritance when extending a template (legacy)', async t => { - const source = `--- -template: second ---- - -<extends src="test/stubs/template-legacy.html"> - <block name="button">Child in second.html</block> -</extends>` - - let html = await renderString(source) - - html = html.replace(/[^\S\r\n]+$/gm, '').trim() - - t.is(html, `Parent - Child in second.html`) -}) - -test('components (legacy)', async t => { - const source = await fixture('components/backwards-compatibility') - - const options = { - maizzle: { - env: 'maizzle-ci', - build: { - posthtml: { - expressions: { - delimiters: ['[[', ']]'] - } - } - } - } - } - - const html = await renderString(source, options) - - t.is(html.replace(/\n+/g, '\n').trim(), await expected('components/backwards-compatibility')) -}) - -test('fetch component', async t => { - const source = `<extends src="test/stubs/layouts/legacy.html"> - <block name="template"> - <fetch url="test/stubs/data.json"> - <each loop="user in response">[[ user.name + (loop.last ? '' : ', ') ]]</each> - </fetch> - </block> - </extends>` - - const options = { - maizzle: { - env: 'maizzle-ci', - build: { - posthtml: { - expressions: { - delimiters: ['[[', ']]'] - } - } - } - } - } - - const html = await renderString(source, options) - - t.is(html.trim(), 'Leanne Graham, Ervin Howell, Clementine Bauch') -}) - -test.serial('components', async t => { - const source = await fixture('components/kitchen-sink') - - const options = { - maizzle: { - env: 'maizzle-ci', - build: { - components: { - folders: ['test/stubs/layouts', 'test/stubs/components'] - } - } - }, - beforeRender(html, config) { - config.foo = 'bar' - - return html - } - } - - const html = await renderString(source, options) - - t.is( - await prettify(html, {ocd: true}), - await expected('components/kitchen-sink') - ) -}) diff --git a/test/test-serve.js b/test/test-serve.js deleted file mode 100644 index fc5d8cea..00000000 --- a/test/test-serve.js +++ /dev/null @@ -1,57 +0,0 @@ -const test = require('ava') -const fs = require('fs-extra') -const Maizzle = require('../src') - -test.beforeEach(t => { - t.context.folder = '_temp_' + Math.random().toString(36).slice(2, 9) - t.context.log = console.log() -}) - -test.afterEach.always(async t => { - if (t.context.folder) { - await fs.remove(t.context.folder) - t.context.folder = undefined - } -}) - -test('throws if it cannot spin up local development server', async t => { - // Should throw because there are no template sources in `build.templates` - await t.throwsAsync(async () => { - await Maizzle.serve('local', {}) - }, {instanceOf: Error}) -}) - -test('local server does not compile unwanted file types', async t => { - await Maizzle.serve('local', { - build: { - console: { - clear: true - }, - browsersync: { - ui: false - }, - templates: { - source: 'test/stubs/templates', - destination: { - path: `${t.context.folder}` - } - } - }, - events: { - beforeCreate(config) { - config.foo = 'bar' - } - } - }) - - t.true(await fs.pathExists(`${t.context.folder}`)) - t.true(await fs.pathExists(`${t.context.folder}/2.test`)) - - // Tests watching changes to files - await fs.outputFile('test/stubs/templates/2.html', '<div class="inline">html modified</div>') - t.is(await fs.readFile('test/stubs/templates/2.html', 'utf8'), '<div class="inline">html modified</div>') - - // Don't trigger rebuilds on files not in `filetypes` - await fs.outputFile('test/stubs/templates/2.test', 'test') - t.is(await fs.readFile('test/stubs/templates/2.test', 'utf8'), 'test') -}) diff --git a/test/test-tailwindcss.js b/test/test-tailwindcss.js deleted file mode 100644 index b226b697..00000000 --- a/test/test-tailwindcss.js +++ /dev/null @@ -1,206 +0,0 @@ -const test = require('ava') -const Tailwind = require('../src/generators/tailwindcss') - -test('throws on compile error', async t => { - await t.throwsAsync(async () => { - await Tailwind.compile({ - css: 'div {@apply inexistent;}', - html: '<div class="inline">Test</a>' - }) - }, {instanceOf: SyntaxError}) -}) - -test('uses defaults if no config specified', async t => { - const css = await Tailwind.compile({ - css: '@tailwind utilities;', - html: '<p class="xl:w-1"></p>' - }) - - t.not(css, undefined) - t.true(css.includes('@media (min-width: 1280px)')) -}) - -test('uses css file provided in environment config', async t => { - const config = { - build: { - tailwind: { - css: './test/stubs/main.css' - } - } - } - - const css = await Tailwind.compile({ - html: '<div class="text-center foo">test</div>', - config - }) - - t.not(css, undefined) - t.true(css.includes('.text-center')) - t.true(css.includes('.foo')) -}) - -test('works with custom `content` sources', async t => { - const css = await Tailwind.compile({ - config: { - build: { - tailwind: { - config: { - content: ['./test/stubs/tailwind/*.html'] - } - } - } - } - }) - - t.true(css.includes('.hidden')) -}) - -test('works with custom `files` sources', async t => { - const css = await Tailwind.compile({ - config: { - build: { - tailwind: { - config: { - content: { - files: ['./test/stubs/tailwind/*.html'] - } - } - } - } - } - }) - - t.true(css.includes('.hidden')) -}) - -test('uses maizzle template path as content source', async t => { - const css = await Tailwind.compile({ - config: { - build: { - templates: { - source: './test/stubs/tailwind' - } - } - } - }) - - t.true(css.includes('.hidden')) -}) - -test('uses maizzle template path as content source (single file)', async t => { - const css = await Tailwind.compile({ - config: { - build: { - templates: { - source: './test/stubs/tailwind/content-source.html' - } - } - } - }) - - t.true(css.includes('.hidden')) -}) - -test('uses custom postcss plugins from the maizzle config', async t => { - const config = { - build: { - postcss: { - plugins: [ - require('autoprefixer')({overrideBrowserslist: ['> 0.1%']}) - ] - } - } - } - - const css = await Tailwind.compile({ - css: '.test {transform: scale(0.5)}', - html: '<div class="test">Test</div>', - config - }) - - t.not(css, undefined) - t.is(css.trim(), '.test {transform: scale(0.5)}') -}) - -test('respects `shorthandCSS` in maizzle config', async t => { - const shorthandDisabled = await Tailwind.compile({ - css: '@layer utilities { .padded {@apply px-4 py-6;} }', - html: '<div class="padded">Test</div>' - }) - - const shorthandEnabled = await Tailwind.compile({ - css: '@layer utilities { .padded {@apply px-4 py-6;} }', - html: '<div class="padded">Test</div>', - config: { - shorthandCSS: true - } - }) - - t.is( - shorthandDisabled.replace(/\s+/g, '').trim(), - '.padded{padding-left:1rem;padding-right:1rem;padding-top:1.5rem;padding-bottom:1.5rem}' - ) - - t.is( - shorthandEnabled.replace(/\s+/g, '').trim(), - '.padded{padding:1.5rem1rem}' - ) -}) - -test('works with custom `layouts.root`', async t => { - const css = await Tailwind.compile({ - config: { - build: { - layouts: { - root: './test/stubs/layouts' - }, - tailwind: { - config: { - content: ['./test/stubs/tailwind/*.html'] - } - } - } - } - }) - - t.true(css.includes('.bg-red-500')) -}) - -test('adds `!important` to selectors that will not be inlined', async t => { - const css = await Tailwind.compile({ - config: { - build: { - tailwind: { - config: { - content: ['./test/stubs/tailwind/*.html'] - } - } - } - } - }) - - t.true(css.includes('display: block !important')) - t.true(css.includes('display: flex !important')) - t.true(css.includes('opacity: 0.5 !important')) - t.true(css.includes('margin-top: 1rem !important')) - t.true(css.includes('text-transform: uppercase !important')) - - t.false(css.includes('border: 0 !important')) -}) - -test('respects `important: false` from tailwind config', async t => { - const css = await Tailwind.compile({ - config: { - build: { - tailwind: { - config: { - important: false, - content: ['./test/stubs/tailwind/*.html'] - } - } - } - } - }) - - t.false(css.includes('display: block !important')) -}) diff --git a/test/test-todisk.js b/test/test-todisk.js deleted file mode 100644 index 172f4d61..00000000 --- a/test/test-todisk.js +++ /dev/null @@ -1,660 +0,0 @@ -const test = require('ava') -const fs = require('fs-extra') -const Maizzle = require('../src') - -test.beforeEach(t => { - t.context.folder = '_temp_' + Math.random().toString(36).slice(2, 9) - t.context.log = console.log() -}) - -test.afterEach.always(async t => { - if (t.context.folder) { - await fs.remove(t.context.folder) - t.context.folder = undefined - } -}) - -test('throws if config cannot be computed', async t => { - await t.throwsAsync(async () => { - await Maizzle.build('missing') - }, {instanceOf: Error}) -}) - -test('throws if a template cannot be rendered', async t => { - await t.throwsAsync(async () => { - await Maizzle.build('maizzle-ci', { - build: { - templates: { - source: 'test/stubs/breaking', - destination: { - path: t.context.folder - } - } - } - }) - }, {instanceOf: Error}) -}) - -test('skips if no templates found', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - filetypes: 'fake', - destination: { - path: t.context.folder - } - } - } - }) - - t.is(files.length, 0) -}) - -test('outputs files at the correct location', async t => { - const {files: stringSource} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - filetypes: 'html|test', - destination: { - path: t.context.folder - } - } - } - }) - - // `filetypes` will default to `html` if not set - const {files: arraySource} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: ['test/stubs/templates'], - destination: { - path: t.context.folder - } - } - } - }) - - t.true(await fs.pathExists(t.context.folder)) - t.is(stringSource.length, 4) - t.is(arraySource.length, 4) -}) - -test('outputs files at the correct location if multiple template sources are used', async t => { - const {files} = await Maizzle.build('local', { - build: { - fail: 'silent', - templates: [ - { - source: 'test/stubs/templates', - destination: { - path: t.context.folder - } - }, - { - source: 'test/stubs/plaintext', - destination: { - path: t.context.folder - } - } - ] - } - }) - - t.true(await fs.pathExists(t.context.folder)) - t.is(files.length, 7) -}) - -test('copies all files in the `filetypes` option to destination', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - filetypes: ['html', 'test'], - destination: { - path: t.context.folder - } - } - } - }) - - t.true(await fs.pathExists(t.context.folder)) - t.is(files.length, 4) -}) - -test('outputs files with the correct extension', async t => { - await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - destination: { - path: t.context.folder, - extension: 'blade.php' - } - } - } - }) - - const filelist = await fs.readdir(t.context.folder) - - t.true(filelist.includes('1.blade.php')) -}) - -test('outputs plaintext files', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - fail: 'silent', - build: { - templates: { - source: 'test/stubs/plaintext', - destination: { - path: t.context.folder - }, - plaintext: true - } - }, - extraAttributes: false - }) - - t.true(files.includes(`${t.context.folder}/plaintext.txt`)) - - t.is( - await fs.readFile(`${t.context.folder}/plaintext.txt`, 'utf8'), - 'Show in HTML\nShow in plaintext' - ) - - t.is( - await fs.readFile(`${t.context.folder}/plaintext.html`, 'utf8'), - '<div>Show in HTML</div>\n\n\n <p>Do not show <a href="url">this</a> in plaintext.</p>\n\n' - ) -}) - -test('outputs plaintext files (front matter)', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - fail: 'silent', - build: { - templates: { - source: 'test/stubs/plaintext', - destination: { - path: t.context.folder - } - } - }, - extraAttributes: false - }) - - t.true(files.includes(`${t.context.folder}/front-matter.txt`)) - - t.is( - await fs.readFile(`${t.context.folder}/front-matter.txt`, 'utf8'), - 'Show in HTML\nShow in plaintext' - ) - - t.is( - await fs.readFile(`${t.context.folder}/front-matter.html`, 'utf8'), - '<div>Show in HTML</div>\n\n\n <table><tr><td>Remove from plaintext</td></tr></table>\n\n' - ) -}) - -test('outputs plaintext files (custom path)', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - fail: 'silent', - build: { - templates: { - source: 'test/stubs/plaintext', - destination: { - path: t.context.folder - }, - plaintext: { - destination: { - path: `${t.context.folder}/nested/plain.text` - } - } - } - } - }) - - t.true(files.includes(`${t.context.folder}/nested/plain.text`)) -}) - -test('renders plaintext string', async t => { - const html = await fs.readFile('test/stubs/plaintext/plaintext.html', 'utf8') - const {plaintext} = await Maizzle.plaintext(html) - - t.is(plaintext, 'Show in HTML\nShow in plaintext') -}) - -test('copies assets to destination', async t => { - await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - destination: { - path: t.context.folder - }, - assets: { - source: 'test/stubs/assets', - destination: 'images' - } - } - } - }) - - const filelist = await fs.readdir(`${t.context.folder}/images`) - - t.is(await fs.pathExists(`${t.context.folder}/images`), true) - t.is(filelist.length, 1) -}) - -test('copies assets array to destinations', async t => { - await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - destination: { - path: t.context.folder - }, - assets: [ - { - source: 'test/stubs/assets', - destination: 'assets/images1' - }, - { - source: 'test/stubs/assets2', - destination: 'assets/images2' - } - ] - } - } - }) - - const images1 = await fs.readdir(`${t.context.folder}/assets/images1`) - t.is(await fs.pathExists(`${t.context.folder}/assets/images1`), true) - t.true(images1.includes('foo.bar')) - - const images2 = await fs.readdir(`${t.context.folder}/assets/images2`) - t.is(await fs.pathExists(`${t.context.folder}/assets/images2`), true) - t.true(images2.includes('foo1.bar')) - t.true(images2.includes('foo2.bar')) -}) - -test('runs the `beforeCreate` event', async t => { - await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/events', - destination: { - path: t.context.folder - } - } - }, - events: { - beforeCreate(config) { - config.foo = 'bar' - } - } - }) - - const filename = await fs.readdir(t.context.folder) - const html = await fs.readFile(`${t.context.folder}/${filename[0]}`, 'utf8') - - t.is(html.trim(), '<div class="inline">Foo is bar</div>') -}) - -test('runs the `afterBuild` event', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - destination: { - path: t.context.folder - } - } - }, - events: { - afterBuild(files) { - t.context.afterBuild = files - } - } - }) - - const getIntersection = (a, ...array) => [...new Set(a)].filter(v => array.every(b => b.includes(v))) - - t.deepEqual(getIntersection(t.context.afterBuild, files), files) -}) - -test('supports multiple asset paths', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - destination: { - path: t.context.folder - }, - assets: { - source: ['test/stubs/assets', 'test/stubs/plaintext', 'test/stubs/invalid'], - destination: 'extras' - } - } - } - }) - - t.true(files.includes(`${t.context.folder}/extras/foo.bar`)) - t.true(files.includes(`${t.context.folder}/extras/plaintext.html`)) - t.false(files.includes(`${t.context.folder}/extras/invalid`)) -}) - -test('supports multiple assets array paths', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - destination: { - path: t.context.folder - }, - assets: [ - { - source: ['test/stubs/plaintext', 'test/stubs/invalid'], - destination: 'extras' - }, - { - source: ['test/stubs/assets'], - destination: 'assets/images1' - }, - { - source: ['test/stubs/assets2'], - destination: 'assets/images2' - } - ] - } - } - }) - - t.true(files.includes(`${t.context.folder}/extras/plaintext.html`)) - t.false(files.includes(`${t.context.folder}/extras/invalid`)) - - t.true(files.includes(`${t.context.folder}/assets/images1/foo.bar`)) - - t.true(files.includes(`${t.context.folder}/assets/images2/foo1.bar`)) - t.true(files.includes(`${t.context.folder}/assets/images2/foo2.bar`)) -}) - -test('supports multiple assets array paths with templates array', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: [ - { - source: 'test/stubs/plaintext', - destination: { - path: t.context.folder - }, - assets: [ - { - source: ['test/stubs/invalid', 'test/stubs/assets'], - destination: 'assets/extras1' - }, - { - source: ['test/stubs/assets2'], - destination: 'assets/extras2' - } - ] - }, - { - source: 'test/stubs/templates', - destination: { - path: t.context.folder - }, - assets: [ - { - source: ['test/stubs/invalid', 'test/stubs/assets'], - destination: 'assets/extras3' - }, - { - source: ['test/stubs/assets2'], - destination: 'assets/extras4' - } - ] - } - ] - } - }) - - t.false(files.includes(`${t.context.folder}/assets/extras1/invalid`)) - t.true(files.includes(`${t.context.folder}/assets/extras1/foo.bar`)) - - t.true(files.includes(`${t.context.folder}/assets/extras2/foo1.bar`)) - t.true(files.includes(`${t.context.folder}/assets/extras2/foo2.bar`)) - - t.false(files.includes(`${t.context.folder}/assets/extras3/invalid`)) - t.true(files.includes(`${t.context.folder}/assets/extras3/foo.bar`)) - - t.true(files.includes(`${t.context.folder}/assets/extras4/foo1.bar`)) - t.true(files.includes(`${t.context.folder}/assets/extras4/foo2.bar`)) -}) - -test('warns if a template cannot be rendered and `fail` option is `verbose`', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'verbose', - templates: { - source: 'test/stubs/breaking', - destination: { - path: t.context.folder - } - } - } - }) - - t.false(files.includes('empty.html')) -}) - -test('warns if a template cannot be rendered and `fail` option is `silent`', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/breaking', - destination: { - path: t.context.folder - } - } - } - }) - - t.false(files.includes('empty.html')) -}) - -test('throws if `templates.source` is undefined', async t => { - await t.throwsAsync(async () => { - await Maizzle.build('maizzle-ci') - }, {instanceOf: Error}) -}) - -test('`templates.source` defined as function (string paths)', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: () => 'test/stubs/templates', - destination: { - path: t.context.folder - } - } - } - }) - - t.is(files.length, 4) -}) - -test('`templates.source` defined as function (array paths)', async t => { - const {files} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - customSources: ['test/stubs/templates', 'test/stubs/templates'], - templates: { - source: config => { - return config.build.customSources - }, - destination: { - path: t.context.folder - } - } - } - }) - - t.is(files.length, 4) -}) - -test('throws if templates path is invalid', async t => { - await t.throwsAsync(async () => { - await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: false, - destination: { - path: t.context.folder - } - } - } - }) - }, {instanceOf: TypeError}) -}) - -test('throws if templates path is invalid (function)', async t => { - await t.throwsAsync(async () => { - await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: () => {}, - destination: { - path: t.context.folder - } - } - } - }) - }, {instanceOf: TypeError}) -}) - -test('sets config.build.current.path', async t => { - await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - destination: { - path: t.context.folder - } - } - }, - events: { - beforeRender(html, config) { - t.context.current = config.build.current - - return html - } - } - }) - - t.deepEqual(t.context.current, { - path: { - root: '', - dir: `${t.context.folder}/nested`, - base: '3.html', - ext: '.html', - name: '3' - } - }) -}) - -test('skips compiling templates', async t => { - let parsedFilesFromStringSource = 0 - await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - skip: '1.html', - destination: { - path: t.context.folder - } - } - }, - // Increment counter for each file that was actually parsed - events: { - afterRender(html) { - parsedFilesFromStringSource++ - - return html - } - } - }) - - let parsedFilesFromArraySource = 0 - await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: ['test/stubs/templates'], - skip: ['1.html', 'nested/3.html'], - destination: { - path: t.context.folder - } - } - }, - events: { - afterRender(html) { - parsedFilesFromArraySource++ - - return html - } - } - }) - - t.is(parsedFilesFromStringSource, 2) - t.is(parsedFilesFromArraySource, 1) -}) - -test('does not output omitted files', async t => { - const {files: fromStringSource} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: 'test/stubs/templates', - omit: '1.html', - destination: { - path: t.context.folder - } - } - } - }) - - const {files: fromArraySource} = await Maizzle.build('maizzle-ci', { - build: { - fail: 'silent', - templates: { - source: ['test/stubs/templates'], - omit: ['1.html', 'nested/3.html'], - destination: { - path: t.context.folder - } - } - } - }) - - t.is(fromStringSource.length, 3) - t.is(fromArraySource.length, 2) -}) diff --git a/test/test-tostring.js b/test/test-tostring.js deleted file mode 100644 index d145e381..00000000 --- a/test/test-tostring.js +++ /dev/null @@ -1,165 +0,0 @@ -const test = require('ava') -const Maizzle = require('../src') - -const renderString = (string, options = {}) => Maizzle.render(string, options).then(({html}) => html) - -test('uses environment config file(s) if available', async t => { - const source = `<div class="inline">{{ page.mail }}</div>` - - const html = await renderString(source, { - maizzle: { - mail: 'puzzle' - } - }) - - t.is(html, '<div class="inline">puzzle</div>') -}) - -test('throws if first argument is not an HTML string', async t => { - await t.throwsAsync(async () => { - await renderString() - }, {instanceOf: TypeError, message: 'first argument must be an HTML string, received undefined'}) -}) - -test('throws if first argument is an empty string', async t => { - await t.throwsAsync(async () => { - await renderString('') - }, {instanceOf: RangeError, message: 'received empty string'}) -}) - -test('runs the `beforeRender` event', async t => { - const html = await renderString(`<div class="inline">{{ page.foo }}</div>`, { - beforeRender(html, config) { - config.foo = 'bar' - - return html - } - }) - - t.is(html, `<div class="inline">bar</div>`) -}) - -test('runs the `afterRender` event', async t => { - const result = await renderString(`<div class="inline">foo</div>`, { - afterRender(html, config) { - config.replaceStrings = { - foo: 'baz' - } - - return html - } - }) - - t.is(result, `<div class="inline">baz</div>`) -}) - -test('runs the `afterTransformers` event', async t => { - const result = await renderString(`<div class="inline">foo</div>`, { - maizzle: { - title: 'bar' - }, - afterTransformers(html, config) { - return html.replace('foo', config.title) - } - }) - - t.is(result, '<div class="inline">bar</div>') -}) - -test('locals work when defined in all supported places', async t => { - const result = await renderString('{{ page.one }}, {{ two }}, {{ three }}, {{ inline }}', { - maizzle: { - one: 1, - build: { - posthtml: { - expressions: { - locals: { - two: 2 - } - } - } - }, - locals: { - three: 3 - } - } - }) - - t.is(result, '1, 2, 3, undefined') -}) - -test.serial('prevents overwriting page object', async t => { - const result = await renderString('{{ page.one }}, {{ page.two }}, {{ page.three }}, {{ inline }}', { - maizzle: { - one: 1, - build: { - posthtml: { - expressions: { - locals: { - page: { - two: 2 - } - } - } - } - }, - locals: { - page: { - three: 3 - } - } - } - }) - - t.is(result, '1, 2, 3, undefined') -}) - -test('preserves css in marked style tags (tailwindcss)', async t => { - const source = `<html> - <head> - <style tailwindcss preserve> - div { - @apply uppercase; - } - [data-ogsc] .inexistent { - color: #ef4444; - } - div > u + .body .gmail-android-block { - display: block !important; - } - u + #body a { - color: inherit; - } - </style> - </head> - <body> - <div>test</div> - </body> - </html>` - - const html = await renderString(source, { - maizzle: { - removeUnusedCSS: true - }, - // So that we don't compile twice - tailwind: { - compiled: '' - } - }) - - t.true(html.replace(/[\n\s\r]+/g, '').includes('div{text-transform:uppercase')) - t.true(html.includes('div > u + .body .gmail-android-block')) - t.true(html.includes('[data-ogsc] .inexistent')) - t.true(html.includes('u + #body a')) -}) - -test('@import css files in marked style tags', async t => { - const source = '<style postcss>@import "test/stubs/post.css";</style>' - const html = await renderString(source, { - maizzle: { - shorthandCSS: true - } - }) - - t.is(html.replace(/\n {2,}/g, ''), '<style>div {margin: 1px 2px 3px 4px;\n}</style>') -}) diff --git a/test/test-transformers.js b/test/test-transformers.js deleted file mode 100644 index 5e23a2c4..00000000 --- a/test/test-transformers.js +++ /dev/null @@ -1,664 +0,0 @@ -const test = require('ava') -const Maizzle = require('../src') - -const fs = require('node:fs') -const path = require('node:path') - -const readFile = (dir, filename) => fs.promises - .readFile(path.join(__dirname, dir, `${filename}.html`), 'utf8') - .then(html => html.trim()) - -const fixture = file => readFile('fixtures/transformers', file) -const expected = file => readFile('expected/transformers', file) - -test('remove inline sizes', async t => { - const options = { - width: ['table'], - height: ['td'] - } - - const html = await Maizzle.removeInlineSizes(` - <table style="width: 10px; height: auto;"> - <tr> - <td style="width: 100%; height: 10px;">test</td> - </tr> - </table>`, - options) - - t.is(html, ` - <table style="height: auto"> - <tr> - <td style="width: 100%">test</td> - </tr> - </table>`) -}) - -test('remove inline background-color', async t => { - const html = await Maizzle.removeInlineBgColor(`<td style="background-color: red" bgcolor="red">test</td>`) - const html2 = await Maizzle.removeInlineBgColor( - `<td style="background-color: red" bgcolor="red">test</td>`, - { - inlineCSS: { - preferBgColorAttribute: true - } - } - ) - - t.is(html, '<td style="" bgcolor="red">test</td>') - t.is(html2, '<td style="" bgcolor="red">test</td>') -}) - -test('remove inline background-color (with tags)', async t => { - const html = await Maizzle.removeInlineBgColor( - `<table style="background-color: red"><tr><td style="background-color: red">test</td></tr></table>`, - ['table'] - ) - - t.is(html, '<table style="" bgcolor="red"><tr><td style="background-color: red">test</td></tr></table>') -}) - -test('inline CSS', async t => { - const html = ` - <table class="w-1 h-1 text-center"> - <tr> - <td class="foo bar h-1">test</td> - </tr> - </table>` - const css = ` - .w-1 {width: 4px} - .h-1 {height: 4px} - .foo {color: red} - .bar {cursor: pointer} - .text-center {text-align: center} - ` - - const html2 = ` - <html> - <head> - <style>${css}</style> - </head> - <body> - <table class="w-1 h-1 text-center"> - <tr> - <td class="foo bar h-1">test</td> - </tr> - </table> - </body> - </html>` - - const result1 = await Maizzle.inlineCSS(html, { - customCSS: css, - removeStyleTags: false, - styleToAttribute: { - 'text-align': 'align' - }, - applyWidthAttributes: ['table'], - applyHeightAttributes: ['td'], - mergeLonghand: ['div'], - excludedProperties: ['cursor'], - codeBlocks: { - RB: { - start: '<%', - end: '%>' - } - } - }) - const result2 = await Maizzle.inlineCSS(html2, { - removeStyleTags: false, - styleToAttribute: { - 'text-align': 'align' - }, - applyWidthAttributes: ['table'], - applyHeightAttributes: ['td'], - mergeLonghand: ['div'], - excludedProperties: ['cursor'], - codeBlocks: { - RB: { - start: '<%', - end: '%>' - } - } - }) - - t.is(result1, ` - <table class="w-1 h-1 text-center" style="width: 4px; height: 4px; text-align: center;" width="4" align="center"> - <tr> - <td class="foo bar h-1" style="height: 4px; color: red;" height="4">test</td> - </tr> - </table>`) - - t.is(result2, ` - <html> - <head> - <style> - .w-1 {width: 4px} - .h-1 {height: 4px} - .foo {color: red} - .bar {cursor: pointer} - .text-center {text-align: center} - </style> - </head> - <body> - <table class="w-1 h-1 text-center" style="width: 4px; height: 4px; text-align: center;" width="4" align="center"> - <tr> - <td class="foo bar h-1" style="height: 4px; color: red;" height="4">test</td> - </tr> - </table> - </body> - </html>`) -}) - -test('inline CSS (disabled)', async t => { - const html = '<div class="foo">test</div>' - const css = '.foo {color: red}' - - const result = await Maizzle.inlineCSS(html, {inlineCSS: false, customCSS: css}) - - t.is(result, '<div class="foo">test</div>') -}) - -test('remove unused CSS', async t => { - const html = `<!DOCTYPE html> - <html> - <head> - <style> - @media (screen) { - .should-remove {color: yellow} - } - .foo {color: red} - .foo:hover {color: blue} - .bar-baz {color: blue} - .should-remove {color: white} - </style> - </head> - <body> - <div class="foo {{ test }}">test div with some text</div> - </body> - </html>` - - const withOptionsResult = `<!DOCTYPE html> - <html> - <head> - <style> - .foo {color: red} - .foo:hover {color: blue} - .bar-baz {color: blue} - </style> - </head> - <body> - <div class="foo {{ test }}">test div with some text</div> - </body> - </html>` - - const disabled = await Maizzle.removeUnusedCSS(html) - const withOptions = await Maizzle.removeUnusedCSS(html, {whitelist: ['.bar*']}) - - t.is(disabled, html) - t.is(withOptions, withOptionsResult) -}) - -test('remove attributes', async t => { - const html = await Maizzle.removeAttributes( - `<div style="" remove keep role="article" delete-me="with-regex"></div>`, - [ - {name: 'role', value: 'article'}, - 'remove', - {name: 'delete-me', value: /^with/} - ] - ) - - t.is(html, '<div keep></div>') -}) - -test('extra attributes', async t => { - const html = await Maizzle.applyExtraAttributes('<div />', {div: {role: 'article'}}) - - t.is(html, '<div role="article"></div>') -}) - -test('extra attributes (disabled)', async t => { - const html = await Maizzle.applyExtraAttributes('<img src="example.jpg">', {extraAttributes: false}) - - t.is(html, '<img src="example.jpg">') -}) - -test('base URL (string)', async t => { - const source = await fixture('base-url') - const html = await Maizzle.applyBaseUrl(source, 'https://example.com/') - - t.is(html, await expected('base-url')) -}) - -test('base URL (object)', async t => { - const source = await fixture('base-url') - const html = await Maizzle.applyBaseUrl(source, { - url: 'https://example.com/', - allTags: true - }) - - t.is(html, await expected('base-url')) -}) - -test('prettify', async t => { - // `prettify: true` - const html2 = await Maizzle.prettify('<div><p>test</p></div>', true) - - // With custom object config - // eslint-disable-next-line - const html = await Maizzle.prettify('<div><p>test</p></div>', {indent_inner_result: true}) - - // No config - const html3 = await Maizzle.prettify('<div><p>test</p></div>') - - // Empty object config - const html4 = await Maizzle.prettify('<div><p>test</p></div>', {}) - - t.is(html, '<div>\n <p>test</p>\n</div>') - t.is(html2, '<div>\n <p>test</p>\n</div>') - t.is(html3, '<div><p>test</p></div>') - t.is(html4, '<div><p>test</p></div>') -}) - -test('minify', async t => { - const html = await Maizzle.minify('<div>\n\n<p>\n\ntest</p></div>', {lineLengthLimit: 10}) - - t.is(html, '<div><p>\ntest</p>\n</div>') -}) - -test('minify (disabled)', async t => { - const html = await Maizzle.minify('<div>\n\n<p>\n\ntest</p></div>', {minify: false}) - - t.is(html, '<div>\n\n<p>\n\ntest</p></div>') -}) - -test('replace strings', async t => { - const html = await Maizzle.replaceStrings('initial text', {initial: 'updated'}) - - t.is(html, 'updated text') -}) - -test('safe class names', async t => { - const html = await Maizzle.safeClassNames('<div class="sm:text-left w-1.5">foo</div>', {'.': '_dot_'}) - - t.is(html, '<div class="sm-text-left w-1_dot_5">foo</div>') -}) - -test('safe class names (disabled)', async t => { - const html = await Maizzle.safeClassNames('<div class="sm:text-left">foo</div>') - - t.is(html, '<div class="sm:text-left">foo</div>') -}) - -test('six digit hex', async t => { - const html = await Maizzle.ensureSixHEX( - ` -<div bgcolor="#000" style="color: #fff; background-color: #000">This should not change: #ffc</div> -<font color="#fff">Text</font> - `) - - t.is( - html.trim(), - ` -<div bgcolor="#000000" style="color: #fff; background-color: #000">This should not change: #ffc</div> -<font color="#ffffff">Text</font> - `.trim() - ) -}) - -test('six digit hex (disabled)', async t => { - const html = await Maizzle.ensureSixHEX('<td style="color: #ffc" bgcolor="#000"></td>', {sixHex: false}) - - t.is(html, '<td style="color: #ffc" bgcolor="#000"></td>') -}) - -test('filters (default)', async t => { - const source = await fixture('filters') - const html = await Maizzle.withFilters(source) - - t.is(html, await expected('filters')) -}) - -test('filters (disabled)', async t => { - const html = await Maizzle.withFilters('<p uppercase>test</p>', {filters: false}) - - t.is(html, '<p uppercase>test</p>') -}) - -test('filters (tailwindcss)', async t => { - const html = await Maizzle.withFilters( - `<style tailwindcss> - div { - @apply hidden; - } - </style>` - ) - - t.true(html.replace(/\s/g, '').includes('div{display:none}')) -}) - -test('filters (postcss)', async t => { - const html = await Maizzle.withFilters( - `<style postcss> - div { - margin-top: 1px; - margin-right: 2px; - margin-bottom: 3px; - margin-left: 4px; - } - </style>`, - { - shorthandCSS: true - } - ) - - t.is(html.replace(/\n {2,}/g, ''), '<style>div {margin: 1px 2px 3px 4px;}</style>') -}) - -test('url parameters', async t => { - const simple = await Maizzle.addURLParams( - `<a href="https://example.com">test</a> - <link href="https://foo.bar">`, - { - bar: 'baz', - qix: 'qux' - } - ) - - const withOptions = await Maizzle.addURLParams( - `<a href="example.com">test</a> - <link href="https://foo.bar">`, - { - _options: { - tags: ['a[href*="example"]'], - strict: false, - qs: { - encode: true - } - }, - foo: '@Bar@', - bar: 'baz' - } - ) - - t.is(simple, `<a href="https://example.com?bar=baz&qix=qux">test</a> - <link href="https://foo.bar">`) - - t.is(withOptions, `<a href="example.com?bar=baz&foo=%40Bar%40">test</a> - <link href="https://foo.bar">`) -}) - -test('attribute to style', async t => { - const html = `<table width="100%" height="600" align="left" bgcolor="#FFFFFF" background="https://example.com/image.jpg"> - <tr> - <td align="center" valign="top"></td> - </tr> - </table>` - - const expected = `<table width="100%" height="600" align="left" bgcolor="#FFFFFF" background="https://example.com/image.jpg" style="width: 100%; height: 600px; float: left; background-color: #FFFFFF; background-image: url('https://example.com/image.jpg')"> - <tr style> - <td align="center" valign="top" style="text-align: center; vertical-align: top"></td> - </tr> - </table>` - - const html2 = `<table align="center"> - <tr> - <td></td> - </tr> - </table>` - - const expected2 = `<table align="center" style="margin-left: auto; margin-right: auto"> - <tr style> - <td style></td> - </tr> - </table>` - - const withArray = await Maizzle.attributeToStyle(html, ['width', 'height', 'bgcolor', 'background', 'align', 'valign']) - const withOptionBoolean = await Maizzle.attributeToStyle(html2, {inlineCSS: {attributeToStyle: true}}) - const withOptionArray = await Maizzle.attributeToStyle(html2, {inlineCSS: {attributeToStyle: ['align']}}) - - t.is(withArray, expected) - t.is(withOptionBoolean, expected2) - t.is(withOptionArray, expected2) -}) - -test('prevent widows', async t => { - const html = await Maizzle.preventWidows(` - <!--[if mso]> - <p>A paragraph inside an Outlook MSO comment</p> - <![endif]--> - <div>Text following an MSO comment</div> - `) - - t.is(html, ` - <!--[if mso]> - <p>A paragraph inside an Outlook MSO&nbsp;comment</p> - <![endif]--> - <div>Text following an MSO&nbsp;comment</div> - `) -}) - -test('prevent widows (with options)', async t => { - const html = await Maizzle.preventWidows(` - <div no-widows> - <p>Text following an MSO comment</p> - <!--[if mso 15]> - <p>A paragraph inside an Outlook MSO comment</p> - <p>unescaped {{{ foo }}}</p> - <![endif]--> - <p>expression {{ foo }}</p> - <!--[if !mso]><!--> - <div>All Outlooks will ignore this</div> - <!--<![endif]--> - <p>unescaped {{{ foo }}}</p> - </div> - <p>Should not remove widows here</p> - `, { - attrName: 'no-widows', - minWordCount: 3, - ignore: [ - { - heads: 'foo', - tails: 'bar' - } - ] - }) - - t.is(html, ` - <div> - <p>Text following an MSO&nbsp;comment</p> - <!--[if mso 15]> - <p>A paragraph inside an Outlook MSO&nbsp;comment</p> - <p>unescaped {{{ foo }}}</p> - <![endif]--> - <p>expression {{ foo }}</p> - <!--[if !mso]><!--> - <div>All Outlooks will ignore this</div> - <!--<![endif]--> - <p>unescaped {{{ foo }}}</p> - </div> - <p>Should not remove widows here</p> - `) -}) - -test('markdown (disabled)', async t => { - const html = await Maizzle.markdown('> a quote', {markdown: false}) - - t.is(html, '> a quote') -}) - -test('remove inlined selectors', async t => { - const html = `<!DOCTYPE html> - <html> - <head> - <style> - img { - border: 0; - vertical-align: middle - } - .hover-text-blue:hover { - color: #00a8ff; - } - - .padded { - padding: 0 20px; - } - - [data-ogsc] .hidden {display: none} - - #keepId {float:none} - - .foo-class { - /* COMMENT */ - color: red; - } - - .ignore { - display: inline-block; - } - - @media (max-width: 600px) { - .ignore {color: blue} - } - </style> - <style> - .keep {margin: 0} - </style> - </head> - <body> - <div no-value id="keepId" class="keep ignore foo-class" style="color: red; display: inline"> - <h1 class="padded hover-text-blue" style="padding: 0 20px">Title</h1> - <img src="https://example.com/image.jpg" style="border: 0; vertical-align: middle"> - <div id="keepId" class="keep ignore" style="color: red; display: inline">text</div> - </div> - </body> - </html>` - - const expectedHTML = `<!DOCTYPE html> - <html> - <head> - <style>.hover-text-blue:hover { - color: #00a8ff; - } - - [data-ogsc] .hidden {display: none} - - #keepId {float:none} - - .foo-class { - /* COMMENT */ - color: red; - } - - @media (max-width: 600px) { - .ignore {color: blue} - }</style> - <style>.keep {margin: 0}</style> - </head> - <body> - <div no-value id="keepId" class="keep ignore foo-class" style="color: red; display: inline"> - <h1 class="hover-text-blue" style="padding: 0 20px">Title</h1> - <img src="https://example.com/image.jpg" style="border: 0; vertical-align: middle"> - <div id="keepId" class="keep ignore" style="color: red; display: inline">text</div> - </div> - </body> - </html>` - - const html2 = `<!DOCTYPE html> - <html> - <head><style> - img { - border: 0; - vertical-align: middle - } - </style></head> - <body> - <img src="https://example.com/image.jpg" style="border: 0; vertical-align: middle"> - </body> - </html>` - - const expectedNoEmptyStyleTags = `<!DOCTYPE html> - <html> - <head></head> - <body> - <img src="https://example.com/image.jpg" style="border: 0; vertical-align: middle"> - </body> - </html>` - - const safelisted = `<!DOCTYPE html> - <html> - <head><style>.preserve-me { - color: red; - }</style></head> - <body> - <div class="preserve-me" style="color: red"></div> - </body> - </html>` - - const basic = await Maizzle.removeInlinedClasses(html) - const noEmptyStyle = await Maizzle.removeInlinedClasses(html2) - const safelistedHTML = await Maizzle.removeInlinedClasses(safelisted, {whitelist: ['.preserve-me']}) - - const withPostHTMLOptions = await Maizzle.removeInlinedClasses(html, { - build: { - posthtml: { - options: { - recognizeNoValueAttribute: true - } - } - } - }) - - t.is(basic, expectedHTML) - t.is(withPostHTMLOptions, expectedHTML) - t.is(noEmptyStyle, expectedNoEmptyStyleTags) - t.is(safelistedHTML, safelisted) -}) - -test('remove inlined selectors (disabled)', async t => { - const html = `<!DOCTYPE html> - <html> - <head> - <style> - .remove {color: red} - </style> - </head> - <body> - <div class="remove" style="color: red"></div> - </body> - </html>` - - const withRemoveUnusedCSS = await Maizzle.removeUnusedCSS(html, {removeInlinedSelectors: false}) - const withRemoveInlinedSelectors = await Maizzle.removeInlinedClasses(html, {removeInlinedSelectors: false}) - - t.is(withRemoveUnusedCSS, html) - t.is(withRemoveInlinedSelectors, html) -}) - -test('shorthand inline css', async t => { - const html = ` - <div style="padding-left: 2px; padding-right: 2px; padding-top: 2px; padding-bottom: 2px;">padding</div> - <div style="margin-left: 2px; margin-right: 2px; margin-top: 2px; margin-bottom: 2px;">margin</div> - <div style="border-width: 1px; border-style: solid; border-color: #000;">border</div> - <p style="border-width: 1px; border-style: solid; border-color: #000;">border</p> - ` - - const expect = ` - <div style="padding: 2px;">padding</div> - <div style="margin: 2px;">margin</div> - <div style="border: 1px solid #000;">border</div> - <p style="border: 1px solid #000;">border</p> - ` - - const expect2 = ` - <div style="padding: 2px;">padding</div> - <div style="margin: 2px;">margin</div> - <div style="border: 1px solid #000;">border</div> - <p style="border-width: 1px; border-style: solid; border-color: #000;">border</p> - ` - - const result = await Maizzle.shorthandInlineCSS(html) - const result2 = await Maizzle.shorthandInlineCSS(html, {tags: ['div']}) - - t.is(result, expect) - t.is(result2, expect2) -}) diff --git a/test/transformers.test.js b/test/transformers.test.js new file mode 100644 index 00000000..4c6a4685 --- /dev/null +++ b/test/transformers.test.js @@ -0,0 +1,573 @@ +import { describe, expect, test } from 'vitest' +import { readFile } from 'node:fs/promises' +import { + addAttributes, + attributeToStyle, + addBaseUrl, + purgeCSS, + filters, + inlineCSS , + markdown, + minify, + useMso, + prettify, + removeAttributes, + replaceStrings, + safeClassNames, + shorthandCSS, + sixHEX, + addURLParams, + useAttributeSizes, + preventWidows +} from '../src/index.js' +import { run as useTransformers } from '../src/transformers/index.js' + +describe.concurrent('Transformers', () => { + test('Core', async () => { + // Removes <plaintext> tag in local dev + const removesPlaintextTag = await useTransformers( + 'keep<plaintext>remove</plaintext>', + { _dev: true } + ) + + expect(removesPlaintextTag.html).toBe('keep') + }) + + test('Safe class names', async () => { + const html = ` + <style> + .sm\\:text-left { + text-align: left; + } + .w-1\\.5 { + width: 1.5rem; + } + </style> + <div class="sm:text-left w-1.5">foo</div> + ` + + const result = await safeClassNames(html, { + replacements: { + '.': '_dot_', + } + }) + + const withBooleanOptions = await safeClassNames(html, true) + + const withPostHTML = await useTransformers(html, { + css: { + safeClassNames: { + replacements: { + '.': '_dot_', + } + } + } + }).then(({ html }) => html) + + const expected = `<style> + .sm-text-left { + text-align: left; + } + .w-1_dot_5 { + width: 1.5rem; + } + </style> + <div class="sm-text-left w-1_dot_5">foo</div>` + + expect(result.trim()).toBe(expected) + expect(withPostHTML.trim()).toBe(expected) + + expect(withBooleanOptions).toBe(` + <style> + .sm-text-left { + text-align: left; + } + .w-1_5 { + width: 1.5rem; + } + </style> + <div class="sm-text-left w-1_5">foo</div> + `) + }) + + test('Filters', async () => { + const fixture = await readFile(new URL('fixtures/filters.html', import.meta.url), 'utf8') + const expected = await readFile(new URL('expected/filters.html', import.meta.url), 'utf8') + const customFilters = { + 'underscore-case': string => string.split('').join('_'), + } + + const result = await filters(fixture, customFilters) + + expect(result).toBe(expected) + expect( + await useTransformers(fixture, { filters: customFilters }).then(({ html }) => html) + ).toBe(expected) + }) + + test('Markdown', async () => { + const result = await markdown('# Foo\n_foo_') + const result2 = await markdown('<md tag="section"># Foo\n_foo_</md>', { manual: true }) + + expect(result).toBe('<h1>Foo</h1>\n<p><em>foo</em></p>\n') + expect(result2).toBe('<section>\n<h1>Foo</h1>\n<p><em>foo</em></p>\n</section>') + expect( + await useTransformers('# Foo\n_foo_', { markdown: false }).then(({ html }) => html) + ).toBe('# Foo\n_foo_') + }) + + test('Widow words', async () => { + const result = await preventWidows('one two', { minWordCount: 2 }) + const result2 = await preventWidows('<div prevent-widows>one two three</div>', { withAttributes: true }) + const result3 = await preventWidows('<div prevent-widows>{{{ one two three }}</div>', { + ignore: [ + { heads: '{{{', tails: '}}}' } + ], + withAttributes: true + }) + + expect(result).toBe('one&nbsp;two') + expect(result2).toBe('<div>one two&nbsp;three</div>') + expect(result3).toBe('<div>{{{ one two three }}</div>') + expect( + await useTransformers('<div prevent-widows>one two three</div>', { widowWords: { minWordCount: 3 } }).then(({ html }) => html) + ).toBe('<div>one two&nbsp;three</div>') + }) + + test('Attribute to style', async () => { + const html = `<table align="left" width="100%" height="600" bgcolor="#FFFFFF" background="https://example.com/image.jpg"> + <tr> + <td align="center" valign="top"></td> + </tr> + </table>` + + const expected = `<table align="left" width="100%" height="600" bgcolor="#FFFFFF" background="https://example.com/image.jpg" style="float: left; width: 100%; height: 600px; background-color: #FFFFFF; background-image: url('https://example.com/image.jpg')"> + <tr> + <td align="center" valign="top" style="text-align: center; vertical-align: top"></td> + </tr> + </table>` + + const html2 = `<table align="center"> + <tr> + <td></td> + </tr> + </table>` + + const expected2 = `<table align="center" style="margin-left: auto; margin-right: auto"> + <tr> + <td></td> + </tr> + </table>` + + // Expands attributes to inline CSS + expect( + await attributeToStyle(html, ['width', 'height', 'bgcolor', 'background', 'align', 'valign']) + ).toBe(expected) + // Expands align="center" to style="margin-left: auto; margin-right: auto" + expect(await attributeToStyle(html2, ['align'])).toBe(expected2) + // Does not expand anything if options are empty or false + expect(await attributeToStyle(html2, [])).toBe(html2) + expect(await attributeToStyle(html2, false)).toBe(html2) + // Defaults to px for width values without units + expect(await attributeToStyle('<td width="100" style="color: #000;"></td>', ['width'])).toBe('<td width="100" style="color: #000; width: 100px"></td>') + + expect( + await useTransformers(html, { + attributes: { add: false }, + css: { inline: { attributeToStyle: ['width', 'height'] } }, + }).then(({ html }) => html) + ).toBe(`<table align="left" width="100%" height="600" bgcolor="#ffffff" background="https://example.com/image.jpg" style="width: 100%; height: 600px"> + <tr> + <td align="center" valign="top"></td> + </tr> + </table>`) + }) + + test('Inline CSS', async () => { + // Test for invalid input + expect(await inlineCSS()).toBe('') + expect(await inlineCSS('')).toBe('') + + const css = ` + .w-1 {width: 4px} + .h-1 {height: 4px} + .foo {color: red} + .bar {cursor: pointer; margin: calc(4px * 0)} + .hover\\:foo:hover {color: blue} + @media (max-width: 600px) { + .sm\\:text-center {text-align: center} + } + ` + + // Basic test + const html = ` + <style>${css}</style> + <p class="bar">test</p> + <table class="w-1 h-1 sm:text-center"> + <tr> + <td class="foo bar h-1">test</td> + </tr> + </table>` + + const result = await inlineCSS(html, { + removeInlinedSelectors: true, + codeBlocks: { + RB: { + start: '<%', + end: '%>', + }, + }, + }) + + expect(result).toBe(` + <style> + .hover\\:foo:hover {color: blue} + @media (max-width: 600px) { + .sm\\:text-center {text-align: center} + } + </style> + <p style="cursor: pointer; margin: 0">test</p> + <table class="sm:text-center" style="width: 4px; height: 4px"> + <tr> + <td style="height: 4px; color: red; cursor: pointer; margin: 0">test</td> + </tr> + </table>`) + + // Test preserving selectors + const withPreservedSelectors = await inlineCSS(html, { + removeInlinedSelectors: false, + }) + + expect(withPreservedSelectors).toBe(` + <style> + .w-1 {width: 4px} + .h-1 {height: 4px} + .foo {color: red} + .bar {cursor: pointer; margin: calc(4px * 0)} + .hover\\:foo:hover {color: blue} + @media (max-width: 600px) { + .sm\\:text-center {text-align: center} + } + </style> + <p class="bar" style="cursor: pointer; margin: 0">test</p> + <table class="w-1 h-1 sm:text-center" style="width: 4px; height: 4px"> + <tr> + <td class="foo bar h-1" style="height: 4px; color: red; cursor: pointer; margin: 0">test</td> + </tr> + </table>`) + + // Test using the transformer with options + expect( + await useTransformers(html, { + attributes: { add: false }, + css: { inline: { removeInlinedSelectors: true } }, + }).then(({ html }) => html) + ).toBe(` + <style> + .hover-foo:hover {color: blue} + @media (max-width: 600px) { + .sm-text-center {text-align: center} + } + </style> + <p style="cursor: pointer; margin: 0">test</p> + <table class="sm-text-center" style="width: 4px; height: 4px"> + <tr> + <td style="height: 4px; color: red; cursor: pointer; margin: 0">test</td> + </tr> + </table>`) + + // Test using custom CSS + const withCustomCSS = await inlineCSS( + '<p class="bar" style="color: red"></p>', + { + customCSS: '.bar {display: flex;}' + } + ) + expect(withCustomCSS).toBe('<p class="bar" style="display: flex; color: red;"></p>') + + // With excludedProperties + const withExcludedProperties = await inlineCSS(` + <style>.bar {cursor: pointer; margin: 0}</style> + <p class="bar">test</p>`, { + removeInlinedSelectors: true, + excludedProperties: ['margin'] + }) + + expect(withExcludedProperties).toBe(` + <style></style> + <p style="cursor: pointer">test</p>`) + + expect( + await inlineCSS(` + <style embed>.foo {color: red}</style> + <p class="foo">test</p>`) + ).toBe(` + <style>.foo {color: red}</style> + <p class="foo">test</p>` + ) + + // applyWidthAttributes and applyHeightAttributes + expect( + await useTransformers('<style>.size-10px {width: 10px; height: 10px}</style><img class="size-10px">', { + css: { inline: { removeInlinedSelectors: true } }, + }).then(({ html }) => html) + ).toBe('<style></style><img style="width: 10px; height: 10px" width="10" height="10" alt="">') + }) + + test('Purge CSS', async () => { + const html = ` + <!DOCTYPE html> + <html> + <head> + <style> + @media (screen) { + .should-remove {color: yellow} + } + .foo {color: red} + .foo:hover {color: blue} + .bar-baz {color: blue} + .should-remove {color: white} + </style> + </head> + <body> + <div class="foo {{ test }}">test div with some text</div> + </body> + </html>` + + const options = { + backend: [ + { heads: '{{', tails: '}}' } + ], + whitelist: ['.bar*'] + } + + const result = await purgeCSS(html, options) + + const expected = `<!DOCTYPE html> + <html> + <head> + <style> + .foo {color: red} + .foo:hover {color: blue} + .bar-baz {color: blue} + </style> + </head> + <body> + <div class="foo {{ test }}">test div with some text</div> + </body> + </html>` + + expect(result).toBe(expected) + + expect( + await useTransformers(html, { css: { purge: options } }).then(({ html }) => html) + ).toBe(expected) + }) + + test('Remove attributes', async () => { + const html = '<div style="" remove keep role="article" delete-me="with-regex">test</div>' + + const options = [ + { name: 'role', value: 'article' }, + 'remove', + { name: 'delete-me', value: /^with/ } + ] + + expect(await removeAttributes(html, options)).toBe('<div keep>test</div>') + + expect( + await useTransformers(html, { attributes: { remove: options } }).then(({ html }) => html) + ).toBe('<div keep>test</div>') + }) + + test('Shorthand CSS', async () => { + const html = '<div style="margin-top: 0px; margin-right: 4px; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 2px;"></div>' + const expected = '<div style="margin: 0px 4px 0 0; padding: 0 0 0 2px;"></div>' + + expect(await shorthandCSS(html)).toBe(expected) + expect(await shorthandCSS(html, { + tags: ['div'] + })).toBe(expected) + expect( + await useTransformers(html, { css: { shorthand: true } }).then(({ html }) => html) + ).toBe(expected) + }) + + test('Add attributes', async () => { + const result = await addAttributes('<div></div>', { + div: { + role: 'article' + } + }) + + expect(result).toBe('<div role="article"></div>') + + expect( + await useTransformers('<div></div>', { attributes: { add: { div: { role: 'article' } } } }).then(({ html }) => html) + ).toBe('<div role="article"></div>') + }) + + test('Prefer attribute sizes', async () => { + const html = '<img src="image.jpg" style="width: 100px; height: auto">' + + expect(await useAttributeSizes(html)).toBe(html) + expect(await useAttributeSizes(html, { + width: ['table'], + height: ['table'] + })).toBe(html) + expect(await useAttributeSizes(html, { + width: ['img'], + height: ['img'] + })).toBe('<img src="image.jpg" width="100" height="auto">') + + expect( + await useTransformers( + html, + { + css: { + inline: { + useAttributeSizes: true, + } + } + }) + .then(({ html }) => html) + ).toBe('<img src="image.jpg" width="100" height="auto" alt="">') + }) + + test('Base URL', async () => { + const fixture = await readFile(new URL('fixtures/base-url.html', import.meta.url), 'utf8') + const expected = await readFile(new URL('expected/base-url.html', import.meta.url), 'utf8') + + const withInvalid = await addBaseUrl(fixture, true) + const withString = await addBaseUrl(fixture, 'https://example.com/') + const withObject = await addBaseUrl(fixture, { + url: 'https://example.com/', + allTags: true, + }) + + expect(withInvalid).toBe(fixture) + expect(withString).toBe(expected) + expect(withObject).toBe(expected) + + expect( + await useTransformers(fixture, { + baseURL: 'https://example.com/', + // Expected string too long, need to disable auto-adding of attributes + attributes: { + add: { + table: false, + img: false + } + } + }).then(({ html }) => html) + ).toBe(expected) + }) + + test('URL parameters', async () => { + const simple = await addURLParams( + `<a href="https://example.com">test</a> + <link href="https://foo.bar">`, + { + bar: 'baz', + qix: 'qux' + } + ) + + const withOptions = await addURLParams( + `<a href="example.com">test</a> + <link href="https://foo.bar">`, + { + _options: { + tags: ['a[href*="example"]', 'link'], + strict: false, + qs: { + encode: true + } + }, + foo: '@Bar@', + bar: 'baz' + } + ) + + expect(simple).toBe( + `<a href="https://example.com?bar=baz&qix=qux">test</a> + <link href="https://foo.bar">` + ) + + expect(withOptions).toBe( + `<a href="example.com?bar=baz&foo=%40Bar%40">test</a> + <link href="https://foo.bar?bar=baz&foo=%40Bar%40">` + ) + + expect( + await useTransformers(simple, { + urlParameters: { + bar: 'baz', + qix: 'qux' + } + }).then(({ html }) => html) + ).toBe(simple) + }) + + test('Six-digit HEX', async () => { + const html = await sixHEX(` + <div bgcolor="#000" style="color: #fff; background-color: #000">This should not change: #ffc</div> + <font color="#fff">Text</font>`) + + expect(html).toBe(` + <div bgcolor="#000000" style="color: #fff; background-color: #000">This should not change: #ffc</div> + <font color="#ffffff">Text</font>`) + + expect( + await useTransformers(html, { css: { sixHex: true } }).then(({ html }) => html) + ).toBe(html) + }) + + test('MSO tags', async () => { + const html = await useMso(` + <outlook>show in outlook</outlook> + <not-outlook>hide from outlook</not-outlook> + `) + + expect(html).toBe(` + <!--[if mso]>show in outlook<![endif]--> + <!--[if !mso]><!-->hide from outlook<!--<![endif]--> + `) + + expect( + await useTransformers('<mso>show in outlook</mso>', { outlook: { tag: 'mso' } }).then(({ html }) => html) + ).toBe('<!--[if mso]>show in outlook<![endif]-->') + }) + + test('Prettify', async () => { + const html = '<div><p>test</p></div>' + + expect(await prettify(html)).toBe('<div>\n <p>test</p>\n</div>') + expect(await prettify(html, { indent_size: 4 })).toBe('<div>\n <p>test</p>\n</div>') + + expect( + await useTransformers(html, { prettify: true }).then(({ html }) => html) + ).toBe('<div>\n <p>test</p>\n</div>') + }) + + test('Minify', async () => { + const html = '<div>\n\n<p>\n\n test</p></div>' + + expect(await minify(html)).toBe('<div><p> test</p></div>') + expect(await minify(html, { lineLengthLimit: 4 })).toBe('<div>\n<p>\ntest\n</p>\n</div>') + expect( + await useTransformers(html, { minify: true }).then(({ html }) => html) + ).toBe('<div><p> test</p></div>') + }) + + test('Replace strings', async () => { + expect(await replaceStrings('initial text')).toBe('initial text') + expect(await replaceStrings('initial text', {})).toBe('initial text') + expect(await replaceStrings('initial text', { '/not/': 'found' })).toBe('initial text') + expect(await replaceStrings('initial text', { 'initial': 'updated' })).toBe('updated text') + + expect( + await useTransformers('initial text', { replaceStrings: { 'initial': 'updated' } }).then(({ html }) => html) + ).toBe('updated text') + }) +}) diff --git a/test/utils.test.js b/test/utils.test.js new file mode 100644 index 00000000..ea55939d --- /dev/null +++ b/test/utils.test.js @@ -0,0 +1,125 @@ +import os from 'node:os' +import { describe, expect, test, vi, afterAll } from 'vitest' +import { + injectScript, + findCommonPrefix, + formatMs, + formatTime, + humanFileSize +} from '../src/utils/string.js' + +import { + getLocalIP, + getFileSize, + getColorizedFileSize, + parseFrontMatter +} from '../src/utils/node.js' + +describe.concurrent('String utils', () => { + test('Injects script at correct location', () => { + const script = '<script src="test.js"></script>' + + // Returns the HTML if no valid location is found + expect(injectScript('<p></p>', script)).toBe(script + '<p></p>') + + // Injects script before </head> + expect(injectScript('<html><head><title>Test</title></head><body></body></html>', script)) + .toBe('<html><head><title>Test</title><script src="test.js"></script></head><body></body></html>') + + // Injects script after </title> + expect(injectScript('<html><title>Test</title><body></body></html>', script)) + .toBe('<html><title>Test</title><script src="test.js"></script><body></body></html>') + + // Injects script before </body> + expect(injectScript('<html><body><p>foo</p></body></html>', script)) + .toBe('<html><body><p>foo</p><script src="test.js"></script></body></html>') + + // Injects script before </html> + expect(injectScript('<html><p>foo</p></html>', script)) + .toBe('<html><p>foo</p><script src="test.js"></script></html>') + + // Injects script after <!doctype html> + expect(injectScript('<!doctype html><p>foo</p>', script)) + .toBe('<!doctype html><script src="test.js"></script><p>foo</p>') + }) + + test('Finds common prefix', () => { + expect(findCommonPrefix(['foo', 'foobar', 'foobar'])).toBe('foo') + + expect(() => findCommonPrefix(true)).toThrow() + }) + + test('Formats milliseconds to time', () => { + expect(formatMs(100000)).toBe('00:01:40') + }) + + test('Formats milliseconds to human-readable time', () => { + expect(formatTime(100000)).toBe('1.67 min') + expect(formatTime(40000)).toBe('40.00 s') + expect(formatTime(900)).toBe('900 ms') + }) + + test('Formats bytes to human-readable size', () => { + expect(humanFileSize(100)).toBe('100 B') + expect(humanFileSize(1048576)).toBe('1.00 MB') + expect(humanFileSize(1024, true)).toBe('1.02 KB') + }) +}) + +describe.concurrent('Node utils', () => { + test('Gets local IP address', () => { + expect(getLocalIP()).toBeDefined() + expect(getLocalIP()).toContain('.') + }) + + test('should return a valid IPv4 address if found', () => { + // Mock data for a valid IPv4 address + const mockInterfaces = { + eth0: [ + { family: 'IPv4', internal: false, address: '192.168.1.100' }, + { family: 'IPv6', internal: false, address: 'fe80::1' } + ] + } + + const mockedInterface = vi.spyOn(os, 'networkInterfaces').mockReturnValue(mockInterfaces) + + afterAll(() => { + mockedInterface.mockReset() + }) + + expect(getLocalIP()).toBe('192.168.1.100') + }) + + test('`getLocalIP` returns default IP when no suitable IP is found', () => { + const mockInterfaces = { + eth0: [ + { family: 'IPv6', internal: false, address: 'fe80::1' } + ] + } + + const mockNetworkInterfaces = vi.spyOn(os, 'networkInterfaces').mockReturnValue(mockInterfaces) + + afterAll(() => { + mockNetworkInterfaces.mockReset() + }) + + expect(getLocalIP()).toBe('127.0.0.1') + }) + + test('Gets file size of a string', () => { + expect(getFileSize('foo')).toBe('3.00') + + // Colorized file size + expect(getColorizedFileSize('foo')).toBe('3.00 B') + expect(getColorizedFileSize('x'.repeat(49 * 1024))).toContain('49.00 KB') + expect(getColorizedFileSize('x'.repeat(101 * 1024))).toContain('101.00 KB') + expect(getColorizedFileSize('x'.repeat(102 * 1024))).toContain('102.00 KB') + }) + + test('Parses front matter', () => { + const result = parseFrontMatter('---\ntitle: Test\n---\n\n<p>Test</p>') + + expect(result.data.title).toBe('Test') + expect(result.content.trim()).toBe('<p>Test</p>') + }) +}) diff --git a/test/websockets.test.js b/test/websockets.test.js new file mode 100644 index 00000000..a70a80f8 --- /dev/null +++ b/test/websockets.test.js @@ -0,0 +1,38 @@ +import { EventEmitter } from 'node:events' +import { describe, expect, test } from 'vitest' +import { initWebSockets } from '../src/server/websockets.js' + +describe.concurrent('Websockets', () => { + test('Starts websockets server', async () => { + class MockWebSocket extends EventEmitter { + constructor() { + super() + this.clients = new Set() + } + + send(data) { + this.emit('message', data) + } + } + + const mockWSS = new MockWebSocket() + initWebSockets(mockWSS) + + mockWSS.emit('connection', mockWSS) + + expect(mockWSS.listenerCount('connection')).toBe(1) + expect(mockWSS.listenerCount('message')).toBe(1) + + // Test if the message is broadcasted + const mockClient = new MockWebSocket() + mockClient.readyState = 1 + mockWSS.clients.add(mockClient) + + // Add a 'message' event listener to the mockClient instance + mockClient.on('message', () => {}) + + mockWSS.emit('message', JSON.stringify({ test: 'test' })) + + expect(mockClient.listenerCount('message')).toBe(1) + }) +}) diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 74a45b0d..00000000 --- a/tsconfig.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "compilerOptions": { - "target": "ES6", - "module": "commonjs", - "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "noImplicitThis": true, - "alwaysStrict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "moduleResolution": "node", - "lib": [ - "ES6" - ] - }, - "files": [ - "types/index.d.ts" - ] -} diff --git a/types/baseUrl.d.ts b/types/baseUrl.d.ts deleted file mode 100644 index c76ec656..00000000 --- a/types/baseUrl.d.ts +++ /dev/null @@ -1,79 +0,0 @@ -export default interface BaseURLConfig { - /** - The URL to prepend. - - @default undefined - */ - url: string; - - /** - Tags to apply the `url` to. When using this option, the `url` will only be prepended to the specified tags. - - Maizzle uses a [custom set of tags](https://github.com/posthtml/posthtml-base-url/blob/main/lib/index.js#L6-L60) by default. - - @example - - Prepend `url` to all 'source'-like attribute values on image tags, like `src` and `srcset`: - - ``` - module.exports = { - baseURL: { - url: 'https://cdn.example.com/', - tags: ['img'], - }, - } - ``` - - With more granular control: - - ``` - module.exports = { - baseURL: { - url: 'https://cdn.example.com/', - tags: { - img: { - src: true, // use the value of `url` above - srcset: 'https://bar.com/', - }, - }, - }, - } - ``` - */ - tags?: string[] | Record<string, unknown>; - - /** - Key-value pairs of attributes and the string to prepend to their existing value. - - @default {} - - @example - - Prepend `https://example.com/` to all `data-url` attribute values: - - ``` - module.exports = { - baseURL: { - attributes: { - 'data-url': 'https://example.com/', - }, - }, - } - ``` - */ - attributes?: Record<string, unknown>; - - /** - Whether the string defined in `url` should be prepended to `url()` values in CSS `<style>` tags. - - @default true - */ - styleTag?: boolean; - - /** - Whether the string defined in `url` should be prepended to `url()` values in inline CSS. - - @default true - */ - inlineCss?: boolean; -} diff --git a/types/build.d.ts b/types/build.d.ts index 5fb51dc5..f55ef5d1 100644 --- a/types/build.d.ts +++ b/types/build.d.ts @@ -1,74 +1,134 @@ -import type LayoutsConfig from './layouts'; -import type PostHTMLConfig from './posthtml'; -import type TailwindConfig from './tailwind'; -import type TemplatesConfig from './templates'; -import type ComponentsConfig from './components'; -import type {Options as BrowserSyncConfig} from 'browser-sync'; +import ComponentsConfig from './components'; +import type { SpinnerName } from 'cli-spinners'; export default interface BuildConfig { /** - Templates configuration. - */ - templates: TemplatesConfig; - - /** - Tailwind CSS configuration. - */ - tailwind?: TailwindConfig; - - /** - [DEPRECATED] Layouts configuration. - */ - layouts?: LayoutsConfig; - - /** - Components configuration. - */ + * Components configuration. + */ components?: ComponentsConfig; /** - PostHTML configuration. - */ - posthtml?: PostHTMLConfig; + * Directory where Maizzle should look for Templates to compile. + * + * @default ['src/templates/**\/*.html'] + * + * @example + * ``` + * export default { + * build: { + * files: ['src/templates/**\/*.html'] + * } + * } + * ``` + */ + files?: string | string[]; /** - Configure PostCSS + * Define the output path for compiled Templates, and what file extension they should use. + * + * @example + * ``` + * export default { + * build: { + * output: { + * path: 'build_production', + * extension: 'html' + * } + * } + * } + * ``` */ - postcss?: { + output?: { /** - Additional PostCSS plugins that you would like to use. - - @default [] - - @example - ``` - const examplePlugin = require('postcss-example-plugin') - module.exports = { - build: { - postcss: { - plugins: [ - examplePlugin() - ] - } - } - } - ``` - */ - plugins?: any[]; + * Directory where Maizzle should output compiled Templates. + * + * @default 'build_{env}' + */ + path?: string; + /** + * File extension to be used for compiled Templates. + * + * @default 'html' + */ + extension: string; }; /** - Browsersync configuration. - - When you run the `maizzle serve` command, Maizzle uses [Browsersync](https://browsersync.io/) - to start a local development server and open a directory listing of your emails in your default browser. - */ - browsersync?: BrowserSyncConfig; + * Source and destination directories for static files. + * + * @example + * ``` + * export default { + * build: { + * static: { + * source: ['src/images/**\/*.*'], + * destination: 'images' + * } + * } + * } + * ``` + */ + static?: { + /** + * Array of paths where Maizzle should look for static files. + * + * @default undefined + */ + source?: string[]; + /** + * Directory where static files should be copied to, + * relative to the `build.output` path. + * + * @default undefined + */ + destination?: string; + } | { + /** + * An array of objects specifying source and destination directories for static files. + */ + static: Array<{ + /** + * Array of paths where Maizzle should look for static files. + */ + source: string[]; + /** + * Directory where static files should be copied to, + * relative to the `build.output` path. + */ + destination: string; + }>; + }; /** - Configure how build errors are handled when developing with the Maizzle CLI. + * Type of spinner to show in the console. + * + * @default 'dots' + * + * @example + * ``` + * export default { + * build: { + * spinner: 'bounce' + * } + * } + * ``` + */ + spinner?: SpinnerName; - @default undefined - */ - fail?: 'silent' | 'verbose'; + /** + * Show a summary of files that were compiled, along with their + * size and the time it took to compile them. + * + * @default false + * + * @example + * ``` + * export default { + * build: { + * summary: true + * } + * } + * ``` + */ + summary?: boolean; } diff --git a/types/components.d.ts b/types/components.d.ts index fe24f4bf..9dbb5994 100644 --- a/types/components.d.ts +++ b/types/components.d.ts @@ -1,177 +1,195 @@ +import type ExpressionsConfig from './expressions'; +import type { Options as PostHTMLParserOptions } from 'posthtml-parser'; + +interface AnyObject { + [key: string]: string | AnyObject; +} + export default interface ComponentsConfig { /** - Root path where to look for folders containing component files. - - @default './' - */ + * Root path where to look for folders containing component files. + * + * @default './' + */ root?: string; /** - Paths where to look for component files. Must be relative to `root`. - - @default ['src/components', 'src/layouts', 'src/templates'] - */ + * Paths where to look for component files. Must be relative to `root`. + * + * @default ['src/components', 'src/layouts', 'src/templates'] + */ folders?: string[]; /** - Prefix to use for component tags. - - @default 'x-' - */ + * Prefix to use for component tags. + * + * @default 'x-' + */ tagPrefix?: string; /** - Tag name to be used in HTML when using a component. - - @default 'component' - */ + * Tag name to be used in HTML when using a component. + * + * @default 'component' + */ tag?: string; /** - Attribute name to be used when referencing a component via its path. - - @default 'src' - */ + * Attribute name to be used when referencing a component via its path. + * + * @default 'src' + */ attribute?: string; /** - File extension that component files must use. - Any other files will be ignored and not be made available as components. - - @default 'html' - */ + * File extension that component files must use. + * Any other files will be ignored and not be made available as components. + * + * @default 'html' + */ fileExtension?: string; /** - Name of the tag that will be replaced with the content that is passed to the component. - - @default 'content' - */ + * Name of the tag that will be replaced with the content that is passed to the component. + * + * @default 'yield' + */ yield?: string; /** - Name of the slot tag, where the content will be injected. - - @default 'slot' + * Name of the slot tag, where the content will be injected. + * + * @default 'slot' */ slot?: string; /** - Name of the fill tag, where the content to be injected is defined. - - @default 'fill' - */ + * Name of the fill tag, where the content to be injected is defined. + * + * @default 'fill' + */ fill?: string; /** - String to use as a separator between the slot tag and its name. - - @default ':' - */ + * String to use as a separator between the slot tag and its name. + * + * @default ':' + */ slotSeparator?: string; /** - Tag name for pushing content to a stack. - - @default 'push' - */ + * Tag name for pushing content to a stack. + * + * @default 'push' + */ push?: string; /** - Tag name for popping (rendering) content from a stack. - - @default 'stack' - */ + * Tag name for popping (rendering) content from a stack. + * + * @default 'stack' + */ stack?: string; /** - Name of the props attribute to use in the `<script>` tag of a component. - - @default 'props' - */ + * Name of the props attribute to use in the `<script>` tag of a component. + * + * @default 'props' + */ propsScriptAttribute?: string; /** - Name of the object that will be used to store the props of a component. - - @default 'props' - */ + * Name of the object that will be used to store the props of a component. + * + * @default 'props' + */ propsContext?: string; /** - Name of the attribute that will be used to pass props to a component as JSON. - - @default 'locals' - */ + * Name of the attribute that will be used to pass props to a component as JSON. + * + * @default 'locals' + */ propsAttribute?: string; /** - Name of the key to use when retrieving props passed to a slot via `$slots.slotName.props`. - - @default 'props' - */ + * Name of the key to use when retrieving props passed to a slot via `$slots.slotName.props`. + * + * @default 'props' + */ propsSlot?: string; /** - Configure [`posthtml-parser`](https://github.com/posthtml/posthtml-parser). - - @default {recognizeSelfClosing:true} - */ - parserOptions?: Record<string, any>; - - /** - Configure [`posthtml-expressions`](https://github.com/posthtml/posthtml-expressions). - - @default {} // custom object - */ - expressions?: Record<any, any>; - - /** - PostHTML plugins to apply to each parsed component. - - @default [] - */ - plugins?: any[]; - - /** - Extra rules for the PostHTML plugin that is used by components to parse attributes. - - @default {} - */ - attrsParserRules?: Record<any, any>; - - /** - In strict mode, an error will be thrown if a component cannot be rendered. - - @default true - */ + * Configure [`posthtml-parser`](https://github.com/posthtml/posthtml-parser). + * + * @default + * { + * recognizeNoValueAttribute: true, + * recognizeSelfClosing: true + * } + */ + parserOptions?: PostHTMLParserOptions; + + /** + * Configure [`posthtml-expressions`](https://github.com/posthtml/posthtml-expressions). + * + * @default + * { + * strictMode: false, + * missingLocal: '{local}', + * locals: { + * page: config, // the computed Maizzle config object + * } + * } + */ + expressions?: ExpressionsConfig; + + /** + * PostHTML plugins to apply to each parsed component. + * + * @default [] + */ + plugins?: Array<() => void>; + + /** + * Extra rules for the PostHTML plugin that is used by components to parse attributes. + * + * @default {} + */ + attrsParserRules?: Record<string, AnyObject>; + + /** + * In strict mode, an error will be thrown if a component cannot be rendered. + * + * @default true + */ strict?: boolean; /** - Utility methods to be passed to `<script props>` in a component. - - @default {merge: _.mergeWith, template: _.template} - */ + * Utility methods to be passed to `<script props>` in a component. + * + * @default {merge: _.mergeWith, template: _.template} + */ utilities?: Record<string, unknown>; /** - Define additional attributes that should be preserved for specific HTML elements. - - @default {} - */ + * Define additional attributes that should be preserved for specific HTML elements. + * + * @default {} + */ elementAttributes?: Record<string, void>; /** - Attributes that should be preserved on all elements in components. - - @default ['data-*'] - */ + * Attributes that should be preserved on all elements in components. + * + * @default ['data-*'] + */ safelistAttributes?: string[]; /** - Attributes that should be removed from all elements in components. - - @default [] - */ + * Attributes that should be removed from all elements in components. + * + * @default [] + */ blacklistAttributes?: string[]; } diff --git a/types/config.d.ts b/types/config.d.ts index c98c1df2..bc3c3c54 100644 --- a/types/config.d.ts +++ b/types/config.d.ts @@ -1,31 +1,82 @@ import type BuildConfig from './build'; -import type InlineCSSConfig from './inlineCss'; -import type RemoveUnusedCSSConfig from './removeUnusedCss'; -import type WidowWordsConfig from './widowWords'; -import type BaseURLConfig from './baseURL'; -import type URLParametersConfig from './urlParameters'; -import type {CoreBeautifyOptions} from 'js-beautify'; import type MinifyConfig from './minify'; +import type PostHTMLConfig from './posthtml'; import type MarkdownConfig from './markdown'; -import type EventsConfig from './events'; +import type { ProcessOptions } from 'postcss'; +import type PurgeCSSConfig from './css/purge'; +import type CSSInlineConfig from './css/inline'; +import type ComponentsConfig from './components'; +import type WidowWordsConfig from './widowWords'; +import type { CoreBeautifyOptions } from 'js-beautify'; +import type { BaseURLConfig } from 'posthtml-base-url'; +import type URLParametersConfig from './urlParameters'; +import type { + beforeCreateType, + beforeRenderType, + afterRenderType, + afterTransformersType, + afterBuildType +} from './events'; +import type PlaintextConfig from './plaintext'; + +import type { Config as TailwindConfig } from 'tailwindcss'; export default interface Config { - [key: string]: any; + [key: string]: any; // eslint-disable-line + + /** + * Add or remove attributes from elements. + */ + attributes?: { + /** + * Add attributes to specific elements. + * + * @default {} + * + * @example + * ``` + * export default { + * attributes: { + * add: { + * table: { + * cellpadding: 0, + * cellspacing: 0, + * } + * } + * } + * } + * ``` + */ + add?: Record<string, Record<string, string|number>>; + + /** + * Remove attributes from elements. + * + * @default {} + * + * @example + * ``` + * export default { + * attributes: { + * remove: ['width', 'height'], + * } + * } + * ``` + */ + remove?: Record<string, string[]>; + } /** Configure build settings. @example ``` - module.exports = { + export default { build: { - templates: TemplatesConfig, - tailwind: TailwindConfig, - layouts: LayoutsConfig, components: ComponentsConfig, posthtml: PostHTMLConfig, - browsersync: BrowserSyncConfig, - fail: 'silent' // or 'verbose' + tailwind: TailwindConfig, + templates: TemplatesConfig, } } ``` @@ -33,192 +84,327 @@ export default interface Config { build: BuildConfig; /** - Toggle the use of Transformers. - - @default true - - @example - ``` - module.exports = { - applyTransformers: false, - } - ``` - */ - applyTransformers?: boolean; - - /** - Configure CSS inlining. + Define a string that will be prepended to sources and hrefs in your HTML and CSS. - To enable it with defaults, simply set it to `true`. @example - ```js - module.exports = { - inlineCSS: true, - } - ``` - */ - inlineCSS?: boolean | InlineCSSConfig; - /** - Configure unused CSS purging. + Prepend to all sources and hrefs: - To enable it with defaults, simply set it to `true`. - @example ``` - module.exports = { - removeUnusedCSS: true, + export default { + baseURL: 'https://cdn.example.com/' } ``` - */ - removeUnusedCSS?: boolean | RemoveUnusedCSSConfig; - - /** - Automatically remove HTML attributes. - By default, empty `style` and `class` attributes are removed. - - @default ['style', 'class'] + Prepend only to `src` attributes on image tags: - @example ``` - module.exports = { - removeAttributes: ['data-src'] + export default { + baseURL: { + url: 'https://cdn.example.com/', + tags: ['img'], + }, } ``` */ - removeAttributes?: - | string[] - | Array<{ - name: string; - value: string | RegExp; - }>; + baseURL?: string | BaseURLConfig; /** - Prevent widow words inside a tag by adding a `&nbsp;` between its last two words. + * Configure components. + */ + components?: ComponentsConfig; - @example - ``` - module.exports = { - widowWords: true, + /** + * Configure how CSS is handled. + */ + css: { + /** + * Configure CSS inlining. + */ + inline?: CSSInlineConfig; + + /** + * Configure CSS purging. + */ + purge?: PurgeCSSConfig; + + /** + * Normalize escaped character class names like `\:` or `\/` by replacing them + * with email-safe alternatives. + * + * @example + * ``` + * export default { + * css: { + * safeClassNames: { + * ':': '__', + * '!': 'i-', + * } + * } + * } + * ``` + */ + safeClassNames?: boolean | Record<string, string>; + + /** + * Ensure that all your HEX colors inside `bgcolor` and `color` attributes are defined with six digits. + * + * @default true + * + * @example + * ``` + * export default { + * css: { + * sixHex: false, + * } + * } + * ``` + */ + sixHex?: boolean; + + /** + * Rewrite longhand CSS inside style attributes with shorthand syntax. + * Only works with `margin`, `padding` and `border`, and only when + * all sides are specified. + * + * @default [] + * + * @example + * ``` + * export default { + * css: { + * shorthand: { + * tags: ['td', 'div'], + * } // or shorthand: true + * } + * } + * ``` + */ + shorthand?: boolean | Record<string, string[]>; + + /** + * Use a custom Tailwind CSS configuration object. + * + */ + tailwind?: TailwindConfig; } - ``` - */ - widowWords?: WidowWordsConfig; /** - [Add attributes](https://maizzle.com/docs/transformers/add-attributes) to elements in your HTML. - - @default - { - table: { - cellpadding: 0, - cellspacing: 0, - role: 'none' - }, - img: { - alt: '' - }, - } - */ - extraAttributes?: boolean | Record<string, unknown>; + * Transform text inside elements marked with custom attributes. + * Filters work only on elements that contain only text. + * + * @default {} + * + * @example + * ``` + * export default { + * filters: { + * uppercase: str => str.toUpperCase(), + * } + * } + * ``` + */ + filters: boolean | Record<string, (str: string) => string>; /** - Normalize escaped character class names like `\:` or `\/` by replacing them with email-safe alternatives. - - @example - ``` - module.exports = { - safeClassNames: { - ':': '__', - '!': 'i-', - } - } - ``` - */ - safeClassNames?: boolean | Record<string, string>; + * Define variables outside of the `page` object. + * + * @default {} + * + * @example + * ``` + * export default { + * locals: { + * company: { + * name: 'Spacely Space Sprockets, Inc.' + * } + * } + * } + * ``` + * + * `company` can then be used like this: + * + * ``` + * <p>{{ company.name }}</p> + * ``` + */ + locals?: Record<string, any>; // eslint-disable-line /** - Rewrite longhand CSS inside style attributes with shorthand syntax. - Only works with margin, padding and border, and only when all sides are specified. - - @default [] - - @example - ``` - module.exports = { - shorthandCSS: true, // or ['td', 'div'] to only apply to those tags - } - ``` - */ - shorthandCSS?: boolean | string[]; + * Configure the Markdown parser. + * + * @example + * + * ``` + * export default { + * markdown: { + * root: './', // Path relative to which markdown files are imported + * encoding: 'utf8', // Encoding for imported Markdown files + * markdownit: {}, // Options passed to markdown-it + * plugins: [], // Plugins for markdown-it + * } + * } + * ``` + */ + markdown?: MarkdownConfig; /** - Define a string that will be prepended to sources and hrefs in your HTML and CSS. - - @example - - Prepend to all sources and hrefs: + * Minify the compiled HTML email code. + * + * @default false + * + * @example + * ``` + * export default { + * minify: true, + * } + * ``` + */ + minify?: boolean | MinifyConfig; - ``` - module.exports = { - baseURL: 'https://cdn.example.com/' - } - ``` + /** + Configure the `posthtml-mso` plugin. + */ + outlook?: { + /** + The tag name to use for Outlook conditional comments. - Prepend only to `src` attributes on image tags: + @default 'outlook' - ``` - module.exports = { - baseURL: { - url: 'https://cdn.example.com/', - tags: ['img'], - }, - } - ``` - */ - baseURL?: string | BaseURLConfig; + @example + ``` + export default { + outlook: { + tag: 'mso' + } + } + // You now write <mso>...</mso> instead of <outlook>...</outlook> + ``` + */ + tag?: string; + }; /** - Transform text inside elements marked with custom attributes. + * Configure plaintext generation. + */ + plaintext?: PlaintextConfig; - Filters work only on elements that contain only text. - - @default {} + /** + * PostHTML configuration. + */ + posthtml?: PostHTMLConfig; - @example - ``` - module.exports = { - filters: { - uppercase: str => str.toUpperCase() - } - } - ``` - */ - filters: Record<string, unknown>; + /** + * Configure PostCSS + */ + postcss?: { + /** + * Additional PostCSS plugins that you would like to use. + * @default [] + * @example + * ``` + * import examplePlugin from 'postcss-example-plugin' + * export default { + * postcss: { + * plugins: [ + * examplePlugin() + * ] + * } + * } + * ``` + */ + plugins?: Array<() => void>; + + /** + * PostCSS options + * @default {} + * @example + * ``` + * export default { + * postcss: { + * options: { + * map: true + * } + * } + * ``` + */ + options?: ProcessOptions; + }; /** - Define variables outside of the `page` object. + * [Pretty print](https://maizzle.com/docs/transformers/prettify) your HTML email code + * so that it's nicely indented and more human-readable. + * + * @default undefined + * + * @example + * ``` + * export default { + * prettify: true, + * } + * ``` + */ + prettify?: boolean | CoreBeautifyOptions; - @default {} + /** + * Batch-replace strings in your HTML. + * + * @default {} + * + * @example + * ``` + * export default { + * replaceStrings: { + * 'replace this exact string': 'with this one', + * '\\s?data-src=""': '', // remove empty data-src="" attributes + * } + * } + * ``` + */ + replaceStrings?: Record<string, string>; - @example - ``` - module.exports = { - locals: { - company: { - name: 'Spacely Space Sprockets, Inc.' - } - } + /** + * Configure local server settings. + */ + server?: { + /** + * Port to run the local server on. + * + * @default 3000 + */ + port?: number; + + /** + * Enable HMR-like local development. + * When enabled, Maizzle will watch for changes in your templates + * and inject them into the browser without a full page reload. + * + * @default true + */ + hmr?: boolean; + + /** + * Enable synchronized scrolling across devices. + * + * @default false + */ + syncScroll?: boolean; + + /** + * Paths to watch for changes. + * When a file in these paths changes, Maizzle will do a full rebuild. + * + * @default [] + */ + watch?: string[]; + + /** + * Toggle reporting compiled file size in the console. + * + * @default false + */ + reportFileSize?: boolean; } - ``` - - `company` can be then used like this: - - ``` - <p>{{ company.name }}</p> - ``` - */ - locals?: Record<string, unknown>; /** Configure custom parameters to append to URLs. @@ -243,99 +429,125 @@ export default interface Config { urlParameters?: URLParametersConfig; /** - Ensure that all your HEX colors inside `bgcolor` and `color` attributes are defined with six digits. - - @default true - - @example - ``` - module.exports = { - sixHex: false, - } - ``` + * Enable or disable all Transformers. + * + * @default true + * + * @example + * ``` + * export default { + * useTransformers: false, + * } + * ``` */ - sixHex?: boolean; + useTransformers?: boolean; /** - [Pretty print](https://maizzle.com/docs/transformers/prettify) your HTML email code so that it's nicely indented and more human-readable. - - @default undefined - - @example - ``` - module.exports = { - prettify: true, - } - ``` - */ - prettify?: boolean | CoreBeautifyOptions; + * Prevent widow words inside a tag by adding a `&nbsp;` between its last two words. + * + * @default + * { + * minWordCount: 3, + * attrName: 'prevent-widows' + * } + * + * @example + * ``` + * export default { + * widowWords: { + * minWordCount: 5, + * }, + * } + * ``` + */ + widowWords?: WidowWordsConfig; /** - Minify the compiled HTML email code. - - @default false - - @example - ``` - module.exports = { - minify: true, - } - ``` + * Runs after the Environment config has been computed, but before Templates are processed. + * Exposes the `config` object so you can further customize it. + * + * @default undefined + * + * @example + * ``` + * export default { + * beforeCreate: async (config) => { + * // do something with `config` + * } + * } + * ``` */ - minify?: boolean | MinifyConfig; + beforeCreate: beforeCreateType; /** - Configure the Markdown parser. + * Runs after the Template's config has been computed, but just before it is compiled. + * It exposes the Template's HTML, its config, and the Maizzle `render` function. + * Must return the `html` string. + * + * @default undefined + * + * @example + * ``` + * export default { + * beforeRender: async ({html, config, render}) => { + * // do something... + * return html; + * } + * } + * ``` + */ + beforeRender: beforeRenderType; - @example - - ``` - module.exports = { - markdown: { - root: './', // A path relative to which markdown files are imported - encoding: 'utf8', // Encoding for imported Markdown files - markdownit: {}, // Options passed to markdown-it - plugins: [], // Plugins for markdown-it - } - } - ``` + /** + * Runs after the Template has been compiled, but before any Transformers have been applied. + * Exposes the rendered `html` string and the `config`. Must return the `html` string. + * + * @default undefined + * + * @example + * ``` + * export default { + * afterRender: async ({html, config}) => { + * // do something... + * return html; + * } + * } + * ``` */ - markdown?: MarkdownConfig; + afterRender: afterRenderType; /** - Batch-replace strings in your HTML. - - @default {} - - @example - ``` - module.exports = { - replaceStrings: { - 'replace this exact string': 'with this one', - '\\s?data-src=""': '', // remove empty data-src="" attributes - } - } - ``` + * Runs after all Transformers have been applied, just before the final HTML is returned. + * Exposes the rendered `html` string and the `config`. Must return the `html` string. + * + * @default undefined + * + * @example + * ``` + * export default { + * afterTransformers: async ({html, config, render}) => { + * // do something... + * return html; + * } + * } + * ``` */ - replaceStrings?: Record<string, string>; + afterTransformers: afterTransformersType; /** - When compiling your email templates, Maizzle goes through a series of steps like generating a Template config, rendering, or applying Transformers. - You can hook into the build process and manipulate it by using functions that run before or after some of these steps. - - @default {} - - @example - ``` - module.exports = { - events: { - beforeRender: async (html, config) => { - // do something with html and config - return html; - }, - } - } - ``` + * Runs after all Templates have been compiled and output to disk. + * The files parameter will contain the paths to all the files inside the `build.templates.destination.path` directory. + * + * @default undefined + * + * @example + * ``` + * export default { + * afterBuild: async ({files, config, render}) => { + * // do something... + * } + * } + * ``` */ - events?: EventsConfig; + afterBuild: afterBuildType; } diff --git a/types/css/inline.d.ts b/types/css/inline.d.ts new file mode 100644 index 00000000..bd961493 --- /dev/null +++ b/types/css/inline.d.ts @@ -0,0 +1,234 @@ +export type AttributeToStyleSupportedAttributes = + | 'width' + | 'height' + | 'bgcolor' + | 'background' + | 'align' + | 'valign'; + +export default interface InlineCSSConfig { + /** + * Which CSS properties should be duplicated as what HTML attributes. + * + * @default {} + * + * @example + * ``` + * export default { + * css: { + * inline: { + * styleToAttribute: { + * 'background-color': 'bgcolor', + * } + * } + * } + * } + * ``` + */ + styleToAttribute?: Record<string, string>; + + /** + * Duplicate HTML attributes to inline CSS. + * + * @default false + * + * @example + * ``` + * export default { + * css: { + * inline: { + * attributeToStyle: ['width', 'bgcolor', 'background'] + * } + * } + * } + * ``` + */ + attributeToStyle?: boolean | AttributeToStyleSupportedAttributes[]; + + /** + * Use any CSS pixel widths to create `width` attributes on elements set in `widthElements`. + * + * @default true + * + * @example + * ``` + * export default { + * css: { + * inline: { + * applyWidthAttributes: true, + * } + * } + * } + * ``` + */ + applyWidthAttributes?: boolean; + + /** + * Use any CSS pixel widths to create `height` attributes on elements set in `heightElements`. + * + * @default true + * + * @example + * ``` + * export default { + * css: { + * inline: { + * applyHeightAttributes: true, + * } + * } + * } + * ``` + */ + applyHeightAttributes?: boolean; + + /** + * Prefer HTML `width` and `height` attributes over inline CSS. + * The inline CSS `width` and `height` will be removed. + * + * @example + * ``` + * export default { + * css: { + * inline: { + * useAttributeSizes: true + * } + * } + * } + * ``` + */ + useAttributeSizes?: boolean; + + /** + * Array of CSS property names that should be excluded from the CSS inlining process. + * + * @default [] + * + * @example + * ``` + * export default { + * css: { + * inline: { + * excludedProperties: ['padding', 'padding-left'] + * } + * } + * } + * ``` + */ + excludedProperties?: string[]; + + /** + * Fenced code blocks that should be ignored during CSS inlining. + * + * @default + * { + * EJS: { start: '<%', end: '%>' }, + * HBS: { start: '{{', end: '}}' } + * } + * + * @example + * ``` + * export default { + * css: { + * inline: { + * codeBlocks: { + * EJS: { start: '<%', end: '%>' }, + * HBS: { start: '{{', end: '}}' }, + * } + * } + * } + * } + * ``` + */ + codeBlocks?: Record<string, { start: string; end: string }>; + + /** + * Provide your own CSS to be inlined. Must be vanilla or pre-compiled CSS. + * + * Existing `<style>` in your HTML tags will be ignored and their contents won't be inlined. + * + * @default false + * + * @example + * ``` + * export default { + * css: { + * inline: { + * customCSS: `.custom-class { color: red }` + * } + * } + * } + * ``` + */ + customCSS?: string | false; + + /** + * Resolve CSS variables and replace them with their values. + * + * @default true + * + * @example + * ``` + * export default { + * css: { + * inline: { + * resolveVariables: true + * } + * } + * } + * ``` + */ + resolveVariables?: boolean; + + /** + * Remove inlined CSS selectors from the `<style>` tag. + * + * @default true + * + * @example + * ``` + * export default { + * css: { + * inline: { + * removeInlinedSelectors: true + * } + * } + * ``` + */ + removeInlinedSelectors?: boolean; + + /** + * Resolve calc() expressions in CSS to their computed values. + * + * @default true + * + * @example + * ``` + * export default { + * css: { + * inline: { + * resolveCalc: true + * } + * } + * } + * ``` + */ + resolveCalc?: boolean; + + /** + * Prefer unitless CSS values + * + * @default true + * + * @example + * ``` + * export default { + * css: { + * inline: { + * preferUnitless: true + * } + * } + * } + * ``` + */ + preferUnitlessValues?: boolean; +} diff --git a/types/css/purge.d.ts b/types/css/purge.d.ts new file mode 100644 index 00000000..d8c4c840 --- /dev/null +++ b/types/css/purge.d.ts @@ -0,0 +1,125 @@ +import type { Opts } from 'email-comb'; + +export default interface PurgeCSSConfig { + /** + * Classes or IDs that you don't want removed. + * + * @default [] + * + * @example + * ``` + * export default { + * css: { + * purge: { + * whitelist: ['.some-class', '.Mso*', '#*'], + * } + * } + * } + * ``` + */ + whitelist?: Opts['whitelist']; + + /** + * Start and end delimiters for computed classes that you don't want removed. + * + * @default + * [ + * { + * heads: '{{', + * tails: '}}', + * }, + * { + * heads: '{%', + * tails: '%}', + * } + * ] + * + * @example + * ``` + * export default { + * css: { + * purge: { + * backend: [ + * { heads: '[[', tails: ']]' }, + * ] + * } + * } + * } + * ``` + */ + backend?: Opts['backend']; + + /** + * Whether to remove `<!-- HTML comments -->`. + * + * @default true + * + * @example + * ``` + * export default { + * css: { + * purge: { + * removeHTMLComments: false, + * } + * } + * } + * ``` + */ + removeHTMLComments?: Opts['removeHTMLComments']; + + /** + * Whether to remove `/* CSS comments *\/`. + * + * @default true + * + * @example + * ``` + * export default { + * css: { + * purge: { + * removeCSSComments: false, + * } + * } + * } + * ``` + */ + removeCSSComments?: Opts['removeCSSComments']; + + /** + * List of strings representing start of a conditional comment that should not be removed. + * + * @default + * ['[if', '[endif'] + * + * @example + * ``` + * export default { + * css: { + * purge: { + * doNotRemoveHTMLCommentsWhoseOpeningTagContains: ['[if', '[endif'], + * } + * } + * } + * ``` + */ + doNotRemoveHTMLCommentsWhoseOpeningTagContains: Opts['doNotRemoveHTMLCommentsWhoseOpeningTagContains']; + + /** + * Rename all classes and IDs in both your `<style>` tags and your body HTML elements, + * to be as few characters as possible. + * + * @default false + * + * @example + * ``` + * export default { + * css: { + * purge: { + * uglify: true, + * } + * } + * } + * ``` + */ + uglify?: Opts['uglify']; +} diff --git a/types/events.d.ts b/types/events.d.ts index 28cf153f..56f650ff 100644 --- a/types/events.d.ts +++ b/types/events.d.ts @@ -1,105 +1,5 @@ -export type beforeCreateType = (config: any) => Promise<void>; -export type beforeRenderType = (html: string, config: any) => Promise<string>; -export type afterRenderType = (html: string, config: any) => Promise<string>; -export type afterTransformersType = (html: string, config: any) => Promise<string>; -export type afterBuildType = (files: any[], config: any) => Promise<void>; - -export default interface EventsConfig { - /** - Runs after the Environment config has been computed, but before Templates are processed. - Exposes the `config` object so you can further customize it. - - @default undefined - - @example - ``` - module.exports = { - events: { - beforeCreate: async (config) => { - // do something with `config` - } - } - } - ``` - */ - beforeCreate: beforeCreateType; - - /** - Runs after the Template's config has been computed, but just before it is compiled. - It exposes the Template's config, as well as the HTML. Must return the `html` string. - - @default undefined - - @example - ``` - module.exports = { - events: { - beforeRender: async (html, config) => { - // do something with html and config - return html; - } - } - } - ``` - */ - beforeRender: beforeRenderType; - - /** - Runs after the Template has been compiled, but before any Transformers have been applied. - Exposes the rendered `html` string and the `config`. Must return the `html` string. - - @default undefined - - @example - ``` - module.exports = { - events: { - afterRender: async (html, config) => { - // do something with html and config - return html; - } - } - } - ``` - */ - afterRender: afterRenderType; - - /** - Runs after all Transformers have been applied, just before the final HTML is returned. - Exposes the rendered `html` string and the `config`. Must return the `html` string. - - @default undefined - - @example - ``` - module.exports = { - events: { - afterTransformers: async (html, config) => { - // do something with html and config - return html; - } - } - } - ``` - */ - afterTransformers: afterTransformersType; - - /** - Runs after all Templates have been compiled and output to disk. - The files parameter will contain the paths to all the files inside the `build.templates.destination.path` directory. - - @default undefined - - @example - ``` - module.exports = { - events: { - afterBuild: async (files, config) => { - // do something with files or config - } - } - } - ``` - */ - afterBuild: afterBuildType; -} +export type beforeCreateType = (config: object) => Promise<void>; +export type beforeRenderType = (html: string, config: object, render: (html: string, config: object) => Promise<string>) => Promise<string>; +export type afterRenderType = ({ html, config }: { html: string, config: object }) => Promise<string>; +export type afterTransformersType = ({ html, config, render }: { html: string, config: object, render: (html: string, config: object) => Promise<string> }) => Promise<string>; +export type afterBuildType = ({ files, config, render }: { files: string[], config: object, render: (html: string, config: object) => Promise<string> }) => Promise<void>; diff --git a/types/fetch.d.ts b/types/fetch.d.ts deleted file mode 100644 index 27edb09a..00000000 --- a/types/fetch.d.ts +++ /dev/null @@ -1,143 +0,0 @@ -import type {Options as GotOptions} from 'got'; -import type ExpressionsConfig from './expressions'; - -export default interface PostHTMLFetchConfig { - /** - Supported tag names. - Only tags from this array will be processed by the plugin. - - @default ['fetch', 'remote'] - - @example - ``` - module.exports = { - build: { - posthtml: { - fetch: { - tags: ['get'] - } - } - } - } - ``` - */ - tags?: string[]; - - /** - String representing the attribute name containing the URL to fetch. - - @default 'url' - - @example - ``` - module.exports = { - build: { - posthtml: { - fetch: { - attribute: 'from' - } - } - } - } - ``` - */ - attribute?: string; - - /** - `posthtml-fetch` uses `got` to fetch data. - You can pass options directly to it, inside the `got` object. - - @default {} - - @example - ``` - module.exports = { - build: { - posthtml: { - got: { - prefixUrl: '...' - } - } - } - } - ``` - */ - got?: GotOptions; - - /** - When set to `true`, this option will preserve the `tag`, i.e. `<fetch>` around the response body. - - @default false - - @example - ``` - module.exports = { - build: { - posthtml: { - fetch: { - preserveTag: true - } - } - } - } - ``` - */ - preserveTag?: boolean; - - /** - Pass options to `posthtml-expressions`. - - @default {} - - @example - ``` - module.exports = { - build: { - posthtml: { - fetch: { - expressions: { - delimiters: ['[[', ']]'] - } - } - } - } - } - ``` - */ - expressions?: ExpressionsConfig; - - /** - List of plugins that will be called after/before receiving and processing `locals`. - - @default {} - - @example - ``` - module.exports = { - build: { - posthtml: { - fetch: { - plugins: { - after(tree) { - // Your plugin implementation - }, - before: [ - tree => { - // Your plugin implementation - }, - tree => { - // .. - } - ] - } - } - } - } - } - ``` - */ - plugins?: { - after?: (tree: any) => void; - before?: Array<(tree: any) => void>; - }; -} diff --git a/types/index.d.ts b/types/index.d.ts index 4d2256ef..cfcc7432 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,90 +1,110 @@ -import type {AttributeToStyleSupportedAttributes} from './inlineCss'; -import type BaseURLConfig from './baseURL'; import type Config from './config'; -import type {CoreBeautifyOptions} from 'js-beautify'; -import type InlineCSSConfig from './inlineCss'; -import type {Options as MarkdownItOptions} from 'markdown-it'; import type MinifyConfig from './minify'; +import type PostHTMLConfig from './posthtml'; +import type { RenderOutput } from './render'; +import type MarkdownConfig from './markdown'; +import type PurgeCSSConfig from './css/purge'; import type PlaintextConfig from './plaintext'; -import type RenderOptions from './render'; -import type {RenderOutput} from './render'; -import type RemoveUnusedCSSConfig from './removeUnusedCss'; -import type URLParametersConfig from './urlParameters'; +import type CSSInlineConfig from './css/inline'; import type WidowWordsConfig from './widowWords'; +import type { BaseURLConfig } from 'posthtml-base-url'; +import type { HTMLBeautifyOptions } from 'js-beautify' +import type { URLParametersConfig } from 'posthtml-url-parameters'; +import type { AttributeToStyleSupportedAttributes } from './css/inline'; declare namespace MaizzleFramework { /** - Compile an HTML string with Maizzle. - - @param {string} html The HTML string to render. - @param {RenderOptions} [options] Options to pass to the renderer. - */ - function render(html: string, options?: RenderOptions): Promise<RenderOutput>; + * Compile an HTML string with Maizzle. + * + * @param {string} html The HTML string to render. + * @param {Config} [config] A Maizzle configuration object. + * @returns {Promise<RenderOutput>} The rendered HTML and the Maizzle configuration object. + */ + function render(html: string, config?: Config): Promise<RenderOutput>; /** - Normalize escaped character class names like `\:` or `\/` by replacing them with email-safe alternatives. - - @param {string} html The HTML string to render. - @param {object} replacements Customize replacements strategy. + * Normalize escaped character class names like `\:` or `\/` by replacing them with email-safe alternatives. + * + * @param {string} html The HTML string to normalize. + * @param {Record<string, string>} replacements A dictionary of replacements to apply. + * @returns {string} The normalized HTML string. + * @see https://maizzle.com/docs/transformers/safe-class-names */ function safeClassNames(html: string, replacements: Record<string, string>): string; /** - Compile Markdown to HTML. - - @param {string} input String to compile with Markdown. - @param {Options} [options] markdown-it options. + * Compile Markdown to HTML. + * + * @param {string} input The Markdown string to compile. + * @param {MarkdownConfig} [options] A configuration object for the Markdown compiler. + * @returns {string} The compiled HTML string. + * @see https://maizzle.com/docs/transformers/markdown */ - function markdown(input: string, options?: MarkdownItOptions): string; + function markdown(input: string, options?: MarkdownConfig): string; /** - Prevent widow words inside a tag by adding a `&nbsp;` between its last two words. - - @param {string} html The HTML string to render. - @param {WidowWordsConfig} [options] Options to pass to the transformer. - */ + * Prevent widow words inside a tag by adding a `&nbsp;` between its last two words. + * + * @param {string} html The HTML string to process. + * @param {WidowWordsConfig} [options] A configuration object for the widow words transformer. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/widows + */ function preventWidows(html: string, options?: WidowWordsConfig): string; /** - Duplicate HTML attributes to inline CSS. - - @param {string} html The HTML string to render. - @param {AttributeToStyleSupportedAttributes} [options] Options to pass to the transformer. - */ + * Duplicate HTML attributes to inline CSS. + * + * @param {string} html The HTML string to process. + * @param {AttributeToStyleSupportedAttributes[]} attributes An array of attributes to inline. + * @param {PostHTMLConfig} [posthtmlConfig] A configuration object for PostHTML. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/attribute-to-style + */ function attributeToStyle( html: string, - options?: AttributeToStyleSupportedAttributes[] + attributes: AttributeToStyleSupportedAttributes[], + posthtmlConfig?: PostHTMLConfig ): string; /** - Inline CSS styles from `<style>` tags found in `<head>`. - - @param {string} html The HTML string to render. - @param {InlineCSSConfig} [options] Options to pass to the transformer. - */ - function inlineCSS(html: string, options?: InlineCSSConfig): string; + * Inline CSS styles in an HTML string. + * + * @param {string} html The HTML string to process. + * @param {CSSInlineConfig} [options] A configuration object for the CSS inliner. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/inline-css + */ + function inlineCSS(html: string, options?: CSSInlineConfig): string; /** - Rewrite longhand CSS inside style attributes with shorthand syntax. - Only works with margin, padding and border, and only when all sides are specified. - - @param {string} html The HTML string to render. - */ + * Rewrite longhand CSS inside style attributes with shorthand syntax. + * Only works with margin, padding and border, and only when all sides are specified. + * + * @param {string} html The HTML string to process. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/shorthand-css + */ function shorthandCSS(html: string): string; /** - Remove unused CSS from `<style>` tags and HTML elements. - - @param {string} html The HTML string to use. - @param {RemoveUnusedCSSConfig} [options] Options to pass to the transformer. - */ - function removeUnusedCSS(html: string, options?: RemoveUnusedCSSConfig): string; + * Remove unused CSS from `<style>` tags and HTML elements. + * + * @param {string} html The HTML string to process. + * @param {PurgeCSSConfig} [options] A configuration object for `email-comb`. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/remove-unused-css + */ + function removeUnusedCSS(html: string, options?: PurgeCSSConfig): string; /** - Automatically remove HTML attributes. - @param {string} html The HTML string to use. - @param options Either an array of attribute names, or an array of objects with `name` and `value` properties. - */ + * Remove HTML attributes from an HTML string. + * + * @param {string} html The HTML string to process. + * @param {string[] | Array<{ name: string; value: string | RegExp }>} [options] An array of attribute names to remove, or an array of objects with `name` and `value` properties. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/remove-attributes + */ function removeAttributes( html: string, options?: @@ -96,92 +116,104 @@ declare namespace MaizzleFramework { ): string; /** - Add attributes to elements in your HTML. - - @param {string} html The HTML string to use. - @param {object} options Attributes to add. - */ + * Add attributes to elements in an HTML string. + * + * @param {string} html The HTML string to process. + * @param {Record<string, unknown>} [options] A dictionary of attributes to add. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/add-attributes + */ function addAttributes(html: string, options?: Record<string, unknown>): string; /** - Pretty print HTML code so that it's nicely indented and more human-readable. - @param {string} html The HTML string to prettify. - @param {CoreBeautifyOptions} [options] Options to pass to the prettifier. - */ - function prettify(html: string, options?: CoreBeautifyOptions): string; + * Pretty-print an HTML string. + * + * @param {string} html The HTML string to prettify. + * @param {HTMLBeautifyOptions} [options] A configuration object for `js-beautify`. + * @returns {string} The prettified HTML string. + * @see https://maizzle.com/docs/transformers/prettify + */ + function prettify(html: string, options?: HTMLBeautifyOptions): string; /** - Prepend a string to sources and hrefs in an HTML string. - - @param {string} html The HTML string to use. - @param {BaseURLConfig} [options] Options to pass to the transformer. - */ + * Prepend a string to sources and hrefs in an HTML string. + * + * @param {string} html The HTML string to process. + * @param {string | BaseURLConfig} [options] A string to prepend to sources and hrefs, or a configuration object for `posthtml-base-url`. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/base-url + */ function applyBaseURL(html: string, options?: string | BaseURLConfig): string; /** - Append parameters to URLs in an HTML string. - @param {string} html The HTML string to use. - @param {URLParametersConfig} [options] Options to pass to the transformer. - */ + * Append parameters to URLs in an HTML string. + * + * @param {string} html The HTML string to process. + * @param {URLParametersConfig} [options] A configuration object for `posthtml-url-parameters`. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/url-parameters + */ function addURLParameters(html: string, options?: URLParametersConfig): string; /** - Ensure that all your HEX colors inside `bgcolor` and `color` attributes are defined with six digits. - - @param {string} html The HTML string to use. - */ - function ensureSixHex(html: string): string; + * Ensure that all HEX colors inside `bgcolor` and `color` attributes are defined with six digits. + * + * @param {string} html The HTML string to process. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/six-hex + */ + function sixHEX(html: string): string; /** - Minify a string of HTML code. - - @param {string} html The HTML string to minify. - @param {MinifyConfig} [options] Options to pass to the minifier. - */ + * Minify an HTML string, with email client considerations. + * + * @param {string} html The HTML string to minify. + * @param {MinifyConfig} [options] A configuration object for `html-minifier`. + * @returns {string} The minified HTML string. + * @see https://maizzle.com/docs/transformers/minify + */ function minify(html: string, options?: MinifyConfig): string; /** - Batch-replace strings in an HTML string. - - @param {string} html The HTML string to use. - @param {object} replacements Strings to find and replace. - */ + * Batch-replace strings in an HTML string. + * + * @param {string} html The HTML string to process. + * @param {Record<string, string>} [replacements] A dictionary of strings to replace. + * @returns {string} The processed HTML string. + * @see https://maizzle.com/docs/transformers/replace-strings + */ function replaceStrings(html: string, replacements?: Record<string, string>): string; /** - Generate a plaintext version of an HTML string. - - @param {string} html The HTML string to use. - @param {PlaintextConfig} [options] Options to pass to the plaintext generator. - */ - function plaintext(html: string, options?: PlaintextConfig): Promise<{ - html: string; - plaintext: string; - destination: string; - }>; + * Generate a plaintext version of an HTML string. + * @param {string} html - The HTML string to convert to plaintext. + * @param {PlaintextConfig} [options] - A configuration object for the plaintext generator. + * @returns {Promise<string>} The plaintext version of the HTML string. + * @see https://maizzle.com/docs/plaintext + */ + function plaintext(html: string, options?: PlaintextConfig): Promise<string>; export { Config, - RenderOptions, - // Functions - addAttributes, - addURLParameters, - applyBaseURL, - attributeToStyle, - ensureSixHex, - inlineCSS, + render, + safeClassNames, markdown, - minify, - plaintext, preventWidows, - prettify, - removeAttributes, + attributeToStyle, + inlineCSS, + shorthandCSS, removeUnusedCSS, - render, + removeUnusedCSS as purgeCSS, + removeAttributes, + addAttributes, + prettify, + applyBaseURL, + addURLParameters as addUrlParams, + sixHEX, + minify, replaceStrings, - safeClassNames, - shorthandCSS - }; + plaintext, + } } export = MaizzleFramework; diff --git a/types/inlineCss.d.ts b/types/inlineCss.d.ts deleted file mode 100644 index 0540851b..00000000 --- a/types/inlineCss.d.ts +++ /dev/null @@ -1,207 +0,0 @@ -export type AttributeToStyleSupportedAttributes = - | 'width' - | 'height' - | 'bgcolor' - | 'background' - | 'align' - | 'valign'; - -export default interface InlineCSSConfig { - /** - Which CSS properties should be duplicated as what HTML attributes. - - @default {} - - @example - ``` - module.exports = { - build: { - inlineCSS: { - styleToAttribute: { - 'background-color': 'bgcolor', - } - } - } - } - ``` - */ - styleToAttribute?: Record<string, string>; - - /** - Duplicate HTML attributes to inline CSS. - - @default false - - @example - ``` - module.exports = { - build: { - inlineCSS: { - attributeToStyle: ['width', 'bgcolor', 'background'] - } - } - } - ``` - */ - attributeToStyle?: boolean | AttributeToStyleSupportedAttributes[]; - - /** - HTML elements that will receive `width` attributes based on inline CSS width. - - @default [] - - @example - ``` - module.exports = { - build: { - inlineCSS: { - applyWidthAttributes: ['td', 'th'] - } - } - } - ``` - */ - applyWidthAttributes?: string[]; - - /** - HTML elements that will receive `height` attributes based on inline CSS height. - - @default [] - - @example - ``` - module.exports = { - build: { - inlineCSS: { - applyHeightAttributes: ['td', 'th'] - } - } - } - ``` - */ - applyHeightAttributes?: string[]; - - /** - List of elements that should only use `width` and `height`. Their inline CSS `width` and `height` will be removed. - - @example - ``` - module.exports = { - inlineCSS: { - keepOnlyAttributeSizes: { - width: ['img', 'video'], - height: ['img', 'video'] - } - } - } - ``` - */ - keepOnlyAttributeSizes?: { - /** - List of elements that should only use the `width` HTML attribute (inline CSS width will be removed). - - @default [] - - @example - ``` - module.exports = { - inlineCSS: { - keepOnlyAttributeSizes: { - width: ['img', 'video'], - } - } - } - ``` - */ - width?: string[]; - /** - List of elements that should only use the `height` HTML attribute (inline CSS height will be removed). - - @default [] - - @example - ``` - module.exports = { - inlineCSS: { - keepOnlyAttributeSizes: { - height: ['img', 'video'] - } - } - } - ``` - */ - height?: string[]; - }; - - /** - Remove inlined `background-color` CSS on elements containing a `bgcolor` HTML attribute. - - @default false - - @example - ``` - module.exports = { - inlineCSS: { - preferBgColorAttribute: ['td'] // default: ['body', 'marquee', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr'] - } - } - ``` - */ - preferBgColorAttribute?: boolean | string[]; - - /** - Array of CSS property names that should be excluded from the CSS inlining process. `--tw-shadow` is excluded by default. - - @default [] - - @example - ``` - module.exports = { - inlineCSS: { - excludedProperties: ['padding', 'padding-left'] - } - } - ``` - */ - excludedProperties?: string[]; - - /** - An object where each value has a `start` and `end` to specify fenced code blocks that should be ignored during CSS inlining. - - @default {EJS: {}, HBS: {}} - - @example - ``` - module.exports = { - EJS: { start: '<%', end: '%>' }, - HBS: { start: '{{', end: '}}' }, - } - ``` - */ - codeBlocks?: { - EJS?: Record<string, string>; - HBS?: Record<string, string>; - }; - - /** - Provide your own CSS to be inlined. Must be vanilla or pre-compiled CSS. - - Existing `<style>` in your HTML tags will be ignored and their contents won't be inlined. - - @default undefined - - @example - ``` - module.exports = { - inlineCSS: { - customCSS: ` - .custom-class { - color: red; - } - ` - } - } - ``` - */ - customCSS?: string; -} diff --git a/types/layouts.d.ts b/types/layouts.d.ts deleted file mode 100644 index 99f7ff60..00000000 --- a/types/layouts.d.ts +++ /dev/null @@ -1,39 +0,0 @@ -export default interface LayoutsConfig { - /** - Encoding to be used when reading a layout file from disk. - - @default 'utf8' - */ - encoding?: string; - - /** - Name of the slot tag, where the content will be injected. - This is typically used in a Layout file, to define the place where to inject a Template. - - @default 'block' - */ - slotTagName?: string; - - /** - Name of the fill tag, inside of which content that will be injected is defined. - This is typically used in a Template file, to extend a Layout. - - @default 'block' - */ - fillTagName?: string; - - /** - Path to the layouts folder, relative to the project root. - - @default 'src/layouts' - */ - root?: string; - - /** - Tag name to be used in HTML when extending a layout. - - @default 'extends' - */ - tagName?: string; - -} diff --git a/types/markdown.d.ts b/types/markdown.d.ts index 40b661f5..8f304492 100644 --- a/types/markdown.d.ts +++ b/types/markdown.d.ts @@ -1,31 +1,33 @@ -import type {Options as MarkdownItOptions} from 'markdown-it'; +import type { Options as MarkdownItOptions } from 'markdown-it'; export default interface MarkdownConfig { /** - Path relative to which markdown files are imported. - - @default './' - */ + * Path relative to which markdown files are imported. + * + * @default './' + */ root?: string; /** - Encoding for imported Markdown files. - - @default 'utf8' - */ + * Encoding for imported Markdown files. + * + * @default 'utf8' + */ encoding?: string; /** - Options to pass to the `markdown-it` library. - - @default {} - */ + * Options to pass to the `markdown-it` library. + * + * @default {} + */ markdownit?: MarkdownItOptions; /** - Plugins for the `markdown-it` library. - - @default [] - */ - plugins?: any[]; + * Plugins for the `markdown-it` library. + * @default [] + */ + plugins?: Array<{ + plugin: string; + options: Record<string, unknown>; + }>; } diff --git a/types/minify.d.ts b/types/minify.d.ts index 3bd50956..48e37b0e 100644 --- a/types/minify.d.ts +++ b/types/minify.d.ts @@ -1,136 +1,138 @@ +import type { Opts } from 'html-crush'; + export default interface MinifyConfig { /** - Maximum line length. Works only when `removeLineBreaks` is `true`. - - @default 500 - */ - lineLengthLimit?: number; + * Maximum line length. Works only when `removeLineBreaks` is `true`. + * + * @default 500 + */ + lineLengthLimit?: Opts['lineLengthLimit']; /** - Remove all line breaks from HTML when minifying. - - @default true - */ - removeLineBreaks?: boolean; + * Remove all line breaks from HTML when minifying. + * + * @default true + */ + removeLineBreaks?: Opts['removeLineBreaks']; /** - Remove code indentation when minifying HTML. - - @default true + * Remove code indentation when minifying HTML. + * + * @default true */ - removeIndentations?: boolean; + removeIndentations?: Opts['removeIndentations']; /** - Remove `<!-- HTML comments -->` when minifying HTML. - - `0` - don't remove any HTML comments - - `1` - remove all comments except Outlook conditional comments - - `2` - remove all comments, including Outlook conditional comments - - @default false - */ - removeHTMLComments?: boolean | number; + * Remove `<!-- HTML comments -->` when minifying HTML. + * + * `0` - don't remove any HTML comments + * + * `1` - remove all comments except Outlook conditional comments + * + * `2` - remove all comments, including Outlook conditional comments + * + * @default false + */ + removeHTMLComments?: Opts['removeHTMLComments']; /** - Remove CSS comments when minifying HTML. - - @default true - */ - removeCSSComments?: boolean; + * Remove CSS comments when minifying HTML. + * + * @default true + */ + removeCSSComments?: Opts['removeCSSComments']; /** - When any of given strings are encountered and `removeLineBreaks` is true, current line will be terminated. - - @default - [ - '</td', - '<html', - '</html', - '<head', - '</head', - '<meta', - '<link', - '<table', - '<script', - '</script', - '<!DOCTYPE', - '<style', - '</style', - '<title', - '<body', - '@media', - '</body', - '<!--[if', - '<!--<![endif', - '<![endif]' - ] - */ - breakToTheLeftOf?: string[] | boolean | null; + * When any of given strings are encountered and `removeLineBreaks` is true, current line will be terminated. + * + * @default + * [ + * '</td', + * '<html', + * '</html', + * '<head', + * '</head', + * '<meta', + * '<link', + * '<table', + * '<script', + * '</script', + * '<!DOCTYPE', + * '<style', + * '</style', + * '<title', + * '<body', + * '@media', + * '</body', + * '<!--[if', + * '<!--<![endif', + * '<![endif]' + * ] + */ + breakToTheLeftOf?: Opts['breakToTheLeftOf']; /** - Some inline tags can accidentally introduce extra text. - The minifier will take extra precaution when minifying around these tags. - - @default - [ - 'a', - 'abbr', - 'acronym', - 'audio', - 'b', - 'bdi', - 'bdo', - 'big', - 'br', - 'button', - 'canvas', - 'cite', - 'code', - 'data', - 'datalist', - 'del', - 'dfn', - 'em', - 'embed', - 'i', - 'iframe', - 'img', - 'input', - 'ins', - 'kbd', - 'label', - 'map', - 'mark', - 'meter', - 'noscript', - 'object', - 'output', - 'picture', - 'progress', - 'q', - 'ruby', - 's', - 'samp', - 'script', - 'select', - 'slot', - 'small', - 'span', - 'strong', - 'sub', - 'sup', - 'svg', - 'template', - 'textarea', - 'time', - 'u', - 'tt', - 'var', - 'video', - 'wbr' - ] - */ - mindTheInlineTags?: string[] | boolean | null; + * Some inline tags can accidentally introduce extra text. + * The minifier will take extra precaution when minifying around these tags. + * + * @default + * [ + * 'a', + * 'abbr', + * 'acronym', + * 'audio', + * 'b', + * 'bdi', + * 'bdo', + * 'big', + * 'br', + * 'button', + * 'canvas', + * 'cite', + * 'code', + * 'data', + * 'datalist', + * 'del', + * 'dfn', + * 'em', + * 'embed', + * 'i', + * 'iframe', + * 'img', + * 'input', + * 'ins', + * 'kbd', + * 'label', + * 'map', + * 'mark', + * 'meter', + * 'noscript', + * 'object', + * 'output', + * 'picture', + * 'progress', + * 'q', + * 'ruby', + * 's', + * 'samp', + * 'script', + * 'select', + * 'slot', + * 'small', + * 'span', + * 'strong', + * 'sub', + * 'sup', + * 'svg', + * 'template', + * 'textarea', + * 'time', + * 'u', + * 'tt', + * 'var', + * 'video', + * 'wbr' + * ] + */ + mindTheInlineTags?: Opts['mindTheInlineTags']; } diff --git a/types/plaintext.d.ts b/types/plaintext.d.ts index 2b581307..cc2e9699 100644 --- a/types/plaintext.d.ts +++ b/types/plaintext.d.ts @@ -1,62 +1,56 @@ -import type {Opts as PlaintextOptions} from 'string-strip-html'; +import type { Opts as PlaintextOptions } from 'string-strip-html'; export default interface PlaintextConfig extends PlaintextOptions { /** - Configure where plaintext files should be output. - - @example - ``` - module.exports = { - build: { - plaintext: { - destination: { - path: 'dist/brand/plaintext', - extension: 'rtxt' - } - } - } - } - ``` - */ - destination?: { + * Configure where plaintext files should be output. + * + * @example + * ``` + * export default { + * plaintext: { + * output: { + * path: 'dist/brand/plaintext', + * extension: 'rtxt' + * } + * } + * } + * ``` + */ + output?: { /** - Directory where Maizzle should output compiled Plaintext files. - - @default 'build_{env}' - - @example - ``` - module.exports = { - build: { - plaintext: { - destination: { - path: 'dist/brand/plaintext' - } - } - } - } - ``` - */ + * Directory where Maizzle should output compiled Plaintext files. + * + * @default 'build_{env}' + * + * @example + * ``` + * export default { + * plaintext: { + * output: { + * path: 'dist/brand/plaintext' + * } + * } + * } + * ``` + */ path?: string; /** - File extension to be used for compiled Plaintext files. - - @default 'txt' - - @example - ``` - module.exports = { - build: { - plaintext: { - destination: { - extension: 'rtxt' - } - } - } - } - ``` - */ + * File extension to be used for compiled Plaintext files. + * + * @default 'txt' + * + * @example + * ``` + * export default { + * plaintext: { + * output: { + * extension: 'rtxt' + * } + * } + * } + * ``` + */ extension: string; }; } diff --git a/types/posthtml.d.ts b/types/posthtml.d.ts index 99f37149..f78b54f3 100644 --- a/types/posthtml.d.ts +++ b/types/posthtml.d.ts @@ -1,128 +1,128 @@ -import type PostHTMLFetchConfig from './fetch'; +import type { Directive } from 'posthtml-parser'; import type ExpressionsConfig from './expressions'; export interface PostHTMLOptions { /** - Configure the PostHTML parser to process custom directives. - - @default [] - */ - directives?: any[]; + * Configure the PostHTML parser to process custom directives. + * + * @default [] + */ + directives?: Directive[]; /** - Enable `xmlMode` if you're using Maizzle to output XML content, and not actual HTML. - - @default false - */ + * Enable `xmlMode` if you're using Maizzle to output XML content, and not actual HTML. + * + * @default false + */ xmlMode?: boolean; /** - Decode entities in the HTML. - - @default false - */ + * Decode entities in the HTML. + * + * @default false + */ decodeEntities?: boolean; /** - Output all tags in lowercase. Works only when `xmlMode` is disabled. - - @default false - */ + * Output all tags in lowercase. Works only when `xmlMode` is disabled. + * + * @default false + */ lowerCaseTags?: boolean; /** - Output all attribute names in lowercase. - - @default false - */ + * Output all attribute names in lowercase. + * + * @default false + */ lowerCaseAttributeNames?: boolean; /** - Recognize CDATA sections as text even if the `xmlMode` option is disabled. - - @default false - */ + * Recognize CDATA sections as text even if the `xmlMode` option is disabled. + * + * @default false + */ recognizeCDATA?: boolean; /** - Recognize self-closing tags. - Disabling this will cause rendering to stop at the first self-closing custom (non-HTML) tag. - - @default true - */ + * Recognize self-closing tags. + * Disabling this will cause rendering to stop at the first self-closing custom (non-HTML) tag. + * + * @default true + */ recognizeSelfClosing?: boolean; /** - If enabled, AST nodes will have a location property containing the `start` and `end` line and column position of the node. - - @default false - */ + * If enabled, AST nodes will have a location property containing the `start` and `end` line and column position of the node. + * + * @default false + */ sourceLocations?: boolean; /** - Whether attributes with no values should render exactly as they were written, without `=""` appended. - - @default true - */ + * Whether attributes with no values should render exactly as they were written, without `=""` appended. + * + * @default true + */ recognizeNoValueAttribute?: boolean; /** - Tell PostHTML to treat custom tags as self-closing. - - @default [] - */ + * Make PostHTML to treat custom tags as self-closing. + * + * @default [] + */ singleTags?: string[] | RegExp[]; /** - Define the closing format for single tags. - - @default 'default' - */ + * Define the closing format for single tags. + * + * @default 'default' + */ closingSingleTag?: 'tag' | 'slash'; /** - Whether to quote all attribute values. - - @default true - */ + * Whether to quote all attribute values. + * + * @default true + */ quoteAllAttributes?: boolean; /** - Replaces quotes in attribute values with `&quote;`. - - @default true - */ + * Replaces quotes in attribute values with `&quote;`. + * + * @default true + */ replaceQuote?: boolean; /** - Specify the style of quote around the attribute values. - - @default 2 - - @example - - `0` - Quote style is based on attribute values (an alternative for `replaceQuote` option) - - ``` - <img src="example.jpg" onload='testFunc("test")'> - ``` - - @example - - `1` - Attribute values are wrapped in single quotes - - ``` - <img src='example.jpg' onload='testFunc("test")'> - ``` - - @example - - `2` - Attribute values are wrapped in double quotes - - ``` - <img src="example.jpg" onload="testFunc("test")"> - ``` - */ + * Specify the style of quote around the attribute values. + * + * @default 2 + * + * @example + * + * `0` - Quote style is based on attribute values (an alternative for `replaceQuote` option) + * + * ``` + * <img src="example.jpg" onload='testFunc("test")'> + * ``` + * + * @example + * + * `1` - Attribute values are wrapped in single quotes + * + * ``` + * <img src='example.jpg' onload='testFunc("test")'> + * ``` + * + * @example + * + * `2` - Attribute values are wrapped in double quotes + * + * ``` + * <img src="example.jpg" onload="testFunc("test")"> + * ``` + */ quoteStyle?: 0 | 1 | 2; } @@ -138,58 +138,25 @@ export default interface PostHTMLConfig { options?: PostHTMLOptions; /** - Additional PostHTML plugins that you would like to use. - - These will run last, after components. - - @default [] - - @example - ``` - const spaceless = require('posthtml-spaceless') - module.exports = { - build: { - posthtml: { - plugins: [ - spaceless() - ] - } - } - } - ``` - */ - plugins?: any[]; - - /** - Configure the `posthtml-mso` plugin. - */ - outlook?: { + * PostHTML plugins to apply before or after Maizzle's own plugins. + * + * @example + * ``` + * import spaceless from 'posthtml-spaceless' + * export default { + * posthtml: { + * plugins: [ + * spaceless() + * ] + * } + * } + * ``` + */ + plugins?: { + before: Array<() => void>; /** - The tag name to use for Outlook conditional comments. - - @default 'outlook' - - @example - ``` - module.exports = { - build: { - posthtml: { - outlook: { - tag: 'mso' - } - } - } - } - // You now write <mso>...</mso> instead of <outlook>...</outlook> - ``` - */ - tag?: string; - }; - - /** - Configure the `<fetch>` tag behavior. - - @default {} - */ - fetch?: PostHTMLFetchConfig; + * Plugins to apply after Maizzle's own plugins. + */ + after: Array<() => void>; + } | (() => void)[]; } diff --git a/types/removeUnusedCss.d.ts b/types/removeUnusedCss.d.ts deleted file mode 100644 index 66f9694a..00000000 --- a/types/removeUnusedCss.d.ts +++ /dev/null @@ -1,115 +0,0 @@ -export default interface RemoveUnusedCSSConfig { - /** - Classes or IDs that you don't want removed. - - @default [] - - @example - ``` - module.exports = { - removeUnusedCSS: { - whitelist: ['.some-class', '.Mso*', '#*'], - } - } - ``` - */ - whitelist?: string[]; - - /** - Start and end delimiters for computed classes that you don't want removed. - - @default [{heads: '{{', tails: '}}'}, {heads: '{%', tails: '%}'}] - - @example - ``` - module.exports = { - removeUnusedCSS: { - backend: [ - { heads: '[[', tails: ']]' }, - ] - } - } - ``` - */ - backend?: Array<Record<string, string>>; - - /** - Whether to remove `<!-- HTML comments -->`. - - @default true - - @example - ``` - module.exports = { - removeUnusedCSS: { - removeHTMLComments: false - } - } - ``` - */ - removeHTMLComments?: boolean; - - /** - Whether to remove `/* CSS comments *\/`. - - @default true - - @example - ``` - module.exports = { - removeUnusedCSS: { - removeCSSComments: false - } - } - ``` - */ - removeCSSComments?: boolean; - - /** - Whether to remove classes that have been inlined. - - @default undefined - - @example - ``` - module.exports = { - removeUnusedCSS: { - removeInlinedSelectors: false, - } - } - ``` - */ - removeInlinedSelectors?: boolean; - - /** - List of strings representing start of a conditional comment that should not be removed. - - @default ['[if', '[endif'] - - @example - ``` - module.exports = { - removeUnusedCSS: { - doNotRemoveHTMLCommentsWhoseOpeningTagContains: ['[if', '[endif'] - } - } - ``` - */ - doNotRemoveHTMLCommentsWhoseOpeningTagContains: string[]; - - /** - Rename all classes and IDs in both your `<style>` tags and your body HTML elements, to be as few characters as possible. - - @default false - - @example - ``` - module.exports = { - removeUnusedCSS: { - uglify: true - } - } - ``` - */ - uglify?: boolean; -} diff --git a/types/render.d.ts b/types/render.d.ts index 9e0fb745..19f95d55 100644 --- a/types/render.d.ts +++ b/types/render.d.ts @@ -1,10 +1,4 @@ -import { - beforeRenderType, - afterRenderType, - afterTransformersType -} from './events'; import type Config from './config'; -import type TailwindConfig from './tailwind'; export type RenderOutput = { /** @@ -17,114 +11,3 @@ export type RenderOutput = { */ config: Config; }; - -export default interface RenderOptions { - /** - A Maizzle configuration object. - - @default {} - - @example - ``` - const Maizzle = require('@maizzle/framework'); - - Maizzle - .render(`html string`, { - maizzle: { - inlineCSS: true, - } - }) - .then(({html, config}) => console.log(html, config)) - ``` - */ - maizzle: Config; - - /** - Tailwind CSS configuration object. - - @default {} - - @example - ``` - const Maizzle = require('@maizzle/framework'); - - Maizzle - .render(`html string`, { - tailwind: { - config: './tailwind-custom.config.js', - }, - }) - .then(({html, config}) => console.log(html, config)) - ``` - */ - tailwind?: TailwindConfig; - - /** - A function that runs after the Template's config has been computed, but just before it is compiled. - - It exposes the Template's config, as well as the HTML. - - @default undefined - - @example - ``` - const Maizzle = require('@maizzle/framework'); - - Maizzle - .render(`html string`, { - beforeRender: (html, config) => { - // do something with html and config - return html; - }, - }) - .then(({html, config}) => console.log(html, config)) - ``` - */ - beforeRender?: beforeRenderType; - - /** - A function that runs after the Template has been compiled, but before any Transformers have been applied. - - Exposes the rendered html string and the Templates' config. - - @default undefined - - @example - ``` - const Maizzle = require('@maizzle/framework'); - - Maizzle - .render(`html string`, { - afterRender: (html, config) => { - // do something with html and config - return html; - }, - }) - .then(({html, config}) => console.log(html, config)) - ``` - */ - afterRender?: afterRenderType; - - /** - A function that runs after all Transformers have been applied, just before the final HTML is returned. - - It exposes the Template's config, as well as the HTML. - - @default undefined - - @example - ``` - const Maizzle = require('@maizzle/framework'); - - Maizzle - .render(`html string`, { - afterTransformers: (html, config) => { - // do something with html and config - return html; - }, - }) - .then(({html, config}) => console.log(html, config)) - ``` - */ - afterTransformers?: afterTransformersType; -} diff --git a/types/tailwind.d.ts b/types/tailwind.d.ts deleted file mode 100644 index 75503666..00000000 --- a/types/tailwind.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -export default interface TailwindConfig { - /** - Path to the Tailwind config file. - - @default 'tailwind.config.js' - */ - config?: string; - - /** - Path to your main CSS file, that will be compiled with Tailwind CSS. - - @default 'src/css/tailwind.css' - */ - css?: string; - - /** - Pre-compiled CSS. Skip Tailwind CSS processing by providing your own CSS string. - - @default '' - */ - compiled?: string; -} diff --git a/types/templates.d.ts b/types/templates.d.ts deleted file mode 100644 index 2e22ccb1..00000000 --- a/types/templates.d.ts +++ /dev/null @@ -1,181 +0,0 @@ -import type Config from './config'; -import type PlaintextConfig from './plaintext'; - -export default interface TemplatesConfig { - /** - Directory where Maizzle should look for Templates to compile. - - @default 'src/templates' - - @example - ``` - module.exports = { - build: { - templates: { - source: 'src/templates' - } - } - } - ``` - */ - source?: - | string - | Array<string | TemplatesConfig> - | ((config: Config) => string | string[]); - - /** - Define what file extensions your Templates use. - Maizzle will only compile files from your `source` directory that have these extensions. - - @default 'html' - - @example - ``` - module.exports = { - build: { - templates: { - filetypes: ['html', 'blade.php'] - } - } - } - ``` - */ - filetypes?: string | string[]; - - /** - Define the output path for compiled Templates, and what file extension they should use. - - @example - ``` - module.exports = { - build: { - templates: { - destination: { - path: 'build_production', - extension: 'html' - } - } - } - } - ``` - */ - destination?: { - /** - Directory where Maizzle should output compiled Templates. - - @default 'build_{env}' - */ - path?: string; - /** - File extension to be used for compiled Templates. - - @default 'html' - */ - extension: string; - }; - - /** - * Source and destination directories for your asset files. - * - * @example - * ``` - * module.exports = { - * build: { - * templates: { - * assets: { - * source: 'src/images', - * destination: 'images' - * } - * } - * } - * } - * ``` - */ - assets?: { - /** - * Directory where Maizzle should look for asset files. - * - * @default '' - */ - source?: string; - /** - * Directory where asset files should be copied to. - * - * @default 'assets' - */ - destination?: string; - } | { - /** - * An array of objects specifying source and destination directories for asset files. - */ - assets: Array<{ - /** - * Directory where Maizzle should look for asset files. - */ - source: string; - /** - * Directory where asset files should be copied to. - */ - destination: string; - }>; - }; - - /** - Configure plaintext generation. - - @example - ``` - module.exports = { - build: { - plaintext: { - skipHtmlDecoding: true, - destination: { - path: 'dist/brand/plaintext', - extension: 'rtxt' - } - } - } - } - ``` - */ - plaintext?: boolean | PlaintextConfig; - - /** - Paths to files or directories from your `source` that should _not_ be copied over to the build destination. - - @default [''] - - @example - ``` - module.exports = { - build: { - templates: { - source: 'src/templates', - omit: ['1.html', 'archive/4.html'], - } - } - } - ``` - */ - omit?: string[]; - - /** - Paths to files relative to your `source` directory that should not be parsed. - They will be copied over to the build destination as-is. - - @default [''] - - @example - ``` - module.exports = { - build: { - templates: { - source: 'src/templates', - skip: ['1.html', 'archive/3.html'], - } - } - } - ``` - */ - skip?: string | string[]; -} diff --git a/types/urlParameters.d.ts b/types/urlParameters.d.ts index e44a9760..3ccb4f29 100644 --- a/types/urlParameters.d.ts +++ b/types/urlParameters.d.ts @@ -1,27 +1,28 @@ -import type {StringifyOptions} from 'query-string'; +import type { URLParametersConfig as URLParamsConfig } from 'posthtml-url-parameters'; export default interface URLParametersConfig { - [key: string]: any; + [key: string]: any; // eslint-disable-line _options?: { /** - Array of tag names to process. Only URLs inside `href` attributes of tags in this array will be processed. - - @default ['a'] - - @example - ``` - module.exports = { - urlParameters: { - _options: { - tags: ['a[href*="example.com"]'], - }, - utm_source: 'maizzle', - } - } - ``` - */ - tags?: string[]; + * Array of tag names to process. Only URLs inside `href` attributes + * of tags in this array will be processed. + * + * @default ['a'] + * + * @example + * ``` + * export default { + * urlParameters: { + * _options: { + * tags: ['a[href*="example.com"]'], + * }, + * utm_source: 'maizzle', + * } + * } + * ``` + */ + tags?: URLParamsConfig['tags']; /** By default, query parameters are appended only to valid URLs. @@ -34,6 +35,6 @@ export default interface URLParametersConfig { /** Options to pass to the `query-string` library. */ - qs?: StringifyOptions; + qs?: URLParamsConfig['qs']; }; } diff --git a/types/widowWords.d.ts b/types/widowWords.d.ts index 0b364730..01937669 100644 --- a/types/widowWords.d.ts +++ b/types/widowWords.d.ts @@ -1,3 +1,5 @@ +import type { Opts } from 'string-remove-widows'; + export default interface WidowWordsConfig { /** The attribute name to use. @@ -12,45 +14,45 @@ export default interface WidowWordsConfig { @default false */ - removeWindowPreventionMeasures?: boolean; + removeWidowPreventionMeasures?: Opts['removeWidowPreventionMeasures']; /** Convert the space entity to the `targetLanguage`. @default true */ - convertEntities?: boolean; + convertEntities?: Opts['convertEntities']; /** Language to encode non-breaking spaces in. @default 'html' */ - targetLanguage?: 'html' | 'css' | 'js'; + targetLanguage?: Opts['targetLanguage']; /** Should whitespace in front of dashes (-), n-dashes (–) or m-dashes (—) be replaced with a `&nbsp;`. @default true */ - hyphens?: boolean; + hyphens?: Opts['hyphens']; /** The minimum amount of words in a target string, in order to trigger the transformer. @default 3 */ - minWordCount?: number; + minWordCount?: Opts['minWordCount']; /** The minimum amount non-whitespace characters in a target string, in order to trigger the transformer. @default 20 */ - minCharCount?: number; + minCharCount?: Opts['minCharCount']; /** Start/end pairs of strings that will prevent the transformer from removing widow words inside them. */ - ignore?: string | string[]; + ignore?: Opts['ignore']; } diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 00000000..accd0259 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + include: ['test/*test.js'], + testTimeout: 10000, + }, +})