2
0

(settings) Parse custom head code to remove invalid text nodes

This commit is contained in:
Baptiste Arnaud
2023-07-11 19:17:38 +02:00
parent b2a973472f
commit 174d50ad1b
6 changed files with 48 additions and 28 deletions

View File

@@ -29,6 +29,7 @@
"libphonenumber-js": "1.10.30", "libphonenumber-js": "1.10.30",
"next": "13.4.3", "next": "13.4.3",
"nextjs-cors": "2.1.2", "nextjs-cors": "2.1.2",
"node-html-parser": "^6.1.5",
"nodemailer": "6.9.2", "nodemailer": "6.9.2",
"openai": "3.2.1", "openai": "3.2.1",
"openai-edge": "^1.1.0", "openai-edge": "^1.1.0",

View File

@@ -25,12 +25,13 @@ import {
setResultAsCompleted, setResultAsCompleted,
startBotFlow, startBotFlow,
} from '../helpers' } from '../helpers'
import { env, isDefined, omit } from '@typebot.io/lib' import { env, isDefined, isNotEmpty, omit } from '@typebot.io/lib'
import { prefillVariables } from '@/features/variables/prefillVariables' import { prefillVariables } from '@/features/variables/prefillVariables'
import { injectVariablesFromExistingResult } from '@/features/variables/injectVariablesFromExistingResult' import { injectVariablesFromExistingResult } from '@/features/variables/injectVariablesFromExistingResult'
import { deepParseVariables } from '@/features/variables/deepParseVariable' import { deepParseVariables } from '@/features/variables/deepParseVariable'
import { parseVariables } from '@/features/variables/parseVariables' import { parseVariables } from '@/features/variables/parseVariables'
import { saveLog } from '@/features/logs/saveLog' import { saveLog } from '@/features/logs/saveLog'
import { NodeType, parse } from 'node-html-parser'
export const sendMessage = publicProcedure export const sendMessage = publicProcedure
.meta({ .meta({
@@ -448,7 +449,9 @@ const parseStartClientSideAction = (
): NonNullable<ChatReply['clientSideActions']>[number] | undefined => { ): NonNullable<ChatReply['clientSideActions']>[number] | undefined => {
const blocks = typebot.groups.flatMap((group) => group.blocks) const blocks = typebot.groups.flatMap((group) => group.blocks)
const startPropsToInject = { const startPropsToInject = {
customHeadCode: typebot.settings.metadata.customHeadCode, customHeadCode: isNotEmpty(typebot.settings.metadata.customHeadCode)
? parseHeadCode(typebot.settings.metadata.customHeadCode)
: undefined,
gtmId: typebot.settings.metadata.googleTagManagerId, gtmId: typebot.settings.metadata.googleTagManagerId,
googleAnalyticsId: ( googleAnalyticsId: (
blocks.find( blocks.find(
@@ -479,3 +482,33 @@ const parseStartClientSideAction = (
startPropsToInject, startPropsToInject,
} }
} }
const parseHeadCode = (code: string) => {
code = injectTryCatch(code)
return parse(code)
.childNodes.filter((child) => child.nodeType !== NodeType.TEXT_NODE)
.join('\n')
}
const injectTryCatch = (headCode: string) => {
const scriptTagRegex = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi
const scriptTags = headCode.match(scriptTagRegex)
if (scriptTags) {
scriptTags.forEach(function (tag) {
const wrappedTag = tag.replace(
/(<script\b[^>]*>)([\s\S]*?)(<\/script>)/gi,
function (_, openingTag, content, closingTag) {
return `${openingTag}
try {
${content}
} catch (e) {
console.warn(e);
}
${closingTag}`
}
)
headCode = headCode.replace(tag, wrappedTag)
})
}
return headCode
}

View File

@@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/js", "name": "@typebot.io/js",
"version": "0.0.73", "version": "0.0.74",
"description": "Javascript library to display typebots on your website", "description": "Javascript library to display typebots on your website",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/react", "name": "@typebot.io/react",
"version": "0.0.73", "version": "0.0.74",
"description": "React library to display typebots on your website", "description": "React library to display typebots on your website",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",

View File

@@ -287,7 +287,6 @@ export const parseNumberWithCommas = (num: number) =>
num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
export const injectCustomHeadCode = (customHeadCode: string) => { export const injectCustomHeadCode = (customHeadCode: string) => {
customHeadCode = injectTryCatch(customHeadCode)
const headCodes = customHeadCode.split('</noscript>') const headCodes = customHeadCode.split('</noscript>')
headCodes.forEach((headCode) => { headCodes.forEach((headCode) => {
const [codeToInject, noScriptContentToInject] = headCode.split('<noscript>') const [codeToInject, noScriptContentToInject] = headCode.split('<noscript>')
@@ -307,29 +306,6 @@ export const injectCustomHeadCode = (customHeadCode: string) => {
}) })
} }
const injectTryCatch = (headCode: string) => {
const scriptTagRegex = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi
const scriptTags = headCode.match(scriptTagRegex)
if (scriptTags) {
scriptTags.forEach(function (tag) {
const wrappedTag = tag.replace(
/(<script\b[^>]*>)([\s\S]*?)(<\/script>)/gi,
function (_, openingTag, content, closingTag) {
return `${openingTag}
try {
${content}
} catch (e) {
console.warn(e);
}
${closingTag}`
}
)
headCode = headCode.replace(tag, wrappedTag)
})
}
return headCode
}
export const getAtPath = <T>(obj: T, path: string): unknown => { export const getAtPath = <T>(obj: T, path: string): unknown => {
if (isNotDefined(obj)) return undefined if (isNotDefined(obj)) return undefined
const pathParts = path.split('.') const pathParts = path.split('.')

10
pnpm-lock.yaml generated
View File

@@ -547,6 +547,9 @@ importers:
nextjs-cors: nextjs-cors:
specifier: 2.1.2 specifier: 2.1.2
version: 2.1.2(next@13.4.3) version: 2.1.2(next@13.4.3)
node-html-parser:
specifier: ^6.1.5
version: 6.1.5
nodemailer: nodemailer:
specifier: 6.9.2 specifier: 6.9.2
version: 6.9.2 version: 6.9.2
@@ -16474,6 +16477,13 @@ packages:
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
engines: {node: '>= 6.13.0'} engines: {node: '>= 6.13.0'}
/node-html-parser@6.1.5:
resolution: {integrity: sha512-fAaM511feX++/Chnhe475a0NHD8M7AxDInsqQpz6x63GRF7xYNdS8Vo5dKsIVPgsOvG7eioRRTZQnWBrhDHBSg==}
dependencies:
css-select: 5.1.0
he: 1.2.0
dev: false
/node-int64@0.4.0: /node-int64@0.4.0:
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
dev: true dev: true