@imwz/wp-pattern-sentinel 1.1.1 → 1.1.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/package.json +1 -1
- package/src/editor.js +15 -0
- package/src/validation.js +38 -0
package/package.json
CHANGED
package/src/editor.js
CHANGED
|
@@ -113,6 +113,21 @@ export async function insertPatternIntoEditor(page, blockContent, verbose = fals
|
|
|
113
113
|
{ timeout: 15000 }
|
|
114
114
|
);
|
|
115
115
|
|
|
116
|
+
// Nested `core/pattern` placeholders are swapped for the referenced
|
|
117
|
+
// pattern's blocks asynchronously, once the pattern registry has loaded.
|
|
118
|
+
// Wait for that so the save and the content comparison see the expanded
|
|
119
|
+
// tree. Unregistered slugs never expand, so a timeout here is non-fatal.
|
|
120
|
+
if (/<!-- wp:pattern\s/.test(blockContent)) {
|
|
121
|
+
await page
|
|
122
|
+
.waitForFunction(() => {
|
|
123
|
+
const hasPattern = blocks => blocks.some(
|
|
124
|
+
b => b.name === 'core/pattern' || hasPattern(b.innerBlocks ?? [])
|
|
125
|
+
);
|
|
126
|
+
return !hasPattern(window.wp.data.select('core/block-editor').getBlocks());
|
|
127
|
+
}, { timeout: 10000 })
|
|
128
|
+
.catch(() => {});
|
|
129
|
+
}
|
|
130
|
+
|
|
116
131
|
if (verbose) log(' → Pattern inserted', 'gray');
|
|
117
132
|
return true;
|
|
118
133
|
} catch (error) {
|
package/src/validation.js
CHANGED
|
@@ -93,6 +93,33 @@ const collapseInterTagWhitespace = str => str.replace(/>\s+</g, '><');
|
|
|
93
93
|
const normalizeForComparison = str =>
|
|
94
94
|
collapseInterTagWhitespace(normalizeBlockAttrJson(normalizeCssProps(stripNavRef(str))));
|
|
95
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Matches a nested pattern reference: `<!-- wp:pattern {"slug":"theme/x"} /-->`.
|
|
98
|
+
* The editor replaces these with the referenced pattern's blocks, so the
|
|
99
|
+
* source must be expanded the same way before it can be diffed.
|
|
100
|
+
*/
|
|
101
|
+
const PATTERN_REF = /<!-- wp:pattern (\{[\s\S]*?\}) \/-->/g;
|
|
102
|
+
|
|
103
|
+
/** Map of registered pattern name → raw content, read from the REST API. */
|
|
104
|
+
const fetchRegisteredPatterns = page =>
|
|
105
|
+
page.evaluate(async () => {
|
|
106
|
+
const patterns = await window.wp.apiFetch({ path: '/wp/v2/block-patterns/patterns' });
|
|
107
|
+
return Object.fromEntries(patterns.map(p => [p.name, p.content]));
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Recursively substitute each `wp:pattern` reference with the referenced
|
|
112
|
+
* pattern's content. Unregistered slugs and self-references are left as-is,
|
|
113
|
+
* mirroring the editor, which leaves those `core/pattern` blocks unexpanded.
|
|
114
|
+
*/
|
|
115
|
+
const expandPatternRefs = (str, registry, seen = []) =>
|
|
116
|
+
str.replace(PATTERN_REF, (match, json) => {
|
|
117
|
+
let slug;
|
|
118
|
+
try { slug = JSON.parse(json).slug; } catch { return match; }
|
|
119
|
+
if (typeof registry[slug] !== 'string' || seen.includes(slug)) return match;
|
|
120
|
+
return expandPatternRefs(registry[slug], registry, [...seen, slug]);
|
|
121
|
+
});
|
|
122
|
+
|
|
96
123
|
/**
|
|
97
124
|
* Compare the editor's serialized output against the original source.
|
|
98
125
|
* Whitespace-normalizes both sides before diffing to avoid false positives
|
|
@@ -108,6 +135,17 @@ export async function compareContent(page, originalContent, verbose = false) {
|
|
|
108
135
|
);
|
|
109
136
|
result.savedContent = savedContent;
|
|
110
137
|
|
|
138
|
+
if (originalContent.includes('<!-- wp:pattern ')) {
|
|
139
|
+
try {
|
|
140
|
+
originalContent = expandPatternRefs(originalContent, await fetchRegisteredPatterns(page));
|
|
141
|
+
} catch (error) {
|
|
142
|
+
result.warnings.push({
|
|
143
|
+
type: 'pattern_ref_unresolved',
|
|
144
|
+
message: `Could not resolve nested wp:pattern references: ${error.message}`,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
111
149
|
const normalize = str => str.replace(/\s+/g, ' ').trim();
|
|
112
150
|
if (normalize(normalizeForComparison(savedContent)) === normalize(normalizeForComparison(originalContent))) {
|
|
113
151
|
if (verbose) log(' → Content matches', 'gray');
|