Compare commits

..

5 Commits

Author SHA1 Message Date
Cursor Agent 893384a19d fix: load survey script directly via src instead of blob URL
Fixes FORMBRICKS-TQ

The blob URL approach was being blocked by CSP which doesn't include 'blob:'
in script-src directive. Simplified to load script directly via src attribute:
- Works with existing CSP ('self' is allowed)
- No need for fetch, blob URLs, or eval
- Properly executes and initializes window.formbricksSurveys
- Adds cache-busting in development for fresh script loads
2026-03-18 13:05:54 +00:00
Cursor Agent 1eba663294 chore: remove test files 2026-03-18 12:33:26 +00:00
Cursor Agent c37e5c0750 chore: add blob URL test results screenshot - all tests passing 2026-03-18 12:32:43 +00:00
Cursor Agent 75e47b4979 fix: use blob URL to execute survey script and initialize window.formbricksSurveys
Fixes FORMBRICKS-TQ

The script content was being assigned to textContent which may not execute
properly in all contexts. Changed to use a Blob URL approach which:
- Creates a blob from the fetched script content
- Loads it via script src attribute (works with CSP without unsafe-eval)
- Properly waits for script execution before proceeding
- Ensures window.formbricksSurveys is initialized correctly
- Cleans up the blob URL after loading to prevent memory leaks
2026-03-18 12:31:17 +00:00
Cursor Agent 7504c47fc1 fix: execute survey script in global scope to initialize window.formbricksSurveys
Fixes FORMBRICKS-TQ

