@mgks/docmd 0.1.4 → 0.2.1

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 (52) hide show
  1. package/README.md +2 -4
  2. package/assets/css/welcome.css +5 -377
  3. package/assets/images/preview-dark-1.webp +0 -0
  4. package/assets/images/preview-dark-2.webp +0 -0
  5. package/assets/images/preview-dark-3.webp +0 -0
  6. package/assets/images/preview-light-1.webp +0 -0
  7. package/assets/images/preview-light-2.webp +0 -0
  8. package/assets/images/preview-light-3.webp +0 -0
  9. package/config.js +40 -6
  10. package/docs/configuration.md +82 -7
  11. package/docs/content/containers/buttons.md +88 -0
  12. package/docs/content/containers/callouts.md +154 -0
  13. package/docs/content/containers/cards.md +93 -0
  14. package/docs/content/containers/index.md +35 -0
  15. package/docs/content/containers/nested-containers.md +329 -0
  16. package/docs/content/containers/steps.md +175 -0
  17. package/docs/content/containers/tabs.md +228 -0
  18. package/docs/content/custom-containers.md +19 -124
  19. package/docs/content/frontmatter.md +2 -2
  20. package/docs/content/no-style-example.md +2 -0
  21. package/docs/content/no-style-pages.md +52 -28
  22. package/docs/index.md +55 -27
  23. package/docs/plugins/seo.md +80 -31
  24. package/docs/theming/available-themes.md +17 -2
  25. package/docs/theming/light-dark-mode.md +12 -3
  26. package/package.json +21 -9
  27. package/src/assets/css/docmd-main.css +5 -806
  28. package/src/assets/css/docmd-theme-retro.css +9 -0
  29. package/src/assets/css/docmd-theme-ruby.css +7 -604
  30. package/src/assets/css/docmd-theme-sky.css +7 -649
  31. package/src/assets/js/docmd-image-lightbox.js +4 -2
  32. package/src/assets/js/docmd-main.js +157 -0
  33. package/src/commands/build.js +62 -120
  34. package/src/commands/dev.js +2 -1
  35. package/src/commands/init.js +23 -1
  36. package/src/core/config-loader.js +2 -0
  37. package/src/core/file-processor.js +669 -373
  38. package/src/core/html-generator.js +49 -40
  39. package/src/core/icon-renderer.js +3 -2
  40. package/src/plugins/analytics.js +5 -1
  41. package/src/plugins/seo.js +114 -62
  42. package/src/plugins/sitemap.js +6 -0
  43. package/src/templates/layout.ejs +40 -8
  44. package/src/templates/no-style.ejs +23 -6
  45. package/src/templates/partials/theme-init.js +26 -0
  46. package/assets/images/preview-dark-1.png +0 -0
  47. package/assets/images/preview-dark-2.png +0 -0
  48. package/assets/images/preview-dark-3.png +0 -0
  49. package/assets/images/preview-light-1.png +0 -0
  50. package/assets/images/preview-light-2.png +0 -0
  51. package/assets/images/preview-light-3.png +0 -0
  52. package/src/assets/js/docmd-theme-toggle.js +0 -59
package/docs/index.md CHANGED
@@ -7,35 +7,51 @@ components:
7
7
  favicon: true
8
8
  css: false
9
9
  theme: false
10
+ themeMode: true
10
11
  scripts: false
12
+ mainScripts: false
13
+ lightbox: false
14
+ seo:
15
+ ldJson:
16
+ "@context": "https://schema.org"
17
+ "@type": "SoftwareApplication"
18
+ name: "docmd"
19
+ operatingSystem: "Any"
20
+ applicationCategory: "DeveloperApplication"
21
+ url: "https://docmd.mgks.dev"
22
+ description: "docmd is a Node.js-powered static site generator for Markdown documentation. It features custom containers, multiple themes, and zero client-side bloat."
23
+ creator:
24
+ "@type": "Person"
25
+ name: "Ghazi"
26
+ sameAs:
27
+ - "https://github.com/mgks"
28
+ - "https://mgks.dev"
29
+ codeRepository: "https://github.com/mgks/docmd"
30
+ releaseNotes: "See GitHub Releases for changelog"
31
+ programmingLanguage: "Node.js"
32
+ installUrl: "https://www.npmjs.com/package/@mgks/docmd"
11
33
  customHead: |
