@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.
Files changed (61) hide show
  1. package/package/--package.json +8 -5
  2. package/package/CHANGELOG.md +13 -0
  3. package/package/components/render-block/render-block.svelte +6 -6
  4. package/package/components/render-content/components/render-styles.svelte +1 -1
  5. package/package/components/render-content/render-content.svelte +84 -2
  6. package/package/components/render-content/render-content.svelte.d.ts +5 -0
  7. package/package/components/render-content/render-content.types.d.ts +11 -2
  8. package/package/components/render-content/wrap-component-ref.d.ts +6 -0
  9. package/package/components/render-content/wrap-component-ref.js +6 -0
  10. package/package/components/render-content-variants/helpers.d.ts +17 -0
  11. package/package/components/render-content-variants/helpers.js +182 -0
  12. package/package/components/render-content-variants/render-content-variants.svelte +70 -0
  13. package/package/components/render-content-variants/render-content-variants.svelte.d.ts +23 -0
  14. package/package/components/render-inlined-styles.svelte +3 -15
  15. package/package/components/render-inlined-styles.svelte.d.ts +2 -0
  16. package/package/constants/sdk-version.d.ts +1 -1
  17. package/package/constants/sdk-version.js +1 -1
  18. package/package/functions/get-content/generate-content-url.js +2 -2
  19. package/package/functions/get-content/generate-content-url.test.js +15 -0
  20. package/package/functions/get-content/index.d.ts +7 -2
  21. package/package/functions/get-content/index.js +43 -20
  22. package/package/functions/get-content/types.d.ts +6 -0
  23. package/package/helpers/ab-tests.d.ts +8 -7
  24. package/package/helpers/ab-tests.js +103 -4
  25. package/package/helpers/canTrack.d.ts +1 -0
  26. package/package/helpers/canTrack.js +2 -0
  27. package/package/helpers/cookie.d.ts +7 -3
  28. package/package/helpers/cookie.js +9 -6
  29. package/package/helpers/logger.d.ts +1 -0
  30. package/package/helpers/logger.js +1 -0
  31. package/package/index-helpers/blocks-exports.d.ts +1 -1
  32. package/package/index-helpers/blocks-exports.js +1 -1
  33. package/package/index.d.ts +8 -7
  34. package/package/index.js +6 -7
  35. package/package/scripts/init-editing.d.ts +1 -0
  36. package/package/types/builder-content.d.ts +1 -3
  37. package/package.json +4 -5
  38. package/src/components/render-block/render-block.svelte +6 -6
  39. package/src/components/render-content/components/render-styles.svelte +1 -1
  40. package/src/components/render-content/render-content.svelte +86 -2
  41. package/src/components/render-content/render-content.types.ts +11 -2
  42. package/src/components/render-content/wrap-component-ref.ts +6 -0
  43. package/src/components/render-content-variants/helpers.ts +245 -0
  44. package/src/components/render-content-variants/render-content-variants.svelte +83 -0
  45. package/src/components/render-inlined-styles.svelte +3 -16
  46. package/src/constants/sdk-version.ts +1 -1
  47. package/src/functions/get-content/generate-content-url.test.ts +17 -0
  48. package/src/functions/get-content/generate-content-url.ts +2 -1
  49. package/src/functions/get-content/index.ts +57 -26
  50. package/src/functions/get-content/types.ts +7 -0
  51. package/src/helpers/ab-tests.ts +164 -11
  52. package/src/helpers/canTrack.ts +4 -0
  53. package/src/helpers/cookie.ts +16 -11
  54. package/src/helpers/logger.ts +1 -0
  55. package/src/index-helpers/blocks-exports.ts +1 -1
  56. package/src/index.ts +17 -8
  57. package/src/scripts/init-editing.ts +1 -0
  58. package/src/types/builder-content.ts +1 -3
  59. package/package/functions/get-content/ab-testing.d.ts +0 -5
  60. package/package/functions/get-content/ab-testing.js +0 -78
  61. package/src/functions/get-content/ab-testing.ts +0 -132
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-svelte",
3
3
  "description": "Builder.io SDK for Svelte",
