@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
package/lib/src/print.mjs
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export const chalk = {
|
|
2
|
-
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
3
|
-
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
4
|
-
blue: (s) => `\x1b[34m${s}\x1b[0m`,
|
|
5
|
-
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
6
|
-
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
7
|
-
purple: (s) => `\x1b[35m${s}\x1b[0m`,
|
|
8
|
-
gray: (s) => `\x1b[90m${s}\x1b[0m`,
|
|
9
|
-
boldGreen: (s) => `\x1b[1;32m${s}\x1b[0m`,
|
|
10
|
-
boldRed: (s) => `\x1b[1;31m${s}\x1b[0m`,
|
|
11
|
-
boldBlue: (s) => `\x1b[1;34m${s}\x1b[0m`,
|
|
12
|
-
boldYellow: (s) => `\x1b[1;33m${s}\x1b[0m`,
|
|
13
|
-
boldCyan: (s) => `\x1b[1;36m${s}\x1b[0m`,
|
|
14
|
-
boldPurple: (s) => `\x1b[1;35m${s}\x1b[0m`,
|
|
15
|
-
boldGray: (s) => `\x1b[1;90m${s}\x1b[0m`,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const print = {
|
|
19
|
-
head: (s) => console.log(`${chalk.purple(s)}`),
|
|
20
|
-
boldHead : (s) => console.log(`${chalk.boldPurple(s)}`),
|
|
21
|
-
section: (s) => console.log(`${chalk.yellow(s)}`),
|
|
22
|
-
boldSection: (s) => console.log(`${chalk.boldYellow(s)}`),
|
|
23
|
-
info: (s) => console.log(`${chalk.green(s)}`),
|
|
24
|
-
boldInfo: (s) => console.log(`${chalk.boldGreen(s)}`),
|
|
25
|
-
success: (s) => console.log(`${chalk.cyan(s)}`),
|
|
26
|
-
boldSuccess: (s) => console.log(`${chalk.boldCyan(s)}`),
|
|
27
|
-
error: (s) => console.error(`${chalk.red(s)}`),
|
|
28
|
-
boldError: (s) => console.error(`${chalk.boldRed(s)}`),
|
|
29
|
-
grayError: (s) => console.error(`${chalk.gray(s)}`),
|
|
30
|
-
blue: (s) => console.log(`${chalk.blue(s)}`),
|
|
31
|
-
boldBlue: (s) => console.log(`${chalk.boldBlue(s)}`),
|
|
32
|
-
}
|
package/lib/src/utils.mjs
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { exec } from 'child_process';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
|
-
import { print } from './print.mjs';
|
|
4
|
-
|
|
5
|
-
export const promiseExec = promisify(exec);
|
|
6
|
-
|
|
7
|
-
export function displaySuccessMessage(answers) {
|
|
8
|
-
const { projectName, packageManager, deployHelper } = answers;
|
|
9
|
-
print.boldSuccess('\n🎉 Your project is ready!');
|
|
10
|
-
print.boldInfo(`Documentation on https://www.nutin.org`);
|
|
11
|
-
|
|
12
|
-
if (packageManager === 'pnpm' || packageManager === 'bun') {
|
|
13
|
-
if (deployHelper) print.boldError(`You'll need to modify the Dockerfile to support ${packageManager}`)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
print.info('Next steps:');
|
|
17
|
-
print.info(` cd ${projectName} && ${packageManager} run serve\n`);
|
|
18
|
-
}
|
package/lib/src/version.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const packageVersion = '1.3.1';
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
esbuild: {
|
|
3
|
-
bundle: true,
|
|
4
|
-
minify: true,
|
|
5
|
-
sourcemap: false,
|
|
6
|
-
drop: ['console', 'debugger'],
|
|
7
|
-
platform: 'browser',
|
|
8
|
-
format: 'esm',
|
|
9
|
-
target: ['es2015'],
|
|
10
|
-
legalComments: 'none',
|
|
11
|
-
loader: {
|
|
12
|
-
'.json': 'json',
|
|
13
|
-
},
|
|
14
|
-
define: {
|
|
15
|
-
'process.env.NODE_ENV': '"production"',
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
sass: {
|
|
19
|
-
paths: [
|
|
20
|
-
'base',
|
|
21
|
-
'core',
|
|
22
|
-
{{#if stylinNutin}}
|
|
23
|
-
'components',
|
|
24
|
-
'views',
|
|
25
|
-
{{/if}}
|
|
26
|
-
], // in styles/
|
|
27
|
-
},
|
|
28
|
-
{{#if deployHelper}}
|
|
29
|
-
compression: {
|
|
30
|
-
gzip: true,
|
|
31
|
-
// BROTLI OPTIONAL
|
|
32
|
-
// brotli: false,
|
|
33
|
-
},
|
|
34
|
-
{{/if}}
|
|
35
|
-
verbose: false,
|
|
36
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { AnchorManager, Component, IAnchorConfig } from '../../../../core/index.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ```typescript
|
|
5
|
-
* interface IAnchorConfig {
|
|
6
|
-
// prefix href with '#' for internal anchor
|
|
7
|
-
href: string;
|
|
8
|
-
target?: string;
|
|
9
|
-
textContent?: string;
|
|
10
|
-
{{#if i18n}}
|
|
11
|
-
i18nKey?: string;
|
|
12
|
-
{{/if}}
|
|
13
|
-
className?: string;
|
|
14
|
-
style?: string;
|
|
15
|
-
// use regular pipe syntax for arguments / chaining
|
|
16
|
-
pipes?: string;
|
|
17
|
-
tagName?: keyof HTMLElementTagNameMap;
|
|
18
|
-
}
|
|
19
|
-
```
|
|
20
|
-
*/
|
|
21
|
-
export class AnchorComponent extends Component<HTMLAnchorElement, IAnchorConfig> {
|
|
22
|
-
|
|
23
|
-
constructor(mountTarget: HTMLElement, config: IAnchorConfig) {
|
|
24
|
-
super({
|
|
25
|
-
mountTarget,
|
|
26
|
-
tagName: config.tagName,
|
|
27
|
-
config,
|
|
28
|
-
normalizeKeys: ['style', 'pipes', 'className']
|
|
29
|
-
});
|
|
30
|
-
new AnchorManager(config, this.element);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { BaseButton, Component } from '../../../../core/index.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ```typescript
|
|
5
|
-
interface IAttributesConfig {
|
|
6
|
-
{{#if i18n}}
|
|
7
|
-
i18nKey?: string;
|
|
8
|
-
{{/if}}
|
|
9
|
-
textContent?: string;
|
|
10
|
-
className?: string;
|
|
11
|
-
style?: string;
|
|
12
|
-
// use regular pipe syntax for arguments / chaining
|
|
13
|
-
pipes?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface BaseButton extends IAttributesConfig {
|
|
17
|
-
callback: () => void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface ButtonContainerOptions {
|
|
21
|
-
containerClassName?: string;
|
|
22
|
-
containerStyles?: string;
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
* Note : To ensure 'this' is bound properly
|
|
26
|
-
* ```typescript
|
|
27
|
-
// Will handle 'this' inside doStuff
|
|
28
|
-
* { callback: () => this.doStuff() }
|
|
29
|
-
* // Will still work, but won't handle 'this' inside doStuff
|
|
30
|
-
* { callback: this.doStuff }
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
export class ButtonComponent extends Component<HTMLButtonElement> {
|
|
34
|
-
constructor(mountTarget: HTMLElement, button: BaseButton) {
|
|
35
|
-
super({
|
|
36
|
-
mountTarget,
|
|
37
|
-
props: { buttons: [button] }
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
describe('App container', () => {
|
|
2
|
-
it('should be defined', () => {
|
|
3
|
-
const appContainer = document.getElementById('app');
|
|
4
|
-
expect(appContainer).toBeDefined();
|
|
5
|
-
});
|
|
6
|
-
it('should have title', () => {
|
|
7
|
-
expect(document.title).toEqual('{{projectName}}');
|
|
8
|
-
});
|
|
9
|
-
it('should have meta description', () => {
|
|
10
|
-
const desc = document.querySelector('meta[name="description"]').content;
|
|
11
|
-
expect(desc).toEqual('{{projectName}}');
|
|
12
|
-
});
|
|
13
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Service } from "../../../core/index.js";
|
|
2
|
-
|
|
3
|
-
export class Example extends Service<Example> {
|
|
4
|
-
constructor() {
|
|
5
|
-
super();
|
|
6
|
-
this.registerCallback();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
protected registerCallback(): void {
|
|
10
|
-
console.debug('No cleanup callbacks registered for service: Example')
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
protected onDestroy(): void {
|
|
14
|
-
this.dispose();
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const exampleService = Example.getInstance();
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { HomeView } from '#root/dist/src/app/views/index.js';
|
|
2
|
-
|
|
3
|
-
let view;
|
|
4
|
-
|
|
5
|
-
describe('HomeView', () => {
|
|
6
|
-
beforeAll(() => {
|
|
7
|
-
view = new HomeView();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('should be defined', () => {
|
|
11
|
-
expect(view).toBeDefined();
|
|
12
|
-
});
|
|
13
|
-
{{#if i18n}}
|
|
14
|
-
it('should have title with i18n key', () => {
|
|
15
|
-
const h1 = view.element.querySelector('h1');
|
|
16
|
-
expect(h1).toBeDefined();
|
|
17
|
-
expect(h1.textContent).toBe('home.title');
|
|
18
|
-
});
|
|
19
|
-
{{else}}
|
|
20
|
-
it('should have title', () => {
|
|
21
|
-
const h1 = view.element.querySelector('h1');
|
|
22
|
-
expect(h1).toBeDefined();
|
|
23
|
-
expect(h1.textContent).toBe('{{projectName}}');
|
|
24
|
-
});
|
|
25
|
-
{{/if}}
|
|
26
|
-
})
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Service, AppEventBus } from "../../index.js";
|
|
2
|
-
|
|
3
|
-
export type StoreState = Record<string, any>;
|
|
4
|
-
|
|
5
|
-
export class Store extends Service<Store> {
|
|
6
|
-
private _state: StoreState = {};
|
|
7
|
-
|
|
8
|
-
constructor() {
|
|
9
|
-
super();
|
|
10
|
-
this.registerCleanup(this.clear);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
public set<T = any>(key: string, value: T): void {
|
|
14
|
-
this._state[key] = value;
|
|
15
|
-
AppEventBus.emit(`store:${key}`, value);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
public get<T = any>(key: string): T | undefined {
|
|
19
|
-
return this._state[key];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public subscribe<T = any>(key: string, callback: (value: T) => void): void {
|
|
23
|
-
AppEventBus.subscribe(`store:${key}`, callback);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public unsubscribe<T = any>(key: string, callback: (value: T) => void): void {
|
|
27
|
-
AppEventBus.off(`store:${key}`, callback);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public clear(): void {
|
|
31
|
-
this._state = {};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
protected onDestroy(): void {
|
|
35
|
-
this.clear();
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const AppStore = Store.getInstance();
|
|
File without changes
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { AttributesHelper, IAttributesConfig } from "../helpers/attributes.helper.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ```typescript
|
|
5
|
-
interface IAttributesConfig {
|
|
6
|
-
{{#if i18n}}
|
|
7
|
-
i18nKey?: string;
|
|
8
|
-
{{/if}}
|
|
9
|
-
textContent?: string;
|
|
10
|
-
className?: string;
|
|
11
|
-
style?: string;
|
|
12
|
-
// use regular pipe syntax for arguments / chaining
|
|
13
|
-
pipes?: string;
|
|
14
|
-
}
|
|
15
|
-
interface IAnchorConfig extends IAttributesConfig {
|
|
16
|
-
// prefix href with '#' for internal anchor
|
|
17
|
-
href: string;
|
|
18
|
-
target?: string;
|
|
19
|
-
tagName?: keyof HTMLElementTagNameMap;
|
|
20
|
-
}
|
|
21
|
-
```
|
|
22
|
-
*/
|
|
23
|
-
export interface IAnchorConfig extends IAttributesConfig {
|
|
24
|
-
href: string;
|
|
25
|
-
target?: string;
|
|
26
|
-
tagName?: keyof HTMLElementTagNameMap;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class AnchorManager {
|
|
30
|
-
private config: IAnchorConfig;
|
|
31
|
-
|
|
32
|
-
constructor(
|
|
33
|
-
config: IAnchorConfig,
|
|
34
|
-
target: HTMLElement
|
|
35
|
-
) {
|
|
36
|
-
this.config = config;
|
|
37
|
-
this.appendAnchorElement(target);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
private appendAnchorElement(target: HTMLElement): void {
|
|
41
|
-
const container = this.createAnchorContainer();
|
|
42
|
-
target.appendChild(container);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
private createAnchorContainer(): HTMLSpanElement {
|
|
46
|
-
const container = document.createElement('span');
|
|
47
|
-
const anchor = this.createAnchor();
|
|
48
|
-
container.appendChild(anchor);
|
|
49
|
-
return container;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private createAnchor(): HTMLElement {
|
|
53
|
-
const anchor = document.createElement('a');
|
|
54
|
-
this.setAnchorRef(anchor);
|
|
55
|
-
AttributesHelper.setAttributes(anchor, this.config);
|
|
56
|
-
this.handleClick(anchor);
|
|
57
|
-
return anchor;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
private setAnchorRef(anchor: HTMLAnchorElement): void {
|
|
61
|
-
anchor.setAttribute('href', this.config.href);
|
|
62
|
-
if (this.config.target) {
|
|
63
|
-
anchor.setAttribute('target', this.config.target);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private handleClick(anchor: HTMLAnchorElement): void {
|
|
68
|
-
const isInternal = this.config.href.startsWith('#');
|
|
69
|
-
if (!isInternal) return;
|
|
70
|
-
|
|
71
|
-
const id = this.config.href.slice(1);
|
|
72
|
-
|
|
73
|
-
anchor?.addEventListener('click', (e) => {
|
|
74
|
-
e.preventDefault();
|
|
75
|
-
const target = document.getElementById(id);
|
|
76
|
-
this.scrollToTarget(target);
|
|
77
|
-
this.accessibilityFeatures(target, id);
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
private scrollToTarget(target: HTMLElement | null): void {
|
|
82
|
-
const targetPosition = target?.offsetTop;
|
|
83
|
-
window.scrollTo({
|
|
84
|
-
top: targetPosition,
|
|
85
|
-
behavior: 'smooth'
|
|
86
|
-
})
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private accessibilityFeatures(target: HTMLElement | null, id: string) {
|
|
90
|
-
this.setFocus(target);
|
|
91
|
-
this.setAriaLive(target, id);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
private setFocus(target: HTMLElement | null): void {
|
|
95
|
-
setTimeout(() => {
|
|
96
|
-
target?.setAttribute('tabindex', '-1');
|
|
97
|
-
target?.focus({ preventScroll: true });
|
|
98
|
-
// Remove tabindex after focus
|
|
99
|
-
target?.addEventListener('blur', () => {
|
|
100
|
-
target?.removeAttribute('tabindex');
|
|
101
|
-
}, { once: true });
|
|
102
|
-
}, 100);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
private setAriaLive(target: HTMLElement | null, id: string): void {
|
|
106
|
-
const announcement = document.createElement('div');
|
|
107
|
-
announcement.setAttribute('aria-live', 'polite');
|
|
108
|
-
announcement.className = 'sr-only';
|
|
109
|
-
announcement.textContent = `Navigated to ${ target?.textContent || id }`;
|
|
110
|
-
document.body.appendChild(announcement);
|
|
111
|
-
setTimeout(() => document.body.removeChild(announcement), 1000);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
import { ButtonManager } from '#root/dist/src/core/index.js';
|
|
2
|
-
|
|
3
|
-
describe('ButtonManager', () => {
|
|
4
|
-
it('should initialize with default options', () => {
|
|
5
|
-
const mockComponent = {};
|
|
6
|
-
const manager = new ButtonManager(mockComponent);
|
|
7
|
-
|
|
8
|
-
expect(manager.component).toBe(mockComponent);
|
|
9
|
-
expect(manager.buttons.length).toBe(0);
|
|
10
|
-
expect(manager.containerOptions.containerClassName).toBe('dynamic-buttons');
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should initialize with custom options', () => {
|
|
14
|
-
const mockComponent = {};
|
|
15
|
-
const buttons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test' }];
|
|
16
|
-
const options = {
|
|
17
|
-
containerClassName: 'custom-container',
|
|
18
|
-
buttonClassName: 'custom-button'
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const manager = new ButtonManager(mockComponent, buttons, options);
|
|
22
|
-
|
|
23
|
-
expect(manager.buttons.length).toBe(1);
|
|
24
|
-
expect(manager.containerOptions.containerClassName).toBe('custom-container');
|
|
25
|
-
expect(manager.containerOptions.buttonClassName).toBe('custom-button');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should return null for empty buttons array', () => {
|
|
29
|
-
const mockComponent = {};
|
|
30
|
-
const manager = new ButtonManager(mockComponent, []);
|
|
31
|
-
|
|
32
|
-
const container = manager.createButtonContainer();
|
|
33
|
-
expect(container).toBeUndefined();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should return null for undefined buttons', () => {
|
|
37
|
-
const mockComponent = {};
|
|
38
|
-
const manager = new ButtonManager(mockComponent);
|
|
39
|
-
|
|
40
|
-
const container = manager.createButtonContainer();
|
|
41
|
-
expect(container).toBeUndefined();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should create container with correct class name', () => {
|
|
45
|
-
const mockComponent = {};
|
|
46
|
-
const buttons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test' }];
|
|
47
|
-
const manager = new ButtonManager(mockComponent, buttons);
|
|
48
|
-
|
|
49
|
-
const container = manager.createButtonContainer();
|
|
50
|
-
|
|
51
|
-
expect(container).toBeDefined();
|
|
52
|
-
expect(container.className).toBe('dynamic-buttons');
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('should create container with custom class name', () => {
|
|
56
|
-
const mockComponent = {};
|
|
57
|
-
const buttons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test' }];
|
|
58
|
-
const options = { containerClassName: 'my-buttons' };
|
|
59
|
-
const manager = new ButtonManager(mockComponent, buttons, options);
|
|
60
|
-
|
|
61
|
-
const container = manager.createButtonContainer();
|
|
62
|
-
|
|
63
|
-
expect(container.className).toBe('my-buttons');
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should create correct number of buttons', () => {
|
|
67
|
-
const mockComponent = {};
|
|
68
|
-
const buttons = [
|
|
69
|
-
{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'button1' },
|
|
70
|
-
{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'button2' },
|
|
71
|
-
{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'button3' }
|
|
72
|
-
];
|
|
73
|
-
const manager = new ButtonManager(mockComponent, buttons);
|
|
74
|
-
|
|
75
|
-
const container = manager.createButtonContainer();
|
|
76
|
-
|
|
77
|
-
expect(container.children.length).toBe(3);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should create button with {{#if i18n}}i18nKey{{else}}textContent{{/if}} as text', () => {
|
|
81
|
-
const mockComponent = {};
|
|
82
|
-
const manager = new ButtonManager(mockComponent);
|
|
83
|
-
const btn = { {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'save' };
|
|
84
|
-
|
|
85
|
-
const button = manager.createButton(btn, 0);
|
|
86
|
-
|
|
87
|
-
{{#if i18n}}
|
|
88
|
-
expect(button.getAttribute('data-i18n')).toBe('save');
|
|
89
|
-
{{else}}
|
|
90
|
-
expect(button.textContent).toBe('save');
|
|
91
|
-
{{/if}}
|
|
92
|
-
});
|
|
93
|
-
{{#if i18n}}
|
|
94
|
-
|
|
95
|
-
it('should prioritize textContent over i18nKey', () => {
|
|
96
|
-
const mockComponent = {};
|
|
97
|
-
const manager = new ButtonManager(mockComponent);
|
|
98
|
-
const btn = {
|
|
99
|
-
i18nKey: 'save',
|
|
100
|
-
textContent: 'Save Document'
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const button = manager.createButton(btn, 0);
|
|
104
|
-
|
|
105
|
-
expect(button.textContent).toBe('Save Document');
|
|
106
|
-
expect(button.getAttribute('data-i18n')).toBe('save');
|
|
107
|
-
});
|
|
108
|
-
{{/if}}
|
|
109
|
-
|
|
110
|
-
it('should set button className correctly', () => {
|
|
111
|
-
const mockComponent = {};
|
|
112
|
-
const manager = new ButtonManager(mockComponent, []);
|
|
113
|
-
const btn = {
|
|
114
|
-
i18nKey: 'save',
|
|
115
|
-
className: 'btn-primary'
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const button = manager.createButton(btn, 0);
|
|
119
|
-
|
|
120
|
-
expect(button.className).toBe('btn-primary');
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('should set data-event attribute correctly', () => {
|
|
124
|
-
const mockComponent = {};
|
|
125
|
-
const manager = new ButtonManager(mockComponent);
|
|
126
|
-
const btn = { {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'save' };
|
|
127
|
-
|
|
128
|
-
const button = manager.createButton(btn, 2);
|
|
129
|
-
|
|
130
|
-
expect(button.getAttribute('data-event')).toBe('click:onButtonClick_2');
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('should bind callback method to component', () => {
|
|
134
|
-
const mockComponent = {};
|
|
135
|
-
const manager = new ButtonManager(mockComponent);
|
|
136
|
-
const btn = {
|
|
137
|
-
{{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test',
|
|
138
|
-
callback: () => 'called'
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
manager.bindButtonCallback(btn, 1);
|
|
142
|
-
|
|
143
|
-
expect(typeof mockComponent.onButtonClick_1).toBe('function')
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('should execute callback when bound method is called', () => {
|
|
147
|
-
const mockComponent = {};
|
|
148
|
-
const manager = new ButtonManager(mockComponent);
|
|
149
|
-
let callbackExecuted = false;
|
|
150
|
-
const btn = {
|
|
151
|
-
{{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test',
|
|
152
|
-
callback: () => { callbackExecuted = true; }
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
manager.bindButtonCallback(btn, 0);
|
|
156
|
-
mockComponent.onButtonClick_0();
|
|
157
|
-
|
|
158
|
-
expect(callbackExecuted).toBe(true);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('should append button container to target element', () => {
|
|
162
|
-
const mockComponent = {};
|
|
163
|
-
const buttons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test' }];
|
|
164
|
-
const manager = new ButtonManager(mockComponent, buttons);
|
|
165
|
-
const target = document.createElement('div');
|
|
166
|
-
|
|
167
|
-
manager.appendTo(target);
|
|
168
|
-
|
|
169
|
-
expect(target.children.length).toBe(1);
|
|
170
|
-
expect(target.children[0].className).toBe('dynamic-buttons')
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('should not append anything for empty buttons', () => {
|
|
174
|
-
const mockComponent = {};
|
|
175
|
-
const manager = new ButtonManager(mockComponent, []);
|
|
176
|
-
const target = document.createElement('div');
|
|
177
|
-
|
|
178
|
-
manager.appendTo(target);
|
|
179
|
-
|
|
180
|
-
expect(target.children.length).toBe(0);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('should create complete button setup end-to-end', () => {
|
|
184
|
-
const mockComponent = {};
|
|
185
|
-
let button1Clicked = false;
|
|
186
|
-
let button2Clicked = false;
|
|
187
|
-
|
|
188
|
-
const buttons = [
|
|
189
|
-
{
|
|
190
|
-
{{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'save',
|
|
191
|
-
className: 'btn-primary',
|
|
192
|
-
callback: () => { button1Clicked = true; }
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
{{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'cancel',
|
|
196
|
-
textContent: 'Cancel Action',
|
|
197
|
-
className: 'btn-secondary',
|
|
198
|
-
callback: () => { button2Clicked = true; }
|
|
199
|
-
}
|
|
200
|
-
];
|
|
201
|
-
|
|
202
|
-
const manager = new ButtonManager(mockComponent, buttons, {
|
|
203
|
-
containerClassName: 'form-buttons'
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
const container = manager.createButtonContainer();
|
|
207
|
-
|
|
208
|
-
expect(container.className).toBe('form-buttons');
|
|
209
|
-
expect(container.children.length).toBe(2);
|
|
210
|
-
|
|
211
|
-
const firstButton = container.children[0];
|
|
212
|
-
expect(firstButton.className).toBe('btn-primary');
|
|
213
|
-
expect(firstButton.getAttribute('data-event')).toBe('click:onButtonClick_0');
|
|
214
|
-
|
|
215
|
-
const secondButton = container.children[1];
|
|
216
|
-
expect(secondButton.className).toBe('btn-secondary');
|
|
217
|
-
expect(secondButton.getAttribute('data-event')).toBe('click:onButtonClick_1');
|
|
218
|
-
|
|
219
|
-
mockComponent.onButtonClick_0();
|
|
220
|
-
mockComponent.onButtonClick_1();
|
|
221
|
-
|
|
222
|
-
expect(button1Clicked).toBe(true);
|
|
223
|
-
expect(button2Clicked).toBe(true);
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it('should handle button with empty {{#if i18n}}i18nKey{{else}}textContent{{/if}}', () => {
|
|
227
|
-
const mockComponent = {};
|
|
228
|
-
const manager = new ButtonManager(mockComponent);
|
|
229
|
-
const btn = { {{#if i18n}}i18nKey{{else}}textContent{{/if}}: '' };
|
|
230
|
-
|
|
231
|
-
const button = manager.createButton(btn, 0);
|
|
232
|
-
|
|
233
|
-
expect(button.textContent).toBe('');
|
|
234
|
-
expect(button.getAttribute('data-i18n')).toBe(null);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('should handle updateButtons method', () => {
|
|
238
|
-
const mockComponent = {};
|
|
239
|
-
const initialButtons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'initial' }];
|
|
240
|
-
const manager = new ButtonManager(mockComponent, initialButtons);
|
|
241
|
-
|
|
242
|
-
const newButtons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'new1' }, { {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'new2' }];
|
|
243
|
-
manager.updateButtons(newButtons);
|
|
244
|
-
|
|
245
|
-
expect(manager.buttons.length).toBe(2);
|
|
246
|
-
expect(manager.buttons[0].{{#if i18n}}i18nKey{{else}}textContent{{/if}}).toBe('new1');
|
|
247
|
-
expect(manager.buttons[1].{{#if i18n}}i18nKey{{else}}textContent{{/if}}).toBe('new2');
|
|
248
|
-
});
|
|
249
|
-
})
|