@wp-typia/project-tools 0.23.1 → 0.24.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/dist/runtime/built-in-block-non-ts-basic-artifacts.d.ts +9 -0
- package/dist/runtime/built-in-block-non-ts-basic-artifacts.js +84 -0
- package/dist/runtime/built-in-block-non-ts-compound-artifacts.d.ts +9 -0
- package/dist/runtime/built-in-block-non-ts-compound-artifacts.js +36 -0
- package/dist/runtime/built-in-block-non-ts-compound-templates.d.ts +23 -0
- package/dist/runtime/built-in-block-non-ts-compound-templates.js +453 -0
- package/dist/runtime/built-in-block-non-ts-family-artifacts.d.ts +8 -26
- package/dist/runtime/built-in-block-non-ts-family-artifacts.js +8 -1034
- package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.d.ts +9 -0
- package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.js +83 -0
- package/dist/runtime/built-in-block-non-ts-persistence-artifacts.d.ts +9 -0
- package/dist/runtime/built-in-block-non-ts-persistence-artifacts.js +33 -0
- package/dist/runtime/built-in-block-non-ts-persistence-templates.d.ts +23 -0
- package/dist/runtime/built-in-block-non-ts-persistence-templates.js +395 -0
- package/dist/runtime/cli-add-collision.js +8 -0
- package/dist/runtime/cli-add-help.js +10 -7
- package/dist/runtime/cli-add-kind-ids.d.ts +1 -1
- package/dist/runtime/cli-add-kind-ids.js +1 -0
- package/dist/runtime/cli-add-types.d.ts +28 -1
- package/dist/runtime/cli-add-types.js +2 -0
- package/dist/runtime/cli-add-workspace-ability-anchors.d.ts +24 -0
- package/dist/runtime/cli-add-workspace-ability-anchors.js +294 -0
- package/dist/runtime/cli-add-workspace-ability-registry.d.ts +10 -0
- package/dist/runtime/cli-add-workspace-ability-registry.js +51 -0
- package/dist/runtime/cli-add-workspace-ability-scaffold.d.ts +1 -1
- package/dist/runtime/cli-add-workspace-ability-scaffold.js +5 -311
- package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +1 -1
- package/dist/runtime/cli-add-workspace-ai-anchors.d.ts +4 -4
- package/dist/runtime/cli-add-workspace-ai-anchors.js +4 -232
- package/dist/runtime/cli-add-workspace-ai-scaffold.js +4 -2
- package/dist/runtime/cli-add-workspace-ai-source-emitters.d.ts +1 -4
- package/dist/runtime/cli-add-workspace-ai-source-emitters.js +1 -145
- package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.d.ts +5 -0
- package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.js +236 -0
- package/dist/runtime/cli-add-workspace-ai-sync-script-source.d.ts +4 -0
- package/dist/runtime/cli-add-workspace-ai-sync-script-source.js +145 -0
- package/dist/runtime/cli-add-workspace-assets.d.ts +6 -63
- package/dist/runtime/cli-add-workspace-assets.js +6 -950
- package/dist/runtime/cli-add-workspace-binding-source-anchors.d.ts +23 -0
- package/dist/runtime/cli-add-workspace-binding-source-anchors.js +112 -0
- package/dist/runtime/cli-add-workspace-binding-source-source-emitters.d.ts +33 -0
- package/dist/runtime/cli-add-workspace-binding-source-source-emitters.js +436 -0
- package/dist/runtime/cli-add-workspace-binding-source-types.d.ts +20 -0
- package/dist/runtime/cli-add-workspace-binding-source-types.js +1 -0
- package/dist/runtime/cli-add-workspace-binding-source.d.ts +40 -0
- package/dist/runtime/cli-add-workspace-binding-source.js +275 -0
- package/dist/runtime/cli-add-workspace-block-style.d.ts +22 -0
- package/dist/runtime/cli-add-workspace-block-style.js +148 -0
- package/dist/runtime/cli-add-workspace-block-transform.d.ts +32 -0
- package/dist/runtime/cli-add-workspace-block-transform.js +197 -0
- package/dist/runtime/cli-add-workspace-contract.js +1 -1
- package/dist/runtime/cli-add-workspace-core-variation.d.ts +20 -0
- package/dist/runtime/cli-add-workspace-core-variation.js +322 -0
- package/dist/runtime/cli-add-workspace-editor-plugin-anchors.d.ts +37 -0
- package/dist/runtime/cli-add-workspace-editor-plugin-anchors.js +206 -0
- package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.d.ts +47 -0
- package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.js +219 -0
- package/dist/runtime/cli-add-workspace-editor-plugin.d.ts +22 -0
- package/dist/runtime/cli-add-workspace-editor-plugin.js +78 -0
- package/dist/runtime/cli-add-workspace-hooked-block.d.ts +23 -0
- package/dist/runtime/cli-add-workspace-hooked-block.js +57 -0
- package/dist/runtime/cli-add-workspace-integration-env-files.d.ts +33 -0
- package/dist/runtime/cli-add-workspace-integration-env-files.js +65 -0
- package/dist/runtime/cli-add-workspace-integration-env-package-json.d.ts +38 -0
- package/dist/runtime/cli-add-workspace-integration-env-package-json.js +122 -0
- package/dist/runtime/cli-add-workspace-integration-env-source-emitters.d.ts +44 -0
- package/dist/runtime/cli-add-workspace-integration-env-source-emitters.js +262 -0
- package/dist/runtime/cli-add-workspace-integration-env.js +5 -345
- package/dist/runtime/cli-add-workspace-pattern-anchors.d.ts +10 -0
- package/dist/runtime/cli-add-workspace-pattern-anchors.js +95 -0
- package/dist/runtime/cli-add-workspace-pattern-options.d.ts +20 -0
- package/dist/runtime/cli-add-workspace-pattern-options.js +113 -0
- package/dist/runtime/cli-add-workspace-pattern-source-emitters.d.ts +20 -0
- package/dist/runtime/cli-add-workspace-pattern-source-emitters.js +57 -0
- package/dist/runtime/cli-add-workspace-pattern.d.ts +42 -0
- package/dist/runtime/cli-add-workspace-pattern.js +99 -0
- package/dist/runtime/cli-add-workspace-post-meta.js +1 -1
- package/dist/runtime/cli-add-workspace-registration-hooks.d.ts +50 -0
- package/dist/runtime/cli-add-workspace-registration-hooks.js +162 -0
- package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +6 -9
- package/dist/runtime/cli-add-workspace-rest-anchors.js +6 -466
- package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.d.ts +17 -0
- package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.js +108 -0
- package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.d.ts +9 -0
- package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.js +142 -0
- package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.d.ts +51 -0
- package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.js +415 -0
- package/dist/runtime/cli-add-workspace-rest-generated.js +5 -3
- package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.d.ts +80 -0
- package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.js +238 -0
- package/dist/runtime/cli-add-workspace-rest-manual.js +3 -16
- package/dist/runtime/cli-add-workspace-rest-php-templates.d.ts +1 -7
- package/dist/runtime/cli-add-workspace-rest-php-templates.js +3 -322
- package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.d.ts +33 -0
- package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.js +145 -0
- package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.d.ts +9 -0
- package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.js +162 -0
- package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.d.ts +7 -0
- package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.js +193 -0
- package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +5 -99
- package/dist/runtime/cli-add-workspace-rest-source-emitters.js +5 -663
- package/dist/runtime/cli-add-workspace-rest-source-utils.d.ts +17 -0
- package/dist/runtime/cli-add-workspace-rest-source-utils.js +50 -0
- package/dist/runtime/cli-add-workspace-rest-sync-script-shared.d.ts +56 -0
- package/dist/runtime/cli-add-workspace-rest-sync-script-shared.js +122 -0
- package/dist/runtime/cli-add-workspace-rest-types.d.ts +3 -3
- package/dist/runtime/cli-add-workspace-variation.d.ts +22 -0
- package/dist/runtime/cli-add-workspace-variation.js +162 -0
- package/dist/runtime/cli-add-workspace.d.ts +42 -107
- package/dist/runtime/cli-add-workspace.js +42 -674
- package/dist/runtime/cli-add.d.ts +3 -3
- package/dist/runtime/cli-add.js +2 -2
- package/dist/runtime/cli-core.d.ts +2 -1
- package/dist/runtime/cli-core.js +1 -1
- package/dist/runtime/cli-doctor-workspace-bindings.js +59 -0
- package/dist/runtime/cli-doctor-workspace-block-addons.js +33 -5
- package/dist/runtime/cli-doctor.d.ts +2 -0
- package/dist/runtime/cli-doctor.js +13 -2
- package/dist/runtime/cli-help.js +6 -4
- package/dist/runtime/index.d.ts +5 -2
- package/dist/runtime/index.js +4 -2
- package/dist/runtime/local-dev-presets.js +2 -1
- package/dist/runtime/package-versions.d.ts +1 -0
- package/dist/runtime/package-versions.js +10 -2
- package/dist/runtime/pattern-catalog.d.ts +122 -0
- package/dist/runtime/pattern-catalog.js +471 -0
- package/dist/runtime/post-meta-binding-fields.d.ts +46 -0
- package/dist/runtime/post-meta-binding-fields.js +135 -0
- package/dist/runtime/typia-llm-json-schema.d.ts +24 -0
- package/dist/runtime/typia-llm-json-schema.js +33 -0
- package/dist/runtime/typia-llm-openapi-constraints.d.ts +20 -0
- package/dist/runtime/typia-llm-openapi-constraints.js +254 -0
- package/dist/runtime/typia-llm-projection.d.ts +25 -0
- package/dist/runtime/typia-llm-projection.js +58 -0
- package/dist/runtime/typia-llm-render.d.ts +21 -0
- package/dist/runtime/typia-llm-render.js +252 -0
- package/dist/runtime/typia-llm-sync.d.ts +10 -0
- package/dist/runtime/typia-llm-sync.js +63 -0
- package/dist/runtime/typia-llm-types.d.ts +197 -0
- package/dist/runtime/typia-llm-types.js +1 -0
- package/dist/runtime/typia-llm.d.ts +9 -255
- package/dist/runtime/typia-llm.js +5 -634
- package/dist/runtime/workspace-inventory-mutations.js +13 -0
- package/dist/runtime/workspace-inventory-section-descriptors.js +9 -1
- package/dist/runtime/workspace-inventory-templates.d.ts +2 -2
- package/dist/runtime/workspace-inventory-templates.js +9 -1
- package/dist/runtime/workspace-inventory-types.d.ts +9 -1
- package/package.json +8 -3
- package/templates/_shared/compound/core/scripts/block-config.ts.mustache +22 -0
- package/templates/_shared/compound/core/scripts/sync-types-to-block-json.ts.mustache +103 -2
- package/templates/_shared/compound/core/src/inner-blocks-templates.ts.mustache +13 -0
- package/templates/_shared/compound/persistence/scripts/block-config.ts.mustache +22 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BuiltInCodeArtifact } from "./built-in-block-code-artifacts.js";
|
|
2
|
+
import type { ScaffoldTemplateVariables } from "./scaffold.js";
|
|
3
|
+
/**
|
|
4
|
+
* Builds the basic family non-TypeScript scaffold artifacts.
|
|
5
|
+
*
|
|
6
|
+
* @param variables Scaffold template variables used to render the artifact set.
|
|
7
|
+
* @returns The SCSS and PHP artifacts owned by the basic template family.
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildBasicArtifacts(variables: ScaffoldTemplateVariables): BuiltInCodeArtifact[];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { renderArtifact } from "./built-in-block-non-ts-render-utils.js";
|
|
2
|
+
const BASIC_STYLE_TEMPLATE = `/**
|
|
3
|
+
* {{title}} Block Styles
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
.{{cssClassName}} {
|
|
7
|
+
padding: 20px;
|
|
8
|
+
border: 1px solid #ddd;
|
|
9
|
+
border-radius: 4px;
|
|
10
|
+
background-color: #fff;
|
|
11
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
12
|
+
|
|
13
|
+
&.is-hidden {
|
|
14
|
+
display: none;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
&__content {
|
|
18
|
+
font-size: 16px;
|
|
19
|
+
line-height: 1.6;
|
|
20
|
+
color: #333;
|
|
21
|
+
|
|
22
|
+
// Alignment styles
|
|
23
|
+
&[data-align="center"] {
|
|
24
|
+
text-align: center;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&[data-align="right"] {
|
|
28
|
+
text-align: right;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&[data-align="justify"] {
|
|
32
|
+
text-align: justify;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Hover state
|
|
37
|
+
&:hover {
|
|
38
|
+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
|
39
|
+
transition: box-shadow 0.2s ease;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
43
|
+
const BASIC_EDITOR_STYLE_TEMPLATE = `/**
|
|
44
|
+
* {{title}} Block Editor Styles
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
.{{cssClassName}} {
|
|
48
|
+
outline: 1px dashed #ddd;
|
|
49
|
+
outline-offset: -1px;
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
const BASIC_RENDER_TEMPLATE = `<?php
|
|
53
|
+
/**
|
|
54
|
+
* Optional server render placeholder for {{title}}.
|
|
55
|
+
*
|
|
56
|
+
* The basic scaffold stays static by default. Keep \`src/save.tsx\` as the
|
|
57
|
+
* canonical frontend output unless you intentionally convert this block into a
|
|
58
|
+
* dynamic render path and add \`render\` to \`block.json\`.
|
|
59
|
+
*
|
|
60
|
+
* @package {{slug}}
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
64
|
+
exit;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
?>
|
|
68
|
+
<div class="{{cssClassName}}__server-placeholder" hidden>
|
|
69
|
+
<?php esc_html_e( 'Server render placeholder.', '{{textDomain}}' ); ?>
|
|
70
|
+
</div>
|
|
71
|
+
`;
|
|
72
|
+
/**
|
|
73
|
+
* Builds the basic family non-TypeScript scaffold artifacts.
|
|
74
|
+
*
|
|
75
|
+
* @param variables Scaffold template variables used to render the artifact set.
|
|
76
|
+
* @returns The SCSS and PHP artifacts owned by the basic template family.
|
|
77
|
+
*/
|
|
78
|
+
export function buildBasicArtifacts(variables) {
|
|
79
|
+
return [
|
|
80
|
+
renderArtifact("src/editor.scss", BASIC_EDITOR_STYLE_TEMPLATE, variables),
|
|
81
|
+
renderArtifact("src/style.scss", BASIC_STYLE_TEMPLATE, variables),
|
|
82
|
+
renderArtifact("src/render.php", BASIC_RENDER_TEMPLATE, variables),
|
|
83
|
+
];
|
|
84
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BuiltInCodeArtifact } from "./built-in-block-code-artifacts.js";
|
|
2
|
+
import type { ScaffoldTemplateVariables } from "./scaffold.js";
|
|
3
|
+
/**
|
|
4
|
+
* Builds the compound family non-TypeScript scaffold artifacts.
|
|
5
|
+
*
|
|
6
|
+
* @param variables Scaffold template variables used to render the artifact set.
|
|
7
|
+
* @returns The compound SCSS and PHP artifacts, including persistence variants when enabled.
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildCompoundArtifacts(variables: ScaffoldTemplateVariables): BuiltInCodeArtifact[];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { buildAlternateRenderEntryArtifact, renderArtifact, toPhpSingleQuotedString, } from "./built-in-block-non-ts-render-utils.js";
|
|
2
|
+
import { COMPOUND_PERSISTENCE_RENDER_TARGETS_TEMPLATE, COMPOUND_PERSISTENCE_RENDER_TEMPLATE, COMPOUND_STYLE_TEMPLATE, } from "./built-in-block-non-ts-compound-templates.js";
|
|
3
|
+
import { getScaffoldAlternateRenderTargets, isCompoundPersistenceEnabled, } from "./scaffold-template-variable-groups.js";
|
|
4
|
+
/**
|
|
5
|
+
* Builds the compound family non-TypeScript scaffold artifacts.
|
|
6
|
+
*
|
|
7
|
+
* @param variables Scaffold template variables used to render the artifact set.
|
|
8
|
+
* @returns The compound SCSS and PHP artifacts, including persistence variants when enabled.
|
|
9
|
+
*/
|
|
10
|
+
export function buildCompoundArtifacts(variables) {
|
|
11
|
+
const alternateRenderTargets = getScaffoldAlternateRenderTargets(variables);
|
|
12
|
+
const artifacts = [
|
|
13
|
+
renderArtifact(`src/blocks/${variables.slugKebabCase}/style.scss`, COMPOUND_STYLE_TEMPLATE, variables),
|
|
14
|
+
];
|
|
15
|
+
if (isCompoundPersistenceEnabled(variables)) {
|
|
16
|
+
const renderView = {
|
|
17
|
+
...variables,
|
|
18
|
+
titlePhpLiteral: toPhpSingleQuotedString(variables.title),
|
|
19
|
+
};
|
|
20
|
+
if (alternateRenderTargets.enabled) {
|
|
21
|
+
artifacts.push(renderArtifact(`src/blocks/${variables.slugKebabCase}/render-targets.php`, COMPOUND_PERSISTENCE_RENDER_TARGETS_TEMPLATE, renderView), buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render.php`, "web", variables));
|
|
22
|
+
if (alternateRenderTargets.hasEmail) {
|
|
23
|
+
artifacts.push(buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render-email.php`, "email", variables));
|
|
24
|
+
}
|
|
25
|
+
if (alternateRenderTargets.hasMjml) {
|
|
26
|
+
artifacts.push(buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render-mjml.php`, "mjml", variables));
|
|
27
|
+
}
|
|
28
|
+
if (alternateRenderTargets.hasPlainText) {
|
|
29
|
+
artifacts.push(buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render-text.php`, "plain-text", variables));
|
|
30
|
+
}
|
|
31
|
+
return artifacts;
|
|
32
|
+
}
|
|
33
|
+
artifacts.push(renderArtifact(`src/blocks/${variables.slugKebabCase}/render.php`, COMPOUND_PERSISTENCE_RENDER_TEMPLATE, renderView));
|
|
34
|
+
}
|
|
35
|
+
return artifacts;
|
|
36
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHP helper template for compound parent alternate render targets.
|
|
3
|
+
*
|
|
4
|
+
* @remarks Consumed by `buildCompoundArtifacts()` for email, MJML,
|
|
5
|
+
* plain-text, and web render entries with block identity, namespace, text
|
|
6
|
+
* domain, storage, policy, CSS class, and title placeholders.
|
|
7
|
+
*/
|
|
8
|
+
export declare const COMPOUND_PERSISTENCE_RENDER_TARGETS_TEMPLATE = "<?php\n/**\n * Alternate render target helpers for the {{title}} compound parent block.\n *\n * @package {{pascalCase}}\n */\n\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n\nif ( ! function_exists( '{{phpPrefix}}_{{slugSnakeCase}}_build_render_context' ) ) {\n\tfunction {{phpPrefix}}_{{slugSnakeCase}}_build_render_context( $attributes, $content, $block ) {\n\t\t$validator_path = __DIR__ . '/typia-validator.php';\n\t\tif ( ! file_exists( $validator_path ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t$validator = require $validator_path;\n\t\tif ( ! is_object( $validator ) || ! method_exists( $validator, 'apply_defaults' ) || ! method_exists( $validator, 'validate' ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t$normalized = $validator->apply_defaults( is_array( $attributes ) ? $attributes : array() );\n\t\t$validation = $validator->validate( $normalized );\n\t\t$resource_key = isset( $normalized['resourceKey'] ) ? (string) $normalized['resourceKey'] : '';\n\t\t$heading = isset( $normalized['heading'] ) ? (string) $normalized['heading'] : {{titlePhpLiteral}};\n\t\t$intro = isset( $normalized['intro'] ) ? (string) $normalized['intro'] : '';\n\t\t$button_label = isset( $normalized['buttonLabel'] ) ? (string) $normalized['buttonLabel'] : 'Persist Count';\n\t\t$show_count = ! empty( $normalized['showCount'] );\n\t\t$show_dividers = ! empty( $normalized['showDividers'] );\n\t\t$post_id = is_object( $block ) && isset( $block->context['postId'] )\n\t\t\t? (int) $block->context['postId']\n\t\t\t: (int) get_queried_object_id();\n\t\t$storage_mode = '{{dataStorageMode}}';\n\t\t$persistence_policy = '{{persistencePolicy}}';\n\n\t\t$notice_message = 'authenticated' === $persistence_policy\n\t\t\t? __( 'Sign in to persist this counter.', '{{textDomain}}' )\n\t\t\t: __( 'Public writes are temporarily unavailable.', '{{textDomain}}' );\n\n\t\tif ( empty( $validation['valid'] ) || '' === $resource_key ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t{{phpPrefix}}_record_rendered_block_instance(\n\t\t\t(int) $post_id,\n\t\t\t'{{namespace}}/{{slugKebabCase}}',\n\t\t\t$resource_key\n\t\t);\n\n\t\t$web_context = array(\n\t\t\t'bootstrapReady' => false,\n\t\t\t'buttonLabel' => $button_label,\n\t\t\t'canWrite' => false,\n\t\t\t'client' => array(\n\t\t\t\t'writeExpiry' => 0,\n\t\t\t\t'writeNonce' => '',\n\t\t\t\t'writeToken' => '',\n\t\t\t),\n\t\t\t'count' => 0,\n\t\t\t'error' => '',\n\t\t\t'isBootstrapping' => false,\n\t\t\t'isLoading' => false,\n\t\t\t'isSaving' => false,\n\t\t\t'persistencePolicy' => $persistence_policy,\n\t\t\t'postId' => (int) $post_id,\n\t\t\t'resourceKey' => $resource_key,\n\t\t\t'showCount' => $show_count,\n\t\t\t'storage' => $storage_mode,\n\t\t);\n\n\t\t$allowed_inner_html = wp_kses_allowed_html( 'post' );\n\n\t\tforeach ( $allowed_inner_html as &$allowed_attributes ) {\n\t\t\tif ( ! is_array( $allowed_attributes ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$allowed_attributes['data-wp-bind--disabled'] = true;\n\t\t\t$allowed_attributes['data-wp-bind--hidden'] = true;\n\t\t\t$allowed_attributes['data-wp-bind--value'] = true;\n\t\t\t$allowed_attributes['data-wp-class'] = true;\n\t\t\t$allowed_attributes['data-wp-class--active'] = true;\n\t\t\t$allowed_attributes['data-wp-context'] = true;\n\t\t\t$allowed_attributes['data-wp-init'] = true;\n\t\t\t$allowed_attributes['data-wp-interactive'] = true;\n\t\t\t$allowed_attributes['data-wp-on--click'] = true;\n\t\t\t$allowed_attributes['data-wp-on--mouseenter'] = true;\n\t\t\t$allowed_attributes['data-wp-on--mouseleave'] = true;\n\t\t\t$allowed_attributes['data-wp-run--mounted'] = true;\n\t\t\t$allowed_attributes['data-wp-style--width'] = true;\n\t\t\t$allowed_attributes['data-wp-text'] = true;\n\t\t}\n\t\tunset( $allowed_attributes );\n\n\t\treturn array(\n\t\t\t'buttonLabel' => $button_label,\n\t\t\t'frontendClassName' => '{{cssClassName}}',\n\t\t\t'heading' => $heading,\n\t\t\t'intro' => $intro,\n\t\t\t'isVisible' => true,\n\t\t\t'normalized' => $normalized,\n\t\t\t'noticeMessage' => $notice_message,\n\t\t\t'postId' => (int) $post_id,\n\t\t\t'resourceKey' => $resource_key,\n\t\t\t'sanitizedContent' => wp_kses( $content, $allowed_inner_html ),\n\t\t\t'showCount' => $show_count,\n\t\t\t'showDividers' => $show_dividers,\n\t\t\t'title' => {{titleJson}},\n\t\t\t'webContext' => $web_context,\n\t\t);\n\t}\n}\n\nif ( ! function_exists( '{{phpPrefix}}_{{slugSnakeCase}}_render_target' ) ) {\n\tfunction {{phpPrefix}}_{{slugSnakeCase}}_render_target( string $target, $attributes, $content = '', $block = null ): string {\n\t\t$context = {{phpPrefix}}_{{slugSnakeCase}}_build_render_context( $attributes, $content, $block );\n\t\tif ( null === $context ) {\n\t\t\treturn '';\n\t\t}\n\n\t\t$target_context = apply_filters(\n\t\t\t'{{phpPrefix}}_{{slugSnakeCase}}_render_target_context',\n\t\t\t$context,\n\t\t\t$target,\n\t\t\t$attributes,\n\t\t\t$block\n\t\t);\n\n\t\t$markup = '';\n\t\tswitch ( $target ) {\n\t\t\tcase 'email':\n\t\t\t\t$parts = array(\n\t\t\t\t\t'<div class=\"' . esc_attr( $target_context['frontendClassName'] ) . '-email\">',\n\t\t\t\t\t'<h3>' . esc_html( $target_context['heading'] ) . '</h3>',\n\t\t\t\t);\n\t\t\t\tif ( '' !== $target_context['intro'] ) {\n\t\t\t\t\t$parts[] = '<p>' . esc_html( $target_context['intro'] ) . '</p>';\n\t\t\t\t}\n\t\t\t\tif ( ! empty( $target_context['showCount'] ) ) {\n\t\t\t\t\t$parts[] = '<p><strong>' . esc_html__( 'Count', '{{textDomain}}' ) . ':</strong> ' . esc_html( (string) $target_context['webContext']['count'] ) . '</p>';\n\t\t\t\t}\n\t\t\t\t$parts[] = wp_kses_post( $target_context['sanitizedContent'] );\n\t\t\t\t$parts[] = '<p>' . esc_html( $target_context['noticeMessage'] ) . '</p>';\n\t\t\t\t$parts[] = '</div>';\n\t\t\t\t$markup = implode( '', $parts );\n\t\t\t\tbreak;\n\t\t\tcase 'mjml':\n\t\t\t\t$markup = '<mjml><mj-body><mj-section><mj-column><mj-text font-weight=\"700\">' . esc_html( $target_context['heading'] ) . '</mj-text>';\n\t\t\t\tif ( '' !== $target_context['intro'] ) {\n\t\t\t\t\t$markup .= '<mj-text>' . esc_html( $target_context['intro'] ) . '</mj-text>';\n\t\t\t\t}\n\t\t\t\tif ( ! empty( $target_context['showCount'] ) ) {\n\t\t\t\t\t$markup .= '<mj-text>' . esc_html__( 'Count', '{{textDomain}}' ) . ': ' . esc_html( (string) $target_context['webContext']['count'] ) . '</mj-text>';\n\t\t\t\t}\n\t\t\t\t$markup .= '<mj-text>' . esc_html( wp_strip_all_tags( $target_context['sanitizedContent'] ) ) . '</mj-text>';\n\t\t\t\t$markup .= '<mj-text>' . esc_html( $target_context['noticeMessage'] ) . '</mj-text></mj-column></mj-section></mj-body></mjml>';\n\t\t\t\tbreak;\n\t\t\tcase 'plain-text':\n\t\t\t\t$markup = implode(\n\t\t\t\t\t\"\\n\",\n\t\t\t\t\tarray_filter(\n\t\t\t\t\t\tarray(\n\t\t\t\t\t\t\t$target_context['heading'],\n\t\t\t\t\t\t\t$target_context['intro'],\n\t\t\t\t\t\t\twp_strip_all_tags( $target_context['sanitizedContent'] ),\n\t\t\t\t\t\t\t! empty( $target_context['showCount'] )\n\t\t\t\t\t\t\t\t? sprintf( '%s: %s', __( 'Count', '{{textDomain}}' ), (string) $target_context['webContext']['count'] )\n\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t$target_context['noticeMessage'],\n\t\t\t\t\t\t),\n\t\t\t\t\t\tstatic fn( $value ) => is_string( $value ) && '' !== $value\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase 'web':\n\t\t\tdefault:\n\t\t\t\t$wrapper_attributes = get_block_wrapper_attributes(\n\t\t\t\t\tarray(\n\t\t\t\t\t\t'class' => '{{cssClassName}}',\n\t\t\t\t\t\t'data-show-dividers' => $target_context['showDividers'] ? 'true' : 'false',\n\t\t\t\t\t\t'data-wp-context' => wp_json_encode( $target_context['webContext'] ),\n\t\t\t\t\t\t'data-wp-init' => 'callbacks.init',\n\t\t\t\t\t\t'data-wp-interactive' => '{{slugKebabCase}}',\n\t\t\t\t\t\t'data-wp-run--mounted' => 'callbacks.mounted',\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t\tob_start();\n\t\t\t\t?>\n<div <?php echo $wrapper_attributes; ?>>\n\t<h3 class=\"{{cssClassName}}__heading\"><?php echo esc_html( $target_context['heading'] ); ?></h3>\n\t<?php if ( '' !== $target_context['intro'] ) : ?>\n\t\t<p class=\"{{cssClassName}}__intro\"><?php echo esc_html( $target_context['intro'] ); ?></p>\n\t<?php endif; ?>\n\t<p\n\t\tclass=\"{{cssClassName}}__notice\"\n\t\tdata-wp-bind--hidden=\"!context.bootstrapReady || context.canWrite\"\n\t\thidden\n\t>\n\t\t<?php echo esc_html( $target_context['noticeMessage'] ); ?>\n\t</p>\n\t<p\n\t\tclass=\"{{cssClassName}}__error\"\n\t\trole=\"status\"\n\t\taria-live=\"polite\"\n\t\taria-atomic=\"true\"\n\t\tdata-wp-bind--hidden=\"!context.error\"\n\t\tdata-wp-text=\"context.error\"\n\t\thidden\n\t></p>\n\t<?php if ( ! empty( $target_context['showCount'] ) ) : ?>\n\t\t<div class=\"{{cssClassName}}__counter\">\n\t\t\t<span\n\t\t\t\tclass=\"{{cssClassName}}__count\"\n\t\t\t\trole=\"status\"\n\t\t\t\taria-live=\"polite\"\n\t\t\t\taria-atomic=\"true\"\n\t\t\t\tdata-wp-text=\"context.count\"\n\t\t\t>0</span>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled\n\t\t\t\tdata-wp-bind--disabled=\"!context.canWrite\"\n\t\t\t\tdata-wp-on--click=\"actions.increment\"\n\t\t\t>\n\t\t\t\t<?php echo esc_html( $target_context['buttonLabel'] ); ?>\n\t\t\t</button>\n\t\t</div>\n\t<?php endif; ?>\n\t<div class=\"{{cssClassName}}__items\">\n\t\t<?php echo wp_kses_post( $target_context['sanitizedContent'] ); ?>\n\t</div>\n</div>\n\t\t\t\t<?php\n\t\t\t\t$markup = (string) ob_get_clean();\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn apply_filters(\n\t\t\t'{{phpPrefix}}_{{slugSnakeCase}}_render_target_markup',\n\t\t\t$markup,\n\t\t\t$target,\n\t\t\t$target_context\n\t\t);\n\t}\n}\n";
|
|
9
|
+
/**
|
|
10
|
+
* SCSS template for compound parent block styles.
|
|
11
|
+
*
|
|
12
|
+
* @remarks Consumed by `buildCompoundArtifacts()` with `{{cssClassName}}`
|
|
13
|
+
* and `{{compoundChildCssClassName}}` scaffold placeholders.
|
|
14
|
+
*/
|
|
15
|
+
export declare const COMPOUND_STYLE_TEMPLATE = ".{{cssClassName}} {\n\tborder: 1px solid #dcdcde;\n\tborder-radius: 12px;\n\tpadding: 1.25rem;\n\tbackground: #fff;\n}\n\n.{{cssClassName}}__heading {\n\tmargin: 0 0 0.5rem;\n\tfont-size: 1.2rem;\n}\n\n.{{cssClassName}}__intro {\n\tmargin: 0 0 1rem;\n\tcolor: #50575e;\n}\n\n.{{cssClassName}}__items {\n\tdisplay: grid;\n\tgap: 0.75rem;\n}\n\n.{{cssClassName}}[data-show-dividers='true'] .{{compoundChildCssClassName}} {\n\tborder-top: 1px solid #dcdcde;\n\tpadding-top: 0.75rem;\n}\n\n.{{cssClassName}}[data-show-dividers='true'] .{{compoundChildCssClassName}}:first-child {\n\tborder-top: 0;\n\tpadding-top: 0;\n}\n";
|
|
16
|
+
/**
|
|
17
|
+
* Main PHP `render.php` template for the compound parent block.
|
|
18
|
+
*
|
|
19
|
+
* @remarks Consumed by `buildCompoundArtifacts()` with scaffold placeholders
|
|
20
|
+
* for block identity, namespace, text domain, storage mode, persistence policy,
|
|
21
|
+
* CSS class names, and PHP-safe title output.
|
|
22
|
+
*/
|
|
23
|
+
export declare const COMPOUND_PERSISTENCE_RENDER_TEMPLATE = "<?php\n/**\n * Dynamic render entry for the {{title}} compound parent block.\n *\n * @package {{pascalCase}}\n */\n\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n\n$validator_path = __DIR__ . '/typia-validator.php';\nif ( ! file_exists( $validator_path ) ) {\n\treturn '';\n}\n\n$validator = require $validator_path;\nif ( ! is_object( $validator ) || ! method_exists( $validator, 'apply_defaults' ) || ! method_exists( $validator, 'validate' ) ) {\n\treturn '';\n}\n\n$normalized = $validator->apply_defaults( is_array( $attributes ) ? $attributes : array() );\n$validation = $validator->validate( $normalized );\n$resource_key = isset( $normalized['resourceKey'] ) ? (string) $normalized['resourceKey'] : '';\n$heading = isset( $normalized['heading'] ) ? (string) $normalized['heading'] : {{titlePhpLiteral}};\n$intro = isset( $normalized['intro'] ) ? (string) $normalized['intro'] : '';\n$button_label = isset( $normalized['buttonLabel'] ) ? (string) $normalized['buttonLabel'] : 'Persist Count';\n$show_count = ! empty( $normalized['showCount'] );\n$show_dividers = ! empty( $normalized['showDividers'] );\n$post_id = is_object( $block ) && isset( $block->context['postId'] )\n\t? (int) $block->context['postId']\n\t: (int) get_queried_object_id();\n$storage_mode = '{{dataStorageMode}}';\n$persistence_policy = '{{persistencePolicy}}';\n\n$notice_message = 'authenticated' === $persistence_policy\n\t? __( 'Sign in to persist this counter.', '{{textDomain}}' )\n\t: __( 'Public writes are temporarily unavailable.', '{{textDomain}}' );\n\nif ( empty( $validation['valid'] ) || '' === $resource_key ) {\n\treturn '';\n}\n\n{{phpPrefix}}_record_rendered_block_instance(\n\t(int) $post_id,\n\t'{{namespace}}/{{slugKebabCase}}',\n\t$resource_key\n);\n\n$context = array(\n\t'bootstrapReady' => false,\n\t'buttonLabel' => $button_label,\n\t'canWrite' => false,\n\t'client' => array(\n\t\t'writeExpiry' => 0,\n\t\t'writeNonce' => '',\n\t\t'writeToken' => '',\n\t),\n\t'count' => 0,\n\t'error' => '',\n\t'isBootstrapping' => false,\n\t'isLoading' => false,\n\t'isSaving' => false,\n\t'persistencePolicy' => $persistence_policy,\n\t'postId' => (int) $post_id,\n\t'resourceKey' => $resource_key,\n\t'showCount' => $show_count,\n\t'storage' => $storage_mode,\n);\n\n$allowed_inner_html = wp_kses_allowed_html( 'post' );\n\nforeach ( $allowed_inner_html as &$allowed_attributes ) {\n\tif ( ! is_array( $allowed_attributes ) ) {\n\t\tcontinue;\n\t}\n\n\t$allowed_attributes['data-wp-bind--disabled'] = true;\n\t$allowed_attributes['data-wp-bind--hidden'] = true;\n\t$allowed_attributes['data-wp-bind--value'] = true;\n\t$allowed_attributes['data-wp-class'] = true;\n\t$allowed_attributes['data-wp-class--active'] = true;\n\t$allowed_attributes['data-wp-context'] = true;\n\t$allowed_attributes['data-wp-init'] = true;\n\t$allowed_attributes['data-wp-interactive'] = true;\n\t$allowed_attributes['data-wp-on--click'] = true;\n\t$allowed_attributes['data-wp-on--mouseenter'] = true;\n\t$allowed_attributes['data-wp-on--mouseleave'] = true;\n\t$allowed_attributes['data-wp-run--mounted'] = true;\n\t$allowed_attributes['data-wp-style--width'] = true;\n\t$allowed_attributes['data-wp-text'] = true;\n}\nunset( $allowed_attributes );\n\n$sanitized_content = wp_kses( $content, $allowed_inner_html );\n\n$wrapper_attributes = get_block_wrapper_attributes(\n\tarray(\n\t\t'class' => '{{cssClassName}}',\n\t\t'data-show-dividers' => $show_dividers ? 'true' : 'false',\n\t\t'data-wp-context' => wp_json_encode( $context ),\n\t\t'data-wp-init' => 'callbacks.init',\n\t\t'data-wp-interactive' => '{{slugKebabCase}}',\n\t\t'data-wp-run--mounted' => 'callbacks.mounted',\n\t)\n);\n?>\n\n<div <?php echo $wrapper_attributes; ?>>\n\t<h3 class=\"{{cssClassName}}__heading\"><?php echo esc_html( $heading ); ?></h3>\n\t<?php if ( '' !== $intro ) : ?>\n\t\t<p class=\"{{cssClassName}}__intro\"><?php echo esc_html( $intro ); ?></p>\n\t<?php endif; ?>\n\t<p\n\t\tclass=\"{{cssClassName}}__notice\"\n\t\tdata-wp-bind--hidden=\"!context.bootstrapReady || context.canWrite\"\n\t\thidden\n\t>\n\t\t<?php echo esc_html( $notice_message ); ?>\n\t</p>\n\t<p\n\t\tclass=\"{{cssClassName}}__error\"\n\t\trole=\"status\"\n\t\taria-live=\"polite\"\n\t\taria-atomic=\"true\"\n\t\tdata-wp-bind--hidden=\"!context.error\"\n\t\tdata-wp-text=\"context.error\"\n\t\thidden\n\t></p>\n\t<?php if ( $show_count ) : ?>\n\t\t<div class=\"{{cssClassName}}__counter\">\n\t\t\t<span\n\t\t\t\tclass=\"{{cssClassName}}__count\"\n\t\t\t\trole=\"status\"\n\t\t\t\taria-live=\"polite\"\n\t\t\t\taria-atomic=\"true\"\n\t\t\t\tdata-wp-text=\"context.count\"\n\t\t\t>0</span>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled\n\t\t\t\tdata-wp-bind--disabled=\"!context.canWrite\"\n\t\t\t\tdata-wp-on--click=\"actions.increment\"\n\t\t\t>\n\t\t\t\t<?php echo esc_html( $button_label ); ?>\n\t\t\t</button>\n\t\t</div>\n\t<?php endif; ?>\n\t<div class=\"{{cssClassName}}__items\">\n\t\t<?php echo $sanitized_content; ?>\n\t</div>\n</div>\n";
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHP helper template for compound parent alternate render targets.
|
|
3
|
+
*
|
|
4
|
+
* @remarks Consumed by `buildCompoundArtifacts()` for email, MJML,
|
|
5
|
+
* plain-text, and web render entries with block identity, namespace, text
|
|
6
|
+
* domain, storage, policy, CSS class, and title placeholders.
|
|
7
|
+
*/
|
|
8
|
+
export const COMPOUND_PERSISTENCE_RENDER_TARGETS_TEMPLATE = `<?php
|
|
9
|
+
/**
|
|
10
|
+
* Alternate render target helpers for the {{title}} compound parent block.
|
|
11
|
+
*
|
|
12
|
+
* @package {{pascalCase}}
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
16
|
+
exit;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if ( ! function_exists( '{{phpPrefix}}_{{slugSnakeCase}}_build_render_context' ) ) {
|
|
20
|
+
function {{phpPrefix}}_{{slugSnakeCase}}_build_render_context( $attributes, $content, $block ) {
|
|
21
|
+
$validator_path = __DIR__ . '/typia-validator.php';
|
|
22
|
+
if ( ! file_exists( $validator_path ) ) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
$validator = require $validator_path;
|
|
27
|
+
if ( ! is_object( $validator ) || ! method_exists( $validator, 'apply_defaults' ) || ! method_exists( $validator, 'validate' ) ) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
$normalized = $validator->apply_defaults( is_array( $attributes ) ? $attributes : array() );
|
|
32
|
+
$validation = $validator->validate( $normalized );
|
|
33
|
+
$resource_key = isset( $normalized['resourceKey'] ) ? (string) $normalized['resourceKey'] : '';
|
|
34
|
+
$heading = isset( $normalized['heading'] ) ? (string) $normalized['heading'] : {{titlePhpLiteral}};
|
|
35
|
+
$intro = isset( $normalized['intro'] ) ? (string) $normalized['intro'] : '';
|
|
36
|
+
$button_label = isset( $normalized['buttonLabel'] ) ? (string) $normalized['buttonLabel'] : 'Persist Count';
|
|
37
|
+
$show_count = ! empty( $normalized['showCount'] );
|
|
38
|
+
$show_dividers = ! empty( $normalized['showDividers'] );
|
|
39
|
+
$post_id = is_object( $block ) && isset( $block->context['postId'] )
|
|
40
|
+
? (int) $block->context['postId']
|
|
41
|
+
: (int) get_queried_object_id();
|
|
42
|
+
$storage_mode = '{{dataStorageMode}}';
|
|
43
|
+
$persistence_policy = '{{persistencePolicy}}';
|
|
44
|
+
|
|
45
|
+
$notice_message = 'authenticated' === $persistence_policy
|
|
46
|
+
? __( 'Sign in to persist this counter.', '{{textDomain}}' )
|
|
47
|
+
: __( 'Public writes are temporarily unavailable.', '{{textDomain}}' );
|
|
48
|
+
|
|
49
|
+
if ( empty( $validation['valid'] ) || '' === $resource_key ) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
{{phpPrefix}}_record_rendered_block_instance(
|
|
54
|
+
(int) $post_id,
|
|
55
|
+
'{{namespace}}/{{slugKebabCase}}',
|
|
56
|
+
$resource_key
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
$web_context = array(
|
|
60
|
+
'bootstrapReady' => false,
|
|
61
|
+
'buttonLabel' => $button_label,
|
|
62
|
+
'canWrite' => false,
|
|
63
|
+
'client' => array(
|
|
64
|
+
'writeExpiry' => 0,
|
|
65
|
+
'writeNonce' => '',
|
|
66
|
+
'writeToken' => '',
|
|
67
|
+
),
|
|
68
|
+
'count' => 0,
|
|
69
|
+
'error' => '',
|
|
70
|
+
'isBootstrapping' => false,
|
|
71
|
+
'isLoading' => false,
|
|
72
|
+
'isSaving' => false,
|
|
73
|
+
'persistencePolicy' => $persistence_policy,
|
|
74
|
+
'postId' => (int) $post_id,
|
|
75
|
+
'resourceKey' => $resource_key,
|
|
76
|
+
'showCount' => $show_count,
|
|
77
|
+
'storage' => $storage_mode,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
$allowed_inner_html = wp_kses_allowed_html( 'post' );
|
|
81
|
+
|
|
82
|
+
foreach ( $allowed_inner_html as &$allowed_attributes ) {
|
|
83
|
+
if ( ! is_array( $allowed_attributes ) ) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
$allowed_attributes['data-wp-bind--disabled'] = true;
|
|
88
|
+
$allowed_attributes['data-wp-bind--hidden'] = true;
|
|
89
|
+
$allowed_attributes['data-wp-bind--value'] = true;
|
|
90
|
+
$allowed_attributes['data-wp-class'] = true;
|
|
91
|
+
$allowed_attributes['data-wp-class--active'] = true;
|
|
92
|
+
$allowed_attributes['data-wp-context'] = true;
|
|
93
|
+
$allowed_attributes['data-wp-init'] = true;
|
|
94
|
+
$allowed_attributes['data-wp-interactive'] = true;
|
|
95
|
+
$allowed_attributes['data-wp-on--click'] = true;
|
|
96
|
+
$allowed_attributes['data-wp-on--mouseenter'] = true;
|
|
97
|
+
$allowed_attributes['data-wp-on--mouseleave'] = true;
|
|
98
|
+
$allowed_attributes['data-wp-run--mounted'] = true;
|
|
99
|
+
$allowed_attributes['data-wp-style--width'] = true;
|
|
100
|
+
$allowed_attributes['data-wp-text'] = true;
|
|
101
|
+
}
|
|
102
|
+
unset( $allowed_attributes );
|
|
103
|
+
|
|
104
|
+
return array(
|
|
105
|
+
'buttonLabel' => $button_label,
|
|
106
|
+
'frontendClassName' => '{{cssClassName}}',
|
|
107
|
+
'heading' => $heading,
|
|
108
|
+
'intro' => $intro,
|
|
109
|
+
'isVisible' => true,
|
|
110
|
+
'normalized' => $normalized,
|
|
111
|
+
'noticeMessage' => $notice_message,
|
|
112
|
+
'postId' => (int) $post_id,
|
|
113
|
+
'resourceKey' => $resource_key,
|
|
114
|
+
'sanitizedContent' => wp_kses( $content, $allowed_inner_html ),
|
|
115
|
+
'showCount' => $show_count,
|
|
116
|
+
'showDividers' => $show_dividers,
|
|
117
|
+
'title' => {{titleJson}},
|
|
118
|
+
'webContext' => $web_context,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if ( ! function_exists( '{{phpPrefix}}_{{slugSnakeCase}}_render_target' ) ) {
|
|
124
|
+
function {{phpPrefix}}_{{slugSnakeCase}}_render_target( string $target, $attributes, $content = '', $block = null ): string {
|
|
125
|
+
$context = {{phpPrefix}}_{{slugSnakeCase}}_build_render_context( $attributes, $content, $block );
|
|
126
|
+
if ( null === $context ) {
|
|
127
|
+
return '';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
$target_context = apply_filters(
|
|
131
|
+
'{{phpPrefix}}_{{slugSnakeCase}}_render_target_context',
|
|
132
|
+
$context,
|
|
133
|
+
$target,
|
|
134
|
+
$attributes,
|
|
135
|
+
$block
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
$markup = '';
|
|
139
|
+
switch ( $target ) {
|
|
140
|
+
case 'email':
|
|
141
|
+
$parts = array(
|
|
142
|
+
'<div class="' . esc_attr( $target_context['frontendClassName'] ) . '-email">',
|
|
143
|
+
'<h3>' . esc_html( $target_context['heading'] ) . '</h3>',
|
|
144
|
+
);
|
|
145
|
+
if ( '' !== $target_context['intro'] ) {
|
|
146
|
+
$parts[] = '<p>' . esc_html( $target_context['intro'] ) . '</p>';
|
|
147
|
+
}
|
|
148
|
+
if ( ! empty( $target_context['showCount'] ) ) {
|
|
149
|
+
$parts[] = '<p><strong>' . esc_html__( 'Count', '{{textDomain}}' ) . ':</strong> ' . esc_html( (string) $target_context['webContext']['count'] ) . '</p>';
|
|
150
|
+
}
|
|
151
|
+
$parts[] = wp_kses_post( $target_context['sanitizedContent'] );
|
|
152
|
+
$parts[] = '<p>' . esc_html( $target_context['noticeMessage'] ) . '</p>';
|
|
153
|
+
$parts[] = '</div>';
|
|
154
|
+
$markup = implode( '', $parts );
|
|
155
|
+
break;
|
|
156
|
+
case 'mjml':
|
|
157
|
+
$markup = '<mjml><mj-body><mj-section><mj-column><mj-text font-weight="700">' . esc_html( $target_context['heading'] ) . '</mj-text>';
|
|
158
|
+
if ( '' !== $target_context['intro'] ) {
|
|
159
|
+
$markup .= '<mj-text>' . esc_html( $target_context['intro'] ) . '</mj-text>';
|
|
160
|
+
}
|
|
161
|
+
if ( ! empty( $target_context['showCount'] ) ) {
|
|
162
|
+
$markup .= '<mj-text>' . esc_html__( 'Count', '{{textDomain}}' ) . ': ' . esc_html( (string) $target_context['webContext']['count'] ) . '</mj-text>';
|
|
163
|
+
}
|
|
164
|
+
$markup .= '<mj-text>' . esc_html( wp_strip_all_tags( $target_context['sanitizedContent'] ) ) . '</mj-text>';
|
|
165
|
+
$markup .= '<mj-text>' . esc_html( $target_context['noticeMessage'] ) . '</mj-text></mj-column></mj-section></mj-body></mjml>';
|
|
166
|
+
break;
|
|
167
|
+
case 'plain-text':
|
|
168
|
+
$markup = implode(
|
|
169
|
+
"\\n",
|
|
170
|
+
array_filter(
|
|
171
|
+
array(
|
|
172
|
+
$target_context['heading'],
|
|
173
|
+
$target_context['intro'],
|
|
174
|
+
wp_strip_all_tags( $target_context['sanitizedContent'] ),
|
|
175
|
+
! empty( $target_context['showCount'] )
|
|
176
|
+
? sprintf( '%s: %s', __( 'Count', '{{textDomain}}' ), (string) $target_context['webContext']['count'] )
|
|
177
|
+
: null,
|
|
178
|
+
$target_context['noticeMessage'],
|
|
179
|
+
),
|
|
180
|
+
static fn( $value ) => is_string( $value ) && '' !== $value
|
|
181
|
+
)
|
|
182
|
+
);
|
|
183
|
+
break;
|
|
184
|
+
case 'web':
|
|
185
|
+
default:
|
|
186
|
+
$wrapper_attributes = get_block_wrapper_attributes(
|
|
187
|
+
array(
|
|
188
|
+
'class' => '{{cssClassName}}',
|
|
189
|
+
'data-show-dividers' => $target_context['showDividers'] ? 'true' : 'false',
|
|
190
|
+
'data-wp-context' => wp_json_encode( $target_context['webContext'] ),
|
|
191
|
+
'data-wp-init' => 'callbacks.init',
|
|
192
|
+
'data-wp-interactive' => '{{slugKebabCase}}',
|
|
193
|
+
'data-wp-run--mounted' => 'callbacks.mounted',
|
|
194
|
+
)
|
|
195
|
+
);
|
|
196
|
+
ob_start();
|
|
197
|
+
?>
|
|
198
|
+
<div <?php echo $wrapper_attributes; ?>>
|
|
199
|
+
<h3 class="{{cssClassName}}__heading"><?php echo esc_html( $target_context['heading'] ); ?></h3>
|
|
200
|
+
<?php if ( '' !== $target_context['intro'] ) : ?>
|
|
201
|
+
<p class="{{cssClassName}}__intro"><?php echo esc_html( $target_context['intro'] ); ?></p>
|
|
202
|
+
<?php endif; ?>
|
|
203
|
+
<p
|
|
204
|
+
class="{{cssClassName}}__notice"
|
|
205
|
+
data-wp-bind--hidden="!context.bootstrapReady || context.canWrite"
|
|
206
|
+
hidden
|
|
207
|
+
>
|
|
208
|
+
<?php echo esc_html( $target_context['noticeMessage'] ); ?>
|
|
209
|
+
</p>
|
|
210
|
+
<p
|
|
211
|
+
class="{{cssClassName}}__error"
|
|
212
|
+
role="status"
|
|
213
|
+
aria-live="polite"
|
|
214
|
+
aria-atomic="true"
|
|
215
|
+
data-wp-bind--hidden="!context.error"
|
|
216
|
+
data-wp-text="context.error"
|
|
217
|
+
hidden
|
|
218
|
+
></p>
|
|
219
|
+
<?php if ( ! empty( $target_context['showCount'] ) ) : ?>
|
|
220
|
+
<div class="{{cssClassName}}__counter">
|
|
221
|
+
<span
|
|
222
|
+
class="{{cssClassName}}__count"
|
|
223
|
+
role="status"
|
|
224
|
+
aria-live="polite"
|
|
225
|
+
aria-atomic="true"
|
|
226
|
+
data-wp-text="context.count"
|
|
227
|
+
>0</span>
|
|
228
|
+
<button
|
|
229
|
+
type="button"
|
|
230
|
+
disabled
|
|
231
|
+
data-wp-bind--disabled="!context.canWrite"
|
|
232
|
+
data-wp-on--click="actions.increment"
|
|
233
|
+
>
|
|
234
|
+
<?php echo esc_html( $target_context['buttonLabel'] ); ?>
|
|
235
|
+
</button>
|
|
236
|
+
</div>
|
|
237
|
+
<?php endif; ?>
|
|
238
|
+
<div class="{{cssClassName}}__items">
|
|
239
|
+
<?php echo wp_kses_post( $target_context['sanitizedContent'] ); ?>
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
<?php
|
|
243
|
+
$markup = (string) ob_get_clean();
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return apply_filters(
|
|
248
|
+
'{{phpPrefix}}_{{slugSnakeCase}}_render_target_markup',
|
|
249
|
+
$markup,
|
|
250
|
+
$target,
|
|
251
|
+
$target_context
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
`;
|
|
256
|
+
/**
|
|
257
|
+
* SCSS template for compound parent block styles.
|
|
258
|
+
*
|
|
259
|
+
* @remarks Consumed by `buildCompoundArtifacts()` with `{{cssClassName}}`
|
|
260
|
+
* and `{{compoundChildCssClassName}}` scaffold placeholders.
|
|
261
|
+
*/
|
|
262
|
+
export const COMPOUND_STYLE_TEMPLATE = `.{{cssClassName}} {
|
|
263
|
+
border: 1px solid #dcdcde;
|
|
264
|
+
border-radius: 12px;
|
|
265
|
+
padding: 1.25rem;
|
|
266
|
+
background: #fff;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.{{cssClassName}}__heading {
|
|
270
|
+
margin: 0 0 0.5rem;
|
|
271
|
+
font-size: 1.2rem;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.{{cssClassName}}__intro {
|
|
275
|
+
margin: 0 0 1rem;
|
|
276
|
+
color: #50575e;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.{{cssClassName}}__items {
|
|
280
|
+
display: grid;
|
|
281
|
+
gap: 0.75rem;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.{{cssClassName}}[data-show-dividers='true'] .{{compoundChildCssClassName}} {
|
|
285
|
+
border-top: 1px solid #dcdcde;
|
|
286
|
+
padding-top: 0.75rem;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.{{cssClassName}}[data-show-dividers='true'] .{{compoundChildCssClassName}}:first-child {
|
|
290
|
+
border-top: 0;
|
|
291
|
+
padding-top: 0;
|
|
292
|
+
}
|
|
293
|
+
`;
|
|
294
|
+
/**
|
|
295
|
+
* Main PHP `render.php` template for the compound parent block.
|
|
296
|
+
*
|
|
297
|
+
* @remarks Consumed by `buildCompoundArtifacts()` with scaffold placeholders
|
|
298
|
+
* for block identity, namespace, text domain, storage mode, persistence policy,
|
|
299
|
+
* CSS class names, and PHP-safe title output.
|
|
300
|
+
*/
|
|
301
|
+
export const COMPOUND_PERSISTENCE_RENDER_TEMPLATE = `<?php
|
|
302
|
+
/**
|
|
303
|
+
* Dynamic render entry for the {{title}} compound parent block.
|
|
304
|
+
*
|
|
305
|
+
* @package {{pascalCase}}
|
|
306
|
+
*/
|
|
307
|
+
|
|
308
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
309
|
+
exit;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
$validator_path = __DIR__ . '/typia-validator.php';
|
|
313
|
+
if ( ! file_exists( $validator_path ) ) {
|
|
314
|
+
return '';
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
$validator = require $validator_path;
|
|
318
|
+
if ( ! is_object( $validator ) || ! method_exists( $validator, 'apply_defaults' ) || ! method_exists( $validator, 'validate' ) ) {
|
|
319
|
+
return '';
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
$normalized = $validator->apply_defaults( is_array( $attributes ) ? $attributes : array() );
|
|
323
|
+
$validation = $validator->validate( $normalized );
|
|
324
|
+
$resource_key = isset( $normalized['resourceKey'] ) ? (string) $normalized['resourceKey'] : '';
|
|
325
|
+
$heading = isset( $normalized['heading'] ) ? (string) $normalized['heading'] : {{titlePhpLiteral}};
|
|
326
|
+
$intro = isset( $normalized['intro'] ) ? (string) $normalized['intro'] : '';
|
|
327
|
+
$button_label = isset( $normalized['buttonLabel'] ) ? (string) $normalized['buttonLabel'] : 'Persist Count';
|
|
328
|
+
$show_count = ! empty( $normalized['showCount'] );
|
|
329
|
+
$show_dividers = ! empty( $normalized['showDividers'] );
|
|
330
|
+
$post_id = is_object( $block ) && isset( $block->context['postId'] )
|
|
331
|
+
? (int) $block->context['postId']
|
|
332
|
+
: (int) get_queried_object_id();
|
|
333
|
+
$storage_mode = '{{dataStorageMode}}';
|
|
334
|
+
$persistence_policy = '{{persistencePolicy}}';
|
|
335
|
+
|
|
336
|
+
$notice_message = 'authenticated' === $persistence_policy
|
|
337
|
+
? __( 'Sign in to persist this counter.', '{{textDomain}}' )
|
|
338
|
+
: __( 'Public writes are temporarily unavailable.', '{{textDomain}}' );
|
|
339
|
+
|
|
340
|
+
if ( empty( $validation['valid'] ) || '' === $resource_key ) {
|
|
341
|
+
return '';
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
{{phpPrefix}}_record_rendered_block_instance(
|
|
345
|
+
(int) $post_id,
|
|
346
|
+
'{{namespace}}/{{slugKebabCase}}',
|
|
347
|
+
$resource_key
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
$context = array(
|
|
351
|
+
'bootstrapReady' => false,
|
|
352
|
+
'buttonLabel' => $button_label,
|
|
353
|
+
'canWrite' => false,
|
|
354
|
+
'client' => array(
|
|
355
|
+
'writeExpiry' => 0,
|
|
356
|
+
'writeNonce' => '',
|
|
357
|
+
'writeToken' => '',
|
|
358
|
+
),
|
|
359
|
+
'count' => 0,
|
|
360
|
+
'error' => '',
|
|
361
|
+
'isBootstrapping' => false,
|
|
362
|
+
'isLoading' => false,
|
|
363
|
+
'isSaving' => false,
|
|
364
|
+
'persistencePolicy' => $persistence_policy,
|
|
365
|
+
'postId' => (int) $post_id,
|
|
366
|
+
'resourceKey' => $resource_key,
|
|
367
|
+
'showCount' => $show_count,
|
|
368
|
+
'storage' => $storage_mode,
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
$allowed_inner_html = wp_kses_allowed_html( 'post' );
|
|
372
|
+
|
|
373
|
+
foreach ( $allowed_inner_html as &$allowed_attributes ) {
|
|
374
|
+
if ( ! is_array( $allowed_attributes ) ) {
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
$allowed_attributes['data-wp-bind--disabled'] = true;
|
|
379
|
+
$allowed_attributes['data-wp-bind--hidden'] = true;
|
|
380
|
+
$allowed_attributes['data-wp-bind--value'] = true;
|
|
381
|
+
$allowed_attributes['data-wp-class'] = true;
|
|
382
|
+
$allowed_attributes['data-wp-class--active'] = true;
|
|
383
|
+
$allowed_attributes['data-wp-context'] = true;
|
|
384
|
+
$allowed_attributes['data-wp-init'] = true;
|
|
385
|
+
$allowed_attributes['data-wp-interactive'] = true;
|
|
386
|
+
$allowed_attributes['data-wp-on--click'] = true;
|
|
387
|
+
$allowed_attributes['data-wp-on--mouseenter'] = true;
|
|
388
|
+
$allowed_attributes['data-wp-on--mouseleave'] = true;
|
|
389
|
+
$allowed_attributes['data-wp-run--mounted'] = true;
|
|
390
|
+
$allowed_attributes['data-wp-style--width'] = true;
|
|
391
|
+
$allowed_attributes['data-wp-text'] = true;
|
|
392
|
+
}
|
|
393
|
+
unset( $allowed_attributes );
|
|
394
|
+
|
|
395
|
+
$sanitized_content = wp_kses( $content, $allowed_inner_html );
|
|
396
|
+
|
|
397
|
+
$wrapper_attributes = get_block_wrapper_attributes(
|
|
398
|
+
array(
|
|
399
|
+
'class' => '{{cssClassName}}',
|
|
400
|
+
'data-show-dividers' => $show_dividers ? 'true' : 'false',
|
|
401
|
+
'data-wp-context' => wp_json_encode( $context ),
|
|
402
|
+
'data-wp-init' => 'callbacks.init',
|
|
403
|
+
'data-wp-interactive' => '{{slugKebabCase}}',
|
|
404
|
+
'data-wp-run--mounted' => 'callbacks.mounted',
|
|
405
|
+
)
|
|
406
|
+
);
|
|
407
|
+
?>
|
|
408
|
+
|
|
409
|
+
<div <?php echo $wrapper_attributes; ?>>
|
|
410
|
+
<h3 class="{{cssClassName}}__heading"><?php echo esc_html( $heading ); ?></h3>
|
|
411
|
+
<?php if ( '' !== $intro ) : ?>
|
|
412
|
+
<p class="{{cssClassName}}__intro"><?php echo esc_html( $intro ); ?></p>
|
|
413
|
+
<?php endif; ?>
|
|
414
|
+
<p
|
|
415
|
+
class="{{cssClassName}}__notice"
|
|
416
|
+
data-wp-bind--hidden="!context.bootstrapReady || context.canWrite"
|
|
417
|
+
hidden
|
|
418
|
+
>
|
|
419
|
+
<?php echo esc_html( $notice_message ); ?>
|
|
420
|
+
</p>
|
|
421
|
+
<p
|
|
422
|
+
class="{{cssClassName}}__error"
|
|
423
|
+
role="status"
|
|
424
|
+
aria-live="polite"
|
|
425
|
+
aria-atomic="true"
|
|
426
|
+
data-wp-bind--hidden="!context.error"
|
|
427
|
+
data-wp-text="context.error"
|
|
428
|
+
hidden
|
|
429
|
+
></p>
|
|
430
|
+
<?php if ( $show_count ) : ?>
|
|
431
|
+
<div class="{{cssClassName}}__counter">
|
|
432
|
+
<span
|
|
433
|
+
class="{{cssClassName}}__count"
|
|
434
|
+
role="status"
|
|
435
|
+
aria-live="polite"
|
|
436
|
+
aria-atomic="true"
|
|
437
|
+
data-wp-text="context.count"
|
|
438
|
+
>0</span>
|
|
439
|
+
<button
|
|
440
|
+
type="button"
|
|
441
|
+
disabled
|
|
442
|
+
data-wp-bind--disabled="!context.canWrite"
|
|
443
|
+
data-wp-on--click="actions.increment"
|
|
444
|
+
>
|
|
445
|
+
<?php echo esc_html( $button_label ); ?>
|
|
446
|
+
</button>
|
|
447
|
+
</div>
|
|
448
|
+
<?php endif; ?>
|
|
449
|
+
<div class="{{cssClassName}}__items">
|
|
450
|
+
<?php echo $sanitized_content; ?>
|
|
451
|
+
</div>
|
|
452
|
+
</div>
|
|
453
|
+
`;
|