@mgks/docmd 0.2.0 → 0.2.2

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.
@@ -1,66 +1,6 @@
1
- :root{--primary-color:#047bf1;--primary-hover:#026ed9;--text-color:#333;--text-light:#666;--bg-color:#fff;--bg-secondary:#f8f9fa;--border-color:#eaeaea;--shadow-color:#00000014;--container-padding:5rem}
2
- @media (prefers-color-scheme: dark) {
3
- :root{--primary-color:#047bf1;--primary-hover:#026ed9;--text-color:#e0e0e0;--text-light:#aaa;--bg-color:#121212;--bg-secondary:#1e1e1e;--border-color:#333;--shadow-color:#0000004d}
4
- }
5
- [data-theme="light"]{--primary-color:#047bf1;--primary-hover:#026ed9;--text-color:#333;--text-light:#666;--bg-color:#fff;--bg-secondary:#f8f9fa;--border-color:#eaeaea;--shadow-color:#00000059}
6
- [data-theme="dark"]{--primary-color:#1955b6;--primary-hover:#084dbd;--text-color:#e0e0e0;--text-light:#aaa;--bg-color:#121212;--bg-secondary:#1e1e1e;--border-color:#333;--shadow-color:#000000de}
7
- *{margin:0;padding:0;box-sizing:border-box}
8
- body{font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif;line-height:1.5;color:var(--text-color);background-color:var(--bg-color);height:100vh;display:flex;overflow:hidden}
9
- .landing-container{display:flex;width:100%;height:100%;padding:0 var(--container-padding);max-width:1600px;margin:0 auto}
10
- .content-side{flex:1;padding:3rem 2rem 3rem 0;display:flex;flex-direction:column;justify-content:center}
11
- .preview-side{flex:1;display:flex;align-items:center;justify-content:flex-start;position:relative;overflow:visible}
12
- .header-top{position:absolute;top:2rem;right:3rem;z-index:100}
13
- .theme-toggle{background:var(--bg-secondary);border:1px solid var(--border-color);color:var(--text-color);width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease}
14
- .theme-toggle:hover{background:var(--border-color)}
15
- .logo{margin-bottom:1.5rem;display:flex;align-items:center}
16
- .logo svg{height:48px;width:auto}
17
- .logo-text{font-family:'PT Mono',monospace;font-weight:700;font-size:2em;margin-left:.25em}
18
- h1{font-size:3rem;font-weight:700;margin-bottom:1rem;letter-spacing:-.02em}
19
- .tagline{font-size:1.25rem;color:var(--text-light);margin-bottom:2rem;font-weight:400}
20
- .features{display:grid;grid-template-columns:repeat(2,1fr);gap:1.5rem;margin-bottom:2rem}
21
- .feature{display:flex;align-items:flex-start;gap:.75rem}
22
- .feature-icon{background-color:var(--primary-color);color:#fff;width:32px;height:32px;border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
23
- .feature-text{font-size:.9rem}
24
- .feature-text strong{display:block;margin-bottom:.25rem}
25
- .buttons{display:flex;gap:1rem;margin-bottom:2rem}
26
- .btn{display:inline-flex;align-items:center;gap:.5rem;padding:.75rem 1.5rem;border-radius:8px;font-weight:600;font-size:1rem;text-decoration:none;transition:all .2s ease}
27
- .btn-primary{background-color:var(--primary-color);color:#fff;border:none}
28
- .btn-primary:hover{background-color:var(--primary-hover)}
29
- .btn-secondary{background-color:var(--bg-secondary);color:var(--text-color);border:1px solid var(--border-color)}
30
- .btn-secondary:hover{background-color:var(--border-color)}
31
- .social-links{display:flex;gap:1rem;padding:0 .25em}
32
- .social-link{color:var(--text-light);transition:color .2s ease}
33
- .social-link:hover{color:var(--primary-color)}
34
- .preview-stack{position:relative;width:100%;height:400px;transform:translateX(15%);perspective:1000px}
35
- .preview-image{position:absolute;width:100%;max-width:700px;height:400px;border-radius:20px;box-shadow:0 25px 50px -12px var(--shadow-color);transition:all .3s ease;overflow:hidden}
36
- .preview-image img{width:100%;height:100%;object-fit:cover;object-position:left top;border-radius:8px;pointer-events:none}
37
- .preview-image.top{z-index:3;transform:rotate(3deg) translateY(-10%) translateX(7%)}
38
- .preview-image.middle{z-index:2;transform:rotate(-3deg) translateY(1%) translateX(-2%)}
39
- .preview-image.bottom{z-index:1;transform:rotate(-8deg) translateY(10%) translateX(-10%)}
40
- body[data-theme="light"] .preview-image .light-img{display:block}
41
- body[data-theme="light"] .preview-image .dark-img{display:none}
42
- body[data-theme="dark"] .preview-image .light-img{display:none}
43
- body[data-theme="dark"] .preview-image .dark-img{display:block}
44
- @media (max-width: 1400px) {
45
- :root{--container-padding:3rem}
46
- .preview-stack{transform:translateX(15%)}
47
- }
48
- @media (max-width: 1200px) {
49
- :root{--container-padding:2rem}
50
- .preview-side{display:none}
51
- .content-side{max-width:100%;padding:3rem 0}
52
- .header-top{right:2rem}
53
- }
54
- @media (max-width: 768px) {
55
- :root{--container-padding:1.5rem}
56
- body{overflow:auto}
57
- .content-side{padding:2rem 0}
58
- h1{font-size:2.5rem}
59
- .features{grid-template-columns:1fr}
60
- .buttons{flex-direction:column}
61
- .header-top{padding:1rem 0;text-align:center;right:1rem}
62
- h1{font-size:2.5rem}
63
- .tagline{font-size:1em;font-weight:500}
64
- .landing-container{padding:1rem;flex-direction:column}
65
- }
66
- .social-links .lucide-heart-handshake{color:#cd2727}
1
+ /*
2
+ * Source file from the docmd project — https://github.com/mgks/docmd
3
+ * Configuration for the docmd project's own documentation
4
+ */
5
+
6
+ :root,html[data-theme=light]{--primary-color:#047bf1;--primary-hover:#026ed9;--text-color:#333;--text-light:#666;--bg-color:#fff;--bg-secondary:#f8f9fa;--border-color:#eaeaea}.theme-toggle,body{color:var(--text-color);display:flex}.logo-text,h1{font-weight:700}.install-code pre,.logo-text{font-family:'PT Mono',monospace}:root{--shadow-color:#00000014;--container-padding:5rem}@media (prefers-color-scheme:dark){:root{--primary-color:#047bf1;--primary-hover:#026ed9;--text-color:#e0e0e0;--text-light:#aaa;--bg-color:#121212;--bg-secondary:#1e1e1e;--border-color:#333;--shadow-color:#0000004d}}[data-theme=light]{--shadow-color:#00000059}[data-theme=dark]{--primary-color:#1955b6;--primary-hover:#084dbd;--text-color:#e0e0e0;--text-light:#aaa;--bg-color:#121212;--bg-secondary:#1e1e1e;--border-color:#333;--shadow-color:#000000de}*{margin:0;padding:0;box-sizing:border-box}body{font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif;line-height:1.5;background-color:var(--bg-color);height:100vh;overflow:hidden}.landing-container{display:flex;width:100%;height:100%;padding:0 var(--container-padding);max-width:1600px;margin:0 auto}.content-side{flex:1;padding:3rem 2rem 3rem 0;display:flex;flex-direction:column;justify-content:center}.preview-side{flex:1;display:flex;align-items:center;justify-content:flex-start;position:relative;overflow:visible}.header-top{position:absolute;top:2rem;right:3rem;z-index:100}.theme-toggle{background:var(--bg-secondary);border:1px solid var(--border-color);width:40px;height:40px;border-radius:50%;align-items:center;justify-content:center;cursor:pointer;transition:.2s}.theme-toggle:hover{background:var(--border-color)}.logo{margin-bottom:1.5rem;display:flex;align-items:center}.buttons,.features,.install-section,.tagline{margin-bottom:2rem}.logo svg{height:48px;width:auto}.logo-text{font-size:2em;margin-left:.25em}h1{font-size:3rem;margin-bottom:1rem;letter-spacing:-.02em}.tagline{font-size:1.25rem;color:var(--text-light);font-weight:400}.btn-primary,.feature-icon{background-color:var(--primary-color);color:#fff}.features{display:grid;grid-template-columns:repeat(2,1fr);gap:1.5rem}.feature{display:flex;align-items:flex-start;gap:.75rem}.feature-icon{width:32px;height:32px;border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.feature-text{font-size:.9rem}.feature-text strong{display:block;margin-bottom:.25rem}.buttons{display:flex;gap:1rem}.btn{display:inline-flex;align-items:center;gap:.5rem;padding:.75rem 1.5rem;border-radius:8px;font-weight:600;font-size:1rem;text-decoration:none;transition:.2s}.btn-primary{border:none}.btn-secondary,.install-code pre{background-color:var(--bg-secondary);border:1px solid var(--border-color)}.btn-primary:hover{background-color:var(--primary-hover)}.btn-secondary{color:var(--text-color)}.btn-secondary:hover{background-color:var(--border-color)}.social-links{display:flex;gap:1rem;padding:0 .25em}.social-link{color:var(--text-light);transition:color .2s}.social-link:hover{color:var(--primary-color)}.preview-stack{position:relative;width:100%;height:400px;transform:translateX(15%);perspective:1000px}.preview-image{position:absolute;width:100%;max-width:700px;height:400px;border-radius:20px;box-shadow:0 25px 50px -12px var(--shadow-color);transition:.3s;overflow:hidden}.preview-image img{width:100%;height:100%;object-fit:cover;object-position:left top;border-radius:8px;pointer-events:none}.preview-image.top{z-index:3;transform:rotate(3deg) translateY(-10%) translateX(7%)}.preview-image.middle{z-index:2;transform:rotate(-3deg) translateY(1%) translateX(-2%)}.preview-image.bottom{z-index:1;transform:rotate(-8deg) translateY(10%) translateX(-10%)}[data-theme=dark] .preview-image .dark-img,[data-theme=light] .preview-image .light-img{display:block}[data-theme=dark] .preview-image .light-img,[data-theme=light] .preview-image .dark-img{display:none}@media (max-width:1400px){:root{--container-padding:3rem}.preview-stack{transform:translateX(15%)}}@media (max-width:1200px){:root{--container-padding:2rem}.preview-side{display:none}.content-side{max-width:100%;padding:3rem 0}.header-top{right:2rem}}@media (max-width:768px){:root{--container-padding:1.5rem}body{overflow:auto}.content-side{padding:2rem 0}.features{grid-template-columns:1fr}.buttons{flex-direction:column}.header-top{padding:1rem 0;text-align:center;right:1rem}h1{font-size:2.5rem}.tagline{font-size:1em;font-weight:500}.landing-container{padding:1rem;flex-direction:column}}.social-links .lucide-heart-handshake{color:#cd2727}.install-code{position:relative;display:inline-block}.install-code pre{border-radius:8px;padding:1rem 3.5rem 1rem 1rem;margin:0;font-size:.9rem;color:var(--text-color)}.install-code code{background:0 0;padding:0;color:inherit}.copy-button{position:absolute;top:.5rem;right:.5rem;background:var(--bg-color);border:1px solid var(--border-color);border-radius:4px;padding:.5rem;cursor:pointer;transition:.2s;color:var(--text-light)}.copy-button:hover{background:var(--border-color);color:var(--text-color)}
package/config.js CHANGED
@@ -1,4 +1,6 @@
1
- // config.js (for docmd's own documentation)
1
+ // Source file from the docmd project — https://github.com/mgks/docmd
2
+
3
+ // Configuration for the docmd project's own documentation
2
4
  module.exports = {
3
5
  // Core Site Metadata
4
6
  siteTitle: 'docmd',
@@ -26,10 +28,11 @@ module.exports = {
26
28
 
27
29
  // Theme Configuration
28
30
  theme: {
29
- name: 'sky', // Themes: 'default', 'sky'
31
+ name: 'sky', // Themes: 'default', 'sky', 'retro', 'ruby'
30
32
  defaultMode: 'light', // Initial color mode: 'light' or 'dark'
31
33
  enableModeToggle: true, // Show UI button to toggle light/dark modes
32
- positionMode: 'top', // 'top' or 'bottom' for the theme toggle
34
+ positionMode: 'top', // 'top' or 'bottom' for the theme toggle
35
+ codeHighlight: true, // Enable/disable codeblock highlighting and import of highlight.js
33
36
  customCss: [ // Array of paths to custom CSS files
34
37
  // '/assets/css/custom.css', // Custom TOC styles
35
38
  ],
@@ -42,13 +45,15 @@ module.exports = {
42
45
 
43
46
  // Content Processing
44
47
  autoTitleFromH1: true, // Set to true to automatically use the first H1 as page title
48
+ copyCode: true, // Enable/disable the copy code button on code blocks
45
49
 
46
50
  // Plugins Configuration (Object format)
47
51
  // Plugins are configured here. docmd will look for these keys.
48
52
  plugins: {
49
53
  // SEO Plugin Configuration
50
- // Most SEO data is pulled from page frontmatter (title, description, image, etc.)
51
- // These are fallbacks or site-wide settings.
54
+ // These are site-wide fallbacks. For detailed per-page SEO controls,
55
+ // including structured data (LD+JSON), use the `seo` key in your page's frontmatter.
56
+ // See the SEO plugin documentation for all available frontmatter options.
52
57
  seo: {
53
58
  // Default meta description if a page doesn't have one in its frontmatter
54
59
  defaultDescription: 'docmd is a Node.js command-line tool for generating beautiful, lightweight static documentation sites from Markdown files.',
@@ -102,6 +107,7 @@ module.exports = {
102
107
  title: 'Content',
103
108
  icon: 'layout-template',
104
109
  path: '/content/',
110
+ collapsible: true,
105
111
  children: [
106
112
  { title: 'Frontmatter', path: '/content/frontmatter', icon: 'file-text' },
107
113
  { title: 'Markdown Syntax', path: '/content/markdown-syntax', icon: 'code-2' },
@@ -110,6 +116,7 @@ module.exports = {
110
116
  title: 'Custom Containers',
111
117
  path: '/content/containers/',
112
118
  icon: 'box',
119
+ collapsible: true,
113
120
  children: [
114
121
  { title: 'Callouts', path: '/content/containers/callouts', icon: 'megaphone' },
115
122
  { title: 'Cards', path: '/content/containers/cards', icon: 'panel-top' },
@@ -128,6 +135,7 @@ module.exports = {
128
135
  title: 'Theming',
129
136
  icon: 'palette',
130
137
  path: '/theming/',
138
+ collapsible: true,
131
139
  children: [
132
140
  { title: 'Available Themes', path: '/theming/available-themes', icon: 'layout-grid' },
133
141
  { title: 'Light & Dark Mode', path: '/theming/light-dark-mode', icon: 'sun-moon' },
@@ -139,6 +147,7 @@ module.exports = {
139
147
  title: 'Plugins',
140
148
  icon: 'puzzle',
141
149
  path: '/plugins/',
150
+ collapsible: true,
142
151
  children: [
143
152
  { title: 'SEO & Meta Tags', path: '/plugins/seo', icon: 'search' },
144
153
  { title: 'Analytics', path: '/plugins/analytics', icon: 'bar-chart' },
@@ -32,7 +32,7 @@ module.exports = {
32
32
  name: 'sky',
33
33
  defaultMode: 'light',
34
34
  enableModeToggle: true,
35
- positionMode: 'bottom', // 'top' or 'bottom'
35
+ positionMode: 'top', // 'top' or 'bottom'
36
36
  customCss: [ // Array of paths to your custom CSS files
37
37
  // '/css/override-styles.css', // Paths are relative to the outputDir root
38
38
  ],
@@ -44,6 +44,7 @@ module.exports = {
44
44
  ],
45
45
 
46
46
  autoTitleFromH1: true,
47
+ copyCode: true,
47
48
 
48
49
  sponsor: {
49
50
  enabled: true,
@@ -83,6 +84,7 @@ module.exports = {
83
84
  {
84
85
  title: 'Guides',
85
86
  icon: 'book-open',
87
+ collapsible: true, // This makes the 'Guides' section collapsible
86
88
  children: [
87
89
  { title: 'Installation', path: '/guides/installation', icon: 'download' },
88
90
  { title: 'Project GitHub', path: 'https://github.com/mgks/docmd', icon: 'github', external: true }
@@ -141,6 +143,11 @@ module.exports = {
141
143
  // ---
142
144
  ```
143
145
 
146
+ ### `copyCode`
147
+ * **Type:** `Boolean`
148
+ * **Default:** `true`
149
+ * **Description:** If `true`, a "Copy" button will be added to the top-right corner of all code blocks, allowing users to easily copy the code to their clipboard with a single click. **Note:** This setting only applies to regular pages. For noStyle pages, copy code functionality must be explicitly enabled via the `components.mainScripts: true` setting.
150
+
144
151
  ## `sidebar` (Object)
145
152
 
146
153
  Configures the behavior of the sidebar.
@@ -186,7 +193,7 @@ Configures the visual theme of your site.
186
193
  ### `theme.customCss`
187
194
  * **Type:** `Array` of `String`
188
195
  * **Default:** `[]` (empty array)
189
- * **Description:** An array of paths to your custom CSS files. These files will be linked in the `<head>` of every page *after* the main theme CSS, allowing you to override or extend styles.
196
+ * **Description:** An array of paths to your custom CSS files. These files will be linked in the `<head>` of every regular page *after* the main theme CSS, allowing you to override or extend styles. **Note:** For noStyle pages, custom CSS must be explicitly enabled via `components.customCss: true`.
190
197
  * **Paths:** Should be relative to the `outputDir` root (e.g., `'/css/my-styles.css'`). You are responsible for ensuring these files exist at the specified location in your final `site/` output (e.g., by placing them in an assets folder that `docmd` copies, or in your project's static assets if your `srcDir` is part of a larger project).
191
198
  * **Example:** `customCss: ['/assets/css/custom-branding.css']`
192
199
 
@@ -197,7 +204,7 @@ Configures the visual theme of your site.
197
204
  ## `customJs` (Array of String)
198
205
  * **Type:** `Array` of `String`
199
206
  * **Default:** `[]`
200
- * **Description:** An array of paths to your custom JavaScript files. These files will be included as `<script>` tags just before the closing `</body>` tag on every page.
207
+ * **Description:** An array of paths to your custom JavaScript files. These files will be included as `<script>` tags just before the closing `</body>` tag on every regular page. **Note:** For noStyle pages, custom JavaScript must be explicitly enabled via `components.customJs: true`.
201
208
  * **Paths:** Should be relative to the `outputDir` root (e.g., `'/js/my-analytics-alternative.js'`).
202
209
  * **Example:** `customJs: ['/assets/js/interactive-component.js']`
203
210
 
@@ -219,14 +226,16 @@ Configures the visual theme of your site.
219
226
  * `path` (String, Required for direct links)
220
227
  * `children` (Array, Optional)
221
228
  * `icon` (String, Optional): The name of an SVG icon to display next to the navigation item. `docmd` will look for an SVG file named `icon-name.svg` in its bundled assets (e.g., `home` for `home.svg`). Ensure the chosen icon name corresponds to an available SVG. See [Theming > Icons](/theming/icons/) for more details.
229
+ * `collapsible` (Boolean, Optional): If set to `true` on a parent item (an item with `children`), the item will become a collapsible accordion. It will be collapsed by default unless one of its children is the currently active page. User interactions (opening/closing) are saved in `sessionStorage`. Defaults to `false`.
222
230
  * `external` (Boolean, Optional): If set to `true`, the `path` is treated as an absolute external URL and the link will open in a new tab (`target="_blank"`). Defaults to `false`.
231
+ * `collapsible` (Boolean, Optional): If set to `true` on a parent item (an item with `children`), the item will become a collapsible accordion. It will be collapsed by default unless one of its children is the currently active page. User interactions (opening/closing) are saved in `sessionStorage`. Defaults to `false`.
223
232
 
224
233
  ## `footer` (String, Optional)
225
- * **Description:** Custom footer text (Markdown supported).
234
+ * **Description:** Custom footer text (Markdown supported). **Note:** For noStyle pages, the footer must be explicitly enabled via `components.footer: true`.
226
235
 
227
236
  ## `sponsor` (Object, Optional)
228
237
  * **Type:** `Object`
229
- * **Description:** Configures a sponsor ribbon that appears in the bottom-right corner of every page.
238
+ * **Description:** Configures a sponsor ribbon that appears in the bottom-right corner of every regular page. **Note:** For noStyle pages, the sponsor ribbon must be explicitly enabled via `components.branding: true`.
230
239
  * **Properties:**
231
240
  * `enabled` (Boolean, Optional): Whether to show the sponsor ribbon. Defaults to `true` if the sponsor object is provided.
232
241
  * `title` (String, Optional): Text to display on the ribbon. Defaults to `'Sponsor the Project'`.
@@ -242,6 +251,6 @@ Configures the visual theme of your site.
242
251
  * **Note:** The ribbon is positioned fixed in the bottom-right corner and includes a heart icon with a subtle animation.
243
252
 
244
253
  ## `favicon` (String, Optional)
245
- * **Description:** Path to your favicon file, relative to `outputDir` root.
254
+ * **Description:** Path to your favicon file, relative to `outputDir` root. **Note:** For noStyle pages, the favicon must be explicitly enabled via `components.favicon: true`.
246
255
 
247
256
  This file needs significant detail for each new option, explaining its purpose, type, default value, and how to use it with examples.
@@ -74,7 +74,7 @@ You can include cards, callouts, and buttons inside steps for richer content:
74
74
  3. **Initialize Project**
75
75
  Create the project structure and configuration files.
76
76
 
77
- ::: button Create_Project external:https://github.com/new color:blue
77
+ ::: button Create_Project external:https://github.com/new color:#2564e4
78
78
 
79
79
  4. **Start Coding**
80
80
  Begin implementing your application features.
@@ -110,7 +110,7 @@ You can include cards, callouts, and buttons inside steps for richer content:
110
110
  3. **Initialize Project**
111
111
  Create the project structure and configuration files.
112
112
 
113
- ::: button Create_Project external:https://github.com/new color:blue
113
+ ::: button Create_Project external:https://github.com/new color:#2564e4
114
114
 
115
115
  4. **Start Coding**
116
116
  Begin implementing your application features.
@@ -0,0 +1,24 @@
1
+ ---
2
+ title: "Custom Containers"
3
+ description: "Enhance your documentation with special components like callouts, cards, and steps using docmd's custom container syntax."
4
+ noStyle: true
5
+ components:
6
+ meta: false
7
+ favicon: true
8
+ css: false
9
+ theme: false
10
+ scripts: false
11
+ customHead: |
12
+ <script>
13
+ window.location.href = "https://docmd.mgks.dev/content/containers/";
14
+ document.addEventListener("DOMContentLoaded", function () {
15
+ window.location.href = "https://docmd.mgks.dev/content/containers/";
16
+ });
17
+ </script>
18
+ bodyClass: "no-style-example"
19
+ ---
20
+
21
+ <div class="container">
22
+ Redirecting...<br/>
23
+ /custom-containers have moved to /containers now <a href="https://docmd.mgks.dev/content/containers/">Visit New Custom Containers Page</a>
24
+ </div>
@@ -8,6 +8,8 @@ components:
8
8
  css: true
9
9
  theme: true
10
10
  scripts: true
11
+ mainScripts: true
12
+ copyCode: true
11
13
  customHead: |
12
14
  <style>
13
15
  body {
@@ -17,7 +17,9 @@ docmd offers a "no-style" page format that gives you maximum flexibility to crea
17
17
 
18
18
  To create a no-style page, add `noStyle: true` to your page's frontmatter. This tells docmd to use a special template that only includes the components you explicitly request.
19
19
 
20
- By default, a no-style page will render just your content with minimal HTML structure. You can then selectively enable specific components via the `components` object in frontmatter.
20
+ By default, a no-style page will render just your content with minimal HTML structure. **All components are disabled by default** and must be explicitly enabled via the `components` object in frontmatter.
21
+
22
+ > **Note:** This behavior changed in v0.2.0. Previously, some components were enabled by default and had to be disabled. Now all components are opt-in only.
21
23
 
22
24
  ## HTML Support
23
25
 
@@ -36,7 +38,7 @@ description: "Welcome to my project"
36
38
  noStyle: true
37
39
  components:
38
40
  meta: true # Include meta tags, title, description
39
- css: false # Don't include default CSS
41
+ # css: false # Not needed - CSS is disabled by default
40
42
  ---
41
43
 
42
44
  <div style="text-align: center; padding: 50px;">
@@ -48,32 +50,35 @@ components:
48
50
 
49
51
  ## Available Components
50
52
 
51
- You can control exactly which components are included in your page by setting them to `true` or `false` in the `components` object:
52
-
53
- | Component | Description | Default |
54
- |-----------|-------------|---------|
55
- | `meta` | Meta tags, title, description | `true` |
56
- | `siteTitle` | Include site title after page title | `true` |
57
- | `favicon` | Include favicon | `true` |
58
- | `css` | Include main CSS | `false` |
59
- | `highlight` | Include syntax highlighting CSS | `false` |
60
- | `theme` | Include theme-specific CSS | `false` |
61
- | `customCss` | Include custom CSS files from config | `false` |
62
- | `pluginStyles` | Include plugin-specific CSS | `false` |
63
- | `pluginHeadScripts` | Include plugin scripts in head | `false` |
64
- | `layout` | Use main content layout (`true`, `'full'`, or `false`) | `false` |
65
- | `sidebar` | Include sidebar | `false` |
66
- | `header` | Include page header | `false` |
67
- | `pageTitle` | Include page title in header | `false` |
68
- | `footer` | Include page footer | `false` |
69
- | `branding` | Include docmd branding in footer | `false` |
70
- | `logo` | Include logo in sidebar | `false` |
71
- | `navigation` | Include navigation in sidebar | `false` |
72
- | `themeToggle` | Include theme toggle button | `false` |
73
- | `toc` | Include table of contents | `false` |
74
- | `scripts` | Include all scripts | `false` |
75
- | `customJs` | Include custom JS files from config | `false` |
76
- | `pluginBodyScripts` | Include plugin scripts at end of body | `false` |
53
+ You can control exactly which components are included in your page by setting them to `true` in the `components` object. **All components are disabled by default** and must be explicitly enabled:
54
+
55
+ | Component | Description | Required Setting |
56
+ |-----------|-------------|------------------|
57
+ | `meta` | Meta tags, title, description | `meta: true` |
58
+ | `siteTitle` | Include site title after page title | `siteTitle: true` |
59
+ | `favicon` | Include favicon | `favicon: true` |
60
+ | `css` | Include main CSS | `css: true` |
61
+ | `highlight` | Include syntax highlighting CSS | `highlight: true` |
62
+ | `theme` | Include theme-specific CSS | `theme: true` |
63
+ | `themeMode` | Include theme mode toggle functionality | `themeMode: true` |
64
+ | `customCss` | Include custom CSS files from config | `customCss: true` |
65
+ | `pluginStyles` | Include plugin-specific CSS | `pluginStyles: true` |
66
+ | `pluginHeadScripts` | Include plugin scripts in head | `pluginHeadScripts: true` |
67
+ | `layout` | Use main content layout (`true`, `'full'`, or `false`) | `layout: true` or `layout: 'full'` |
68
+ | `sidebar` | Include sidebar | `sidebar: true` |
69
+ | `header` | Include page header | `header: true` |
70
+ | `pageTitle` | Include page title in header | `pageTitle: true` |
71
+ | `footer` | Include page footer | `footer: true` |
72
+ | `branding` | Include docmd branding in footer | `branding: true` |
73
+ | `logo` | Include logo in sidebar | `logo: true` |
74
+ | `navigation` | Include navigation in sidebar | `navigation: true` |
75
+ | `themeToggle` | Include theme toggle button | `themeToggle: true` |
76
+ | `toc` | Include table of contents | `toc: true` |
77
+ | `scripts` | Enable script loading (required for other script components) | `scripts: true` |
78
+ | `mainScripts` | Include main JavaScript (copy code, theme toggle, etc.) | `mainScripts: true` |
79
+ | `lightbox` | Include image lightbox functionality | `lightbox: true` |
80
+ | `customJs` | Include custom JS files from config | `customJs: true` |
81
+ | `pluginBodyScripts` | Include plugin scripts at end of body | `pluginBodyScripts: true` |
77
82
 
78
83
  ## Layout Options
79
84
 
@@ -83,6 +88,22 @@ The `components.layout` property has three possible values:
83
88
  - `true`: Use the main content layout with optional header and footer
84
89
  - `'full'`: Same as `true`, a full layout with content area
85
90
 
91
+ ## Script Components
92
+
93
+ Script components work in a hierarchical manner:
94
+
95
+ 1. **`scripts: true`** - Enables script loading (required for all other script components)
96
+ 2. **`mainScripts: true`** - Includes main JavaScript functionality (copy code, theme toggle, etc.)
97
+ 3. **`lightbox: true`** - Includes image lightbox functionality (requires `mainScripts: true`)
98
+
99
+ **Example:**
100
+ ```yaml
101
+ components:
102
+ scripts: true # Enable script loading
103
+ mainScripts: true # Include main JavaScript
104
+ lightbox: true # Include lightbox (requires mainScripts)
105
+ ```
106
+
86
107
  ## Sidebar Option
87
108
 
88
109
  If you set `components.sidebar: true`, the sidebar will be included with optional logo, navigation, and theme toggle button.
@@ -124,12 +145,15 @@ components:
124
145
  favicon: true
125
146
  css: true
126
147
  theme: true
148
+ themeMode: true
127
149
  layout: true
128
150
  header: true
129
151
  pageTitle: true
130
152
  footer: true
131
153
  branding: true
132
154
  scripts: true
155
+ mainScripts: true
156
+ lightbox: true
133
157
  customHead: |
134
158
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" rel="stylesheet">
135
159
  <style>
package/docs/index.md CHANGED
@@ -7,32 +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
34
  <link rel="stylesheet" href="/assets/css/welcome.css">
14
35
  <script>
15
- // Initialize theme from localStorage or system preference
16
- function initTheme() {
17
- const storedTheme = localStorage.getItem('docmd-theme');
18
- if (storedTheme) {
19
- document.body.setAttribute('data-theme', storedTheme);
20
- } else {
21
- const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
22
- document.body.setAttribute('data-theme', prefersDark ? 'dark' : 'light');
23
- }
24
- }
25
-
26
- // Toggle theme between light and dark
27
36
  function toggleTheme() {
28
- const currentTheme = document.body.getAttribute('data-theme');
37
+ const currentTheme = document.documentElement.getAttribute('data-theme');
29
38
  const newTheme = currentTheme === 'light' ? 'dark' : 'light';
30
- document.body.setAttribute('data-theme', newTheme);
39
+ document.documentElement.setAttribute('data-theme', newTheme);
31
40
  localStorage.setItem('docmd-theme', newTheme);
32
41
  }
33
-
34
- // Run on page load
35
- 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
+ }
36
55
  </script>
37
56
  ---
38
57
 
@@ -97,6 +116,18 @@ customHead: |
97
116
  </div>
98
117
  </div>
99
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
+
100
131
  <div class="buttons">
101
132
  <a href="/getting-started/" class="btn btn-primary">
102
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>
@@ -36,46 +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
65
- permalink: "https://example.com/docs/widgets/advanced-configuration" # Canonical URL
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
66
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)
67
79
 
68
- # Advanced Widget Configuration
69
- ...
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
+ ---
70
93
  ```
71
- Supported frontmatter fields that the `seo` plugin may look for:
72
- * `title` (Used for `og:title`, `twitter:title`)
73
- * `description` (Used for `<meta name="description">`, `og:description`, `twitter:description`)
74
- * `image` or `ogImage` (Used for `og:image`, `twitter:image`)
75
- * `ogType` (Overrides default `og:type`)
76
- * `twitterCard` (Overrides `config.seo.twitter.cardType` for this page)
77
- * `twitterCreator` (Overrides `config.seo.twitter.creatorUsername` for this page)
78
- * `noindex` (Boolean): If `true`, adds `<meta name="robots" content="noindex">` to discourage search engines from indexing this specific page.
79
- * `permalink` (String): If provided, sets a canonical URL for the page. This is useful when you have duplicate content across different URLs and want to indicate the preferred version. If not specified, the page's URL will be used as the canonical URL. (Note: `canonicalUrl` is also supported for backward compatibility)
80
-
81
- 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.