@lupinum/ginko-content 1.0.0-beta.5 → 1.0.0-beta.7
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 +4 -4
- package/dist/module.json +1 -1
- package/dist/module.mjs +33 -2
- package/dist/public/client.d.ts +4 -2
- package/dist/public/client.js +1 -0
- package/dist/runtime/app/composables/use-content-locale-path.d.ts +10 -0
- package/dist/runtime/app/composables/use-content-locale-path.js +20 -0
- package/dist/runtime/app/composables/use-content-page.js +1 -11
- package/dist/runtime/app/composables/use-content-shared.d.ts +15 -0
- package/dist/runtime/app/composables/use-content-shared.js +10 -0
- package/dist/web-types.json +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
17
|
> [!WARNING]
|
|
18
|
-
> Version `1.0.0-beta.
|
|
18
|
+
> Version `1.0.0-beta.7` is a prerelease. Install it from npm's `next`
|
|
19
19
|
> channel. The stable `0.3` line remains on `latest`.
|
|
20
20
|
|
|
21
21
|
## Why use this package?
|
|
@@ -32,7 +32,7 @@ output.
|
|
|
32
32
|
|
|
33
33
|
- Node.js 22.18–22.x, 24.11–24.x, or 26+
|
|
34
34
|
- Nuxt 4.5.1 through Nuxt 4.x
|
|
35
|
-
- Vue 3.5.
|
|
35
|
+
- Vue 3.5.40 through Vue 3.x
|
|
36
36
|
- ESM; CommonJS `require()` is not supported
|
|
37
37
|
|
|
38
38
|
## Installation
|
|
@@ -40,13 +40,13 @@ output.
|
|
|
40
40
|
Use the Nuxt CLI:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
npx nuxi module add @lupinum/ginko-content@1.0.0-beta.
|
|
43
|
+
npx nuxi module add @lupinum/ginko-content@1.0.0-beta.7
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
Or install and register the module by hand:
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
|
-
pnpm add @lupinum/ginko-content@1.0.0-beta.
|
|
49
|
+
pnpm add @lupinum/ginko-content@1.0.0-beta.7
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
```ts
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -34,7 +34,7 @@ import { assertCanonicalHighlightOptionNames } from '../dist/parsers/markdown-pl
|
|
|
34
34
|
import { BUILTIN_MARKDOWN_RENDER_CONTRACTS } from '../dist/core/markdown/builtin-render-contracts.js';
|
|
35
35
|
|
|
36
36
|
const name = "@lupinum/ginko-content";
|
|
37
|
-
const version = "1.0.0-beta.
|
|
37
|
+
const version = "1.0.0-beta.7";
|
|
38
38
|
const peerDependencies = {
|
|
39
39
|
nuxt: ">=4.5.1 <5"};
|
|
40
40
|
|
|
@@ -252,6 +252,7 @@ const registerContentDevRuntime = (nuxt, options, contentContext) => {
|
|
|
252
252
|
};
|
|
253
253
|
|
|
254
254
|
const runtimeAppImportSpecs = [
|
|
255
|
+
{ name: "useContentLocalePath", as: "useContentLocalePath", from: "./app/composables/use-content-locale-path.js" },
|
|
255
256
|
{ name: "useContentPage", as: "useContentPage", from: "./app/composables/use-content-page.js" },
|
|
256
257
|
{ name: "useContentSearch", as: "useGinkoContentSearch", from: "./app/composables/search.js" }
|
|
257
258
|
];
|
|
@@ -1109,6 +1110,7 @@ const collectRawMarkdownRoutesFromGeneratedFrontmatter = (markdown) => {
|
|
|
1109
1110
|
};
|
|
1110
1111
|
const publicOutputPath = (publicDir, route) => join(publicDir, normalizeStaticRoutePath(route).replace(/^\//, ""));
|
|
1111
1112
|
|
|
1113
|
+
const runtimeModuleImportURL = (modulePath, toFileURL = pathToFileURL) => toFileURL(modulePath).href;
|
|
1112
1114
|
const assertPrerenderedContentSnapshot = (buildDir) => {
|
|
1113
1115
|
const snapshotPath = resolve$1(buildDir, "content-cache/snapshot.json");
|
|
1114
1116
|
let raw;
|
|
@@ -1166,7 +1168,7 @@ ${details}` : "")
|
|
|
1166
1168
|
writeFileSync(indexPath, json, "utf8");
|
|
1167
1169
|
if (searchRuntime.engine === "pagefind") {
|
|
1168
1170
|
const records = JSON.parse(json);
|
|
1169
|
-
const { writePagefindIndex } = await import(resolveRuntimeModule("./server/pagefind.js"));
|
|
1171
|
+
const { writePagefindIndex } = await import(runtimeModuleImportURL(resolveRuntimeModule("./server/pagefind.js")));
|
|
1170
1172
|
await writePagefindIndex(records, resolve$1(publicDir, "pagefind"), resolvedI18n.defaultLocale);
|
|
1171
1173
|
}
|
|
1172
1174
|
}
|
|
@@ -1364,6 +1366,29 @@ const registerContentNitroIntegrationHooks = (nitroConfig, options, contentConte
|
|
|
1364
1366
|
});
|
|
1365
1367
|
};
|
|
1366
1368
|
|
|
1369
|
+
const NUXT_NITRO_CACHE_DRIVER_SUFFIX = "/node_modules/@nuxt/nitro-server/dist/runtime/utils/cache-driver.mjs";
|
|
1370
|
+
const createNuxtWindowsCacheDriverResolver = (platform = process.platform, fromFileURL = fileURLToPath) => {
|
|
1371
|
+
if (platform !== "win32") {
|
|
1372
|
+
return void 0;
|
|
1373
|
+
}
|
|
1374
|
+
return {
|
|
1375
|
+
name: "ginko-content:nuxt-windows-cache-driver",
|
|
1376
|
+
resolveId(id) {
|
|
1377
|
+
if (!id.startsWith("file:")) {
|
|
1378
|
+
return null;
|
|
1379
|
+
}
|
|
1380
|
+
try {
|
|
1381
|
+
const url = new URL(id);
|
|
1382
|
+
if (url.protocol !== "file:" || url.hostname !== "" || url.search !== "" || url.hash !== "" || !url.pathname.toLowerCase().endsWith(NUXT_NITRO_CACHE_DRIVER_SUFFIX)) {
|
|
1383
|
+
return null;
|
|
1384
|
+
}
|
|
1385
|
+
return fromFileURL(url);
|
|
1386
|
+
} catch {
|
|
1387
|
+
return null;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
};
|
|
1391
|
+
};
|
|
1367
1392
|
const hookNuxtBoundary$1 = (nuxt, name, callback) => {
|
|
1368
1393
|
const hook = nuxt.hook;
|
|
1369
1394
|
hook(name, callback);
|
|
@@ -1414,6 +1439,12 @@ const registerContentNitroConfig = ({
|
|
|
1414
1439
|
}
|
|
1415
1440
|
nitroConfig.bundledStorage = nitroConfig.bundledStorage || [];
|
|
1416
1441
|
nitroConfig.bundledStorage.push("cache:content");
|
|
1442
|
+
const windowsCacheDriverResolver = createNuxtWindowsCacheDriverResolver();
|
|
1443
|
+
if (windowsCacheDriverResolver) {
|
|
1444
|
+
nitroConfig.rollupConfig ||= {};
|
|
1445
|
+
nitroConfig.rollupConfig.plugins ||= [];
|
|
1446
|
+
nitroConfig.rollupConfig.plugins.push(windowsCacheDriverResolver);
|
|
1447
|
+
}
|
|
1417
1448
|
nitroConfig.externals = defu(typeof nitroConfig.externals === "object" ? nitroConfig.externals : {}, {
|
|
1418
1449
|
inline: [
|
|
1419
1450
|
resolveModuleFile("."),
|
package/dist/public/client.d.ts
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
* Client-side public API surface (browser + SSR Vue).
|
|
3
3
|
*
|
|
4
4
|
* The unified query API (ADR-0016) is the supported core read path. The
|
|
5
|
-
* public composable surface
|
|
6
|
-
*
|
|
5
|
+
* public composable surface includes page loading, locale links, and
|
|
6
|
+
* search; every other application workflow is
|
|
7
7
|
* ordinary Nuxt composition over the one-shot async query operations below.
|
|
8
8
|
*/
|
|
9
9
|
export { one, many, count, paginate, backlinks, resolveOne, surround, navigation } from '../runtime/app/composables/query-api.js';
|
|
10
10
|
export { getCollectionPath } from '../features/query/routes.js';
|
|
11
11
|
export type { CollectionPathOptions } from '../features/query/routes.js';
|
|
12
12
|
export { findFirstNavigationPage } from '../features/navigation/resolve.js';
|
|
13
|
+
export { useContentLocalePath } from '../runtime/app/composables/use-content-locale-path.js';
|
|
14
|
+
export type { ContentLocalePage, UseContentLocalePathOptions } from '../runtime/app/composables/use-content-locale-path.js';
|
|
13
15
|
export { useContentPage } from '../runtime/app/composables/use-content-page.js';
|
|
14
16
|
export type { ContentPageStatus, UseContentPageOptions, UseContentPageReturn } from '../runtime/app/composables/use-content-page.js';
|
|
15
17
|
export type { QueryWhere, QueryOperators, ContentSelector, BacklinkFields, BacklinkSource, BacklinksOptions, BacklinksResult, CountOptions, LocaleFallback, DocumentFromHandle, OneOptions, ManyOptions, PaginationOptions, PaginationResult, PopulateSpec, PopulatedDocument, ResolveOneOptions, ResolveOneResult, LocalizedContentDocument, ResolutionEnvelope, SortSpec, ContentAlternate, ContentDocumentRoute, ContentDocumentResolution, ContentNavigationItem, ContentCollectionName, ContentCollectionTarget, ContentSearchSection, SurroundOptions, SurroundResult, NavigationOptions, ContentNavigationTreeItem, ResolvedContentNavigationItem, PaginationMode, OffsetPaginationResult, CursorPaginationResult } from '../types/query.js';
|
package/dist/public/client.js
CHANGED
|
@@ -10,6 +10,7 @@ export {
|
|
|
10
10
|
} from "../runtime/app/composables/query-api.js";
|
|
11
11
|
export { getCollectionPath } from "../features/query/routes.js";
|
|
12
12
|
export { findFirstNavigationPage } from "../features/navigation/resolve.js";
|
|
13
|
+
export { useContentLocalePath } from "../runtime/app/composables/use-content-locale-path.js";
|
|
13
14
|
export { useContentPage } from "../runtime/app/composables/use-content-page.js";
|
|
14
15
|
export { useContentSearch } from "../runtime/app/composables/search.js";
|
|
15
16
|
export { querySiteData } from "../runtime/app/composables/site-data.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type MaybeRefOrGetter } from 'vue';
|
|
2
|
+
import type { UseContentPageReturn } from './use-content-page';
|
|
3
|
+
/** The existing page result supplies the facts; no shared state or second query. */
|
|
4
|
+
export type ContentLocalePage = Pick<UseContentPageReturn<unknown>, 'page' | 'status'>;
|
|
5
|
+
export interface UseContentLocalePathOptions<L extends string = string> {
|
|
6
|
+
/** Used only when the source is undefined (an application-only page). */
|
|
7
|
+
fallback?: (locale: L) => string | undefined;
|
|
8
|
+
}
|
|
9
|
+
/** Derive interactive locale links from a page result supplied by its owner. */
|
|
10
|
+
export declare function useContentLocalePath<L extends string = string>(source: MaybeRefOrGetter<ContentLocalePage | undefined>, options?: UseContentLocalePathOptions<L>): (locale: L) => string | undefined;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { toValue } from "vue";
|
|
2
|
+
import { useRoute, useRouter } from "#imports";
|
|
3
|
+
import { pageMatchesRoute } from "./use-content-shared.js";
|
|
4
|
+
import { getContentRuntime } from "./runtime.js";
|
|
5
|
+
export function useContentLocalePath(source, options = {}) {
|
|
6
|
+
const route = useRoute();
|
|
7
|
+
const router = useRouter();
|
|
8
|
+
const runtime = getContentRuntime();
|
|
9
|
+
return (locale) => {
|
|
10
|
+
const result = toValue(source);
|
|
11
|
+
if (!result) return runtime.locales?.includes(locale) ? options.fallback?.(locale) : void 0;
|
|
12
|
+
if (result.status.value !== "success") return void 0;
|
|
13
|
+
const document = result.page.value;
|
|
14
|
+
if (!document || !pageMatchesRoute(document, route.path)) return void 0;
|
|
15
|
+
const alternates = document.route.alternates;
|
|
16
|
+
const alternate = alternates.find((item) => item.locale === locale && item.source === "variant") ?? alternates.find((item) => item.locale === locale);
|
|
17
|
+
if (!alternate) return void 0;
|
|
18
|
+
return router.resolve({ path: alternate.path, query: route.query, hash: route.hash }).fullPath;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -3,21 +3,11 @@ import { useAsyncData, useRoute } from "#imports";
|
|
|
3
3
|
import { resolveCollectionI18n } from "../../../features/localization/path.js";
|
|
4
4
|
import { one, surround } from "./query-api.js";
|
|
5
5
|
import { getContentRuntime } from "./runtime.js";
|
|
6
|
-
import { contentCollectionName, resolveLocaleFromRoutePath, resolveOptions, stableKey } from "./use-content-shared.js";
|
|
7
|
-
const normalizeRoutePath = (path) => {
|
|
8
|
-
if (typeof path !== "string") return void 0;
|
|
9
|
-
const normalized = path.replace(/\/+$/, "");
|
|
10
|
-
return normalized || "/";
|
|
11
|
-
};
|
|
6
|
+
import { contentCollectionName, normalizeRoutePath, pageMatchesRoute, resolveLocaleFromRoutePath, resolveOptions, stableKey } from "./use-content-shared.js";
|
|
12
7
|
const normalizePageSurround = (surroundOption) => {
|
|
13
8
|
if (!surroundOption) return void 0;
|
|
14
9
|
return surroundOption === true ? {} : surroundOption;
|
|
15
10
|
};
|
|
16
|
-
const pageMatchesRoute = (doc, path) => {
|
|
17
|
-
if (!doc?.route) return false;
|
|
18
|
-
const normalizedPath = normalizeRoutePath(path);
|
|
19
|
-
return normalizeRoutePath(doc.route.requestedPath) === normalizedPath || normalizeRoutePath(doc.route.resolvedPath) === normalizedPath;
|
|
20
|
-
};
|
|
21
11
|
export async function useContentPage(handle, options = {}) {
|
|
22
12
|
const route = useRoute();
|
|
23
13
|
const { surround: surroundOption, ...oneOptions } = options;
|
|
@@ -11,3 +11,18 @@ export declare const resolveOptions: <T extends Record<string, unknown>>(reactiv
|
|
|
11
11
|
export declare const stableKey: (prefix: string, name: string, options: unknown) => string;
|
|
12
12
|
export declare const contentCollectionName: (handle: ContentCollectionTarget) => string;
|
|
13
13
|
export declare const resolveLocaleFromRoutePath: (path: string, locales: string[], defaultLocale?: string) => string | undefined;
|
|
14
|
+
export declare const normalizeRoutePath: (path: unknown) => string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* A resolved page "matches" the current route when either the exact
|
|
17
|
+
* selector the app queried with (`route.requestedPath`) or the document's
|
|
18
|
+
* own canonical public path (`route.resolvedPath`) equals the current route
|
|
19
|
+
* — the first covers a provider/alias match whose canonical path differs
|
|
20
|
+
* from the requested one, the
|
|
21
|
+
* second covers static/prerendered routes served under a normalized path.
|
|
22
|
+
*/
|
|
23
|
+
export declare const pageMatchesRoute: (doc: {
|
|
24
|
+
route?: {
|
|
25
|
+
requestedPath?: string;
|
|
26
|
+
resolvedPath?: string;
|
|
27
|
+
};
|
|
28
|
+
} | null | undefined, path: string) => boolean;
|
|
@@ -27,3 +27,13 @@ export const resolveLocaleFromRoutePath = (path, locales, defaultLocale) => {
|
|
|
27
27
|
const firstSegment = path.split("/").filter(Boolean)[0];
|
|
28
28
|
return firstSegment && locales.includes(firstSegment) ? firstSegment : defaultLocale;
|
|
29
29
|
};
|
|
30
|
+
export const normalizeRoutePath = (path) => {
|
|
31
|
+
if (typeof path !== "string") return void 0;
|
|
32
|
+
const normalized = path.replace(/\/+$/, "");
|
|
33
|
+
return normalized || "/";
|
|
34
|
+
};
|
|
35
|
+
export const pageMatchesRoute = (doc, path) => {
|
|
36
|
+
if (!doc?.route) return false;
|
|
37
|
+
const normalizedPath = normalizeRoutePath(path);
|
|
38
|
+
return normalizeRoutePath(doc.route.requestedPath) === normalizedPath || normalizeRoutePath(doc.route.resolvedPath) === normalizedPath;
|
|
39
|
+
};
|
package/dist/web-types.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lupinum/ginko-content",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.7",
|
|
4
4
|
"description": "Collection-first content engine for Nuxt",
|
|
5
5
|
"homepage": "https://ginko-content.lupinum.com",
|
|
6
6
|
"bugs": {
|
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
"nuxt": ">=4.5.1 <5",
|
|
173
173
|
"pagefind": "^1.5.2",
|
|
174
174
|
"vitest": ">=4.1.6 <5",
|
|
175
|
-
"vue": "^3.5.
|
|
175
|
+
"vue": "^3.5.40"
|
|
176
176
|
},
|
|
177
177
|
"peerDependenciesMeta": {
|
|
178
178
|
"beautiful-mermaid": {
|