mirror of
https://github.com/silverstripe/doc.silverstripe.org
synced 2024-10-22 15:05:50 +00:00
Add Children "only, includeFolders, reverse" flags, add document unhideSelf (#209)
This commit is contained in:
parent
4fa94b50d0
commit
fa241c0f61
@ -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,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -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 &&
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user