Add Children "only, includeFolders, reverse" flags, add document unhideSelf (#209)

This commit is contained in:
Serge Latyntsev 2019-11-21 10:26:11 +13:00 committed by Aaron Carlino
parent 4fa94b50d0
commit fa241c0f61
5 changed files with 71 additions and 40 deletions

View File

@ -12,7 +12,7 @@ const createSlug = (filePath, version) => {
.toLowerCase() .toLowerCase()
}; };
exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNodeId, createContentDigest }) => { exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNodeId, createContentDigest }) => {
if (node.internal.type !== 'MarkdownRemark') { if (node.internal.type !== 'MarkdownRemark') {
return; return;
} }
@ -29,14 +29,14 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
if (version.match(/^watcher--/)) { if (version.match(/^watcher--/)) {
const existing = getNodesByType('SilverstripeDocument') const existing = getNodesByType('SilverstripeDocument')
.find(n => n.fileAbsolutePath === node.fileAbsolutePath); .find(n => n.fileAbsolutePath === node.fileAbsolutePath);
if (existing) { if (existing) {
// Pair the document with its watched file so we can inject it into the template // Pair the document with its watched file so we can inject it into the template
// as a dependency. // as a dependency.
existing.watchFile___NODE = node.id; existing.watchFile___NODE = node.id;
return; return;
} }
} }
const filePath = createFilePath({ const filePath = createFilePath({
node, node,
@ -51,6 +51,7 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
const docTitle = fileToTitle(fileTitle); const docTitle = fileToTitle(fileTitle);
const slug = createSlug(filePath, version); const slug = createSlug(filePath, version);
const parentSlug = `${path.resolve(slug, '../')}/`; const parentSlug = `${path.resolve(slug, '../')}/`;
const unhideSelf = false;
const docData = { const docData = {
isIndex, isIndex,
@ -58,7 +59,8 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
fileTitle, fileTitle,
slug, slug,
parentSlug, parentSlug,
...node.frontmatter, unhideSelf,
...node.frontmatter,
}; };
if (!docData.title || docData.title === '') { if (!docData.title || docData.title === '') {
@ -72,7 +74,7 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
rawMarkdownBody: node.rawMarkdownBody, rawMarkdownBody: node.rawMarkdownBody,
}), }),
}; };
const nodeData = { const nodeData = {
...node, ...node,
id: createNodeId(`SilverstripeDocument${node.id}`), id: createNodeId(`SilverstripeDocument${node.id}`),
...docData, ...docData,
@ -95,7 +97,7 @@ exports.createPages = async ({ actions, graphql }) => {
slug slug
} }
} }
}`); }`);
if (result.errors) { if (result.errors) {
@ -111,6 +113,6 @@ exports.createPages = async ({ actions, graphql }) => {
slug: node.slug, slug: node.slug,
} }
}); });
}) })
}; };

View File