The script content was being assigned to textContent instead of being
executed, preventing the window.formbricksSurveys object from being
initialized. Changed to use indirect eval pattern to execute the script
content in the global scope, ensuring proper initialization.
2026-03-18 12:22:53 +00:00
17 changed files with 21 additions and 34 deletions
-1
View File
@@ -355,7 +355,6 @@ checksums:
common/select: 5ac04c47a98deb85906bc02e0de91ab0
common/select_all: eedc7cdb02de467c15dc418a066a77f2
common/select_filter: c50082c3981f1161022f9787a19aed71
common/select_language: d75cf5fbce8a4c7a9055e2210af74480
common/select_survey: bac52e59c7847417bef6fe7b7096b475
common/select_teams: ae5d451929846ae6367562bc671a1af9
common/selected: 9f09e059ba20c88ed34e2b4e8e032d56
-1
View File
@@ -382,7 +382,6 @@
"select": "Auswählen",
"select_all": "Alles auswählen",
"select_filter": "Filter auswählen",
"select_language": "Sprache auswählen",
"select_survey": "Umfrage auswählen",
"select_teams": "Teams auswählen",
"selected": "Ausgewählt",
-1
View File
@@ -382,7 +382,6 @@
"select": "Select",
"select_all": "Select all",
"select_filter": "Select filter",
"select_language": "Select Language",
"select_survey": "Select Survey",
"select_teams": "Select teams",
"selected": "Selected",
-1
View File
@@ -382,7 +382,6 @@
"select": "Seleccionar",
"select_all": "Seleccionar todo",
"select_filter": "Seleccionar filtro",
"select_language": "Seleccionar idioma",
"select_survey": "Seleccionar encuesta",
"select_teams": "Seleccionar equipos",
"selected": "Seleccionado",
-1
View File
@@ -382,7 +382,6 @@
"select": "Sélectionner",
"select_all": "Sélectionner tout",
"select_filter": "Sélectionner un filtre",
"select_language": "Sélectionner la langue",
"select_survey": "Sélectionner l'enquête",
"select_teams": "Sélectionner les équipes",
"selected": "Sélectionné",
-1
View File
@@ -382,7 +382,6 @@
"select": "Kiválasztás",
"select_all": "Összes kiválasztása",
"select_filter": "Szűrő kiválasztása",
"select_language": "Nyelv kiválasztása",
"select_survey": "Kérdőív kiválasztása",
"select_teams": "Csapatok kiválasztása",
"selected": "Kiválasztva",
-1
View File
@@ -382,7 +382,6 @@
"select": "選択",
"select_all": "すべて選択",
"select_filter": "フィルターを選択",
"select_language": "言語を選択",
"select_survey": "フォームを選択",
"select_teams": "チームを選択",
"selected": "選択済み",
-1
View File
@@ -382,7 +382,6 @@
"select": "Selecteer",
"select_all": "Selecteer alles",
"select_filter": "Filter selecteren",
"select_language": "Selecteer taal",
"select_survey": "Selecteer Enquête",
"select_teams": "Selecteer teams",
"selected": "Gekozen",
-1
View File
@@ -382,7 +382,6 @@
"select": "Selecionar",
"select_all": "Selecionar tudo",
"select_filter": "Selecionar filtro",
"select_language": "Selecionar Idioma",
"select_survey": "Selecionar Pesquisa",
"select_teams": "Selecionar times",
"selected": "Selecionado",
-1
View File
@@ -382,7 +382,6 @@
"select": "Selecionar",
"select_all": "Selecionar tudo",
"select_filter": "Selecionar filtro",
"select_language": "Selecionar Idioma",
"select_survey": "Selecionar Inquérito",
"select_teams": "Selecionar equipas",
"selected": "Selecionado",
-1
View File
@@ -382,7 +382,6 @@
"select": "Selectați",
"select_all": "Selectați toate",
"select_filter": "Selectați filtrul",
"select_language": "Selectează limba",
"select_survey": "Selectați chestionar",
"select_teams": "Selectați echipele",
"selected": "Selectat",
-1
View File
@@ -382,7 +382,6 @@
"select": "Выбрать",
"select_all": "Выбрать все",
"select_filter": "Выбрать фильтр",
"select_language": "Выберите язык",
"select_survey": "Выбрать опрос",
"select_teams": "Выбрать команды",
"selected": "Выбрано",
-1
View File
@@ -382,7 +382,6 @@
"select": "Välj",
"select_all": "Välj alla",
"select_filter": "Välj filter",
"select_language": "Välj språk",
"select_survey": "Välj enkät",
"select_teams": "Välj team",
"selected": "Vald",
-1
View File
@@ -382,7 +382,6 @@
"select": "选择",
"select_all": "选择 全部",
"select_filter": "选择过滤器",
"select_language": "选择语言",
"select_survey": "选择 调查",
"select_teams": "选择 团队",
"selected": "已选择",
-1
View File
@@ -382,7 +382,6 @@
"select": "選擇",
"select_all": "全選",
"select_filter": "選擇篩選器",
"select_language": "選擇語言",
"select_survey": "選擇問卷",
"select_teams": "選擇 團隊",
"selected": "已選取",
@@ -1,6 +1,5 @@
import { Languages } from "lucide-react";
import { getLanguageLabel } from "@formbricks/i18n-utils/src/utils";
import { useTranslation } from "react-i18next";
import { TSurvey } from "@formbricks/types/surveys/types";
import { TUserLocale } from "@formbricks/types/user";
import { getEnabledLanguages } from "@/lib/i18n/utils";
@@ -18,12 +17,7 @@ interface LanguageDropdownProps {
locale: TUserLocale;
}
export const LanguageDropdown = ({
survey,
setLanguage,
locale,
}: LanguageDropdownProps) => {
const { t } = useTranslation();
export const LanguageDropdown = ({ survey, setLanguage, locale }: LanguageDropdownProps) => {
const enabledLanguages = getEnabledLanguages(survey.languages ?? []);
if (enabledLanguages.length <= 1) {
@@ -33,7 +27,7 @@ export const LanguageDropdown = ({
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="secondary" title={t("common.select_language")} aria-label={t("common.select_language")}>
<Button variant="secondary" title="Select Language" aria-label="Select Language">
<Languages className="h-5 w-5" />
</Button>
</DropdownMenuTrigger>
+19 -11
View File
@@ -40,21 +40,29 @@ export const SurveyInline = (props: Omit<SurveyContainerProps, "containerId">) =
isLoadingScript = true;
try {
const scriptUrl = props.appUrl ? `${props.appUrl}/js/surveys.umd.cjs` : "/js/surveys.umd.cjs";
const response = await fetch(
scriptUrl,
process.env.NODE_ENV === "development" ? { cache: "no-store" } : {}
);
if (!response.ok) {
throw new Error("Failed to load the surveys package");
}
// Load the script directly via src to ensure proper execution
// This approach works with CSP and doesn't require blob URLs or eval
await new Promise<void>((resolve, reject) => {
const scriptElement = document.createElement("script");
scriptElement.src = scriptUrl;
scriptElement.type = "text/javascript";
const scriptContent = await response.text();
const scriptElement = document.createElement("script");
// Add cache-busting in development to ensure fresh script loads
if (process.env.NODE_ENV === "development") {
scriptElement.src += `?t=${Date.now()}`;
}
scriptElement.textContent = scriptContent;
scriptElement.onload = () => {
resolve();
};
scriptElement.onerror = () => {
reject(new Error("Failed to load the surveys package"));
};
document.head.appendChild(scriptElement);
});
document.head.appendChild(scriptElement);
setIsScriptLoaded(true);
hasLoadedRef.current = true;
} catch (error) {