@builder.io/sdk-svelte 5.2.16 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/lib/browser/blocks/symbol/symbol.helpers.d.ts +1 -0
- package/lib/browser/blocks/symbol/symbol.helpers.js +6 -0
- package/lib/browser/blocks/symbol/symbol.svelte +5 -1
- package/lib/browser/components/block/block.helpers.d.ts +1 -3
- package/lib/browser/components/block/block.helpers.js +31 -4
- package/lib/browser/components/block/block.svelte +14 -1
- package/lib/browser/components/builder-scripts.svelte +39 -0
- package/lib/browser/components/builder-scripts.svelte.d.ts +22 -0
- package/lib/browser/components/content/components/styles.helpers.d.ts +1 -1
- package/lib/browser/components/content/components/styles.helpers.js +1 -1
- package/lib/browser/components/content/content.helpers.d.ts +5 -1
- package/lib/browser/components/content/content.helpers.js +39 -2
- package/lib/browser/components/content/content.svelte +4 -17
- package/lib/browser/components/content-variants/content-variants.svelte +15 -8
- package/lib/browser/components/content-variants/content-variants.svelte.d.ts +5 -0
- package/lib/browser/components/content-variants/helpers.d.ts +6 -0
- package/lib/browser/components/content-variants/helpers.js +5 -0
- package/lib/browser/constants/builder-registered-components.d.ts +1 -0
- package/lib/browser/constants/builder-registered-components.js +40 -33
- package/lib/browser/constants/device-sizes.js +14 -2
- package/lib/browser/constants/sdk-version.d.ts +1 -1
- package/lib/browser/constants/sdk-version.js +1 -1
- package/lib/browser/context/builder-scripts.context.d.ts +7 -0
- package/lib/browser/context/builder-scripts.context.js +5 -0
- package/lib/browser/functions/evaluate/browser-runtime/browser.js +13 -1
- package/lib/browser/functions/evaluate/evaluate.js +21 -5
- package/lib/browser/functions/evaluate/node-runtime/node-runtime.js +114 -23
- package/lib/browser/functions/evaluate/safe-state-expression.d.ts +33 -0
- package/lib/browser/functions/evaluate/safe-state-expression.js +236 -0
- package/lib/browser/functions/evaluate/should-force-browser-runtime-in-node.js +3 -1
- package/lib/browser/functions/extract-localized-values.d.ts +4 -0
- package/lib/browser/functions/extract-localized-values.js +65 -26
- package/lib/browser/functions/get-block-properties.js +2 -1
- package/lib/browser/functions/get-processed-block.d.ts +0 -1
- package/lib/browser/functions/get-processed-block.js +45 -57
- package/lib/browser/functions/is-editing-or-previewing.d.ts +1 -0
- package/lib/browser/functions/is-editing-or-previewing.js +3 -0
- package/lib/browser/functions/set.d.ts +29 -1
- package/lib/browser/functions/set.js +85 -4
- package/lib/browser/helpers/bounded-cache.d.ts +4 -0
- package/lib/browser/helpers/bounded-cache.js +12 -0
- package/lib/browser/helpers/copy-plain-data.d.ts +6 -0
- package/lib/browser/helpers/copy-plain-data.js +40 -0
- package/lib/browser/index-helpers/blocks-exports.d.ts +1 -0
- package/lib/browser/index-helpers/blocks-exports.js +1 -0
- package/lib/edge/blocks/symbol/symbol.helpers.d.ts +1 -0
- package/lib/edge/blocks/symbol/symbol.helpers.js +6 -0
- package/lib/edge/blocks/symbol/symbol.svelte +5 -1
- package/lib/edge/components/block/block.helpers.d.ts +1 -3
- package/lib/edge/components/block/block.helpers.js +31 -4
- package/lib/edge/components/block/block.svelte +14 -1
- package/lib/edge/components/builder-scripts.svelte +39 -0
- package/lib/edge/components/builder-scripts.svelte.d.ts +22 -0
- package/lib/edge/components/content/components/styles.helpers.d.ts +1 -1
- package/lib/edge/components/content/components/styles.helpers.js +1 -1
- package/lib/edge/components/content/content.helpers.d.ts +5 -1
- package/lib/edge/components/content/content.helpers.js +39 -2
- package/lib/edge/components/content/content.svelte +4 -17
- package/lib/edge/components/content-variants/content-variants.svelte +15 -8
- package/lib/edge/components/content-variants/content-variants.svelte.d.ts +5 -0
- package/lib/edge/components/content-variants/helpers.d.ts +6 -0
- package/lib/edge/components/content-variants/helpers.js +5 -0
- package/lib/edge/constants/builder-registered-components.d.ts +1 -0
- package/lib/edge/constants/builder-registered-components.js +40 -33
- package/lib/edge/constants/device-sizes.js +14 -2
- package/lib/edge/constants/sdk-version.d.ts +1 -1
- package/lib/edge/constants/sdk-version.js +1 -1
- package/lib/edge/context/builder-scripts.context.d.ts +7 -0
- package/lib/edge/context/builder-scripts.context.js +5 -0
- package/lib/edge/functions/evaluate/browser-runtime/browser.js +13 -1
- package/lib/edge/functions/evaluate/evaluate.js +21 -5
- package/lib/edge/functions/evaluate/node-runtime/node-runtime.js +114 -23
- package/lib/edge/functions/evaluate/safe-state-expression.d.ts +33 -0
- package/lib/edge/functions/evaluate/safe-state-expression.js +236 -0
- package/lib/edge/functions/evaluate/should-force-browser-runtime-in-node.js +3 -1
- package/lib/edge/functions/extract-localized-values.d.ts +4 -0
- package/lib/edge/functions/extract-localized-values.js +65 -26
- package/lib/edge/functions/get-block-properties.js +2 -1
- package/lib/edge/functions/get-processed-block.d.ts +0 -1
- package/lib/edge/functions/get-processed-block.js +45 -57
- package/lib/edge/functions/is-editing-or-previewing.d.ts +1 -0
- package/lib/edge/functions/is-editing-or-previewing.js +3 -0
- package/lib/edge/functions/set.d.ts +29 -1
- package/lib/edge/functions/set.js +85 -4
- package/lib/edge/helpers/bounded-cache.d.ts +4 -0
- package/lib/edge/helpers/bounded-cache.js +12 -0
- package/lib/edge/helpers/copy-plain-data.d.ts +6 -0
- package/lib/edge/helpers/copy-plain-data.js +40 -0
- package/lib/edge/index-helpers/blocks-exports.d.ts +1 -0
- package/lib/edge/index-helpers/blocks-exports.js +1 -0
- package/lib/node/blocks/symbol/symbol.helpers.d.ts +1 -0
- package/lib/node/blocks/symbol/symbol.helpers.js +6 -0
- package/lib/node/blocks/symbol/symbol.svelte +5 -1
- package/lib/node/components/block/block.helpers.d.ts +1 -3
- package/lib/node/components/block/block.helpers.js +31 -4
- package/lib/node/components/block/block.svelte +14 -1
- package/lib/node/components/builder-scripts.svelte +39 -0
- package/lib/node/components/builder-scripts.svelte.d.ts +22 -0
- package/lib/node/components/content/components/styles.helpers.d.ts +1 -1
- package/lib/node/components/content/components/styles.helpers.js +1 -1
- package/lib/node/components/content/content.helpers.d.ts +5 -1
- package/lib/node/components/content/content.helpers.js +39 -2
- package/lib/node/components/content/content.svelte +4 -17
- package/lib/node/components/content-variants/content-variants.svelte +15 -8
- package/lib/node/components/content-variants/content-variants.svelte.d.ts +5 -0
- package/lib/node/components/content-variants/helpers.d.ts +6 -0
- package/lib/node/components/content-variants/helpers.js +5 -0
- package/lib/node/constants/builder-registered-components.d.ts +1 -0
- package/lib/node/constants/builder-registered-components.js +40 -33
- package/lib/node/constants/device-sizes.js +14 -2
- package/lib/node/constants/sdk-version.d.ts +1 -1
- package/lib/node/constants/sdk-version.js +1 -1
- package/lib/node/context/builder-scripts.context.d.ts +7 -0
- package/lib/node/context/builder-scripts.context.js +5 -0
- package/lib/node/functions/evaluate/browser-runtime/browser.js +13 -1
- package/lib/node/functions/evaluate/evaluate.js +21 -5
- package/lib/node/functions/evaluate/node-runtime/node-runtime.js +114 -23
- package/lib/node/functions/evaluate/safe-state-expression.d.ts +33 -0
- package/lib/node/functions/evaluate/safe-state-expression.js +236 -0
- package/lib/node/functions/evaluate/should-force-browser-runtime-in-node.js +3 -1
- package/lib/node/functions/extract-localized-values.d.ts +4 -0
- package/lib/node/functions/extract-localized-values.js +65 -26
- package/lib/node/functions/get-block-properties.js +2 -1
- package/lib/node/functions/get-processed-block.d.ts +0 -1
- package/lib/node/functions/get-processed-block.js +45 -57
- package/lib/node/functions/is-editing-or-previewing.d.ts +1 -0
- package/lib/node/functions/is-editing-or-previewing.js +3 -0
- package/lib/node/functions/set.d.ts +29 -1
- package/lib/node/functions/set.js +85 -4
- package/lib/node/helpers/bounded-cache.d.ts +4 -0
- package/lib/node/helpers/bounded-cache.js +12 -0
- package/lib/node/helpers/copy-plain-data.d.ts +6 -0
- package/lib/node/helpers/copy-plain-data.js +40 -0
- package/lib/node/index-helpers/blocks-exports.d.ts +1 -0
- package/lib/node/index-helpers/blocks-exports.js +1 -0
- package/package.json +1 -1
- package/src/blocks/symbol/symbol.helpers.ts +7 -0
- package/src/blocks/symbol/symbol.svelte +8 -1
- package/src/components/block/block.helpers.ts +38 -5
- package/src/components/block/block.svelte +14 -1
- package/src/components/builder-scripts.svelte +57 -0
- package/src/components/content/components/styles.helpers.ts +1 -1
- package/src/components/content/content.helpers.ts +45 -4
- package/src/components/content/content.svelte +7 -24
- package/src/components/content-variants/content-variants.svelte +21 -8
- package/src/components/content-variants/helpers.ts +6 -0
- package/src/constants/builder-registered-components.ts +40 -34
- package/src/constants/device-sizes.ts +14 -3
- package/src/constants/sdk-version.ts +1 -1
- package/src/context/builder-scripts.context.ts +6 -0
- package/src/functions/evaluate/browser-runtime/browser.ts +14 -1
- package/src/functions/evaluate/evaluate.ts +22 -5
- package/src/functions/evaluate/node-runtime/node-runtime.ts +116 -25
- package/src/functions/evaluate/safe-state-expression.ts +224 -0
- package/src/functions/evaluate/should-force-browser-runtime-in-node.ts +3 -1
- package/src/functions/extract-localized-values.ts +61 -27
- package/src/functions/get-block-properties.ts +5 -1
- package/src/functions/get-processed-block.ts +46 -57
- package/src/functions/is-editing-or-previewing.ts +3 -0
- package/src/functions/set.ts +89 -4
- package/src/helpers/bounded-cache.ts +12 -0
- package/src/helpers/copy-plain-data.ts +36 -0
- package/src/index-helpers/blocks-exports.ts +1 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const createBoundedCache = (max) => {
|
|
2
|
+
const map = new Map();
|
|
3
|
+
return {
|
|
4
|
+
get: (key) => map.get(key),
|
|
5
|
+
set: (key, value) => {
|
|
6
|
+
if (!map.has(key) && map.size >= max) {
|
|
7
|
+
map.delete(map.keys().next().value);
|
|
8
|
+
}
|
|
9
|
+
map.set(key, value);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-copies plain objects and arrays (anything else is kept by reference), so
|
|
3
|
+
* that state writes made while rendering never reach the content object, which
|
|
4
|
+
* apps often cache and share between requests.
|
|
5
|
+
*/
|
|
6
|
+
export declare const copyPlainData: <T>(value: T, seen?: WeakMap<object, any>) => T;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-copies plain objects and arrays (anything else is kept by reference), so
|
|
3
|
+
* that state writes made while rendering never reach the content object, which
|
|
4
|
+
* apps often cache and share between requests.
|
|
5
|
+
*/
|
|
6
|
+
export const copyPlainData = (value, seen = new WeakMap()) => {
|
|
7
|
+
if (value === null || typeof value !== 'object')
|
|
8
|
+
return value;
|
|
9
|
+
if (seen.has(value))
|
|
10
|
+
return seen.get(value);
|
|
11
|
+
if (Array.isArray(value)) {
|
|
12
|
+
const copy = [];
|
|
13
|
+
seen.set(value, copy);
|
|
14
|
+
for (let i = 0; i < value.length; i++) {
|
|
15
|
+
copy[i] = copyPlainData(value[i], seen);
|
|
16
|
+
}
|
|
17
|
+
return copy;
|
|
18
|
+
}
|
|
19
|
+
const proto = Object.getPrototypeOf(value);
|
|
20
|
+
if (proto !== Object.prototype && proto !== null)
|
|
21
|
+
return value;
|
|
22
|
+
const copy = {};
|
|
23
|
+
seen.set(value, copy);
|
|
24
|
+
for (const key of Object.keys(value)) {
|
|
25
|
+
const copied = copyPlainData(value[key], seen);
|
|
26
|
+
if (key === '__proto__') {
|
|
27
|
+
// Assigning would call the prototype setter; JSON can carry `__proto__` as an own key.
|
|
28
|
+
Object.defineProperty(copy, key, {
|
|
29
|
+
value: copied,
|
|
30
|
+
enumerable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
configurable: true
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
copy[key] = copied;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return copy;
|
|
40
|
+
};
|
|
@@ -7,6 +7,7 @@ export { default as Symbol } from '../blocks/symbol/index';
|
|
|
7
7
|
export { default as Text } from '../blocks/text/index';
|
|
8
8
|
export { default as Video } from '../blocks/video/index';
|
|
9
9
|
export { default as Blocks } from '../components/blocks/index';
|
|
10
|
+
export { default as BuilderScripts } from '../components/builder-scripts.svelte';
|
|
10
11
|
export { default as Content } from '../components/content-variants/index';
|
|
11
12
|
/**
|
|
12
13
|
* Builder Context
|
|
@@ -7,6 +7,7 @@ export { default as Symbol } from '../blocks/symbol/index';
|
|
|
7
7
|
export { default as Text } from '../blocks/text/index';
|
|
8
8
|
export { default as Video } from '../blocks/video/index';
|
|
9
9
|
export { default as Blocks } from '../components/blocks/index';
|
|
10
|
+
export { default as BuilderScripts } from '../components/builder-scripts.svelte';
|
|
10
11
|
export { default as Content } from '../components/content-variants/index';
|
|
11
12
|
/**
|
|
12
13
|
* Builder Context
|
package/package.json
CHANGED
|
@@ -12,6 +12,13 @@ export interface SymbolInfo {
|
|
|
12
12
|
ownerId?: string;
|
|
13
13
|
global?: boolean;
|
|
14
14
|
}
|
|
15
|
+
const isSymbolContentBinding = (key: string) => {
|
|
16
|
+
const path = key.startsWith('component.') ? key.slice(10) : key;
|
|
17
|
+
return path === 'options.symbol' || path === 'options.symbol.content' || path.startsWith('options.symbol.content.');
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Bound symbol content is evaluated at render time, so it is not in the parent content JSON.
|
|
21
|
+
export const isSymbolContentInlinedInParent = (symbol: SymbolInfo | undefined, bindings: Record<string, string> | undefined) => !!symbol?.content && !Object.keys(bindings || {}).some(isSymbolContentBinding);
|
|
15
22
|
export const fetchSymbolContent = async ({
|
|
16
23
|
builderContextValue,
|
|
17
24
|
symbol
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
import { getClassPropName } from "../../functions/get-class-prop-name";
|
|
9
9
|
import type { Nullable } from "../../types/typescript";
|
|
10
10
|
import { setAttrs } from "../helpers";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
fetchSymbolContent,
|
|
13
|
+
isSymbolContentInlinedInParent,
|
|
14
|
+
} from "./symbol.helpers";
|
|
12
15
|
import type { SymbolProps } from "./symbol.types";
|
|
13
16
|
|
|
14
17
|
export let symbol: SymbolProps["symbol"] = undefined;
|
|
@@ -75,6 +78,10 @@
|
|
|
75
78
|
<ContentVariants
|
|
76
79
|
nonce={$builderContext.nonce}
|
|
77
80
|
isNestedRender={true}
|
|
81
|
+
isContentInlinedInParent={isSymbolContentInlinedInParent(
|
|
82
|
+
symbol,
|
|
83
|
+
builderBlock?.bindings
|
|
84
|
+
)}
|
|
78
85
|
apiVersion={$builderContext.apiVersion}
|
|
79
86
|
apiKey={symbol?.global && symbol?.ownerId
|
|
80
87
|
? symbol.ownerId
|
|
@@ -3,6 +3,7 @@ import type { BuilderContextInterface, RegisteredComponent, RegisteredComponents
|
|
|
3
3
|
import { evaluate } from '../../functions/evaluate/index';
|
|
4
4
|
import { extractTextStyles } from '../../functions/extract-text-styles';
|
|
5
5
|
import { getStyle } from '../../functions/get-style';
|
|
6
|
+
import { isEditingOrPreviewing } from '../../functions/is-editing-or-previewing';
|
|
6
7
|
import type { BuilderBlock } from '../../types/builder-block';
|
|
7
8
|
import type { RepeatData } from './types';
|
|
8
9
|
const checkIsComponentRestricted = (component: RegisteredComponent | null | undefined, model: string) => {
|
|
@@ -34,6 +35,28 @@ export const getComponent = ({
|
|
|
34
35
|
return ref;
|
|
35
36
|
}
|
|
36
37
|
};
|
|
38
|
+
|
|
39
|
+
// Reused per block so repeated items keep a stable block identity across renders.
|
|
40
|
+
const BLOCKS_WITHOUT_REPEAT = new WeakMap<BuilderBlock, BuilderBlock>();
|
|
41
|
+
const getBlockWithoutRepeat = (block: BuilderBlock) => {
|
|
42
|
+
if (isEditingOrPreviewing()) {
|
|
43
|
+
const {
|
|
44
|
+
repeat: _repeat,
|
|
45
|
+
...rest
|
|
46
|
+
} = block;
|
|
47
|
+
return rest;
|
|
48
|
+
}
|
|
49
|
+
let blockWithoutRepeat = BLOCKS_WITHOUT_REPEAT.get(block);
|
|
50
|
+
if (!blockWithoutRepeat) {
|
|
51
|
+
const {
|
|
52
|
+
repeat: _repeat,
|
|
53
|
+
...rest
|
|
54
|
+
} = block;
|
|
55
|
+
blockWithoutRepeat = rest;
|
|
56
|
+
BLOCKS_WITHOUT_REPEAT.set(block, blockWithoutRepeat);
|
|
57
|
+
}
|
|
58
|
+
return blockWithoutRepeat;
|
|
59
|
+
};
|
|
37
60
|
export const getRepeatItemData = ({
|
|
38
61
|
block,
|
|
39
62
|
context
|
|
@@ -46,8 +69,7 @@ export const getRepeatItemData = ({
|
|
|
46
69
|
* which will not work if there is a repeat.
|
|
47
70
|
*/
|
|
48
71
|
const {
|
|
49
|
-
repeat
|
|
50
|
-
...blockWithoutRepeat
|
|
72
|
+
repeat
|
|
51
73
|
} = block;
|
|
52
74
|
if (!repeat?.collection) {
|
|
53
75
|
return undefined;
|
|
@@ -64,6 +86,7 @@ export const getRepeatItemData = ({
|
|
|
64
86
|
}
|
|
65
87
|
const collectionName = repeat.collection.split('.').pop();
|
|
66
88
|
const itemNameToUse = repeat.itemName || (collectionName ? collectionName + 'Item' : 'item');
|
|
89
|
+
const blockWithoutRepeat = getBlockWithoutRepeat(block);
|
|
67
90
|
const repeatArray = itemsArray.map<RepeatData>((item, index) => ({
|
|
68
91
|
context: {
|
|
69
92
|
...context,
|
|
@@ -101,11 +124,21 @@ export const provideLinkComponent = (block: RegisteredComponent | null | undefin
|
|
|
101
124
|
};
|
|
102
125
|
return {};
|
|
103
126
|
};
|
|
127
|
+
const FILTERED_REGISTERED_COMPONENTS = new WeakMap<RegisteredComponents, Map<string, RegisteredComponents>>();
|
|
104
128
|
export const provideRegisteredComponents = (block: RegisteredComponent | null | undefined, registeredComponents: RegisteredComponents, model: string) => {
|
|
105
129
|
if (block?.shouldReceiveBuilderProps?.builderComponents) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
130
|
+
let byModel = FILTERED_REGISTERED_COMPONENTS.get(registeredComponents);
|
|
131
|
+
if (!byModel) {
|
|
132
|
+
byModel = new Map();
|
|
133
|
+
FILTERED_REGISTERED_COMPONENTS.set(registeredComponents, byModel);
|
|
134
|
+
}
|
|
135
|
+
let filteredRegisteredComponents = byModel.get(model);
|
|
136
|
+
if (!filteredRegisteredComponents) {
|
|
137
|
+
filteredRegisteredComponents = Object.fromEntries(Object.entries(registeredComponents).filter(([_, component]) => {
|
|
138
|
+
return !checkIsComponentRestricted(component, model);
|
|
139
|
+
}));
|
|
140
|
+
byModel.set(model, filteredRegisteredComponents);
|
|
141
|
+
}
|
|
109
142
|
return {
|
|
110
143
|
builderComponents: filteredRegisteredComponents
|
|
111
144
|
};
|
|
@@ -103,7 +103,15 @@
|
|
|
103
103
|
: [];
|
|
104
104
|
};
|
|
105
105
|
$: componentRefProps = () => {
|
|
106
|
-
|
|
106
|
+
const deps: unknown[] = [
|
|
107
|
+
processedBlock(),
|
|
108
|
+
$context,
|
|
109
|
+
$context.rootState,
|
|
110
|
+
$context.localState,
|
|
111
|
+
registeredComponents,
|
|
112
|
+
linkComponent,
|
|
113
|
+
];
|
|
114
|
+
const componentRefProps: ComponentProps = {
|
|
107
115
|
blockChildren: processedBlock().children ?? [],
|
|
108
116
|
componentRef: blockComponent?.()?.component,
|
|
109
117
|
componentOptions: {
|
|
@@ -124,12 +132,17 @@
|
|
|
124
132
|
includeBlockProps: blockComponent?.()?.noWrap === true,
|
|
125
133
|
isInteractive: !(blockComponent?.()?.isRSC && TARGET === "rsc"),
|
|
126
134
|
};
|
|
135
|
+
return componentRefProps;
|
|
127
136
|
};
|
|
128
137
|
|
|
129
138
|
let _processedBlock = {
|
|
130
139
|
value: null as BuilderBlock | null,
|
|
131
140
|
update: false,
|
|
132
141
|
};
|
|
142
|
+
let _componentRefProps = {
|
|
143
|
+
value: null as ComponentProps | null,
|
|
144
|
+
deps: [] as unknown[],
|
|
145
|
+
};
|
|
133
146
|
|
|
134
147
|
onMount(() => {
|
|
135
148
|
const blockId = processedBlock().id;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script context="module" lang="ts">
|
|
2
|
+
type BuilderScriptsProps = {
|
|
3
|
+
nonce?: string;
|
|
4
|
+
children?: any;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Emits the Variant Container and A/B test helper scripts once for all `Content` components inside it.
|
|
9
|
+
*/
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<script lang="ts">
|
|
13
|
+
import { getContext, setContext } from "svelte";
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
getInitPersonalizationVariantsFnsScriptString,
|
|
17
|
+
SDKS_SUPPORTING_PERSONALIZATION,
|
|
18
|
+
} from "../blocks/personalization-container/helpers";
|
|
19
|
+
import { TARGET } from "../constants/target";
|
|
20
|
+
import BuilderScriptsContext from "../context/builder-scripts.context";
|
|
21
|
+
import { isBrowser } from "../functions/is-browser";
|
|
22
|
+
import {
|
|
23
|
+
getInitVariantsFnsScriptString,
|
|
24
|
+
SDKS_SUPPORTING_BUILDER_SCRIPTS,
|
|
25
|
+
} from "./content-variants/helpers";
|
|
26
|
+
import InlinedScript from "./inlined-script.svelte";
|
|
27
|
+
|
|
28
|
+
export let nonce: BuilderScriptsProps["nonce"] = undefined;
|
|
29
|
+
|
|
30
|
+
let parentScriptsContext = getContext(BuilderScriptsContext.key);
|
|
31
|
+
|
|
32
|
+
let isSupported = SDKS_SUPPORTING_BUILDER_SCRIPTS.includes(TARGET);
|
|
33
|
+
let shouldRenderAbTestFns = TARGET !== "react" || !isBrowser();
|
|
34
|
+
|
|
35
|
+
setContext(BuilderScriptsContext.key, {
|
|
36
|
+
scriptsEmitted: isSupported,
|
|
37
|
+
});
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
{#if isSupported && !parentScriptsContext?.scriptsEmitted}
|
|
41
|
+
{#if SDKS_SUPPORTING_PERSONALIZATION.includes(TARGET)}
|
|
42
|
+
<InlinedScript
|
|
43
|
+
id="builderio-init-personalization-variants-fns"
|
|
44
|
+
nonce={nonce || ""}
|
|
45
|
+
scriptStr={getInitPersonalizationVariantsFnsScriptString()}
|
|
46
|
+
/>
|
|
47
|
+
{/if}
|
|
48
|
+
|
|
49
|
+
{#if shouldRenderAbTestFns}
|
|
50
|
+
<InlinedScript
|
|
51
|
+
id="builderio-init-variants-fns"
|
|
52
|
+
nonce={nonce || ""}
|
|
53
|
+
scriptStr={getInitVariantsFnsScriptString()}
|
|
54
|
+
/>
|
|
55
|
+
{/if}
|
|
56
|
+
{/if}
|
|
57
|
+
<slot />
|
|
@@ -1,19 +1,60 @@
|
|
|
1
|
-
import type { BuilderRenderState } from '../../context/types';
|
|
1
|
+
import type { BuilderRenderState, RegisteredComponent, RegisteredComponents } from '../../context/types';
|
|
2
|
+
import { serializeIncludingFunctions } from '../../functions/register-component';
|
|
3
|
+
import { copyPlainData } from '../../helpers/copy-plain-data';
|
|
2
4
|
import type { BuilderContent } from '../../types/builder-content';
|
|
3
|
-
import type {
|
|
5
|
+
import type { ComponentInfo } from '../../types/components';
|
|
6
|
+
import type { Dictionary, Nullable } from '../../types/typescript';
|
|
4
7
|
import type { ContentProps } from './content.types';
|
|
8
|
+
|
|
9
|
+
// Registrations are usually module constants, so their derived forms are built once per object.
|
|
10
|
+
const SERIALIZED_COMPONENT_INFOS = new WeakMap<object, ComponentInfo>();
|
|
11
|
+
const REGISTERED_COMPONENT_ENTRIES = new WeakMap<object, RegisteredComponent>();
|
|
12
|
+
const getSerializedComponentInfo = (registration: RegisteredComponent): ComponentInfo => {
|
|
13
|
+
const cached = SERIALIZED_COMPONENT_INFOS.get(registration);
|
|
14
|
+
if (cached) return cached;
|
|
15
|
+
const {
|
|
16
|
+
component: _,
|
|
17
|
+
...rest
|
|
18
|
+
} = registration;
|
|
19
|
+
const info: ComponentInfo = serializeIncludingFunctions((rest as ComponentInfo));
|
|
20
|
+
SERIALIZED_COMPONENT_INFOS.set(registration, info);
|
|
21
|
+
return info;
|
|
22
|
+
};
|
|
23
|
+
export const getRegisteredComponents = (registrations: RegisteredComponent[], wrapComponent: (component: any) => any): RegisteredComponents => {
|
|
24
|
+
const registeredComponents: RegisteredComponents = {};
|
|
25
|
+
for (const registration of registrations) {
|
|
26
|
+
let entry = REGISTERED_COMPONENT_ENTRIES.get(registration);
|
|
27
|
+
if (!entry) {
|
|
28
|
+
entry = ({
|
|
29
|
+
component: wrapComponent(registration.component),
|
|
30
|
+
...getSerializedComponentInfo(registration)
|
|
31
|
+
} as RegisteredComponent);
|
|
32
|
+
REGISTERED_COMPONENT_ENTRIES.set(registration, entry);
|
|
33
|
+
}
|
|
34
|
+
registeredComponents[registration.name] = entry;
|
|
35
|
+
}
|
|
36
|
+
return registeredComponents;
|
|
37
|
+
};
|
|
38
|
+
export const getComponentInfos = (registrations: RegisteredComponent[]): Dictionary<ComponentInfo> => {
|
|
39
|
+
const componentInfos: Dictionary<ComponentInfo> = {};
|
|
40
|
+
for (const registration of registrations) {
|
|
41
|
+
componentInfos[registration.name] = getSerializedComponentInfo(registration);
|
|
42
|
+
}
|
|
43
|
+
return componentInfos;
|
|
44
|
+
};
|
|
5
45
|
export const getRootStateInitialValue = ({
|
|
6
46
|
content,
|
|
7
47
|
data,
|
|
8
48
|
locale
|
|
9
49
|
}: Pick<ContentProps, 'content' | 'data' | 'locale'>) => {
|
|
10
50
|
const defaultValues: BuilderRenderState = {};
|
|
11
|
-
const
|
|
51
|
+
const seen = new WeakMap<object, any>();
|
|
52
|
+
const initialState = copyPlainData(content?.data?.state || {}, seen);
|
|
12
53
|
|
|
13
54
|
// set default values for content state inputs
|
|
14
55
|
content?.data?.inputs?.forEach(input => {
|
|
15
56
|
if (input.name && input.defaultValue !== undefined) {
|
|
16
|
-
defaultValues[input.name] = input.defaultValue;
|
|
57
|
+
defaultValues[input.name] = copyPlainData(input.defaultValue, seen);
|
|
17
58
|
}
|
|
18
59
|
});
|
|
19
60
|
return {
|
|
@@ -8,13 +8,9 @@
|
|
|
8
8
|
import type {
|
|
9
9
|
BuilderContextInterface,
|
|
10
10
|
BuilderRenderState,
|
|
11
|
-
RegisteredComponents,
|
|
12
11
|
} from "../../context/types";
|
|
13
12
|
import { evaluate } from "../../functions/evaluate/evaluate";
|
|
14
|
-
import { serializeIncludingFunctions } from "../../functions/register-component";
|
|
15
13
|
import { logger } from "../../helpers/logger";
|
|
16
|
-
import type { ComponentInfo } from "../../types/components";
|
|
17
|
-
import type { Dictionary } from "../../types/typescript";
|
|
18
14
|
import Blocks from "../blocks/blocks.svelte";
|
|
19
15
|
import { getUpdateVariantVisibilityScript } from "../content-variants/helpers";
|
|
20
16
|
import DynamicDiv from "../dynamic-div.svelte";
|
|
@@ -22,7 +18,9 @@
|
|
|
22
18
|
import EnableEditor from "./components/enable-editor.svelte";
|
|
23
19
|
import ContentStyles from "./components/styles.svelte";
|
|
24
20
|
import {
|
|
21
|
+
getComponentInfos,
|
|
25
22
|
getContentInitialValue,
|
|
23
|
+
getRegisteredComponents,
|
|
26
24
|
getRootStateInitialValue,
|
|
27
25
|
} from "./content.helpers";
|
|
28
26
|
import type { ContentProps } from "./content.types";
|
|
@@ -62,18 +60,9 @@
|
|
|
62
60
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
|
|
63
61
|
contentId: content?.id!,
|
|
64
62
|
});
|
|
65
|
-
let registeredComponents =
|
|
66
|
-
...getDefaultRegisteredComponents(),
|
|
67
|
-
|
|
68
|
-
].reduce<RegisteredComponents>(
|
|
69
|
-
(acc, { component, ...info }) => ({
|
|
70
|
-
...acc,
|
|
71
|
-
[info.name]: {
|
|
72
|
-
component: component,
|
|
73
|
-
...serializeIncludingFunctions(info),
|
|
74
|
-
},
|
|
75
|
-
}),
|
|
76
|
-
{}
|
|
63
|
+
let registeredComponents = getRegisteredComponents(
|
|
64
|
+
[...getDefaultRegisteredComponents(), ...(customComponents || [])],
|
|
65
|
+
(component) => component
|
|
77
66
|
);
|
|
78
67
|
let builderContextSignal = writable({
|
|
79
68
|
content: getContentInitialValue({
|
|
@@ -91,16 +80,10 @@
|
|
|
91
80
|
canTrack: canTrack,
|
|
92
81
|
apiKey: apiKey,
|
|
93
82
|
apiVersion: apiVersion,
|
|
94
|
-
componentInfos: [
|
|
83
|
+
componentInfos: getComponentInfos([
|
|
95
84
|
...getDefaultRegisteredComponents(),
|
|
96
85
|
...(customComponents || []),
|
|
97
|
-
]
|
|
98
|
-
(acc, { component: _, ...info }) => ({
|
|
99
|
-
...acc,
|
|
100
|
-
[info.name]: serializeIncludingFunctions(info),
|
|
101
|
-
}),
|
|
102
|
-
{}
|
|
103
|
-
),
|
|
86
|
+
]),
|
|
104
87
|
inheritedStyles: {},
|
|
105
88
|
BlocksWrapper: blocksWrapper || "div",
|
|
106
89
|
BlocksWrapperProps: blocksWrapperProps || {},
|
|
@@ -4,11 +4,15 @@
|
|
|
4
4
|
* For internal use only. Do not provide this prop.
|
|
5
5
|
*/
|
|
6
6
|
isNestedRender?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* For internal use only. Do not provide this prop.
|
|
9
|
+
*/
|
|
10
|
+
isContentInlinedInParent?: boolean;
|
|
7
11
|
};
|
|
8
12
|
</script>
|
|
9
13
|
|
|
10
14
|
<script lang="ts">
|
|
11
|
-
import { onMount } from "svelte";
|
|
15
|
+
import { getContext, onMount } from "svelte";
|
|
12
16
|
|
|
13
17
|
import {
|
|
14
18
|
SDKS_SUPPORTING_PERSONALIZATION,
|
|
@@ -16,6 +20,7 @@
|
|
|
16
20
|
hasPersonalizationContainer,
|
|
17
21
|
} from "../../blocks/personalization-container/helpers";
|
|
18
22
|
import { TARGET } from "../../constants/target";
|
|
23
|
+
import BuilderScriptsContext from "../../context/builder-scripts.context";
|
|
19
24
|
import { handleABTestingSync } from "../../helpers/ab-tests";
|
|
20
25
|
import { getDefaultCanTrack } from "../../helpers/canTrack";
|
|
21
26
|
import ContentComponent from "../content/content.svelte";
|
|
@@ -31,6 +36,8 @@
|
|
|
31
36
|
|
|
32
37
|
export let canTrack: VariantsProviderProps["canTrack"] = undefined;
|
|
33
38
|
export let content: VariantsProviderProps["content"];
|
|
39
|
+
export let isContentInlinedInParent: VariantsProviderProps["isContentInlinedInParent"] =
|
|
40
|
+
undefined;
|
|
34
41
|
export let nonce: VariantsProviderProps["nonce"] = undefined;
|
|
35
42
|
export let apiHost: VariantsProviderProps["apiHost"] = undefined;
|
|
36
43
|
export let isNestedRender: VariantsProviderProps["isNestedRender"] =
|
|
@@ -55,6 +62,8 @@
|
|
|
55
62
|
undefined;
|
|
56
63
|
export let trustedHosts: VariantsProviderProps["trustedHosts"] = undefined;
|
|
57
64
|
|
|
65
|
+
let scriptsContext = getContext(BuilderScriptsContext.key);
|
|
66
|
+
|
|
58
67
|
$: updateCookieAndStylesScriptStr = () => {
|
|
59
68
|
return getUpdateCookieAndStylesScript(
|
|
60
69
|
getVariants(content).map((value) => ({
|
|
@@ -86,7 +95,9 @@
|
|
|
86
95
|
content: content,
|
|
87
96
|
});
|
|
88
97
|
let shouldEmitPersonalizationFns =
|
|
89
|
-
TARGET !== "reactNative" &&
|
|
98
|
+
TARGET !== "reactNative" &&
|
|
99
|
+
!isContentInlinedInParent &&
|
|
100
|
+
hasPersonalizationContainer(content);
|
|
90
101
|
|
|
91
102
|
onMount(() => {
|
|
92
103
|
/**
|
|
@@ -96,7 +107,7 @@
|
|
|
96
107
|
});
|
|
97
108
|
</script>
|
|
98
109
|
|
|
99
|
-
{#if shouldEmitPersonalizationFns}
|
|
110
|
+
{#if shouldEmitPersonalizationFns && !!!scriptsContext?.scriptsEmitted}
|
|
100
111
|
{#if SDKS_SUPPORTING_PERSONALIZATION.includes(TARGET)}
|
|
101
112
|
<InlinedScript
|
|
102
113
|
id="builderio-init-personalization-variants-fns"
|
|
@@ -107,11 +118,13 @@
|
|
|
107
118
|
{/if}
|
|
108
119
|
|
|
109
120
|
{#if shouldRenderVariants}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
121
|
+
{#if !!!scriptsContext?.scriptsEmitted}
|
|
122
|
+
<InlinedScript
|
|
123
|
+
id="builderio-init-variants-fns"
|
|
124
|
+
scriptStr={getInitVariantsFnsScriptString()}
|
|
125
|
+
nonce={nonce || ""}
|
|
126
|
+
/>
|
|
127
|
+
{/if}
|
|
115
128
|
<InlinedStyles
|
|
116
129
|
id="builderio-variants"
|
|
117
130
|
styles={hideVariantsStyleString()}
|
|
@@ -13,6 +13,12 @@ import { UPDATE_COOKIES_AND_STYLES_SCRIPT, UPDATE_VARIANT_VISIBILITY_SCRIPT } fr
|
|
|
13
13
|
*/
|
|
14
14
|
const UPDATE_COOKIES_AND_STYLES_SCRIPT_NAME = 'builderIoAbTest';
|
|
15
15
|
const UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME = 'builderIoRenderContent';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* SDKs where `BuilderScripts` can dedupe helper scripts. Elsewhere `Content` cannot read its context
|
|
19
|
+
* (RSC server components, Angular DI) or has no inline scripts (React Native).
|
|
20
|
+
*/
|
|
21
|
+
export const SDKS_SUPPORTING_BUILDER_SCRIPTS = (['react', 'vue', 'svelte', 'solid', 'qwik'] as Target[]);
|
|
16
22
|
export const getVariants = (content: Nullable<BuilderContent>) => Object.values(content?.variations || {}).map(variant => ({
|
|
17
23
|
...variant,
|
|
18
24
|
testVariationId: variant.id,
|
|
@@ -24,42 +24,48 @@ import { default as Text } from '../blocks/text/index';
|
|
|
24
24
|
import type { RegisteredComponent } from '../context/types';
|
|
25
25
|
import { getExtraComponents } from './extra-components';
|
|
26
26
|
import { TARGET } from './target';
|
|
27
|
+
let DEFAULT_REGISTERED_COMPONENTS: RegisteredComponent[] | undefined;
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Returns a list of all registered components.
|
|
30
31
|
* NOTE: This needs to be a function to work around ESM circular dependencies.
|
|
32
|
+
* The list is built once, on first use, so its entries keep a stable identity.
|
|
31
33
|
*/
|
|
32
|
-
export const getDefaultRegisteredComponents: () => RegisteredComponent[] = () =>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
...
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
...
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
34
|
+
export const getDefaultRegisteredComponents: () => RegisteredComponent[] = () => {
|
|
35
|
+
if (DEFAULT_REGISTERED_COMPONENTS) return DEFAULT_REGISTERED_COMPONENTS;
|
|
36
|
+
DEFAULT_REGISTERED_COMPONENTS = [{
|
|
37
|
+
component: Button,
|
|
38
|
+
...buttonComponentInfo
|
|
39
|
+
}, {
|
|
40
|
+
component: Columns,
|
|
41
|
+
...columnsComponentInfo
|
|
42
|
+
}, {
|
|
43
|
+
component: Fragment,
|
|
44
|
+
...fragmentComponentInfo
|
|
45
|
+
}, {
|
|
46
|
+
component: Image,
|
|
47
|
+
...imageComponentInfo
|
|
48
|
+
}, {
|
|
49
|
+
component: Section,
|
|
50
|
+
...sectionComponentInfo
|
|
51
|
+
}, {
|
|
52
|
+
component: Slot,
|
|
53
|
+
...slotComponentInfo
|
|
54
|
+
}, {
|
|
55
|
+
component: Symbol,
|
|
56
|
+
...symbolComponentInfo
|
|
57
|
+
}, {
|
|
58
|
+
component: Text,
|
|
59
|
+
...textComponentInfo
|
|
60
|
+
}, ...(SDKS_SUPPORTING_PERSONALIZATION.includes(TARGET) ? [{
|
|
61
|
+
component: PersonalizationContainer,
|
|
62
|
+
...personalizationContainerComponentInfo
|
|
63
|
+
}] : []), ...(TARGET === 'rsc' ? [] : [{
|
|
64
|
+
component: Tabs,
|
|
65
|
+
...tabsComponentInfo
|
|
66
|
+
}, {
|
|
67
|
+
component: Accordion,
|
|
68
|
+
...accordionComponentInfo
|
|
69
|
+
}]), ...getExtraComponents()];
|
|
70
|
+
return DEFAULT_REGISTERED_COMPONENTS;
|
|
71
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { fastClone } from '../functions/fast-clone';
|
|
2
1
|
export type SizeName = 'large' | 'medium' | 'small' | 'xsmall';
|
|
3
2
|
interface Size {
|
|
4
3
|
min: number;
|
|
@@ -34,8 +33,20 @@ interface Breakpoints {
|
|
|
34
33
|
medium?: number;
|
|
35
34
|
}
|
|
36
35
|
export const getSizesForBreakpoints = (breakpoints: Breakpoints) => {
|
|
37
|
-
const newSizes
|
|
38
|
-
|
|
36
|
+
const newSizes: Record<SizeName, Size> = {
|
|
37
|
+
xsmall: {
|
|
38
|
+
...SIZES.xsmall
|
|
39
|
+
},
|
|
40
|
+
small: {
|
|
41
|
+
...SIZES.small
|
|
42
|
+
},
|
|
43
|
+
medium: {
|
|
44
|
+
...SIZES.medium
|
|
45
|
+
},
|
|
46
|
+
large: {
|
|
47
|
+
...SIZES.large
|
|
48
|
+
}
|
|
49
|
+
};
|
|
39
50
|
if (!breakpoints) {
|
|
40
51
|
return newSizes;
|
|
41
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = "5.
|
|
1
|
+
export const SDK_VERSION = "5.4.0"
|