mechanica 2.0.3 → 2.1.0-beta.2
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/dist/chunks/{editor-JV0Nhfw4.js → editor-MStotuaz.js} +276 -106
- package/dist/chunks/node-adapter-4eD9p0iP.js +699 -0
- package/dist/chunks/page-assets-DsJXmoDs.js +70 -0
- package/dist/chunks/{page-assets-CM_MCuoa.js → rich-text-codec--Nssj0Nn.js} +71 -117
- package/dist/chunks/site-DR_X2rzc.js +62 -0
- package/dist/cli.js +59 -23
- package/dist/composer.js +16 -65
- package/dist/editor.css +112 -112
- package/dist/editor.js +69 -123
- package/dist/export.js +8 -5
- package/dist/plugin.js +69 -656
- package/dist/server.js +4 -0
- package/dist/types/cli/build.d.ts +3 -1
- package/dist/types/editor/lib/backend.d.ts +90 -0
- package/dist/types/editor/lib/page-list.d.ts +5 -20
- package/dist/types/{vite/dev → server}/assets-store.d.ts +2 -2
- package/dist/types/server/editor-page.d.ts +23 -0
- package/dist/types/server/index.d.ts +11 -0
- package/dist/types/server/node-adapter.d.ts +11 -0
- package/dist/types/{vite/dev → server}/pages-store.d.ts +5 -5
- package/dist/types/{vite → server}/rich-text-codec.d.ts +6 -0
- package/dist/types/server/service.d.ts +53 -0
- package/dist/types/server/site.d.ts +29 -0
- package/dist/types/vite/dev/middleware.d.ts +6 -28
- package/package.json +6 -2
- /package/dist/types/{vite/dev → server}/composed-store.d.ts +0 -0
- /package/dist/types/{vite/dev → server}/data-store.d.ts +0 -0
- /package/dist/types/{vite/dev → server}/fs-utils.d.ts +0 -0
- /package/dist/types/{vite/dev → server}/image-preview.d.ts +0 -0
- /package/dist/types/{vite/dev → server}/page-state.d.ts +0 -0
- /package/dist/types/{vite/dev → server}/query-dev.d.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as renderCrop, c as useDialog, d as _plugin_vue_export_helper_default, i as readImageSize, l as VIcon_default, n as VDialog_default, r as analyzeImageFile, s as dialogKey, t as ImagePickerDialog_default } from "./ImagePickerDialog-DJGhtW3r.js";
|
|
2
2
|
import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, inject, mergeProps, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onErrorCaptured, onMounted, openBlock, provide, reactive, ref, renderList, renderSlot, resolveDynamicComponent, shallowRef, toDisplayString, unref, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
|
|
3
|
-
import { deepEqual, getDefaultValue } from "mechanica-shared";
|
|
3
|
+
import { EDITOR_API_BASE, UPLOADS_PREFIX, deepEqual, getDefaultValue } from "mechanica-shared";
|
|
4
4
|
import { unfoldSchema } from "compact-json-schema";
|
|
5
5
|
import { TextEditor, uid } from "vuewrite";
|
|
6
6
|
import { blocksToMarkdown, markdownToBlocks } from "vuewrite/markdown";
|
|
@@ -540,8 +540,6 @@ var ColorField_default = /* @__PURE__ */ defineComponent({
|
|
|
540
540
|
});
|
|
541
541
|
//#endregion
|
|
542
542
|
//#region src/editor/lib/image-crop.ts
|
|
543
|
-
/** URL prefix uploaded assets are served under (mirrors the dev assets-store). */
|
|
544
|
-
var UPLOADS_PREFIX = "/@mechanica/assets/";
|
|
545
543
|
var positive = (n) => typeof n === "number" && isFinite(n) && n > 0 ? n : void 0;
|
|
546
544
|
/**
|
|
547
545
|
* Resolve a field's `crop` annotation into cropping intent, or `null` when the
|
|
@@ -670,7 +668,7 @@ function derivativeName(src, rect, target) {
|
|
|
670
668
|
/** A readable, filename-safe stem for an asset src (`hero` from `…/hero.png`). */
|
|
671
669
|
function baseName(src) {
|
|
672
670
|
if (!src.startsWith(UPLOADS_PREFIX)) return "image";
|
|
673
|
-
let file = src.slice(
|
|
671
|
+
let file = src.slice(UPLOADS_PREFIX.length);
|
|
674
672
|
try {
|
|
675
673
|
file = decodeURIComponent(file);
|
|
676
674
|
} catch {}
|
|
@@ -1047,6 +1045,275 @@ var ImageField_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__P
|
|
|
1047
1045
|
}
|
|
1048
1046
|
}), [["__scopeId", "data-v-664f68c6"]]);
|
|
1049
1047
|
//#endregion
|
|
1048
|
+
//#region src/editor/lib/save-queue.ts
|
|
1049
|
+
/** Throw from `send` to signal a version conflict (page changed on disk). */
|
|
1050
|
+
var SaveConflictError = class extends Error {
|
|
1051
|
+
constructor(message = "Page changed on disk") {
|
|
1052
|
+
super(message);
|
|
1053
|
+
this.name = "SaveConflictError";
|
|
1054
|
+
}
|
|
1055
|
+
};
|
|
1056
|
+
/**
|
|
1057
|
+
* Debounced, status-tracking save pipeline. Only the newest snapshot is ever
|
|
1058
|
+
* sent; a failure keeps it around (status `error`) until `retry()` or a newer
|
|
1059
|
+
* edit re-triggers the send. No automatic retry loop — the UI surfaces the
|
|
1060
|
+
* failure instead.
|
|
1061
|
+
*/
|
|
1062
|
+
function createSaveQueue(options) {
|
|
1063
|
+
const delay = options.delay ?? 500;
|
|
1064
|
+
const state = reactive({ status: "saved" });
|
|
1065
|
+
let timer = null;
|
|
1066
|
+
let last = null;
|
|
1067
|
+
/** A snapshot exists that the server hasn't confirmed yet. */
|
|
1068
|
+
let unsaved = false;
|
|
1069
|
+
/** The save request currently in flight, if any. */
|
|
1070
|
+
let inflight = null;
|
|
1071
|
+
const cancelTimer = () => {
|
|
1072
|
+
if (timer != null) clearTimeout(timer);
|
|
1073
|
+
timer = null;
|
|
1074
|
+
};
|
|
1075
|
+
function send() {
|
|
1076
|
+
if (inflight) return inflight;
|
|
1077
|
+
if (last == null) return Promise.resolve();
|
|
1078
|
+
cancelTimer();
|
|
1079
|
+
state.status = "saving";
|
|
1080
|
+
const snapshot = last;
|
|
1081
|
+
inflight = options.send(snapshot).then(() => {
|
|
1082
|
+
if (last === snapshot) {
|
|
1083
|
+
unsaved = false;
|
|
1084
|
+
state.status = "saved";
|
|
1085
|
+
} else {
|
|
1086
|
+
state.status = "pending";
|
|
1087
|
+
schedule();
|
|
1088
|
+
}
|
|
1089
|
+
}).catch((error) => {
|
|
1090
|
+
state.status = error instanceof SaveConflictError ? "conflict" : "error";
|
|
1091
|
+
}).finally(() => {
|
|
1092
|
+
inflight = null;
|
|
1093
|
+
});
|
|
1094
|
+
return inflight;
|
|
1095
|
+
}
|
|
1096
|
+
const schedule = () => {
|
|
1097
|
+
cancelTimer();
|
|
1098
|
+
timer = setTimeout(() => void send(), delay);
|
|
1099
|
+
};
|
|
1100
|
+
return {
|
|
1101
|
+
get status() {
|
|
1102
|
+
return state.status;
|
|
1103
|
+
},
|
|
1104
|
+
push(snapshot) {
|
|
1105
|
+
last = snapshot;
|
|
1106
|
+
unsaved = true;
|
|
1107
|
+
if (!inflight) state.status = "pending";
|
|
1108
|
+
schedule();
|
|
1109
|
+
},
|
|
1110
|
+
hasUnsaved: () => unsaved || inflight != null,
|
|
1111
|
+
async flush() {
|
|
1112
|
+
cancelTimer();
|
|
1113
|
+
if (inflight) await inflight;
|
|
1114
|
+
if (unsaved && state.status !== "error" && state.status !== "conflict") await send();
|
|
1115
|
+
return !unsaved;
|
|
1116
|
+
},
|
|
1117
|
+
retry() {
|
|
1118
|
+
if (state.status !== "error" && state.status !== "conflict") return;
|
|
1119
|
+
send();
|
|
1120
|
+
},
|
|
1121
|
+
discard() {
|
|
1122
|
+
cancelTimer();
|
|
1123
|
+
last = null;
|
|
1124
|
+
unsaved = false;
|
|
1125
|
+
state.status = "saved";
|
|
1126
|
+
},
|
|
1127
|
+
flushOnUnload() {
|
|
1128
|
+
if (!unsaved && !inflight) return true;
|
|
1129
|
+
if (state.status === "conflict") return false;
|
|
1130
|
+
if (!options.beacon || last == null) return false;
|
|
1131
|
+
const queued = options.beacon(last);
|
|
1132
|
+
if (queued) {
|
|
1133
|
+
unsaved = false;
|
|
1134
|
+
cancelTimer();
|
|
1135
|
+
state.status = "saved";
|
|
1136
|
+
}
|
|
1137
|
+
return queued;
|
|
1138
|
+
},
|
|
1139
|
+
dispose: cancelTimer
|
|
1140
|
+
};
|
|
1141
|
+
}
|
|
1142
|
+
//#endregion
|
|
1143
|
+
//#region src/editor/lib/backend.ts
|
|
1144
|
+
/** A failed request; `message` is fit for showing to the user. */
|
|
1145
|
+
var BackendError = class extends Error {
|
|
1146
|
+
status;
|
|
1147
|
+
constructor(message, status) {
|
|
1148
|
+
super(message);
|
|
1149
|
+
this.status = status;
|
|
1150
|
+
this.name = "BackendError";
|
|
1151
|
+
}
|
|
1152
|
+
};
|
|
1153
|
+
var errorMessage = (body, field) => typeof body?.error === "object" ? body.error[field] : body?.error;
|
|
1154
|
+
/** Slug shared with the thumbs CLI's `pageSlug`: `/` → `index`, `/docs/api` → `docs-api`. */
|
|
1155
|
+
function pageSlug(path) {
|
|
1156
|
+
const trimmed = path.replace(/^\/+|\/+$/g, "");
|
|
1157
|
+
return trimmed ? trimmed.replace(/\//g, "-") : "index";
|
|
1158
|
+
}
|
|
1159
|
+
var JSON_HEADERS = { "content-type": "application/json" };
|
|
1160
|
+
/** Build a backend over HTTP for a host config (all defaults = the dev server). */
|
|
1161
|
+
function createEditorBackend(config = {}) {
|
|
1162
|
+
const base = (config.base ?? EDITOR_API_BASE).replace(/\/+$/, "");
|
|
1163
|
+
const hostHeaders = config.headers ?? {};
|
|
1164
|
+
const hasHostHeaders = Object.keys(hostHeaders).length > 0;
|
|
1165
|
+
const url = (route, params) => {
|
|
1166
|
+
const query = new URLSearchParams();
|
|
1167
|
+
for (const [key, value] of Object.entries(params ?? {})) if (value != null) query.set(key, value);
|
|
1168
|
+
const search = query.toString();
|
|
1169
|
+
return `${base}${route}${search ? `?${search}` : ""}`;
|
|
1170
|
+
};
|
|
1171
|
+
const request = (target, init) => {
|
|
1172
|
+
if (!hasHostHeaders) return init ? fetch(target, init) : fetch(target);
|
|
1173
|
+
return fetch(target, {
|
|
1174
|
+
...init,
|
|
1175
|
+
headers: {
|
|
1176
|
+
...hostHeaders,
|
|
1177
|
+
...init?.headers
|
|
1178
|
+
}
|
|
1179
|
+
});
|
|
1180
|
+
};
|
|
1181
|
+
const postJson = (target, body) => request(target, {
|
|
1182
|
+
method: "POST",
|
|
1183
|
+
headers: JSON_HEADERS,
|
|
1184
|
+
body: JSON.stringify(body)
|
|
1185
|
+
});
|
|
1186
|
+
const readJson = (response) => response.json().catch(() => null);
|
|
1187
|
+
const writePage = async (target, input) => {
|
|
1188
|
+
const response = await postJson(target, input);
|
|
1189
|
+
const data = await readJson(response);
|
|
1190
|
+
if (!response.ok) return {
|
|
1191
|
+
ok: false,
|
|
1192
|
+
error: errorMessage(data, "path") ?? "Could not save the page"
|
|
1193
|
+
};
|
|
1194
|
+
return {
|
|
1195
|
+
ok: true,
|
|
1196
|
+
path: data?.path
|
|
1197
|
+
};
|
|
1198
|
+
};
|
|
1199
|
+
const saveUrl = (target) => url("/save", {
|
|
1200
|
+
path: target.path,
|
|
1201
|
+
locale: target.locale
|
|
1202
|
+
});
|
|
1203
|
+
const upload = async (body, name, derived) => {
|
|
1204
|
+
const response = await request(url("/upload"), {
|
|
1205
|
+
method: "POST",
|
|
1206
|
+
headers: {
|
|
1207
|
+
"x-file-name": encodeURIComponent(name),
|
|
1208
|
+
...derived ? { "x-derived-asset": "1" } : {}
|
|
1209
|
+
},
|
|
1210
|
+
body
|
|
1211
|
+
});
|
|
1212
|
+
if (!response.ok) throw new BackendError(`Upload failed (${response.status})`, response.status);
|
|
1213
|
+
return await response.json();
|
|
1214
|
+
};
|
|
1215
|
+
const writeComposed = async (target, body, verb) => {
|
|
1216
|
+
const response = await postJson(target, body);
|
|
1217
|
+
if (response.status === 409) throw new SaveConflictError();
|
|
1218
|
+
if (!response.ok) throw new BackendError(errorMessage(await readJson(response), "id") ?? `${verb} failed (${response.status})`, response.status);
|
|
1219
|
+
return { version: (await readJson(response))?.version ?? null };
|
|
1220
|
+
};
|
|
1221
|
+
return {
|
|
1222
|
+
capabilities: {
|
|
1223
|
+
composer: true,
|
|
1224
|
+
...config.capabilities
|
|
1225
|
+
},
|
|
1226
|
+
pages: {
|
|
1227
|
+
list: async () => (await request(url("/pages"))).json(),
|
|
1228
|
+
create: (input) => writePage(url("/pages"), input),
|
|
1229
|
+
update: (path, input) => writePage(url("/pages", { path }), input),
|
|
1230
|
+
duplicate: (path, input) => writePage(url("/pages/duplicate", { path }), input),
|
|
1231
|
+
remove: async (path) => (await request(url("/pages", { path }), { method: "DELETE" })).ok,
|
|
1232
|
+
setDraft: async (path, draft) => (await postJson(url("/pages/draft", { path }), { draft })).ok,
|
|
1233
|
+
createTranslation: async (path, locale) => {
|
|
1234
|
+
const response = await request(url("/pages/translation", {
|
|
1235
|
+
path,
|
|
1236
|
+
locale
|
|
1237
|
+
}), { method: "POST" });
|
|
1238
|
+
if (!response.ok && response.status !== 400) throw new BackendError(`Create failed (${response.status})`, response.status);
|
|
1239
|
+
},
|
|
1240
|
+
state: async (path) => {
|
|
1241
|
+
const response = await request(url("/state", { path }));
|
|
1242
|
+
return response.ok ? await response.json() : null;
|
|
1243
|
+
},
|
|
1244
|
+
save: async (target, body) => {
|
|
1245
|
+
const response = await postJson(saveUrl(target), body);
|
|
1246
|
+
if (response.status === 409) throw new SaveConflictError();
|
|
1247
|
+
if (!response.ok) throw new BackendError(`Save failed (${response.status})`, response.status);
|
|
1248
|
+
return {
|
|
1249
|
+
success: true,
|
|
1250
|
+
version: (await readJson(response))?.version ?? null
|
|
1251
|
+
};
|
|
1252
|
+
},
|
|
1253
|
+
saveOnUnload: (target, body) => {
|
|
1254
|
+
const payload = JSON.stringify(body);
|
|
1255
|
+
if (hasHostHeaders) {
|
|
1256
|
+
request(saveUrl(target), {
|
|
1257
|
+
method: "POST",
|
|
1258
|
+
headers: JSON_HEADERS,
|
|
1259
|
+
body: payload,
|
|
1260
|
+
keepalive: true
|
|
1261
|
+
});
|
|
1262
|
+
return true;
|
|
1263
|
+
}
|
|
1264
|
+
return navigator.sendBeacon(saveUrl(target), new Blob([payload], { type: "application/json" }));
|
|
1265
|
+
}
|
|
1266
|
+
},
|
|
1267
|
+
assets: {
|
|
1268
|
+
upload: async (file) => {
|
|
1269
|
+
const { src, previewSrc, width, height } = await upload(file, file.name, false);
|
|
1270
|
+
return {
|
|
1271
|
+
src,
|
|
1272
|
+
previewSrc,
|
|
1273
|
+
width,
|
|
1274
|
+
height
|
|
1275
|
+
};
|
|
1276
|
+
},
|
|
1277
|
+
uploadDerived: async (blob, name) => ({ src: (await upload(blob, name, true)).src }),
|
|
1278
|
+
images: async () => {
|
|
1279
|
+
const response = await request(url("/images"));
|
|
1280
|
+
return response.ok ? await response.json() : [];
|
|
1281
|
+
}
|
|
1282
|
+
},
|
|
1283
|
+
composed: {
|
|
1284
|
+
get: async (id) => {
|
|
1285
|
+
const response = await request(url("/composed/get", { id }));
|
|
1286
|
+
return response.ok ? await response.json() : null;
|
|
1287
|
+
},
|
|
1288
|
+
create: (def) => writeComposed(url("/composed/create"), def, "Create"),
|
|
1289
|
+
save: (id, def, version) => writeComposed(url("/composed/save", { id }), {
|
|
1290
|
+
def,
|
|
1291
|
+
version
|
|
1292
|
+
}, "Save"),
|
|
1293
|
+
remove: async (id) => {
|
|
1294
|
+
await request(url("/composed/delete", { id }), { method: "POST" });
|
|
1295
|
+
}
|
|
1296
|
+
},
|
|
1297
|
+
urls: {
|
|
1298
|
+
pageThumb: (path) => `${base}/thumbs/${pageSlug(path)}.png`,
|
|
1299
|
+
blockThumb: (blockId) => `${base}/thumbs/blocks/${encodeURIComponent(blockId)}.png`,
|
|
1300
|
+
composer: (blockId) => `${base}/composer/${encodeURIComponent(blockId)}`
|
|
1301
|
+
},
|
|
1302
|
+
onStoreChange(listener) {
|
|
1303
|
+
return () => {};
|
|
1304
|
+
}
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
var current = null;
|
|
1308
|
+
/**
|
|
1309
|
+
* The backend for this page — created on first use from the host's
|
|
1310
|
+
* `window.__MECHANICA_EDITOR__` config (absent → the dev server).
|
|
1311
|
+
*/
|
|
1312
|
+
function editorBackend() {
|
|
1313
|
+
if (!current) current = createEditorBackend(typeof window === "undefined" ? void 0 : window.__MECHANICA_EDITOR__);
|
|
1314
|
+
return current;
|
|
1315
|
+
}
|
|
1316
|
+
//#endregion
|
|
1050
1317
|
//#region src/editor/lib/page-list.ts
|
|
1051
1318
|
var pagesPromise = null;
|
|
1052
1319
|
/**
|
|
@@ -1054,17 +1321,15 @@ var pagesPromise = null;
|
|
|
1054
1321
|
* many link fields share one request. Resolves to `[]` when unavailable.
|
|
1055
1322
|
*/
|
|
1056
1323
|
function fetchPages() {
|
|
1057
|
-
if (!pagesPromise) pagesPromise =
|
|
1324
|
+
if (!pagesPromise) pagesPromise = editorBackend().pages.list().catch(() => []);
|
|
1058
1325
|
return pagesPromise;
|
|
1059
1326
|
}
|
|
1060
1327
|
/**
|
|
1061
|
-
* The
|
|
1062
|
-
* `.mech/thumbs/`).
|
|
1063
|
-
* `/docs/api` → `docs-api`. The file may not exist — callers need a fallback.
|
|
1328
|
+
* The URL of a page's thumbnail (written by `mechanica thumbs` into
|
|
1329
|
+
* `.mech/thumbs/`). The file may not exist — callers need a fallback.
|
|
1064
1330
|
*/
|
|
1065
1331
|
function pageThumbUrl(path) {
|
|
1066
|
-
|
|
1067
|
-
return `/@mechanica/thumbs/${trimmed ? trimmed.replace(/\//g, "-") : "index"}.png`;
|
|
1332
|
+
return editorBackend().urls.pageThumb(path);
|
|
1068
1333
|
}
|
|
1069
1334
|
/**
|
|
1070
1335
|
* Derive a URL path from a page name: a lowercase ASCII slug, prefixed with
|
|
@@ -3217,99 +3482,4 @@ function normalizeTemplate(template) {
|
|
|
3217
3482
|
return [createRootFrame(template.slice())];
|
|
3218
3483
|
}
|
|
3219
3484
|
//#endregion
|
|
3220
|
-
|
|
3221
|
-
/** Throw from `send` to signal a version conflict (page changed on disk). */
|
|
3222
|
-
var SaveConflictError = class extends Error {
|
|
3223
|
-
constructor(message = "Page changed on disk") {
|
|
3224
|
-
super(message);
|
|
3225
|
-
this.name = "SaveConflictError";
|
|
3226
|
-
}
|
|
3227
|
-
};
|
|
3228
|
-
/**
|
|
3229
|
-
* Debounced, status-tracking save pipeline. Only the newest snapshot is ever
|
|
3230
|
-
* sent; a failure keeps it around (status `error`) until `retry()` or a newer
|
|
3231
|
-
* edit re-triggers the send. No automatic retry loop — the UI surfaces the
|
|
3232
|
-
* failure instead.
|
|
3233
|
-
*/
|
|
3234
|
-
function createSaveQueue(options) {
|
|
3235
|
-
const delay = options.delay ?? 500;
|
|
3236
|
-
const state = reactive({ status: "saved" });
|
|
3237
|
-
let timer = null;
|
|
3238
|
-
let last = null;
|
|
3239
|
-
/** A snapshot exists that the server hasn't confirmed yet. */
|
|
3240
|
-
let unsaved = false;
|
|
3241
|
-
/** The save request currently in flight, if any. */
|
|
3242
|
-
let inflight = null;
|
|
3243
|
-
const cancelTimer = () => {
|
|
3244
|
-
if (timer != null) clearTimeout(timer);
|
|
3245
|
-
timer = null;
|
|
3246
|
-
};
|
|
3247
|
-
function send() {
|
|
3248
|
-
if (inflight) return inflight;
|
|
3249
|
-
if (last == null) return Promise.resolve();
|
|
3250
|
-
cancelTimer();
|
|
3251
|
-
state.status = "saving";
|
|
3252
|
-
const snapshot = last;
|
|
3253
|
-
inflight = options.send(snapshot).then(() => {
|
|
3254
|
-
if (last === snapshot) {
|
|
3255
|
-
unsaved = false;
|
|
3256
|
-
state.status = "saved";
|
|
3257
|
-
} else {
|
|
3258
|
-
state.status = "pending";
|
|
3259
|
-
schedule();
|
|
3260
|
-
}
|
|
3261
|
-
}).catch((error) => {
|
|
3262
|
-
state.status = error instanceof SaveConflictError ? "conflict" : "error";
|
|
3263
|
-
}).finally(() => {
|
|
3264
|
-
inflight = null;
|
|
3265
|
-
});
|
|
3266
|
-
return inflight;
|
|
3267
|
-
}
|
|
3268
|
-
const schedule = () => {
|
|
3269
|
-
cancelTimer();
|
|
3270
|
-
timer = setTimeout(() => void send(), delay);
|
|
3271
|
-
};
|
|
3272
|
-
return {
|
|
3273
|
-
get status() {
|
|
3274
|
-
return state.status;
|
|
3275
|
-
},
|
|
3276
|
-
push(snapshot) {
|
|
3277
|
-
last = snapshot;
|
|
3278
|
-
unsaved = true;
|
|
3279
|
-
if (!inflight) state.status = "pending";
|
|
3280
|
-
schedule();
|
|
3281
|
-
},
|
|
3282
|
-
hasUnsaved: () => unsaved || inflight != null,
|
|
3283
|
-
async flush() {
|
|
3284
|
-
cancelTimer();
|
|
3285
|
-
if (inflight) await inflight;
|
|
3286
|
-
if (unsaved && state.status !== "error" && state.status !== "conflict") await send();
|
|
3287
|
-
return !unsaved;
|
|
3288
|
-
},
|
|
3289
|
-
retry() {
|
|
3290
|
-
if (state.status !== "error" && state.status !== "conflict") return;
|
|
3291
|
-
send();
|
|
3292
|
-
},
|
|
3293
|
-
discard() {
|
|
3294
|
-
cancelTimer();
|
|
3295
|
-
last = null;
|
|
3296
|
-
unsaved = false;
|
|
3297
|
-
state.status = "saved";
|
|
3298
|
-
},
|
|
3299
|
-
flushOnUnload() {
|
|
3300
|
-
if (!unsaved && !inflight) return true;
|
|
3301
|
-
if (state.status === "conflict") return false;
|
|
3302
|
-
if (!options.beacon || last == null) return false;
|
|
3303
|
-
const queued = options.beacon(last);
|
|
3304
|
-
if (queued) {
|
|
3305
|
-
unsaved = false;
|
|
3306
|
-
cancelTimer();
|
|
3307
|
-
state.status = "saved";
|
|
3308
|
-
}
|
|
3309
|
-
return queued;
|
|
3310
|
-
},
|
|
3311
|
-
dispose: cancelTimer
|
|
3312
|
-
};
|
|
3313
|
-
}
|
|
3314
|
-
//#endregion
|
|
3315
|
-
export { createContextMenu as A, placeBlock as C, registerBuiltinFieldEditors as D, uid$1 as E, groupPagesByFolder as F, pageThumbUrl as I, pathFromName as L, SmartLinkField_default as M, fetchPages as N, registerRichTextWidgets as O, filterPages as P, VSelect_default as R, moveBlock as S, removeBlock as T, duplicateBlock as _, SchemaForm_default as a, findParentList as b, shortcutChar as c, compareBlocks as d, createContentBlock as f, cloneBlock as g, humanize as h, normalizeTemplate as i, VSegmented_default as j, contextMenuKey as k, blockAvailableForLayout as l, toBlockMeta as m, createSaveQueue as n, SchemaField_default as o, isUnderFolder as p, createRootFrame as r, FieldControl_default as s, SaveConflictError as t, blockAvailableIn as u, ensureSlotList as v, relocateBlock as w, findParentSlot as x, findBlock as y, VPopover_default as z };
|
|
3485
|
+
export { SmartLinkField_default as A, removeBlock as C, contextMenuKey as D, registerRichTextWidgets as E, pathFromName as F, editorBackend as I, createSaveQueue as L, filterPages as M, groupPagesByFolder as N, createContextMenu as O, pageThumbUrl as P, VSelect_default as R, relocateBlock as S, registerBuiltinFieldEditors as T, findBlock as _, FieldControl_default as a, moveBlock as b, blockAvailableIn as c, isUnderFolder as d, toBlockMeta as f, ensureSlotList as g, duplicateBlock as h, SchemaField_default as i, fetchPages as j, VSegmented_default as k, compareBlocks as l, cloneBlock as m, normalizeTemplate as n, shortcutChar as o, humanize as p, SchemaForm_default as r, blockAvailableForLayout as s, createRootFrame as t, createContentBlock as u, findParentList as v, uid$1 as w, placeBlock as x, findParentSlot as y, VPopover_default as z };
|