@mgks/docmd 0.3.0 → 0.3.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.
@@ -68,6 +68,41 @@ function initializeCollapsibleNav() {
68
68
  });
69
69
  }
70
70
 
71
+ // --- Mobile Menu Logic ---
72
+ function initializeMobileMenus() {
73
+ // 1. Sidebar Toggle
74
+ const sidebarBtn = document.querySelector('.sidebar-menu-button');
75
+ const sidebar = document.querySelector('.sidebar');
76
+
77
+ if (sidebarBtn && sidebar) {
78
+ sidebarBtn.addEventListener('click', (e) => {
79
+ e.stopPropagation(); // Prevent bubbling
80
+ sidebar.classList.toggle('mobile-expanded');
81
+ });
82
+ }
83
+
84
+ // 2. TOC Toggle
85
+ const tocBtn = document.querySelector('.toc-menu-button');
86
+ const tocContainer = document.querySelector('.toc-container');
87
+ // Also allow clicking the title text to toggle
88
+ const tocTitle = document.querySelector('.toc-title');
89
+
90
+ const toggleToc = (e) => {
91
+ // Only engage on mobile view (check if button is visible)
92
+ if (window.getComputedStyle(tocBtn).display === 'none') return;
93
+
94
+ e.stopPropagation();
95
+ tocContainer.classList.toggle('mobile-expanded');
96
+ };
97
+
98
+ if (tocBtn && tocContainer) {
99
+ tocBtn.addEventListener('click', toggleToc);
100
+ if (tocTitle) {
101
+ tocTitle.addEventListener('click', toggleToc);
102
+ }
103
+ }
104
+ }
105
+
71
106
  // --- Sidebar Scroll Preservation ---
