@wp-typia/block-types 0.3.1 → 0.3.2
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/blocks/bindings-core.d.ts +2 -9
- package/dist/blocks/bindings-core.js +4 -290
- package/dist/blocks/bindings-diagnostics.d.ts +8 -0
- package/dist/blocks/bindings-diagnostics.js +95 -0
- package/dist/blocks/bindings-manifest.d.ts +12 -0
- package/dist/blocks/bindings-manifest.js +82 -0
- package/dist/blocks/bindings-settings.d.ts +27 -0
- package/dist/blocks/bindings-settings.js +115 -0
- package/dist/blocks/supports-diagnostics.d.ts +3 -0
- package/dist/blocks/supports-diagnostics.js +7 -0
- package/dist/blocks/supports-features.d.ts +10 -0
- package/dist/blocks/supports-features.js +53 -0
- package/dist/blocks/supports-manifest.d.ts +4 -0
- package/dist/blocks/supports-manifest.js +97 -0
- package/dist/blocks/supports-settings.d.ts +8 -0
- package/dist/blocks/supports-settings.js +42 -0
- package/dist/blocks/supports.d.ts +5 -14
- package/dist/blocks/supports.js +6 -197
- package/dist/blocks/variations-diagnostics.d.ts +6 -0
- package/dist/blocks/variations-diagnostics.js +123 -0
- package/dist/blocks/variations-manifest.d.ts +5 -0
- package/dist/blocks/variations-manifest.js +17 -0
- package/dist/blocks/variations-settings.d.ts +18 -0
- package/dist/blocks/variations-settings.js +50 -0
- package/dist/blocks/variations.d.ts +3 -3
- package/dist/blocks/variations.js +5 -164
- package/package.json +1 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { BlockAttributes } from "./registration.js";
|
|
2
2
|
import { type WordPressBlockApiCompatibilityDiagnostic, type WordPressBlockApiCompatibilityFeature, type WordPressBlockApiCompatibilityManifest, type WordPressCompatibilitySettings, type WordPressVersion } from "./compatibility.js";
|
|
3
3
|
import { type DiagnosticLogger } from "./shared/diagnostics.js";
|
|
4
|
+
import { collectBindingSourceCompatibilityFeatures, createBindingSourceCompatibilityManifest } from "./bindings-manifest.js";
|
|
5
|
+
export { collectBindingSourceCompatibilityFeatures, createBindingSourceCompatibilityManifest, };
|
|
4
6
|
export type BindingSourceName = `${string}/${string}`;
|
|
5
7
|
export type BindingSourceArgs = Readonly<Record<string, unknown>>;
|
|
6
8
|
export type BindingFieldType = "array" | "boolean" | "integer" | "number" | "object" | "string";
|
|
@@ -101,14 +103,6 @@ export interface BindingSourceRegistrationEntry {
|
|
|
101
103
|
readonly metadata: DefinedBlockBindingSourceMetadata;
|
|
102
104
|
readonly source: DefinedBindingSource;
|
|
103
105
|
}
|
|
104
|
-
export declare function collectBindingSourceCompatibilityFeatures(settings?: {
|
|
105
|
-
readonly editor?: boolean;
|
|
106
|
-
readonly fieldsList?: boolean;
|
|
107
|
-
readonly metadata?: boolean;
|
|
108
|
-
readonly server?: boolean;
|
|
109
|
-
readonly supportedAttributesFilter?: boolean;
|
|
110
|
-
}): readonly WordPressBlockApiCompatibilityFeature[];
|
|
111
|
-
export declare function createBindingSourceCompatibilityManifest(settings?: DefineBindingSourceOptions): WordPressBlockApiCompatibilityManifest;
|
|
112
106
|
export declare function getDefinedBindingSourceMetadata(source: unknown): DefinedBlockBindingSourceMetadata | undefined;
|
|
113
107
|
export declare function getDefinedBindingSourceCompatibilityManifest(source: unknown): WordPressBlockApiCompatibilityManifest | undefined;
|
|
114
108
|
export declare function defineBindingSource<const TSource extends BindingSourceDefinition & DefineBindingSourceInlineOptions>(source: TSource, options?: DefineBindingSourceOptions): DefinedBindingSource<Extract<TSource["name"], string>, TSource extends {
|
|
@@ -120,4 +114,3 @@ export declare function defineBindableAttributes<TAttributes extends BlockAttrib
|
|
|
120
114
|
export declare function defineBlockMetadataBindings<const TBindings extends Readonly<Record<string, BlockBinding | undefined>>>(bindings: TBindings): BlockMetadataBindings<TBindings>;
|
|
121
115
|
export declare function defineTypedBlockMetadataBindings<TAttributes extends BlockAttributes, const TBindings extends BlockBindingMap<TAttributes> = BlockBindingMap<TAttributes>>(bindings: TBindings): TypedBlockMetadataBindings<TAttributes, TBindings>;
|
|
122
116
|
export declare function createBindingSourceRegistrationPlan(sources: readonly DefinedBindingSource[]): readonly BindingSourceRegistrationEntry[];
|
|
123
|
-
export {};
|
|
@@ -1,295 +1,9 @@
|
|
|
1
|
-
import { DEFAULT_WORDPRESS_COMPATIBILITY_MIN_VERSION, evaluateWordPressBlockApiCompatibility, } from "./compatibility.js";
|
|
2
|
-
import { getDiagnosticSeverity, handleDiagnostics, } from "./shared/diagnostics.js";
|
|
3
1
|
import { isObjectRecord } from "./shared/object-utils.js";
|
|
2
|
+
import { createBindingSourceDiagnostics, handleBindingSourceDiagnostics, } from "./bindings-diagnostics.js";
|
|
3
|
+
import { collectBindingSourceCompatibilityFeatures, createBindingCompatibilityManifest, createBindingSourceCompatibilityManifest, } from "./bindings-manifest.js";
|
|
4
|
+
import { resolveDefineBindingSourceSettings, splitDefineBindingSourceInput, } from "./bindings-settings.js";
|
|
5
|
+
export { collectBindingSourceCompatibilityFeatures, createBindingSourceCompatibilityManifest, };
|
|
4
6
|
export const DEFINED_BLOCK_BINDING_SOURCE_METADATA = Symbol.for("@wp-typia/block-types/defined-binding-source");
|
|
5
|
-
const DEFINE_BINDING_SOURCE_INLINE_OPTION_KEYS = new Set([
|
|
6
|
-
"allowUnknownFutureKeys",
|
|
7
|
-
"editor",
|
|
8
|
-
"fieldsList",
|
|
9
|
-
"logger",
|
|
10
|
-
"minVersion",
|
|
11
|
-
"minWordPress",
|
|
12
|
-
"minWordPressEditor",
|
|
13
|
-
"minWordPressFieldsList",
|
|
14
|
-
"minWordPressServer",
|
|
15
|
-
"minWordPressSupportedAttributesFilter",
|
|
16
|
-
"onDiagnostic",
|
|
17
|
-
"server",
|
|
18
|
-
"strict",
|
|
19
|
-
"supportedAttributesFilter",
|
|
20
|
-
]);
|
|
21
|
-
const SOURCE_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\/[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u;
|
|
22
|
-
const FIELD_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]*$/u;
|
|
23
|
-
function isBindingSourceVersionGates(value) {
|
|
24
|
-
return isObjectRecord(value);
|
|
25
|
-
}
|
|
26
|
-
function splitDefineBindingSourceInput(source) {
|
|
27
|
-
const inlineOptions = {};
|
|
28
|
-
const normalizedSource = {};
|
|
29
|
-
for (const [key, value] of Object.entries(source)) {
|
|
30
|
-
if (DEFINE_BINDING_SOURCE_INLINE_OPTION_KEYS.has(key)) {
|
|
31
|
-
Object.assign(inlineOptions, { [key]: value });
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
normalizedSource[key] = value;
|
|
35
|
-
}
|
|
36
|
-
return {
|
|
37
|
-
inlineOptions,
|
|
38
|
-
source: normalizedSource,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
function resolveMinWordPress(inlineOptions, options) {
|
|
42
|
-
const optionMinWordPress = options.minWordPress;
|
|
43
|
-
const inlineMinWordPress = inlineOptions.minWordPress;
|
|
44
|
-
const optionGates = isBindingSourceVersionGates(optionMinWordPress)
|
|
45
|
-
? optionMinWordPress
|
|
46
|
-
: {};
|
|
47
|
-
const inlineGates = isBindingSourceVersionGates(inlineMinWordPress)
|
|
48
|
-
? inlineMinWordPress
|
|
49
|
-
: {};
|
|
50
|
-
const minVersion = options.minVersion ??
|
|
51
|
-
(typeof optionMinWordPress === "string" ? optionMinWordPress : undefined) ??
|
|
52
|
-
inlineOptions.minVersion ??
|
|
53
|
-
(typeof inlineMinWordPress === "string" ? inlineMinWordPress : undefined);
|
|
54
|
-
const compatibility = {
|
|
55
|
-
strict: options.strict ?? inlineOptions.strict ?? true,
|
|
56
|
-
};
|
|
57
|
-
if (options.allowUnknownFutureKeys ?? inlineOptions.allowUnknownFutureKeys) {
|
|
58
|
-
Object.assign(compatibility, {
|
|
59
|
-
allowUnknownFutureKeys: options.allowUnknownFutureKeys ?? inlineOptions.allowUnknownFutureKeys,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
if (minVersion !== undefined) {
|
|
63
|
-
Object.assign(compatibility, { minVersion });
|
|
64
|
-
}
|
|
65
|
-
const gates = {};
|
|
66
|
-
const editor = options.minWordPressEditor ??
|
|
67
|
-
optionGates.editor ??
|
|
68
|
-
inlineOptions.minWordPressEditor ??
|
|
69
|
-
inlineGates.editor;
|
|
70
|
-
const fieldsList = options.minWordPressFieldsList ??
|
|
71
|
-
optionGates.fieldsList ??
|
|
72
|
-
inlineOptions.minWordPressFieldsList ??
|
|
73
|
-
inlineGates.fieldsList;
|
|
74
|
-
const server = options.minWordPressServer ??
|
|
75
|
-
optionGates.server ??
|
|
76
|
-
inlineOptions.minWordPressServer ??
|
|
77
|
-
inlineGates.server;
|
|
78
|
-
const supportedAttributesFilter = options.minWordPressSupportedAttributesFilter ??
|
|
79
|
-
optionGates.supportedAttributesFilter ??
|
|
80
|
-
inlineOptions.minWordPressSupportedAttributesFilter ??
|
|
81
|
-
inlineGates.supportedAttributesFilter;
|
|
82
|
-
if (editor !== undefined) {
|
|
83
|
-
Object.assign(gates, { editor });
|
|
84
|
-
}
|
|
85
|
-
if (fieldsList !== undefined) {
|
|
86
|
-
Object.assign(gates, { fieldsList });
|
|
87
|
-
}
|
|
88
|
-
if (server !== undefined) {
|
|
89
|
-
Object.assign(gates, { server });
|
|
90
|
-
}
|
|
91
|
-
if (supportedAttributesFilter !== undefined) {
|
|
92
|
-
Object.assign(gates, { supportedAttributesFilter });
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
compatibility,
|
|
96
|
-
gates,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
function resolveDefineBindingSourceSettings(inlineOptions, options, source) {
|
|
100
|
-
const { compatibility, gates } = resolveMinWordPress(inlineOptions, options);
|
|
101
|
-
const strict = compatibility.strict ?? true;
|
|
102
|
-
const hasFields = (source.fields?.length ?? 0) > 0;
|
|
103
|
-
const hasBindableAttributes = (source.bindableAttributes?.length ?? 0) > 0;
|
|
104
|
-
return {
|
|
105
|
-
compatibility,
|
|
106
|
-
features: {
|
|
107
|
-
editor: options.editor ?? inlineOptions.editor ?? true,
|
|
108
|
-
fieldsList: options.fieldsList ?? inlineOptions.fieldsList ?? hasFields,
|
|
109
|
-
metadata: true,
|
|
110
|
-
server: options.server ?? inlineOptions.server ?? true,
|
|
111
|
-
supportedAttributesFilter: options.supportedAttributesFilter ??
|
|
112
|
-
inlineOptions.supportedAttributesFilter ??
|
|
113
|
-
hasBindableAttributes,
|
|
114
|
-
},
|
|
115
|
-
gates,
|
|
116
|
-
logger: options.logger ?? inlineOptions.logger,
|
|
117
|
-
onDiagnostic: options.onDiagnostic ?? inlineOptions.onDiagnostic,
|
|
118
|
-
strict,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
function getFeatureMinVersion(feature, fallback, gates) {
|
|
122
|
-
if (feature.area !== "blockBindings") {
|
|
123
|
-
return fallback;
|
|
124
|
-
}
|
|
125
|
-
switch (feature.feature) {
|
|
126
|
-
case "metadata.bindings":
|
|
127
|
-
case "serverRegistration":
|
|
128
|
-
return gates.server ?? fallback;
|
|
129
|
-
case "editorFieldsList":
|
|
130
|
-
return gates.fieldsList ?? fallback;
|
|
131
|
-
case "editorRegistration":
|
|
132
|
-
case "editorSourceLookup":
|
|
133
|
-
return gates.editor ?? fallback;
|
|
134
|
-
case "supportedAttributesFilter":
|
|
135
|
-
return gates.supportedAttributesFilter ?? gates.fieldsList ?? fallback;
|
|
136
|
-
default:
|
|
137
|
-
return fallback;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
function createBindingCompatibilityManifest(features, settings, gates) {
|
|
141
|
-
const fallback = settings.minVersion ?? DEFAULT_WORDPRESS_COMPATIBILITY_MIN_VERSION;
|
|
142
|
-
const strict = settings.strict ?? true;
|
|
143
|
-
const allowUnknownFutureKeys = settings.allowUnknownFutureKeys ?? false;
|
|
144
|
-
const evaluations = features.map((feature) => evaluateWordPressBlockApiCompatibility(feature, {
|
|
145
|
-
allowUnknownFutureKeys,
|
|
146
|
-
minVersion: getFeatureMinVersion(feature, fallback, gates),
|
|
147
|
-
strict,
|
|
148
|
-
}));
|
|
149
|
-
const diagnostics = evaluations.flatMap((evaluation) => evaluation.diagnostic ? [evaluation.diagnostic] : []);
|
|
150
|
-
return {
|
|
151
|
-
allowUnknownFutureKeys,
|
|
152
|
-
diagnostics,
|
|
153
|
-
evaluations,
|
|
154
|
-
minVersion: fallback,
|
|
155
|
-
strict,
|
|
156
|
-
supported: evaluations.filter((evaluation) => evaluation.status === "supported"),
|
|
157
|
-
unknown: evaluations.filter((evaluation) => evaluation.status === "unknown"),
|
|
158
|
-
unsupported: evaluations.filter((evaluation) => evaluation.status === "unsupported"),
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
export function collectBindingSourceCompatibilityFeatures(settings = {}) {
|
|
162
|
-
const features = [];
|
|
163
|
-
if (settings.metadata ?? true) {
|
|
164
|
-
features.push({
|
|
165
|
-
area: "blockBindings",
|
|
166
|
-
feature: "metadata.bindings",
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
if (settings.server ?? true) {
|
|
170
|
-
features.push({
|
|
171
|
-
area: "blockBindings",
|
|
172
|
-
feature: "serverRegistration",
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
if (settings.editor ?? true) {
|
|
176
|
-
features.push({
|
|
177
|
-
area: "blockBindings",
|
|
178
|
-
feature: "editorRegistration",
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
if (settings.fieldsList ?? false) {
|
|
182
|
-
features.push({
|
|
183
|
-
area: "blockBindings",
|
|
184
|
-
feature: "editorFieldsList",
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
if (settings.supportedAttributesFilter ?? false) {
|
|
188
|
-
features.push({
|
|
189
|
-
area: "blockBindings",
|
|
190
|
-
feature: "supportedAttributesFilter",
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
return features;
|
|
194
|
-
}
|
|
195
|
-
export function createBindingSourceCompatibilityManifest(settings = {}) {
|
|
196
|
-
const resolved = resolveDefineBindingSourceSettings({}, settings, {
|
|
197
|
-
name: "wp-typia/binding-source",
|
|
198
|
-
});
|
|
199
|
-
return createBindingCompatibilityManifest(collectBindingSourceCompatibilityFeatures(resolved.features), resolved.compatibility, resolved.gates);
|
|
200
|
-
}
|
|
201
|
-
function createBindingSourceDiagnostics(source, options) {
|
|
202
|
-
const diagnostics = [];
|
|
203
|
-
const severity = getDiagnosticSeverity(options.strict);
|
|
204
|
-
if (!SOURCE_NAME_PATTERN.test(source.name)) {
|
|
205
|
-
diagnostics.push({
|
|
206
|
-
code: "invalid-source-name",
|
|
207
|
-
message: `Block binding source "${source.name}" must be lowercase and namespaced, such as "acme/profile-data".`,
|
|
208
|
-
severity,
|
|
209
|
-
sourceName: source.name,
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
if (options.server && !source.getValueCallback) {
|
|
213
|
-
diagnostics.push({
|
|
214
|
-
code: "missing-php-callback",
|
|
215
|
-
message: `Block binding source "${source.name}" needs getValueCallback when server registration is enabled.`,
|
|
216
|
-
severity,
|
|
217
|
-
sourceName: source.name,
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
if (options.fieldsList && !options.editor) {
|
|
221
|
-
diagnostics.push({
|
|
222
|
-
code: "fields-list-requires-editor",
|
|
223
|
-
message: `Block binding source "${source.name}" enables getFieldsList() without editor registration.`,
|
|
224
|
-
severity,
|
|
225
|
-
sourceName: source.name,
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
const seenFields = new Set();
|
|
229
|
-
for (const field of source.fields ?? []) {
|
|
230
|
-
if (!FIELD_NAME_PATTERN.test(field.name)) {
|
|
231
|
-
diagnostics.push({
|
|
232
|
-
code: "invalid-field-name",
|
|
233
|
-
fieldName: field.name,
|
|
234
|
-
message: `Block binding source "${source.name}" field "${field.name}" must be a stable identifier.`,
|
|
235
|
-
severity,
|
|
236
|
-
sourceName: source.name,
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
if (seenFields.has(field.name)) {
|
|
240
|
-
diagnostics.push({
|
|
241
|
-
code: "duplicate-field-name",
|
|
242
|
-
fieldName: field.name,
|
|
243
|
-
message: `Block binding source "${source.name}" declares duplicate field "${field.name}".`,
|
|
244
|
-
severity,
|
|
245
|
-
sourceName: source.name,
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
seenFields.add(field.name);
|
|
249
|
-
}
|
|
250
|
-
for (const target of source.bindableAttributes ?? []) {
|
|
251
|
-
if (!SOURCE_NAME_PATTERN.test(target.blockName)) {
|
|
252
|
-
diagnostics.push({
|
|
253
|
-
blockName: target.blockName,
|
|
254
|
-
code: "invalid-block-name",
|
|
255
|
-
message: `Bindable attributes target "${target.blockName}" must be a lowercase namespaced block name.`,
|
|
256
|
-
severity,
|
|
257
|
-
sourceName: source.name,
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
const seenAttributes = new Set();
|
|
261
|
-
for (const attribute of target.attributes) {
|
|
262
|
-
if (!FIELD_NAME_PATTERN.test(attribute)) {
|
|
263
|
-
diagnostics.push({
|
|
264
|
-
attribute,
|
|
265
|
-
blockName: target.blockName,
|
|
266
|
-
code: "invalid-bindable-attribute",
|
|
267
|
-
message: `Bindable attribute "${attribute}" for "${target.blockName}" must be a stable identifier.`,
|
|
268
|
-
severity,
|
|
269
|
-
sourceName: source.name,
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
if (seenAttributes.has(attribute)) {
|
|
273
|
-
diagnostics.push({
|
|
274
|
-
attribute,
|
|
275
|
-
blockName: target.blockName,
|
|
276
|
-
code: "duplicate-bindable-attribute",
|
|
277
|
-
message: `Bindable attribute "${attribute}" for "${target.blockName}" is declared more than once.`,
|
|
278
|
-
severity,
|
|
279
|
-
sourceName: source.name,
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
seenAttributes.add(attribute);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return diagnostics;
|
|
286
|
-
}
|
|
287
|
-
function handleBindingSourceDiagnostics(diagnostics, onDiagnostic, logger) {
|
|
288
|
-
handleDiagnostics(diagnostics, onDiagnostic, {
|
|
289
|
-
failureHeading: "WordPress block binding source check failed:",
|
|
290
|
-
logger,
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
7
|
export function getDefinedBindingSourceMetadata(source) {
|
|
294
8
|
return isObjectRecord(source)
|
|
295
9
|
? source[DEFINED_BLOCK_BINDING_SOURCE_METADATA]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BindingSourceAuthoringDiagnostic, BindingSourceDefinition, BindingSourceDiagnostic, DefineBindingSourceOptions } from "./bindings-core.js";
|
|
2
|
+
export declare function createBindingSourceDiagnostics(source: BindingSourceDefinition, options: {
|
|
3
|
+
readonly editor: boolean;
|
|
4
|
+
readonly fieldsList: boolean;
|
|
5
|
+
readonly server: boolean;
|
|
6
|
+
readonly strict: boolean;
|
|
7
|
+
}): readonly BindingSourceAuthoringDiagnostic[];
|
|
8
|
+
export declare function handleBindingSourceDiagnostics(diagnostics: readonly BindingSourceDiagnostic[], onDiagnostic: DefineBindingSourceOptions["onDiagnostic"], logger: DefineBindingSourceOptions["logger"]): void;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { getDiagnosticSeverity, handleDiagnostics } from "./shared/diagnostics.js";
|
|
2
|
+
const SOURCE_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\/[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u;
|
|
3
|
+
const FIELD_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]*$/u;
|
|
4
|
+
export function createBindingSourceDiagnostics(source, options) {
|
|
5
|
+
const diagnostics = [];
|
|
6
|
+
const severity = getDiagnosticSeverity(options.strict);
|
|
7
|
+
if (!SOURCE_NAME_PATTERN.test(source.name)) {
|
|
8
|
+
diagnostics.push({
|
|
9
|
+
code: "invalid-source-name",
|
|
10
|
+
message: `Block binding source "${source.name}" must be lowercase and namespaced, such as "acme/profile-data".`,
|
|
11
|
+
severity,
|
|
12
|
+
sourceName: source.name,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
if (options.server && !source.getValueCallback) {
|
|
16
|
+
diagnostics.push({
|
|
17
|
+
code: "missing-php-callback",
|
|
18
|
+
message: `Block binding source "${source.name}" needs getValueCallback when server registration is enabled.`,
|
|
19
|
+
severity,
|
|
20
|
+
sourceName: source.name,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
if (options.fieldsList && !options.editor) {
|
|
24
|
+
diagnostics.push({
|
|
25
|
+
code: "fields-list-requires-editor",
|
|
26
|
+
message: `Block binding source "${source.name}" enables getFieldsList() without editor registration.`,
|
|
27
|
+
severity,
|
|
28
|
+
sourceName: source.name,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
const seenFields = new Set();
|
|
32
|
+
for (const field of source.fields ?? []) {
|
|
33
|
+
if (!FIELD_NAME_PATTERN.test(field.name)) {
|
|
34
|
+
diagnostics.push({
|
|
35
|
+
code: "invalid-field-name",
|
|
36
|
+
fieldName: field.name,
|
|
37
|
+
message: `Block binding source "${source.name}" field "${field.name}" must be a stable identifier.`,
|
|
38
|
+
severity,
|
|
39
|
+
sourceName: source.name,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (seenFields.has(field.name)) {
|
|
43
|
+
diagnostics.push({
|
|
44
|
+
code: "duplicate-field-name",
|
|
45
|
+
fieldName: field.name,
|
|
46
|
+
message: `Block binding source "${source.name}" declares duplicate field "${field.name}".`,
|
|
47
|
+
severity,
|
|
48
|
+
sourceName: source.name,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
seenFields.add(field.name);
|
|
52
|
+
}
|
|
53
|
+
for (const target of source.bindableAttributes ?? []) {
|
|
54
|
+
if (!SOURCE_NAME_PATTERN.test(target.blockName)) {
|
|
55
|
+
diagnostics.push({
|
|
56
|
+
blockName: target.blockName,
|
|
57
|
+
code: "invalid-block-name",
|
|
58
|
+
message: `Bindable attributes target "${target.blockName}" must be a lowercase namespaced block name.`,
|
|
59
|
+
severity,
|
|
60
|
+
sourceName: source.name,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const seenAttributes = new Set();
|
|
64
|
+
for (const attribute of target.attributes) {
|
|
65
|
+
if (!FIELD_NAME_PATTERN.test(attribute)) {
|
|
66
|
+
diagnostics.push({
|
|
67
|
+
attribute,
|
|
68
|
+
blockName: target.blockName,
|
|
69
|
+
code: "invalid-bindable-attribute",
|
|
70
|
+
message: `Bindable attribute "${attribute}" for "${target.blockName}" must be a stable identifier.`,
|
|
71
|
+
severity,
|
|
72
|
+
sourceName: source.name,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (seenAttributes.has(attribute)) {
|
|
76
|
+
diagnostics.push({
|
|
77
|
+
attribute,
|
|
78
|
+
blockName: target.blockName,
|
|
79
|
+
code: "duplicate-bindable-attribute",
|
|
80
|
+
message: `Bindable attribute "${attribute}" for "${target.blockName}" is declared more than once.`,
|
|
81
|
+
severity,
|
|
82
|
+
sourceName: source.name,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
seenAttributes.add(attribute);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return diagnostics;
|
|
89
|
+
}
|
|
90
|
+
export function handleBindingSourceDiagnostics(diagnostics, onDiagnostic, logger) {
|
|
91
|
+
handleDiagnostics(diagnostics, onDiagnostic, {
|
|
92
|
+
failureHeading: "WordPress block binding source check failed:",
|
|
93
|
+
logger,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type WordPressBlockApiCompatibilityFeature, type WordPressBlockApiCompatibilityManifest, type WordPressCompatibilitySettings } from "./compatibility.js";
|
|
2
|
+
import type { BindingSourceVersionGates, DefineBindingSourceOptions } from "./bindings-core.js";
|
|
3
|
+
export interface BindingSourceCompatibilityFeatureSettings {
|
|
4
|
+
readonly editor?: boolean;
|
|
5
|
+
readonly fieldsList?: boolean;
|
|
6
|
+
readonly metadata?: boolean;
|
|
7
|
+
readonly server?: boolean;
|
|
8
|
+
readonly supportedAttributesFilter?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function createBindingCompatibilityManifest(features: readonly WordPressBlockApiCompatibilityFeature[], settings: WordPressCompatibilitySettings, gates: BindingSourceVersionGates): WordPressBlockApiCompatibilityManifest;
|
|
11
|
+
export declare function collectBindingSourceCompatibilityFeatures(settings?: BindingSourceCompatibilityFeatureSettings): readonly WordPressBlockApiCompatibilityFeature[];
|
|
12
|
+
export declare function createBindingSourceCompatibilityManifest(settings?: DefineBindingSourceOptions): WordPressBlockApiCompatibilityManifest;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { DEFAULT_WORDPRESS_COMPATIBILITY_MIN_VERSION, evaluateWordPressBlockApiCompatibility, } from "./compatibility.js";
|
|
2
|
+
import { resolveDefineBindingSourceSettings } from "./bindings-settings.js";
|
|
3
|
+
function getFeatureMinVersion(feature, fallback, gates) {
|
|
4
|
+
if (feature.area !== "blockBindings") {
|
|
5
|
+
return fallback;
|
|
6
|
+
}
|
|
7
|
+
switch (feature.feature) {
|
|
8
|
+
case "metadata.bindings":
|
|
9
|
+
case "serverRegistration":
|
|
10
|
+
return gates.server ?? fallback;
|
|
11
|
+
case "editorFieldsList":
|
|
12
|
+
return gates.fieldsList ?? fallback;
|
|
13
|
+
case "editorRegistration":
|
|
14
|
+
case "editorSourceLookup":
|
|
15
|
+
return gates.editor ?? fallback;
|
|
16
|
+
case "supportedAttributesFilter":
|
|
17
|
+
return gates.supportedAttributesFilter ?? gates.fieldsList ?? fallback;
|
|
18
|
+
default:
|
|
19
|
+
return fallback;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function createBindingCompatibilityManifest(features, settings, gates) {
|
|
23
|
+
const fallback = settings.minVersion ?? DEFAULT_WORDPRESS_COMPATIBILITY_MIN_VERSION;
|
|
24
|
+
const strict = settings.strict ?? true;
|
|
25
|
+
const allowUnknownFutureKeys = settings.allowUnknownFutureKeys ?? false;
|
|
26
|
+
const evaluations = features.map((feature) => evaluateWordPressBlockApiCompatibility(feature, {
|
|
27
|
+
allowUnknownFutureKeys,
|
|
28
|
+
minVersion: getFeatureMinVersion(feature, fallback, gates),
|
|
29
|
+
strict,
|
|
30
|
+
}));
|
|
31
|
+
const diagnostics = evaluations.flatMap((evaluation) => evaluation.diagnostic ? [evaluation.diagnostic] : []);
|
|
32
|
+
return {
|
|
33
|
+
allowUnknownFutureKeys,
|
|
34
|
+
diagnostics,
|
|
35
|
+
evaluations,
|
|
36
|
+
minVersion: fallback,
|
|
37
|
+
strict,
|
|
38
|
+
supported: evaluations.filter((evaluation) => evaluation.status === "supported"),
|
|
39
|
+
unknown: evaluations.filter((evaluation) => evaluation.status === "unknown"),
|
|
40
|
+
unsupported: evaluations.filter((evaluation) => evaluation.status === "unsupported"),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export function collectBindingSourceCompatibilityFeatures(settings = {}) {
|
|
44
|
+
const features = [];
|
|
45
|
+
if (settings.metadata ?? true) {
|
|
46
|
+
features.push({
|
|
47
|
+
area: "blockBindings",
|
|
48
|
+
feature: "metadata.bindings",
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (settings.server ?? true) {
|
|
52
|
+
features.push({
|
|
53
|
+
area: "blockBindings",
|
|
54
|
+
feature: "serverRegistration",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (settings.editor ?? true) {
|
|
58
|
+
features.push({
|
|
59
|
+
area: "blockBindings",
|
|
60
|
+
feature: "editorRegistration",
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (settings.fieldsList ?? false) {
|
|
64
|
+
features.push({
|
|
65
|
+
area: "blockBindings",
|
|
66
|
+
feature: "editorFieldsList",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (settings.supportedAttributesFilter ?? false) {
|
|
70
|
+
features.push({
|
|
71
|
+
area: "blockBindings",
|
|
72
|
+
feature: "supportedAttributesFilter",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return features;
|
|
76
|
+
}
|
|
77
|
+
export function createBindingSourceCompatibilityManifest(settings = {}) {
|
|
78
|
+
const resolved = resolveDefineBindingSourceSettings({}, settings, {
|
|
79
|
+
name: "wp-typia/binding-source",
|
|
80
|
+
});
|
|
81
|
+
return createBindingCompatibilityManifest(collectBindingSourceCompatibilityFeatures(resolved.features), resolved.compatibility, resolved.gates);
|
|
82
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { WordPressCompatibilitySettings, WordPressVersion } from "./compatibility.js";
|
|
2
|
+
import type { BindingSourceDefinition, BindingSourceVersionGates, DefineBindingSourceInlineOptions, DefineBindingSourceOptions, StripDefineBindingSourceOptions } from "./bindings-core.js";
|
|
3
|
+
export declare const DEFINE_BINDING_SOURCE_INLINE_OPTION_KEYS: Set<string>;
|
|
4
|
+
export interface ResolvedDefineBindingSourceSettings {
|
|
5
|
+
readonly compatibility: WordPressCompatibilitySettings;
|
|
6
|
+
readonly features: {
|
|
7
|
+
readonly editor: boolean;
|
|
8
|
+
readonly fieldsList: boolean;
|
|
9
|
+
readonly metadata: boolean;
|
|
10
|
+
readonly server: boolean;
|
|
11
|
+
readonly supportedAttributesFilter: boolean;
|
|
12
|
+
};
|
|
13
|
+
readonly gates: BindingSourceVersionGates;
|
|
14
|
+
readonly logger: DefineBindingSourceOptions["logger"];
|
|
15
|
+
readonly onDiagnostic: DefineBindingSourceOptions["onDiagnostic"];
|
|
16
|
+
readonly strict: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function isBindingSourceVersionGates(value: WordPressVersion | BindingSourceVersionGates | undefined): value is BindingSourceVersionGates;
|
|
19
|
+
export declare function splitDefineBindingSourceInput<TSource extends BindingSourceDefinition & DefineBindingSourceInlineOptions>(source: TSource): {
|
|
20
|
+
inlineOptions: DefineBindingSourceInlineOptions;
|
|
21
|
+
source: StripDefineBindingSourceOptions<TSource> & BindingSourceDefinition;
|
|
22
|
+
};
|
|
23
|
+
export declare function resolveMinWordPress(inlineOptions: DefineBindingSourceInlineOptions, options: DefineBindingSourceOptions): {
|
|
24
|
+
compatibility: WordPressCompatibilitySettings;
|
|
25
|
+
gates: BindingSourceVersionGates;
|
|
26
|
+
};
|
|
27
|
+
export declare function resolveDefineBindingSourceSettings(inlineOptions: DefineBindingSourceInlineOptions, options: DefineBindingSourceOptions, source: BindingSourceDefinition): ResolvedDefineBindingSourceSettings;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { isObjectRecord } from "./shared/object-utils.js";
|
|
2
|
+
export const DEFINE_BINDING_SOURCE_INLINE_OPTION_KEYS = new Set([
|
|
3
|
+
"allowUnknownFutureKeys",
|
|
4
|
+
"editor",
|
|
5
|
+
"fieldsList",
|
|
6
|
+
"logger",
|
|
7
|
+
"minVersion",
|
|
8
|
+
"minWordPress",
|
|
9
|
+
"minWordPressEditor",
|
|
10
|
+
"minWordPressFieldsList",
|
|
11
|
+
"minWordPressServer",
|
|
12
|
+
"minWordPressSupportedAttributesFilter",
|
|
13
|
+
"onDiagnostic",
|
|
14
|
+
"server",
|
|
15
|
+
"strict",
|
|
16
|
+
"supportedAttributesFilter",
|
|
17
|
+
]);
|
|
18
|
+
export function isBindingSourceVersionGates(value) {
|
|
19
|
+
return isObjectRecord(value);
|
|
20
|
+
}
|
|
21
|
+
export function splitDefineBindingSourceInput(source) {
|
|
22
|
+
const inlineOptions = {};
|
|
23
|
+
const normalizedSource = {};
|
|
24
|
+
for (const [key, value] of Object.entries(source)) {
|
|
25
|
+
if (DEFINE_BINDING_SOURCE_INLINE_OPTION_KEYS.has(key)) {
|
|
26
|
+
Object.assign(inlineOptions, { [key]: value });
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
normalizedSource[key] = value;
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
inlineOptions,
|
|
33
|
+
source: normalizedSource,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function resolveMinWordPress(inlineOptions, options) {
|
|
37
|
+
const optionMinWordPress = options.minWordPress;
|
|
38
|
+
const inlineMinWordPress = inlineOptions.minWordPress;
|
|
39
|
+
const optionGates = isBindingSourceVersionGates(optionMinWordPress)
|
|
40
|
+
? optionMinWordPress
|
|
41
|
+
: {};
|
|
42
|
+
const inlineGates = isBindingSourceVersionGates(inlineMinWordPress)
|
|
43
|
+
? inlineMinWordPress
|
|
44
|
+
: {};
|
|
45
|
+
const minVersion = options.minVersion ??
|
|
46
|
+
(typeof optionMinWordPress === "string" ? optionMinWordPress : undefined) ??
|
|
47
|
+
inlineOptions.minVersion ??
|
|
48
|
+
(typeof inlineMinWordPress === "string" ? inlineMinWordPress : undefined);
|
|
49
|
+
const compatibility = {
|
|
50
|
+
strict: options.strict ?? inlineOptions.strict ?? true,
|
|
51
|
+
};
|
|
52
|
+
if (options.allowUnknownFutureKeys ?? inlineOptions.allowUnknownFutureKeys) {
|
|
53
|
+
Object.assign(compatibility, {
|
|
54
|
+
allowUnknownFutureKeys: options.allowUnknownFutureKeys ?? inlineOptions.allowUnknownFutureKeys,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (minVersion !== undefined) {
|
|
58
|
+
Object.assign(compatibility, { minVersion });
|
|
59
|
+
}
|
|
60
|
+
const gates = {};
|
|
61
|
+
const editor = options.minWordPressEditor ??
|
|
62
|
+
optionGates.editor ??
|
|
63
|
+
inlineOptions.minWordPressEditor ??
|
|
64
|
+
inlineGates.editor;
|
|
65
|
+
const fieldsList = options.minWordPressFieldsList ??
|
|
66
|
+
optionGates.fieldsList ??
|
|
67
|
+
inlineOptions.minWordPressFieldsList ??
|
|
68
|
+
inlineGates.fieldsList;
|
|
69
|
+
const server = options.minWordPressServer ??
|
|
70
|
+
optionGates.server ??
|
|
71
|
+
inlineOptions.minWordPressServer ??
|
|
72
|
+
inlineGates.server;
|
|
73
|
+
const supportedAttributesFilter = options.minWordPressSupportedAttributesFilter ??
|
|
74
|
+
optionGates.supportedAttributesFilter ??
|
|
75
|
+
inlineOptions.minWordPressSupportedAttributesFilter ??
|
|
76
|
+
inlineGates.supportedAttributesFilter;
|
|
77
|
+
if (editor !== undefined) {
|
|
78
|
+
Object.assign(gates, { editor });
|
|
79
|
+
}
|
|
80
|
+
if (fieldsList !== undefined) {
|
|
81
|
+
Object.assign(gates, { fieldsList });
|
|
82
|
+
}
|
|
83
|
+
if (server !== undefined) {
|
|
84
|
+
Object.assign(gates, { server });
|
|
85
|
+
}
|
|
86
|
+
if (supportedAttributesFilter !== undefined) {
|
|
87
|
+
Object.assign(gates, { supportedAttributesFilter });
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
compatibility,
|
|
91
|
+
gates,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export function resolveDefineBindingSourceSettings(inlineOptions, options, source) {
|
|
95
|
+
const { compatibility, gates } = resolveMinWordPress(inlineOptions, options);
|
|
96
|
+
const strict = compatibility.strict ?? true;
|
|
97
|
+
const hasFields = (source.fields?.length ?? 0) > 0;
|
|
98
|
+
const hasBindableAttributes = (source.bindableAttributes?.length ?? 0) > 0;
|
|
99
|
+
return {
|
|
100
|
+
compatibility,
|
|
101
|
+
features: {
|
|
102
|
+
editor: options.editor ?? inlineOptions.editor ?? true,
|
|
103
|
+
fieldsList: options.fieldsList ?? inlineOptions.fieldsList ?? hasFields,
|
|
104
|
+
metadata: true,
|
|
105
|
+
server: options.server ?? inlineOptions.server ?? true,
|
|
106
|
+
supportedAttributesFilter: options.supportedAttributesFilter ??
|
|
107
|
+
inlineOptions.supportedAttributesFilter ??
|
|
108
|
+
hasBindableAttributes,
|
|
109
|
+
},
|
|
110
|
+
gates,
|
|
111
|
+
logger: options.logger ?? inlineOptions.logger,
|
|
112
|
+
onDiagnostic: options.onDiagnostic ?? inlineOptions.onDiagnostic,
|
|
113
|
+
strict,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { WordPressBlockApiCompatibilityDiagnostic } from "./compatibility.js";
|
|
2
|
+
import type { DefineSupportsOptions } from "./supports.js";
|
|
3
|
+
export declare function handleDefineSupportsDiagnostics(diagnostics: readonly WordPressBlockApiCompatibilityDiagnostic[], onDiagnostic: DefineSupportsOptions["onDiagnostic"], logger: DefineSupportsOptions["logger"]): void;
|