From f905f962992f5f42398f230a2f2a48ed51631beb Mon Sep 17 00:00:00 2001 From: Kartik Gupta Date: Mon, 22 Jul 2024 14:32:26 +0530 Subject: [PATCH] add kebab case validation to rename page handle (#10352) --- .../SidebarPageSelector/EditModal.jsx | 11 +++++++-- frontend/src/_helpers/utils.js | 23 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/frontend/src/Editor/LeftSidebar/SidebarPageSelector/EditModal.jsx b/frontend/src/Editor/LeftSidebar/SidebarPageSelector/EditModal.jsx index fb0dba2df2..31505fb862 100644 --- a/frontend/src/Editor/LeftSidebar/SidebarPageSelector/EditModal.jsx +++ b/frontend/src/Editor/LeftSidebar/SidebarPageSelector/EditModal.jsx @@ -3,6 +3,8 @@ import { Modal } from 'react-bootstrap'; import { Button } from '@/_ui/LeftSidebar'; import { Alert } from '@/_ui/Alert'; import { EditInput } from './EditInput'; +import { validateKebabCase } from '@/_helpers/utils'; +import _ from 'lodash'; export const EditModal = ({ slug, page, show, handleClose, updatePageHandle, darkMode }) => { const [pageHandle, setPageHandle] = useState(page.handle); @@ -17,9 +19,14 @@ export const EditModal = ({ slug, page, show, handleClose, updatePageHandle, dar if (pageHandle === page.handle) { return handleClose(); } - + const { isValid, error } = validateKebabCase(pageHandle); + if (!isValid) { + setError(error); + return; + } + const transformedPageHandle = _.kebabCase(pageHandle); setIsSaving(true); - updatePageHandle(page.id, pageHandle); + updatePageHandle(page.id, transformedPageHandle); setTimeout(() => { setIsSaving(false); return handleClose(); diff --git a/frontend/src/_helpers/utils.js b/frontend/src/_helpers/utils.js index c550ebe502..6164e2ba19 100644 --- a/frontend/src/_helpers/utils.js +++ b/frontend/src/_helpers/utils.js @@ -318,6 +318,29 @@ export function validateQueryName(name) { return nameRegex.test(name); } +export function validateKebabCase(slug) { + const pattern = /^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$/; + if (slug === '') { + return { isValid: false, error: 'Handle cannot be empty.' }; + } + if (!/^[a-zA-Z0-9]/.test(slug)) { + return { isValid: false, error: 'Handle must start with a letter or number.' }; + } + if (/[^a-zA-Z0-9-]/.test(slug)) { + return { isValid: false, error: 'Handle can only contain letters, numbers, and hyphens.' }; + } + if (/--/.test(slug)) { + return { isValid: false, error: 'Handle cannot contain consecutive hyphens.' }; + } + if (slug.endsWith('-')) { + return { isValid: false, error: 'Handle cannot end with a hyphen.' }; + } + if (!pattern.test(slug)) { + return { isValid: false, error: 'Handle does not match the kebab-case pattern.' }; + } + return { isValid: true, error: null }; +} + export const convertToKebabCase = (string) => string .replace(/([a-z])([A-Z])/g, '$1-$2')