Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions packages/block-library/src/heading/autogenerate-anchors.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
*/
import { deburr, trim } from 'lodash';

/**
* Object map tracking anchors.
*
* @type {Record<string, string | null>}
*/
const anchors = {};

/**
* Returns the text without markup.
*
Expand Down Expand Up @@ -36,30 +43,39 @@ const getSlug = ( content ) => {
/**
* Generate the anchor for a heading.
*
* @param {string} clientId The block ID.
* @param {string} content The block content.
* @param {string[]} allHeadingAnchors An array containing all headings anchors.
* @param {string} clientId The block ID.
* @param {string} content The block content.
*
* @return {string|null} Return the heading anchor.
*/
export const generateAnchor = ( clientId, content, allHeadingAnchors ) => {
export const generateAnchor = ( clientId, content ) => {
const slug = getSlug( content );
// If slug is empty, then return null.
// Returning null instead of an empty string allows us to check again when the content changes.
if ( '' === slug ) {
return null;
}

delete allHeadingAnchors[ clientId ];
delete anchors[ clientId ];

let anchor = slug;
let i = 0;

// If the anchor already exists in another heading, append -i.
while ( Object.values( allHeadingAnchors ).includes( anchor ) ) {
while ( Object.values( anchors ).includes( anchor ) ) {
i += 1;
anchor = slug + '-' + i;
}

return anchor;
};

/**
* Set the anchor for a heading.
*
* @param {string} clientId The block ID.
* @param {string|null} anchor The block anchor.
*/
export const setAnchor = ( clientId, anchor ) => {
anchors[ clientId ] = anchor;
};
21 changes: 7 additions & 14 deletions packages/block-library/src/heading/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ import {
* Internal dependencies
*/
import HeadingLevelDropdown from './heading-level-dropdown';
import { generateAnchor } from './autogenerate-anchors';

const allHeadingAnchors = {};
import { generateAnchor, setAnchor } from './autogenerate-anchors';

function HeadingEdit( {
attributes,
Expand Down Expand Up @@ -54,28 +52,23 @@ function HeadingEdit( {
// This side-effect should not create an undo level.
__unstableMarkNextChangeAsNotPersistent();
setAttributes( {
anchor: generateAnchor( clientId, content, allHeadingAnchors ),
anchor: generateAnchor( clientId, content ),
} );
}
setAnchor( clientId, anchor );

allHeadingAnchors[ clientId ] = anchor;
return () => {
delete allHeadingAnchors[ clientId ];
};
// Remove anchor map when block unmounts.
return () => setAnchor( clientId, null );
}, [ content, anchor ] );

const onContentChange = ( value ) => {
const newAttrs = { content: value };
if (
! anchor ||
! value ||
generateAnchor( clientId, content, allHeadingAnchors ) === anchor
generateAnchor( clientId, content ) === anchor
) {
newAttrs.anchor = generateAnchor(
clientId,
value,
allHeadingAnchors
);
newAttrs.anchor = generateAnchor( clientId, value );
}
setAttributes( newAttrs );
};
Expand Down