From 888fcf6d09c923c50898690a318a4cc0a2d8116b Mon Sep 17 00:00:00 2001 From: Paul Gottschling Date: Mon, 8 Jul 2024 11:46:13 -0400 Subject: [PATCH] Sort out runtime errors --- server/remark-toc.ts | 37 ++++++++++++++++++++++++------------ uvu-tests/remark-toc.test.ts | 4 ++-- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/server/remark-toc.ts b/server/remark-toc.ts index 17aad51f14..5aa7487e20 100644 --- a/server/remark-toc.ts +++ b/server/remark-toc.ts @@ -1,10 +1,22 @@ import * as nodeFS from "fs"; import * as path from "path"; +import matter from "gray-matter"; + +// relativePathToFile takes a filepath and returns a path we can use in links +// to the file in a table of contents page. The link path is a relative path +// to the directory where we are placing the table of contents page. +// @param filepath {string} - the path from which to generate a link path. +const relativePathToFile = (root: string, filepath: string) => { + // Return the filepath without the first segment, removing the first + // slash. This is because the TOC file we are generating is located at + // root. + return filepath.slice(root.length).replace(/^\//, ""); +}; export const resolveTOCIncludes = (dirPath: string, fs = nodeFS) => { const parts = path.parse(dirPath); const tocIntro = path.join(parts.dir, parts.name, parts.name + ".mdx"); - if (!this.fs.existsSync(tocIntro)) { + if (!fs.existsSync(tocIntro)) { throw `There must be a page called ${tocIntro} to introduce ${dirPath}".`; } @@ -12,7 +24,7 @@ export const resolveTOCIncludes = (dirPath: string, fs = nodeFS) => { let mdxFiles = new Set(); const dirs = files.reduce((accum, current) => { - const stats = this.fs.statSync(path.join(dirPath, current)); + const stats = fs.statSync(path.join(dirPath, current)); if (!stats.isDirectory()) { mdxFiles.add(path.join(dirPath, current)); return accum; @@ -24,7 +36,7 @@ export const resolveTOCIncludes = (dirPath: string, fs = nodeFS) => { // Add rows to the menu page for non-menu pages. let entries = []; mdxFiles.forEach((f, idx) => { - const text = this.fs.readFileSync(f, "utf8"); + const text = fs.readFileSync(f, "utf8"); const lines = text.split("\n"); // Skip TOC pages (with the same name as the parent directory) since we @@ -34,27 +46,28 @@ export const resolveTOCIncludes = (dirPath: string, fs = nodeFS) => { return; } - let relPath = this.relativePathToFile(f); - const fm = this.getFrontmatter(text); + let relPath = relativePathToFile(dirPath, f); + const { data } = matter(text); - entries.push(`- [${fm.title}](${relPath}): ${fm.description}`); + entries.push(`- [${data.title}](${relPath}): ${data.description}`); }); - newText += entries.join(""); // Add rows to the menu page for first-level child menu pages let menuEntries = []; dirs.forEach((f, idx) => { const menuPath = path.join(f, path.parse(f).base + ".mdx"); - if (!this.fs.existsSync(menuPath)) { + if (!fs.existsSync(menuPath)) { throw new Error( `there must be a page called ${menuPath} that introduces ${f}` ); } - const text = this.fs.readFileSync(menuPath, "utf8"); - let relPath = this.relativePathToFile(menuPath); - const fm = this.getFrontmatter(text); + const text = fs.readFileSync(menuPath, "utf8"); + let relPath = relativePathToFile(dirPath, menuPath); + const { data } = matter(text); - entries.push(`- [${fm.title}](${relPath}) (section): ${fm.description}`); + entries.push( + `- [${data.title}](${relPath}) (section): ${data.description}` + ); }); entries.sort(); return entries.join("\n"); diff --git a/uvu-tests/remark-toc.test.ts b/uvu-tests/remark-toc.test.ts index 1868b6affd..9febbdfb7d 100644 --- a/uvu-tests/remark-toc.test.ts +++ b/uvu-tests/remark-toc.test.ts @@ -85,7 +85,7 @@ description: "Protecting App 2 with Teleport" Suite("multiple links to directories", () => { const expected = `- [Application Access](application-access/application-access.mdx) (section): Guides related to Application Access -- [Database Access](database-access/database-access.mdx): Guides related to Database Access +- [Database Access](database-access/database-access.mdx) (section): Guides related to Database Access. `; const vol = Volume.fromJSON(testFilesTwoSections); @@ -132,7 +132,7 @@ description: "Guides related to JWTs" Suite("orders sections correctly", () => { const expected = ` - [Application Access](application-access/application-access.mdx) (section): Guides related to Application Access -- [Desktop Access](desktop-access/database-access.mdx) (seciton): Guides related to Desktop Access +- [Desktop Access](desktop-access/database-access.mdx) (section): Guides related to Desktop Access - [API Usage](api.mdx): Using the API. - [Initial Setup](initial-setup.mdx): How to set up the product for the first time. - [Kubernetes](kubernetes.mdx): A guide related to Kubernetes.