@lupinum/ginko 0.6.1 → 0.6.3

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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # @lupinum/ginko
2
2
 
3
+ ## 0.6.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#34](https://github.com/lupinum-dev/ginko/pull/34) [`d451a07`](https://github.com/lupinum-dev/ginko/commit/d451a0764427989ad4abfb346c390a28d2955dd6) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add `idPrefix` to `GinkoMarkdown`: it puts a prefix before every id and `#` link of one body, so a page that shows several bodies has no duplicate ids. The docs changelog uses it with each release's anchor.
8
+
9
+ - [#34](https://github.com/lupinum-dev/ginko/pull/34) [`d451a07`](https://github.com/lupinum-dev/ginko/commit/d451a0764427989ad4abfb346c390a28d2955dd6) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Add `NUXT_PUBLIC_GINKO_NOINDEX=true`, which keeps a whole deployment out of search, its own address included. Use it for demos and for a site that runs on a preview address before its domain switch: robots.txt then disallows everything and every response sends `X-Robots-Tag: noindex`. Site responses now also send `Permissions-Policy: camera=(), geolocation=(), microphone=()`.
10
+
11
+ - [#34](https://github.com/lupinum-dev/ginko/pull/34) [`d451a07`](https://github.com/lupinum-dev/ginko/commit/d451a0764427989ad4abfb346c390a28d2955dd6) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Change the generated share card of a page with an image to JPEG. As PNG such a card weighed 400-700 KB, and WhatsApp drops preview images over about 300 KB. Cards without an image stay PNG.
12
+ - Updated dependencies []:
13
+ - @lupinum/ginko-i18n@0.6.3
14
+
15
+ ## 0.6.2
16
+
17
+ ### Patch Changes
18
+
19
+ - [#32](https://github.com/lupinum-dev/ginko/pull/32) [`d082b85`](https://github.com/lupinum-dev/ginko/commit/d082b856851dabbf1d02d06d2d5796c50a3f825d) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix the first `ops:import` into a new site on the hosted platform once more: the history entry of its first release no longer counts as an edit.
20
+ - Updated dependencies []:
21
+ - @lupinum/ginko-i18n@0.6.2
22
+
3
23
  ## 0.6.1
4
24
 
5
25
  ### Patch Changes
package/dist/basics.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BasicsOptions, H as HoursContext } from './shared/ginko.C_nq6vk7.mjs';
2
- export { D as DayHours, a as DayRule, E as EventJsonLdInput, b as EventsOptions, c as Exception, d as HolidayClosure, e as HolidayNames, f as HolidaySetting, g as HourPlan, h as HoursData, i as HoursLine, j as HoursLineContext, k as HoursOptions, l as HoursSource, S as SessionJsonLdInput, m as SessionStatus, n as Span, T as Times, o as TodayState, W as Weekday, p as austrianHolidays, q as calendarIn, r as calendarOf, s as closedOnClosure, t as eventJsonLd, u as events, v as germanHolidays, w as holidayOn, x as hourPlans, y as hours, z as hoursLine, A as hoursOn, C as notices, F as noticesOn, G as offerJsonLd, I as planOn, J as sessions, K as sessionsInOrder, L as singaporeHolidays, M as spansOf, N as spansText, O as timesOf, P as todayState, Q as upcomingClosures, R as upcomingHolidayClosures, U as upcomingPlans, V as weekFor, X as weekOf, Y as weekdayOf } from './shared/ginko.C_nq6vk7.mjs';
1
+ import { B as BasicsOptions, H as HoursContext } from './shared/ginko.Dz3fNfap.mjs';
2
+ export { D as DayHours, a as DayRule, E as EventJsonLdInput, b as EventsOptions, c as Exception, d as HolidayClosure, e as HolidayNames, f as HolidaySetting, g as HourPlan, h as HoursData, i as HoursLine, j as HoursLineContext, k as HoursOptions, l as HoursSource, S as SessionJsonLdInput, m as SessionStatus, n as Span, T as Times, o as TodayState, W as Weekday, p as austrianHolidays, q as calendarIn, r as calendarOf, s as closedOnClosure, t as eventJsonLd, u as events, v as germanHolidays, w as holidayOn, x as hourPlans, y as hours, z as hoursLine, A as hoursOn, C as notices, F as noticesOn, G as offerJsonLd, I as planOn, J as sessions, K as sessionsInOrder, L as singaporeHolidays, M as spansOf, N as spansText, O as timesOf, P as todayState, Q as upcomingClosures, R as upcomingHolidayClosures, U as upcomingPlans, V as weekFor, X as weekOf, Y as weekdayOf } from './shared/ginko.Dz3fNfap.mjs';
3
3
  import { SingleBrick, Locale, CollectionBrick } from './index.mjs';
4
4
  import { TextField, LongTextField, SlugField, ChoiceField, DateField, MarkdownField, ImageField, RefField, ListField, FileField } from './internal.mjs';
5
5
  export { s as Holiday, t as HolidayCalendar, y as HolidayCalendarName, H as HolidaysOption, u as StoredHolidays, z as calendarOfCountry } from './shared/ginko.DrkUeYFP.mjs';
package/dist/basics.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BasicsOptions, H as HoursContext } from './shared/ginko.D2oht0Kx.js';
2
- export { D as DayHours, a as DayRule, E as EventJsonLdInput, b as EventsOptions, c as Exception, d as HolidayClosure, e as HolidayNames, f as HolidaySetting, g as HourPlan, h as HoursData, i as HoursLine, j as HoursLineContext, k as HoursOptions, l as HoursSource, S as SessionJsonLdInput, m as SessionStatus, n as Span, T as Times, o as TodayState, W as Weekday, p as austrianHolidays, q as calendarIn, r as calendarOf, s as closedOnClosure, t as eventJsonLd, u as events, v as germanHolidays, w as holidayOn, x as hourPlans, y as hours, z as hoursLine, A as hoursOn, C as notices, F as noticesOn, G as offerJsonLd, I as planOn, J as sessions, K as sessionsInOrder, L as singaporeHolidays, M as spansOf, N as spansText, O as timesOf, P as todayState, Q as upcomingClosures, R as upcomingHolidayClosures, U as upcomingPlans, V as weekFor, X as weekOf, Y as weekdayOf } from './shared/ginko.D2oht0Kx.js';
1
+ import { B as BasicsOptions, H as HoursContext } from './shared/ginko.HFGxAlOn.js';
2
+ export { D as DayHours, a as DayRule, E as EventJsonLdInput, b as EventsOptions, c as Exception, d as HolidayClosure, e as HolidayNames, f as HolidaySetting, g as HourPlan, h as HoursData, i as HoursLine, j as HoursLineContext, k as HoursOptions, l as HoursSource, S as SessionJsonLdInput, m as SessionStatus, n as Span, T as Times, o as TodayState, W as Weekday, p as austrianHolidays, q as calendarIn, r as calendarOf, s as closedOnClosure, t as eventJsonLd, u as events, v as germanHolidays, w as holidayOn, x as hourPlans, y as hours, z as hoursLine, A as hoursOn, C as notices, F as noticesOn, G as offerJsonLd, I as planOn, J as sessions, K as sessionsInOrder, L as singaporeHolidays, M as spansOf, N as spansText, O as timesOf, P as todayState, Q as upcomingClosures, R as upcomingHolidayClosures, U as upcomingPlans, V as weekFor, X as weekOf, Y as weekdayOf } from './shared/ginko.HFGxAlOn.js';
3
3
  import { SingleBrick, Locale, CollectionBrick } from './index.js';
4
4
  import { TextField, LongTextField, SlugField, ChoiceField, DateField, MarkdownField, ImageField, RefField, ListField, FileField } from './internal.js';
5
5
  export { s as Holiday, t as HolidayCalendar, y as HolidayCalendarName, H as HolidaysOption, u as StoredHolidays, z as calendarOfCountry } from './shared/ginko.DrkUeYFP.js';
package/dist/basics.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import { f, O as studioLabel } from './shared/ginko.BNVC-g9n.mjs';
2
2
  import { s as single, c as collection } from './shared/ginko.C-oz8wwI.mjs';
3
3
  export { h as withoutFiles } from './shared/ginko.C-oz8wwI.mjs';
4
- import { o as organizationLd, c as compact, a as articleLd, p as postalAddressLd, d as faqLd } from './shared/ginko.DCHGkQ7P.mjs';
5
- 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.WAfoMhv1.mjs';
6
- 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.WAfoMhv1.mjs';
4
+ import { o as organizationLd, c as compact, a as articleLd, p as postalAddressLd, d as faqLd } from './shared/ginko.CvlgoIVE.mjs';
5
+ 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.BsikHfwf.mjs';
6
+ 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.BsikHfwf.mjs';
7
7
  import { l as limitOf } from './shared/ginko.D1PeQ3ds.mjs';
8
8
  export { c as calendarOfCountry } from './shared/ginko.D1PeQ3ds.mjs';
9
9
  import 'comark';
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  export { c as collection, d as defineSite, s as single, a as startOfWeek } from './shared/ginko.C-oz8wwI.mjs';
2
2
  export { d as defineComponents, f, p as plainText, s as safeHref, w as wordsOf } from './shared/ginko.BNVC-g9n.mjs';
3
- export { b as breadcrumbJsonLd, f as formatMoney } from './shared/ginko.DCHGkQ7P.mjs';
3
+ export { b as breadcrumbJsonLd, f as formatMoney } from './shared/ginko.CvlgoIVE.mjs';
4
4
  import 'comark';
5
5
  import 'comark/plugins/alert';
6
6
  import 'comark/plugins/attributes';
@@ -6,7 +6,7 @@ import { M as MarkdownTrees, B as Bundle, a as BundleItem } from './shared/ginko
6
6
  export { b as BUNDLE_FORMAT, c as BundleBrick, d as bundleFits, i as isBundle, k as knownBricks, m as markdownTrees, w as withFileBricks } from './shared/ginko.6cI8KXZP.mjs';
7
7
  export { C as Condition, Q as Query, a as QueryOrder, b as QueryResult, c as QuerySchema, f as formatMoney, i as isSafeHref, m as minorDigits, n as neighbors, q as query, s as safeHref } from './shared/ginko.BaFweQcB.mjs';
8
8
  export { A as ArticleLdInput, N as NavNode, a as ORGANIZATION_TYPES, O as OrganizationLdInput, S as SeoHead, b as SeoImage, c as SeoInput, d as articleLd, e as breadcrumbJsonLd, f as breadcrumbs, g as faqLd, i as isPreviewHost, n as navTree, o as organizationLd, r as robotsTxt, s as seoHead, h as siteHeaders, w as websiteLd, j as withCountry } from './shared/ginko.o1yIKlgj.mjs';
9
- export { g as HourPlan, i as HoursLine, j as HoursLineContext, Z as HoursTexts, _ as NoticeTask, $ as PostalAddressInput, a0 as WeekRow, a1 as eventsBrick, a2 as hourPlansBrick, a3 as hoursBrick, z as hoursLine, a4 as noticesBrick, a5 as offerPrice, a6 as postalAddress, a7 as weekdays } from './shared/ginko.C_nq6vk7.mjs';
9
+ export { g as HourPlan, i as HoursLine, j as HoursLineContext, Z as HoursTexts, _ as NoticeTask, $ as PostalAddressInput, a0 as WeekRow, a1 as eventsBrick, a2 as hourPlansBrick, a3 as hoursBrick, z as hoursLine, a4 as noticesBrick, a5 as offerPrice, a6 as postalAddress, a7 as weekdays } from './shared/ginko.Dz3fNfap.mjs';
10
10
  import '@lupinum/ginko-i18n/core';
11
11
  import 'comark';
12
12
 
@@ -6,7 +6,7 @@ import { M as MarkdownTrees, B as Bundle, a as BundleItem } from './shared/ginko
6
6
  export { b as BUNDLE_FORMAT, c as BundleBrick, d as bundleFits, i as isBundle, k as knownBricks, m as markdownTrees, w as withFileBricks } from './shared/ginko.B_pACpVU.js';
7
7
  export { C as Condition, Q as Query, a as QueryOrder, b as QueryResult, c as QuerySchema, f as formatMoney, i as isSafeHref, m as minorDigits, n as neighbors, q as query, s as safeHref } from './shared/ginko.BiDXgjLy.js';
8
8
  export { A as ArticleLdInput, N as NavNode, a as ORGANIZATION_TYPES, O as OrganizationLdInput, S as SeoHead, b as SeoImage, c as SeoInput, d as articleLd, e as breadcrumbJsonLd, f as breadcrumbs, g as faqLd, i as isPreviewHost, n as navTree, o as organizationLd, r as robotsTxt, s as seoHead, h as siteHeaders, w as websiteLd, j as withCountry } from './shared/ginko.CjWB8N7f.js';
9
- export { g as HourPlan, i as HoursLine, j as HoursLineContext, Z as HoursTexts, _ as NoticeTask, $ as PostalAddressInput, a0 as WeekRow, a1 as eventsBrick, a2 as hourPlansBrick, a3 as hoursBrick, z as hoursLine, a4 as noticesBrick, a5 as offerPrice, a6 as postalAddress, a7 as weekdays } from './shared/ginko.D2oht0Kx.js';
9
+ export { g as HourPlan, i as HoursLine, j as HoursLineContext, Z as HoursTexts, _ as NoticeTask, $ as PostalAddressInput, a0 as WeekRow, a1 as eventsBrick, a2 as hourPlansBrick, a3 as hoursBrick, z as hoursLine, a4 as noticesBrick, a5 as offerPrice, a6 as postalAddress, a7 as weekdays } from './shared/ginko.HFGxAlOn.js';
10
10
  import '@lupinum/ginko-i18n/core';
11
11
  import 'comark';
12
12
 
package/dist/internal.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { k as isVisible, v as visibleUntil, m as printOf } from './shared/ginko.t-gbwzxh.mjs';
2
2
  export { S as SITE_BUDGET, n as applyDefaults, o as blockedSlugs, q as buildBundle, s as byteSize, j as defaultDir, d as defaultsFor, t as deletesExpired, b as diffSchema, e as entryBytes, f as fieldsChanged, a as fitsBudget, l as largestEntryBytes, c as largestFieldBytes, h as pathOf, r as releaseData, u as resolveEntry, w as routeUrls, x as servedBundle, y as sortEntries, z as untranslatedMode, A as urlClashes, B as urlsFor } from './shared/ginko.t-gbwzxh.mjs';
3
- export { H as eventsBrick, I as hourPlansBrick, J as hoursBrick, q as hoursLine, K as noticesBrick, L as offerPrice, M as postalAddress, N as weekdays } from './shared/ginko.WAfoMhv1.mjs';
3
+ export { H as eventsBrick, I as hourPlansBrick, J as hoursBrick, q as hoursLine, K as noticesBrick, L as offerPrice, M as postalAddress, N as weekdays } from './shared/ginko.BsikHfwf.mjs';
4
4
  import { b as addDays } from './shared/ginko.C-oz8wwI.mjs';
5
5
  export { D as DEFAULT_WEEK, c as collection, d as defineSite, f as firstDayShown, r as resolveToken, s as single, g as siteForContent, a as startOfWeek, t as todayIn, e as weekInfoOf, h as withoutFiles, w as workWeekOf, i as zoneOffset, z as zonedDateTime } from './shared/ginko.C-oz8wwI.mjs';
6
6
  import { a as parseMarkdown, h as stableJson, u as labelOf, i as isTranslatable, g as effectiveMax, P as describeProfile, y as effectiveProfile } from './shared/ginko.BNVC-g9n.mjs';
@@ -8,8 +8,8 @@ export { v as ALT_INVISIBLE, A as ALT_MAX, Q as FILE_REF, R as GINKO_COMPONENTS_
8
8
  import { e as entryTitle$1 } from './shared/ginko.yKMIjJ68.mjs';
9
9
  export { B as BUNDLE_FORMAT, b as bundleFits, i as isBundle, k as knownBricks, m as markdownTrees, a as withFileBricks } from './shared/ginko.yKMIjJ68.mjs';
10
10
  export { C as CALENDAR_NAMES, S as STORED_HOLIDAYS, U as UPLOAD_TYPES, a as acceptOf, c as calendarOfCountry, f as formatMb, h as holidaysOf, l as limitOf } from './shared/ginko.D1PeQ3ds.mjs';
11
- import { m as minorDigits } from './shared/ginko.DCHGkQ7P.mjs';
12
- export { O as ORGANIZATION_TYPES, a as articleLd, b as breadcrumbJsonLd, d as faqLd, f as formatMoney, i as isPreviewHost, o as organizationLd, r as robotsTxt, s as seoHead, e as siteHeaders, w as websiteLd, g as withCountry } from './shared/ginko.DCHGkQ7P.mjs';
11
+ import { m as minorDigits } from './shared/ginko.CvlgoIVE.mjs';
12
+ export { O as ORGANIZATION_TYPES, a as articleLd, b as breadcrumbJsonLd, d as faqLd, f as formatMoney, i as isPreviewHost, o as organizationLd, r as robotsTxt, s as seoHead, e as siteHeaders, w as websiteLd, g as withCountry } from './shared/ginko.CvlgoIVE.mjs';
13
13
  import { o as ordered, b as createAsks } from './shared/ginko.B1-DoOea.mjs';
14
14
  export { P as PREFILL_TOKENS, d as SCHEMA_LIMITS, e as SHAPE_CODES, f as SLUG_PATTERN, a as checkSchema, c as checkSite, g as duePlan, h as fileProblem, i as grantGroups, j as isDate, k as isHourPlans, l as isPrefillToken, m as isTimeZone, n as liveFrom, q as mainLocale, r as migrationFingerprint, t as plannedWeeks, u as plansThisWeek, p as platformSchema, s as serializeSchema, w as slugBases, x as slugify, y as staleOf, z as uniqueSlug, v as validate, A as weekStartField, C as weeklyTask } from './shared/ginko.B1-DoOea.mjs';
15
15
  import { renderMarkdown } from 'comark/render';
@@ -268,7 +268,8 @@ const module$1 = defineNuxtModule({
268
268
  holidays: schema.holidays ?? "",
269
269
  seo: site.seo ?? {},
270
270
  agents: site.agents ?? {},
271
- sources
271
+ sources,
272
+ noindex: false
272
273
  } });
273
274
  checkI18nOptions(nuxt.options.i18n);
274
275
  const i18n = await tryResolveModule("@lupinum/ginko-i18n", import.meta.url);
@@ -14,6 +14,11 @@ export declare const GinkoMarkdown: import("vue").DefineComponent<import("vue").
14
14
  type: PropType<Record<string, Component | string>>;
15
15
  default: () => {};
16
16
  };
