@jahia/agentic 0.3.0 → 0.4.1
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 +8 -0
- package/dist/claude/.claude/rules/jahia.md +13 -40
- package/dist/claude/.claude/skills/jahia-cnd-author/SKILL.md +94 -0
- package/dist/claude/.claude/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
- package/dist/claude/.claude/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
- package/dist/claude/.claude/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
- package/dist/claude/.claude/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
- package/dist/claude/.claude/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
- package/dist/claude/.claude/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
- package/dist/claude/.claude/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
- package/dist/claude/.claude/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
- package/dist/claude/.claude/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
- package/dist/claude/.claude/skills/jahia-dev-accessibility/SKILL.md +5 -265
- package/dist/claude/.claude/skills/jahia-dev-build-component/SKILL.md +15 -7
- package/dist/claude/.claude/skills/jahia-dev-create-page-template/SKILL.md +59 -21
- package/dist/claude/.claude/skills/jahia-dev-create-template-set/SKILL.md +20 -47
- package/dist/claude/.claude/skills/jahia-dev-create-view/SKILL.md +3 -3
- package/dist/claude/.claude/skills/jahia-dev-review-cnd/SKILL.md +79 -0
- package/dist/claude/.claude/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
- package/dist/claude/.claude/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
- package/dist/claude/.claude/skills/jahia-dev-site-review/SKILL.md +70 -0
- package/dist/claude/.claude/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
- package/dist/claude/.claude/skills/jahia-dev-start-local/SKILL.md +18 -26
- package/dist/claude/CLAUDE.md +14 -41
- package/dist/codex/.agents/skills/jahia-cnd-author/SKILL.md +94 -0
- package/dist/codex/.agents/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
- package/dist/codex/.agents/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
- package/dist/codex/.agents/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
- package/dist/codex/.agents/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
- package/dist/codex/.agents/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
- package/dist/codex/.agents/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
- package/dist/codex/.agents/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
- package/dist/codex/.agents/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
- package/dist/codex/.agents/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
- package/dist/codex/.agents/skills/jahia-dev-accessibility/SKILL.md +5 -265
- package/dist/codex/.agents/skills/jahia-dev-build-component/SKILL.md +15 -7
- package/dist/codex/.agents/skills/jahia-dev-create-page-template/SKILL.md +59 -21
- package/dist/codex/.agents/skills/jahia-dev-create-template-set/SKILL.md +20 -47
- package/dist/codex/.agents/skills/jahia-dev-create-view/SKILL.md +3 -3
- package/dist/codex/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
- package/dist/codex/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
- package/dist/codex/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
- package/dist/codex/.agents/skills/jahia-dev-site-review/SKILL.md +70 -0
- package/dist/codex/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
- package/dist/codex/.agents/skills/jahia-dev-start-local/SKILL.md +18 -26
- package/dist/codex/AGENTS.md +15 -42
- package/dist/copilot/.agents/skills/jahia-cnd-author/SKILL.md +94 -0
- package/dist/copilot/.agents/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
- package/dist/copilot/.agents/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
- package/dist/copilot/.agents/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
- package/dist/copilot/.agents/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
- package/dist/copilot/.agents/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
- package/dist/copilot/.agents/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
- package/dist/copilot/.agents/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
- package/dist/copilot/.agents/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
- package/dist/copilot/.agents/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
- package/dist/copilot/.agents/skills/jahia-dev-accessibility/SKILL.md +5 -265
- package/dist/copilot/.agents/skills/jahia-dev-build-component/SKILL.md +15 -7
- package/dist/copilot/.agents/skills/jahia-dev-create-page-template/SKILL.md +59 -21
- package/dist/copilot/.agents/skills/jahia-dev-create-template-set/SKILL.md +20 -47
- package/dist/copilot/.agents/skills/jahia-dev-create-view/SKILL.md +3 -3
- package/dist/copilot/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
- package/dist/copilot/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
- package/dist/copilot/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
- package/dist/copilot/.agents/skills/jahia-dev-site-review/SKILL.md +70 -0
- package/dist/copilot/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
- package/dist/copilot/.agents/skills/jahia-dev-start-local/SKILL.md +18 -26
- package/dist/copilot/AGENTS.md +15 -42
- package/dist/cursor/.agents/skills/jahia-cnd-author/SKILL.md +94 -0
- package/dist/cursor/.agents/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
- package/dist/cursor/.agents/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
- package/dist/cursor/.agents/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
- package/dist/cursor/.agents/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
- package/dist/cursor/.agents/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
- package/dist/cursor/.agents/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
- package/dist/cursor/.agents/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
- package/dist/cursor/.agents/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
- package/dist/cursor/.agents/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
- package/dist/cursor/.agents/skills/jahia-dev-accessibility/SKILL.md +5 -265
- package/dist/cursor/.agents/skills/jahia-dev-build-component/SKILL.md +15 -7
- package/dist/cursor/.agents/skills/jahia-dev-create-page-template/SKILL.md +59 -21
- package/dist/cursor/.agents/skills/jahia-dev-create-template-set/SKILL.md +20 -47
- package/dist/cursor/.agents/skills/jahia-dev-create-view/SKILL.md +3 -3
- package/dist/cursor/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
- package/dist/cursor/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
- package/dist/cursor/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
- package/dist/cursor/.agents/skills/jahia-dev-site-review/SKILL.md +70 -0
- package/dist/cursor/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
- package/dist/cursor/.agents/skills/jahia-dev-start-local/SKILL.md +18 -26
- package/dist/cursor/.cursor/rules/jahia.mdc +13 -40
- package/dist/gemini/.agents/skills/jahia-cnd-author/SKILL.md +94 -0
- package/dist/gemini/.agents/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
- package/dist/gemini/.agents/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
- package/dist/gemini/.agents/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
- package/dist/gemini/.agents/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
- package/dist/gemini/.agents/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
- package/dist/gemini/.agents/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
- package/dist/gemini/.agents/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
- package/dist/gemini/.agents/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
- package/dist/gemini/.agents/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
- package/dist/gemini/.agents/skills/jahia-dev-accessibility/SKILL.md +5 -265
- package/dist/gemini/.agents/skills/jahia-dev-build-component/SKILL.md +15 -7
- package/dist/gemini/.agents/skills/jahia-dev-create-page-template/SKILL.md +59 -21
- package/dist/gemini/.agents/skills/jahia-dev-create-template-set/SKILL.md +20 -47
- package/dist/gemini/.agents/skills/jahia-dev-create-view/SKILL.md +3 -3
- package/dist/gemini/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
- package/dist/gemini/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
- package/dist/gemini/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
- package/dist/gemini/.agents/skills/jahia-dev-site-review/SKILL.md +70 -0
- package/dist/gemini/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
- package/dist/gemini/.agents/skills/jahia-dev-start-local/SKILL.md +18 -26
- package/dist/gemini/AGENTS.md +15 -42
- package/dist/gemini/GEMINI.md +2 -2
- package/dist/index.js +13 -0
- package/dist/opencode/.agents/skills/jahia-cnd-author/SKILL.md +94 -0
- package/dist/opencode/.agents/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
- package/dist/opencode/.agents/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
- package/dist/opencode/.agents/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
- package/dist/opencode/.agents/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
- package/dist/opencode/.agents/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
- package/dist/opencode/.agents/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
- package/dist/opencode/.agents/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
- package/dist/opencode/.agents/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
- package/dist/opencode/.agents/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
- package/dist/opencode/.agents/skills/jahia-dev-accessibility/SKILL.md +5 -265
- package/dist/opencode/.agents/skills/jahia-dev-build-component/SKILL.md +15 -7
- package/dist/opencode/.agents/skills/jahia-dev-create-page-template/SKILL.md +59 -21
- package/dist/opencode/.agents/skills/jahia-dev-create-template-set/SKILL.md +20 -47
- package/dist/opencode/.agents/skills/jahia-dev-create-view/SKILL.md +3 -3
- package/dist/opencode/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
- package/dist/opencode/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
- package/dist/opencode/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
- package/dist/opencode/.agents/skills/jahia-dev-site-review/SKILL.md +70 -0
- package/dist/opencode/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
- package/dist/opencode/.agents/skills/jahia-dev-start-local/SKILL.md +18 -26
- package/dist/opencode/AGENTS.md +15 -42
- package/dist/windsurf/.windsurf/rules/jahia.md +13 -40
- package/dist/windsurf/.windsurf/skills/jahia-cnd-author/SKILL.md +94 -0
- package/dist/windsurf/.windsurf/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
- package/dist/windsurf/.windsurf/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
- package/dist/windsurf/.windsurf/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
- package/dist/windsurf/.windsurf/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
- package/dist/windsurf/.windsurf/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
- package/dist/windsurf/.windsurf/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
- package/dist/windsurf/.windsurf/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
- package/dist/windsurf/.windsurf/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
- package/dist/windsurf/.windsurf/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-accessibility/SKILL.md +5 -265
- package/dist/windsurf/.windsurf/skills/jahia-dev-build-component/SKILL.md +15 -7
- package/dist/windsurf/.windsurf/skills/jahia-dev-create-page-template/SKILL.md +59 -21
- package/dist/windsurf/.windsurf/skills/jahia-dev-create-template-set/SKILL.md +20 -47
- package/dist/windsurf/.windsurf/skills/jahia-dev-create-view/SKILL.md +3 -3
- package/dist/windsurf/.windsurf/skills/jahia-dev-review-cnd/SKILL.md +79 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-site-review/SKILL.md +70 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-start-local/SKILL.md +18 -26
- package/dist/windsurf/AGENTS.md +15 -42
- package/package.json +1 -1
- package/dist/claude/.claude/skills/jahia/SKILL.md +0 -144
- package/dist/claude/.claude/skills/jahia-content/SKILL.md +0 -157
- package/dist/claude/.claude/skills/jahia-content-create-content/SKILL.md +0 -359
- package/dist/claude/.claude/skills/jahia-content-explore-structure/SKILL.md +0 -255
- package/dist/claude/.claude/skills/jahia-content-media-upload/SKILL.md +0 -197
- package/dist/claude/.claude/skills/jahia-content-move-content/SKILL.md +0 -231
- package/dist/claude/.claude/skills/jahia-content-organize/SKILL.md +0 -209
- package/dist/claude/.claude/skills/jahia-content-publish/SKILL.md +0 -181
- package/dist/claude/.claude/skills/jahia-content-query-content/SKILL.md +0 -174
- package/dist/claude/.claude/skills/jahia-content-translate-content/SKILL.md +0 -226
- package/dist/claude/.claude/skills/jahia-dev/SKILL.md +0 -124
- package/dist/claude/.claude/skills/jahia-dev-apis/SKILL.md +0 -52
- package/dist/claude/.claude/skills/jahia-dev-apis/references/authentication.md +0 -484
- package/dist/claude/.claude/skills/jahia-dev-apis/references/graphql.md +0 -657
- package/dist/claude/.claude/skills/jahia-dev-apis/references/jcr-api.md +0 -465
- package/dist/claude/.claude/skills/jahia-dev-apis/references/security.md +0 -541
- package/dist/claude/.claude/skills/jahia-dev-cypress/SKILL.md +0 -265
- package/dist/claude/.claude/skills/jahia-dev-define-content-type/SKILL.md +0 -536
- package/dist/claude/.claude/skills/jahia-dev-java/SKILL.md +0 -110
- package/dist/claude/.claude/skills/jahia-dev-java/references/backend.md +0 -331
- package/dist/claude/.claude/skills/jahia-dev-java/references/content-types.md +0 -273
- package/dist/claude/.claude/skills/jahia-dev-java/references/modules.md +0 -218
- package/dist/claude/.claude/skills/jahia-dev-java/references/osgi.md +0 -208
- package/dist/claude/.claude/skills/jahia-dev-java/references/rendering.md +0 -191
- package/dist/claude/.claude/skills/jahia-dev-java/references/ui-extensions.md +0 -344
- package/dist/claude/.claude/skills/jahia-dev-osgi-module/SKILL.md +0 -297
- package/dist/claude/.claude/skills/jahia-dev-ui-extension/SKILL.md +0 -559
- package/dist/claude/.claude/skills/jahia-java-concurrency/SKILL.md +0 -308
- package/dist/claude/.claude/skills/jahia-java-jcr/SKILL.md +0 -153
- package/dist/claude/.claude/skills/jahia-java-osgi/SKILL.md +0 -134
- package/dist/claude/.claude/skills/jahia-java-persistence/SKILL.md +0 -177
- package/dist/claude/.claude/skills/jahia-java-security/SKILL.md +0 -84
- package/dist/claude/.claude/skills/jahia-review-java/SKILL.md +0 -131
- package/dist/claude/.claude/skills/jahia-review-java/references/code-review-output.md +0 -121
- package/dist/codex/.agents/skills/jahia/SKILL.md +0 -144
- package/dist/codex/.agents/skills/jahia-content/SKILL.md +0 -157
- package/dist/codex/.agents/skills/jahia-content-create-content/SKILL.md +0 -359
- package/dist/codex/.agents/skills/jahia-content-explore-structure/SKILL.md +0 -255
- package/dist/codex/.agents/skills/jahia-content-media-upload/SKILL.md +0 -197
- package/dist/codex/.agents/skills/jahia-content-move-content/SKILL.md +0 -231
- package/dist/codex/.agents/skills/jahia-content-organize/SKILL.md +0 -209
- package/dist/codex/.agents/skills/jahia-content-publish/SKILL.md +0 -181
- package/dist/codex/.agents/skills/jahia-content-query-content/SKILL.md +0 -174
- package/dist/codex/.agents/skills/jahia-content-translate-content/SKILL.md +0 -226
- package/dist/codex/.agents/skills/jahia-dev/SKILL.md +0 -124
- package/dist/codex/.agents/skills/jahia-dev-apis/SKILL.md +0 -52
- package/dist/codex/.agents/skills/jahia-dev-apis/references/authentication.md +0 -484
- package/dist/codex/.agents/skills/jahia-dev-apis/references/graphql.md +0 -657
- package/dist/codex/.agents/skills/jahia-dev-apis/references/jcr-api.md +0 -465
- package/dist/codex/.agents/skills/jahia-dev-apis/references/security.md +0 -541
- package/dist/codex/.agents/skills/jahia-dev-cypress/SKILL.md +0 -265
- package/dist/codex/.agents/skills/jahia-dev-define-content-type/SKILL.md +0 -536
- package/dist/codex/.agents/skills/jahia-dev-java/SKILL.md +0 -110
- package/dist/codex/.agents/skills/jahia-dev-java/references/backend.md +0 -331
- package/dist/codex/.agents/skills/jahia-dev-java/references/content-types.md +0 -273
- package/dist/codex/.agents/skills/jahia-dev-java/references/modules.md +0 -218
- package/dist/codex/.agents/skills/jahia-dev-java/references/osgi.md +0 -208
- package/dist/codex/.agents/skills/jahia-dev-java/references/rendering.md +0 -191
- package/dist/codex/.agents/skills/jahia-dev-java/references/ui-extensions.md +0 -344
- package/dist/codex/.agents/skills/jahia-dev-osgi-module/SKILL.md +0 -297
- package/dist/codex/.agents/skills/jahia-dev-ui-extension/SKILL.md +0 -559
- package/dist/codex/.agents/skills/jahia-java-concurrency/SKILL.md +0 -308
- package/dist/codex/.agents/skills/jahia-java-jcr/SKILL.md +0 -153
- package/dist/codex/.agents/skills/jahia-java-osgi/SKILL.md +0 -134
- package/dist/codex/.agents/skills/jahia-java-persistence/SKILL.md +0 -177
- package/dist/codex/.agents/skills/jahia-java-security/SKILL.md +0 -84
- package/dist/codex/.agents/skills/jahia-review-java/SKILL.md +0 -131
- package/dist/codex/.agents/skills/jahia-review-java/references/code-review-output.md +0 -121
- package/dist/copilot/.agents/skills/jahia/SKILL.md +0 -144
- package/dist/copilot/.agents/skills/jahia-content/SKILL.md +0 -157
- package/dist/copilot/.agents/skills/jahia-content-create-content/SKILL.md +0 -359
- package/dist/copilot/.agents/skills/jahia-content-explore-structure/SKILL.md +0 -255
- package/dist/copilot/.agents/skills/jahia-content-media-upload/SKILL.md +0 -197
- package/dist/copilot/.agents/skills/jahia-content-move-content/SKILL.md +0 -231
- package/dist/copilot/.agents/skills/jahia-content-organize/SKILL.md +0 -209
- package/dist/copilot/.agents/skills/jahia-content-publish/SKILL.md +0 -181
- package/dist/copilot/.agents/skills/jahia-content-query-content/SKILL.md +0 -174
- package/dist/copilot/.agents/skills/jahia-content-translate-content/SKILL.md +0 -226
- package/dist/copilot/.agents/skills/jahia-dev/SKILL.md +0 -124
- package/dist/copilot/.agents/skills/jahia-dev-apis/SKILL.md +0 -52
- package/dist/copilot/.agents/skills/jahia-dev-apis/references/authentication.md +0 -484
- package/dist/copilot/.agents/skills/jahia-dev-apis/references/graphql.md +0 -657
- package/dist/copilot/.agents/skills/jahia-dev-apis/references/jcr-api.md +0 -465
- package/dist/copilot/.agents/skills/jahia-dev-apis/references/security.md +0 -541
- package/dist/copilot/.agents/skills/jahia-dev-cypress/SKILL.md +0 -265
- package/dist/copilot/.agents/skills/jahia-dev-define-content-type/SKILL.md +0 -536
- package/dist/copilot/.agents/skills/jahia-dev-java/SKILL.md +0 -110
- package/dist/copilot/.agents/skills/jahia-dev-java/references/backend.md +0 -331
- package/dist/copilot/.agents/skills/jahia-dev-java/references/content-types.md +0 -273
- package/dist/copilot/.agents/skills/jahia-dev-java/references/modules.md +0 -218
- package/dist/copilot/.agents/skills/jahia-dev-java/references/osgi.md +0 -208
- package/dist/copilot/.agents/skills/jahia-dev-java/references/rendering.md +0 -191
- package/dist/copilot/.agents/skills/jahia-dev-java/references/ui-extensions.md +0 -344
- package/dist/copilot/.agents/skills/jahia-dev-osgi-module/SKILL.md +0 -297
- package/dist/copilot/.agents/skills/jahia-dev-ui-extension/SKILL.md +0 -559
- package/dist/copilot/.agents/skills/jahia-java-concurrency/SKILL.md +0 -308
- package/dist/copilot/.agents/skills/jahia-java-jcr/SKILL.md +0 -153
- package/dist/copilot/.agents/skills/jahia-java-osgi/SKILL.md +0 -134
- package/dist/copilot/.agents/skills/jahia-java-persistence/SKILL.md +0 -177
- package/dist/copilot/.agents/skills/jahia-java-security/SKILL.md +0 -84
- package/dist/copilot/.agents/skills/jahia-review-java/SKILL.md +0 -131
- package/dist/copilot/.agents/skills/jahia-review-java/references/code-review-output.md +0 -121
- package/dist/cursor/.agents/skills/jahia/SKILL.md +0 -144
- package/dist/cursor/.agents/skills/jahia-content/SKILL.md +0 -157
- package/dist/cursor/.agents/skills/jahia-content-create-content/SKILL.md +0 -359
- package/dist/cursor/.agents/skills/jahia-content-explore-structure/SKILL.md +0 -255
- package/dist/cursor/.agents/skills/jahia-content-media-upload/SKILL.md +0 -197
- package/dist/cursor/.agents/skills/jahia-content-move-content/SKILL.md +0 -231
- package/dist/cursor/.agents/skills/jahia-content-organize/SKILL.md +0 -209
- package/dist/cursor/.agents/skills/jahia-content-publish/SKILL.md +0 -181
- package/dist/cursor/.agents/skills/jahia-content-query-content/SKILL.md +0 -174
- package/dist/cursor/.agents/skills/jahia-content-translate-content/SKILL.md +0 -226
- package/dist/cursor/.agents/skills/jahia-dev/SKILL.md +0 -124
- package/dist/cursor/.agents/skills/jahia-dev-apis/SKILL.md +0 -52
- package/dist/cursor/.agents/skills/jahia-dev-apis/references/authentication.md +0 -484
- package/dist/cursor/.agents/skills/jahia-dev-apis/references/graphql.md +0 -657
- package/dist/cursor/.agents/skills/jahia-dev-apis/references/jcr-api.md +0 -465
- package/dist/cursor/.agents/skills/jahia-dev-apis/references/security.md +0 -541
- package/dist/cursor/.agents/skills/jahia-dev-cypress/SKILL.md +0 -265
- package/dist/cursor/.agents/skills/jahia-dev-define-content-type/SKILL.md +0 -536
- package/dist/cursor/.agents/skills/jahia-dev-java/SKILL.md +0 -110
- package/dist/cursor/.agents/skills/jahia-dev-java/references/backend.md +0 -331
- package/dist/cursor/.agents/skills/jahia-dev-java/references/content-types.md +0 -273
- package/dist/cursor/.agents/skills/jahia-dev-java/references/modules.md +0 -218
- package/dist/cursor/.agents/skills/jahia-dev-java/references/osgi.md +0 -208
- package/dist/cursor/.agents/skills/jahia-dev-java/references/rendering.md +0 -191
- package/dist/cursor/.agents/skills/jahia-dev-java/references/ui-extensions.md +0 -344
- package/dist/cursor/.agents/skills/jahia-dev-osgi-module/SKILL.md +0 -297
- package/dist/cursor/.agents/skills/jahia-dev-ui-extension/SKILL.md +0 -559
- package/dist/cursor/.agents/skills/jahia-java-concurrency/SKILL.md +0 -308
- package/dist/cursor/.agents/skills/jahia-java-jcr/SKILL.md +0 -153
- package/dist/cursor/.agents/skills/jahia-java-osgi/SKILL.md +0 -134
- package/dist/cursor/.agents/skills/jahia-java-persistence/SKILL.md +0 -177
- package/dist/cursor/.agents/skills/jahia-java-security/SKILL.md +0 -84
- package/dist/cursor/.agents/skills/jahia-review-java/SKILL.md +0 -131
- package/dist/cursor/.agents/skills/jahia-review-java/references/code-review-output.md +0 -121
- package/dist/gemini/.agents/skills/jahia/SKILL.md +0 -144
- package/dist/gemini/.agents/skills/jahia-content/SKILL.md +0 -157
- package/dist/gemini/.agents/skills/jahia-content-create-content/SKILL.md +0 -359
- package/dist/gemini/.agents/skills/jahia-content-explore-structure/SKILL.md +0 -255
- package/dist/gemini/.agents/skills/jahia-content-media-upload/SKILL.md +0 -197
- package/dist/gemini/.agents/skills/jahia-content-move-content/SKILL.md +0 -231
- package/dist/gemini/.agents/skills/jahia-content-organize/SKILL.md +0 -209
- package/dist/gemini/.agents/skills/jahia-content-publish/SKILL.md +0 -181
- package/dist/gemini/.agents/skills/jahia-content-query-content/SKILL.md +0 -174
- package/dist/gemini/.agents/skills/jahia-content-translate-content/SKILL.md +0 -226
- package/dist/gemini/.agents/skills/jahia-dev/SKILL.md +0 -124
- package/dist/gemini/.agents/skills/jahia-dev-apis/SKILL.md +0 -52
- package/dist/gemini/.agents/skills/jahia-dev-apis/references/authentication.md +0 -484
- package/dist/gemini/.agents/skills/jahia-dev-apis/references/graphql.md +0 -657
- package/dist/gemini/.agents/skills/jahia-dev-apis/references/jcr-api.md +0 -465
- package/dist/gemini/.agents/skills/jahia-dev-apis/references/security.md +0 -541
- package/dist/gemini/.agents/skills/jahia-dev-cypress/SKILL.md +0 -265
- package/dist/gemini/.agents/skills/jahia-dev-define-content-type/SKILL.md +0 -536
- package/dist/gemini/.agents/skills/jahia-dev-java/SKILL.md +0 -110
- package/dist/gemini/.agents/skills/jahia-dev-java/references/backend.md +0 -331
- package/dist/gemini/.agents/skills/jahia-dev-java/references/content-types.md +0 -273
- package/dist/gemini/.agents/skills/jahia-dev-java/references/modules.md +0 -218
- package/dist/gemini/.agents/skills/jahia-dev-java/references/osgi.md +0 -208
- package/dist/gemini/.agents/skills/jahia-dev-java/references/rendering.md +0 -191
- package/dist/gemini/.agents/skills/jahia-dev-java/references/ui-extensions.md +0 -344
- package/dist/gemini/.agents/skills/jahia-dev-osgi-module/SKILL.md +0 -297
- package/dist/gemini/.agents/skills/jahia-dev-ui-extension/SKILL.md +0 -559
- package/dist/gemini/.agents/skills/jahia-java-concurrency/SKILL.md +0 -308
- package/dist/gemini/.agents/skills/jahia-java-jcr/SKILL.md +0 -153
- package/dist/gemini/.agents/skills/jahia-java-osgi/SKILL.md +0 -134
- package/dist/gemini/.agents/skills/jahia-java-persistence/SKILL.md +0 -177
- package/dist/gemini/.agents/skills/jahia-java-security/SKILL.md +0 -84
- package/dist/gemini/.agents/skills/jahia-review-java/SKILL.md +0 -131
- package/dist/gemini/.agents/skills/jahia-review-java/references/code-review-output.md +0 -121
- package/dist/opencode/.agents/skills/jahia/SKILL.md +0 -144
- package/dist/opencode/.agents/skills/jahia-content/SKILL.md +0 -157
- package/dist/opencode/.agents/skills/jahia-content-create-content/SKILL.md +0 -359
- package/dist/opencode/.agents/skills/jahia-content-explore-structure/SKILL.md +0 -255
- package/dist/opencode/.agents/skills/jahia-content-media-upload/SKILL.md +0 -197
- package/dist/opencode/.agents/skills/jahia-content-move-content/SKILL.md +0 -231
- package/dist/opencode/.agents/skills/jahia-content-organize/SKILL.md +0 -209
- package/dist/opencode/.agents/skills/jahia-content-publish/SKILL.md +0 -181
- package/dist/opencode/.agents/skills/jahia-content-query-content/SKILL.md +0 -174
- package/dist/opencode/.agents/skills/jahia-content-translate-content/SKILL.md +0 -226
- package/dist/opencode/.agents/skills/jahia-dev/SKILL.md +0 -124
- package/dist/opencode/.agents/skills/jahia-dev-apis/SKILL.md +0 -52
- package/dist/opencode/.agents/skills/jahia-dev-apis/references/authentication.md +0 -484
- package/dist/opencode/.agents/skills/jahia-dev-apis/references/graphql.md +0 -657
- package/dist/opencode/.agents/skills/jahia-dev-apis/references/jcr-api.md +0 -465
- package/dist/opencode/.agents/skills/jahia-dev-apis/references/security.md +0 -541
- package/dist/opencode/.agents/skills/jahia-dev-cypress/SKILL.md +0 -265
- package/dist/opencode/.agents/skills/jahia-dev-define-content-type/SKILL.md +0 -536
- package/dist/opencode/.agents/skills/jahia-dev-java/SKILL.md +0 -110
- package/dist/opencode/.agents/skills/jahia-dev-java/references/backend.md +0 -331
- package/dist/opencode/.agents/skills/jahia-dev-java/references/content-types.md +0 -273
- package/dist/opencode/.agents/skills/jahia-dev-java/references/modules.md +0 -218
- package/dist/opencode/.agents/skills/jahia-dev-java/references/osgi.md +0 -208
- package/dist/opencode/.agents/skills/jahia-dev-java/references/rendering.md +0 -191
- package/dist/opencode/.agents/skills/jahia-dev-java/references/ui-extensions.md +0 -344
- package/dist/opencode/.agents/skills/jahia-dev-osgi-module/SKILL.md +0 -297
- package/dist/opencode/.agents/skills/jahia-dev-ui-extension/SKILL.md +0 -559
- package/dist/opencode/.agents/skills/jahia-java-concurrency/SKILL.md +0 -308
- package/dist/opencode/.agents/skills/jahia-java-jcr/SKILL.md +0 -153
- package/dist/opencode/.agents/skills/jahia-java-osgi/SKILL.md +0 -134
- package/dist/opencode/.agents/skills/jahia-java-persistence/SKILL.md +0 -177
- package/dist/opencode/.agents/skills/jahia-java-security/SKILL.md +0 -84
- package/dist/opencode/.agents/skills/jahia-review-java/SKILL.md +0 -131
- package/dist/opencode/.agents/skills/jahia-review-java/references/code-review-output.md +0 -121
- package/dist/windsurf/.windsurf/skills/jahia/SKILL.md +0 -144
- package/dist/windsurf/.windsurf/skills/jahia-content/SKILL.md +0 -157
- package/dist/windsurf/.windsurf/skills/jahia-content-create-content/SKILL.md +0 -359
- package/dist/windsurf/.windsurf/skills/jahia-content-explore-structure/SKILL.md +0 -255
- package/dist/windsurf/.windsurf/skills/jahia-content-media-upload/SKILL.md +0 -197
- package/dist/windsurf/.windsurf/skills/jahia-content-move-content/SKILL.md +0 -231
- package/dist/windsurf/.windsurf/skills/jahia-content-organize/SKILL.md +0 -209
- package/dist/windsurf/.windsurf/skills/jahia-content-publish/SKILL.md +0 -181
- package/dist/windsurf/.windsurf/skills/jahia-content-query-content/SKILL.md +0 -174
- package/dist/windsurf/.windsurf/skills/jahia-content-translate-content/SKILL.md +0 -226
- package/dist/windsurf/.windsurf/skills/jahia-dev/SKILL.md +0 -124
- package/dist/windsurf/.windsurf/skills/jahia-dev-apis/SKILL.md +0 -52
- package/dist/windsurf/.windsurf/skills/jahia-dev-apis/references/authentication.md +0 -484
- package/dist/windsurf/.windsurf/skills/jahia-dev-apis/references/graphql.md +0 -657
- package/dist/windsurf/.windsurf/skills/jahia-dev-apis/references/jcr-api.md +0 -465
- package/dist/windsurf/.windsurf/skills/jahia-dev-apis/references/security.md +0 -541
- package/dist/windsurf/.windsurf/skills/jahia-dev-cypress/SKILL.md +0 -265
- package/dist/windsurf/.windsurf/skills/jahia-dev-define-content-type/SKILL.md +0 -536
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/SKILL.md +0 -110
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/backend.md +0 -331
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/content-types.md +0 -273
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/modules.md +0 -218
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/osgi.md +0 -208
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/rendering.md +0 -191
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/ui-extensions.md +0 -344
- package/dist/windsurf/.windsurf/skills/jahia-dev-osgi-module/SKILL.md +0 -297
- package/dist/windsurf/.windsurf/skills/jahia-dev-ui-extension/SKILL.md +0 -559
- package/dist/windsurf/.windsurf/skills/jahia-java-concurrency/SKILL.md +0 -308
- package/dist/windsurf/.windsurf/skills/jahia-java-jcr/SKILL.md +0 -153
- package/dist/windsurf/.windsurf/skills/jahia-java-osgi/SKILL.md +0 -134
- package/dist/windsurf/.windsurf/skills/jahia-java-persistence/SKILL.md +0 -177
- package/dist/windsurf/.windsurf/skills/jahia-java-security/SKILL.md +0 -84
- package/dist/windsurf/.windsurf/skills/jahia-review-java/SKILL.md +0 -131
- package/dist/windsurf/.windsurf/skills/jahia-review-java/references/code-review-output.md +0 -121
|
@@ -14,35 +14,72 @@ A **page template** defines the full layout of a page. It is registered with `co
|
|
|
14
14
|
|
|
15
15
|
## Step 1 — Create the template file
|
|
16
16
|
|
|
17
|
-
Page templates live in `src/templates
|
|
17
|
+
Page templates live in `src/templates/<ModuleName>Template/`. Name the file `default.server.tsx`.
|
|
18
18
|
|
|
19
19
|
```tsx
|
|
20
|
-
import
|
|
21
|
-
import {
|
|
20
|
+
import React from "react";
|
|
21
|
+
import { Area, AbsoluteArea, getChildNodes, buildNodeUrl, jahiaComponent } from "@jahia/javascript-modules-library";
|
|
22
|
+
import styles from "./template.module.css";
|
|
22
23
|
|
|
23
24
|
jahiaComponent(
|
|
24
25
|
{
|
|
25
26
|
componentType: "template", // "template" for full pages, not "view"
|
|
26
27
|
nodeType: "jnt:page", // always jnt:page for page templates
|
|
27
|
-
displayName: "
|
|
28
|
-
name: "
|
|
28
|
+
displayName: "Default Template",
|
|
29
|
+
name: "default",
|
|
30
|
+
},
|
|
31
|
+
({ "jcr:title": title }, { renderContext, mainNode }) => {
|
|
32
|
+
// Pages live under /sites/<key>/home — not directly under the site node
|
|
33
|
+
const siteHome = renderContext.getSite().getNode("home");
|
|
34
|
+
const navPages = getChildNodes(siteHome, -1, 0, n => n.isNodeType("jnt:page"));
|
|
35
|
+
const siteName = renderContext.getSite().getPropertyAsString("j:siteTitle") ?? renderContext.getSite().getName();
|
|
36
|
+
return (
|
|
37
|
+
<html lang="en">
|
|
38
|
+
<head>
|
|
39
|
+
<meta charSet="UTF-8" />
|
|
40
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
41
|
+
{/* jcr:title is the short page name — template appends site name for SEO */}
|
|
42
|
+
<title>{title}{siteName ? ` | ${siteName}` : ""}</title>
|
|
43
|
+
</head>
|
|
44
|
+
<body>
|
|
45
|
+
<a href="#main-content" className={styles.skipLink}>Skip to main content</a>
|
|
46
|
+
<header className={styles.header}>
|
|
47
|
+
<nav aria-label="Main navigation">
|
|
48
|
+
<ul className={styles.navList}>
|
|
49
|
+
<li key={siteHome.getPath()}>
|
|
50
|
+
<a href={buildNodeUrl(siteHome)} aria-current={siteHome.getPath() === mainNode.getPath() ? "page" : undefined}>
|
|
51
|
+
{siteHome.getPropertyAsString("jcr:title") ?? siteHome.getName()}
|
|
52
|
+
</a>
|
|
53
|
+
</li>
|
|
54
|
+
{navPages.map(page => (
|
|
55
|
+
<li key={page.getPath()}>
|
|
56
|
+
<a
|
|
57
|
+
href={buildNodeUrl(page)}
|
|
58
|
+
aria-current={page.getPath() === mainNode.getPath() ? "page" : undefined}
|
|
59
|
+
>
|
|
60
|
+
{page.getPropertyAsString("jcr:title") ?? page.getName()}
|
|
61
|
+
</a>
|
|
62
|
+
</li>
|
|
63
|
+
))}
|
|
64
|
+
</ul>
|
|
65
|
+
</nav>
|
|
66
|
+
</header>
|
|
67
|
+
<main id="main-content">
|
|
68
|
+
<h1 className={styles.pageTitle}>{title}</h1>
|
|
69
|
+
<Area name="pagecontent" />
|
|
70
|
+
</main>
|
|
71
|
+
<footer className={styles.footer}>
|
|
72
|
+
<AbsoluteArea name="footer" parent={renderContext.getSite()} />
|
|
73
|
+
<p className={styles.copyright}>{"© "}{renderContext.getSite().getName()}</p>
|
|
74
|
+
</footer>
|
|
75
|
+
</body>
|
|
76
|
+
</html>
|
|
77
|
+
);
|
|
29
78
|
},
|
|
30
|
-
({ "jcr:title": title }, { renderContext }) => (
|
|
31
|
-
<Layout title={title}>
|
|
32
|
-
<Area name="header" nodeType="namespace:header" />
|
|
33
|
-
<main style={{ maxWidth: "40rem", margin: "0 auto" }}>
|
|
34
|
-
<Area name="main" />
|
|
35
|
-
</main>
|
|
36
|
-
<AbsoluteArea
|
|
37
|
-
name="footer"
|
|
38
|
-
parent={renderContext.getSite()}
|
|
39
|
-
nodeType="namespace:footer"
|
|
40
|
-
/>
|
|
41
|
-
</Layout>
|
|
42
|
-
),
|
|
43
79
|
);
|
|
44
80
|
```
|
|
45
81
|
|
|
82
|
+
|
|
46
83
|
---
|
|
47
84
|
|
|
48
85
|
## Step 2 — Choose: Area vs AbsoluteArea
|
|
@@ -266,13 +303,14 @@ After deploying, the new template will appear in the **template selection** step
|
|
|
266
303
|
---
|
|
267
304
|
|
|
268
305
|
## Validation checklist
|
|
269
|
-
- [ ] File is in `src/templates/Page/`
|
|
270
306
|
- [ ] `componentType: "template"` and `nodeType: "jnt:page"`
|
|
271
307
|
- [ ] `name` is set (used in Jahia UI template picker)
|
|
308
|
+
- [ ] Skip link present: `<a href="#main-content">Skip to main content</a>`
|
|
309
|
+
- [ ] Nav built from `getChildNodes(site.getNode('home'), ...)` — pages are children of `home`, not of the site node
|
|
310
|
+
- [ ] `<h1>{title}</h1>` in the template — no `<h1>` in any component
|
|
311
|
+
- [ ] `<footer>` landmark always has visible content (never empty)
|
|
272
312
|
- [ ] Areas use a custom area node type (not bare `<Area name="..."/>`)
|
|
273
313
|
- [ ] Custom area type has `jmix:list`, `jmix:hiddenType`, and `orderable`
|
|
274
|
-
- [ ] `AbsoluteArea` uses `renderContext.getSite()` as parent
|
|
275
|
-
- [ ] Structural container nodes use `jmix:hiddenType` (hidden from picker)
|
|
276
314
|
- [ ] Decision made: page template vs sectioning component (see Step 4)
|
|
277
315
|
- [ ] `yarn build && yarn jahia-deploy` run and template appears in Jahia UI
|
|
278
316
|
|
|
@@ -119,66 +119,39 @@ yarn build && yarn jahia-deploy
|
|
|
119
119
|
|
|
120
120
|
Verify the module is installed:
|
|
121
121
|
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
-H "Content-Type: application/json" \
|
|
126
|
-
-d '{"query":"{ jcr { nodeByPath(path:\"/modules/<module-name>\") { name } } }"}'
|
|
122
|
+
```
|
|
123
|
+
tool: content.get
|
|
124
|
+
args: { "path": "/modules/<module-name>" }
|
|
127
125
|
```
|
|
128
126
|
|
|
129
|
-
Replace `<module-name>` with the `name` from `package.json`. The response should contain
|
|
127
|
+
Replace `<module-name>` with the `name` from `package.json`. The response should contain the module node.
|
|
130
128
|
|
|
131
129
|
---
|
|
132
130
|
|
|
133
131
|
## Step 5 — Create a new site in Jahia
|
|
134
132
|
|
|
135
|
-
After the module is deployed, create the site via
|
|
136
|
-
|
|
137
|
-
> ⚠️ **CRITICAL: syntax is `- createSite: ""`** — the empty string `""` after the colon is **mandatory**. Without it, Jahia returns HTTP 200 but silently creates nothing. Using `- createSite:` with nested properties is **wrong and will fail silently**.
|
|
133
|
+
After the module is deployed, create the site via MCP:
|
|
138
134
|
|
|
139
|
-
```bash
|
|
140
|
-
MODULE_NAME=<module-name> # value of "name" in package.json
|
|
141
|
-
|
|
142
|
-
curl -u root:root1234 \
|
|
143
|
-
-X POST \
|
|
144
|
-
-H "Content-Type: application/yaml" \
|
|
145
|
-
--data-binary "- createSite: \"\"
|
|
146
|
-
siteKey: ${MODULE_NAME}
|
|
147
|
-
title: \"My Site\"
|
|
148
|
-
defaultLanguage: en
|
|
149
|
-
serverName: localhost
|
|
150
|
-
templateSet: ${MODULE_NAME}" \
|
|
151
|
-
http://localhost:8080/modules/api/provisioning
|
|
152
135
|
```
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
siteKey: ${MODULE_NAME}
|
|
162
|
-
title: "My Site"
|
|
163
|
-
defaultLanguage: en
|
|
164
|
-
serverName: localhost
|
|
165
|
-
templateSet: ${MODULE_NAME}
|
|
166
|
-
EOF
|
|
167
|
-
|
|
168
|
-
curl -u root:root1234 -X POST -H "Content-Type: application/yaml" \
|
|
169
|
-
--data-binary @/tmp/create-site.yaml \
|
|
170
|
-
http://localhost:8080/modules/api/provisioning
|
|
136
|
+
tool: site.create
|
|
137
|
+
args: {
|
|
138
|
+
"siteKey": "<module-name>",
|
|
139
|
+
"title": "My Site",
|
|
140
|
+
"templateSet": "<module-name>",
|
|
141
|
+
"defaultLanguage": "en",
|
|
142
|
+
"serverName": "localhost"
|
|
143
|
+
}
|
|
171
144
|
```
|
|
172
145
|
|
|
146
|
+
Replace `<module-name>` with the `name` from `package.json`. `templateSet` must exactly match the deployed module name.
|
|
147
|
+
|
|
173
148
|
Verify the site was created:
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
-X POST http://localhost:8080/modules/graphql \
|
|
178
|
-
-d "{\"query\":\"{ jcr { nodeByPath(path:\\\"/sites/${MODULE_NAME}\\\") { name } } }\"}"
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
tool: site.list
|
|
179
152
|
```
|
|
180
153
|
|
|
181
|
-
The
|
|
154
|
+
The site key must appear in the response. If it does not, check that `templateSet` exactly matches the deployed module name.
|
|
182
155
|
|
|
183
156
|
---
|
|
184
157
|
|
|
@@ -229,4 +202,4 @@ If anything goes wrong during setup or scaffolding, refer to the official Jahia
|
|
|
229
202
|
- [ ] Module directory created with expected structure
|
|
230
203
|
- [ ] `yarn install` completes without errors
|
|
231
204
|
- [ ] `yarn build && yarn jahia-deploy` succeeds — module appears at `/modules/<name>` in JCR
|
|
232
|
-
- [ ] Site created with `
|
|
205
|
+
- [ ] Site created with `site.create` — `site.list` confirms site key exists
|
|
@@ -100,11 +100,11 @@ Every `<img>` must have an `alt` attribute. Decorative images use `alt=""`. Info
|
|
|
100
100
|
// ❌ Missing alt
|
|
101
101
|
<img src={buildNodeUrl(props.image)} />
|
|
102
102
|
|
|
103
|
-
// ✅
|
|
104
|
-
<img src={buildNodeUrl(props.image)} alt={props.
|
|
103
|
+
// ✅ Alt from the image node's title (no extra CND property needed)
|
|
104
|
+
<img src={buildNodeUrl(props.image)} alt={props.image?.getPropertyAsString("jcr:title") ?? ""} />
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
The image node already has `jcr:title` (from `mix:title`). **Do not add `imageAlt (string) i18n`** to the CND — it forces editors to enter duplicate data.
|
|
108
108
|
|
|
109
109
|
### Colour contrast
|
|
110
110
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jahia-dev-review-cnd
|
|
3
|
+
description: Use after writing any CND file to validate it against Jahia best practices. Runs the deterministic cnd-checker script and reports PASS / FAIL with file:line citations and fixes. Run /jahia-dev-review-cnd <path> to check a specific file or directory, or without arguments to check all CND files in the current module.
|
|
4
|
+
allowed-tools: Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Step 1 — Run the checker
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
CND_SCRIPT=$(find .claude .agents -name "check-cnd.mjs" 2>/dev/null | head -1)
|
|
11
|
+
node "$CND_SCRIPT" <path-to-file-or-directory>
|
|
12
|
+
# or, to check all CND files in the module:
|
|
13
|
+
node "$CND_SCRIPT" src/
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The script exits with code 0 for PASS and code 1 for FAIL.
|
|
17
|
+
|
|
18
|
+
## Step 2 — Fix and repeat until clean
|
|
19
|
+
|
|
20
|
+
This is a loop. Run the checker, fix every issue reported, run it again. Repeat until the result is `PASS`.
|
|
21
|
+
|
|
22
|
+
- **FAIL** — fix every issue, re-run. Do not proceed until exit code is 0.
|
|
23
|
+
- **PASS** — clean. Continue.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Antipattern reference
|
|
28
|
+
|
|
29
|
+
The checker enforces these patterns. Use this as a guide when interpreting output or fixing issues manually.
|
|
30
|
+
|
|
31
|
+
### `rawStringLink`
|
|
32
|
+
Property whose name contains `link`, `url`, `href`, or `path` declared as `(string)`.
|
|
33
|
+
**Fix**: Use the link picker:
|
|
34
|
+
```cnd
|
|
35
|
+
- j:linkType (string, choicelist[linkTypeInitializer]) mandatory
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### `singleHardcodedCta`
|
|
39
|
+
A type with both a CTA label (`ctaText`, `ctaLabel`, `buttonText`, `buttonLabel`) and a CTA link (`ctaLink`, `ctaUrl`, `ctaHref`, `buttonLink`) as flat properties, with no child node.
|
|
40
|
+
**Fix**: Replace with a child node:
|
|
41
|
+
```cnd
|
|
42
|
+
+ * (ns:cta)
|
|
43
|
+
|
|
44
|
+
[ns:cta] > jnt:content, nsmix:component
|
|
45
|
+
- label (string) i18n mandatory
|
|
46
|
+
- j:linkType (string, choicelist[linkTypeInitializer]) mandatory
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### `directDroppable`
|
|
50
|
+
A concrete type extending `jmix:droppableContent` directly.
|
|
51
|
+
**Fix**: Extend the module mixin: `[ns:hero] > jnt:content, nsmix:component`
|
|
52
|
+
|
|
53
|
+
### `missingRatingConstraint`
|
|
54
|
+
`rating (long)` without a range constraint — unconstrained ratings cause data integrity issues.
|
|
55
|
+
**Fix**: Add `< "[1,5]"`
|
|
56
|
+
|
|
57
|
+
### `redundantImageAlt`
|
|
58
|
+
`imageAlt (string)` alongside an image weakreference. The image node already has `jcr:title`.
|
|
59
|
+
**Fix**: Remove `imageAlt`. In the view: `image.getPropertyAsString("jcr:title") ?? ""`
|
|
60
|
+
|
|
61
|
+
### `rawTitleProp`
|
|
62
|
+
Property named `title`, `heroTitle`, `pageTitle`, or `sectionTitle` typed as `(string)`.
|
|
63
|
+
**Fix**: Remove it, extend `mix:title`. Access as `props["jcr:title"]`.
|
|
64
|
+
|
|
65
|
+
### `weakrefNoConstraint`
|
|
66
|
+
`(weakreference)` with no `< ` type constraint.
|
|
67
|
+
**Fix**: Add constraint — `< jmix:image` for images, `< jnt:file` for files.
|
|
68
|
+
|
|
69
|
+
### `weakrefWrongConstraint`
|
|
70
|
+
`< 'jnt:file'` (quoted form).
|
|
71
|
+
**Fix**: `< jmix:image` (unquoted).
|
|
72
|
+
|
|
73
|
+
### `missingI18n`
|
|
74
|
+
User-visible string (`title`, `text`, `label`, `description`, `subtitle`, `caption`, `alt`, `heading`, `summary`, `excerpt`, `body`) without `i18n`.
|
|
75
|
+
**Fix**: Add `i18n` after the type declaration.
|
|
76
|
+
|
|
77
|
+
### `studioOnly`
|
|
78
|
+
Any use of `jmix:studioOnly`.
|
|
79
|
+
**Fix**: Replace with `jmix:hiddenType`.
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
|
|
5
|
+
function findCndFiles(dir) {
|
|
6
|
+
const results = [];
|
|
7
|
+
function walk(current) {
|
|
8
|
+
try {
|
|
9
|
+
const stat = statSync(current);
|
|
10
|
+
if (stat.isFile()) {
|
|
11
|
+
if (current.endsWith(".cnd")) results.push(current);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
15
|
+
if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== ".git") {
|
|
16
|
+
walk(join(current, entry.name));
|
|
17
|
+
} else if (entry.isFile() && entry.name.endsWith(".cnd")) {
|
|
18
|
+
results.push(join(current, entry.name));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
} catch {
|
|
22
|
+
// skip unreadable paths
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
walk(dir);
|
|
26
|
+
return results;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function checkFile(filePath, content) {
|
|
30
|
+
const issues = [];
|
|
31
|
+
const lines = content.split("\n");
|
|
32
|
+
|
|
33
|
+
lines.forEach((line, i) => {
|
|
34
|
+
const lineNum = i + 1;
|
|
35
|
+
const trimmed = line.trim();
|
|
36
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("<")) return;
|
|
37
|
+
|
|
38
|
+
// rawStringLink
|
|
39
|
+
if (
|
|
40
|
+
/^-\s+\w*(Url|Href|Link)\s+\(string[,)]/i.test(trimmed) &&
|
|
41
|
+
!/choicelist\[linkTypeInitializer\]/.test(trimmed)
|
|
42
|
+
) {
|
|
43
|
+
const propName = trimmed.match(/^-\s+(\w+)/)?.[1] ?? "unknown";
|
|
44
|
+
issues.push({
|
|
45
|
+
file: filePath, line: lineNum,
|
|
46
|
+
pattern: "rawStringLink",
|
|
47
|
+
message: `"${propName}" uses (string) for a link/url — use choicelist[linkTypeInitializer]`,
|
|
48
|
+
fix: "Replace with: - j:linkType (string, choicelist[linkTypeInitializer]) mandatory",
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// rawTitleProp
|
|
53
|
+
if (/^-\s+(title|heroTitle|pageTitle|sectionTitle)\s+\(string[,)]/i.test(trimmed)) {
|
|
54
|
+
const propName = trimmed.match(/^-\s+(\w+)/)?.[1] ?? "unknown";
|
|
55
|
+
issues.push({
|
|
56
|
+
file: filePath, line: lineNum,
|
|
57
|
+
pattern: "rawTitleProp",
|
|
58
|
+
message: `"${propName}" is a plain string — extend mix:title instead`,
|
|
59
|
+
fix: "Add mix:title to the type declaration and remove this property",
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// weakrefNoConstraint: (weakreference) with no < constraint on same line
|
|
64
|
+
if (/\(weakreference[,)]/.test(trimmed) && !/<\s*\S/.test(trimmed)) {
|
|
65
|
+
issues.push({
|
|
66
|
+
file: filePath, line: lineNum,
|
|
67
|
+
pattern: "weakrefNoConstraint",
|
|
68
|
+
message: "Unconstrained weakreference — add a type constraint",
|
|
69
|
+
fix: "Add e.g. (weakreference, picker[type='image']) < jmix:image",
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// weakrefWrongConstraint
|
|
74
|
+
if (/< ['"]jnt:file['"]/.test(trimmed)) {
|
|
75
|
+
issues.push({
|
|
76
|
+
file: filePath, line: lineNum,
|
|
77
|
+
pattern: "weakrefWrongConstraint",
|
|
78
|
+
message: "< 'jnt:file' (quoted) does not enforce image type",
|
|
79
|
+
fix: "Replace with < jmix:image for images",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// missingI18n: user-visible string without i18n
|
|
84
|
+
if (
|
|
85
|
+
/^-\s+\w+\s+\(string(,\s*(textarea|richtext))?[,)]/.test(trimmed) &&
|
|
86
|
+
!/ i18n/.test(trimmed) &&
|
|
87
|
+
!/^-\s+j:/.test(trimmed) &&
|
|
88
|
+
/(title|text|label|description|subtitle|caption|alt|heading|summary|excerpt|body)/i.test(trimmed)
|
|
89
|
+
) {
|
|
90
|
+
issues.push({
|
|
91
|
+
file: filePath, line: lineNum,
|
|
92
|
+
pattern: "missingI18n",
|
|
93
|
+
message: "User-visible string property missing i18n",
|
|
94
|
+
fix: "Add i18n keyword after the type declaration",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// directDroppable: concrete type (not mixin) extending jmix:droppableContent
|
|
99
|
+
if (trimmed.startsWith("[") && /jmix:droppableContent/.test(trimmed) && !/\bmixin\b/.test(trimmed)) {
|
|
100
|
+
issues.push({
|
|
101
|
+
file: filePath, line: lineNum,
|
|
102
|
+
pattern: "directDroppable",
|
|
103
|
+
message: "Extends jmix:droppableContent directly — always extend the module component mixin",
|
|
104
|
+
fix: "Replace jmix:droppableContent with nsmix:component (or your module's equivalent)",
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// studioOnly
|
|
109
|
+
if (/jmix:studioOnly/.test(trimmed)) {
|
|
110
|
+
issues.push({
|
|
111
|
+
file: filePath, line: lineNum,
|
|
112
|
+
pattern: "studioOnly",
|
|
113
|
+
message: "jmix:studioOnly causes silent rendering issues",
|
|
114
|
+
fix: "Replace with jmix:hiddenType",
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// redundantImageAlt: imageAlt as plain string — image node already has jcr:title
|
|
119
|
+
if (/^-\s+imageAlt\s+\(string[,)]/i.test(trimmed)) {
|
|
120
|
+
issues.push({
|
|
121
|
+
file: filePath, line: lineNum,
|
|
122
|
+
pattern: "redundantImageAlt",
|
|
123
|
+
message: '"imageAlt" is redundant — the image node\'s jcr:title (mix:title) serves as alt text',
|
|
124
|
+
fix: 'Remove imageAlt. In the view, use image.getPropertyAsString("jcr:title") for alt text',
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// missingRatingConstraint: rating (long) without a range constraint
|
|
129
|
+
if (/^-\s+rating\s+\(long[,)]/i.test(trimmed) && !/<\s*"?\[/.test(trimmed)) {
|
|
130
|
+
issues.push({
|
|
131
|
+
file: filePath, line: lineNum,
|
|
132
|
+
pattern: "missingRatingConstraint",
|
|
133
|
+
message: '"rating" (long) has no range constraint — unconstrained ratings cause data integrity issues',
|
|
134
|
+
fix: 'Add: < "[1,5]"',
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// singleHardcodedCta: check whole-file type blocks
|
|
140
|
+
const typeBlocks = content.split(/(?=^\[)/m);
|
|
141
|
+
for (const block of typeBlocks) {
|
|
142
|
+
if (!block.trim().startsWith("[")) continue;
|
|
143
|
+
const hasCtaLabel = /^\s*-\s+cta(Text|Label|ButtonText|ButtonLabel)\s+\(/im.test(block);
|
|
144
|
+
const hasCtaLink = /^\s*-\s+cta(Link|Url|Href|ButtonLink|ButtonUrl)\s+\(/im.test(block);
|
|
145
|
+
const hasChildNodes = /^\s*\+\s+/.test(block);
|
|
146
|
+
if (hasCtaLabel && hasCtaLink && !hasChildNodes) {
|
|
147
|
+
const typeName = block.match(/^\[(\S+)\]/m)?.[1] ?? "unknown";
|
|
148
|
+
const typeLineIdx = lines.findIndex((l) => l.includes(`[${typeName}]`));
|
|
149
|
+
issues.push({
|
|
150
|
+
file: filePath,
|
|
151
|
+
...(typeLineIdx >= 0 ? { line: typeLineIdx + 1 } : {}),
|
|
152
|
+
pattern: "singleHardcodedCta",
|
|
153
|
+
message: `${typeName}: flat ctaText+ctaLink forces a single CTA — model as child nodes`,
|
|
154
|
+
fix: "Remove ctaText and ctaLink. Add: + * (ns:cta). Create a [ns:cta] type with label + j:linkType",
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return issues;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function checkCndFiles(projectDir) {
|
|
163
|
+
const files = findCndFiles(projectDir);
|
|
164
|
+
const allIssues = [];
|
|
165
|
+
|
|
166
|
+
for (const file of files) {
|
|
167
|
+
try {
|
|
168
|
+
const content = readFileSync(file, "utf-8");
|
|
169
|
+
allIssues.push(...checkFile(file, content));
|
|
170
|
+
} catch {
|
|
171
|
+
// skip unreadable files
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return { score: Math.exp(-allIssues.length * 0.5), issues: allIssues, filesChecked: files.length };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (import.meta.main) {
|
|
179
|
+
const targetPath = resolve(process.argv[2] ?? ".");
|
|
180
|
+
const { score, issues, filesChecked } = checkCndFiles(targetPath);
|
|
181
|
+
|
|
182
|
+
console.log(`\nCND Review: ${filesChecked} file${filesChecked !== 1 ? "s" : ""} checked\n`);
|
|
183
|
+
|
|
184
|
+
if (issues.length > 0) {
|
|
185
|
+
console.log(`ISSUES (${issues.length}):`);
|
|
186
|
+
for (const issue of issues) {
|
|
187
|
+
const loc = issue.line ? `${issue.file}:${issue.line}` : issue.file;
|
|
188
|
+
console.log(` [${issue.pattern}] ${loc}`);
|
|
189
|
+
console.log(` ${issue.message}`);
|
|
190
|
+
console.log(` Fix: ${issue.fix}`);
|
|
191
|
+
}
|
|
192
|
+
console.log();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const verdict = issues.length > 0 ? "FAIL" : "PASS";
|
|
196
|
+
console.log(`Result: ${verdict} (score=${score.toFixed(2)})`);
|
|
197
|
+
process.exit(issues.length > 0 ? 1 : 0);
|
|
198
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jahia-dev-site-review
|
|
3
|
+
description: Scores live pages for accessibility (WCAG 2.1 AA via axe-core) and SEO (title, meta description, h1, alt). Use after deploying to get a pass/fail signal with per-violation detail before completing development.
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: jahia-dev-site-review
|
|
8
|
+
|
|
9
|
+
Runs automated a11y and SEO checks against every URL in `pages.json`. Reports a numeric score per page, lists violations by severity, and exits non-zero on any critical/serious a11y violation or missing SEO baseline.
|
|
10
|
+
|
|
11
|
+
**A11y scoring:** `Math.exp(-Σ impact_weights)` where `critical=1, serious=0.5, moderate=0.25, minor=0.1`. Score of 1.0 = perfect; 0.607 = one serious violation.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Step 1 — Ensure tooling is installed
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
node -e "require('@axe-core/playwright'); require('playwright')" 2>/dev/null || \
|
|
19
|
+
npm install --no-save @axe-core/playwright playwright && npx playwright install chromium --with-deps
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Step 2 — Run the review
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
SCRIPT=$(find .claude .agents -name "review-pages.mjs" 2>/dev/null | head -1)
|
|
28
|
+
node "$SCRIPT" 2>&1 | tee /tmp/site-review.txt
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Step 3 — Interpret and fix
|
|
34
|
+
|
|
35
|
+
The script exits 1 if any page has:
|
|
36
|
+
- A `🔴 [critical]` or `🔴 [serious]` a11y violation
|
|
37
|
+
- A `🔍 SEO` issue (missing title, meta description, h1, or img alt)
|
|
38
|
+
|
|
39
|
+
`🟡 [moderate]` and `🟡 [minor]` violations are reported but do not fail the run — fix them for a higher score.
|
|
40
|
+
|
|
41
|
+
**Common violations and where to fix them:**
|
|
42
|
+
|
|
43
|
+
| Violation | Fix location |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `landmark-*` empty nav or footer | Page template — ensure `<nav>` has inline content, `<footer>` has fallback text |
|
|
46
|
+
| `page-has-heading-one` | Page template — add `<h1>{title}</h1>` |
|
|
47
|
+
| `image-alt` | Component `.server.tsx` — use `imageAlt \|\| title \|\| 'Image'` |
|
|
48
|
+
| `color-contrast` | Component `.module.css` — check foreground/background ratio ≥ 4.5:1 |
|
|
49
|
+
| `heading-order` | Component — components start at `<h2>`, sub-items at `<h3>` |
|
|
50
|
+
| Missing `<title>` | Page template `<head>` |
|
|
51
|
+
| Missing meta description | Page template `<head>` — add `<meta name="description" content={…} />` |
|
|
52
|
+
| Multiple `<h1>` | Remove `<h1>` from components; only the template renders one |
|
|
53
|
+
|
|
54
|
+
After fixing, redeploy and re-run:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
yarn build && yarn jahia-deploy
|
|
58
|
+
node "$SCRIPT"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Iterate until the script exits 0.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Validation checklist
|
|
66
|
+
- [ ] Script exits 0 (no critical/serious violations, no SEO issues)
|
|
67
|
+
- [ ] Average a11y score ≥ 0.8
|
|
68
|
+
- [ ] Every page has a unique, non-empty `<title>`
|
|
69
|
+
- [ ] Every page has `<meta name="description">`
|
|
70
|
+
- [ ] Every page has exactly one `<h1>`
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Runs a11y (axe-core) + SEO checks on every URL in pages.json.
|
|
3
|
+
// Exits 1 if any page has critical/serious a11y violations or missing SEO basics.
|
|
4
|
+
import { chromium } from "playwright";
|
|
5
|
+
import { AxeBuilder } from "@axe-core/playwright";
|
|
6
|
+
import { readFileSync } from "fs";
|
|
7
|
+
|
|
8
|
+
const IMPACTS = { minor: 0.1, moderate: 0.25, serious: 0.5, critical: 1 };
|
|
9
|
+
|
|
10
|
+
const urls = JSON.parse(readFileSync("pages.json", "utf-8"));
|
|
11
|
+
const browser = await chromium.launch({ args: ["--no-sandbox"] });
|
|
12
|
+
const context = await browser.newContext();
|
|
13
|
+
const page = await context.newPage();
|
|
14
|
+
|
|
15
|
+
const results = [];
|
|
16
|
+
|
|
17
|
+
for (const url of urls) {
|
|
18
|
+
process.stdout.write(`\nChecking ${url} … `);
|
|
19
|
+
await page.goto(url, { waitUntil: "networkidle", timeout: 30_000 });
|
|
20
|
+
|
|
21
|
+
// A11y
|
|
22
|
+
const axe = await new AxeBuilder({ page })
|
|
23
|
+
.withTags(["wcag2a", "wcag2aa", "wcag21aa"])
|
|
24
|
+
.analyze();
|
|
25
|
+
|
|
26
|
+
const a11yScore = Math.exp(
|
|
27
|
+
-axe.violations.reduce((t, v) => t + (IMPACTS[v.impact] ?? 0), 0),
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// SEO
|
|
31
|
+
const title = await page.title();
|
|
32
|
+
const metaDesc = await page
|
|
33
|
+
.$eval('meta[name="description"]', el => el.getAttribute("content"))
|
|
34
|
+
.catch(() => null);
|
|
35
|
+
const h1s = await page.$$eval("h1", els => els.map(e => e.textContent?.trim()));
|
|
36
|
+
const imgsMissingAlt = await page.$$eval(
|
|
37
|
+
"img",
|
|
38
|
+
els => els.filter(e => !e.getAttribute("alt")).map(e => e.outerHTML.slice(0, 80)),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const seoIssues = [];
|
|
42
|
+
if (!title) seoIssues.push("missing <title>");
|
|
43
|
+
if (!metaDesc) seoIssues.push("missing <meta name=description>");
|
|
44
|
+
if (h1s.length === 0) seoIssues.push("no <h1>");
|
|
45
|
+
if (h1s.length > 1) seoIssues.push(`${h1s.length} <h1> elements (must be exactly 1)`);
|
|
46
|
+
if (imgsMissingAlt.length > 0)
|
|
47
|
+
seoIssues.push(`${imgsMissingAlt.length} <img> missing alt attribute`);
|
|
48
|
+
|
|
49
|
+
process.stdout.write(`a11y=${a11yScore.toFixed(3)}\n`);
|
|
50
|
+
results.push({ url, a11yScore, violations: axe.violations, seoIssues });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
await browser.close();
|
|
54
|
+
|
|
55
|
+
// ── Report ──────────────────────────────────────────────────────────────────
|
|
56
|
+
let failed = false;
|
|
57
|
+
|
|
58
|
+
for (const r of results) {
|
|
59
|
+
const critical = r.violations.filter(v => v.impact === "critical" || v.impact === "serious");
|
|
60
|
+
const pageOk = critical.length === 0 && r.seoIssues.length === 0;
|
|
61
|
+
if (!pageOk) failed = true;
|
|
62
|
+
|
|
63
|
+
console.log(`\n${"─".repeat(70)}`);
|
|
64
|
+
console.log(`${pageOk ? "✅" : "❌"} ${r.url}`);
|
|
65
|
+
console.log(` A11y score : ${r.a11yScore.toFixed(3)} (1.0 = perfect)`);
|
|
66
|
+
|
|
67
|
+
for (const v of r.violations) {
|
|
68
|
+
const marker = v.impact === "critical" || v.impact === "serious" ? "🔴" : "🟡";
|
|
69
|
+
console.log(` ${marker} [${v.impact}] ${v.id} — ${v.description} (${v.nodes.length} node${v.nodes.length !== 1 ? "s" : ""})`);
|
|
70
|
+
for (const node of v.nodes.slice(0, 3)) {
|
|
71
|
+
console.log(` ${node.html.slice(0, 100)}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
for (const issue of r.seoIssues) {
|
|
76
|
+
console.log(` 🔍 SEO: ${issue}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log(`\n${"═".repeat(70)}`);
|
|
81
|
+
const avg = results.reduce((t, r) => t + r.a11yScore, 0) / results.length;
|
|
82
|
+
console.log(`Average a11y score: ${avg.toFixed(3)}`);
|
|
83
|
+
console.log(failed ? "\n❌ FAIL — fix the issues above, redeploy, and re-run." : "\n✅ PASS");
|
|
84
|
+
|
|
85
|
+
process.exit(failed ? 1 : 0);
|