coretik-block-generator-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CLAUDE_INSTRUCTIONS.md +30 -0
  2. package/README.md +193 -0
  3. package/dist/constants.d.ts +55 -0
  4. package/dist/constants.d.ts.map +1 -0
  5. package/dist/constants.js +27 -0
  6. package/dist/constants.js.map +1 -0
  7. package/dist/conventions.d.ts +19 -0
  8. package/dist/conventions.d.ts.map +1 -0
  9. package/dist/conventions.js +158 -0
  10. package/dist/conventions.js.map +1 -0
  11. package/dist/index.d.ts +9 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +518 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/schemas/learned-conventions.d.ts +53 -0
  16. package/dist/schemas/learned-conventions.d.ts.map +1 -0
  17. package/dist/schemas/learned-conventions.js +47 -0
  18. package/dist/schemas/learned-conventions.js.map +1 -0
  19. package/dist/services/convention-store.d.ts +9 -0
  20. package/dist/services/convention-store.d.ts.map +1 -0
  21. package/dist/services/convention-store.js +84 -0
  22. package/dist/services/convention-store.js.map +1 -0
  23. package/dist/services/feedback.d.ts +29 -0
  24. package/dist/services/feedback.d.ts.map +1 -0
  25. package/dist/services/feedback.js +199 -0
  26. package/dist/services/feedback.js.map +1 -0
  27. package/dist/services/naming.d.ts +51 -0
  28. package/dist/services/naming.d.ts.map +1 -0
  29. package/dist/services/naming.js +87 -0
  30. package/dist/services/naming.js.map +1 -0
  31. package/dist/services/pattern-extractor.d.ts +14 -0
  32. package/dist/services/pattern-extractor.d.ts.map +1 -0
  33. package/dist/services/pattern-extractor.js +310 -0
  34. package/dist/services/pattern-extractor.js.map +1 -0
  35. package/dist/services/registration.d.ts +31 -0
  36. package/dist/services/registration.d.ts.map +1 -0
  37. package/dist/services/registration.js +275 -0
  38. package/dist/services/registration.js.map +1 -0
  39. package/dist/templates/generators.d.ts +59 -0
  40. package/dist/templates/generators.d.ts.map +1 -0
  41. package/dist/templates/generators.js +79 -0
  42. package/dist/templates/generators.js.map +1 -0
  43. package/dist/templates/html-template.d.ts +12 -0
  44. package/dist/templates/html-template.d.ts.map +1 -0
  45. package/dist/templates/html-template.js +189 -0
  46. package/dist/templates/html-template.js.map +1 -0
  47. package/dist/templates/php-class.d.ts +19 -0
  48. package/dist/templates/php-class.d.ts.map +1 -0
  49. package/dist/templates/php-class.js +271 -0
  50. package/dist/templates/php-class.js.map +1 -0
  51. package/dist/templates/scss.d.ts +7 -0
  52. package/dist/templates/scss.d.ts.map +1 -0
  53. package/dist/templates/scss.js +102 -0
  54. package/dist/templates/scss.js.map +1 -0
  55. package/dist/utils.d.ts +18 -0
  56. package/dist/utils.d.ts.map +1 -0
  57. package/dist/utils.js +56 -0
  58. package/dist/utils.js.map +1 -0
  59. package/package.json +48 -0
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Schema for learned conventions stored in .coretik-conventions.json
3
+ */
4
+ export function createEmptyConventions() {
5
+ return {
6
+ version: 1,
7
+ learnedAt: new Date().toISOString(),
8
+ blockCount: 0,
9
+ php: {
10
+ imports: [],
11
+ traits: [],
12
+ interfaces: [],
13
+ baseClasses: {},
14
+ propertyVisibility: 'protected',
15
+ useSettingsPattern: true,
16
+ extraMethods: [],
17
+ },
18
+ template: {
19
+ wrapperTag: 'div',
20
+ wrapperAttributes: [],
21
+ escapingFunctions: {},
22
+ emptyCheckStyle: '!empty',
23
+ imageRenderFunction: 'wp_get_attachment_image',
24
+ htmlSnippets: [],
25
+ },
26
+ scss: {
27
+ methodology: 'BEM',
28
+ containerLayout: 'flex',
29
+ spacingVariables: [],
30
+ colorVariables: [],
31
+ breakpoints: [],
32
+ },
33
+ naming: {
34
+ blockNamePrefix: {},
35
+ classNameSuffix: {},
36
+ bemSuffix: {},
37
+ templateSubDir: {},
38
+ },
39
+ fields: {
40
+ commonFieldPatterns: [],
41
+ imageReturnFormat: 'id',
42
+ linkReturnFormat: 'array',
43
+ },
44
+ generations: {},
45
+ };
46
+ }
47
+ //# sourceMappingURL=learned-conventions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learned-conventions.js","sourceRoot":"","sources":["../../src/schemas/learned-conventions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyDH,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,UAAU,EAAE,CAAC;QACb,GAAG,EAAE;YACH,OAAO,EAAE,EAAE;YACX,MAAM,EAAE,EAAE;YACV,UAAU,EAAE,EAAE;YACd,WAAW,EAAE,EAAE;YACf,kBAAkB,EAAE,WAAW;YAC/B,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,EAAE;SACjB;QACD,QAAQ,EAAE;YACR,UAAU,EAAE,KAAK;YACjB,iBAAiB,EAAE,EAAE;YACrB,iBAAiB,EAAE,EAAE;YACrB,eAAe,EAAE,QAAQ;YACzB,mBAAmB,EAAE,yBAAyB;YAC9C,YAAY,EAAE,EAAE;SACjB;QACD,IAAI,EAAE;YACJ,WAAW,EAAE,KAAK;YAClB,eAAe,EAAE,MAAM;YACvB,gBAAgB,EAAE,EAAE;YACpB,cAAc,EAAE,EAAE;YAClB,WAAW,EAAE,EAAE;SAChB;QACD,MAAM,EAAE;YACN,eAAe,EAAE,EAAE;YACnB,eAAe,EAAE,EAAE;YACnB,SAAS,EAAE,EAAE;YACb,cAAc,EAAE,EAAE;SACnB;QACD,MAAM,EAAE;YACN,mBAAmB,EAAE,EAAE;YACvB,iBAAiB,EAAE,IAAI;YACvB,gBAAgB,EAAE,OAAO;SAC1B;QACD,WAAW,EAAE,EAAE;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { LearnedConventions } from '../schemas/learned-conventions.js';
2
+ export declare function loadConventions(projectRoot: string): Promise<LearnedConventions | null>;
3
+ export declare function saveConventions(projectRoot: string, conventions: LearnedConventions): Promise<void>;
4
+ /**
5
+ * Merge new learnings into existing conventions.
6
+ * New values take precedence; arrays are deduplicated.
7
+ */
8
+ export declare function mergeConventions(existing: LearnedConventions, incoming: LearnedConventions): LearnedConventions;
9
+ //# sourceMappingURL=convention-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convention-store.d.ts","sourceRoot":"","sources":["../../src/services/convention-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAK5E,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAQ7F;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGzG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,EAAE,kBAAkB,GAC3B,kBAAkB,CA8CpB"}
@@ -0,0 +1,84 @@
1
+ import { join } from 'path';
2
+ import { readFileSafe, writeFileSafe } from '../utils.js';
3
+ const FILENAME = '.coretik-conventions.json';
4
+ export async function loadConventions(projectRoot) {
5
+ const content = await readFileSafe(join(projectRoot, FILENAME));
6
+ if (!content)
7
+ return null;
8
+ try {
9
+ return JSON.parse(content);
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ export async function saveConventions(projectRoot, conventions) {
16
+ const filePath = join(projectRoot, FILENAME);
17
+ await writeFileSafe(filePath, JSON.stringify(conventions, null, 2));
18
+ }
19
+ /**
20
+ * Merge new learnings into existing conventions.
21
+ * New values take precedence; arrays are deduplicated.
22
+ */
23
+ export function mergeConventions(existing, incoming) {
24
+ return {
25
+ version: Math.max(existing.version, incoming.version),
26
+ learnedAt: incoming.learnedAt,
27
+ blockCount: incoming.blockCount,
28
+ php: {
29
+ imports: dedup([...existing.php.imports, ...incoming.php.imports]),
30
+ traits: dedup([...existing.php.traits, ...incoming.php.traits]),
31
+ interfaces: dedup([...existing.php.interfaces, ...incoming.php.interfaces]),
32
+ baseClasses: { ...existing.php.baseClasses, ...incoming.php.baseClasses },
33
+ propertyVisibility: incoming.php.propertyVisibility,
34
+ useSettingsPattern: incoming.php.useSettingsPattern,
35
+ extraMethods: dedup([...existing.php.extraMethods, ...incoming.php.extraMethods]),
36
+ },
37
+ template: {
38
+ wrapperTag: incoming.template.wrapperTag,
39
+ wrapperAttributes: dedup([...existing.template.wrapperAttributes, ...incoming.template.wrapperAttributes]),
40
+ escapingFunctions: mergeRecordArrays(existing.template.escapingFunctions, incoming.template.escapingFunctions),
41
+ emptyCheckStyle: incoming.template.emptyCheckStyle,
42
+ imageRenderFunction: incoming.template.imageRenderFunction,
43
+ htmlSnippets: incoming.template.htmlSnippets,
44
+ },
45
+ scss: {
46
+ methodology: incoming.scss.methodology,
47
+ containerLayout: incoming.scss.containerLayout,
48
+ spacingVariables: dedup([...existing.scss.spacingVariables, ...incoming.scss.spacingVariables]),
49
+ colorVariables: dedup([...existing.scss.colorVariables, ...incoming.scss.colorVariables]),
50
+ breakpoints: dedup([...existing.scss.breakpoints, ...incoming.scss.breakpoints]),
51
+ },
52
+ naming: incoming.naming,
53
+ fields: {
54
+ commonFieldPatterns: mergeFieldPatterns(existing.fields.commonFieldPatterns, incoming.fields.commonFieldPatterns),
55
+ imageReturnFormat: incoming.fields.imageReturnFormat,
56
+ linkReturnFormat: incoming.fields.linkReturnFormat,
57
+ },
58
+ generations: { ...existing.generations, ...incoming.generations },
59
+ };
60
+ }
61
+ function dedup(arr) {
62
+ return [...new Set(arr)];
63
+ }
64
+ function mergeRecordArrays(a, b) {
65
+ const result = { ...a };
66
+ for (const [key, values] of Object.entries(b)) {
67
+ result[key] = dedup([...(result[key] || []), ...values]);
68
+ }
69
+ return result;
70
+ }
71
+ function mergeFieldPatterns(existing, incoming) {
72
+ const map = new Map();
73
+ for (const p of [...existing, ...incoming]) {
74
+ const key = `${p.name}:${p.type}`;
75
+ const prev = map.get(key);
76
+ map.set(key, {
77
+ name: p.name,
78
+ type: p.type,
79
+ frequency: prev ? Math.max(prev.frequency, p.frequency) : p.frequency,
80
+ });
81
+ }
82
+ return [...map.values()].sort((a, b) => b.frequency - a.frequency);
83
+ }
84
+ //# sourceMappingURL=convention-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convention-store.js","sourceRoot":"","sources":["../../src/services/convention-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { LearnedConventions } from '../schemas/learned-conventions.js';
2
+ interface PathsConfig {
3
+ blocksPhp: string;
4
+ templates: string;
5
+ scss: string;
6
+ thumbnails: string;
7
+ acfAdmin: string;
8
+ }
9
+ export declare function hashContent(content: string): string;
10
+ /**
11
+ * Record a generation manifest entry for a block.
12
+ */
13
+ export declare function recordGeneration(conventions: LearnedConventions, blockName: string, files: Record<string, string>): LearnedConventions;
14
+ interface FeedbackResult {
15
+ summary: string;
16
+ changes: Array<{
17
+ file: string;
18
+ fileType: string;
19
+ status: 'unchanged' | 'modified' | 'deleted' | 'not_tracked';
20
+ }>;
21
+ learnedPatterns: string[];
22
+ }
23
+ /**
24
+ * Analyze a block to detect manual edits since generation.
25
+ * Extracts patterns from the edited files to improve future generations.
26
+ */
27
+ export declare function analyzeFeedback(blockName: string, projectRoot: string, paths: PathsConfig, conventions: LearnedConventions): Promise<FeedbackResult>;
28
+ export {};
29
+ //# sourceMappingURL=feedback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback.d.ts","sourceRoot":"","sources":["../../src/services/feedback.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAG5E,UAAU,WAAW;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,kBAAkB,EAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,kBAAkB,CAUpB;AAED,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,CAAC;KAC9D,CAAC,CAAC;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,WAAW,EAAE,kBAAkB,GAC9B,OAAO,CAAC,cAAc,CAAC,CA4HzB"}
@@ -0,0 +1,199 @@
1
+ import { createHash } from 'crypto';
2
+ import { join, relative } from 'path';
3
+ import { readFileSafe, findFiles } from '../utils.js';
4
+ export function hashContent(content) {
5
+ return createHash('sha256').update(content).digest('hex').substring(0, 16);
6
+ }
7
+ /**
8
+ * Record a generation manifest entry for a block.
9
+ */
10
+ export function recordGeneration(conventions, blockName, files // filetype -> content
11
+ ) {
12
+ const hashes = {};
13
+ for (const [key, content] of Object.entries(files)) {
14
+ hashes[key] = hashContent(content);
15
+ }
16
+ conventions.generations[blockName] = {
17
+ generatedAt: new Date().toISOString(),
18
+ files: hashes,
19
+ };
20
+ return conventions;
21
+ }
22
+ /**
23
+ * Analyze a block to detect manual edits since generation.
24
+ * Extracts patterns from the edited files to improve future generations.
25
+ */
26
+ export async function analyzeFeedback(blockName, projectRoot, paths, conventions) {
27
+ const cleanName = blockName.replace(/^(block|component|composite)\./, '');
28
+ const generation = conventions.generations[blockName] || conventions.generations[cleanName];
29
+ if (!generation) {
30
+ return {
31
+ summary: `Block "${blockName}" has no generation record. Use learn_conventions to analyze existing blocks instead.`,
32
+ changes: [],
33
+ learnedPatterns: [],
34
+ };
35
+ }
36
+ const changes = [];
37
+ const learnedPatterns = [];
38
+ // Find the PHP file
39
+ const phpDir = join(projectRoot, paths.blocksPhp);
40
+ const phpFiles = await findFiles(phpDir, /\.php$/);
41
+ let phpContent = null;
42
+ let phpPath = '';
43
+ for (const file of phpFiles) {
44
+ const content = await readFileSafe(file);
45
+ if (content && (content.includes(`'${blockName}'`) ||
46
+ content.includes(`'block.${cleanName}'`) ||
47
+ content.includes(`'component.${cleanName}'`))) {
48
+ phpContent = content;
49
+ phpPath = relative(projectRoot, file);
50
+ break;
51
+ }
52
+ }
53
+ // Check PHP changes
54
+ if (phpContent) {
55
+ const currentHash = hashContent(phpContent);
56
+ const originalHash = generation.files['php'];
57
+ if (originalHash && currentHash !== originalHash) {
58
+ changes.push({ file: phpPath, fileType: 'php', status: 'modified' });
59
+ const patterns = extractPhpEditPatterns(phpContent);
60
+ learnedPatterns.push(...patterns);
61
+ }
62
+ else if (originalHash) {
63
+ changes.push({ file: phpPath, fileType: 'php', status: 'unchanged' });
64
+ }
65
+ }
66
+ else if (generation.files['php']) {
67
+ changes.push({ file: 'php', fileType: 'php', status: 'deleted' });
68
+ }
69
+ // Check template changes
70
+ const templatePaths = [
71
+ join(projectRoot, paths.templates, 'block', `${cleanName}.php`),
72
+ join(projectRoot, paths.templates, 'component', `${cleanName}.php`),
73
+ ];
74
+ let templateContent = null;
75
+ let templatePath = '';
76
+ for (const tp of templatePaths) {
77
+ const content = await readFileSafe(tp);
78
+ if (content) {
79
+ templateContent = content;
80
+ templatePath = relative(projectRoot, tp);
81
+ break;
82
+ }
83
+ }
84
+ if (templateContent) {
85
+ const currentHash = hashContent(templateContent);
86
+ const originalHash = generation.files['template'];
87
+ if (originalHash && currentHash !== originalHash) {
88
+ changes.push({ file: templatePath, fileType: 'template', status: 'modified' });
89
+ const patterns = extractTemplateEditPatterns(templateContent);
90
+ learnedPatterns.push(...patterns);
91
+ }
92
+ else if (originalHash) {
93
+ changes.push({ file: templatePath, fileType: 'template', status: 'unchanged' });
94
+ }
95
+ }
96
+ else if (generation.files['template']) {
97
+ changes.push({ file: 'template', fileType: 'template', status: 'deleted' });
98
+ }
99
+ // Check SCSS changes
100
+ const scssFile = join(projectRoot, paths.scss, `_${cleanName}.scss`);
101
+ const scssContent = await readFileSafe(scssFile);
102
+ if (scssContent) {
103
+ const currentHash = hashContent(scssContent);
104
+ const originalHash = generation.files['scss'];
105
+ if (originalHash && currentHash !== originalHash) {
106
+ changes.push({ file: relative(projectRoot, scssFile), fileType: 'scss', status: 'modified' });
107
+ const patterns = extractScssEditPatterns(scssContent);
108
+ learnedPatterns.push(...patterns);
109
+ }
110
+ else if (originalHash) {
111
+ changes.push({ file: relative(projectRoot, scssFile), fileType: 'scss', status: 'unchanged' });
112
+ }
113
+ }
114
+ else if (generation.files['scss']) {
115
+ changes.push({ file: 'scss', fileType: 'scss', status: 'deleted' });
116
+ }
117
+ // Build summary
118
+ const modified = changes.filter(c => c.status === 'modified');
119
+ const unchanged = changes.filter(c => c.status === 'unchanged');
120
+ let summary = `# Feedback for "${blockName}"\n\n`;
121
+ if (modified.length === 0 && unchanged.length > 0) {
122
+ summary += `No manual edits detected. All ${unchanged.length} tracked file(s) are unchanged.\n`;
123
+ }
124
+ else {
125
+ summary += `## Modified files (${modified.length}):\n`;
126
+ for (const c of modified) {
127
+ summary += `- ${c.file} (${c.fileType})\n`;
128
+ }
129
+ if (unchanged.length > 0) {
130
+ summary += `\n## Unchanged files (${unchanged.length}):\n`;
131
+ for (const c of unchanged) {
132
+ summary += `- ${c.file} (${c.fileType})\n`;
133
+ }
134
+ }
135
+ if (learnedPatterns.length > 0) {
136
+ summary += `\n## Patterns learned from edits:\n`;
137
+ for (const p of learnedPatterns) {
138
+ summary += `- ${p}\n`;
139
+ }
140
+ }
141
+ }
142
+ return { summary, changes, learnedPatterns };
143
+ }
144
+ // ─── Edit Pattern Extractors ────────────────────────────────────────────────
145
+ function extractPhpEditPatterns(content) {
146
+ const patterns = [];
147
+ // Detect new use-statements (imports)
148
+ const imports = content.match(/^use\s+[A-Z][^;]+;/gm) || [];
149
+ if (imports.length > 0) {
150
+ patterns.push(`PHP imports: ${imports.map(i => i.replace(/^use\s+/, '').replace(/;$/, '')).join(', ')}`);
151
+ }
152
+ // Detect traits
153
+ const classBody = content.match(/class\s+\w+[^{]*\{([\s\S]*)\}/)?.[1] || '';
154
+ const traits = classBody.match(/^\s+use\s+(\w+);/gm) || [];
155
+ if (traits.length > 0) {
156
+ patterns.push(`PHP traits: ${traits.map(t => t.trim().replace(/^use\s+/, '').replace(/;$/, '')).join(', ')}`);
157
+ }
158
+ // Detect extra methods
159
+ const methods = content.match(/public\s+function\s+(\w+)\s*\(/g) || [];
160
+ const standard = new Set(['fieldsBuilder', 'toArray', 'prepareComponents', 'getPlainHtml', '__construct']);
161
+ const extra = methods
162
+ .map(m => m.match(/function\s+(\w+)/)?.[1])
163
+ .filter((m) => !!m && !standard.has(m));
164
+ if (extra.length > 0) {
165
+ patterns.push(`Extra PHP methods: ${extra.join(', ')}`);
166
+ }
167
+ return patterns;
168
+ }
169
+ function extractTemplateEditPatterns(content) {
170
+ const patterns = [];
171
+ // Detect wrapper tag
172
+ const tagMatch = content.match(/<(\w+)\s+class="/);
173
+ if (tagMatch && tagMatch[1] !== 'div') {
174
+ patterns.push(`Template uses <${tagMatch[1]}> as wrapper (not default <div>)`);
175
+ }
176
+ // Detect escaping functions
177
+ const escFns = new Set((content.match(/(esc_html|esc_attr|esc_url|wp_kses|wp_kses_post)\(/g) || [])
178
+ .map(m => m.replace('(', '')));
179
+ if (escFns.size > 0) {
180
+ patterns.push(`Escaping functions: ${[...escFns].join(', ')}`);
181
+ }
182
+ return patterns;
183
+ }
184
+ function extractScssEditPatterns(content) {
185
+ const patterns = [];
186
+ // Detect CSS variables
187
+ const vars = content.match(/var\(--([^)]+)\)/g) || [];
188
+ if (vars.length > 0) {
189
+ const uniqueVars = [...new Set(vars)];
190
+ patterns.push(`CSS variables: ${uniqueVars.join(', ')}`);
191
+ }
192
+ // Detect breakpoints
193
+ const bps = content.match(/@include\s+\w+|@media\s*\([^)]+\)/g) || [];
194
+ if (bps.length > 0) {
195
+ patterns.push(`Breakpoints/mixins: ${[...new Set(bps)].join(', ')}`);
196
+ }
197
+ return patterns;
198
+ }
199
+ //# sourceMappingURL=feedback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback.js","sourceRoot":"","sources":["../../src/services/feedback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import type { BlockType } from '../constants.js';
2
+ /**
3
+ * Convert a label to various case formats used in Coretik.
4
+ */
5
+ /** "Text And Image" → "text-and-image" */
6
+ export declare function toKebabCase(label: string): string;
7
+ /** "Text And Image" → "text_and_image" */
8
+ export declare function toSnakeCase(label: string): string;
9
+ /** "Text And Image" → "TextAndImage" */
10
+ export declare function toPascalCase(label: string): string;
11
+ /** "Text And Image" → "textAndImage" */
12
+ export declare function toCamelCase(label: string): string;
13
+ /**
14
+ * Generate the Coretik block NAME constant.
15
+ * Convention: "type.kebab-case"
16
+ * e.g. "component.title", "block.text-and-image", "block.title-editor"
17
+ */
18
+ export declare function toBlockName(label: string, type: BlockType): string;
19
+ /**
20
+ * Generate the PHP class name.
21
+ * Convention: PascalCase + suffix based on type
22
+ * e.g. "TitleComponent", "TextAndImageBlock", "TitleAndTextComposite"
23
+ */
24
+ export declare function toClassName(label: string, type: BlockType): string;
25
+ /**
26
+ * Generate the PHP subdirectory based on block type.
27
+ * Convention: Component/, Block/, Composite/
28
+ */
29
+ export declare function toSubDirectory(type: BlockType): string;
30
+ /**
31
+ * Generate the template path relative to template directory.
32
+ * Convention: type/kebab-case.php
33
+ * e.g. "block/text-and-image.php"
34
+ */
35
+ export declare function toTemplatePath(label: string, type: BlockType): string;
36
+ /**
37
+ * Generate the SCSS filename.
38
+ * Convention: _kebab-case.scss
39
+ */
40
+ export declare function toScssFilename(label: string): string;
41
+ /**
42
+ * Generate the BEM-style CSS base class.
43
+ * Convention: kebab-case-block
44
+ */
45
+ export declare function toBemBase(label: string, type: BlockType): string;
46
+ /**
47
+ * Generate the ACF thumbnail filename.
48
+ * Convention: type--kebab-case.jpg (or .png)
49
+ */
50
+ export declare function toThumbnailFilename(label: string, type: BlockType): string;
51
+ //# sourceMappingURL=naming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../src/services/naming.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;GAEG;AAEH,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAElE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAMlE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAErE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAGhE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAE1E"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Convert a label to various case formats used in Coretik.
3
+ */
4
+ /** "Text And Image" → "text-and-image" */
5
+ export function toKebabCase(label) {
6
+ return label
7
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
8
+ .replace(/[\s_]+/g, '-')
9
+ .replace(/[^a-zA-Z0-9-]/g, '')
10
+ .toLowerCase();
11
+ }
12
+ /** "Text And Image" → "text_and_image" */
13
+ export function toSnakeCase(label) {
14
+ return toKebabCase(label).replace(/-/g, '_');
15
+ }
16
+ /** "Text And Image" → "TextAndImage" */
17
+ export function toPascalCase(label) {
18
+ return label
19
+ .replace(/[^a-zA-Z0-9\s]/g, '')
20
+ .split(/[\s_-]+/)
21
+ .map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
22
+ .join('');
23
+ }
24
+ /** "Text And Image" → "textAndImage" */
25
+ export function toCamelCase(label) {
26
+ const pascal = toPascalCase(label);
27
+ return pascal.charAt(0).toLowerCase() + pascal.slice(1);
28
+ }
29
+ /**
30
+ * Generate the Coretik block NAME constant.
31
+ * Convention: "type.kebab-case"
32
+ * e.g. "component.title", "block.text-and-image", "block.title-editor"
33
+ */
34
+ export function toBlockName(label, type) {
35
+ return `${type}.${toKebabCase(label)}`;
36
+ }
37
+ /**
38
+ * Generate the PHP class name.
39
+ * Convention: PascalCase + suffix based on type
40
+ * e.g. "TitleComponent", "TextAndImageBlock", "TitleAndTextComposite"
41
+ */
42
+ export function toClassName(label, type) {
43
+ const pascal = toPascalCase(label);
44
+ const suffix = type === 'component' ? 'Component' : type === 'composite' ? 'Composite' : 'Block';
45
+ // Avoid double suffix
46
+ if (pascal.endsWith(suffix))
47
+ return pascal;
48
+ return `${pascal}${suffix}`;
49
+ }
50
+ /**
51
+ * Generate the PHP subdirectory based on block type.
52
+ * Convention: Component/, Block/, Composite/
53
+ */
54
+ export function toSubDirectory(type) {
55
+ return type.charAt(0).toUpperCase() + type.slice(1) + '/';
56
+ }
57
+ /**
58
+ * Generate the template path relative to template directory.
59
+ * Convention: type/kebab-case.php
60
+ * e.g. "block/text-and-image.php"
61
+ */
62
+ export function toTemplatePath(label, type) {
63
+ return `${type}/${toKebabCase(label)}.php`;
64
+ }
65
+ /**
66
+ * Generate the SCSS filename.
67
+ * Convention: _kebab-case.scss
68
+ */
69
+ export function toScssFilename(label) {
70
+ return `_${toKebabCase(label)}.scss`;
71
+ }
72
+ /**
73
+ * Generate the BEM-style CSS base class.
74
+ * Convention: kebab-case-block
75
+ */
76
+ export function toBemBase(label, type) {
77
+ const suffix = type === 'component' ? '-component' : '-block';
78
+ return `${toKebabCase(label)}${suffix}`;
79
+ }
80
+ /**
81
+ * Generate the ACF thumbnail filename.
82
+ * Convention: type--kebab-case.jpg (or .png)
83
+ */
84
+ export function toThumbnailFilename(label, type) {
85
+ return `${type}--${toKebabCase(label)}.jpg`;
86
+ }
87
+ //# sourceMappingURL=naming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.js","sourceRoot":"","sources":["../../src/services/naming.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { LearnedConventions } from '../schemas/learned-conventions.js';
2
+ interface PathsConfig {
3
+ blocksPhp: string;
4
+ templates: string;
5
+ scss: string;
6
+ thumbnails: string;
7
+ acfAdmin: string;
8
+ }
9
+ /**
10
+ * Scan all existing blocks and extract patterns into LearnedConventions.
11
+ */
12
+ export declare function extractPatterns(projectRoot: string, paths: PathsConfig): Promise<LearnedConventions>;
13
+ export {};
14
+ //# sourceMappingURL=pattern-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-extractor.d.ts","sourceRoot":"","sources":["../../src/services/pattern-extractor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAI5E,UAAU,WAAW;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,kBAAkB,CAAC,CAe7B"}