@lupinum/ginko 0.4.0 → 0.6.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 +161 -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 +59 -56
- 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 +108 -15
- 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.BBkZW2nW.d.ts → ginko.6cI8KXZP.d.mts} +2 -2
- package/dist/shared/{ginko.CrNRBkS5.mjs → ginko.B1-DoOea.mjs} +253 -309
- 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.BaFweQcB.d.mts +91 -0
- package/dist/shared/ginko.BiDXgjLy.d.ts +91 -0
- package/dist/shared/ginko.C-oz8wwI.mjs +95 -0
- package/dist/shared/{ginko.BDF3bW0C.d.ts → ginko.CLzVaDi4.d.ts} +56 -5
- package/dist/shared/ginko.C_nq6vk7.d.mts +1622 -0
- package/dist/shared/ginko.CjWB8N7f.d.ts +128 -0
- package/dist/shared/ginko.D1PeQ3ds.mjs +36 -0
- package/dist/shared/ginko.D2oht0Kx.d.ts +1622 -0
- package/dist/shared/ginko.DCHGkQ7P.mjs +116 -0
- package/dist/shared/ginko.DIl7l-75.mjs +26 -0
- package/dist/shared/{ginko.akHewCGt.d.mts → ginko.DkIc0ZZk.d.mts} +56 -5
- 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.WAfoMhv1.mjs +601 -0
- package/dist/shared/ginko.o1yIKlgj.d.mts +128 -0
- package/dist/shared/{ginko.Dht0xxE5.mjs → ginko.raCzOPYC.mjs} +1 -2
- package/dist/shared/{ginko.C90fPpMP.mjs → ginko.t-gbwzxh.mjs} +128 -101
- 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.CQvxhyez.mjs +0 -40
- package/dist/shared/ginko.Dc0oNcDv.d.ts +0 -172
- package/dist/shared/ginko.Mn30dmlm.mjs +0 -20
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { B as Bundle } from './ginko.6cI8KXZP.mjs';
|
|
2
|
+
import { L as Locale } from './ginko.DrkUeYFP.mjs';
|
|
3
|
+
|
|
4
|
+
interface NavNode {
|
|
5
|
+
title: string;
|
|
6
|
+
path: string;
|
|
7
|
+
id?: string;
|
|
8
|
+
brick?: string;
|
|
9
|
+
children: NavNode[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Navigation tree of the collections `bricks` in `locale`, built from item URLs. An item is a child of the
|
|
13
|
+
* node at its nearest existing path prefix, else a root node. A string `parent` field (item id) overrides that.
|
|
14
|
+
* Siblings keep the item order of the bundle (bricks in the given order).
|
|
15
|
+
*/
|
|
16
|
+
declare function navTree(bundle: Bundle, bricks: string[], locale: Locale): NavNode[];
|
|
17
|
+
/** Nodes from the root down to the node at `path`; empty when the path is not in the tree. */
|
|
18
|
+
declare function breadcrumbs(tree: NavNode[], path: string): NavNode[];
|
|
19
|
+
|
|
20
|
+
interface SeoImage {
|
|
21
|
+
url: string;
|
|
22
|
+
width?: number;
|
|
23
|
+
height?: number;
|
|
24
|
+
alt?: string;
|
|
25
|
+
}
|
|
26
|
+
interface SeoInput {
|
|
27
|
+
siteName: string;
|
|
28
|
+
/** `%s` is replaced by the page title; default '%s · <siteName>'. A page without title gets siteName alone. */
|
|
29
|
+
titleTemplate?: string;
|
|
30
|
+
title?: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
image?: SeoImage;
|
|
33
|
+
type?: 'website' | 'article';
|
|
34
|
+
noindex?: boolean;
|
|
35
|
+
}
|
|
36
|
+
interface SeoHead {
|
|
37
|
+
title: string;
|
|
38
|
+
meta: (({
|
|
39
|
+
name: string;
|
|
40
|
+
} | {
|
|
41
|
+
property: string;
|
|
42
|
+
}) & {
|
|
43
|
+
content: string;
|
|
44
|
+
})[];
|
|
45
|
+
}
|
|
46
|
+
declare function seoHead(input: SeoInput): SeoHead;
|
|
47
|
+
/** True when a request for `host` (with port, as in the Host header) is not for the site's own address: preview deployments, staging, localhost. Those must never be indexed. */
|
|
48
|
+
declare function isPreviewHost(host: string | undefined, siteUrl: string): boolean;
|
|
49
|
+
declare function robotsTxt(options: {
|
|
50
|
+
sitemap?: string;
|
|
51
|
+
noindex?: boolean;
|
|
52
|
+
disallow?: string[];
|
|
53
|
+
}): string;
|
|
54
|
+
declare function websiteLd(o: {
|
|
55
|
+
name: string;
|
|
56
|
+
url: string;
|
|
57
|
+
lang: string;
|
|
58
|
+
}): Record<string, unknown>;
|
|
59
|
+
/**
|
|
60
|
+
* `node` with the site's `country` (ISO 3166 code) where a builder left it out: `addressCountry` of every PostalAddress,
|
|
61
|
+
* and where remote applicants of a remote JobPosting must live. The Nuxt module applies it to a page's JSON-LD, so
|
|
62
|
+
* `siteJsonLd` and `jobJsonLd` need no `country` (an explicit one wins). An empty `country` changes nothing.
|
|
63
|
+
*/
|
|
64
|
+
declare function withCountry<T>(node: T, country: string): T;
|
|
65
|
+
/** The schema.org types `organizationLd` writes. A page whose JSON-LD has a node of one of them is the site's organisation node. */
|
|
66
|
+
declare const ORGANIZATION_TYPES: readonly ["Organization", "LocalBusiness", "NGO"];
|
|
67
|
+
interface OrganizationLdInput {
|
|
68
|
+
name: string;
|
|
69
|
+
url: string;
|
|
70
|
+
/** `Organization` (default), `LocalBusiness` for a shop or practice, `NGO` for a nonprofit. */
|
|
71
|
+
type?: (typeof ORGANIZATION_TYPES)[number];
|
|
72
|
+
legalName?: string;
|
|
73
|
+
/** Absolute URL of the logo. */
|
|
74
|
+
logo?: string;
|
|
75
|
+
email?: string;
|
|
76
|
+
telephone?: string;
|
|
77
|
+
address?: {
|
|
78
|
+
street?: string;
|
|
79
|
+
postalCode?: string;
|
|
80
|
+
city?: string;
|
|
81
|
+
country?: string;
|
|
82
|
+
};
|
|
83
|
+
vatID?: string;
|
|
84
|
+
/** Absolute URLs of the organisation's profiles elsewhere. */
|
|
85
|
+
sameAs?: string[];
|
|
86
|
+
}
|
|
87
|
+
declare function organizationLd(o: OrganizationLdInput): Record<string, unknown>;
|
|
88
|
+
/**
|
|
89
|
+
* A schema.org BreadcrumbList from the first step (usually the home page) to the page itself. Each step has a `title`
|
|
90
|
+
* and a `path` of the site, as the nodes of `useGinkoBreadcrumbs` do; `siteUrl` (`useGinkoSite().url`) makes the
|
|
91
|
+
* paths absolute.
|
|
92
|
+
*/
|
|
93
|
+
declare function breadcrumbJsonLd(steps: readonly Pick<NavNode, 'title' | 'path'>[], siteUrl: string): Record<string, unknown>;
|
|
94
|
+
interface ArticleLdInput {
|
|
95
|
+
/** `Article` (default) or `BlogPosting` for a post of a blog. */
|
|
96
|
+
type?: 'Article' | 'BlogPosting';
|
|
97
|
+
title: string;
|
|
98
|
+
url: string;
|
|
99
|
+
description?: string;
|
|
100
|
+
image?: string;
|
|
101
|
+
published?: string;
|
|
102
|
+
modified?: string;
|
|
103
|
+
/** One author by name, or a list of authors with an optional website each. */
|
|
104
|
+
author?: string | readonly {
|
|
105
|
+
name: string;
|
|
106
|
+
url?: string;
|
|
107
|
+
}[];
|
|
108
|
+
keywords?: readonly string[];
|
|
109
|
+
lang: string;
|
|
110
|
+
}
|
|
111
|
+
declare function articleLd(o: ArticleLdInput): Record<string, unknown>;
|
|
112
|
+
declare function faqLd(pairs: {
|
|
113
|
+
question: string;
|
|
114
|
+
answer: string;
|
|
115
|
+
}[]): Record<string, unknown>;
|
|
116
|
+
/**
|
|
117
|
+
* Headers every response of a Ginko site carries. Only the platform may frame `/__ginko` (the preview); nothing
|
|
118
|
+
* else is framed. `nosniff` stops a browser from reading user text (`.md`, `llms.txt`, JSON) as HTML, and the
|
|
119
|
+
* referrer policy keeps full URLs from leaving the site.
|
|
120
|
+
*/
|
|
121
|
+
declare function siteHeaders(input: {
|
|
122
|
+
preview: boolean;
|
|
123
|
+
platformOrigin: string;
|
|
124
|
+
noindex: boolean;
|
|
125
|
+
}): Record<string, string>;
|
|
126
|
+
|
|
127
|
+
export { ORGANIZATION_TYPES as a, articleLd as d, breadcrumbJsonLd as e, breadcrumbs as f, faqLd as g, siteHeaders as h, isPreviewHost as i, withCountry as j, navTree as n, organizationLd as o, robotsTxt as r, seoHead as s, websiteLd as w };
|
|
128
|
+
export type { ArticleLdInput as A, NavNode as N, OrganizationLdInput as O, SeoHead as S, SeoImage as b, SeoInput as c };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { readFileSync, mkdirSync, writeFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
|
-
import { c as checkLinks, e as externalLinks } from './ginko.
|
|
4
|
-
import { m as msg } from './ginko.C-QjDn3O.mjs';
|
|
3
|
+
import { c as checkLinks, e as externalLinks, m as msg } from './ginko.BNVC-g9n.mjs';
|
|
5
4
|
|
|
6
5
|
const TIMEOUT_MS = 8e3;
|
|
7
6
|
const CONCURRENCY = 4;
|
|
@@ -1,9 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { B as BRICK_KEYS, F as FIELD_KEYS, S as SCHEMA_KEYS
|
|
3
|
-
import {
|
|
1
|
+
import { i as isTranslatable, A as ALT_MAX, g as effectiveMax, m as msg, h as stableJson, j as bare, k as sameLabel, l as effectiveMin, n as sha256, r as resolveRouteLinks, o as resolveFileRefs, q as effectiveAlt } from './ginko.BNVC-g9n.mjs';
|
|
2
|
+
import { B as BRICK_KEYS, F as FIELD_KEYS, S as SCHEMA_KEYS } from './ginko.B1-DoOea.mjs';
|
|
3
|
+
import { b as addDays } from './ginko.C-oz8wwI.mjs';
|
|
4
|
+
import { B as BUNDLE_FORMAT, w as withMarkdownTrees } from './ginko.yKMIjJ68.mjs';
|
|
5
|
+
|
|
6
|
+
const SITE_BUDGET = { siteBytes: 4 * 1024 * 1024, entries: 2e3, entryBytes: 480 * 1024, treeBytes: 8 * 1024 * 1024, trashBytes: 4 * 1024 * 1024 };
|
|
7
|
+
function byteSize(value) {
|
|
8
|
+
return new TextEncoder().encode(JSON.stringify(value ?? null)).byteLength;
|
|
9
|
+
}
|
|
10
|
+
function entryBytes(data, prints = {}) {
|
|
11
|
+
return byteSize(data) + byteSize(prints);
|
|
12
|
+
}
|
|
13
|
+
function fitsBudget(after, before, limit) {
|
|
14
|
+
return after <= limit || after <= before;
|
|
15
|
+
}
|
|
16
|
+
const VALUE_JSON = 8;
|
|
17
|
+
const ID_BYTES = 40;
|
|
18
|
+
const SHORT_VALUE = 32;
|
|
19
|
+
function largestFieldBytes(field, locales) {
|
|
20
|
+
if (field.retired) return 0;
|
|
21
|
+
const values = isTranslatable(field) ? locales.length : 1;
|
|
22
|
+
switch (field.type) {
|
|
23
|
+
case "text":
|
|
24
|
+
case "longtext":
|
|
25
|
+
case "markdown":
|
|
26
|
+
return (effectiveMax(field) + VALUE_JSON) * values;
|
|
27
|
+
case "list":
|
|
28
|
+
return field.max * (largestEntryBytes(field.of, locales) + ID_BYTES);
|
|
29
|
+
case "choices":
|
|
30
|
+
return effectiveMax(field) * ID_BYTES;
|
|
31
|
+
case "ref":
|
|
32
|
+
return field.multiple ? (field.max ?? 0) * ID_BYTES : ID_BYTES;
|
|
33
|
+
case "image":
|
|
34
|
+
case "file":
|
|
35
|
+
return ID_BYTES + ALT_MAX * locales.length;
|
|
36
|
+
default:
|
|
37
|
+
return SHORT_VALUE * values;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function largestEntryBytes(fields, locales) {
|
|
41
|
+
return Object.values(fields).reduce((sum, field) => sum + largestFieldBytes(field, locales), 0);
|
|
42
|
+
}
|
|
4
43
|
|
|
5
44
|
const fx = (key) => msg(`diff.fix.${key}`);
|
|
6
|
-
const NEW_FIELD_FIX = fx("newField");
|
|
45
|
+
const NEW_FIELD_FIX = /* @__PURE__ */ fx("newField");
|
|
7
46
|
function diffSchema(prod, next) {
|
|
8
47
|
const changes = [];
|
|
9
48
|
const rejected = [];
|
|
@@ -28,6 +67,7 @@ function diffSchema(prod, next) {
|
|
|
28
67
|
}
|
|
29
68
|
for (const k of ["name", "url"]) if (prod[k] !== next[k]) ok(k, k, msg("diff.valueChanged", { name: k }));
|
|
30
69
|
if (stableJson(prod.week) !== stableJson(next.week)) ok("week", "week", msg("diff.valueChanged", { name: "week" }));
|
|
70
|
+
if ((prod.holidays ?? null) !== (next.holidays ?? null)) ok("holidays", "holidays", msg("diff.valueChanged", { name: "holidays" }));
|
|
31
71
|
if (stableJson(prod.pages) !== stableJson(next.pages)) ok("pages", "pages", msg("diff.pagesChanged"));
|
|
32
72
|
if (stableJson(prod.agents ?? null) !== stableJson(next.agents ?? null)) ok("agents", "agents", msg("diff.agentsChanged"));
|
|
33
73
|
for (const [path, rule] of Object.entries(prod.retired)) {
|
|
@@ -92,6 +132,8 @@ function diffBrick(key, before, after, newFills, newLocales, ok, no) {
|
|
|
92
132
|
if (!sameLabel(before.describe ?? "", after.describe ?? "")) ok(`${key}.describe`, "text", msg("diff.textChanged"));
|
|
93
133
|
if ((before.layout ?? "sections") !== (after.layout ?? "sections")) ok(`${key}.layout`, "text", msg("diff.textChanged"));
|
|
94
134
|
if (stableJson(before.tasks ?? []) !== stableJson(after.tasks ?? [])) ok(`${key}.tasks`, "tasks", msg("diff.tasksChanged"));
|
|
135
|
+
if (stableJson(before.planned ?? null) !== stableJson(after.planned ?? null)) ok(`${key}.planned`, "planned", msg("diff.valueChanged", { name: "planned" }));
|
|
136
|
+
if (stableJson(before.status ?? null) !== stableJson(after.status ?? null)) ok(`${key}.status`, "text", msg("diff.textChanged"));
|
|
95
137
|
if (before.kind === "collection" && after.kind === "collection") {
|
|
96
138
|
if (after.max < before.max) no(`${key}.max`, "maxLowered", msg("diff.maxLowered", { at: key }), fx("keepMax"));
|
|
97
139
|
else if (after.max > before.max) ok(`${key}.max`, "maxRaised", msg("diff.maxRaised"));
|
|
@@ -158,7 +200,7 @@ function diffField(at, old, next, newFills, ok, no) {
|
|
|
158
200
|
if (onGrid) ok(at, "minLowered", msg("diff.minLowered"));
|
|
159
201
|
else no(at, "minOffGrid", msg("diff.minOffGrid", { at, step }), fx("minOnGrid"));
|
|
160
202
|
}
|
|
161
|
-
for (const k of ["step", "format", "currency", "from", "accept", "to", "multiple"]) {
|
|
203
|
+
for (const k of ["step", "format", "currency", "from", "accept", "to", "multiple", "after"]) {
|
|
162
204
|
if (stableJson(o[k] ?? null) !== stableJson(n[k] ?? null)) no(at, `${k}Changed`, msg("diff.propChanged", { at, prop: k }));
|
|
163
205
|
}
|
|
164
206
|
if ((old.type === "choice" || old.type === "choices") && (next.type === "choice" || next.type === "choices")) {
|
|
@@ -179,7 +221,7 @@ function diffField(at, old, next, newFills, ok, no) {
|
|
|
179
221
|
}
|
|
180
222
|
}
|
|
181
223
|
|
|
182
|
-
const isRecord
|
|
224
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
183
225
|
function releaseData(stored, next, data, written) {
|
|
184
226
|
const out = { ...data };
|
|
185
227
|
for (const [name, field] of Object.entries(next)) {
|
|
@@ -193,7 +235,7 @@ function releaseData(stored, next, data, written) {
|
|
|
193
235
|
const columns = Object.entries(field.of).filter(([column, inner]) => !Object.hasOwn(old.of, column) && !inner.optional && !inner.retired && inner.default !== void 0);
|
|
194
236
|
if (!columns.length) continue;
|
|
195
237
|
out[name] = out[name].map((row) => {
|
|
196
|
-
if (!isRecord
|
|
238
|
+
if (!isRecord(row)) return row;
|
|
197
239
|
const filled = { ...row };
|
|
198
240
|
for (const [column, inner] of columns) if (filled[column] === void 0) filled[column] = inner.default;
|
|
199
241
|
return filled;
|
|
@@ -209,81 +251,9 @@ function fieldsChanged(stored, next, brick) {
|
|
|
209
251
|
return !!before && !!after && stableJson(before.fields) !== stableJson(after.fields);
|
|
210
252
|
}
|
|
211
253
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (!isRecord(value)) return false;
|
|
215
|
-
const b = value;
|
|
216
|
-
if (b.format !== BUNDLE_FORMAT || typeof b.site !== "string" || typeof b.locale !== "string") return false;
|
|
217
|
-
if (!Number.isInteger(b.schemaRev) || !Number.isInteger(b.contentRev) || !isRecord(b.bricks)) return false;
|
|
218
|
-
return Object.values(b.bricks).every(isBundleBrick);
|
|
219
|
-
}
|
|
220
|
-
function knownBricks(bundle, schema) {
|
|
221
|
-
return { ...bundle, bricks: Object.fromEntries(Object.entries(bundle.bricks).filter(([key]) => Object.hasOwn(schema.bricks, key))) };
|
|
222
|
-
}
|
|
223
|
-
function withFileBricks(platform, files, schema) {
|
|
224
|
-
const base = platform ?? files;
|
|
225
|
-
if (!base) throw new Error("withFileBricks: no bundle");
|
|
226
|
-
const fromPlatform = Object.entries(platform?.bricks ?? {}).filter(([key]) => schema.bricks[key]?.source !== "files");
|
|
227
|
-
return { ...base, bricks: { ...Object.fromEntries(fromPlatform), ...files?.bricks } };
|
|
228
|
-
}
|
|
229
|
-
async function markdownTrees(fields, data) {
|
|
230
|
-
const trees = {};
|
|
231
|
-
const parse = async (text) => (await parseMarkdown(text)).value;
|
|
232
|
-
const walk = async (inner, row, path) => {
|
|
233
|
-
for (const [name, field] of Object.entries(inner)) {
|
|
234
|
-
const value = row[name];
|
|
235
|
-
const leaf = path ? `${path}.${name}` : name;
|
|
236
|
-
if (field.type === "markdown" && typeof value === "string") trees[leaf] = await parse(value);
|
|
237
|
-
else if (field.type === "markdown" && isRecord(value)) {
|
|
238
|
-
const perLocale = {};
|
|
239
|
-
for (const [locale, text] of Object.entries(value)) if (typeof text === "string") perLocale[locale] = await parse(text);
|
|
240
|
-
trees[leaf] = perLocale;
|
|
241
|
-
} else if (field.type === "list" && Array.isArray(value)) {
|
|
242
|
-
for (const r of value) if (isRecord(r) && typeof r._id === "string") await walk(field.of, r, `${leaf}.${r._id}`);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
};
|
|
246
|
-
await walk(fields, data, "");
|
|
247
|
-
return trees;
|
|
248
|
-
}
|
|
249
|
-
async function withMarkdownTrees(bundle, schema) {
|
|
250
|
-
const fill = async (fields, data) => {
|
|
251
|
-
const out = { ...data };
|
|
252
|
-
for (const [key, field] of Object.entries(fields)) {
|
|
253
|
-
const value = out[key];
|
|
254
|
-
if (field.type === "markdown" && typeof value === "string") out[key] = (await parseMarkdown(value)).value;
|
|
255
|
-
else if (field.type === "list" && Array.isArray(value)) out[key] = await Promise.all(value.map((row) => isRecord(row) ? fill(field.of, row) : row));
|
|
256
|
-
}
|
|
257
|
-
return out;
|
|
258
|
-
};
|
|
259
|
-
const bricks = {};
|
|
260
|
-
for (const [key, brick] of Object.entries(bundle.bricks)) {
|
|
261
|
-
const fields = Object.hasOwn(schema.bricks, key) ? schema.bricks[key].fields : void 0;
|
|
262
|
-
if (!fields) bricks[key] = brick;
|
|
263
|
-
else if (brick.kind === "single") bricks[key] = { ...brick, data: await fill(fields, brick.data) };
|
|
264
|
-
else bricks[key] = { ...brick, items: await Promise.all(brick.items.map(async (item) => ({ ...item, data: await fill(fields, item.data) }))) };
|
|
265
|
-
}
|
|
266
|
-
return { ...bundle, bricks };
|
|
254
|
+
function untranslatedMode(brick) {
|
|
255
|
+
return brick.untranslated ?? (brick.route ? "hide" : "fallback");
|
|
267
256
|
}
|
|
268
|
-
function bundleFits(bundle, schema) {
|
|
269
|
-
return Object.entries(schema.bricks).every(([key, brick]) => {
|
|
270
|
-
const have = Object.hasOwn(bundle.bricks, key) ? bundle.bricks[key] : void 0;
|
|
271
|
-
return have === void 0 || have.kind === (brick.kind === "single" ? "single" : "collection");
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
function isBundleBrick(brick) {
|
|
275
|
-
if (!isRecord(brick)) return false;
|
|
276
|
-
if (brick.kind === "single") return isRecord(brick.data) && isStrings(brick.fallback);
|
|
277
|
-
if (brick.kind !== "collection" || !Array.isArray(brick.items)) return false;
|
|
278
|
-
return brick.items.every((item) => isRecord(item) && typeof item.id === "string" && isRecord(item.data) && isStrings(item.fallback) && (item.urls === void 0 || isRecord(item.urls) && Object.values(item.urls).every((u) => typeof u === "string")) && (item.updatedAt === void 0 || typeof item.updatedAt === "string") && (item.source === void 0 || typeof item.source === "string"));
|
|
279
|
-
}
|
|
280
|
-
function isStrings(value) {
|
|
281
|
-
return Array.isArray(value) && value.every((v) => typeof v === "string");
|
|
282
|
-
}
|
|
283
|
-
function isRecord(value) {
|
|
284
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
257
|
function printOf(mainValue) {
|
|
288
258
|
return sha256(stableJson(mainValue ?? null));
|
|
289
259
|
}
|
|
@@ -291,8 +261,9 @@ function resolveEntry(schema, brickKey, entry, ctx) {
|
|
|
291
261
|
const brick = schema.bricks[brickKey];
|
|
292
262
|
const main = schema.locales[0];
|
|
293
263
|
const fallback = [];
|
|
294
|
-
const
|
|
295
|
-
const
|
|
264
|
+
const outdated = [];
|
|
265
|
+
const blocking = [];
|
|
266
|
+
const state = { schema, brickKey, entry, ctx, main, fallback, outdated, blocking };
|
|
296
267
|
const data = resolveFields(brick.fields, entry.data, "", state);
|
|
297
268
|
for (const [name, field] of Object.entries(brick.fields)) {
|
|
298
269
|
if (!field.retired) continue;
|
|
@@ -303,12 +274,13 @@ function resolveEntry(schema, brickKey, entry, ctx) {
|
|
|
303
274
|
if (leaf === rule.from || leaf.startsWith(`${rule.from}.`)) fallback.push(name + leaf.slice(rule.from.length));
|
|
304
275
|
}
|
|
305
276
|
} else if (entry.data[name] !== void 0) {
|
|
306
|
-
data[name] = resolveValue(field, entry.data[name], name, { ...state,
|
|
277
|
+
data[name] = resolveValue(field, entry.data[name], name, { ...state, blocking: [], outdated: [] });
|
|
307
278
|
} else if ("value" in rule) {
|
|
308
|
-
data[name] = resolveValue(field, rule.value, name, { ...state,
|
|
279
|
+
data[name] = resolveValue(field, rule.value, name, { ...state, blocking: [], outdated: [] });
|
|
309
280
|
}
|
|
310
281
|
}
|
|
311
|
-
|
|
282
|
+
const hidden = blocking.length > 0 && brick.kind === "collection" && untranslatedMode(brick) === "hide";
|
|
283
|
+
return { data, fallback, outdated, blocking, hidden };
|
|
312
284
|
}
|
|
313
285
|
function resolveFields(fields, stored, path, state) {
|
|
314
286
|
const out = {};
|
|
@@ -362,8 +334,9 @@ function altOf(own, library, leaf, state, field) {
|
|
|
362
334
|
const fromLibrary = (l) => effectiveAlt(map, void 0, l) ? "" : effectiveAlt(void 0, library, l);
|
|
363
335
|
if (!markAllFallback && locale !== state.main && fromLibrary(locale)) return fromLibrary(locale);
|
|
364
336
|
const main = fromLibrary(state.main);
|
|
365
|
-
return localized(main ? { ...map, [state.main]: main } : map, leaf, state, field) ?? "";
|
|
337
|
+
return localized(main ? { ...map, [state.main]: main } : map, leaf, { ...state, blocking: [] }, field) ?? "";
|
|
366
338
|
}
|
|
339
|
+
const isEmpty = (value) => value === void 0 || value === null || value === "";
|
|
367
340
|
function localized(value, leaf, state, field) {
|
|
368
341
|
const map = value ?? {};
|
|
369
342
|
const mainValue = map[state.main];
|
|
@@ -374,14 +347,16 @@ function localized(value, leaf, state, field) {
|
|
|
374
347
|
}
|
|
375
348
|
if (locale === state.main) return mainValue;
|
|
376
349
|
const own = map[locale];
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
if (state.flags.canHide && !field.optional) state.flags.hidden = true;
|
|
350
|
+
if (isEmpty(own)) {
|
|
351
|
+
if (!isEmpty(mainValue)) {
|
|
352
|
+
state.fallback.push(leaf);
|
|
353
|
+
if (!field.optional && field.type !== "slug") state.blocking.push(leaf);
|
|
354
|
+
}
|
|
383
355
|
return mainValue;
|
|
384
356
|
}
|
|
357
|
+
if (field.type === "slug" || state.entry.prints?.[leaf]?.[locale] === printOf(mainValue)) return own;
|
|
358
|
+
if (isEmpty(mainValue)) return mainValue;
|
|
359
|
+
state.outdated.push(leaf);
|
|
385
360
|
return own;
|
|
386
361
|
}
|
|
387
362
|
function defaultsFor(fields) {
|
|
@@ -401,13 +376,19 @@ function visibleUntil(brick, data) {
|
|
|
401
376
|
return typeof last === "string" ? addDays(last, vis.days ?? 0) : void 0;
|
|
402
377
|
}
|
|
403
378
|
const deletesExpired = (brick) => brick.kind === "collection" && brick.visible?.mode === "until" && brick.visible.deleteExpired === true;
|
|
404
|
-
function sortEntries(brick, entries) {
|
|
379
|
+
function sortEntries(brick, entries, languages) {
|
|
405
380
|
const copy = [...entries];
|
|
406
381
|
if (brick.order === "manual") return copy.sort((a, b) => (a.order ?? 0) - (b.order ?? 0) || a.id.localeCompare(b.id));
|
|
407
382
|
const { field, dir } = brick.order;
|
|
408
383
|
const sign = dir === "desc" ? -1 : 1;
|
|
384
|
+
const def = brick.fields[field];
|
|
385
|
+
const translated = def !== void 0 && isTranslatable(def);
|
|
409
386
|
const key = (e) => {
|
|
410
|
-
|
|
387
|
+
let v = e.data[field];
|
|
388
|
+
if (translated && languages && typeof v === "object" && v !== null && !Array.isArray(v)) {
|
|
389
|
+
const map = v;
|
|
390
|
+
v = isEmpty(map[languages.locale]) ? map[languages.main] : map[languages.locale];
|
|
391
|
+
}
|
|
411
392
|
if (v === void 0 || v === null) return [];
|
|
412
393
|
if (typeof v === "number") return [v];
|
|
413
394
|
if (typeof v === "object" && !Array.isArray(v) && "amount" in v) return [Number(v.amount)];
|
|
@@ -426,7 +407,10 @@ function sortEntries(brick, entries) {
|
|
|
426
407
|
return copy.sort((a, b) => sign * compare(key(a), key(b)) || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
427
408
|
}
|
|
428
409
|
async function servedBundle(input) {
|
|
429
|
-
|
|
410
|
+
const bundle = buildBundle(input);
|
|
411
|
+
const main = bundle.locale === bundle.mainLocale ? void 0 : buildBundle({ ...input, requestedLocale: bundle.mainLocale });
|
|
412
|
+
const trees = await withMarkdownTrees(bundle, input.schema);
|
|
413
|
+
return resolveRouteLinks(resolveFileRefs(trees, input.schema, input.files), input.schema, main);
|
|
430
414
|
}
|
|
431
415
|
function buildBundle(input) {
|
|
432
416
|
const { schema } = input;
|
|
@@ -444,7 +428,7 @@ function buildBundle(input) {
|
|
|
444
428
|
continue;
|
|
445
429
|
}
|
|
446
430
|
const items = [];
|
|
447
|
-
for (const entry of sortEntries(brick, stored)) {
|
|
431
|
+
for (const entry of sortEntries(brick, stored, { locale, main })) {
|
|
448
432
|
const r = resolveEntry(schema, key, entry, ctx);
|
|
449
433
|
if (r.hidden) continue;
|
|
450
434
|
const item = { id: entry.id, data: r.data, fallback: r.fallback };
|
|
@@ -453,7 +437,7 @@ function buildBundle(input) {
|
|
|
453
437
|
if (entry.updatedAt !== void 0) item.updatedAt = entry.updatedAt;
|
|
454
438
|
const source = entry.sources?.[locale] ?? entry.sources?.[main];
|
|
455
439
|
if (source !== void 0) item.source = source;
|
|
456
|
-
if (brick.route && isVisible(brick, r.data, input.today)) item.urls = urlsFor(schema, key, brick, entry
|
|
440
|
+
if (brick.route && isVisible(brick, r.data, input.today)) item.urls = urlsFor(schema, key, brick, entry);
|
|
457
441
|
items.push(item);
|
|
458
442
|
}
|
|
459
443
|
bricks[key] = { kind: "collection", items };
|
|
@@ -472,20 +456,27 @@ function buildBundle(input) {
|
|
|
472
456
|
bricks
|
|
473
457
|
};
|
|
474
458
|
}
|
|
475
|
-
function
|
|
459
|
+
function routeUrls(schema, brick, entry) {
|
|
476
460
|
const slugField = Object.entries(brick.fields).find(([, field]) => field.type === "slug" && !field.retired)?.[0];
|
|
477
461
|
if (!slugField || !brick.route) return {};
|
|
478
462
|
const slugs = entry.data[slugField] ?? {};
|
|
479
463
|
const main = schema.locales[0];
|
|
480
464
|
const urls = {};
|
|
481
465
|
for (const locale of schema.locales) {
|
|
482
|
-
if (locale !== main && brick.untranslated === "hide" && resolveEntry(schema, key, entry, { locale, files }).hidden) continue;
|
|
483
466
|
const slug = slugs[locale] || slugs[main];
|
|
484
467
|
const route = brick.route[locale];
|
|
485
468
|
if (slug && route) urls[locale] = route.replace("[slug]", slug);
|
|
486
469
|
}
|
|
487
470
|
return urls;
|
|
488
471
|
}
|
|
472
|
+
function urlsFor(schema, key, brick, entry) {
|
|
473
|
+
const urls = routeUrls(schema, brick, entry);
|
|
474
|
+
const main = schema.locales[0];
|
|
475
|
+
for (const locale of schema.locales) {
|
|
476
|
+
if (locale !== main && urls[locale] && resolveEntry(schema, key, entry, { locale, files: () => void 0 }).blocking.length) delete urls[locale];
|
|
477
|
+
}
|
|
478
|
+
return urls;
|
|
479
|
+
}
|
|
489
480
|
function urlClashes(entries) {
|
|
490
481
|
const owner = /* @__PURE__ */ new Map();
|
|
491
482
|
const clashes = [];
|
|
@@ -541,4 +532,40 @@ function applyDefaults(bundle, schema) {
|
|
|
541
532
|
return { ...bundle, bricks };
|
|
542
533
|
}
|
|
543
534
|
|
|
544
|
-
|
|
535
|
+
class CliError extends Error {
|
|
536
|
+
code;
|
|
537
|
+
constructor(message, code = "INVALID") {
|
|
538
|
+
super(message);
|
|
539
|
+
this.code = code;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
543
|
+
function parseReleaseState(value) {
|
|
544
|
+
if (!isObject(value)) throw new CliError("The platform did not return a valid state.", "UNAVAILABLE");
|
|
545
|
+
const { site, schema, schemaRev, contentRev, migrations, entries } = value;
|
|
546
|
+
const valid = typeof site === "string" && isObject(schema) && isObject(schema.bricks) && Array.isArray(schema.migrations) && isObject(schema.retired) && typeof schemaRev === "number" && typeof contentRev === "number" && Array.isArray(migrations) && Array.isArray(entries) && entries.every((e) => isObject(e) && typeof e.id === "string" && typeof e.brick === "string" && isObject(e.data));
|
|
547
|
+
if (!valid) throw new CliError("The platform returned an incomplete state.", "UNAVAILABLE");
|
|
548
|
+
return value;
|
|
549
|
+
}
|
|
550
|
+
const EXTENSIONS = {
|
|
551
|
+
"image/jpeg": ".jpg",
|
|
552
|
+
"image/png": ".png",
|
|
553
|
+
"image/webp": ".webp",
|
|
554
|
+
"image/avif": ".avif",
|
|
555
|
+
"application/pdf": ".pdf"
|
|
556
|
+
};
|
|
557
|
+
function defaultDir(site, now) {
|
|
558
|
+
return `ginko-export-${site}-${now.toISOString().slice(0, 10)}`;
|
|
559
|
+
}
|
|
560
|
+
function pathOf(file) {
|
|
561
|
+
return `files/${file.id}${EXTENSIONS[file.mime] ?? ""}`;
|
|
562
|
+
}
|
|
563
|
+
function parseExport(value, locator, problem) {
|
|
564
|
+
const optionalNumber = (v) => v === void 0 || typeof v === "number";
|
|
565
|
+
const optionalString = (v) => v === void 0 || typeof v === "string";
|
|
566
|
+
const valid = isObject(value) && value.format === 1 && typeof value.site === "string" && typeof value.name === "string" && typeof value.exportedAt === "string" && isObject(value.schema) && isObject(value.schema.bricks) && typeof value.schemaRev === "number" && typeof value.contentRev === "number" && Array.isArray(value.entries) && value.entries.every((e) => isObject(e) && typeof e.id === "string" && typeof e.brick === "string" && (e.kind === "single" || e.kind === "item") && typeof e.order === "number" && isObject(e.data) && isObject(e.prints) && typeof e.rev === "number" && optionalNumber(e.deletedAt)) && Array.isArray(value.files) && value.files.every((f) => isObject(f) && typeof f.id === "string" && typeof f.name === "string" && typeof f.mime === "string" && typeof f.size === "number" && typeof f[locator] === "string" && optionalNumber(f.width) && optionalNumber(f.height) && optionalString(f.folder) && optionalString(f.sha256) && (f.kept === void 0 || typeof f.kept === "boolean") && (f.original === void 0 || f.original === true) && (f.alt === void 0 || isObject(f.alt) && Object.values(f.alt).every((text) => typeof text === "string")) && (f.focus === void 0 || isObject(f.focus) && typeof f.focus.x === "number" && typeof f.focus.y === "number")) && (value.folders === void 0 || Array.isArray(value.folders) && value.folders.every((f) => isObject(f) && typeof f.id === "string" && typeof f.name === "string" && optionalString(f.parent)));
|
|
567
|
+
if (!valid) throw new CliError(problem, "UNAVAILABLE" );
|
|
568
|
+
return value;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
export { urlClashes as A, urlsFor as B, CliError as C, SITE_BUDGET as S, fitsBudget as a, diffSchema as b, largestFieldBytes as c, defaultsFor as d, entryBytes as e, fieldsChanged as f, parseReleaseState as g, pathOf as h, isObject as i, defaultDir as j, isVisible as k, largestEntryBytes as l, printOf as m, applyDefaults as n, blockedSlugs as o, parseExport as p, buildBundle as q, releaseData as r, byteSize as s, deletesExpired as t, resolveEntry as u, visibleUntil as v, routeUrls as w, servedBundle as x, sortEntries as y, untranslatedMode as z };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { a as parseMarkdown } from './ginko.BNVC-g9n.mjs';
|
|
2
|
+
|
|
3
|
+
const BUNDLE_FORMAT = 3;
|
|
4
|
+
function entryTitle(item, fields) {
|
|
5
|
+
if (typeof item.data.title === "string") return item.data.title;
|
|
6
|
+
const slug = Object.values(fields ?? {}).find((field) => field.type === "slug");
|
|
7
|
+
const named = slug?.type === "slug" ? item.data[slug.from] : void 0;
|
|
8
|
+
return typeof named === "string" && named.trim() ? named : item.id;
|
|
9
|
+
}
|
|
10
|
+
function isBundle(value) {
|
|
11
|
+
if (!isRecord(value)) return false;
|
|
12
|
+
const b = value;
|
|
13
|
+
if (b.format !== BUNDLE_FORMAT || typeof b.site !== "string" || typeof b.locale !== "string") return false;
|
|
14
|
+
if (!Number.isInteger(b.schemaRev) || !Number.isInteger(b.contentRev) || !isRecord(b.bricks)) return false;
|
|
15
|
+
return Object.values(b.bricks).every(isBundleBrick);
|
|
16
|
+
}
|
|
17
|
+
function knownBricks(bundle, schema) {
|
|
18
|
+
return { ...bundle, bricks: Object.fromEntries(Object.entries(bundle.bricks).filter(([key]) => Object.hasOwn(schema.bricks, key))) };
|
|
19
|
+
}
|
|
20
|
+
function withFileBricks(platform, files, schema) {
|
|
21
|
+
const base = platform ?? files;
|
|
22
|
+
if (!base) throw new Error("withFileBricks: no bundle");
|
|
23
|
+
const fromPlatform = Object.entries(platform?.bricks ?? {}).filter(([key]) => schema.bricks[key]?.source !== "files");
|
|
24
|
+
return { ...base, bricks: { ...Object.fromEntries(fromPlatform), ...files?.bricks } };
|
|
25
|
+
}
|
|
26
|
+
async function markdownTrees(fields, data) {
|
|
27
|
+
const trees = {};
|
|
28
|
+
const parse = async (text) => (await parseMarkdown(text)).value;
|
|
29
|
+
const walk = async (inner, row, path) => {
|
|
30
|
+
for (const [name, field] of Object.entries(inner)) {
|
|
31
|
+
const value = row[name];
|
|
32
|
+
const leaf = path ? `${path}.${name}` : name;
|
|
33
|
+
if (field.type === "markdown" && typeof value === "string") trees[leaf] = await parse(value);
|
|
34
|
+
else if (field.type === "markdown" && isRecord(value)) {
|
|
35
|
+
const perLocale = {};
|
|
36
|
+
for (const [locale, text] of Object.entries(value)) if (typeof text === "string") perLocale[locale] = await parse(text);
|
|
37
|
+
trees[leaf] = perLocale;
|
|
38
|
+
} else if (field.type === "list" && Array.isArray(value)) {
|
|
39
|
+
for (const r of value) if (isRecord(r) && typeof r._id === "string") await walk(field.of, r, `${leaf}.${r._id}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
await walk(fields, data, "");
|
|
44
|
+
return trees;
|
|
45
|
+
}
|
|
46
|
+
async function withMarkdownTrees(bundle, schema) {
|
|
47
|
+
const fill = async (fields, data) => {
|
|
48
|
+
const out = { ...data };
|
|
49
|
+
for (const [key, field] of Object.entries(fields)) {
|
|
50
|
+
const value = out[key];
|
|
51
|
+
if (field.type === "markdown" && typeof value === "string") out[key] = (await parseMarkdown(value)).value;
|
|
52
|
+
else if (field.type === "list" && Array.isArray(value)) out[key] = await Promise.all(value.map((row) => isRecord(row) ? fill(field.of, row) : row));
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
};
|
|
56
|
+
const bricks = {};
|
|
57
|
+
for (const [key, brick] of Object.entries(bundle.bricks)) {
|
|
58
|
+
const fields = Object.hasOwn(schema.bricks, key) ? schema.bricks[key].fields : void 0;
|
|
59
|
+
if (!fields) bricks[key] = brick;
|
|
60
|
+
else if (brick.kind === "single") bricks[key] = { ...brick, data: await fill(fields, brick.data) };
|
|
61
|
+
else bricks[key] = { ...brick, items: await Promise.all(brick.items.map(async (item) => ({ ...item, data: await fill(fields, item.data) }))) };
|
|
62
|
+
}
|
|
63
|
+
return { ...bundle, bricks };
|
|
64
|
+
}
|
|
65
|
+
function bundleFits(bundle, schema) {
|
|
66
|
+
return Object.entries(schema.bricks).every(([key, brick]) => {
|
|
67
|
+
const have = Object.hasOwn(bundle.bricks, key) ? bundle.bricks[key] : void 0;
|
|
68
|
+
return have === void 0 || have.kind === (brick.kind === "single" ? "single" : "collection");
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function isBundleBrick(brick) {
|
|
72
|
+
if (!isRecord(brick)) return false;
|
|
73
|
+
if (brick.kind === "single") return isRecord(brick.data) && isStrings(brick.fallback);
|
|
74
|
+
if (brick.kind !== "collection" || !Array.isArray(brick.items)) return false;
|
|
75
|
+
return brick.items.every((item) => isRecord(item) && typeof item.id === "string" && isRecord(item.data) && isStrings(item.fallback) && (item.urls === void 0 || isRecord(item.urls) && Object.values(item.urls).every((u) => typeof u === "string")) && (item.updatedAt === void 0 || typeof item.updatedAt === "string") && (item.source === void 0 || typeof item.source === "string"));
|
|
76
|
+
}
|
|
77
|
+
function isStrings(value) {
|
|
78
|
+
return Array.isArray(value) && value.every((v) => typeof v === "string");
|
|
79
|
+
}
|
|
80
|
+
function isRecord(value) {
|
|
81
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { BUNDLE_FORMAT as B, withFileBricks as a, bundleFits as b, entryTitle as e, isBundle as i, knownBricks as k, markdownTrees as m, withMarkdownTrees as w };
|
package/dist/vue.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
2
|
import { PropType, Component } from 'vue';
|
|
3
|
-
import { MarkdownTree
|
|
3
|
+
import { MarkdownTree } from './index.mjs';
|
|
4
|
+
import { AttributeRegistry } from './internal.mjs';
|
|
4
5
|
import '@lupinum/ginko-i18n/core';
|
|
5
6
|
import 'comark';
|
|
6
7
|
|
|
@@ -16,7 +17,7 @@ declare const GinkoMarkdown: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
16
17
|
};
|
|
17
18
|
/** The site's component registry (`components` in ginko.config.ts): a component keeps the props it declares there. Without it a component gets only `title`, `lang`, `dir` and `aria-*`. */
|
|
18
19
|
registry: {
|
|
19
|
-
type: PropType<
|
|
20
|
+
type: PropType<AttributeRegistry>;
|
|
20
21
|
default: undefined;
|
|
21
22
|
};
|
|
22
23
|
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
@@ -33,13 +34,13 @@ declare const GinkoMarkdown: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
33
34
|
};
|
|
34
35
|
/** The site's component registry (`components` in ginko.config.ts): a component keeps the props it declares there. Without it a component gets only `title`, `lang`, `dir` and `aria-*`. */
|
|
35
36
|
registry: {
|
|
36
|
-
type: PropType<
|
|
37
|
+
type: PropType<AttributeRegistry>;
|
|
37
38
|
default: undefined;
|
|
38
39
|
};
|
|
39
40
|
}>> & Readonly<{}>, {
|
|
40
41
|
value: MarkdownTree | null | undefined;
|
|
41
42
|
components: Record<string, string | Component>;
|
|
42
|
-
registry:
|
|
43
|
+
registry: AttributeRegistry;
|
|
43
44
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
44
45
|
|
|
45
46
|
export { GinkoMarkdown };
|
package/dist/vue.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
2
|
import { PropType, Component } from 'vue';
|
|
3
|
-
import { MarkdownTree
|
|
3
|
+
import { MarkdownTree } from './index.js';
|
|
4
|
+
import { AttributeRegistry } from './internal.js';
|
|
4
5
|
import '@lupinum/ginko-i18n/core';
|
|
5
6
|
import 'comark';
|
|
6
7
|
|
|
@@ -16,7 +17,7 @@ declare const GinkoMarkdown: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
16
17
|
};
|
|
17
18
|
/** The site's component registry (`components` in ginko.config.ts): a component keeps the props it declares there. Without it a component gets only `title`, `lang`, `dir` and `aria-*`. */
|
|
18
19
|
registry: {
|
|
19
|
-
type: PropType<
|
|
20
|
+
type: PropType<AttributeRegistry>;
|
|
20
21
|
default: undefined;
|
|
21
22
|
};
|
|
22
23
|
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
@@ -33,13 +34,13 @@ declare const GinkoMarkdown: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
33
34
|
};
|
|
34
35
|
/** The site's component registry (`components` in ginko.config.ts): a component keeps the props it declares there. Without it a component gets only `title`, `lang`, `dir` and `aria-*`. */
|
|
35
36
|
registry: {
|
|
36
|
-
type: PropType<
|
|
37
|
+
type: PropType<AttributeRegistry>;
|
|
37
38
|
default: undefined;
|
|
38
39
|
};
|
|
39
40
|
}>> & Readonly<{}>, {
|
|
40
41
|
value: MarkdownTree | null | undefined;
|
|
41
42
|
components: Record<string, string | Component>;
|
|
42
|
-
registry:
|
|
43
|
+
registry: AttributeRegistry;
|
|
43
44
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
44
45
|
|
|
45
46
|
export { GinkoMarkdown };
|