@occluze/tether 0.6.8 → 0.7.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 +11 -11
- package/dist/esm/astro.js +2 -2
- package/dist/esm/chunks/account-UIPWJQ3Y.js +1 -0
- package/dist/esm/chunks/account-pages-6ROA6Y4V.js +1 -0
- package/dist/esm/chunks/analytics-2V632IRV.js +1 -0
- package/dist/esm/chunks/chunk-4GCXM764.js +1 -0
- package/dist/esm/chunks/chunk-56FCLJJD.js +1 -0
- package/dist/esm/chunks/chunk-5Z5O3767.js +1 -0
- package/dist/esm/chunks/chunk-6OZJCAGZ.js +1 -0
- package/dist/esm/chunks/chunk-A5SYCVQM.js +1 -0
- package/dist/esm/chunks/chunk-BA4LQJJQ.js +1 -0
- package/dist/esm/chunks/chunk-BFTZR4OB.js +4 -0
- package/dist/esm/chunks/chunk-C5JYQCWH.js +1 -0
- package/dist/esm/chunks/chunk-E5YO6274.js +1 -0
- package/dist/esm/chunks/chunk-MPDWM2NN.js +1 -0
- package/dist/esm/chunks/chunk-T44MUL4Y.js +1 -0
- package/dist/esm/chunks/chunk-YLUULATY.js +1 -0
- package/dist/esm/chunks/diagnose-3FEKRIEK.js +14 -0
- package/dist/esm/chunks/extras-6POFBNOP.js +1 -0
- package/dist/esm/chunks/markets-ui-FD6NI2OG.js +1 -0
- package/dist/esm/chunks/search-UJ73YBQ5.js +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/server.js +2 -2
- package/dist/presets/barba.esm.js +19 -23
- package/dist/tether.account-pages.js +320 -365
- package/dist/tether.account-pages.min.js +1 -1
- package/dist/tether.account.js +242 -491
- package/dist/tether.account.min.js +1 -1
- package/dist/tether.analytics.js +66 -88
- package/dist/tether.analytics.min.js +1 -1
- package/dist/tether.diagnose.js +36 -33
- package/dist/tether.diagnose.min.js +2 -2
- package/dist/tether.extras.js +28 -36
- package/dist/tether.extras.min.js +1 -1
- package/dist/tether.js +1270 -894
- package/dist/tether.markets.js +73 -90
- package/dist/tether.markets.min.js +1 -1
- package/dist/tether.min.js +0 -0
- package/dist/tether.min.js.map +4 -4
- package/dist/tether.search.js +44 -68
- package/dist/tether.search.min.js +1 -1
- package/dist/types/server/src/shared/account-orders.d.ts +44 -0
- package/dist/types/server/src/shared/account-routes.d.ts +153 -0
- package/dist/types/server/src/shared/api-versions.d.ts +13 -0
- package/dist/types/server/src/shared/error-message.d.ts +2 -0
- package/dist/types/server/src/shared/json.d.ts +25 -0
- package/dist/types/server/src/shared/market-codes.d.ts +16 -0
- package/dist/types/src/account/addresses-view.d.ts +5 -0
- package/dist/types/src/account/answers.d.ts +40 -0
- package/dist/types/src/account/markup.d.ts +19 -0
- package/dist/types/src/account/operations.d.ts +41 -0
- package/dist/types/src/account/order-lines.d.ts +13 -0
- package/dist/types/src/account/order-list.d.ts +12 -0
- package/dist/types/src/account/order-page.d.ts +6 -0
- package/dist/types/src/account/page-answers.d.ts +182 -0
- package/dist/types/src/account/page-events.d.ts +2 -0
- package/dist/types/src/account/server-client.d.ts +60 -0
- package/dist/types/src/account/subscriptions-view.d.ts +2 -0
- package/dist/types/src/account-api.d.ts +18 -0
- package/dist/types/src/account-marks.d.ts +15 -0
- package/dist/types/src/account-pages.d.ts +8 -0
- package/dist/types/src/account.d.ts +64 -0
- package/dist/types/src/amounts.d.ts +12 -0
- package/dist/types/src/analytics-shopify.d.ts +41 -0
- package/dist/types/src/analytics.d.ts +2 -0
- package/dist/types/src/api-version.d.ts +28 -0
- package/dist/types/src/astro.d.ts +42 -0
- package/dist/types/src/cart/cart-shape.d.ts +43 -0
- package/dist/types/src/cart/checkout.d.ts +16 -0
- package/dist/types/src/cart/drawer.d.ts +18 -0
- package/dist/types/src/cart/mutations.d.ts +79 -0
- package/dist/types/src/cart/render.d.ts +17 -0
- package/dist/types/src/cart/store.d.ts +182 -0
- package/dist/types/src/cart.d.ts +106 -0
- package/dist/types/src/client.d.ts +100 -0
- package/dist/types/src/collection.d.ts +25 -0
- package/dist/types/src/config-sections.d.ts +40 -0
- package/dist/types/src/config.d.ts +185 -0
- package/dist/types/src/controls/cart-controls.d.ts +2 -0
- package/dist/types/src/controls/discount.d.ts +2 -0
- package/dist/types/src/controls/extras.d.ts +5 -0
- package/dist/types/src/controls/navigation.d.ts +12 -0
- package/dist/types/src/diagnose-markup.d.ts +19 -0
- package/dist/types/src/diagnose.d.ts +60 -0
- package/dist/types/src/dom.d.ts +75 -0
- package/dist/types/src/extras.d.ts +21 -0
- package/dist/types/src/fragments.d.ts +158 -0
- package/dist/types/src/globals.d.ts +15 -0
- package/dist/types/src/images.d.ts +20 -0
- package/dist/types/src/index.d.ts +167 -0
- package/dist/types/src/initial.d.ts +56 -0
- package/dist/types/src/lazy.d.ts +28 -0
- package/dist/types/src/loader.d.ts +84 -0
- package/dist/types/src/market-codes.d.ts +6 -0
- package/dist/types/src/markets-ui.d.ts +32 -0
- package/dist/types/src/markets.d.ts +72 -0
- package/dist/types/src/markup.d.ts +131 -0
- package/dist/types/src/mounting.d.ts +46 -0
- package/dist/types/src/page-market.d.ts +27 -0
- package/dist/types/src/presets/barba.d.ts +56 -0
- package/dist/types/src/product-events.d.ts +2 -0
- package/dist/types/src/product-render.d.ts +17 -0
- package/dist/types/src/product-shape.d.ts +88 -0
- package/dist/types/src/product-state.d.ts +110 -0
- package/dist/types/src/product.d.ts +66 -0
- package/dist/types/src/repeaters.d.ts +16 -0
- package/dist/types/src/search.d.ts +33 -0
- package/dist/types/src/selling-plans.d.ts +64 -0
- package/dist/types/src/server.d.ts +88 -0
- package/dist/types/src/shopify-values.d.ts +46 -0
- package/dist/types/src/status.d.ts +33 -0
- package/dist/types/src/storage.d.ts +12 -0
- package/dist/types/src/store-html.d.ts +39 -0
- package/dist/types/src/storefront/catalog.d.ts +38 -0
- package/dist/types/src/storefront/json-ld.d.ts +20 -0
- package/dist/types/src/variant-render.d.ts +14 -0
- package/package.json +24 -23
- package/src/account/addresses-view.ts +58 -0
- package/src/account/answers.ts +79 -0
- package/src/account/markup.ts +36 -0
- package/src/account/operations.ts +145 -0
- package/src/account/{order-lines.js → order-lines.ts} +20 -41
- package/src/account/order-list.ts +107 -0
- package/src/account/order-page.ts +137 -0
- package/src/account/page-answers.ts +317 -0
- package/src/account/{page-events.js → page-events.ts} +55 -90
- package/src/account/server-client.ts +183 -0
- package/src/account/{subscriptions-view.js → subscriptions-view.ts} +25 -68
- package/src/account-api.ts +98 -0
- package/src/account-marks.ts +35 -0
- package/src/{account-pages.js → account-pages.ts} +29 -37
- package/src/account.ts +284 -0
- package/src/amounts.ts +64 -0
- package/src/{analytics-shopify.js → analytics-shopify.ts} +112 -107
- package/src/analytics.ts +315 -0
- package/src/{api-version.js → api-version.ts} +25 -31
- package/src/{astro.js → astro.ts} +110 -104
- package/src/cart/cart-shape.ts +25 -0
- package/src/cart/checkout.ts +101 -0
- package/src/cart/{drawer.js → drawer.ts} +18 -31
- package/src/cart/mutations.ts +237 -0
- package/src/cart/{render.js → render.ts} +68 -96
- package/src/cart/store.ts +279 -0
- package/src/{cart.js → cart.ts} +82 -128
- package/src/client.ts +391 -0
- package/src/{collection.js → collection.ts} +30 -38
- package/src/config-sections.ts +284 -0
- package/src/config.ts +480 -0
- package/src/controls/{cart-controls.js → cart-controls.ts} +22 -54
- package/src/controls/{discount.js → discount.ts} +13 -34
- package/src/controls/{extras.js → extras.ts} +15 -24
- package/src/controls/{navigation.js → navigation.ts} +24 -30
- package/src/{diagnose-markup.js → diagnose-markup.ts} +37 -72
- package/src/{diagnose.js → diagnose.ts} +95 -96
- package/src/dom.ts +268 -0
- package/src/{extras.js → extras.ts} +43 -52
- package/src/fragments.ts +261 -0
- package/src/globals.d.ts +15 -0
- package/src/{images.js → images.ts} +30 -43
- package/src/index.ts +415 -0
- package/src/initial.ts +101 -0
- package/src/lazy-iife.ts +197 -0
- package/src/lazy.ts +42 -0
- package/src/{loader.js → loader.ts} +149 -123
- package/src/market-codes.ts +6 -0
- package/src/{markets-ui.js → markets-ui.ts} +91 -68
- package/src/markets.ts +246 -0
- package/src/markup.ts +127 -0
- package/src/{mounting.js → mounting.ts} +88 -101
- package/src/{page-market.js → page-market.ts} +32 -38
- package/src/part-integrity.ts +7 -0
- package/src/parts/account-pages.ts +7 -0
- package/src/parts/account.ts +7 -0
- package/src/parts/analytics.ts +7 -0
- package/src/parts/diagnose.ts +7 -0
- package/src/parts/extras.ts +7 -0
- package/src/parts/markets.ts +7 -0
- package/src/parts/search.ts +7 -0
- package/src/presets/barba.ts +194 -0
- package/src/{product-events.js → product-events.ts} +33 -48
- package/src/{product-render.js → product-render.ts} +38 -77
- package/src/product-shape.ts +49 -0
- package/src/product-state.ts +318 -0
- package/src/{product.js → product.ts} +90 -126
- package/src/{repeaters.js → repeaters.ts} +40 -52
- package/src/{search.js → search.ts} +85 -103
- package/src/selling-plans.ts +145 -0
- package/src/server.ts +211 -0
- package/src/{shopify-values.js → shopify-values.ts} +24 -22
- package/src/{status.js → status.ts} +34 -54
- package/src/storage.ts +34 -0
- package/src/store-html.ts +359 -0
- package/src/storefront/catalog.ts +196 -0
- package/src/storefront/{json-ld.js → json-ld.ts} +45 -68
- package/src/{variant-render.js → variant-render.ts} +24 -50
- package/dist/esm/chunks/account-C3NP6HFB.js +0 -1
- package/dist/esm/chunks/account-pages-WLK374FO.js +0 -1
- package/dist/esm/chunks/analytics-G3SAWMNL.js +0 -1
- package/dist/esm/chunks/chunk-27PJJZGC.js +0 -1
- package/dist/esm/chunks/chunk-2FSXS55U.js +0 -1
- package/dist/esm/chunks/chunk-FCSWQDVV.js +0 -1
- package/dist/esm/chunks/chunk-FOMSMIAM.js +0 -1
- package/dist/esm/chunks/chunk-GZJTCLLW.js +0 -1
- package/dist/esm/chunks/chunk-HEQILZVR.js +0 -1
- package/dist/esm/chunks/chunk-JOOEXYF3.js +0 -4
- package/dist/esm/chunks/chunk-MPTQYLSM.js +0 -1
- package/dist/esm/chunks/chunk-NEHZ37TU.js +0 -3
- package/dist/esm/chunks/chunk-V74KGEJF.js +0 -1
- package/dist/esm/chunks/chunk-VT4CDUJJ.js +0 -1
- package/dist/esm/chunks/chunk-YJLWX2HK.js +0 -1
- package/dist/esm/chunks/diagnose-6VVGZNTY.js +0 -14
- package/dist/esm/chunks/extras-GJVRDFM3.js +0 -1
- package/dist/esm/chunks/markets-ui-UNB4PTA7.js +0 -1
- package/dist/esm/chunks/search-OU75RNQL.js +0 -1
- package/src/account/addresses-view.js +0 -92
- package/src/account/browser-session.js +0 -359
- package/src/account/markup.js +0 -48
- package/src/account/operations.js +0 -180
- package/src/account/order-list.js +0 -91
- package/src/account/order-page.js +0 -192
- package/src/account/server-client.js +0 -172
- package/src/account/shared.js +0 -111
- package/src/account/shopify-auth.js +0 -150
- package/src/account-api.js +0 -118
- package/src/account-links.js +0 -35
- package/src/account.js +0 -342
- package/src/amounts.js +0 -36
- package/src/analytics.js +0 -352
- package/src/cart/checkout.js +0 -97
- package/src/cart/mutations.js +0 -234
- package/src/cart/store.js +0 -326
- package/src/client.js +0 -267
- package/src/config.js +0 -349
- package/src/dom.js +0 -287
- package/src/fragments.js +0 -237
- package/src/index.js +0 -353
- package/src/initial.js +0 -87
- package/src/lazy-iife.js +0 -116
- package/src/lazy.js +0 -39
- package/src/market-codes.js +0 -35
- package/src/markets.js +0 -334
- package/src/markup.js +0 -64
- package/src/parts/account-pages.js +0 -6
- package/src/parts/account.js +0 -6
- package/src/parts/analytics.js +0 -6
- package/src/parts/diagnose.js +0 -6
- package/src/parts/extras.js +0 -6
- package/src/parts/markets.js +0 -6
- package/src/parts/search.js +0 -6
- package/src/presets/barba.js +0 -190
- package/src/product-state.js +0 -318
- package/src/selling-plans.js +0 -154
- package/src/server.js +0 -215
- package/src/store-html.js +0 -0
- package/src/storefront/catalog.js +0 -199
- package/types/astro.d.ts +0 -28
- package/types/barba.d.ts +0 -16
- package/types/index.d.ts +0 -577
- package/types/server.d.ts +0 -182
package/src/lazy-iife.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `<script>` build: the optional parts are separate files next to tether(.min).js (tether.markets.min.js), loaded on
|
|
3
|
-
* first use. `partsUrl` sets another folder. A part registers itself in `window.Tether.__parts` and uses the core
|
|
4
|
-
* modules in `window.Tether.__core` instead of bundling copies of them.
|
|
5
|
-
*/
|
|
6
|
-
import * as config from './config.js';
|
|
7
|
-
import * as client from './client.js';
|
|
8
|
-
import * as dom from './dom.js';
|
|
9
|
-
import * as fragments from './fragments.js';
|
|
10
|
-
import * as loader from './loader.js';
|
|
11
|
-
import * as sellingPlans from './selling-plans.js';
|
|
12
|
-
import * as status from './status.js';
|
|
13
|
-
import * as cart from './cart.js';
|
|
14
|
-
import * as product from './product.js';
|
|
15
|
-
import * as collection from './collection.js';
|
|
16
|
-
import * as mounting from './mounting.js';
|
|
17
|
-
import * as marketCodes from './market-codes.js';
|
|
18
|
-
import * as shopifyValues from './shopify-values.js';
|
|
19
|
-
import * as storeHtml from './store-html.js';
|
|
20
|
-
/** @import { Parts, PartName } from './lazy.js' */
|
|
21
|
-
|
|
22
|
-
const { cfg } = config;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* The modules a part may use, shared instead of bundled twice (scripts/build.mjs maps a part's imports to these).
|
|
26
|
-
*
|
|
27
|
-
* @type {Record<string, object>}
|
|
28
|
-
*/
|
|
29
|
-
export const coreModules = {
|
|
30
|
-
'config.js': config,
|
|
31
|
-
'client.js': client,
|
|
32
|
-
'dom.js': dom,
|
|
33
|
-
'fragments.js': fragments,
|
|
34
|
-
'loader.js': loader,
|
|
35
|
-
'selling-plans.js': sellingPlans,
|
|
36
|
-
'status.js': status,
|
|
37
|
-
'cart.js': cart,
|
|
38
|
-
'product.js': product,
|
|
39
|
-
'collection.js': collection,
|
|
40
|
-
'mounting.js': mounting,
|
|
41
|
-
'market-codes.js': marketCodes,
|
|
42
|
-
'shopify-values.js': shopifyValues,
|
|
43
|
-
'store-html.js': storeHtml,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const MINIFIED_SCRIPT = /\.min\.js(\?|$)/;
|
|
47
|
-
const coreScript = typeof document === 'undefined' ? '' : (document.currentScript?.getAttribute('src') ?? '');
|
|
48
|
-
const coreScriptUrl = coreScript ? new URL(coreScript, document.baseURI).href : '';
|
|
49
|
-
|
|
50
|
-
/** @type {Map<PartName, Promise<unknown>>} Parts loaded or loading. */
|
|
51
|
-
const parts = new Map();
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* The folder parts load from: `partsUrl`, else the core script's own folder. A `partsUrl` must be https or on this
|
|
55
|
-
* site, because the parts run with the same access as the core (the account part holds customer sessions).
|
|
56
|
-
*
|
|
57
|
-
* @throws {Error} For a `partsUrl` that is neither.
|
|
58
|
-
*/
|
|
59
|
-
function partsFolder() {
|
|
60
|
-
if (!cfg.partsUrl) return coreScriptUrl.replace(/[^/]*$/, '');
|
|
61
|
-
const folder = new URL(cfg.partsUrl, document.baseURI);
|
|
62
|
-
if (folder.protocol !== 'https:' && folder.origin !== window.location.origin) {
|
|
63
|
-
throw new Error(`partsUrl must be https or on this site: ${folder.href}`);
|
|
64
|
-
}
|
|
65
|
-
return folder.href;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* @param {PartName} name
|
|
70
|
-
* @param {string} url
|
|
71
|
-
* @returns {Promise<unknown>}
|
|
72
|
-
*/
|
|
73
|
-
function loadScript(name, url) {
|
|
74
|
-
return new Promise((resolve, reject) => {
|
|
75
|
-
const script = document.createElement('script');
|
|
76
|
-
script.src = url;
|
|
77
|
-
script.async = true;
|
|
78
|
-
script.onload = () => {
|
|
79
|
-
const { Tether } = /** @type {Window & { Tether?: { __parts?: Record<string, unknown> } }} */ (window);
|
|
80
|
-
const part = Tether?.__parts?.[name];
|
|
81
|
-
if (part) resolve(part);
|
|
82
|
-
else reject(new Error(`${url} did not register`));
|
|
83
|
-
};
|
|
84
|
-
script.onerror = () => {
|
|
85
|
-
parts.delete(name);
|
|
86
|
-
reject(new Error(`Could not load ${url}. Host it next to the Tether script, or set partsUrl.`));
|
|
87
|
-
};
|
|
88
|
-
document.head.appendChild(script);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* @template {PartName} Name
|
|
94
|
-
* @param {Name} name
|
|
95
|
-
* @returns {Promise<Parts[Name]>}
|
|
96
|
-
* @throws {Error} (rejected) When the part's file can't be loaded or doesn't register.
|
|
97
|
-
*/
|
|
98
|
-
export function loadPart(name) {
|
|
99
|
-
let loading = parts.get(name);
|
|
100
|
-
if (!loading) {
|
|
101
|
-
let folder;
|
|
102
|
-
try {
|
|
103
|
-
folder = partsFolder();
|
|
104
|
-
} catch (error) {
|
|
105
|
-
return Promise.reject(error instanceof Error ? error : new Error(String(error)));
|
|
106
|
-
}
|
|
107
|
-
const suffix = MINIFIED_SCRIPT.test(coreScriptUrl) || !coreScriptUrl ? '.min' : '';
|
|
108
|
-
loading = loadScript(name, `${folder.replace(/\/?$/, '/')}tether.${name}${suffix}.js`);
|
|
109
|
-
parts.set(name, loading);
|
|
110
|
-
}
|
|
111
|
-
// A part's file is built from the module `Parts[Name]` names (scripts/build.mjs), and registers that module.
|
|
112
|
-
return /** @type {Promise<Parts[Name]>} */ (loading);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Parts that load other parts (account → account-pages) use this same loader.
|
|
116
|
-
coreModules['lazy.js'] = { loadPart, coreModules };
|
package/src/lazy.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Optional parts that most pages never need, loaded on first use. In the ESM and Node builds they are dynamic
|
|
3
|
-
* imports, which bundlers split into their own chunks; the `<script>` build swaps this file for `lazy-iife.js`
|
|
4
|
-
* (scripts/build.mjs).
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {{
|
|
9
|
-
* diagnose: typeof import('./diagnose.js'),
|
|
10
|
-
* markets: typeof import('./markets-ui.js'),
|
|
11
|
-
* search: typeof import('./search.js'),
|
|
12
|
-
* extras: typeof import('./extras.js'),
|
|
13
|
-
* account: typeof import('./account.js'),
|
|
14
|
-
* 'account-pages': typeof import('./account-pages.js'),
|
|
15
|
-
* analytics: typeof import('./analytics.js'),
|
|
16
|
-
* }} Parts
|
|
17
|
-
*/
|
|
18
|
-
/** @typedef {keyof Parts} PartName */
|
|
19
|
-
|
|
20
|
-
/** @type {{ [Name in PartName]: () => Promise<Parts[Name]> }} */
|
|
21
|
-
const PARTS = {
|
|
22
|
-
diagnose: () => import('./diagnose.js'),
|
|
23
|
-
markets: () => import('./markets-ui.js'),
|
|
24
|
-
search: () => import('./search.js'),
|
|
25
|
-
extras: () => import('./extras.js'),
|
|
26
|
-
account: () => import('./account.js'),
|
|
27
|
-
'account-pages': () => import('./account-pages.js'),
|
|
28
|
-
analytics: () => import('./analytics.js'),
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @template {PartName} Name
|
|
33
|
-
* @param {Name} name
|
|
34
|
-
* @returns {Promise<Parts[Name]>}
|
|
35
|
-
*/
|
|
36
|
-
export const loadPart = (name) => PARTS[name]();
|
|
37
|
-
|
|
38
|
-
/** Only the `<script>` build shares its modules with separately loaded parts. */
|
|
39
|
-
export const coreModules = undefined;
|
package/src/market-codes.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Country and language codes as Shopify's `@inContext` takes them. Every market value that reaches a query passes
|
|
3
|
-
* through here: they are written into the query text, so anything else is dropped rather than sent.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/** @typedef {string & { readonly __brand: 'CountryCode' }} CountryCode An ISO 3166-1 alpha-2 code, upper case. */
|
|
7
|
-
/** @typedef {string & { readonly __brand: 'LanguageCode' }} LanguageCode A Shopify `LanguageCode` value. */
|
|
8
|
-
|
|
9
|
-
const COUNTRY = /^[A-Z]{2}$/;
|
|
10
|
-
/** Cloudflare's codes for an unknown country (XX) and Tor (T1), which a `cf-ipcountry` cookie can carry. */
|
|
11
|
-
const NOT_A_COUNTRY = new Set(['XX', 'T1']);
|
|
12
|
-
/** Shopify `LanguageCode` values with a region. Every other language is its plain ISO 639 code. */
|
|
13
|
-
const REGIONAL_LANGUAGES = new Set(['PT_BR', 'PT_PT', 'ZH_CN', 'ZH_TW']);
|
|
14
|
-
const LANGUAGE = /^[A-Z]{2,3}$/;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @param {unknown} value
|
|
18
|
-
* @returns {CountryCode | null} `'de'` → `'DE'`; `null` for anything that is not a country code.
|
|
19
|
-
*/
|
|
20
|
-
export function toCountry(value) {
|
|
21
|
-
const code = (typeof value === 'string' ? value : '').trim().toUpperCase();
|
|
22
|
-
if (!COUNTRY.test(code) || NOT_A_COUNTRY.has(code)) return null;
|
|
23
|
-
return /** @type {CountryCode} */ (code);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @param {unknown} value
|
|
28
|
-
* @returns {LanguageCode | null} `'de-DE'` → `'DE'`, `'pt-BR'` → `'PT_BR'`, `'en'` → `'EN'`; `null` otherwise.
|
|
29
|
-
*/
|
|
30
|
-
export function toLanguage(value) {
|
|
31
|
-
const raw = (typeof value === 'string' ? value : '').trim().replace('-', '_').toUpperCase();
|
|
32
|
-
if (REGIONAL_LANGUAGES.has(raw)) return /** @type {LanguageCode} */ (raw);
|
|
33
|
-
const primary = raw.split('_')[0] ?? '';
|
|
34
|
-
return LANGUAGE.test(primary) ? /** @type {LanguageCode} */ (primary) : null;
|
|
35
|
-
}
|
package/src/markets.js
DELETED
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Markets: which country and language prices, currency and translations follow.
|
|
3
|
-
*
|
|
4
|
-
* markets: {
|
|
5
|
-
* detect: true, // or a list: ['saved', 'server', 'webflow']
|
|
6
|
-
* locales: { // Webflow Localization: locale subdirectory or <html lang>
|
|
7
|
-
* de: { country: 'DE', language: 'DE', locale: 'de-DE' },
|
|
8
|
-
* 'fr-be': { country: 'BE', language: 'FR' },
|
|
9
|
-
* },
|
|
10
|
-
* cookie: 'tether_country', // a cookie your server or Worker sets (from cf-ipcountry)
|
|
11
|
-
* remember: true, // keep the visitor's tether-country-select choice
|
|
12
|
-
* }
|
|
13
|
-
*
|
|
14
|
-
* Sources, first match wins per field:
|
|
15
|
-
* saved the visitor's own choice (localStorage), from tether-country-select / Tether.setCountry()
|
|
16
|
-
* server window.TETHER_COUNTRY, <meta name="tether-country" content="DE">, or the cookie
|
|
17
|
-
* webflow locale subdirectory (/de/...) or <html lang="de-DE">, through `locales`
|
|
18
|
-
* then the static `country` / `language` config. Without `detect`, only `saved` applies, so a country select keeps
|
|
19
|
-
* working across pages; `detect: false` turns even that off. Tether never calls an IP lookup service: a country from
|
|
20
|
-
* the visitor's IP only comes from the site's own server (see README).
|
|
21
|
-
*/
|
|
22
|
-
import { cfg } from './config.js';
|
|
23
|
-
import { gql } from './client.js';
|
|
24
|
-
import { toCountry, toLanguage } from './market-codes.js';
|
|
25
|
-
/** @import { MarketsConfig } from './config.js' */
|
|
26
|
-
/** @import { CountryCode, LanguageCode } from './market-codes.js' */
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @typedef {object} Market A market a visitor chose, as `setCountry()` stores it.
|
|
30
|
-
* @property {CountryCode} country
|
|
31
|
-
* @property {LanguageCode | undefined} language
|
|
32
|
-
* @property {string | undefined} locale An `Intl` locale for money and dates.
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
/** @typedef {'saved' | 'server' | 'webflow'} MarketSource */
|
|
36
|
-
/** @typedef {'country' | 'language' | 'locale'} MarketField */
|
|
37
|
-
/** @typedef {Partial<Record<MarketField, MarketSource>>} MarketSources */
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @typedef {object} DetectedMarket The fields detection found, and the source each came from.
|
|
41
|
-
* @property {CountryCode} [country]
|
|
42
|
-
* @property {LanguageCode} [language]
|
|
43
|
-
* @property {string} [locale]
|
|
44
|
-
* @property {MarketSources} [sources] Absent when `detect: false` turns detection off.
|
|
45
|
-
*/
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @typedef {object} MarketEnv What detection reads, passed in so it runs on any document.
|
|
49
|
-
* @property {Pick<Document, 'cookie' | 'querySelector' | 'documentElement'> | null} document
|
|
50
|
-
* @property {Pick<Location, 'pathname'> | null} location
|
|
51
|
-
* @property {Pick<Storage, 'getItem'> | null} storage
|
|
52
|
-
* @property {object} global Where `TETHER_COUNTRY` and `TETHER_LANGUAGE` are read from (`window`).
|
|
53
|
-
*/
|
|
54
|
-
|
|
55
|
-
/** @typedef {{ country?: unknown, language?: unknown, locale?: unknown }} MarketHint A source's raw values. */
|
|
56
|
-
|
|
57
|
-
/** @typedef {{ isoCode: string, name: string }} NamedCode */
|
|
58
|
-
/** @typedef {{ isoCode: string, symbol: string }} Currency */
|
|
59
|
-
/** @typedef {NamedCode & { currency: Currency }} LocalizedCountry */
|
|
60
|
-
/**
|
|
61
|
-
* @typedef {object} Localization The store's markets, from the Storefront API's `localization`.
|
|
62
|
-
* @property {LocalizedCountry} country The country of the current `@inContext`.
|
|
63
|
-
* @property {NamedCode} language
|
|
64
|
-
* @property {(LocalizedCountry & { availableLanguages: NamedCode[] })[]} availableCountries
|
|
65
|
-
*/
|
|
66
|
-
|
|
67
|
-
/** @type {readonly MarketSource[]} */
|
|
68
|
-
const ALL_SOURCES = ['saved', 'server', 'webflow'];
|
|
69
|
-
const DEFAULT_COOKIE = 'tether_country';
|
|
70
|
-
|
|
71
|
-
/** @returns {string} The localStorage key of the visitor's market: `<prefix>:market:<domain>`. */
|
|
72
|
-
export const storageKey = () => `${cfg.prefix}:market:${cfg.domain}`;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Accessing `localStorage` throws where the browser blocks storage (sandboxed frames, cookies turned off); the visitor
|
|
76
|
-
* then simply has no saved market.
|
|
77
|
-
*
|
|
78
|
-
* @returns {Storage | null}
|
|
79
|
-
*/
|
|
80
|
-
function localStorageIfAllowed() {
|
|
81
|
-
if (typeof window === 'undefined') return null;
|
|
82
|
-
try {
|
|
83
|
-
return window.localStorage;
|
|
84
|
-
} catch {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/** @returns {MarketEnv} The page this script runs on. */
|
|
90
|
-
function pageEnv() {
|
|
91
|
-
const hasWindow = typeof window !== 'undefined';
|
|
92
|
-
return {
|
|
93
|
-
document: typeof document !== 'undefined' ? document : null,
|
|
94
|
-
location: hasWindow ? window.location : null,
|
|
95
|
-
storage: localStorageIfAllowed(),
|
|
96
|
-
global: hasWindow ? window : {},
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* @param {string} text
|
|
102
|
-
* @returns {unknown} The JSON value, `null` for text that isn't JSON (a key another script wrote).
|
|
103
|
-
*/
|
|
104
|
-
function parseJsonOrNull(text) {
|
|
105
|
-
try {
|
|
106
|
-
return /** @type {unknown} */ (JSON.parse(text));
|
|
107
|
-
} catch (error) {
|
|
108
|
-
if (error instanceof SyntaxError) return null;
|
|
109
|
-
throw error;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* @param {unknown} value
|
|
115
|
-
* @returns {Market | null} `value` as a market, when it has a valid country. A language or locale that isn't valid is
|
|
116
|
-
* left out.
|
|
117
|
-
*/
|
|
118
|
-
function toMarket(value) {
|
|
119
|
-
if (typeof value !== 'object' || value === null) return null;
|
|
120
|
-
const country = toCountry(Reflect.get(value, 'country'));
|
|
121
|
-
if (!country) return null;
|
|
122
|
-
const locale = /** @type {unknown} */ (Reflect.get(value, 'locale'));
|
|
123
|
-
return {
|
|
124
|
-
country,
|
|
125
|
-
language: toLanguage(Reflect.get(value, 'language')) ?? undefined,
|
|
126
|
-
locale: typeof locale === 'string' && locale ? locale : undefined,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* The visitor's saved market (`setCountry()`, `tether-country-select`), validated: storage is written by other tabs,
|
|
132
|
-
* older versions and other scripts too.
|
|
133
|
-
*
|
|
134
|
-
* @param {Pick<Storage, 'getItem'> | null} [storage] Default `localStorage`, `null` where the browser blocks it.
|
|
135
|
-
* @returns {Market | null} `null` when nothing valid is saved.
|
|
136
|
-
*/
|
|
137
|
-
export function readSavedMarket(storage = localStorageIfAllowed()) {
|
|
138
|
-
const text = storage?.getItem(storageKey());
|
|
139
|
-
return text ? toMarket(parseJsonOrNull(text)) : null;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* @param {Pick<Document, 'cookie'> | null} doc
|
|
144
|
-
* @param {string} name
|
|
145
|
-
* @returns {string | null}
|
|
146
|
-
*/
|
|
147
|
-
function readCookie(doc, name) {
|
|
148
|
-
if (!doc || !name) return null;
|
|
149
|
-
const cookie = doc.cookie
|
|
150
|
-
.split(';')
|
|
151
|
-
.map((part) => part.trim())
|
|
152
|
-
.find((part) => part.startsWith(`${name}=`));
|
|
153
|
-
return cookie ? decodeURIComponent(cookie.slice(name.length + 1)) : null;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* @param {MarketsConfig['locales']} locales
|
|
158
|
-
* @param {string | undefined} key
|
|
159
|
-
* @returns {MarketHint | null} The entry for `key`, ignoring case.
|
|
160
|
-
*/
|
|
161
|
-
function lookupLocale(locales, key) {
|
|
162
|
-
if (!locales || !key) return null;
|
|
163
|
-
const wanted = key.toLowerCase();
|
|
164
|
-
const found = Object.keys(locales).find((name) => name.toLowerCase() === wanted);
|
|
165
|
-
return found ? (locales[found] ?? null) : null;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* @param {MarketsConfig} markets
|
|
170
|
-
* @param {MarketEnv} env
|
|
171
|
-
* @returns {MarketHint}
|
|
172
|
-
*/
|
|
173
|
-
function readServerHint(markets, env) {
|
|
174
|
-
/** @param {string} name */
|
|
175
|
-
const meta = (name) => env.document?.querySelector(`meta[name="${name}"]`)?.getAttribute('content');
|
|
176
|
-
return {
|
|
177
|
-
country:
|
|
178
|
-
Reflect.get(env.global, 'TETHER_COUNTRY') ||
|
|
179
|
-
meta('tether-country') ||
|
|
180
|
-
readCookie(env.document, markets.cookie || DEFAULT_COOKIE),
|
|
181
|
-
language: Reflect.get(env.global, 'TETHER_LANGUAGE') || meta('tether-language'),
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* @param {MarketsConfig} markets
|
|
187
|
-
* @param {MarketEnv} env
|
|
188
|
-
* @returns {MarketHint | null}
|
|
189
|
-
*/
|
|
190
|
-
function readWebflowLocale(markets, env) {
|
|
191
|
-
const segment = (env.location?.pathname ?? '/').split('/').find((part) => part !== '');
|
|
192
|
-
const fromPath = lookupLocale(markets.locales, segment);
|
|
193
|
-
if (fromPath) return fromPath;
|
|
194
|
-
const lang = env.document?.documentElement.getAttribute('lang');
|
|
195
|
-
if (!lang) return null;
|
|
196
|
-
const mapped = lookupLocale(markets.locales, lang) ?? lookupLocale(markets.locales, lang.split('-')[0]);
|
|
197
|
-
if (mapped) return { locale: lang, ...mapped };
|
|
198
|
-
if (markets.locales && markets.strict) return null;
|
|
199
|
-
// Unmapped: the language from <html lang>, a country only from a region subtag (de-CH -> CH).
|
|
200
|
-
const region = lang.split('-')[1];
|
|
201
|
-
return { language: lang, country: region?.length === 2 ? region : null, locale: lang };
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* @param {MarketSource} source
|
|
206
|
-
* @param {MarketsConfig} markets
|
|
207
|
-
* @param {MarketEnv} env
|
|
208
|
-
* @returns {MarketHint | null}
|
|
209
|
-
*/
|
|
210
|
-
function readSource(source, markets, env) {
|
|
211
|
-
switch (source) {
|
|
212
|
-
case 'saved':
|
|
213
|
-
return markets.remember === false ? null : readSavedMarket(env.storage);
|
|
214
|
-
case 'server':
|
|
215
|
-
return readServerHint(markets, env);
|
|
216
|
-
case 'webflow':
|
|
217
|
-
return readWebflowLocale(markets, env);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* @param {unknown} name
|
|
223
|
-
* @returns {name is MarketSource}
|
|
224
|
-
*/
|
|
225
|
-
const isMarketSource = (name) => ALL_SOURCES.some((source) => source === name);
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* @param {MarketsConfig['detect']} detect
|
|
229
|
-
* @returns {readonly MarketSource[]} Without `detect`, only the visitor's own choice from a country select.
|
|
230
|
-
*/
|
|
231
|
-
function sourcesFor(detect) {
|
|
232
|
-
if (!detect) return ['saved'];
|
|
233
|
-
if (detect === true) return ALL_SOURCES;
|
|
234
|
-
// The config comes from the page unvalidated, so a single name or an unknown one can arrive here.
|
|
235
|
-
return /** @type {unknown[]} */ ([detect].flat()).filter(isMarketSource);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* The market the page's sources point to. Reads the DOM and storage only, so it can run on any `env`.
|
|
240
|
-
*
|
|
241
|
-
* @param {MarketsConfig | null | undefined} [markets]
|
|
242
|
-
* @param {MarketEnv} [env]
|
|
243
|
-
* @returns {DetectedMarket} Only the fields found; `{}` with `detect: false`.
|
|
244
|
-
*/
|
|
245
|
-
export function detectMarket(markets = cfg.markets, env = pageEnv()) {
|
|
246
|
-
const config = markets ?? {};
|
|
247
|
-
if (config.detect === false) return {};
|
|
248
|
-
/** @type {MarketSources} */
|
|
249
|
-
const sources = {};
|
|
250
|
-
/** @type {DetectedMarket} */
|
|
251
|
-
const found = { sources };
|
|
252
|
-
for (const source of sourcesFor(config.detect)) {
|
|
253
|
-
const hint = readSource(source, config, env);
|
|
254
|
-
if (!hint) continue;
|
|
255
|
-
const country = toCountry(hint.country);
|
|
256
|
-
const language = toLanguage(hint.language);
|
|
257
|
-
const locale = typeof hint.locale === 'string' && hint.locale ? hint.locale : null;
|
|
258
|
-
if (country && !found.country) {
|
|
259
|
-
found.country = country;
|
|
260
|
-
sources.country = source;
|
|
261
|
-
}
|
|
262
|
-
if (language && !found.language) {
|
|
263
|
-
found.language = language;
|
|
264
|
-
sources.language = source;
|
|
265
|
-
}
|
|
266
|
-
if (locale && !found.locale) {
|
|
267
|
-
found.locale = locale;
|
|
268
|
-
sources.locale = source;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
return found;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* `setItem` throws when storage is full or blocked (Safari's private mode); the choice then lasts for this page only.
|
|
276
|
-
*
|
|
277
|
-
* @param {string} key
|
|
278
|
-
* @param {string} value
|
|
279
|
-
*/
|
|
280
|
-
function storeIfAllowed(key, value) {
|
|
281
|
-
try {
|
|
282
|
-
localStorage.setItem(key, value);
|
|
283
|
-
} catch {
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Saves the visitor's choice for the next pages, unless `markets.remember` is false.
|
|
290
|
-
*
|
|
291
|
-
* @param {{ country: CountryCode, language?: string | null | undefined, locale?: string | null | undefined }} market
|
|
292
|
-
*/
|
|
293
|
-
export function rememberMarket(market) {
|
|
294
|
-
if (cfg.markets?.remember === false) return;
|
|
295
|
-
const saved = { country: market.country, language: market.language || undefined, locale: market.locale || undefined };
|
|
296
|
-
storeIfAllowed(storageKey(), JSON.stringify(saved));
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/** @type {Promise<Localization> | null} */
|
|
300
|
-
let localizationPromise = null;
|
|
301
|
-
|
|
302
|
-
/** Forgets the cached localization, for when country names change language. */
|
|
303
|
-
export function clearLocalization() {
|
|
304
|
-
localizationPromise = null;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const LOCALIZATION_QUERY = `query TetherLocalization {
|
|
308
|
-
localization {
|
|
309
|
-
country { isoCode name currency { isoCode symbol } }
|
|
310
|
-
language { isoCode name }
|
|
311
|
-
availableCountries { isoCode name currency { isoCode symbol } availableLanguages { isoCode name } }
|
|
312
|
-
}
|
|
313
|
-
}`;
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* The countries the store sells to (Shopify Markets), with their currency. Cached per page; a failed request is not
|
|
317
|
-
* cached, so the next call tries again.
|
|
318
|
-
*
|
|
319
|
-
* @returns {Promise<Localization>}
|
|
320
|
-
*/
|
|
321
|
-
export function getLocalization() {
|
|
322
|
-
if (!localizationPromise) {
|
|
323
|
-
/** @type {Promise<{ localization: Localization }>} */
|
|
324
|
-
const loading = gql(LOCALIZATION_QUERY);
|
|
325
|
-
localizationPromise = loading.then(
|
|
326
|
-
(data) => data.localization,
|
|
327
|
-
(/** @type {unknown} */ error) => {
|
|
328
|
-
localizationPromise = null;
|
|
329
|
-
throw error;
|
|
330
|
-
},
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
return localizationPromise;
|
|
334
|
-
}
|
package/src/markup.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* How Tether finds its markup: attribute names carry the configured prefix (`tether-product`, or `wfs-product` with
|
|
3
|
-
* `prefix: 'wfs'`), and so do the selectors and the DOM events built from them.
|
|
4
|
-
*/
|
|
5
|
-
import { cfg } from './config.js';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @param {string} name
|
|
9
|
-
* @returns {string} The prefixed attribute name: `product` → `tether-product`.
|
|
10
|
-
*/
|
|
11
|
-
export const attr = (name) => `${cfg.prefix}-${name}`;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @param {string} name
|
|
15
|
-
* @param {string} [value]
|
|
16
|
-
* @returns {string} A selector for the attribute, with that exact value when given.
|
|
17
|
-
*/
|
|
18
|
-
export const sel = (name, value) => (value === undefined ? `[${attr(name)}]` : `[${attr(name)}="${value}"]`);
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @param {Element} el
|
|
22
|
-
* @param {string} name
|
|
23
|
-
*/
|
|
24
|
-
export const get = (el, name) => el.getAttribute(attr(name));
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @param {Element} el
|
|
28
|
-
* @param {string} name
|
|
29
|
-
*/
|
|
30
|
-
export const has = (el, name) => el.hasAttribute(attr(name));
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Tether's attributes go on HTML elements, so matches are typed as such. An SVG element that carries one still has
|
|
34
|
-
* the `style`, `dataset` and attribute methods Tether uses.
|
|
35
|
-
*
|
|
36
|
-
* @param {ParentNode | null | undefined} root
|
|
37
|
-
* @param {string} selector
|
|
38
|
-
* @returns {HTMLElement[]} The matches in `root`, none without a root.
|
|
39
|
-
*/
|
|
40
|
-
export function qsa(root, selector) {
|
|
41
|
-
if (!root) return [];
|
|
42
|
-
return [.../** @type {NodeListOf<HTMLElement>} */ (root.querySelectorAll(selector))];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @param {Element | null | undefined} root
|
|
47
|
-
* @param {string} selector
|
|
48
|
-
* @param {string} scopeSelector
|
|
49
|
-
* @returns {HTMLElement[]} Matches in `root` whose nearest `scopeSelector` ancestor is `root` itself, not a nested
|
|
50
|
-
* scope.
|
|
51
|
-
*/
|
|
52
|
-
export const scoped = (root, selector, scopeSelector) =>
|
|
53
|
-
qsa(root, selector).filter((el) => el.closest(scopeSelector) === root);
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Dispatches the bubbling event `<prefix>:<name>`.
|
|
57
|
-
*
|
|
58
|
-
* @param {string} name
|
|
59
|
-
* @param {unknown} [detail]
|
|
60
|
-
* @param {EventTarget} [target]
|
|
61
|
-
*/
|
|
62
|
-
export function emit(name, detail, target = document) {
|
|
63
|
-
target.dispatchEvent(new CustomEvent(`${cfg.prefix}:${name}`, { detail, bubbles: true }));
|
|
64
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// The <script> build's tether.account-pages.js: registers the part where the core script's loader (lazy-iife.js) finds it.
|
|
2
|
-
import * as part from '../account-pages.js';
|
|
3
|
-
|
|
4
|
-
const { Tether } = /** @type {Window & { Tether?: { __parts: Record<string, unknown> } }} */ (window);
|
|
5
|
-
if (!Tether) throw new Error('tether.account-pages.js runs after the Tether script, which loads it');
|
|
6
|
-
Tether.__parts['account-pages'] = part;
|
package/src/parts/account.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// The <script> build's tether.account.js: registers the part where the core script's loader (lazy-iife.js) finds it.
|
|
2
|
-
import * as part from '../account.js';
|
|
3
|
-
|
|
4
|
-
const { Tether } = /** @type {Window & { Tether?: { __parts: Record<string, unknown> } }} */ (window);
|
|
5
|
-
if (!Tether) throw new Error('tether.account.js runs after the Tether script, which loads it');
|
|
6
|
-
Tether.__parts['account'] = part;
|
package/src/parts/analytics.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// The <script> build's tether.analytics.js: registers the part where the core script's loader (lazy-iife.js) finds it.
|
|
2
|
-
import * as part from '../analytics.js';
|
|
3
|
-
|
|
4
|
-
const { Tether } = /** @type {Window & { Tether?: { __parts: Record<string, unknown> } }} */ (window);
|
|
5
|
-
if (!Tether) throw new Error('tether.analytics.js runs after the Tether script, which loads it');
|
|
6
|
-
Tether.__parts['analytics'] = part;
|
package/src/parts/diagnose.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// The <script> build's tether.diagnose.js: registers the part where the core script's loader (lazy-iife.js) finds it.
|
|
2
|
-
import * as part from '../diagnose.js';
|
|
3
|
-
|
|
4
|
-
const { Tether } = /** @type {Window & { Tether?: { __parts: Record<string, unknown> } }} */ (window);
|
|
5
|
-
if (!Tether) throw new Error('tether.diagnose.js runs after the Tether script, which loads it');
|
|
6
|
-
Tether.__parts['diagnose'] = part;
|
package/src/parts/extras.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// The <script> build's tether.extras.js: registers the part where the core script's loader (lazy-iife.js) finds it.
|
|
2
|
-
import * as part from '../extras.js';
|
|
3
|
-
|
|
4
|
-
const { Tether } = /** @type {Window & { Tether?: { __parts: Record<string, unknown> } }} */ (window);
|
|
5
|
-
if (!Tether) throw new Error('tether.extras.js runs after the Tether script, which loads it');
|
|
6
|
-
Tether.__parts['extras'] = part;
|
package/src/parts/markets.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// The <script> build's tether.markets.js: registers the part where the core script's loader (lazy-iife.js) finds it.
|
|
2
|
-
import * as part from '../markets-ui.js';
|
|
3
|
-
|
|
4
|
-
const { Tether } = /** @type {Window & { Tether?: { __parts: Record<string, unknown> } }} */ (window);
|
|
5
|
-
if (!Tether) throw new Error('tether.markets.js runs after the Tether script, which loads it');
|
|
6
|
-
Tether.__parts['markets'] = part;
|
package/src/parts/search.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// The <script> build's tether.search.js: registers the part where the core script's loader (lazy-iife.js) finds it.
|
|
2
|
-
import * as part from '../search.js';
|
|
3
|
-
|
|
4
|
-
const { Tether } = /** @type {Window & { Tether?: { __parts: Record<string, unknown> } }} */ (window);
|
|
5
|
-
if (!Tether) throw new Error('tether.search.js runs after the Tether script, which loads it');
|
|
6
|
-
Tether.__parts['search'] = part;
|