diff --git a/lib/shared/markdown.js b/lib/shared/markdown.js --- a/lib/shared/markdown.js +++ b/lib/shared/markdown.js @@ -251,6 +251,47 @@ } const spoilerRegex: RegExp = /^\|\|([^\n]+?)\|\|/g; +const spoilerReplacement: string = '⬛⬛⬛'; + +function traverseASTForSpoilers(ast: SingleASTNode[]): SingleASTNode[] { + return traverseASTRecursively(ast, false); +} + +function traverseASTRecursively( + ast: SingleASTNode[], + isTextASpoiler: boolean, +): SingleASTNode[] { + return ast.map(node => { + return { + ...node, + content: replaceSpoilers(node.type, node.content, isTextASpoiler), + }; + }); +} + +function replaceSpoilers( + type: string, + content: string, + isTextASpoiler: boolean, +): SingleASTNode[] | string { + // Check if content is an array - if it is, we need to continue traversing + if (Array.isArray(content)) { + const isTypeASpoiler = type === 'spoiler'; + return traverseASTRecursively(content, isTextASpoiler || isTypeASpoiler); + } + // Text Node within a spoiler node (i.e. isTextASpoiler === true), + // so we replace the text with the spoiler replacement + if (type === 'text' && isTextASpoiler) { + return spoilerReplacement; + } + // Text Node outside of a spoiler node (i.e. isTextASpoiler === false), + // so we maintain the original text content + if (type === 'text') { + return content; + } + // All other instances of a node type + return content; +} export { paragraphRegex, @@ -272,4 +313,5 @@ matchList, parseList, matchMentions, + traverseASTForSpoilers, }; diff --git a/lib/shared/messages/text-message-spec.js b/lib/shared/messages/text-message-spec.js --- a/lib/shared/messages/text-message-spec.js +++ b/lib/shared/messages/text-message-spec.js @@ -16,7 +16,11 @@ import type { NotifTexts } from '../../types/notif-types'; import type { ThreadInfo } from '../../types/thread-types'; import type { RelativeUserInfo } from '../../types/user-types'; -import { type ASTNode, type SingleASTNode } from '../markdown'; +import { + type ASTNode, + type SingleASTNode, + traverseASTForSpoilers, +} from '../markdown'; import { threadIsGroupChat } from '../thread-utils'; import { stringForUser } from '../user-utils'; import type { @@ -85,8 +89,9 @@ messageTitle({ messageInfo, markdownRules }) { const { text } = messageInfo; const parser = SimpleMarkdown.parserFor(markdownRules); - const ast = parser(text, { disableAutoBlockNewlines: true }); - + const ast = traverseASTForSpoilers( + parser(text, { disableAutoBlockNewlines: true }), + ); return getFirstNonQuotedRawLine(ast).trim(); },