17
+ /** Puts `idPrefix-` before every id and `#` link of this body, for a page that shows several bodies (a changelog). */
18
+ idPrefix: {
19
+ type: StringConstructor;
20
+ default: string;
21
+ };
17
22
  }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
18
23
  [key: string]: any;
19
24
  }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
@@ -30,7 +35,13 @@ export declare const GinkoMarkdown: import("vue").DefineComponent<import("vue").
30
35
  type: PropType<Record<string, Component | string>>;
31
36
  default: () => {};
32
37
  };
38
+ /** Puts `idPrefix-` before every id and `#` link of this body, for a page that shows several bodies (a changelog). */
39
+ idPrefix: {
40
+ type: StringConstructor;
41
+ default: string;
42
+ };
33
43
  }>> & Readonly<{}>, {
34
44
  value: MarkdownValue | undefined;
35
45
  components: Record<string, string | Component>;
46
+ idPrefix: string;
36
47
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -12,13 +12,15 @@ export const GinkoMarkdown = defineComponent({
12
12
  * provides under `ginko:components` (e.g. by `@lupinum/ginko-components`), so a tag given here wins.
13
13
  * Other tags use a global component of that name (PascalCase), else a plain element.
14
14
  */
15
- components: { type: Object, default: () => ({}) }
15
+ components: { type: Object, default: () => ({}) },
16
+ /** Puts `idPrefix-` before every id and `#` link of this body, for a page that shows several bodies (a changelog). */
17
+ idPrefix: { type: String, default: "" }
16
18
  },
17
19
  async setup(props) {
18
20
  const provided = inject(GINKO_COMPONENTS_KEY, {});
19
21
  let tree;
20
22
  provide(GINKO_TOC_KEY, computed(() => tree?.value?.toc ?? null));
21
23
  tree = await useGinkoMarkdown(() => props.value);
22
- return () => h(GinkoMarkdownTree, { value: tree.value, components: { ...provided, ...props.components }, registry: components });
24
+ return () => h(GinkoMarkdownTree, { value: tree.value, components: { ...provided, ...props.components }, registry: components, idPrefix: props.idPrefix });
23
25
  }
24
26
  });
@@ -152,7 +152,10 @@ export function useGinkoSeo(input) {
152
152
  alt: () => {
153
153
  const image = toValue(input).image;
154
154
  return (typeof image === "object" ? image.alt : void 0) ?? toValue(input).title ?? config.name;
155
- }
155
+ },
156
+ // A card with a photo is a JPEG: as PNG it weighs 400-700 KB, and WhatsApp drops preview images over about 300 KB.
157
+ // A card of text and colour stays PNG, which keeps it sharp and small.
158
+ extension: cardImage(toValue(input).image) ? "jpeg" : "png"
156
159
  });
157
160
  }
158
161
  const pageLd = () => (toValue(input).jsonLd ?? []).map((node) => withCountry(node, config.country));
@@ -1,9 +1,9 @@
1
1
  import { defineEventHandler, getRequestHost, getRequestURL, useRuntimeConfig } from "nuxt/server";
2
2
  import { isPreviewHost, siteHeaders } from "../../../internal.mjs";
3
3
  export default defineEventHandler((event) => {
4
- const { platform, url } = useRuntimeConfig().public.ginko;
4
+ const { platform, url, noindex } = useRuntimeConfig().public.ginko;
5
5
  const preview = /^\/__ginko(\/|$)/.test(getRequestURL(event).pathname);
6
6
  const origin = platform ? new URL(platform).origin : "";
7
- const headers = siteHeaders({ preview, platformOrigin: origin, noindex: isPreviewHost(getRequestHost(event), url) });
7
+ const headers = siteHeaders({ preview, platformOrigin: origin, noindex: noindex || isPreviewHost(getRequestHost(event), url) });
8
8
  for (const [name, value] of Object.entries(headers)) event.res.headers.set(name, value);
9
9
  });
