@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,23 @@
|
|
|
1
|
+
import type { WorkspaceProject } from "./workspace-project.js";
|
|
2
|
+
/**
|
|
3
|
+
* Ensure the workspace bootstrap loads binding-source PHP and editor bundles.
|
|
4
|
+
*
|
|
5
|
+
* @param workspace Official workspace metadata used to locate and patch the bootstrap file.
|
|
6
|
+
* @returns A promise that resolves after the bootstrap anchors are present.
|
|
7
|
+
*/
|
|
8
|
+
export declare function ensureBindingSourceBootstrapAnchors(workspace: WorkspaceProject): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the binding-source editor registry path, preferring existing TypeScript or JavaScript registries.
|
|
11
|
+
*
|
|
12
|
+
* @param projectDir Workspace root directory to inspect.
|
|
13
|
+
* @returns A promise for the registry path to read or write.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveBindingSourceRegistryPath(projectDir: string): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Rewrite the binding-source editor registry with the requested source slug included.
|
|
18
|
+
*
|
|
19
|
+
* @param projectDir Workspace root directory that owns `src/bindings`.
|
|
20
|
+
* @param bindingSourceSlug Binding source slug that must be imported by the registry.
|
|
21
|
+
* @returns A promise that resolves after the registry has been written.
|
|
22
|
+
*/
|
|
23
|
+
export declare function writeBindingSourceRegistry(projectDir: string, bindingSourceSlug: string): Promise<void>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { promises as fsp } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
|
|
4
|
+
import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
|
|
5
|
+
import { pathExists } from "./fs-async.js";
|
|
6
|
+
import { hasPhpFunctionDefinition } from "./php-utils.js";
|
|
7
|
+
const BINDING_SOURCE_SERVER_GLOB = "/src/bindings/*/server.php";
|
|
8
|
+
const BINDING_SOURCE_EDITOR_SCRIPT = "build/bindings/index.js";
|
|
9
|
+
const BINDING_SOURCE_EDITOR_ASSET = "build/bindings/index.asset.php";
|
|
10
|
+
function buildBindingSourceIndexSource(bindingSourceSlugs) {
|
|
11
|
+
const importLines = bindingSourceSlugs
|
|
12
|
+
.map((bindingSourceSlug) => `import './${bindingSourceSlug}/editor';`)
|
|
13
|
+
.join("\n");
|
|
14
|
+
return `${importLines}${importLines ? "\n\n" : ""}// wp-typia add binding-source entries\n`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Ensure the workspace bootstrap loads binding-source PHP and editor bundles.
|
|
18
|
+
*
|
|
19
|
+
* @param workspace Official workspace metadata used to locate and patch the bootstrap file.
|
|
20
|
+
* @returns A promise that resolves after the bootstrap anchors are present.
|
|
21
|
+
*/
|
|
22
|
+
export async function ensureBindingSourceBootstrapAnchors(workspace) {
|
|
23
|
+
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
24
|
+
await patchFile(bootstrapPath, (source) => {
|
|
25
|
+
let nextSource = source;
|
|
26
|
+
const workspaceBaseName = workspace.packageName.split("/").pop() ?? workspace.packageName;
|
|
27
|
+
const bindingRegistrationFunctionName = `${workspace.workspace.phpPrefix}_register_binding_sources`;
|
|
28
|
+
const bindingEditorEnqueueFunctionName = `${workspace.workspace.phpPrefix}_enqueue_binding_sources_editor`;
|
|
29
|
+
const bindingRegistrationHook = `add_action( 'init', '${bindingRegistrationFunctionName}', 20 );`;
|
|
30
|
+
const bindingEditorEnqueueHook = `add_action( 'enqueue_block_editor_assets', '${bindingEditorEnqueueFunctionName}' );`;
|
|
31
|
+
const bindingRegistrationFunction = `
|
|
32
|
+
|
|
33
|
+
function ${bindingRegistrationFunctionName}() {
|
|
34
|
+
\tforeach ( glob( __DIR__ . '${BINDING_SOURCE_SERVER_GLOB}' ) ?: array() as $binding_source_module ) {
|
|
35
|
+
\t\trequire_once $binding_source_module;
|
|
36
|
+
\t}
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
const bindingEditorEnqueueFunction = `
|
|
40
|
+
|
|
41
|
+
function ${bindingEditorEnqueueFunctionName}() {
|
|
42
|
+
\t$script_path = __DIR__ . '/${BINDING_SOURCE_EDITOR_SCRIPT}';
|
|
43
|
+
\t$asset_path = __DIR__ . '/${BINDING_SOURCE_EDITOR_ASSET}';
|
|
44
|
+
|
|
45
|
+
\tif ( ! file_exists( $script_path ) || ! file_exists( $asset_path ) ) {
|
|
46
|
+
\t\treturn;
|
|
47
|
+
\t}
|
|
48
|
+
|
|
49
|
+
\t$asset = require $asset_path;
|
|
50
|
+
\tif ( ! is_array( $asset ) ) {
|
|
51
|
+
\t\t$asset = array();
|
|
52
|
+
\t}
|
|
53
|
+
|
|
54
|
+
\twp_enqueue_script(
|
|
55
|
+
\t\t'${workspaceBaseName}-binding-sources',
|
|
56
|
+
\t\tplugins_url( '${BINDING_SOURCE_EDITOR_SCRIPT}', __FILE__ ),
|
|
57
|
+
\t\tisset( $asset['dependencies'] ) && is_array( $asset['dependencies'] ) ? $asset['dependencies'] : array(),
|
|
58
|
+
\t\tisset( $asset['version'] ) ? $asset['version'] : filemtime( $script_path ),
|
|
59
|
+
\t\ttrue
|
|
60
|
+
\t);
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
if (!hasPhpFunctionDefinition(nextSource, bindingRegistrationFunctionName)) {
|
|
64
|
+
nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, bindingRegistrationFunction);
|
|
65
|
+
}
|
|
66
|
+
if (!hasPhpFunctionDefinition(nextSource, bindingEditorEnqueueFunctionName)) {
|
|
67
|
+
nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, bindingEditorEnqueueFunction);
|
|
68
|
+
}
|
|
69
|
+
if (!nextSource.includes(bindingRegistrationHook)) {
|
|
70
|
+
nextSource = appendPhpSnippetBeforeClosingTag(nextSource, bindingRegistrationHook);
|
|
71
|
+
}
|
|
72
|
+
if (!nextSource.includes(bindingEditorEnqueueHook)) {
|
|
73
|
+
nextSource = appendPhpSnippetBeforeClosingTag(nextSource, bindingEditorEnqueueHook);
|
|
74
|
+
}
|
|
75
|
+
return nextSource;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Resolve the binding-source editor registry path, preferring existing TypeScript or JavaScript registries.
|
|
80
|
+
*
|
|
81
|
+
* @param projectDir Workspace root directory to inspect.
|
|
82
|
+
* @returns A promise for the registry path to read or write.
|
|
83
|
+
*/
|
|
84
|
+
export async function resolveBindingSourceRegistryPath(projectDir) {
|
|
85
|
+
const bindingsDir = path.join(projectDir, "src", "bindings");
|
|
86
|
+
for (const candidatePath of [
|
|
87
|
+
path.join(bindingsDir, "index.ts"),
|
|
88
|
+
path.join(bindingsDir, "index.js"),
|
|
89
|
+
]) {
|
|
90
|
+
if (await pathExists(candidatePath)) {
|
|
91
|
+
return candidatePath;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return path.join(bindingsDir, "index.ts");
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Rewrite the binding-source editor registry with the requested source slug included.
|
|
98
|
+
*
|
|
99
|
+
* @param projectDir Workspace root directory that owns `src/bindings`.
|
|
100
|
+
* @param bindingSourceSlug Binding source slug that must be imported by the registry.
|
|
101
|
+
* @returns A promise that resolves after the registry has been written.
|
|
102
|
+
*/
|
|
103
|
+
export async function writeBindingSourceRegistry(projectDir, bindingSourceSlug) {
|
|
104
|
+
const bindingsDir = path.join(projectDir, "src", "bindings");
|
|
105
|
+
const bindingsIndexPath = await resolveBindingSourceRegistryPath(projectDir);
|
|
106
|
+
await fsp.mkdir(bindingsDir, { recursive: true });
|
|
107
|
+
const existingBindingSourceSlugs = (await fsp.readdir(bindingsDir, { withFileTypes: true }))
|
|
108
|
+
.filter((entry) => entry.isDirectory())
|
|
109
|
+
.map((entry) => entry.name);
|
|
110
|
+
const nextBindingSourceSlugs = Array.from(new Set([...existingBindingSourceSlugs, bindingSourceSlug])).sort();
|
|
111
|
+
await fsp.writeFile(bindingsIndexPath, buildBindingSourceIndexSource(nextBindingSourceSlugs), "utf8");
|
|
112
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { BindingPostMetaSource, BindingTarget } from "./cli-add-workspace-binding-source-types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Render one `scripts/block-config.ts` binding-source inventory entry.
|
|
4
|
+
*
|
|
5
|
+
* @param bindingSourceSlug Normalized binding-source slug.
|
|
6
|
+
* @param target Optional block attribute target wired to the binding source.
|
|
7
|
+
* @param postMeta Optional post-meta contract backing this binding source.
|
|
8
|
+
* @returns TypeScript source for the inventory entry.
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildBindingSourceConfigEntry(bindingSourceSlug: string, target?: BindingTarget, postMeta?: BindingPostMetaSource): string;
|
|
11
|
+
/**
|
|
12
|
+
* Render the PHP registration module for a generated binding source.
|
|
13
|
+
*
|
|
14
|
+
* @param bindingSourceSlug Normalized binding-source slug.
|
|
15
|
+
* @param phpPrefix Workspace PHP function prefix.
|
|
16
|
+
* @param namespace Workspace block namespace.
|
|
17
|
+
* @param textDomain Workspace text domain used for labels.
|
|
18
|
+
* @param target Optional block attribute target wired to the binding source.
|
|
19
|
+
* @param postMeta Optional post-meta contract backing this binding source.
|
|
20
|
+
* @returns PHP source for `src/bindings/<slug>/server.php`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildBindingSourceServerSource(bindingSourceSlug: string, phpPrefix: string, namespace: string, textDomain: string, target?: BindingTarget, postMeta?: BindingPostMetaSource): string;
|
|
23
|
+
/**
|
|
24
|
+
* Render the editor registration module for a generated binding source.
|
|
25
|
+
*
|
|
26
|
+
* @param bindingSourceSlug Normalized binding-source slug.
|
|
27
|
+
* @param namespace Workspace block namespace.
|
|
28
|
+
* @param textDomain Workspace text domain used for labels.
|
|
29
|
+
* @param target Optional block attribute target wired to the binding source.
|
|
30
|
+
* @param postMeta Optional post-meta contract backing this binding source.
|
|
31
|
+
* @returns TypeScript source for `src/bindings/<slug>/editor.ts`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildBindingSourceEditorSource(bindingSourceSlug: string, namespace: string, textDomain: string, target?: BindingTarget, postMeta?: BindingPostMetaSource): string;
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { quoteTsString } from "./cli-add-shared.js";
|
|
2
|
+
import { quotePhpString } from "./php-utils.js";
|
|
3
|
+
import { toTitleCase } from "./string-case.js";
|
|
4
|
+
/**
|
|
5
|
+
* Render one `scripts/block-config.ts` binding-source inventory entry.
|
|
6
|
+
*
|
|
7
|
+
* @param bindingSourceSlug Normalized binding-source slug.
|
|
8
|
+
* @param target Optional block attribute target wired to the binding source.
|
|
9
|
+
* @param postMeta Optional post-meta contract backing this binding source.
|
|
10
|
+
* @returns TypeScript source for the inventory entry.
|
|
11
|
+
*/
|
|
12
|
+
export function buildBindingSourceConfigEntry(bindingSourceSlug, target, postMeta) {
|
|
13
|
+
return [
|
|
14
|
+
"\t{",
|
|
15
|
+
...(target ? [`\t\tattribute: ${quoteTsString(target.attributeName)},`] : []),
|
|
16
|
+
...(target ? [`\t\tblock: ${quoteTsString(target.blockSlug)},`] : []),
|
|
17
|
+
`\t\teditorFile: ${quoteTsString(`src/bindings/${bindingSourceSlug}/editor.ts`)},`,
|
|
18
|
+
...(postMeta ? [`\t\tmetaPath: ${quoteTsString(postMeta.metaPath)},`] : []),
|
|
19
|
+
...(postMeta ? [`\t\tpostMeta: ${quoteTsString(postMeta.postMetaSlug)},`] : []),
|
|
20
|
+
`\t\tserverFile: ${quoteTsString(`src/bindings/${bindingSourceSlug}/server.php`)},`,
|
|
21
|
+
`\t\tslug: ${quoteTsString(bindingSourceSlug)},`,
|
|
22
|
+
"\t},",
|
|
23
|
+
].join("\n");
|
|
24
|
+
}
|
|
25
|
+
function buildPhpStringList(values) {
|
|
26
|
+
if (values.length === 0) {
|
|
27
|
+
return "array()";
|
|
28
|
+
}
|
|
29
|
+
return `array( ${values.map((value) => quotePhpString(value)).join(", ")} )`;
|
|
30
|
+
}
|
|
31
|
+
function buildBindingPostMetaServerSource(options) {
|
|
32
|
+
const bindingSourceTitle = toTitleCase(options.bindingSourceSlug);
|
|
33
|
+
const bindingSourcePhpId = options.bindingSourceSlug.replace(/-/g, "_");
|
|
34
|
+
const functionPrefix = `${options.phpPrefix}_${bindingSourcePhpId}`;
|
|
35
|
+
const fieldsFunctionName = `${functionPrefix}_post_meta_binding_fields`;
|
|
36
|
+
const canReadFunctionName = `${functionPrefix}_can_read_post_meta`;
|
|
37
|
+
const resolveFunctionName = `${functionPrefix}_resolve_binding_source_value`;
|
|
38
|
+
const supportedAttributesFunctionName = `${functionPrefix}_supported_binding_attributes`;
|
|
39
|
+
const fieldNames = options.postMeta.fields.map((field) => field.name);
|
|
40
|
+
const supportedAttributesSource = options.target
|
|
41
|
+
? `
|
|
42
|
+
if ( ! function_exists( '${supportedAttributesFunctionName}' ) ) {
|
|
43
|
+
\tfunction ${supportedAttributesFunctionName}( array $supported_attributes ) : array {
|
|
44
|
+
\t\tif ( ! in_array( ${quotePhpString(options.target.attributeName)}, $supported_attributes, true ) ) {
|
|
45
|
+
\t\t\t$supported_attributes[] = ${quotePhpString(options.target.attributeName)};
|
|
46
|
+
\t\t}
|
|
47
|
+
|
|
48
|
+
\t\treturn $supported_attributes;
|
|
49
|
+
\t}
|
|
50
|
+
}
|
|
51
|
+
`
|
|
52
|
+
: "";
|
|
53
|
+
const supportedAttributesHook = options.target
|
|
54
|
+
? `
|
|
55
|
+
if ( function_exists( '${supportedAttributesFunctionName}' ) ) {
|
|
56
|
+
\tadd_filter(
|
|
57
|
+
\t\t${quotePhpString(`block_bindings_supported_attributes_${options.namespace}/${options.target.blockSlug}`)},
|
|
58
|
+
\t\t${quotePhpString(supportedAttributesFunctionName)}
|
|
59
|
+
\t);
|
|
60
|
+
}
|
|
61
|
+
`
|
|
62
|
+
: "";
|
|
63
|
+
return `<?php
|
|
64
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
65
|
+
\treturn;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if ( ! function_exists( 'register_block_bindings_source' ) ) {
|
|
69
|
+
\treturn;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if ( ! function_exists( '${fieldsFunctionName}' ) ) {
|
|
73
|
+
\tfunction ${fieldsFunctionName}() : array {
|
|
74
|
+
\t\t$schema_file = dirname( __DIR__, 3 ) . '/${options.postMeta.schemaFile}';
|
|
75
|
+
\t\tif ( file_exists( $schema_file ) ) {
|
|
76
|
+
\t\t\t$schema = json_decode( (string) file_get_contents( $schema_file ), true );
|
|
77
|
+
\t\t\tif ( is_array( $schema ) && isset( $schema['properties'] ) && is_array( $schema['properties'] ) ) {
|
|
78
|
+
\t\t\t\treturn array_values( array_filter( array_keys( $schema['properties'] ), 'is_string' ) );
|
|
79
|
+
\t\t\t}
|
|
80
|
+
\t\t}
|
|
81
|
+
|
|
82
|
+
\t\treturn ${buildPhpStringList(fieldNames)};
|
|
83
|
+
\t}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if ( ! function_exists( '${canReadFunctionName}' ) ) {
|
|
87
|
+
\tfunction ${canReadFunctionName}( int $post_id ) : bool {
|
|
88
|
+
\t\t$post = get_post( $post_id );
|
|
89
|
+
\t\tif ( ! $post ) {
|
|
90
|
+
\t\t\treturn false;
|
|
91
|
+
\t\t}
|
|
92
|
+
\t\t$post_type = is_string( $post->post_type ) ? $post->post_type : '';
|
|
93
|
+
\t\tif ( '' === $post_type ) {
|
|
94
|
+
\t\t\treturn false;
|
|
95
|
+
\t\t}
|
|
96
|
+
\t\tif ( ( ! is_post_publicly_viewable( $post ) && ! current_user_can( 'read_post', $post_id ) ) || post_password_required( $post ) ) {
|
|
97
|
+
\t\t\treturn false;
|
|
98
|
+
\t\t}
|
|
99
|
+
|
|
100
|
+
\t\t$meta_keys = get_registered_meta_keys( 'post', $post_type );
|
|
101
|
+
\t\t$meta_keys = array_merge( $meta_keys, get_registered_meta_keys( 'post', '' ) );
|
|
102
|
+
|
|
103
|
+
\t\treturn ! empty( $meta_keys[ ${quotePhpString(options.postMeta.metaKey)} ]['show_in_rest'] );
|
|
104
|
+
\t}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if ( ! function_exists( '${resolveFunctionName}' ) ) {
|
|
108
|
+
\tfunction ${resolveFunctionName}( array $source_args, $block_instance = null, $attribute_name = null ) {
|
|
109
|
+
\t\tunset( $attribute_name );
|
|
110
|
+
|
|
111
|
+
\t\t$field = isset( $source_args['field'] ) && is_string( $source_args['field'] )
|
|
112
|
+
\t\t\t? $source_args['field']
|
|
113
|
+
\t\t\t: ${quotePhpString(options.postMeta.metaPath)};
|
|
114
|
+
\t\tif ( ! in_array( $field, ${fieldsFunctionName}(), true ) ) {
|
|
115
|
+
\t\t\treturn null;
|
|
116
|
+
\t\t}
|
|
117
|
+
|
|
118
|
+
\t\t$post_id = 0;
|
|
119
|
+
\t\tif (
|
|
120
|
+
\t\t\tis_object( $block_instance ) &&
|
|
121
|
+
\t\t\tproperty_exists( $block_instance, 'context' ) &&
|
|
122
|
+
\t\t\tis_array( $block_instance->context ) &&
|
|
123
|
+
\t\t\tisset( $block_instance->context['postId'] )
|
|
124
|
+
\t\t) {
|
|
125
|
+
\t\t\t$post_id = absint( $block_instance->context['postId'] );
|
|
126
|
+
\t\t}
|
|
127
|
+
\t\tif ( ! $post_id || ! ${canReadFunctionName}( $post_id ) ) {
|
|
128
|
+
\t\t\treturn null;
|
|
129
|
+
\t\t}
|
|
130
|
+
|
|
131
|
+
\t\t$value = null;
|
|
132
|
+
\t\tif ( $post_id ) {
|
|
133
|
+
\t\t\t$meta = get_post_meta( $post_id, ${quotePhpString(options.postMeta.metaKey)}, true );
|
|
134
|
+
\t\t\tif ( is_array( $meta ) && array_key_exists( $field, $meta ) ) {
|
|
135
|
+
\t\t\t\t$value = $meta[ $field ];
|
|
136
|
+
\t\t\t}
|
|
137
|
+
\t\t}
|
|
138
|
+
\t\tif ( null === $value ) {
|
|
139
|
+
\t\t\treturn null;
|
|
140
|
+
\t\t}
|
|
141
|
+
|
|
142
|
+
\t\treturn $value;
|
|
143
|
+
\t}
|
|
144
|
+
}
|
|
145
|
+
${supportedAttributesSource}
|
|
146
|
+
|
|
147
|
+
register_block_bindings_source(
|
|
148
|
+
\t${quotePhpString(`${options.namespace}/${options.bindingSourceSlug}`)},
|
|
149
|
+
\tarray(
|
|
150
|
+
\t\t'label' => __( ${quotePhpString(bindingSourceTitle)}, ${quotePhpString(options.textDomain)} ),
|
|
151
|
+
\t\t'get_value_callback' => ${quotePhpString(resolveFunctionName)},
|
|
152
|
+
\t\t'uses_context' => array( 'postId', 'postType' ),
|
|
153
|
+
\t)
|
|
154
|
+
);
|
|
155
|
+
${supportedAttributesHook}`;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Render the PHP registration module for a generated binding source.
|
|
159
|
+
*
|
|
160
|
+
* @param bindingSourceSlug Normalized binding-source slug.
|
|
161
|
+
* @param phpPrefix Workspace PHP function prefix.
|
|
162
|
+
* @param namespace Workspace block namespace.
|
|
163
|
+
* @param textDomain Workspace text domain used for labels.
|
|
164
|
+
* @param target Optional block attribute target wired to the binding source.
|
|
165
|
+
* @param postMeta Optional post-meta contract backing this binding source.
|
|
166
|
+
* @returns PHP source for `src/bindings/<slug>/server.php`.
|
|
167
|
+
*/
|
|
168
|
+
export function buildBindingSourceServerSource(bindingSourceSlug, phpPrefix, namespace, textDomain, target, postMeta) {
|
|
169
|
+
if (postMeta) {
|
|
170
|
+
return buildBindingPostMetaServerSource({
|
|
171
|
+
bindingSourceSlug,
|
|
172
|
+
namespace,
|
|
173
|
+
phpPrefix,
|
|
174
|
+
postMeta,
|
|
175
|
+
target,
|
|
176
|
+
textDomain,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
const bindingSourceTitle = toTitleCase(bindingSourceSlug);
|
|
180
|
+
const bindingSourcePhpId = bindingSourceSlug.replace(/-/g, "_");
|
|
181
|
+
const bindingSourceValueFunctionName = `${phpPrefix}_${bindingSourcePhpId}_binding_source_values`;
|
|
182
|
+
const bindingSourceResolveFunctionName = `${phpPrefix}_${bindingSourcePhpId}_resolve_binding_source_value`;
|
|
183
|
+
const bindingSourceSupportedAttributesFunctionName = `${phpPrefix}_${bindingSourcePhpId}_supported_binding_attributes`;
|
|
184
|
+
const starterValue = `${bindingSourceTitle} starter value`;
|
|
185
|
+
const supportedAttributesSource = target
|
|
186
|
+
? `
|
|
187
|
+
if ( ! function_exists( '${bindingSourceSupportedAttributesFunctionName}' ) ) {
|
|
188
|
+
\tfunction ${bindingSourceSupportedAttributesFunctionName}( array $supported_attributes ) : array {
|
|
189
|
+
\t\tif ( ! in_array( ${quotePhpString(target.attributeName)}, $supported_attributes, true ) ) {
|
|
190
|
+
\t\t\t$supported_attributes[] = ${quotePhpString(target.attributeName)};
|
|
191
|
+
\t\t}
|
|
192
|
+
|
|
193
|
+
\t\treturn $supported_attributes;
|
|
194
|
+
\t}
|
|
195
|
+
}
|
|
196
|
+
`
|
|
197
|
+
: "";
|
|
198
|
+
const supportedAttributesHook = target
|
|
199
|
+
? `
|
|
200
|
+
if ( function_exists( '${bindingSourceSupportedAttributesFunctionName}' ) ) {
|
|
201
|
+
\tadd_filter(
|
|
202
|
+
\t\t${quotePhpString(`block_bindings_supported_attributes_${namespace}/${target.blockSlug}`)},
|
|
203
|
+
\t\t${quotePhpString(bindingSourceSupportedAttributesFunctionName)}
|
|
204
|
+
\t);
|
|
205
|
+
}
|
|
206
|
+
`
|
|
207
|
+
: "";
|
|
208
|
+
return `<?php
|
|
209
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
210
|
+
\treturn;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if ( ! function_exists( 'register_block_bindings_source' ) ) {
|
|
214
|
+
\treturn;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if ( ! function_exists( '${bindingSourceValueFunctionName}' ) ) {
|
|
218
|
+
\tfunction ${bindingSourceValueFunctionName}() : array {
|
|
219
|
+
\t\treturn array(
|
|
220
|
+
\t\t\t${quotePhpString(bindingSourceSlug)} => ${quotePhpString(starterValue)},
|
|
221
|
+
\t\t);
|
|
222
|
+
\t}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if ( ! function_exists( '${bindingSourceResolveFunctionName}' ) ) {
|
|
226
|
+
\tfunction ${bindingSourceResolveFunctionName}( array $source_args ) : string {
|
|
227
|
+
\t\t$field = isset( $source_args['field'] ) && is_string( $source_args['field'] )
|
|
228
|
+
\t\t\t? $source_args['field']
|
|
229
|
+
\t\t\t: '${bindingSourceSlug}';
|
|
230
|
+
\t\t$binding_source_values = ${bindingSourceValueFunctionName}();
|
|
231
|
+
\t\t$value = $binding_source_values[ $field ] ?? '';
|
|
232
|
+
|
|
233
|
+
\t\treturn is_string( $value ) ? $value : '';
|
|
234
|
+
\t}
|
|
235
|
+
}
|
|
236
|
+
${supportedAttributesSource}
|
|
237
|
+
|
|
238
|
+
register_block_bindings_source(
|
|
239
|
+
\t${quotePhpString(`${namespace}/${bindingSourceSlug}`)},
|
|
240
|
+
\tarray(
|
|
241
|
+
\t\t'label' => __( ${quotePhpString(bindingSourceTitle)}, ${quotePhpString(textDomain)} ),
|
|
242
|
+
\t\t'get_value_callback' => ${quotePhpString(bindingSourceResolveFunctionName)},
|
|
243
|
+
\t)
|
|
244
|
+
);
|
|
245
|
+
${supportedAttributesHook}`;
|
|
246
|
+
}
|
|
247
|
+
function buildTsPostMetaPreviewValue(field) {
|
|
248
|
+
switch (field.schemaType) {
|
|
249
|
+
case "array":
|
|
250
|
+
return "[]";
|
|
251
|
+
case "boolean":
|
|
252
|
+
return field.fallbackValue === "true" ? "true" : "false";
|
|
253
|
+
case "integer":
|
|
254
|
+
case "number": {
|
|
255
|
+
const value = Number(field.fallbackValue);
|
|
256
|
+
return Number.isFinite(value) ? String(value) : "0";
|
|
257
|
+
}
|
|
258
|
+
case "object":
|
|
259
|
+
return "{}";
|
|
260
|
+
default:
|
|
261
|
+
return quoteTsString(field.fallbackValue);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function buildTsPostMetaFieldEntries(fields, textDomain) {
|
|
265
|
+
return fields
|
|
266
|
+
.map((field) => [
|
|
267
|
+
"\t{",
|
|
268
|
+
`\t\tfallbackValue: ${quoteTsString(field.fallbackValue)},`,
|
|
269
|
+
`\t\tlabel: __( ${quoteTsString(field.label)}, ${quoteTsString(textDomain)} ),`,
|
|
270
|
+
`\t\tname: ${quoteTsString(field.name)},`,
|
|
271
|
+
`\t\tpreviewValue: ${buildTsPostMetaPreviewValue(field)},`,
|
|
272
|
+
`\t\trequired: ${field.required ? "true" : "false"},`,
|
|
273
|
+
`\t\tschemaType: ${quoteTsString(field.schemaType)},`,
|
|
274
|
+
"\t},",
|
|
275
|
+
].join("\n"))
|
|
276
|
+
.join("\n");
|
|
277
|
+
}
|
|
278
|
+
function buildBindingPostMetaEditorSource(options) {
|
|
279
|
+
const bindingSourceTitle = toTitleCase(options.bindingSourceSlug);
|
|
280
|
+
const bindingSourceName = `${options.namespace}/${options.bindingSourceSlug}`;
|
|
281
|
+
const targetSource = options.target
|
|
282
|
+
? `
|
|
283
|
+
export const BINDING_SOURCE_TARGET = {
|
|
284
|
+
\tattribute: ${quoteTsString(options.target.attributeName)},
|
|
285
|
+
\tblock: ${quoteTsString(`${options.namespace}/${options.target.blockSlug}`)},
|
|
286
|
+
\tfield: ${quoteTsString(options.postMeta.metaPath)},
|
|
287
|
+
\tsource: ${quoteTsString(bindingSourceName)},
|
|
288
|
+
} as const;
|
|
289
|
+
`
|
|
290
|
+
: "";
|
|
291
|
+
return `import { registerBlockBindingsSource } from '@wordpress/blocks';
|
|
292
|
+
import { __ } from '@wordpress/i18n';
|
|
293
|
+
|
|
294
|
+
interface BindingSourceRegistration {
|
|
295
|
+
\targs?: {
|
|
296
|
+
\t\tfield?: string;
|
|
297
|
+
\t};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export const POST_META_BINDING_SOURCE = {
|
|
301
|
+
\tmetaKey: ${quoteTsString(options.postMeta.metaKey)},
|
|
302
|
+
\tpostMeta: ${quoteTsString(options.postMeta.postMetaSlug)},
|
|
303
|
+
\tpostType: ${quoteTsString(options.postMeta.postType)},
|
|
304
|
+
\tschemaFile: ${quoteTsString(options.postMeta.schemaFile)},
|
|
305
|
+
\tsourceTypeName: ${quoteTsString(options.postMeta.sourceTypeName)},
|
|
306
|
+
} as const;
|
|
307
|
+
|
|
308
|
+
const POST_META_BINDING_FIELDS = [
|
|
309
|
+
${buildTsPostMetaFieldEntries(options.postMeta.fields, options.textDomain)}
|
|
310
|
+
] as const;
|
|
311
|
+
|
|
312
|
+
const POST_META_PREVIEW_VALUES: Record<string, unknown> = Object.fromEntries(
|
|
313
|
+
\tPOST_META_BINDING_FIELDS.map( ( field ) => [
|
|
314
|
+
\t\tfield.name,
|
|
315
|
+
\t\tfield.previewValue,
|
|
316
|
+
\t] )
|
|
317
|
+
);
|
|
318
|
+
${targetSource}
|
|
319
|
+
|
|
320
|
+
function resolveBindingFieldType( schemaType: string ): string {
|
|
321
|
+
\treturn schemaType === 'unknown' ? 'string' : schemaType;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function resolveBindingSourceValue( field: string ): unknown {
|
|
325
|
+
\treturn POST_META_PREVIEW_VALUES[ field ] ?? '';
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
registerBlockBindingsSource( {
|
|
329
|
+
\tname: ${quoteTsString(bindingSourceName)},
|
|
330
|
+
\tlabel: __( ${quoteTsString(bindingSourceTitle)}, ${quoteTsString(options.textDomain)} ),
|
|
331
|
+
\tgetFieldsList() {
|
|
332
|
+
\t\treturn POST_META_BINDING_FIELDS.map( ( field ) => ( {
|
|
333
|
+
\t\t\tlabel: field.label,
|
|
334
|
+
\t\t\ttype: resolveBindingFieldType( field.schemaType ),
|
|
335
|
+
\t\t\targs: {
|
|
336
|
+
\t\t\t\tfield: field.name,
|
|
337
|
+
\t\t\t},
|
|
338
|
+
\t\t} ) );
|
|
339
|
+
\t},
|
|
340
|
+
\tgetValues( { bindings } ) {
|
|
341
|
+
\t\tconst values: Record<string, unknown> = {};
|
|
342
|
+
\t\tfor ( const [ attributeName, binding ] of Object.entries(
|
|
343
|
+
\t\t\tbindings as Record<string, BindingSourceRegistration>
|
|
344
|
+
\t\t) ) {
|
|
345
|
+
\t\t\tconst field =
|
|
346
|
+
\t\t\t\ttypeof binding?.args?.field === 'string'
|
|
347
|
+
\t\t\t\t\t? binding.args.field
|
|
348
|
+
\t\t\t\t\t: ${quoteTsString(options.postMeta.metaPath)};
|
|
349
|
+
\t\t\tvalues[ attributeName ] = resolveBindingSourceValue( field );
|
|
350
|
+
\t\t}
|
|
351
|
+
\t\treturn values;
|
|
352
|
+
\t},
|
|
353
|
+
} );
|
|
354
|
+
`;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Render the editor registration module for a generated binding source.
|
|
358
|
+
*
|
|
359
|
+
* @param bindingSourceSlug Normalized binding-source slug.
|
|
360
|
+
* @param namespace Workspace block namespace.
|
|
361
|
+
* @param textDomain Workspace text domain used for labels.
|
|
362
|
+
* @param target Optional block attribute target wired to the binding source.
|
|
363
|
+
* @param postMeta Optional post-meta contract backing this binding source.
|
|
364
|
+
* @returns TypeScript source for `src/bindings/<slug>/editor.ts`.
|
|
365
|
+
*/
|
|
366
|
+
export function buildBindingSourceEditorSource(bindingSourceSlug, namespace, textDomain, target, postMeta) {
|
|
367
|
+
if (postMeta) {
|
|
368
|
+
return buildBindingPostMetaEditorSource({
|
|
369
|
+
bindingSourceSlug,
|
|
370
|
+
namespace,
|
|
371
|
+
postMeta,
|
|
372
|
+
target,
|
|
373
|
+
textDomain,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
const bindingSourceTitle = toTitleCase(bindingSourceSlug);
|
|
377
|
+
const starterValue = `${bindingSourceTitle} starter value`;
|
|
378
|
+
const bindingSourceName = `${namespace}/${bindingSourceSlug}`;
|
|
379
|
+
const targetSource = target
|
|
380
|
+
? `
|
|
381
|
+
export const BINDING_SOURCE_TARGET = {
|
|
382
|
+
\tattribute: ${quoteTsString(target.attributeName)},
|
|
383
|
+
\tblock: ${quoteTsString(`${namespace}/${target.blockSlug}`)},
|
|
384
|
+
\tfield: ${quoteTsString(bindingSourceSlug)},
|
|
385
|
+
\tsource: ${quoteTsString(bindingSourceName)},
|
|
386
|
+
} as const;
|
|
387
|
+
`
|
|
388
|
+
: "";
|
|
389
|
+
return `import { registerBlockBindingsSource } from '@wordpress/blocks';
|
|
390
|
+
import { __ } from '@wordpress/i18n';
|
|
391
|
+
|
|
392
|
+
interface BindingSourceRegistration {
|
|
393
|
+
\targs?: {
|
|
394
|
+
\t\tfield?: string;
|
|
395
|
+
\t};
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const BINDING_SOURCE_VALUES: Record<string, string> = {
|
|
399
|
+
\t${quoteTsString(bindingSourceSlug)}: ${quoteTsString(starterValue)},
|
|
400
|
+
};
|
|
401
|
+
${targetSource}
|
|
402
|
+
|
|
403
|
+
function resolveBindingSourceValue( field: string ): string {
|
|
404
|
+
\treturn BINDING_SOURCE_VALUES[ field ] ?? '';
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
registerBlockBindingsSource( {
|
|
408
|
+
\tname: ${quoteTsString(bindingSourceName)},
|
|
409
|
+
\tlabel: __( ${quoteTsString(bindingSourceTitle)}, ${quoteTsString(textDomain)} ),
|
|
410
|
+
\tgetFieldsList() {
|
|
411
|
+
\t\treturn [
|
|
412
|
+
\t\t\t{
|
|
413
|
+
\t\t\t\tlabel: __( ${quoteTsString(bindingSourceTitle)}, ${quoteTsString(textDomain)} ),
|
|
414
|
+
\t\t\t\ttype: 'string',
|
|
415
|
+
\t\t\t\targs: {
|
|
416
|
+
\t\t\t\t\tfield: ${quoteTsString(bindingSourceSlug)},
|
|
417
|
+
\t\t\t\t},
|
|
418
|
+
\t\t\t},
|
|
419
|
+
\t\t];
|
|
420
|
+
\t},
|
|
421
|
+
\tgetValues( { bindings } ) {
|
|
422
|
+
\t\tconst values: Record<string, string> = {};
|
|
423
|
+
\t\tfor ( const [ attributeName, binding ] of Object.entries(
|
|
424
|
+
\t\t\tbindings as Record<string, BindingSourceRegistration>
|
|
425
|
+
\t\t) ) {
|
|
426
|
+
\t\t\tconst field =
|
|
427
|
+
\t\t\t\ttypeof binding?.args?.field === 'string'
|
|
428
|
+
\t\t\t\t\t? binding.args.field
|
|
429
|
+
\t\t\t\t\t: ${quoteTsString(bindingSourceSlug)};
|
|
430
|
+
\t\t\tvalues[ attributeName ] = resolveBindingSourceValue( field );
|
|
431
|
+
\t\t}
|
|
432
|
+
\t\treturn values;
|
|
433
|
+
\t},
|
|
434
|
+
} );
|
|
435
|
+
`;
|
|
436
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PostMetaBindingField } from "./post-meta-binding-fields.js";
|
|
2
|
+
/**
|
|
3
|
+
* Target block attribute that should receive generated binding-source wiring.
|
|
4
|
+
*/
|
|
5
|
+
export type BindingTarget = {
|
|
6
|
+
attributeName: string;
|
|
7
|
+
blockSlug: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Resolved post-meta contract data used to generate a binding source.
|
|
11
|
+
*/
|
|
12
|
+
export type BindingPostMetaSource = {
|
|
13
|
+
fields: PostMetaBindingField[];
|
|
14
|
+
metaKey: string;
|
|
15
|
+
metaPath: string;
|
|
16
|
+
postMetaSlug: string;
|
|
17
|
+
postType: string;
|
|
18
|
+
schemaFile: string;
|
|
19
|
+
sourceTypeName: string;
|
|
20
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type RunAddBindingSourceCommandOptions } from "./cli-add-shared.js";
|
|
2
|
+
/**
|
|
3
|
+
* Add one block binding source scaffold to an official workspace project.
|
|
4
|
+
*
|
|
5
|
+
* @param options Command options for the binding-source scaffold workflow.
|
|
6
|
+
* @param options.attributeName Optional generated block attribute to declare as
|
|
7
|
+
* bindable. Must be provided together with `blockName`.
|
|
8
|
+
* @param options.blockName Optional generated block slug or full block name to
|
|
9
|
+
* receive the bindable attribute wiring. Must be provided together with
|
|
10
|
+
* `attributeName`.
|
|
11
|
+
* @param options.bindingSourceName Human-entered binding source name that will
|
|
12
|
+
* be normalized and validated before files are written.
|
|
13
|
+
* @param options.cwd Working directory used to resolve the nearest official
|
|
14
|
+
* workspace. Defaults to `process.cwd()`.
|
|
15
|
+
* @param options.metaPath Optional top-level post-meta field used as the
|
|
16
|
+
* binding source's default `field` arg. Requires `postMetaName`.
|
|
17
|
+
* @param options.postMetaName Optional generated post-meta contract slug used
|
|
18
|
+
* to back the binding source with `get_post_meta()`.
|
|
19
|
+
* @returns A promise that resolves with the normalized `bindingSourceSlug` and
|
|
20
|
+
* owning `projectDir` after the server/editor files, optional target block
|
|
21
|
+
* metadata, and inventory entry have been written successfully. Post-meta
|
|
22
|
+
* backed results additionally include `metaKey`, `metaPath`, `postMetaSlug`,
|
|
23
|
+
* `postType`, and `schemaFile`.
|
|
24
|
+
* @throws {Error} When the command is run outside an official workspace, when
|
|
25
|
+
* the slug is invalid, when a binding target is incomplete or unknown, or when
|
|
26
|
+
* a conflicting file or inventory entry exists. Post-meta backed runs also
|
|
27
|
+
* throw when the referenced contract or requested top-level field cannot be
|
|
28
|
+
* resolved.
|
|
29
|
+
*/
|
|
30
|
+
export declare function runAddBindingSourceCommand({ attributeName, bindingSourceName, blockName, cwd, metaPath, postMetaName, }: RunAddBindingSourceCommandOptions): Promise<{
|
|
31
|
+
attributeName?: string;
|
|
32
|
+
bindingSourceSlug: string;
|
|
33
|
+
blockSlug?: string;
|
|
34
|
+
metaKey?: string;
|
|
35
|
+
metaPath?: string;
|
|
36
|
+
postMetaSlug?: string;
|
|
37
|
+
postType?: string;
|
|
38
|
+
projectDir: string;
|
|
39
|
+
schemaFile?: string;
|
|
40
|
+
}>;
|