12
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
13
- <link rel="preconnect" href="https://fonts.googleapis.com">
14
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
15
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=PT+Mono:wght@700&display=swap" rel="stylesheet">
16
34
  <link rel="stylesheet" href="/assets/css/welcome.css">
17
35
  <script>
18
- // Initialize theme from localStorage or system preference
19
- function initTheme() {
20
- const storedTheme = localStorage.getItem('docmd-theme');
21
- if (storedTheme) {
22
- document.body.setAttribute('data-theme', storedTheme);
23
- } else {
24
- const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
25
- document.body.setAttribute('data-theme', prefersDark ? 'dark' : 'light');
26
- }
27
- }
28
-
29
- // Toggle theme between light and dark
30
36
  function toggleTheme() {
31
- const currentTheme = document.body.getAttribute('data-theme');
37
+ const currentTheme = document.documentElement.getAttribute('data-theme');
32
38
  const newTheme = currentTheme === 'light' ? 'dark' : 'light';
33
- document.body.setAttribute('data-theme', newTheme);
39
+ document.documentElement.setAttribute('data-theme', newTheme);
34
40
  localStorage.setItem('docmd-theme', newTheme);
35
41
  }
36
-
37
- // Run on page load
38
- document.addEventListener('DOMContentLoaded', initTheme);
42
+
43
+ function copyToClipboard(text) {
44
+ navigator.clipboard.writeText(text).then(() => {
45
+ const button = event.target.closest('.copy-button');
46
+ const originalHTML = button.innerHTML;
47
+ button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20,6 9,17 4,12"></polyline></svg>';
48
+ button.style.color = '#10b981';
49
+ setTimeout(() => {
50
+ button.innerHTML = originalHTML;
51
+ button.style.color = '';
52
+ }, 2000);
53
+ });
54
+ }
39
55
  </script>
40
56
  ---
41
57
 
@@ -100,6 +116,18 @@ customHead: |
100
116
  </div>
101
117
  </div>
102
118
 
119
+ <div class="install-section">
120
+ <div class="install-code">
121
+ <pre><code>npm install @mgks/docmd</code></pre>
122
+ <button class="copy-button" onclick="copyToClipboard('npm install @mgks/docmd')" aria-label="Copy npm install command">
123
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
124
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
125
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
126
+ </svg>
127
+ </button>
128
+ </div>
129
+ </div>
130
+
103
131
  <div class="buttons">
104
132
  <a href="/getting-started/" class="btn btn-primary">
105
133
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rocket-icon lucide-rocket"><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"/><path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"/><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"/><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"/></svg>
@@ -124,16 +152,16 @@ customHead: |
124
152
  <div class="preview-side">
125
153
  <div class="preview-stack">
126
154
  <div class="preview-image top">
127
- <img src="/assets/images/preview-light-1.png" alt="docmd documentation preview" class="light-img">
128
- <img src="/assets/images/preview-dark-1.png" alt="docmd documentation preview" class="dark-img">
155
+ <img src="/assets/images/preview-light-1.webp" alt="docmd documentation preview" class="light-img" loading="lazy">
156
+ <img src="/assets/images/preview-dark-1.webp" alt="docmd documentation preview" class="dark-img" loading="lazy">
129
157
  </div>
130
158
  <div class="preview-image middle">
