Skip to content

Commit

Permalink
Fix double-encoding of HTML entities in certain chat messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpd236 committed Dec 21, 2024
1 parent a3855d7 commit ab4f8ce
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 6 deletions.
15 changes: 11 additions & 4 deletions imports/client/components/ChatMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable react/no-array-index-key */
import * as he from "he";
import { marked } from "marked";
import React from "react";
import styled from "styled-components";
Expand Down Expand Up @@ -38,6 +39,9 @@ const StyledCodeBlock = styled.code`

// Renders a markdown token to React components.
const MarkdownToken = ({ token }: { token: marked.Token }) => {
// NOTE: Marked's lexer encodes using HTML entities in the text; see:
// https://github.com/markedjs/marked/discussions/1737
// We need to decode the text since React will apply its own escaping.
if (token.type === "text") {
return <PreWrapSpan>{token.raw}</PreWrapSpan>;
} else if (token.type === "space") {
Expand All @@ -48,8 +52,9 @@ const MarkdownToken = ({ token }: { token: marked.Token }) => {
const children = token.tokens.map((t, i) => (
<MarkdownToken key={i} token={t} />
));
if (token.raw.length > token.text.length) {
const trail = token.raw.substring(token.text.length);
const decodedText = he.decode(token.text);
if (token.raw.length > decodedText.length) {
const trail = token.raw.substring(decodedText.length);
if (trail.trim() === "") {
const syntheticSpace: marked.Tokens.Space = {
type: "space",
Expand Down Expand Up @@ -95,9 +100,11 @@ const MarkdownToken = ({ token }: { token: marked.Token }) => {
));
return <del>{children}</del>;
} else if (token.type === "codespan") {
return <code>{token.text}</code>;
const decodedText = he.decode(token.text);
return <code>{decodedText}</code>;
} else if (token.type === "code") {
return <StyledCodeBlock>{token.text}</StyledCodeBlock>;
const decodedText = he.decode(token.text);
return <StyledCodeBlock>{decodedText}</StyledCodeBlock>;
} else {
// Unhandled token types: just return the raw string with pre-wrap.
// This covers things like bulleted or numbered lists, which we explicitly
Expand Down
9 changes: 7 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"form-data": "^4.0.1",
"gaxios": "^6.7.1",
"glob": "^8.1.0",
"he": "^1.2.0",
"http-proxy": "^1.18.1",
"ip-address": "^10.0.1",
"logfmt": "^1.4.0",
Expand Down Expand Up @@ -84,6 +85,7 @@
"@types/element-resize-detector": "^1.1.6",
"@types/express": "^4.17.21",
"@types/glob": "^8.1.0",
"@types/he": "^1.2.3",
"@types/http-proxy": "^1.17.15",
"@types/jsbn": "^1.2.33",
"@types/lodash": "^4.17.13",
Expand Down

0 comments on commit ab4f8ce

Please sign in to comment.