diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml
index 65dbfe7e1..cb6ec6d84 100644
--- a/.github/workflows/deploy.yaml
+++ b/.github/workflows/deploy.yaml
@@ -50,6 +50,8 @@ jobs:
uses: actions/configure-pages@v5
- name: Install Node.js dependencies
run: "npm ci"
+ - name: Build admin CMS
+ run: "npm run build:admin"
- name: Cache Hugo Resources
uses: actions/cache@v4
with:
diff --git a/.github/workflows/pullrequest.yaml b/.github/workflows/pullrequest.yaml
index dd6e5fd63..fa11391d2 100644
--- a/.github/workflows/pullrequest.yaml
+++ b/.github/workflows/pullrequest.yaml
@@ -44,6 +44,8 @@ jobs:
uses: actions/configure-pages@v5
- name: Install Node.js dependencies
run: "npm ci"
+ - name: Build admin CMS
+ run: "npm run build:admin"
- name: Cache Hugo Resources
uses: actions/cache@v4
with:
diff --git a/.gitignore b/.gitignore
index b0228f713..5594abba1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
node_modules/
public/
resources/
+static/admin/
hugo.exe
.hugo_build.lock
.DS_Store
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 49723a8ca..7b8da0a14 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -33,6 +33,12 @@ First of all, we have to the install the node packages by running:
npm i
```
+The CMS admin interface (`/admin`) is bundled separately with Vite and is not rebuilt automatically by Hugo. Run the following command whenever you change files in `assets/admin/` (or after installing/updating packages) to (re)generate it:
+
+```zsh
+npm run build:admin
+```
+
Then, we can start the integrated hugo server with:
```zsh
diff --git a/assets/admin/fields.js b/assets/admin/fields.js
new file mode 100644
index 000000000..ccf326809
--- /dev/null
+++ b/assets/admin/fields.js
@@ -0,0 +1,113 @@
+import { createElement as h } from "react";
+import { getFieldType, registerFieldType } from "@sveltia/cms";
+
+var SelectControl = getFieldType("select").control;
+
+function FipValiditySelectControl(props) {
+ var groups = props.entry ? props.entry.getIn(["data", "groups"]) : null;
+ groups = groups && typeof groups.toJS === "function" ? groups.toJS() : [];
+ var groupType = props.field ? props.field.get("group_type") : null;
+ if (groupType) {
+ groups = groups.filter(function (group) {
+ return !group.type || group.type === groupType;
+ });
+ }
+ var options = groups
+ .filter(function (group) {
+ return !!group.name;
+ })
+ .map(function (group) {
+ return { label: group.name, value: group.name };
+ });
+
+ return h(SelectControl, {
+ field: { name: props.field.get("name"), options },
+ value: props.value,
+ forID: props.forID,
+ onChange: props.onChange,
+ });
+}
+
+registerFieldType(
+ "fip-validity-select",
+ FipValiditySelectControl,
+ FipValiditySelectControl,
+);
+
+function CmsEditLinkControl(props) {
+ var field = props.field;
+ var getValue = field.get("get_value");
+ var hrefTemplate = field.get("href");
+ var labelTemplate = field.get("label_template");
+ var emptyHint = field.get("empty_hint");
+ var isStatic = field.get("static");
+
+ var value = isStatic ? "" : String(getValue(props) || "");
+
+ if (!isStatic && !value) {
+ return h("p", { className: "o-cms-edit-link__info" }, emptyHint);
+ }
+
+ var href = hrefTemplate.replace(/\{value\}/g, value);
+ var label = labelTemplate.replace(/\{value\}/g, value);
+ return h(
+ "p",
+ { className: "o-cms-edit-link__info" },
+ h(
+ "a",
+ {
+ href: href,
+ onClick: function (event) {
+ event.preventDefault();
+ if (
+ event.metaKey ||
+ event.ctrlKey ||
+ event.shiftKey ||
+ event.button === 1
+ ) {
+ window.open(href, "_blank");
+ return;
+ }
+ window.location.hash = href;
+ },
+ onAuxClick: function (event) {
+ event.preventDefault();
+ if (event.button === 1) {
+ window.open(href, "_blank");
+ }
+ },
+ },
+ label,
+ ),
+ );
+}
+
+registerFieldType("cms-edit-link", CmsEditLinkControl, CmsEditLinkControl);
+
+var NumberControl = getFieldType("number").control;
+
+function CmsNumberWithUsageControl(props) {
+ var field = props.field;
+ var template = field.get("template");
+ var value = props.value;
+
+ var text = template.replace(/\{value\}/g, String(value ?? ""));
+
+ return h(
+ "div",
+ {},
+ h(NumberControl, {
+ field: { name: field.get("name") },
+ value: value,
+ forID: props.forID,
+ onChange: props.onChange,
+ }),
+ h("p", { className: "o-cms-display__info" }, text),
+ );
+}
+
+registerFieldType(
+ "cms-number-with-usage",
+ CmsNumberWithUsageControl,
+ CmsNumberWithUsageControl,
+);
diff --git a/assets/admin/index.html b/assets/admin/index.html
new file mode 100644
index 000000000..e4060cf4b
--- /dev/null
+++ b/assets/admin/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ FIP Guide Content Manager
+
+
+
+
+
+
diff --git a/assets/admin/main.js b/assets/admin/main.js
new file mode 100644
index 000000000..9eafcb913
--- /dev/null
+++ b/assets/admin/main.js
@@ -0,0 +1,6 @@
+import CMS from "@sveltia/cms";
+
+import "./fields.js";
+import "./shortcodes.js";
+
+CMS.init();
diff --git a/assets/admin/shortcodes.js b/assets/admin/shortcodes.js
new file mode 100644
index 000000000..fcc0bdf36
--- /dev/null
+++ b/assets/admin/shortcodes.js
@@ -0,0 +1,1082 @@
+import { registerEditorComponent } from "@sveltia/cms";
+
+function parseHugoParams(str) {
+ var result = {};
+ var re = /([\w.]+)=(?:"([^"]*)"|(\S+))/g;
+ var m;
+ while ((m = re.exec(str)) !== null) {
+ var val = m[2] !== undefined ? m[2] : m[3];
+ if (val === "true") val = true;
+ else if (val === "false") val = false;
+ result[m[1]] = val;
+ }
+ return result;
+}
+
+function shortcodePattern(name, bracket) {
+ var open = bracket || "[%<]";
+ var close = bracket === "%" ? "%" : bracket === "<" ? ">" : "[%>]";
+ return new RegExp(
+ "\\{\\{" +
+ open +
+ " " +
+ name +
+ "(?![\\w-])([\\s\\S]*?)" +
+ close +
+ "\\}\\}([\\s\\S]*?)\\{\\{" +
+ open +
+ " \\/" +
+ name +
+ " " +
+ close +
+ "\\}\\}",
+ );
+}
+
+function selfClosingPattern(name) {
+ return new RegExp("\\{\\{[%<] " + name + "(?![\\w-])([\\s\\S]*?)[%>/]\\}\\}");
+}
+
+function dualFormPattern(name) {
+ return new RegExp(
+ "\\{\\{[%<] " +
+ name +
+ "(?![\\w-])([\\s\\S]*?)(?:\\/[%>]\\}\\}|[%>]\\}\\}([\\s\\S]*?)\\{\\{[%<] \\/" +
+ name +
+ " [%>]\\}\\})",
+ );
+}
+
+function renderParamList(fields, data) {
+ var out = [];
+ (fields || []).forEach(function (field) {
+ var spec = field.param;
+ if (!spec) return;
+ var value = data[field.name];
+ if (spec.transform) value = spec.transform(value, data);
+ if (!spec.required && !value) return;
+ if (spec.positional) {
+ out.push(spec.quote ? '"' + value + '"' : String(value));
+ return;
+ }
+ var paramName = spec.name || field.name;
+ out.push(paramName + "=" + (spec.bare ? String(value) : '"' + value + '"'));
+ });
+ return out;
+}
+
+function renderInlineOpen(bracket, name, params, closer) {
+ var paramsStr = params.join(" ");
+ var close =
+ closer === "slash"
+ ? bracket === "%"
+ ? "/%}}"
+ : "/>}}"
+ : bracket === "%"
+ ? "%}}"
+ : ">}}";
+ return (
+ "{{" +
+ bracket +
+ " " +
+ name +
+ (paramsStr ? " " + paramsStr : "") +
+ " " +
+ close
+ );
+}
+
+function renderMultilineOpen(bracket, name, params, opts) {
+ opts = opts || {};
+ var pad = " ";
+ var headParams = opts.firstInline ? params.slice(0, 1) : [];
+ var restParams = opts.firstInline ? params.slice(1) : params;
+ var close =
+ opts.closer === "slash"
+ ? bracket === "%"
+ ? "/%}}"
+ : "/>}}"
+ : bracket === "%"
+ ? "%}}"
+ : ">}}";
+ var header =
+ "{{" +
+ bracket +
+ " " +
+ name +
+ (headParams.length ? " " + headParams.join(" ") : "");
+ var lines = [header].concat(
+ restParams.map(function (p) {
+ return pad + p;
+ }),
+ );
+ return lines.join("\n") + "\n" + close;
+}
+
+function makeToBlock(name, cfg) {
+ var bracket = cfg.bracket || "%";
+ var bodyMode = cfg.bodyMode || "none";
+ var bodySep = cfg.bodySeparator || "\n";
+ var closeTag =
+ "{{" + bracket + " /" + name + " " + (bracket === "%" ? "%}}" : ">}}");
+
+ function openTag(params, closer) {
+ var wrap = cfg.multiline && params.length > (cfg.multilineThreshold || 0);
+ if (wrap) {
+ return renderMultilineOpen(bracket, name, params, {
+ firstInline: cfg.firstInline,
+ closer: closer,
+ });
+ }
+ return renderInlineOpen(bracket, name, params, closer);
+ }
+
+ return function (data) {
+ var params = renderParamList(cfg.fields, data);
+
+ if (bodyMode === "none") {
+ return openTag(params, "plain");
+ }
+
+ var body = String(data[cfg.bodyField || "body"] || "");
+
+ if (bodyMode === "dual") {
+ if (!body.trim()) return openTag(params, "slash");
+ return openTag(params, "plain") + bodySep + body + bodySep + closeTag;
+ }
+
+ var open = openTag(params, "plain");
+
+ if (bodyMode === "optionalPaired") {
+ return open + "\n" + (body ? body + "\n" : "") + closeTag;
+ }
+
+ return open + bodySep + body + bodySep + closeTag;
+ };
+}
+
+var highlightFields = [
+ {
+ name: "type",
+ label: "Type",
+ widget: "select",
+ options: ["important", "tip", "confusion", "inofficial"],
+ param: { positional: true, required: true },
+ },
+ {
+ name: "body",
+ label: "Content",
+ widget: "markdown",
+ editor_components: ["button", "float-image", "highlight", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "highlight",
+ label: "Highlight",
+ fields: highlightFields,
+ pattern: shortcodePattern("highlight", "%"),
+ fromBlock: function (match) {
+ return { type: match[1].trim(), body: match[2].trim() };
+ },
+ toBlock: makeToBlock("highlight", {
+ fields: highlightFields,
+ bodyMode: "required",
+ bodySeparator: "\n",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+registerEditorComponent({
+ id: "highlight-raw",
+ label: "Highlight",
+ fields: highlightFields,
+ pattern: shortcodePattern("highlight", "<"),
+ fromBlock: function (match) {
+ return { type: match[1].trim(), body: match[2].trim() };
+ },
+ toBlock: makeToBlock("highlight", {
+ bracket: "<",
+ fields: highlightFields,
+ bodyMode: "required",
+ bodySeparator: "\n",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var expanderFields = [
+ {
+ name: "title",
+ label: "Title",
+ widget: "string",
+ param: { positional: true, quote: true, required: true },
+ },
+ {
+ name: "variant",
+ label: "Variant",
+ widget: "select",
+ options: [{ label: "None", value: "" }, "border", "info"],
+ required: false,
+ param: { positional: true },
+ },
+ {
+ name: "body",
+ label: "Content",
+ widget: "markdown",
+ editor_components: ["button", "float-image", "highlight-raw", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "expander",
+ label: "Expander",
+ fields: expanderFields,
+ pattern: shortcodePattern("expander"),
+ fromBlock: function (match) {
+ var titleMatch = match[1].match(/"([^"]*)"/);
+ var rest = match[1].replace(/"[^"]*"/, "").trim();
+ var variantMatch = rest.match(/^(\w+)/);
+ return {
+ title: titleMatch ? titleMatch[1] : "",
+ variant: variantMatch ? variantMatch[1] : "",
+ body: match[2].trim(),
+ };
+ },
+ toBlock: makeToBlock("expander", {
+ fields: expanderFields,
+ bodyMode: "required",
+ bodySeparator: "\n\n",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var fipValidityFields = [
+ {
+ name: "type",
+ label: "Type",
+ widget: "select",
+ options: [
+ "fip-coupon",
+ "fip-reduced-ticket",
+ "fip-global-fare",
+ "additional",
+ ],
+ param: { required: true },
+ },
+ {
+ name: "status",
+ label: "Status",
+ widget: "select",
+ options: ["valid", "invalid", "unknown"],
+ param: { required: true },
+ },
+ {
+ name: "subtitle",
+ label: "Subtitle",
+ widget: "string",
+ required: false,
+ param: {},
+ },
+ {
+ name: "text",
+ label: "Additional Text",
+ widget: "string",
+ required: false,
+ param: {},
+ },
+ {
+ name: "disable_dialog",
+ label: "Disable info dialog",
+ widget: "boolean",
+ default: false,
+ required: false,
+ param: { bare: true },
+ },
+];
+
+registerEditorComponent({
+ id: "fip-validity",
+ label: "FIP Validity Badge",
+ fields: fipValidityFields,
+ pattern: selfClosingPattern("fip-validity"),
+ fromBlock: function (match) {
+ var p = parseHugoParams(match[1]);
+ return {
+ type: p.type || "fip-coupon",
+ status: p.status || "valid",
+ subtitle: p.subtitle || "",
+ text: p.text || "",
+ disable_dialog: p.disable_dialog === true,
+ };
+ },
+ toBlock: makeToBlock("fip-validity", {
+ bracket: "<",
+ fields: fipValidityFields,
+ bodyMode: "none",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var trainCategoryFields = [
+ {
+ name: "id",
+ label: "ID (anchor)",
+ widget: "string",
+ param: { required: true },
+ },
+ {
+ name: "title",
+ label: "Title",
+ widget: "string",
+ param: { required: true },
+ },
+ {
+ name: "type",
+ label: "Type",
+ widget: "select",
+ options: [
+ "highspeed",
+ "regional",
+ "subway",
+ "sleeper",
+ "funicular",
+ "bus",
+ "ship",
+ "tram",
+ ],
+ param: { required: true },
+ },
+ {
+ name: "fip_accepted",
+ label: "FIP accepted",
+ widget: "select",
+ options: [
+ { label: "No", value: "false" },
+ { label: "Yes", value: "true" },
+ { label: "Partially", value: "partially" },
+ { label: "Unknown", value: "unknown" },
+ ],
+ default: "true",
+ param: { bare: true, required: true },
+ },
+ {
+ name: "reservation_required",
+ label: "Reservation required",
+ widget: "select",
+ options: [
+ { label: "No", value: "false" },
+ { label: "Yes", value: "true" },
+ { label: "Partially", value: "partially" },
+ ],
+ default: "false",
+ param: { bare: true, required: true },
+ },
+ {
+ name: "reservation_possible",
+ label: "Reservation possible",
+ widget: "select",
+ options: [
+ { label: "No", value: "false" },
+ { label: "Yes", value: "true" },
+ { label: "Partially", value: "partially" },
+ ],
+ default: "false",
+ param: { bare: true, required: true },
+ },
+ {
+ name: "route_overview_url",
+ label: "Route overview URL",
+ widget: "string",
+ required: false,
+ param: {},
+ },
+ {
+ name: "additional_information_url",
+ label: "Additional information URL",
+ widget: "string",
+ required: false,
+ param: {},
+ },
+ {
+ name: "body",
+ label: "Description",
+ widget: "markdown",
+ editor_components: ["button", "float-image", "highlight-raw", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "train-category",
+ label: "Train Category",
+ fields: trainCategoryFields,
+ pattern: shortcodePattern("train-category"),
+ fromBlock: function (match) {
+ var p = parseHugoParams(match[1]);
+ return {
+ id: String(p.id || ""),
+ title: String(p.title || ""),
+ type: String(p.type || "regional"),
+ fip_accepted: String(p.fip_accepted ?? true),
+ reservation_required: String(p.reservation_required || "false"),
+ reservation_possible: String(p.reservation_possible || "false"),
+ route_overview_url: String(p.route_overview_url || ""),
+ additional_information_url: String(p.additional_information_url || ""),
+ body: match[2].trim(),
+ };
+ },
+ toBlock: makeToBlock("train-category", {
+ fields: trainCategoryFields,
+ bodyMode: "required",
+ bodySeparator: "\n\n",
+ multiline: true,
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var bookingFields = [
+ {
+ name: "id",
+ label: "Booking Platform",
+ widget: "relation",
+ collection: "booking",
+ search_fields: ["title"],
+ value_field: "{{slug}}",
+ display_fields: ["title"],
+ param: {
+ required: true,
+ transform: function (v) {
+ return String(v || "").replace(/\/index$/, "");
+ },
+ },
+ },
+ {
+ name: "booking_data_link",
+ label: "Booking Platform Link",
+ widget: "cms-edit-link",
+ static: true,
+ href: "#/collections/booking",
+ label_template: "Manage Booking Platforms \u2192",
+ },
+ {
+ name: "subtitle",
+ label: "Subtitle",
+ widget: "string",
+ required: false,
+ param: {},
+ },
+ {
+ name: "classes_first",
+ label: "1st class reservation costs (overwrite)",
+ widget: "string",
+ required: false,
+ param: { name: "classes.first" },
+ },
+ {
+ name: "classes_second",
+ label: "2nd class reservation costs (overwrite)",
+ widget: "string",
+ required: false,
+ param: { name: "classes.second" },
+ },
+ {
+ name: "fip_50",
+ label: "FIP 50 (override)",
+ widget: "select",
+ required: false,
+ options: [
+ { label: "Default", value: "" },
+ { label: "Hide", value: "nil" },
+ { label: "Yes", value: "true" },
+ { label: "No", value: "false" },
+ ],
+ default: "",
+ param: { bare: true },
+ },
+ {
+ name: "fip_75",
+ label: "FIP 75 (override)",
+ widget: "select",
+ required: false,
+ options: [
+ { label: "Default", value: "" },
+ { label: "Hide", value: "nil" },
+ { label: "Yes", value: "true" },
+ { label: "No", value: "false" },
+ ],
+ default: "",
+ param: { bare: true },
+ },
+ {
+ name: "fip_global_fare",
+ label: "FIP Global Fare (override)",
+ widget: "select",
+ required: false,
+ options: [
+ { label: "Default", value: "" },
+ { label: "Hide", value: "nil" },
+ { label: "Yes", value: "true" },
+ { label: "No", value: "false" },
+ ],
+ default: "",
+ param: { bare: true },
+ },
+ {
+ name: "reservations",
+ label: "Reservations (override)",
+ widget: "select",
+ required: false,
+ options: [
+ { label: "Default", value: "" },
+ { label: "Hide", value: "nil" },
+ { label: "Yes", value: "true" },
+ { label: "No", value: "false" },
+ ],
+ default: "",
+ param: { bare: true },
+ },
+ {
+ name: "fee",
+ label: "Fee (override)",
+ widget: "string",
+ required: false,
+ hint: 'Overwrites the booking fee text, e.g. "5 %". Leave empty to use the booking platform default.',
+ param: {},
+ },
+ {
+ name: "body",
+ label: "Additional info",
+ widget: "markdown",
+ required: false,
+ editor_components: ["button", "float-image", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "booking",
+ label: "Booking",
+ fields: bookingFields,
+ pattern: dualFormPattern("booking"),
+ fromBlock: function (match) {
+ var p = parseHugoParams(match[1]);
+ var rawId = p.id ? String(p.id) : "";
+ return {
+ id: rawId,
+ booking_data_link: rawId,
+ subtitle: String(p.subtitle || ""),
+ classes_first: String(p["classes.first"] || ""),
+ classes_second: String(p["classes.second"] || ""),
+ fip_50: String(p.fip_50 ?? ""),
+ fip_75: String(p.fip_75 ?? ""),
+ fip_global_fare: String(p.fip_global_fare ?? ""),
+ reservations: String(p.reservations ?? ""),
+ fee: String(p.fee || ""),
+ body: match[2] ? match[2].trim() : "",
+ };
+ },
+ toBlock: makeToBlock("booking", {
+ fields: bookingFields,
+ bodyMode: "dual",
+ bodySeparator: "\n",
+ multiline: true,
+ firstInline: true,
+ multilineThreshold: 1,
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var bookingSectionFields = [
+ {
+ name: "section",
+ label: "Section",
+ widget: "select",
+ options: [
+ { label: "FIP 50", value: "fip_50" },
+ { label: "FIP 75", value: "fip_75" },
+ { label: "FIP Global Fare", value: "fip_global_fare" },
+ { label: "Reservations", value: "reservations" },
+ ],
+ param: { positional: true, quote: true, required: true },
+ },
+ {
+ name: "body",
+ label: "Content",
+ widget: "markdown",
+ editor_components: ["button", "float-image", "highlight-raw", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "booking-section",
+ label: "Booking Section",
+ fields: bookingSectionFields,
+ pattern: shortcodePattern("booking-section"),
+ fromBlock: function (match) {
+ var sectionMatch = match[1].match(/"(\w+)"/);
+ return {
+ section: sectionMatch ? sectionMatch[1] : "",
+ body: match[2].trim(),
+ };
+ },
+ toBlock: makeToBlock("booking-section", {
+ fields: bookingSectionFields,
+ bodyMode: "required",
+ bodySeparator: "\n",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var buttonFields = [
+ {
+ name: "destination",
+ label: "URL",
+ widget: "string",
+ param: { required: true },
+ },
+ {
+ name: "text",
+ label: "Button text",
+ widget: "string",
+ param: { required: true },
+ },
+];
+
+registerEditorComponent({
+ id: "button",
+ label: "Button",
+ fields: buttonFields,
+ pattern: selfClosingPattern("button"),
+ fromBlock: function (match) {
+ var p = parseHugoParams(match[1]);
+ return {
+ destination: String(p.destination || ""),
+ text: String(p.text || ""),
+ };
+ },
+ toBlock: makeToBlock("button", {
+ bracket: "<",
+ fields: buttonFields,
+ bodyMode: "none",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var identifyOperatorFields = [
+ {
+ name: "sources",
+ label: "Sources",
+ widget: "relation",
+ collection: "identify-operator",
+ search_fields: ["title"],
+ value_field: "{{slug}}",
+ display_fields: ["title"],
+ multiple: true,
+ required: false,
+ param: {
+ transform: function (value) {
+ var arr = Array.isArray(value) ? value : value ? [value] : [];
+ return arr
+ .map(function (s) {
+ return String(s).replace(/\/index$/, "");
+ })
+ .join(",");
+ },
+ },
+ },
+ {
+ name: "body",
+ label: "Additional info",
+ widget: "markdown",
+ required: false,
+ editor_components: ["button", "float-image", "highlight", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "identify-operator",
+ label: "Identify Operator",
+ fields: identifyOperatorFields,
+ pattern: dualFormPattern("identify-operator"),
+ fromBlock: function (match) {
+ var p = parseHugoParams(match[1] || "");
+ return {
+ sources: p.sources
+ ? p.sources.split(",").map(function (s) {
+ return s.trim();
+ })
+ : [],
+ body: match[2] ? match[2].trim() : "",
+ };
+ },
+ toBlock: makeToBlock("identify-operator", {
+ bracket: "<",
+ fields: identifyOperatorFields,
+ bodyMode: "dual",
+ bodySeparator: "\n",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var satelliteFields = [
+ {
+ name: "body",
+ label: "Additional info",
+ widget: "markdown",
+ required: false,
+ editor_components: ["button", "float-image", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "satellite",
+ label: "Satellite Notice",
+ fields: satelliteFields,
+ pattern: dualFormPattern("satellite"),
+ fromBlock: function (match) {
+ return { body: match[2] ? match[2].trim() : "" };
+ },
+ toBlock: makeToBlock("satellite", {
+ fields: satelliteFields,
+ bodyMode: "dual",
+ bodySeparator: "\n",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var dialogFields = [
+ {
+ name: "id",
+ label: "Dialog ID (anchor)",
+ widget: "string",
+ param: { required: true },
+ },
+ {
+ name: "title",
+ label: "Title",
+ widget: "string",
+ param: { required: true },
+ },
+ {
+ name: "body",
+ label: "Content",
+ widget: "markdown",
+ editor_components: ["button", "float-image", "highlight", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "dialog",
+ label: "Dialog",
+ fields: dialogFields,
+ pattern: shortcodePattern("dialog"),
+ fromBlock: function (match) {
+ var p = parseHugoParams(match[1]);
+ return {
+ id: String(p.id || ""),
+ title: String(p.title || ""),
+ body: match[2].trim(),
+ };
+ },
+ toBlock: makeToBlock("dialog", {
+ fields: dialogFields,
+ bodyMode: "required",
+ bodySeparator: "\n",
+ multiline: true,
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var floatImageFields = [
+ { name: "src", label: "Image", widget: "image", param: { required: true } },
+ {
+ name: "alt",
+ label: "Alt text",
+ widget: "string",
+ param: { required: true },
+ },
+ {
+ name: "caption",
+ label: "Caption",
+ widget: "string",
+ required: false,
+ param: {},
+ },
+ {
+ name: "width",
+ label: "Width (CSS)",
+ widget: "string",
+ default: "50%",
+ required: false,
+ param: {},
+ },
+ {
+ name: "position",
+ label: "Position",
+ widget: "select",
+ options: ["right", "left"],
+ default: "right",
+ param: {},
+ },
+ {
+ name: "body",
+ label: "Surrounding text",
+ widget: "markdown",
+ required: false,
+ editor_components: ["button", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "float-image",
+ label: "Float Image",
+ fields: floatImageFields,
+ pattern: shortcodePattern("float-image"),
+ fromBlock: function (match) {
+ var p = parseHugoParams(match[1]);
+ return {
+ src: String(p.src || ""),
+ alt: String(p.alt || ""),
+ caption: String(p.caption || ""),
+ width: String(p.width || "50%"),
+ position: String(p.position || "right"),
+ body: match[2].trim(),
+ };
+ },
+ toBlock: makeToBlock("float-image", {
+ fields: floatImageFields,
+ bodyMode: "optionalPaired",
+ multiline: true,
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+registerEditorComponent({
+ id: "wip",
+ label: "Work in Progress",
+ fields: [],
+ pattern: selfClosingPattern("wip"),
+ fromBlock: function () {
+ return {};
+ },
+ toBlock: makeToBlock("wip", { bracket: "<", fields: [], bodyMode: "none" }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var updateFields = [
+ {
+ name: "date",
+ label: "Date",
+ widget: "datetime",
+ date_format: "YYYY-MM-DD",
+ time_format: false,
+ param: { required: true },
+ },
+ {
+ name: "body",
+ label: "Content",
+ widget: "markdown",
+ editor_components: ["button", "float-image", "highlight", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "update",
+ label: "Update",
+ fields: updateFields,
+ pattern: shortcodePattern("update"),
+ fromBlock: function (match) {
+ var p = parseHugoParams(match[1]);
+ return { date: String(p.date || ""), body: match[2].trim() };
+ },
+ toBlock: makeToBlock("update", {
+ fields: updateFields,
+ bodyMode: "required",
+ bodySeparator: "\n",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var columnFields = [
+ {
+ name: "width",
+ label: "Width (CSS)",
+ widget: "string",
+ param: { required: true },
+ },
+ {
+ name: "body",
+ label: "Content",
+ widget: "markdown",
+ editor_components: ["button", "float-image", "highlight", "image"],
+ },
+];
+
+registerEditorComponent({
+ id: "column",
+ label: "Column",
+ fields: columnFields,
+ pattern: shortcodePattern("column"),
+ fromBlock: function (match) {
+ var p = parseHugoParams(match[1]);
+ return { width: String(p.width || ""), body: match[2].trim() };
+ },
+ toBlock: makeToBlock("column", {
+ fields: columnFields,
+ bodyMode: "required",
+ bodySeparator: "\n",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var columnsFields = [
+ {
+ name: "body",
+ label: "Content",
+ widget: "markdown",
+ editor_components: ["column"],
+ },
+];
+
+registerEditorComponent({
+ id: "columns",
+ label: "Columns",
+ fields: columnsFields,
+ pattern: shortcodePattern("columns"),
+ fromBlock: function (match) {
+ return { body: match[2].trim() };
+ },
+ toBlock: makeToBlock("columns", {
+ fields: columnsFields,
+ bodyMode: "required",
+ bodySeparator: "\n",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
+
+var fipValidityTableFields = [
+ {
+ name: "type",
+ label: "Type",
+ widget: "select",
+ options: ["fip-coupon", "fip-reduced-ticket"],
+ param: { required: true },
+ },
+ {
+ name: "validity_data_link",
+ label: "FIP Validity Table",
+ widget: "cms-edit-link",
+ get_value: function () {
+ var match = window.location.hash.match(
+ /#\/collections\/application\/entries\/([^/]+)/,
+ );
+ return match ? match[1] : "";
+ },
+ href: "#/collections/fip-validity/entries/{value}/validity",
+ label_template:
+ "Edit the FIP Validity Table for \u201c{value}\u201d \u2192",
+ empty_hint: "Save this page first to link its FIP Validity Table.",
+ },
+];
+
+var footnoteFields = [
+ {
+ name: "id",
+ label: "Number",
+ widget: "cms-number-with-usage",
+ template:
+ "You can use this footnote by writing out [^{value}] in the text editor.",
+ param: { required: true },
+ },
+ {
+ name: "name",
+ label: "Source Name",
+ widget: "string",
+ param: { required: true },
+ },
+ {
+ name: "link",
+ label: "Link",
+ widget: "string",
+ param: { required: true },
+ },
+];
+
+registerEditorComponent({
+ id: "footnote",
+ label: "Footnote",
+ fields: footnoteFields,
+ pattern: /^\[\^([^\]]+)\]: \[([^\]]*)\]\(([^)]*)\)$/,
+ fromBlock: function (match) {
+ var num = Number(match[1]);
+ var id = Number.isNaN(num) ? match[1] : num;
+ return {
+ id: id,
+ name: String(match[2] || ""),
+ link: String(match[3] || ""),
+ };
+ },
+ toBlock: function (data) {
+ return (
+ "[^" +
+ (data.id ?? "") +
+ "]: [" +
+ (data.name || "") +
+ "](" +
+ (data.link || "") +
+ ")"
+ );
+ },
+ toPreview: function () {
+ return "";
+ },
+});
+
+registerEditorComponent({
+ id: "fip-validity-table",
+ label: "FIP Validity Table",
+ fields: fipValidityTableFields,
+ pattern: selfClosingPattern("fip-validity-table"),
+ fromBlock: function (match) {
+ var p = parseHugoParams(match[1]);
+ return { type: p.type || "fip-coupon" };
+ },
+ toBlock: makeToBlock("fip-validity-table", {
+ bracket: "<",
+ fields: fipValidityTableFields,
+ bodyMode: "none",
+ }),
+ toPreview: function () {
+ return "";
+ },
+});
diff --git a/static/admin/style.css b/assets/admin/style.css
similarity index 100%
rename from static/admin/style.css
rename to assets/admin/style.css
diff --git a/hugo.yaml b/hugo.yaml
index 02f3860d8..ae6ce0ea7 100644
--- a/hugo.yaml
+++ b/hugo.yaml
@@ -35,8 +35,6 @@ module:
target: "static/css/@fontsource"
- source: "node_modules/@material-symbols/svg-700/rounded"
target: "static/icons/material-symbols-rounded"
- - source: "node_modules/@sveltia/cms/dist"
- target: "static/admin/sveltia-cms"
hugoVersion:
min: "0.164.0"
diff --git a/netlify.toml b/netlify.toml
index 40eef66bc..8fab1904c 100644
--- a/netlify.toml
+++ b/netlify.toml
@@ -1,5 +1,5 @@
[build]
- command = "echo 'resourceDir: /opt/build/cache/resources_cache' >> hugo.yaml && FIPGUIDE_BRANCH=\"$HEAD\" hugo --gc --minify -b $DEPLOY_PRIME_URL && npx -y pagefind --site public"
+ command = "npm run build:admin && echo 'resourceDir: /opt/build/cache/resources_cache' >> hugo.yaml && FIPGUIDE_BRANCH=\"$HEAD\" hugo --gc --minify -b $DEPLOY_PRIME_URL && npx -y pagefind --site public"
publish = "public"
[build.environment]
diff --git a/package-lock.json b/package-lock.json
index accab1920..544d37993 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,12 +13,456 @@
"@fontsource/sansita": "^5.3.0",
"@material-symbols/svg-700": "^0.47.5",
"@panzoom/panzoom": "^4.6.2",
- "@sveltia/cms": "^0.220.0",
- "pagefind": "^1.5.2"
+ "@sveltia/cms": "^0.221.1",
+ "pagefind": "^1.5.2",
+ "react": "19.3.0"
},
"devDependencies": {
"prettier": "^3.9.9",
- "prettier-plugin-go-template": "^0.0.15"
+ "prettier-plugin-go-template": "^0.0.15",
+ "vite": "7.3.6"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
+ "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
+ "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
+ "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
+ "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
+ "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
+ "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
+ "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
+ "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
+ "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
+ "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
+ "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
+ "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
+ "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
+ "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
+ "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
+ "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
+ "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
+ "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
+ "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
+ "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
+ "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
"node_modules/@fontsource/roboto": {
@@ -45,6 +489,29 @@
"integrity": "sha512-3qo9xw/W36BP5G7UAvxOlBsJf83jFuOc++qm9fMkphW4HXmvSDLh0CE3MEK+ciXxKAPQrFddVj3T5rbDmRfnMw==",
"license": "Apache-2.0"
},
+ "node_modules/@mixmark-io/domino": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz",
+ "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/@napi-rs/lzma-linux-x64-gnu": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz",
+ "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^22.20 || ^24.12 || >=25"
+ }
+ },
"node_modules/@pagefind/darwin-arm64": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.5.2.tgz",
@@ -76,80 +543,800 @@
"resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.5.2.tgz",
"integrity": "sha512-7EVzo9+0w+2cbe671BtMj10UlNo83I+HrLVLfRxO731svHRJKUfJ/mo05gU14pe9PCfpKNQT8FS3Xc/oDN6pOA==",
"cpu": [
- "x64"
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@pagefind/linux-arm64": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.5.2.tgz",
+ "integrity": "sha512-Ovt9+K35sqzn8H3ZMXGwls4TD/wMJuvRtShHIsmUQREmaxjrDEX7gHckRCrwYJ4XE1H1p6HkLz3wukrAnsfXQw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@pagefind/linux-x64": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.5.2.tgz",
+ "integrity": "sha512-V+tFqHKXhQKq/WqPBD67AFy7scn1/aZID00ws4fSDd+1daSi5UHR9VVlRrOUYKxn3VuFQYRD7lYXdZK1WED1YA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@pagefind/windows-arm64": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/@pagefind/windows-arm64/-/windows-arm64-1.5.2.tgz",
+ "integrity": "sha512-hN9Nh90fNW61nNRCW9ZyQrAj/mD0eRvmJ8NlTUzkbuW8kIzGJUi3cxjFkEcMZ5h/8FsKWD/VcouZl4yo1F7B6g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@pagefind/windows-x64": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.5.2.tgz",
+ "integrity": "sha512-Fa2Iyw7kaDRzGMfNYNUXNW2zbL5FQVDgSOcbDHdzBrDEdpqOqg8TcZ68F22ol6NJ9IGzvUdmeyZypLW5dyhqsg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@panzoom/panzoom": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/@panzoom/panzoom/-/panzoom-4.6.2.tgz",
+ "integrity": "sha512-Zn3B5/hwa6eYIPRSKX0xf2clv8nviTX8AnAU5kU/EugiTDhG41ya2wlBqYrZJYCWQROr/5XkWObZhIkepi89qw==",
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.63.5.tgz",
+ "integrity": "sha512-J25QJU+B78T4FhhBsNpLJyVWOi31mwtpcMwywHmOKH65Q9IWGA81gPj+dnwlhU8wktVriYE+tFAaQgrnJRzAZg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.63.5.tgz",
+ "integrity": "sha512-LDopB3zuZM5Ux9TT2luNEBJW/tYbGU2g1d+VpKk6I+gSKDb+/7sYE6M225gRQt4RbMX6MSwMsVR/phdjVUgRLg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.63.5.tgz",
+ "integrity": "sha512-wlJEERGfeuHeBavCL2qVnNacOK43NDoZM4sjkeRPymd04OAE9T1zBqDJgmZ+CIsPTYKwdzpUC8vmOw84dwY4Tg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.63.5.tgz",
+ "integrity": "sha512-4nJJGg5jbo2wwPP4JP+LfEBA3bvP8rU9CLuhp7jWvq9sxEyhjQFTFdrqi+/dHEin/pd8jpT0vcehIpnZtmEdcQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.63.5.tgz",
+ "integrity": "sha512-DrZbyCDF1hneuO6jRbvZ2D7+PIBM6yIwYnJpg2vIk58T+wuFpiaGZrfUr59lDWw45bg+IrpTGLPiNi/Fk4w3Cg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.63.5.tgz",
+ "integrity": "sha512-gqfUVMJMB3mehqywxp6hTBFfgtMQykZY19+cfiaYP0toIJLb/1DZRJHVkQQGP13W4TAwfZDWeg1qBcheTRioXQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.63.5.tgz",
+ "integrity": "sha512-CFmhpvAwzSaWMlN3VN7UtmoTihlZNzoP0juQib5TQRnYUyDV8dXeWOp29sobWAT6gXl/hQgAClLlEiYozQG3OQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.63.5.tgz",
+ "integrity": "sha512-Uc9H8eXCOayV6JLTH5bXKMId6qbhNHa818/BgYjm4jrlq3vZquC9cqyvHBw17xy5Mnj5f+I3gFK5JcEf3hSqrw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.63.5.tgz",
+ "integrity": "sha512-VcPr/szv/1BFw112Kt//fxulXt/JPqzzidU84iW68L2DdjnOO8QFUv2zTSYBEPHD6movBD4z+bbr5y60GYM7Jw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.63.5.tgz",
+ "integrity": "sha512-BnxtJ5/91BrIHYIkGrmjz/lbMhqEHt1dPFqIxIFR+jPn0xVc/oUSCtIT089zfp5ufwGDlYz2UC+Fe1SRBpYFbQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.63.5.tgz",
+ "integrity": "sha512-LrYcHZwF+fAMNKHYTOQ5osWM4AZF7YF6D+XtsjDyEvljtt11twc+zHVXBLNEjxVSUnKYsOhvVz4Z213eW02COQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.63.5.tgz",
+ "integrity": "sha512-nj7QKQePAAUpCpJHtg0pR0W/b92A9NO17JS3BAQmHDn/yhmkir2p8llrKY9TOhleKIaSzy1JhxS3T9FVld6coA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.63.5.tgz",
+ "integrity": "sha512-5ylkX6dWMeBKge9nTU+Rxfb+ZfaCIJ9lRqIFaK0eAMcWp7OJbYnLveLgXmm0VrvuLKb8qIK+mHyH0qu88RM+iA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.63.5.tgz",
+ "integrity": "sha512-oHK4ZHYFDKjZviK34I+NwgfbGxgI7ztrNxj2hPTSSNFgeq1a/lEd7dHV2fdGAuTH4Iym3RHJg+vAbWaWG4B7Zg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.63.5.tgz",
+ "integrity": "sha512-UcetmHZ6XOXuUByiKZyQmb55ZPr0LABr3Ec/HB9wKZn6CEAFWZkE+hsJErJ9hbPBC7nI0dKuELx7CoV6IM7TMg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.63.5.tgz",
+ "integrity": "sha512-C5CmDPQBtvjVo8cgQsBs+w6WB0JLkiixhgi6hVLV11hERWdn/p0XcPU2OUcZzac9BPOFq7SbaHFa8r3SWEysCQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.63.5.tgz",
+ "integrity": "sha512-lHVQHJFKsuuxLMi3MQO9XVL8Tje3JR82CzB+QDKC5NWBcsIWuwsn9uIM5e3lBhI+fF1/s63qnyYqsg65+8rV/w==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.63.5.tgz",
+ "integrity": "sha512-3W9bTFcQNJn71cSJVM9RKIiZOy8DO/XLDii8Uv/Pm6WKqDRj7JV3ZfuXIEfyuy5LXpIzAbB/1M4Ukp9GKNa7nA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.63.5.tgz",
+ "integrity": "sha512-VDC7rRJlee/scpki96GZ27Omf6yU87s1YXwVTpjE5841faVlDYYT565rgfmoR1U0sqL7z5ivQSDjcsF6VRXyBA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.63.5.tgz",
+ "integrity": "sha512-z86Ok2p4pTdv5xqCKZsTooO7yBEiaJR/HzU3Wx8RmWsPoLppnMKROhJusQob8B3IE1ghC343kUW9rC2r+Wf3ig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.63.5.tgz",
+ "integrity": "sha512-IzQmj+xXwQFGhMAMKMQVXkMwMZN3TqkJgAE0nSsqvVwWWciP4AIPMmWRqOQ2GfX7TUDZr+xqGFcBS36CRPGw0g==",
+ "cpu": [
+ "arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
- "freebsd"
+ "openharmony"
]
},
- "node_modules/@pagefind/linux-arm64": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.5.2.tgz",
- "integrity": "sha512-Ovt9+K35sqzn8H3ZMXGwls4TD/wMJuvRtShHIsmUQREmaxjrDEX7gHckRCrwYJ4XE1H1p6HkLz3wukrAnsfXQw==",
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.63.5.tgz",
+ "integrity": "sha512-F6qpTaPc9bwBH85kjy0/BLmLSW1uv7AoOXCoRIkg2arlgCYlWYcAbiMkvZuAcaWk9TpCRG//okznLAqLGshkMw==",
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
- "linux"
+ "win32"
]
},
- "node_modules/@pagefind/linux-x64": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.5.2.tgz",
- "integrity": "sha512-V+tFqHKXhQKq/WqPBD67AFy7scn1/aZID00ws4fSDd+1daSi5UHR9VVlRrOUYKxn3VuFQYRD7lYXdZK1WED1YA==",
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.63.5.tgz",
+ "integrity": "sha512-igoDsTFhhwECBeGbUuLeIk7t8Y1apa+cs6mDWpx2EZ0ch7oEQgzHbFUXN9euoHekCAQzXdXApAGkV6jznS7tWw==",
"cpu": [
- "x64"
+ "ia32"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
- "linux"
+ "win32"
]
},
- "node_modules/@pagefind/windows-arm64": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/@pagefind/windows-arm64/-/windows-arm64-1.5.2.tgz",
- "integrity": "sha512-hN9Nh90fNW61nNRCW9ZyQrAj/mD0eRvmJ8NlTUzkbuW8kIzGJUi3cxjFkEcMZ5h/8FsKWD/VcouZl4yo1F7B6g==",
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.63.5.tgz",
+ "integrity": "sha512-U3teMeMbXFmaM5D+OTJpsOXd+wV/qftIeYF9kBKL4v73641qyJmoXFtA28DQLsnmlyayEsTe72xpLHrArq6vHw==",
"cpu": [
- "arm64"
+ "x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
- "node_modules/@pagefind/windows-x64": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.5.2.tgz",
- "integrity": "sha512-Fa2Iyw7kaDRzGMfNYNUXNW2zbL5FQVDgSOcbDHdzBrDEdpqOqg8TcZ68F22ol6NJ9IGzvUdmeyZypLW5dyhqsg==",
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.63.5.tgz",
+ "integrity": "sha512-ypfC34F3RKXvCXBglGqGMsUSMKlgwd1HX9AOAlx9RoZZ6GaI42YHVeKpzg3JG+wpBUJYTG+NNZhqbDWL8tBZkw==",
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
- "node_modules/@panzoom/panzoom": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/@panzoom/panzoom/-/panzoom-4.6.2.tgz",
- "integrity": "sha512-Zn3B5/hwa6eYIPRSKX0xf2clv8nviTX8AnAU5kU/EugiTDhG41ya2wlBqYrZJYCWQROr/5XkWObZhIkepi89qw==",
+ "node_modules/@shikijs/langs": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz",
+ "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "4.4.3"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@shikijs/themes": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz",
+ "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "4.4.3"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@shikijs/types": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz",
+ "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
+ "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
"license": "MIT"
},
"node_modules/@sveltia/cms": {
- "version": "0.220.0",
- "resolved": "https://registry.npmjs.org/@sveltia/cms/-/cms-0.220.0.tgz",
- "integrity": "sha512-MVIIfnw8ptT5GIPf0TtJDEVeJ/nQkJnC3ODPoo4tTtWfcdtulE0d66GQ7QunhhTBvdjmfg8Sv3xPMlZrPd4zlw==",
+ "version": "0.221.1",
+ "resolved": "https://registry.npmjs.org/@sveltia/cms/-/cms-0.221.1.tgz",
+ "integrity": "sha512-J+Qoik9kGMk2L7vNpOQrnDmFRi+NB6vwJ0f657YtsxWH0P8WYSYRRSRC2pQ/jGGbVlM//Pg/WIgmkpswqoo3gQ==",
"license": "MIT",
+ "dependencies": {
+ "@shikijs/langs": "4.4.3",
+ "@shikijs/themes": "4.4.3",
+ "exifr": "^7.1.3",
+ "immutable": "^5.1.9",
+ "leaflet": "^1.9.4",
+ "svgo": "^4.1.0",
+ "terra-draw": "^1.35.0",
+ "terra-draw-leaflet-adapter": "1.0.3",
+ "turndown": "^7.2.4"
+ },
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kyoshino"
+ },
+ "peerDependencies": {
+ "@types/react": "^19.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/hast": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz",
+ "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "license": "MIT"
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "license": "ISC"
+ },
+ "node_modules/commander": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-6.0.0.tgz",
+ "integrity": "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^7.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.2",
+ "nth-check": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-tree": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
+ "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.27.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-7.0.0.tgz",
+ "integrity": "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/csso": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
+ "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "~2.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/css-tree": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
+ "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.0.28",
+ "source-map-js": "^1.0.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/mdn-data": {
+ "version": "2.0.28",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
+ "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
+ "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.28.2",
+ "@esbuild/android-arm": "0.28.2",
+ "@esbuild/android-arm64": "0.28.2",
+ "@esbuild/android-x64": "0.28.2",
+ "@esbuild/darwin-arm64": "0.28.2",
+ "@esbuild/darwin-x64": "0.28.2",
+ "@esbuild/freebsd-arm64": "0.28.2",
+ "@esbuild/freebsd-x64": "0.28.2",
+ "@esbuild/linux-arm": "0.28.2",
+ "@esbuild/linux-arm64": "0.28.2",
+ "@esbuild/linux-ia32": "0.28.2",
+ "@esbuild/linux-loong64": "0.28.2",
+ "@esbuild/linux-mips64el": "0.28.2",
+ "@esbuild/linux-ppc64": "0.28.2",
+ "@esbuild/linux-riscv64": "0.28.2",
+ "@esbuild/linux-s390x": "0.28.2",
+ "@esbuild/linux-x64": "0.28.2",
+ "@esbuild/netbsd-arm64": "0.28.2",
+ "@esbuild/netbsd-x64": "0.28.2",
+ "@esbuild/openbsd-arm64": "0.28.2",
+ "@esbuild/openbsd-x64": "0.28.2",
+ "@esbuild/openharmony-arm64": "0.28.2",
+ "@esbuild/sunos-x64": "0.28.2",
+ "@esbuild/win32-arm64": "0.28.2",
+ "@esbuild/win32-ia32": "0.28.2",
+ "@esbuild/win32-x64": "0.28.2"
+ }
+ },
+ "node_modules/exifr": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz",
+ "integrity": "sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw==",
+ "license": "MIT"
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/immutable": {
+ "version": "5.1.9",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.9.tgz",
+ "integrity": "sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==",
+ "license": "MIT"
+ },
+ "node_modules/leaflet": {
+ "version": "1.9.4",
+ "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
+ "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/mdn-data": {
+ "version": "2.27.1",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
+ "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.19",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",
+ "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/pagefind": {
@@ -170,6 +1357,54 @@
"@pagefind/windows-x64": "1.5.2"
}
},
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.28",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",
+ "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.18",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
"node_modules/prettier": {
"version": "3.9.9",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.9.tgz",
@@ -202,6 +1437,150 @@
"prettier": "^3.0.0"
}
},
+ "node_modules/react": {
+ "version": "19.3.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz",
+ "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.63.5",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.63.5.tgz",
+ "integrity": "sha512-KRWwmNLlPw5M7HcdYfm15oBv9n9LPtjzpzCIxS/phwqvPyxHSoKX6Y2YU3pxSPfy0CLquVgsx/j/hBi6OvH1Nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.9"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@napi-rs/lzma-linux-x64-gnu": "1.5.1",
+ "@rollup/rollup-android-arm-eabi": "4.63.5",
+ "@rollup/rollup-android-arm64": "4.63.5",
+ "@rollup/rollup-darwin-arm64": "4.63.5",
+ "@rollup/rollup-darwin-x64": "4.63.5",
+ "@rollup/rollup-freebsd-arm64": "4.63.5",
+ "@rollup/rollup-freebsd-x64": "4.63.5",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.63.5",
+ "@rollup/rollup-linux-arm-musleabihf": "4.63.5",
+ "@rollup/rollup-linux-arm64-gnu": "4.63.5",
+ "@rollup/rollup-linux-arm64-musl": "4.63.5",
+ "@rollup/rollup-linux-loong64-gnu": "4.63.5",
+ "@rollup/rollup-linux-loong64-musl": "4.63.5",
+ "@rollup/rollup-linux-ppc64-gnu": "4.63.5",
+ "@rollup/rollup-linux-ppc64-musl": "4.63.5",
+ "@rollup/rollup-linux-riscv64-gnu": "4.63.5",
+ "@rollup/rollup-linux-riscv64-musl": "4.63.5",
+ "@rollup/rollup-linux-s390x-gnu": "4.63.5",
+ "@rollup/rollup-linux-x64-gnu": "4.63.5",
+ "@rollup/rollup-linux-x64-musl": "4.63.5",
+ "@rollup/rollup-openbsd-x64": "4.63.5",
+ "@rollup/rollup-openharmony-arm64": "4.63.5",
+ "@rollup/rollup-win32-arm64-msvc": "4.63.5",
+ "@rollup/rollup-win32-ia32-msvc": "4.63.5",
+ "@rollup/rollup-win32-x64-gnu": "4.63.5",
+ "@rollup/rollup-win32-x64-msvc": "4.63.5",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/sax": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz",
+ "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=11.0.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/svgo": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.1.0.tgz",
+ "integrity": "sha512-bkxnTg1kSU0guhIBmibA6UUhrQmPVA1XsQLN+ylCd+UWzbnLkySOcXpyk1mrl05f+pcaCx2eHb+sp6BgMZWX+Q==",
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^11.1.0",
+ "css-select": "^6.0.0",
+ "css-tree": "^3.0.1",
+ "css-what": "^7.0.0",
+ "csso": "^5.0.5",
+ "picocolors": "^1.1.1",
+ "sax": "1.6.1"
+ },
+ "bin": {
+ "svgo": "bin/svgo.js"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/svgo"
+ }
+ },
+ "node_modules/terra-draw": {
+ "version": "1.35.0",
+ "resolved": "https://registry.npmjs.org/terra-draw/-/terra-draw-1.35.0.tgz",
+ "integrity": "sha512-uQI8lcPiUMqwVV29CexTfvT/AM4lGHtA+xWraW4njVExiM1+eGvRetYOBXmXEmgy5pL4X2dmjwMRH8JEYVtbgw==",
+ "license": "MIT"
+ },
+ "node_modules/terra-draw-leaflet-adapter": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/terra-draw-leaflet-adapter/-/terra-draw-leaflet-adapter-1.0.3.tgz",
+ "integrity": "sha512-yYUDwyKxGj69pUzd4L2YclXwAxNhuXI01DCm8KbOtGxnf4I+PmFsAQrwA/sU5EbdaOj1AaPrPqadihgFvrSOng==",
+ "license": "MIT",
+ "peerDependencies": {
+ "leaflet": "^1.9.4",
+ "terra-draw": "^1.0.0"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/turndown": {
+ "version": "7.2.4",
+ "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.4.tgz",
+ "integrity": "sha512-I8yFsfRzmzK0WV1pNNOA4A7y4RDfFxPRxb3t+e3ui14qSGOxGtiSP6GjeX+Y6CHb7HYaFj7ECUD7VE5kQMZWGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@mixmark-io/domino": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=18",
+ "npm": ">=9"
+ }
+ },
"node_modules/ulid": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/ulid/-/ulid-2.4.0.tgz",
@@ -211,6 +1590,81 @@
"bin": {
"ulid": "bin/cli.js"
}
+ },
+ "node_modules/vite": {
+ "version": "7.3.6",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz",
+ "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.27.0 || ^0.28.0",
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rollup": "^4.43.0",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "lightningcss": "^1.21.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
}
}
}
diff --git a/package.json b/package.json
index ba65e9954..6a35e5a42 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,7 @@
"version": "1.0.0",
"main": "index.html",
"scripts": {
+ "build:admin": "vite build",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
@@ -21,11 +22,13 @@
"@fontsource/sansita": "^5.3.0",
"@material-symbols/svg-700": "^0.47.5",
"@panzoom/panzoom": "^4.6.2",
- "@sveltia/cms": "^0.220.0",
- "pagefind": "^1.5.2"
+ "@sveltia/cms": "^0.221.1",
+ "pagefind": "^1.5.2",
+ "react": "19.3.0"
},
"devDependencies": {
"prettier": "^3.9.9",
- "prettier-plugin-go-template": "^0.0.15"
+ "prettier-plugin-go-template": "^0.0.15",
+ "vite": "7.3.6"
}
}
diff --git a/static/admin/fields.js b/static/admin/fields.js
deleted file mode 100644
index df880e5ae..000000000
--- a/static/admin/fields.js
+++ /dev/null
@@ -1,116 +0,0 @@
-(function () {
- var SelectControl = CMS.getFieldType("select").control;
-
- function FipValiditySelectControl(props) {
- var groups = props.entry ? props.entry.getIn(["data", "groups"]) : null;
- groups = groups && typeof groups.toJS === "function" ? groups.toJS() : [];
- var groupType = props.field ? props.field.get("group_type") : null;
- if (groupType) {
- groups = groups.filter(function (group) {
- return !group.type || group.type === groupType;
- });
- }
- var options = groups
- .filter(function (group) {
- return !!group.name;
- })
- .map(function (group) {
- return { label: group.name, value: group.name };
- });
-
- return h(SelectControl, {
- field: { name: props.field.get("name"), options },
- value: props.value,
- forID: props.forID,
- onChange: props.onChange,
- });
- }
-
- CMS.registerFieldType(
- "fip-validity-select",
- FipValiditySelectControl,
- FipValiditySelectControl,
- );
-
- function CmsEditLinkControl(props) {
- var field = props.field;
- var getValue = field.get("get_value");
- var hrefTemplate = field.get("href");
- var labelTemplate = field.get("label_template");
- var emptyHint = field.get("empty_hint");
- var isStatic = field.get("static");
-
- var value = isStatic ? "" : String(getValue(props) || "");
-
- if (!isStatic && !value) {
- return h("p", { className: "o-cms-edit-link__info" }, emptyHint);
- }
-
- var href = hrefTemplate.replace(/\{value\}/g, value);
- var label = labelTemplate.replace(/\{value\}/g, value);
- return h(
- "p",
- { className: "o-cms-edit-link__info" },
- h(
- "a",
- {
- href: href,
- onClick: function (event) {
- event.preventDefault();
- if (
- event.metaKey ||
- event.ctrlKey ||
- event.shiftKey ||
- event.button === 1
- ) {
- window.open(href, "_blank");
- return;
- }
- window.location.hash = href;
- },
- onAuxClick: function (event) {
- event.preventDefault();
- if (event.button === 1) {
- window.open(href, "_blank");
- }
- },
- },
- label,
- ),
- );
- }
-
- CMS.registerFieldType(
- "cms-edit-link",
- CmsEditLinkControl,
- CmsEditLinkControl,
- );
-
- var NumberControl = CMS.getFieldType("number").control;
-
- function CmsNumberWithUsageControl(props) {
- var field = props.field;
- var template = field.get("template");
- var value = props.value;
-
- var text = template.replace(/\{value\}/g, String(value ?? ""));
-
- return h(
- "div",
- {},
- h(NumberControl, {
- field: { name: field.get("name") },
- value: value,
- forID: props.forID,
- onChange: props.onChange,
- }),
- h("p", { className: "o-cms-display__info" }, text),
- );
- }
-
- CMS.registerFieldType(
- "cms-number-with-usage",
- CmsNumberWithUsageControl,
- CmsNumberWithUsageControl,
- );
-})();
diff --git a/static/admin/index.html b/static/admin/index.html
index 7bf579281..263995a54 100644
--- a/static/admin/index.html
+++ b/static/admin/index.html
@@ -4,11 +4,9 @@
FIP Guide Content Manager
-
+
+
-
-
-