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
extendify / src / QuickEdit / lib / fingerprint.js

fingerprint.js in Extendify 3.2.1, at src/QuickEdit/lib/fingerprint.js

40 lines 1.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 // The clicked block's render-time identity, sent with every save so the server
2 // can refuse (409) when its parse-time block count resolves to a different
3 // block of the same type — synced patterns, nested navs, and dynamic expansion
4 // all desync the two counts past the type guard.
5 //
6 // Read from the LIVE element the user clicked, never the cached block source:
7 // that source is resolved by the same count as the save, so it would echo a
8 // misresolve and the check would pass on the wrong block.
9
10 // The client reads the block's text from the rendered DOM, where the_content
11 // has run wptexturize (straight quotes → curly, -- → dash, ... → ellipsis);
12 // the server fingerprints the raw stored markup. Fold those substitutions back
13 // to ASCII so an apostrophe alone ("Woody's" vs "Woody’s") can't false a 409.
14 // `\s` already covers non-breaking/unicode spaces in JS. Must stay in lockstep
15 // with BlockFingerprint::normalize on the PHP side.
16 export const normalizeText = (value) =>
17 String(value ?? '')
18 .replace(/[‘’‚‛]/g, "'")
19 .replace(/[“”„‟]/g, '"')
20 .replace(/[‒–—―]/g, '-')
21 .replace(/-{2,}/g, '-')
22 .replace(//g, '...')
23 .replace(/\s+/g, ' ')
24 .trim();
25
26 // The live→canvas swap-reveal poll compares the canvas editable's text against
27 // the live block's rendered text to know when the editor has caught up. The
28 // live text is wptexturize'd (curly) and the editable is raw (straight), so
29 // both sides must fold through normalizeText — a whitespace-only compare leaves
30 // a smart-quote block forever unequal, stranding the reveal on its frame-cap.
31 export const normalizedTextEquals = (a, b) =>
32 normalizeText(a) === normalizeText(b);
33
34 // Omitted (null) when the element has no visible text, so blocks like images
35 // fail open instead of 409-ing on an empty match.
36 export const textFingerprint = (el) => {
37 const text = normalizeText(el?.textContent);
38 return text ? { text } : null;
39 };
40