@ayushshanker/mdo 0.2.0 → 0.3.0

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # @ayushshanker/mdo
1
+ # mdo
2
2
 
3
- `@ayushshanker/mdo` is the npm package name. It installs the `mdo` CLI for previewing Markdown files and folders in your browser.
3
+ Contains `mdo` CLI for previewing Markdown files and folders in your browser.
4
4
 
5
5
  ## Install
6
6
 
@@ -89,7 +89,7 @@ mdo docs --port 3000
89
89
  ## Flags
90
90
 
91
91
  - `--dark` uses the GitHub dark theme
92
- - `--theme <name>` selects `github`, `github-dark`, `sepia`, `earth`, `earthsong`, `gruvbox`, or `dracula`
92
+ - `--theme <name>` selects `github-light`, `github-dark`, `belafonte-day`, `belafonte-night`, `earth`, `earthsong`, or `dracula`
93
93
  - `--output <file>` writes HTML to disk instead of opening the browser; file mode only
94
94
  - `--port <port>` uses a fixed port for folder mode
95
95
  - `--help` prints usage information
package/lib/browser.js ADDED
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ const { spawn } = require("node:child_process");
4
+
5
+ function getBrowserCommand(target) {
6
+ switch (process.platform) {
7
+ case "darwin":
8
+ if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(target)) {
9
+ return { command: "/usr/bin/open", args: ["-u", target] };
10
+ }
11
+ return { command: "/usr/bin/open", args: [target] };
12
+ case "win32":
13
+ return {
14
+ command: "cmd",
15
+ args: ["/c", "start", "", target]
16
+ };
17
+ default:
18
+ return { command: "xdg-open", args: [target] };
19
+ }
20
+ }
21
+
22
+ function openInBrowser(target) {
23
+ const { command, args } = getBrowserCommand(target);
24
+
25
+ return new Promise((resolve, reject) => {
26
+ const child = spawn(command, args, {
27
+ detached: true,
28
+ stdio: "ignore"
29
+ });
30
+
31
+ child.once("error", reject);
32
+ child.once("spawn", () => {
33
+ child.unref();
34
+ resolve();
35
+ });
36
+ });
37
+ }
38
+
39
+ module.exports = {
40
+ getBrowserCommand,
41
+ openInBrowser
42
+ };
package/lib/cli.js CHANGED
@@ -20,7 +20,7 @@ function resolveThemeOption(options) {
20
20
  return options.theme;
21
21
  }
22
22
 
23
- return options.dark ? "github-dark" : "github";
23
+ return options.dark ? "github-dark" : "github-light";
24
24
  }
25
25
 
