Skip to content

Commit

Permalink
Standardize Dialog Components, handle zero width spaces in common blo…
Browse files Browse the repository at this point in the history
…cks, fix flip cards in Firefox (#1368)

* Make PageEditor to remove non-breaking spaces from content on save

- Added `removeNonBreakingSpaces` utility to clean up uncommon space characters in paragraph blocks.
- Updated `PageEditor` to utilize the new utility when normalizing document content.
- Introduced unit tests for `removeNonBreakingSpaces` to ensure functionality across various block types and nested structures.

* Rename `removeNonBreakingSpaces` to `removeUncommonSpacesFromBlocks`

* Update space normalization in Gutenberg blocks to support more blocks

* Refactor FlipCard components, fix content showing through in Firefox

* Make images not interactive inside the flip cards

* Fix clicking on images

* WIP cleaning up dialogs

* Clean up dialogs

* Remove unused variables

* Add missing props

* FIx

* Update snapshots

* System test fixes

* More dialog cleanup
  • Loading branch information
nygrenh authored Jan 21, 2025
1 parent e636db2 commit 526c74b
Show file tree
Hide file tree
Showing 72 changed files with 1,205 additions and 989 deletions.
1 change: 1 addition & 0 deletions .stylelintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"function-no-unknown": null,
"media-query-no-invalid": null,
"declaration-property-value-no-unknown": null,
"at-rule-descriptor-no-unknown": null,
"selector-type-no-unknown": [
true,
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { css } from "@emotion/css"
import { InnerBlocks } from "@wordpress/block-editor"
import { BlockEditProps } from "@wordpress/blocks"
import React from "react"
Expand All @@ -16,7 +17,11 @@ const BackFlipCardEditor: React.FC<BlockEditProps<Record<string, never>>> = ({ c
title={t("back-card")}
explanation={t("back-card-explanation")}
>
<div>
<div
className={css`
width: 100%;
`}
>
<InnerBlocks allowedBlocks={ALLOWED_NESTED_BLOCKS} templateLock={false} />
</div>
</BlockPlaceholderWrapper>
Expand Down
7 changes: 6 additions & 1 deletion services/cms/src/blocks/FlipCard/FlipCardEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { css } from "@emotion/css"
import { InnerBlocks, InspectorControls } from "@wordpress/block-editor"
import { BlockEditProps, TemplateArray } from "@wordpress/blocks"
import React from "react"
Expand Down Expand Up @@ -31,7 +32,11 @@ const FlipCardEditor: React.FC<React.PropsWithChildren<BlockEditProps<FlipCardAt
<InspectorControls key="flip-card-settings">
<FlipBoxSizeCustomizer attributes={attributes} setAttributes={setAttributes} />
</InspectorControls>
<div>
<div
className={css`
width: 100%;
`}
>
<InnerBlocks
allowedBlocks={ALLOWED_NESTED_BLOCKS}
template={INNER_BLOCKS_TEMPLATE}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { css } from "@emotion/css"
import { InnerBlocks } from "@wordpress/block-editor"
import { BlockEditProps } from "@wordpress/blocks"
import React from "react"
Expand All @@ -16,7 +17,11 @@ const FrontFlipCardEditor: React.FC<BlockEditProps<Record<string, never>>> = ({
title={t("front-card")}
explanation={t("front-card-explanation")}
>
<div>
<div
className={css`
width: 100%;
`}
>
<InnerBlocks allowedBlocks={ALLOWED_NESTED_BLOCKS} templateLock={false} />
</div>
</BlockPlaceholderWrapper>
Expand Down
4 changes: 2 additions & 2 deletions services/cms/src/components/editors/PageEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { EditorContentDispatch, editorContentReducer } from "../../contexts/Edit
import usePageInfo from "../../hooks/usePageInfo"
import mediaUploadBuilder from "../../services/backend/media/mediaUpload"
import { fetchNextPageRoutingData } from "../../services/backend/pages"
import { modifyBlocks } from "../../utils/Gutenberg/modifyBlocks"
import { modifyBlocks, removeUncommonSpacesFromBlocks } from "../../utils/Gutenberg/modifyBlocks"
import { removeUnsupportedBlockType } from "../../utils/Gutenberg/removeUnsupportedBlockType"
import { denormalizeDocument, normalizeDocument } from "../../utils/documentSchemaProcessor"
import { makeSurePeerOrSelfReviewConfigAdditionalInstructionsAreNullInsteadOfEmptyLookingArray } from "../../utils/peerOrSelfReviewConfig"
Expand Down Expand Up @@ -89,7 +89,7 @@ const PageEditor: React.FC<React.PropsWithChildren<PageEditorProps>> = ({
setCurrentlySaving(true)
const dataToSave = normalizeDocument({
chapterId: data.chapter_id,
content: removeUnsupportedBlockType(content),
content: removeUncommonSpacesFromBlocks(removeUnsupportedBlockType(content)),
title,
urlPath: data.url_path,
})
Expand Down
2 changes: 1 addition & 1 deletion services/cms/src/styles/LocalStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { primaryFont } from "@/shared-module/common/styles"
const localCss = css`
.wp-block-button__link {
border-radius: 0;
${BASE_BUTTON_STYLES}
${BASE_BUTTON_STYLES({ variant: "primary", size: "large" })}
}
/* stylelint-disable-next-line block-no-empty */
.is-style-material-primary-button .wp-block-button__link {
Expand Down
64 changes: 64 additions & 0 deletions services/cms/src/utils/Gutenberg/modifyBlocks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable i18next/no-literal-string */
import { BlockInstance } from "@wordpress/blocks"

const UNCOMMON_SPACES_REGEX = /[\u00A0\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/g

export const modifyBlocks = (
blocks: BlockInstance[],
supportedBlocks: string[],
Expand All @@ -20,3 +22,65 @@ export const modifyBlocks = (
})
return modifiedBlocks
}

/**
* Internal helper function used by removeUncommonSpacesFromBlocks.
* Replaces various Unicode space characters (like non-breaking spaces,
* mathematical spaces, etc.) with standard spaces.
*
* @param text - The text to process
* @returns Text with standardized spaces
*/
const replaceUncommonSpaces = (text: string): string => {
return text.replace(UNCOMMON_SPACES_REGEX, " ")
}

/**
* Recursively removes uncommon space characters from paragraph blocks and returns a new array with the changes.
* This function creates deep copies and does not modify the original blocks.
*
* Handles the following Unicode space characters:
* - U+00A0 (Non-breaking space)
* - U+2000 to U+200A (Various width spaces)
* - U+2028 (Line separator)
* - U+2029 (Paragraph separator)
* - U+202F (Narrow non-breaking space)
* - U+205F (Medium mathematical space)
* - U+3000 (Ideographic space)
*
* @param blocks - Array of Gutenberg block instances to process
* @returns A new array of blocks with uncommon spaces replaced
*/
export const removeUncommonSpacesFromBlocks = (blocks: BlockInstance[]): BlockInstance[] => {
return blocks.map((block) => {
const newBlock = { ...block }
const attributes = { ...block.attributes }

// Handle different block types
switch (block.name) {
case "core/paragraph":
case "core/heading":
if (attributes.content) {
attributes.content = replaceUncommonSpaces(attributes.content)
}
break

case "moocfi/hero-section":
if (attributes.title) {
attributes.title = replaceUncommonSpaces(attributes.title)
}
if (attributes.subtitle) {
attributes.subtitle = replaceUncommonSpaces(attributes.subtitle)
}
break
}

newBlock.attributes = attributes

if (block.innerBlocks && block.innerBlocks.length > 0) {
newBlock.innerBlocks = removeUncommonSpacesFromBlocks(block.innerBlocks)
}

return newBlock
})
}
118 changes: 118 additions & 0 deletions services/cms/tests/utils/modifyBlocks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { BlockInstance } from "@wordpress/blocks"

import { removeUncommonSpacesFromBlocks } from "../../src/utils/Gutenberg/modifyBlocks"

describe("removeUncommonSpacesFromBlocks", () => {
it("should replace non-breaking spaces with regular spaces in paragraph blocks", () => {
const blocks: BlockInstance[] = [
{
name: "core/paragraph",
attributes: {
content: "Hello\u00A0World\u2003More\u3000Text",
},
clientId: "1",
isValid: true,
innerBlocks: [],
},
]

const result = removeUncommonSpacesFromBlocks(blocks)

expect(result[0].attributes.content).toBe("Hello World More Text")
expect(blocks[0].attributes.content).toBe("Hello\u00A0World\u2003More\u3000Text")
})

it("should replace non-breaking spaces in heading blocks", () => {
const blocks: BlockInstance[] = [
{
name: "core/heading",
attributes: {
content: "Header\u00A0Text\u2003Here",
level: 2,
},
clientId: "1",
isValid: true,
innerBlocks: [],
},
]

const result = removeUncommonSpacesFromBlocks(blocks)

expect(result[0].attributes.content).toBe("Header Text Here")
expect(blocks[0].attributes.content).toBe("Header\u00A0Text\u2003Here")
})

it("should replace non-breaking spaces in hero-section blocks", () => {
const blocks: BlockInstance[] = [
{
name: "moocfi/hero-section",
attributes: {
title: "Main\u00A0Title\u2003Here",
subtitle: "Sub\u00A0Title\u2003Text",
},
clientId: "1",
isValid: true,
innerBlocks: [],
},
]

const result = removeUncommonSpacesFromBlocks(blocks)

expect(result[0].attributes.title).toBe("Main Title Here")
expect(result[0].attributes.subtitle).toBe("Sub Title Text")
expect(blocks[0].attributes.title).toBe("Main\u00A0Title\u2003Here")
expect(blocks[0].attributes.subtitle).toBe("Sub\u00A0Title\u2003Text")
})

it("should handle nested blocks", () => {
const blocks: BlockInstance[] = [
{
name: "core/group",
attributes: {},
clientId: "1",
isValid: true,
innerBlocks: [
{
name: "core/paragraph",
attributes: {
content: "Nested\u00A0Content",
},
clientId: "2",
isValid: true,
innerBlocks: [],
},
],
},
]

const result = removeUncommonSpacesFromBlocks(blocks)

expect(result[0].innerBlocks[0].attributes.content).toBe("Nested Content")
expect(blocks[0].innerBlocks[0].attributes.content).toBe("Nested\u00A0Content")
})

it("should ignore unsupported block types", () => {
const blocks: BlockInstance[] = [
{
name: "core/image",
attributes: {
caption: "Image\u00A0Caption",
},
clientId: "1",
isValid: true,
innerBlocks: [],
},
]

const result = removeUncommonSpacesFromBlocks(blocks)

expect(result[0].attributes.caption).toBe("Image\u00A0Caption")
expect(blocks[0].attributes.caption).toBe("Image\u00A0Caption")
})

it("should handle empty blocks array", () => {
const blocks: BlockInstance[] = []
const result = removeUncommonSpacesFromBlocks(blocks)
expect(result).toEqual([])
})
})
Loading

0 comments on commit 526c74b

Please sign in to comment.