mintlify 2.1.0 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +2 -16
- package/index.js +3 -0
- package/package.json +23 -46
- package/bin/browser.js +0 -24
- package/bin/browser.js.map +0 -1
- package/bin/constants.js +0 -32
- package/bin/constants.js.map +0 -1
- package/bin/downloadImage.js +0 -85
- package/bin/downloadImage.js.map +0 -1
- package/bin/index.js +0 -49
- package/bin/index.js.map +0 -1
- package/bin/local-preview/helper-commands/installDepsCommand.js +0 -12
- package/bin/local-preview/helper-commands/installDepsCommand.js.map +0 -1
- package/bin/local-preview/index.js +0 -154
- package/bin/local-preview/index.js.map +0 -1
- package/bin/local-preview/listener/categorize.js +0 -95
- package/bin/local-preview/listener/categorize.js.map +0 -1
- package/bin/local-preview/listener/categorizeFiles.js +0 -47
- package/bin/local-preview/listener/categorizeFiles.js.map +0 -1
- package/bin/local-preview/listener/generate.js +0 -89
- package/bin/local-preview/listener/generate.js.map +0 -1
- package/bin/local-preview/listener/index.js +0 -200
- package/bin/local-preview/listener/index.js.map +0 -1
- package/bin/local-preview/listener/update.js +0 -24
- package/bin/local-preview/listener/update.js.map +0 -1
- package/bin/local-preview/listener/utils/createPage.js +0 -167
- package/bin/local-preview/listener/utils/createPage.js.map +0 -1
- package/bin/local-preview/listener/utils/fileIsMdxOrMd.js +0 -12
- package/bin/local-preview/listener/utils/fileIsMdxOrMd.js.map +0 -1
- package/bin/local-preview/listener/utils/getOpenApiContext.js +0 -57
- package/bin/local-preview/listener/utils/getOpenApiContext.js.map +0 -1
- package/bin/local-preview/listener/utils/mintConfigFile.js +0 -22
- package/bin/local-preview/listener/utils/mintConfigFile.js.map +0 -1
- package/bin/local-preview/listener/utils/toTitleCase.js +0 -36
- package/bin/local-preview/listener/utils/toTitleCase.js.map +0 -1
- package/bin/local-preview/listener/utils/types.js +0 -2
- package/bin/local-preview/listener/utils/types.js.map +0 -1
- package/bin/local-preview/listener/utils.js +0 -67
- package/bin/local-preview/listener/utils.js.map +0 -1
- package/bin/local-preview/utils/categorizeFiles.js +0 -63
- package/bin/local-preview/utils/categorizeFiles.js.map +0 -1
- package/bin/local-preview/utils/getOpenApiContext.js +0 -58
- package/bin/local-preview/utils/getOpenApiContext.js.map +0 -1
- package/bin/local-preview/utils/injectFavicons.js +0 -72
- package/bin/local-preview/utils/injectFavicons.js.map +0 -1
- package/bin/local-preview/utils/listener.js +0 -116
- package/bin/local-preview/utils/listener.js.map +0 -1
- package/bin/local-preview/utils/metadata.js +0 -118
- package/bin/local-preview/utils/metadata.js.map +0 -1
- package/bin/local-preview/utils/mintConfigFile.js +0 -43
- package/bin/local-preview/utils/mintConfigFile.js.map +0 -1
- package/bin/local-preview/utils/openApiCheck.js +0 -15
- package/bin/local-preview/utils/openApiCheck.js.map +0 -1
- package/bin/local-preview/utils/slugToTitle.js +0 -8
- package/bin/local-preview/utils/slugToTitle.js.map +0 -1
- package/bin/navigation.js +0 -4
- package/bin/navigation.js.map +0 -1
- package/bin/pageTemplate.js +0 -30
- package/bin/pageTemplate.js.map +0 -1
- package/bin/scraping/combineNavWithEmptyGroupTitles.js +0 -20
- package/bin/scraping/combineNavWithEmptyGroupTitles.js.map +0 -1
- package/bin/scraping/detectFramework.js +0 -39
- package/bin/scraping/detectFramework.js.map +0 -1
- package/bin/scraping/downloadAllImages.js +0 -33
- package/bin/scraping/downloadAllImages.js.map +0 -1
- package/bin/scraping/downloadLogoImage.js +0 -13
- package/bin/scraping/downloadLogoImage.js.map +0 -1
- package/bin/scraping/getSitemapLinks.js +0 -18
- package/bin/scraping/getSitemapLinks.js.map +0 -1
- package/bin/scraping/replaceImagePaths.js +0 -17
- package/bin/scraping/replaceImagePaths.js.map +0 -1
- package/bin/scraping/scrapeFileGettingFileNameFromUrl.js +0 -43
- package/bin/scraping/scrapeFileGettingFileNameFromUrl.js.map +0 -1
- package/bin/scraping/scrapeGettingFileNameFromUrl.js +0 -13
- package/bin/scraping/scrapeGettingFileNameFromUrl.js.map +0 -1
- package/bin/scraping/scrapePage.js +0 -10
- package/bin/scraping/scrapePage.js.map +0 -1
- package/bin/scraping/scrapePageCommands.js +0 -55
- package/bin/scraping/scrapePageCommands.js.map +0 -1
- package/bin/scraping/scrapeSection.js +0 -12
- package/bin/scraping/scrapeSection.js.map +0 -1
- package/bin/scraping/scrapeSectionCommands.js +0 -66
- package/bin/scraping/scrapeSectionCommands.js.map +0 -1
- package/bin/scraping/site-scrapers/Intercom/scrapeIntercomPage.js +0 -27
- package/bin/scraping/site-scrapers/Intercom/scrapeIntercomPage.js.map +0 -1
- package/bin/scraping/site-scrapers/Intercom/scrapeIntercomSection.js +0 -32
- package/bin/scraping/site-scrapers/Intercom/scrapeIntercomSection.js.map +0 -1
- package/bin/scraping/site-scrapers/alternateGroupTitle.js +0 -9
- package/bin/scraping/site-scrapers/alternateGroupTitle.js.map +0 -1
- package/bin/scraping/site-scrapers/links-per-group/getDocusaurusLinksPerGroup.js +0 -34
- package/bin/scraping/site-scrapers/links-per-group/getDocusaurusLinksPerGroup.js.map +0 -1
- package/bin/scraping/site-scrapers/links-per-group/getLinksRecursively.js +0 -38
- package/bin/scraping/site-scrapers/links-per-group/getLinksRecursively.js.map +0 -1
- package/bin/scraping/site-scrapers/links-per-group/getLinksRecursivelyGitBook.js +0 -38
- package/bin/scraping/site-scrapers/links-per-group/getLinksRecursivelyGitBook.js.map +0 -1
- package/bin/scraping/site-scrapers/openNestedDocusaurusMenus.js +0 -30
- package/bin/scraping/site-scrapers/openNestedDocusaurusMenus.js.map +0 -1
- package/bin/scraping/site-scrapers/openNestedGitbookMenus.js +0 -17
- package/bin/scraping/site-scrapers/openNestedGitbookMenus.js.map +0 -1
- package/bin/scraping/site-scrapers/scrapeDocusaurusPage.js +0 -49
- package/bin/scraping/site-scrapers/scrapeDocusaurusPage.js.map +0 -1
- package/bin/scraping/site-scrapers/scrapeDocusaurusSection.js +0 -30
- package/bin/scraping/site-scrapers/scrapeDocusaurusSection.js.map +0 -1
- package/bin/scraping/site-scrapers/scrapeGitBookPage.js +0 -47
- package/bin/scraping/site-scrapers/scrapeGitBookPage.js.map +0 -1
- package/bin/scraping/site-scrapers/scrapeGitBookSection.js +0 -52
- package/bin/scraping/site-scrapers/scrapeGitBookSection.js.map +0 -1
- package/bin/scraping/site-scrapers/scrapeReadMePage.js +0 -36
- package/bin/scraping/site-scrapers/scrapeReadMePage.js.map +0 -1
- package/bin/scraping/site-scrapers/scrapeReadMeSection.js +0 -44
- package/bin/scraping/site-scrapers/scrapeReadMeSection.js.map +0 -1
- package/bin/util.js +0 -129
- package/bin/util.js.map +0 -1
- package/bin/validation/isValidLink.js +0 -11
- package/bin/validation/isValidLink.js.map +0 -1
- package/bin/validation/stopIfInvalidLink.js +0 -9
- package/bin/validation/stopIfInvalidLink.js.map +0 -1
- package/scraper.md +0 -121
- package/src/browser.ts +0 -24
- package/src/constants.ts +0 -40
- package/src/downloadImage.ts +0 -110
- package/src/index.ts +0 -112
- package/src/local-preview/helper-commands/installDepsCommand.ts +0 -13
- package/src/local-preview/index.ts +0 -195
- package/src/local-preview/listener/categorize.ts +0 -105
- package/src/local-preview/listener/generate.ts +0 -110
- package/src/local-preview/listener/index.ts +0 -228
- package/src/local-preview/listener/update.ts +0 -27
- package/src/local-preview/listener/utils/createPage.ts +0 -211
- package/src/local-preview/listener/utils/getOpenApiContext.ts +0 -77
- package/src/local-preview/listener/utils/mintConfigFile.ts +0 -28
- package/src/local-preview/listener/utils/toTitleCase.ts +0 -40
- package/src/local-preview/listener/utils/types.ts +0 -16
- package/src/local-preview/listener/utils.ts +0 -78
- package/src/scraping/combineNavWithEmptyGroupTitles.ts +0 -21
- package/src/scraping/detectFramework.ts +0 -47
- package/src/scraping/downloadAllImages.ts +0 -60
- package/src/scraping/downloadLogoImage.ts +0 -25
- package/src/scraping/getSitemapLinks.ts +0 -18
- package/src/scraping/replaceImagePaths.ts +0 -21
- package/src/scraping/scrapeFileGettingFileNameFromUrl.ts +0 -86
- package/src/scraping/scrapeGettingFileNameFromUrl.ts +0 -54
- package/src/scraping/scrapePage.ts +0 -24
- package/src/scraping/scrapePageCommands.ts +0 -66
- package/src/scraping/scrapeSection.ts +0 -28
- package/src/scraping/scrapeSectionCommands.ts +0 -110
- package/src/scraping/site-scrapers/Intercom/scrapeIntercomPage.ts +0 -51
- package/src/scraping/site-scrapers/Intercom/scrapeIntercomSection.ts +0 -53
- package/src/scraping/site-scrapers/alternateGroupTitle.ts +0 -8
- package/src/scraping/site-scrapers/links-per-group/getDocusaurusLinksPerGroup.ts +0 -44
- package/src/scraping/site-scrapers/links-per-group/getLinksRecursively.ts +0 -45
- package/src/scraping/site-scrapers/links-per-group/getLinksRecursivelyGitBook.ts +0 -46
- package/src/scraping/site-scrapers/openNestedDocusaurusMenus.ts +0 -42
- package/src/scraping/site-scrapers/openNestedGitbookMenus.ts +0 -24
- package/src/scraping/site-scrapers/scrapeDocusaurusPage.ts +0 -81
- package/src/scraping/site-scrapers/scrapeDocusaurusSection.ts +0 -63
- package/src/scraping/site-scrapers/scrapeGitBookPage.ts +0 -74
- package/src/scraping/site-scrapers/scrapeGitBookSection.ts +0 -80
- package/src/scraping/site-scrapers/scrapeReadMePage.ts +0 -60
- package/src/scraping/site-scrapers/scrapeReadMeSection.ts +0 -70
- package/src/types.d.ts +0 -29
- package/src/util.ts +0 -161
- package/src/validation/isValidLink.ts +0 -9
- package/src/validation/stopIfInvalidLink.ts +0 -9
- package/tsconfig.json +0 -18
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
// TODO - put in prebuild package
|
|
2
|
-
import path from "path";
|
|
3
|
-
|
|
4
|
-
import { getFileExtension, openApiCheck, getFileList } from "./utils.js";
|
|
5
|
-
import { PotentialFileCategory } from "./utils/types.js";
|
|
6
|
-
|
|
7
|
-
export const categorizeFiles = async (contentDirectoryPath: string) => {
|
|
8
|
-
const allFilesInCmdExecutionPath = await getFileList(contentDirectoryPath);
|
|
9
|
-
const contentFilenames = [];
|
|
10
|
-
const staticFilenames = [];
|
|
11
|
-
const promises = [];
|
|
12
|
-
const openApiFiles = [];
|
|
13
|
-
const snippets = [];
|
|
14
|
-
allFilesInCmdExecutionPath.forEach((filename) => {
|
|
15
|
-
promises.push(
|
|
16
|
-
(async () => {
|
|
17
|
-
const extension = getFileExtension(filename);
|
|
18
|
-
let isOpenApi = false;
|
|
19
|
-
if (extension && (extension === "mdx" || extension === "md")) {
|
|
20
|
-
if (filename.startsWith("/_snippets")) {
|
|
21
|
-
snippets.push(filename);
|
|
22
|
-
} else {
|
|
23
|
-
contentFilenames.push(filename);
|
|
24
|
-
}
|
|
25
|
-
} else if (
|
|
26
|
-
extension &&
|
|
27
|
-
(extension === "json" || extension === "yaml" || extension === "yml")
|
|
28
|
-
) {
|
|
29
|
-
const openApiInfo = await openApiCheck(
|
|
30
|
-
path.join(contentDirectoryPath, filename)
|
|
31
|
-
);
|
|
32
|
-
isOpenApi = openApiInfo.isOpenApi;
|
|
33
|
-
if (isOpenApi) {
|
|
34
|
-
const fileName = path.parse(filename).base;
|
|
35
|
-
openApiFiles.push({
|
|
36
|
-
filename: fileName.substring(0, fileName.lastIndexOf(".")),
|
|
37
|
-
spec: openApiInfo.spec,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
} else if (!filename.endsWith("mint.json") && !isOpenApi) {
|
|
41
|
-
// all other files
|
|
42
|
-
staticFilenames.push(filename);
|
|
43
|
-
}
|
|
44
|
-
})()
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
await Promise.all(promises);
|
|
48
|
-
|
|
49
|
-
return { contentFilenames, staticFilenames, openApiFiles, snippets };
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const excludedMdFiles = ["readme", "license", "contributing", "contribute"];
|
|
53
|
-
|
|
54
|
-
const supportedStaticFileExtensions = [
|
|
55
|
-
".jpeg",
|
|
56
|
-
".jpg",
|
|
57
|
-
".jfif",
|
|
58
|
-
".pjpeg",
|
|
59
|
-
".pjp",
|
|
60
|
-
".png",
|
|
61
|
-
".svg",
|
|
62
|
-
".svgz",
|
|
63
|
-
".ico",
|
|
64
|
-
".webp",
|
|
65
|
-
".gif",
|
|
66
|
-
".apng",
|
|
67
|
-
".avif",
|
|
68
|
-
".bmp",
|
|
69
|
-
".mp4",
|
|
70
|
-
];
|
|
71
|
-
|
|
72
|
-
export const getCategory = (filePath: string): PotentialFileCategory => {
|
|
73
|
-
filePath = filePath.toLowerCase();
|
|
74
|
-
|
|
75
|
-
const parsed = path.parse(filePath);
|
|
76
|
-
|
|
77
|
-
if (parsed.base === "mint.json") {
|
|
78
|
-
return "mintConfig";
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const fileName = parsed.name;
|
|
82
|
-
const extension = parsed.ext;
|
|
83
|
-
if (
|
|
84
|
-
filePath.startsWith("_snippets") &&
|
|
85
|
-
(extension === ".mdx" || extension === ".md")
|
|
86
|
-
) {
|
|
87
|
-
return "snippet";
|
|
88
|
-
} else if (extension === ".mdx") {
|
|
89
|
-
return "page";
|
|
90
|
-
} else if (extension === ".md") {
|
|
91
|
-
// Exclude common markdown files people don't want on their docs website
|
|
92
|
-
if (excludedMdFiles.includes(fileName)) {
|
|
93
|
-
throw new Error("Excluded Md File");
|
|
94
|
-
}
|
|
95
|
-
return "page";
|
|
96
|
-
} else if (extension === ".yaml" || extension === ".yml") {
|
|
97
|
-
return "potentialYamlOpenApiSpec";
|
|
98
|
-
} else if (extension === ".json") {
|
|
99
|
-
return "potentialJsonOpenApiSpec";
|
|
100
|
-
} else if (supportedStaticFileExtensions.includes(extension)) {
|
|
101
|
-
return "staticFile";
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
throw new Error("Unsupported File Type, No change enacted");
|
|
105
|
-
};
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
// TODO - add types
|
|
2
|
-
import { promises as _promises } from "fs";
|
|
3
|
-
import { outputFile } from "fs-extra";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import createPage from "./utils/createPage.js";
|
|
6
|
-
import { OpenApiFile } from "./utils/types.js";
|
|
7
|
-
import { categorizeFiles } from "./categorize.js";
|
|
8
|
-
import { CMD_EXEC_PATH } from "../../constants.js";
|
|
9
|
-
import { getConfigObj } from "./utils/mintConfigFile.js";
|
|
10
|
-
const { readFile } = _promises;
|
|
11
|
-
|
|
12
|
-
// TODO: Put in prebuild package
|
|
13
|
-
const generateNavFromPages = (pages, mintConfigNav) => {
|
|
14
|
-
const createNav = (nav) => {
|
|
15
|
-
return {
|
|
16
|
-
group: nav.group,
|
|
17
|
-
version: nav.version,
|
|
18
|
-
pages: nav.pages.map((page) => {
|
|
19
|
-
if (typeof page === "string") {
|
|
20
|
-
return pages[page];
|
|
21
|
-
}
|
|
22
|
-
return createNav(page);
|
|
23
|
-
}),
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
if (mintConfigNav == null) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let navFile = mintConfigNav.map((nav) => createNav(nav));
|
|
32
|
-
const filterOutNullInPages = (pages) => {
|
|
33
|
-
const newPages = [];
|
|
34
|
-
pages.forEach((page) => {
|
|
35
|
-
if (page == null) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
if (page?.pages) {
|
|
39
|
-
const newGroup = filterOutNullInGroup(page);
|
|
40
|
-
newPages.push(newGroup);
|
|
41
|
-
} else {
|
|
42
|
-
newPages.push(page);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
return newPages;
|
|
47
|
-
};
|
|
48
|
-
const filterOutNullInGroup = (group) => {
|
|
49
|
-
const newPages = filterOutNullInPages(group.pages);
|
|
50
|
-
const newGroup = {
|
|
51
|
-
...group,
|
|
52
|
-
pages: newPages,
|
|
53
|
-
};
|
|
54
|
-
return newGroup;
|
|
55
|
-
};
|
|
56
|
-
const newNavFile = navFile.map((group) => {
|
|
57
|
-
return filterOutNullInGroup(group);
|
|
58
|
-
});
|
|
59
|
-
return newNavFile;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// TODO: Put in prebuild package
|
|
63
|
-
const createPagesAcc = async (
|
|
64
|
-
contentDirectoryPath: string,
|
|
65
|
-
contentFilenames: string[],
|
|
66
|
-
openApiFiles: OpenApiFile[],
|
|
67
|
-
clientPath?: string,
|
|
68
|
-
writeFiles = false
|
|
69
|
-
) => {
|
|
70
|
-
let pagesAcc = {};
|
|
71
|
-
const contentPromises = [];
|
|
72
|
-
contentFilenames.forEach((filename) => {
|
|
73
|
-
contentPromises.push(
|
|
74
|
-
(async () => {
|
|
75
|
-
const sourcePath = path.join(contentDirectoryPath, filename);
|
|
76
|
-
|
|
77
|
-
const contentStr = (await readFile(sourcePath)).toString();
|
|
78
|
-
const { slug, pageMetadata, pageContent } = await createPage(
|
|
79
|
-
filename,
|
|
80
|
-
contentStr,
|
|
81
|
-
contentDirectoryPath,
|
|
82
|
-
openApiFiles
|
|
83
|
-
);
|
|
84
|
-
if (clientPath && writeFiles) {
|
|
85
|
-
const targetPath = path.join(clientPath, "src", "_props", filename);
|
|
86
|
-
await outputFile(targetPath, pageContent, {
|
|
87
|
-
flag: "w",
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
pagesAcc = {
|
|
91
|
-
...pagesAcc,
|
|
92
|
-
[slug]: pageMetadata,
|
|
93
|
-
};
|
|
94
|
-
})()
|
|
95
|
-
);
|
|
96
|
-
});
|
|
97
|
-
await Promise.all(contentPromises);
|
|
98
|
-
return pagesAcc;
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
export const generateNav = async () => {
|
|
102
|
-
const { contentFilenames, openApiFiles } = await categorizeFiles(
|
|
103
|
-
CMD_EXEC_PATH
|
|
104
|
-
);
|
|
105
|
-
const [pageAcc, configObj] = await Promise.all([
|
|
106
|
-
createPagesAcc(CMD_EXEC_PATH, contentFilenames, openApiFiles),
|
|
107
|
-
getConfigObj(CMD_EXEC_PATH),
|
|
108
|
-
]);
|
|
109
|
-
return generateNavFromPages(pageAcc, configObj?.navigation);
|
|
110
|
-
};
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import chokidar from "chokidar";
|
|
2
|
-
import fse from "fs-extra";
|
|
3
|
-
import pathUtil from "path";
|
|
4
|
-
import Chalk from "chalk";
|
|
5
|
-
import mintValidation from "@mintlify/validation";
|
|
6
|
-
import { isFileSizeValid, openApiCheck } from "./utils.js";
|
|
7
|
-
import { updateGeneratedNav, updateOpenApiFiles } from "./update.js";
|
|
8
|
-
import { CLIENT_PATH, CMD_EXEC_PATH } from "../../constants.js";
|
|
9
|
-
import { promises as _promises } from "fs";
|
|
10
|
-
import createPage from "./utils/createPage.js";
|
|
11
|
-
import { getCategory } from "./categorize.js";
|
|
12
|
-
import { PotentialFileCategory, FileCategory } from "./utils/types.js";
|
|
13
|
-
|
|
14
|
-
const { readFile } = _promises;
|
|
15
|
-
|
|
16
|
-
const listener = () => {
|
|
17
|
-
chokidar
|
|
18
|
-
.watch(CMD_EXEC_PATH, {
|
|
19
|
-
ignoreInitial: true,
|
|
20
|
-
ignored: ["node_modules", ".git", ".idea"],
|
|
21
|
-
cwd: CMD_EXEC_PATH,
|
|
22
|
-
})
|
|
23
|
-
.on("add", async (filename: string) => {
|
|
24
|
-
try {
|
|
25
|
-
const category = await onUpdateEvent(filename);
|
|
26
|
-
switch (category) {
|
|
27
|
-
case "page":
|
|
28
|
-
console.log("New page detected: ", filename);
|
|
29
|
-
break;
|
|
30
|
-
case "snippet":
|
|
31
|
-
console.log("New snippet detected: ", filename);
|
|
32
|
-
break;
|
|
33
|
-
case "mintConfig":
|
|
34
|
-
console.log("Config added");
|
|
35
|
-
break;
|
|
36
|
-
case "openApi":
|
|
37
|
-
console.log("OpenApi spec added: ", filename);
|
|
38
|
-
break;
|
|
39
|
-
case "staticFile":
|
|
40
|
-
console.log("Static file added: ", filename);
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
43
|
-
} catch (error) {
|
|
44
|
-
console.error(error.message);
|
|
45
|
-
}
|
|
46
|
-
})
|
|
47
|
-
.on("change", async (filename: string) => {
|
|
48
|
-
try {
|
|
49
|
-
const category = await onUpdateEvent(filename);
|
|
50
|
-
switch (category) {
|
|
51
|
-
case "page":
|
|
52
|
-
console.log("Page edited: ", filename);
|
|
53
|
-
break;
|
|
54
|
-
case "snippet":
|
|
55
|
-
console.log("Snippet edited: ", filename);
|
|
56
|
-
break;
|
|
57
|
-
case "mintConfig":
|
|
58
|
-
console.log("Config edited");
|
|
59
|
-
break;
|
|
60
|
-
case "openApi":
|
|
61
|
-
console.log("OpenApi spec edited: ", filename);
|
|
62
|
-
break;
|
|
63
|
-
case "staticFile":
|
|
64
|
-
console.log("Static file edited: ", filename);
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
} catch (error) {
|
|
68
|
-
console.error(error.message);
|
|
69
|
-
}
|
|
70
|
-
})
|
|
71
|
-
.on("unlink", async (filename: string) => {
|
|
72
|
-
try {
|
|
73
|
-
const potentialCategory = getCategory(filename);
|
|
74
|
-
const targetPath = getTargetPath(potentialCategory, filename);
|
|
75
|
-
if (
|
|
76
|
-
potentialCategory === "page" ||
|
|
77
|
-
potentialCategory === "snippet" ||
|
|
78
|
-
potentialCategory === "mintConfig" ||
|
|
79
|
-
potentialCategory === "staticFile"
|
|
80
|
-
) {
|
|
81
|
-
await fse.remove(targetPath);
|
|
82
|
-
}
|
|
83
|
-
switch (potentialCategory) {
|
|
84
|
-
case "page":
|
|
85
|
-
console.log(`Page deleted: ${filename}`);
|
|
86
|
-
break;
|
|
87
|
-
case "snippet":
|
|
88
|
-
console.log(`Snippet deleted: ${filename}`);
|
|
89
|
-
break;
|
|
90
|
-
case "mintConfig":
|
|
91
|
-
console.log(
|
|
92
|
-
"⚠️ mint.json deleted. Please create a new mint.json file as it is mandatory."
|
|
93
|
-
);
|
|
94
|
-
process.exit(1);
|
|
95
|
-
case "potentialJsonOpenApiSpec":
|
|
96
|
-
case "potentialYamlOpenApiSpec":
|
|
97
|
-
await updateOpenApiFiles();
|
|
98
|
-
await updateGeneratedNav();
|
|
99
|
-
break;
|
|
100
|
-
case "staticFile":
|
|
101
|
-
console.log("Static file deleted: ", filename);
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
} catch (error) {
|
|
105
|
-
console.error(error.message);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const getTargetPath = (
|
|
111
|
-
potentialCategory: PotentialFileCategory,
|
|
112
|
-
filePath: string
|
|
113
|
-
): string => {
|
|
114
|
-
switch (potentialCategory) {
|
|
115
|
-
case "page":
|
|
116
|
-
case "snippet":
|
|
117
|
-
return pathUtil.join(CLIENT_PATH, "src", "_props", filePath);
|
|
118
|
-
case "mintConfig":
|
|
119
|
-
return pathUtil.join(CLIENT_PATH, "src", "_props", "mint.json");
|
|
120
|
-
case "potentialYamlOpenApiSpec":
|
|
121
|
-
case "potentialJsonOpenApiSpec":
|
|
122
|
-
return pathUtil.join(CLIENT_PATH, "src", "_props", "openApiFiles.json");
|
|
123
|
-
case "staticFile":
|
|
124
|
-
return pathUtil.join(CLIENT_PATH, "public", filePath);
|
|
125
|
-
default:
|
|
126
|
-
throw new Error("Invalid category");
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* This function is called when a file is added or changed
|
|
132
|
-
* @param filename
|
|
133
|
-
* @returns FileCategory
|
|
134
|
-
*/
|
|
135
|
-
const onUpdateEvent = async (filename: string): Promise<FileCategory> => {
|
|
136
|
-
const filePath = pathUtil.join(CMD_EXEC_PATH, filename);
|
|
137
|
-
const potentialCategory = getCategory(filename);
|
|
138
|
-
const targetPath = getTargetPath(potentialCategory, filename);
|
|
139
|
-
let regenerateNav = false;
|
|
140
|
-
let category: FileCategory =
|
|
141
|
-
potentialCategory === "potentialYamlOpenApiSpec" ||
|
|
142
|
-
potentialCategory === "potentialJsonOpenApiSpec"
|
|
143
|
-
? "staticFile"
|
|
144
|
-
: potentialCategory;
|
|
145
|
-
|
|
146
|
-
switch (potentialCategory) {
|
|
147
|
-
case "page":
|
|
148
|
-
regenerateNav = true;
|
|
149
|
-
|
|
150
|
-
const contentStr = (await readFile(filePath)).toString();
|
|
151
|
-
const { pageContent } = await createPage(
|
|
152
|
-
filename,
|
|
153
|
-
contentStr,
|
|
154
|
-
CMD_EXEC_PATH,
|
|
155
|
-
[]
|
|
156
|
-
);
|
|
157
|
-
await fse.outputFile(targetPath, pageContent, {
|
|
158
|
-
flag: "w",
|
|
159
|
-
});
|
|
160
|
-
break;
|
|
161
|
-
case "snippet":
|
|
162
|
-
await fse.copy(filePath, targetPath);
|
|
163
|
-
break;
|
|
164
|
-
case "mintConfig":
|
|
165
|
-
regenerateNav = true;
|
|
166
|
-
|
|
167
|
-
const mintJsonFileContent = (await readFile(filePath)).toString();
|
|
168
|
-
try {
|
|
169
|
-
const mintConfig = JSON.parse(mintJsonFileContent);
|
|
170
|
-
const { status, errors, warnings } =
|
|
171
|
-
mintValidation.validateMintConfig(mintConfig);
|
|
172
|
-
|
|
173
|
-
errors.forEach((error) => {
|
|
174
|
-
console.error(`🚨 ${Chalk.red(error)}`);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
warnings.forEach((warning) => {
|
|
178
|
-
console.warn(`⚠️ ${Chalk.yellow(warning)}`);
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
if (status === "success") {
|
|
182
|
-
await fse.copy(filePath, targetPath);
|
|
183
|
-
}
|
|
184
|
-
} catch (error) {
|
|
185
|
-
if (error.name === "SyntaxError") {
|
|
186
|
-
console.error(
|
|
187
|
-
`🚨 ${Chalk.red(
|
|
188
|
-
"mint.json has invalid JSON. You are likely missing a comma or a bracket. You can paste your mint.json file into https://jsonlint.com/ to get a more specific error message."
|
|
189
|
-
)}`
|
|
190
|
-
);
|
|
191
|
-
} else {
|
|
192
|
-
console.error(`🚨 ${Chalk.red(error.message)}`);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
break;
|
|
197
|
-
case "potentialYamlOpenApiSpec":
|
|
198
|
-
case "potentialJsonOpenApiSpec":
|
|
199
|
-
let isOpenApi = false;
|
|
200
|
-
const openApiInfo = await openApiCheck(filePath);
|
|
201
|
-
isOpenApi = openApiInfo.isOpenApi;
|
|
202
|
-
if (isOpenApi) {
|
|
203
|
-
// TODO: Instead of re-generating all openApi files, optimize by just updating the specific file that changed.
|
|
204
|
-
await updateOpenApiFiles();
|
|
205
|
-
regenerateNav = true;
|
|
206
|
-
category = "openApi";
|
|
207
|
-
}
|
|
208
|
-
break;
|
|
209
|
-
case "staticFile":
|
|
210
|
-
if (await isFileSizeValid(filePath, 5)) {
|
|
211
|
-
await fse.copy(filePath, targetPath);
|
|
212
|
-
} else {
|
|
213
|
-
console.error(
|
|
214
|
-
Chalk.red(
|
|
215
|
-
`🚨 The file at ${filename} is too big. The maximum file size is 5 mb.`
|
|
216
|
-
)
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
break;
|
|
220
|
-
}
|
|
221
|
-
if (regenerateNav) {
|
|
222
|
-
// TODO: Instead of re-generating the entire nav, optimize by just updating the specific page that changed.
|
|
223
|
-
await updateGeneratedNav();
|
|
224
|
-
}
|
|
225
|
-
return category;
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
export default listener;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
// TODO: Add Types
|
|
2
|
-
import fse from "fs-extra";
|
|
3
|
-
import { promises as _promises } from "fs";
|
|
4
|
-
import { CLIENT_PATH, CMD_EXEC_PATH } from "../../constants.js";
|
|
5
|
-
import { join } from "path";
|
|
6
|
-
import { generateNav } from "./generate.js";
|
|
7
|
-
import { categorizeFiles } from "./categorize.js";
|
|
8
|
-
|
|
9
|
-
const { readFile } = _promises;
|
|
10
|
-
|
|
11
|
-
// TODO: Put in prebuild package
|
|
12
|
-
|
|
13
|
-
export const updateGeneratedNav = async () => {
|
|
14
|
-
const generatedNav = await generateNav();
|
|
15
|
-
const targetPath = join(CLIENT_PATH, "src", "_props", "generatedNav.json");
|
|
16
|
-
await fse.outputFile(targetPath, JSON.stringify(generatedNav, null, 2), {
|
|
17
|
-
flag: "w",
|
|
18
|
-
});
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const updateOpenApiFiles = async () => {
|
|
22
|
-
const { openApiFiles } = await categorizeFiles(CMD_EXEC_PATH);
|
|
23
|
-
const targetPath = join(CLIENT_PATH, "src", "_props", "openApiFiles.json");
|
|
24
|
-
await fse.outputFile(targetPath, JSON.stringify(openApiFiles, null, 2), {
|
|
25
|
-
flag: "w",
|
|
26
|
-
});
|
|
27
|
-
};
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
// TODO: Put in the prebuild package
|
|
2
|
-
import matter from "gray-matter";
|
|
3
|
-
import isAbsoluteUrl from "is-absolute-url";
|
|
4
|
-
import { remark } from "remark";
|
|
5
|
-
import remarkFrontmatter from "remark-frontmatter";
|
|
6
|
-
import remarkGfm from "remark-gfm";
|
|
7
|
-
import remarkMdx from "remark-mdx";
|
|
8
|
-
import { visit } from "unist-util-visit";
|
|
9
|
-
import type { OpenApiFile } from "./types.js";
|
|
10
|
-
|
|
11
|
-
const createPage = async (
|
|
12
|
-
pagePath: string,
|
|
13
|
-
pageContent: string,
|
|
14
|
-
contentDirectoryPath: string,
|
|
15
|
-
openApiFiles: OpenApiFile[]
|
|
16
|
-
) => {
|
|
17
|
-
let { data: metadata } = matter(pageContent);
|
|
18
|
-
try {
|
|
19
|
-
const parsedContent = await preParseMdx(pageContent, contentDirectoryPath);
|
|
20
|
-
pageContent = parsedContent;
|
|
21
|
-
} catch (error) {
|
|
22
|
-
pageContent = `🚧 A parsing error occured. Please contact the owner of this website.`;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Replace .mdx so we can pass file paths into this function
|
|
26
|
-
const slug = pagePath.replace(/\.mdx?$/, "");
|
|
27
|
-
let defaultTitle = slugToTitle(slug);
|
|
28
|
-
// Append data from OpenAPI if it exists
|
|
29
|
-
const { title, description } = getOpenApiTitleAndDescription(
|
|
30
|
-
openApiFiles,
|
|
31
|
-
metadata?.openapi
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
if (title) {
|
|
35
|
-
defaultTitle = title;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const pageMetadata = {
|
|
39
|
-
title: defaultTitle,
|
|
40
|
-
description,
|
|
41
|
-
...metadata,
|
|
42
|
-
href: optionallyAddLeadingSlash(slug),
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
pageMetadata,
|
|
47
|
-
pageContent,
|
|
48
|
-
slug: removeLeadingSlash(slug),
|
|
49
|
-
};
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const preParseMdx = async (fileContent, contentDirectoryPath) => {
|
|
53
|
-
const removeContentDirectoryPath = (filePath) => {
|
|
54
|
-
const pathArr = createPathArr(filePath);
|
|
55
|
-
const contentDirectoryPathArr = createPathArr(contentDirectoryPath);
|
|
56
|
-
contentDirectoryPathArr.reverse().forEach((dir, index) => {
|
|
57
|
-
if (pathArr[index] === dir) {
|
|
58
|
-
pathArr.pop();
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
return "/" + pathArr.join("/");
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const removeContentDirectoryPaths = () => {
|
|
65
|
-
return (tree) => {
|
|
66
|
-
visit(tree, (node) => {
|
|
67
|
-
if (node == null) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (node.name === "img" || node.name === "source") {
|
|
71
|
-
const srcAttrIndex = node.attributes.findIndex(
|
|
72
|
-
(attr) => attr?.name === "src"
|
|
73
|
-
);
|
|
74
|
-
const nodeUrl = node.attributes[srcAttrIndex].value;
|
|
75
|
-
if (
|
|
76
|
-
// <img/> component
|
|
77
|
-
srcAttrIndex !== -1 &&
|
|
78
|
-
!isAbsoluteUrl(nodeUrl) &&
|
|
79
|
-
!isDataString(nodeUrl)
|
|
80
|
-
) {
|
|
81
|
-
node.attributes[srcAttrIndex].value =
|
|
82
|
-
removeContentDirectoryPath(nodeUrl);
|
|
83
|
-
}
|
|
84
|
-
} else if (
|
|
85
|
-
// ![]() format
|
|
86
|
-
node.type === "image" &&
|
|
87
|
-
node.url &&
|
|
88
|
-
!isAbsoluteUrl(node.url) &&
|
|
89
|
-
!isDataString(node.url)
|
|
90
|
-
) {
|
|
91
|
-
node.url = removeContentDirectoryPath(node.url);
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
return tree;
|
|
95
|
-
};
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const file = await remark()
|
|
99
|
-
.use(remarkMdx)
|
|
100
|
-
.use(remarkGfm)
|
|
101
|
-
.use(remarkFrontmatter, ["yaml", "toml"])
|
|
102
|
-
.use(removeContentDirectoryPaths)
|
|
103
|
-
.process(fileContent);
|
|
104
|
-
return String(file);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const removeLeadingSlash = (str) => {
|
|
108
|
-
const path = createPathArr(str);
|
|
109
|
-
return path.join("/");
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const createPathArr = (path) => {
|
|
113
|
-
return path.split("/").filter((dir) => dir !== "");
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const isDataString = (str) => str.startsWith("data:");
|
|
117
|
-
|
|
118
|
-
const getOpenApiTitleAndDescription = (openApiFiles, openApiMetaField) => {
|
|
119
|
-
if (openApiFiles == null || !openApiMetaField || openApiMetaField == null) {
|
|
120
|
-
return {};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const { operation } = getOpenApiOperationMethodAndEndpoint(
|
|
124
|
-
openApiFiles,
|
|
125
|
-
openApiMetaField
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
if (operation == null) {
|
|
129
|
-
return {};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
title: operation.summary,
|
|
134
|
-
description: operation.description,
|
|
135
|
-
};
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const getOpenApiOperationMethodAndEndpoint = (
|
|
139
|
-
openApiFiles,
|
|
140
|
-
openApiMetaField
|
|
141
|
-
) => {
|
|
142
|
-
const { endpoint, method, filename } =
|
|
143
|
-
extractMethodAndEndpoint(openApiMetaField);
|
|
144
|
-
|
|
145
|
-
let path;
|
|
146
|
-
|
|
147
|
-
openApiFiles?.forEach((file) => {
|
|
148
|
-
const openApiFile = file.spec;
|
|
149
|
-
const openApiPath = openApiFile.paths && openApiFile.paths[endpoint];
|
|
150
|
-
const isFilenameOrNone = !filename || filename === file.filename;
|
|
151
|
-
if (openApiPath && isFilenameOrNone) {
|
|
152
|
-
path = openApiPath;
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
if (path == null) {
|
|
157
|
-
return {};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
let operation;
|
|
161
|
-
if (method) {
|
|
162
|
-
operation = path[method.toLowerCase()];
|
|
163
|
-
} else {
|
|
164
|
-
const firstOperationKey = Object.keys(path)[0];
|
|
165
|
-
operation = path[firstOperationKey];
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return {
|
|
169
|
-
operation,
|
|
170
|
-
method,
|
|
171
|
-
endpoint,
|
|
172
|
-
};
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const extractMethodAndEndpoint = (openApiMetaField) => {
|
|
176
|
-
const methodRegex = /(get|post|put|delete|patch)\s/i;
|
|
177
|
-
const trimmed = openApiMetaField.trim();
|
|
178
|
-
const foundMethod = trimmed.match(methodRegex);
|
|
179
|
-
|
|
180
|
-
const startIndexOfMethod = foundMethod
|
|
181
|
-
? openApiMetaField.indexOf(foundMethod[0])
|
|
182
|
-
: 0;
|
|
183
|
-
const endIndexOfMethod = foundMethod
|
|
184
|
-
? startIndexOfMethod + foundMethod[0].length - 1
|
|
185
|
-
: 0;
|
|
186
|
-
|
|
187
|
-
const filename = openApiMetaField.substring(0, startIndexOfMethod).trim();
|
|
188
|
-
|
|
189
|
-
return {
|
|
190
|
-
method: foundMethod ? foundMethod[0].slice(0, -1).toUpperCase() : undefined,
|
|
191
|
-
endpoint: openApiMetaField.substring(endIndexOfMethod).trim(),
|
|
192
|
-
filename: filename ? filename : undefined,
|
|
193
|
-
};
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
function optionallyAddLeadingSlash(path) {
|
|
197
|
-
if (!path || path.startsWith("/")) {
|
|
198
|
-
return path;
|
|
199
|
-
}
|
|
200
|
-
return "/" + path;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export const slugToTitle = (slug) => {
|
|
204
|
-
const slugArr = slug.split("/");
|
|
205
|
-
let defaultTitle = slugArr[slugArr.length - 1].split("-").join(" "); //replace all dashes
|
|
206
|
-
defaultTitle = defaultTitle.split("_").join(" "); //replace all underscores
|
|
207
|
-
defaultTitle = defaultTitle.charAt(0).toUpperCase() + defaultTitle.slice(1); //capitalize first letter
|
|
208
|
-
return defaultTitle;
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
export default createPage;
|