scavold 0.2.0 → 0.2.1

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
@@ -9,6 +9,14 @@ one offered; a patch release does not.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.2.1] — 2026-10-04
13
+
14
+ ### Fixed
15
+
16
+ - Menus and breadcrumbs no longer link a folder without an `index.md` — there is no page
17
+ to go to, and the link was dead. Such a folder is named as text above its pages where a
18
+ menu shows them, left out where a menu does not, and named as text in a breadcrumb.
19
+
12
20
  ## [0.2.0] — 2026-10-04
13
21
 
14
22
  ### Added
@@ -361,7 +369,8 @@ First published release. Version `0.1.0` existed in-tree only.
361
369
  - Only images are processed out of `media_folder`; other file types (video, documents)
362
370
  are never copied into the build output and have to live in the static folder.
363
371
 
364
- [Unreleased]: https://gitlab.com/cratly/scavold/-/compare/v0.2.0...main
372
+ [Unreleased]: https://gitlab.com/cratly/scavold/-/compare/v0.2.1...main
373
+ [0.2.1]: https://gitlab.com/cratly/scavold/-/compare/v0.2.0...v0.2.1
365
374
  [0.2.0]: https://gitlab.com/cratly/scavold/-/compare/v0.2.0-rc.12...v0.2.0
366
375
  [0.2.0-rc.12]: https://gitlab.com/cratly/scavold/-/compare/v0.2.0-rc.11...v0.2.0-rc.12
367
376
  [0.2.0-rc.11]: https://gitlab.com/cratly/scavold/-/compare/v0.2.0-rc.10...v0.2.0-rc.11
package/COMPONENTS.md CHANGED
@@ -28,6 +28,9 @@ Each item in the trail carries `.active` (all ancestor items) and `.current` (th
28
28
  last item, if the current page is included). This makes it straightforward to style
29
29
  the current crumb differently in CSS.
30
30
 
31
+ A folder on the way that has no `index.md` is named as text, a `<span>` in place of the
32
+ `<a>`: it is part of where the page sits, but there is no page to go to.
33
+
31
34
  #### Props
32
35
 
33
36
  | Prop | Type | Default | Description |
@@ -486,6 +489,10 @@ The `.active` class is set on any item that is an ancestor of the current page o
486
489
  current page itself. The `.current` class is set only on the item that exactly matches
487
490
  the current page.
488
491
 
492
+ A folder without an `index.md` has no page to link to. Where the menu shows the
493
+ pages below it, the folder is named as text — a `<span>` in place of the `<a>` — and
494
+ groups them; where it does not, the folder is left out, as it would lead nowhere.
495
+
489
496
  #### Label resolution
490
497
 
491
498
  Item labels are resolved in this order:
@@ -19,7 +19,9 @@ const { nodeLabel, nodeHref } = useHierarchy();
19
19
  current: item.current,
20
20
  }"
21
21
  >
22
- <a :href="nodeHref( item.node )" :aria-current="item.current ? 'page' : undefined">{{ nodeLabel( item.node ) }}</a>
22
+ <a v-if="item.node.isPage" :href="nodeHref( item.node )" :aria-current="item.current ? 'page' : undefined">{{ nodeLabel( item.node ) }}</a>
23
+ <!-- A folder without an index.md: there is no page to go to, only the ones below. -->
24
+ <span v-else>{{ nodeLabel( item.node ) }}</span>
23
25
  <ScavoldMenuItems
24
26
  v-if="item.children.length"
25
27
  :items="item.children"
@@ -152,7 +152,10 @@ export function useHierarchy() {
152
152
  ? collectItems( node, remaining === -1 ? -1 : remaining - 1, activeOnly, expand )
153
153
  : [],
154
154
  };
155
- } );
155
+ } )
156
+ // A folder without an index.md is no page to link to: it only groups the
157
+ // pages below it, and where those are not shown it leads nowhere.
158
+ .filter( item => item.node.isPage || item.children.length );
156
159
  };
157
160
 
158
161
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scavold",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "VitePress theme framework — a scaffold for building custom VitePress themes with Vue at the core",
6
6
  "keywords": [
@@ -352,6 +352,21 @@ expect( menu.includes( '<a href="/containers.html">' ),
352
352
  expect( crumbs.includes( '<a href="/blog/index.html"' ) && crumbs.includes( 'aria-current="page"' ),
353
353
  "marks the page the breadcrumb ends on" );
354
354
 
355
+ console.log( "\nfolders without an index page" );
356
+
357
+ const sitemapNav = ( blogPage.match( /<nav aria-label="Sitemap"[\s\S]*?<\/nav>/ ) ?? [""] )[0];
358
+ const guidePage = built( join( "guides", "first.html" ) );
359
+ const guideCrumbs = ( guidePage.match( /<nav class="breadcrumb"[\s\S]*?<\/nav>/ ) ?? [""] )[0];
360
+
361
+ expect( ![ blogPage, guidePage ].some( page => page.includes( 'href="/guides.html"' ) ),
362
+ "never links a folder that has no page of its own" );
363
+ expect( !/>guides</.test( menu ),
364
+ "leaves such a folder out of a menu that shows none of the pages below it" );
365
+ expect( /<span>guides<\/span><ul>(?:<!--\[-->)?<li[^>]*><a href="\/guides\/first\.html"/.test( sitemapNav ),
366
+ "names such a folder as text above its pages where the menu shows them" );
367
+ expect( /<span>guides<\/span>/.test( guideCrumbs ) && guideCrumbs.includes( 'aria-current="page"' ),
368
+ "names such a folder as text in the breadcrumb" );
369
+
355
370
  console.log( "\nnamed menus" );
356
371
 
357
372
  const footer = ( blogPage.match( /<nav aria-label="Footer"[\s\S]*?<\/nav>/ ) ?? [""] )[0];
@@ -413,7 +428,9 @@ expect( entryTitles( dated ).join( " | " ) === "Newest post | Middle post",
413
428
  expect( entryTitles( titled ).join( " | " ) === "Middle post | Newest post | Not announced | Oldest post",
414
429
  "orders by title and lists every page when the limit is 0",
415
430
  `found ${entryTitles( titled ).join( " | " ) || "nothing"}` );
416
- expect( !blog.includes( "Unlisted draft" ), "leaves out a page whose front matter says hide: list" );
431
+ // Menus are left aside: hide: list keeps a page out of lists, not navigation.
432
+ expect( !blog.replace( /<nav[\s\S]*?<\/nav>/g, "" ).includes( "Unlisted draft" ),
433
+ "leaves out a page whose front matter says hide: list" );
417
434
  expect( /<h3 class="scavold-pagelist__title"/.test( dated ) && !/<h\d class="scavold-pagelist__title"/.test( titled ),
418
435
  "uses the requested heading level, and no heading at all without one" );
419
436
  // The displayed text follows the page's locale, which the fixture leaves to the