mintlify 2.0.6 → 2.0.8

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.
Files changed (39) hide show
  1. package/README.md +14 -0
  2. package/bin/constants.js +3 -0
  3. package/bin/constants.js.map +1 -1
  4. package/bin/index.js +2 -2
  5. package/bin/index.js.map +1 -1
  6. package/bin/local-preview/index.js +73 -56
  7. package/bin/local-preview/index.js.map +1 -1
  8. package/bin/local-preview/listener/categorizeFiles.js +47 -0
  9. package/bin/local-preview/listener/categorizeFiles.js.map +1 -0
  10. package/bin/local-preview/listener/utils/fileIsMdxOrMd.js +12 -0
  11. package/bin/local-preview/listener/utils/fileIsMdxOrMd.js.map +1 -0
  12. package/bin/local-preview/utils/categorizeFiles.js +63 -0
  13. package/bin/local-preview/utils/categorizeFiles.js.map +1 -0
  14. package/bin/local-preview/utils/getOpenApiContext.js +58 -0
  15. package/bin/local-preview/utils/getOpenApiContext.js.map +1 -0
  16. package/bin/local-preview/utils/injectFavicons.js +72 -0
  17. package/bin/local-preview/utils/injectFavicons.js.map +1 -0
  18. package/bin/local-preview/utils/listener.js +116 -0
  19. package/bin/local-preview/utils/listener.js.map +1 -0
  20. package/bin/local-preview/utils/metadata.js +118 -0
  21. package/bin/local-preview/utils/metadata.js.map +1 -0
  22. package/bin/local-preview/utils/mintConfigFile.js +43 -0
  23. package/bin/local-preview/utils/mintConfigFile.js.map +1 -0
  24. package/bin/local-preview/utils/openApiCheck.js +15 -0
  25. package/bin/local-preview/utils/openApiCheck.js.map +1 -0
  26. package/bin/local-preview/utils/slugToTitle.js +8 -0
  27. package/bin/local-preview/utils/slugToTitle.js.map +1 -0
  28. package/bin/navigation.js +4 -0
  29. package/bin/navigation.js.map +1 -0
  30. package/bin/pageTemplate.js +30 -0
  31. package/bin/pageTemplate.js.map +1 -0
  32. package/bin/scraping/scrapePageCommands.js.map +1 -1
  33. package/bin/scraping/scrapeSectionCommands.js.map +1 -1
  34. package/package.json +2 -2
  35. package/src/constants.ts +5 -0
  36. package/src/index.ts +2 -2
  37. package/src/local-preview/index.ts +102 -66
  38. package/src/scraping/scrapePageCommands.ts +2 -1
  39. package/src/scraping/scrapeSectionCommands.ts +2 -1
@@ -1,19 +1,22 @@
1
1
  import Chalk from "chalk";
2
2
  import open from "open";
3
- import { promises as _promises } from "fs";
4
3
  import fse, { pathExists } from "fs-extra";
5
4
  import inquirer from "inquirer";
6
5
  import { isInternetAvailable } from "is-internet-available";
7
6
  import path from "path";
8
7
  import shell from "shelljs";
8
+ import { Octokit } from "@octokit/rest";
9
9
  import {
10
10
  CLIENT_PATH,
11
11
  HOME_DIR,
12
12
  DOT_MINTLIFY,
13
13
  CMD_EXEC_PATH,
14
+ TARGET_MINT_VERSION,
15
+ VERSION_PATH,
14
16
  } from "../constants.js";
15
17
  import { buildLogger, ensureYarn } from "../util.js";
16
18
  import listener from "./listener/index.js";
19
+ import { ArgumentsCamelCase } from "yargs";
17
20
 
18
21
  const shellExec = (cmd: string) => {
19
22
  return shell.exec(cmd, { silent: true });
@@ -45,96 +48,129 @@ const promptForYarn = async () => {
45
48
  }
46
49
  };
47
50
 
