@kenjura/ursa 0.32.0 → 0.33.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/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 0.33
2
+ 2025-12-10
3
+
4
+ - Fixed the broke-ass menu
5
+
1
6
  # 0.32
2
7
  2025-12-10
3
8
 
package/meta/menu.js CHANGED
@@ -257,6 +257,22 @@ document.addEventListener('DOMContentLoaded', () => {
257
257
  caret.addEventListener('click', toggleExpand);
258
258
  }
259
259
 
260
+ // If the link points to the current page, clicking it should toggle instead of navigate
261
+ if (link) {
262
+ link.addEventListener('click', (e) => {
263
+ const linkHref = link.getAttribute('href');
264
+ const currentHref = window.location.pathname;
265
+ const normalizedLinkHref = linkHref.replace(/\/index\.html$/, '').replace(/\.html$/, '');
266
+ const normalizedCurrentHref = currentHref.replace(/\/index\.html$/, '').replace(/\.html$/, '');
267
+
268
+ if (normalizedLinkHref === normalizedCurrentHref) {
269
+ // Already on this page - toggle instead of navigate
270
+ toggleExpand(e);
271
+ }
272
+ // Otherwise, let the default navigation happen
273
+ });
274
+ }
275
+
260
276
  row.addEventListener('click', (e) => {
261
277
  if (!e.target.closest('a')) {
262
278
  toggleExpand(e);
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@kenjura/ursa",
3
3
  "author": "Andrew London <andrew@kenjura.com>",
4
4
  "type": "module",
5
- "version": "0.32.0",
5
+ "version": "0.33.0",
6
6
  "description": "static site generator from MD/wikitext/YML",
7
7
  "main": "lib/index.js",
8
8
  "bin": {
@@ -137,10 +137,13 @@ function buildMenuData(tree, source, validPaths, parentPath = '') {
137
137
  let rawHref = null;
138
138
  if (hasChildren) {
139
139
  if (hasIndexFile(item.path)) {
140
- rawHref = `/${relativePath}/index.html`;
140
+ // Construct proper path - relativePath already starts with /
141
+ const cleanPath = relativePath.startsWith('/') ? relativePath : '/' + relativePath;
142
+ rawHref = `${cleanPath}/index.html`.replace(/\/\//g, '/');
141
143
  }
142
144
  } else {
143
- rawHref = `/${relativePath.replace(ext, '')}`;
145
+ const cleanPath = relativePath.startsWith('/') ? relativePath : '/' + relativePath;
146
+ rawHref = cleanPath.replace(ext, '');
144
147
  }
145
148
 
146
149
  // Resolve the href and check if target exists
@@ -173,7 +176,9 @@ function buildMenuData(tree, source, validPaths, parentPath = '') {
173
176
  }
174
177
 
175
178
  export async function getAutomenu(source, validPaths) {
176
- const tree = dirTree(source);
179
+ const tree = dirTree(source, {
180
+ exclude: /[\/\\]\.|node_modules/, // Exclude hidden folders (starting with .) and node_modules
181
+ });
177
182
  const menuData = buildMenuData(tree, source, validPaths);
178
183
 
179
184
  // Add home item with resolved href
@@ -205,10 +210,9 @@ function renderMenuLevel(items, level) {
205
210
  const hasChildrenClass = item.hasChildren ? ' has-children' : '';
206
211
  const hasChildrenIndicator = item.hasChildren ? '<span class="menu-more">⋯</span>' : '';
207
212
  const inactiveClass = item.inactive ? ' inactive' : '';
208
- const debugText = item.debug ? ` [DEBUG: ${item.debug}]` : '';
209
213
 
210
214
  const labelHtml = item.href
211
- ? `<a href="${item.href}" class="menu-label${inactiveClass}">${item.label}${debugText}</a>`
215
+ ? `<a href="${item.href}" class="menu-label${inactiveClass}">${item.label}</a>`
212
216
  : `<span class="menu-label">${item.label}</span>`;
213
217
 
214
218
  return `
@@ -103,13 +103,14 @@ export async function generate({
103
103
 
104
104
  // read all articles, process them, copy them to build
105
105
  const articleExtensions = /\.(md|txt|yml)/;
106
+ const hiddenOrSystemDirs = /[\/\\]\.(?!\.)|[\/\\]node_modules[\/\\]/; // Matches hidden folders (starting with .) or node_modules
106
107
  const allSourceFilenamesThatAreArticles = allSourceFilenames.filter(
107
- (filename) => filename.match(articleExtensions)
108
+ (filename) => filename.match(articleExtensions) && !filename.match(hiddenOrSystemDirs)
108
109
  );
109
- const allSourceFilenamesThatAreDirectories = await filterAsync(
110
+ const allSourceFilenamesThatAreDirectories = (await filterAsync(
110
111
  allSourceFilenames,
111
112
  (filename) => isDirectory(filename)
112
- );
113
+ )).filter((filename) => !filename.match(hiddenOrSystemDirs));
113
114
 
114
115
  // Build set of valid internal paths for link validation (must be before menu)
115
116
  const validPaths = buildValidPaths(allSourceFilenamesThatAreArticles, source);