diff --git a/packages/tools/docs-tools/package.json b/packages/tools/docs-tools/package.json index 5e9673a672e..4555b20a2a4 100644 --- a/packages/tools/docs-tools/package.json +++ b/packages/tools/docs-tools/package.json @@ -27,16 +27,23 @@ "@kadena-dev/eslint-config": "workspace:^", "@kadena-dev/lint-package": "workspace:^", "@kadena-dev/shared-config": "workspace:^", - "@types/mdast": "^4.0.1", - "@types/node": "^18.17.14", - "@types/unist": "^3.0.1", - "eslint": "^8.48.0", + "@types/js-yaml": "^4.0.9", + "@types/mdast": "^4.0.3", + "@types/node": "^20.9.0", + "@types/react": "^18.2.15", + "@types/unist": "^3.0.2", + "acorn": "~8.8.2", + "date-fns": "~2.30.0", + "eslint": "^8.53.0", + "js-yaml": "~4.1.0", "mdast": "^3.0.0", "prettier": "~3.0.3", - "typescript": "5.2.2" + "react": "^18.2.0", + "typescript": "^5.2.2", + "unified": "^11.0.4" }, "dependencies": { - "mdast-util-to-string": "~3.2.0", + "mdast-util-to-string": "~4.0.0", "remark-gfm": "^4.0.0" } } diff --git a/packages/tools/docs-tools/src/data/authors.json b/packages/tools/docs-tools/src/data/authors.json new file mode 100644 index 00000000000..975461b2e4d --- /dev/null +++ b/packages/tools/docs-tools/src/data/authors.json @@ -0,0 +1,176 @@ +[ + { + "id": "stuart.popejoy", + "name": "Stuart Popejoy", + "avatar": "/assets/blog/author/stuart.popejoy.jpg", + "description": "Founder & CEO", + "twitter": "SirLensALot" + }, + { + "id": "will.martino", + "name": "Will Martino", + "avatar": "/assets/blog/author/will.martino.jpg", + "description": "Founder & President", + "twitter": "_wjmartino_" + }, + { + "id": "doug.beardsley", + "name": "Doug Beardsley", + "avatar": "/assets/blog/author/doug.beardsley.jpg", + "description": "Director of Engineering", + "twitter": "BlockchainDoug" + }, + { + "id": "albert.g", + "name": "Albert Groothedde", + "avatar": "/assets/blog/author/albert.groothedde.jpg", + "description": "Architect DevEx at Kadena", + "twitter": "alber70g" + }, + { + "id": "vivienne.chen", + "name": "Vivienne Chen", + "avatar": "/assets/blog/author/vivienne.chen.jpg", + "twitter": "ViviennexChen" + }, + { + "id": "john.wiegley", + "name": "John Wiegley", + "avatar": "/assets/blog/author/john.wiegley.jpg", + "description": "Chief Technology Officer", + "twitter": "jwiegley" + }, + { + "id": "leah.bingham", + "name": "Leah Bingham", + "avatar": "/assets/blog/author/leah.bingham.jpg" + }, + { + "id": "linda.ortega", + "name": "Linda Ortega", + "avatar": "/assets/blog/author/linda.ortega.jpg", + "twitter": "linda_ioc" + }, + { + "id": "dan.wiggins", + "name": "Dan Wiggins", + "avatar": "/assets/blog/author/dan.wiggins.jpg" + }, + { + "id": "monica.quaintance", + "name": "Monica Quaintance", + "avatar": "/assets/blog/author/monica.quaintance.jpg", + "twitter": "QuaintM" + }, + { + "id": "tyler.benster", + "name": "Tyler Benster", + "avatar": "/assets/blog/author/tyler.benster.jpg" + }, + { + "id": "ben.jessel", + "name": "Ben Jessel", + "avatar": "/assets/blog/author/ben.jessel.jpg" + }, + { + "id": "marie.leaf", + "name": "Marie Leaf", + "avatar": "/assets/blog/author/marie.leaf.jpg" + }, + { + "id": "anagha.mercado", + "name": "Anagha Mercado", + "avatar": "/assets/blog/author/anagha.mercado.jpg" + }, + { + "id": "miguel.angel", + "name": "Miguel Angel Romero Jr.", + "avatar": "/assets/blog/author/miguel.angel.romero.png" + }, + { + "id": "rebecca.rodriguez", + "name": "Rebecca Rodriguez", + "avatar": "/assets/blog/author/rebecca.rodriguez.jpg" + }, + { + "id": "tony.pham", + "name": "Tony Pham", + "avatar": "/assets/blog/author/tony.pham.jpg" + }, + { + "id": "taylor.rolfe", + "name": "Taylor Rolfe", + "avatar": "/assets/blog/author/taylor.rolfe.jpg" + }, + { + "id": "francesco.melpignano", + "name": "Francesco Melpignano", + "avatar": "/assets/blog/author/francesco.melpignano.jpg", + "twitter": "fmelp" + }, + { + "id": "andy", + "name": "Andy", + "avatar": "/assets/blog/author/andy.tang.jpg", + "description": "Frontend developer", + "twitter": "andortang" + }, + { + "id": "jermaine.jong", + "name": "Jermaine Jong", + "avatar": "/assets/blog/author/jermaine.jong.png", + "description": "Frontend developer" + }, + { + "id": "randy.daal", + "name": "Randy Daal", + "avatar": "/assets/blog/author/randy.daal.jpg", + "description": "Chief Experience Officer @kadena_io", + "twitter": "Randynamic_4" + }, + { + "id": "jose.cardona", + "name": "Jose Cardona", + "avatar": "/assets/blog/author/jose.cardona.jpg", + "twitter": "JM0x5C" + }, + { + "id": "kadena", + "name": "Kadena", + "avatar": "/assets/blog/author/kadena.png", + "description": "The only layer 1 PoW blockchain that scales.", + "twitter": "kadena_io" + }, + { + "id": "heekyun", + "name": "Heekyun", + "avatar": "/assets/blog/author/hee.kyun.yun.jpg", + "description": "Dev Experience @kadena_io PactJS and Pact Smart Contract Lead", + "twitter": "HeeKyunYun1" + }, + { + "id": "robert.soeldner", + "name": "Robert Soeldner", + "avatar": "/assets/blog/author/robert.soeldner.jpeg", + "description": "Software Engineer" + }, + { + "id": "emily.pillmore", + "name": "Emily Pillmore", + "avatar": "/assets/blog/author/emily.pillmore.jpg", + "description": "M L E that's me", + "twitter": "yandereidiot" + }, + { + "id": "ryan.levy", + "name": "Ryan Levy", + "avatar": "/assets/blog/author/ryan.levy.png", + "description": "Business Development" + }, + { + "id": "glenn.reyes", + "name": "Glenn Reyes", + "avatar": "/assets/blog/author/glenn.reyes.jpeg", + "description": "Developer Relations" + } +] diff --git a/packages/tools/docs-tools/src/remarkAdmonition.ts b/packages/tools/docs-tools/src/remarkAdmonition.ts new file mode 100644 index 00000000000..8b92540dae4 --- /dev/null +++ b/packages/tools/docs-tools/src/remarkAdmonition.ts @@ -0,0 +1,128 @@ +import { Paragraph, PhrasingContent } from "mdast"; +import { DocsRootContent, ITree, Plugin, ChildrenWithValues, typeWithValue } from "./types"; + +const STARTNOTER_EGEXP = /^:::\s?(\w+)\s?([\w\s]+)?$/; +const ENDNOTER_EGEXP = /:::\s*$/m; + +let STARTELM: Paragraph | undefined; + +// check the branch with the start of a notification +// notifications start with ':::' followed by a label and maybe a title +const isStart = (branch: DocsRootContent): null | string[] => { + if('children' in branch === false) return null; + + if ('children' in branch) { + if(branch.children.length === 0) return null; + const value = (branch.children as ChildrenWithValues)?.[0].value ?? ''; + console.log('isStart ', value.match(STARTNOTER_EGEXP)); + return value.match(STARTNOTER_EGEXP); + } + return null; +}; + +const isEnd = (branch: DocsRootContent): boolean => { + if('children' in branch === false) return false; + if('children' in branch) { + if (branch.children.length === 0) return false; + + const endLeaf = (branch.children as ChildrenWithValues).find((item: typeWithValue) => + item.value?.match(ENDNOTER_EGEXP), + ); + + if (endLeaf) { + endLeaf.value = endLeaf.value?.replace(':::', ''); + return Boolean(endLeaf); + } + } + + return false; +}; + +// get the props (label and title) for the notification +const getProps = (branch: DocsRootContent) => { + if('children' in branch === false) return {}; + + if('children' in branch) { + if (branch.children.length === 0) return {}; + const value = (branch.children as ChildrenWithValues)[0].value ?? ''; + + const match = STARTNOTER_EGEXP.exec(value); + if (!match) return {}; + + return { + label: match[1], + title: match[2], + }; + } +}; + +const getStartElm = () => { + return STARTELM; +}; + +const setStartElm = (startElm: Paragraph) => { + STARTELM = startElm; +}; + +const clearStartElm = () => { + STARTELM = undefined; +}; + +/** + * the reduce function will make all the branches between the start and end of a notification a child of the start branch + */ +const reduceToNotifications = (acc: DocsRootContent[], branch:DocsRootContent) => { + if(branch.type === 'paragraph') { + if (isStart(branch)) { + setStartElm(branch); + + const props = getProps(branch); + // @ts-ignore + branch.type = 'element'; + (branch.children as ChildrenWithValues)[0].value = ''; + branch.data = { + hName: 'kda-notification', + hProperties: props, + }; + + if (isEnd(branch)) { + clearStartElm(); + } + + return [...acc, branch]; + } + } else { + return [...acc, branch]; + } + + + const startElm = getStartElm(); + if (startElm) { + if (isEnd(branch)) { + clearStartElm(); + } + console.log('startElm ', startElm); + startElm.children = [ + ...startElm.children, + branch, + ] as PhrasingContent[]; + + // if in the middle or end of the notification do not return the branch. + // the branch is now a child of the startbranch + return acc; + } + + return [...acc, branch]; +}; + +const remarkAdmonitions = (): Plugin => { + return async (tree): Promise => { + const newChildren = tree.children + .reduce(reduceToNotifications, []); + + tree.children = newChildren; + return tree; + }; +}; + +export { remarkAdmonitions as default }; diff --git a/packages/tools/docs-tools/src/remarkCheckForCodeTitle.ts b/packages/tools/docs-tools/src/remarkCheckForCodeTitle.ts index 05663c94c0b..f2287c3c3de 100644 --- a/packages/tools/docs-tools/src/remarkCheckForCodeTitle.ts +++ b/packages/tools/docs-tools/src/remarkCheckForCodeTitle.ts @@ -1,8 +1,4 @@ -import type { Root, RootContent } from 'mdast'; - -interface Tree extends Omit { - children: RootContent[]; -} +import { ITree, Plugin } from './types'; const replaceOrConcatString = (str?: string | null): string => { if (!str) str = ''; @@ -18,12 +14,12 @@ const replaceOrConcatString = (str?: string | null): string => { return str; }; -const remarkCheckForCodeTitle = () => { - return async (tree: Tree) => { +const remarkCheckForCodeTitle = (): Plugin => { + return async (tree: ITree): Promise => { const children = tree.children.map((node) => { const { type } = node; - if (type == 'code') { + if (type === 'code') { node.meta = replaceOrConcatString(node.meta); } diff --git a/packages/tools/docs-tools/src/remarkFigureOutOfParagraph.ts b/packages/tools/docs-tools/src/remarkFigureOutOfParagraph.ts new file mode 100644 index 00000000000..9e4d4077922 --- /dev/null +++ b/packages/tools/docs-tools/src/remarkFigureOutOfParagraph.ts @@ -0,0 +1,40 @@ +/** + * This plugin will remove the outer Paragraph for a figure tag + * @param {*} tree + * @returns + */ + +import { DocsRootContent, ITree, Plugin } from "./types"; + +const remarkFigureOutOfParagraph = (): Plugin => { + return async (tree): Promise => { + const children = tree.children.map((node) => { + const { type } = node; + + if ( + type === 'paragraph' && + node.children && + node.children[0].type === 'image' + ) { + const leaf = node.children[0] ?? null; + + const newNode = { + ...leaf, + ...node, + type: 'image', + }; + + // @ts-ignore + delete newNode.children; + return newNode; + } + + return node; + }); + + tree.children = children as DocsRootContent[]; + return tree; + }; +}; + +export { remarkFigureOutOfParagraph as default }; diff --git a/packages/tools/docs-tools/src/remarkFixAbsoluteLinks.ts b/packages/tools/docs-tools/src/remarkFixAbsoluteLinks.ts new file mode 100644 index 00000000000..65bf352fdcd --- /dev/null +++ b/packages/tools/docs-tools/src/remarkFixAbsoluteLinks.ts @@ -0,0 +1,35 @@ +import { Definition, Link } from 'mdast'; +import { DocsRootContent, ITree, Plugin } from './types'; + +export const getTypes = (tree: ITree | DocsRootContent, type: string, arr: T[] = []): T[] => { + if ('children' in tree) { + tree.children.forEach((branch: DocsRootContent) => { + if (branch.type === type) { + arr.push(branch as unknown as T); + } + getTypes(branch, type, arr); + }); + } + return arr; +}; + +const remarkFixAbsoluteLinks = (): Plugin => { + return async (tree): Promise => { + const links= getTypes(tree, 'link'); + const references = getTypes(tree, 'definition'); + + var regExp = /^(https?:\/\/docs\.kadena\.io)/; + + [links, references].flat().forEach((link) => { + if (link.url.match(regExp)) { + const newLink = link.url.replace(regExp, '') || '/'; + + link.url = newLink; + } + }); + + return tree; + }; +}; + +export { remarkFixAbsoluteLinks as default }; diff --git a/packages/tools/docs-tools/src/remarkFrontmatterToProps.ts b/packages/tools/docs-tools/src/remarkFrontmatterToProps.ts new file mode 100644 index 00000000000..862f0eb2e8e --- /dev/null +++ b/packages/tools/docs-tools/src/remarkFrontmatterToProps.ts @@ -0,0 +1,136 @@ +import { compareDesc } from 'date-fns'; +import yaml from 'js-yaml'; +import authors from './data/authors.json' assert { type: 'json' }; +import { getPathName } from './utils/staticGeneration/checkSubTreeForActive.mjs'; +import { getData } from './utils/staticGeneration/getData.mjs'; +import { getReadTime } from './utils.mjs'; +import { DocsRootContent, ITree, Plugin } from './types'; + +const flat = (acc, val) => { + const { children, ...newVal } = val; + + return [ + ...acc, + newVal, + children ? children.reduce(flat, []).flat() : undefined, + ]; +}; + +const getFlatData = () => { + return getData().reduce(flat, []).flat(); +}; + +const getCurrentPostFromJson = (root) => { + const data = getFlatData(); + + return data.find((item) => { + return item && (item.root === root || `${item.root}/` === root); + }); +}; + +const getFrontMatter = (node: DocsRootContent) => { + const { type } = node; + + if (type === 'yaml') { + return yaml.load(node.value); + } +}; + +const getLatestBlogPostsOfAuthor = (author) => { + const data = getData(); + + const STARTBRANCH = '/blogchain'; + + const startBranch = data.find((item) => item.root === STARTBRANCH); + + let posts = + startBranch.children.flatMap((item) => { + return item.children; + }) ?? []; + + return posts + .filter((post) => post.authorId === author.id) + .sort((a, b) => + compareDesc(new Date(a.publishDate), new Date(b.publishDate)), + ) + .slice(0, 5); +}; + +const getBlogAuthorInfo = (data) => { + const authorId = data.authorId; + if (!authorId) return; + + const author = authors.find((author) => author.id === authorId); + if (!author) return; + + author.posts = getLatestBlogPostsOfAuthor(author); + + return author; +}; + +const getFileName = (file) => { + if (file.history.length === 0) return ''; + return file.history[0]; +}; + +const getFileNameInPackage = (file) => { + const filename = getFileName(file); + if (!filename) return ''; + const endPoint = 'packages'; + + const dirArray = filename.split('/'); + + const newPath = dirArray + .reverse() + .slice(0, dirArray.indexOf(endPoint) + 1) + .reverse() + .join('/'); + + return `/${newPath}`; +}; + +/** + * create a navigation object with the next and previous link in the navigation json. + */ +const createNavigation = (file) => { + const path = getPathName(getFileName(file)); + const flatData = getFlatData(); + + const itemIdx = flatData.findIndex((i) => { + return i && (i.root === path || `${i.root}/` === path); + }); + + return { + previous: flatData[itemIdx - 1] ?? undefined, + next: flatData[itemIdx + 1] ?? undefined, + }; +}; + +const remarkFrontmatterToProps = (): Plugin => { + return async (tree, file): Promise => { + tree.children = tree.children.map((node) => { + const frontMatterData = getFrontMatter(node); + if (!frontMatterData) return node; + const menuData = + getCurrentPostFromJson(getPathName(getFileName(file))) ?? {}; + + return { + type: 'props', + data: { + frontmatter: { + lastModifiedDate: menuData.lastModifiedDate, + ...getReadTime(file.value), + editLink: + process.env.NEXT_PUBLIC_GIT_EDIT_ROOT + + getFileNameInPackage(file), + navigation: createNavigation(file), + ...frontMatterData, + authorInfo: getBlogAuthorInfo(frontMatterData), + }, + }, + }; + }); + }; +}; + +export { remarkFrontmatterToProps as default }; diff --git a/packages/tools/docs-tools/src/remarkHeadersToProps.ts b/packages/tools/docs-tools/src/remarkHeadersToProps.ts index 6e4e16f991c..29fb2181c04 100644 --- a/packages/tools/docs-tools/src/remarkHeadersToProps.ts +++ b/packages/tools/docs-tools/src/remarkHeadersToProps.ts @@ -1,14 +1,11 @@ import { toString } from 'mdast-util-to-string'; import { getValues } from './utils.mjs'; -import type { Root, RootContent, Heading } from 'mdast'; +import type { Heading, PhrasingContent } from 'mdast'; +import type { DocsRootContent, IStartArray, ITree, Plugin, TagNameType } from './types'; -interface Tree extends Omit { - children: RootContent[]; -} +const getTagName = (depth = 1) => `h${depth}` as TagNameType; -const getTagName = (depth = 1) => `h${depth}`; - -const lastHeading = (parent, newChild) => { +const lastHeading = (parent: IStartArray, newChild: Heading): IStartArray => { const nodes = [parent]; let child = parent.children[parent.children.length - 1] ?? parent; @@ -26,34 +23,31 @@ const lastHeading = (parent, newChild) => { return nodes[nodes.length - 1]; }; -const cleanupHeading = (item) => { +const cleanupHeading = (item: Heading): void => { const newChild = { type: 'text', value: '', - postion: { - start: {}, - end: {}, - }, }; const value = getValues(item).join(' '); - item.children = [{ ...newChild, value }]; + item.children = [{ ...newChild, value }] as PhrasingContent[]; }; -const getHeaders = (tree: Root) => { - return tree.children.filter((branch: RootContent) => { - return branch.type === 'heading'; - }) as Heading[] ?? []; +const getHeaders = (tree: ITree): Heading[] => { + return tree.children.filter((child: DocsRootContent) => { + return child.type === 'heading'; + }) as Heading[]; }; -const remarkHeadersToProps = () => { - return async (tree: Tree) => { +const remarkHeadersToProps = (): Plugin => { + return async (tree: ITree): Promise => { const headers = getHeaders(tree); - let startArray = [ + const startArray:IStartArray[] = [ { + type: 'heading', tag: 'h1', depth: 1, children: [], @@ -70,7 +64,8 @@ const remarkHeadersToProps = () => { return; } - const elm = { + const elm: IStartArray = { + type: item.type, depth: item.depth, tag: getTagName(item.depth), title: toString(item) ?? '', diff --git a/packages/tools/docs-tools/src/remarkPlugin.ts b/packages/tools/docs-tools/src/remarkPlugin.ts new file mode 100644 index 00000000000..56dfad54ca0 --- /dev/null +++ b/packages/tools/docs-tools/src/remarkPlugin.ts @@ -0,0 +1,27 @@ + +import { Node } from 'unist'; +import { Plugin } from 'unified'; +import { visit } from 'unist-util-visit'; + +interface Options { + // Define any options you need for your plugin here +} + +const remarkPlugin: Plugin<[Options?]> = (options = {}) => { + + interface Options { + // Define any options you need for your plugin here + } + + const remarkPlugin: Plugin<[Options?]> = (options = {}) => { + return (tree: Node) => { + visit(tree, 'link', (node: Node) => { + const children = node.children[0]; + + + }); + }; + }; +}; + +export default remarkPlugin; diff --git a/packages/tools/docs-tools/src/remarkPropsToStaticRender.ts b/packages/tools/docs-tools/src/remarkPropsToStaticRender.ts new file mode 100644 index 00000000000..e1ebaab0754 --- /dev/null +++ b/packages/tools/docs-tools/src/remarkPropsToStaticRender.ts @@ -0,0 +1,49 @@ +import { parse as parseAst } from 'acorn'; +import { DocsRootContent, IPropsType, ITree, Plugin } from './types'; + +// find all the props objects in the tree +const getProps = (tree: ITree): IPropsType[] => { + return tree.children.filter((branch) => { + return branch.type === 'props'; + }) as IPropsType[]; +}; + +// add a getStaticProps to every MD or MDX file +const renderer = (data: IPropsType[]) => { + if (!data) return; + + const newData = data.reduce((acc, val) => { + return { ...acc, ...val.data }; + }, {}); + + return ` + export const getStaticProps = async () => { + return { props: ${JSON.stringify(newData)} } + } + `; +}; + +const remarkPropsToStaticRender = (): Plugin => { + return async (tree): Promise => { + const props = getProps(tree); + + const renderedString = renderer(props); + const { body } = parseAst(renderedString, { + sourceType: 'module', + ecmaVersion: 'latest', + }); + + tree.children.push({ + type: 'mdxjsEsm', + data: { + estree: { + type: 'Program', + sourceType: 'module', + body, + }, + }, + }); + }; +}; + +export { remarkPropsToStaticRender as default }; diff --git a/packages/tools/docs-tools/src/remarkTwitter.ts b/packages/tools/docs-tools/src/remarkTwitter.ts index eed66413dd3..b3f525c7505 100644 --- a/packages/tools/docs-tools/src/remarkTwitter.ts +++ b/packages/tools/docs-tools/src/remarkTwitter.ts @@ -1,8 +1,4 @@ -import type { Root, RootContent } from 'mdast'; - -interface ITree extends Omit { - children: RootContent[]; -} +import type { ITree, Plugin, RootContent } from './types'; const getTwitterStatusId = (url: string): string | undefined => { if (!url) return; @@ -19,32 +15,31 @@ const getTwitterStatusId = (url: string): string | undefined => { return; }; -const remarkTwitter = () => { - return async (tree: ITree) => { +const remarkTwitter = (): Plugin => { + return async (tree: ITree): Promise => { const children = tree.children.map((node) => { if (node.type === 'paragraph' && node.children?.length === 1) { const leaf = node.children?.[0] ?? null; - if(leaf.type === 'link') { - const twitterStatusId = getTwitterStatusId(leaf.url); - - if (twitterStatusId) { - const newNode = { - ...leaf, - ...node, - type: 'element', - value: leaf.url, - data: { - ...node.data, - hName: 'kda-tweet', - hProperties: { - tweetId: twitterStatusId, - }, + if(leaf.type !== 'link') return node; + + const twitterStatusId = getTwitterStatusId(leaf.url); + if (twitterStatusId) { + const newNode = { + ...leaf, + ...node, + type: 'element', + value: leaf.url, + data: { + ...node.data, + hName: 'kda-tweet', + hProperties: { + tweetId: twitterStatusId, }, - }; + }, + }; - newNode.children = []; - return newNode; - } + newNode.children = []; + return newNode; } } return node; diff --git a/packages/tools/docs-tools/src/remarkYoutube.ts b/packages/tools/docs-tools/src/remarkYoutube.ts index 4a4ec05e3d5..04929420bee 100644 --- a/packages/tools/docs-tools/src/remarkYoutube.ts +++ b/packages/tools/docs-tools/src/remarkYoutube.ts @@ -1,9 +1,4 @@ -import type { Root, RootContent } from 'mdast'; - -interface Tree extends Omit { - children: RootContent[]; -} - +import type { ITree, Plugin, RootContent } from "./types"; const getYouTubeVideoId = (link: string): string | undefined => { if (!link) return; @@ -17,8 +12,8 @@ const getYouTubeVideoId = (link: string): string | undefined => { return; }; -const remarkYoutube = () => { - return async (tree: Tree) => { +const remarkYoutube = (): Plugin => { + return async (tree: ITree) => { const children = tree.children.map((node) => { if (node.type === 'paragraph' && node.children?.length === 1) { const leaf = node.children[0] ?? null; diff --git a/packages/tools/docs-tools/src/types.ts b/packages/tools/docs-tools/src/types.ts new file mode 100644 index 00000000000..b194f08a442 --- /dev/null +++ b/packages/tools/docs-tools/src/types.ts @@ -0,0 +1,200 @@ +import type { Root, RootContent, Heading, RootContentMap, PhrasingContent, InlineCode, Text, Yaml, Html, Code } from 'mdast'; +import type { ReactNode } from 'react'; + +export interface ITopDoc { + label: string; + url: string; +} + +export type TagNameType = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; + +export interface IStartArray { + type: 'heading'; + tag: TagNameType; + depth: 1 | 2 | 3 | 4 | 5 | 6; + children: IStartArray[]; + title?: string; +} + +export type LayoutType = + | 'full' + | 'landing' + | 'home' + | 'redocly' + | 'blog' + | 'code'; + +export interface ISubHeaderElement { + tag: TagNameType; + title?: string; + slug?: string; + children: ISubHeaderElement[]; +} + +export interface INavigation { + previous?: INavigationMenuItem; + next?: INavigationMenuItem; +} + +interface INavigationMenuItem { + title: string; + root: string; +} + +export interface IBasePageMeta { + title: string; + menu: string; // name in the main menu + order: number; + label: string; // name of the pagdescription: string; + layout: LayoutType; + description: string; + subTitle?: string; + lastModifiedDate?: Date; +} + +export interface IAuthorInfo { + id: string; + name: string; + avatar: string; + description?: string; + twitter?: string; + linkedin?: string; + posts?: IMenuData[]; +} +export interface IPageMeta extends IBasePageMeta { + editLink: string; + navigation: INavigation; + publishDate?: string; + headerImage?: string; + tags?: string[]; + author?: string; + authorId?: string; + authorInfo?: IAuthorInfo; + readingTimeInMinutes?: number; + wordCount?: number; +} + +export interface IMenuItem { + root: string; + title: string; + menu: string; + label: string; + isActive: boolean; // checks that the actual item is active in the menu + isMenuOpen: boolean; // makes sure that the parent slide menu is open + children: IMenuItem[]; + isIndex?: boolean; +} + +export interface ILayout { + children?: ReactNode; + isAsideOpen?: boolean; + aSideMenuTree?: ISubHeaderElement[]; + editLink?: string; + navigation?: INavigation; + publishDate?: string; + author?: string; +} + +export type LevelType = 1 | 2 | 3; + +export interface IPageProps { + children?: ReactNode; + menuItems: IMenuItem[]; + aSideMenuTree: ISubHeaderElement[]; + frontmatter: IPageMeta; + leftMenuTree: IMenuItem[]; + topDocs: ITopDoc[]; +} + +export interface IBasePageProps extends Omit { + frontmatter: IBasePageMeta; +} + +export interface IMenuData { + children: IMenuData[]; + root: string; + title: string; + description?: string; + menu: string; + label: string; + order: number; + layout: LayoutType; + isMenuOpen: boolean; + isActive: boolean; + publishDate?: string; + headerImage?: string; + tags?: string[]; + author?: string; + authorId?: string; + authorInfo?: IAuthorInfo; + wordCount?: number; + readingTimeInMinutes?: number; +} + +export interface ITag { + tag: string; + count: number; + links: IMenuData[]; +} + +interface IPropsData { + frontmatter: IPageMeta +} + +interface IAsideMenuData { + aSideMenuTree: ISubHeaderElement[]; +} + +export interface IPropsType { + type: "props", + children: [], + data: IPropsData | IAsideMenuData, +} + +export type typeWithValue = InlineCode | Text | Yaml | Html | Code; + +export type ChildrenWithValues = typeWithValue[]; + +export interface IElementType { + type: "element", + children: typeWithValue[], + data: { + hName: string, + hProperties: { + [key: string]: any, + }, + }, +} + +export interface IEsTree { + type: 'Program', + sourceType: 'module', + body: any[], +} + +export interface IMdxJSEsm { + type: 'mdxjsEsm', + data: { + + } +} + +export interface IDocsRootContentMap extends RootContentMap { + props: IPropsType; + element: IElementType; + mdxjsEsm: IMdxJSEsm; +} + +export type DocsRootContent = IDocsRootContentMap[keyof IDocsRootContentMap]; + +export interface ITree extends Omit { + children: DocsRootContent[]; +} + +export interface IHeadingTree extends Omit { + children: Heading[]; +} + +export type Plugin = (tree: ITree, file: any) => Promise; + +export { RootContent, Root } diff --git a/packages/tools/docs-tools/src/utils/staticGeneration/checkSubTreeForActive.mjs b/packages/tools/docs-tools/src/utils/staticGeneration/checkSubTreeForActive.mjs new file mode 100644 index 00000000000..f18888980c0 --- /dev/null +++ b/packages/tools/docs-tools/src/utils/staticGeneration/checkSubTreeForActive.mjs @@ -0,0 +1,84 @@ +import path from 'path'; +import { getData } from './getData.mjs'; + +const omit = (obj, keysToOmit) => + Object.keys(obj) + .filter((key) => !keysToOmit.includes(key)) + .reduce((acc, key) => ({ ...acc, [key]: obj[key] }), {}); + +const isIndex = (filename) => { + return filename === 'index'; +}; + +// we dont want the last option in the path be "index" +const lastInPath = (filename) => { + if (isIndex(filename)) return ''; + return `${filename}`; +}; + +export const getPathName = (filename) => { + const endPoint = 'pages'; + + const dirArray = filename.split('/'); + + const newPath = dirArray + .reverse() + .slice(1, dirArray.indexOf(endPoint)) + .reverse() + .join('/'); + + const lastPath = lastInPath(path.parse(filename).name); + if (newPath) return `/${newPath}/${lastPath}`; + + return `/${lastPath}`; +}; + +const IsMenuOpen = (pathname, itemRoot) => + `${pathname}/`.startsWith(`${itemRoot}/`); + +const isPathRoot = (pathname, itemRoot) => itemRoot === pathname; + +const mapSubTree = (pathname, noChildren, isRoot) => (item) => { + const newItem = omit(item, [ + 'description', + 'subTitle', + 'layout', + 'navigation', + 'editLink', + 'order', + 'lastModifiedDate', + 'publishDate', + 'author', + 'wordCount', + 'readingTimeInMinutes', + ]); + + if (IsMenuOpen(pathname, newItem.root)) { + newItem.isMenuOpen = true; + } else { + newItem.isMenuOpen = false; + } + + if (isPathRoot(pathname, newItem.root)) { + newItem.isActive = true; + } else { + newItem.isActive = false; + } + + // is the actual item active + if (!newItem.children || noChildren) newItem.children = []; + if (isRoot && !pathname.includes(newItem.root)) newItem.children = []; + newItem.children = newItem.children.map(mapSubTree(pathname, noChildren)); + + return newItem; +}; + +export const checkSubTreeForActive = (path, noChildren = false) => { + const tree = getData(); + + if (!path) { + throw new Error('no path'); + } + + return tree.map(mapSubTree(path, noChildren, true)); +}; diff --git a/packages/tools/docs-tools/src/utils/staticGeneration/flatPosts.mjs b/packages/tools/docs-tools/src/utils/staticGeneration/flatPosts.mjs new file mode 100644 index 00000000000..9dec51bed43 --- /dev/null +++ b/packages/tools/docs-tools/src/utils/staticGeneration/flatPosts.mjs @@ -0,0 +1,13 @@ +export const flatPosts = (acc = [], val) => { + const { children, ...newVal } = val; + + if (!children || !children.length) { + return [...acc, newVal]; + } + return [...acc, newVal, ...children.reduce(flatPosts, []).flat()]; +}; + +export const getFlatData = async () => { + const { menuData: data } = await import('./../../_generated/menu.mjs'); + return data.reduce(flatPosts, []).flat(); +}; diff --git a/packages/tools/docs-tools/src/utils/staticGeneration/getData.mjs b/packages/tools/docs-tools/src/utils/staticGeneration/getData.mjs new file mode 100644 index 00000000000..202acc20428 --- /dev/null +++ b/packages/tools/docs-tools/src/utils/staticGeneration/getData.mjs @@ -0,0 +1,5 @@ +import { menuData } from './../../_generated/menu.mjs'; + +export const getData = () => { + return menuData; +}; diff --git a/packages/tools/docs-tools/src/utils/staticGeneration/getJsonData.mjs b/packages/tools/docs-tools/src/utils/staticGeneration/getJsonData.mjs new file mode 100644 index 00000000000..6a93613f697 --- /dev/null +++ b/packages/tools/docs-tools/src/utils/staticGeneration/getJsonData.mjs @@ -0,0 +1,36 @@ +import authorData from '../../data/authors.json' assert { type: 'json' }; + +export const getAuthorData = () => { + return authorData; +}; + +const PostsPerTag = (tag, data) => { + if (!data) return { count: 0, links: [] }; + + const links = data.filter((post) => post.tags?.includes(tag)); + + return { + count: links.length, + links: links.slice(0, 3), + }; +}; + +export const getTagsData = async () => { + const STARTBRANCH = '/blogchain'; + const { menuData: data } = await import('./../../_generated/menu.mjs'); + + const startBranch = data.find((item) => item.root === STARTBRANCH); + + const posts = startBranch?.children.flatMap((item) => { + return item.children; + }); + + return [...new Set(posts?.map((post) => post.tags ?? []).flat() ?? [])] + .sort() + .map((tag) => { + return { + tag, + ...PostsPerTag(tag, posts), + }; + }); +}; diff --git a/packages/tools/docs-tools/tsconfig.json b/packages/tools/docs-tools/tsconfig.json index 635de30048a..f4ccc8df86d 100644 --- a/packages/tools/docs-tools/tsconfig.json +++ b/packages/tools/docs-tools/tsconfig.json @@ -5,6 +5,8 @@ "types": ["node"], "module": "NodeNext", "skipLibCheck": true, - "resolveJsonModule": true + "resolveJsonModule": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b16a10ca36d..432b2421622 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1714,8 +1714,8 @@ importers: packages/tools/docs-tools: dependencies: mdast-util-to-string: - specifier: ~3.2.0 - version: 3.2.0 + specifier: ~4.0.0 + version: 4.0.0 remark-gfm: specifier: ^4.0.0 version: 4.0.0 @@ -1729,27 +1729,48 @@ importers: '@kadena-dev/shared-config': specifier: workspace:^ version: link:../shared-config + '@types/js-yaml': + specifier: ^4.0.9 + version: 4.0.9 '@types/mdast': - specifier: ^4.0.1 - version: 4.0.2 + specifier: ^4.0.3 + version: 4.0.3 '@types/node': - specifier: ^18.17.14 - version: 18.17.14 + specifier: ^20.9.0 + version: 20.9.0 + '@types/react': + specifier: ^18.2.15 + version: 18.2.15 '@types/unist': - specifier: ^3.0.1 - version: 3.0.1 + specifier: ^3.0.2 + version: 3.0.2 + acorn: + specifier: ~8.8.2 + version: 8.8.2 + date-fns: + specifier: ~2.30.0 + version: 2.30.0 eslint: - specifier: ^8.48.0 - version: 8.48.0 + specifier: ^8.53.0 + version: 8.53.0 + js-yaml: + specifier: ~4.1.0 + version: 4.1.0 mdast: specifier: ^3.0.0 version: 3.0.0 prettier: specifier: ~3.0.3 version: 3.0.3 + react: + specifier: ^18.2.0 + version: 18.2.0 typescript: - specifier: 5.2.2 + specifier: ^5.2.2 version: 5.2.2 + unified: + specifier: ^11.0.4 + version: 11.0.4 packages/tools/e2e-tests: devDependencies: @@ -4594,6 +4615,16 @@ packages: eslint-visitor-keys: 3.4.3 dev: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.53.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.53.0 + eslint-visitor-keys: 3.4.3 + dev: true + /@eslint-community/regexpp@4.6.2: resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -4653,6 +4684,23 @@ packages: - supports-color dev: true + /@eslint/eslintrc@2.1.3: + resolution: {integrity: sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4(supports-color@5.5.0) + espree: 9.6.1 + globals: 13.21.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + /@eslint/js@8.44.0: resolution: {integrity: sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4662,6 +4710,11 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@eslint/js@8.53.0: + resolution: {integrity: sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + /@exodus/schemasafe@1.1.1: resolution: {integrity: sha512-Pd7+aGvWIaTDL5ecV4ZBEtBrjXnk8/ly5xyHbikxVhgcq7qhihzHWHbcYmFupQBT2A5ggNZGvT7Bpj0M6AKHjA==} dev: false @@ -5514,6 +5567,17 @@ packages: - supports-color dev: true + /@humanwhocodes/config-array@0.11.13: + resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.1 + debug: 4.3.4(supports-color@5.5.0) + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + /@humanwhocodes/config-array@0.5.0: resolution: {integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==} engines: {node: '>=10.10.0'} @@ -5532,6 +5596,10 @@ packages: /@humanwhocodes/object-schema@1.2.1: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + /@humanwhocodes/object-schema@2.0.1: + resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + dev: true + /@iarna/toml@2.2.5: resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} dev: true @@ -9446,7 +9514,7 @@ packages: engines: {node: '>=14'} dependencies: '@babel/code-frame': 7.22.13 - '@babel/runtime': 7.22.6 + '@babel/runtime': 7.22.15 '@types/aria-query': 5.0.1 aria-query: 5.1.3 chalk: 4.1.2 @@ -9558,7 +9626,7 @@ packages: /@types/concat-stream@2.0.0: resolution: {integrity: sha512-t3YCerNM7NTVjLuICZo5gYAXYoDvpuuTceCcFQWcDQz26kxUR5uIWolxbIR5jRNIXpMqhOpW/b8imCR1LEmuJw==} dependencies: - '@types/node': 18.17.14 + '@types/node': 20.9.0 dev: false /@types/connect@3.4.36: @@ -9691,7 +9759,7 @@ packages: /@types/hast@3.0.1: resolution: {integrity: sha512-hs/iBJx2aydugBQx5ETV3ZgeSS0oIreQrFJ4bjBl0XvM4wAmDjFEALY7p0rTSLt2eL+ibjRAAs9dTPiCLtmbqQ==} dependencies: - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 dev: false /@types/html-minifier-terser@6.1.0: @@ -9748,6 +9816,10 @@ packages: resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} dev: true + /@types/js-yaml@4.0.9: + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + dev: true + /@types/json-schema@7.0.12: resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} @@ -9811,7 +9883,13 @@ packages: /@types/mdast@4.0.2: resolution: {integrity: sha512-tYR83EignvhYO9iU3kDg8V28M0jqyh9zzp5GV+EO+AYnyUl3P5ltkTeJuTiFZQFz670FSb3EwT/6LQdX+UdKfw==} dependencies: - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 + dev: true + + /@types/mdast@4.0.3: + resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} + dependencies: + '@types/unist': 3.0.2 /@types/mdurl@1.0.2: resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} @@ -9876,11 +9954,10 @@ packages: /@types/node@18.17.14: resolution: {integrity: sha512-ZE/5aB73CyGqgQULkLG87N9GnyGe5TcQjv34pwS8tfBs1IkCh0ASM69mydb2znqd6v0eX+9Ytvk6oQRqu8T1Vw==} - /@types/node@20.8.7: - resolution: {integrity: sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==} + /@types/node@20.9.0: + resolution: {integrity: sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==} dependencies: - undici-types: 5.25.3 - dev: false + undici-types: 5.26.5 /@types/normalize-package-data@2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} @@ -10016,11 +10093,8 @@ packages: /@types/unist@2.0.8: resolution: {integrity: sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==} - /@types/unist@3.0.0: - resolution: {integrity: sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==} - - /@types/unist@3.0.1: - resolution: {integrity: sha512-ue/hDUpPjC85m+PM9OQDMZr3LywT+CT6mPsQq8OJtCLiERkGRcQUFvu9XASF5XWqyZFXbf15lvb3JFJ4dRLWPg==} + /@types/unist@3.0.2: + resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} /@types/webpack-env@1.18.1: resolution: {integrity: sha512-D0HJET2/UY6k9L6y3f5BL+IDxZmPkYmPT4+qBrRdmRLYRuV0qNKizMgTvYxXZYn+36zjPeoDZAEYBCM6XB+gww==} @@ -10703,7 +10777,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.59.11 - eslint-visitor-keys: 3.4.2 + eslint-visitor-keys: 3.4.3 /@typescript-eslint/visitor-keys@5.62.0: resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} @@ -10714,7 +10788,6 @@ packages: /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: false /@vanilla-extract/babel-plugin-debug-ids@1.0.3: resolution: {integrity: sha512-vm4jYu1xhSa6ofQ9AhIpR3DkAp4c+eoR1Rpm8/TQI4DmWbmGbOjYRcqV0aWsfaIlNhN4kFuxFMKBNN9oG6iRzA==} @@ -13640,7 +13713,7 @@ packages: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} dependencies: - '@babel/runtime': 7.22.6 + '@babel/runtime': 7.22.15 /date-time@3.1.0: resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} @@ -15086,6 +15159,53 @@ packages: - supports-color dev: true + /eslint@8.53.0: + resolution: {integrity: sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) + '@eslint-community/regexpp': 4.8.0 + '@eslint/eslintrc': 2.1.3 + '@eslint/js': 8.53.0 + '@humanwhocodes/config-array': 0.11.13 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4(supports-color@5.5.0) + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.21.0 + graphemer: 1.4.0 + ignore: 5.2.4 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + /espree@6.2.1: resolution: {integrity: sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==} engines: {node: '>=6.0.0'} @@ -16563,7 +16683,7 @@ packages: resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} dependencies: '@types/hast': 3.0.1 - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 devlop: 1.1.0 hastscript: 8.0.0 property-information: 6.2.0 @@ -16582,7 +16702,7 @@ packages: resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==} dependencies: '@types/hast': 3.0.1 - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 '@ungap/structured-clone': 1.2.0 hast-util-from-parse5: 8.0.1 hast-util-to-parse5: 8.0.0 @@ -18510,7 +18630,7 @@ packages: /mdast-comment-marker@3.0.0: resolution: {integrity: sha512-bt08sLmTNg00/UtVDiqZKocxqvQqqyQZAg1uaRuO/4ysXV5motg7RolF5o5yy/sY1rG0v2XgZEqFWho1+2UquA==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 mdast-util-mdx-expression: 2.0.0 transitivePeerDependencies: - supports-color @@ -18540,7 +18660,7 @@ packages: /mdast-util-find-and-replace@3.0.0: resolution: {integrity: sha512-8wLPIKAvGdA5jgkI8AYKfSorV3og3vE6HA+gKeKEZydbi1EtUu2g4XCxIBj3R+AsFqY/uRtoYbH30tiWsFKkBQ==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 escape-string-regexp: 5.0.0 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 @@ -18585,8 +18705,8 @@ packages: /mdast-util-from-markdown@2.0.0: resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} dependencies: - '@types/mdast': 4.0.2 - '@types/unist': 3.0.1 + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 decode-named-character-reference: 1.0.2 devlop: 1.1.0 mdast-util-to-string: 4.0.0 @@ -18611,7 +18731,7 @@ packages: /mdast-util-frontmatter@2.0.1: resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 devlop: 1.1.0 escape-string-regexp: 5.0.0 mdast-util-from-markdown: 2.0.0 @@ -18632,7 +18752,7 @@ packages: /mdast-util-gfm-autolink-literal@2.0.0: resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 ccount: 2.0.1 devlop: 1.1.0 mdast-util-find-and-replace: 3.0.0 @@ -18648,7 +18768,7 @@ packages: /mdast-util-gfm-footnote@2.0.0: resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 devlop: 1.1.0 mdast-util-from-markdown: 2.0.0 mdast-util-to-markdown: 2.1.0 @@ -18665,7 +18785,7 @@ packages: /mdast-util-gfm-strikethrough@2.0.0: resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 mdast-util-from-markdown: 2.0.0 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: @@ -18684,7 +18804,7 @@ packages: /mdast-util-gfm-table@2.0.0: resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 devlop: 1.1.0 markdown-table: 3.0.3 mdast-util-from-markdown: 2.0.0 @@ -18701,7 +18821,7 @@ packages: /mdast-util-gfm-task-list-item@2.0.0: resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 devlop: 1.1.0 mdast-util-from-markdown: 2.0.0 mdast-util-to-markdown: 2.1.0 @@ -18750,7 +18870,7 @@ packages: dependencies: '@types/estree-jsx': 1.0.0 '@types/hast': 3.0.1 - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 devlop: 1.1.0 mdast-util-from-markdown: 2.0.0 mdast-util-to-markdown: 2.1.0 @@ -18807,7 +18927,7 @@ packages: /mdast-util-phrasing@4.0.0: resolution: {integrity: sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 unist-util-is: 6.0.0 /mdast-util-to-hast@12.3.0: @@ -18827,7 +18947,7 @@ packages: resolution: {integrity: sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==} dependencies: '@types/hast': 3.0.1 - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 '@ungap/structured-clone': 1.2.0 devlop: 1.1.0 micromark-util-sanitize-uri: 2.0.0 @@ -18851,8 +18971,8 @@ packages: /mdast-util-to-markdown@2.1.0: resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} dependencies: - '@types/mdast': 4.0.2 - '@types/unist': 3.0.0 + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 longest-streak: 3.1.0 mdast-util-phrasing: 4.0.0 mdast-util-to-string: 4.0.0 @@ -18872,13 +18992,13 @@ packages: /mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 /mdast-zone@6.0.1: resolution: {integrity: sha512-IdpunGNXN4WKIXzUJYedOTxpDeJbJNifZ+hvHjaftNvZItWYFYc3G7HXElwZrs5PS0Xj/y0Gc3UPriuXh7QdCw==} dependencies: - '@types/mdast': 4.0.2 - '@types/unist': 3.0.0 + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 mdast-comment-marker: 3.0.0 unist-util-visit: 5.0.0 transitivePeerDependencies: @@ -22311,10 +22431,10 @@ packages: /remark-frontmatter@5.0.0: resolution: {integrity: sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 mdast-util-frontmatter: 2.0.1 micromark-extension-frontmatter: 2.0.0 - unified: 11.0.3 + unified: 11.0.4 transitivePeerDependencies: - supports-color dev: false @@ -22332,12 +22452,12 @@ packages: /remark-gfm@4.0.0: resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 mdast-util-gfm: 3.0.0 micromark-extension-gfm: 3.0.0 remark-parse: 11.0.0 remark-stringify: 11.0.0 - unified: 11.0.3 + unified: 11.0.4 transitivePeerDependencies: - supports-color dev: false @@ -22379,10 +22499,10 @@ packages: /remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 mdast-util-from-markdown: 2.0.0 micromark-util-types: 2.0.0 - unified: 11.0.3 + unified: 11.0.4 transitivePeerDependencies: - supports-color dev: false @@ -22390,7 +22510,7 @@ packages: /remark-reference-links@7.0.0: resolution: {integrity: sha512-OMACEps7CkpBio5nutUToCcXFJr9QkkoHdku41iIholMdFZ0jdRxgFmPm2B7R+DSvW83ZShdA3ubWTH+C3M6Eg==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 unist-util-visit: 5.0.0 dev: false @@ -22421,9 +22541,9 @@ packages: /remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 mdast-util-to-markdown: 2.1.0 - unified: 11.0.3 + unified: 11.0.4 dev: false /remark@14.0.3: @@ -22439,10 +22559,10 @@ packages: /remark@15.0.1: resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==} dependencies: - '@types/mdast': 4.0.2 + '@types/mdast': 4.0.3 remark-parse: 11.0.0 remark-stringify: 11.0.0 - unified: 11.0.3 + unified: 11.0.4 transitivePeerDependencies: - supports-color dev: false @@ -24624,9 +24744,8 @@ packages: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} dev: false - /undici-types@5.25.3: - resolution: {integrity: sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==} - dev: false + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} /undici@5.22.1: resolution: {integrity: sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==} @@ -24689,8 +24808,8 @@ packages: '@types/concat-stream': 2.0.0 '@types/debug': 4.1.8 '@types/is-empty': 1.2.1 - '@types/node': 20.8.7 - '@types/unist': 3.0.1 + '@types/node': 20.9.0 + '@types/unist': 3.0.2 '@ungap/structured-clone': 1.2.0 concat-stream: 2.0.0 debug: 4.3.4(supports-color@5.5.0) @@ -24717,7 +24836,7 @@ packages: prettier: ^3.0.0 dependencies: prettier: 3.0.3 - unified: 11.0.3 + unified: 11.0.4 dev: false /unified@10.1.2: @@ -24734,7 +24853,19 @@ packages: /unified@11.0.3: resolution: {integrity: sha512-jlCV402P+YDcFcB2VcN/n8JasOddqIiaxv118wNBoZXEhOn+lYG7BR4Bfg2BwxvlK58dwbuH2w7GX2esAjL6Mg==} dependencies: - '@types/unist': 3.0.0 + '@types/unist': 3.0.2 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.1.0 + vfile: 6.0.1 + dev: true + + /unified@11.0.4: + resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==} + dependencies: + '@types/unist': 3.0.2 bail: 2.0.2 devlop: 1.1.0 extend: 3.0.2 @@ -24752,7 +24883,7 @@ packages: /unist-builder@4.0.0: resolution: {integrity: sha512-wmRFnH+BLpZnTKpc5L7O67Kac89s9HMrtELpnNaE6TAobq5DTZZs5YaTQfAZBA9bFPECx2uVAPO31c+GVug8mg==} dependencies: - '@types/unist': 3.0.0 + '@types/unist': 3.0.2 dev: true /unist-util-generated@2.0.1: @@ -24762,7 +24893,7 @@ packages: /unist-util-inspect@8.0.0: resolution: {integrity: sha512-/3Wn/wU6/H6UEo4FoYUeo8KUePN8ERiZpQYFWYoihOsr1DoDuv80PeB0hobVZyYSvALa2e556bG1A1/AbwU4yg==} dependencies: - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 dev: false /unist-util-is@4.1.0: @@ -24777,7 +24908,7 @@ packages: /unist-util-is@6.0.0: resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} dependencies: - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 /unist-util-position-from-estree@1.1.2: resolution: {integrity: sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==} @@ -24793,7 +24924,7 @@ packages: /unist-util-position@5.0.0: resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} dependencies: - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 dev: false /unist-util-remove-position@4.0.2: @@ -24818,7 +24949,7 @@ packages: /unist-util-stringify-position@4.0.0: resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} dependencies: - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 /unist-util-visit-parents@3.1.1: resolution: {integrity: sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==} @@ -24836,7 +24967,7 @@ packages: /unist-util-visit-parents@6.0.1: resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} dependencies: - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 unist-util-is: 6.0.0 /unist-util-visit@2.0.3: @@ -24857,7 +24988,7 @@ packages: /unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} dependencies: - '@types/unist': 3.0.0 + '@types/unist': 3.0.2 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 @@ -25164,7 +25295,7 @@ packages: /vfile-location@5.0.2: resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} dependencies: - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 vfile: 6.0.1 dev: false @@ -25177,7 +25308,7 @@ packages: /vfile-message@4.0.2: resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} dependencies: - '@types/unist': 3.0.1 + '@types/unist': 3.0.2 unist-util-stringify-position: 4.0.0 /vfile-reporter@8.1.0: @@ -25218,7 +25349,7 @@ packages: /vfile@6.0.1: resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} dependencies: - '@types/unist': 3.0.0 + '@types/unist': 3.0.2 unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2