PluginProbe
Block Animations, Motion & Scroll Effects – Ghost Kit / 3.3.2
Block Animations, Motion & Scroll Effects – Ghost Kit v3.3.2
3.7.2 3.7.1 3.7.0 3.6.1 trunk 1.6.3 2.25.0 3.3.0 3.3.1 3.3.2 3.3.3 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.6.0
ghostkit / gutenberg / extend / toc-headings / index.js

index.js in Block Animations, Motion & Scroll Effects – Ghost Kit 3.3.2, at gutenberg/extend/toc-headings/index.js

124 lines 2.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { debounce } from 'throttle-debounce';
2
3 import { select, subscribe } from '@wordpress/data';
4
5 import { getSlug } from '../../utils/get-unique-slug';
6
7 /**
8 * Get available TOC block.
9 *
10 * @param {Array | boolean} blocks blocks array.
11 *
12 * @return {Array} toc block data.
13 */
14 function getTOC(blocks = false) {
15 let result = false;
16
17 if (!blocks) {
18 const { getBlocks } = select('core/block-editor');
19
20 blocks = getBlocks();
21 }
22
23 blocks.forEach((block) => {
24 if (!result) {
25 if (block.name === 'ghostkit/table-of-contents') {
26 result = block;
27 } else if (block.innerBlocks && block.innerBlocks.length) {
28 result = getTOC(block.innerBlocks);
29 }
30 }
31 });
32
33 return result;
34 }
35
36 /**
37 * Get available heading blocks.
38 *
39 * @param {Array} blocks blocks array.
40 *
41 * @return {Array} toc block data.
42 */
43 function getHeadings(blocks = false) {
44 let result = [];
45
46 if (!blocks) {
47 const { getBlocks } = select('core/block-editor');
48
49 blocks = getBlocks();
50 }
51
52 blocks.forEach((block) => {
53 if (block.name === 'core/heading') {
54 result.push(block);
55 } else if (block.innerBlocks && block.innerBlocks.length) {
56 result = [...result, ...getHeadings(block.innerBlocks)];
57 }
58 });
59
60 return result;
61 }
62
63 let prevHeadings = '';
64
65 /**
66 * Update heading ID.
67 */
68 function updateHeadingIDs() {
69 const tocBlock = getTOC();
70
71 if (!tocBlock) {
72 return;
73 }
74
75 const headings = getHeadings();
76
77 if (prevHeadings && prevHeadings === JSON.stringify(headings)) {
78 return;
79 }
80
81 const collisionCollector = {};
82
83 headings.forEach((block) => {
84 let { anchor } = block.attributes;
85
86 const { content } = block.attributes;
87
88 // create new
89 if (content && !anchor) {
90 anchor = getSlug(content);
91 block.attributes.anchor = anchor;
92 }
93
94 // check collisions.
95 if (anchor) {
96 if (typeof collisionCollector[anchor] !== 'undefined') {
97 collisionCollector[anchor] += 1;
98 anchor += `-${collisionCollector[anchor]}`;
99 block.attributes.anchor = anchor;
100 } else {
101 collisionCollector[anchor] = 1;
102 }
103 }
104 });
105
106 prevHeadings = JSON.stringify(headings);
107 }
108
109 const updateHeadingIDsDebounce = debounce(300, updateHeadingIDs);
110
111 /**
112 * Subscribe to all editor changes.
113 * We don't need to run this code in WordPress >= 5.9, as anchors already adds automatically.
114 */
115 if (
116 !wp.blockEditor.__experimentalBlockPatternSetup &&
117 !wp.blockEditor.BlockPatternSetup &&
118 !wp.blockEditor.blockPatternSetup
119 ) {
120 subscribe(() => {
121 updateHeadingIDsDebounce();
122 });
123 }
124