@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.
Files changed (89) hide show
  1. package/CHANGELOG.md +150 -0
  2. package/README.md +2 -2
  3. package/dist/basics.d.mts +492 -0
  4. package/dist/basics.d.ts +492 -0
  5. package/dist/basics.mjs +416 -0
  6. package/dist/cli/index.mjs +54 -55
  7. package/dist/index.d.mts +5 -4
  8. package/dist/index.d.ts +5 -4
  9. package/dist/index.mjs +3 -3
  10. package/dist/internal/search.mjs +6 -3
  11. package/dist/internal.d.mts +387 -41
  12. package/dist/internal.d.ts +387 -41
  13. package/dist/internal.mjs +267 -101
  14. package/dist/nuxt/module.d.mts +2 -2
  15. package/dist/nuxt/module.d.ts +2 -2
  16. package/dist/nuxt/module.mjs +105 -13
  17. package/dist/nuxt/runtime/GinkoImage.d.mts +1 -1
  18. package/dist/nuxt/runtime/GinkoMarkdown.mjs +2 -2
  19. package/dist/nuxt/runtime/composables.d.mts +4 -3
  20. package/dist/nuxt/runtime/composables.mjs +19 -15
  21. package/dist/nuxt/runtime/fetch.d.mts +3 -1
  22. package/dist/nuxt/runtime/fetch.mjs +12 -6
  23. package/dist/nuxt/runtime/markdown.d.mts +3 -0
  24. package/dist/nuxt/runtime/markdown.mjs +15 -3
  25. package/dist/nuxt/runtime/plugin.mjs +6 -35
  26. package/dist/nuxt/runtime/preview-listener.d.mts +13 -0
  27. package/dist/nuxt/runtime/preview-listener.mjs +37 -0
  28. package/dist/nuxt/runtime/preview.vue +3 -1
  29. package/dist/nuxt/runtime/schema.d.ts +6 -0
  30. package/dist/nuxt/runtime/server/bundles.d.ts +4 -0
  31. package/dist/nuxt/runtime/server/files-md.d.ts +2 -0
  32. package/dist/nuxt/runtime/server/files.d.ts +2 -0
  33. package/dist/nuxt/runtime/server/headers.d.ts +2 -0
  34. package/dist/nuxt/runtime/server/items.d.mts +12 -0
  35. package/dist/nuxt/runtime/server/items.d.ts +12 -0
  36. package/dist/nuxt/runtime/server/items.mjs +17 -0
  37. package/dist/nuxt/runtime/server/llms-full.d.ts +2 -0
  38. package/dist/nuxt/runtime/server/llms.d.ts +2 -0
  39. package/dist/nuxt/runtime/server/markdown-trees.d.ts +2 -0
  40. package/dist/nuxt/runtime/server/markdown.d.ts +2 -0
  41. package/dist/nuxt/runtime/server/markdown.mjs +1 -1
  42. package/dist/nuxt/runtime/server/platform-md.d.mts +3 -0
  43. package/dist/nuxt/runtime/server/platform-md.d.ts +3 -0
  44. package/dist/nuxt/runtime/server/platform-md.mjs +71 -0
  45. package/dist/nuxt/runtime/server/redirects.d.ts +2 -0
  46. package/dist/nuxt/runtime/server/robots.d.ts +2 -0
  47. package/dist/nuxt/runtime/server/search.d.ts +2 -0
  48. package/dist/nuxt/runtime/server/site-config.d.ts +14 -0
  49. package/dist/nuxt/runtime/server/sitemap-source.d.ts +2 -0
  50. package/dist/nuxt/runtime/server/sitemap-xml.d.ts +24 -0
  51. package/dist/nuxt/runtime/server/sitemap.d.ts +2 -0
  52. package/dist/nuxt/runtime/shared.d.mts +10 -3
  53. package/dist/nuxt/runtime/shared.mjs +2 -2
  54. package/dist/shared/ginko.1wwZv4B_.d.ts +1622 -0
  55. package/dist/shared/{ginko.BBkZW2nW.d.ts → ginko.6cI8KXZP.d.mts} +2 -2
  56. package/dist/shared/{ginko.CQvxhyez.mjs → ginko.AprJymER.mjs} +30 -1
  57. package/dist/shared/ginko.BNVC-g9n.mjs +10389 -0
  58. package/dist/shared/{ginko.Bwan3BB-.d.mts → ginko.B_pACpVU.d.ts} +2 -2
  59. package/dist/shared/{ginko.CrNRBkS5.mjs → ginko.C4gcOovG.mjs} +253 -309
  60. package/dist/shared/{ginko.C90fPpMP.mjs → ginko.CXA2R3aS.mjs} +128 -101
  61. package/dist/shared/ginko.CjWB8N7f.d.ts +128 -0
  62. package/dist/shared/ginko.D1PeQ3ds.mjs +36 -0
  63. package/dist/shared/ginko.DIl7l-75.mjs +26 -0
  64. package/dist/shared/ginko.DY7RbCEw.mjs +601 -0
  65. package/dist/shared/ginko.Dmgixfpf.mjs +130 -0
  66. package/dist/shared/{ginko.D-fNojn9.d.mts → ginko.DrkUeYFP.d.mts} +824 -10
  67. package/dist/shared/{ginko.D-fNojn9.d.ts → ginko.DrkUeYFP.d.ts} +824 -10
  68. package/dist/shared/{ginko.akHewCGt.d.mts → ginko.DvPtlHIz.d.mts} +50 -5
  69. package/dist/shared/{ginko.BDF3bW0C.d.ts → ginko.EelR5dt9.d.ts} +50 -5
  70. package/dist/shared/ginko.ULKQnAWd.d.ts +91 -0
  71. package/dist/shared/ginko.loGIxGZg.d.mts +91 -0
  72. package/dist/shared/ginko.o1yIKlgj.d.mts +128 -0
  73. package/dist/shared/ginko.plW4dLmm.d.mts +1622 -0
  74. package/dist/shared/{ginko.Dht0xxE5.mjs → ginko.raCzOPYC.mjs} +1 -2
  75. package/dist/shared/ginko.yKMIjJ68.mjs +84 -0
  76. package/dist/vue.d.mts +5 -4
  77. package/dist/vue.d.ts +5 -4
  78. package/dist/vue.mjs +1 -1
  79. package/i18n/ar.json +212 -0
  80. package/i18n/de.json +9 -1
  81. package/i18n/en.json +9 -1
  82. package/i18n/es.json +12 -4
  83. package/i18n/fr.json +212 -0
  84. package/i18n/it.json +212 -0
  85. package/package.json +7 -3
  86. package/dist/shared/ginko.BTUfZCfa.d.mts +0 -172
  87. package/dist/shared/ginko.C-QjDn3O.mjs +0 -4944
  88. package/dist/shared/ginko.Dc0oNcDv.d.ts +0 -172
  89. package/dist/shared/ginko.Mn30dmlm.mjs +0 -20
