superdoc 2.13.0-next.2 → 2.13.0-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/public/collaboration-worker.cjs +9 -0
- package/dist/public/collaboration-worker.es.js +8 -0
- package/dist/style.css +25 -25
- package/dist/style.layered.css +25 -25
- package/dist/superdoc/src/core/collaboration/resolve-v2-collaboration-target.d.ts +7 -3
- package/dist/superdoc/src/core/types/index.d.ts +26 -11
- package/dist/superdoc/src/public/collaboration-worker.d.cts +18 -0
- package/dist/superdoc/src/public/collaboration-worker.d.ts +48 -0
- package/dist/superdoc.cjs +62 -6
- package/dist/superdoc.es.js +62 -6
- package/dist-cdn/style.layered.css +1 -1
- package/dist-cdn/superdoc.min.css +1 -1
- package/dist-cdn/superdoc.min.js +18 -18
- package/package.json +13 -2
package/dist/superdoc.cjs
CHANGED
|
@@ -316,7 +316,7 @@ var shuffleArray = (array) => {
|
|
|
316
316
|
var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
|
|
317
317
|
function getSuperdocVersion() {
|
|
318
318
|
try {
|
|
319
|
-
return "2.13.0-next.
|
|
319
|
+
return "2.13.0-next.3";
|
|
320
320
|
} catch {
|
|
321
321
|
return "unknown";
|
|
322
322
|
}
|
|
@@ -20579,7 +20579,7 @@ function resolveWebsocketFamily(family, candidate) {
|
|
|
20579
20579
|
message: `SuperDoc v2 collaboration requires a valid ws:// or wss:// URL for the "${family}" provider (received: ${redactCollaborationUrl(rawUrl)}).`
|
|
20580
20580
|
};
|
|
20581
20581
|
const params = normalizeParams(candidate.params);
|
|
20582
|
-
const token = family === "hocuspocus" ? normalizeNonEmptyString(candidate.token) : null;
|
|
20582
|
+
const token = family === "hocuspocus" && typeof candidate.token === "function" ? candidate.token : family === "hocuspocus" ? normalizeNonEmptyString(candidate.token) : null;
|
|
20583
20583
|
const roomMode = normalizeRoomMode(candidate.roomMode);
|
|
20584
20584
|
if (!roomMode) return invalidRoomMode();
|
|
20585
20585
|
return {
|
|
@@ -20594,6 +20594,43 @@ function resolveWebsocketFamily(family, candidate) {
|
|
|
20594
20594
|
}
|
|
20595
20595
|
};
|
|
20596
20596
|
}
|
|
20597
|
+
function resolveProviderExtension(candidate) {
|
|
20598
|
+
const adapterId = normalizeNonEmptyString(candidate.adapterId);
|
|
20599
|
+
if (!adapterId) return {
|
|
20600
|
+
ok: false,
|
|
20601
|
+
reason: "invalid-adapter-id",
|
|
20602
|
+
message: "SuperDoc v2 provider extensions require a non-empty v2Collaboration.adapterId."
|
|
20603
|
+
};
|
|
20604
|
+
const documentId = normalizeNonEmptyString(candidate.documentId);
|
|
20605
|
+
if (!documentId) return {
|
|
20606
|
+
ok: false,
|
|
20607
|
+
reason: "invalid-document-id",
|
|
20608
|
+
message: "SuperDoc v2 provider extensions require a non-empty v2Collaboration.documentId."
|
|
20609
|
+
};
|
|
20610
|
+
const roomMode = normalizeRoomMode(candidate.roomMode);
|
|
20611
|
+
if (!roomMode) return invalidRoomMode();
|
|
20612
|
+
if (Object.prototype.hasOwnProperty.call(candidate, "providerOptions")) try {
|
|
20613
|
+
structuredClone(candidate.providerOptions);
|
|
20614
|
+
} catch {
|
|
20615
|
+
return {
|
|
20616
|
+
ok: false,
|
|
20617
|
+
reason: "invalid-provider-options",
|
|
20618
|
+
message: "SuperDoc v2 provider extension options must be structured-clone-safe."
|
|
20619
|
+
};
|
|
20620
|
+
}
|
|
20621
|
+
const token = typeof candidate.token === "function" ? candidate.token : normalizeNonEmptyString(candidate.token);
|
|
20622
|
+
return {
|
|
20623
|
+
ok: true,
|
|
20624
|
+
target: {
|
|
20625
|
+
providerFamily: "extension",
|
|
20626
|
+
adapterId,
|
|
20627
|
+
documentId,
|
|
20628
|
+
roomMode,
|
|
20629
|
+
...Object.prototype.hasOwnProperty.call(candidate, "providerOptions") ? { providerOptions: candidate.providerOptions } : {},
|
|
20630
|
+
...token ? { token } : {}
|
|
20631
|
+
}
|
|
20632
|
+
};
|
|
20633
|
+
}
|
|
20597
20634
|
/** Resolve the Liveblocks family (exactly one of publicApiKey / authEndpoint). */
|
|
20598
20635
|
function resolveLiveblocksFamily(candidate, authEndpointBaseUrl) {
|
|
20599
20636
|
const documentId = normalizeNonEmptyString(candidate.documentId ?? candidate.roomId);
|
|
@@ -20690,10 +20727,11 @@ function resolveV2CollaborationTarget(input) {
|
|
|
20690
20727
|
if (providerType === null || providerType === "y-websocket") return resolveWebsocketFamily("y-websocket", candidate);
|
|
20691
20728
|
if (providerType === "hocuspocus") return resolveWebsocketFamily("hocuspocus", candidate);
|
|
20692
20729
|
if (providerType === "liveblocks") return resolveLiveblocksFamily(candidate, authEndpointBaseUrl);
|
|
20730
|
+
if (providerType === "extension") return resolveProviderExtension(candidate);
|
|
20693
20731
|
return {
|
|
20694
20732
|
ok: false,
|
|
20695
20733
|
reason: "unsupported-provider-family",
|
|
20696
|
-
message: `SuperDoc v2 collaboration does not support the "${providerType}" provider family. Supported families are y-websocket, hocuspocus, and
|
|
20734
|
+
message: `SuperDoc v2 collaboration does not support the "${providerType}" provider family. Supported families are y-websocket, hocuspocus, liveblocks, and extension.`
|
|
20697
20735
|
};
|
|
20698
20736
|
}
|
|
20699
20737
|
//#endregion
|
|
@@ -21888,6 +21926,10 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
|
|
|
21888
21926
|
const clearV2RuntimeRegistration = (documentId) => {
|
|
21889
21927
|
clearV2CommandShortcutBinding(documentId);
|
|
21890
21928
|
clearV2SessionShortcutBinding(documentId);
|
|
21929
|
+
const document = getDocument(documentId);
|
|
21930
|
+
const provider = document?.provider ?? null;
|
|
21931
|
+
if (provider && proxy.$superdoc.provider === provider) proxy.$superdoc.provider = void 0;
|
|
21932
|
+
if (document && provider?.sendStateless) document.provider = null;
|
|
21891
21933
|
const entry = v2Runtimes.get(documentId);
|
|
21892
21934
|
if (!entry) return;
|
|
21893
21935
|
proxy.$superdoc.unregisterEditorRuntime(entry.runtimeId);
|
|
@@ -22076,7 +22118,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
|
|
|
22076
22118
|
clearV2EditorFailure(payload.documentId ?? null);
|
|
22077
22119
|
clearV2AuthorRequired(payload.documentId ?? null);
|
|
22078
22120
|
clearV2EditRejected(payload.documentId ?? null);
|
|
22079
|
-
const { host, mount, documentId, capabilities, editCommands, bindEditShortcuts, bindSessionShortcuts, commentsAdapter, trackedChangesAdapter, contextMenu, documentApi, documentMutationReadiness, documentApiUnavailableReason, pageMetrics, pageLayout, pageFurniture, presence, lock, fonts, replaceFile, upgradeToCollaboration, documentOpenToken } = payload;
|
|
22121
|
+
const { host, mount, documentId, capabilities, editCommands, bindEditShortcuts, bindSessionShortcuts, commentsAdapter, trackedChangesAdapter, contextMenu, documentApi, documentMutationReadiness, documentApiUnavailableReason, pageMetrics, pageLayout, pageFurniture, presence, lock, collaborationProvider, fonts, replaceFile, upgradeToCollaboration, documentOpenToken } = payload;
|
|
22080
22122
|
documentOpenTelemetry?.trackDocumentOpen(documentOpenToken ?? null, documentId ?? null);
|
|
22081
22123
|
const saveV2Bytes = async (saveOptions = {}) => {
|
|
22082
22124
|
if (!host || typeof host.save !== "function") throw new Error("v2-editor: save unavailable");
|
|
@@ -22351,6 +22393,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
|
|
|
22351
22393
|
pageFurniture: pageFurniture ?? null,
|
|
22352
22394
|
presence: presence ?? null,
|
|
22353
22395
|
lock: lock ?? null,
|
|
22396
|
+
provider: collaborationProvider ?? null,
|
|
22354
22397
|
reviewWindow: {
|
|
22355
22398
|
getDiagnostics: () => v2ReviewWindowController.getDiagnostics(),
|
|
22356
22399
|
getSnapshot: () => v2ReviewWindowController.getSnapshot?.() ?? null,
|
|
@@ -22385,6 +22428,11 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
|
|
|
22385
22428
|
proxy.$superdoc.setActiveEditor(facade);
|
|
22386
22429
|
syncV2EditRejectedActiveDocument();
|
|
22387
22430
|
}
|
|
22431
|
+
if (collaborationProvider) {
|
|
22432
|
+
const provider = (0, vue.markRaw)(collaborationProvider);
|
|
22433
|
+
proxy.$superdoc.provider = provider;
|
|
22434
|
+
if (doc) doc.provider = provider;
|
|
22435
|
+
}
|
|
22388
22436
|
proxy.$superdoc.broadcastEditorCreate(facade);
|
|
22389
22437
|
installV2CommandShortcutBinding({
|
|
22390
22438
|
documentId,
|
|
@@ -24160,7 +24208,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
|
|
|
24160
24208
|
], 38);
|
|
24161
24209
|
};
|
|
24162
24210
|
}
|
|
24163
|
-
}, [["__scopeId", "data-v-
|
|
24211
|
+
}, [["__scopeId", "data-v-f0b56abb"]]);
|
|
24164
24212
|
//#endregion
|
|
24165
24213
|
//#region src/core/create-app.js
|
|
24166
24214
|
var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
|
|
@@ -45356,7 +45404,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
|
|
|
45356
45404
|
this.config.colors = shuffleArray(this.config.colors);
|
|
45357
45405
|
this.userColorMap = /* @__PURE__ */ new Map();
|
|
45358
45406
|
this.colorIndex = 0;
|
|
45359
|
-
this.version = "2.13.0-next.
|
|
45407
|
+
this.version = "2.13.0-next.3";
|
|
45360
45408
|
this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
|
|
45361
45409
|
this.superdocId = config.superdocId || require_uuid.v4();
|
|
45362
45410
|
this.colors = this.config.colors ?? [];
|
|
@@ -46010,6 +46058,14 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
|
|
|
46010
46058
|
storeDoc.v2Collaboration = value;
|
|
46011
46059
|
}
|
|
46012
46060
|
#toV2CollaborationConfig(target) {
|
|
46061
|
+
if (target.providerFamily === "extension") return {
|
|
46062
|
+
providerType: "extension",
|
|
46063
|
+
adapterId: target.adapterId,
|
|
46064
|
+
documentId: target.documentId,
|
|
46065
|
+
roomMode: target.roomMode,
|
|
46066
|
+
...target.providerOptions !== void 0 ? { providerOptions: target.providerOptions } : {},
|
|
46067
|
+
...target.token ? { token: target.token } : {}
|
|
46068
|
+
};
|
|
46013
46069
|
if (target.providerFamily === "liveblocks") return {
|
|
46014
46070
|
providerType: "liveblocks",
|
|
46015
46071
|
documentId: target.documentId,
|
package/dist/superdoc.es.js
CHANGED
|
@@ -315,7 +315,7 @@ var shuffleArray = (array) => {
|
|
|
315
315
|
var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
|
|
316
316
|
function getSuperdocVersion() {
|
|
317
317
|
try {
|
|
318
|
-
return "2.13.0-next.
|
|
318
|
+
return "2.13.0-next.3";
|
|
319
319
|
} catch {
|
|
320
320
|
return "unknown";
|
|
321
321
|
}
|
|
@@ -20547,7 +20547,7 @@ function resolveWebsocketFamily(family, candidate) {
|
|
|
20547
20547
|
message: `SuperDoc v2 collaboration requires a valid ws:// or wss:// URL for the "${family}" provider (received: ${redactCollaborationUrl(rawUrl)}).`
|
|
20548
20548
|
};
|
|
20549
20549
|
const params = normalizeParams(candidate.params);
|
|
20550
|
-
const token = family === "hocuspocus" ? normalizeNonEmptyString(candidate.token) : null;
|
|
20550
|
+
const token = family === "hocuspocus" && typeof candidate.token === "function" ? candidate.token : family === "hocuspocus" ? normalizeNonEmptyString(candidate.token) : null;
|
|
20551
20551
|
const roomMode = normalizeRoomMode(candidate.roomMode);
|
|
20552
20552
|
if (!roomMode) return invalidRoomMode();
|
|
20553
20553
|
return {
|
|
@@ -20562,6 +20562,43 @@ function resolveWebsocketFamily(family, candidate) {
|
|
|
20562
20562
|
}
|
|
20563
20563
|
};
|
|
20564
20564
|
}
|
|
20565
|
+
function resolveProviderExtension(candidate) {
|
|
20566
|
+
const adapterId = normalizeNonEmptyString(candidate.adapterId);
|
|
20567
|
+
if (!adapterId) return {
|
|
20568
|
+
ok: false,
|
|
20569
|
+
reason: "invalid-adapter-id",
|
|
20570
|
+
message: "SuperDoc v2 provider extensions require a non-empty v2Collaboration.adapterId."
|
|
20571
|
+
};
|
|
20572
|
+
const documentId = normalizeNonEmptyString(candidate.documentId);
|
|
20573
|
+
if (!documentId) return {
|
|
20574
|
+
ok: false,
|
|
20575
|
+
reason: "invalid-document-id",
|
|
20576
|
+
message: "SuperDoc v2 provider extensions require a non-empty v2Collaboration.documentId."
|
|
20577
|
+
};
|
|
20578
|
+
const roomMode = normalizeRoomMode(candidate.roomMode);
|
|
20579
|
+
if (!roomMode) return invalidRoomMode();
|
|
20580
|
+
if (Object.prototype.hasOwnProperty.call(candidate, "providerOptions")) try {
|
|
20581
|
+
structuredClone(candidate.providerOptions);
|
|
20582
|
+
} catch {
|
|
20583
|
+
return {
|
|
20584
|
+
ok: false,
|
|
20585
|
+
reason: "invalid-provider-options",
|
|
20586
|
+
message: "SuperDoc v2 provider extension options must be structured-clone-safe."
|
|
20587
|
+
};
|
|
20588
|
+
}
|
|
20589
|
+
const token = typeof candidate.token === "function" ? candidate.token : normalizeNonEmptyString(candidate.token);
|
|
20590
|
+
return {
|
|
20591
|
+
ok: true,
|
|
20592
|
+
target: {
|
|
20593
|
+
providerFamily: "extension",
|
|
20594
|
+
adapterId,
|
|
20595
|
+
documentId,
|
|
20596
|
+
roomMode,
|
|
20597
|
+
...Object.prototype.hasOwnProperty.call(candidate, "providerOptions") ? { providerOptions: candidate.providerOptions } : {},
|
|
20598
|
+
...token ? { token } : {}
|
|
20599
|
+
}
|
|
20600
|
+
};
|
|
20601
|
+
}
|
|
20565
20602
|
/** Resolve the Liveblocks family (exactly one of publicApiKey / authEndpoint). */
|
|
20566
20603
|
function resolveLiveblocksFamily(candidate, authEndpointBaseUrl) {
|
|
20567
20604
|
const documentId = normalizeNonEmptyString(candidate.documentId ?? candidate.roomId);
|
|
@@ -20658,10 +20695,11 @@ function resolveV2CollaborationTarget(input) {
|
|
|
20658
20695
|
if (providerType === null || providerType === "y-websocket") return resolveWebsocketFamily("y-websocket", candidate);
|
|
20659
20696
|
if (providerType === "hocuspocus") return resolveWebsocketFamily("hocuspocus", candidate);
|
|
20660
20697
|
if (providerType === "liveblocks") return resolveLiveblocksFamily(candidate, authEndpointBaseUrl);
|
|
20698
|
+
if (providerType === "extension") return resolveProviderExtension(candidate);
|
|
20661
20699
|
return {
|
|
20662
20700
|
ok: false,
|
|
20663
20701
|
reason: "unsupported-provider-family",
|
|
20664
|
-
message: `SuperDoc v2 collaboration does not support the "${providerType}" provider family. Supported families are y-websocket, hocuspocus, and
|
|
20702
|
+
message: `SuperDoc v2 collaboration does not support the "${providerType}" provider family. Supported families are y-websocket, hocuspocus, liveblocks, and extension.`
|
|
20665
20703
|
};
|
|
20666
20704
|
}
|
|
20667
20705
|
//#endregion
|
|
@@ -21848,6 +21886,10 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
21848
21886
|
const clearV2RuntimeRegistration = (documentId) => {
|
|
21849
21887
|
clearV2CommandShortcutBinding(documentId);
|
|
21850
21888
|
clearV2SessionShortcutBinding(documentId);
|
|
21889
|
+
const document = getDocument(documentId);
|
|
21890
|
+
const provider = document?.provider ?? null;
|
|
21891
|
+
if (provider && proxy.$superdoc.provider === provider) proxy.$superdoc.provider = void 0;
|
|
21892
|
+
if (document && provider?.sendStateless) document.provider = null;
|
|
21851
21893
|
const entry = v2Runtimes.get(documentId);
|
|
21852
21894
|
if (!entry) return;
|
|
21853
21895
|
proxy.$superdoc.unregisterEditorRuntime(entry.runtimeId);
|
|
@@ -22036,7 +22078,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
22036
22078
|
clearV2EditorFailure(payload.documentId ?? null);
|
|
22037
22079
|
clearV2AuthorRequired(payload.documentId ?? null);
|
|
22038
22080
|
clearV2EditRejected(payload.documentId ?? null);
|
|
22039
|
-
const { host, mount, documentId, capabilities, editCommands, bindEditShortcuts, bindSessionShortcuts, commentsAdapter, trackedChangesAdapter, contextMenu, documentApi, documentMutationReadiness, documentApiUnavailableReason, pageMetrics, pageLayout, pageFurniture, presence, lock, fonts, replaceFile, upgradeToCollaboration, documentOpenToken } = payload;
|
|
22081
|
+
const { host, mount, documentId, capabilities, editCommands, bindEditShortcuts, bindSessionShortcuts, commentsAdapter, trackedChangesAdapter, contextMenu, documentApi, documentMutationReadiness, documentApiUnavailableReason, pageMetrics, pageLayout, pageFurniture, presence, lock, collaborationProvider, fonts, replaceFile, upgradeToCollaboration, documentOpenToken } = payload;
|
|
22040
22082
|
documentOpenTelemetry?.trackDocumentOpen(documentOpenToken ?? null, documentId ?? null);
|
|
22041
22083
|
const saveV2Bytes = async (saveOptions = {}) => {
|
|
22042
22084
|
if (!host || typeof host.save !== "function") throw new Error("v2-editor: save unavailable");
|
|
@@ -22311,6 +22353,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
22311
22353
|
pageFurniture: pageFurniture ?? null,
|
|
22312
22354
|
presence: presence ?? null,
|
|
22313
22355
|
lock: lock ?? null,
|
|
22356
|
+
provider: collaborationProvider ?? null,
|
|
22314
22357
|
reviewWindow: {
|
|
22315
22358
|
getDiagnostics: () => v2ReviewWindowController.getDiagnostics(),
|
|
22316
22359
|
getSnapshot: () => v2ReviewWindowController.getSnapshot?.() ?? null,
|
|
@@ -22345,6 +22388,11 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
22345
22388
|
proxy.$superdoc.setActiveEditor(facade);
|
|
22346
22389
|
syncV2EditRejectedActiveDocument();
|
|
22347
22390
|
}
|
|
22391
|
+
if (collaborationProvider) {
|
|
22392
|
+
const provider = markRaw(collaborationProvider);
|
|
22393
|
+
proxy.$superdoc.provider = provider;
|
|
22394
|
+
if (doc) doc.provider = provider;
|
|
22395
|
+
}
|
|
22348
22396
|
proxy.$superdoc.broadcastEditorCreate(facade);
|
|
22349
22397
|
installV2CommandShortcutBinding({
|
|
22350
22398
|
documentId,
|
|
@@ -24120,7 +24168,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
24120
24168
|
], 38);
|
|
24121
24169
|
};
|
|
24122
24170
|
}
|
|
24123
|
-
}, [["__scopeId", "data-v-
|
|
24171
|
+
}, [["__scopeId", "data-v-f0b56abb"]]);
|
|
24124
24172
|
//#endregion
|
|
24125
24173
|
//#region src/core/create-app.js
|
|
24126
24174
|
var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
|
|
@@ -45287,7 +45335,7 @@ var SuperDoc = class extends import_eventemitter3.default {
|
|
|
45287
45335
|
this.config.colors = shuffleArray(this.config.colors);
|
|
45288
45336
|
this.userColorMap = /* @__PURE__ */ new Map();
|
|
45289
45337
|
this.colorIndex = 0;
|
|
45290
|
-
this.version = "2.13.0-next.
|
|
45338
|
+
this.version = "2.13.0-next.3";
|
|
45291
45339
|
this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
|
|
45292
45340
|
this.superdocId = config.superdocId || v4();
|
|
45293
45341
|
this.colors = this.config.colors ?? [];
|
|
@@ -45941,6 +45989,14 @@ var SuperDoc = class extends import_eventemitter3.default {
|
|
|
45941
45989
|
storeDoc.v2Collaboration = value;
|
|
45942
45990
|
}
|
|
45943
45991
|
#toV2CollaborationConfig(target) {
|
|
45992
|
+
if (target.providerFamily === "extension") return {
|
|
45993
|
+
providerType: "extension",
|
|
45994
|
+
adapterId: target.adapterId,
|
|
45995
|
+
documentId: target.documentId,
|
|
45996
|
+
roomMode: target.roomMode,
|
|
45997
|
+
...target.providerOptions !== void 0 ? { providerOptions: target.providerOptions } : {},
|
|
45998
|
+
...target.token ? { token: target.token } : {}
|
|
45999
|
+
};
|
|
45944
46000
|
if (target.providerFamily === "liveblocks") return {
|
|
45945
46001
|
providerType: "liveblocks",
|
|
45946
46002
|
documentId: target.documentId,
|