@ -11,7 +11,7 @@ const createCards = (children: SilverstripeDocument[]): ReactElement[] => {
<div className="card shadow-sm"> <div className="card shadow-sm">
<div className="card-body"> <div className="card-body">
<h5 className="card-title"> <h5 className="card-title">
<span className="theme-icon-holder card-icon-holder mr-2"> <span className="theme-icon-holder card-icon-holder mr-2">
<i className={iconClass}></i> <i className={iconClass}></i>
</span> </span>
<span className="card-title-text">{title}</span> <span className="card-title-text">{title}</span>
@ -28,7 +28,7 @@ const createCards = (children: SilverstripeDocument[]): ReactElement[] => {
}; };
const createList = (children: SilverstripeDocument[]): ReactElement[] => { const createList = (children: SilverstripeDocument[]): ReactElement[] => {
return children.map(({ summary, slug, title }) => { return children.map(({ summary, slug, title }) => {
return ( return (
<React.Fragment key={slug}> <React.Fragment key={slug}>
<dt><Link to={slug}>{title}</Link></dt> <dt><Link to={slug}>{title}</Link></dt>
@ -38,33 +38,40 @@ const createList = (children: SilverstripeDocument[]): ReactElement[] => {
}); });
}; };
const ChildrenOf: StatelessComponent<ChildrenOfProps> = ({ folderName, exclude, currentNode, asList }) => { const ChildrenOf: StatelessComponent<ChildrenOfProps> = ({ folderName, exclude, only, currentNode, asList, includeFolders, reverse }) => {
if (!currentNode) { if (!currentNode) {
return null; return null;
} }
let children: ReactElement[] = [];
if (!folderName && !exclude) { var nodes: SilverstripeDocument[] = [];
const sourceNodes = currentNode.isIndex ? getChildren(currentNode, false) : getSiblings(currentNode)
children = asList ? createList(sourceNodes) : createCards(sourceNodes); if (!folderName && !exclude && !only) {
nodes = currentNode.isIndex ? getChildren(currentNode, false) : getSiblings(currentNode)
} else if (folderName) { } else if (folderName) {
const targetFolder = getChildren(currentNode, true).find( const targetFolder = getChildren(currentNode, true).find(
child => child.isIndex && child.fileTitle.toLowerCase() === folderName.toLowerCase() child => child.isIndex && child.fileTitle.toLowerCase() === folderName.toLowerCase()
); );
if (targetFolder) { if (targetFolder) {
children = asList nodes = getChildren(targetFolder, false);
? createList(getChildren(targetFolder, false))
: createCards(getChildren(targetFolder, false));
} else {
children = [];
} }
} else if (exclude) { } else if (exclude) {
const exclusions = exclude.split(',').map(e => e.toLowerCase()); const exclusions = exclude.split(',').map(e => e.toLowerCase());
const nodes = getChildren(currentNode, false).filter( nodes = getChildren(currentNode, includeFolders).filter(
child => !exclusions.includes(child.fileTitle.toLowerCase()) child => !exclusions.includes(child.fileTitle.toLowerCase())
); );
children = asList ? createList(nodes) : createCards(nodes); } else if (only) {
const inclusions = only.split(',').map(e => e.toLowerCase());
nodes = getChildren(currentNode, includeFolders).filter(
child => inclusions.includes(child.fileTitle.toLowerCase())
);
} }
if (reverse) {
nodes.reverse();
}
let children: ReactElement[] = asList ? createList(nodes) : createCards(nodes);
return ( return (
<div className="docs-overview py-5"> <div className="docs-overview py-5">
{asList && {asList &&

View File

@ -19,7 +19,7 @@ export interface SinglePage {
webLink: string; webLink: string;
} }
} }
} }
}; };
@ -33,6 +33,7 @@ export interface SilverstripeDocument {
iconBrand?: string; iconBrand?: string;
hideChildren?: boolean; hideChildren?: boolean;
hideSelf?: boolean; hideSelf?: boolean;
unhideSelf?: boolean;
parentSlug: string; parentSlug: string;
summary: string; summary: string;
fileTitle: string; fileTitle: string;
@ -48,6 +49,9 @@ export interface HierarchyQuery {
export interface ChildrenOfProps { export interface ChildrenOfProps {
folderName?: string; folderName?: string;
exclude?: string; exclude?: string;
only?: string;
currentNode: SilverstripeDocument | null; currentNode: SilverstripeDocument | null;
asList?: boolean; asList?: boolean;
includeFolders?: boolean;
reverse?: boolean;
}; };

View File

@ -31,6 +31,7 @@ const getNodes = (): SilverstripeDocument[] => {
icon icon
iconBrand iconBrand
hideChildren hideChildren
unhideSelf
slug slug
parentSlug parentSlug
fileTitle fileTitle
@ -49,9 +50,9 @@ const getNodes = (): SilverstripeDocument[] => {
/** /**
* Get the children of a given node * Get the children of a given node
* *
* @param node * @param node
* @param includeFolders * @param includeFolders
*/ */
const getChildren = ( const getChildren = (
node: SilverstripeDocument, node: SilverstripeDocument,
@ -75,8 +76,8 @@ const getChildren = (
/** /**
* Get children of a given node that should be shown in navigation * Get children of a given node that should be shown in navigation
* *
* @param node * @param node
*/ */
const getNavChildren = (node: SilverstripeDocument): SilverstripeDocument[] => { const getNavChildren = (node: SilverstripeDocument): SilverstripeDocument[] => {
if (navChildrenMap.has(node.slug)) { if (navChildrenMap.has(node.slug)) {
@ -87,6 +88,8 @@ const getNavChildren = (node: SilverstripeDocument): SilverstripeDocument[] => {
children = getChildren(node, true).filter(n => !n.hideSelf); children = getChildren(node, true).filter(n => !n.hideSelf);
} }
getChildren(node, true).filter(n => n.unhideSelf).forEach(c => children.push(c));
navChildrenMap.set(node.slug, children); navChildrenMap.set(node.slug, children);
return navChildrenMap.get(node.slug); return navChildrenMap.get(node.slug);
@ -94,10 +97,10 @@ const getNavChildren = (node: SilverstripeDocument): SilverstripeDocument[] => {
/** /**
* Get the siblings of a given node * Get the siblings of a given node
* *
* @param node * @param node
*/ */
const getSiblings = (node: SilverstripeDocument): SilverstripeDocument[] => { const getSiblings = (node: SilverstripeDocument): SilverstripeDocument[] => {
if (siblingMap.has(node.slug)) { if (siblingMap.has(node.slug)) {
return siblingMap.get(node.slug); return siblingMap.get(node.slug);
} }
@ -111,7 +114,7 @@ const getSiblings = (node: SilverstripeDocument): SilverstripeDocument[] => {
/** /**
* Get the parent of a given node * Get the parent of a given node
* @param node * @param node
*/ */
const getParent = (node: SilverstripeDocument): SilverstripeDocument | null => { const getParent = (node: SilverstripeDocument): SilverstripeDocument | null => {
if (parentMap.has(node.slug)) { if (parentMap.has(node.slug)) {
@ -154,7 +157,7 @@ const getCurrentVersion = (): string => __currentVersion || '4';
/** /**
* Set the current node by its slug. * Set the current node by its slug.
* @param slug * @param slug
*/ */
const setCurrentNode = (slug: string): void => { const setCurrentNode = (slug: string): void => {
const currentNode = getNodes().find(n => n.slug === slug) || null; const currentNode = getNodes().find(n => n.slug === slug) || null;

View File

@ -9,23 +9,38 @@ import { getCurrentNode } from '../utils/nodes';
const parseChildrenOf = (data: any): ReactElement|false => { const parseChildrenOf = (data: any): ReactElement|false => {
const currentNode = getCurrentNode(); const currentNode = getCurrentNode();
let matches; let matches;
matches = data.match(/\[CHILDREN(\sasList)?\]/);
if (matches) {
const asList = !!matches[1];
return createElement(ChildrenOf, { currentNode, asList })
}
matches = data.match(/\[CHILDREN Folder="?([A-Za-z0-9_<>\/]+)"?.*?\]/); matches = data.match(/\[CHILDREN Folder="?([A-Za-z0-9_<>\/]+)"?.*?\]/);
if (matches) { if (matches) {
const folderName = matches[1].replace(/<\/?em>/g, '_'); const folderName = matches[1].replace(/<\/?em>/g, '_');
const asList = matches[0].match(' asList'); const asList = matches[0].match(' asList');
return createElement(ChildrenOf, { folderName, currentNode, asList }) const includeFolders = matches[0].match(' includeFolders');
const reverse = matches[0].match(' reverse');
return createElement(ChildrenOf, { folderName, currentNode, asList, includeFolders, reverse })
} }
matches = data.match(/\[CHILDREN Exclude="?([A-Za-z0-9_,]+)"?.*?\]/); matches = data.match(/\[CHILDREN Exclude="?([A-Za-z0-9_,]+)"?.*?\]/);
if (matches) { if (matches) {
const asList = matches[0].match(' asList'); const asList = matches[0].match(' asList');
const includeFolders = matches[0].match(' includeFolders');
const reverse = matches[0].match(' reverse');
const exclude = matches[1].replace(/<\/?em>/g, '_'); const exclude = matches[1].replace(/<\/?em>/g, '_');
return createElement(ChildrenOf, { exclude, currentNode, asList }) return createElement(ChildrenOf, { exclude, currentNode, asList, includeFolders, reverse })
}
matches = data.match(/\[CHILDREN Only="?([A-Za-z0-9_,]+)"?.*?\]/);
if (matches) {
const asList = matches[0].match(' asList');
const includeFolders = matches[0].match(' includeFolders');
const reverse = matches[0].match(' reverse');
const only = matches[1].replace(/<\/?em>/g, '_');
return createElement(ChildrenOf, { only, currentNode, asList, includeFolders, reverse })
}
matches = data.match(/\[CHILDREN(\sasList)?.*?\]/);
if (matches) {
const asList = !!matches[1];
const includeFolders = matches[0].match(' includeFolders');
const reverse = matches[0].match(' reverse');
return createElement(ChildrenOf, { currentNode, asList, includeFolders, reverse })
} }
return false; return false;