@@ -1,8 +1,8 @@
1
1
  import { defineEventHandler, getRequestHost, useRuntimeConfig } from "nuxt/server";
2
2
  import { isPreviewHost, robotsTxt } from "../../../internal.mjs";
3
3
  export default defineEventHandler((event) => {
4
- const { url } = useRuntimeConfig().public.ginko;
4
+ const { url, noindex: always } = useRuntimeConfig().public.ginko;
5
5
  event.res.headers.set("content-type", "text/plain; charset=utf-8");
6
- const noindex = !import.meta.prerender && isPreviewHost(getRequestHost(event), url);
6
+ const noindex = always || !import.meta.prerender && isPreviewHost(getRequestHost(event), url);
7
7
  return robotsTxt({ noindex, sitemap: new URL("/sitemap.xml", url).href });
8
8
  });
@@ -20,6 +20,9 @@ export interface GinkoPublicConfig {
20
20
  platform: boolean;
21
21
  files: boolean;
22
22
  };
23
+ /** True keeps every host of this deployment out of search, its own address included: a demo, or a site served on a
24
+ * preview address before its domain switch. Set per deployment with NUXT_PUBLIC_GINKO_NOINDEX=true. */
25
+ noindex: boolean;
23
26
  }
24
27
  /**
25
28
  * The page a request may ask Markdown for (docs: 10.seo-und-agenten "Addresses and headers"): `<page>.md` always
@@ -1,7 +1,7 @@
1
1
  import { c as calendarOfCountry } from './ginko.D1PeQ3ds.mjs';
2
2
  import { c as collection, s as single, t as todayIn, z as zonedDateTime } from './ginko.C-oz8wwI.mjs';
3
3
  import { f, p as plainText } from './ginko.BNVC-g9n.mjs';
4
- import { m as minorDigits } from './ginko.DCHGkQ7P.mjs';
4
+ import { m as minorDigits } from './ginko.CvlgoIVE.mjs';
5
5
 
6
6
  const sourceOf = (o) => o.source ? { source: o.source } : {};
7
7
 
@@ -99,6 +99,8 @@ function siteHeaders(input) {
99
99
  "content-security-policy": input.preview && input.platformOrigin ? `frame-ancestors ${input.platformOrigin}` : `frame-ancestors 'self'`,
100
100
  "x-content-type-options": "nosniff",
101
101
  "referrer-policy": "strict-origin-when-cross-origin",
102
+ // No site template uses camera, location or microphone; a page that needs one sets its own header.
103
+ "permissions-policy": "camera=(), geolocation=(), microphone=()",
102
104
  ...input.noindex ? { "x-robots-tag": "noindex" } : {}
103
105
  };
104
106
  }
@@ -708,7 +708,7 @@ declare function hoursBrick(t: HoursTexts, week: readonly WeekRow[], opts: Hours
708
708
  readonly not: true;
709
709
  };
710
710
  };
711
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
711
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
712
712
  readonly options: readonly [{
713
713
  readonly value: "mo";
714
714
  readonly label: {
@@ -788,7 +788,7 @@ declare function hoursBrick(t: HoursTexts, week: readonly WeekRow[], opts: Hours
788
788
  readonly not: true;
789
789
  };
790
790
  };
791
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
791
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
792
792
  readonly options: readonly [{
793
793
  readonly value: "mo";
794
794
  readonly label: {
@@ -1010,7 +1010,7 @@ declare function hourPlansBrick(t: HoursTexts, week: readonly WeekRow[], opts: B
1010
1010
  readonly not: true;
1011
1011
  };
1012
1012
  };
1013
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1013
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1014
1014
  readonly options: readonly [{
1015
1015
  readonly value: "mo";
1016
1016
  readonly label: {
@@ -1090,7 +1090,7 @@ declare function hourPlansBrick(t: HoursTexts, week: readonly WeekRow[], opts: B
1090
1090
  readonly not: true;
1091
1091
  };
1092
1092
  };
1093
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1093
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1094
1094
  readonly options: readonly [{
1095
1095
  readonly value: "mo";
1096
1096
  readonly label: {
@@ -1180,7 +1180,7 @@ declare function hours(opts?: HoursOptions): SingleBrick<{
1180
1180
  readonly not: true;
1181
1181
  };
1182
1182
  };
1183
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1183
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1184
1184
  readonly options: readonly [{
1185
1185
  readonly value: "mo";
1186
1186
  readonly label: {
@@ -1260,7 +1260,7 @@ declare function hours(opts?: HoursOptions): SingleBrick<{
1260
1260
  readonly not: true;
1261
1261
  };
1262
1262
  };
1263
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1263
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1264
1264
  readonly options: readonly [{
1265
1265
  readonly value: "mo";
1266
1266
  readonly label: {
@@ -1482,7 +1482,7 @@ declare function hourPlans(opts?: BasicsOptions): CollectionBrick<{
1482
1482
  readonly not: true;
1483
1483
  };
1484
1484
  };
1485
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1485
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1486
1486
  readonly options: readonly [{
1487
1487
  readonly value: "mo";
1488
1488
  readonly label: {
@@ -1562,7 +1562,7 @@ declare function hourPlans(opts?: BasicsOptions): CollectionBrick<{
1562
1562
  readonly not: true;
1563
1563
  };
1564
1564
  };
1565
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1565
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1566
1566
  readonly options: readonly [{
1567
1567
  readonly value: "mo";
1568
1568
  readonly label: {
@@ -708,7 +708,7 @@ declare function hoursBrick(t: HoursTexts, week: readonly WeekRow[], opts: Hours
708
708
  readonly not: true;
709
709
  };
710
710
  };
711
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
711
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
712
712
  readonly options: readonly [{
713
713
  readonly value: "mo";
714
714
  readonly label: {
@@ -788,7 +788,7 @@ declare function hoursBrick(t: HoursTexts, week: readonly WeekRow[], opts: Hours
788
788
  readonly not: true;
789
789
  };
790
790
  };
791
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
791
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
792
792
  readonly options: readonly [{
793
793
  readonly value: "mo";
794
794
  readonly label: {
@@ -1010,7 +1010,7 @@ declare function hourPlansBrick(t: HoursTexts, week: readonly WeekRow[], opts: B
1010
1010
  readonly not: true;
1011
1011
  };
1012
1012
  };
1013
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1013
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1014
1014
  readonly options: readonly [{
1015
1015
  readonly value: "mo";
1016
1016
  readonly label: {
@@ -1090,7 +1090,7 @@ declare function hourPlansBrick(t: HoursTexts, week: readonly WeekRow[], opts: B
1090
1090
  readonly not: true;
1091
1091
  };
1092
1092
  };
1093
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1093
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1094
1094
  readonly options: readonly [{
1095
1095
  readonly value: "mo";
1096
1096
  readonly label: {
@@ -1180,7 +1180,7 @@ declare function hours(opts?: HoursOptions): SingleBrick<{
1180
1180
  readonly not: true;
1181
1181
  };
1182
1182
  };
1183
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1183
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1184
1184
  readonly options: readonly [{
1185
1185
  readonly value: "mo";
1186
1186
  readonly label: {
@@ -1260,7 +1260,7 @@ declare function hours(opts?: HoursOptions): SingleBrick<{
1260
1260
  readonly not: true;
1261
1261
  };
1262
1262
  };
1263
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1263
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1264
1264
  readonly options: readonly [{
1265
1265
  readonly value: "mo";
1266
1266
  readonly label: {
@@ -1482,7 +1482,7 @@ declare function hourPlans(opts?: BasicsOptions): CollectionBrick<{
1482
1482
  readonly not: true;
1483
1483
  };
1484
1484
  };
1485
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1485
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1486
1486
  readonly options: readonly [{
1487
1487
  readonly value: "mo";
1488
1488
  readonly label: {
@@ -1562,7 +1562,7 @@ declare function hourPlans(opts?: BasicsOptions): CollectionBrick<{
1562
1562
  readonly not: true;
1563
1563
  };
1564
1564
  };
1565
- readonly day: ChoiceField<"fr" | "th" | "mo" | "tu" | "we" | "sa" | "su"> & Omit<{
1565
+ readonly day: ChoiceField<"th" | "mo" | "tu" | "we" | "fr" | "sa" | "su"> & Omit<{
1566
1566
  readonly options: readonly [{
1567
1567
  readonly value: "mo";
1568
1568
  readonly label: {
package/dist/vue.d.mts CHANGED
@@ -20,6 +20,11 @@ declare const GinkoMarkdown: vue.DefineComponent<vue.ExtractPropTypes<{
20
20
  type: PropType<AttributeRegistry>;
21
21
  default: undefined;
22
22
  };
23
+ /** Puts `idPrefix-` before every id and `#` link of this body, for a page that shows several bodies. The tree's table of contents keeps the plain ids. */
24
+ idPrefix: {
25
+ type: StringConstructor;
26
+ default: string;
27
+ };
23
28
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
24
29
  [key: string]: any;
