@mgks/docmd 0.3.9 → 0.4.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.
Files changed (47) hide show
  1. package/README.md +15 -160
  2. package/bin/docmd.js +6 -69
  3. package/package.json +6 -79
  4. package/bin/postinstall.js +0 -14
  5. package/src/assets/css/docmd-highlight-dark.css +0 -86
  6. package/src/assets/css/docmd-highlight-light.css +0 -86
  7. package/src/assets/css/docmd-main.css +0 -1736
  8. package/src/assets/css/docmd-theme-retro.css +0 -867
  9. package/src/assets/css/docmd-theme-ruby.css +0 -629
  10. package/src/assets/css/docmd-theme-sky.css +0 -617
  11. package/src/assets/favicon.ico +0 -0
  12. package/src/assets/images/docmd-logo-dark.png +0 -0
  13. package/src/assets/images/docmd-logo-light.png +0 -0
  14. package/src/assets/js/docmd-image-lightbox.js +0 -74
  15. package/src/assets/js/docmd-main.js +0 -260
  16. package/src/assets/js/docmd-mermaid.js +0 -205
  17. package/src/assets/js/docmd-search.js +0 -218
  18. package/src/commands/build.js +0 -237
  19. package/src/commands/dev.js +0 -352
  20. package/src/commands/init.js +0 -277
  21. package/src/commands/live.js +0 -145
  22. package/src/core/asset-manager.js +0 -72
  23. package/src/core/config-loader.js +0 -58
  24. package/src/core/config-validator.js +0 -80
  25. package/src/core/file-processor.js +0 -103
  26. package/src/core/fs-utils.js +0 -40
  27. package/src/core/html-generator.js +0 -184
  28. package/src/core/icon-renderer.js +0 -106
  29. package/src/core/logger.js +0 -21
  30. package/src/core/markdown/containers.js +0 -94
  31. package/src/core/markdown/renderers.js +0 -90
  32. package/src/core/markdown/rules.js +0 -402
  33. package/src/core/markdown/setup.js +0 -113
  34. package/src/core/navigation-helper.js +0 -74
  35. package/src/index.js +0 -12
  36. package/src/live/core.js +0 -67
  37. package/src/live/index.html +0 -216
  38. package/src/live/live.css +0 -256
  39. package/src/live/shims.js +0 -1
  40. package/src/plugins/analytics.js +0 -48
  41. package/src/plugins/seo.js +0 -107
  42. package/src/plugins/sitemap.js +0 -127
  43. package/src/templates/layout.ejs +0 -187
  44. package/src/templates/navigation.ejs +0 -87
  45. package/src/templates/no-style.ejs +0 -166
  46. package/src/templates/partials/theme-init.js +0 -30
  47. package/src/templates/toc.ejs +0 -38
