@kirchdev/duxt 0.8.1 → 0.8.2-dev-main.59-9244f91

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.
@@ -56,7 +56,8 @@ const file = computed(() => {
56
56
  ? sourceFilePath(
57
57
  page.value.stem,
58
58
  source.value?.prefix ?? '',
59
- source.value?.path ?? 'docs'
59
+ // The folder on the forge, where the one on disk is a copy of it.
60
+ source.value?.originPath ?? source.value?.path ?? 'docs'
60
61
  )
61
62
  : undefined;
62
63
  });
@@ -292,7 +292,7 @@ declare global {
292
292
  * The repository a source read off disk lives in, for links back to it.
293
293
  * Not `repo`, which is what makes Content download a source.
294
294
  */
295
- origin?: { repo: string; ref?: string };
295
+ origin?: { repo: string; ref?: string; path?: string };
296
296
  /**
297
297
  * Read this source's git history for "Last updated" and the contributors.
298
298
  * Off by default for a remote source: Content clones with `--depth 1`, and
@@ -480,6 +480,8 @@ declare global {
480
480
  repositoryUrl?: string;
481
481
  ref?: string;
482
482
  refKind?: 'branch' | 'tag';
483
+ /** Folder inside `repository`, where it is not `path` — see `origin.path`. */
484
+ originPath?: string;
483
485
  path: string;
484
486
  /** The locale this collection serves; absent on a site with no translations. */
485
487
  locale?: string;
@@ -141,8 +141,14 @@ export interface DuxtSource {
141
141
  * Writing `repo` instead would be the obvious move and the wrong one: `repo`
142
142
  * is what makes Content DOWNLOAD a source, so naming this repository there
143
143
  * would have the build clone the checkout it is already standing in.
144
+ *
145
+ * `path` is the folder in THAT repository which this source's own `path`
146
+ * stands for. Only needed where the two differ — content copied into a
147
+ * build context, or a sibling checkout read through `../` — because the
148
+ * folder on disk is then not the folder on the forge, and "Edit this page"
149
+ * would open a file that does not exist there.
144
150
  */
145
- origin?: { repo: string; ref?: string };
151
+ origin?: { repo: string; ref?: string; path?: string };
146
152
  /**
147
153
  * Read this source's git history for "Last updated" and the contributors.
148
154
  *
@@ -348,6 +354,11 @@ export interface DuxtResolvedSource {
348
354
  repositoryUrl?: string;
349
355
  /** The ref the pages were read at, by name. */
350
356
  ref?: string;
357
+ /**
358
+ * Folder inside `repository` holding this collection's Markdown, where it is
359
+ * not `path` — see `origin.path`. Links back read this first.
360
+ */
361
+ originPath?: string;
351
362
  /** Which namespace that ref lives in. */
352
363
  refKind?: 'branch' | 'tag';
353
364
  /** Folder inside the repository holding the Markdown. */
@@ -603,6 +614,45 @@ export function expandSources(
603
614
  );
604
615
  }
605
616
 
617
+ /**
618
+ * Where a folder read off disk sits in the repository `origin` names.
619
+ *
620
+ * A locale's folder is mapped through the source's own: `wiki-content/docs/en`
621
+ * under `wiki-content/docs`, with `origin.path` `docs`, is `docs/en`. A folder
622
+ * outside the source's cannot be mapped, and is rejected rather than guessed —
623
+ * a link to the wrong file is worse than no link.
624
+ */
625
+ export function originFolder(
626
+ originPath: string | undefined,
627
+ sourcePath: string | undefined,
628
+ folder: string
629
+ ): string | undefined {
630
+ if (originPath === undefined) return undefined;
631
+
632
+ // A loop rather than `/\/+$/`: the paths are consumer input, and an anchored
633
+ // repetition is a polynomial backtrack on a long run of slashes.
634
+ const trim = (value: string) => {
635
+ let end = value.length;
636
+ while (end > 0 && value[end - 1] === '/') end--;
637
+ const kept = value.slice(0, end);
638
+ return kept.startsWith('./') ? kept.slice(2) : kept;
639
+ };
640
+ const base = trim(sourcePath ?? '');
641
+ const target = trim(originPath);
642
+ const own = trim(folder);
643
+
644
+ if (own === base) return target;
645
+ if (base === '' || own.startsWith(`${base}/`)) {
646
+ const rest = base === '' ? own : own.slice(base.length + 1);
647
+ return [target, rest].filter(Boolean).join('/');
648
+ }
649
+
650
+ throw new Error(
651
+ `duxt: origin.path cannot map "${folder}", which is outside the source ` +
652
+ `path "${sourcePath ?? ''}". Keep its locale folders under the source.`
653
+ );
654
+ }
655
+
606
656
  export function resolveSources(
607
657
  sources: DuxtSource[],
608
658
  options: DuxtSourcesOptions = {}
@@ -732,6 +782,9 @@ export function resolveSources(
732
782
  ? repoUrl(source.origin.repo)
733
783
  : undefined,
734
784
  ref: name ?? source.origin?.ref,
785
+ originPath: entry.repo
786
+ ? undefined
787
+ : originFolder(source.origin?.path, source.path, entry.path),
735
788
  refKind: effectiveRef
736
789
  ? refIsTag(effectiveRef)
737
790
  ? 'tag'
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.1",
4
+ "version": "0.8.2-dev-main.59-9244f91",
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",