25
30
  }> | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
@@ -37,10 +42,16 @@ declare const GinkoMarkdown: vue.DefineComponent<vue.ExtractPropTypes<{
37
42
  type: PropType<AttributeRegistry>;
38
43
  default: undefined;
39
44
  };
45
+ /** Puts `idPrefix-` before every id and `#` link of this body, for a page that shows several bodies. The tree's table of contents keeps the plain ids. */
46
+ idPrefix: {
47
+ type: StringConstructor;
48
+ default: string;
49
+ };
40
50
  }>> & Readonly<{}>, {
41
51
  value: MarkdownTree | null | undefined;
42
52
  components: Record<string, string | Component>;
43
53
  registry: AttributeRegistry;
54
+ idPrefix: string;
44
55
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
45
56
 
46
57
  export { GinkoMarkdown };
package/dist/vue.d.ts CHANGED
@@ -20,6 +20,11 @@ declare const GinkoMarkdown: vue.DefineComponent<vue.ExtractPropTypes<{
20
20
  type: PropType<AttributeRegistry>;
21
21
  default: undefined;
22
22
  };
23
+ /** Puts `idPrefix-` before every id and `#` link of this body, for a page that shows several bodies. The tree's table of contents keeps the plain ids. */
24
+ idPrefix: {
25
+ type: StringConstructor;
26
+ default: string;
27
+ };
23
28
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
24
29
  [key: string]: any;
25
30
  }> | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
