From 80bcd0820c09dddb14ffa1c4a0c3318c61d40de2 Mon Sep 17 00:00:00 2001 From: Katrin Shibakova Date: Fri, 6 May 2022 13:26:39 +0300 Subject: [PATCH 1/7] added a data field to the link, removed unused imports --- server/mdx-config-docs.ts | 1 - server/mdx-helpers.ts | 1 - server/remark-includes.ts | 13 +++++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/server/mdx-config-docs.ts b/server/mdx-config-docs.ts index 1c9bfb8d88..d1a8188d1b 100644 --- a/server/mdx-config-docs.ts +++ b/server/mdx-config-docs.ts @@ -19,7 +19,6 @@ import remarkVariables from "./remark-variables"; import remarkMdxDisableExplicitJsx from "remark-mdx-disable-explicit-jsx"; import remarkCodeSnippet from "./remark-code-snippet"; import remarkImportFiles from "./remark-import-files"; -import remarkLintDetails from "./remark-lint-details"; import { getVersion, getVersionRootPath } from "./docs-helpers"; import { loadConfig } from "./config-docs"; import { fetchVideoMeta } from "./youtube-meta"; diff --git a/server/mdx-helpers.ts b/server/mdx-helpers.ts index 406eeb0db9..e1b88835f6 100644 --- a/server/mdx-helpers.ts +++ b/server/mdx-helpers.ts @@ -13,7 +13,6 @@ import type { } from "./types-unist"; import { createEstree } from "./estree-helpers"; -import stringifyObject from "stringify-object"; export const createMdxjsEsmNode = (value: string): EsmNode => { return { diff --git a/server/remark-includes.ts b/server/remark-includes.ts index a44fb4ffb8..129aec53be 100644 --- a/server/remark-includes.ts +++ b/server/remark-includes.ts @@ -26,6 +26,7 @@ import { mdxFromMarkdown } from "mdast-util-mdx"; import { gfmFromMarkdown } from "mdast-util-gfm"; import { frontmatterFromMarkdown } from "mdast-util-frontmatter"; +import { updateOrCreateAttribute } from "./mdx-helpers"; import updateMessages from "./update-vfile-messages"; const includeRegexpBase = "\\(!([^!]+)!\\)`?"; @@ -66,6 +67,15 @@ const numIncludes = (value: string) => value.match(globalIncludeRegexp).length; const isInclude = (node: Code | Text): node is Code | Text => typeof node.value === "string" && includeRegexp.test(node.value); +const addDataToLinks = (node, path: string) => { + if (node.type === "link") { + if (!node.data) { + node.data = { partialPath: path }; + } + } + node.children?.forEach((child) => addDataToLinks(child, path)); +}; + export interface RemarkIncludesOptions { rootDir?: string | ((vfile: VFile) => string); lint?: boolean; @@ -131,12 +141,15 @@ export default function remarkIncludes({ ], }); + addDataToLinks(tree, path); + const grandParent = ancestors[ancestors.length - 2] as Parent; const parentIndex = grandParent.children.indexOf(parent); grandParent.children.splice(parentIndex, 1, ...tree.children); } else { node.value = result; + console.log("node-value", result); } } From 9712e13b3f1975ecfb0d1492d4daa56f4e2fe9f9 Mon Sep 17 00:00:00 2001 From: Katrin Shibakova Date: Tue, 10 May 2022 17:45:24 +0300 Subject: [PATCH 2/7] simple relative links are implemented --- server/remark-includes.ts | 4 +--- server/remark-links.ts | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/server/remark-includes.ts b/server/remark-includes.ts index 129aec53be..7a492c8678 100644 --- a/server/remark-includes.ts +++ b/server/remark-includes.ts @@ -69,9 +69,7 @@ const isInclude = (node: Code | Text): node is Code | Text => const addDataToLinks = (node, path: string) => { if (node.type === "link") { - if (!node.data) { - node.data = { partialPath: path }; - } + node.data = { partialPath: path }; } node.children?.forEach((child) => addDataToLinks(child, path)); }; diff --git a/server/remark-links.ts b/server/remark-links.ts index e0beaab113..9682cd8b1d 100644 --- a/server/remark-links.ts +++ b/server/remark-links.ts @@ -15,6 +15,7 @@ import type { Link as MdastLink } from "mdast"; import type { EsmNode, MdxAnyElement, MdxastNode } from "./types-unist"; import { visit } from "unist-util-visit"; +import { dirname, join, relative } from "path"; import { isExternalLink, isHash, isPage } from "../utils/url"; interface ObjectHref { @@ -73,13 +74,35 @@ const isRemarkLinkWilthLocalHref = (node: MdxastNode): node is MdastLink => { return node.type === "link" && isLocalHref(node.url); }; +const getRelativePath = ( + href: string, + basefilePath: string, + partialPath: string +) => { + const path = dirname("docs/pages" + basefilePath.split("docs/pages")[1]); + const pathFromPartial = join(dirname(partialPath), href); + const relativePath = relative(path, pathFromPartial); + + return relativePath; +}; + export default function remarkLinks(): Transformer { return (root, vfile) => { const basename = vfile?.basename || ""; visit(root, (node: MdxastNode) => { if (isRemarkLinkWilthLocalHref(node)) { - node.url = updateHref(basename, node.url) as string; + let url = node.url; + + if (node.data?.partialPath) { + url = getRelativePath( + url, + vfile.path, + node.data?.partialPath as string + ); + } + + node.url = updateHref(basename, url) as string; } else if (isMdxComponentWithLocalHref(node)) { const hrefAttribute = node.attributes.find( ({ name }) => name === "href" From 13af089d6c4c331ffc74d8392a9705160e46be47 Mon Sep 17 00:00:00 2001 From: Katrin Shibakova Date: Wed, 11 May 2022 12:57:36 +0300 Subject: [PATCH 3/7] added support for relative links inside a component --- server/remark-links.ts | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/server/remark-links.ts b/server/remark-links.ts index 9682cd8b1d..0c16dcc5a8 100644 --- a/server/remark-links.ts +++ b/server/remark-links.ts @@ -75,10 +75,14 @@ const isRemarkLinkWilthLocalHref = (node: MdxastNode): node is MdastLink => { }; const getRelativePath = ( - href: string, + href: Href, basefilePath: string, partialPath: string ) => { + if (!isPlainString(href)) { + return href; + } + const path = dirname("docs/pages" + basefilePath.split("docs/pages")[1]); const pathFromPartial = join(dirname(partialPath), href); const relativePath = relative(path, pathFromPartial); @@ -94,12 +98,12 @@ export default function remarkLinks(): Transformer { if (isRemarkLinkWilthLocalHref(node)) { let url = node.url; - if (node.data?.partialPath) { + if (node.data?.partialPath && !/^\//.test(url)) { url = getRelativePath( url, vfile.path, node.data?.partialPath as string - ); + ) as string; } node.url = updateHref(basename, url) as string; @@ -107,11 +111,21 @@ export default function remarkLinks(): Transformer { const hrefAttribute = node.attributes.find( ({ name }) => name === "href" ); + let href = hrefAttribute.value; + + if ( + node.data?.partialPath && + typeof href === "string" && + !/^\//.test(href) + ) { + href = getRelativePath( + href as Href, + vfile.path, + node.data?.partialPath as string + ) as string; + } - hrefAttribute.value = updateHref( - basename, - hrefAttribute.value as Href - ) as string; + hrefAttribute.value = updateHref(basename, href as Href) as string; } }); }; From d9367ed5a8792eb42f35ff5f957e2ac4f561bba3 Mon Sep 17 00:00:00 2001 From: Katrin Shibakova Date: Wed, 11 May 2022 18:38:42 +0300 Subject: [PATCH 4/7] added a some code improvements --- server/remark-includes.ts | 2 -- server/remark-links.ts | 52 +++++++++++++-------------------------- 2 files changed, 17 insertions(+), 37 deletions(-) diff --git a/server/remark-includes.ts b/server/remark-includes.ts index 7a492c8678..18ede9268a 100644 --- a/server/remark-includes.ts +++ b/server/remark-includes.ts @@ -26,7 +26,6 @@ import { mdxFromMarkdown } from "mdast-util-mdx"; import { gfmFromMarkdown } from "mdast-util-gfm"; import { frontmatterFromMarkdown } from "mdast-util-frontmatter"; -import { updateOrCreateAttribute } from "./mdx-helpers"; import updateMessages from "./update-vfile-messages"; const includeRegexpBase = "\\(!([^!]+)!\\)`?"; @@ -147,7 +146,6 @@ export default function remarkIncludes({ grandParent.children.splice(parentIndex, 1, ...tree.children); } else { node.value = result; - console.log("node-value", result); } } diff --git a/server/remark-links.ts b/server/remark-links.ts index 0c16dcc5a8..3020053393 100644 --- a/server/remark-links.ts +++ b/server/remark-links.ts @@ -74,21 +74,25 @@ const isRemarkLinkWilthLocalHref = (node: MdxastNode): node is MdastLink => { return node.type === "link" && isLocalHref(node.url); }; -const getRelativePath = ( - href: Href, - basefilePath: string, - partialPath: string -) => { - if (!isPlainString(href)) { +function handlePartialLink( + href: T, + node: MdxastNode, + mdxPath: string +): T | string { + if ( + typeof href !== "string" || + href.at(0) === "/" || + !node.data?.partialPath + ) { return href; } - const path = dirname("docs/pages" + basefilePath.split("docs/pages")[1]); - const pathFromPartial = join(dirname(partialPath), href); - const relativePath = relative(path, pathFromPartial); + const absStart = "docs/pages"; + const absMdxPath = dirname(absStart + mdxPath.split(absStart).pop()); + const absTargetPath = join(dirname(node.data.partialPath as string), href); - return relativePath; -}; + return relative(absMdxPath, absTargetPath); +} export default function remarkLinks(): Transformer { return (root, vfile) => { @@ -96,35 +100,13 @@ export default function remarkLinks(): Transformer { visit(root, (node: MdxastNode) => { if (isRemarkLinkWilthLocalHref(node)) { - let url = node.url; - - if (node.data?.partialPath && !/^\//.test(url)) { - url = getRelativePath( - url, - vfile.path, - node.data?.partialPath as string - ) as string; - } - + const url = handlePartialLink(node.url, node, vfile.path); node.url = updateHref(basename, url) as string; } else if (isMdxComponentWithLocalHref(node)) { const hrefAttribute = node.attributes.find( ({ name }) => name === "href" ); - let href = hrefAttribute.value; - - if ( - node.data?.partialPath && - typeof href === "string" && - !/^\//.test(href) - ) { - href = getRelativePath( - href as Href, - vfile.path, - node.data?.partialPath as string - ) as string; - } - + const href = handlePartialLink(hrefAttribute.value, node, vfile.path); hrefAttribute.value = updateHref(basename, href as Href) as string; } }); From 81b87aad28cfc8c8d0544e045a51a9c2d315e6f9 Mon Sep 17 00:00:00 2001 From: Katrin Shibakova Date: Wed, 11 May 2022 18:46:14 +0300 Subject: [PATCH 5/7] fixed tests --- server/remark-links.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/server/remark-links.ts b/server/remark-links.ts index 3020053393..7c5a23ef8a 100644 --- a/server/remark-links.ts +++ b/server/remark-links.ts @@ -79,11 +79,7 @@ function handlePartialLink( node: MdxastNode, mdxPath: string ): T | string { - if ( - typeof href !== "string" || - href.at(0) === "/" || - !node.data?.partialPath - ) { + if (typeof href !== "string" || href[0] === "/" || !node.data?.partialPath) { return href; } From 87f49a6331fb14b5b84860feff5e558ae4d04f80 Mon Sep 17 00:00:00 2001 From: Katrin Shibakova Date: Fri, 13 May 2022 19:33:53 +0400 Subject: [PATCH 6/7] moved the relative link logic to the renark-include plugin --- server/remark-includes.ts | 21 +++++++++++++++------ server/remark-links.ts | 26 +++++--------------------- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/server/remark-includes.ts b/server/remark-includes.ts index 18ede9268a..e74e66b3c0 100644 --- a/server/remark-includes.ts +++ b/server/remark-includes.ts @@ -11,11 +11,10 @@ import type { Parent } from "unist"; import type { Content, Code, Text } from "mdast"; import type { VFile } from "vfile"; +import { dirname, join, relative } from "path"; import { existsSync, readFileSync } from "fs"; -import { join } from "path"; import { visitParents } from "unist-util-visit-parents"; - import { fromMarkdown } from "mdast-util-from-markdown"; import { mdxjs } from "micromark-extension-mdxjs"; @@ -66,11 +65,21 @@ const numIncludes = (value: string) => value.match(globalIncludeRegexp).length; const isInclude = (node: Code | Text): node is Code | Text => typeof node.value === "string" && includeRegexp.test(node.value); -const addDataToLinks = (node, path: string) => { +const handlePartialLink = (node, path: string, mdxPath: string) => { if (node.type === "link") { - node.data = { partialPath: path }; + const href = node.url; + + if (typeof href !== "string" || href[0] === "/" || /^http/.test(href)) { + return href; + } + + const absStart = "docs/pages"; + const absMdxPath = dirname(absStart + mdxPath.split(absStart).pop()); + const absTargetPath = join(dirname(path), href); + + node.url = relative(absMdxPath, absTargetPath); } - node.children?.forEach((child) => addDataToLinks(child, path)); + node.children?.forEach((child) => handlePartialLink(child, path, mdxPath)); }; export interface RemarkIncludesOptions { @@ -138,7 +147,7 @@ export default function remarkIncludes({ ], }); - addDataToLinks(tree, path); + handlePartialLink(tree, path, vfile.path); const grandParent = ancestors[ancestors.length - 2] as Parent; const parentIndex = grandParent.children.indexOf(parent); diff --git a/server/remark-links.ts b/server/remark-links.ts index 7c5a23ef8a..abcb0de053 100644 --- a/server/remark-links.ts +++ b/server/remark-links.ts @@ -15,7 +15,6 @@ import type { Link as MdastLink } from "mdast"; import type { EsmNode, MdxAnyElement, MdxastNode } from "./types-unist"; import { visit } from "unist-util-visit"; -import { dirname, join, relative } from "path"; import { isExternalLink, isHash, isPage } from "../utils/url"; interface ObjectHref { @@ -74,36 +73,21 @@ const isRemarkLinkWilthLocalHref = (node: MdxastNode): node is MdastLink => { return node.type === "link" && isLocalHref(node.url); }; -function handlePartialLink( - href: T, - node: MdxastNode, - mdxPath: string -): T | string { - if (typeof href !== "string" || href[0] === "/" || !node.data?.partialPath) { - return href; - } - - const absStart = "docs/pages"; - const absMdxPath = dirname(absStart + mdxPath.split(absStart).pop()); - const absTargetPath = join(dirname(node.data.partialPath as string), href); - - return relative(absMdxPath, absTargetPath); -} - export default function remarkLinks(): Transformer { return (root, vfile) => { const basename = vfile?.basename || ""; visit(root, (node: MdxastNode) => { if (isRemarkLinkWilthLocalHref(node)) { - const url = handlePartialLink(node.url, node, vfile.path); - node.url = updateHref(basename, url) as string; + node.url = updateHref(basename, node.url) as string; } else if (isMdxComponentWithLocalHref(node)) { const hrefAttribute = node.attributes.find( ({ name }) => name === "href" ); - const href = handlePartialLink(hrefAttribute.value, node, vfile.path); - hrefAttribute.value = updateHref(basename, href as Href) as string; + hrefAttribute.value = updateHref( + basename, + hrefAttribute.value as Href + ) as string; } }); }; From a3b2f914655a27cbfcd23e682d1c9156e4a51e70 Mon Sep 17 00:00:00 2001 From: Katrin Shibakova Date: Wed, 18 May 2022 16:59:52 +0300 Subject: [PATCH 7/7] edits to the reviewer's comments have been added --- server/remark-includes.ts | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/server/remark-includes.ts b/server/remark-includes.ts index e74e66b3c0..1fad62b7f0 100644 --- a/server/remark-includes.ts +++ b/server/remark-includes.ts @@ -11,6 +11,7 @@ import type { Parent } from "unist"; import type { Content, Code, Text } from "mdast"; import type { VFile } from "vfile"; +import type { Node } from "mdast-util-from-markdown/lib"; import { dirname, join, relative } from "path"; import { existsSync, readFileSync } from "fs"; @@ -65,21 +66,41 @@ const numIncludes = (value: string) => value.match(globalIncludeRegexp).length; const isInclude = (node: Code | Text): node is Code | Text => typeof node.value === "string" && includeRegexp.test(node.value); -const handlePartialLink = (node, path: string, mdxPath: string) => { +/** + * correct relative paths resolving in partial docs + * i.e. start realtive paths from the partial file directory, not from place where it is being inserted + * example: + * main file: docs/page/1.mdx + * partial: docs/partials/headers/1.mdx + * + * With this utility path like that + * ../image.jpg + * in partial will be pointing to + * docs/partials/image.jpg + * and without: + * docs/image.jpg + */ +const handlePartialLink = (node: Node, path: string, mdxPath: string) => { if (node.type === "link") { const href = node.url; if (typeof href !== "string" || href[0] === "/" || /^http/.test(href)) { return href; } - + // root where all documentation pages store const absStart = "docs/pages"; + // find an "abs" (starting with root) directory path of the file in which the partial doc was inserted const absMdxPath = dirname(absStart + mdxPath.split(absStart).pop()); const absTargetPath = join(dirname(path), href); - + // make the reference path relative to the place where the partial doc was inserted node.url = relative(absMdxPath, absTargetPath); } - node.children?.forEach((child) => handlePartialLink(child, path, mdxPath)); + + if ("children" in node) { + node.children?.forEach?.((child) => + handlePartialLink(child, path, mdxPath) + ); + } }; export interface RemarkIncludesOptions {