@@ -0,0 +1,416 @@
1
+ import { f, O as studioLabel } from './shared/ginko.BNVC-g9n.mjs';
2
+ import { s as single, o as organizationLd, c as collection, a as compact, e as articleLd, p as postalAddressLd, g as faqLd } from './shared/ginko.Dmgixfpf.mjs';
3
+ export { w as withoutFiles } from './shared/ginko.Dmgixfpf.mjs';
4
+ import { s as sourceOf, w as weekFor, a as addDays, h as hoursOn, b as weekdayOf, c as spansOf, d as weekdayKeys, e as both } from './shared/ginko.DY7RbCEw.mjs';
5
+ export { f as austrianHolidays, g as calendarIn, i as calendarOf, j as closedOnClosure, k as eventJsonLd, l as events, m as germanHolidays, n as holidayOn, o as hourPlans, p as hours, q as hoursLine, r as notices, t as noticesOn, u as offerJsonLd, v as planOn, x as sessions, y as sessionsInOrder, z as singaporeHolidays, A as spansText, B as timesOf, C as todayState, D as upcomingClosures, E as upcomingHolidayClosures, F as upcomingPlans, G as weekOf } from './shared/ginko.DY7RbCEw.mjs';
6
+ import { l as limitOf } from './shared/ginko.D1PeQ3ds.mjs';
7
+ export { c as calendarOfCountry } from './shared/ginko.D1PeQ3ds.mjs';
8
+ import 'comark';
9
+ import 'comark/plugins/alert';
10
+ import 'comark/plugins/attributes';
11
+ import 'comark/plugins/components';
12
+ import 'comark/plugins/emoji';
13
+ import 'comark/plugins/footnotes';
14
+ import 'comark/plugins/frontmatter';
15
+ import 'comark/plugins/math';
16
+ import 'comark/plugins/mermaid';
17
+ import 'comark/plugins/task-list';
18
+ import 'comark/plugins/toc';
19
+ import '@lupinum/ginko-i18n/core';
20
+ import './shared/ginko.AprJymER.mjs';
21
+
22
+ function site(o = {}) {
23
+ const plain = { optional: true, translate: false };
24
+ const fields = {
25
+ legalName: f.text(studioLabel("Offizieller Name", "Legal name", "Nombre legal", "Raison sociale"), {
26
+ ...plain,
27
+ hint: studioLabel("Wie im Register eingetragen.", "As registered.", "Tal como figura en el registro.", "Tel qu\u2019enregistr\xE9.")
28
+ }),
29
+ street: f.text(studioLabel("Stra\xDFe und Hausnummer", "Street and number", "Calle y n\xFAmero", "Rue et num\xE9ro"), plain),
30
+ postalCode: f.text(studioLabel("Postleitzahl", "Postcode", "C\xF3digo postal", "Code postal"), { ...plain, max: 10 }),
31
+ city: f.text(studioLabel("Ort", "Town or city", "Localidad", "Ville"), plain),
32
+ email: f.text(studioLabel("E-Mail", "Email", "Correo electr\xF3nico", "E-mail"), { optional: true, format: "email" }),
33
+ phone: f.text(studioLabel("Telefon", "Phone", "Tel\xE9fono", "T\xE9l\xE9phone"), {
34
+ optional: true,
35
+ format: "tel",
36
+ hint: studioLabel("Mit L\xE4ndervorwahl.", "With country code.", "Con prefijo internacional.", "Avec l\u2019indicatif du pays.")
37
+ }),
38
+ registryNumber: f.text(studioLabel("Registernummer", "Registration number", "N\xFAmero de registro", "Num\xE9ro d\u2019immatriculation"), plain),
39
+ registryCourt: f.text(studioLabel("Registergericht", "Registry", "Registro", "Greffe"), { optional: true }),
40
+ vatId: f.text(studioLabel("Umsatzsteuer-ID", "VAT number", "NIF-IVA", "Num\xE9ro de TVA"), plain)
41
+ };
42
+ return single({
43
+ label: o.label ?? studioLabel("Kontakt und Anschrift", "Contact and address", "Contacto y direcci\xF3n", "Contact et adresse"),
44
+ describe: studioLabel(
45
+ "Name, Anschrift und Kontakt, zum Beispiel f\xFCr das Impressum und die Fu\xDFzeile.",
46
+ "Name, address and contact details, for example for the imprint and the footer.",
47
+ "Nombre, direcci\xF3n y datos de contacto, por ejemplo para el aviso legal y el pie de p\xE1gina.",
48
+ "Nom, adresse et coordonn\xE9es, par exemple pour les mentions l\xE9gales et le pied de page."
49
+ ),
50
+ ...sourceOf(o),
51
+ fields,
52
+ tasks: [{
53
+ id: "edit",
54
+ kind: "edit",
55
+ label: studioLabel("Kontaktdaten \xE4ndern", "Change contact details", "Cambiar los datos de contacto", "Modifier les coordonn\xE9es"),
56
+ fields: Object.keys(fields)
57
+ }]
58
+ });
59
+ }
60
+ function siteJsonLd(data, o) {
61
+ return organizationLd({
62
+ ...o,
63
+ legalName: data.legalName,
64
+ email: data.email,
65
+ telephone: data.phone,
66
+ address: { street: data.street, postalCode: data.postalCode, city: data.city, country: o.country },
67
+ vatID: data.vatId
68
+ });
69
+ }
70
+
71
+ const legalTypes = [
72
+ { value: "privacy", label: studioLabel("Datenschutz", "Privacy policy", "Pol\xEDtica de privacidad", "Politique de confidentialit\xE9") },
73
+ { value: "customer-privacy", label: studioLabel("Datenschutz f\xFCr Kunden", "Privacy policy for customers", "Privacidad para clientes", "Confidentialit\xE9 pour les clients") },
74
+ { value: "imprint", label: studioLabel("Impressum", "Imprint", "Aviso legal", "Mentions l\xE9gales") },
75
+ { value: "terms", label: studioLabel("AGB", "Terms and conditions", "T\xE9rminos y condiciones", "Conditions g\xE9n\xE9rales") },
76
+ { value: "cookies", label: studioLabel("Cookies", "Cookie policy", "Pol\xEDtica de cookies", "Politique relative aux cookies") },
77
+ { value: "accessibility", label: studioLabel("Barrierefreiheit", "Accessibility statement", "Declaraci\xF3n de accesibilidad", "D\xE9claration d\u2019accessibilit\xE9") }
78
+ ];
79
+ function legal(o = {}) {
80
+ return collection({
81
+ label: o.label ?? studioLabel("Rechtliches", "Legal", "Textos legales", "Informations l\xE9gales"),
82
+ ...sourceOf(o),
83
+ max: 20,
84
+ order: "manual",
85
+ ...o.route ? { route: o.route } : {},
86
+ tasks: [{
87
+ id: "update",
88
+ kind: "edit",
89
+ pick: true,
90
+ fields: ["body", "updatedAt"],
91
+ prefill: { updatedAt: "@today" },
92
+ label: studioLabel("Rechtstext aktualisieren", "Update a legal text", "Actualizar un texto legal", "Mettre \xE0 jour un texte juridique")
93
+ }],
94
+ fields: {
95
+ title: f.text(studioLabel("Titel", "Title", "T\xEDtulo", "Titre")),
96
+ description: f.longtext(studioLabel("Beschreibung", "Description", "Descripci\xF3n", "Description"), { optional: true }),
97
+ slug: f.slug(studioLabel("Adresse", "Address", "Direcci\xF3n", "Adresse"), { from: "title" }),
98
+ legalType: f.choice(studioLabel("Art", "Kind", "Tipo", "Type"), { options: legalTypes }),
99
+ updatedAt: f.date(studioLabel("Stand", "Last updated", "\xDAltima actualizaci\xF3n", "Derni\xE8re mise \xE0 jour")),
100
+ // Never machine-translated: a legal text in another language is a legal text of its own.
101
+ body: f.markdown(studioLabel("Text", "Text", "Texto", "Texte"), { translate: "manual" })
102
+ }
103
+ });
104
+ }
105
+
106
+ const slugField = () => f.slug(studioLabel("Adresse", "Address", "Direcci\xF3n", "Adresse"), { from: "name" });
107
+ function people(o = {}) {
108
+ return collection({
109
+ label: o.label ?? studioLabel("Personen", "People", "Personas", "Personnes"),
110
+ ...sourceOf(o),
111
+ max: 100,
112
+ order: "manual",
113
+ ...o.route ? { route: o.route } : {},
114
+ tasks: [
115
+ { id: "add", kind: "create", label: studioLabel("Person hinzuf\xFCgen", "Add a person", "A\xF1adir una persona", "Ajouter une personne") },
116
+ { id: "edit", kind: "edit", pick: true, fields: ["name", "role", "bio", "email", "phone", "photo"], label: studioLabel("Person bearbeiten", "Edit a person", "Editar una persona", "Modifier une personne") },
117
+ { id: "remove", kind: "remove", label: studioLabel("Person entfernen", "Remove a person", "Eliminar una persona", "Retirer une personne") }
118
+ ],
119
+ fields: {
120
+ // A name is the same in every language.
121
+ name: f.text(studioLabel("Name", "Name", "Nombre", "Nom"), { translate: false }),
122
+ role: f.text(studioLabel("Rolle", "Role", "Funci\xF3n", "Fonction"), { optional: true }),
123
+ bio: f.longtext(studioLabel("Kurzbiografie", "Short bio", "Biograf\xEDa breve", "Courte biographie"), { optional: true }),
124
+ email: f.text(studioLabel("E-Mail", "Email", "Correo electr\xF3nico", "E-mail"), { optional: true, format: "email", translate: false }),
125
+ phone: f.text(studioLabel("Telefon", "Phone", "Tel\xE9fono", "T\xE9l\xE9phone"), { optional: true, format: "tel", translate: false }),
126
+ photo: f.image(studioLabel("Foto", "Photo", "Foto", "Photo"), { optional: true }),
127
+ // Only with a route: the stored shape of people without pages does not change.
128
+ // `o.route` is the runtime value of `R`, so the spread matches SlugOf<R>; TypeScript cannot narrow a generic by it.
129
+ ...o.route ? { slug: slugField() } : {}
130
+ }
131
+ });
132
+ }
133
+ function personJsonLd(p) {
134
+ return compact({
135
+ "@context": "https://schema.org",
136
+ "@type": "Person",
137
+ name: p.name,
138
+ jobTitle: p.role,
139
+ description: p.bio,
140
+ email: p.email,
141
+ telephone: p.phone,
142
+ image: p.image,
143
+ url: p.url,
144
+ worksFor: p.worksFor ? compact({ "@type": "Organization", name: p.worksFor.name, url: p.worksFor.url }) : void 0
145
+ });
146
+ }
147
+
148
+ function posts(o = {}) {
149
+ const tag = studioLabel("Schlagwort", "Tag", "Etiqueta", "Mot-cl\xE9");
150
+ return collection({
151
+ label: o.label ?? studioLabel("Beitr\xE4ge", "Posts", "Art\xEDculos", "Articles"),
152
+ ...sourceOf(o),
153
+ max: o.max ?? 500,
154
+ order: { field: "date", dir: "desc" },
155
+ ...o.route ? { route: o.route } : {},
156
+ fields: {
157
+ title: f.text(studioLabel("Titel", "Title", "T\xEDtulo", "Titre")),
158
+ description: f.longtext(studioLabel("Beschreibung", "Description", "Descripci\xF3n", "Description"), { optional: true }),
159
+ date: f.date(studioLabel("Datum", "Date", "Fecha", "Date")),
160
+ authors: f.refs(studioLabel("Autorinnen und Autoren", "Authors", "Autores", "Auteurs"), { to: o.authors ?? "authors", optional: true }),
161
+ image: f.image(studioLabel("Bild", "Image", "Imagen", "Image"), { optional: true }),
162
+ tags: f.list(studioLabel("Schlagw\xF6rter", "Tags", "Etiquetas", "Mots-cl\xE9s"), { itemLabel: tag, fields: { tag: f.text(tag, { max: 40 }) }, max: 10, optional: true }),
163
+ slug: f.slug(studioLabel("Adresse", "Address", "Direcci\xF3n", "Adresse"), { from: "title" }),
164
+ body: f.markdown(studioLabel("Text", "Text", "Texto", "Texte"), { profile: "page" })
165
+ }
166
+ });
167
+ }
168
+ function authors(o = {}) {
169
+ return collection({
170
+ label: o.label ?? studioLabel("Autorinnen und Autoren", "Authors", "Autores", "Auteurs"),
171
+ ...sourceOf(o),
172
+ max: 100,
173
+ order: "manual",
174
+ fields: {
175
+ name: f.text(studioLabel("Name", "Name", "Nombre", "Nom")),
176
+ role: f.text(studioLabel("Rolle", "Role", "Funci\xF3n", "Fonction"), { optional: true }),
177
+ avatar: f.image(studioLabel("Bild", "Image", "Imagen", "Image"), { optional: true }),
178
+ /** Shown as a link on the author's name. */
179
+ url: f.text(studioLabel("Website", "Website", "Sitio web", "Site web"), { format: "url", optional: true })
180
+ }
181
+ });
182
+ }
183
+ function changelog(o = {}) {
184
+ return collection({
185
+ label: o.label ?? studioLabel("\xC4nderungen", "Changelog", "Registro de cambios", "Journal des modifications"),
186
+ ...sourceOf(o),
187
+ max: o.max ?? 500,
188
+ order: { field: "date", dir: "desc" },
189
+ // A release written ahead is the normal case: an entry dated after the build day is scheduled, `draft: true` holds it back.
190
+ drafts: true,
191
+ fields: {
192
+ version: f.text(studioLabel("Version", "Version", "Versi\xF3n", "Version"), { max: 40, translate: false }),
193
+ date: f.date(studioLabel("Datum", "Date", "Fecha", "Date")),
194
+ body: f.markdown(studioLabel("Text", "Text", "Texto", "Texte"), { profile: "page" })
195
+ }
196
+ });
197
+ }
198
+ function releaseAnchor(version) {
199
+ return `v${version.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}`;
200
+ }
201
+ function postJsonLd(p) {
202
+ return articleLd({
203
+ type: "BlogPosting",
204
+ title: p.title,
205
+ url: p.url,
206
+ description: p.description,
207
+ image: p.image,
208
+ published: p.date,
209
+ modified: p.modified,
210
+ author: p.authors,
211
+ keywords: p.tags,
212
+ lang: p.lang
213
+ });
214
+ }
215
+
216
+ const employmentTypes = [
217
+ { value: "fullTime", label: studioLabel("Vollzeit", "Full time", "Jornada completa", "Temps plein") },
218
+ { value: "partTime", label: studioLabel("Teilzeit", "Part time", "Media jornada", "Temps partiel") },
219
+ { value: "freelance", label: studioLabel("Freie Mitarbeit", "Freelance", "Aut\xF3nomo", "Ind\xE9pendant") },
220
+ { value: "internship", label: studioLabel("Praktikum", "Internship", "Pr\xE1cticas", "Stage") },
221
+ { value: "apprenticeship", label: studioLabel("Lehre", "Apprenticeship", "Formaci\xF3n profesional", "Apprentissage") }
222
+ ];
223
+ const workPlaces = [
224
+ { value: "onsite", label: studioLabel("Vor Ort", "On site", "Presencial", "Sur place") },
225
+ { value: "hybrid", label: studioLabel("Hybrid", "Hybrid", "H\xEDbrido", "Hybride") },
226
+ { value: "remote", label: studioLabel("Remote", "Remote", "Remoto", "\xC0 distance") }
227
+ ];
228
+ function jobs(o = {}) {
229
+ return collection({
230
+ label: o.label ?? studioLabel("Stellen", "Jobs", "Empleos", "Offres d\u2019emploi"),
231
+ ...sourceOf(o),
232
+ max: 30,
233
+ order: { field: "title", dir: "asc" },
234
+ ...o.route ? { route: o.route } : {},
235
+ visible: { mode: "until", field: "validUntil" },
236
+ tasks: [
237
+ { id: "add", kind: "create", label: studioLabel("Stelle ausschreiben", "Post a job", "Publicar una oferta", "Publier une offre") },
238
+ { id: "extend", kind: "edit", pick: true, fields: ["validUntil"], label: studioLabel("Bewerbungsfrist \xE4ndern", "Change the deadline", "Cambiar el plazo", "Modifier la date limite") },
239
+ { id: "remove", kind: "remove", label: studioLabel("Stelle entfernen", "Remove a job", "Eliminar una oferta", "Retirer une offre") }
240
+ ],
241
+ fields: {
242
+ title: f.text(studioLabel("Titel", "Title", "T\xEDtulo", "Titre")),
243
+ description: f.longtext(studioLabel("Kurzbeschreibung", "Short description", "Descripci\xF3n breve", "Description courte")),
244
+ slug: f.slug(studioLabel("Adresse", "Address", "Direcci\xF3n", "Adresse"), { from: "title" }),
245
+ location: f.text(studioLabel("Ort", "Location", "Ubicaci\xF3n", "Lieu")),
246
+ employmentType: f.choice(studioLabel("Anstellung", "Employment", "Tipo de contrato", "Type de contrat"), { options: employmentTypes }),
247
+ remote: f.choice(studioLabel("Arbeitsort", "Work place", "Lugar de trabajo", "Lieu de travail"), { options: workPlaces, default: "onsite" }),
248
+ applyUrl: f.text(studioLabel("Bewerbungs-Link", "Application link", "Enlace de solicitud", "Lien de candidature"), { format: "url", optional: true }),
249
+ applyEmail: f.text(studioLabel("Bewerbungs-E-Mail", "Application email", "Correo de solicitud", "E-mail de candidature"), { format: "email", optional: true }),
250
+ validUntil: f.date(studioLabel("Ausgeschrieben bis", "Open until", "Abierta hasta", "Ouverte jusqu\u2019au"), {
251
+ hint: studioLabel("Am Tag danach verschwindet die Stelle von der Website.", "The job leaves the website the day after.", "La oferta desaparece del sitio web al d\xEDa siguiente.", "L\u2019offre dispara\xEEt du site le lendemain.")
252
+ }),
253
+ body: f.markdown(studioLabel("Beschreibung", "Description", "Descripci\xF3n", "Description"))
254
+ }
255
+ });
256
+ }
257
+ const SCHEMA_EMPLOYMENT = {
258
+ fullTime: "FULL_TIME",
259
+ partTime: "PART_TIME",
260
+ freelance: "CONTRACTOR",
261
+ internship: "INTERN",
262
+ apprenticeship: "OTHER"
263
+ };
264
+ function jobJsonLd(j) {
265
+ const remote = j.remote === "remote";
266
+ return compact({
267
+ "@context": "https://schema.org",
268
+ "@type": "JobPosting",
269
+ title: j.title,
270
+ url: j.url,
271
+ description: j.description,
272
+ datePosted: j.datePosted,
273
+ validThrough: j.validUntil,
274
+ employmentType: j.employmentType && Object.hasOwn(SCHEMA_EMPLOYMENT, j.employmentType) ? SCHEMA_EMPLOYMENT[j.employmentType] : void 0,
275
+ hiringOrganization: compact({ "@type": "Organization", name: j.organization.name, sameAs: j.organization.url, logo: j.organization.logo }),
276
+ jobLocation: j.location ? { "@type": "Place", address: postalAddressLd({ city: j.location, country: j.country }) } : void 0,
277
+ jobLocationType: remote ? "TELECOMMUTE" : void 0,
278
+ applicantLocationRequirements: remote && j.country ? { "@type": "Country", name: j.country } : void 0
279
+ });
280
+ }
281
+
282
+ function faq(o = {}) {
283
+ return collection({
284
+ label: o.label ?? studioLabel("H\xE4ufige Fragen", "FAQ", "Preguntas frecuentes", "Questions fr\xE9quentes"),
285
+ ...sourceOf(o),
286
+ max: 100,
287
+ order: "manual",
288
+ tasks: [
289
+ { id: "add", kind: "create", label: studioLabel("Frage hinzuf\xFCgen", "Add a question", "A\xF1adir una pregunta", "Ajouter une question") },
290
+ { id: "edit", kind: "edit", pick: true, fields: ["question", "answer"], label: studioLabel("Frage bearbeiten", "Edit a question", "Editar una pregunta", "Modifier une question") },
291
+ { id: "remove", kind: "remove", label: studioLabel("Frage entfernen", "Remove a question", "Eliminar una pregunta", "Retirer une question") }
292
+ ],
293
+ fields: {
294
+ question: f.text(studioLabel("Frage", "Question", "Pregunta", "Question")),
295
+ answer: f.longtext(studioLabel("Antwort", "Answer", "Respuesta", "R\xE9ponse"))
296
+ }
297
+ });
298
+ }
299
+ function faqJsonLd(items) {
300
+ return faqLd([...items]);
301
+ }
302
+
303
+ function downloads(o = {}) {
304
+ return collection({
305
+ label: o.label ?? studioLabel("Downloads", "Downloads", "Descargas", "T\xE9l\xE9chargements"),
306
+ ...sourceOf(o),
307
+ max: 100,
308
+ order: { field: "date", dir: "desc" },
309
+ tasks: [
310
+ { id: "add", kind: "create", label: studioLabel("Datei hinzuf\xFCgen", "Add a file", "A\xF1adir un archivo", "Ajouter un fichier") },
311
+ { id: "edit", kind: "edit", pick: true, fields: ["title", "summary", "date", "file", "language"], label: studioLabel("Datei bearbeiten", "Edit a file", "Editar un archivo", "Modifier un fichier") },
312
+ { id: "remove", kind: "remove", label: studioLabel("Datei entfernen", "Remove a file", "Eliminar un archivo", "Retirer un fichier") }
313
+ ],
314
+ fields: {
315
+ title: f.text(studioLabel("Titel", "Title", "T\xEDtulo", "Titre")),
316
+ summary: f.longtext(studioLabel("Kurzbeschreibung", "Summary", "Resumen", "R\xE9sum\xE9"), { optional: true }),
317
+ date: f.date(studioLabel("Datum", "Date", "Fecha", "Date")),
318
+ file: f.file(studioLabel("Datei", "File", "Archivo", "Fichier"), { accept: ["pdf"], maxBytes: limitOf("file") }),
319
+ // The language of the document (a code such as `en`): one file serves every language of the site, so the list
320
+ // can say "in English" on the German page. Empty: the site's main language.
321
+ language: f.text(studioLabel("Sprache des Dokuments", "Language of the document", "Idioma del documento", "Langue du document"), {
322
+ optional: true,
323
+ translate: false,
324
+ max: 35,
325
+ hint: studioLabel("Sprachcode, zum Beispiel de oder en.", "A language code, for example en or de.", "Un c\xF3digo de idioma, por ejemplo es o en.", "Un code de langue, par exemple fr ou en.")
326
+ })
327
+ }
328
+ });
329
+ }
330
+
331
+ const escapeXml = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
332
+ const rfc822 = (day) => (/* @__PURE__ */ new Date(`${day}T00:00:00Z`)).toUTCString();
333
+ const tag = (name, value) => `<${name}>${escapeXml(value)}</${name}>`;
334
+ function rssXml(feed) {
335
+ const items = feed.items.map((item) => [
336
+ " <item>",
337
+ ` ${tag("title", item.title)}`,
338
+ ` ${tag("link", item.link)}`,
339
+ ` <guid isPermaLink="true">${escapeXml(item.link)}</guid>`,
340
+ ` ${tag("pubDate", rfc822(item.date))}`,
341
+ ...item.description ? [` ${tag("description", item.description)}`] : [],
342
+ ...item.authors.map((a) => ` ${tag("dc:creator", a)}`),
343
+ " </item>"
344
+ ].join("\n"));
345
+ const newest = feed.items.map((i) => i.date).sort().at(-1);
346
+ return [
347
+ '<?xml version="1.0" encoding="UTF-8"?>',
348
+ '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">',
349
+ " <channel>",
350
+ ` ${tag("title", feed.title)}`,
351
+ ` ${tag("link", feed.link)}`,
352
+ ` ${tag("description", feed.description)}`,
353
+ ` ${tag("language", feed.language)}`,
354
+ ...newest ? [` ${tag("lastBuildDate", rfc822(newest))}`] : [],
355
+ ` <atom:link href="${escapeXml(feed.self)}" rel="self" type="application/rss+xml"/>`,
356
+ ...items,
357
+ " </channel>",
358
+ "</rss>",
359
+ ""
360
+ ].join("\n");
361
+ }
362
+
363
+ const dayNames = { mo: "Monday", tu: "Tuesday", we: "Wednesday", th: "Thursday", fr: "Friday", sa: "Saturday", su: "Sunday" };
364
+ const spanKey = (spans) => spans.map((s) => `${s.from}-${s.to}`).join(",");
365
+ function weeklySpecs(week) {
366
+ const groups = /* @__PURE__ */ new Map();
367
+ for (const key of weekdayKeys) {
368
+ const day = week.find((d) => d.day === key);
369
+ const spans = !day || day.closed ? [] : spansOf(day);
370
+ if (!spans.length) continue;
371
+ const k = spanKey(spans);
372
+ const group = groups.get(k) ?? { spans, days: [] };
373
+ group.days.push(key);
374
+ groups.set(k, group);
375
+ }
376
+ return [...groups.values()].flatMap((g) => g.spans.map((s) => ({ "@type": "OpeningHoursSpecification", dayOfWeek: g.days.map((d) => dayNames[d]), opens: s.from, closes: s.to })));
377
+ }
378
+ function specialSpecs(ctx, today, days, week) {
379
+ const runs = [];
380
+ for (let i = 0; i < days; i++) {
381
+ const date = addDays(today, i);
382
+ const rule = hoursOn(ctx, date);
383
+ const base = week.find((d) => d.day === weekdayOf(date));
384
+ const baseKey = !base || base.closed ? "" : spanKey(spansOf(base));
385
+ const key = rule.closed ? "" : spanKey(rule.times);
386
+ if (key === baseKey) continue;
387
+ const last = runs[runs.length - 1];
388
+ if (last && last.key === key && last.to === addDays(date, -1)) last.to = date;
389
+ else runs.push({ key, spans: rule.closed ? [] : rule.times, from: date, to: date });
390
+ }
391
+ return runs.flatMap((r) => (r.spans.length ? r.spans : [{ from: "00:00", to: "00:00" }]).map((s) => ({
392
+ "@type": "OpeningHoursSpecification",
393
+ validFrom: r.from,
394
+ validThrough: r.to,
395
+ opens: s.from,
396
+ closes: s.to
397
+ })));
398
+ }
399
+ function openingHoursJsonLd(ctx, today, days = 60) {
400
+ const { week } = weekFor(ctx, today);
401
+ const special = specialSpecs(ctx, today, days, week);
402
+ return { openingHoursSpecification: weeklySpecs(week), ...special.length ? { specialOpeningHoursSpecification: special } : {} };
403
+ }
404
+
405
+ function gallery(opts = {}) {
406
+ return single({
407
+ label: opts.label ?? both("Galerie", "Gallery"),
408
+ ...sourceOf(opts),
409
+ fields: {
410
+ images: f.list(both("Bilder", "Images"), { itemLabel: both("Bild", "Image"), fields: { image: f.image(both("Bild", "Image")) }, max: 24, default: [] })
411
+ },
412
+ tasks: [{ id: "edit", label: both("Fotos bearbeiten", "Edit photos"), kind: "edit", fields: ["images"] }]
413
+ });
414
+ }
415
+
416
+ export { authors, changelog, downloads, faq, faqJsonLd, gallery, hoursOn, jobJsonLd, jobs, legal, legalTypes, openingHoursJsonLd, people, personJsonLd, postJsonLd, posts, releaseAnchor, rssXml, site, siteJsonLd, spansOf, weekFor, weekdayOf };
@@ -2,12 +2,15 @@
2
2
  import { existsSync, realpathSync, readFileSync } from 'node:fs';