@@ -37,10 +42,16 @@ declare const GinkoMarkdown: vue.DefineComponent<vue.ExtractPropTypes<{
37
42
  type: PropType<AttributeRegistry>;
38
43
  default: undefined;
39
44
  };
45
+ /** Puts `idPrefix-` before every id and `#` link of this body, for a page that shows several bodies. The tree's table of contents keeps the plain ids. */
46
+ idPrefix: {
47
+ type: StringConstructor;
48
+ default: string;
49
+ };
40
50
  }>> & Readonly<{}>, {
41
51
  value: MarkdownTree | null | undefined;
42
52
  components: Record<string, string | Component>;
43
53
  registry: AttributeRegistry;
54
+ idPrefix: string;
44
55
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
45
56
 
46
57
  export { GinkoMarkdown };
package/dist/vue.mjs CHANGED
@@ -62,6 +62,14 @@ function dropUnsafe(node, components, registry) {
62
62
  const safe = Object.fromEntries(Object.entries(props ?? {}).filter(([name, value]) => !attributeProblem(tag ?? "", name, value, registry)));
63
63
  return [[tag, safe, ...children.flatMap((child) => dropUnsafe(child, components, registry))]];
64
64
  }
65
+ function prefixIds(node, prefix) {
66
+ if (!Array.isArray(node)) return node;
67
+ const [tag, props, ...children] = node;
68
+ const next = { ...props };
69
+ if (typeof next.id === "string" && next.id) next.id = `${prefix}-${next.id}`;
70
+ if (typeof next.href === "string" && next.href.length > 1 && next.href.startsWith("#")) next.href = `#${prefix}-${next.href.slice(1)}`;
71
+ return [tag, next, ...children.map((child) => prefixIds(child, prefix))];
72
+ }
65
73
  const GinkoMarkdown = defineComponent({
66
74
  name: "GinkoMarkdown",
67
75
  props: {
@@ -69,13 +77,16 @@ const GinkoMarkdown = defineComponent({
69
77
  /** Tag → component (or another tag name), e.g. `{ callout: Callout }`. Other tags use a global component of that name (PascalCase), else a plain element. */
70
78
  components: { type: Object, default: () => ({}) },
71
79
  /** 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-*`. */
72
- registry: { type: Object, default: void 0 }
80
+ registry: { type: Object, default: void 0 },
81
+ /** Puts `idPrefix-` before every id and `#` link of this body, for a page that shows several bodies. The tree's table of contents keeps the plain ids. */
82
+ idPrefix: { type: String, default: "" }
73
83
  },
74
84
  setup(props) {
75
85
  return () => {
76
86
  if (!props.value) return null;
77
87
  const components = { ...sourceOnly, ...props.components };
78
- const nodes = props.value.nodes.flatMap((node) => dropUnsafe(node, components, props.registry)).map(labelCheckboxes);
88
+ const safe = props.value.nodes.flatMap((node) => dropUnsafe(node, components, props.registry)).map(labelCheckboxes);
89
+ const nodes = props.idPrefix ? safe.map((node) => prefixIds(node, props.idPrefix)) : safe;
79
90
  return h(MarkdownDocument, { value: { nodes }, components });
80
91
  };
81
92
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lupinum/ginko",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "Ginko: a typed, file-based content model for Nuxt sites (core, CLI and Nuxt module).",
5
5
  "license": "MIT",
6
6
  "author": "Lupinum OG <info@lupinum.com> (https://lupinum.com)",
@@ -66,14 +66,14 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@comark/vue": "0.7.0",
69
- "@lupinum/ginko-i18n": "^0.6.1",
69
+ "@lupinum/ginko-i18n": "^0.6.3",
70
70
  "@nuxt/kit": "^4.6.0",
71
71
  "@zbsearch/stemmers": "4.0.1",
72
72
  "comark": "0.7.0",
73
73
  "minisearch": "7.2.0"
74
74
  },
75
75
  "devDependencies": {
76
- "@lupinum/ginko-content": "^0.6.1",
76
+ "@lupinum/ginko-content": "^0.6.3",
77
77
  "@vue/test-utils": "2.5.1",
78
78
  "happy-dom": "20.14.5",
79
79
  "nuxt": "4.6.0",