UNPKG

@wordpress/block-library

Version:
104 lines (103 loc) 3.73 kB
// packages/block-library/src/table-of-contents/hooks.js import fastDeepEqual from "fast-deep-equal/es6"; import { useRegistry } from "@wordpress/data"; import { __unstableStripHTML as stripHTML } from "@wordpress/dom"; import { useEffect } from "@wordpress/element"; import { addQueryArgs, removeQueryArgs } from "@wordpress/url"; import { store as blockEditorStore } from "@wordpress/block-editor"; function getLatestHeadings(select, clientId) { const { getBlockAttributes, getBlockName, getBlocksByName, getClientIdsOfDescendants } = select(blockEditorStore); const permalink = select("core/editor").getPermalink() ?? null; const isPaginated = getBlocksByName("core/nextpage").length !== 0; const { onlyIncludeCurrentPage, maxLevel } = getBlockAttributes(clientId) ?? {}; const [postContentClientId = ""] = getBlocksByName("core/post-content"); const allBlockClientIds = getClientIdsOfDescendants(postContentClientId); let tocPage = 1; if (isPaginated && onlyIncludeCurrentPage) { const tocIndex = allBlockClientIds.indexOf(clientId); for (const [ blockIndex, blockClientId ] of allBlockClientIds.entries()) { if (blockIndex >= tocIndex) { break; } if (getBlockName(blockClientId) === "core/nextpage") { tocPage++; } } } const latestHeadings = []; let headingPage = 1; let headingPageLink = null; if (typeof permalink === "string") { headingPageLink = isPaginated ? addQueryArgs(permalink, { page: headingPage }) : permalink; } for (const blockClientId of allBlockClientIds) { const blockName = getBlockName(blockClientId); if (blockName === "core/nextpage") { headingPage++; if (onlyIncludeCurrentPage && headingPage > tocPage) { break; } if (typeof permalink === "string") { headingPageLink = addQueryArgs( removeQueryArgs(permalink, ["page"]), { page: headingPage } ); } } else if (!onlyIncludeCurrentPage || headingPage === tocPage) { if (blockName === "core/heading") { const headingAttributes = getBlockAttributes(blockClientId); if (maxLevel && headingAttributes.level > maxLevel) { continue; } const canBeLinked = typeof headingPageLink === "string" && typeof headingAttributes.anchor === "string" && headingAttributes.anchor !== ""; latestHeadings.push({ // Convert line breaks to spaces, and get rid of HTML tags in the headings. content: stripHTML( headingAttributes.content.replace( /(<br *\/?>)+/g, " " ) ), level: headingAttributes.level, link: canBeLinked ? `${headingPageLink}#${headingAttributes.anchor}` : null }); } } } return latestHeadings; } function observeCallback(select, dispatch, clientId) { const { getBlockAttributes } = select(blockEditorStore); const { updateBlockAttributes, __unstableMarkNextChangeAsNotPersistent } = dispatch(blockEditorStore); const attributes = getBlockAttributes(clientId); if (attributes === null) { return; } const headings = getLatestHeadings(select, clientId); if (!fastDeepEqual(headings, attributes.headings)) { window.queueMicrotask(() => { __unstableMarkNextChangeAsNotPersistent(); updateBlockAttributes(clientId, { headings }); }); } } function useObserveHeadings(clientId) { const registry = useRegistry(); useEffect(() => { return registry.subscribe( () => observeCallback(registry.select, registry.dispatch, clientId) ); }, [registry, clientId]); } export { useObserveHeadings }; //# sourceMappingURL=hooks.js.map