3
3
  import { join, dirname, resolve } from 'node:path';
4
4
  import { pathToFileURL, fileURLToPath } from 'node:url';
5
- import { f as fileLinkIssues } from '../shared/ginko.Dht0xxE5.mjs';
6
- import { n as coreMessage, i as isTranslatable } from '../shared/ginko.C-QjDn3O.mjs';
7
- import { s as serializeSchema, a as checkSite, G as validate, g as SITE_BUDGET, A as platformSchema, j as checkSchema } from '../shared/ginko.CrNRBkS5.mjs';
8
- import { e as defaultsFor, h as fieldsChanged, r as releaseData, m as markdownTrees, g as diffSchema } from '../shared/ginko.C90fPpMP.mjs';
5
+ import { C as CliError, i as isObject, d as defaultsFor, f as fieldsChanged, r as releaseData, S as SITE_BUDGET, e as entryBytes, a as fitsBudget, b as diffSchema, l as largestEntryBytes, c as largestFieldBytes, p as parseExport, g as parseReleaseState, h as pathOf, j as defaultDir } from '../shared/ginko.CXA2R3aS.mjs';
6
+ import { f as fileLinkIssues } from '../shared/ginko.raCzOPYC.mjs';
7
+ import { F as coreMessage, i as isTranslatable, g as effectiveMax } from '../shared/ginko.BNVC-g9n.mjs';
8
+ import { s as serializeSchema, c as checkSite, v as validate, p as platformSchema, a as checkSchema } from '../shared/ginko.C4gcOovG.mjs';
9
+ import { c as calendarOfCountry } from '../shared/ginko.D1PeQ3ds.mjs';
9
10
  import { mkdir, writeFile, rm, readdir } from 'node:fs/promises';
