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.
- package/CLAUDE_INSTRUCTIONS.md +30 -0
- package/README.md +193 -0
- package/dist/constants.d.ts +55 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +27 -0
- package/dist/constants.js.map +1 -0
- package/dist/conventions.d.ts +19 -0
- package/dist/conventions.d.ts.map +1 -0
- package/dist/conventions.js +158 -0
- package/dist/conventions.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +518 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/learned-conventions.d.ts +53 -0
- package/dist/schemas/learned-conventions.d.ts.map +1 -0
- package/dist/schemas/learned-conventions.js +47 -0
- package/dist/schemas/learned-conventions.js.map +1 -0
- package/dist/services/convention-store.d.ts +9 -0
- package/dist/services/convention-store.d.ts.map +1 -0
- package/dist/services/convention-store.js +84 -0
- package/dist/services/convention-store.js.map +1 -0
- package/dist/services/feedback.d.ts +29 -0
- package/dist/services/feedback.d.ts.map +1 -0
- package/dist/services/feedback.js +199 -0
- package/dist/services/feedback.js.map +1 -0
- package/dist/services/naming.d.ts +51 -0
- package/dist/services/naming.d.ts.map +1 -0
- package/dist/services/naming.js +87 -0
- package/dist/services/naming.js.map +1 -0
- package/dist/services/pattern-extractor.d.ts +14 -0
- package/dist/services/pattern-extractor.d.ts.map +1 -0
- package/dist/services/pattern-extractor.js +310 -0
- package/dist/services/pattern-extractor.js.map +1 -0
- package/dist/services/registration.d.ts +31 -0
- package/dist/services/registration.d.ts.map +1 -0
- package/dist/services/registration.js +275 -0
- package/dist/services/registration.js.map +1 -0
- package/dist/templates/generators.d.ts +59 -0
- package/dist/templates/generators.d.ts.map +1 -0
- package/dist/templates/generators.js +79 -0
- package/dist/templates/generators.js.map +1 -0
- package/dist/templates/html-template.d.ts +12 -0
- package/dist/templates/html-template.d.ts.map +1 -0
- package/dist/templates/html-template.js +189 -0
- package/dist/templates/html-template.js.map +1 -0
- package/dist/templates/php-class.d.ts +19 -0
- package/dist/templates/php-class.d.ts.map +1 -0
- package/dist/templates/php-class.js +271 -0
- package/dist/templates/php-class.js.map +1 -0
- package/dist/templates/scss.d.ts +7 -0
- package/dist/templates/scss.d.ts.map +1 -0
- package/dist/templates/scss.js +102 -0
- package/dist/templates/scss.js.map +1 -0
- package/dist/utils.d.ts +18 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +56 -0
- package/dist/utils.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { LearnedConventions } from '../schemas/learned-conventions.js';
|
|
2
|
+
/**
|
|
3
|
+
* Field definition as expected by index.ts tool schema.
|
|
4
|
+
*/
|
|
5
|
+
export interface BlockFieldDefinition {
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
label: string;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
instructions?: string;
|
|
11
|
+
defaultValue?: string;
|
|
12
|
+
returnFormat?: string;
|
|
13
|
+
choices?: Array<{
|
|
14
|
+
value: string;
|
|
15
|
+
label: string;
|
|
16
|
+
}>;
|
|
17
|
+
width?: string;
|
|
18
|
+
subFields?: BlockFieldDefinition[];
|
|
19
|
+
rows?: number;
|
|
20
|
+
mediaUpload?: boolean;
|
|
21
|
+
conditional?: {
|
|
22
|
+
field: string;
|
|
23
|
+
operator: string;
|
|
24
|
+
value: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Block definition as expected by index.ts tool schema.
|
|
29
|
+
*/
|
|
30
|
+
export interface BlockDefinition {
|
|
31
|
+
name: string;
|
|
32
|
+
label: string;
|
|
33
|
+
type: 'component' | 'block' | 'composite';
|
|
34
|
+
fields: BlockFieldDefinition[];
|
|
35
|
+
components?: Array<{
|
|
36
|
+
key: string;
|
|
37
|
+
className: string;
|
|
38
|
+
required?: boolean;
|
|
39
|
+
}>;
|
|
40
|
+
renderingType?: 'Html' | 'Array' | 'Object';
|
|
41
|
+
gutenberg?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Generate the PHP class for any block type.
|
|
45
|
+
*/
|
|
46
|
+
export declare function generateBlockPhp(def: BlockDefinition, rootNamespace: string, learned?: LearnedConventions | null): string;
|
|
47
|
+
/**
|
|
48
|
+
* Generate the HTML template.
|
|
49
|
+
*/
|
|
50
|
+
export declare function generateTemplate(def: BlockDefinition, learned?: LearnedConventions | null): string;
|
|
51
|
+
/**
|
|
52
|
+
* Generate the SCSS stylesheet.
|
|
53
|
+
*/
|
|
54
|
+
export declare function generateScss(def: BlockDefinition, learned?: LearnedConventions | null): string;
|
|
55
|
+
/**
|
|
56
|
+
* Generate a placeholder SVG thumbnail for the block.
|
|
57
|
+
*/
|
|
58
|
+
export declare function generatePlaceholderSvg(def: BlockDefinition): string;
|
|
59
|
+
//# sourceMappingURL=generators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../src/templates/generators.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAM5E;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,WAAW,GAAG,OAAO,GAAG,WAAW,CAAC;IAC1C,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC3E,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC5C,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAgCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,MAAM,CAoBzH;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,MAAM,CAIlG;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,MAAM,CAG9F;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAQnE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { generateBlockClass, generateComponentClass, generateCompositeClass } from './php-class.js';
|
|
2
|
+
import { generateHtmlTemplate } from './html-template.js';
|
|
3
|
+
import { generateScss as generateScssInternal } from './scss.js';
|
|
4
|
+
import { toKebabCase } from '../services/naming.js';
|
|
5
|
+
/**
|
|
6
|
+
* Convert BlockFieldDefinition to BlockField (internal format).
|
|
7
|
+
*/
|
|
8
|
+
function toBlockField(def) {
|
|
9
|
+
return {
|
|
10
|
+
name: def.name,
|
|
11
|
+
type: def.type,
|
|
12
|
+
label: def.label,
|
|
13
|
+
required: def.required,
|
|
14
|
+
defaultValue: def.defaultValue,
|
|
15
|
+
choices: def.choices?.map(c => c.value),
|
|
16
|
+
instructions: def.instructions,
|
|
17
|
+
subFields: def.subFields?.map(toBlockField),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Convert BlockDefinition to BlockSpec (internal format).
|
|
22
|
+
*/
|
|
23
|
+
function toBlockSpec(def) {
|
|
24
|
+
return {
|
|
25
|
+
label: def.label,
|
|
26
|
+
name: def.name,
|
|
27
|
+
type: def.type,
|
|
28
|
+
fields: def.fields.map(toBlockField),
|
|
29
|
+
components: def.components?.map(c => c.className),
|
|
30
|
+
blockTypeSupport: def.gutenberg,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate the PHP class for any block type.
|
|
35
|
+
*/
|
|
36
|
+
export function generateBlockPhp(def, rootNamespace, learned) {
|
|
37
|
+
const spec = toBlockSpec(def);
|
|
38
|
+
switch (def.type) {
|
|
39
|
+
case 'component':
|
|
40
|
+
return generateComponentClass(spec, rootNamespace, learned);
|
|
41
|
+
case 'composite':
|
|
42
|
+
return generateCompositeClass(spec, rootNamespace, (def.components || []).map(c => ({
|
|
43
|
+
key: c.key,
|
|
44
|
+
className: c.className,
|
|
45
|
+
fqcn: `${rootNamespace}\\Component\\${c.className}`,
|
|
46
|
+
})), learned);
|
|
47
|
+
case 'block':
|
|
48
|
+
default:
|
|
49
|
+
return generateBlockClass(spec, rootNamespace, learned);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate the HTML template.
|
|
54
|
+
*/
|
|
55
|
+
export function generateTemplate(def, learned) {
|
|
56
|
+
const spec = toBlockSpec(def);
|
|
57
|
+
const components = def.components?.map(c => ({ key: c.key, className: c.className }));
|
|
58
|
+
return generateHtmlTemplate(spec, learned, components);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generate the SCSS stylesheet.
|
|
62
|
+
*/
|
|
63
|
+
export function generateScss(def, learned) {
|
|
64
|
+
const spec = toBlockSpec(def);
|
|
65
|
+
return generateScssInternal(spec, learned);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate a placeholder SVG thumbnail for the block.
|
|
69
|
+
*/
|
|
70
|
+
export function generatePlaceholderSvg(def) {
|
|
71
|
+
const kebab = toKebabCase(def.name);
|
|
72
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 120" fill="none">
|
|
73
|
+
<rect width="200" height="120" rx="4" fill="#f0f0f0"/>
|
|
74
|
+
<text x="100" y="55" text-anchor="middle" fill="#666" font-family="sans-serif" font-size="12">${def.label}</text>
|
|
75
|
+
<text x="100" y="75" text-anchor="middle" fill="#999" font-family="sans-serif" font-size="10">${kebab}</text>
|
|
76
|
+
</svg>
|
|
77
|
+
`;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=generators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generators.js","sourceRoot":"","sources":["../../src/templates/generators.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BlockSpec } from '../constants.js';
|
|
2
|
+
import type { LearnedConventions } from '../schemas/learned-conventions.js';
|
|
3
|
+
/**
|
|
4
|
+
* Generate the PHP/HTML template file for a block.
|
|
5
|
+
* For composites, generates component method calls ($component->render(), etc.)
|
|
6
|
+
* For components, generates field-level HTML with short echo tags.
|
|
7
|
+
*/
|
|
8
|
+
export declare function generateHtmlTemplate(spec: BlockSpec, learned?: LearnedConventions | null, components?: Array<{
|
|
9
|
+
key: string;
|
|
10
|
+
className: string;
|
|
11
|
+
}>): string;
|
|
12
|
+
//# sourceMappingURL=html-template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-template.d.ts","sourceRoot":"","sources":["../../src/templates/html-template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAG5E;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,EACf,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,EACnC,UAAU,CAAC,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,GACrD,MAAM,CAYR"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { toBemBase, toKebabCase } from '../services/naming.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generate the PHP/HTML template file for a block.
|
|
4
|
+
* For composites, generates component method calls ($component->render(), etc.)
|
|
5
|
+
* For components, generates field-level HTML with short echo tags.
|
|
6
|
+
*/
|
|
7
|
+
export function generateHtmlTemplate(spec, learned, components) {
|
|
8
|
+
const bemBase = toBemBase(spec.label, spec.type);
|
|
9
|
+
// Composite blocks use <section>, components use <div>
|
|
10
|
+
const defaultTag = spec.type === 'component' ? 'div' : 'section';
|
|
11
|
+
const wrapperTag = learned?.template.wrapperTag || defaultTag;
|
|
12
|
+
if (spec.type === 'composite' && components && components.length > 0) {
|
|
13
|
+
return generateCompositeTemplate(spec, bemBase, wrapperTag, components);
|
|
14
|
+
}
|
|
15
|
+
return generateFieldTemplate(spec, bemBase, wrapperTag, learned);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Generate a template for a composite block using component method calls.
|
|
19
|
+
*/
|
|
20
|
+
function generateCompositeTemplate(spec, bemBase, wrapperTag, components) {
|
|
21
|
+
const lines = [];
|
|
22
|
+
lines.push('<?php');
|
|
23
|
+
lines.push(`/**`);
|
|
24
|
+
lines.push(` * Block: ${spec.label}`);
|
|
25
|
+
lines.push(` *`);
|
|
26
|
+
for (const comp of components) {
|
|
27
|
+
lines.push(` * @var \\Coretik\\PageBuilder\\Core\\Block\\BlockComponent $${comp.key}`);
|
|
28
|
+
}
|
|
29
|
+
lines.push(` */`);
|
|
30
|
+
lines.push('');
|
|
31
|
+
// Class list with context awareness (real Coretik pattern)
|
|
32
|
+
lines.push(`use Coretik\\PageBuilder\\Core\\Block\\Context\\BlockContextType;`);
|
|
33
|
+
lines.push('');
|
|
34
|
+
lines.push(`$classlist = ['${bemBase}'];`);
|
|
35
|
+
lines.push(`if (!empty($context) && $context['type'] === BlockContextType::CONTAINER->name) {`);
|
|
36
|
+
lines.push(` $classlist[] = 'contained';`);
|
|
37
|
+
lines.push(`}`);
|
|
38
|
+
lines.push('?>');
|
|
39
|
+
lines.push(`<${wrapperTag} class="<?= implode(' ', $classlist) ?>">`);
|
|
40
|
+
lines.push(` <div class="container">`);
|
|
41
|
+
for (const comp of components) {
|
|
42
|
+
lines.push(` <?php if (!empty($${comp.key})) : ?>`);
|
|
43
|
+
lines.push(` <div class="${bemBase}__${toKebabCase(comp.key)}">`);
|
|
44
|
+
lines.push(` <?php $${comp.key}->render(); ?>`);
|
|
45
|
+
lines.push(` </div>`);
|
|
46
|
+
lines.push(` <?php endif; ?>`);
|
|
47
|
+
}
|
|
48
|
+
lines.push(` </div>`);
|
|
49
|
+
lines.push(`</${wrapperTag}>`);
|
|
50
|
+
return lines.join('\n') + '\n';
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate a template for a component/block using direct field HTML.
|
|
54
|
+
*/
|
|
55
|
+
function generateFieldTemplate(spec, bemBase, wrapperTag, learned) {
|
|
56
|
+
const docParams = spec.fields
|
|
57
|
+
.map(f => ` * @var ${phpTypeFromAcf(f.type)} $${f.name}`)
|
|
58
|
+
.join('\n');
|
|
59
|
+
const htmlContent = generateFieldsHtml(spec.fields, bemBase, ' ', learned);
|
|
60
|
+
return `<?php
|
|
61
|
+
/**
|
|
62
|
+
* Block: ${spec.label}
|
|
63
|
+
*
|
|
64
|
+
${docParams}
|
|
65
|
+
*/
|
|
66
|
+
?>
|
|
67
|
+
<${wrapperTag} class="${bemBase}">
|
|
68
|
+
${htmlContent}
|
|
69
|
+
</${wrapperTag}>
|
|
70
|
+
`;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Generate HTML for each field based on its ACF type.
|
|
74
|
+
*/
|
|
75
|
+
function generateFieldsHtml(fields, bemBase, indent = ' ', learned) {
|
|
76
|
+
return fields.map(field => {
|
|
77
|
+
const elementClass = `${bemBase}__${toKebabCase(field.name)}`;
|
|
78
|
+
return generateSingleFieldHtml(field, elementClass, indent, learned);
|
|
79
|
+
}).join('\n');
|
|
80
|
+
}
|
|
81
|
+
function generateSingleFieldHtml(field, cssClass, indent, learned) {
|
|
82
|
+
const imgFn = learned?.template.imageRenderFunction || 'wp_get_attachment_image';
|
|
83
|
+
switch (field.type) {
|
|
84
|
+
case 'image':
|
|
85
|
+
return `${indent}<?php if (!empty($${field.name})) : ?>
|
|
86
|
+
${indent}<div class="${cssClass}">
|
|
87
|
+
${indent} <?= ${imgFn}($${field.name}, 'large', false, ['class' => '${cssClass}-img']) ?>
|
|
88
|
+
${indent}</div>
|
|
89
|
+
${indent}<?php endif; ?>`;
|
|
90
|
+
case 'wysiwyg':
|
|
91
|
+
return `${indent}<?php if (!empty($${field.name})) : ?>
|
|
92
|
+
${indent}<div class="${cssClass}">
|
|
93
|
+
${indent} <?= $${field.name} ?>
|
|
94
|
+
${indent}</div>
|
|
95
|
+
${indent}<?php endif; ?>`;
|
|
96
|
+
case 'link':
|
|
97
|
+
return `${indent}<?php if (!empty($${field.name})) : ?>
|
|
98
|
+
${indent}<a class="${cssClass}" href="<?= $${field.name}['url'] ?>" target="<?= $${field.name}['target'] ?: '_self' ?>">
|
|
99
|
+
${indent} <?= $${field.name}['title'] ?>
|
|
100
|
+
${indent}</a>
|
|
101
|
+
${indent}<?php endif; ?>`;
|
|
102
|
+
case 'gallery':
|
|
103
|
+
return `${indent}<?php if (!empty($${field.name})) : ?>
|
|
104
|
+
${indent}<div class="${cssClass}">
|
|
105
|
+
${indent} <?php foreach ($${field.name} as $image) : ?>
|
|
106
|
+
${indent} <?= ${imgFn}($image, 'medium', false, ['class' => '${cssClass}-img']) ?>
|
|
107
|
+
${indent} <?php endforeach; ?>
|
|
108
|
+
${indent}</div>
|
|
109
|
+
${indent}<?php endif; ?>`;
|
|
110
|
+
case 'repeater':
|
|
111
|
+
const subHtml = (field.subFields || [])
|
|
112
|
+
.map(sub => {
|
|
113
|
+
const subClass = `${cssClass}-item__${toKebabCase(sub.name)}`;
|
|
114
|
+
return generateSingleFieldHtml(sub, subClass, indent + ' ', learned);
|
|
115
|
+
})
|
|
116
|
+
.join('\n');
|
|
117
|
+
return `${indent}<?php if (!empty($${field.name})) : ?>
|
|
118
|
+
${indent}<div class="${cssClass}">
|
|
119
|
+
${indent} <?php foreach ($${field.name} as $item) : ?>
|
|
120
|
+
${indent} <div class="${cssClass}-item">
|
|
121
|
+
${subHtml}
|
|
122
|
+
${indent} </div>
|
|
123
|
+
${indent} <?php endforeach; ?>
|
|
124
|
+
${indent}</div>
|
|
125
|
+
${indent}<?php endif; ?>`;
|
|
126
|
+
case 'true_false':
|
|
127
|
+
return `${indent}<?php if ($${field.name}) : ?>
|
|
128
|
+
${indent}<div class="${cssClass}">
|
|
129
|
+
${indent} <!-- ${field.label} -->
|
|
130
|
+
${indent}</div>
|
|
131
|
+
${indent}<?php endif; ?>`;
|
|
132
|
+
case 'select':
|
|
133
|
+
case 'radio':
|
|
134
|
+
return `${indent}<?php if (!empty($${field.name})) : ?>
|
|
135
|
+
${indent}<div class="${cssClass}" data-value="<?= $${field.name} ?>">
|
|
136
|
+
${indent} <?= $${field.name} ?>
|
|
137
|
+
${indent}</div>
|
|
138
|
+
${indent}<?php endif; ?>`;
|
|
139
|
+
case 'oembed':
|
|
140
|
+
return `${indent}<?php if (!empty($${field.name})) : ?>
|
|
141
|
+
${indent}<div class="${cssClass}">
|
|
142
|
+
${indent} <?= $${field.name} ?>
|
|
143
|
+
${indent}</div>
|
|
144
|
+
${indent}<?php endif; ?>`;
|
|
145
|
+
case 'text':
|
|
146
|
+
case 'textarea':
|
|
147
|
+
case 'email':
|
|
148
|
+
case 'url':
|
|
149
|
+
case 'number':
|
|
150
|
+
default:
|
|
151
|
+
return `${indent}<?php if (!empty($${field.name})) : ?>
|
|
152
|
+
${indent}<div class="${cssClass}">
|
|
153
|
+
${indent} <?= $${field.name} ?>
|
|
154
|
+
${indent}</div>
|
|
155
|
+
${indent}<?php endif; ?>`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function phpTypeFromAcf(type) {
|
|
159
|
+
const map = {
|
|
160
|
+
text: 'string',
|
|
161
|
+
textarea: 'string',
|
|
162
|
+
wysiwyg: 'string',
|
|
163
|
+
image: 'int|array',
|
|
164
|
+
gallery: 'array',
|
|
165
|
+
file: 'int|array',
|
|
166
|
+
select: 'string|array',
|
|
167
|
+
radio: 'string',
|
|
168
|
+
checkbox: 'array',
|
|
169
|
+
true_false: 'bool',
|
|
170
|
+
link: 'array',
|
|
171
|
+
url: 'string',
|
|
172
|
+
number: 'int|float',
|
|
173
|
+
range: 'int|float',
|
|
174
|
+
email: 'string',
|
|
175
|
+
repeater: 'array',
|
|
176
|
+
group: 'array',
|
|
177
|
+
relationship: 'array',
|
|
178
|
+
post_object: 'int|WP_Post',
|
|
179
|
+
taxonomy: 'int|WP_Term',
|
|
180
|
+
user: 'int|WP_User',
|
|
181
|
+
color_picker: 'string',
|
|
182
|
+
date_picker: 'string',
|
|
183
|
+
date_time_picker: 'string',
|
|
184
|
+
time_picker: 'string',
|
|
185
|
+
oembed: 'string',
|
|
186
|
+
};
|
|
187
|
+
return map[type] || 'mixed';
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=html-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-template.js","sourceRoot":"","sources":["../../src/templates/html-template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BlockSpec } from '../constants.js';
|
|
2
|
+
import type { LearnedConventions } from '../schemas/learned-conventions.js';
|
|
3
|
+
/**
|
|
4
|
+
* Generate a Block PHP class.
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateBlockClass(spec: BlockSpec, rootNamespace: string, learned?: LearnedConventions | null): string;
|
|
7
|
+
/**
|
|
8
|
+
* Generate a Component PHP class.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateComponentClass(spec: BlockSpec, rootNamespace: string, learned?: LearnedConventions | null): string;
|
|
11
|
+
/**
|
|
12
|
+
* Generate a Composite PHP class.
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateCompositeClass(spec: BlockSpec, rootNamespace: string, componentsMap: Array<{
|
|
15
|
+
key: string;
|
|
16
|
+
className: string;
|
|
17
|
+
fqcn: string;
|
|
18
|
+
}>, learned?: LearnedConventions | null): string;
|
|
19
|
+
//# sourceMappingURL=php-class.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"php-class.d.ts","sourceRoot":"","sources":["../../src/templates/php-class.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAsF5E;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,MAAM,CAmEtH;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,MAAM,CAuE1H;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,EACf,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACtE,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAClC,MAAM,CAkDR"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { toBlockName, toClassName, toPascalCase, toBemBase, } from '../services/naming.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generate the ACF FieldsBuilder method chain for a single field.
|
|
4
|
+
*/
|
|
5
|
+
function generateFieldBuilder(field, indent = ' ') {
|
|
6
|
+
const lines = [];
|
|
7
|
+
const addMethod = getAddMethod(field.type);
|
|
8
|
+
let fieldLine = `${indent}->${addMethod}('${field.name}')`;
|
|
9
|
+
lines.push(fieldLine);
|
|
10
|
+
lines.push(`${indent} ->setLabel('${escapePhp(field.label)}')`);
|
|
11
|
+
if (field.required) {
|
|
12
|
+
lines.push(`${indent} ->setRequired()`);
|
|
13
|
+
}
|
|
14
|
+
if (field.instructions) {
|
|
15
|
+
lines.push(`${indent} ->setInstructions('${escapePhp(field.instructions)}')`);
|
|
16
|
+
}
|
|
17
|
+
if (field.defaultValue !== undefined) {
|
|
18
|
+
lines.push(`${indent} ->setDefaultValue('${escapePhp(field.defaultValue)}')`);
|
|
19
|
+
}
|
|
20
|
+
if (field.choices && field.choices.length > 0) {
|
|
21
|
+
for (const choice of field.choices) {
|
|
22
|
+
lines.push(`${indent} ->addChoice('${escapePhp(choice)}')`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Handle repeater/group sub-fields
|
|
26
|
+
if (field.subFields && field.subFields.length > 0) {
|
|
27
|
+
for (const sub of field.subFields) {
|
|
28
|
+
lines.push(generateFieldBuilder(sub, indent + ' '));
|
|
29
|
+
}
|
|
30
|
+
lines.push(`${indent} ->endRepeater()`);
|
|
31
|
+
}
|
|
32
|
+
return lines.join('\n');
|
|
33
|
+
}
|
|
34
|
+
function getAddMethod(type) {
|
|
35
|
+
const map = {
|
|
36
|
+
text: 'addText',
|
|
37
|
+
textarea: 'addTextarea',
|
|
38
|
+
wysiwyg: 'addWysiwyg',
|
|
39
|
+
image: 'addImage',
|
|
40
|
+
gallery: 'addGallery',
|
|
41
|
+
file: 'addFile',
|
|
42
|
+
select: 'addSelect',
|
|
43
|
+
radio: 'addRadio',
|
|
44
|
+
checkbox: 'addCheckbox',
|
|
45
|
+
true_false: 'addTrueFalse',
|
|
46
|
+
link: 'addLink',
|
|
47
|
+
url: 'addUrl',
|
|
48
|
+
number: 'addNumber',
|
|
49
|
+
range: 'addRange',
|
|
50
|
+
email: 'addEmail',
|
|
51
|
+
password: 'addPassword',
|
|
52
|
+
repeater: 'addRepeater',
|
|
53
|
+
group: 'addGroup',
|
|
54
|
+
relationship: 'addRelationship',
|
|
55
|
+
post_object: 'addPostObject',
|
|
56
|
+
taxonomy: 'addTaxonomy',
|
|
57
|
+
user: 'addUser',
|
|
58
|
+
color_picker: 'addColorPicker',
|
|
59
|
+
date_picker: 'addDatePicker',
|
|
60
|
+
date_time_picker: 'addDateTimePicker',
|
|
61
|
+
time_picker: 'addTimePicker',
|
|
62
|
+
oembed: 'addOembed',
|
|
63
|
+
};
|
|
64
|
+
return map[type] || 'addText';
|
|
65
|
+
}
|
|
66
|
+
function escapePhp(str) {
|
|
67
|
+
return str.replace(/'/g, "\\'");
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Generate a Block PHP class.
|
|
71
|
+
*/
|
|
72
|
+
export function generateBlockClass(spec, rootNamespace, learned) {
|
|
73
|
+
const className = spec.name ? toPascalCase(spec.name) : toClassName(spec.label, 'block');
|
|
74
|
+
const blockName = toBlockName(spec.label, 'block');
|
|
75
|
+
const namespace = `${rootNamespace}\\Block`;
|
|
76
|
+
const vis = learned?.php.propertyVisibility || 'protected';
|
|
77
|
+
const properties = spec.fields.map(f => ` ${vis} $${f.name};`).join('\n');
|
|
78
|
+
const fieldsBuilder = spec.fields.map(f => generateFieldBuilder(f)).join('\n');
|
|
79
|
+
const toArrayEntries = spec.fields
|
|
80
|
+
.map(f => ` '${f.name}' => $this->${f.name},`)
|
|
81
|
+
.join('\n');
|
|
82
|
+
const blockTypeImports = spec.blockTypeSupport
|
|
83
|
+
? `\nuse Coretik\\PageBuilder\\Core\\Contract\\ShouldBuildBlockType;\nuse Coretik\\PageBuilder\\Core\\Block\\Traits\\BlockType;`
|
|
84
|
+
: '';
|
|
85
|
+
const blockTypeImplements = spec.blockTypeSupport ? ' implements ShouldBuildBlockType' : '';
|
|
86
|
+
const blockTypeTrait = spec.blockTypeSupport ? '\n use BlockType;\n' : '';
|
|
87
|
+
// Learned extra imports
|
|
88
|
+
const learnedImports = buildLearnedImports(learned, [
|
|
89
|
+
'Coretik\\PageBuilder\\Core\\Block\\Block',
|
|
90
|
+
'StoutLogic\\AcfBuilder\\FieldsBuilder',
|
|
91
|
+
]);
|
|
92
|
+
// Learned traits
|
|
93
|
+
const learnedTraits = buildLearnedTraits(learned, spec.blockTypeSupport ? ['BlockType'] : []);
|
|
94
|
+
// Learned extra methods
|
|
95
|
+
const learnedMethods = buildLearnedMethods(learned);
|
|
96
|
+
const useSettingsLine = (!learned || learned.php.useSettingsPattern)
|
|
97
|
+
? '\n $this->useSettingsOn($field);' : '';
|
|
98
|
+
return `<?php
|
|
99
|
+
|
|
100
|
+
namespace ${namespace};
|
|
101
|
+
|
|
102
|
+
use Coretik\\PageBuilder\\Core\\Block\\Block;${blockTypeImports}
|
|
103
|
+
use StoutLogic\\AcfBuilder\\FieldsBuilder;${learnedImports}
|
|
104
|
+
|
|
105
|
+
class ${className} extends Block${blockTypeImplements}
|
|
106
|
+
{${blockTypeTrait}${learnedTraits}
|
|
107
|
+
const NAME = '${blockName}';
|
|
108
|
+
const LABEL = '${escapePhp(spec.label)}';
|
|
109
|
+
|
|
110
|
+
${properties}
|
|
111
|
+
|
|
112
|
+
public function fieldsBuilder(): FieldsBuilder
|
|
113
|
+
{
|
|
114
|
+
$field = $this->createFieldsBuilder();
|
|
115
|
+
$field
|
|
116
|
+
${fieldsBuilder};
|
|
117
|
+
${useSettingsLine}
|
|
118
|
+
return $field;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public function toArray()
|
|
122
|
+
{
|
|
123
|
+
return [
|
|
124
|
+
${toArrayEntries}
|
|
125
|
+
];
|
|
126
|
+
}${learnedMethods}
|
|
127
|
+
}
|
|
128
|
+
`;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Generate a Component PHP class.
|
|
132
|
+
*/
|
|
133
|
+
export function generateComponentClass(spec, rootNamespace, learned) {
|
|
134
|
+
const className = spec.name ? toPascalCase(spec.name) : toClassName(spec.label, 'component');
|
|
135
|
+
const blockName = toBlockName(spec.label, 'component');
|
|
136
|
+
const namespace = `${rootNamespace}\\Component`;
|
|
137
|
+
const bemBase = toBemBase(spec.label, 'component');
|
|
138
|
+
const vis = learned?.php.propertyVisibility || 'protected';
|
|
139
|
+
const properties = spec.fields.map(f => ` ${vis} $${f.name};`).join('\n');
|
|
140
|
+
const fieldsBuilder = spec.fields.map(f => generateFieldBuilder(f)).join('\n');
|
|
141
|
+
const toArrayEntries = spec.fields
|
|
142
|
+
.map(f => ` '${f.name}' => $this->${f.name},`)
|
|
143
|
+
.join('\n');
|
|
144
|
+
const blockTypeImports = spec.blockTypeSupport
|
|
145
|
+
? `\nuse Coretik\\PageBuilder\\Core\\Contract\\ShouldBuildBlockType;\nuse Coretik\\PageBuilder\\Core\\Block\\Traits\\BlockType;`
|
|
146
|
+
: '';
|
|
147
|
+
const blockTypeImplements = spec.blockTypeSupport ? ' implements ShouldBuildBlockType' : '';
|
|
148
|
+
const blockTypeTrait = spec.blockTypeSupport ? '\n use BlockType;\n' : '';
|
|
149
|
+
const learnedImports = buildLearnedImports(learned, [
|
|
150
|
+
'Coretik\\PageBuilder\\Core\\Block\\BlockComponent',
|
|
151
|
+
'StoutLogic\\AcfBuilder\\FieldsBuilder',
|
|
152
|
+
]);
|
|
153
|
+
const learnedTraits = buildLearnedTraits(learned, spec.blockTypeSupport ? ['BlockType'] : []);
|
|
154
|
+
const learnedMethods = buildLearnedMethods(learned);
|
|
155
|
+
const useSettingsLine = (!learned || learned.php.useSettingsPattern)
|
|
156
|
+
? '\n $this->useSettingsOn($field);' : '';
|
|
157
|
+
return `<?php
|
|
158
|
+
|
|
159
|
+
namespace ${namespace};
|
|
160
|
+
|
|
161
|
+
use Coretik\\PageBuilder\\Core\\Block\\BlockComponent;${blockTypeImports}
|
|
162
|
+
use StoutLogic\\AcfBuilder\\FieldsBuilder;${learnedImports}
|
|
163
|
+
|
|
164
|
+
class ${className} extends BlockComponent${blockTypeImplements}
|
|
165
|
+
{${blockTypeTrait}${learnedTraits}
|
|
166
|
+
const NAME = '${blockName}';
|
|
167
|
+
const LABEL = '${escapePhp(spec.label)}';
|
|
168
|
+
|
|
169
|
+
${properties}
|
|
170
|
+
|
|
171
|
+
public function fieldsBuilder(): FieldsBuilder
|
|
172
|
+
{
|
|
173
|
+
$field = $this->createFieldsBuilder();
|
|
174
|
+
$field
|
|
175
|
+
${fieldsBuilder};
|
|
176
|
+
${useSettingsLine}
|
|
177
|
+
return $field;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
public function toArray()
|
|
181
|
+
{
|
|
182
|
+
return [
|
|
183
|
+
${toArrayEntries}
|
|
184
|
+
];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
protected function getPlainHtml(array $parameters): string
|
|
188
|
+
{
|
|
189
|
+
return sprintf(
|
|
190
|
+
'<div class="${bemBase}">%s</div>',
|
|
191
|
+
implode('', array_values($parameters))
|
|
192
|
+
);
|
|
193
|
+
}${learnedMethods}
|
|
194
|
+
}
|
|
195
|
+
`;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Generate a Composite PHP class.
|
|
199
|
+
*/
|
|
200
|
+
export function generateCompositeClass(spec, rootNamespace, componentsMap, learned) {
|
|
201
|
+
const className = spec.name ? toPascalCase(spec.name) : toClassName(spec.label, 'composite');
|
|
202
|
+
const blockName = toBlockName(spec.label, 'composite');
|
|
203
|
+
const namespace = `${rootNamespace}\\Composite`;
|
|
204
|
+
const bemBase = toBemBase(spec.label, 'composite');
|
|
205
|
+
const useStatements = componentsMap
|
|
206
|
+
.map(c => `use ${c.fqcn};`)
|
|
207
|
+
.join('\n');
|
|
208
|
+
const prepareEntries = componentsMap
|
|
209
|
+
.map(c => ` '${c.key}' => ${c.className}::class,`)
|
|
210
|
+
.join('\n');
|
|
211
|
+
const htmlParts = componentsMap
|
|
212
|
+
.map(c => `$parameters['${c.key}']`)
|
|
213
|
+
.join(', ');
|
|
214
|
+
const blockTypeImports = spec.blockTypeSupport
|
|
215
|
+
? `\nuse Coretik\\PageBuilder\\Core\\Contract\\ShouldBuildBlockType;\nuse Coretik\\PageBuilder\\Core\\Block\\Traits\\BlockType;`
|
|
216
|
+
: '';
|
|
217
|
+
const blockTypeImplements = spec.blockTypeSupport ? ' implements ShouldBuildBlockType' : '';
|
|
218
|
+
const blockTypeTrait = spec.blockTypeSupport ? '\n use BlockType;\n' : '';
|
|
219
|
+
return `<?php
|
|
220
|
+
|
|
221
|
+
namespace ${namespace};
|
|
222
|
+
|
|
223
|
+
use Coretik\\PageBuilder\\Core\\Block\\BlockComposite;${blockTypeImports}
|
|
224
|
+
${useStatements}
|
|
225
|
+
|
|
226
|
+
class ${className} extends BlockComposite${blockTypeImplements}
|
|
227
|
+
{${blockTypeTrait}
|
|
228
|
+
const NAME = '${blockName}';
|
|
229
|
+
const LABEL = '${escapePhp(spec.label)}';
|
|
230
|
+
|
|
231
|
+
protected function prepareComponents(): array
|
|
232
|
+
{
|
|
233
|
+
return [
|
|
234
|
+
${prepareEntries}
|
|
235
|
+
];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
protected function getPlainHtml(array $parameters): string
|
|
239
|
+
{
|
|
240
|
+
return sprintf('<div class="${bemBase}">%s</div>', implode('', [${htmlParts}]));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
`;
|
|
244
|
+
}
|
|
245
|
+
// ─── Learned Convention Helpers ─────────────────────────────────────────────
|
|
246
|
+
function buildLearnedImports(learned, alreadyImported) {
|
|
247
|
+
if (!learned?.php.imports.length)
|
|
248
|
+
return '';
|
|
249
|
+
const existing = new Set(alreadyImported);
|
|
250
|
+
const extra = learned.php.imports.filter(i => !existing.has(i));
|
|
251
|
+
if (extra.length === 0)
|
|
252
|
+
return '';
|
|
253
|
+
return '\n' + extra.map(i => `use ${i};`).join('\n');
|
|
254
|
+
}
|
|
255
|
+
function buildLearnedTraits(learned, alreadyUsed) {
|
|
256
|
+
if (!learned?.php.traits.length)
|
|
257
|
+
return '';
|
|
258
|
+
const existing = new Set(alreadyUsed);
|
|
259
|
+
const extra = learned.php.traits.filter(t => !existing.has(t));
|
|
260
|
+
if (extra.length === 0)
|
|
261
|
+
return '';
|
|
262
|
+
return '\n' + extra.map(t => ` use ${t};`).join('\n');
|
|
263
|
+
}
|
|
264
|
+
function buildLearnedMethods(learned) {
|
|
265
|
+
if (!learned?.php.extraMethods.length)
|
|
266
|
+
return '';
|
|
267
|
+
return '\n\n' + learned.php.extraMethods
|
|
268
|
+
.map(m => ` // TODO: Implement ${m}() — pattern detected in existing blocks`)
|
|
269
|
+
.join('\n');
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=php-class.js.map
|