@lupinum/ginko 0.4.0 → 0.5.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 +150 -0
- package/README.md +2 -2
- package/dist/basics.d.mts +492 -0
- package/dist/basics.d.ts +492 -0
- package/dist/basics.mjs +416 -0
- package/dist/cli/index.mjs +54 -55
- package/dist/index.d.mts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.mjs +3 -3
- package/dist/internal/search.mjs +6 -3
- package/dist/internal.d.mts +387 -41
- package/dist/internal.d.ts +387 -41
- package/dist/internal.mjs +267 -101
- package/dist/nuxt/module.d.mts +2 -2
- package/dist/nuxt/module.d.ts +2 -2
- package/dist/nuxt/module.mjs +105 -13
- package/dist/nuxt/runtime/GinkoImage.d.mts +1 -1
- package/dist/nuxt/runtime/GinkoMarkdown.mjs +2 -2
- package/dist/nuxt/runtime/composables.d.mts +4 -3
- package/dist/nuxt/runtime/composables.mjs +19 -15
- package/dist/nuxt/runtime/fetch.d.mts +3 -1
- package/dist/nuxt/runtime/fetch.mjs +12 -6
- package/dist/nuxt/runtime/markdown.d.mts +3 -0
- package/dist/nuxt/runtime/markdown.mjs +15 -3
- package/dist/nuxt/runtime/plugin.mjs +6 -35
- package/dist/nuxt/runtime/preview-listener.d.mts +13 -0
- package/dist/nuxt/runtime/preview-listener.mjs +37 -0
- package/dist/nuxt/runtime/preview.vue +3 -1
- package/dist/nuxt/runtime/schema.d.ts +6 -0
- package/dist/nuxt/runtime/server/bundles.d.ts +4 -0
- package/dist/nuxt/runtime/server/files-md.d.ts +2 -0
- package/dist/nuxt/runtime/server/files.d.ts +2 -0
- package/dist/nuxt/runtime/server/headers.d.ts +2 -0
- package/dist/nuxt/runtime/server/items.d.mts +12 -0
- package/dist/nuxt/runtime/server/items.d.ts +12 -0
- package/dist/nuxt/runtime/server/items.mjs +17 -0
- package/dist/nuxt/runtime/server/llms-full.d.ts +2 -0
- package/dist/nuxt/runtime/server/llms.d.ts +2 -0
- package/dist/nuxt/runtime/server/markdown-trees.d.ts +2 -0
- package/dist/nuxt/runtime/server/markdown.d.ts +2 -0
- package/dist/nuxt/runtime/server/markdown.mjs +1 -1
- package/dist/nuxt/runtime/server/platform-md.d.mts +3 -0
- package/dist/nuxt/runtime/server/platform-md.d.ts +3 -0
- package/dist/nuxt/runtime/server/platform-md.mjs +71 -0
- package/dist/nuxt/runtime/server/redirects.d.ts +2 -0
- package/dist/nuxt/runtime/server/robots.d.ts +2 -0
- package/dist/nuxt/runtime/server/search.d.ts +2 -0
- package/dist/nuxt/runtime/server/site-config.d.ts +14 -0
- package/dist/nuxt/runtime/server/sitemap-source.d.ts +2 -0
- package/dist/nuxt/runtime/server/sitemap-xml.d.ts +24 -0
- package/dist/nuxt/runtime/server/sitemap.d.ts +2 -0
- package/dist/nuxt/runtime/shared.d.mts +10 -3
- package/dist/nuxt/runtime/shared.mjs +2 -2
- package/dist/shared/ginko.1wwZv4B_.d.ts +1622 -0
- package/dist/shared/{ginko.BBkZW2nW.d.ts → ginko.6cI8KXZP.d.mts} +2 -2
- package/dist/shared/{ginko.CQvxhyez.mjs → ginko.AprJymER.mjs} +30 -1
- package/dist/shared/ginko.BNVC-g9n.mjs +10389 -0
- package/dist/shared/{ginko.Bwan3BB-.d.mts → ginko.B_pACpVU.d.ts} +2 -2
- package/dist/shared/{ginko.CrNRBkS5.mjs → ginko.C4gcOovG.mjs} +253 -309
- package/dist/shared/{ginko.C90fPpMP.mjs → ginko.CXA2R3aS.mjs} +128 -101
- package/dist/shared/ginko.CjWB8N7f.d.ts +128 -0
- package/dist/shared/ginko.D1PeQ3ds.mjs +36 -0
- package/dist/shared/ginko.DIl7l-75.mjs +26 -0
- package/dist/shared/ginko.DY7RbCEw.mjs +601 -0
- package/dist/shared/ginko.Dmgixfpf.mjs +130 -0
- package/dist/shared/{ginko.D-fNojn9.d.mts → ginko.DrkUeYFP.d.mts} +824 -10
- package/dist/shared/{ginko.D-fNojn9.d.ts → ginko.DrkUeYFP.d.ts} +824 -10
- package/dist/shared/{ginko.akHewCGt.d.mts → ginko.DvPtlHIz.d.mts} +50 -5
- package/dist/shared/{ginko.BDF3bW0C.d.ts → ginko.EelR5dt9.d.ts} +50 -5
- package/dist/shared/ginko.ULKQnAWd.d.ts +91 -0
- package/dist/shared/ginko.loGIxGZg.d.mts +91 -0
- package/dist/shared/ginko.o1yIKlgj.d.mts +128 -0
- package/dist/shared/ginko.plW4dLmm.d.mts +1622 -0
- package/dist/shared/{ginko.Dht0xxE5.mjs → ginko.raCzOPYC.mjs} +1 -2
- package/dist/shared/ginko.yKMIjJ68.mjs +84 -0
- package/dist/vue.d.mts +5 -4
- package/dist/vue.d.ts +5 -4
- package/dist/vue.mjs +1 -1
- package/i18n/ar.json +212 -0
- package/i18n/de.json +9 -1
- package/i18n/en.json +9 -1
- package/i18n/es.json +12 -4
- package/i18n/fr.json +212 -0
- package/i18n/it.json +212 -0
- package/package.json +7 -3
- package/dist/shared/ginko.BTUfZCfa.d.mts +0 -172
- package/dist/shared/ginko.C-QjDn3O.mjs +0 -4944
- package/dist/shared/ginko.Dc0oNcDv.d.ts +0 -172
- package/dist/shared/ginko.Mn30dmlm.mjs +0 -20
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type RequestEvent } from 'nuxt/server';
|
|
2
|
+
import { type BundleItem } from '../../../internal.mjs';
|
|
3
|
+
/** An entry as `getGinkoItems` returns it: `url` is its path in the requested language (collections with a route). */
|
|
4
|
+
export type GinkoServerItem = BundleItem & {
|
|
5
|
+
url?: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* The visible entries of collection `brick` in `locale` (default: the main language), in the collection's order, as
|
|
9
|
+
* `useGinko(brick).items` has them on a page: drafts and entries past their `visible` date are left out. Throws a 404
|
|
10
|
+
* for a language the site does not have or a key that is no collection, and a 503 when the platform cannot be reached.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getGinkoItems(event: RequestEvent, brick: string, locale?: string): Promise<GinkoServerItem[]>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createError, useRuntimeConfig } from "nuxt/server";
|
|
2
|
+
import schema from "#ginko/schema";
|
|
3
|
+
import { isVisible, todayIn } from "../../../internal.mjs";
|
|
4
|
+
import { withUrl } from "../shared.mjs";
|
|
5
|
+
import { loadServerBundles } from "./bundles.mjs";
|
|
6
|
+
export async function getGinkoItems(event, brick, locale) {
|
|
7
|
+
const config = useRuntimeConfig().public.ginko;
|
|
8
|
+
const code = locale ?? config.mainLocale;
|
|
9
|
+
const def = schema.bricks[brick];
|
|
10
|
+
if (!config.locales.includes(code) || def?.kind !== "collection") throw createError({ statusCode: 404, statusMessage: "Not found" });
|
|
11
|
+
const bundle = (await loadServerBundles(event, config, [code]))[code];
|
|
12
|
+
const value = bundle?.bricks[brick];
|
|
13
|
+
if (!bundle || value?.kind !== "collection") return [];
|
|
14
|
+
const today = todayIn(config.timeZone);
|
|
15
|
+
const items = value.items.filter((item) => isVisible(def, item.data, today));
|
|
16
|
+
return def.route ? withUrl(items, bundle.locale, bundle.mainLocale) : items;
|
|
17
|
+
}
|
|
@@ -28,7 +28,7 @@ export default defineEventHandler(async (event) => {
|
|
|
28
28
|
event.res.headers.set("content-type", "text/markdown; charset=utf-8");
|
|
29
29
|
if (!match) {
|
|
30
30
|
setResponseStatus(event, 404);
|
|
31
|
-
return markdownNotFound(bundle, path, { origin: config.url });
|
|
31
|
+
return markdownNotFound(bundle, path, { origin: config.url, schema });
|
|
32
32
|
}
|
|
33
33
|
event.res.headers.set("x-ginko-rev", `${bundle.schemaRev}.${bundle.contentRev}`);
|
|
34
34
|
return entryMarkdown(match.item, match.brick, { schema, trees: markdownTrees });
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createError, defineEventHandler, getRequestURL, useRuntimeConfig } from "nuxt/server";
|
|
2
|
+
import schema from "#ginko/schema";
|
|
3
|
+
import { platformMarkdownRef, withMarkdownRefs } from "../../../internal.mjs";
|
|
4
|
+
import { fetchBundle, PlatformError } from "../fetch.mjs";
|
|
5
|
+
const PATH = /^\/__ginko\/platform\/([^/]+)\/(\d+\.\d+)\/md\//;
|
|
6
|
+
const copies = /* @__PURE__ */ new Map();
|
|
7
|
+
const flights = /* @__PURE__ */ new Map();
|
|
8
|
+
const ahead = /* @__PURE__ */ new Map();
|
|
9
|
+
const AHEAD_MS = 1e4;
|
|
10
|
+
const newer = (a, b) => {
|
|
11
|
+
const [as = 0, ac = 0] = a.split(".").map(Number);
|
|
12
|
+
const [bs = 0, bc = 0] = b.split(".").map(Number);
|
|
13
|
+
return as !== bs ? as > bs : ac > bc;
|
|
14
|
+
};
|
|
15
|
+
const stale = (error) => error instanceof PlatformError && error.platformStatus === 409;
|
|
16
|
+
function covering(locale, rev) {
|
|
17
|
+
const copy = copies.get(locale);
|
|
18
|
+
return copy && !newer(rev, copy.rev) ? copy : void 0;
|
|
19
|
+
}
|
|
20
|
+
function isAhead(locale, rev) {
|
|
21
|
+
const known = ahead.get(locale);
|
|
22
|
+
return !!known && known.until > Date.now() && !newer(known.rev, rev);
|
|
23
|
+
}
|
|
24
|
+
function flightFor(config, locale, rev) {
|
|
25
|
+
const running = flights.get(locale);
|
|
26
|
+
if (running) return running;
|
|
27
|
+
const siteToken = useRuntimeConfig().ginkoRevalidateToken;
|
|
28
|
+
const copy = fetchBundle(config, locale, rev, siteToken).then((bundle) => {
|
|
29
|
+
const actual = `${bundle.schemaRev}.${bundle.contentRev}`;
|
|
30
|
+
const trees = /* @__PURE__ */ new Map();
|
|
31
|
+
withMarkdownRefs(bundle, schema, trees, (brick, id, field) => platformMarkdownRef(locale, actual, brick, id, field));
|
|
32
|
+
const fresh = { rev: actual, trees };
|
|
33
|
+
const current = copies.get(locale);
|
|
34
|
+
if (!current || newer(actual, current.rev)) copies.set(locale, fresh);
|
|
35
|
+
return fresh;
|
|
36
|
+
}, (error) => {
|
|
37
|
+
if (stale(error)) ahead.set(locale, { rev, until: Date.now() + AHEAD_MS });
|
|
38
|
+
throw error;
|
|
39
|
+
}).finally(() => flights.delete(locale));
|
|
40
|
+
flights.set(locale, copy);
|
|
41
|
+
return copy;
|
|
42
|
+
}
|
|
43
|
+
async function copyFor(config, locale, rev) {
|
|
44
|
+
for (let round = 0; round < 2; round++) {
|
|
45
|
+
const copy = covering(locale, rev);
|
|
46
|
+
if (copy) return copy;
|
|
47
|
+
if (isAhead(locale, rev)) return void 0;
|
|
48
|
+
try {
|
|
49
|
+
await flightFor(config, locale, rev);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
if (!stale(error)) throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return covering(locale, rev);
|
|
55
|
+
}
|
|
56
|
+
export default defineEventHandler(async (event) => {
|
|
57
|
+
const config = useRuntimeConfig().public.ginko;
|
|
58
|
+
const path = getRequestURL(event).pathname;
|
|
59
|
+
const [, locale = "", rev = ""] = PATH.exec(path) ?? [];
|
|
60
|
+
if (!config.locales.includes(locale)) throw createError({ statusCode: 404, statusMessage: "Text not found" });
|
|
61
|
+
let copy;
|
|
62
|
+
try {
|
|
63
|
+
copy = await copyFor(config, locale, rev);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (error instanceof PlatformError) throw createError({ statusCode: error.statusCode, statusMessage: error.message, cause: error.cause });
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
const tree = copy?.trees.get(path.replace(PATH, `/__ginko/platform/${locale}/${copy.rev}/md/`));
|
|
69
|
+
if (!tree) throw createError({ statusCode: 404, statusMessage: "Text not found" });
|
|
70
|
+
return tree;
|
|
71
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getRequestHost } from 'nuxt/server';
|
|
2
|
+
type SiteConfigInit = {
|
|
3
|
+
event: Parameters<typeof getRequestHost>[0];
|
|
4
|
+
siteConfig: {
|
|
5
|
+
push: (input: Record<string, unknown>) => void;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
type ServerApp = {
|
|
9
|
+
hooks: {
|
|
10
|
+
hook: (name: 'site-config:init', fn: (ctx: SiteConfigInit) => void) => void;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
declare const _default: (app: ServerApp) => void;
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type LocaleConfig } from '@lupinum/ginko-i18n/core';
|
|
2
|
+
import { type Bundle, type Locale, type Schema } from '../../../internal.mjs';
|
|
3
|
+
/** One `<url>`, in the shape @nuxtjs/sitemap reads from a source. All URLs are absolute. */
|
|
4
|
+
export interface SitemapUrl {
|
|
5
|
+
loc: string;
|
|
6
|
+
/** ISO 8601 time of the entry's last change (`updatedAt`); static pages have none. */
|
|
7
|
+
lastmod?: string;
|
|
8
|
+
/** hreflang alternates, `x-default` included; only for pages with more than one locale. */
|
|
9
|
+
alternatives?: {
|
|
10
|
+
hreflang: string;
|
|
11
|
+
href: string;
|
|
12
|
+
}[];
|
|
13
|
+
images?: {
|
|
14
|
+
loc: string;
|
|
15
|
+
}[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* `bundles` must hold every locale of the site for routed entries; `today` is the site's date
|
|
19
|
+
* (todayIn of its time zone), so the visibility rule matches the pages. `locales` is ginko-i18n's
|
|
20
|
+
* config: hreflang uses its languages and `x-default`, exactly as the page head does.
|
|
21
|
+
*/
|
|
22
|
+
export declare function sitemapUrls(site: Schema, bundles: Partial<Record<Locale, Bundle>>, today: string, locales: Pick<LocaleConfig, 'locales' | 'defaultLocale'>): SitemapUrl[];
|
|
23
|
+
/** The sitemap document of `sitemapUrls`. */
|
|
24
|
+
export declare function sitemapXml(site: Schema, bundles: Partial<Record<Locale, Bundle>>, today: string, locales: Pick<LocaleConfig, 'locales' | 'defaultLocale'>): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Locale, type SiteInput } from '../../internal.mjs';
|
|
1
|
+
import { type Locale, type SiteInput, type StoredHolidays } from '../../internal.mjs';
|
|
2
2
|
export interface GinkoPublicConfig {
|
|
3
3
|
site: string;
|
|
4
4
|
name: string;
|
|
@@ -7,6 +7,10 @@ export interface GinkoPublicConfig {
|
|
|
7
7
|
locales: Locale[];
|
|
8
8
|
mainLocale: Locale;
|
|
9
9
|
timeZone: string;
|
|
10
|
+
/** `country` of the site config (ISO 3166-1), or '' when unset. */
|
|
11
|
+
country: string;
|
|
12
|
+
/** The stored holiday calendar (`AT`, `DE`, `SG`, `none`, `custom`), or '' when the config sets neither `calendar` nor `country`. */
|
|
13
|
+
holidays: StoredHolidays | '';
|
|
10
14
|
/** `seo` of the site config (`useGinkoSeo` defaults). */
|
|
11
15
|
seo: NonNullable<SiteInput['seo']>;
|
|
12
16
|
/** `agents` of the site config (llms.txt, Markdown routes). */
|
|
@@ -27,9 +31,12 @@ export declare function agentRequest(path: string): {
|
|
|
27
31
|
page: string;
|
|
28
32
|
asMarkdown: boolean;
|
|
29
33
|
} | undefined;
|
|
30
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* The items of a routed brick, each with `url`: its address in `locale`. An entry without a page there (listed under
|
|
36
|
+
* `untranslated: 'fallback'`) links to its page in the main language `main`.
|
|
37
|
+
*/
|
|
31
38
|
export declare function withUrl<T extends {
|
|
32
39
|
urls?: Partial<Record<string, string>>;
|
|
33
|
-
}>(items: T[], locale: Locale): (T & {
|
|
40
|
+
}>(items: T[], locale: Locale, main: Locale): (T & {
|
|
34
41
|
url?: string;
|
|
35
42
|
})[];
|
|
@@ -4,6 +4,6 @@ export function agentRequest(path) {
|
|
|
4
4
|
const page = markdownRequestPath(path);
|
|
5
5
|
return page === void 0 ? { page: path, asMarkdown: false } : { page, asMarkdown: true };
|
|
6
6
|
}
|
|
7
|
-
export function withUrl(items, locale) {
|
|
8
|
-
return items.map((item) => ({ ...item, url: item.urls?.[locale] }));
|
|
7
|
+
export function withUrl(items, locale, main) {
|
|
8
|
+
return items.map((item) => ({ ...item, url: item.urls?.[locale] ?? item.urls?.[main] }));
|
|
9
9
|
}
|