fix: harden article rich content rendering (#36) (thanks @crcatala)

This commit is contained in:
Peter Steinberger
2026-01-12 05:14:39 +00:00
parent 316cdf77be
commit 28695d2ef0
6 changed files with 121 additions and 25 deletions
+33
View File
@@ -0,0 +1,33 @@
import { describe, expect, it } from 'vitest';
import type { GraphqlTweetResult } from '../src/lib/twitter-client-types.js';
import { extractArticleText } from '../src/lib/twitter-client-utils.js';
describe('extractArticleText', () => {
it('does not duplicate title when rich content starts with a heading', () => {
const result = {
rest_id: '1',
article: {
title: 'Hello World',
article_results: {
result: {
title: 'Hello World',
content_state: {
blocks: [
{
key: '1',
type: 'header-one',
text: 'Hello World',
entityRanges: [],
inlineStyleRanges: [],
},
],
entityMap: [],
},
},
},
},
} as GraphqlTweetResult;
expect(extractArticleText(result)).toBe('# Hello World');
});
});
+29
View File
@@ -114,6 +114,27 @@ describe('renderContentState', () => {
expect(result).toBe('```bash\necho "hello"\n```');
});
it('handles entityMap object form', () => {
const result = renderContentState({
blocks: [
{
key: '1',
type: 'atomic',
text: ' ',
entityRanges: [{ key: 0, offset: 0, length: 1 }],
},
],
entityMap: {
0: {
type: 'MARKDOWN',
mutability: 'Mutable',
data: { markdown: '```js\nconsole.log("ok")\n```' },
},
},
});
expect(result).toBe('```js\nconsole.log("ok")\n```');
});
it('renders DIVIDER entity as horizontal rule', () => {
const result = renderContentState({
blocks: [
@@ -290,6 +311,14 @@ describe('renderContentState', () => {
expect(result).toBe('Content\n\nMore content');
});
it('handles missing entityRanges on text blocks', () => {
const result = renderContentState({
blocks: [{ key: '1', type: 'unstyled', text: 'Content' }],
entityMap: [],
});
expect(result).toBe('Content');
});
it('handles atomic block with missing entity gracefully', () => {
const result = renderContentState({
blocks: [