@jahia/agentic 0.4.1 → 0.5.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.
Files changed (178) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/antigravity/.agents/rules/jahia.md +51 -0
  3. package/dist/antigravity/.agents/skills/jahia-cnd-author/SKILL.md +94 -0
  4. package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
  5. package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
  6. package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
  7. package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
  8. package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
  9. package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
  10. package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
  11. package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
  12. package/dist/antigravity/.agents/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
  13. package/dist/antigravity/.agents/skills/jahia-dev-accessibility/SKILL.md +11 -0
  14. package/dist/antigravity/.agents/skills/jahia-dev-build-component/SKILL.md +133 -0
  15. package/dist/antigravity/.agents/skills/jahia-dev-create-page-template/SKILL.md +341 -0
  16. package/dist/antigravity/.agents/skills/jahia-dev-create-template-set/SKILL.md +205 -0
  17. package/dist/antigravity/.agents/skills/jahia-dev-create-view/SKILL.md +896 -0
  18. package/dist/antigravity/.agents/skills/jahia-dev-debug/SKILL.md +176 -0
  19. package/dist/antigravity/.agents/skills/jahia-dev-import-from/SKILL.md +244 -0
  20. package/dist/antigravity/.agents/skills/jahia-dev-jexperience/SKILL.md +269 -0
  21. package/dist/antigravity/.agents/skills/jahia-dev-ops/SKILL.md +50 -0
  22. package/dist/antigravity/.agents/skills/jahia-dev-ops/references/docker.md +151 -0
  23. package/dist/antigravity/.agents/skills/jahia-dev-ops/references/monitoring.md +195 -0
  24. package/dist/antigravity/.agents/skills/jahia-dev-ops/references/provisioning.md +269 -0
  25. package/dist/antigravity/.agents/skills/jahia-dev-properties/SKILL.md +147 -0
  26. package/dist/antigravity/.agents/skills/jahia-dev-properties/references/all-properties.md +231 -0
  27. package/dist/antigravity/.agents/skills/jahia-dev-query-content/SKILL.md +204 -0
  28. package/dist/antigravity/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
  29. package/dist/antigravity/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
  30. package/dist/antigravity/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
  31. package/dist/antigravity/.agents/skills/jahia-dev-screenshot/SKILL.md +177 -0
  32. package/dist/antigravity/.agents/skills/jahia-dev-start-local/SKILL.md +121 -0
  33. package/dist/antigravity/.agents/skills/jahia-jcr-sql2/SKILL.md +257 -0
  34. package/dist/antigravity/.agents/skills/jahia-review/SKILL.md +63 -0
  35. package/dist/{claude/.claude/skills/jahia-dev-review → antigravity/.agents/skills/jahia-review-code}/SKILL.md +3 -3
  36. package/dist/antigravity/.agents/skills/jahia-review-site/SKILL.md +52 -0
  37. package/dist/antigravity/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
  38. package/dist/antigravity/AGENTS.md +62 -0
  39. package/dist/claude/.claude/rules/jahia.md +1 -1
  40. package/dist/claude/.claude/skills/jahia-dev-build-component/SKILL.md +2 -2
  41. package/dist/claude/.claude/skills/jahia-dev-create-view/SKILL.md +2 -2
  42. package/dist/claude/.claude/skills/jahia-dev-import-from/SKILL.md +1 -1
  43. package/dist/claude/.claude/skills/jahia-dev-properties/SKILL.md +1 -1
  44. package/dist/claude/.claude/skills/jahia-dev-query-content/SKILL.md +1 -1
  45. package/dist/claude/.claude/skills/jahia-jcr-sql2/SKILL.md +1 -2
  46. package/dist/claude/.claude/skills/jahia-review/SKILL.md +63 -0
  47. package/dist/{copilot/.agents/skills/jahia-dev-review → claude/.claude/skills/jahia-review-code}/SKILL.md +3 -3
  48. package/dist/claude/.claude/skills/jahia-review-site/SKILL.md +52 -0
  49. package/dist/claude/.claude/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
  50. package/dist/claude/.mcp.json +11 -0
  51. package/dist/claude/CLAUDE.md +2 -2
  52. package/dist/codex/.agents/skills/jahia-dev-build-component/SKILL.md +2 -2
  53. package/dist/codex/.agents/skills/jahia-dev-create-view/SKILL.md +2 -2
  54. package/dist/codex/.agents/skills/jahia-dev-import-from/SKILL.md +1 -1
  55. package/dist/codex/.agents/skills/jahia-dev-properties/SKILL.md +1 -1
  56. package/dist/codex/.agents/skills/jahia-dev-query-content/SKILL.md +1 -1
  57. package/dist/codex/.agents/skills/jahia-jcr-sql2/SKILL.md +1 -2
  58. package/dist/codex/.agents/skills/jahia-review/SKILL.md +63 -0
  59. package/dist/{cursor/.agents/skills/jahia-dev-review → codex/.agents/skills/jahia-review-code}/SKILL.md +3 -3
  60. package/dist/codex/.agents/skills/jahia-review-site/SKILL.md +52 -0
  61. package/dist/codex/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
  62. package/dist/codex/AGENTS.md +2 -2
  63. package/dist/copilot/.agents/skills/jahia-dev-build-component/SKILL.md +2 -2
  64. package/dist/copilot/.agents/skills/jahia-dev-create-view/SKILL.md +2 -2
  65. package/dist/copilot/.agents/skills/jahia-dev-import-from/SKILL.md +1 -1
  66. package/dist/copilot/.agents/skills/jahia-dev-properties/SKILL.md +1 -1
  67. package/dist/copilot/.agents/skills/jahia-dev-query-content/SKILL.md +1 -1
  68. package/dist/copilot/.agents/skills/jahia-jcr-sql2/SKILL.md +1 -2
  69. package/dist/copilot/.agents/skills/jahia-review/SKILL.md +63 -0
  70. package/dist/{codex/.agents/skills/jahia-dev-review → copilot/.agents/skills/jahia-review-code}/SKILL.md +3 -3
  71. package/dist/copilot/.agents/skills/jahia-review-site/SKILL.md +52 -0
  72. package/dist/copilot/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
  73. package/dist/copilot/AGENTS.md +2 -2
  74. package/dist/cursor/.agents/skills/jahia-dev-build-component/SKILL.md +2 -2
  75. package/dist/cursor/.agents/skills/jahia-dev-create-view/SKILL.md +2 -2
  76. package/dist/cursor/.agents/skills/jahia-dev-import-from/SKILL.md +1 -1
  77. package/dist/cursor/.agents/skills/jahia-dev-properties/SKILL.md +1 -1
  78. package/dist/cursor/.agents/skills/jahia-dev-query-content/SKILL.md +1 -1
  79. package/dist/cursor/.agents/skills/jahia-jcr-sql2/SKILL.md +1 -2
  80. package/dist/cursor/.agents/skills/jahia-review/SKILL.md +63 -0
  81. package/dist/cursor/.agents/skills/jahia-review-code/SKILL.md +228 -0
  82. package/dist/cursor/.agents/skills/jahia-review-site/SKILL.md +52 -0
  83. package/dist/cursor/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
  84. package/dist/cursor/.cursor/mcp.json +11 -0
  85. package/dist/cursor/.cursor/rules/jahia.mdc +1 -1
  86. package/dist/gemini/.agents/skills/jahia-dev-build-component/SKILL.md +2 -2
  87. package/dist/gemini/.agents/skills/jahia-dev-create-view/SKILL.md +2 -2
  88. package/dist/gemini/.agents/skills/jahia-dev-import-from/SKILL.md +1 -1
  89. package/dist/gemini/.agents/skills/jahia-dev-properties/SKILL.md +1 -1
  90. package/dist/gemini/.agents/skills/jahia-dev-query-content/SKILL.md +1 -1
  91. package/dist/gemini/.agents/skills/jahia-jcr-sql2/SKILL.md +1 -2
  92. package/dist/gemini/.agents/skills/jahia-review/SKILL.md +63 -0
  93. package/dist/gemini/.agents/skills/jahia-review-code/SKILL.md +228 -0
  94. package/dist/gemini/.agents/skills/jahia-review-site/SKILL.md +52 -0
  95. package/dist/gemini/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
  96. package/dist/gemini/.gemini/settings.json +10 -0
  97. package/dist/gemini/AGENTS.md +2 -2
  98. package/dist/index.js +14 -2
  99. package/dist/kiro/.kiro/settings/mcp.json +10 -0
  100. package/dist/kiro/.kiro/skills/jahia-cnd-author/SKILL.md +94 -0
  101. package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
  102. package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
  103. package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
  104. package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
  105. package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
  106. package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
  107. package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
  108. package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
  109. package/dist/kiro/.kiro/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
  110. package/dist/kiro/.kiro/skills/jahia-dev-accessibility/SKILL.md +11 -0
  111. package/dist/kiro/.kiro/skills/jahia-dev-build-component/SKILL.md +133 -0
  112. package/dist/kiro/.kiro/skills/jahia-dev-create-page-template/SKILL.md +341 -0
  113. package/dist/kiro/.kiro/skills/jahia-dev-create-template-set/SKILL.md +205 -0
  114. package/dist/kiro/.kiro/skills/jahia-dev-create-view/SKILL.md +896 -0
  115. package/dist/kiro/.kiro/skills/jahia-dev-debug/SKILL.md +176 -0
  116. package/dist/kiro/.kiro/skills/jahia-dev-import-from/SKILL.md +244 -0
  117. package/dist/kiro/.kiro/skills/jahia-dev-jexperience/SKILL.md +269 -0
  118. package/dist/kiro/.kiro/skills/jahia-dev-ops/SKILL.md +50 -0
  119. package/dist/kiro/.kiro/skills/jahia-dev-ops/references/docker.md +151 -0
  120. package/dist/kiro/.kiro/skills/jahia-dev-ops/references/monitoring.md +195 -0
  121. package/dist/kiro/.kiro/skills/jahia-dev-ops/references/provisioning.md +269 -0
  122. package/dist/kiro/.kiro/skills/jahia-dev-properties/SKILL.md +147 -0
  123. package/dist/kiro/.kiro/skills/jahia-dev-properties/references/all-properties.md +231 -0
  124. package/dist/kiro/.kiro/skills/jahia-dev-query-content/SKILL.md +204 -0
  125. package/dist/kiro/.kiro/skills/jahia-dev-review-cnd/SKILL.md +79 -0
  126. package/dist/kiro/.kiro/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
  127. package/dist/kiro/.kiro/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
  128. package/dist/kiro/.kiro/skills/jahia-dev-screenshot/SKILL.md +177 -0
  129. package/dist/kiro/.kiro/skills/jahia-dev-start-local/SKILL.md +121 -0
  130. package/dist/kiro/.kiro/skills/jahia-jcr-sql2/SKILL.md +257 -0
  131. package/dist/kiro/.kiro/skills/jahia-review/SKILL.md +63 -0
  132. package/dist/kiro/.kiro/skills/jahia-review-code/SKILL.md +228 -0
  133. package/dist/kiro/.kiro/skills/jahia-review-site/SKILL.md +52 -0
  134. package/dist/kiro/.kiro/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
  135. package/dist/kiro/.kiro/steering/jahia.md +55 -0
  136. package/dist/kiro/AGENTS.md +62 -0
  137. package/dist/opencode/.agents/skills/jahia-dev-build-component/SKILL.md +2 -2
  138. package/dist/opencode/.agents/skills/jahia-dev-create-view/SKILL.md +2 -2
  139. package/dist/opencode/.agents/skills/jahia-dev-import-from/SKILL.md +1 -1
  140. package/dist/opencode/.agents/skills/jahia-dev-properties/SKILL.md +1 -1
  141. package/dist/opencode/.agents/skills/jahia-dev-query-content/SKILL.md +1 -1
  142. package/dist/opencode/.agents/skills/jahia-jcr-sql2/SKILL.md +1 -2
  143. package/dist/opencode/.agents/skills/jahia-review/SKILL.md +63 -0
  144. package/dist/opencode/.agents/skills/jahia-review-code/SKILL.md +228 -0
  145. package/dist/opencode/.agents/skills/jahia-review-site/SKILL.md +52 -0
  146. package/dist/opencode/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
  147. package/dist/opencode/AGENTS.md +2 -2
  148. package/dist/opencode/opencode.json +12 -0
  149. package/dist/windsurf/.windsurf/rules/jahia.md +1 -1
  150. package/dist/windsurf/.windsurf/skills/jahia-dev-build-component/SKILL.md +2 -2
  151. package/dist/windsurf/.windsurf/skills/jahia-dev-create-view/SKILL.md +2 -2
  152. package/dist/windsurf/.windsurf/skills/jahia-dev-import-from/SKILL.md +1 -1
  153. package/dist/windsurf/.windsurf/skills/jahia-dev-properties/SKILL.md +1 -1
  154. package/dist/windsurf/.windsurf/skills/jahia-dev-query-content/SKILL.md +1 -1
  155. package/dist/windsurf/.windsurf/skills/jahia-jcr-sql2/SKILL.md +1 -2
  156. package/dist/windsurf/.windsurf/skills/jahia-review/SKILL.md +63 -0
  157. package/dist/windsurf/.windsurf/skills/jahia-review-code/SKILL.md +228 -0
  158. package/dist/windsurf/.windsurf/skills/jahia-review-site/SKILL.md +52 -0
  159. package/dist/windsurf/.windsurf/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
  160. package/dist/windsurf/AGENTS.md +2 -2
  161. package/package.json +1 -1
  162. package/dist/claude/.claude/skills/jahia-dev-site-review/SKILL.md +0 -70
  163. package/dist/claude/.claude/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
  164. package/dist/codex/.agents/skills/jahia-dev-site-review/SKILL.md +0 -70
  165. package/dist/codex/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
  166. package/dist/copilot/.agents/skills/jahia-dev-site-review/SKILL.md +0 -70
  167. package/dist/copilot/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
  168. package/dist/cursor/.agents/skills/jahia-dev-site-review/SKILL.md +0 -70
  169. package/dist/cursor/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
  170. package/dist/gemini/.agents/skills/jahia-dev-review/SKILL.md +0 -228
  171. package/dist/gemini/.agents/skills/jahia-dev-site-review/SKILL.md +0 -70
  172. package/dist/gemini/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
  173. package/dist/opencode/.agents/skills/jahia-dev-review/SKILL.md +0 -228
  174. package/dist/opencode/.agents/skills/jahia-dev-site-review/SKILL.md +0 -70
  175. package/dist/opencode/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
  176. package/dist/windsurf/.windsurf/skills/jahia-dev-review/SKILL.md +0 -228
  177. package/dist/windsurf/.windsurf/skills/jahia-dev-site-review/SKILL.md +0 -70
  178. package/dist/windsurf/.windsurf/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
