From 5f84150958224bfffea71e75512d4bc9be07ac68 Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Thu, 25 Jul 2024 19:56:27 +0200 Subject: [PATCH 1/7] fix: datalayer optional param --- src/third-parties/google-analytics/data.json | 8 +++++--- src/third-parties/google-tag-manager/data.json | 7 ++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/third-parties/google-analytics/data.json b/src/third-parties/google-analytics/data.json index 12c8a48..12a4f26 100644 --- a/src/third-parties/google-analytics/data.json +++ b/src/third-parties/google-analytics/data.json @@ -5,15 +5,17 @@ "scripts": [ { "url": "https://www.googletagmanager.com/gtag/js", - "params": ["id", "l"], + "params": ["id"], + "optionalParams": ["l"], "strategy": "worker", "location": "head", "action": "append", "key": "gtag" }, { - "code": "window['{{l}}']=window['{{l}}']||[];window['{{l}}'].push({'js':new Date()});window['{{l}}'].push({'config':'{{id}}'})", - "params": ["id", "l"], + "code": "window['{{l}}'??'dataLayer']=window['{{l}}'??'dataLayer']||[];window['{{l}}'??'dataLayer'].push({'js':new Date()});window['{{l}}'??'dataLayer'].push({'config':'{{id}}'})", + "params": ["id"], + "optionalParams": ["l"], "strategy": "worker", "location": "head", "action": "append", diff --git a/src/third-parties/google-tag-manager/data.json b/src/third-parties/google-tag-manager/data.json index 757afbf..3910f09 100644 --- a/src/third-parties/google-tag-manager/data.json +++ b/src/third-parties/google-tag-manager/data.json @@ -5,15 +5,16 @@ "scripts": [ { "url": "https://www.googletagmanager.com/gtm.js", - "params": ["id", "l"], + "params": ["id"], + "optionalParams": ["l"], "strategy": "worker", "location": "head", "action": "append", "key": "gtm" }, { - "code": "window['{{l}}']=window['{{l}}']||[];window['{{l}}'].push({'gtm.start':new Date().getTime(),event:'gtm.js'});", - "params": ["l"], + "code": "window['{{l}}'??'dataLayer']=window['{{l}}'??'dataLayer']||[];window['{{l}}'??'dataLayer'].push({'gtm.start':new Date().getTime(),event:'gtm.js'});", + "optionalParams": ["l"], "strategy": "worker", "location": "head", "action": "append", From fe62f73ef85d2b15a65f2548b5ce2776870da04e Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Thu, 25 Jul 2024 19:57:35 +0200 Subject: [PATCH 2/7] fix: addd type --- src/third-parties/google-analytics/data.json | 4 ++-- src/third-parties/google-tag-manager/data.json | 4 ++-- src/types/type-declarations.ts | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/third-parties/google-analytics/data.json b/src/third-parties/google-analytics/data.json index 12a4f26..dd726ba 100644 --- a/src/third-parties/google-analytics/data.json +++ b/src/third-parties/google-analytics/data.json @@ -6,7 +6,7 @@ { "url": "https://www.googletagmanager.com/gtag/js", "params": ["id"], - "optionalParams": ["l"], + "optionalParam": ["l"], "strategy": "worker", "location": "head", "action": "append", @@ -15,7 +15,7 @@ { "code": "window['{{l}}'??'dataLayer']=window['{{l}}'??'dataLayer']||[];window['{{l}}'??'dataLayer'].push({'js':new Date()});window['{{l}}'??'dataLayer'].push({'config':'{{id}}'})", "params": ["id"], - "optionalParams": ["l"], + "optionalParam": ["l"], "strategy": "worker", "location": "head", "action": "append", diff --git a/src/third-parties/google-tag-manager/data.json b/src/third-parties/google-tag-manager/data.json index 3910f09..b64319c 100644 --- a/src/third-parties/google-tag-manager/data.json +++ b/src/third-parties/google-tag-manager/data.json @@ -6,7 +6,7 @@ { "url": "https://www.googletagmanager.com/gtm.js", "params": ["id"], - "optionalParams": ["l"], + "optionalParam": ["l"], "strategy": "worker", "location": "head", "action": "append", @@ -14,7 +14,7 @@ }, { "code": "window['{{l}}'??'dataLayer']=window['{{l}}'??'dataLayer']||[];window['{{l}}'??'dataLayer'].push({'gtm.start':new Date().getTime(),event:'gtm.js'});", - "optionalParams": ["l"], + "optionalParam": ["l"], "strategy": "worker", "location": "head", "action": "append", diff --git a/src/types/type-declarations.ts b/src/types/type-declarations.ts index 76dbd09..c648023 100644 --- a/src/types/type-declarations.ts +++ b/src/types/type-declarations.ts @@ -17,6 +17,7 @@ export type HtmlAttributes = { type ScriptBase = { params?: Array; + optionalParam?: Array; strategy: ScriptStrategy; location: ScriptLocation; action: ScriptAction; From 6fd93934529d1ebc0e3129775e1cf93148f3b376 Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Thu, 25 Jul 2024 21:46:36 +0200 Subject: [PATCH 3/7] fix: add back l in param to avoid breaking changes --- src/third-parties/google-analytics/data.json | 2 +- src/third-parties/google-tag-manager/data.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/third-parties/google-analytics/data.json b/src/third-parties/google-analytics/data.json index dd726ba..438baaa 100644 --- a/src/third-parties/google-analytics/data.json +++ b/src/third-parties/google-analytics/data.json @@ -5,7 +5,7 @@ "scripts": [ { "url": "https://www.googletagmanager.com/gtag/js", - "params": ["id"], + "params": ["id", "l"], "optionalParam": ["l"], "strategy": "worker", "location": "head", diff --git a/src/third-parties/google-tag-manager/data.json b/src/third-parties/google-tag-manager/data.json index b64319c..4a20844 100644 --- a/src/third-parties/google-tag-manager/data.json +++ b/src/third-parties/google-tag-manager/data.json @@ -5,7 +5,7 @@ "scripts": [ { "url": "https://www.googletagmanager.com/gtm.js", - "params": ["id"], + "params": ["id", "l"], "optionalParam": ["l"], "strategy": "worker", "location": "head", From 620df5569872b737e041d5cc1890ae8d8251c5a7 Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Fri, 26 Jul 2024 21:25:22 +0200 Subject: [PATCH 4/7] refactor: stringify input --- src/third-parties/google-analytics/data.json | 2 +- .../google-tag-manager/data.json | 2 +- src/utils/index.test.ts | 48 ++++++++++++++++++- src/utils/index.ts | 2 +- 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/third-parties/google-analytics/data.json b/src/third-parties/google-analytics/data.json index 438baaa..5e0ac1e 100644 --- a/src/third-parties/google-analytics/data.json +++ b/src/third-parties/google-analytics/data.json @@ -13,7 +13,7 @@ "key": "gtag" }, { - "code": "window['{{l}}'??'dataLayer']=window['{{l}}'??'dataLayer']||[];window['{{l}}'??'dataLayer'].push({'js':new Date()});window['{{l}}'??'dataLayer'].push({'config':'{{id}}'})", + "code": "window[{{l}}??'dataLayer']=window[{{l}}??'dataLayer']||[];window[{{l}}??'dataLayer'].push({'js':new Date()});window[{{l}}??'dataLayer'].push({'config':{{id}}})", "params": ["id"], "optionalParam": ["l"], "strategy": "worker", diff --git a/src/third-parties/google-tag-manager/data.json b/src/third-parties/google-tag-manager/data.json index 4a20844..d489fff 100644 --- a/src/third-parties/google-tag-manager/data.json +++ b/src/third-parties/google-tag-manager/data.json @@ -13,7 +13,7 @@ "key": "gtm" }, { - "code": "window['{{l}}'??'dataLayer']=window['{{l}}'??'dataLayer']||[];window['{{l}}'??'dataLayer'].push({'gtm.start':new Date().getTime(),event:'gtm.js'});", + "code": "window[{{l}}??'dataLayer']=window[{{l}}??'dataLayer']||[];window[{{l}}??'dataLayer'].push({'gtm.start':new Date().getTime(),event:'gtm.js'});", "optionalParam": ["l"], "strategy": "worker", "location": "head", diff --git a/src/utils/index.test.ts b/src/utils/index.test.ts index be82e02..d667388 100644 --- a/src/utils/index.test.ts +++ b/src/utils/index.test.ts @@ -1,4 +1,4 @@ -import { formatUrl, createHtml, formatData } from '.'; +import { formatUrl, createHtml, formatData, formatCode } from '.'; import type { Data, ExternalScript } from '../types'; describe('Utils', () => { @@ -231,4 +231,50 @@ describe('Utils', () => { expect(result.scripts).toEqual(undefined); }); }); + describe('formatCode', () => { + it.each([ + // string + { + input: "window[{{l}}??'dataLayer']=window[{{l}}??'dataLayer']||[];", + params: { + l: 'some-datalayer', + }, + output: `window["some-datalayer"??'dataLayer']=window["some-datalayer"??'dataLayer']||[];`, + }, + // number + { + input: '{{number}}+1', + params: { + number: 4, + }, + output: `4+1`, + }, + // boolean + { + input: '{{bool}}', + params: { + bool: false, + }, + output: `false`, + }, + // null + { + input: '{{val}}', + params: { + val: null, + }, + output: `null`, + }, + // undefined + { + input: "window[{{l}}??'dataLayer']=window[{{l}}??'dataLayer']||[];", + output: `window[undefined??'dataLayer']=window[undefined??'dataLayer']||[];`, + }, + ])( + 'should replace the input and stringify it', + ({ input, output, params }) => { + expect(formatCode(input, params)).toEqual(output); + }, + ); + }); }); diff --git a/src/utils/index.ts b/src/utils/index.ts index 679711e..6bfabc9 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -47,7 +47,7 @@ export function formatUrl( export function formatCode(code: string, args?: Inputs) { return code.replace(/{{(.*?)}}/g, (match) => { - return args?.[match.split(/{{|}}/).filter(Boolean)[0]]; + return JSON.stringify(args?.[match.split(/{{|}}/).filter(Boolean)[0]]); }); } From 6307dd3fa74fdd58c15520e97b03ca0bba42d48d Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Sat, 27 Jul 2024 00:56:35 +0200 Subject: [PATCH 5/7] refactor: discord discussion feedback --- src/third-parties/google-analytics/data.json | 12 ++-- .../google-tag-manager/data.json | 12 ++-- src/types/type-declarations.ts | 2 +- src/utils/index.test.ts | 58 ++++++++++++++----- src/utils/index.ts | 13 ++++- 5 files changed, 72 insertions(+), 25 deletions(-) diff --git a/src/third-parties/google-analytics/data.json b/src/third-parties/google-analytics/data.json index 5e0ac1e..92ee4af 100644 --- a/src/third-parties/google-analytics/data.json +++ b/src/third-parties/google-analytics/data.json @@ -5,17 +5,21 @@ "scripts": [ { "url": "https://www.googletagmanager.com/gtag/js", - "params": ["id", "l"], - "optionalParam": ["l"], + "params": ["id"], + "optionalParams": { + "l": null + }, "strategy": "worker", "location": "head", "action": "append", "key": "gtag" }, { - "code": "window[{{l}}??'dataLayer']=window[{{l}}??'dataLayer']||[];window[{{l}}??'dataLayer'].push({'js':new Date()});window[{{l}}??'dataLayer'].push({'config':{{id}}})", + "code": "window[{{l}}]=window[{{l}}]||[];window[{{l}}].push({'js':new Date()});window[{{l}}].push({'config':{{id}}})", "params": ["id"], - "optionalParam": ["l"], + "optionalParams": { + "l": "dataLayer" + }, "strategy": "worker", "location": "head", "action": "append", diff --git a/src/third-parties/google-tag-manager/data.json b/src/third-parties/google-tag-manager/data.json index d489fff..50447b6 100644 --- a/src/third-parties/google-tag-manager/data.json +++ b/src/third-parties/google-tag-manager/data.json @@ -5,16 +5,20 @@ "scripts": [ { "url": "https://www.googletagmanager.com/gtm.js", - "params": ["id", "l"], - "optionalParam": ["l"], + "params": ["id"], + "optionalParams": { + "l": null + }, "strategy": "worker", "location": "head", "action": "append", "key": "gtm" }, { - "code": "window[{{l}}??'dataLayer']=window[{{l}}??'dataLayer']||[];window[{{l}}??'dataLayer'].push({'gtm.start':new Date().getTime(),event:'gtm.js'});", - "optionalParam": ["l"], + "code": "window[{{l}}]=window[{{l}}]||[];window[{{l}}].push({'gtm.start':new Date().getTime(),event:'gtm.js'});", + "optionalParams": { + "l": "dataLayer" + }, "strategy": "worker", "location": "head", "action": "append", diff --git a/src/types/type-declarations.ts b/src/types/type-declarations.ts index c648023..a419f9d 100644 --- a/src/types/type-declarations.ts +++ b/src/types/type-declarations.ts @@ -17,7 +17,7 @@ export type HtmlAttributes = { type ScriptBase = { params?: Array; - optionalParam?: Array; + optionalParams?: Record; strategy: ScriptStrategy; location: ScriptLocation; action: ScriptAction; diff --git a/src/utils/index.test.ts b/src/utils/index.test.ts index d667388..2e72ba8 100644 --- a/src/utils/index.test.ts +++ b/src/utils/index.test.ts @@ -14,6 +14,26 @@ describe('Utils', () => { const newUrl = formatUrl(oldUrl, requiredParams, args); expect(newUrl).toEqual('https://example.com/?unit=imperial&type=main'); }); + + it('should add default value', () => { + const oldUrl = 'https://example.com'; + const requiredParams = ['unit', 'type']; + const args = { + unit: 'imperial', + }; + const optionalParams = { + type: 'main', + }; + + const newUrl = formatUrl( + oldUrl, + requiredParams, + args, + undefined, + optionalParams, + ); + expect(newUrl).toEqual('https://example.com/?unit=imperial&type=main'); + }); }); describe('createHtml', () => { @@ -231,15 +251,16 @@ describe('Utils', () => { expect(result.scripts).toEqual(undefined); }); }); + describe('formatCode', () => { - it.each([ + const inputs = [ // string { - input: "window[{{l}}??'dataLayer']=window[{{l}}??'dataLayer']||[];", + input: 'window[{{l}}]=window[{{l}}]||[];', params: { l: 'some-datalayer', }, - output: `window["some-datalayer"??'dataLayer']=window["some-datalayer"??'dataLayer']||[];`, + output: `window["some-datalayer"]=window["some-datalayer"]||[];`, }, // number { @@ -257,24 +278,33 @@ describe('Utils', () => { }, output: `false`, }, - // null - { - input: '{{val}}', - params: { - val: null, - }, - output: `null`, - }, // undefined { - input: "window[{{l}}??'dataLayer']=window[{{l}}??'dataLayer']||[];", - output: `window[undefined??'dataLayer']=window[undefined??'dataLayer']||[];`, + input: 'window[{{l}}]=window[{{l}}]||[];', + output: `window[undefined]=window[undefined]||[];`, }, - ])( + ]; + + it.each(inputs)( 'should replace the input and stringify it', ({ input, output, params }) => { expect(formatCode(input, params)).toEqual(output); }, ); + + it.each(inputs)( + 'should replace the input and stringify it with the default value', + ({ input, output, params }) => { + expect(formatCode(input, undefined, params)).toEqual(output); + }, + ); + + it('should replace the input and stringify it with the default value', () => { + const input = 'window[{{l}}]=window[{{l}}]||[];'; + + expect( + formatCode(input, { l: 'test' }, { l: 'dataLayer' }), + ).toMatchInlineSnapshot(`"window["test"]=window["test"]||[];"`); + }); }); }); diff --git a/src/utils/index.ts b/src/utils/index.ts index 6bfabc9..a3bca1c 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -30,6 +30,7 @@ export function formatUrl( params?: string[], args?: Inputs, slug?: Inputs, + optionalParams?: Inputs, ) { const newUrl = slug && Object.keys(slug).length > 0 @@ -39,15 +40,23 @@ export function formatUrl( if (params && args) { params.forEach((param: string) => { if (args[param]) newUrl.searchParams.set(param, args[param]); + else if (optionalParams?.[param]) { + newUrl.searchParams.set(param, optionalParams?.[param]); + } }); } return newUrl.toString(); } -export function formatCode(code: string, args?: Inputs) { +export function formatCode( + code: string, + args?: Inputs, + optionalParams?: Inputs, +) { return code.replace(/{{(.*?)}}/g, (match) => { - return JSON.stringify(args?.[match.split(/{{|}}/).filter(Boolean)[0]]); + const name = match.split(/{{|}}/).filter(Boolean)[0]; + return JSON.stringify(args?.[name] ?? optionalParams?.[name]); }); } From b43561f11331d181a3799b0d57e14f5fb2861d7c Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Sat, 27 Jul 2024 10:07:29 +0200 Subject: [PATCH 6/7] feedbacks + tests --- src/types/type-declarations.ts | 2 +- src/utils/index.test.ts | 46 +++++++++++++++++++++++++++++++++- src/utils/index.ts | 15 +++++++++-- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/types/type-declarations.ts b/src/types/type-declarations.ts index a419f9d..b43c2e9 100644 --- a/src/types/type-declarations.ts +++ b/src/types/type-declarations.ts @@ -17,7 +17,7 @@ export type HtmlAttributes = { type ScriptBase = { params?: Array; - optionalParams?: Record; + optionalParams?: Record; strategy: ScriptStrategy; location: ScriptLocation; action: ScriptAction; diff --git a/src/utils/index.test.ts b/src/utils/index.test.ts index 2e72ba8..f25cf92 100644 --- a/src/utils/index.test.ts +++ b/src/utils/index.test.ts @@ -1,5 +1,5 @@ import { formatUrl, createHtml, formatData, formatCode } from '.'; -import type { Data, ExternalScript } from '../types'; +import type { CodeBlock, Data, ExternalScript } from '../types'; describe('Utils', () => { describe('formatUrl', () => { @@ -250,6 +250,50 @@ describe('Utils', () => { ); expect(result.scripts).toEqual(undefined); }); + + it('should replace with default values when needed', () => { + const data = { + id: 'third-party', + description: 'Description', + html: { + element: 'iframe', + attributes: { + loading: 'lazy', + src: { + url: 'https://www.google.com/maps/embed/v1/place', + slugParam: 'mode', + params: ['key'], + }, + }, + }, + scripts: [ + { + code: 'window[{{hello}}]=window[{{hello}}]||[];console.log({{world}})', + optionalParams: { + hello: 'hoho', + }, + params: ['world'], + strategy: 'worker', + location: 'head', + action: 'append', + key: 'setup', + } as CodeBlock, + ], + }; + + const result = formatData(data, { + test: 'hello', + world: 'earth', + key: 404, + }); + const script = result.scripts![0] as CodeBlock; + expect(script.code).toEqual( + 'window["hoho"]=window["hoho"]||[];console.log("earth")', + ); + expect(result.html).toEqual( + '', + ); + }); }); describe('formatCode', () => { diff --git a/src/utils/index.ts b/src/utils/index.ts index a3bca1c..fa76f55 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -105,6 +105,7 @@ export function formatData(data: Data, args: Inputs): Output { (acc, script) => [ ...acc, ...(Array.isArray(script.params) ? script.params : []), + ...(script.optionalParams ? Object.keys(script.optionalParams) : []), ], [] as string[], ); @@ -152,11 +153,21 @@ export function formatData(data: Data, args: Inputs): Output { return isExternalScript(script) ? { ...script, - url: formatUrl(script.url, script.params, scriptUrlParamInputs), + url: formatUrl( + script.url, + allScriptParams, + scriptUrlParamInputs, + undefined, + script.optionalParams, + ), } : { ...script, - code: formatCode(script.code, scriptUrlParamInputs), + code: formatCode( + script.code, + scriptUrlParamInputs, + script.optionalParams, + ), }; }) : undefined, From f4a043174f013757871aaf0174e31f6b15614b48 Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Sat, 27 Jul 2024 10:33:40 +0200 Subject: [PATCH 7/7] fix: don't fallback if user value is null --- src/utils/index.test.ts | 8 ++++++++ src/utils/index.ts | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/utils/index.test.ts b/src/utils/index.test.ts index f25cf92..c98fbfe 100644 --- a/src/utils/index.test.ts +++ b/src/utils/index.test.ts @@ -322,6 +322,14 @@ describe('Utils', () => { }, output: `false`, }, + // boolean + { + input: '{{val}}', + params: { + val: null, + }, + output: `null`, + }, // undefined { input: 'window[{{l}}]=window[{{l}}]||[];', diff --git a/src/utils/index.ts b/src/utils/index.ts index fa76f55..bfb30be 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -56,7 +56,9 @@ export function formatCode( ) { return code.replace(/{{(.*?)}}/g, (match) => { const name = match.split(/{{|}}/).filter(Boolean)[0]; - return JSON.stringify(args?.[name] ?? optionalParams?.[name]); + return JSON.stringify( + args && name in args ? args?.[name] : optionalParams?.[name], + ); }); }