26
26
  function buildProgram() {
package/lib/constants.js CHANGED
@@ -11,7 +11,7 @@ const MERMAID_VERSION = "11.12.0";
11
11
  const MERMAID_CDN_URL = `https://cdn.jsdelivr.net/npm/mermaid@${MERMAID_VERSION}/dist/mermaid.min.js`;
12
12
  const LIGHT_HLJS_THEME = "github.css";
13
13
  const DARK_HLJS_THEME = "github-dark.css";
14
- const GITHUB_MARKDOWN_CSS = "github-markdown.css";
14
+ const GITHUB_MARKDOWN_LIGHT_CSS = "github-markdown-light.css";
15
15
  const GITHUB_MARKDOWN_DARK_CSS = "github-markdown-dark.css";
16
16
  const DEFAULT_ARTICLE_TITLE = "Markdown Preview";
17
17
  const PACKAGE_ROOT = path.resolve(__dirname, "..");
@@ -19,7 +19,7 @@ const PACKAGE_ROOT = path.resolve(__dirname, "..");
19
19
  module.exports = {
20
20
  DARK_HLJS_THEME,
21
21
  DEFAULT_ARTICLE_TITLE,
22
- GITHUB_MARKDOWN_CSS,
22
+ GITHUB_MARKDOWN_LIGHT_CSS,
23
23
  GITHUB_MARKDOWN_DARK_CSS,
24
24
  LIGHT_HLJS_THEME,
25
25
  LOOPBACK_HOST,
package/lib/file-mode.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require("node:fs/promises");
4
4
  const path = require("node:path");
5
- const open = require("open");
5
+ const { openInBrowser } = require("./browser");
6
6
  const { renderMarkdownFile } = require("./renderer");
7
7
  const {
8
8
  humanUrlPath,
@@ -26,13 +26,17 @@ async function runFileMode({ filePath, outputPath, cwdRealPath, themeName }) {
26
26
  await writeUtf8File(htmlPath, html);
27
27
 
28
28
  try {
29
- await open(htmlPath);
29
+ await openInBrowser(htmlPath);
30
30
  } catch (error) {
31
31
  process.stderr.write(`Browser open failed. File available at ${htmlPath}\n`);
32
- throw new Error(`Failed to open browser for ${humanUrlPath(cwdRealPath, filePath)}.`);
32
+ return {
33
+ browserOpened: false,
34
+ outputPath: htmlPath,
35
+ visiblePath: humanUrlPath(cwdRealPath, filePath)
36
+ };
33
37
  }
34
38
 
35
- return { outputPath: htmlPath, opened: true };
39
+ return { browserOpened: true, outputPath: htmlPath, visiblePath: humanUrlPath(cwdRealPath, filePath) };
36
40
  }
37
41
 
38
42
  module.exports = {
@@ -3,10 +3,10 @@
3
3
  const http = require("node:http");
4
4
  const fs = require("node:fs/promises");
5
5
  const path = require("node:path");
6
- const open = require("open");
6
+ const { openInBrowser } = require("./browser");
7
7
  const { LOOPBACK_HOST, MAX_PORT, MIN_PORT, PORT_RETRIES } = require("./constants");
8
8
  const { renderDirectoryListing, renderMarkdownFile } = require("./renderer");
9
- const { isMarkdownPath, toPosixPath } = require("./utils");
9
+ const { isMarkdownPath } = require("./utils");
10
10
 
11
11
  async function resolveInsideRoot(rootRealPath, requestPath) {
12
12
  const normalized = decodeURIComponent(requestPath || "/");
@@ -145,19 +145,18 @@ function installShutdownHandlers(server) {
145
145
  return;
146
146
  }
147
147
  shuttingDown = true;
148
- const timeout = setTimeout(() => {
149
- process.exit(0);
150
- }, 2000);
151
- timeout.unref();
152
-
153
- server.close(() => {
154
- clearTimeout(timeout);
155
- process.exit(0);
156
- });
148
+ server.close();
149
+ if (signal === "SIGINT") {
150
+ process.exit(130);
151
+ }
152
+ if (signal === "SIGTERM") {
153
+ process.exit(143);
154
+ }
155
+ process.exit(0);
157
156
  };
158
157
 
159
- process.on("SIGINT", shutdown);
160
- process.on("SIGTERM", shutdown);
158
+ process.once("SIGINT", shutdown);
159
+ process.once("SIGTERM", shutdown);
161
160
  }
162
161
 
163
162
  async function runFolderMode({ directoryPath, fixedPort, themeName }) {
@@ -215,13 +214,13 @@ async function runFolderMode({ directoryPath, fixedPort, themeName }) {
215
214
 
216
215
  const url = `http://${LOOPBACK_HOST}:${port}/`;
217
216
  try {
218
- await open(url);
217
+ await openInBrowser(url);
219
218
  } catch {
220
219
  process.stderr.write(`Browser open failed. Server available at ${url}\n`);
221
- throw new Error("Failed to open browser.");
220
+ return { browserOpened: false, port, rootRealPath, url, server };
222
221
  }
223
222
 
224
- return { port, rootRealPath, url, server };
223
+ return { browserOpened: true, port, rootRealPath, url, server };
225
224
  }
226
225
 
227
226
  module.exports = {
package/lib/renderer.js CHANGED
@@ -10,7 +10,7 @@ const hljs = require("highlight.js");
10
10
  const {
11
11
  DARK_HLJS_THEME,
12
12
  DEFAULT_ARTICLE_TITLE,
13
- GITHUB_MARKDOWN_CSS,
13
+ GITHUB_MARKDOWN_LIGHT_CSS,
14
14
  GITHUB_MARKDOWN_DARK_CSS,
15
15
  LIGHT_HLJS_THEME,
16
16
  MERMAID_CDN_URL,
@@ -26,7 +26,7 @@ function loadCss(relativePath) {
26
26
  return fs.readFileSync(cssPath, "utf8");
27
27
  }
28
28
 
29
- const markdownCssLight = loadCss(`github-markdown-css/${GITHUB_MARKDOWN_CSS}`);
29
+ const markdownCssLight = loadCss(`github-markdown-css/${GITHUB_MARKDOWN_LIGHT_CSS}`);
30
30
  const markdownCssDark = loadCss(`github-markdown-css/${GITHUB_MARKDOWN_DARK_CSS}`);
31
31
  const hljsCssLight = loadCss(`highlight.js/styles/${LIGHT_HLJS_THEME}`);
32
32
  const hljsCssDark = loadCss(`highlight.js/styles/${DARK_HLJS_THEME}`);
@@ -56,7 +56,7 @@ function createMarkdownRenderer() {
56
56
  const renderer = createMarkdownRenderer();
57
57
 
58
58
  const THEMES = {
59
- github: {
59
+ "github-light": {
60
60
  accent: "#0969da",
61
61
  background: "#ffffff",
62
62
  color: "#1f2328",
@@ -78,28 +78,59 @@ const THEMES = {
78
78
  navFontColor: "#8b949e",
79
79
  overlayCss: ""
80
80
  },
81
- sepia: {
82
- accent: "#8b5e34",
83
- background: "#f6efe2",
84
- color: "#433422",
81
+ "belafonte-day": {
82
+ accent: "#8f5a2b",
83
+ background: "#f6f1e7",
84
+ color: "#3d3126",
85
85
  darkMode: false,
86
86
  hljsCss: hljsCssLight,
87
87
  markdownCss: markdownCssLight,
88
88
  mermaidTheme: "neutral",
89
- navFontColor: "#6e5a43",
89
+ navFontColor: "#6f5a46",
90
90
  overlayCss: `
91
- body { background-image: linear-gradient(180deg, rgba(139, 94, 52, 0.06), rgba(139, 94, 52, 0)); }
91
+ body { background-image: linear-gradient(135deg, rgba(143, 90, 43, 0.08), rgba(191, 143, 84, 0.05)); }
92
92
  .markdown-body {
93
- color: #433422;
93
+ color: #3d3126;
94
94
  }
95
95
  .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 {
96
- color: #2f2418;
96
+ color: #2b2219;
97
97
  }
98
98
  .markdown-body pre, .markdown-body code, .markdown-body blockquote {
99
- background-color: rgba(114, 87, 56, 0.08);
99
+ background-color: rgba(120, 90, 59, 0.09);
100
100
  }
101
101
  .markdown-body table tr {
102
- background-color: rgba(255, 255, 255, 0.35);
102
+ background-color: rgba(255, 248, 238, 0.5);
103
+ }
104
+ .markdown-body a, .mdo-nav a {
105
+ color: #8f5a2b;
106
+ }
107
+ `
108
+ },
109
+ "belafonte-night": {
110
+ accent: "#d7995b",
111
+ background: "#20111b",
112
+ color: "#f2e7d5",
113
+ darkMode: true,
114
+ hljsCss: hljsCssDark,
115
+ markdownCss: markdownCssDark,
116
+ mermaidTheme: "dark",
117
+ navFontColor: "#ccb9a4",
118
+ overlayCss: `
119
+ body { background-image: radial-gradient(circle at top, rgba(215, 153, 91, 0.2), rgba(32, 17, 27, 0) 42%); }
120
+ .markdown-body {
121
+ color: #f2e7d5;
122
+ }
123
+ .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 {
124
+ color: #ffd7a8;
125
+ }
126
+ .markdown-body pre, .markdown-body code, .markdown-body blockquote {
127
+ background-color: rgba(75, 49, 44, 0.94);
128
+ }
129
+ .markdown-body table tr {
130
+ background-color: rgba(92, 62, 54, 0.45);
131
+ }
132
+ .markdown-body a, .mdo-nav a {
133
+ color: #d7995b;
103
134
  }
104
135
  `
105
136
  },
@@ -157,34 +188,6 @@ body { background-image: radial-gradient(circle at top, rgba(185, 119, 50, 0.2),
157
188
  .markdown-body table tr {
158
189
  background-color: rgba(90, 66, 49, 0.48);
159
190
  }
160
- `
161
- },
162
- gruvbox: {
163
- accent: "#d79921",
164
- background: "#282828",
165
- color: "#ebdbb2",
166
- darkMode: true,
167
- hljsCss: hljsCssDark,
168
- markdownCss: markdownCssDark,
169
- mermaidTheme: "dark",
170
- navFontColor: "#d5c4a1",
171
- overlayCss: `
172
- body { background-image: linear-gradient(180deg, rgba(215, 153, 33, 0.08), rgba(40, 40, 40, 0)); }
173
- .markdown-body {
174
- color: #ebdbb2;
175
- }
176
- .markdown-body a, .mdo-nav a {
177
- color: #d79921;
178
- }
179
- .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 {
180
- color: #fabd2f;
181
- }
182
- .markdown-body pre, .markdown-body code, .markdown-body blockquote {
183
- background-color: rgba(60, 56, 54, 0.95);
184
- }
185
- .markdown-body table tr {
186
- background-color: rgba(80, 73, 69, 0.45);
187
- }
188
191
  `
189
192
  },
190
193
  dracula: {
@@ -215,7 +218,7 @@ body { background-image: radial-gradient(circle at top, rgba(189, 147, 249, 0.18
215
218
  };
216
219
 
217
220
  function resolveTheme(themeName) {
218
- return THEMES[themeName] || THEMES.github;
221
+ return THEMES[themeName] || THEMES["github-light"];
219
222
  }
220
223
 
221
224
  function buildStyles(themeName) {
@@ -306,7 +309,7 @@ async function renderMarkdownFile(filePath, options = {}) {
306
309
  return {
307
310
  html: buildDocument({
308
311
  bodyHtml,
309
- themeName: options.themeName || "github",
312
+ themeName: options.themeName || "github-light",
310
313
  title,
311
314
  backHref: options.backHref,
312
315
  backLabel: options.backLabel,
@@ -336,7 +339,7 @@ function renderDirectoryListing({ directoryName, entries, themeName, requestPath
336
339
  <meta name="viewport" content="width=device-width, initial-scale=1">
337
340
  <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline';">
338
341
  <title>${escapeHtml(heading)}</title>
339
- <style>${buildStyles(themeName || "github")}</style>
342
+ <style>${buildStyles(themeName || "github-light")}</style>
340
343
  </head>
341
344
  <body>
342
345
  ${backHref}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ayushshanker/mdo",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Preview Markdown files and folders in the browser",
5
5
  "bin": {
6
6
  "mdo": "bin/mdo.js"