@@ -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,177 @@
1
+ ---
2
+ name: jahia-dev-screenshot
3
+ description: Takes screenshots of a reference URL and the local Jahia render for visual comparison. Use before building a view (inspiration) and after (validation).
4
+ ---
5
+
6
+ # Skill: jahia-dev-screenshot
7
+
8
+ Takes screenshots for two purposes:
9
+ 1. **Reference** — capture an existing site as a visual spec before building
10
+ 2. **Result** — capture the local Jahia render after building to compare
11
+
12
+ ---
13
+
14
+ ## Step 1 — Detect screenshot tool
15
+
16
+ Check what is available:
17
+
18
+ ```bash
19
+ # Playwright (preferred)
20
+ npx playwright --version 2>/dev/null
21
+
22
+ # Puppeteer
23
+ node -e "require('puppeteer'); console.log('ok')" 2>/dev/null
24
+
25
+ # System Chrome/Chromium
26
+ which google-chrome || which chromium || which chromium-browser 2>/dev/null
27
+ ```
28
+
29
+ Use the first one that works. If none is available, ask the user:
30
+
31
+ > No screenshot tool found. Which would you like to install?
32
+ > - `npm install -g playwright` then `npx playwright install chromium`
33
+ > - `npm install puppeteer` (downloads Chromium automatically)
34
+ > - I'll take the screenshots manually and paste them in
35
+
36
+ If the user chooses manual, skip to Step 4 and ask them to paste the screenshots.
37
+
38
+ ---
39
+
40
+ ## Step 2 — Take reference screenshot
41
+
42
+ Ask the user for the reference URL if not already provided.
43
+
44
+ Create the output directory:
45
+ ```bash
46
+ mkdir -p /tmp/jahia-screenshots
47
+ ```
48
+
49
+ ### With Playwright:
50
+ ```bash
51
+ npx playwright screenshot \
52
+ --browser chromium \
53
+ --full-page \
54
+ "<REFERENCE_URL>" \
55
+ /tmp/jahia-screenshots/reference.png
56
+ ```
57
+
58
+ ### With Puppeteer (Node.js one-liner):
59
+ ```bash
60
+ node -e "
61
+ const puppeteer = require('puppeteer');
62
+ (async () => {
63
+ const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
64
+ const page = await browser.newPage();
65
+ await page.setViewport({ width: 1440, height: 900 });
66
+ await page.goto('<REFERENCE_URL>', { waitUntil: 'networkidle2' });
67
+ await page.screenshot({ path: '/tmp/jahia-screenshots/reference.png', fullPage: true });
68
+ await browser.close();
69
+ })();
70
+ "
71
+ ```
72
+
73
+ After capturing, **view the screenshot** to use it as visual context:
74
+
75
+ ```
76
+ view /tmp/jahia-screenshots/reference.png
77
+ ```
78
+
79
+ Describe the key design elements you observe:
80
+ - Layout structure (hero, grid, sidebar, etc.)
81
+ - Color palette (dominant, accent, background)
82
+ - Typography (heading sizes, font weight)
83
+ - Component anatomy (what sub-elements make it up)
84
+
85
+ Share this description with the user before proceeding to build.
86
+
87
+ ---
88
+
89
+ ## Step 3 — Take result screenshot (after building)
90
+
91
+ Once the view is built and deployed (`yarn build` + `yarn jahia-deploy`), capture the Jahia render.
92
+
93
+ Ask the user for the Jahia page URL, or construct it:
94
+ - Default: `http://localhost:8080/cms/render/default/en/sites/<siteName>/home.html`
95
+ - Or ask: "What is the URL of the page where the component is placed?"
96
+
97
+ Jahia requires authentication. Use the `--auth` header or log in first:
98
+
99
+ ### With Playwright:
100
+ ```bash
101
+ npx playwright screenshot \
102
+ --browser chromium \
103
+ --full-page \
104
+ "http://localhost:8080/cms/render/default/en/sites/<siteName>/home.html" \
105
+ /tmp/jahia-screenshots/result.png
106
+ ```
107
+
108
+ > Note: if the page requires login, authenticate first:
109
+ > ```bash
110
+ > node -e "
111
+ > const puppeteer = require('puppeteer');
112
+ > (async () => {
113
+ > const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
114
+ > const page = await browser.newPage();
115
+ > await page.setViewport({ width: 1440, height: 900 });
116
+ > await page.goto('http://localhost:8080/cms/login', { waitUntil: 'networkidle2' });
117
+ > await page.type('#username', 'root');
118
+ > await page.type('#password', 'root1234');
119
+ > await Promise.all([page.waitForNavigation(), page.keyboard.press('Enter')]);
120
+ > await page.goto('<PAGE_URL>', { waitUntil: 'networkidle2' });
121
+ > await page.screenshot({ path: '/tmp/jahia-screenshots/result.png', fullPage: true });
122
+ > await browser.close();
123
+ > })();
124
+ > "
125
+ > ```
126
+
127
+ After capturing, **view the screenshot**:
128
+
129
+ ```
130
+ view /tmp/jahia-screenshots/result.png
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Step 4 — Compare and report gaps
136
+
137
+ View both screenshots and compare them side by side (or sequentially).
138
+
139
+ Report gaps to the user:
140
+
141
+ ```
142
+ ## Visual Comparison
143
+
144
+ ### Reference: <URL>
145
+ [description of reference]
146
+
147
+ ### Result: http://localhost:8080/...
148
+ [description of result]
149
+
150
+ ### Gaps
151
+ - [ ] Background color differs (reference: dark navy, result: white)
152
+ - [ ] Hero text not centered
153
+ - [ ] CTA button missing border-radius
154
+ - [ ] Font size smaller than reference
155
+
156
+ ### Suggested fixes
157
+ ...
158
+ ```
159
+
160
+ Ask: **"Would you like me to fix these gaps?"**
161
+
162
+ If yes, update the view's `.tsx` and `.module.css` files using `/jahia-dev-create-view` guidance, rebuild, and re-screenshot to verify.
163
+
164
+ ---
165
+
166
+ ## Integration points
167
+
168
+ This skill is called from:
169
+ - `/jahia-dev-build-component` — Step 0 (optional reference) and Step 4 (result check)
170
+ - `/jahia-dev-create-view` — Step 0 (optional reference) and after deploy
171
+
172
+ ---
173
+
174
+ ## References
175
+
176
+ - Playwright CLI: https://playwright.dev/docs/cli
177
+ - Puppeteer: https://pptr.dev
@@ -0,0 +1,121 @@
1
+ ---
2
+ name: jahia-dev-start-local
3
+ description: Starts a local Jahia instance for development and guides the user through creating their first site. Use this after creating a template set to get a running Jahia environment.
4
+ ---
5
+
6
+ ## Overview
7
+
8
+ This skill starts a local Jahia instance for development. Two approaches are available depending on the environment. Try Docker first; fall back to bare metal only if Docker is not an option.
9
+
10
+ ---
11
+
12
+ ## Step 1 — Try Docker first (recommended)
13
+
14
+ Check if Docker is available:
15
+
16
+ ```bash
17
+ docker info
18
+ ```
19
+
20
+ - If the command **succeeds** → proceed with Docker (Step 2)
21
+ - If the command **fails with a connection error** → Docker Desktop is likely not running. Tell the user: **"Please start Docker Desktop and try again."** Then retry `docker info`.
22
+ - If Docker is **not installed** → skip to Step 3 (bare metal fallback)
23
+
24
+ ---
25
+
26
+ ## Step 2 — Start with Docker Compose
27
+
28
+ From the module directory (where `docker-compose.yml` lives):
29
+
30
+ ```bash
31
+ docker compose up --wait
32
+ ```
33
+
34
+ This will:
35
+ - Pull and start a local Jahia instance
36
+ - Wait until Jahia is fully ready before returning
37
+
38
+ Once up, Jahia will be available at **http://localhost:8080**.
39
+
40
+ **Tell the user the URL and credentials** (default: `root` / `root1234` — can only be changed in `docker-compose.yml`).
41
+
42
+ Then ask the user to run the following command **themselves in a separate terminal** — do NOT run it on their behalf, as it produces continuous feedback they need to see:
43
+
44
+ ```
45
+ 👉 In a new terminal, from the module directory, run:
46
+
47
+ yarn dev
48
+
49
+ This watches for file changes and pushes the compiled template set to the running Jahia instance. Leave it running while you develop.
50
+ ```
51
+
52
+ > **Agent note:** `yarn dev` is for interactive human development only. When building features programmatically, always use `yarn build && yarn jahia-deploy` for explicit one-shot deploys — never start `yarn dev` from an agent.
53
+
54
+ After `docker compose up --wait`, deploy the module immediately:
55
+
56
+ ```bash
57
+ yarn build && yarn jahia-deploy
58
+ ```
59
+
60
+ `yarn jahia-deploy` (from `@jahia/vite-plugin` 1.2.0+) always uses curl to `http://localhost:8080` with credentials `root:root1234` — no `.env` changes needed for standard local development.
61
+
62
+ ---
63
+
64
+ ## Step 3 — Bare metal fallback (no Docker)
65
+
66
+ If Docker is not available, Jahia can be run locally with a JVM.
67
+
68
+ Fetch the latest download and setup instructions from:
69
+
70
+ > https://academy.jahia.com/downloads
71
+
72
+ Key requirements:
73
+ - A working JVM (Java 11 or 17)
74
+ - The Jahia distribution ZIP or installer from the downloads page
75
+
76
+ Follow the instructions on that page for the user's platform, then return here to deploy with `yarn build && yarn jahia-deploy` once Jahia is started.
77
+
78
+ ---
79
+
80
+ ## Step 4 — Create a new site in Jahia
81
+
82
+ Once the module is deployed to Jahia, create the site via MCP:
83
+
84
+ ```
85
+ tool: site.create
86
+ args: {
87
+ "siteKey": "<module-name>",
88
+ "title": "My Site",
89
+ "templateSet": "<module-name>",
90
+ "defaultLanguage": "en",
91
+ "serverName": "localhost"
92
+ }
93
+ ```
94
+
95
+ Replace `<module-name>` with the `name` from `package.json`. `templateSet` must exactly match the deployed module name.
96
+
97
+ Verify the site exists:
98
+
99
+ ```
100
+ tool: site.list
101
+ ```
102
+
103
+ The site key must appear in the response. If it does not, check that `templateSet` exactly matches the deployed module name.
104
+
105
+ Then open **Page Builder** at http://localhost:8080/jahia/page-builder to start building.
106
+
107
+ ---
108
+
109
+ ## Validation checklist
110
+ - [ ] `docker info` succeeds (or bare metal Jahia is running)
111
+ - [ ] `docker compose up --wait` completes without errors (Docker path)
112
+ - [ ] Jahia UI is reachable at http://localhost:8080
113
+ - [ ] Module deployed to Jahia (`yarn build && yarn jahia-deploy` run; or `yarn dev` in user terminal for interactive development)
114
+ - [ ] Site created via `site.create` MCP tool with correct `templateSet`
115
+ - [ ] `site.list` confirms site key exists
116
+
117
+ ## Troubleshooting
118
+
119
+ If anything goes wrong during setup or startup, refer to the official Jahia front-end developer setup guide:
120
+
121
+ > https://academy.jahia.com/tutorials-get-started/front-end-developer/setting-up-your-dev-environment