@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.
- package/README.md +15 -160
- package/bin/docmd.js +6 -69
- package/package.json +6 -79
- package/bin/postinstall.js +0 -14
- package/src/assets/css/docmd-highlight-dark.css +0 -86
- package/src/assets/css/docmd-highlight-light.css +0 -86
- package/src/assets/css/docmd-main.css +0 -1736
- package/src/assets/css/docmd-theme-retro.css +0 -867
- package/src/assets/css/docmd-theme-ruby.css +0 -629
- package/src/assets/css/docmd-theme-sky.css +0 -617
- package/src/assets/favicon.ico +0 -0
- package/src/assets/images/docmd-logo-dark.png +0 -0
- package/src/assets/images/docmd-logo-light.png +0 -0
- package/src/assets/js/docmd-image-lightbox.js +0 -74
- package/src/assets/js/docmd-main.js +0 -260
- package/src/assets/js/docmd-mermaid.js +0 -205
- package/src/assets/js/docmd-search.js +0 -218
- package/src/commands/build.js +0 -237
- package/src/commands/dev.js +0 -352
- package/src/commands/init.js +0 -277
- package/src/commands/live.js +0 -145
- package/src/core/asset-manager.js +0 -72
- package/src/core/config-loader.js +0 -58
- package/src/core/config-validator.js +0 -80
- package/src/core/file-processor.js +0 -103
- package/src/core/fs-utils.js +0 -40
- package/src/core/html-generator.js +0 -184
- package/src/core/icon-renderer.js +0 -106
- package/src/core/logger.js +0 -21
- package/src/core/markdown/containers.js +0 -94
- package/src/core/markdown/renderers.js +0 -90
- package/src/core/markdown/rules.js +0 -402
- package/src/core/markdown/setup.js +0 -113
- package/src/core/navigation-helper.js +0 -74
- package/src/index.js +0 -12
- package/src/live/core.js +0 -67
- package/src/live/index.html +0 -216
- package/src/live/live.css +0 -256
- package/src/live/shims.js +0 -1
- package/src/plugins/analytics.js +0 -48
- package/src/plugins/seo.js +0 -107
- package/src/plugins/sitemap.js +0 -127
- package/src/templates/layout.ejs +0 -187
- package/src/templates/navigation.ejs +0 -87
- package/src/templates/no-style.ejs +0 -166
- package/src/templates/partials/theme-init.js +0 -30
- package/src/templates/toc.ejs +0 -38
package/src/plugins/sitemap.js
DELETED
|
@@ -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 };
|
package/src/templates/layout.ejs
DELETED
|
@@ -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
|
-
})();
|
package/src/templates/toc.ejs
DELETED
|
@@ -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(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'").replace(/ /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
|
-
<% } } %>
|