@nutin/cli 1.3.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +89 -9
- package/README.md +20 -35
- package/bin/add-feature.mjs +9 -0
- package/bin/cli.mjs +8 -0
- package/bin/create-app.mjs +5 -4
- package/bin/update-app.mjs +9 -0
- package/lib/index.mjs +76 -25
- package/lib/src/add-feature/feature-adder.mjs +83 -0
- package/lib/src/add-feature/feature-context-builder.mjs +25 -0
- package/lib/src/add-feature/nutin-config-updater.mjs +29 -0
- package/lib/src/add-feature/package-json-updater.mjs +49 -0
- package/lib/src/common/feature-registry.mjs +11 -0
- package/lib/src/common/file-generator.mjs +159 -0
- package/lib/src/common/meta-bootstrap-prompt.mjs +33 -0
- package/lib/src/common/package-data.mjs +10 -0
- package/lib/src/common/package-json-helper.mjs +103 -0
- package/lib/src/common/project-meta.mjs +54 -0
- package/lib/src/create-app/context-builder.mjs +21 -0
- package/lib/src/{git-manager.mjs → create-app/git-manager.mjs} +2 -2
- package/lib/src/create-app/json-manager.mjs +73 -0
- package/lib/src/{prompts.mjs → create-app/new-app-prompt.mjs} +6 -6
- package/lib/src/{project-generator.mjs → create-app/project-generator.mjs} +10 -8
- package/lib/src/create-app/success-message.mjs +14 -0
- package/lib/src/update-app/conflict-report-writer.mjs +31 -0
- package/lib/src/update-app/fetch-old-templates.mjs +61 -0
- package/lib/src/update-app/project-updater.mjs +136 -0
- package/lib/src/update-app/template-differ.mjs +124 -0
- package/lib/src/update-app/update-context-builder.mjs +25 -0
- package/lib/src/update-app/update-summary-printer.mjs +22 -0
- package/lib/src/update-app/version-compare.mjs +12 -0
- package/lib/src/utils/print.mjs +36 -0
- package/lib/src/utils/promise-exec-alias.mjs +4 -0
- package/package.json +17 -12
- package/templates/base/.gitignore.hbs +6 -1
- package/templates/base/AGENTS.md.hbs +169 -0
- package/templates/base/GETTING_STARTED.md.hbs +227 -0
- package/templates/base/README.md.hbs +8 -17
- package/templates/base/config/languages.json.hbs +6 -0
- package/templates/base/config/seo.json.hbs +12 -0
- package/templates/base/nutin.config.js.hbs +51 -0
- package/templates/base/src/app/components/index.ts.hbs +1 -2
- package/templates/base/src/app/globals.d.ts.hbs +3 -19
- package/templates/base/src/{libs/guards → app}/guards.ts.hbs +1 -5
- package/templates/base/src/app/main.ts.hbs +7 -26
- package/templates/base/src/app/services/index.ts.hbs +1 -1
- package/templates/base/src/app/views/home/home.view.html.hbs +7 -0
- package/templates/base/src/app/views/home/home.view.ts.hbs +1 -56
- package/templates/base/src/app/views/index.ts.hbs +1 -0
- package/templates/base/src/app/views/not-found/not-found.view.html.hbs +8 -0
- package/templates/base/src/app/views/not-found/not-found.view.ts.hbs +4 -37
- package/templates/base/src/core/base-classes/base-component/base-component.test.js.hbs +158 -0
- package/templates/base/src/core/base-classes/base-component/base-component.ts.hbs +68 -35
- package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.test.js.hbs +124 -0
- package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.ts.hbs +9 -8
- package/templates/base/src/core/base-classes/base-component/helpers/children.helper.test.js.hbs +74 -0
- package/templates/base/src/core/base-classes/base-component/helpers/children.helper.ts.hbs +1 -1
- package/templates/base/src/core/base-classes/base-component/helpers/dom.helper.test.js.hbs +145 -0
- package/templates/base/src/core/base-classes/base-component/helpers/dom.helper.ts.hbs +7 -1
- package/templates/base/src/core/base-classes/base-component/helpers/event.helper.test.js.hbs +88 -0
- package/templates/base/src/core/base-classes/base-component/helpers/event.helper.ts.hbs +2 -2
- package/templates/base/src/core/base-classes/base-component/helpers/i18n.helper.test.js.hbs +62 -0
- package/templates/base/src/core/base-classes/base-component/helpers/pipe.helper.test.js.hbs +82 -0
- package/templates/base/src/core/base-classes/base-component/helpers/security.helper.test.js.hbs +142 -0
- package/templates/base/src/core/base-classes/base-component/helpers/security.helper.ts.hbs +67 -22
- package/templates/base/src/core/base-classes/base-component/helpers/token.helper.test.js.hbs +183 -0
- package/templates/base/src/core/base-classes/component/component.test.js.hbs +85 -0
- package/templates/base/src/core/base-classes/component/component.ts.hbs +24 -33
- package/templates/base/src/core/base-classes/component/helpers/config.helper.test.js.hbs +58 -0
- package/templates/base/src/core/base-classes/component/helpers/data-binding.helper.test.js.hbs +75 -0
- package/templates/base/src/core/base-classes/service/service.test.js.hbs +150 -0
- package/templates/base/src/core/base-classes/service/service.ts.hbs +26 -20
- package/templates/base/src/core/base-classes/view/view.test.js.hbs +74 -0
- package/templates/base/src/core/base-classes/view/view.ts.hbs +17 -41
- package/templates/base/src/core/config.ts.hbs +7 -0
- package/templates/base/src/core/index.ts.hbs +0 -3
- package/templates/base/src/core/internals.d.ts.hbs +27 -0
- package/templates/base/src/core/nutin-config.d.ts.hbs +4 -0
- package/templates/base/src/core/services/event-bus/event-bus.test.js.hbs +67 -3
- package/templates/base/src/core/services/event-bus/event-bus.ts.hbs +9 -4
- package/templates/base/src/core/services/event-bus/index.ts.hbs +3 -0
- package/templates/base/src/core/services/event-bus/lifecycle.facade.test.js.hbs +123 -0
- package/templates/base/src/core/services/event-bus/lifecycle.facade.ts.hbs +61 -0
- package/templates/base/src/core/services/event-bus/navigation.facade.test.js.hbs +46 -0
- package/templates/base/src/core/services/event-bus/navigation.facade.ts.hbs +25 -0
- package/templates/base/src/core/services/globals/globals.test.js.hbs +149 -0
- package/templates/base/src/core/services/globals/globals.ts.hbs +95 -0
- package/templates/base/src/core/services/http-client/helpers/http-builder.helper.test.js.hbs +25 -0
- package/templates/base/src/core/services/http-client/helpers/http-manager.helper.test.js.hbs +20 -0
- package/templates/base/src/core/services/http-client/http-client.test.js.hbs +43 -0
- package/templates/base/src/core/services/i18n/i18n.test.js.hbs +270 -0
- package/templates/{features/i18n → base}/src/core/services/i18n/i18n.ts.hbs +22 -4
- package/templates/base/src/core/services/index.ts.hbs +5 -6
- package/templates/base/src/core/services/pipe-registry/pipe-registry.test.js.hbs +60 -1
- package/templates/base/src/core/services/pipe-registry/pipe-registry.ts.hbs +1 -1
- package/templates/base/src/core/services/pipe-registry/pipes.test.js.hbs +128 -0
- package/templates/base/src/{libs/pipes → core/services/pipe-registry}/pipes.ts.hbs +8 -5
- package/templates/base/src/core/services/router/helpers/navigation-manager.helper.test.js.hbs +149 -6
- package/templates/base/src/core/services/router/helpers/navigation-manager.helper.ts.hbs +40 -29
- package/templates/base/src/core/services/router/helpers/route-guard-manager.helper.test.js.hbs +27 -0
- package/templates/base/src/core/services/router/helpers/view-render-manager.helper.test.js.hbs +83 -17
- package/templates/base/src/core/services/router/helpers/view-render-manager.helper.ts.hbs +14 -38
- package/templates/base/src/core/services/router/router.test.js.hbs +226 -2
- package/templates/base/src/core/services/router/router.ts.hbs +40 -8
- package/templates/base/src/index.html.hbs +2 -6
- package/templates/base/src/styles/_styles.scss.hbs +102 -43
- package/templates/base/src/styles/base/_variables.scss.hbs +1 -86
- package/templates/base/src/styles/main.scss.hbs +1 -18
- package/templates/base/src/styles/tailwind.css.hbs +2 -0
- package/templates/base/tools/builder/builder.config.js.hbs +40 -0
- package/templates/base/tools/builder/builder.js.hbs +24 -26
- package/templates/base/tools/builder/core/app/binary-extensions.test.js.hbs +16 -0
- package/templates/base/tools/builder/core/app/compile-ts.js.hbs +16 -0
- package/templates/base/tools/builder/core/{copy-static.js.hbs → app/copy-static.js.hbs} +27 -34
- package/templates/base/tools/builder/core/app/validate-routes.js.hbs +77 -0
- package/templates/base/tools/builder/core/finalize-build.js.hbs +16 -7
- package/templates/base/tools/builder/core/{add-tags.js.hbs → html-index/add-tags.js.hbs} +2 -2
- package/templates/base/tools/builder/core/html-index/add-tags.test.js.hbs +56 -0
- package/templates/base/tools/builder/core/{validate-html.js.hbs → html-index/validate-html.js.hbs} +5 -11
- package/templates/base/tools/builder/core/html-templates/merge-templates.js.hbs +152 -0
- package/templates/base/tools/builder/core/html-templates/minify-html.js.hbs +15 -0
- package/templates/base/tools/builder/core/html-templates/process-html-templates.js.hbs +8 -0
- package/templates/{features/i18n/tools/builder/core → base/tools/builder/core/i18n}/build-i18n.js.hbs +6 -17
- package/templates/base/tools/builder/core/prod-bundle/compress-files.js.hbs +37 -0
- package/templates/base/tools/builder/core/prod-bundle/esbuild.js.hbs +30 -0
- package/templates/base/tools/builder/core/{hash-files.js.hbs → prod-bundle/hash-files.js.hbs} +14 -11
- package/templates/base/tools/builder/core/seo/generate-robots-txt.js.hbs +51 -0
- package/templates/base/tools/builder/core/seo/generate-seo-files.js.hbs +16 -0
- package/templates/base/tools/builder/core/seo/generate-seo-html.js.hbs +128 -0
- package/templates/base/tools/builder/core/seo/generate-sitemap-xml.js.hbs +43 -0
- package/templates/base/tools/builder/core/seo/html-substitutions.js.hbs +99 -0
- package/templates/base/tools/builder/core/seo/i18n-resolution.js.hbs +66 -0
- package/templates/base/tools/builder/core/seo/route-output.js.hbs +64 -0
- package/templates/base/tools/builder/core/seo/ssr/ssr-bundle.js.hbs +54 -0
- package/templates/base/tools/builder/core/seo/ssr/ssr-polyfills.js.hbs +132 -0
- package/templates/base/tools/builder/core/seo/ssr/ssr-render.js.hbs +95 -0
- package/templates/base/tools/builder/core/styles/sass.js.hbs +40 -0
- package/templates/base/tools/builder/core/styles/tailwind.js.hbs +84 -0
- package/templates/base/tools/dev/dev-serve.js.hbs +26 -18
- package/templates/base/tools/dev/serve.js.hbs +11 -1
- package/templates/base/tools/dev/watcher.js.hbs +14 -6
- package/templates/base/tools/generator/generator.js.hbs +64 -47
- package/templates/base/tools/generator/handle-file.js.hbs +17 -44
- package/templates/base/tools/generator/handle-file.test.js.hbs +72 -0
- package/templates/base/tools/generator/templates/{component.template.js.hbs → component/component.template.js.hbs} +3 -2
- package/templates/base/tools/generator/templates/component/component.template.test.js.hbs +23 -0
- package/templates/base/tools/generator/templates/html/html.template.js.hbs +2 -0
- package/templates/base/tools/generator/templates/html/html.template.test.js.hbs +7 -0
- package/templates/base/tools/generator/templates/index.js.hbs +7 -12
- package/templates/base/tools/generator/templates/locale/locale.template.js.hbs +4 -0
- package/templates/base/tools/generator/templates/locale/locale.template.test.js.hbs +7 -0
- package/templates/base/tools/generator/templates/scss/scss.template.js.hbs +1 -0
- package/templates/base/tools/generator/templates/scss/scss.template.test.js.hbs +7 -0
- package/templates/base/tools/generator/templates/service/service.template.js.hbs +17 -0
- package/templates/base/tools/generator/templates/service/service.template.test.js.hbs +22 -0
- package/templates/base/tools/generator/templates/test/test.template.js.hbs +10 -0
- package/templates/base/tools/generator/templates/test/test.template.test.js.hbs +27 -0
- package/templates/base/tools/generator/templates/{view.template.js.hbs → view/view.template.js.hbs} +3 -2
- package/templates/base/tools/generator/templates/view/view.template.test.js.hbs +24 -0
- package/templates/base/tools/testin-nutin/core/coverage/collect-coverage.js.hbs +39 -0
- package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.js.hbs +115 -0
- package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.test.js.hbs +74 -0
- package/templates/base/tools/testin-nutin/core/coverage/write-summary-report.js.hbs +54 -0
- package/templates/base/tools/testin-nutin/core/coverage/write-uncovered-report.js.hbs +44 -0
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/assertion-lib.js.hbs +62 -24
- package/templates/base/tools/testin-nutin/core/globals/clock.js.hbs +206 -0
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/jsdom-setup.js.hbs +19 -6
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/register-test-globals.js.hbs +13 -4
- package/templates/base/tools/testin-nutin/core/globals/silence-console.js.hbs +23 -0
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/spyon.js.hbs +2 -0
- package/templates/base/tools/testin-nutin/core/index.js.hbs +9 -0
- package/templates/base/tools/testin-nutin/core/printer.js.hbs +85 -0
- package/templates/base/tools/testin-nutin/core/queue/queue.test.js.hbs +46 -0
- package/templates/base/tools/testin-nutin/core/queue/test-discovery.test.js.hbs +46 -0
- package/templates/base/tools/testin-nutin/core/queue/test-queue.js.hbs +154 -0
- package/templates/{features/testinNutin → base/tools}/testin-nutin/core/tests/assertions.test.js.hbs +27 -0
- package/templates/base/tools/testin-nutin/core/tests/clock.test.js.hbs +118 -0
- package/templates/base/tools/testin-nutin/core/tests/globals-each-all.test.js.hbs +28 -0
- package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/create-mock-method.js.hbs +2 -1
- package/templates/base/tools/testin-nutin/mocks/create-mock-method.test.js.hbs +64 -0
- package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-event-bus.js.hbs +3 -2
- package/templates/base/tools/testin-nutin/mocks/mock-event-bus.test.js.hbs +66 -0
- package/templates/base/tools/testin-nutin/mocks/mock-http-client.test.js.hbs +26 -0
- package/templates/base/tools/testin-nutin/mocks/mock-i18n.test.js.hbs +61 -0
- package/templates/base/tools/testin-nutin/mocks/mock-router.test.js.hbs +29 -0
- package/templates/base/tools/testin-nutin/runner.js.hbs +100 -0
- package/templates/base/tools/testin-nutin/watch-tests.js.hbs +37 -0
- package/templates/base/tools/utils/error-exit.js.hbs +8 -0
- package/templates/base/tools/utils/format.js.hbs +10 -10
- package/templates/base/tools/utils/format.test.js.hbs +45 -0
- package/templates/base/tools/utils/get-files-recursive.js.hbs +6 -1
- package/templates/base/tools/utils/get-files-recursive.test.js.hbs +49 -0
- package/templates/base/tools/utils/get-rel-to-core.test.js.hbs +18 -0
- package/templates/base/tools/utils/index.js.hbs +1 -3
- package/templates/base/tools/utils/languages.js.hbs +15 -0
- package/templates/base/tools/utils/languages.test.js.hbs +16 -0
- package/templates/base/tools/utils/print.js.hbs +19 -13
- package/templates/base/tools/utils/print.test.js.hbs +60 -0
- package/templates/base/tools/utils/prompt-boolean.js.hbs +7 -0
- package/templates/base/tools/utils/prompt-boolean.test.js.hbs +54 -0
- package/templates/base/tools/utils/run-command.js.hbs +4 -2
- package/templates/base/tools/utils/run-command.test.js.hbs +19 -0
- package/templates/base/tools/utils/run-script.js.hbs +14 -3
- package/templates/base/tools/utils/run-script.test.js.hbs +40 -0
- package/templates/features/{deployHelper → docker}/.dockerignore.hbs +4 -4
- package/templates/features/docker/tools/docker/Dockerfile.template.hbs +51 -0
- package/templates/features/{deployHelper/tools/deployment/nginx.conf.hbs → docker/tools/docker/nginx.conf.template} +4 -2
- package/templates/features/docker/tools/docker/scripts/docker-build.js.hbs +20 -0
- package/templates/features/docker/tools/docker/scripts/docker-ports.js.hbs +48 -0
- package/templates/features/docker/tools/docker/scripts/docker-ports.test.js.hbs +52 -0
- package/templates/features/docker/tools/docker/scripts/docker-run.js.hbs +28 -0
- package/templates/features/docker/tools/docker/scripts/render-docker-template.js.hbs +23 -0
- package/templates/features/docker/tools/docker/scripts/render-docker-template.test.js.hbs +60 -0
- package/templates/features/docker/tools/docker/scripts/validate-docker.js.hbs +30 -0
- package/lib/src/context-builder.mjs +0 -40
- package/lib/src/file-generator.mjs +0 -109
- package/lib/src/json-generator.mjs +0 -31
- package/lib/src/package-manager.mjs +0 -139
- package/lib/src/print.mjs +0 -32
- package/lib/src/utils.mjs +0 -18
- package/lib/src/version.mjs +0 -1
- package/templates/base/builder.config.js.hbs +0 -36
- package/templates/base/src/app/components/common/anchor/anchor.component.ts.hbs +0 -32
- package/templates/base/src/app/components/common/button/button.component.ts.hbs +0 -40
- package/templates/base/src/app/dom.test.js.hbs +0 -13
- package/templates/base/src/app/services/example/example.service.ts.hbs +0 -18
- package/templates/base/src/app/views/home/home.view.test.js.hbs +0 -26
- package/templates/base/src/core/services/store/store.test.js.hbs +0 -8
- package/templates/base/src/core/services/store/store.ts.hbs +0 -39
- package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.test.js.hbs +0 -0
- package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.ts.hbs +0 -113
- package/templates/base/src/core/utils/button-manager/button-manager.utils.test.js.hbs +0 -249
- package/templates/base/src/core/utils/button-manager/button-manager.utils.ts.hbs +0 -131
- package/templates/base/src/core/utils/helpers/attributes.helper.ts.hbs +0 -50
- package/templates/base/src/core/utils/index.ts.hbs +0 -2
- package/templates/base/src/libs/index.ts.hbs +0 -4
- package/templates/base/src/libs/popover/helpers/focus-trap.helper.ts.hbs +0 -197
- package/templates/base/src/libs/popover/helpers/popover-dom.helper.ts.hbs +0 -75
- package/templates/base/src/libs/popover/popover.ts.hbs +0 -138
- package/templates/base/src/libs/snackbar/snackbar.ts.hbs +0 -75
- package/templates/base/src/styles/base/_functions.scss.hbs +0 -9
- package/templates/base/src/styles/core/_anchors.scss.hbs +0 -10
- package/templates/base/src/styles/core/_index.scss.hbs +0 -6
- package/templates/base/src/styles/core/_popover.scss.hbs +0 -96
- package/templates/base/src/styles/core/_snackbar.scss.hbs +0 -50
- package/templates/base/tools/builder/core/esbuild.js.hbs +0 -25
- package/templates/base/tools/builder/core/minify-html.js.hbs +0 -60
- package/templates/base/tools/builder/core/sass.js.hbs +0 -22
- package/templates/base/tools/builder/core/tsc.js.hbs +0 -12
- package/templates/base/tools/generator/templates/service.template.js.hbs +0 -17
- package/templates/base/tools/utils/export-flags.js.hbs +0 -6
- package/templates/features/deployHelper/tools/builder/core/compress-files.js.hbs +0 -56
- package/templates/features/deployHelper/tools/deployment/Dockerfile.hbs +0 -30
- package/templates/features/i18n/src/app/views/home/locales/en.json.hbs +0 -9
- package/templates/features/i18n/src/app/views/not-found/locales/en.json +0 -8
- package/templates/features/i18n/src/app/views/not-found/locales/fr.json +0 -8
- package/templates/features/i18n/src/core/config.ts.hbs +0 -3
- package/templates/features/i18n/src/core/services/i18n/i18n.test.js.hbs +0 -125
- package/templates/features/i18n/tools/generator/templates/json.template.js.hbs +0 -8
- package/templates/features/i18n/tools/utils/languages.js.hbs +0 -7
- package/templates/features/stylinNutin/src/styles/_custom-classes.scss.hbs +0 -9
- package/templates/features/stylinNutin/src/styles/base/_mixins.scss.hbs +0 -372
- package/templates/features/stylinNutin/src/styles/components/_index.scss.hbs +0 -3
- package/templates/features/stylinNutin/src/styles/core/_utilities.scss.hbs +0 -254
- package/templates/features/stylinNutin/src/styles/views/_index.scss.hbs +0 -0
- package/templates/features/stylinNutin/tools/generator/templates/scss.template.js.hbs +0 -4
- package/templates/features/template/src/app/views/home/home.view.html.hbs +0 -56
- package/templates/features/template/src/app/views/not-found/not-found.view.html.hbs +0 -19
- package/templates/features/template/tools/builder/core/merge-templates.js.hbs +0 -49
- package/templates/features/template/tools/generator/templates/html.template.js.hbs +0 -2
- package/templates/features/testinNutin/testin-nutin/core/index.js.hbs +0 -5
- package/templates/features/testinNutin/testin-nutin/core/src/utils/print.js.hbs +0 -64
- package/templates/features/testinNutin/testin-nutin/core/src/utils/test-queue.js.hbs +0 -64
- package/templates/features/testinNutin/testin-nutin/core/tests/globals-each-all.test.js.hbs +0 -28
- package/templates/features/testinNutin/testin-nutin/mocks/mock-store.js.hbs +0 -38
- package/templates/features/testinNutin/testin-nutin/runner.js.hbs +0 -36
- package/templates/features/testinNutin/testin-nutin/watch-tests.js.hbs +0 -21
- package/templates/features/testinNutin/testin-nutin.config.js.hbs +0 -14
- /package/lib/src/{template-compiler.mjs → common/template-compiler.mjs} +0 -0
- /package/templates/{features/i18n → base}/src/core/base-classes/base-component/helpers/i18n.helper.ts.hbs +0 -0
- /package/templates/{features/i18n → base}/src/core/services/i18n/languages.ts.hbs +0 -0
- /package/templates/base/tools/builder/{variables → core/app}/binary-extensions.js.hbs +0 -0
- /package/templates/base/tools/builder/core/{paths.js.hbs → app/paths.js.hbs} +0 -0
- /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/queue.js.hbs +0 -0
- /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/test-discovery.js.hbs +0 -0
- /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-http-client.js.hbs +0 -0
- /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-i18n.js.hbs +0 -0
- /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-router.js.hbs +0 -0
|
@@ -1,86 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Variables used in libs (snackbar, popover){{#if stylinNutin}} and utility classes{{/if}}
|
|
3
|
-
Adapt to customize
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// colours (RGB)
|
|
7
|
-
$background-color: rgb(255 255 255); // WHITE
|
|
8
|
-
$text-color: rgb(0 0 0); // BLACK
|
|
9
|
-
$primary-color: rgb(0 0 0); // BLACK
|
|
10
|
-
$secondary-color: rgb(0 0 0); // BLACK
|
|
11
|
-
$accent-color: rgb(0 0 0); // BLACK
|
|
12
|
-
|
|
13
|
-
// snackbar colours
|
|
14
|
-
$snack-success: rgb(76 175 80);
|
|
15
|
-
$snack-error: rgb(244 67 54);
|
|
16
|
-
$snack-info: rgb(33 150 243);
|
|
17
|
-
$snack-default: rgb(153 153 153);
|
|
18
|
-
|
|
19
|
-
{{#if stylinNutin}}
|
|
20
|
-
/*
|
|
21
|
-
Variables used in utility classes
|
|
22
|
-
Adapt to customize
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
// fonts
|
|
26
|
-
$primary-font: Arial, Helvetica, sans-serif;
|
|
27
|
-
$secondary-font: Arial, Helvetica, sans-serif;
|
|
28
|
-
|
|
29
|
-
// font sizes
|
|
30
|
-
$font-sizes: (
|
|
31
|
-
smallest: 0.75rem, // 12px
|
|
32
|
-
small: 0.875rem, // 14px
|
|
33
|
-
medium: 1rem, // 16px (base)
|
|
34
|
-
large: 1.5rem, // 24px
|
|
35
|
-
largest: 2rem, // 32px
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
// spacing (margin / padding / gap)
|
|
39
|
-
$spacings: (
|
|
40
|
-
smallest: 0.25rem, // 4px
|
|
41
|
-
small: 0.5rem, // 8px
|
|
42
|
-
medium: 1rem, // 16px
|
|
43
|
-
large: 1.5rem, // 24px
|
|
44
|
-
largest: 2rem, // 32px
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
// border radius
|
|
48
|
-
$border-radius: (
|
|
49
|
-
small: 2px,
|
|
50
|
-
medium: 4px,
|
|
51
|
-
large: 8px,
|
|
52
|
-
pill: 9999px,
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
// box sizes
|
|
56
|
-
$box-sizes: (
|
|
57
|
-
small: 32px,
|
|
58
|
-
medium: 64px,
|
|
59
|
-
large: 128px,
|
|
60
|
-
largest: 256px,
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
// shadows
|
|
64
|
-
$shadows: (
|
|
65
|
-
small: 0 1px 2px rgba(0, 0, 0, 0.05),
|
|
66
|
-
medium: 0 4px 6px rgba(0, 0, 0, 0.1),
|
|
67
|
-
large: 0 10px 15px rgba(0, 0, 0, 0.15),
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
// breakpoints
|
|
71
|
-
$breakpoints: (
|
|
72
|
-
small: 576px,
|
|
73
|
-
medium: 768px,
|
|
74
|
-
large: 992px,
|
|
75
|
-
largest: 1201px,
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
// animations
|
|
79
|
-
// transition Duration
|
|
80
|
-
$transitions: (
|
|
81
|
-
fast: 0.2s,
|
|
82
|
-
normal: 0.3s,
|
|
83
|
-
slow: 0.5s,
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
{{/if}}
|
|
1
|
+
// variables
|
|
@@ -1,19 +1,2 @@
|
|
|
1
|
-
//
|
|
2
|
-
@use "core";
|
|
3
|
-
|
|
4
|
-
{{#if stylinNutin}}
|
|
5
|
-
// built-in classes
|
|
6
|
-
@use "utilities";
|
|
7
|
-
|
|
8
|
-
{{/if}}
|
|
9
|
-
// global styles
|
|
1
|
+
// CSS reset & global styles
|
|
10
2
|
@use "styles";
|
|
11
|
-
|
|
12
|
-
{{#if stylinNutin}}
|
|
13
|
-
// custom classes
|
|
14
|
-
@use "custom-classes";
|
|
15
|
-
// components styles
|
|
16
|
-
@use "components";
|
|
17
|
-
// views styles
|
|
18
|
-
@use "views";
|
|
19
|
-
{{/if}}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import process from 'process';
|
|
2
|
+
import nutinConfig from '../../nutin.config.js';
|
|
3
|
+
import { errorExit } from '../utils/index.js';
|
|
4
|
+
|
|
5
|
+
function validateConfig(config) {
|
|
6
|
+
if (!config || typeof config !== 'object') {
|
|
7
|
+
errorExit(new Error('nutin.config.js must export a default object.'), 'builder.config');
|
|
8
|
+
}
|
|
9
|
+
if (!config.builder || typeof config.builder !== 'object') {
|
|
10
|
+
errorExit(new Error('nutin.config.js is missing the required "builder" object.'), 'builder.config');
|
|
11
|
+
}
|
|
12
|
+
if (!Array.isArray(config.builder.sass?.paths)) {
|
|
13
|
+
errorExit(new Error('nutin.config.js is missing "builder.sass.paths" (expected an array).'), 'builder.config');
|
|
14
|
+
}
|
|
15
|
+
if (!config.builder.esbuild || typeof config.builder.esbuild !== 'object') {
|
|
16
|
+
errorExit(new Error('nutin.config.js is missing the required "builder.esbuild" object.'), 'builder.config');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
validateConfig(nutinConfig);
|
|
21
|
+
|
|
22
|
+
const wellKnownNonSEORoutes = [
|
|
23
|
+
'/400',
|
|
24
|
+
'/401',
|
|
25
|
+
'/403',
|
|
26
|
+
'/404',
|
|
27
|
+
'/500',
|
|
28
|
+
'/502',
|
|
29
|
+
'/503',
|
|
30
|
+
'/504',
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
export const builderConfig = {
|
|
34
|
+
...nutinConfig.builder,
|
|
35
|
+
isProd: process.env.NODE_ENV === 'production',
|
|
36
|
+
i18n: nutinConfig.i18n,
|
|
37
|
+
tailwind: nutinConfig.tailwind,
|
|
38
|
+
generateSEO: nutinConfig.generateSEOFiles,
|
|
39
|
+
WELL_KNOWN_NON_SEO_ROUTES: wellKnownNonSEORoutes,
|
|
40
|
+
};
|
|
@@ -1,38 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import path from 'path';
|
|
4
|
-
import { print,
|
|
4
|
+
import { print, runScript } from '../utils/index.js';
|
|
5
|
+
import { builderConfig } from './builder.config.js';
|
|
5
6
|
|
|
6
7
|
const scriptsDir = path.join(process.cwd(), 'tools', 'builder', 'core');
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
runScript(path.join(scriptsDir, '
|
|
28
|
-
runScript(path.join(scriptsDir, '
|
|
29
|
-
{{#if deployHelper}}
|
|
30
|
-
runScript(path.join(scriptsDir, 'compress-files.js'), 'Compressing files...');
|
|
31
|
-
{{/if}}
|
|
9
|
+
print.boldHead(`\nStarting build...`);
|
|
10
|
+
|
|
11
|
+
runScript(path.join(scriptsDir, 'app', 'copy-static.js'), 'Copying files...');
|
|
12
|
+
|
|
13
|
+
runScript(path.join(scriptsDir, 'html-index', 'validate-html.js'), 'Processing index.html...');
|
|
14
|
+
runScript(path.join(scriptsDir, 'app', 'validate-routes.js'), 'Validating app routes...');
|
|
15
|
+
|
|
16
|
+
runScript(path.join(scriptsDir, 'app', 'compile-ts.js'), 'Compiling TypeScript...');
|
|
17
|
+
|
|
18
|
+
runScript(path.join(scriptsDir, 'html-templates', 'process-html-templates.js'), 'Processing HTML templates...');
|
|
19
|
+
|
|
20
|
+
runScript(path.join(scriptsDir, 'styles', 'sass.js'), 'Compiling styles...');
|
|
21
|
+
if (builderConfig.tailwind) runScript(path.join(scriptsDir, 'styles', 'tailwind.js'), 'Compiling Tailwind CSS...');
|
|
22
|
+
|
|
23
|
+
if (builderConfig.i18n) runScript(path.join(scriptsDir, 'i18n', 'build-i18n.js'), 'Combining locales...');
|
|
24
|
+
|
|
25
|
+
if (builderConfig.isProd) {
|
|
26
|
+
runScript(path.join(scriptsDir, 'prod-bundle', 'esbuild.js'), 'Running esbuild...');
|
|
27
|
+
runScript(path.join(scriptsDir, 'prod-bundle', 'hash-files.js'), 'Hashing files...');
|
|
28
|
+
runScript(path.join(scriptsDir, 'prod-bundle', 'compress-files.js'), 'Compressing files...');
|
|
29
|
+
if (builderConfig.generateSEO) runScript(path.join(scriptsDir, 'seo', 'generate-seo-files.js'), 'Generating SEO Files...');
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
runScript(path.join(scriptsDir, 'finalize-build.js'), 'Finalizing build...')
|
|
35
33
|
|
|
36
34
|
print.boldSuccess(`\nBuild successful!\n`);
|
|
37
35
|
|
|
38
|
-
if (!isProd) print.
|
|
36
|
+
if (!builderConfig.isProd) print.info('For production, use "{{packageManager}} run build:prod"');
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BINARY_EXTENSIONS } from './binary-extensions.js';
|
|
2
|
+
|
|
3
|
+
describe('BINARY_EXTENSIONS', () => {
|
|
4
|
+
it('is a Set containing common binary asset extensions', () => {
|
|
5
|
+
expect(BINARY_EXTENSIONS).toBeInstanceOf(Set);
|
|
6
|
+
expect(BINARY_EXTENSIONS.has('.png')).toBeTruthy();
|
|
7
|
+
expect(BINARY_EXTENSIONS.has('.woff2')).toBeTruthy();
|
|
8
|
+
expect(BINARY_EXTENSIONS.has('.gz')).toBeTruthy();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('does not treat text/source extensions as binary', () => {
|
|
12
|
+
expect(BINARY_EXTENSIONS.has('.js')).toBeFalsy();
|
|
13
|
+
expect(BINARY_EXTENSIONS.has('.css')).toBeFalsy();
|
|
14
|
+
expect(BINARY_EXTENSIONS.has('.html')).toBeFalsy();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { runCommand, print, errorExit } from "../../../utils/index.js";
|
|
2
|
+
import { builderConfig } from '../../builder.config.js';
|
|
3
|
+
|
|
4
|
+
async function compileTS() {
|
|
5
|
+
// Prod bundles straight from .ts source (see prod-bundle/esbuild.js), so tsc only
|
|
6
|
+
// needs to type-check there, not emit — emitting would leave a stale, unmerged .js
|
|
7
|
+
// sibling next to each merged .ts view/component's source.
|
|
8
|
+
const args = ['--project', 'tsconfig.json'];
|
|
9
|
+
if (builderConfig.isProd) args.push('--noEmit');
|
|
10
|
+
|
|
11
|
+
await runCommand('tsc', args);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
compileTS().catch((err) => {
|
|
15
|
+
errorExit(err, 'compile-ts');
|
|
16
|
+
});
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { BINARY_EXTENSIONS } from '../variables/binary-extensions.js';
|
|
3
|
+
import { getFilesRecursive, print, errorExit } from '../../../utils/index.js';
|
|
4
|
+
import { BINARY_EXTENSIONS } from './binary-extensions.js';
|
|
6
5
|
import { PATHS } from './paths.js';
|
|
6
|
+
import { builderConfig } from '../../builder.config.js';
|
|
7
7
|
|
|
8
8
|
async function copyStatic() {
|
|
9
|
-
const extensions = [...BINARY_EXTENSIONS, 'html'];
|
|
10
|
-
if (isProd) extensions.push('.ts');
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
const extensions = [...BINARY_EXTENSIONS, '.html'];
|
|
10
|
+
if (builderConfig.isProd) extensions.push('.ts');
|
|
11
|
+
|
|
12
|
+
// Every build starts from a clean dist-build: a failed/interrupted prior
|
|
13
|
+
// build never gets renamed away by finalize-build.js, so a stale sibling
|
|
14
|
+
// (already merged, placeholder gone) can otherwise sit next to the next
|
|
15
|
+
// run's fresh output and trip merge-templates.js's per-sibling check.
|
|
16
|
+
await fs.rm(PATHS.temp, { recursive: true, force: true });
|
|
14
17
|
await ensureDir(PATHS.tempSource);
|
|
15
18
|
|
|
16
19
|
await copyFavicon();
|
|
17
|
-
{{#if i18n}}
|
|
18
20
|
await copyConfig();
|
|
19
|
-
{{/if}}
|
|
20
21
|
|
|
21
22
|
for (const extension of extensions) {
|
|
22
23
|
const files = await getFilesRecursive(PATHS.source, extension);
|
|
@@ -27,17 +28,13 @@ async function copyStatic() {
|
|
|
27
28
|
|
|
28
29
|
try {
|
|
29
30
|
await copyFile(file, dest);
|
|
30
|
-
if (isVerbose) print.info(`✅ Copied: ${file} → ${dest}`);
|
|
31
31
|
} catch (err) {
|
|
32
|
-
|
|
33
|
-
exit(1);
|
|
32
|
+
throw new Error(`Failed to copy: ${file}. ${err.message}`, { cause: err });
|
|
34
33
|
}
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
if (isProd) await copyJsonFiles(PATHS.source, PATHS.tempSource);
|
|
39
|
-
|
|
40
|
-
if (isVerbose) print.boldInfo(`Copy complete.\n`);
|
|
37
|
+
if (builderConfig.isProd) await copyJsonFiles(PATHS.source, PATHS.tempSource);
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
async function ensureDir(dir) {
|
|
@@ -55,33 +52,31 @@ async function copyFavicon() {
|
|
|
55
52
|
|
|
56
53
|
try {
|
|
57
54
|
await copyFile(srcPath, destPath);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
} catch (err) {
|
|
56
|
+
if (err.code === 'ENOENT') print.warn('No favicon found at public/favicon.ico');
|
|
57
|
+
else errorExit(err, 'copy-static');
|
|
61
58
|
}
|
|
62
59
|
}
|
|
63
60
|
|
|
64
|
-
{{#if i18n}}
|
|
65
61
|
async function copyConfig() {
|
|
66
62
|
const srcPath = path.resolve(path.join('config'));
|
|
67
|
-
const temp = isProd ? PATHS.temp : PATHS.tempSource;
|
|
63
|
+
const temp = builderConfig.isProd ? PATHS.temp : PATHS.tempSource;
|
|
68
64
|
const destPath = path.join(temp, 'config');
|
|
69
65
|
try {
|
|
70
66
|
await copyJsonFiles(srcPath, destPath);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
67
|
+
await copyFile(path.resolve('nutin.config.js'), path.join(temp, 'nutin.config.js'));
|
|
68
|
+
|
|
69
|
+
// for testin-nutin tests to run
|
|
70
|
+
if (!builderConfig.isProd) {
|
|
71
|
+
await copyJsonFiles(srcPath, path.join(PATHS.temp, 'config'));
|
|
72
|
+
await copyFile(path.resolve('nutin.config.js'), path.join(PATHS.temp, 'nutin.config.js'));
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
errorExit(err, 'copy-static');
|
|
79
76
|
}
|
|
80
77
|
}
|
|
81
78
|
|
|
82
|
-
{{/if}}
|
|
83
79
|
async function copyJsonFiles(sourceDir, destDir) {
|
|
84
|
-
|
|
85
80
|
const items = await fs.readdir(sourceDir, { withFileTypes: true });
|
|
86
81
|
|
|
87
82
|
for (const item of items) {
|
|
@@ -93,12 +88,10 @@ async function copyJsonFiles(sourceDir, destDir) {
|
|
|
93
88
|
} else if (item.isFile() && path.extname(item.name) === '.json') {
|
|
94
89
|
await fs.mkdir(path.dirname(destPath), { recursive: true });
|
|
95
90
|
await fs.copyFile(sourcePath, destPath);
|
|
96
|
-
if (isVerbose) print.info(`Copied JSON: ${sourcePath} -> ${destPath}`);
|
|
97
91
|
}
|
|
98
92
|
}
|
|
99
93
|
}
|
|
100
94
|
|
|
101
95
|
copyStatic().catch((err) => {
|
|
102
|
-
|
|
103
|
-
exit(1);
|
|
96
|
+
errorExit(err, 'copy-static');
|
|
104
97
|
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
import { print, errorExit } from '../../../utils/index.js';
|
|
5
|
+
import { PATHS } from './paths.js';
|
|
6
|
+
|
|
7
|
+
const ROUTES_FILE = path.join(PATHS.sourceApp, 'routes.ts');
|
|
8
|
+
|
|
9
|
+
function findAppRoutesObjectLiteral(sourceFile) {
|
|
10
|
+
let objectLiteral;
|
|
11
|
+
|
|
12
|
+
ts.forEachChild(sourceFile, function visit(node) {
|
|
13
|
+
if (
|
|
14
|
+
ts.isVariableDeclaration(node) &&
|
|
15
|
+
ts.isIdentifier(node.name) &&
|
|
16
|
+
node.name.text === 'appRoutes' &&
|
|
17
|
+
node.initializer &&
|
|
18
|
+
ts.isObjectLiteralExpression(node.initializer)
|
|
19
|
+
) {
|
|
20
|
+
objectLiteral = node.initializer;
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
ts.forEachChild(node, visit);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return objectLiteral;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getRouteKeys(objectLiteral) {
|
|
30
|
+
return objectLiteral.properties
|
|
31
|
+
.filter((prop) => ts.isPropertyAssignment(prop) && ts.isStringLiteralLike(prop.name))
|
|
32
|
+
.map((prop) => prop.name.text);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function findDuplicates(keys) {
|
|
36
|
+
const seen = new Set();
|
|
37
|
+
const duplicates = new Set();
|
|
38
|
+
|
|
39
|
+
for (const key of keys) {
|
|
40
|
+
if (seen.has(key)) duplicates.add(key);
|
|
41
|
+
seen.add(key);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return [...duplicates];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function validateRoutes() {
|
|
48
|
+
let source;
|
|
49
|
+
try {
|
|
50
|
+
source = readFileSync(ROUTES_FILE, 'utf-8');
|
|
51
|
+
} catch {
|
|
52
|
+
errorExit(`Failed to read ${ROUTES_FILE}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const sourceFile = ts.createSourceFile(ROUTES_FILE, source, ts.ScriptTarget.Latest, true);
|
|
56
|
+
const objectLiteral = findAppRoutesObjectLiteral(sourceFile);
|
|
57
|
+
|
|
58
|
+
if (!objectLiteral) {
|
|
59
|
+
errorExit(`Could not find an "appRoutes" object literal in ${ROUTES_FILE}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const duplicates = findDuplicates(getRouteKeys(objectLiteral));
|
|
63
|
+
|
|
64
|
+
if (duplicates.length > 0) {
|
|
65
|
+
const list = duplicates.map((key) => `"${key}"`).join(', ');
|
|
66
|
+
errorExit(
|
|
67
|
+
`Duplicate route key(s) in ${ROUTES_FILE}: ${list} — an earlier route with this path is silently unreachable.`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
validateRoutes();
|
|
75
|
+
} catch(err) {
|
|
76
|
+
errorExit(err, 'validate-routes');
|
|
77
|
+
}
|
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import { print, isProd, isVerbose } from "../../utils/index.js";
|
|
2
1
|
import fs from 'fs';
|
|
3
2
|
import path from 'path';
|
|
4
|
-
import { PATHS } from "./paths.js";
|
|
3
|
+
import { PATHS } from "./app/paths.js";
|
|
4
|
+
import { builderConfig } from '../builder.config.js';
|
|
5
|
+
import { print, errorExit } from "../../utils/index.js";
|
|
5
6
|
|
|
6
7
|
function finalizeBuild() {
|
|
7
|
-
if (isProd) removeFoldersAfterBundle();
|
|
8
|
+
if (builderConfig.isProd) removeFoldersAfterBundle();
|
|
9
|
+
if (builderConfig.isProd) removeNutinConfig();
|
|
8
10
|
replaceDir(PATHS.temp, PATHS.build);
|
|
9
|
-
if (isVerbose) print.boldInfo('Build finalized.\n');
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
function removeFoldersAfterBundle() {
|
|
13
|
-
const foldersToRemove = ['core', '
|
|
14
|
+
const foldersToRemove = [ 'core', 'app', path.join('..', 'config') ];
|
|
14
15
|
const pathToFolder = (folder) => path.join(PATHS.tempSource, folder);
|
|
15
16
|
|
|
16
|
-
foldersToRemove.forEach(folder => fs.rmSync(pathToFolder(folder), { recursive : true }));
|
|
17
|
+
foldersToRemove.forEach(folder => fs.rmSync(pathToFolder(folder), { recursive: true, force: true }));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function removeNutinConfig() {
|
|
21
|
+
fs.rmSync(path.join(PATHS.temp, 'nutin.config.js'));
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
function replaceDir(src, dest) {
|
|
@@ -21,4 +26,8 @@ function replaceDir(src, dest) {
|
|
|
21
26
|
fs.renameSync(src, dest);
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
try {
|
|
30
|
+
finalizeBuild();
|
|
31
|
+
} catch(err) {
|
|
32
|
+
errorExit(err, 'finalize-build')
|
|
33
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { print, isProd } from '../../utils/index.js';
|
|
2
1
|
import { writeFile } from 'fs/promises';
|
|
2
|
+
import { builderConfig } from '../../builder.config.js';
|
|
3
3
|
|
|
4
4
|
export async function addTags(htmlContent, filePath) {
|
|
5
|
-
const scriptSrc = isProd ? "bundle.js" : "app/main.js";
|
|
5
|
+
const scriptSrc = builderConfig.isProd ? "bundle.js" : "app/main.js";
|
|
6
6
|
|
|
7
7
|
const tags = [
|
|
8
8
|
{ type: 'stylesheet', href: 'main.css', position: 'head' },
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { addTags } from './add-tags.js';
|
|
5
|
+
|
|
6
|
+
describe('addTags', () => {
|
|
7
|
+
let tmpDir;
|
|
8
|
+
let filePath;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nutin-add-tags-'));
|
|
12
|
+
filePath = path.join(tmpDir, 'index.html');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('inserts the stylesheet before </head> and the script before </body>', async () => {
|
|
20
|
+
const html = '<html><head><title>T</title></head><body></body></html>';
|
|
21
|
+
|
|
22
|
+
const result = await addTags(html, filePath);
|
|
23
|
+
|
|
24
|
+
expect(result).toBe(
|
|
25
|
+
'<html><head><title>T</title><link rel="stylesheet" href="/main.css"></head><body><script type="module" src="/app/main.js"></script></body></html>'
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('falls back to inserting the stylesheet before <title> when there is no </head>', async () => {
|
|
30
|
+
const html = '<html><title>T</title><body></body></html>';
|
|
31
|
+
|
|
32
|
+
const result = await addTags(html, filePath);
|
|
33
|
+
|
|
34
|
+
expect(result).toBe(
|
|
35
|
+
'<html><link rel="stylesheet" href="/main.css"><title>T</title><body><script type="module" src="/app/main.js"></script></body></html>'
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('appends both tags to the end when neither anchor is present', async () => {
|
|
40
|
+
const html = '<html></html>';
|
|
41
|
+
|
|
42
|
+
const result = await addTags(html, filePath);
|
|
43
|
+
|
|
44
|
+
expect(result).toBe(
|
|
45
|
+
'<html></html><link rel="stylesheet" href="/main.css"><script type="module" src="/app/main.js"></script>'
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('writes the modified html to filePath', async () => {
|
|
50
|
+
const html = '<html><head></head><body></body></html>';
|
|
51
|
+
|
|
52
|
+
const result = await addTags(html, filePath);
|
|
53
|
+
|
|
54
|
+
expect(fs.readFileSync(filePath, 'utf8')).toBe(result);
|
|
55
|
+
});
|
|
56
|
+
});
|
package/templates/base/tools/builder/core/{validate-html.js.hbs → html-index/validate-html.js.hbs}
RENAMED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'fs/promises';
|
|
2
|
-
import { exit } from 'process';
|
|
3
|
-
import { print, isVerbose } from '../../utils/index.js';
|
|
4
|
-
import { PATHS } from './paths.js';
|
|
5
2
|
import path from 'path';
|
|
3
|
+
import { print, errorExit } from '../../../utils/index.js';
|
|
4
|
+
import { PATHS } from '../app/paths.js';
|
|
6
5
|
import { addTags } from './add-tags.js';
|
|
7
6
|
|
|
8
7
|
async function validateHtml() {
|
|
@@ -27,13 +26,8 @@ async function validateHtml() {
|
|
|
27
26
|
if (!/<link[^>]*rel=["']stylesheet["']/.test(htmlContent)) {
|
|
28
27
|
errorExit('No stylesheet found in HTML');
|
|
29
28
|
}
|
|
30
|
-
|
|
31
|
-
if (isVerbose) print.boldInfo('HTML validation passed\n');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function errorExit(message) {
|
|
35
|
-
print.boldError(`[ERROR] ${message}`);
|
|
36
|
-
exit(1);
|
|
37
29
|
}
|
|
38
30
|
|
|
39
|
-
validateHtml()
|
|
31
|
+
validateHtml().catch((err) => {
|
|
32
|
+
errorExit(err, 'validate-html');
|
|
33
|
+
});
|