Skip to content

Remove generic 'handle' prefix from Social Web UI function names#2485

Merged
obenland merged 2 commits intoadd/readerfrom
remove/handle-naming
Nov 18, 2025
Merged

Remove generic 'handle' prefix from Social Web UI function names#2485
obenland merged 2 commits intoadd/readerfrom
remove/handle-naming

Conversation

@obenland
Copy link
Member

Summary

Refactored event handler function names in the Social Web UI to be more descriptive and meaningful by removing the generic 'handle' prefix.

Changes

src/social-web/routes/feed/stage.tsx:

  • handleChangeSelectionchangeSelection

src/social-web/components/layout/index.tsx:

  • handleHashChangesyncUrlToState
  • handleSelectItemselectItem
  • handleCloseInspectorcloseInspector
  • handleNavigatenavigate

Test Plan

  • Verify feed page loads correctly
  • Test selecting items from the feed opens the inspector
  • Test closing the inspector works
  • Test navigation between sections (Feed, Following, Interactions)
  • Test browser back/forward buttons work correctly
  • Verify no console errors

Copilot AI review requested due to automatic review settings November 17, 2025 21:41
@obenland obenland self-assigned this Nov 17, 2025
@obenland obenland requested a review from a team November 17, 2025 21:41
@github-actions github-actions bot added [Feature] Collections [Feature] REST API [Feature] WP Admin [Focus] Editor Changes to the ActivityPub experience in the block editor labels Nov 17, 2025
getValue: ( { item }: { item: FeedPost } ) => {
// Strip HTML tags for plain text value (used for search/sort)
const text = item.excerpt?.rendered || item.content?.rendered || '';
const stripped = text.replace( /<[^>]*>/g, '' );

Check failure

Code scanning / CodeQL

Incomplete multi-character sanitization

This string may still contain [<script](1), which may cause an HTML element injection vulnerability.

Copilot Autofix

AI 4 months ago

The ideal fix is to use a well-tested library for HTML-to-text conversion (such as striptags or sanitize-html with options to allow no tags) rather than manual regular expressions, which are rarely robust for HTML parsing or sanitization. These libraries will reliably remove all HTML tags, including edge cases like nested or malformed tags.

If the project cannot depend on external libraries, another option is to repeatedly apply the same regex until no further replacements are possible OR to use the browser's own HTML parser to strip tags safely (e.g., by creating a temporary DOM element in a browser environment).

For the scope shown, the recommended change is to use striptags for line 18: Replace the regex-based method with the library method, ensuring proper import at the top of the file. This will fully and reliably remove all HTML tags.

Edits to be made:

  • Add the import for striptags at the top.
  • Change line 18 to: const stripped = striptags(text);

Suggested changeset 2
src/social-web/components/fields/content/index.tsx

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/social-web/components/fields/content/index.tsx b/src/social-web/components/fields/content/index.tsx
--- a/src/social-web/components/fields/content/index.tsx
+++ b/src/social-web/components/fields/content/index.tsx
@@ -1,5 +1,6 @@
 import { __ } from '@wordpress/i18n';
 import { decodeEntities } from '@wordpress/html-entities';
+import striptags from 'striptags';
 import type { Field } from '@wordpress/dataviews';
 import type { FeedPost } from '../../types';
 
@@ -15,7 +16,7 @@
 	getValue: ( { item }: { item: FeedPost } ) => {
 		// Strip HTML tags for plain text value (used for search/sort)
 		const text = item.excerpt?.rendered || item.content?.rendered || '';
-		const stripped = text.replace( /<[^>]*>/g, '' );
+		const stripped = striptags(text);
 		return decodeEntities( stripped );
 	},
 	render: ( { item }: { item: FeedPost } ) => {
EOF
@@ -1,5 +1,6 @@
import { __ } from '@wordpress/i18n';
import { decodeEntities } from '@wordpress/html-entities';
import striptags from 'striptags';
import type { Field } from '@wordpress/dataviews';
import type { FeedPost } from '../../types';

@@ -15,7 +16,7 @@
getValue: ( { item }: { item: FeedPost } ) => {
// Strip HTML tags for plain text value (used for search/sort)
const text = item.excerpt?.rendered || item.content?.rendered || '';
const stripped = text.replace( /<[^>]*>/g, '' );
const stripped = striptags(text);
return decodeEntities( stripped );
},
render: ( { item }: { item: FeedPost } ) => {
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -70,12 +70,12 @@
 		"@wordpress/primitives": "^4.31.0",
 		"@wordpress/scripts": "^30.23.0",
 		"@wordpress/url": "^4.22.0",
-		"@wordpress/views": "^1.0.0",
 		"@wordpress/viewport": "^6.32.0",
 		"@wordpress/views": "^1.0.0",
 		"prettier": "npm:wp-prettier@^3.0.3"
 	},
 	"dependencies": {
-		"clsx": "^2.1.1"
+		"clsx": "^2.1.1",
+		"striptags": "^3.2.0"
 	}
 }
EOF
@@ -70,12 +70,12 @@
"@wordpress/primitives": "^4.31.0",
"@wordpress/scripts": "^30.23.0",
"@wordpress/url": "^4.22.0",
"@wordpress/views": "^1.0.0",
"@wordpress/viewport": "^6.32.0",
"@wordpress/views": "^1.0.0",
"prettier": "npm:wp-prettier@^3.0.3"
},
"dependencies": {
"clsx": "^2.1.1"
"clsx": "^2.1.1",
"striptags": "^3.2.0"
}
}
This fix introduces these dependencies
Package Version Security advisories
striptags (npm) 3.2.0 None
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
getValue: ( { item }: { item: FeedPost } ) => {
// Strip HTML tags for plain text value
const text = item.excerpt?.rendered || item.content?.rendered || '';
const stripped = text.replace( /<[^>]*>/g, '' );

Check failure

Code scanning / CodeQL

Incomplete multi-character sanitization

This string may still contain [<script](1), which may cause an HTML element injection vulnerability.

Copilot Autofix

AI 4 months ago

To fix this problem robustly and in line with best practices, we should use a well-tested HTML sanitization library. For React/Node projects, one of the most popular is sanitize-html. This library removes all HTML tags and scripts from a string robustly, ensuring no fragments or malicious input remains after sanitization.

To minimize changes, we will replace the manual regex stripping of HTML tags with a call to sanitize-html. This should be done in both places in the file where .replace(/<[^>]*>/g, '') currently appears:

  • Line 14: In the getValue implementation.
  • Line 20: In the render implementation.

We will import sanitize-html at the top of the file.

No changes need to be made to the logic that follows, as the output is already run through decodeEntities and potentially .trim(), which both remain fine.

Suggested changeset 2
src/social-web/components/fields/excerpt/index.tsx

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/social-web/components/fields/excerpt/index.tsx b/src/social-web/components/fields/excerpt/index.tsx
--- a/src/social-web/components/fields/excerpt/index.tsx
+++ b/src/social-web/components/fields/excerpt/index.tsx
@@ -1,5 +1,6 @@
 import { __ } from '@wordpress/i18n';
 import { decodeEntities } from '@wordpress/html-entities';
+import sanitizeHtml from 'sanitize-html';
 import type { Field } from '@wordpress/dataviews';
 import type { FeedPost } from '../../types';
 
@@ -11,13 +12,13 @@
 	getValue: ( { item }: { item: FeedPost } ) => {
 		// Strip HTML tags for plain text value
 		const text = item.excerpt?.rendered || item.content?.rendered || '';
-		const stripped = text.replace( /<[^>]*>/g, '' );
+		const stripped = sanitizeHtml( text, { allowedTags: [], allowedAttributes: {} } );
 		return decodeEntities( stripped );
 	},
 	render: ( { item }: { item: FeedPost } ) => {
 		const excerpt = item.excerpt?.rendered || item.content?.rendered || '';
 		// Strip HTML tags, remove backslash escapes, and decode HTML entities
-		const stripped = excerpt.replace( /<[^>]*>/g, '' ).trim();
+		const stripped = sanitizeHtml( excerpt, { allowedTags: [], allowedAttributes: {} } ).trim();
 		const unescaped = stripped.replace( /\\(.)/g, '$1' );
 		const plainText = decodeEntities( unescaped );
 
EOF
@@ -1,5 +1,6 @@
import { __ } from '@wordpress/i18n';
import { decodeEntities } from '@wordpress/html-entities';
import sanitizeHtml from 'sanitize-html';
import type { Field } from '@wordpress/dataviews';
import type { FeedPost } from '../../types';

@@ -11,13 +12,13 @@
getValue: ( { item }: { item: FeedPost } ) => {
// Strip HTML tags for plain text value
const text = item.excerpt?.rendered || item.content?.rendered || '';
const stripped = text.replace( /<[^>]*>/g, '' );
const stripped = sanitizeHtml( text, { allowedTags: [], allowedAttributes: {} } );
return decodeEntities( stripped );
},
render: ( { item }: { item: FeedPost } ) => {
const excerpt = item.excerpt?.rendered || item.content?.rendered || '';
// Strip HTML tags, remove backslash escapes, and decode HTML entities
const stripped = excerpt.replace( /<[^>]*>/g, '' ).trim();
const stripped = sanitizeHtml( excerpt, { allowedTags: [], allowedAttributes: {} } ).trim();
const unescaped = stripped.replace( /\\(.)/g, '$1' );
const plainText = decodeEntities( unescaped );

package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -70,12 +70,12 @@
 		"@wordpress/primitives": "^4.31.0",
 		"@wordpress/scripts": "^30.23.0",
 		"@wordpress/url": "^4.22.0",
-		"@wordpress/views": "^1.0.0",
 		"@wordpress/viewport": "^6.32.0",
 		"@wordpress/views": "^1.0.0",
 		"prettier": "npm:wp-prettier@^3.0.3"
 	},
 	"dependencies": {
-		"clsx": "^2.1.1"
+		"clsx": "^2.1.1",
+		"sanitize-html": "^2.17.0"
 	}
 }
EOF
@@ -70,12 +70,12 @@
"@wordpress/primitives": "^4.31.0",
"@wordpress/scripts": "^30.23.0",
"@wordpress/url": "^4.22.0",
"@wordpress/views": "^1.0.0",
"@wordpress/viewport": "^6.32.0",
"@wordpress/views": "^1.0.0",
"prettier": "npm:wp-prettier@^3.0.3"
},
"dependencies": {
"clsx": "^2.1.1"
"clsx": "^2.1.1",
"sanitize-html": "^2.17.0"
}
}
This fix introduces these dependencies
Package Version Security advisories
sanitize-html (npm) 2.17.0 None
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
render: ( { item }: { item: FeedPost } ) => {
const excerpt = item.excerpt?.rendered || item.content?.rendered || '';
// Strip HTML tags, remove backslash escapes, and decode HTML entities
const stripped = excerpt.replace( /<[^>]*>/g, '' ).trim();

Check failure

Code scanning / CodeQL

Incomplete multi-character sanitization

This string may still contain [<script](1), which may cause an HTML element injection vulnerability.

Copilot Autofix

AI 4 months ago

The best fix is to use a well-tested library to sanitize or strip HTML from untrusted input rather than using a fragile regular expression. For React/JS projects, the sanitize-html or dompurify library are standard choices. Since we only need plain text (no HTML at all is allowed), a robust and minimal library like striptags is suitable for stripping ALL tags.
To fix the code:

  • Replace the manual .replace(/<[^>]*>/g, '') code (lines 14 and 20) with a call to striptags.
  • Import striptags at the top of the file.
  • Make the replacement in both the getValue and render methods, ensuring all HTML tags are stripped, regardless of input complexity.
  • No other changes are needed to logic or functionality.
  • striptags should be installed as a project dependency.

Suggested changeset 2
src/social-web/components/fields/excerpt/index.tsx

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/social-web/components/fields/excerpt/index.tsx b/src/social-web/components/fields/excerpt/index.tsx
--- a/src/social-web/components/fields/excerpt/index.tsx
+++ b/src/social-web/components/fields/excerpt/index.tsx
@@ -2,6 +2,7 @@
 import { decodeEntities } from '@wordpress/html-entities';
 import type { Field } from '@wordpress/dataviews';
 import type { FeedPost } from '../../types';
+import striptags from 'striptags';
 
 export const excerptField: Field< FeedPost > = {
 	id: 'excerpt.rendered',
@@ -11,13 +12,13 @@
 	getValue: ( { item }: { item: FeedPost } ) => {
 		// Strip HTML tags for plain text value
 		const text = item.excerpt?.rendered || item.content?.rendered || '';
-		const stripped = text.replace( /<[^>]*>/g, '' );
+		const stripped = striptags(text);
 		return decodeEntities( stripped );
 	},
 	render: ( { item }: { item: FeedPost } ) => {
 		const excerpt = item.excerpt?.rendered || item.content?.rendered || '';
 		// Strip HTML tags, remove backslash escapes, and decode HTML entities
-		const stripped = excerpt.replace( /<[^>]*>/g, '' ).trim();
+		const stripped = striptags(excerpt).trim();
 		const unescaped = stripped.replace( /\\(.)/g, '$1' );
 		const plainText = decodeEntities( unescaped );
 
EOF
@@ -2,6 +2,7 @@
import { decodeEntities } from '@wordpress/html-entities';
import type { Field } from '@wordpress/dataviews';
import type { FeedPost } from '../../types';
import striptags from 'striptags';

export const excerptField: Field< FeedPost > = {
id: 'excerpt.rendered',
@@ -11,13 +12,13 @@
getValue: ( { item }: { item: FeedPost } ) => {
// Strip HTML tags for plain text value
const text = item.excerpt?.rendered || item.content?.rendered || '';
const stripped = text.replace( /<[^>]*>/g, '' );
const stripped = striptags(text);
return decodeEntities( stripped );
},
render: ( { item }: { item: FeedPost } ) => {
const excerpt = item.excerpt?.rendered || item.content?.rendered || '';
// Strip HTML tags, remove backslash escapes, and decode HTML entities
const stripped = excerpt.replace( /<[^>]*>/g, '' ).trim();
const stripped = striptags(excerpt).trim();
const unescaped = stripped.replace( /\\(.)/g, '$1' );
const plainText = decodeEntities( unescaped );

package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -70,12 +70,12 @@
 		"@wordpress/primitives": "^4.31.0",
 		"@wordpress/scripts": "^30.23.0",
 		"@wordpress/url": "^4.22.0",
-		"@wordpress/views": "^1.0.0",
 		"@wordpress/viewport": "^6.32.0",
 		"@wordpress/views": "^1.0.0",
 		"prettier": "npm:wp-prettier@^3.0.3"
 	},
 	"dependencies": {
-		"clsx": "^2.1.1"
+		"clsx": "^2.1.1",
+		"striptags": "^3.2.0"
 	}
 }
EOF
@@ -70,12 +70,12 @@
"@wordpress/primitives": "^4.31.0",
"@wordpress/scripts": "^30.23.0",
"@wordpress/url": "^4.22.0",
"@wordpress/views": "^1.0.0",
"@wordpress/viewport": "^6.32.0",
"@wordpress/views": "^1.0.0",
"prettier": "npm:wp-prettier@^3.0.3"
},
"dependencies": {
"clsx": "^2.1.1"
"clsx": "^2.1.1",
"striptags": "^3.2.0"
}
}
This fix introduces these dependencies
Package Version Security advisories
striptags (npm) 3.2.0 None
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@obenland obenland force-pushed the remove/handle-naming branch from 0c71357 to 4ab7b6b Compare November 17, 2025 22:27
Renamed functions to better describe their purpose:
- handleChangeSelection → changeSelection
- handleHashChange → syncUrlToState
- handleSelectItem → selectItem
- handleCloseInspector → closeInspector
- handleNavigate → navigate
@obenland obenland force-pushed the remove/handle-naming branch from 4ab7b6b to bb28cb8 Compare November 17, 2025 22:38
@pfefferle
Copy link
Member

What about using striptags as proposed by @copilot ?

Copy link

Copilot AI commented Nov 18, 2025

@pfefferle I've opened a new pull request, #2486, to work on those changes. Once the pull request is ready, I'll request review from you.

@obenland
Copy link
Member Author

@pfefferle The github-advanced-security is from the initial version of the PR, when it was created against trunk instead of add/reader. It doesn't apply to the current version of this PR. I'm unable to remove the comments.

This could still use your review.

@pfefferle
Copy link
Member

what about the striptags recommendation?

@obenland
Copy link
Member Author

Could you link me to that recommendation so I can learn more about it?

@pfefferle
Copy link
Member

It is one of the recommendations of copilot!

@pfefferle
Copy link
Member

but it seems to be also for old code. let's merge it!

@obenland
Copy link
Member Author

🤷

image

@obenland obenland merged commit 309eb5a into add/reader Nov 18, 2025
3 checks passed
@obenland obenland deleted the remove/handle-naming branch November 18, 2025 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] WP Admin [Focus] Editor Changes to the ActivityPub experience in the block editor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants