| 1 |
import { fetchBlockCodeById } from '@agent/lib/block-code'; |
| 2 |
import { applyBlockPatch } from '@agent/lib/block-patch'; |
| 3 |
import { ensureCoreBlocksRegistered } from '@agent/lib/register-blocks'; |
| 4 |
import { getBlockType, parse } from '@wordpress/blocks'; |
| 5 |
|
| 6 |
// An accordion question keeps its text in `title`, not `content`. |
| 7 |
const richTextAttribute = (markup) => { |
| 8 |
const attributes = getBlockType(parse(markup)[0]?.name)?.attributes ?? {}; |
| 9 |
return Object.keys(attributes).find( |
| 10 |
(name) => attributes[name].source === 'rich-text', |
| 11 |
); |
| 12 |
}; |
| 13 |
|
| 14 |
// null means no rewrite landed, so the save clones the original instead. |
| 15 |
export const duplicateMarkup = async ({ blockId, texts }, source, postId) => { |
| 16 |
if (!texts?.length) return null; |
| 17 |
await ensureCoreBlocksRegistered(); |
| 18 |
const original = await fetchBlockCodeById(blockId, source, postId); |
| 19 |
if (!original) return null; |
| 20 |
const inner = await Promise.all( |
| 21 |
texts.map(({ blockId: id }) => fetchBlockCodeById(id, source, postId)), |
| 22 |
); |
| 23 |
let copy = original; |
| 24 |
for (const [index, code] of inner.entries()) { |
| 25 |
const attribute = code && richTextAttribute(code); |
| 26 |
if (!attribute || !copy.includes(code)) continue; |
| 27 |
const rewritten = applyBlockPatch(code, { |
| 28 |
[attribute]: texts[index].text, |
| 29 |
}); |
| 30 |
copy = copy.replace(code, () => rewritten); |
| 31 |
} |
| 32 |
return copy === original ? null : copy; |
| 33 |
}; |
| 34 |
|