From 5e468d23d00b03a0479653fb6a27fb129f3edd6f Mon Sep 17 00:00:00 2001 From: Santiago Palenque Date: Wed, 4 Feb 2026 14:42:06 -0300 Subject: [PATCH 1/3] fix: change yup string validation for html --- .../form-templates/form-template-popup.js | 3 ++- .../form-templates/sponsor-inventory-popup.js | 5 +++-- .../components/sponsor-form-item-form.js | 3 ++- .../form-template/form-template-form.js | 3 ++- src/utils/yup.js | 16 ++++++++++++++++ 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/pages/sponsors-global/form-templates/form-template-popup.js b/src/pages/sponsors-global/form-templates/form-template-popup.js index ab8807838..51c4d049b 100644 --- a/src/pages/sponsors-global/form-templates/form-template-popup.js +++ b/src/pages/sponsors-global/form-templates/form-template-popup.js @@ -22,6 +22,7 @@ import AdditionalInputList from "../../../components/mui/formik-inputs/additiona import useScrollToError from "../../../hooks/useScrollToError"; import { formMetafieldsValidation, + requiredHTMLValidation, requiredStringValidation } from "../../../utils/yup"; @@ -53,7 +54,7 @@ const FormTemplateDialog = ({ validationSchema: yup.object().shape({ code: requiredStringValidation(), name: requiredStringValidation(), - instructions: requiredStringValidation(), + instructions: requiredHTMLValidation(), meta_fields: formMetafieldsValidation() }), enableReinitialize: true, diff --git a/src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js b/src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js index 3ce55e910..c79f4ee06 100644 --- a/src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js +++ b/src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js @@ -32,7 +32,8 @@ import { decimalValidation, requiredStringValidation, positiveNumberValidation, - formMetafieldsValidation + formMetafieldsValidation, + requiredHTMLValidation } from "../../../utils/yup"; import AdditionalInputList from "../../../components/mui/formik-inputs/additional-input/additional-input-list"; import MuiFormikQuantityField from "../../../components/mui/formik-inputs/mui-formik-quantity-field"; @@ -66,7 +67,7 @@ const SponsorItemDialog = ({ validationSchema: yup.object().shape({ code: requiredStringValidation(), name: requiredStringValidation(), - description: requiredStringValidation(), + description: requiredHTMLValidation(), images: yup.array(), early_bird_rate: decimalValidation(), standard_rate: decimalValidation(), diff --git a/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-item-form.js b/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-item-form.js index d2e350fc6..7176b4b96 100644 --- a/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-item-form.js +++ b/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-item-form.js @@ -18,6 +18,7 @@ import { decimalValidation, formMetafieldsValidation, positiveNumberValidation, + requiredHTMLValidation, requiredStringValidation } from "../../../../utils/yup"; import MuiFormikTextField from "../../../../components/mui/formik-inputs/mui-formik-textfield"; @@ -38,7 +39,7 @@ const SponsorFormItemForm = ({ initialValues, onSubmit }) => { validationSchema: yup.object({ code: requiredStringValidation(), name: requiredStringValidation(), - description: requiredStringValidation(), + description: requiredHTMLValidation(), early_bird_rate: decimalValidation(), standard_rate: decimalValidation(), onsite_rate: decimalValidation(), diff --git a/src/pages/sponsors/sponsor-forms-list-page/components/form-template/form-template-form.js b/src/pages/sponsors/sponsor-forms-list-page/components/form-template/form-template-form.js index aa82f8154..91383ce34 100644 --- a/src/pages/sponsors/sponsor-forms-list-page/components/form-template/form-template-form.js +++ b/src/pages/sponsors/sponsor-forms-list-page/components/form-template/form-template-form.js @@ -17,6 +17,7 @@ import { addIssAfterDateFieldValidator, formMetafieldsValidation, opensAtValidation, + requiredHTMLValidation, requiredStringValidation } from "../../../../../utils/yup"; import DropdownCheckbox from "../../../../../components/mui/dropdown-checkbox"; @@ -51,7 +52,7 @@ const FormTemplateForm = ({ initialValues: buildInitialValues(initialValues, summitTZ), validationSchema: yup.object({ code: requiredStringValidation(), - instructions: requiredStringValidation(), + instructions: requiredHTMLValidation(), opens_at: opensAtValidation(), expires_at: yup .date(T.translate("validation.date")) diff --git a/src/utils/yup.js b/src/utils/yup.js index d350ad232..56fa7cd59 100644 --- a/src/utils/yup.js +++ b/src/utils/yup.js @@ -87,6 +87,22 @@ export const rateCellValidation = () => export const requiredStringValidation = () => yup.string().required(T.translate("validation.required")); +const stripHtmlTags = (htmlString) => htmlString.replace(/<[^>]*>/g, ""); + +export const requiredHTMLValidation = () => + yup + .string() + .transform((value, originalValue) => { + // If the value is a string, strip HTML tags + if (typeof originalValue === "string") { + const strippedValue = stripHtmlTags(originalValue); + // Return the stripped value for subsequent validation + return strippedValue.trim(); // Also trim whitespace + } + return value; // Handle non-string values appropriately + }) + .required(T.translate("validation.required")); + export const positiveNumberValidation = () => numberValidation() .integer(T.translate("validation.integer")) From 29c0d4c86ecbdc644585d0113750b3c42e78e060 Mon Sep 17 00:00:00 2001 From: Santiago Palenque Date: Thu, 5 Feb 2026 11:05:01 -0300 Subject: [PATCH 2/3] fix: use existing method --- src/components/inputs/formik-text-editor.js | 5 ++--- .../__tests__/normalizeHtmlString.test.js} | 8 ++++---- .../normalize-html-string/index.js} | 5 +++-- src/utils/yup.js | 7 ++----- 4 files changed, 11 insertions(+), 14 deletions(-) rename src/{components/inputs/utils/__tests__/normalizeJoditEmpty.test.js => utils/normalize-html-string/__tests__/normalizeHtmlString.test.js} (60%) rename src/{components/inputs/utils/normalizeJoditEmpty.js => utils/normalize-html-string/index.js} (51%) diff --git a/src/components/inputs/formik-text-editor.js b/src/components/inputs/formik-text-editor.js index 346fb23cb..0e2ce7527 100644 --- a/src/components/inputs/formik-text-editor.js +++ b/src/components/inputs/formik-text-editor.js @@ -1,7 +1,7 @@ import React from "react"; import TextEditorV3 from "openstack-uicore-foundation/lib/components/inputs/editor-input-v3"; import { useFormikContext } from "formik"; -import normalizeJoditEmpty from "./utils/normalizeJoditEmpty"; +import normalizeHtmlString from "../../utils/normalize-html-string"; const FormikTextEditor = ({ name, ...props }) => { const { values, errors, touched, setFieldValue, setFieldTouched } = @@ -13,8 +13,7 @@ const FormikTextEditor = ({ name, ...props }) => { id={name} value={values[name]} onChange={(e) => { - const stringValue = normalizeJoditEmpty(e.target.value); - + const stringValue = normalizeHtmlString(e.target.value); setFieldValue(name, stringValue); }} onBlur={() => setFieldTouched(name, true)} diff --git a/src/components/inputs/utils/__tests__/normalizeJoditEmpty.test.js b/src/utils/normalize-html-string/__tests__/normalizeHtmlString.test.js similarity index 60% rename from src/components/inputs/utils/__tests__/normalizeJoditEmpty.test.js rename to src/utils/normalize-html-string/__tests__/normalizeHtmlString.test.js index fe9e66ec6..2e9befe99 100644 --- a/src/components/inputs/utils/__tests__/normalizeJoditEmpty.test.js +++ b/src/utils/normalize-html-string/__tests__/normalizeHtmlString.test.js @@ -1,14 +1,14 @@ import { expect, describe, it } from "@jest/globals"; -import normalizeJoditEmpty from "../normalizeJoditEmpty"; +import normalizeHtmlString from "../index"; -describe("normalizeJoditEmpty", () => { +describe("normalizeHtmlString", () => { it("normalizes an empty string that is surrounded by html tags", () => { const inputString = "