72
107
  function initializeSidebarScroll() {
73
108
  const sidebar = document.querySelector('.sidebar');
@@ -245,5 +280,6 @@ document.addEventListener('DOMContentLoaded', () => {
245
280
  initializeTabs();
246
281
  initializeCopyCodeButtons();
247
282
  initializeCollapsibleNav();
283
+ initializeMobileMenus();
248
284
  initializeSidebarScroll();
249
285
  });
@@ -13,6 +13,8 @@
13
13
  const searchInput = document.getElementById('docmd-search-input');
14
14
  const searchResults = document.getElementById('docmd-search-results');
15
15
 
16
+ const ROOT_PATH = window.DOCMD_ROOT || './';
17
+
16
18
  if (!searchModal) return;
17
19
 
18
20
  const emptyStateHtml = '<div class="search-initial">Type to start searching...</div>';
@@ -102,8 +104,9 @@
102
104
  // 3. Index Loading Logic
103
105
  async function loadIndex() {
104
106
  try {
105
- const basePath = document.documentElement.getAttribute('data-base-url') || '/';
106
- const response = await fetch(`${basePath}search-index.json`);
107
+
108
+ const indexUrl = `${ROOT_PATH}search-index.json`;
109
+ const response = await fetch(indexUrl);
107
110
  if (!response.ok) throw new Error(response.status);
108
111
 
109
112
  const jsonString = await response.text();
@@ -188,9 +191,12 @@
188
191
 
189
192
  const html = results.slice(0, 10).map((result, index) => {
190
193
  const snippet = getSnippet(result.text, query);
194
+
195
+ const linkHref = `${ROOT_PATH}${result.id}`;
196
+
191
197
  // Add data-index for mouse interaction tracking if needed
192
198
  return `
193
- <a href="/${result.id}" class="search-result-item" data-index="${index}" onclick="window.closeDocmdSearch()">
199
+ <a href="${linkHref}" class="search-result-item" data-index="${index}" onclick="window.closeDocmdSearch()">
194
200
  <div class="search-result-title">${result.title}</div>
195
201
  <div class="search-result-preview">${snippet}</div>
196
202
  </a>
@@ -6,7 +6,8 @@ const chalk = require('chalk');
6
6
  const KNOWN_KEYS = [
7
7
  'siteTitle', 'siteUrl', 'srcDir', 'outputDir', 'logo',
8
8
  'sidebar', 'theme', 'customJs', 'autoTitleFromH1',
9
- 'copyCode', 'plugins', 'navigation', 'footer', 'sponsor', 'favicon'
9
+ 'copyCode', 'plugins', 'navigation', 'footer', 'sponsor', 'favicon',
10
+ 'search', 'minify', 'editLink', 'pageNavigation'
10
11
  ];
11
12
 
12
13
  // Common typos mapping
@@ -13,14 +13,19 @@
13
13
 
14
14
  <%- faviconLinkHtml || '' %> <%# Favicon %>
15
15
 
16
- <%- themeInitScript %>
17
-
18
- <link rel="stylesheet" href="<%= relativePathToRoot %>assets/css/docmd-main.css">
16
+ <!-- Define Default Mode (Variable for script) -->
17
+ <script>
18
+ window.DOCMD_DEFAULT_MODE = "<%= defaultMode %>";
19
+ </script>
19
20
 
21
+ <!-- Highlight.js Theme -->
20
22
  <% if (config.theme?.codeHighlight !== false) { %>
21
23
  <link rel="stylesheet" id="highlight-theme" href="<%= relativePathToRoot %>assets/css/docmd-highlight-<%= defaultMode === 'dark' ? 'dark' : 'light' %>.css" data-base-href="<%= relativePathToRoot %>assets/css/">
22
24
  <% } %>
23
25
 
26
+ <!-- Main Theme -->
27
+ <link rel="stylesheet" href="<%= relativePathToRoot %>assets/css/docmd-main.css">
28
+
24
29
  <%- themeCssLinkHtml || '' %> <%# For theme.name specific CSS %>
25
30
 
26
31
  <% (customCssFiles || []).forEach(cssFile => { %>
@@ -29,10 +34,13 @@
29
34
 
30
35
  <%- pluginStylesHtml || '' %> <%# Plugin specific CSS %>
31
36
 
32
- <%- pluginHeadScriptsHtml || '' %> <%# Plugin specific head scripts (e.g., Analytics) %>
37
+ <!-- This checks storage and updates HTML attr + Highlight CSS before final paint -->
38
+ <%- themeInitScript %>
39
+
40
+ <%- pluginHeadScriptsHtml || '' %> <%# Plugin specific head scripts %>
33
41
  </head>
34
42
  <body class="<%= sidebarConfig.collapsible ? 'sidebar-collapsible' : 'sidebar-not-collapsible' %>"
35
- data-theme="<%= defaultMode %>" data-default-collapsed="<%= sidebarConfig.defaultCollapsed %>"
43
+ data-default-collapsed="<%= sidebarConfig.defaultCollapsed %>"
36
44
  data-copy-code-enabled="<%= config.copyCode === true %>">
37
45
  <aside class="sidebar">
38
46
  <div class="sidebar-header">
@@ -44,11 +52,13 @@
44
52
  <% } else { %>
45
53
  <h1><a href="<%= relativePathToRoot %>index.html"><%= siteTitle %></a></h1>
46
54
  <% } %>
55
+ <span class="mobile-view sidebar-menu-button float-right">
56
+ <%- renderIcon("ellipsis-vertical") %>
57
+ </span>
47
58
  </div>
48
59
  <%- navigationHtml %>
49
60
  <% if (theme && theme.enableModeToggle && theme.positionMode !== 'top') { %>
50
61
  <button id="theme-toggle-button" aria-label="Toggle theme" class="theme-toggle-button">
51
- <%# renderIcon is available in the global EJS scope from html-generator %>
52
62
  <%- renderIcon('sun', { class: 'icon-sun' }) %>
53
63
  <%- renderIcon('moon', { class: 'icon-moon' }) %>
54
64
  </button>
@@ -174,6 +184,10 @@
174
184
  </div>
175
185
  <% } %>
176
186
 
187
+ <script>
188
+ window.DOCMD_ROOT = "<%= relativePathToRoot %>";
189
+ </script>
190
+
177
191
  <script src="<%= relativePathToRoot %>assets/js/docmd-main.js"></script>
178
192
 
179
193
  <% if (config.search !== false) { %>
@@ -17,7 +17,7 @@
17
17
  <% } %>
18
18
 
19
19
  <% if (frontmatter.components?.themeMode !== false) { %>
20
- <%- themeInitScript %>
20
+ <script>window.DOCMD_DEFAULT_MODE = "<%= defaultMode %>";</script>
21
21
  <% } %>
22
22
 
23
23
  <% if (frontmatter.components?.css !== false) { %>
@@ -27,6 +27,10 @@
27
27
  <% } %>
28
28
  <% } %>
29
29
 
30
+ <% if (frontmatter.components?.themeMode !== false) { %>
31
+ <%- themeInitScript %>
32
+ <% } %>
33
+
30
34
  <% if (frontmatter.components?.theme !== false) { %>
31
35
  <%- themeCssLinkHtml || '' %>
32
36
  <% } %>
@@ -5,22 +5,26 @@
5
5
  */
6
6
 
7
7
  (function() {
8
- try {
9
- const storedTheme = localStorage.getItem('docmd-theme');
10
- if (storedTheme) {
11
- document.documentElement.setAttribute('data-theme', storedTheme);
12
-
13
- // Also update highlight CSS link to match the stored theme
14
- const highlightThemeLink = document.getElementById('highlight-theme');
15
- if (highlightThemeLink) {
16
- const baseHref = highlightThemeLink.getAttribute('data-base-href');
17
- if (baseHref) {
18
- const newHref = baseHref + `docmd-highlight-${storedTheme}.css`;
19
- highlightThemeLink.setAttribute('href', newHref);
20
- }
21
- }
8
+ try {
9
+ // Determine Theme
10
+ var localValue = localStorage.getItem('docmd-theme');
11
+ var configValue = window.DOCMD_DEFAULT_MODE || 'light';
12
+ var theme = localValue ? localValue : configValue;
13
+
14
+ // Set HTML Attribute (for main CSS variables)
15
+ document.documentElement.setAttribute('data-theme', theme);
16
+
17
+ // Handle Highlight.js Theme (if present)
18
+ var highlightLink = document.getElementById('highlight-theme');
19
+ if (highlightLink) {
20
+ var baseHref = highlightLink.getAttribute('data-base-href');
21
+ // Check if the current href matches the desired theme
22
+ // If not, swap it immediately before the browser renders code blocks
23
+ if (baseHref && !highlightLink.href.includes('docmd-highlight-' + theme)) {
24
+ highlightLink.href = baseHref + 'docmd-highlight-' + theme + '.css';
22
25
  }
23
- } catch (e) {
24
- console.error('Error applying theme from localStorage', e);
25
26
  }
27
+ } catch (e) {
28
+ console.error('Theme init failed', e);
29
+ }
26
30
  })();
@@ -54,7 +54,7 @@ if (shouldShowToc && !frontmatter?.toc || frontmatter?.toc !== 'false') {
54
54
  if (tocHeadings.length > 1) {
55
55
  %>
56
56
  <div class="toc-container">
57
- <h2 class="toc-title">On This Page</h2>
57
+ <h2 class="toc-title">On This Page<span class="mobile-view toc-menu-button float-right"><%- renderIcon("chevrons-down-up") %></span></h2>
58
58
  <ul class="toc-list">
59
59
  <% tocHeadings.forEach(heading => { %>
60
60
  <li class="toc-item toc-level-<%= heading.level %>">