4
- "version": "0.3.1",
4
+ "version": "0.4.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "package",
@@ -78,6 +78,9 @@
78
78
  "./components/render-content/render-content.helpers": "./components/render-content/render-content.helpers.js",
79
79
  "./components/render-content/render-content.svelte": "./components/render-content/render-content.svelte",
80
80
  "./components/render-content/render-content.types": "./components/render-content/render-content.types.js",
81
+ "./components/render-content/wrap-component-ref": "./components/render-content/wrap-component-ref.js",
82
+ "./components/render-content-variants/helpers": "./components/render-content-variants/helpers.js",
83
+ "./components/render-content-variants/render-content-variants.svelte": "./components/render-content-variants/render-content-variants.svelte",
81
84
  "./components/render-inlined-styles.svelte": "./components/render-inlined-styles.svelte",
82
85
  "./constants/builder-registered-components": "./constants/builder-registered-components.js",
83
86
  "./constants/device-sizes": "./constants/device-sizes.js",
@@ -97,7 +100,6 @@
97
100
  "./functions/get-block-properties": "./functions/get-block-properties.js",
98
101
  "./functions/get-builder-search-params/fn.test": "./functions/get-builder-search-params/fn.test.js",
99
102
  "./functions/get-builder-search-params": "./functions/get-builder-search-params/index.js",
100
- "./functions/get-content/ab-testing": "./functions/get-content/ab-testing.js",
101
103
  "./functions/get-content/generate-content-url.test": "./functions/get-content/generate-content-url.test.js",
102
104
  "./functions/get-content/generate-content-url": "./functions/get-content/generate-content-url.js",
103
105
  "./functions/get-content": "./functions/get-content/index.js",
@@ -126,6 +128,7 @@
126
128
  "./functions/transform-block-properties": "./functions/transform-block-properties.js",
127
129
  "./functions/transform-block": "./functions/transform-block.js",
128
130
  "./helpers/ab-tests": "./helpers/ab-tests.js",
131
+ "./helpers/canTrack": "./helpers/canTrack.js",
129
132
  "./helpers/cookie": "./helpers/cookie.js",
130
133
  "./helpers/css": "./helpers/css.js",
131
134
  "./helpers/flatten": "./helpers/flatten.js",
@@ -155,10 +158,10 @@
155
158
  "types": "./package/index.d.ts",
