@builder.io/sdk-svelte 0.3.1 → 0.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/package/--package.json +8 -5
- package/package/CHANGELOG.md +13 -0
- package/package/components/render-block/render-block.svelte +6 -6
- package/package/components/render-content/components/render-styles.svelte +1 -1
- package/package/components/render-content/render-content.svelte +84 -2
- package/package/components/render-content/render-content.svelte.d.ts +5 -0
- package/package/components/render-content/render-content.types.d.ts +11 -2
- package/package/components/render-content/wrap-component-ref.d.ts +6 -0
- package/package/components/render-content/wrap-component-ref.js +6 -0
- package/package/components/render-content-variants/helpers.d.ts +17 -0
- package/package/components/render-content-variants/helpers.js +182 -0
- package/package/components/render-content-variants/render-content-variants.svelte +70 -0
- package/package/components/render-content-variants/render-content-variants.svelte.d.ts +23 -0
- package/package/components/render-inlined-styles.svelte +3 -15
- package/package/components/render-inlined-styles.svelte.d.ts +2 -0
- package/package/constants/sdk-version.d.ts +1 -1
- package/package/constants/sdk-version.js +1 -1
- package/package/functions/get-content/generate-content-url.js +2 -2
- package/package/functions/get-content/generate-content-url.test.js +15 -0
- package/package/functions/get-content/index.d.ts +7 -2
- package/package/functions/get-content/index.js +43 -20
- package/package/functions/get-content/types.d.ts +6 -0
- package/package/helpers/ab-tests.d.ts +8 -7
- package/package/helpers/ab-tests.js +103 -4
- package/package/helpers/canTrack.d.ts +1 -0
- package/package/helpers/canTrack.js +2 -0
- package/package/helpers/cookie.d.ts +7 -3
- package/package/helpers/cookie.js +9 -6
- package/package/helpers/logger.d.ts +1 -0
- package/package/helpers/logger.js +1 -0
- package/package/index-helpers/blocks-exports.d.ts +1 -1
- package/package/index-helpers/blocks-exports.js +1 -1
- package/package/index.d.ts +8 -7
- package/package/index.js +6 -7
- package/package/scripts/init-editing.d.ts +1 -0
- package/package/types/builder-content.d.ts +1 -3
- package/package.json +4 -5
- package/src/components/render-block/render-block.svelte +6 -6
- package/src/components/render-content/components/render-styles.svelte +1 -1
- package/src/components/render-content/render-content.svelte +86 -2
- package/src/components/render-content/render-content.types.ts +11 -2
- package/src/components/render-content/wrap-component-ref.ts +6 -0
- package/src/components/render-content-variants/helpers.ts +245 -0
- package/src/components/render-content-variants/render-content-variants.svelte +83 -0
- package/src/components/render-inlined-styles.svelte +3 -16
- package/src/constants/sdk-version.ts +1 -1
- package/src/functions/get-content/generate-content-url.test.ts +17 -0
- package/src/functions/get-content/generate-content-url.ts +2 -1
- package/src/functions/get-content/index.ts +57 -26
- package/src/functions/get-content/types.ts +7 -0
- package/src/helpers/ab-tests.ts +164 -11
- package/src/helpers/canTrack.ts +4 -0
- package/src/helpers/cookie.ts +16 -11
- package/src/helpers/logger.ts +1 -0
- package/src/index-helpers/blocks-exports.ts +1 -1
- package/src/index.ts +17 -8
- package/src/scripts/init-editing.ts +1 -0
- package/src/types/builder-content.ts +1 -3
- package/package/functions/get-content/ab-testing.d.ts +0 -5
- package/package/functions/get-content/ab-testing.js +0 -78
- package/src/functions/get-content/ab-testing.ts +0 -132
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import type { BuilderContent } from '../../types/builder-content.js';
|
|
2
2
|
import type { GetContentOptions } from './types.js';
|
|
3
3
|
export declare function getContent(options: GetContentOptions): Promise<BuilderContent | null>;
|
|
4
|
-
type
|
|
4
|
+
type ContentResults = {
|
|
5
5
|
results: BuilderContent[];
|
|
6
|
-
}
|
|
6
|
+
};
|
|
7
|
+
type ContentResponse = ContentResults | {
|
|
7
8
|
status: number;
|
|
8
9
|
message: string;
|
|
9
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Exported only for testing purposes. Should not be used directly.
|
|
13
|
+
*/
|
|
14
|
+
export declare const processContentResult: (options: GetContentOptions, content: ContentResults) => Promise<ContentResults>;
|
|
10
15
|
export declare function getAllContent(options: GetContentOptions): Promise<ContentResponse | null>;
|
|
11
16
|
export {};
|
|
@@ -1,37 +1,60 @@
|
|
|
1
|
+
import { TARGET } from '../../constants/target.js';
|
|
2
|
+
import { handleABTesting } from '../../helpers/ab-tests.js';
|
|
3
|
+
import { getDefaultCanTrack } from '../../helpers/canTrack.js';
|
|
1
4
|
import { logger } from '../../helpers/logger.js';
|
|
2
5
|
import { fetch } from '../get-fetch.js';
|
|
3
|
-
import {
|
|
6
|
+
import { isBrowser } from '../is-browser.js';
|
|
4
7
|
import { generateContentUrl } from './generate-content-url.js';
|
|
8
|
+
const checkContentHasResults = (content) => 'results' in content;
|
|
5
9
|
export async function getContent(options) {
|
|
6
10
|
const allContent = await getAllContent({ ...options, limit: 1 });
|
|
7
|
-
if (allContent &&
|
|
8
|
-
return allContent
|
|
11
|
+
if (allContent && checkContentHasResults(allContent)) {
|
|
12
|
+
return allContent.results[0] || null;
|
|
9
13
|
}
|
|
10
14
|
return null;
|
|
11
15
|
}
|
|
16
|
+
const fetchContent = async (options) => {
|
|
17
|
+
const url = generateContentUrl(options);
|
|
18
|
+
const res = await fetch(url.href);
|
|
19
|
+
const content = await res.json();
|
|
20
|
+
return content;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Exported only for testing purposes. Should not be used directly.
|
|
24
|
+
*/
|
|
25
|
+
export const processContentResult = async (options, content) => {
|
|
26
|
+
const canTrack = getDefaultCanTrack(options.canTrack);
|
|
27
|
+
if (!canTrack)
|
|
28
|
+
return content;
|
|
29
|
+
if (!(isBrowser() || TARGET === 'reactNative'))
|
|
30
|
+
return content;
|
|
31
|
+
/**
|
|
32
|
+
* For client-side navigations, it is ideal to handle AB testing at this point instead of using our
|
|
33
|
+
* complex multi-rendering variants approach, which is only needed for SSR'd content.
|
|
34
|
+
*
|
|
35
|
+
* This is also where react-native would handle AB testing.
|
|
36
|
+
*/
|
|
37
|
+
try {
|
|
38
|
+
const newResults = [];
|
|
39
|
+
for (const item of content.results) {
|
|
40
|
+
newResults.push(await handleABTesting({ item, canTrack }));
|
|
41
|
+
}
|
|
42
|
+
content.results = newResults;
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
logger.error('Could not process A/B tests. ', e);
|
|
46
|
+
}
|
|
47
|
+
return content;
|
|
48
|
+
};
|
|
12
49
|
export async function getAllContent(options) {
|
|
13
50
|
try {
|
|
14
51
|
const url = generateContentUrl(options);
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
if ('status' in content && !('results' in content)) {
|
|
52
|
+
const content = await fetchContent(options);
|
|
53
|
+
if (!checkContentHasResults(content)) {
|
|
18
54
|
logger.error('Error fetching data. ', { url, content, options });
|
|
19
55
|
return content;
|
|
20
56
|
}
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
if (canTrack &&
|
|
24
|
-
// This makes sure we have a non-error response with the results array.
|
|
25
|
-
Array.isArray(content.results)) {
|
|
26
|
-
for (const item of content.results) {
|
|
27
|
-
await handleABTesting({ item, canTrack });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
catch (e) {
|
|
32
|
-
logger.error('Could not setup A/B testing. ', e);
|
|
33
|
-
}
|
|
34
|
-
return content;
|
|
57
|
+
return processContentResult(options, content);
|
|
35
58
|
}
|
|
36
59
|
catch (error) {
|
|
37
60
|
logger.error('Error fetching data. ', error);
|
|
@@ -19,6 +19,7 @@ export interface GetContentOptions {
|
|
|
19
19
|
/**
|
|
20
20
|
* If set to `true`, it will lazy load symbols/references.
|
|
21
21
|
* If set to `false`, it will render the entire content tree eagerly.
|
|
22
|
+
* @deprecated use `enrich` instead
|
|
22
23
|
*/
|
|
23
24
|
noTraverse?: boolean;
|
|
24
25
|
/**
|
|
@@ -30,8 +31,13 @@ export interface GetContentOptions {
|
|
|
30
31
|
canTrack?: boolean;
|
|
31
32
|
/**
|
|
32
33
|
* Include references in the response. Defaults to `true`.
|
|
34
|
+
* @deprecated use `enrich` instead
|
|
33
35
|
*/
|
|
34
36
|
includeRefs?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Include multilevel references in the response.
|
|
39
|
+
*/
|
|
40
|
+
enrich?: boolean;
|
|
35
41
|
/**
|
|
36
42
|
* If provided, the API will auto-resolve localized objects to the value of this `locale` key.
|
|
37
43
|
*/
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { CanTrack } from '../types/can-track.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import type { BuilderContent } from '../types/builder-content.js';
|
|
3
|
+
import type { Nullable } from '../types/typescript.js';
|
|
4
|
+
export declare const handleABTestingSync: ({ item, canTrack, }: {
|
|
5
|
+
item: Nullable<BuilderContent>;
|
|
6
|
+
} & CanTrack) => Nullable<BuilderContent>;
|
|
7
|
+
export declare const handleABTesting: ({ item, canTrack, }: {
|
|
8
|
+
item: BuilderContent;
|
|
9
|
+
} & CanTrack) => Promise<BuilderContent>;
|
|
@@ -1,5 +1,104 @@
|
|
|
1
|
-
import { getCookie, setCookie } from './cookie.js';
|
|
2
|
-
|
|
1
|
+
import { getCookie, getCookieSync, setCookie } from './cookie.js';
|
|
2
|
+
import { checkIsDefined } from '../helpers/nullable.js';
|
|
3
|
+
import { logger } from './logger.js';
|
|
4
|
+
const BUILDER_STORE_PREFIX = 'builder.tests';
|
|
3
5
|
const getContentTestKey = (id) => `${BUILDER_STORE_PREFIX}.${id}`;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
const getContentVariationCookie = ({ contentId }) => getCookie({ name: getContentTestKey(contentId), canTrack: true });
|
|
7
|
+
const getContentVariationCookieSync = ({ contentId }) => getCookieSync({ name: getContentTestKey(contentId), canTrack: true });
|
|
8
|
+
const setContentVariationCookie = ({ contentId, value, }) => setCookie({ name: getContentTestKey(contentId), value, canTrack: true });
|
|
9
|
+
const checkIsBuilderContentWithVariations = (item) => checkIsDefined(item.id) &&
|
|
10
|
+
checkIsDefined(item.variations) &&
|
|
11
|
+
Object.keys(item.variations).length > 0;
|
|
12
|
+
/**
|
|
13
|
+
* Randomly assign a variation to a user
|
|
14
|
+
*/
|
|
15
|
+
const getRandomVariationId = ({ id, variations, }) => {
|
|
16
|
+
let n = 0;
|
|
17
|
+
const random = Math.random();
|
|
18
|
+
// loop over variations test ratios, incrementing a counter,
|
|
19
|
+
// until we find the variation that this user should be assigned to
|
|
20
|
+
for (const id in variations) {
|
|
21
|
+
const testRatio = variations[id]?.testRatio;
|
|
22
|
+
n += testRatio;
|
|
23
|
+
if (random < n) {
|
|
24
|
+
return id;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// the variations array does not include the default variation.
|
|
28
|
+
// if we arrive here, then it means that the random number fits in the default variation bucket.
|
|
29
|
+
return id;
|
|
30
|
+
};
|
|
31
|
+
const getAndSetVariantId = (args) => {
|
|
32
|
+
// if variation not found in storage, assign a random variation to this user
|
|
33
|
+
const randomVariationId = getRandomVariationId(args);
|
|
34
|
+
// store variation in cookies/storage
|
|
35
|
+
setContentVariationCookie({
|
|
36
|
+
contentId: args.id,
|
|
37
|
+
value: randomVariationId,
|
|
38
|
+
}).catch((err) => {
|
|
39
|
+
logger.error('could not store A/B test variation: ', err);
|
|
40
|
+
});
|
|
41
|
+
return randomVariationId;
|
|
42
|
+
};
|
|
43
|
+
const getTestFields = ({ item, testGroupId, }) => {
|
|
44
|
+
const variationValue = item.variations[testGroupId];
|
|
45
|
+
if (testGroupId === item.id ||
|
|
46
|
+
// handle edge-case where `testGroupId` points to non-existing variation
|
|
47
|
+
!variationValue) {
|
|
48
|
+
return {
|
|
49
|
+
testVariationId: item.id,
|
|
50
|
+
testVariationName: 'Default',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return {
|
|
55
|
+
data: variationValue.data,
|
|
56
|
+
testVariationId: variationValue.id,
|
|
57
|
+
testVariationName: variationValue.name || (variationValue.id === item.id ? 'Default' : ''),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
export const handleABTestingSync = ({ item, canTrack, }) => {
|
|
62
|
+
if (!canTrack) {
|
|
63
|
+
return item;
|
|
64
|
+
}
|
|
65
|
+
if (!item) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
if (!checkIsBuilderContentWithVariations(item)) {
|
|
69
|
+
return item;
|
|
70
|
+
}
|
|
71
|
+
const testGroupId = getContentVariationCookieSync({
|
|
72
|
+
contentId: item.id,
|
|
73
|
+
}) ||
|
|
74
|
+
getAndSetVariantId({
|
|
75
|
+
variations: item.variations,
|
|
76
|
+
id: item.id,
|
|
77
|
+
});
|
|
78
|
+
const variationValue = getTestFields({ item, testGroupId });
|
|
79
|
+
return {
|
|
80
|
+
...item,
|
|
81
|
+
...variationValue,
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
export const handleABTesting = async ({ item, canTrack, }) => {
|
|
85
|
+
if (!canTrack) {
|
|
86
|
+
return item;
|
|
87
|
+
}
|
|
88
|
+
if (!checkIsBuilderContentWithVariations(item)) {
|
|
89
|
+
return item;
|
|
90
|
+
}
|
|
91
|
+
const cookieValue = await getContentVariationCookie({
|
|
92
|
+
contentId: item.id,
|
|
93
|
+
});
|
|
94
|
+
const testGroupId = cookieValue ||
|
|
95
|
+
getAndSetVariantId({
|
|
96
|
+
variations: item.variations,
|
|
97
|
+
id: item.id,
|
|
98
|
+
});
|
|
99
|
+
const variationValue = getTestFields({ item, testGroupId });
|
|
100
|
+
return {
|
|
101
|
+
...item,
|
|
102
|
+
...variationValue,
|
|
103
|
+
};
|
|
104
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getDefaultCanTrack: (canTrack?: boolean) => boolean;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { CanTrack } from '../types/can-track.js';
|
|
2
|
+
type GetCookieArgs = {
|
|
3
|
+
name: string;
|
|
4
|
+
} & CanTrack;
|
|
5
|
+
export declare const getCookieSync: ({ name, canTrack, }: GetCookieArgs) => string | undefined;
|
|
2
6
|
/**
|
|
3
7
|
* NOTE: This function is `async` because its react-native override is async. Do not remove the `async` keyword!
|
|
8
|
+
* The sync version is only safe to use in code blocks that `react-native` is guaranteed not to not run.
|
|
4
9
|
*/
|
|
5
|
-
export declare const getCookie: (
|
|
6
|
-
name: string;
|
|
7
|
-
} & CanTrack) => Promise<string | undefined>;
|
|
10
|
+
export declare const getCookie: (args: GetCookieArgs) => Promise<string | undefined>;
|
|
8
11
|
/**
|
|
9
12
|
* NOTE: This function is `async` because its react-native override is async. Do not remove the `async` keyword!
|
|
10
13
|
*/
|
|
@@ -13,3 +16,4 @@ export declare const setCookie: ({ name, value, expires, canTrack, }: {
|
|
|
13
16
|
value: string;
|
|
14
17
|
expires?: Date | undefined;
|
|
15
18
|
} & CanTrack) => Promise<void>;
|
|
19
|
+
export {};
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { isBrowser } from '../functions/is-browser.js';
|
|
2
|
+
import { logger } from './logger.js';
|
|
2
3
|
import { checkIsDefined } from './nullable.js';
|
|
3
4
|
import { getTopLevelDomain } from './url.js';
|
|
4
|
-
|
|
5
|
-
* NOTE: This function is `async` because its react-native override is async. Do not remove the `async` keyword!
|
|
6
|
-
*/
|
|
7
|
-
export const getCookie = async ({ name, canTrack, }) => {
|
|
5
|
+
export const getCookieSync = ({ name, canTrack, }) => {
|
|
8
6
|
try {
|
|
9
7
|
if (!canTrack) {
|
|
10
8
|
return undefined;
|
|
@@ -19,10 +17,15 @@ export const getCookie = async ({ name, canTrack, }) => {
|
|
|
19
17
|
?.split('=')[1];
|
|
20
18
|
}
|
|
21
19
|
catch (err) {
|
|
22
|
-
|
|
20
|
+
logger.warn('[COOKIE] GET error: ', err?.message || err);
|
|
23
21
|
return undefined;
|
|
24
22
|
}
|
|
25
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* NOTE: This function is `async` because its react-native override is async. Do not remove the `async` keyword!
|
|
26
|
+
* The sync version is only safe to use in code blocks that `react-native` is guaranteed not to not run.
|
|
27
|
+
*/
|
|
28
|
+
export const getCookie = async (args) => getCookieSync(args);
|
|
26
29
|
const stringifyCookie = (cookie) => cookie
|
|
27
30
|
.map(([key, value]) => (value ? `${key}=${value}` : key))
|
|
28
31
|
.filter(checkIsDefined)
|
|
@@ -60,6 +63,6 @@ export const setCookie = async ({ name, value, expires, canTrack, }) => {
|
|
|
60
63
|
document.cookie = cookie;
|
|
61
64
|
}
|
|
62
65
|
catch (err) {
|
|
63
|
-
|
|
66
|
+
logger.warn('[COOKIE] SET error: ', err?.message || err);
|
|
64
67
|
}
|
|
65
68
|
};
|
|
@@ -3,4 +3,5 @@ export const logger = {
|
|
|
3
3
|
log: (...message) => console.log(MSG_PREFIX, ...message),
|
|
4
4
|
error: (...message) => console.error(MSG_PREFIX, ...message),
|
|
5
5
|
warn: (...message) => console.warn(MSG_PREFIX, ...message),
|
|
6
|
+
debug: (...message) => console.debug(MSG_PREFIX, ...message),
|
|
6
7
|
};
|
|
@@ -3,8 +3,8 @@ export { default as Columns } from '../blocks/columns/columns.svelte';
|
|
|
3
3
|
export { default as Fragment } from '../blocks/fragment/fragment.svelte';
|
|
4
4
|
export { default as Image } from '../blocks/image/image.svelte';
|
|
5
5
|
export { default as RenderBlocks } from '../components/render-blocks.svelte';
|
|
6
|
-
export { default as RenderContent } from '../components/render-content/render-content.svelte';
|
|
7
6
|
export { default as Section } from '../blocks/section/section.svelte';
|
|
8
7
|
export { default as Symbol } from '../blocks/symbol/symbol.svelte';
|
|
9
8
|
export { default as Text } from '../blocks/text/text.svelte';
|
|
10
9
|
export { default as Video } from '../blocks/video/video.svelte';
|
|
10
|
+
export { default as RenderContent } from '../components/render-content-variants/render-content-variants.svelte';
|
|
@@ -3,8 +3,8 @@ export { default as Columns } from '../blocks/columns/columns.svelte';
|
|
|
3
3
|
export { default as Fragment } from '../blocks/fragment/fragment.svelte';
|
|
4
4
|
export { default as Image } from '../blocks/image/image.svelte';
|
|
5
5
|
export { default as RenderBlocks } from '../components/render-blocks.svelte';
|
|
6
|
-
export { default as RenderContent } from '../components/render-content/render-content.svelte';
|
|
7
6
|
export { default as Section } from '../blocks/section/section.svelte';
|
|
8
7
|
export { default as Symbol } from '../blocks/symbol/symbol.svelte';
|
|
9
8
|
export { default as Text } from '../blocks/text/text.svelte';
|
|
10
9
|
export { default as Video } from '../blocks/video/video.svelte';
|
|
10
|
+
export { default as RenderContent } from '../components/render-content-variants/render-content-variants.svelte';
|
package/package/index.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
export * from './index-helpers/top-of-file.js';
|
|
2
2
|
export * from './index-helpers/blocks-exports.js';
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
export
|
|
9
|
-
export
|
|
3
|
+
export { isEditing } from './functions/is-editing.js';
|
|
4
|
+
export { isPreviewing } from './functions/is-previewing.js';
|
|
5
|
+
export { createRegisterComponentMessage } from './functions/register-component.js';
|
|
6
|
+
export { register } from './functions/register.js';
|
|
7
|
+
export type { InsertMenuConfig, InsertMenuItem } from './functions/register.js';
|
|
8
|
+
export { setEditorSettings } from './functions/set-editor-settings.js';
|
|
9
|
+
export type { Settings } from './functions/set-editor-settings.js';
|
|
10
|
+
export { getAllContent, getContent, processContentResult, } from './functions/get-content/index.js';
|
|
10
11
|
export { track } from './functions/track/index.js';
|
|
11
12
|
export type { RegisteredComponent } from './context/types';
|
|
12
13
|
export type { ComponentInfo } from './types/components';
|
package/package/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
export * from './index-helpers/top-of-file.js';
|
|
2
2
|
export * from './index-helpers/blocks-exports.js';
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
export
|
|
9
|
-
export * from './functions/get-builder-search-params/index.js';
|
|
3
|
+
export { isEditing } from './functions/is-editing.js';
|
|
4
|
+
export { isPreviewing } from './functions/is-previewing.js';
|
|
5
|
+
export { createRegisterComponentMessage } from './functions/register-component.js';
|
|
6
|
+
export { register } from './functions/register.js';
|
|
7
|
+
export { setEditorSettings } from './functions/set-editor-settings.js';
|
|
8
|
+
export { getAllContent, getContent, processContentResult, } from './functions/get-content/index.js';
|
|
10
9
|
export { track } from './functions/track/index.js';
|
|
@@ -30,8 +30,6 @@ export interface BuilderContentVariation {
|
|
|
30
30
|
}
|
|
31
31
|
export interface BuilderContent extends BuilderContentVariation {
|
|
32
32
|
'@version'?: number;
|
|
33
|
-
id?: string;
|
|
34
|
-
name?: string;
|
|
35
33
|
published?: 'published' | 'draft' | 'archived';
|
|
36
34
|
modelId?: string;
|
|
37
35
|
priority?: number;
|
|
@@ -39,7 +37,7 @@ export interface BuilderContent extends BuilderContentVariation {
|
|
|
39
37
|
startDate?: number;
|
|
40
38
|
endDate?: number;
|
|
41
39
|
variations?: {
|
|
42
|
-
[id: string]: BuilderContentVariation
|
|
40
|
+
[id: string]: BuilderContentVariation;
|
|
43
41
|
};
|
|
44
42
|
testVariationId?: string;
|
|
45
43
|
testVariationName?: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@builder.io/sdk-svelte",
|
|
3
3
|
"description": "Builder.io SDK for Svelte",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"package",
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
},
|
|
29
29
|
"types": "./package/index.d.ts",
|
|
30
30
|
"scripts": {
|
|
31
|
-
"dev": "vite dev",
|
|
32
31
|
"build": "svelte-kit sync && svelte-package",
|
|
33
32
|
"build:watch": "svelte-kit sync && svelte-package --watch",
|
|
34
33
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
@@ -36,10 +35,10 @@
|
|
|
36
35
|
},
|
|
37
36
|
"devDependencies": {
|
|
38
37
|
"@sveltejs/adapter-auto": "1.0.0-next.71",
|
|
39
|
-
"@sveltejs/kit": "^1.
|
|
38
|
+
"@sveltejs/kit": "^1.16.2",
|
|
40
39
|
"@sveltejs/package": "1.0.0-next.1",
|
|
41
|
-
"svelte": "^3.
|
|
42
|
-
"svelte-check": "^
|
|
40
|
+
"svelte": "^3.59.1",
|
|
41
|
+
"svelte-check": "^3.3.2",
|
|
43
42
|
"svelte-preprocess": "^4.10.6",
|
|
44
43
|
"tslib": "^2.3.1",
|
|
45
44
|
"typescript": "^4",
|
|
@@ -160,23 +160,23 @@
|
|
|
160
160
|
block: block,
|
|
161
161
|
context: context,
|
|
162
162
|
});
|
|
163
|
-
let
|
|
163
|
+
let Tag = block.tagName || "div";
|
|
164
164
|
</script>
|
|
165
165
|
|
|
166
166
|
{#if canShowBlock()}
|
|
167
167
|
{#if !component?.noWrap}
|
|
168
|
-
{#if isEmptyHtmlElement(
|
|
169
|
-
<svelte:element this={
|
|
168
|
+
{#if isEmptyHtmlElement(Tag)}
|
|
169
|
+
<svelte:element this={Tag} {...attributes()} use:setAttrs={actions()} />
|
|
170
170
|
{/if}
|
|
171
171
|
|
|
172
|
-
{#if !isEmptyHtmlElement(
|
|
172
|
+
{#if !isEmptyHtmlElement(Tag) && repeatItem()}
|
|
173
173
|
{#each repeatItem() as data, index (index)}
|
|
174
174
|
<RenderRepeatedBlock repeatContext={data.context} block={data.block} />
|
|
175
175
|
{/each}
|
|
176
176
|
{/if}
|
|
177
177
|
|
|
178
|
-
{#if !isEmptyHtmlElement(
|
|
179
|
-
<svelte:element this={
|
|
178
|
+
{#if !isEmptyHtmlElement(Tag) && !repeatItem()}
|
|
179
|
+
<svelte:element this={Tag} {...attributes()} use:setAttrs={actions()}>
|
|
180
180
|
<RenderComponent {...renderComponentProps()} />
|
|
181
181
|
|
|
182
182
|
{#each childrenWithoutParentComponent() as child ("render-block-" + child.id)}
|
|
@@ -42,6 +42,37 @@
|
|
|
42
42
|
} from "./render-content.helpers.js";
|
|
43
43
|
import { TARGET } from "../../constants/target.js";
|
|
44
44
|
import { logger } from "../../helpers/logger.js";
|
|
45
|
+
import { getRenderContentScriptString } from "../render-content-variants/helpers.js";
|
|
46
|
+
import { wrapComponentRef } from "./wrap-component-ref.js";
|
|
47
|
+
|
|
48
|
+
const isEvent = (attr) => attr.startsWith("on:");
|
|
49
|
+
const isNonEvent = (attr) => !attr.startsWith("on:");
|
|
50
|
+
const filterAttrs = (attrs = {}, filter) => {
|
|
51
|
+
const validAttr = {};
|
|
52
|
+
Object.keys(attrs).forEach((attr) => {
|
|
53
|
+
if (filter(attr)) {
|
|
54
|
+
validAttr[attr] = attrs[attr];
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return validAttr;
|
|
58
|
+
};
|
|
59
|
+
const setAttrs = (node, attrs = {}) => {
|
|
60
|
+
const attrKeys = Object.keys(attrs);
|
|
61
|
+
const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
|
|
62
|
+
const teardown = (attr) =>
|
|
63
|
+
node.removeEventListener(attr.substr(3), attrs[attr]);
|
|
64
|
+
attrKeys.map(setup);
|
|
65
|
+
return {
|
|
66
|
+
update(attrs = {}) {
|
|
67
|
+
const attrKeys = Object.keys(attrs);
|
|
68
|
+
attrKeys.map(teardown);
|
|
69
|
+
attrKeys.map(setup);
|
|
70
|
+
},
|
|
71
|
+
destroy() {
|
|
72
|
+
attrKeys.map(teardown);
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
};
|
|
45
76
|
|
|
46
77
|
export let content: RenderContentProps["content"];
|
|
47
78
|
export let data: RenderContentProps["data"];
|
|
@@ -51,7 +82,12 @@
|
|
|
51
82
|
export let model: RenderContentProps["model"];
|
|
52
83
|
export let context: RenderContentProps["context"];
|
|
53
84
|
export let apiKey: RenderContentProps["apiKey"];
|
|
85
|
+
export let parentContentId: RenderContentProps["parentContentId"];
|
|
86
|
+
export let hideContent: RenderContentProps["hideContent"];
|
|
87
|
+
export let classNameProp: RenderContentProps["classNameProp"];
|
|
88
|
+
export let isSsrAbTest: RenderContentProps["isSsrAbTest"];
|
|
54
89
|
export let includeRefs: RenderContentProps["includeRefs"];
|
|
90
|
+
export let enrich: RenderContentProps["enrich"];
|
|
55
91
|
export let apiVersion: RenderContentProps["apiVersion"];
|
|
56
92
|
|
|
57
93
|
function mergeNewContent(newContent: BuilderContent) {
|
|
@@ -233,14 +269,22 @@
|
|
|
233
269
|
...components,
|
|
234
270
|
...(customComponents || []),
|
|
235
271
|
].reduce(
|
|
236
|
-
(acc, curr) => ({
|
|
272
|
+
(acc, { component, ...curr }) => ({
|
|
237
273
|
...acc,
|
|
238
|
-
[curr.name]:
|
|
274
|
+
[curr.name]: {
|
|
275
|
+
component: TARGET === "vue3" ? wrapComponentRef(component) : component,
|
|
276
|
+
...curr,
|
|
277
|
+
},
|
|
239
278
|
}),
|
|
240
279
|
{} as RegisteredComponents
|
|
241
280
|
);
|
|
242
281
|
let httpReqsData = {};
|
|
243
282
|
let clicked = false;
|
|
283
|
+
let scriptStr = getRenderContentScriptString({
|
|
284
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
|
|
285
|
+
contentId: content?.id!,
|
|
286
|
+
parentContentId: parentContentId!,
|
|
287
|
+
});
|
|
244
288
|
|
|
245
289
|
onMount(() => {
|
|
246
290
|
if (!apiKey) {
|
|
@@ -263,6 +307,11 @@
|
|
|
263
307
|
includeRefs: includeRefs,
|
|
264
308
|
}
|
|
265
309
|
: {}),
|
|
310
|
+
...(enrich
|
|
311
|
+
? {
|
|
312
|
+
enrich: enrich,
|
|
313
|
+
}
|
|
314
|
+
: {}),
|
|
266
315
|
});
|
|
267
316
|
Object.values<RegisteredComponent>(allRegisteredComponents).forEach(
|
|
268
317
|
(registeredComponent) => {
|
|
@@ -397,7 +446,42 @@
|
|
|
397
446
|
}}
|
|
398
447
|
builder-content-id={useContent?.id}
|
|
399
448
|
builder-model={model}
|
|
449
|
+
{...filterAttrs(
|
|
450
|
+
TARGET === "reactNative"
|
|
451
|
+
? {
|
|
452
|
+
dataSet: {
|
|
453
|
+
// currently, we can't set the actual ID here.
|
|
454
|
+
// we don't need it right now, we just need to identify content divs for testing.
|
|
455
|
+
"builder-content-id": "",
|
|
456
|
+
},
|
|
457
|
+
}
|
|
458
|
+
: {},
|
|
459
|
+
isNonEvent
|
|
460
|
+
)}
|
|
461
|
+
{...hideContent
|
|
462
|
+
? {
|
|
463
|
+
hidden: true,
|
|
464
|
+
"aria-hidden": true,
|
|
465
|
+
}
|
|
466
|
+
: {}}
|
|
467
|
+
class={classNameProp}
|
|
468
|
+
use:setAttrs={filterAttrs(
|
|
469
|
+
TARGET === "reactNative"
|
|
470
|
+
? {
|
|
471
|
+
dataSet: {
|
|
472
|
+
// currently, we can't set the actual ID here.
|
|
473
|
+
// we don't need it right now, we just need to identify content divs for testing.
|
|
474
|
+
"builder-content-id": "",
|
|
475
|
+
},
|
|
476
|
+
}
|
|
477
|
+
: {},
|
|
478
|
+
isEvent
|
|
479
|
+
)}
|
|
400
480
|
>
|
|
481
|
+
{#if isSsrAbTest}
|
|
482
|
+
<svelte:element this={"script"}>{@html scriptStr}</svelte:element>
|
|
483
|
+
{/if}
|
|
484
|
+
|
|
401
485
|
{#if TARGET !== "reactNative"}
|
|
402
486
|
<RenderContentStyles
|
|
403
487
|
contentId={useContent?.id}
|
|
@@ -7,7 +7,7 @@ import type { BuilderContent } from '../../types/builder-content';
|
|
|
7
7
|
import type { Nullable } from '../../types/typescript';
|
|
8
8
|
import type { ApiVersion } from '../../types/api-version';
|
|
9
9
|
|
|
10
|
-
export
|
|
10
|
+
export interface RenderContentProps {
|
|
11
11
|
content?: Nullable<BuilderContent>;
|
|
12
12
|
model?: string;
|
|
13
13
|
data?: { [key: string]: any };
|
|
@@ -17,8 +17,17 @@ export type RenderContentProps = {
|
|
|
17
17
|
customComponents?: RegisteredComponent[];
|
|
18
18
|
canTrack?: boolean;
|
|
19
19
|
locale?: string;
|
|
20
|
+
/** @deprecated use `enrich` instead **/
|
|
20
21
|
includeRefs?: boolean;
|
|
21
|
-
|
|
22
|
+
enrich?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* TO-DO: improve qwik generator to not remap this name for non-HTML tags, then name it `className`
|
|
25
|
+
*/
|
|
26
|
+
classNameProp?: string;
|
|
27
|
+
hideContent?: boolean;
|
|
28
|
+
parentContentId?: string;
|
|
29
|
+
isSsrAbTest?: boolean;
|
|
30
|
+
}
|
|
22
31
|
|
|
23
32
|
export interface BuilderComponentStateChange {
|
|
24
33
|
state: BuilderRenderState;
|