PluginProbe
Extendify / 3.2.1
Extendify v3.2.1
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
← All changes | src/Agent/lib/block-patch.js +46 -6 3.2.03.2.1 View file →
@@ -68,9 +68,21 @@
68 68 ];
69 69
70 70 // A known slug maps to a theme preset class; anything else routes to inline
71 71 // style.color.* — so "yellow" (no matching token) never lands on a wrong slug.
72 -const routeColors = (attributes, patch, colorSlugs) => {
72 +// Kept inline, a token's own hex stops the block following the palette.
73 +const slugForValue = (value, colorValues) => {
74 + const wanted = colord(value);
75 + if (!wanted.isValid()) return null;
76 + const hex = wanted.toHex();
77 + const match = Object.entries(colorValues ?? {}).find(([, preset]) => {
78 + const parsed = colord(String(preset));
79 + return parsed.isValid() && parsed.toHex() === hex;
80 + });
81 + return match?.[0] ?? null;
82 +};
83 +
84 +const routeColors = (attributes, patch, colorSlugs, colorValues) => {
73 85 const slugs = new Set(colorSlugs ?? []);
74 86 const stripped = {};
75 87 let out = attributes;
76 88 for (const [named, key] of COLOR_CHANNELS) {
@@ -75,9 +87,13 @@
75 87 let out = attributes;
76 88 for (const [named, key] of COLOR_CHANNELS) {
77 89 const value = patch?.[named];
78 90 if (value == null) continue;
79 - if (slugs.has(value)) {
91 + const named_slug = slugs.has(value)
92 + ? value
93 + : slugForValue(value, colorValues);
94 + if (named_slug) {
95 + if (named_slug !== value) out = setPath(out, named, named_slug);
80 96 out = unsetPath(out, `style.color.${key}`);
81 97 continue;
82 98 }
83 99 const parsed = colord(value);
@@ -175,8 +191,24 @@
175 191 };
176 192
177 193 // Re-serializing runs the block's own save(), which core/button needs to render
178 194 // the color/border styles it marks __experimentalSkipSerialization.
195 +// Merging an empty value leaves a dead key and keeps the preset class.
196 +const emptyLeafPaths = (patch, prefix = '') =>
197 + Object.entries(patch ?? {}).flatMap(([key, value]) => {
198 + const path = prefix ? `${prefix}.${key}` : key;
199 + if (isMergeable(value)) return emptyLeafPaths(value, path);
200 + return value === '' ? [path] : [];
201 + });
202 +
203 +const withoutEmptyLeaves = (patch) =>
204 + Object.fromEntries(
205 + Object.entries(patch ?? {}).flatMap(([key, value]) => {
206 + if (isMergeable(value)) return [[key, withoutEmptyLeaves(value)]];
207 + return value === '' ? [] : [[key, value]];
208 + }),
209 + );
210 +
179 211 export const applyBlockPatch = (
180 212 serializedBlock,
181 213 patch,
182 214 clear = [],
@@ -183,14 +215,22 @@
183 215 presetSlugs = {},
184 216 ) => {
185 217 const blocks = parse(serializedBlock).map((block) => {
186 218 if (!block.name) return block;
187 - const merged = deepMerge(block.attributes, remapText(block, patch));
219 + const remapped = remapText(block, patch);
220 + const filled = withoutEmptyLeaves(remapped);
221 + const merged = deepMerge(block.attributes, filled);
188 222 const routed = routeNamedPresets(
189 - routeColors(merged, patch, presetSlugs.color),
190 - patch,
223 + routeColors(merged, filled, presetSlugs.color, presetSlugs.colorValues),
224 + filled,
191 225 presetSlugs,
192 226 );
193 - return { ...block, attributes: applyClears(routed, clear ?? []) };
227 + return {
228 + ...block,
229 + attributes: applyClears(routed, [
230 + ...(clear ?? []),
231 + ...emptyLeafPaths(remapped),
232 + ]),
233 + };
194 234 });
195 235 return serialize(blocks);
196 236 };