156
159
  "devDependencies": {
157
160
  "@sveltejs/adapter-auto": "1.0.0-next.71",
158
- "@sveltejs/kit": "^1.15.2",
161
+ "@sveltejs/kit": "^1.16.2",
159
162
  "@sveltejs/package": "1.0.0-next.1",
160
- "svelte": "^3.44.0",
161
- "svelte-check": "^2.7.1",
163
+ "svelte": "^3.59.1",
164
+ "svelte-check": "^3.3.2",
162
165
  "svelte-preprocess": "^4.10.6",
163
166
  "tslib": "^2.3.1",
164
167
  "typescript": "^4",
@@ -1,3 +1,16 @@
1
+ ### 0.4.0
2
+
3
+ - Feature: A/B tests are now rendered correctly during server-side rendering (SSR) when applicable. This behaviour is backwards compatible with previous versions.
4
+
5
+ ### 0.3.1
6
+
7
+ - Feature: Added SDK version to data sent to visual editor for improved debugging.
8
+ - Fix: Columns block: removed redundant margin-left in first column.
9
+
10
+ ### 0.3.0
11
+
12
+ - No Changes.
13
+
1
14
  ### 0.2.3
2
15
 
3
16
  - No Changes.
@@ -139,23 +139,23 @@ let component = getComponent({
139
139
  block: block,
140
140
  context: context,
141
141
  });
142
- let tag = block.tagName || "div";
142
+ let Tag = block.tagName || "div";
143
143
  </script>
144
144
 
145
145
  {#if canShowBlock()}
146
146
  {#if !component?.noWrap}
147
- {#if isEmptyHtmlElement(tag)}
148
- <svelte:element this={tag} {...attributes()} use:setAttrs={actions()} />
147
+ {#if isEmptyHtmlElement(Tag)}
148
+ <svelte:element this={Tag} {...attributes()} use:setAttrs={actions()} />
149
149
  {/if}
150
150
 
151
- {#if !isEmptyHtmlElement(tag) && repeatItem()}
151
+ {#if !isEmptyHtmlElement(Tag) && repeatItem()}
152
152
  {#each repeatItem() as data, index (index)}
153
153
  <RenderRepeatedBlock repeatContext={data.context} block={data.block} />
154
154
  {/each}
155
155
  {/if}
156
156
 
157
- {#if !isEmptyHtmlElement(tag) && !repeatItem()}
158
- <svelte:element this={tag} {...attributes()} use:setAttrs={actions()}>
157
+ {#if !isEmptyHtmlElement(Tag) && !repeatItem()}
158
+ <svelte:element this={Tag} {...attributes()} use:setAttrs={actions()}>
159
159
  <RenderComponent {...renderComponentProps()} />
160
160
 
161
161
  {#each childrenWithoutParentComponent() as child ("render-block-" + child.id)}
@@ -27,7 +27,7 @@ ${getFontCss({
27
27
  text-align: inherit;
28
28
  font-family: inherit;
29
29
  }
30
- `;
30
+ `.trim();
31
31
  </script>
32
32
 
33
33
  <RenderInlinedStyles styles={injectedStyles} />
@@ -17,6 +17,35 @@ import { getInteractionPropertiesForEvent } from "../../functions/track/interact
17
17
  import { getContentInitialValue, getContextStateInitialValue, } from "./render-content.helpers.js";
18
18
  import { TARGET } from "../../constants/target.js";
19
19
  import { logger } from "../../helpers/logger.js";
20
+ import { getRenderContentScriptString } from "../render-content-variants/helpers.js";
21
+ import { wrapComponentRef } from "./wrap-component-ref.js";
22
+ const isEvent = (attr) => attr.startsWith("on:");
23
+ const isNonEvent = (attr) => !attr.startsWith("on:");
24
+ const filterAttrs = (attrs = {}, filter) => {
25
+ const validAttr = {};
26
+ Object.keys(attrs).forEach((attr) => {
27
+ if (filter(attr)) {
28
+ validAttr[attr] = attrs[attr];
29
+ }
30
+ });
31
+ return validAttr;
32
+ };
33
+ const setAttrs = (node, attrs = {}) => {
34
+ const attrKeys = Object.keys(attrs);
35
+ const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
36
+ const teardown = (attr) => node.removeEventListener(attr.substr(3), attrs[attr]);
37
+ attrKeys.map(setup);
38
+ return {
39
+ update(attrs = {}) {
40
+ const attrKeys = Object.keys(attrs);
41
+ attrKeys.map(teardown);
42
+ attrKeys.map(setup);
43
+ },
44
+ destroy() {
45
+ attrKeys.map(teardown);
46
+ },
47
+ };
48
+ };
20
49
  export let content;
21
50
  export let data;
22
51
  export let canTrack;
@@ -25,7 +54,12 @@ export let customComponents;
25
54
  export let model;
26
55
  export let context;
27
56
  export let apiKey;
57
+ export let parentContentId;
58
+ export let hideContent;
59
+ export let classNameProp;
60
+ export let isSsrAbTest;
28
61
  export let includeRefs;
62
+ export let enrich;
29
63
  export let apiVersion;
30
64
  function mergeNewContent(newContent) {
31
65
  useContent = {
@@ -191,12 +225,20 @@ let allRegisteredComponents = [
191
225
  // which is the new standard way of providing custom components, and must therefore take precedence.
192
226
  ...components,
193
227
  ...(customComponents || []),
194
- ].reduce((acc, curr) => ({
228
+ ].reduce((acc, { component, ...curr }) => ({
195
229
  ...acc,
196
- [curr.name]: curr,
230
+ [curr.name]: {
231
+ component: TARGET === "vue3" ? wrapComponentRef(component) : component,
232
+ ...curr,
233
+ },
197
234
  }), {});
198
235
  let httpReqsData = {};
199
236
  let clicked = false;
237
+ let scriptStr = getRenderContentScriptString({
238
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
239
+ contentId: content?.id,
240
+ parentContentId: parentContentId,
241
+ });
200
242
  onMount(() => {
201
243
  if (!apiKey) {
202
244
  logger.error("No API key provided to `RenderContent` component. This can cause issues. Please provide an API key using the `apiKey` prop.");
@@ -216,6 +258,11 @@ onMount(() => {
216
258
  includeRefs: includeRefs,
217
259
  }
218
260
  : {}),
261
+ ...(enrich
262
+ ? {
263
+ enrich: enrich,
264
+ }
265
+ : {}),
219
266
  });
220
267
  Object.values(allRegisteredComponents).forEach((registeredComponent) => {
221
268
  const message = createRegisterComponentMessage(registeredComponent);
@@ -332,7 +379,42 @@ onDestroy(() => {
332
379
  }}
333
380
  builder-content-id={useContent?.id}
334
381
  builder-model={model}
382
+ {...filterAttrs(
383
+ TARGET === "reactNative"
384
+ ? {
385
+ dataSet: {
386
+ // currently, we can't set the actual ID here.
387
+ // we don't need it right now, we just need to identify content divs for testing.
388
+ "builder-content-id": "",
389
+ },
390
+ }
391
+ : {},
392
+ isNonEvent
393
+ )}
394
+ {...hideContent
395
+ ? {
396
+ hidden: true,
397
+ "aria-hidden": true,
398
+ }
399
+ : {}}
400
+ class={classNameProp}
401
+ use:setAttrs={filterAttrs(
402
+ TARGET === "reactNative"
403
+ ? {
404
+ dataSet: {
405
+ // currently, we can't set the actual ID here.
406
+ // we don't need it right now, we just need to identify content divs for testing.
407
+ "builder-content-id": "",
408
+ },
409
+ }
410
+ : {},
411
+ isEvent
412
+ )}
335
413
  >
414
+ {#if isSsrAbTest}
415
+ <svelte:element this={"script"}>{@html scriptStr}</svelte:element>
416
+ {/if}
417
+
336
418
  {#if TARGET !== "reactNative"}
337
419
  <RenderContentStyles
338
420
  contentId={useContent?.id}
@@ -10,7 +10,12 @@ declare const __propDef: {
10
10
  model: RenderContentProps["model"];
11
11
  context: RenderContentProps["context"];
12
12
  apiKey: RenderContentProps["apiKey"];
13
+ parentContentId: RenderContentProps["parentContentId"];
14
+ hideContent: RenderContentProps["hideContent"];
15
+ classNameProp: RenderContentProps["classNameProp"];
16
+ isSsrAbTest: RenderContentProps["isSsrAbTest"];
13
17
  includeRefs: RenderContentProps["includeRefs"];
18
+ enrich: RenderContentProps["enrich"];
14
19
  apiVersion: RenderContentProps["apiVersion"];
15
20
  };
16
21
  events: {
@@ -2,7 +2,7 @@ import type { BuilderRenderContext, RegisteredComponent, BuilderRenderState } fr
2
2
  import type { BuilderContent } from '../../types/builder-content';
3
3
  import type { Nullable } from '../../types/typescript';
4
4
  import type { ApiVersion } from '../../types/api-version';
5
- export type RenderContentProps = {
5
+ export interface RenderContentProps {
6
6
  content?: Nullable<BuilderContent>;
7
7
  model?: string;
8
8
  data?: {
@@ -14,8 +14,17 @@ export type RenderContentProps = {
14
14
  customComponents?: RegisteredComponent[];
15
15
  canTrack?: boolean;
16
16
  locale?: string;
17
+ /** @deprecated use `enrich` instead **/
17
18
  includeRefs?: boolean;
18
- };
19
+ enrich?: boolean;
20
+ /**
21
+ * TO-DO: improve qwik generator to not remap this name for non-HTML tags, then name it `className`
22
+ */
23
+ classNameProp?: string;
24
+ hideContent?: boolean;
25
+ parentContentId?: string;
26
+ isSsrAbTest?: boolean;
27
+ }
19
28
  export interface BuilderComponentStateChange {
20
29
  state: BuilderRenderState;
21
30
  ref: {
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Apply target-specific transformations to the component reference.
3
+ *
4
+ * See overrides/* for examples.
5
+ */
6
+ export declare const wrapComponentRef: (component: any) => any;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Apply target-specific transformations to the component reference.
3
+ *
4
+ * See overrides/* for examples.
5
+ */
6
+ export const wrapComponentRef = (component) => component;
@@ -0,0 +1,17 @@
1
+ import type { Nullable } from '../../helpers/nullable';
2
+ import type { BuilderContent } from '../../types/builder-content';
3
+ export declare const getVariants: (content: Nullable<BuilderContent>) => import("../../types/builder-content").BuilderContentVariation[];
4
+ export declare const checkShouldRunVariants: ({ canTrack, content, }: {
5
+ canTrack: Nullable<boolean>;
6
+ content: Nullable<BuilderContent>;
7
+ }) => boolean;
8
+ type VariantData = {
9
+ id: string;
10
+ testRatio?: number;
11
+ };
12
+ export declare const getVariantsScriptString: (variants: VariantData[], contentId: string) => string;
13
+ export declare const getRenderContentScriptString: ({ parentContentId, contentId, }: {
14
+ contentId: string;
15
+ parentContentId: string;
16
+ }) => string;
17
+ export {};
@@ -0,0 +1,182 @@
1
+ import { isBrowser } from '../../functions/is-browser';
2
+ export const getVariants = (content) => Object.values(content?.variations || {});
3
+ export const checkShouldRunVariants = ({ canTrack, content, }) => {
4
+ const hasVariants = getVariants(content).length > 0;
5
+ if (!hasVariants) {
6
+ return false;
7
+ }
8
+ if (!canTrack) {
9
+ return false;
10
+ }
11
+ if (isBrowser()) {
12
+ return false;
13
+ }
14
+ return true;
15
+ };
16
+ /**
17
+ * NOTE: when this function is stringified, single-line comments can cause weird issues when compiled by Sveltekit.
18
+ * Make sure to write multi-line comments only.
19
+ */
20
+ function bldrAbTest(contentId, variants, isHydrationTarget) {
21
+ function getAndSetVariantId() {
22
+ function setCookie(name, value, days) {
23
+ let expires = '';
24
+ if (days) {
25
+ const date = new Date();
26
+ date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
27
+ expires = '; expires=' + date.toUTCString();
28
+ }
29
+ document.cookie =
30
+ name +
31
+ '=' +
32
+ (value || '') +
33
+ expires +
34
+ '; path=/' +
35
+ '; Secure; SameSite=None';
36
+ }
37
+ function getCookie(name) {
38
+ const nameEQ = name + '=';
39
+ const ca = document.cookie.split(';');
40
+ for (let i = 0; i < ca.length; i++) {
41
+ let c = ca[i];
42
+ while (c.charAt(0) === ' ')
43
+ c = c.substring(1, c.length);
44
+ if (c.indexOf(nameEQ) === 0)
45
+ return c.substring(nameEQ.length, c.length);
46
+ }
47
+ return null;
48
+ }
49
+ const cookieName = `builder.tests.${contentId}`;
50
+ const variantInCookie = getCookie(cookieName);
51
+ const availableIDs = variants.map((vr) => vr.id).concat(contentId);
52
+ /**
53
+ * cookie already exists
54
+ */
55
+ if (variantInCookie && availableIDs.includes(variantInCookie)) {
56
+ return variantInCookie;
57
+ }
58
+ /**
59
+ * no cookie exists, find variant
60
+ */
61
+ let n = 0;
62
+ const random = Math.random();
63
+ for (let i = 0; i < variants.length; i++) {
64
+ const variant = variants[i];
65
+ const testRatio = variant.testRatio;
66
+ n += testRatio;
67
+ if (random < n) {
68
+ setCookie(cookieName, variant.id);
69
+ return variant.id;
70
+ }
71
+ }
72
+ /**
73
+ * no variant found, assign default content
74
+ */
75
+ setCookie(cookieName, contentId);
76
+ return contentId;
77
+ }
78
+ const winningVariantId = getAndSetVariantId();
79
+ const styleEl = document.getElementById(`variants-styles-${contentId}`);
80
+ /**
81
+ * For React to work, we need hydration to match SSR, so we completely remove this node and the styles tag.
82
+ */
83
+ if (isHydrationTarget) {
84
+ styleEl.remove();
85
+ const thisScriptEl = document.getElementById(`variants-script-${contentId}`);
86
+ thisScriptEl?.remove();
87
+ }
88
+ else {
89
+ /* update styles to hide all variants except the winning variant */
90
+ const newStyleStr = variants
91
+ .concat({ id: contentId })
92
+ .filter((variant) => variant.id !== winningVariantId)
93
+ .map((value) => {
94
+ return `.variant-${value.id} { display: none; }
95
+ `;
96
+ })
97
+ .join('');
98
+ /* TO-DO: check if this actually updates the style */
99
+ styleEl.innerHTML = newStyleStr;
100
+ }
101
+ }
102
+ /**
103
+ * NOTE: when this function is stringified, single-line comments can cause weird issues when compiled by Sveltekit.
104
+ * Make sure to write multi-line comments only.
105
+ */
106
+ function bldrCntntScrpt(variantContentId, defaultContentId, isHydrationTarget) {
107
+ if (!navigator.cookieEnabled) {
108
+ return;
109
+ }
110
+ function getCookie(name) {
111
+ const nameEQ = name + '=';
112
+ const ca = document.cookie.split(';');
113
+ for (let i = 0; i < ca.length; i++) {
114
+ let c = ca[i];
115
+ while (c.charAt(0) === ' ')
116
+ c = c.substring(1, c.length);
117
+ if (c.indexOf(nameEQ) === 0)
118
+ return c.substring(nameEQ.length, c.length);
119
+ }
120
+ return null;
121
+ }
122
+ const cookieName = `builder.tests.${defaultContentId}`;
123
+ const variantId = getCookie(cookieName);
124
+ /** get parent div by searching on `builder-content-id` attr */
125
+ const parentDiv = document.querySelector(`[builder-content-id="${variantContentId}"]`);
126
+ const variantIsDefaultContent = variantContentId === defaultContentId;
127
+ if (variantId === variantContentId) {
128
+ if (variantIsDefaultContent) {
129
+ /** the default content is already visible, no need to do anything */
130
+ return;
131
+ }
132
+ /** this is the winning variant and not already visible: remove `hidden` and `aria-hidden` attr */
133
+ parentDiv?.removeAttribute('hidden');
134
+ parentDiv?.removeAttribute('aria-hidden');
135
+ }
136
+ else {
137
+ if (variantIsDefaultContent) {
138
+ if (isHydrationTarget) {
139
+ /**
140
+ * For React to work, we need to support hydration, in which case the first CSR will have none of the hidden variants.
141
+ * So we completely remove that node.
142
+ */
143
+ parentDiv?.remove();
144
+ }
145
+ else {
146
+ /** this is not the winning variant, add `hidden` attr */
147
+ parentDiv?.setAttribute('hidden', 'true');
148
+ parentDiv?.setAttribute('aria-hidden', 'true');
149
+ }
150
+ }
151
+ /** This is not the winning variant, and it's not the default content.
152
+ * There's no need to hide it, because it's already hidden.
153
+ */
154
+ return;
155
+ }
156
+ return;
157
+ }
158
+ const isHydrationTarget = (target) => target === 'react' ||
159
+ target === 'reactNative' ||
160
+ target === 'vue3' ||
161
+ target === 'vue2';
162
+ /**
163
+ * We hardcode explicit function names here, because the `.toString()` of a function can change depending on the bundler.
164
+ * Some bundlers will minify the fn name, etc.
165
+ *
166
+ * So we hardcode the function names here, and then use those names in the script string to make sure the function names are consistent.
167
+ */
168
+ const AB_TEST_FN_NAME = 'bldrAbTest';
169
+ const CONTENT_FN_NAME = 'bldrCntntScrpt';
170
+ export const getVariantsScriptString = (variants, contentId) => {
171
+ const fnStr = bldrAbTest.toString().replace(/\s+/g, ' ');
172
+ const fnStr2 = bldrCntntScrpt.toString().replace(/\s+/g, ' ');
173
+ return `
174
+ const ${AB_TEST_FN_NAME} = ${fnStr}
175
+ const ${CONTENT_FN_NAME} = ${fnStr2}
176
+ ${AB_TEST_FN_NAME}("${contentId}", ${JSON.stringify(variants)}, ${isHydrationTarget})
177
+ `;
178
+ };
179
+ export const getRenderContentScriptString = ({ parentContentId, contentId, }) => {
180
+ return `
181
+ ${CONTENT_FN_NAME}("${contentId}", "${parentContentId}", ${isHydrationTarget})`;
182
+ };
@@ -0,0 +1,70 @@
1
+ <script context="module"></script>
2
+
3
+ <script>import { checkShouldRunVariants, getVariants, getVariantsScriptString, } from "./helpers";
4
+ import RenderContent from "../render-content/render-content.svelte";
5
+ import { getDefaultCanTrack } from "../../helpers/canTrack";
6
+ import RenderInlinedStyles from "../render-inlined-styles.svelte";
7
+ import { handleABTestingSync } from "../../helpers/ab-tests";
8
+ export let content;
9
+ export let canTrack;
10
+ export let apiKey;
11
+ export let apiVersion;
12
+ export let customComponents;
13
+ export let model;
14
+ let variantScriptStr = getVariantsScriptString(getVariants(content).map((value) => ({
15
+ id: value.id,
16
+ testRatio: value.testRatio,
17
+ })), content?.id || "");
18
+ let shouldRenderVariants = checkShouldRunVariants({
19
+ canTrack: getDefaultCanTrack(canTrack),
20
+ content: content,
21
+ });
22
+ let hideVariantsStyleString = getVariants(content)
23
+ .map((value) => `.variant-${value.id} { display: none; } `)
24
+ .join("");
25
+ let contentToRender = checkShouldRunVariants({
26
+ canTrack: getDefaultCanTrack(canTrack),
27
+ content: content,
28
+ })
29
+ ? content
30
+ : handleABTestingSync({
31
+ item: content,
32
+ canTrack: getDefaultCanTrack(canTrack),
33
+ });
34
+ </script>
35
+
36
+ {#if shouldRenderVariants}
37
+ <RenderInlinedStyles
38
+ id={`variants-styles-${content?.id}`}
39
+ styles={hideVariantsStyleString}
40
+ />
41
+
42
+ <svelte:element this={"script"} id={`variants-script-${content?.id}`}
43
+ >{@html variantScriptStr}</svelte:element
44
+ >
45
+
46
+ {#each getVariants(content) as variant (variant.id)}
47
+ <RenderContent
48
+ content={variant}
49
+ {apiKey}
50
+ {apiVersion}
51
+ {canTrack}
52
+ {customComponents}
53
+ hideContent={true}
54
+ parentContentId={content?.id}
55
+ isSsrAbTest={shouldRenderVariants}
56
+ />
57
+ {/each}
58
+ {/if}
59
+
60
+ <RenderContent
61
+ {model}
62
+ content={contentToRender}
63
+ {apiKey}
64
+ {apiVersion}
65
+ {canTrack}
66
+ {customComponents}
67
+ classNameProp={`variant-${content?.id}`}
68
+ parentContentId={content?.id}
69
+ isSsrAbTest={shouldRenderVariants}
70
+ />
@@ -0,0 +1,23 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ type VariantsProviderProps = RenderContentProps;
3
+ import type { RenderContentProps } from "../render-content/render-content.types";
4
+ declare const __propDef: {
5
+ props: {
6
+ content: VariantsProviderProps["content"];
7
+ canTrack: VariantsProviderProps["canTrack"];
8
+ apiKey: VariantsProviderProps["apiKey"];
9
+ apiVersion: VariantsProviderProps["apiVersion"];
10
+ customComponents: VariantsProviderProps["customComponents"];
11
+ model: VariantsProviderProps["model"];
12
+ };
13
+ events: {
14
+ [evt: string]: CustomEvent<any>;
15
+ };
16
+ slots: {};
17
+ };
18
+ export type RenderContentVariantsProps = typeof __propDef.props;
19
+ export type RenderContentVariantsEvents = typeof __propDef.events;
20
+ export type RenderContentVariantsSlots = typeof __propDef.slots;
21
+ export default class RenderContentVariants extends SvelteComponentTyped<RenderContentVariantsProps, RenderContentVariantsEvents, RenderContentVariantsSlots> {
22
+ }
23
+ export {};
@@ -1,19 +1,7 @@
1
1
  <script context="module"></script>
2
2
 
3
- <script>import { TARGET } from "../constants/target.js";
4
- export let styles;
5
- $: tag = () => {
6
- // NOTE: we have to obfuscate the name of the tag due to a limitation in the svelte-preprocessor plugin.
7
- // https://github.com/sveltejs/vite-plugin-svelte/issues/315#issuecomment-1109000027
8
- return ("sty" + "le");
9
- };
10
- $: injectedStyleScript = () => {
11
- return `<${tag()}>${styles}</${tag()}>`;
12
- };
3
+ <script>export let styles;
4
+ export let id;
13
5
  </script>
14
6
 
15
- {#if TARGET === "svelte" || TARGET === "qwik"}
16
- {@html injectedStyleScript()}
17
- {:else}
18
- <svelte:element this={tag()}>{styles}</svelte:element>
19
- {/if}
7
+ <svelte:element this={"sty" + "le"} {id}>{@html styles}</svelte:element>
@@ -1,10 +1,12 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  interface Props {
3
3
  styles: string;
4
+ id?: string;
4
5
  }
5
6
  declare const __propDef: {
6
7
  props: {
7
8
  styles: Props["styles"];
9
+ id: Props["id"];
8
10
  };
9
11
  events: {
10
12
  [evt: string]: CustomEvent<any>;
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "0.3.1";
1
+ export declare const SDK_VERSION = "0.4.0";
@@ -1 +1 @@
1
- export const SDK_VERSION = "0.3.1";
1
+ export const SDK_VERSION = "0.4.0";
@@ -2,14 +2,14 @@ import { flatten } from '../../helpers/flatten.js';
2
2
  import { getBuilderSearchParamsFromWindow, normalizeSearchParams, } from '../get-builder-search-params/index.js';
3
3
  import { DEFAULT_API_VERSION } from '../../types/api-version';
4
4
  export const generateContentUrl = (options) => {
5
- const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, locale, apiVersion = DEFAULT_API_VERSION, } = options;
5
+ const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, enrich, locale, apiVersion = DEFAULT_API_VERSION, } = options;
6
6
  if (!apiKey) {
7
7
  throw new Error('Missing API key');
8
8
  }
9
9
  if (!['v2', 'v3'].includes(apiVersion)) {
10
10
  throw new Error(`Invalid apiVersion: expected 'v2' or 'v3', received '${apiVersion}'`);
11
11
  }
12
- const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ''}`);
12
+ const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ''}${enrich ? `&enrich=${enrich}` : ''}`);
13
13
  const queryOptions = {
14
14
  ...getBuilderSearchParamsFromWindow(),
15
15
  ...normalizeSearchParams(options.options || {}),
@@ -79,4 +79,19 @@ describe('Generate Content URL', () => {
79
79
  });
80
80
  }).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'INVALID_API_VERSION'`);
81
81
  });
82
+ test('generate content url with enrich option true', () => {
83
+ const output = generateContentUrl({
84
+ apiKey: testKey,
85
+ model: testModel,
86
+ enrich: true,
87
+ });
88
+ expect(output).toMatchSnapshot();
89
+ });
90
+ test('generate content url with enrich option not present', () => {
91
+ const output = generateContentUrl({
92
+ apiKey: testKey,
93
+ model: testModel,
94
+ });
95
+ expect(output).toMatchSnapshot();
96
+ });
82
97
  });