48
- const dev = async () => {
51
+ const dev = async (argv: ArgumentsCamelCase) => {
49
52
  shell.cd(HOME_DIR);
50
53
  await promptForYarn();
51
54
  const logger = buildLogger("Starting a local Mintlify instance...");
52
55
  await fse.ensureDir(path.join(DOT_MINTLIFY, "mint"));
53
56
  const MINT_PATH = path.join(DOT_MINTLIFY, "mint");
54
57
  shell.cd(MINT_PATH);
55
- const gitPullStatus = shellExec("git show").stdout;
56
- const currBranch = shellExec("git rev-parse --abbrev-ref HEAD").stdout;
57
- if (
58
- gitPullStatus.startsWith(
59
- "commit 78d764335877932a0dc305d615411dedd18bd18a"
60
- ) ||
61
- currBranch === "legacy-components-import"
62
- ) {
63
- await fse.emptyDir(MINT_PATH);
64
- }
65
-
66
- let runYarn = true;
67
- const gitInstalled = shell.which("git");
68
- let firstInstallation = false;
69
- const gitRepoInitialized = await pathExists(
70
- path.join(DOT_MINTLIFY, "mint", ".git")
71
- );
72
- if (!gitRepoInitialized) {
73
- firstInstallation = true;
74
- if (gitInstalled) {
75
- logger.start("Initializing local Mintlify instance...");
76
- shellExec("git init");
77
- shellExec(
78
- "git remote add -f mint-origin https://github.com/mintlify/mint.git"
79
- );
80
- } else {
81
- logger.fail(
82
- "git must be installed (https://github.com/git-guides/install-git)"
83
- );
84
- process.exit(1);
85
- }
86
- }
87
58
 
59
+ // The CLI can only run offline if Mint was already downloaded
88
60
  const internet = await isInternetAvailable();
89
- let pullOutput = null;
90
- if (internet && gitInstalled) {
91
- shellExec("git config core.sparseCheckout true");
92
- shellExec('echo "client/" >> .git/info/sparse-checkout');
93
- pullOutput = shellExec("git pull mint-origin main").stdout;
94
- shellExec("git config core.sparseCheckout false");
95
- shellExec("rm .git/info/sparse-checkout");
96
- }
97
- if (pullOutput === "Already up to date.\n") {
98
- runYarn = false;
61
+ if (!internet && !(await pathExists(CLIENT_PATH))) {
62
+ logger.fail(
63
+ "Running mintlify dev for the first time requires an internet connection."
64
+ );
65
+ process.exit(1);
99
66
  }
100
- shell.cd(CLIENT_PATH);
101
- if (internet && (runYarn || !(await nodeModulesExists()))) {
102
- if (firstInstallation) {
103
- logger.succeed("Local Mintlify instance initialized");
67
+
68
+ // Avoid checking if we are on the target Mint if we are offline
69
+ if (internet) {
70
+ const mintVersionExists = await pathExists(VERSION_PATH);
71
+
72
+ // We always download the target version of Mintlify if the mint-version.txt file doesn't exist.
73
+ // We do this because users updating from an older version of the CLI never have mint-version.txt set.
74
+ let downloadTargetMint = !mintVersionExists;
75
+
76
+ // Download target mint if the current version is different. Keep in mind this also allows
77
+ // downgrading to an older version of Mintlify by installing an older CLI version.
78
+ if (mintVersionExists) {
79
+ const currVersion = fse.readFileSync(VERSION_PATH, "utf8");
80
+ if (currVersion !== TARGET_MINT_VERSION) {
81
+ downloadTargetMint = true;
82
+ }
104
83
  }
105
- logger.start("Updating dependencies...");
106
- ensureYarn(logger);
107
- shellExec("yarn");
108
- if (firstInstallation) {
109
- logger.succeed("Installation complete");
110
- } else {
111
- logger.succeed("Dependencies updated");
84
+
85
+ if (downloadTargetMint) {
86
+ // Delete any existing contents
87
+ fse.emptyDirSync(MINT_PATH);
88
+
89
+ logger.text = "Downloading Mintlify framework...";
90
+
91
+ const octokit = new Octokit();
92
+ const downloadRes = await octokit.repos.downloadTarballArchive({
93
+ owner: "mintlify",
94
+ repo: "mint",
95
+ ref: TARGET_MINT_VERSION,
96
+ });
97
+
98
+ logger.text = "Extracting Mintlify framework...";
99
+ const TAR_PATH = path.join(MINT_PATH, "mint.tar.gz");
100
+
101
+ // Unzip tar file
102
+ fse.writeFileSync(TAR_PATH, Buffer.from(downloadRes.data as any));
103
+ shellExec("tar -xzf mint.tar.gz");
104
+
105
+ // List all files in tar file and get the first one.
106
+ // There is never anything else in the tar file, so this is safe.
107
+ // We do this because the folder name includes the commit sha, so we can't hardcode it.
108
+ // Lastly, we call .trim() to remove the newline character.
109
+ const extractedFolderName = shellExec(
110
+ 'tar -tzf mint.tar.gz | head -1 | cut -f1 -d"/"'
111
+ ).stdout.trim();
112
+
113
+ // Delete tar file
114
+ fse.removeSync(TAR_PATH);
115
+
116
+ fse.moveSync(
117
+ path.join(MINT_PATH, extractedFolderName, "client"),
118
+ path.join(CLIENT_PATH)
119
+ );
120
+
121
+ // Store the currently downloaded version
122
+ fse.writeFileSync(VERSION_PATH, TARGET_MINT_VERSION);
123
+
124
+ // Delete unnecessary contents downloaded from GitHub
125
+ fse.removeSync(path.join(MINT_PATH, extractedFolderName));
126
+
127
+ logger.text = "Installing dependencies...";
128
+
129
+ ensureYarn(logger);
130
+ shell.cd(CLIENT_PATH);
131
+ shellExec("yarn");
112
132
  }
113
133
  }
114
134
 
115
135
  if (!(await nodeModulesExists())) {
116
- logger.fail(`Dependencies weren\'t installed, run
117
-
118
- mintlify install
119
-
120
- `);
136
+ if (!internet) {
137
+ logger.fail(`Dependencies are missing and you are offline. Connect to the internet and run
138
+
139
+ mintlify install
140
+
141
+ `);
142
+ } else {
143
+ logger.fail(`Dependencies were not installed correctly, run
144
+
145
+ mintlify install
146
+
147
+ `);
148
+ }
121
149
  process.exit(1);
122
150
  }
151
+
123
152
  const relativePath = path.relative(CLIENT_PATH, CMD_EXEC_PATH);
124
153
  shellExec(`yarn preconfigure ${relativePath}`);
125
- logger.succeed("Local Mintlify instance initialized");
126
- run();
154
+ logger.succeed("Local Mintlify instance started.");
155
+ run((argv.port as string) || "3000");
127
156
  };
128
157
 
129
- const run = () => {
158
+ const run = (port: string) => {
130
159
  shell.cd(CLIENT_PATH);
131
160
  console.log(
132
161
  `🌿 ${Chalk.green(
133
- "Navigate to your local preview at http://localhost:3000"
162
+ `Your local preview is available at http://localhost:${port}`
134
163
  )}`
135
164
  );
136
- shell.exec("npm run dev-watch", { async: true });
137
- open("http://localhost:3000");
165
+ console.log(
166
+ `🌿 ${Chalk.green("Press Ctrl+C any time to stop the local preview.")}`
167
+ );
168
+
169
+ // next-remote-watch can only receive ports as env variables
170
+ // https://github.com/hashicorp/next-remote-watch/issues/23
171
+ shell.exec(`PORT=${port} npm run dev-watch`, { async: true });
172
+
173
+ open(`http://localhost:${port}`);
138
174
  listener();
139
175
  };
140
176
 
@@ -6,6 +6,7 @@ import { scrapeReadMePage } from "./site-scrapers/scrapeReadMePage.js";
6
6
  import { detectFramework, Frameworks } from "./detectFramework.js";
7
7
  import { getHrefFromArgs } from "../util.js";
8
8
  import { getHtmlWithPuppeteer } from "../browser.js";
9
+ import { ArgumentsCamelCase } from "yargs";
9
10
 
10
11
  function validateFramework(framework) {
11
12
  if (!framework) {
@@ -20,7 +21,7 @@ function validateFramework(framework) {
20
21
  }
21
22
 
22
23
  export async function scrapePageWrapper(
23
- argv: any,
24
+ argv: ArgumentsCamelCase,
24
25
  scrapeFunc: ScrapePageFn,
25
26
  options?: { version?: string; puppeteer?: boolean }
26
27
  ) {
@@ -8,9 +8,10 @@ import { scrapeGitBookSection } from "./site-scrapers/scrapeGitBookSection.js";
8
8
  import openNestedGitbookMenus from "./site-scrapers/openNestedGitbookMenus.js";
9
9
  import { scrapeReadMeSection } from "./site-scrapers/scrapeReadMeSection.js";
10
10
  import { startBrowser } from "../browser.js";
11
+ import { ArgumentsCamelCase } from "yargs";
11
12
 
12
13
  export async function scrapeSectionAxiosWrapper(
13
- argv: any,
14
+ argv: ArgumentsCamelCase,
14
15
  scrapeFunc: ScrapeSectionFn
15
16
  ) {
16
17
  const href = getHrefFromArgs(argv);