10
11
  import { execFile } from 'node:child_process';
12
+ import '../shared/ginko.AprJymER.mjs';
13
+ import '../shared/ginko.yKMIjJ68.mjs';
11
14
  import 'comark';
12
15
  import 'comark/plugins/alert';
13
16
  import 'comark/plugins/attributes';
@@ -20,30 +23,6 @@ import 'comark/plugins/mermaid';
20
23
  import 'comark/plugins/task-list';
21
24
  import 'comark/plugins/toc';
22
25
  import '@lupinum/ginko-i18n/core';
23
- import '../shared/ginko.CQvxhyez.mjs';
24
-
25
- class CliError extends Error {
26
- code;
27
- constructor(message, code = "INVALID") {
28
- super(message);
29
- this.code = code;
30
- }
31
- }
32
- const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
33
- function parseReleaseState(value) {
34
- if (!isObject(value)) throw new CliError("The platform did not return a valid state.", "UNAVAILABLE");
35
- const { site, schema, schemaRev, contentRev, migrations, entries } = value;
36
- 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));
37
- if (!valid) throw new CliError("The platform returned an incomplete state.", "UNAVAILABLE");
38
- return value;
39
- }
40
- function parseExport(value, locator, problem) {
41
- const optionalNumber = (v) => v === void 0 || typeof v === "number";
42
- const optionalString = (v) => v === void 0 || typeof v === "string";
43
- 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.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)));
44
- if (!valid) throw new CliError(problem, "UNAVAILABLE" );
45
- return value;
46
- }
47
26
 