@@ -1,127 +0,0 @@
1
- // Source file from the docmd project — https://github.com/docmd-io/docmd
2
-
3
- /*
4
- * Generate sitemap.xml in the output directory root
5
- */
6
-
7
- const fs = require('../core/fs-utils');
8
- const path = require('path');
9
-
10
- // Function to format paths for display (relative to CWD)
11
- function formatPathForDisplay(absolutePath) {
12
- const CWD = process.cwd();
13
- const relativePath = path.relative(CWD, absolutePath);
14
-
15
- // If it's not a subdirectory, prefix with ./ for clarity
16
- if (!relativePath.startsWith('..') && !path.isAbsolute(relativePath)) {
17
- return `./${relativePath}`;
18
- }
19
-
20
- // Return the relative path
21
- return relativePath;
22
- }
23
-
24
- /**
25
- * Generate sitemap.xml in the output directory root
26
- * @param {Object} config - The full configuration object
27
- * @param {Array} pages - Array of page objects with data about each processed page
28
- * @param {string} outputDir - Path to the output directory
29
- * @param {Object} options - Additional options
30
- * @param {boolean} options.isDev - Whether running in development mode
31
- */
32
- async function generateSitemap(config, pages, outputDir, options = { isDev: false }) {
33
- // Skip if no siteUrl is defined (sitemap needs absolute URLs)
34
- if (!config.siteUrl) {
35
- if (!options.isDev) {
36
- console.warn('⚠️ No siteUrl defined in config. Skipping sitemap generation.');
37
- }
38
- return;
39
- }
40
-
41
- // Normalize siteUrl to ensure it has no trailing slash
42
- const siteUrl = config.siteUrl.replace(/\/$/, '');
43
-
44
- // Sitemap XML header
45
- let sitemapXml = '<?xml version="1.0" encoding="UTF-8"?>\n';
46
- sitemapXml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n';
47
-
48
- // Get default settings from config
49
- const defaultChangefreq = config.plugins?.sitemap?.defaultChangefreq || 'weekly';
50
- const defaultPriority = config.plugins?.sitemap?.defaultPriority || 0.8;
51
-
52
- const rootPriority = config.plugins?.sitemap?.rootPriority || 1.0;
53
-
54
- // Helper function to convert paths to URLs
55
- function pathToUrl(pagePath) {
56
- // Handle index.html
57
- if (pagePath === 'index.html') {
58
- return siteUrl + '/';
59
- }
60
-
61
- // For paths already using pretty URLs (ending with slash)
62
- if (pagePath.endsWith('/')) {
63
- return siteUrl + '/' + pagePath;
64
- }
65
-
66
- // For paths still using .html extension
67
- // Convert to no-extension format
68
- if (pagePath.endsWith('.html')) {
69
- const pathWithoutExt = pagePath.substring(0, pagePath.length - 5);
70
- if (pathWithoutExt === '') {
71
- return siteUrl + '/';
72
- } else {
73
- return siteUrl + '/' + pathWithoutExt + '/';
74
- }
75
- }
76
-
77
- // Default case
78
- return siteUrl + '/' + pagePath;
79
- }
80
-
81
- for (const page of pages) {
82
- // Parse frontmatter for sitemap-specific overrides and metadata
83
- const frontmatter = page.frontmatter || {};
84
- const pagePath = page.outputPath || '';
85
-
86
- // Skip if page is explicitly excluded from sitemap
87
- if (frontmatter.sitemap === false) {
88
- continue;
89
- }
90
-
91
- // Determine URL for this page
92
- let url = pathToUrl(pagePath);
93
-
94
- // Set priority
95
- let priority = frontmatter.priority ||
96
- (pagePath === 'index.html' ? rootPriority : defaultPriority);
97
-
98
- // Set change frequency
99
- const changefreq = frontmatter.changefreq || defaultChangefreq;
100
-
101
- // Add page to sitemap
102
- sitemapXml += ' <url>\n';
103
- sitemapXml += ` <loc>${url}</loc>\n`;
104
-
105
- // Add lastmod if available in frontmatter
106
- if (frontmatter.lastmod) {
107
- sitemapXml += ` <lastmod>${frontmatter.lastmod}</lastmod>\n`;
108
- }
109
-
110
- sitemapXml += ` <changefreq>${changefreq}</changefreq>\n`;
111
- sitemapXml += ` <priority>${priority}</priority>\n`;
112
- sitemapXml += ' </url>\n';
113
- }
114
-
115
- sitemapXml += '</urlset>';
116
-
117
- // Write sitemap file
118
- const sitemapPath = path.join(outputDir, 'sitemap.xml');
119
- await fs.writeFile(sitemapPath, sitemapXml);
120
-
121
- // Only show sitemap generation message in production mode or if DOCMD_DEV is true
122
- if (!options.isDev || process.env.DOCMD_DEV === 'true') {
123
- console.log(`✅ Generated sitemap at ${formatPathForDisplay(sitemapPath)}`);
124
- }
125
- }
126
-
127
- module.exports = { generateSitemap };
@@ -1,187 +0,0 @@
1
- <%# Source file from the docmd project — https://github.com/docmd-io/docmd %>
2
-
3
- <!DOCTYPE html>
4
- <html lang="en">
5
- <head>
6
- <meta charset="UTF-8">
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
-
9
- <%- metaTagsHtml || '' %>
10
-
11
- <title><%= pageTitle %><% if(siteTitle) { %> : <%= siteTitle %><% } %></title>
12
- <% if (description && !(metaTagsHtml && metaTagsHtml.includes('name="description"'))) { %>
13
- <meta name="description" content="<%= description %>">
14
- <% } %>
15
-
16
- <%- faviconLinkHtml || '' %>
17
-
18
- <!-- Theme Mode -->
19
- <script>window.DOCMD_DEFAULT_MODE = "<%= defaultMode %>";</script>
20
-
21
- <!-- Syntax Highlighting -->
22
- <% if (config.theme?.codeHighlight !== false) { %>
23
- <link rel="stylesheet" id="highlight-theme" href="<%= relativePathToRoot %>assets/css/docmd-highlight-<%= defaultMode === 'dark' ? 'dark' : 'light' %>.css" data-base-href="<%= relativePathToRoot %>assets/css/">
24
- <% } %>
25
-
26
- <!-- Styles -->
27
- <link rel="stylesheet" href="<%= relativePathToRoot %>assets/css/docmd-main.css">
28
- <%- themeCssLinkHtml || '' %>
29
- <% (customCssFiles || []).forEach(cssFile => { %>
30
- <link rel="stylesheet" href="<%= relativePathToRoot %><%- cssFile.startsWith('/') ? cssFile.substring(1) : cssFile %>">
31
- <% }); %>
32
- <%- pluginStylesHtml || '' %>
33
-
34
- <!-- Theme Init -->
35
- <%- themeInitScript %>
36
-
37
- <%- pluginHeadScriptsHtml || '' %>
38
- </head>
39
- <body class="<%= sidebarConfig.collapsible ? 'sidebar-collapsible' : 'sidebar-not-collapsible' %>"
40
- data-default-collapsed="<%= sidebarConfig.defaultCollapsed %>"
41
- data-copy-code-enabled="<%= config.copyCode === true %>">
42
-
43
- <aside class="sidebar">
44
- <div class="sidebar-header">
45
- <% if (logo && logo.light && logo.dark) { %>
46
- <a href="<%= logo.href || relativePathToRoot %>" class="logo-link">
47
- <img src="<%= relativePathToRoot %><%- logo.light.startsWith('/') ? logo.light.substring(1) : logo.light %>" alt="<%= logo.alt || siteTitle %>" class="logo-light" <% if (logo.height) { %>style="height: <%= logo.height %>;"<% } %>>
48
- <img src="<%= relativePathToRoot %><%- logo.dark.startsWith('/') ? logo.dark.substring(1) : logo.dark %>" alt="<%= logo.alt || siteTitle %>" class="logo-dark" <% if (logo.height) { %>style="height: <%= logo.height %>;"<% } %>>
49
- </a>
50
- <% } else { %>
51
- <h1><a href="<%= relativePathToRoot %>index.html"><%= siteTitle %></a></h1>
52
- <% } %>
53
- <span class="mobile-view sidebar-menu-button float-right">
54
- <%- renderIcon("ellipsis-vertical") %>
55
- </span>
56
- </div>
57
-
58
- <%- navigationHtml %>
59
-
60
- <% if (theme && theme.enableModeToggle && theme.positionMode !== 'top') { %>
61
- <button id="theme-toggle-button" aria-label="Toggle theme" class="theme-toggle-button">
62
- <%- renderIcon('sun', { class: 'icon-sun' }) %> <%- renderIcon('moon', { class: 'icon-moon' }) %>
63
- </button>
64
- <% } %>
65
- </aside>
66
-
67
- <div class="main-content-wrapper">
68
- <div class="page-header">
69
- <div class="header-left">
70
- <% if (sidebarConfig.collapsible) { %>
71
- <button id="sidebar-toggle-button" class="sidebar-toggle-button" aria-label="Toggle Sidebar">
72
- <%- renderIcon('panel-left-close') %>
73
- </button>
74
- <% } %>
75
- <h1><%= pageTitle %></h1>
76
- </div>
77
- <% if (theme && theme.enableModeToggle && theme.positionMode === 'top') { %>
78
- <div class="header-right">
79
- <% if (config.search !== false) { %>
80
- <button class="docmd-search-trigger" aria-label="Search">
81
- <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><path d="m21 21-4.34-4.34"></path><circle cx="11" cy="11" r="8"></circle></svg>
82
- <span class="search-label">Search</span>
83
- <span class="search-keys"><kbd class="docmd-kbd">⌘</kbd><kbd class="docmd-kbd">k</kbd></span>
84
- </button>
85
- <% } %>
86
- <button id="theme-toggle-button" aria-label="Toggle theme" class="theme-toggle-button theme-toggle-header">
87
- <%- renderIcon('sun', { class: 'icon-sun' }) %> <%- renderIcon('moon', { class: 'icon-moon' }) %>
88
- </button>
89
- </div>
90
- <% } %>
91
- </div>
92
-
93
- <main class="content-area">
94
- <div class="content-layout">
95
- <div class="main-content">
96
- <%- content %>
97
-
98
- <% if (config.pageNavigation && (prevPage || nextPage)) { %>
99
- <div class="page-navigation">
100
- <% if (prevPage) { %>
101
- <a href="<%= prevPage.url %>" class="prev-page">
102
- <%- renderIcon('arrow-left', { class: 'page-nav-icon' }) %>
103
- <span><small>Previous</small><strong><%= prevPage.title %></strong></span>
104
- </a>
105
- <% } else { %><div class="prev-page-placeholder"></div><% } %>
106
- <% if (nextPage) { %>
107
- <a href="<%= nextPage.url %>" class="next-page">
108
- <span><small>Next</small><strong><%= nextPage.title %></strong></span>
109
- <%- renderIcon('arrow-right', { class: 'page-nav-icon' }) %>
110
- </a>
111
- <% } else { %><div class="next-page-placeholder"></div><% } %>
112
- </div>
113
- <% } %>
114
- </div>
115
-
116
- <div class="toc-sidebar">
117
- <%- include('toc', { content, headings, navigationHtml, isActivePage }) %>
118
- </div>
119
- </div>
120
-
121
- <div class="page-footer-actions">
122
- <% if (locals.editUrl) { %>
123
- <a href="<%= editUrl %>" target="_blank" rel="noopener noreferrer" class="edit-link">
124
- <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-pencil"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/></svg> <%= editLinkText %>
125
- </a>
126
- <% } %>
127
- </div>
128
- </main>
129
-
130
- <footer class="page-footer">
131
- <div class="footer-content">
132
- <div class="user-footer"><%- footerHtml || '' %></div>
133
- <div class="branding-footer">
134
- Build with <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"></path><path d="M12 5 9.04 7.96a2.17 2.17 0 0 0 0 3.08c.82.82 2.13.85 3 .07l2.07-1.9a2.82 2.82 0 0 1 3.79 0l2.96 2.66"></path><path d="m18 15-2-2"></path><path d="m15 18-2-2"></path></svg> <a href="https://docmd.io" target="_blank" rel="noopener">docmd.</a>
135
- </div>
136
- </div>
137
- </footer>
138
- </div>
139
-
140
- <% if (config.search !== false) { %>
141
- <!-- Search Modal -->
142
- <div id="docmd-search-modal" class="docmd-search-modal" style="display: none;">
143
- <div class="docmd-search-box">
144
- <div class="docmd-search-header">
145
- <svg xmlns="http://www.w3.org/2000/svg" width="1.25em" height="1.25em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-icon lucide-search"><path d="m21 21-4.34-4.34"></path><circle cx="11" cy="11" r="8"></circle></svg>
146
- <input type="text" id="docmd-search-input" placeholder="Search documentation..." autocomplete="off" spellcheck="false">
147
- <button onclick="window.closeDocmdSearch()" class="docmd-search-close" aria-label="Close search">
148
- <svg xmlns="http://www.w3.org/2000/svg" width="2em" height="2em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
149
- </button>
150
- </div>
151
- <div id="docmd-search-results" class="docmd-search-results"></div>
152
- <div class="docmd-search-footer">
153
- <span><kbd class="docmd-kbd">↑</kbd> <kbd class="docmd-kbd">↓</kbd> to navigate</span>
154
- <span><kbd class="docmd-kbd">ESC</kbd> to close</span>
155
- </div>
156
- </div>
157
- </div>
158
- <% } %>
159
-
160
- <!-- Scripts -->
161
- <script>window.DOCMD_ROOT = "<%= relativePathToRoot %>";</script>
162
- <script src="<%= relativePathToRoot %>assets/js/docmd-main.js"></script>
163
-
164
- <% if (config.search !== false) { %>
165
- <script src="https://cdn.jsdelivr.net/npm/minisearch@7.2.0/dist/umd/index.min.js"></script>
166
- <script src="<%= relativePathToRoot %>assets/js/docmd-search.js"></script>
167
- <% } %>
168
-
169
- <script src="https://cdn.jsdelivr.net/npm/mermaid@11.12.2/dist/mermaid.min.js"></script>
170
- <script src="<%= relativePathToRoot %>assets/js/docmd-mermaid.js"></script>
171
-
172
- <% (customJsFiles || []).forEach(jsFile => { %>
173
- <script src="<%= relativePathToRoot %><%- jsFile.startsWith('/') ? jsFile.substring(1) : jsFile %>"></script>
174
- <% }); %>
175
-
176
- <%- pluginBodyScriptsHtml || '' %>
177
-
178
- <% if (sponsor && sponsor.enabled) { %>
179
- <div class="sponsor-ribbon">
180
- <a href="<%= sponsor.link %>" target="_blank" rel="noopener noreferrer" class="sponsor-link">
181
- <%- renderIcon('heart', { class: 'sponsor-icon' }) %>
182
- <span class="sponsor-text"><%= sponsor.title %></span>
183
- </a>
184
- </div>
185
- <% } %>
186
- </body>
187
- </html>
@@ -1,87 +0,0 @@
1
- <%# Source file from the docmd project — https://github.com/docmd-io/docmd %>
2
-
3
- <nav class="sidebar-nav" aria-label="Main navigation">
4
- <ul>
5
- <%
6
- function normalizePath(p) {
7
- if (!p) return '#';
8
- if (p.startsWith('http://') || p.startsWith('https://')) return p;
9
- let path = p.replace(/\\/g, '/');
10
- if (path.startsWith('./')) path = path.substring(2);
11
- if (path.endsWith('index.md')) path = path.slice(0, -'index.md'.length);
12
- else path = path.replace(/\.md$/, '');
13
- if (!path.startsWith('/')) path = '/' + path;
14
- if (path.length > 1 && !path.endsWith('/')) path += '/';
15
- if (path === '') path = '/';
16
- return path;
17
- }
18
-
19
- function hasActiveChild(item, currentPagePath) {
20
- if (!item.children || !Array.isArray(item.children)) return false;
21
- return item.children.some(child => {
22
- if (!child.path || child.external) return false;
23
- const childPath = normalizePath(child.path);
24
- if (currentPagePath === childPath) return true;
25
- return hasActiveChild(child, currentPagePath);
26
- });
27
- }
28
-
29
- function renderNav(items) {
30
- if (!items || !Array.isArray(items)) return;
31
- items.forEach(item => {
32
- const isExplicitExternal = item.external || false;
33
- let itemPath = item.path || '#';
34
- const isAbsoluteUrl = itemPath.startsWith('http://') || itemPath.startsWith('https://');
35
- const normalizedItemPath = (isExplicitExternal || isAbsoluteUrl) ? itemPath : normalizePath(itemPath);
36
- const isActive = !isExplicitExternal && !isAbsoluteUrl && currentPagePath === normalizedItemPath;
37
- const isParentOfActive = !isActive && hasActiveChild(item, currentPagePath);
38
- const isCollapsible = item.children && item.collapsible;
39
- const shouldBeOpen = isParentOfActive || (isActive && item.children && item.children.length > 0);
40
- const liClasses = [];
41
- if (isActive) liClasses.push('active');
42
- if (isParentOfActive) liClasses.push('active-parent');
43
- if (isCollapsible) liClasses.push('collapsible');
44
- let liAttributes = `class="${liClasses.join(' ')}"`;
45
- if (isCollapsible) {
46
- liAttributes += ` data-nav-id="${item.path}"`;
47
- if (shouldBeOpen) liAttributes += ` aria-expanded="true"`;
48
- }
49
- let finalHref = item.path;
50
- if (!isExplicitExternal && !isAbsoluteUrl) {
51
- if (!itemPath || itemPath === '#') {
52
- finalHref = '#';
53
- } else {
54
- let cleanPath = item.path;
55
- if (cleanPath.startsWith('/')) cleanPath = cleanPath.substring(1);
56
- finalHref = relativePathToRoot + cleanPath;
57
- const offline = (typeof locals !== 'undefined' && locals.isOfflineMode) === true;
58
- if (offline) {
59
- if (finalHref.endsWith('/')) finalHref += 'index.html';
60
- else if (finalHref === './') finalHref = './index.html';
61
- else if (!finalHref.includes('#')) {
62
- const parts = finalHref.split('?')[0].split('/');
63
- const lastSegment = parts[parts.length - 1];
64
- if (!lastSegment.includes('.')) finalHref += '/index.html';
65
- }
66
- } else {
67
- if (finalHref.endsWith('/index.html')) finalHref = finalHref.substring(0, finalHref.length - 10);
68
- }
69
- }
70
- }
71
- %>
72
- <li <%- liAttributes %>>
73
- <a href="<%- finalHref %>" class="<%- isActive ? 'active' : '' %>" <%- isExplicitExternal ? 'target="_blank" rel="noopener"' : '' %>>
74
- <% if (item.icon) { %> <%- renderIcon(item.icon) %> <% } %>
75
- <span class="nav-item-title"><%= item.title %></span>
76
- <% if (isCollapsible) { %> <%- renderIcon('chevron-right', { class: 'collapse-icon' }) %> <% } %>
77
- <% if (isExplicitExternal) { %> <%- renderIcon('external-link', { class: 'nav-external-icon' }) %> <% } %>
78
- </a>
79
- <% if (item.children) { %>
80
- <ul class="submenu" style="<%= (isCollapsible && shouldBeOpen) ? 'display: block;' : 'display: none;' %>">
81
- <% renderNav(item.children); %>
82
- </ul>
83
- <% } %>
84
- </li>
85
- <% }); } renderNav(navItems); %>
86
- </ul>
87
- </nav>
@@ -1,166 +0,0 @@
1
- <%# Source file from the docmd project — https://github.com/docmd-io/docmd %>
2
-
3
- <!DOCTYPE html>
4
- <html lang="en">
5
- <head>
6
- <meta charset="UTF-8">
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
- <% if (frontmatter.components?.meta !== false) { %>
9
- <%- metaTagsHtml || '' %>
10
- <title><%= pageTitle %><% if (frontmatter.components?.siteTitle !== false) { %> : <%= siteTitle %><% } %></title>
11
- <% if (description && !(metaTagsHtml && metaTagsHtml.includes('name="description"'))) { %>
12
- <meta name="description" content="<%= description %>">
13
- <% } %>
14
- <% } %>
15
- <% if (frontmatter.components?.favicon !== false) { %>
16
- <%- faviconLinkHtml || '' %>
17
- <% } %>
18
- <% if (frontmatter.components?.themeMode !== false) { %>
19
- <script>window.DOCMD_DEFAULT_MODE = "<%= defaultMode %>";</script>
20
- <% } %>
21
- <% if (frontmatter.components?.css !== false) { %>
22
- <link rel="stylesheet" href="<%= relativePathToRoot %>assets/css/docmd-main.css">
23
- <% if (frontmatter.components?.highlight !== false) { %>
24
- <link rel="stylesheet" href="<%= relativePathToRoot %>assets/css/docmd-highlight-<%= defaultMode === 'dark' ? 'dark' : 'light' %>.css" id="highlight-theme">
25
- <% } %>
26
- <% } %>
27
- <% if (frontmatter.components?.themeMode !== false) { %>
28
- <%- themeInitScript %>
29
- <% } %>
30
- <% if (frontmatter.components?.theme !== false) { %>
31
- <%- themeCssLinkHtml || '' %>
32
- <% } %>
33
- <% if (frontmatter.components?.customCss !== false && customCssFiles && customCssFiles.length > 0) { %>
34
- <% customCssFiles.forEach(cssFile => { %>
35
- <link rel="stylesheet" href="<%= relativePathToRoot %><%- cssFile.startsWith('/') ? cssFile.substring(1) : cssFile %>">
36
- <% }); %>
37
- <% } %>
38
- <% if (frontmatter.components?.pluginStyles !== false) { %>
39
- <%- pluginStylesHtml || '' %>
40
- <% } %>
41
- <% if (frontmatter.components?.pluginHeadScripts !== false) { %>
42
- <%- pluginHeadScriptsHtml || '' %>
43
- <% } %>
44
- <% if (frontmatter.customHead) { %>
45
- <%- frontmatter.customHead %>
46
- <% } %>
47
- </head>
48
- <body<% if (frontmatter.components?.theme !== false) { %> data-theme="<%= defaultMode %>"<% } %><% if (frontmatter.bodyClass) { %> class="<%= frontmatter.bodyClass %>"<% } %> data-copy-code-enabled="<%= config.copyCode === true %>">
49
- <% if (frontmatter.components?.layout === true || frontmatter.components?.layout === 'full') { %>
50
- <div class="main-content-wrapper">
51
- <% if (frontmatter.components?.header !== false) { %>
52
- <header class="page-header">
53
- <% if (frontmatter.components?.pageTitle !== false) { %>
54
- <h1><%= pageTitle %></h1>
55
- <% } %>
56
- </header>
57
- <% } %>
58
- <main class="content-area">
59
- <div class="content-layout">
60
- <div class="main-content"><%- content %></div>
61
- <% if (frontmatter.components?.toc !== false && headings && headings.length > 0) { %>
62
- <div class="toc-sidebar">
63
- <%- include('toc', { content, headings, navigationHtml, isActivePage }) %>
64
- </div>
65
- <% } %>
66
- </div>
67
- </main>
68
- <% if (frontmatter.components?.footer !== false) { %>
69
- <footer class="page-footer">
70
- <div class="footer-content">
71
- <div class="user-footer"><%- footerHtml || '' %></div>
72
- <% if (frontmatter.components?.branding !== false) { %>
73
- <div class="branding-footer">
74
- Build with <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"></path><path d="M12 5 9.04 7.96a2.17 2.17 0 0 0 0 3.08c.82.82 2.13.85 3 .07l2.07-1.9a2.82 2.82 0 0 1 3.79 0l2.96 2.66"></path><path d="m18 15-2-2"></path><path d="m15 18-2-2"></path></svg> <a href="https://docmd.io" target="_blank" rel="noopener">docmd.</a>
75
- </div>
76
- <% } %>
77
- </div>
78
- </footer>
79
- <% } %>
80
- </div>
81
- <% } else if (frontmatter.components?.sidebar === true) { %>
82
- <aside class="sidebar">
83
- <% if (frontmatter.components?.logo !== false && logo && logo.light && logo.dark) { %>
84
- <div class="sidebar-header">
85
- <a href="<%= logo.href || (relativePathToRoot + 'index.html') %>" class="logo-link">
86
- <img src="<%= relativePathToRoot %><%- logo.light.startsWith('/') ? logo.light.substring(1) : logo.light %>" alt="<%= logo.alt || siteTitle %>" class="logo-light" <% if (logo.height) { %>style="height: <%= logo.height %>;"<% } %>>
87
- <img src="<%= relativePathToRoot %><%- logo.dark.startsWith('/') ? logo.dark.substring(1) : logo.dark %>" alt="<%= logo.alt || siteTitle %>" class="logo-dark" <% if (logo.height) { %>style="height: <%= logo.height %>;"<% } %>>
88
- </a>
89
- </div>
90
- <% } %>
91
- <% if (frontmatter.components?.navigation !== false) { %>
92
- <%- navigationHtml %>
93
- <% } %>
94
- <% if (frontmatter.components?.themeToggle !== false && theme && theme.enableModeToggle) { %>
95
- <button id="theme-toggle-button" aria-label="Toggle theme" class="theme-toggle-button">
96
- <%- renderIcon('sun', { class: 'icon-sun' }) %> <%- renderIcon('moon', { class: 'icon-moon' }) %>
97
- </button>
98
- <% } %>
99
- </aside>
100
- <div class="main-content-wrapper">
101
- <% if (frontmatter.components?.header !== false) { %>
102
- <header class="page-header">
103
- <% if (frontmatter.components?.pageTitle !== false) { %>
104
- <h1><%= pageTitle %></h1>
105
- <% } %>
106
- </header>
107
- <% } %>
108
- <main class="content-area">
109
- <div class="content-layout">
110
- <div class="main-content"><%- content %></div>
111
- <% if (frontmatter.components?.toc !== false && headings && headings.length > 0) { %>
112
- <div class="toc-sidebar">
113
- <%- include('toc', { content, headings, navigationHtml, isActivePage }) %>
114
- </div>
115
- <% } %>
116
- </div>
117
- </main>
118
- <% if (frontmatter.components?.footer !== false) { %>
119
- <footer class="page-footer">
120
- <div class="footer-content">
121
- <div class="user-footer"><%- footerHtml || '' %></div>
122
- <% if (frontmatter.components?.branding !== false) { %>
123
- <div class="branding-footer">
124
- Build with <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"></path><path d="M12 5 9.04 7.96a2.17 2.17 0 0 0 0 3.08c.82.82 2.13.85 3 .07l2.07-1.9a2.82 2.82 0 0 1 3.79 0l2.96 2.66"></path><path d="m18 15-2-2"></path><path d="m15 18-2-2"></path></svg> <a href="https://docmd.io" target="_blank" rel="noopener">docmd.</a>
125
- </div>
126
- <% } %>
127
- </div>
128
- </footer>
129
- <% } %>
130
- </div>
131
- <% } else { %>
132
- <%- content %>
133
- <% } %>
134
-
135
- <% if (frontmatter.components?.scripts === true) { %>
136
- <% if (frontmatter.components?.mainScripts === true) { %>
137
- <script>window.DOCMD_ROOT = "<%= relativePathToRoot %>";</script>
138
- <script src="<%= relativePathToRoot %>assets/js/docmd-main.js"></script>
139
- <% } %>
140
-
141
- <% if (frontmatter.components?.lightbox === true && frontmatter.components?.mainScripts === true) { %>
142
- <script src="<%= relativePathToRoot %>assets/js/docmd-image-lightbox.js"></script>
143
- <% } %>
144
-
145
- <!-- Mermaid & MiniSearch from CDN -->
146
- <script src="https://cdn.jsdelivr.net/npm/mermaid@11.12.2/dist/mermaid.min.js"></script>
147
- <script src="<%= relativePathToRoot %>assets/js/docmd-mermaid.js"></script>
148
-
149
- <script src="https://cdn.jsdelivr.net/npm/minisearch@7.2.0/dist/umd/index.min.js"></script>
150
- <script src="<%= relativePathToRoot %>assets/js/docmd-search.js"></script>
151
-
152
- <% if (frontmatter.components?.customJs === true && customJsFiles && customJsFiles.length > 0) { %>
153
- <% customJsFiles.forEach(jsFile => { %>
154
- <script src="<%= relativePathToRoot %><%- jsFile.startsWith('/') ? jsFile.substring(1) : jsFile %>"></script>
155
- <% }); %>
156
- <% } %>
157
-
158
- <% if (frontmatter.components?.pluginBodyScripts === true) { %>
159
- <%- pluginBodyScriptsHtml || '' %>
160
- <% } %>
161
- <% } %>
162
- <% if (frontmatter.customScripts) { %>
163
- <%- frontmatter.customScripts %>
164
- <% } %>
165
- </body>
166
- </html>
@@ -1,30 +0,0 @@
1
- /* Source file from the docmd project — https://github.com/docmd-io/docmd */
2
-
3
- (function() {
4
- try {
5
- var localValue = localStorage.getItem('docmd-theme');
6
- var configValue = window.DOCMD_DEFAULT_MODE || 'light';
7
- var theme = localValue ? localValue : configValue;
8
-
9
- // Set HTML Attribute
10
- document.documentElement.setAttribute('data-theme', theme);
11
-
12
- // Resolve 'system' to actual mode for Highlight.js
13
- var effectiveTheme = theme;
14
- if (theme === 'system') {
15
- effectiveTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
16
- }
17
-
18
- // Handle Highlight.js Theme
19
- var highlightLink = document.getElementById('highlight-theme');
20
- if (highlightLink) {
21
- var baseHref = highlightLink.getAttribute('data-base-href');
22
- if (baseHref) {
23
- // Force load the resolved theme (light/dark)
24
- highlightLink.href = baseHref + 'docmd-highlight-' + effectiveTheme + '.css';
25
- }
26
- }
27
- } catch (e) {
28
- console.error('Theme init failed', e);
29
- }
30
- })();
@@ -1,38 +0,0 @@
1
- <%# Source file from the docmd project — https://github.com/docmd-io/docmd %>
2
-
3
- <%
4
- function decodeHtmlEntities(html) {
5
- return html.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&nbsp;/g, ' ');
6
- }
7
- const shouldShowToc = typeof isActivePage !== 'undefined' ? isActivePage :
8
- (typeof navigationHtml !== 'undefined' && navigationHtml && navigationHtml.includes('class="active"'));
9
-
10
- if (shouldShowToc && !frontmatter?.toc || frontmatter?.toc !== 'false') {
11
- let tocHeadings = [];
12
- if (headings && headings.length > 0) {
13
- tocHeadings = headings.filter(h => h.level >= 2 && h.level <= 4);
14
- } else if (content) {
15
- const headingRegex = /<h([2-4])[^>]*?(?:id="([^"]*)")?[^>]*?>([\s\S]*?)<\/h\1>/g;
16
- let match;
17
- let contentStr = content.toString();
18
- while ((match = headingRegex.exec(contentStr)) !== null) {
19
- const level = parseInt(match[1], 10);
20
- let id = match[2];
21
- const text = decodeHtmlEntities(match[3].replace(/<\/?\w+[^>]*>/g, '')); // Stripped tags
22
- if (!id) id = text.toLowerCase().replace(/\s+/g, '-').replace(/[^\w-]/g, '').replace(/--+/g, '-').replace(/^-+|-+$/g, '');
23
- tocHeadings.push({ id, level, text });
24
- }
25
- }
26
- if (tocHeadings.length > 1) {
27
- %>
28
- <div class="toc-container">
29
- <h2 class="toc-title">On This Page<span class="mobile-view toc-menu-button float-right"><%- renderIcon("chevrons-down-up") %></span></h2>
30
- <ul class="toc-list">
31
- <% tocHeadings.forEach(heading => { %>
32
- <li class="toc-item toc-level-<%= heading.level %>">
33
- <a href="#<%= heading.id %>" class="toc-link"><%- heading.text %></a>
34
- </li>
35
- <% }); %>
36
- </ul>
37
- </div>
38
- <% } } %>