remote-components 0.0.33 → 0.0.34
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/{component-loader-28ad0083.d.ts → component-loader-8951c052.d.ts} +6 -4
- package/dist/html/host.cjs +227 -13
- package/dist/html/host.cjs.map +1 -1
- package/dist/html/host.js +227 -13
- package/dist/html/host.js.map +1 -1
- package/dist/html/remote.cjs +198 -0
- package/dist/html/remote.cjs.map +1 -0
- package/dist/html/remote.d.ts +2 -0
- package/dist/html/remote.js +197 -0
- package/dist/html/remote.js.map +1 -0
- package/dist/internal/next/host/app-router-client.cjs +56 -4
- package/dist/internal/next/host/app-router-client.cjs.map +1 -1
- package/dist/internal/next/host/app-router-client.d.ts +3 -3
- package/dist/internal/next/host/app-router-client.js +58 -5
- package/dist/internal/next/host/app-router-client.js.map +1 -1
- package/dist/internal/shared/client/remote-component.cjs +99 -0
- package/dist/internal/shared/client/remote-component.cjs.map +1 -1
- package/dist/internal/shared/client/remote-component.d.ts +11 -4
- package/dist/internal/shared/client/remote-component.js +97 -0
- package/dist/internal/shared/client/remote-component.js.map +1 -1
- package/dist/internal/shared/error.cjs.map +1 -1
- package/dist/internal/shared/error.d.ts +1 -1
- package/dist/internal/shared/error.js.map +1 -1
- package/dist/internal/shared/ssr/dom-flight.cjs +17 -5
- package/dist/internal/shared/ssr/dom-flight.cjs.map +1 -1
- package/dist/internal/shared/ssr/dom-flight.d.ts +1 -1
- package/dist/internal/shared/ssr/dom-flight.js +17 -5
- package/dist/internal/shared/ssr/dom-flight.js.map +1 -1
- package/dist/internal/shared/ssr/fetch-remote-component.cjs +7 -3
- package/dist/internal/shared/ssr/fetch-remote-component.cjs.map +1 -1
- package/dist/internal/shared/ssr/fetch-remote-component.d.ts +2 -1
- package/dist/internal/shared/ssr/fetch-remote-component.js +7 -3
- package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
- package/dist/next/host/app-router-server.cjs +1 -0
- package/dist/next/host/app-router-server.cjs.map +1 -1
- package/dist/next/host/app-router-server.js +1 -0
- package/dist/next/host/app-router-server.js.map +1 -1
- package/dist/next/host/client/index.cjs +292 -103
- package/dist/next/host/client/index.cjs.map +1 -1
- package/dist/next/host/client/index.d.ts +1 -1
- package/dist/next/host/client/index.js +289 -102
- package/dist/next/host/client/index.js.map +1 -1
- package/dist/react/index.cjs +197 -103
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +196 -102
- package/dist/react/index.js.map +1 -1
- package/dist/{types-7c207455.d.ts → types-4e7dea94.d.ts} +2 -1
- package/dist/{types-e4a3fa37.d.ts → types-cbf6c34f.d.ts} +2 -2
- package/package.json +8 -1
package/dist/html/host.js
CHANGED
|
@@ -715,6 +715,106 @@ var init_webpack_adapter = __esm({
|
|
|
715
715
|
}
|
|
716
716
|
});
|
|
717
717
|
|
|
718
|
+
// src/shared/client/static-loader.ts
|
|
719
|
+
async function loadStaticRemoteComponent(scripts, url) {
|
|
720
|
+
const self = globalThis;
|
|
721
|
+
if (self.__remote_script_entrypoint_mount__?.[url.href]) {
|
|
722
|
+
self.__remote_script_entrypoint_mount__[url.href] = /* @__PURE__ */ new Set();
|
|
723
|
+
}
|
|
724
|
+
if (self.__remote_script_entrypoint_unmount__?.[url.href]) {
|
|
725
|
+
self.__remote_script_entrypoint_unmount__[url.href] = /* @__PURE__ */ new Set();
|
|
726
|
+
}
|
|
727
|
+
const mountUnmountSets = await Promise.all(
|
|
728
|
+
scripts.map(async (script) => {
|
|
729
|
+
try {
|
|
730
|
+
let src = typeof script.getAttribute === "function" ? script.getAttribute("src") ?? script.src : script.src;
|
|
731
|
+
if (!src && script.textContent) {
|
|
732
|
+
const blob = new Blob(
|
|
733
|
+
[
|
|
734
|
+
script.textContent.replace(
|
|
735
|
+
/import\.meta\.url/g,
|
|
736
|
+
JSON.stringify(url)
|
|
737
|
+
)
|
|
738
|
+
],
|
|
739
|
+
{
|
|
740
|
+
type: "text/javascript"
|
|
741
|
+
}
|
|
742
|
+
);
|
|
743
|
+
src = URL.createObjectURL(blob);
|
|
744
|
+
}
|
|
745
|
+
const mod = await import(
|
|
746
|
+
/* @vite-ignore */
|
|
747
|
+
/* webpackIgnore: true */
|
|
748
|
+
new URL(src, url).href
|
|
749
|
+
);
|
|
750
|
+
if (src.startsWith("blob:")) {
|
|
751
|
+
URL.revokeObjectURL(src);
|
|
752
|
+
}
|
|
753
|
+
if (typeof mod.mount === "function" || typeof mod.default?.mount === "function") {
|
|
754
|
+
if (!self.__remote_script_entrypoint_mount__) {
|
|
755
|
+
self.__remote_script_entrypoint_mount__ = {};
|
|
756
|
+
}
|
|
757
|
+
if (!self.__remote_script_entrypoint_mount__[url.href]) {
|
|
758
|
+
self.__remote_script_entrypoint_mount__[url.href] = /* @__PURE__ */ new Set();
|
|
759
|
+
}
|
|
760
|
+
self.__remote_script_entrypoint_mount__[url.href]?.add(
|
|
761
|
+
mod.mount || mod.default?.mount || (() => {
|
|
762
|
+
})
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
if (typeof mod.unmount === "function" || typeof mod.default?.unmount === "function") {
|
|
766
|
+
if (!self.__remote_script_entrypoint_unmount__) {
|
|
767
|
+
self.__remote_script_entrypoint_unmount__ = {};
|
|
768
|
+
}
|
|
769
|
+
if (!self.__remote_script_entrypoint_unmount__[url.href]) {
|
|
770
|
+
self.__remote_script_entrypoint_unmount__[url.href] = /* @__PURE__ */ new Set();
|
|
771
|
+
}
|
|
772
|
+
self.__remote_script_entrypoint_unmount__[url.href]?.add(
|
|
773
|
+
mod.unmount || mod.default?.unmount || (() => {
|
|
774
|
+
})
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
return {
|
|
778
|
+
mount: mod.mount || mod.default?.mount,
|
|
779
|
+
unmount: mod.unmount || mod.default?.unmount
|
|
780
|
+
};
|
|
781
|
+
} catch (e) {
|
|
782
|
+
console.error(
|
|
783
|
+
new RemoteComponentsError(
|
|
784
|
+
`Error loading remote component script from "${script.src || url.href}".`,
|
|
785
|
+
{ cause: e }
|
|
786
|
+
)
|
|
787
|
+
);
|
|
788
|
+
return {
|
|
789
|
+
mount: void 0,
|
|
790
|
+
unmount: void 0
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
})
|
|
794
|
+
);
|
|
795
|
+
return mountUnmountSets.reduce(
|
|
796
|
+
(acc, { mount, unmount }) => {
|
|
797
|
+
if (typeof mount === "function") {
|
|
798
|
+
acc.mount.add(mount);
|
|
799
|
+
}
|
|
800
|
+
if (typeof unmount === "function") {
|
|
801
|
+
acc.unmount.add(unmount);
|
|
802
|
+
}
|
|
803
|
+
return acc;
|
|
804
|
+
},
|
|
805
|
+
{
|
|
806
|
+
mount: /* @__PURE__ */ new Set(),
|
|
807
|
+
unmount: /* @__PURE__ */ new Set()
|
|
808
|
+
}
|
|
809
|
+
);
|
|
810
|
+
}
|
|
811
|
+
var init_static_loader = __esm({
|
|
812
|
+
"src/shared/client/static-loader.ts"() {
|
|
813
|
+
"use strict";
|
|
814
|
+
init_error();
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
|
|
718
818
|
// src/shared/client/polyfill.tsx
|
|
719
819
|
import { jsx } from "react/jsx-runtime";
|
|
720
820
|
function applyBundleUrlToSrc(bundle, src) {
|
|
@@ -1085,6 +1185,31 @@ var init_turbopack = __esm({
|
|
|
1085
1185
|
}
|
|
1086
1186
|
});
|
|
1087
1187
|
|
|
1188
|
+
// src/html/host/runtime/script.ts
|
|
1189
|
+
var script_exports = {};
|
|
1190
|
+
__export(script_exports, {
|
|
1191
|
+
scriptRuntime: () => scriptRuntime
|
|
1192
|
+
});
|
|
1193
|
+
function scriptRuntime() {
|
|
1194
|
+
const self = globalThis;
|
|
1195
|
+
return {
|
|
1196
|
+
self,
|
|
1197
|
+
createFromReadableStream: () => Promise.resolve(null),
|
|
1198
|
+
applySharedModules: () => Promise.resolve(),
|
|
1199
|
+
nextClientPagesLoader: () => ({
|
|
1200
|
+
Component: null,
|
|
1201
|
+
App: null
|
|
1202
|
+
}),
|
|
1203
|
+
preloadScripts: loadStaticRemoteComponent
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
var init_script = __esm({
|
|
1207
|
+
"src/html/host/runtime/script.ts"() {
|
|
1208
|
+
"use strict";
|
|
1209
|
+
init_static_loader();
|
|
1210
|
+
}
|
|
1211
|
+
});
|
|
1212
|
+
|
|
1088
1213
|
// src/html/host/index.tsx
|
|
1089
1214
|
import { startTransition, useLayoutEffect } from "react";
|
|
1090
1215
|
import { hydrateRoot } from "react-dom/client";
|
|
@@ -1170,6 +1295,7 @@ function createRSCStream(rscName, data) {
|
|
|
1170
1295
|
}
|
|
1171
1296
|
|
|
1172
1297
|
// src/shared/client/remote-component.ts
|
|
1298
|
+
init_static_loader();
|
|
1173
1299
|
init_webpack_adapter();
|
|
1174
1300
|
init_const();
|
|
1175
1301
|
init_error();
|
|
@@ -1269,9 +1395,12 @@ async function getRuntime(type, url, bundle, shared, remoteShared) {
|
|
|
1269
1395
|
} else if (type === "turbopack") {
|
|
1270
1396
|
const { turbopackRuntime: turbopackRuntime2 } = await Promise.resolve().then(() => (init_turbopack(), turbopack_exports));
|
|
1271
1397
|
return turbopackRuntime2(url, bundle, shared, remoteShared);
|
|
1398
|
+
} else if (type === "script") {
|
|
1399
|
+
const { scriptRuntime: scriptRuntime2 } = await Promise.resolve().then(() => (init_script(), script_exports));
|
|
1400
|
+
return scriptRuntime2();
|
|
1272
1401
|
}
|
|
1273
1402
|
throw new RemoteComponentsError(
|
|
1274
|
-
`Remote Components runtime "${type}" is not supported. Supported runtimes are "webpack" and "
|
|
1403
|
+
`Remote Components runtime "${type}" is not supported. Supported runtimes are "webpack", "turbopack", and "script".`
|
|
1275
1404
|
);
|
|
1276
1405
|
}
|
|
1277
1406
|
|
|
@@ -1284,6 +1413,7 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1284
1413
|
this.__next = null;
|
|
1285
1414
|
this.fouc = null;
|
|
1286
1415
|
this.isLoading = false;
|
|
1416
|
+
this.prevIsRemoteComponent = false;
|
|
1287
1417
|
this.root = null;
|
|
1288
1418
|
}
|
|
1289
1419
|
static get observedAttributes() {
|
|
@@ -1397,23 +1527,27 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1397
1527
|
}
|
|
1398
1528
|
const parser = new DOMParser();
|
|
1399
1529
|
const doc = parser.parseFromString(html, "text/html");
|
|
1400
|
-
if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(
|
|
1530
|
+
if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(
|
|
1531
|
+
`div[data-bundle][data-route][id^="${this.name}"]`
|
|
1532
|
+
) || doc.querySelectorAll("remote-component").length > 1 && !doc.querySelector(`remote-component[name="${this.name}"]`)) {
|
|
1401
1533
|
throw multipleRemoteComponentsError(
|
|
1402
1534
|
url?.href ?? (this.getAttribute("src") || "unknown")
|
|
1403
1535
|
);
|
|
1404
1536
|
}
|
|
1405
1537
|
const component = doc.querySelector(`div[data-bundle][data-route][id^="${this.name}"]`) ?? // fallback to the first element with the data-bundle and data-route attributes when not using a named remote component
|
|
1406
1538
|
doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
|
|
1407
|
-
doc.querySelector("div#__next")
|
|
1539
|
+
doc.querySelector("div#__next") ?? // fallback to a <remote-component> element
|
|
1540
|
+
doc.querySelector(`remote-component[name="${this.name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
|
|
1408
1541
|
const nextData = JSON.parse(
|
|
1409
1542
|
(doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
|
|
1410
1543
|
);
|
|
1544
|
+
const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
|
|
1411
1545
|
if (nextData && nextData.buildId === "development" && !this.reactRoot) {
|
|
1412
1546
|
this.fouc = document.createElement("style");
|
|
1413
1547
|
this.fouc.textContent = `:host { display: none; }`;
|
|
1414
1548
|
this.root.appendChild(this.fouc);
|
|
1415
1549
|
}
|
|
1416
|
-
this.name = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : this.name);
|
|
1550
|
+
this.name = component?.getAttribute("id")?.replace(/_ssr$/, "") || isRemoteComponent && component.getAttribute("name") || (nextData ? "__next" : this.name);
|
|
1417
1551
|
const rsc = doc.querySelector(`#${this.name}_rsc`);
|
|
1418
1552
|
this.bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || this.bundle;
|
|
1419
1553
|
if (url) {
|
|
@@ -1426,12 +1560,13 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1426
1560
|
const metadata = document.createElement("script");
|
|
1427
1561
|
metadata.type = "application/json";
|
|
1428
1562
|
metadata.setAttribute("data-remote-component", "");
|
|
1429
|
-
|
|
1563
|
+
const metadataObj = {
|
|
1430
1564
|
name: this.name,
|
|
1431
1565
|
bundle: this.bundle,
|
|
1432
|
-
route: component?.getAttribute("data-route") ?? nextData?.page ?? "/",
|
|
1433
|
-
runtime: component?.getAttribute("data-runtime") ?? nextData?.props.__REMOTE_COMPONENT__?.runtime
|
|
1434
|
-
}
|
|
1566
|
+
route: component?.getAttribute("data-route") ?? nextData?.page ?? url?.pathname ?? "/",
|
|
1567
|
+
runtime: component?.getAttribute("data-runtime") ?? nextData?.props.__REMOTE_COMPONENT__?.runtime ?? "script"
|
|
1568
|
+
};
|
|
1569
|
+
metadata.textContent = JSON.stringify(metadataObj);
|
|
1435
1570
|
if (this.previousElementSibling?.getAttribute("data-remote-component") !== null) {
|
|
1436
1571
|
this.previousElementSibling?.remove();
|
|
1437
1572
|
}
|
|
@@ -1446,11 +1581,38 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1446
1581
|
remoteShared.__remote_components_missing_shared__
|
|
1447
1582
|
);
|
|
1448
1583
|
}
|
|
1449
|
-
if (!component || !(rsc || nextData)) {
|
|
1584
|
+
if (!component || !(rsc || nextData || isRemoteComponent)) {
|
|
1450
1585
|
throw new RemoteComponentsError(
|
|
1451
1586
|
`Remote Component not found on ${src}.${this.name !== "__vercel_remote_component" ? ` The name for the <RemoteComponent> is "${this.name}". Check <RemoteComponent> usage.` : ""} Did you forget to wrap the content in <RemoteComponent>?`
|
|
1452
1587
|
);
|
|
1453
1588
|
}
|
|
1589
|
+
if (this.prevIsRemoteComponent) {
|
|
1590
|
+
if (this.prevUrl) {
|
|
1591
|
+
const prevUrl = this.prevUrl;
|
|
1592
|
+
const self2 = globalThis;
|
|
1593
|
+
if (self2.__remote_script_entrypoint_unmount__?.[prevUrl.href]) {
|
|
1594
|
+
await Promise.all(
|
|
1595
|
+
Array.from(
|
|
1596
|
+
self2.__remote_script_entrypoint_unmount__[prevUrl.href] ?? []
|
|
1597
|
+
).map(async (unmount) => {
|
|
1598
|
+
try {
|
|
1599
|
+
await unmount(this.root);
|
|
1600
|
+
} catch (e) {
|
|
1601
|
+
console.error(
|
|
1602
|
+
new RemoteComponentsError(
|
|
1603
|
+
`Error while calling unmount() for Remote Component from ${prevUrl.href}.`,
|
|
1604
|
+
{ cause: e }
|
|
1605
|
+
)
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
})
|
|
1609
|
+
);
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
this.root.innerHTML = "";
|
|
1613
|
+
}
|
|
1614
|
+
this.prevUrl = url ?? new URL(location.href);
|
|
1615
|
+
this.prevIsRemoteComponent = isRemoteComponent;
|
|
1454
1616
|
const removable = Array.from(this.childNodes);
|
|
1455
1617
|
const links = doc.querySelectorAll("link[href]");
|
|
1456
1618
|
const remoteComponentSrc = this.getAttribute("src");
|
|
@@ -1516,7 +1678,35 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1516
1678
|
applyOriginToNodes(doc, url ?? new URL(location.href));
|
|
1517
1679
|
if (!this.reactRoot) {
|
|
1518
1680
|
Array.from(component.children).forEach((el) => {
|
|
1519
|
-
|
|
1681
|
+
if (!isRemoteComponent && el.tagName.toLowerCase() === "script") {
|
|
1682
|
+
const newScript = document.createElement("script");
|
|
1683
|
+
for (const attr of el.attributes) {
|
|
1684
|
+
if (attr.name === "src") {
|
|
1685
|
+
newScript.setAttribute(
|
|
1686
|
+
attr.name,
|
|
1687
|
+
new URL(attr.value, url ?? location.origin).href
|
|
1688
|
+
);
|
|
1689
|
+
} else {
|
|
1690
|
+
newScript.setAttribute(attr.name, attr.value);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
newScript.textContent = el.textContent;
|
|
1694
|
+
if (remoteComponentSrc) {
|
|
1695
|
+
newScript.setAttribute(
|
|
1696
|
+
"data-remote-component-src",
|
|
1697
|
+
remoteComponentSrc
|
|
1698
|
+
);
|
|
1699
|
+
}
|
|
1700
|
+
this.root?.appendChild(newScript);
|
|
1701
|
+
} else {
|
|
1702
|
+
const newEl = el.cloneNode(true);
|
|
1703
|
+
for (const attr of el.attributes) {
|
|
1704
|
+
if (attr.name.startsWith("on")) {
|
|
1705
|
+
newEl.setAttribute(attr.name, attr.value);
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
this.root?.appendChild(newEl);
|
|
1709
|
+
}
|
|
1520
1710
|
});
|
|
1521
1711
|
}
|
|
1522
1712
|
for (const el of removable) {
|
|
@@ -1555,7 +1745,7 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1555
1745
|
nextClientPagesLoader: nextClientPagesLoader2,
|
|
1556
1746
|
preloadScripts
|
|
1557
1747
|
} = await getRuntime(
|
|
1558
|
-
|
|
1748
|
+
metadataObj.runtime,
|
|
1559
1749
|
url ?? new URL(location.href),
|
|
1560
1750
|
this.bundle,
|
|
1561
1751
|
{
|
|
@@ -1567,8 +1757,8 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1567
1757
|
},
|
|
1568
1758
|
remoteShared
|
|
1569
1759
|
);
|
|
1570
|
-
const scripts = doc.querySelectorAll(
|
|
1571
|
-
"script[src],script[data-src]"
|
|
1760
|
+
const scripts = isRemoteComponent ? component.querySelectorAll("script") : doc.querySelectorAll(
|
|
1761
|
+
"script[src],script[data-src],script[data-remote-component-entrypoint]"
|
|
1572
1762
|
);
|
|
1573
1763
|
if (!url) {
|
|
1574
1764
|
url = new URL(
|
|
@@ -1582,6 +1772,13 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1582
1772
|
this.bundle ?? "default",
|
|
1583
1773
|
this.name ?? "__vercel_remote_component"
|
|
1584
1774
|
);
|
|
1775
|
+
if (isRemoteComponent) {
|
|
1776
|
+
Array.from(component.children).forEach((child) => {
|
|
1777
|
+
if (child.tagName === "SCRIPT") {
|
|
1778
|
+
child.remove();
|
|
1779
|
+
}
|
|
1780
|
+
});
|
|
1781
|
+
}
|
|
1585
1782
|
const doCleanup = () => {
|
|
1586
1783
|
if (this.root && remoteComponentSrc) {
|
|
1587
1784
|
const selector = `[data-remote-component-src]:not([data-remote-component-src="${remoteComponentSrc}"])`;
|
|
@@ -1703,6 +1900,23 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1703
1900
|
if (this.fouc) {
|
|
1704
1901
|
this.root.removeChild(this.fouc);
|
|
1705
1902
|
}
|
|
1903
|
+
} else if (self.__remote_script_entrypoint_mount__?.[url.href]) {
|
|
1904
|
+
await Promise.all(
|
|
1905
|
+
Array.from(
|
|
1906
|
+
self.__remote_script_entrypoint_mount__[url.href] ?? []
|
|
1907
|
+
).map(async (mount) => {
|
|
1908
|
+
try {
|
|
1909
|
+
await mount(this.root);
|
|
1910
|
+
} catch (e) {
|
|
1911
|
+
console.error(
|
|
1912
|
+
new RemoteComponentsError(
|
|
1913
|
+
`Error while calling mount() for Remote Component from ${url.href}.`,
|
|
1914
|
+
{ cause: e }
|
|
1915
|
+
)
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
})
|
|
1919
|
+
);
|
|
1706
1920
|
}
|
|
1707
1921
|
this.isLoading = false;
|
|
1708
1922
|
}
|