@kirchdev/duxt 0.8.0 → 0.8.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.
@@ -98,9 +98,19 @@ watch(
98
98
  );
99
99
 
100
100
  // One tree instead of two lists: the sections become children of the entry
101
- // that stands for the documentation. See `buildSheetNavigation`.
101
+ // that stands for the documentation. See `buildSheetNavigation`. Without the
102
+ // sections the edition being read does not have — see `sectionsInEdition`.
102
103
  const sheet = computed(() =>
103
- buildSheetNavigation(duxt.navigation, duxt.sections, duxt.resolvedSources)
104
+ buildSheetNavigation(
105
+ duxt.navigation,
106
+ sectionsInEdition(
107
+ duxt.sections ?? [],
108
+ duxt.resolvedSources ?? [],
109
+ path.value,
110
+ navigation.value
111
+ ),
112
+ duxt.resolvedSources
113
+ )
104
114
  );
105
115
 
106
116
  /** A group owns the page when any of its children does. */
@@ -12,18 +12,36 @@
12
12
  export function useDuxtSectionRow() {
13
13
  const duxt = useDuxtConfig();
14
14
  const path = useDuxtPath();
15
+ const { data: navigation } = useDuxtNavigation();
15
16
 
16
17
  /**
17
18
  * THIS AREA'S ENTRIES, not every entry the site declared — see
18
19
  * `sectionsForPath`. A second source has top-level parts of its own, and the
19
20
  * row is "the parts of what you are reading" rather than a site index.
20
21
  */
21
- const sections = computed(() =>
22
+ const scoped = computed(() =>
22
23
  sectionsForPath(duxt.sections ?? [], duxt.resolvedSources ?? [], path.value)
23
24
  );
24
25
 
26
+ /**
27
+ * AND ONLY THOSE THIS EDITION HAS — see `sectionsInEdition`. Read from the
28
+ * same navigation the sidebar and the header already load, so it costs no
29
+ * query of its own.
30
+ */
31
+ const sections = computed(() =>
32
+ sectionsInEdition(
33
+ scoped.value,
34
+ duxt.resolvedSources ?? [],
35
+ path.value,
36
+ navigation.value
37
+ )
38
+ );
39
+
40
+ // From the unfiltered list: the page being read exists, so its own entry is
41
+ // never one the edition lacks, and the header must not move while the tree
42
+ // is still loading.
25
43
  const visible = computed(() =>
26
- sections.value.some(
44
+ scoped.value.some(
27
45
  (section) => section.to && path.value.startsWith(section.to)
28
46
  )
29
47
  );
@@ -208,6 +208,67 @@ export function sectionsForPath<T extends { to?: string }>(
208
208
  });
209
209
  }
210
210
 
211
+ /** The least of a navigation node this file reads: where it is, and below. */
212
+ interface NavigationNode {
213
+ path: string;
214
+ children?: NavigationNode[];
215
+ }
216
+
217
+ /**
218
+ * The entries whose page EXISTS in the edition being read.
219
+ *
220
+ * The row is declared once, for the site as it is today, and every edition
221
+ * shares it. A section added after a release — `/add-ons` beside the guides —
222
+ * is therefore offered on that release and on every older one, where its page
223
+ * was never written, and the entry is a link to a 404 on every page of them.
224
+ *
225
+ * So an entry pointing into the reader's own edition is kept only when that
226
+ * edition's navigation has its page, or a page under it. Everything this cannot
227
+ * judge stays: an entry without `to`, one at the site root, one into another
228
+ * source or a generated section (which has no place in this tree), one at a
229
+ * different edition than the reader's, and every entry while the tree is still
230
+ * unknown — an entry hidden by a lookup that has not answered yet is a part of
231
+ * the site that disappears for no reason.
232
+ */
233
+ export function sectionsInEdition<T extends { to?: string }>(
234
+ sections: T[],
235
+ sources: Area[],
236
+ path: string,
237
+ navigation: readonly NavigationNode[] | null | undefined
238
+ ): T[] {
239
+ // The tree is the one the reader's page is in. On a generated section's page
240
+ // — a release, an endpoint — that is the section's own, and judging the
241
+ // documentation's entries against it would empty the row.
242
+ const reader = sourceForPath(path, sources);
243
+ if (!navigation || !reader || reader.generated) return sections;
244
+
245
+ const pages: string[] = [];
246
+ const walk = (nodes: readonly NavigationNode[]) => {
247
+ for (const node of nodes) {
248
+ pages.push(node.path);
249
+ if (node.children) walk(node.children);
250
+ }
251
+ };
252
+ walk(navigation);
253
+
254
+ return sections.filter((section) => {
255
+ const to = section.to;
256
+ if (!to || to === '/') return true;
257
+
258
+ const target = sourceForPath(to, sources);
259
+ if (
260
+ !target ||
261
+ target.generated ||
262
+ !sameTree(target, reader, sources) ||
263
+ target.version !== reader.version
264
+ ) {
265
+ return true;
266
+ }
267
+
268
+ return pages.some((page) => isInside(page, to));
269
+ });
270
+ }
271
+
211
272
  /**
212
273
  * WHICH ONE of an area's entries is the one being read.
213
274
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://www.schemastore.org/package.json",
3
3
  "name": "@kirchdev/duxt",
4
- "version": "0.8.0",
4
+ "version": "0.8.1",
5
5
  "description": "duxt is a Nuxt layer: extend it and your docs/ folder becomes a site, with theme, search, API reference and llms.txt included. Point it at other repositories, or at tags of the same one, and each becomes a version.",
6
6
  "keywords": [
7
7
  "content-v3",