@caretcms/core 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +195 -12
- package/dist/index.d.ts +26 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +113 -12
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +35 -3
- package/dist/loader.js.map +1 -1
- package/dist/markdown/paragraphs.d.ts +14 -0
- package/dist/markdown/paragraphs.d.ts.map +1 -0
- package/dist/markdown/paragraphs.js +61 -0
- package/dist/markdown/paragraphs.js.map +1 -0
- package/dist/markdown/remark.d.ts.map +1 -1
- package/dist/markdown/remark.js +1 -0
- package/dist/markdown/remark.js.map +1 -1
- package/dist/markdown/satteri.d.ts.map +1 -1
- package/dist/markdown/satteri.js +35 -9
- package/dist/markdown/satteri.js.map +1 -1
- package/dist/markdown/stamp.d.ts +0 -9
- package/dist/markdown/stamp.d.ts.map +1 -1
- package/dist/markdown/stamp.js +6 -0
- package/dist/markdown/stamp.js.map +1 -1
- package/dist/providers/deployment/github.d.ts +27 -0
- package/dist/providers/deployment/github.d.ts.map +1 -0
- package/dist/providers/deployment/github.js +180 -0
- package/dist/providers/deployment/github.js.map +1 -0
- package/dist/providers/deployment/simulated.d.ts +10 -0
- package/dist/providers/deployment/simulated.d.ts.map +1 -0
- package/dist/providers/deployment/simulated.js +29 -0
- package/dist/providers/deployment/simulated.js.map +1 -0
- package/dist/runtime/auth/session.d.ts +1 -0
- package/dist/runtime/auth/session.d.ts.map +1 -1
- package/dist/runtime/auth/session.js +16 -0
- package/dist/runtime/auth/session.js.map +1 -1
- package/dist/runtime/authorization.d.ts +11 -0
- package/dist/runtime/authorization.d.ts.map +1 -0
- package/dist/runtime/authorization.js +29 -0
- package/dist/runtime/authorization.js.map +1 -0
- package/dist/runtime/collection-policy.d.ts +11 -0
- package/dist/runtime/collection-policy.d.ts.map +1 -0
- package/dist/runtime/collection-policy.js +44 -0
- package/dist/runtime/collection-policy.js.map +1 -0
- package/dist/runtime/config.d.ts +3 -0
- package/dist/runtime/config.d.ts.map +1 -1
- package/dist/runtime/config.js +4 -1
- package/dist/runtime/config.js.map +1 -1
- package/dist/runtime/content-errors.d.ts +9 -0
- package/dist/runtime/content-errors.d.ts.map +1 -0
- package/dist/runtime/content-errors.js +17 -0
- package/dist/runtime/content-errors.js.map +1 -0
- package/dist/runtime/content.d.ts.map +1 -1
- package/dist/runtime/content.js +13 -4
- package/dist/runtime/content.js.map +1 -1
- package/dist/runtime/deployment-status.d.ts +14 -0
- package/dist/runtime/deployment-status.d.ts.map +1 -0
- package/dist/runtime/deployment-status.js +57 -0
- package/dist/runtime/deployment-status.js.map +1 -0
- package/dist/runtime/draft-state.d.ts +16 -0
- package/dist/runtime/draft-state.d.ts.map +1 -0
- package/dist/runtime/draft-state.js +29 -0
- package/dist/runtime/draft-state.js.map +1 -0
- package/dist/runtime/i18n.d.ts +97 -0
- package/dist/runtime/i18n.d.ts.map +1 -0
- package/dist/runtime/i18n.js +190 -0
- package/dist/runtime/i18n.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/middleware.d.ts.map +1 -1
- package/dist/runtime/middleware.js +61 -4
- package/dist/runtime/middleware.js.map +1 -1
- package/dist/runtime/mutations/contracts.d.ts +12 -0
- package/dist/runtime/mutations/contracts.d.ts.map +1 -1
- package/dist/runtime/mutations/contracts.js +54 -4
- package/dist/runtime/mutations/contracts.js.map +1 -1
- package/dist/runtime/mutations/engine.d.ts +2 -0
- package/dist/runtime/mutations/engine.d.ts.map +1 -1
- package/dist/runtime/mutations/engine.js +220 -57
- package/dist/runtime/mutations/engine.js.map +1 -1
- package/dist/runtime/providers.d.ts +4 -1
- package/dist/runtime/providers.d.ts.map +1 -1
- package/dist/runtime/providers.js +18 -1
- package/dist/runtime/providers.js.map +1 -1
- package/dist/runtime/publish-recovery.d.ts +32 -0
- package/dist/runtime/publish-recovery.d.ts.map +1 -0
- package/dist/runtime/publish-recovery.js +98 -0
- package/dist/runtime/publish-recovery.js.map +1 -0
- package/dist/runtime/publish.d.ts +10 -4
- package/dist/runtime/publish.d.ts.map +1 -1
- package/dist/runtime/publish.js +105 -63
- package/dist/runtime/publish.js.map +1 -1
- package/dist/runtime/rebuild-webhook.d.ts +4 -0
- package/dist/runtime/rebuild-webhook.d.ts.map +1 -1
- package/dist/runtime/rebuild-webhook.js +12 -2
- package/dist/runtime/rebuild-webhook.js.map +1 -1
- package/dist/runtime/request-context.d.ts +7 -1
- package/dist/runtime/request-context.d.ts.map +1 -1
- package/dist/runtime/request-context.js +7 -1
- package/dist/runtime/request-context.js.map +1 -1
- package/dist/runtime/rewrite.d.ts.map +1 -1
- package/dist/runtime/rewrite.js +28 -2
- package/dist/runtime/rewrite.js.map +1 -1
- package/dist/runtime/rich-allowlist.js +1 -1
- package/dist/runtime/rich-allowlist.js.map +1 -1
- package/dist/runtime/routes/admin-entry.d.ts.map +1 -1
- package/dist/runtime/routes/admin-entry.js +129 -21
- package/dist/runtime/routes/admin-entry.js.map +1 -1
- package/dist/runtime/routes/admin.d.ts.map +1 -1
- package/dist/runtime/routes/admin.js +28 -14
- package/dist/runtime/routes/admin.js.map +1 -1
- package/dist/runtime/routes/auth-login.d.ts.map +1 -1
- package/dist/runtime/routes/auth-login.js +4 -0
- package/dist/runtime/routes/auth-login.js.map +1 -1
- package/dist/runtime/routes/auth-logout.d.ts.map +1 -1
- package/dist/runtime/routes/auth-logout.js +7 -2
- package/dist/runtime/routes/auth-logout.js.map +1 -1
- package/dist/runtime/routes/auth-session.d.ts.map +1 -1
- package/dist/runtime/routes/auth-session.js +10 -2
- package/dist/runtime/routes/auth-session.js.map +1 -1
- package/dist/runtime/routes/collection-list.d.ts.map +1 -1
- package/dist/runtime/routes/collection-list.js +213 -66
- package/dist/runtime/routes/collection-list.js.map +1 -1
- package/dist/runtime/routes/deployment.d.ts +5 -0
- package/dist/runtime/routes/deployment.d.ts.map +1 -0
- package/dist/runtime/routes/deployment.js +38 -0
- package/dist/runtime/routes/deployment.js.map +1 -0
- package/dist/runtime/routes/draft.d.ts.map +1 -1
- package/dist/runtime/routes/draft.js +10 -3
- package/dist/runtime/routes/draft.js.map +1 -1
- package/dist/runtime/routes/entries.d.ts.map +1 -1
- package/dist/runtime/routes/entries.js +87 -43
- package/dist/runtime/routes/entries.js.map +1 -1
- package/dist/runtime/routes/history.d.ts.map +1 -1
- package/dist/runtime/routes/history.js +40 -21
- package/dist/runtime/routes/history.js.map +1 -1
- package/dist/runtime/routes/mutate.d.ts.map +1 -1
- package/dist/runtime/routes/mutate.js +4 -1
- package/dist/runtime/routes/mutate.js.map +1 -1
- package/dist/runtime/routes/publish.d.ts.map +1 -1
- package/dist/runtime/routes/publish.js +127 -33
- package/dist/runtime/routes/publish.js.map +1 -1
- package/dist/runtime/routes/schema.d.ts.map +1 -1
- package/dist/runtime/routes/schema.js +11 -2
- package/dist/runtime/routes/schema.js.map +1 -1
- package/dist/runtime/routes/studio-home.d.ts.map +1 -1
- package/dist/runtime/routes/studio-home.js +41 -20
- package/dist/runtime/routes/studio-home.js.map +1 -1
- package/dist/runtime/routes/upload.d.ts.map +1 -1
- package/dist/runtime/routes/upload.js +3 -0
- package/dist/runtime/routes/upload.js.map +1 -1
- package/dist/runtime/schema-registry.d.ts +8 -1
- package/dist/runtime/schema-registry.d.ts.map +1 -1
- package/dist/runtime/schema-registry.js +49 -3
- package/dist/runtime/schema-registry.js.map +1 -1
- package/dist/runtime/storage/entry-commit.d.ts +8 -0
- package/dist/runtime/storage/entry-commit.d.ts.map +1 -0
- package/dist/runtime/storage/entry-commit.js +45 -0
- package/dist/runtime/storage/entry-commit.js.map +1 -0
- package/dist/runtime/storage/filesystem-adapter.d.ts +5 -0
- package/dist/runtime/storage/filesystem-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/filesystem-adapter.js +12 -3
- package/dist/runtime/storage/filesystem-adapter.js.map +1 -1
- package/dist/runtime/storage/frontmatter-codec.d.ts +5 -23
- package/dist/runtime/storage/frontmatter-codec.d.ts.map +1 -1
- package/dist/runtime/storage/frontmatter-codec.js +156 -13
- package/dist/runtime/storage/frontmatter-codec.js.map +1 -1
- package/dist/runtime/storage/in-memory-adapter.d.ts +7 -0
- package/dist/runtime/storage/in-memory-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/in-memory-adapter.js +6 -0
- package/dist/runtime/storage/in-memory-adapter.js.map +1 -1
- package/dist/runtime/storage/markdown-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/markdown-adapter.js +18 -20
- package/dist/runtime/storage/markdown-adapter.js.map +1 -1
- package/dist/runtime/storage/session-overlay-adapter.d.ts +12 -4
- package/dist/runtime/storage/session-overlay-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/session-overlay-adapter.js +100 -13
- package/dist/runtime/storage/session-overlay-adapter.js.map +1 -1
- package/dist/runtime/storage/sidecar-meta-store.d.ts +5 -0
- package/dist/runtime/storage/sidecar-meta-store.d.ts.map +1 -1
- package/dist/runtime/storage/sidecar-meta-store.js +48 -5
- package/dist/runtime/storage/sidecar-meta-store.js.map +1 -1
- package/dist/runtime/themes/preset-tokens.js +4 -4
- package/dist/runtime/themes/preset-tokens.js.map +1 -1
- package/dist/runtime/utils.d.ts.map +1 -1
- package/dist/runtime/utils.js +3 -4
- package/dist/runtime/utils.js.map +1 -1
- package/dist/runtime/views/studio-layout.d.ts +3 -0
- package/dist/runtime/views/studio-layout.d.ts.map +1 -1
- package/dist/runtime/views/studio-layout.js +36 -13
- package/dist/runtime/views/studio-layout.js.map +1 -1
- package/dist/schema-utils.d.ts +7 -0
- package/dist/schema-utils.d.ts.map +1 -1
- package/dist/schema-utils.js +143 -0
- package/dist/schema-utils.js.map +1 -1
- package/dist/types.d.ts +165 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -3
- package/static/cms/admin-entry.css +144 -13
- package/static/cms/admin-entry.js +539 -586
- package/static/cms/dev-toolbar/app.js +78 -19
- package/static/cms/editor/config.js +35 -15
- package/static/cms/editor/content-map.css +8 -1
- package/static/cms/editor/content-map.js +62 -23
- package/static/cms/editor/deployment-status.js +66 -0
- package/static/cms/editor/draft-client.js +87 -0
- package/static/cms/editor/guards.js +20 -0
- package/static/cms/editor/helpers.js +30 -1
- package/static/cms/editor/highlight.js +1 -0
- package/static/cms/editor/image-edit.js +44 -1
- package/static/cms/editor/image-utils.js +23 -7
- package/static/cms/editor/link-follow.js +122 -41
- package/static/cms/editor/link-ui.css +10 -1
- package/static/cms/editor/linkify.js +2 -0
- package/static/cms/editor/md-block-edit.js +140 -37
- package/static/cms/editor/md-paragraphs.js +98 -0
- package/static/cms/editor/md-serialize.js +1 -1
- package/static/cms/editor/panel.js +53 -7
- package/static/cms/editor/preview-mode.js +44 -0
- package/static/cms/editor/publish-result.js +100 -0
- package/static/cms/editor/rich-toolbar.js +58 -15
- package/static/cms/editor/sanitize.js +6 -2
- package/static/cms/editor/save-queue.js +75 -17
- package/static/cms/editor/section-controls/activation.js +3 -0
- package/static/cms/editor/section-controls/api.js +25 -7
- package/static/cms/editor/section-controls/index.js +60 -8
- package/static/cms/editor/section-controls/model.js +39 -4
- package/static/cms/editor/section-controls/mutations.js +15 -0
- package/static/cms/editor/section-controls/page-context.js +9 -0
- package/static/cms/editor/section-controls/pickers.js +53 -2
- package/static/cms/editor/section-controls/reorder.js +23 -0
- package/static/cms/editor/section-controls/selection.js +6 -0
- package/static/cms/editor/section-controls/spacing-drag.js +16 -0
- package/static/cms/editor/section-controls/ui-elements.js +7 -0
- package/static/cms/editor/section-controls/utils.js +7 -0
- package/static/cms/editor/section-controls.css +18 -3
- package/static/cms/editor/security.js +13 -2
- package/static/cms/editor/stega-hydrate.js +17 -4
- package/static/cms/editor/sync.js +475 -56
- package/static/cms/editor/text-edit.js +37 -3
- package/static/cms/editor/text-link-interactions.js +59 -17
- package/static/cms/editor/toast.js +23 -9
- package/static/cms/editor/tokens-and-text.css +9 -0
- package/static/cms/editor/toolbar.css +5 -0
- package/static/cms/editor/toolbar.js +91 -101
- package/static/cms/editor.css +1 -1
- package/static/cms/editor.js +1 -0
- package/static/cms/studio/entry-loader.js +102 -0
- package/static/cms/studio/field-model.js +110 -0
- package/static/cms/studio/fields.js +319 -0
- package/static/cms/studio/history-client.js +74 -0
- package/static/cms/studio/mutation-client.js +74 -0
- package/static/cms/studio/sync-client.js +107 -0
- package/static/cms/studio/upload-client.js +109 -0
- package/static/cms/studio-tokens.css +4 -4
- package/static/cms/studio.css +24 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const MAX_TEXT = 512;
|
|
2
|
+
function cleanText(value) {
|
|
3
|
+
return typeof value === "string" && value.trim()
|
|
4
|
+
? value.trim().slice(0, MAX_TEXT)
|
|
5
|
+
: undefined;
|
|
6
|
+
}
|
|
7
|
+
function validBuildUrl(value) {
|
|
8
|
+
const text = cleanText(value);
|
|
9
|
+
if (!text)
|
|
10
|
+
return undefined;
|
|
11
|
+
try {
|
|
12
|
+
const url = new URL(text);
|
|
13
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.href : undefined;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** True when provider evidence proves the target revision was in the build. */
|
|
20
|
+
export function deploymentCoversTarget(target, deployed) {
|
|
21
|
+
if (!deployed)
|
|
22
|
+
return false;
|
|
23
|
+
if (target.commit && deployed.commit === target.commit)
|
|
24
|
+
return true;
|
|
25
|
+
if (target.published.length === 0)
|
|
26
|
+
return false;
|
|
27
|
+
const revisions = new Map(deployed.published.map(entry => [`${entry.collection}::${entry.id}`, entry]));
|
|
28
|
+
return target.published.every(targetEntry => {
|
|
29
|
+
const evidence = revisions.get(`${targetEntry.collection}::${targetEntry.id}`);
|
|
30
|
+
return Boolean(evidence && evidence.revision >= targetEntry.revision);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export function normalizeDeploymentEvidence(target, evidence, checkedAt = Date.now()) {
|
|
34
|
+
const buildId = cleanText(evidence.buildId) ?? null;
|
|
35
|
+
const buildUrl = validBuildUrl(evidence.buildUrl);
|
|
36
|
+
const message = cleanText(evidence.message);
|
|
37
|
+
if (!["deploying", "live", "failed"].includes(evidence.state)) {
|
|
38
|
+
return { configured: true, state: "unknown", buildId, target, checkedAt,
|
|
39
|
+
message: "Deployment provider returned an invalid state" };
|
|
40
|
+
}
|
|
41
|
+
if (evidence.state === "live" && (!buildId || !deploymentCoversTarget(target, evidence.deployed))) {
|
|
42
|
+
return { configured: true, state: "unknown", buildId, target, checkedAt,
|
|
43
|
+
message: buildId
|
|
44
|
+
? "The live build did not prove it contains this published revision"
|
|
45
|
+
: "The live deployment did not include a build identity" };
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
configured: true,
|
|
49
|
+
state: evidence.state,
|
|
50
|
+
buildId,
|
|
51
|
+
...(buildUrl ? { buildUrl } : {}),
|
|
52
|
+
...(message ? { message } : {}),
|
|
53
|
+
target,
|
|
54
|
+
checkedAt,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=deployment-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-status.js","sourceRoot":"","sources":["../../src/runtime/deployment-status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Private overlay state. Never accepted from mutation payloads or exposed as content. */
|
|
2
|
+
export declare const DRAFT_STATE_KEY = "__caret_draft__";
|
|
3
|
+
export declare const PUBLISH_RECOVERY_KEY = "__caret_publish__";
|
|
4
|
+
export declare const PRIVATE_ENTRY_KEYS: readonly ["__body", "__caret_tombstone__", "__caret_draft__", "__caret_publish__"];
|
|
5
|
+
export interface DraftState {
|
|
6
|
+
version: 1;
|
|
7
|
+
baseRevision: number;
|
|
8
|
+
baseData: Record<string, unknown> | null;
|
|
9
|
+
/** Structured saves replace the entry; body-only saves leave frontmatter alone. */
|
|
10
|
+
structured: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function contentWithoutState(data: Record<string, unknown>): Record<string, unknown>;
|
|
13
|
+
export declare function readDraftState(data: Record<string, unknown>): DraftState | null;
|
|
14
|
+
/** Object key ordering is not a content change. Arrays retain their order. */
|
|
15
|
+
export declare function sameContent(a: unknown, b: unknown): boolean;
|
|
16
|
+
//# sourceMappingURL=draft-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft-state.d.ts","sourceRoot":"","sources":["../../src/runtime/draft-state.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,eAAO,MAAM,eAAe,oBAAoB,CAAC;AACjD,eAAO,MAAM,oBAAoB,sBAAsB,CAAC;AACxD,eAAO,MAAM,kBAAkB,oFAAoF,CAAC;AAEpH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,CAAC,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,mFAAmF;IACnF,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG1F;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,GAAG,IAAI,CAM/E;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAO3D"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Private overlay state. Never accepted from mutation payloads or exposed as content. */
|
|
2
|
+
export const DRAFT_STATE_KEY = "__caret_draft__";
|
|
3
|
+
export const PUBLISH_RECOVERY_KEY = "__caret_publish__";
|
|
4
|
+
export const PRIVATE_ENTRY_KEYS = ["__body", "__caret_tombstone__", DRAFT_STATE_KEY, PUBLISH_RECOVERY_KEY];
|
|
5
|
+
export function contentWithoutState(data) {
|
|
6
|
+
const { [DRAFT_STATE_KEY]: _draft, [PUBLISH_RECOVERY_KEY]: _publish, ...content } = data;
|
|
7
|
+
return content;
|
|
8
|
+
}
|
|
9
|
+
export function readDraftState(data) {
|
|
10
|
+
const state = data[DRAFT_STATE_KEY];
|
|
11
|
+
if (!state || state.version !== 1 || !Number.isSafeInteger(state.baseRevision) || state.baseRevision < 0 ||
|
|
12
|
+
typeof state.structured !== "boolean" ||
|
|
13
|
+
(state.baseData !== null && (typeof state.baseData !== "object" || Array.isArray(state.baseData))))
|
|
14
|
+
return null;
|
|
15
|
+
return state;
|
|
16
|
+
}
|
|
17
|
+
/** Object key ordering is not a content change. Arrays retain their order. */
|
|
18
|
+
export function sameContent(a, b) {
|
|
19
|
+
if (a === b)
|
|
20
|
+
return true;
|
|
21
|
+
if (a === null || b === null || typeof a !== "object" || typeof b !== "object")
|
|
22
|
+
return false;
|
|
23
|
+
if (Array.isArray(a) !== Array.isArray(b))
|
|
24
|
+
return false;
|
|
25
|
+
const left = Object.keys(a), right = Object.keys(b);
|
|
26
|
+
return left.length === right.length && left.every(key => Object.hasOwn(b, key) &&
|
|
27
|
+
sameContent(a[key], b[key]));
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=draft-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft-state.js","sourceRoot":"","sources":["../../src/runtime/draft-state.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAC;AACjD,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC;AACxD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAQ,EAAE,qBAAqB,EAAE,eAAe,EAAE,oBAAoB,CAAU,CAAC;AAUpH,MAAM,UAAU,mBAAmB,CAAC,IAA6B;IAC/D,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,oBAAoB,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC;IACzF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAA6B;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAA2B,CAAC;IAC9D,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,YAAY,GAAG,CAAC;QACpG,OAAO,KAAK,CAAC,UAAU,KAAK,SAAS;QACrC,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,WAAW,CAAC,CAAU,EAAE,CAAU;IAChD,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC7F,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpD,OAAO,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC;QAC5E,WAAW,CAAE,CAA6B,CAAC,GAAG,CAAC,EAAG,CAA6B,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC3F,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export declare const EN_STUDIO_MESSAGES: {
|
|
2
|
+
readonly "nav.studio": "Studio";
|
|
3
|
+
readonly "nav.signOut": "Sign out";
|
|
4
|
+
readonly "home.title": "Content Studio";
|
|
5
|
+
readonly "home.intro": "Manage your collections and entries.";
|
|
6
|
+
readonly "home.empty": "No collections yet. Create one from Studio, edit any data-caret element on your site, or run npx @caretcms/caretize to make existing pages editable.";
|
|
7
|
+
readonly "count.entry": "entry";
|
|
8
|
+
readonly "count.entries": "entries";
|
|
9
|
+
readonly "common.error": "Error";
|
|
10
|
+
readonly "common.loading": "Loading…";
|
|
11
|
+
readonly "common.close": "Close";
|
|
12
|
+
readonly "common.cancel": "Cancel";
|
|
13
|
+
readonly "common.retry": "Retry";
|
|
14
|
+
readonly "common.saving": "Saving…";
|
|
15
|
+
readonly "collection.search": "Search";
|
|
16
|
+
readonly "collection.searchPlaceholder": "Search entries…";
|
|
17
|
+
readonly "collection.reorder": "Reorder";
|
|
18
|
+
readonly "collection.reordering": "Reordering…";
|
|
19
|
+
readonly "collection.new": "+ New";
|
|
20
|
+
readonly "collection.noEntries": "No entries yet.";
|
|
21
|
+
readonly "collection.createFirst": "Create First Entry";
|
|
22
|
+
readonly "collection.failed": "Failed to load entries.";
|
|
23
|
+
readonly "collection.saveOrder": "Save Order";
|
|
24
|
+
readonly "collection.newEntry": "New Entry";
|
|
25
|
+
readonly "collection.entryId": "Entry ID (slug)";
|
|
26
|
+
readonly "collection.entryIdPlaceholder": "e.g. my-first-entry";
|
|
27
|
+
readonly "collection.idHint": "Use a permanent internal address such as quiet-structures. Lowercase letters, numbers, and hyphens only.";
|
|
28
|
+
readonly "collection.publishHint": "You’ll add the content on the next screen. Collections with a Published switch remain hidden until you turn it on and Save.";
|
|
29
|
+
readonly "collection.create": "Create";
|
|
30
|
+
readonly "collection.untitled": "Untitled";
|
|
31
|
+
readonly "collection.published": "Published";
|
|
32
|
+
readonly "collection.unpublished": "Unpublished";
|
|
33
|
+
readonly "collection.invalid": "Invalid stored data — open to repair";
|
|
34
|
+
readonly "collection.invalidId": "Use lowercase letters, numbers, and hyphens only.";
|
|
35
|
+
readonly "collection.duplicateId": "An entry with this ID already exists.";
|
|
36
|
+
readonly "collection.createFailed": "Failed to create entry. Try again.";
|
|
37
|
+
readonly "entry.loadFailed": "Could not load this entry. Check its source or storage and retry.";
|
|
38
|
+
readonly "entry.unsupported_content": "This entry uses unsupported frontmatter syntax. Update its source format and retry; the file has not been changed.";
|
|
39
|
+
readonly "entry.invalid_content": "This entry contains invalid content. Correct its source file and retry.";
|
|
40
|
+
readonly "entry.storage_error": "Could not read this entry from storage. Check storage access and retry.";
|
|
41
|
+
readonly "collection.previous": "Previous";
|
|
42
|
+
readonly "collection.next": "Next";
|
|
43
|
+
readonly "collection.pagination": "Collection pages";
|
|
44
|
+
readonly "collection.noResults": "No matching entries.";
|
|
45
|
+
readonly "collection.unreadable": "Cannot read entry — open for details";
|
|
46
|
+
readonly "collection.range": "{start}–{end} of {total}";
|
|
47
|
+
readonly "collection.reorderScope": "Reorder is available when all entries are shown on one page without a search filter.";
|
|
48
|
+
readonly "entry.notFound": "Entry not found.";
|
|
49
|
+
readonly "entry.goBack": "Go back";
|
|
50
|
+
readonly "entry.savingLive": "Saving live";
|
|
51
|
+
readonly "entry.savingPreview": "Saving to private preview";
|
|
52
|
+
readonly "entry.preview": "Preview site ↗";
|
|
53
|
+
readonly "entry.history": "History";
|
|
54
|
+
readonly "entry.delete": "Delete";
|
|
55
|
+
readonly "entry.saveLive": "Save live";
|
|
56
|
+
readonly "entry.saveDraft": "Save draft";
|
|
57
|
+
readonly "entry.guideTitle": "How editing works";
|
|
58
|
+
readonly "entry.guideCopy": "Edit any field, add or remove repeatable rows, then choose Save. In the sidebar Studio, text and image edits preview on the page as you work; Save confirms them and refreshes the visual preview for structural changes. Click an image preview to replace it, or paste an image URL. When publication is enabled, the Published switch can show or hide the entry without deleting it.";
|
|
59
|
+
readonly "entry.versionHistory": "Version History";
|
|
60
|
+
readonly "entry.deleteTitle": "Delete Entry";
|
|
61
|
+
readonly "entry.deleteCopy": "Permanently delete this entry? A snapshot will be saved to history for recovery.";
|
|
62
|
+
readonly "entry.allSaved": "All changes saved";
|
|
63
|
+
readonly "entry.unsaved": "Unsaved changes";
|
|
64
|
+
readonly "entry.savingChanges": "Saving changes…";
|
|
65
|
+
readonly "entry.saved": "Saved";
|
|
66
|
+
readonly "entry.liveConfirm": "Save these changes directly to the live site?";
|
|
67
|
+
readonly "entry.validationFailed": "Validation failed";
|
|
68
|
+
readonly "entry.changedElsewhere": "Changed elsewhere — Save again to overwrite";
|
|
69
|
+
readonly "entry.deleteFailed": "Delete failed";
|
|
70
|
+
readonly "entry.deleting": "Deleting…";
|
|
71
|
+
readonly "entry.newGuideTitle": "Entry created with safe defaults";
|
|
72
|
+
readonly "entry.newGuideCopy": "Fill in the fields below. Save becomes available after your first change. In the sidebar Studio, text and image edits preview on the page as you work; Save confirms them and refreshes the visual preview for structural changes. When publication is enabled, new entries stay private until Published is turned on.";
|
|
73
|
+
readonly "field.add": "Add";
|
|
74
|
+
readonly "field.remove": "Remove";
|
|
75
|
+
readonly "field.moveUp": "Move up";
|
|
76
|
+
readonly "field.moveDown": "Move down";
|
|
77
|
+
readonly "field.drag": "Drag to reorder";
|
|
78
|
+
readonly "field.replaceImage": "Replace image";
|
|
79
|
+
readonly "field.uploadOrReplaceImage": "Upload or replace image";
|
|
80
|
+
readonly "field.chooseImage": "Choose an image";
|
|
81
|
+
readonly "login.title": "Sign in";
|
|
82
|
+
readonly "login.password": "Password";
|
|
83
|
+
readonly "login.placeholder": "Enter editor password";
|
|
84
|
+
readonly "login.submit": "Sign in";
|
|
85
|
+
readonly "login.invalid": "Invalid password.";
|
|
86
|
+
readonly "login.status": "Sign in to manage content.";
|
|
87
|
+
readonly "login.noPassword": "Caret needs an editor password before you can sign in.";
|
|
88
|
+
readonly "login.devPassword": "Temporary dev password active — check your terminal to sign in.";
|
|
89
|
+
readonly "login.back": "← Back to site";
|
|
90
|
+
readonly "login.failed": "Login failed";
|
|
91
|
+
};
|
|
92
|
+
export type StudioMessageKey = keyof typeof EN_STUDIO_MESSAGES;
|
|
93
|
+
export type StudioLocale = "en" | "es";
|
|
94
|
+
export type StudioDictionary = Partial<Record<StudioMessageKey, string>>;
|
|
95
|
+
export type ResolvedStudioDictionary = Record<StudioMessageKey, string>;
|
|
96
|
+
export declare function resolveStudioDictionary(locale?: StudioLocale, overrides?: StudioDictionary): ResolvedStudioDictionary;
|
|
97
|
+
//# sourceMappingURL=i18n.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/runtime/i18n.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0FrB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,CAAC;AACvC,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;AACzE,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;AA8FxE,wBAAgB,uBAAuB,CACrC,MAAM,GAAE,YAAmB,EAC3B,SAAS,GAAE,gBAAqB,GAC/B,wBAAwB,CAM1B"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
export const EN_STUDIO_MESSAGES = {
|
|
2
|
+
"nav.studio": "Studio",
|
|
3
|
+
"nav.signOut": "Sign out",
|
|
4
|
+
"home.title": "Content Studio",
|
|
5
|
+
"home.intro": "Manage your collections and entries.",
|
|
6
|
+
"home.empty": "No collections yet. Create one from Studio, edit any data-caret element on your site, or run npx @caretcms/caretize to make existing pages editable.",
|
|
7
|
+
"count.entry": "entry",
|
|
8
|
+
"count.entries": "entries",
|
|
9
|
+
"common.error": "Error",
|
|
10
|
+
"common.loading": "Loading…",
|
|
11
|
+
"common.close": "Close",
|
|
12
|
+
"common.cancel": "Cancel",
|
|
13
|
+
"common.retry": "Retry",
|
|
14
|
+
"common.saving": "Saving…",
|
|
15
|
+
"collection.search": "Search",
|
|
16
|
+
"collection.searchPlaceholder": "Search entries…",
|
|
17
|
+
"collection.reorder": "Reorder",
|
|
18
|
+
"collection.reordering": "Reordering…",
|
|
19
|
+
"collection.new": "+ New",
|
|
20
|
+
"collection.noEntries": "No entries yet.",
|
|
21
|
+
"collection.createFirst": "Create First Entry",
|
|
22
|
+
"collection.failed": "Failed to load entries.",
|
|
23
|
+
"collection.saveOrder": "Save Order",
|
|
24
|
+
"collection.newEntry": "New Entry",
|
|
25
|
+
"collection.entryId": "Entry ID (slug)",
|
|
26
|
+
"collection.entryIdPlaceholder": "e.g. my-first-entry",
|
|
27
|
+
"collection.idHint": "Use a permanent internal address such as quiet-structures. Lowercase letters, numbers, and hyphens only.",
|
|
28
|
+
"collection.publishHint": "You’ll add the content on the next screen. Collections with a Published switch remain hidden until you turn it on and Save.",
|
|
29
|
+
"collection.create": "Create",
|
|
30
|
+
"collection.untitled": "Untitled",
|
|
31
|
+
"collection.published": "Published",
|
|
32
|
+
"collection.unpublished": "Unpublished",
|
|
33
|
+
"collection.invalid": "Invalid stored data — open to repair",
|
|
34
|
+
"collection.invalidId": "Use lowercase letters, numbers, and hyphens only.",
|
|
35
|
+
"collection.duplicateId": "An entry with this ID already exists.",
|
|
36
|
+
"collection.createFailed": "Failed to create entry. Try again.",
|
|
37
|
+
"entry.loadFailed": "Could not load this entry. Check its source or storage and retry.",
|
|
38
|
+
"entry.unsupported_content": "This entry uses unsupported frontmatter syntax. Update its source format and retry; the file has not been changed.",
|
|
39
|
+
"entry.invalid_content": "This entry contains invalid content. Correct its source file and retry.",
|
|
40
|
+
"entry.storage_error": "Could not read this entry from storage. Check storage access and retry.",
|
|
41
|
+
"collection.previous": "Previous",
|
|
42
|
+
"collection.next": "Next",
|
|
43
|
+
"collection.pagination": "Collection pages",
|
|
44
|
+
"collection.noResults": "No matching entries.",
|
|
45
|
+
"collection.unreadable": "Cannot read entry — open for details",
|
|
46
|
+
"collection.range": "{start}–{end} of {total}",
|
|
47
|
+
"collection.reorderScope": "Reorder is available when all entries are shown on one page without a search filter.",
|
|
48
|
+
"entry.notFound": "Entry not found.",
|
|
49
|
+
"entry.goBack": "Go back",
|
|
50
|
+
"entry.savingLive": "Saving live",
|
|
51
|
+
"entry.savingPreview": "Saving to private preview",
|
|
52
|
+
"entry.preview": "Preview site ↗",
|
|
53
|
+
"entry.history": "History",
|
|
54
|
+
"entry.delete": "Delete",
|
|
55
|
+
"entry.saveLive": "Save live",
|
|
56
|
+
"entry.saveDraft": "Save draft",
|
|
57
|
+
"entry.guideTitle": "How editing works",
|
|
58
|
+
"entry.guideCopy": "Edit any field, add or remove repeatable rows, then choose Save. In the sidebar Studio, text and image edits preview on the page as you work; Save confirms them and refreshes the visual preview for structural changes. Click an image preview to replace it, or paste an image URL. When publication is enabled, the Published switch can show or hide the entry without deleting it.",
|
|
59
|
+
"entry.versionHistory": "Version History",
|
|
60
|
+
"entry.deleteTitle": "Delete Entry",
|
|
61
|
+
"entry.deleteCopy": "Permanently delete this entry? A snapshot will be saved to history for recovery.",
|
|
62
|
+
"entry.allSaved": "All changes saved",
|
|
63
|
+
"entry.unsaved": "Unsaved changes",
|
|
64
|
+
"entry.savingChanges": "Saving changes…",
|
|
65
|
+
"entry.saved": "Saved",
|
|
66
|
+
"entry.liveConfirm": "Save these changes directly to the live site?",
|
|
67
|
+
"entry.validationFailed": "Validation failed",
|
|
68
|
+
"entry.changedElsewhere": "Changed elsewhere — Save again to overwrite",
|
|
69
|
+
"entry.deleteFailed": "Delete failed",
|
|
70
|
+
"entry.deleting": "Deleting…",
|
|
71
|
+
"entry.newGuideTitle": "Entry created with safe defaults",
|
|
72
|
+
"entry.newGuideCopy": "Fill in the fields below. Save becomes available after your first change. In the sidebar Studio, text and image edits preview on the page as you work; Save confirms them and refreshes the visual preview for structural changes. When publication is enabled, new entries stay private until Published is turned on.",
|
|
73
|
+
"field.add": "Add",
|
|
74
|
+
"field.remove": "Remove",
|
|
75
|
+
"field.moveUp": "Move up",
|
|
76
|
+
"field.moveDown": "Move down",
|
|
77
|
+
"field.drag": "Drag to reorder",
|
|
78
|
+
"field.replaceImage": "Replace image",
|
|
79
|
+
"field.uploadOrReplaceImage": "Upload or replace image",
|
|
80
|
+
"field.chooseImage": "Choose an image",
|
|
81
|
+
"login.title": "Sign in",
|
|
82
|
+
"login.password": "Password",
|
|
83
|
+
"login.placeholder": "Enter editor password",
|
|
84
|
+
"login.submit": "Sign in",
|
|
85
|
+
"login.invalid": "Invalid password.",
|
|
86
|
+
"login.status": "Sign in to manage content.",
|
|
87
|
+
"login.noPassword": "Caret needs an editor password before you can sign in.",
|
|
88
|
+
"login.devPassword": "Temporary dev password active — check your terminal to sign in.",
|
|
89
|
+
"login.back": "← Back to site",
|
|
90
|
+
"login.failed": "Login failed",
|
|
91
|
+
};
|
|
92
|
+
const ES_STUDIO_MESSAGES = {
|
|
93
|
+
"nav.studio": "Estudio",
|
|
94
|
+
"nav.signOut": "Cerrar sesión",
|
|
95
|
+
"home.title": "Estudio de contenido",
|
|
96
|
+
"home.intro": "Administra tus colecciones y entradas.",
|
|
97
|
+
"home.empty": "Todavía no hay colecciones. Crea una desde el Estudio, edita un elemento data-caret del sitio o ejecuta npx @caretcms/caretize para hacer editables las páginas existentes.",
|
|
98
|
+
"count.entry": "entrada",
|
|
99
|
+
"count.entries": "entradas",
|
|
100
|
+
"common.error": "Error",
|
|
101
|
+
"common.loading": "Cargando…",
|
|
102
|
+
"common.close": "Cerrar",
|
|
103
|
+
"common.cancel": "Cancelar",
|
|
104
|
+
"common.retry": "Reintentar",
|
|
105
|
+
"common.saving": "Guardando…",
|
|
106
|
+
"collection.search": "Buscar",
|
|
107
|
+
"collection.searchPlaceholder": "Buscar entradas…",
|
|
108
|
+
"collection.reorder": "Reordenar",
|
|
109
|
+
"collection.reordering": "Reordenando…",
|
|
110
|
+
"collection.new": "+ Nueva",
|
|
111
|
+
"collection.noEntries": "Todavía no hay entradas.",
|
|
112
|
+
"collection.createFirst": "Crear la primera entrada",
|
|
113
|
+
"collection.failed": "No se pudieron cargar las entradas.",
|
|
114
|
+
"collection.saveOrder": "Guardar orden",
|
|
115
|
+
"collection.newEntry": "Nueva entrada",
|
|
116
|
+
"collection.entryId": "ID de la entrada (slug)",
|
|
117
|
+
"collection.entryIdPlaceholder": "p. ej., mi-primera-entrada",
|
|
118
|
+
"collection.idHint": "Usa una dirección interna permanente como estructuras-tranquilas. Solo letras minúsculas, números y guiones.",
|
|
119
|
+
"collection.publishHint": "Agregarás el contenido en la siguiente pantalla. Las entradas con el interruptor Publicado permanecen ocultas hasta que lo actives y guardes.",
|
|
120
|
+
"collection.create": "Crear",
|
|
121
|
+
"collection.untitled": "Sin título",
|
|
122
|
+
"collection.published": "Publicado",
|
|
123
|
+
"collection.unpublished": "Sin publicar",
|
|
124
|
+
"collection.invalid": "Datos guardados no válidos — abre para corregir",
|
|
125
|
+
"collection.invalidId": "Usa solo letras minúsculas, números y guiones.",
|
|
126
|
+
"collection.duplicateId": "Ya existe una entrada con este ID.",
|
|
127
|
+
"collection.createFailed": "No se pudo crear la entrada. Inténtalo de nuevo.",
|
|
128
|
+
"entry.loadFailed": "No se pudo cargar la entrada. Revisa el archivo o el almacenamiento y reintenta.",
|
|
129
|
+
"entry.unsupported_content": "El formato de metadatos de esta entrada no es compatible. Corrige el archivo y reintenta; no se ha modificado.",
|
|
130
|
+
"entry.invalid_content": "Esta entrada contiene datos no válidos. Corrige el archivo y reintenta.",
|
|
131
|
+
"entry.storage_error": "No se pudo leer esta entrada. Revisa el acceso al almacenamiento y reintenta.",
|
|
132
|
+
"collection.previous": "Anterior",
|
|
133
|
+
"collection.next": "Siguiente",
|
|
134
|
+
"collection.pagination": "Páginas de la colección",
|
|
135
|
+
"collection.noResults": "No hay entradas que coincidan.",
|
|
136
|
+
"collection.unreadable": "No se puede leer — abre para ver detalles",
|
|
137
|
+
"collection.range": "{start}–{end} de {total}",
|
|
138
|
+
"collection.reorderScope": "Solo se puede reordenar cuando todas las entradas aparecen en una página sin filtros.",
|
|
139
|
+
"entry.notFound": "No se encontró la entrada.",
|
|
140
|
+
"entry.goBack": "Volver",
|
|
141
|
+
"entry.savingLive": "Guardado directo en el sitio",
|
|
142
|
+
"entry.savingPreview": "Guardado en vista previa privada",
|
|
143
|
+
"entry.preview": "Ver sitio ↗",
|
|
144
|
+
"entry.history": "Historial",
|
|
145
|
+
"entry.delete": "Eliminar",
|
|
146
|
+
"entry.saveLive": "Guardar en vivo",
|
|
147
|
+
"entry.saveDraft": "Guardar borrador",
|
|
148
|
+
"entry.guideTitle": "Cómo funciona la edición",
|
|
149
|
+
"entry.guideCopy": "Edita cualquier campo, agrega o elimina filas repetibles y luego guarda. En el Estudio lateral, los cambios de texto e imagen aparecen mientras trabajas; Guardar los confirma y actualiza la vista para los cambios estructurales. Haz clic en una imagen para reemplazarla o pega una URL. Cuando la publicación está habilitada, el interruptor Publicado muestra u oculta la entrada sin eliminarla.",
|
|
150
|
+
"entry.versionHistory": "Historial de versiones",
|
|
151
|
+
"entry.deleteTitle": "Eliminar entrada",
|
|
152
|
+
"entry.deleteCopy": "¿Eliminar esta entrada permanentemente? Se guardará una copia en el historial para poder recuperarla.",
|
|
153
|
+
"entry.allSaved": "Todos los cambios están guardados",
|
|
154
|
+
"entry.unsaved": "Cambios sin guardar",
|
|
155
|
+
"entry.savingChanges": "Guardando cambios…",
|
|
156
|
+
"entry.saved": "Guardado",
|
|
157
|
+
"entry.liveConfirm": "¿Guardar estos cambios directamente en el sitio público?",
|
|
158
|
+
"entry.validationFailed": "La validación falló",
|
|
159
|
+
"entry.changedElsewhere": "Hubo cambios en otro lugar — vuelve a guardar para sobrescribir",
|
|
160
|
+
"entry.deleteFailed": "No se pudo eliminar",
|
|
161
|
+
"entry.deleting": "Eliminando…",
|
|
162
|
+
"entry.newGuideTitle": "Entrada creada con valores seguros",
|
|
163
|
+
"entry.newGuideCopy": "Completa los campos. Guardar estará disponible después del primer cambio. En el Estudio lateral, los cambios de texto e imagen aparecen mientras trabajas; Guardar los confirma y actualiza la vista para los cambios estructurales. Cuando la publicación está habilitada, las entradas nuevas permanecen privadas hasta activar Publicado.",
|
|
164
|
+
"field.add": "Agregar",
|
|
165
|
+
"field.remove": "Eliminar",
|
|
166
|
+
"field.moveUp": "Mover arriba",
|
|
167
|
+
"field.moveDown": "Mover abajo",
|
|
168
|
+
"field.drag": "Arrastrar para reordenar",
|
|
169
|
+
"field.replaceImage": "Reemplazar imagen",
|
|
170
|
+
"field.uploadOrReplaceImage": "Subir o reemplazar imagen",
|
|
171
|
+
"field.chooseImage": "Elegir una imagen",
|
|
172
|
+
"login.title": "Iniciar sesión",
|
|
173
|
+
"login.password": "Contraseña",
|
|
174
|
+
"login.placeholder": "Ingresa la contraseña de edición",
|
|
175
|
+
"login.submit": "Iniciar sesión",
|
|
176
|
+
"login.invalid": "Contraseña incorrecta.",
|
|
177
|
+
"login.status": "Inicia sesión para administrar el contenido.",
|
|
178
|
+
"login.noPassword": "Caret necesita una contraseña de edición antes de iniciar sesión.",
|
|
179
|
+
"login.devPassword": "La contraseña temporal de desarrollo está activa — consúltala en la terminal.",
|
|
180
|
+
"login.back": "← Volver al sitio",
|
|
181
|
+
"login.failed": "No se pudo iniciar sesión",
|
|
182
|
+
};
|
|
183
|
+
export function resolveStudioDictionary(locale = "en", overrides = {}) {
|
|
184
|
+
return {
|
|
185
|
+
...EN_STUDIO_MESSAGES,
|
|
186
|
+
...(locale === "es" ? ES_STUDIO_MESSAGES : {}),
|
|
187
|
+
...overrides,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=i18n.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/runtime/i18n.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
export { bindEntry } from "./bind.js";
|
|
7
7
|
export { loadEntry, loadCollection, listCollections } from "./content.js";
|
|
8
8
|
export type { EntryData } from "./content.js";
|
|
9
|
+
export { isPublicEntry, isPublishedEntry } from "./collection-policy.js";
|
|
9
10
|
export { SessionOverlayAdapter } from "./storage/session-overlay-adapter.js";
|
|
10
11
|
export { QuotaUploadHandler } from "./storage/quota-upload-handler.js";
|
|
11
12
|
export type { QuotaCounter, QuotaUploadHandlerOptions, } from "./storage/quota-upload-handler.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1E,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1E,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAGzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,YAAY,EACV,YAAY,EACZ,yBAAyB,GAC1B,MAAM,mCAAmC,CAAC;AAI3C,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC"}
|
package/dist/runtime/index.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
export { bindEntry } from "./bind.js";
|
|
8
8
|
// Content loading — read stored data in .astro frontmatter (power-user API)
|
|
9
9
|
export { loadEntry, loadCollection, listCollections } from "./content.js";
|
|
10
|
+
export { isPublicEntry, isPublishedEntry } from "./collection-policy.js";
|
|
10
11
|
// Sandbox / multi-tenant primitives — used by Cloudflare adapter for demo mode
|
|
11
12
|
export { SessionOverlayAdapter } from "./storage/session-overlay-adapter.js";
|
|
12
13
|
export { QuotaUploadHandler } from "./storage/quota-upload-handler.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,6DAA6D;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,4EAA4E;AAC5E,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,6DAA6D;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,4EAA4E;AAC5E,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAEzE,+EAA+E;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAMvE,+DAA+D;AAC/D,wEAAwE;AACxE,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/runtime/middleware.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/runtime/middleware.ts"],"names":[],"mappings":"AAWA,OAAO,0BAA0B,CAAC;AAElC,KAAK,iBAAiB,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE;QACR,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;KACtD,CAAC;IACF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAqFF,KAAK,cAAc,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;AA4B9C,wBAAsB,SAAS,CAC7B,OAAO,EAAE,iBAAiB,EAC1B,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,QAAQ,CAAC,CAiLnB"}
|
|
@@ -5,6 +5,7 @@ import { runWithRequestContext } from "./request-context.js";
|
|
|
5
5
|
import { rewriteCaretAttributes } from "./rewrite.js";
|
|
6
6
|
import { hasStega, stegaClean } from "./stega.js";
|
|
7
7
|
import { SessionOverlayAdapter } from "./storage/session-overlay-adapter.js";
|
|
8
|
+
import { EDITOR_ID_RE } from "./storage/id-contracts.js";
|
|
8
9
|
// Side-effect import: registers any user-provided schemas into the schema registry
|
|
9
10
|
import "virtual:caretcms/schemas";
|
|
10
11
|
let _cachedRuntimeEnv;
|
|
@@ -77,9 +78,35 @@ async function resolveRuntimeEnv() {
|
|
|
77
78
|
}
|
|
78
79
|
return _cachedRuntimeEnv;
|
|
79
80
|
}
|
|
81
|
+
async function authenticateIdentity(adapter, request) {
|
|
82
|
+
if (!adapter)
|
|
83
|
+
return null;
|
|
84
|
+
try {
|
|
85
|
+
const identity = await adapter.authenticate(request);
|
|
86
|
+
if (!identity)
|
|
87
|
+
return null;
|
|
88
|
+
if (!EDITOR_ID_RE.test(identity.id)) {
|
|
89
|
+
console.error("[caretcms] Identity adapter returned an unsafe editor id; access denied.");
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
id: identity.id,
|
|
94
|
+
...(typeof identity.name === "string" ? { name: identity.name } : {}),
|
|
95
|
+
...(typeof identity.email === "string" ? { email: identity.email } : {}),
|
|
96
|
+
...(Array.isArray(identity.roles)
|
|
97
|
+
? { roles: identity.roles.filter((role) => typeof role === "string") }
|
|
98
|
+
: {}),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
console.error("[caretcms] Identity adapter authentication failed; access denied.", error);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
80
106
|
export async function onRequest(context, next) {
|
|
81
107
|
const services = await getRuntimeServices();
|
|
82
108
|
const runtimeEnv = await resolveRuntimeEnv();
|
|
109
|
+
const request = context.request ?? new Request("http://localhost/");
|
|
83
110
|
let adapter = services.adapter;
|
|
84
111
|
let uploadHandler = services.uploadHandler;
|
|
85
112
|
let sessionId = null;
|
|
@@ -87,14 +114,22 @@ export async function onRequest(context, next) {
|
|
|
87
114
|
let setCookieHeader = null;
|
|
88
115
|
let overlayActive = false;
|
|
89
116
|
const demoMode = isDemoModeEnabled(runtimeEnv);
|
|
117
|
+
const identity = demoMode
|
|
118
|
+
? null
|
|
119
|
+
: await authenticateIdentity(services.identityAdapter, request);
|
|
120
|
+
if (identity)
|
|
121
|
+
editorId = identity.id;
|
|
122
|
+
else if (!demoMode && !services.identityAdapter) {
|
|
123
|
+
editorId = getEditorId(context);
|
|
124
|
+
}
|
|
125
|
+
const policyActive = !demoMode && services.identityAdapter?.authorize !== undefined;
|
|
90
126
|
if (demoMode) {
|
|
91
|
-
const request = context.request ?? new Request("http://localhost/");
|
|
92
127
|
const resolution = resolveDemoSession(context, request);
|
|
93
128
|
sessionId = resolution.sessionId;
|
|
94
129
|
setCookieHeader = resolution.setCookieHeader;
|
|
95
130
|
if (services.adapter.makeSessionOverlay) {
|
|
96
131
|
const overlay = await services.adapter.makeSessionOverlay(sessionId);
|
|
97
|
-
adapter = new SessionOverlayAdapter(services.adapter, overlay);
|
|
132
|
+
adapter = new SessionOverlayAdapter(services.adapter, overlay, false);
|
|
98
133
|
overlayActive = true;
|
|
99
134
|
}
|
|
100
135
|
else {
|
|
@@ -104,13 +139,14 @@ export async function onRequest(context, next) {
|
|
|
104
139
|
uploadHandler = await services.uploadHandler.makeSessionWrapper(sessionId);
|
|
105
140
|
}
|
|
106
141
|
}
|
|
107
|
-
else if (isPreviewRequest(context) && services.adapter.makeEditorOverlay) {
|
|
142
|
+
else if ((isPreviewRequest(context) || policyActive) && services.adapter.makeEditorOverlay) {
|
|
108
143
|
// Draft/preview mode: an authenticated editor opting into preview reads and
|
|
109
144
|
// writes through their per-editor overlay (the public site keeps seeing the
|
|
110
145
|
// base). Keyed by the editor id from the session cookie; absent that (an
|
|
111
146
|
// unauthenticated preview request), there's no editor session so we leave the
|
|
112
147
|
// base adapter in place. Publish later flushes the overlay back to the base.
|
|
113
|
-
const id =
|
|
148
|
+
const id = identity?.id
|
|
149
|
+
?? (services.identityAdapter ? null : getEditorId(context));
|
|
114
150
|
if (id) {
|
|
115
151
|
const overlay = await services.adapter.makeEditorOverlay(id);
|
|
116
152
|
adapter = new SessionOverlayAdapter(services.adapter, overlay);
|
|
@@ -118,11 +154,31 @@ export async function onRequest(context, next) {
|
|
|
118
154
|
editorId = id;
|
|
119
155
|
}
|
|
120
156
|
}
|
|
157
|
+
const decisions = new Map();
|
|
158
|
+
const authorize = async (action, collection, id) => {
|
|
159
|
+
const key = JSON.stringify([action, collection, id]);
|
|
160
|
+
if (!decisions.has(key))
|
|
161
|
+
decisions.set(key, (async () => {
|
|
162
|
+
if (!identity || typeof services.identityAdapter?.authorize !== "function")
|
|
163
|
+
return false;
|
|
164
|
+
try {
|
|
165
|
+
return (await services.identityAdapter.authorize({ identity: structuredClone(identity), request, action, collection, id })) === true;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
console.error("[caretcms] Authorization policy failed; access denied.");
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
})());
|
|
172
|
+
return decisions.get(key);
|
|
173
|
+
};
|
|
121
174
|
const requestContext = {
|
|
122
175
|
adapter,
|
|
123
176
|
uploadHandler,
|
|
124
177
|
sessionId,
|
|
125
178
|
editorId,
|
|
179
|
+
identity,
|
|
180
|
+
identityAuthoritative: services.identityAdapter !== null,
|
|
181
|
+
...(policyActive ? { authorize } : {}),
|
|
126
182
|
demoMode,
|
|
127
183
|
overlayActive,
|
|
128
184
|
runtimeEnv,
|
|
@@ -135,6 +191,7 @@ export async function onRequest(context, next) {
|
|
|
135
191
|
// Mutate the live context object so the loaders see the gate during render.
|
|
136
192
|
requestContext.editor = isEditor;
|
|
137
193
|
context.locals.isEditor = isEditor;
|
|
194
|
+
context.locals.caretIdentity = identity;
|
|
138
195
|
const inner = await next();
|
|
139
196
|
const contentType = inner.headers.get("content-type") ?? "";
|
|
140
197
|
const contentEncoding = inner.headers.get("content-encoding") ?? "";
|