@mgks/docmd 0.3.2 → 0.3.3
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 +5 -1
- package/package.json +28 -24
- package/.gitattributes +0 -2
- package/.github/CODE_OF_CONDUCT.md +0 -48
- package/.github/CONTRIBUTING.md +0 -129
- package/.github/FUNDING.yml +0 -15
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -58
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -27
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -16
- package/.github/SECURITY.md +0 -18
- package/.github/workflows/deploy-docmd.yml +0 -45
- package/.github/workflows/npm-publish.yml +0 -49
- package/assets/css/welcome.css +0 -6
- package/assets/images/preview-dark-1.webp +0 -0
- package/assets/images/preview-dark-2.webp +0 -0
- package/assets/images/preview-dark-3.webp +0 -0
- package/assets/images/preview-dark-welcome.png +0 -0
- package/assets/images/preview-light-1.webp +0 -0
- package/assets/images/preview-light-2.webp +0 -0
- package/assets/images/preview-light-3.webp +0 -0
- package/docs/cli-commands.md +0 -108
- package/docs/comparison.md +0 -56
- package/docs/configuration.md +0 -289
- package/docs/content/containers/buttons.md +0 -88
- package/docs/content/containers/callouts.md +0 -154
- package/docs/content/containers/cards.md +0 -93
- package/docs/content/containers/changelogs.md +0 -128
- package/docs/content/containers/collapsible.md +0 -89
- package/docs/content/containers/index.md +0 -35
- package/docs/content/containers/nested-containers.md +0 -329
- package/docs/content/containers/steps.md +0 -175
- package/docs/content/containers/tabs.md +0 -228
- package/docs/content/custom-containers.md +0 -24
- package/docs/content/frontmatter.md +0 -84
- package/docs/content/images.md +0 -205
- package/docs/content/index.md +0 -19
- package/docs/content/markdown-syntax.md +0 -309
- package/docs/content/mermaid.md +0 -723
- package/docs/content/no-style-example.md +0 -112
- package/docs/content/no-style-pages.md +0 -226
- package/docs/content/search.md +0 -68
- package/docs/contributing.md +0 -101
- package/docs/deployment.md +0 -120
- package/docs/getting-started/basic-usage.md +0 -89
- package/docs/getting-started/index.md +0 -21
- package/docs/getting-started/installation.md +0 -75
- package/docs/index.md +0 -168
- package/docs/overview.md +0 -63
- package/docs/plugins/analytics.md +0 -75
- package/docs/plugins/index.md +0 -70
- package/docs/plugins/seo.md +0 -127
- package/docs/plugins/sitemap.md +0 -87
- package/docs/recipes/custom-fonts.md +0 -43
- package/docs/recipes/favicon.md +0 -38
- package/docs/recipes/index.md +0 -12
- package/docs/recipes/landing-page.md +0 -46
- package/docs/theming/assets-management.md +0 -126
- package/docs/theming/available-themes.md +0 -77
- package/docs/theming/custom-css-js.md +0 -79
- package/docs/theming/icons.md +0 -92
- package/docs/theming/index.md +0 -19
- package/docs/theming/light-dark-mode.md +0 -114
- package/src/assets/css/docmd-highlight-dark.css +0 -1
- package/src/assets/css/docmd-highlight-light.css +0 -1
- package/src/assets/css/docmd-main.css +0 -1627
- package/src/assets/css/docmd-theme-retro.css +0 -868
- package/src/assets/css/docmd-theme-ruby.css +0 -629
- package/src/assets/css/docmd-theme-sky.css +0 -618
- 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/images/docmd-logo.png +0 -0
- package/src/assets/images/docmd-preview.png +0 -0
- package/src/assets/js/docmd-image-lightbox.js +0 -74
- package/src/assets/js/docmd-main.js +0 -285
- package/src/assets/js/docmd-mermaid.js +0 -205
- package/src/assets/js/docmd-search.js +0 -218
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
// Source file from the docmd project — https://github.com/mgks/docmd
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* Client-side search functionality for docmd
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
(function() {
|
|
8
|
-
let miniSearch = null;
|
|
9
|
-
let isIndexLoaded = false;
|
|
10
|
-
let selectedIndex = -1; // Track keyboard selection
|
|
11
|
-
|
|
12
|
-
const searchModal = document.getElementById('docmd-search-modal');
|
|
13
|
-
const searchInput = document.getElementById('docmd-search-input');
|
|
14
|
-
const searchResults = document.getElementById('docmd-search-results');
|
|
15
|
-
|
|
16
|
-
const ROOT_PATH = window.DOCMD_ROOT || './';
|
|
17
|
-
|
|
18
|
-
if (!searchModal) return;
|
|
19
|
-
|
|
20
|
-
const emptyStateHtml = '<div class="search-initial">Type to start searching...</div>';
|
|
21
|
-
|
|
22
|
-
// 1. Open/Close Logic
|
|
23
|
-
function openSearch() {
|
|
24
|
-
searchModal.style.display = 'flex';
|
|
25
|
-
searchInput.focus();
|
|
26
|
-
|
|
27
|
-
if (!searchInput.value.trim()) {
|
|
28
|
-
searchResults.innerHTML = emptyStateHtml;
|
|
29
|
-
selectedIndex = -1;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (!isIndexLoaded) loadIndex();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function closeSearch() {
|
|
36
|
-
searchModal.style.display = 'none';
|
|
37
|
-
selectedIndex = -1; // Reset selection
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// 2. Keyboard Navigation & Shortcuts
|
|
41
|
-
document.addEventListener('keydown', (e) => {
|
|
42
|
-
// Open: Cmd+K / Ctrl+K
|
|
43
|
-
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
|
44
|
-
e.preventDefault();
|
|
45
|
-
if (searchModal.style.display === 'flex') {
|
|
46
|
-
closeSearch();
|
|
47
|
-
} else {
|
|
48
|
-
openSearch();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Context: Only handle these if search is open
|
|
53
|
-
if (searchModal.style.display === 'flex') {
|
|
54
|
-
const items = searchResults.querySelectorAll('.search-result-item');
|
|
55
|
-
|
|
56
|
-
if (e.key === 'Escape') {
|
|
57
|
-
e.preventDefault();
|
|
58
|
-
closeSearch();
|
|
59
|
-
}
|
|
60
|
-
else if (e.key === 'ArrowDown') {
|
|
61
|
-
e.preventDefault();
|
|
62
|
-
if (items.length === 0) return;
|
|
63
|
-
selectedIndex = (selectedIndex + 1) % items.length;
|
|
64
|
-
updateSelection(items);
|
|
65
|
-
}
|
|
66
|
-
else if (e.key === 'ArrowUp') {
|
|
67
|
-
e.preventDefault();
|
|
68
|
-
if (items.length === 0) return;
|
|
69
|
-
selectedIndex = (selectedIndex - 1 + items.length) % items.length;
|
|
70
|
-
updateSelection(items);
|
|
71
|
-
}
|
|
72
|
-
else if (e.key === 'Enter') {
|
|
73
|
-
e.preventDefault();
|
|
74
|
-
if (selectedIndex >= 0 && items[selectedIndex]) {
|
|
75
|
-
items[selectedIndex].click();
|
|
76
|
-
} else if (items.length > 0) {
|
|
77
|
-
// If nothing selected but results exist, click the first one on Enter
|
|
78
|
-
items[0].click();
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
function updateSelection(items) {
|
|
85
|
-
items.forEach((item, index) => {
|
|
86
|
-
if (index === selectedIndex) {
|
|
87
|
-
item.classList.add('selected');
|
|
88
|
-
item.scrollIntoView({ block: 'nearest' });
|
|
89
|
-
} else {
|
|
90
|
-
item.classList.remove('selected');
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Click handlers
|
|
96
|
-
document.querySelectorAll('.docmd-search-trigger').forEach(btn => {
|
|
97
|
-
btn.addEventListener('click', openSearch);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
searchModal.addEventListener('click', (e) => {
|
|
101
|
-
if (e.target === searchModal) closeSearch();
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// 3. Index Loading Logic
|
|
105
|
-
async function loadIndex() {
|
|
106
|
-
try {
|
|
107
|
-
|
|
108
|
-
const indexUrl = `${ROOT_PATH}search-index.json`;
|
|
109
|
-
const response = await fetch(indexUrl);
|
|
110
|
-
if (!response.ok) throw new Error(response.status);
|
|
111
|
-
|
|
112
|
-
const jsonString = await response.text();
|
|
113
|
-
|
|
114
|
-
miniSearch = MiniSearch.loadJSON(jsonString, {
|
|
115
|
-
fields: ['title', 'headings', 'text'],
|
|
116
|
-
storeFields: ['title', 'id', 'text'],
|
|
117
|
-
searchOptions: {
|
|
118
|
-
fuzzy: 0.2,
|
|
119
|
-
prefix: true,
|
|
120
|
-
boost: { title: 2, headings: 1.5 }
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
isIndexLoaded = true;
|
|
125
|
-
// console.log('Search index loaded');
|
|
126
|
-
|
|
127
|
-
if (searchInput.value.trim()) {
|
|
128
|
-
searchInput.dispatchEvent(new Event('input'));
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
} catch (e) {
|
|
132
|
-
console.error('Failed to load search index', e);
|
|
133
|
-
searchResults.innerHTML = '<div class="search-error">Failed to load search index.</div>';
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Helper: Snippets (Same as before)
|
|
138
|
-
function getSnippet(text, query) {
|
|
139
|
-
if (!text) return '';
|
|
140
|
-
const terms = query.split(/\s+/).filter(t => t.length > 2);
|
|
141
|
-
const lowerText = text.toLowerCase();
|
|
142
|
-
let bestIndex = -1;
|
|
143
|
-
|
|
144
|
-
for (const term of terms) {
|
|
145
|
-
const idx = lowerText.indexOf(term.toLowerCase());
|
|
146
|
-
if (idx >= 0) { bestIndex = idx; break; }
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const contextSize = 60;
|
|
150
|
-
let start = 0;
|
|
151
|
-
let end = 120;
|
|
152
|
-
|
|
153
|
-
if (bestIndex >= 0) {
|
|
154
|
-
start = Math.max(0, bestIndex - contextSize);
|
|
155
|
-
end = Math.min(text.length, bestIndex + contextSize);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
let snippet = text.substring(start, end);
|
|
159
|
-
if (start > 0) snippet = '...' + snippet;
|
|
160
|
-
if (end < text.length) snippet = snippet + '...';
|
|
161
|
-
|
|
162
|
-
const safeTerms = terms.map(t => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
|
|
163
|
-
if (safeTerms) {
|
|
164
|
-
const highlightRegex = new RegExp(`(${safeTerms})`, 'gi');
|
|
165
|
-
snippet = snippet.replace(highlightRegex, '<mark>$1</mark>');
|
|
166
|
-
}
|
|
167
|
-
return snippet;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// 4. Search Execution
|
|
171
|
-
searchInput.addEventListener('input', (e) => {
|
|
172
|
-
const query = e.target.value.trim();
|
|
173
|
-
selectedIndex = -1; // Reset selection on new input
|
|
174
|
-
|
|
175
|
-
if (!query) {
|
|
176
|
-
searchResults.innerHTML = emptyStateHtml;
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (!isIndexLoaded) return;
|
|
181
|
-
|
|
182
|
-
const results = miniSearch.search(query);
|
|
183
|
-
renderResults(results, query);
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
function renderResults(results, query) {
|
|
187
|
-
if (results.length === 0) {
|
|
188
|
-
searchResults.innerHTML = '<div class="search-no-results">No results found.</div>';
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const html = results.slice(0, 10).map((result, index) => {
|
|
193
|
-
const snippet = getSnippet(result.text, query);
|
|
194
|
-
|
|
195
|
-
const linkHref = `${ROOT_PATH}${result.id}`;
|
|
196
|
-
|
|
197
|
-
// Add data-index for mouse interaction tracking if needed
|
|
198
|
-
return `
|
|
199
|
-
<a href="${linkHref}" class="search-result-item" data-index="${index}" onclick="window.closeDocmdSearch()">
|
|
200
|
-
<div class="search-result-title">${result.title}</div>
|
|
201
|
-
<div class="search-result-preview">${snippet}</div>
|
|
202
|
-
</a>
|
|
203
|
-
`;
|
|
204
|
-
}).join('');
|
|
205
|
-
|
|
206
|
-
searchResults.innerHTML = html;
|
|
207
|
-
|
|
208
|
-
// Optional: Allow mouse hover to update selectedIndex
|
|
209
|
-
searchResults.querySelectorAll('.search-result-item').forEach((item, idx) => {
|
|
210
|
-
item.addEventListener('mouseenter', () => {
|
|
211
|
-
selectedIndex = idx;
|
|
212
|
-
updateSelection(searchResults.querySelectorAll('.search-result-item'));
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
window.closeDocmdSearch = closeSearch;
|
|
218
|
-
})();
|