"; - expect(normalizeJoditEmpty(inputString)).toBe(""); + expect(normalizeHtmlString(inputString)).toBe(""); }); it("normalizes a string with content is returned without modifications", () => { const inputString = "

This is a content strign

"; - expect(normalizeJoditEmpty(inputString)).toBe(inputString); + expect(normalizeHtmlString(inputString)).toBe(inputString); }); }); diff --git a/src/components/inputs/utils/normalizeJoditEmpty.js b/src/utils/normalize-html-string/index.js similarity index 51% rename from src/components/inputs/utils/normalizeJoditEmpty.js rename to src/utils/normalize-html-string/index.js index 9816d54e5..5d8fa0439 100644 --- a/src/components/inputs/utils/normalizeJoditEmpty.js +++ b/src/utils/normalize-html-string/index.js @@ -1,6 +1,7 @@ -const normalizeJoditEmpty = (textInput) => { +// removes html tags if contained text is empty +const normalizeHtmlString = (textInput) => { const doc = new DOMParser().parseFromString(textInput, "text/html"); return doc.body.textContent.length === 0 ? "" : textInput; }; -export default normalizeJoditEmpty; +export default normalizeHtmlString; diff --git a/src/utils/yup.js b/src/utils/yup.js index 56fa7cd59..3d9c23799 100644 --- a/src/utils/yup.js +++ b/src/utils/yup.js @@ -1,6 +1,7 @@ import * as yup from "yup"; import T from "i18n-react"; import { METAFIELD_TYPES, fieldTypesWithOptions } from "./constants"; +import normalizeHtmlString from "./normalize-html-string"; export const addEmailListValidator = () => { yup.addMethod(yup.string, "emailList", function (errorMessage) { @@ -87,17 +88,13 @@ export const rateCellValidation = () => export const requiredStringValidation = () => yup.string().required(T.translate("validation.required")); -const stripHtmlTags = (htmlString) => htmlString.replace(/<[^>]*>/g, ""); - export const requiredHTMLValidation = () => yup .string() .transform((value, originalValue) => { // If the value is a string, strip HTML tags if (typeof originalValue === "string") { - const strippedValue = stripHtmlTags(originalValue); - // Return the stripped value for subsequent validation - return strippedValue.trim(); // Also trim whitespace + return normalizeHtmlString(originalValue); } return value; // Handle non-string values appropriately }) From 0336f919365cf38f8fd34d96b30d78e2d69f01ba Mon Sep 17 00:00:00 2001 From: smarcet Date: Fri, 6 Feb 2026 15:53:06 -0300 Subject: [PATCH 3/3] chore: add defensive fixes --- src/utils/normalize-html-string/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils/normalize-html-string/index.js b/src/utils/normalize-html-string/index.js index 5d8fa0439..7cfba9f84 100644 --- a/src/utils/normalize-html-string/index.js +++ b/src/utils/normalize-html-string/index.js @@ -1,7 +1,8 @@ // removes html tags if contained text is empty const normalizeHtmlString = (textInput) => { + if (!textInput) return ""; const doc = new DOMParser().parseFromString(textInput, "text/html"); - return doc.body.textContent.length === 0 ? "" : textInput; + return doc.body.textContent.trim().length === 0 ? "" : textInput; }; export default normalizeHtmlString;