48
27
  async function loadConfig(path, revision = 0) {
49
28
  const url = pathToFileURL(path).href + (revision > 0 ? `?rev=${revision}` : "");
@@ -64,6 +43,7 @@ function english(m) {
64
43
  return coreMessage("en", m.key, m.params);
65
44
  }
66
45
  function explainRejected(rejected) {
46
+ if (rejected.length === 0) return [];
67
47
  const lines = ["The schema changes in a way that is not allowed:"];
68
48
  for (const r of rejected) {
69
49
  lines.push(` \u2717 ${r.path}: ${english(r)}`);
@@ -109,8 +89,6 @@ async function checkFileLinks(input) {
109
89
  return ok;
110
90
  }
111
91
 
112
- const BUDGET = SITE_BUDGET;
113
- const byteSize = (value) => new TextEncoder().encode(JSON.stringify(value ?? null)).byteLength;
114
92
  async function buildCandidate(state, site, schema) {
115
93
  const problems = checkSite(site, schema);
116
94
  const applied = new Set([...state.schema.migrations, ...state.migrations].map((m) => m.id));
@@ -175,20 +153,27 @@ async function buildCandidate(state, site, schema) {
175
153
  }
176
154
  const changedData = new Map(changed.map((c) => [c.id, c.data]));
177
155
  const bytes = { site: 0, largest: 0 };
178
- const count = (size, label) => {
156
+ let siteBefore = 0;
157
+ const limit = `the limit is ${kib(SITE_BUDGET.entryBytes)}`;
158
+ for (const entry of state.entries) {
159
+ if (entry.deletedAt !== null) continue;
160
+ const before = entryBytes(entry.data);
161
+ const next = changedData.get(entry.id);
162
+ const after = next ? entryBytes(next) : before;
163
+ siteBefore += before;
164
+ bytes.site += after;
165
+ bytes.largest = Math.max(bytes.largest, after);
166
+ if (!fitsBudget(after, before, SITE_BUDGET.entryBytes)) problems.push(`Entry ${entry.id} (${entry.brick}) would be ${kib(after)} after the release; ${limit}.`);
167
+ }
168
+ for (const single of created) {
169
+ const size = entryBytes(single.data);
179
170
  bytes.site += size;
180
171
  bytes.largest = Math.max(bytes.largest, size);
181
- if (size > BUDGET.entryBytes) problems.push(`${label} is too large (at most 256 KiB).`);
182
- };
183
- const sizeOf = async (brick, data) => {
184
- const fields = (schema.bricks[brick] ?? state.schema.bricks[brick])?.fields ?? {};
185
- return byteSize(data) + byteSize(await markdownTrees(fields, data));
186
- };
187
- for (const entry of state.entries) count(await sizeOf(entry.brick, changedData.get(entry.id) ?? entry.data), `Entry ${entry.id} (${entry.brick})`);
188
- for (const single of created) count(await sizeOf(single.brick, single.data), `The new single brick \u201C${single.brick}\u201D`);
189
- if (bytes.site > BUDGET.siteBytes) problems.push("The site has reached its storage budget (4 MiB).");
172
+ if (size > SITE_BUDGET.entryBytes) problems.push(`The new single brick \u201C${single.brick}\u201D would be ${kib(size)}; ${limit}.`);
173
+ }
174
+ if (!fitsBudget(bytes.site, siteBefore, SITE_BUDGET.siteBytes)) problems.push(`The site would use ${kib(bytes.site)} of its ${kib(SITE_BUDGET.siteBytes)} of storage.`);
190
175
  const liveEntries = state.entries.filter((entry) => entry.deletedAt === null).length;
191
- if (liveEntries + created.length > BUDGET.entries) problems.push(`The site has reached its limit of ${BUDGET.entries} entries.`);
176
+ if (liveEntries + created.length > SITE_BUDGET.entries) problems.push(`The site has reached its limit of ${SITE_BUDGET.entries} entries.`);
192
177
  return {
193
178
  schema,
194
179
  writes: [...writes].map(([entry, fields]) => ({ entry, fields })),
@@ -246,6 +231,8 @@ async function check(input) {
246
231
  for (const problem of problems) input.log(` \u2717 ${problem}`);
247
232
  return false;
248
233
  }
234
+ warnEntrySize(input.config, input.log);
235
+ warnNoCalendar(input.config, input.log);
249
236
  const image = checkSeoImage(input.config, input.root, input.log);
250
237
  const links = await checkFileLinks({ config: input.config, root: input.root, log: input.log, fetch: input.fetch }) && image;
251
238
  if (!input.connect) {
@@ -260,6 +247,26 @@ async function check(input) {
260
247
  return false;
261
248
  }
262
249
  }
250
+ function warnEntrySize(config, log) {
251
+ const { bricks, locales } = platformSchema(serializeSchema(config));
252
+ for (const [key, brick] of Object.entries(bricks)) {
253
+ const max = largestEntryBytes(brick.fields, locales);
254
+ if (max <= SITE_BUDGET.entryBytes) continue;
255
+ const fields = Object.entries(brick.fields).map(([name, field]) => ({ name, field, bytes: largestFieldBytes(field, locales) }));
256
+ const largest = fields.filter((f) => f.bytes > 0).sort((a, b) => b.bytes - a.bytes).slice(0, 3).map(({ name, field, bytes }) => {
257
+ if (field.type === "list") return `${name} ${field.max} rows`;
258
+ if (field.type !== "text" && field.type !== "longtext" && field.type !== "markdown") return `${name} ${kib(bytes)}`;
259
+ const languages = isTranslatable(field) && locales.length > 1 ? ` \xD7 ${locales.length} languages` : "";
260
+ return `${name} ${effectiveMax(field).toLocaleString("en-US")}${languages}`;
261
+ });
262
+ const uncounted = fields.filter(({ field }) => field.type === "ref" && field.multiple && field.max === void 0).map((f) => f.name);
263
+ log(`Warning: brick \u201C${key}\u201D can hold about ${kib(max)} per entry (largest: ${largest.join(", ")}); the entry limit is ${kib(SITE_BUDGET.entryBytes)}. Lower a max so a full entry fits.${uncounted.length ? ` Not counted: ${uncounted.join(", ")} (entries without a max).` : ""}`);
264
+ }
265
+ }
266
+ function warnNoCalendar(config, log) {
267
+ if (config.country === void 0 || config.calendar !== void 0 || calendarOfCountry(config.country)) return;
268
+ log(`Warning: Ginko has no public-holiday calendar for country \u201C${config.country}\u201D, so opening hours count no public holidays (stored as holidays: 'none'). Set \`calendar\` in ginko.config.ts to your own function (year) => holidays, or to 'none' to keep it so.`);
269
+ }
263
270
  function checkSeoImage(config, root, log) {
264
271
  const image = config.seo?.image;
265
272
  if (!image || !image.startsWith("/") || image.startsWith("//")) return true;
@@ -286,7 +293,7 @@ async function checkRelease(input) {
286
293
  const candidate = result.candidate;
287
294
  const migrations = result.schema.migrations.filter((m) => !state.migrations.some((s) => s.id === m.id) && !state.schema.migrations.some((s) => s.id === m.id));
288
295
  if (migrations.length > 0) input.log(`New migrations: ${migrations.map((m) => m.id).join(", ")}. Writes: ${candidate.writes.length} entries.`);
289
- input.log(`Size: site ${kib(candidate.bytes.site)} of 4 MiB, largest entry ${kib(candidate.bytes.largest)} (limit 256 KiB).`);
296
+ input.log(`Size: site ${kib(candidate.bytes.site)} of ${kib(SITE_BUDGET.siteBytes)}, largest entry ${kib(candidate.bytes.largest)} (limit ${kib(SITE_BUDGET.entryBytes)}).`);
290
297
  if (candidate.problems.length > 0) {
291
298
  for (const line of explainProblems(candidate.problems)) input.log(line);
292
299
  return false;
@@ -391,24 +398,11 @@ function createPlatform(options) {
391
398
  };
392
399
  }
393
400
 
394
- const EXTENSIONS = {
395
- "image/jpeg": ".jpg",
396
- "image/png": ".png",
397
- "image/webp": ".webp",
398
- "image/avif": ".avif",
399
- "application/pdf": ".pdf"
400
- };
401
401
  function siteOfKey(key) {
402
402
  const match = PUSH_KEY_FORMAT.exec(key.trim());
403
403
  if (!match) throw new CliError("GINKO_KEY is not a valid key.", "USAGE");
404
404
  return match[1];
405
405
  }
406
- function defaultDir(site, now) {
407
- return `ginko-export-${site}-${now.toISOString().slice(0, 10)}`;
408
- }
409
- function pathOf(file) {
410
- return `files/${file.id}${EXTENSIONS[file.mime] ?? ""}`;
411
- }
412
406
  async function requireEmpty(dir) {
413
407
  let names;
414
408
  try {
@@ -543,6 +537,10 @@ function parseArgs(argv) {
543
537
  const value = arg === "--config" ? argv[++i] : arg.slice("--config=".length);
544
538
  if (!value) throw new CliError("--config needs a path.", "USAGE");
545
539
  args.config = value;
540
+ } else if (arg === "--site" || arg.startsWith("--site=")) {
541
+ const value = arg === "--site" ? argv[++i] : arg.slice("--site=".length);
542
+ if (!value) throw new CliError("--site needs a site slug.", "USAGE");
543
+ args.site = value;
546
544
  } else if (arg.startsWith("-")) args.flags.add(arg);
547
545
  else if (args.command === void 0) args.command = arg;
548
546
  else if (args.folder === void 0) args.folder = arg;
@@ -568,6 +566,7 @@ async function runCli(argv, deps, cli) {
568
566
  const name = `${cli.prefix}${args.command}`;
569
567
  const flag = [...args.flags].find((f) => f !== "--json" && !command.flags?.includes(f));
570
568
  if (flag) throw new CliError(`Unknown option \u201C${flag}\u201D for ${name}.`, "USAGE");
569
+ if (args.site !== void 0 && !command.site) throw new CliError(`Unknown option \u201C--site\u201D for ${name}.`, "USAGE");
571
570
  if (args.folder !== void 0 && !command.folder) throw new CliError(`Unexpected argument \u201C${args.folder}\u201D for ${name}.`, "USAGE");
572
571
  if (args.folder === void 0 && command.folder === "required") throw new CliError(`${name} needs a folder: ${name} <folder>.`, "USAGE");
573
572
  return command.run(args);
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
- export { L as LinkConfig, M as Migration, b as MigrationContext, R as Redirect, c as RouteTemplate, S as SiteInput, e as collection, f as defineSite, s as single } from './shared/ginko.akHewCGt.mjs';
2
- export { B as Brick, d as BrickSource, k as ChoiceOption, e as CollectionBrick, m as ComponentDef, a as ComponentRegistry, C as Currency, q as DataOf, t as Field, F as Fields, v as FileValue, y as ImageValue, z as ItemOf, J as Json, c as Label, L as Locale, Q as MarkdownProfile, U as MarkdownToc, M as MarkdownTree, X as MarkdownValue, Z as Money, f as SingleBrick, T as Task, a8 as TocLink, ab as UnknownChoice, V as Visibility, W as WeekInfo, aj as defineComponents, ao as f, au as plainText, ax as startOfWeek } from './shared/ginko.D-fNojn9.mjs';
3
- export { C as Condition, N as NavNode, Q as Query, d as SeoImage, j as formatMoney, s as safeHref } from './shared/ginko.BTUfZCfa.mjs';
4
- import './shared/ginko.Bwan3BB-.mjs';
1
+ export { L as LinkConfig, M as Migration, b as MigrationContext, c as Redirect, R as RouteTemplate, S as SiteInput, e as collection, f as defineSite, s as single } from './shared/ginko.DvPtlHIz.mjs';
2
+ export { B as Brick, d as BrickSource, Q as BrickStatus, Y as ChoiceOption, f as CollectionBrick, e as CollectionStatus, _ as ComponentDef, b as ComponentRegistry, C as Currency, a2 as DataOf, p as Field, F as Fields, a4 as FileValue, a7 as ImageValue, a8 as ItemOf, J as Json, c as Label, L as Locale, ab as MarkdownProfile, ac as MarkdownToc, M as MarkdownTree, ad as MarkdownValue, af as Money, h as SingleBrick, g as SingleStatus, T as Task, al as TocLink, ao as UnknownChoice, V as Visibility, W as WeekInfo, aw as defineComponents, aB as f, aJ as plainText, aM as startOfWeek, aQ as wordsOf } from './shared/ginko.DrkUeYFP.mjs';
3
+ export { N as NavNode, b as SeoImage, e as breadcrumbJsonLd } from './shared/ginko.o1yIKlgj.mjs';
4
+ export { C as Condition, F as FormatMoneyOptions, Q as Query, f as formatMoney, s as safeHref } from './shared/ginko.loGIxGZg.mjs';
5
+ import './shared/ginko.6cI8KXZP.mjs';
5
6
  import '@lupinum/ginko-i18n/core';
6
7
  import 'comark';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export { L as LinkConfig, M as Migration, b as MigrationContext, R as Redirect, c as RouteTemplate, S as SiteInput, e as collection, f as defineSite, s as single } from './shared/ginko.BDF3bW0C.js';
2
- export { B as Brick, d as BrickSource, k as ChoiceOption, e as CollectionBrick, m as ComponentDef, a as ComponentRegistry, C as Currency, q as DataOf, t as Field, F as Fields, v as FileValue, y as ImageValue, z as ItemOf, J as Json, c as Label, L as Locale, Q as MarkdownProfile, U as MarkdownToc, M as MarkdownTree, X as MarkdownValue, Z as Money, f as SingleBrick, T as Task, a8 as TocLink, ab as UnknownChoice, V as Visibility, W as WeekInfo, aj as defineComponents, ao as f, au as plainText, ax as startOfWeek } from './shared/ginko.D-fNojn9.js';
3
- export { C as Condition, N as NavNode, Q as Query, d as SeoImage, j as formatMoney, s as safeHref } from './shared/ginko.Dc0oNcDv.js';
4
- import './shared/ginko.BBkZW2nW.js';
1
+ export { L as LinkConfig, M as Migration, b as MigrationContext, c as Redirect, R as RouteTemplate, S as SiteInput, e as collection, f as defineSite, s as single } from './shared/ginko.EelR5dt9.js';
2
+ export { B as Brick, d as BrickSource, Q as BrickStatus, Y as ChoiceOption, f as CollectionBrick, e as CollectionStatus, _ as ComponentDef, b as ComponentRegistry, C as Currency, a2 as DataOf, p as Field, F as Fields, a4 as FileValue, a7 as ImageValue, a8 as ItemOf, J as Json, c as Label, L as Locale, ab as MarkdownProfile, ac as MarkdownToc, M as MarkdownTree, ad as MarkdownValue, af as Money, h as SingleBrick, g as SingleStatus, T as Task, al as TocLink, ao as UnknownChoice, V as Visibility, W as WeekInfo, aw as defineComponents, aB as f, aJ as plainText, aM as startOfWeek, aQ as wordsOf } from './shared/ginko.DrkUeYFP.js';
3
+ export { N as NavNode, b as SeoImage, e as breadcrumbJsonLd } from './shared/ginko.CjWB8N7f.js';
4
+ export { C as Condition, F as FormatMoneyOptions, Q as Query, f as formatMoney, s as safeHref } from './shared/ginko.ULKQnAWd.js';
5
+ import './shared/ginko.B_pACpVU.js';
5
6
  import '@lupinum/ginko-i18n/core';
6
7
  import 'comark';