Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Works (except for the icons)D
  • Loading branch information
George Hotelling committed Apr 8, 2020
commit eca78b45518e982198061336e5fe2e2cc9393639
7 changes: 6 additions & 1 deletion blocks/toc/src/block.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{
"name": "jetpack/toc",
"category": "layout",
"attributes": {}
"attributes": {
"ListType": {
"type": "string",
"default": "ol"
}
}
}
90 changes: 63 additions & 27 deletions blocks/toc/src/edit.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
/**
* Internal dependencies
* WordPress dependencies
*/
import Tree from "./tree";
import { BlockControls } from "@wordpress/block-editor";
import { ToolbarGroup } from "@wordpress/components";
import { useDispatch, useSelect } from "@wordpress/data";
import { useEffect } from "@wordpress/element";
import { __ } from "@wordpress/i18n";
import { formatListBullets, formatListNumbered } from "@wordpress/icons";

/**
* WordPress dependencies
* Internal dependencies
*/
import { useDispatch, useSelect } from "@wordpress/data";
import Tree from "./tree";

/**
* External dependencies
*/
import { kebabCase } from "lodash";
import { kebabCase, last } from "lodash";

const node = block => ({
children: [],
Expand All @@ -20,31 +25,32 @@ const node = block => ({
content: block.attributes.content
});

const parent = stack => last(stack);
const sibling = stack => last(parent(stack).children);

const nestTree = blocks => {
const targetStack = [];
const rootNode = node({ attributes: { level: 0 } });
let prevNode = rootNode;
let target = rootNode;
for (let i = 0; i < blocks.length; i++) {
rootNode.children = [node(blocks[0])];
const nodeStack = [rootNode];
for (let i = 1; i < blocks.length; i++) {
const currentNode = node(blocks[i]);
let parentNode = parent(nodeStack);
let siblingNode = sibling(nodeStack);

// if it has the same level, append it to target
if (currentNode.level === prevNode.level) {
target.children.push(currentNode);
} else if (currentNode.level > prevNode.level) {
// if it has a higher level, push target onto stack, set target to current children, append it to target
targetStack.push(prevNode);
target = prevNode;
target.children.push(currentNode);
} else if (currentNode.level < prevNode.level) {
// if it has a lower level, set target to stack pop value, append it to target
do {
target = targetStack.pop(); // TODO wrap in while loop
} while (target.level > currentNode.level);
target.children.push(currentNode);
if (currentNode.level === siblingNode.level) {
parentNode.children.push(currentNode);
} else if (siblingNode.level < currentNode.level) {
nodeStack.push(siblingNode);
siblingNode.children.push(currentNode);
} else if (currentNode.level < siblingNode.level) {
while (currentNode.level < siblingNode.level) {
siblingNode = nodeStack.pop();
parentNode = parent(nodeStack);
}
parentNode.children.push(currentNode);
}
prevNode = currentNode;
}

return rootNode.children;
};

Expand All @@ -58,7 +64,7 @@ const makeAnchor = (title, usedAnchors) => {
return titleCandidate;
};

export default ({ setAttributes }) => {
export default ({ attributes, setAttributes }) => {
const { updateBlockAttributes } = useDispatch("core/editor");

const { headings, anchors } = useSelect(select => {
Expand Down Expand Up @@ -93,7 +99,37 @@ export default ({ setAttributes }) => {
});

const nodes = nestTree(headings);
setAttributes({ nodes });
useEffect(() => {
setAttributes({ nodes });
}, [...headings]);

const ListType = attributes.ordered ? "ol" : "ul";

return <Tree nodes={nodes} />;
return (
<>
<BlockControls>
<ToolbarGroup
controls={[
{
icon: formatListBullets,
title: __("Convert to unordered list"),
isActive: ListType === "ul",
onClick() {
setAttributes({ ordered: false });
}
},
{
icon: formatListNumbered,
title: __("Convert to ordered list"),
isActive: ListType === "ol",
onClick() {
setAttributes({ ordered: true });
}
}
]}
/>
</BlockControls>
<Tree nodes={nodes} ListType={ListType} />
</>
);
};
6 changes: 3 additions & 3 deletions blocks/toc/src/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import Tree from "./tree";

export default ({ attributes }) => {
const { nodes } = attributes;

return <Tree nodes={nodes} />;
const { nodes, ordered } = attributes;
const ListType = ordered ? "ol" : "ul";
return <Tree nodes={nodes} ListType={ListType} />;
};
8 changes: 4 additions & 4 deletions blocks/toc/src/tree.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
const Tree = ({ nodes }) => {
const Tree = ({ nodes, ListType }) => {
if (!nodes || !nodes.length) {
return null;
}

return (
<ul>
<ListType>
{nodes.map(node => {
const { children, anchor, content } = node;

return (
<li key={anchor}>
<a href={"#" + anchor}>{content}</a>
<Tree nodes={children} />
<Tree nodes={children} ListType={ListType} />
</li>
);
})}
</ul>
</ListType>
);
};

Expand Down