mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
Merge branch 'codex/fix/catalog-literal-symbol-preview'
This commit is contained in:
@@ -480,6 +480,22 @@ describe('CatalogRow', () => {
|
||||
expect(container.textContent).toContain('Text title: Plain thread body');
|
||||
});
|
||||
|
||||
it('preserves literal catalog teaser markers without applying body markdown styles', async () => {
|
||||
const post: TestComment = {
|
||||
cid: 'literal-markers',
|
||||
content: '>we got 5chan before Half Life 3\n*poisons u*',
|
||||
replyCount: 2,
|
||||
communityAddress: 'music-posting.eth',
|
||||
};
|
||||
|
||||
await renderWithRouter(createElement(CatalogRow, { row: [post] }), '/mu/catalog');
|
||||
|
||||
expect(container.textContent).toContain('>we got 5chan before Half Life 3');
|
||||
expect(container.textContent).toContain('*poisons u*');
|
||||
expect(container.querySelector('.greentext')).toBeNull();
|
||||
expect(container.querySelector('.spoilertext')).toBeNull();
|
||||
});
|
||||
|
||||
it('applies the estimated row height to the virtualization wrapper', async () => {
|
||||
const post: TestComment = {
|
||||
cid: 'estimated-post',
|
||||
|
||||
@@ -18,7 +18,7 @@ import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
|
||||
import useFetchGifFirstFrame from '../../hooks/use-fetch-gif-first-frame';
|
||||
import useHide from '../../hooks/use-hide';
|
||||
import { isCommentArchived } from '../../lib/utils/comment-moderation-utils';
|
||||
import { removeMarkdown } from '../../lib/utils/post-utils';
|
||||
import { CATALOG_PREVIEW_MARKDOWN_OPTIONS, removeMarkdown } from '../../lib/utils/post-utils';
|
||||
import PostMenuDesktop from '../post-desktop/post-menu-desktop';
|
||||
import styles from './catalog-row.module.css';
|
||||
import capitalize from 'lodash/capitalize';
|
||||
@@ -215,7 +215,7 @@ const CatalogPost = memo(
|
||||
{content ? ': ' : ''}
|
||||
</span>
|
||||
)}
|
||||
{content && removeMarkdown(content)}
|
||||
{content && removeMarkdown(content, CATALOG_PREVIEW_MARKDOWN_OPTIONS)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -105,6 +105,9 @@ describe('misc utils', () => {
|
||||
expect(removeMarkdown('[spoiler]secret[/spoiler]\n>greentext\n**bold** [label](https://example.com) `code` ```block``` ')).toBe(
|
||||
'secret\ngreentext\nbold label code block',
|
||||
);
|
||||
expect(removeMarkdown('>greentext\n*poisons u* _and underlines_', { preserveEmphasisMarkers: true, preserveGreentextMarkers: true })).toBe(
|
||||
'>greentext\n*poisons u* _and underlines_',
|
||||
);
|
||||
});
|
||||
|
||||
it('preloads theme asset URLs through Image instances', () => {
|
||||
|
||||
@@ -21,13 +21,31 @@ export function getTextColorForBackground(rgb: string): string {
|
||||
return brightness > 125 ? 'black' : 'white';
|
||||
}
|
||||
|
||||
export function removeMarkdown(md: string): string {
|
||||
return md
|
||||
export interface RemoveMarkdownOptions {
|
||||
preserveEmphasisMarkers?: boolean;
|
||||
preserveGreentextMarkers?: boolean;
|
||||
}
|
||||
|
||||
export const CATALOG_PREVIEW_MARKDOWN_OPTIONS: RemoveMarkdownOptions = {
|
||||
preserveEmphasisMarkers: true,
|
||||
preserveGreentextMarkers: true,
|
||||
};
|
||||
|
||||
export function removeMarkdown(md: string, options: RemoveMarkdownOptions = {}): string {
|
||||
let withoutMarkdown = md
|
||||
.replace(/\[spoiler\](.*?)\[\/spoiler\]/gis, '$1') // spoiler tags - keep inner text
|
||||
.replace(/\[([^\]]*?)\]\([^)]*\)/g, '$1') // [text](url) -> text
|
||||
.replace(/ /g, ' ') // -> space
|
||||
.replace(/^>\s*/gm, '') // greentext at line start
|
||||
.replace(/[*_]/g, '') // bold/italic markers
|
||||
.replace(/ /g, ' '); // -> space
|
||||
|
||||
if (!options.preserveGreentextMarkers) {
|
||||
withoutMarkdown = withoutMarkdown.replace(/^>\s*/gm, ''); // greentext at line start
|
||||
}
|
||||
|
||||
if (!options.preserveEmphasisMarkers) {
|
||||
withoutMarkdown = withoutMarkdown.replace(/[*_]/g, ''); // bold/italic markers
|
||||
}
|
||||
|
||||
return withoutMarkdown
|
||||
.replace(/```[\s\S]*?```/g, (m) => m.slice(3, -3)) // code blocks - keep content
|
||||
.replace(/`([^`]*)`/g, '$1') // inline code - keep content
|
||||
.trim();
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Comment } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { layout, layoutNextLine, prepare, prepareWithSegments } from '@chenglou/pretext';
|
||||
import { getCommentMediaInfo, getHasThumbnail } from './media-utils';
|
||||
import { EXPANDED_MEDIA_DATA_ATTRIBUTE } from './measurement-attributes';
|
||||
import { removeMarkdown } from './post-utils';
|
||||
import { CATALOG_PREVIEW_MARKDOWN_OPTIONS, removeMarkdown, type RemoveMarkdownOptions } from './post-utils';
|
||||
import { getRenderableMobileBacklinks } from './reply-backlink-utils';
|
||||
|
||||
export type ReplyVirtualizationMode = 'off' | 'estimates' | 'item-size';
|
||||
@@ -393,8 +393,8 @@ const getCatalogPostMediaHeight = (post: Comment | undefined, imageSize: Catalog
|
||||
return mediaBox ? mediaBox.height + CATALOG_CARD_MEDIA_GAP_HEIGHT : 0;
|
||||
};
|
||||
|
||||
const normalizeRenderedCommentText = (rawContent: string): string =>
|
||||
removeMarkdown(rawContent)
|
||||
const normalizeRenderedCommentText = (rawContent: string, markdownOptions?: RemoveMarkdownOptions): string =>
|
||||
removeMarkdown(rawContent, markdownOptions)
|
||||
.replace(/\n \n/g, '\n\n')
|
||||
.replace(/\n{3,}/g, '\n\n')
|
||||
.split('\n')
|
||||
@@ -402,7 +402,7 @@ const normalizeRenderedCommentText = (rawContent: string): string =>
|
||||
.join('\n')
|
||||
.trim();
|
||||
|
||||
const getVisibleCommentBodyText = (comment: Comment | undefined, maxContentChars: number): string => {
|
||||
const getVisibleCommentBodyText = (comment: Comment | undefined, maxContentChars: number, markdownOptions?: RemoveMarkdownOptions): string => {
|
||||
if (!comment) {
|
||||
return '';
|
||||
}
|
||||
@@ -412,7 +412,7 @@ const getVisibleCommentBodyText = (comment: Comment | undefined, maxContentChars
|
||||
const removed = comment.removed;
|
||||
const reason = comment.reason?.trim();
|
||||
const rawContent = comment.content || '';
|
||||
const content = normalizeRenderedCommentText(rawContent.slice(0, maxContentChars));
|
||||
const content = normalizeRenderedCommentText(rawContent.slice(0, maxContentChars), markdownOptions);
|
||||
|
||||
if (purged) {
|
||||
return 'This post was purged';
|
||||
@@ -433,13 +433,13 @@ const getVisibleCommentBodyText = (comment: Comment | undefined, maxContentChars
|
||||
return content;
|
||||
};
|
||||
|
||||
const getVisibleCommentText = (comment: Comment | undefined, maxContentChars: number): string => {
|
||||
const getVisibleCommentText = (comment: Comment | undefined, maxContentChars: number, markdownOptions?: RemoveMarkdownOptions): string => {
|
||||
if (!comment) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const title = comment.title?.trim();
|
||||
const content = getVisibleCommentBodyText(comment, maxContentChars);
|
||||
const content = getVisibleCommentBodyText(comment, maxContentChars, markdownOptions);
|
||||
|
||||
if (title && content) {
|
||||
return `${title}: ${content}`;
|
||||
@@ -455,7 +455,7 @@ const getVisibleCatalogText = (post: Comment | undefined, showOPComment: boolean
|
||||
return '';
|
||||
}
|
||||
|
||||
return getVisibleCommentText(post, 1600);
|
||||
return getVisibleCommentText(post, 1600, CATALOG_PREVIEW_MARKDOWN_OPTIONS);
|
||||
};
|
||||
|
||||
const getMobileBacklinkCount = (reply: Comment, backlinkMaps: ReplyBacklinkMaps): number => {
|
||||
|
||||
Reference in New Issue
Block a user