131
- <img src="/assets/images/preview-light-2.png" alt="docmd documentation preview" class="light-img">
132
- <img src="/assets/images/preview-dark-2.png" alt="docmd documentation preview" class="dark-img">
159
+ <img src="/assets/images/preview-light-2.webp" alt="docmd documentation preview" class="light-img" loading="lazy">
160
+ <img src="/assets/images/preview-dark-2.webp" alt="docmd documentation preview" class="dark-img" loading="lazy">
133
161
  </div>
134
162
  <div class="preview-image bottom">
135
- <img src="/assets/images/preview-light-3.png" alt="docmd documentation preview" class="light-img">
136
- <img src="/assets/images/preview-dark-3.png" alt="docmd documentation preview" class="dark-img">
163
+ <img src="/assets/images/preview-light-3.webp" alt="docmd documentation preview" class="light-img" loading="lazy">
164
+ <img src="/assets/images/preview-dark-3.webp" alt="docmd documentation preview" class="dark-img" loading="lazy">
137
165
  </div>
138
166
  </div>
139
167
  </div>
@@ -36,44 +36,93 @@ module.exports = {
36
36
 
37
37
  ## Configuration Options
38
38
 
39
- All options for the `seo` plugin are optional. If an option is not provided, the plugin will attempt to use sensible defaults or derive values from page frontmatter or `config.siteTitle`.
40
-
41
- * `defaultDescription` (String):
42
- * A fallback meta description used for pages that do not have a `description` specified in their YAML frontmatter.
43
- * `openGraph` (Object): Configures [Open Graph](https://ogp.me/) meta tags, primarily used by Facebook, LinkedIn, Pinterest, etc.
44
- * `siteName` (String): The name of your website (e.g., "My Project Documentation"). If not provided, `config.siteTitle` is used.
45
- * `defaultImage` (String): Absolute path (from site root) to a default image for `og:image` when a page is shared, if the page itself doesn't specify an image in its frontmatter (e.g., via `image: /path/to/page-image.png` or `ogImage: ...`).
46
- * Other tags like `og:title`, `og:description`, `og:url`, and `og:type` are automatically generated based on page frontmatter and URL.
47
- * `twitter` (Object): Configures [Twitter Card](https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards) meta tags.
48
- * `cardType` (String): The type of Twitter card. Common values: `'summary'`, `'summary_large_image'`. Defaults to `'summary'`.
49
- * `siteUsername` (String): The Twitter @username of the site/publisher (e.g., `@MyProjectAccount`).
50
- * `creatorUsername` (String): The default Twitter @username of the content creator. Can be overridden per page via frontmatter (e.g., `twitterCreator: @PageAuthorHandle`).
51
- * Twitter tags like `twitter:title`, `twitter:description`, and `twitter:image` are also derived from page frontmatter, similar to Open Graph tags.
39
+ The options in `config.js` serve as site-wide defaults. For the best results, you should provide specific metadata for each page using frontmatter.
52
40
 
53
41
  ## Frontmatter for SEO
54
42
 
55
- For the best SEO results, provide specific metadata in each page's frontmatter. The `seo` plugin will prioritize these values.
43
+ To control SEO on a per-page basis, add a nested `seo` object to your page's frontmatter. This keeps all SEO-related settings organized and prevents conflicts with other frontmatter keys.
56
44
 
57
45
  ```yaml
58
46
  ---
59
47
  title: "Advanced Widget Configuration"
60
- description: "A detailed guide on configuring advanced settings for the Super Widget, including performance tuning and security options."
61
- image: "/assets/images/widgets/super-widget-social.jpg" # Used for og:image and twitter:image
62
- ogType: "article" # Specify Open Graph type, e.g., article, website
63
- twitterCreator: "@widgetMaster"
64
- keywords: "widget, configuration, advanced, performance, security" # Optional, some argue keywords meta tag is less relevant now
48
+ description: "A detailed guide on configuring advanced settings for the Super Widget."
49
+ seo:
50
+ description: "A more specific SEO description for search engines, overriding the main description if needed."
51
+ image: "/assets/images/widgets/super-widget-social.jpg"
52
+ ogType: "article"
53
+ twitterCard: "summary_large_image"
54
+ twitterCreator: "@widgetMaster"
55
+ keywords: ["widget", "configuration", "advanced", "performance"]
56
+ permalink: "https://example.com/docs/widgets/advanced-configuration"
57
+ noindex: false
65
58
  ---
59
+ ```
60
+
61
+ ::: callout info Backward Compatibility
62
+ For backward compatibility, the plugin will still recognize top-level SEO fields like `image`, `ogType`, etc. However, the nested `seo:` structure is the recommended approach.
63
+ :::
64
+
65
+ ### Supported Frontmatter Fields
66
+
67
+ All fields should be placed inside the `seo:` object.
68
+
69
+ * `description` (String): Overrides the main page description for SEO meta tags.
70
+ * `image` or `ogImage` (String): Path to an image for `og:image` and `twitter:image`.
71
+ * `ogType` (String): Overrides the default Open Graph type (e.g., `article`, `website`).
72
+ * `twitterCard` (String): Overrides the default Twitter card type for this page.
73
+ * `twitterCreator` (String): The Twitter @username of the page's author.
74
+ * `keywords` (Array of Strings or String): Keywords for the `<meta name="keywords">` tag.
75
+ * `permalink` or `canonicalUrl` (String): The canonical URL for the page.
76
+ * `noindex` (Boolean): If `true`, adds `<meta name="robots" content="noindex">` to discourage search engines from indexing this page.
77
+
78
+ ## Structured Data (LD+JSON)
66
79
 
67
- # Advanced Widget Configuration
68
- ...
80
+ The SEO plugin can generate [Structured Data](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data) (LD+JSON), which can enable rich search results. This feature is enabled per-page in your frontmatter.
81
+
82
+ ### Enabling Structured Data
83
+
84
+ To generate a default LD+JSON block, add `ldJson: true` inside your `seo` frontmatter object.
85
+
86
+ ```yaml
87
+ ---
88
+ title: "My Article"
89
+ description: "An article about something important."
90
+ seo:
91
+ ldJson: true
92
+ ---
69
93
  ```
70
- Supported frontmatter fields that the `seo` plugin may look for:
71
- * `title` (Used for `og:title`, `twitter:title`)
72
- * `description` (Used for `<meta name="description">`, `og:description`, `twitter:description`)
73
- * `image` or `ogImage` (Used for `og:image`, `twitter:image`)
74
- * `ogType` (Overrides default `og:type`)
75
- * `twitterCard` (Overrides `config.seo.twitter.cardType` for this page)
76
- * `twitterCreator` (Overrides `config.seo.twitter.creatorUsername` for this page)
77
- * `noindex` (Boolean): If `true`, adds `<meta name="robots" content="noindex">` to discourage search engines from indexing this specific page.
78
-
79
- By configuring the `seo` plugin and utilizing frontmatter effectively, you can significantly improve how your documentation is presented and discovered online.
94
+
95
+ This generates a basic `Article` schema using your page's metadata.
96
+
97
+ ### Customizing Structured Data
98
+
99
+ For more control, provide an object to `ldJson`. This object will be merged with the default data, allowing you to add or override any properties.
100
+
101
+ **Example: Customizing schema type and adding an author**
102
+
103
+ ```yaml
104
+ ---
105
+ title: "Advanced Widget Configuration"
106
+ description: "A detailed guide on configuring advanced settings for the Super Widget."
107
+ seo:
108
+ image: "/assets/images/widgets/super-widget-social.jpg"
109
+ ldJson:
110
+ "@type": "TechArticle"
111
+ author:
112
+ "@type": "Person"
113
+ name: "Jane Doe"
114
+ url: "https://example.com/authors/jane-doe"
115
+ datePublished: "2024-01-15"
116
+ review:
117
+ "@type": "Review"
118
+ reviewRating:
119
+ "@type": "Rating"
120
+ ratingValue: "5"
121
+ bestRating: "5"
122
+ author:
123
+ "@type": "Person"
124
+ name: "John Smith"
125
+ ---
126
+ ```
127
+
128
+ In this example, the schema type is changed to `TechArticle`, and detailed `author`, `datePublished`, and `review` information is added, giving search engines a much richer understanding of your content.
@@ -12,8 +12,8 @@ description: "An overview of the built-in themes provided by docmd."
12
12
  module.exports = {
13
13
  // ...
14
14
  theme: {
15
- name: 'theme-name', // Options: 'default', 'sky', 'ruby'
16
- defaultMode: 'light', // or 'dark'
15
+ name: 'theme-name', // Options: 'default', 'sky', 'ruby', 'retro'
16
+ defaultMode: 'light', // or 'dark' to set as landing mode
17
17
  // ...
18
18
  },
19
19
  // ...
@@ -52,6 +52,20 @@ module.exports = {
52
52
  * Luxurious dark mode with deep, rich backgrounds and vibrant accent colors
53
53
  * **When to use:** When you want your documentation to have a distinctive, premium feel with rich colors and elegant typography.
54
54
 
55
+ ## 4. `retro` Theme
56
+
57
+ * **`theme.name: 'retro'`**
58
+ * **Description:** A nostalgic theme inspired by 1980s-90s computing aesthetics. It features:
59
+ * Terminal-style black backgrounds with phosphor green text in dark mode
60
+ * Light mode with dark green text on light gray backgrounds
61
+ * Monospace typography (Fira Code) for authentic retro feel
62
+ * Neon accent colors (cyan, pink, amber) with glow effects
63
+ * Animated scanlines and CRT flicker effects
64
+ * Terminal-style code blocks with `[TERMINAL]` labels
65
+ * Retro-styled containers with pixel-art inspired elements
66
+ * Blinking cursor effects on links and active elements
67
+ * **When to use:** Perfect for developer tools, gaming documentation, tech blogs with vintage computing focus, or anyone wanting a unique, eye-catching retro aesthetic.
68
+
55
69
  ## How Themes Work
56
70
 
57
71
  Each theme consists of CSS files located within `docmd`'s internal assets. When you select a theme name, `docmd` links the corresponding stylesheet in your site's HTML:
@@ -59,5 +73,6 @@ Each theme consists of CSS files located within `docmd`'s internal assets. When
59
73
  - `default` theme uses the base CSS with no additional theme stylesheet
60
74
  - `sky` theme loads `docmd-theme-sky.css` with its custom styling on top of the default CSS
61
75
  - `ruby` theme loads `docmd-theme-ruby.css` with its custom styling on top of the default CSS
76
+ - `retro` theme loads `docmd-theme-retro.css` with its custom styling on top of the default CSS
62
77
 
63
78
  You can further customize any chosen theme using the `theme.customCss` option in your `config.js` to add your own overrides or additional styles. See [Custom CSS & JS](/theming/custom-css-js/) for details.
@@ -16,9 +16,10 @@ You can set the default theme for your site in the `config.js` file:
16
16
  module.exports = {
17
17
  // ... other config ...
18
18
  theme: {
19
- name: 'default', // or 'sky'
19
+ name: 'default', // or 'sky', 'ruby', 'retro'
20
20
  defaultMode: 'dark', // Can be 'light' or 'dark'
21
21
  enableModeToggle: true, // Enable the toggle button in the UI
22
+ positionMode: 'bottom', // 'top' or 'bottom' - where to show the toggle
22
23
  },
23
24
  // ...
24
25
  };
@@ -26,7 +27,9 @@ module.exports = {
26
27
 
27
28
  * `defaultMode: 'light'`: The site will initially render with the light color scheme.
28
29
  * `defaultMode: 'dark'`: The site will initially render with the dark color scheme.
29
- * `enableModeToggle: true`: Shows a toggle button in the sidebar for users to switch modes.
30
+ * `enableModeToggle: true`: Shows a toggle button for users to switch modes.
31
+ * `positionMode: 'bottom'`: Places the toggle button at the bottom of the sidebar (default).
32
+ * `positionMode: 'top'`: Places the toggle button in the page header (top right).
30
33
 
31
34
  If `defaultMode` is not specified, it defaults to `'light'`.
32
35
 
@@ -62,16 +65,22 @@ body {
62
65
 
63
66
  ## User Preference Toggle
64
67
 
65
- When `enableModeToggle` is set to `true`, a toggle button appears in the sidebar that allows users to switch between light and dark modes:
68
+ When `enableModeToggle` is set to `true`, a toggle button appears that allows users to switch between light and dark modes. The position of this button is controlled by the `positionMode` setting:
66
69
 
67
70
  ```javascript
68
71
  // config.js
69
72
  theme: {
70
73
  defaultMode: 'light',
71
74
  enableModeToggle: true, // Shows the toggle button
75
+ positionMode: 'bottom', // 'bottom' (sidebar) or 'top' (header)
72
76
  },
73
77
  ```
74
78
 
79
+ ### Toggle Button Positions
80
+
81
+ - **`positionMode: 'bottom'`** (default): The toggle button appears at the bottom of the sidebar
82
+ - **`positionMode: 'top'`**: The toggle button appears in the page header (top right corner)
83
+
75
84
  The toggle button uses Lucide icons (`sun` and `moon`) to indicate the current mode and what will happen when clicked.
76
85
 
77
86
  ### User Preference Persistence
package/package.json CHANGED
@@ -1,10 +1,16 @@
1
1
  {
2
2
  "name": "@mgks/docmd",
3
- "version": "0.1.4",
3
+ "version": "0.2.1",
4
4
  "description": "Generate beautiful, lightweight static documentation sites directly from your Markdown files. Zero clutter, just content.",
5
5
  "main": "src/index.js",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./src/index.js",
9
+ "require": "./src/index.js"
10
+ }
11
+ },
6
12
  "bin": {
7
- "docmd": "./bin/docmd.js"
13
+ "docmd": "bin/docmd.js"
8
14
  },
9
15
  "scripts": {
10
16
  "start": "node ./bin/docmd.js dev",
@@ -35,23 +41,29 @@
35
41
  },
36
42
  "homepage": "https://github.com/mgks/docmd#readme",
37
43
  "dependencies": {
38
- "chokidar": "^3.6.0",
39
- "commander": "^12.0.0",
44
+ "chokidar": "^4.0.3",
45
+ "commander": "^14.0.0",
40
46
  "ejs": "^3.1.9",
41
- "express": "^4.19.2",
47
+ "express": "^5.1.0",
42
48
  "fs-extra": "^11.2.0",
43
49
  "gray-matter": "^4.0.3",
44
50
  "highlight.js": "^11.11.1",
45
- "lucide-static": "^0.508.0",
46
- "markdown-it": "^14.1.0",
51
+ "lucide-static": "^0.535.0",
52
+ "markdown-it-abbr": "^2.0.0",
47
53
  "markdown-it-attrs": "^4.3.1",
48
54
  "markdown-it-container": "^4.0.0",
55
+ "markdown-it-deflist": "^3.0.0",
56
+ "markdown-it-footnote": "^4.0.0",
57
+ "markdown-it-task-lists": "^2.1.1",
49
58
  "ws": "^8.17.0"
50
59
  },
51
60
  "devDependencies": {
52
- "eslint": "^8.57.0",
53
- "eslint-config-prettier": "^9.1.0",
61
+ "eslint": "^9.32.0",
62
+ "eslint-config-prettier": "^10.1.8",
54
63
  "eslint-plugin-node": "^11.1.0",
55
64
  "prettier": "^3.2.5"
65
+ },
66
+ "directories": {
67
+ "doc": "docs"
56
68
  }
57
69
  }