0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-25 02:31:59 -05:00

Handle null values for post content & excerpt in admin-x-activitypub (#21989)

Handle null values for post content & excerpt in admin-x-activitypub

refs [TryGhost/ActivityPub#245](https://github.com/TryGhost/ActivityPub/pull/245)

In [TryGhost/ActivityPub#245](https://github.com/TryGhost/ActivityPub/pull/245) we changed the service to allow for `null` values for the `content` & `excerpt` field. This means we could potentially be passing `null` values to `stripHtml` which would cause the app to crash. This commit ensures we always pass a string to `stripHtml` as well as updating the types to reflect what the value can be
This commit is contained in:
Michael Barrett 2025-01-09 15:32:06 +00:00 committed by GitHub
parent ea127b29db
commit 20a1b64a15
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 12 additions and 12 deletions

View file

@ -1,6 +1,6 @@
{
"name": "@tryghost/admin-x-activitypub",
"version": "0.3.42",
"version": "0.3.43",
"license": "MIT",
"repository": {
"type": "git",

View file

@ -148,7 +148,7 @@ const getGroupDescription = (group: GroupedActivity): JSX.Element => {
return <>{actorText} liked your post <span className='font-semibold'>{group.object?.name || ''}</span></>;
case ACTIVITY_TYPE.CREATE:
if (group.object?.inReplyTo && typeof group.object?.inReplyTo !== 'string') {
let content = stripHtml(group.object.inReplyTo.content);
let content = stripHtml(group.object.inReplyTo.content || '');
// If the post has a name, use that instead of the content (short
// form posts do not have a name)

View file

@ -660,11 +660,11 @@ const ArticleModal: React.FC<ArticleModalProps> = ({
{object.type === 'Article' && (
<div className='border-b border-grey-200 pb-8' id='object-content'>
<ArticleBody
excerpt={object?.preview?.content}
excerpt={object?.preview?.content ?? ''}
fontFamily={fontFamily}
fontSize={FONT_SIZES[currentFontSizeIndex]}
heading={object.name}
html={object.content}
html={object.content ?? ''}
image={typeof object.image === 'string' ? object.image : object.image?.url}
lineHeight={LINE_HEIGHTS[currentLineHeightIndex]}
/>
@ -728,7 +728,7 @@ const ArticleModal: React.FC<ArticleModalProps> = ({
{modalSize === MODAL_SIZE_LG && object.type === 'Article' && (
<div className='pointer-events-none sticky bottom-0 flex items-end justify-between px-10 pb-[42px]'>
<div className='pointer-events-auto text-grey-600'>
{getReadingTime(object.content)}
{getReadingTime(object.content ?? '')}
</div>
<div className='pointer-events-auto text-grey-600 transition-all duration-200 ease-out'>
{readingProgress}%

View file

@ -264,7 +264,7 @@ const FeedItem: React.FC<FeedItemProps> = ({actor, object, layout, type, comment
<div className=''>
{(object.type === 'Article') && renderFeedAttachment(object, layout)}
{object.name && <Heading className='my-1 text-pretty leading-tight' level={5} data-test-activity-heading>{object.name}</Heading>}
{(object.preview && object.type === 'Article') ? <div className='line-clamp-3 leading-tight'>{object.preview.content}</div> : <div dangerouslySetInnerHTML={({__html: object.content})} className='ap-note-content text-pretty leading-[1.4285714286] tracking-[-0.006em] text-grey-900'></div>}
{(object.preview && object.type === 'Article') ? <div className='line-clamp-3 leading-tight'>{object.preview.content}</div> : <div dangerouslySetInnerHTML={({__html: object.content ?? ''})} className='ap-note-content text-pretty leading-[1.4285714286] tracking-[-0.006em] text-grey-900'></div>}
{(object.type === 'Note') && renderFeedAttachment(object, layout)}
{(object.type === 'Article') && <Button
className={`mt-3 self-start text-grey-900 transition-all hover:opacity-60`}
@ -318,7 +318,7 @@ const FeedItem: React.FC<FeedItemProps> = ({actor, object, layout, type, comment
<div className={`relative z-10 col-start-1 col-end-3 w-full gap-4`}>
<div className='flex flex-col'>
{object.name && <Heading className='mb-1 leading-tight' level={4} data-test-activity-heading>{object.name}</Heading>}
<div dangerouslySetInnerHTML={({__html: object.content})} className='ap-note-content-large text-pretty text-[1.6rem] tracking-[-0.011em] text-grey-900'></div>
<div dangerouslySetInnerHTML={({__html: object.content ?? ''})} className='ap-note-content-large text-pretty text-[1.6rem] tracking-[-0.011em] text-grey-900'></div>
{renderFeedAttachment(object, layout)}
<div className='space-between ml-[-7px] mt-3 flex'>
<FeedItemStats
@ -372,7 +372,7 @@ const FeedItem: React.FC<FeedItemProps> = ({actor, object, layout, type, comment
<div className='flex flex-col'>
{(object.type === 'Article') && renderFeedAttachment(object, layout)}
{object.name && <Heading className='my-1 text-pretty leading-tight' level={5} data-test-activity-heading>{object.name}</Heading>}
{(object.preview && object.type === 'Article') ? <div className='line-clamp-3 leading-tight'>{object.preview.content}</div> : <div dangerouslySetInnerHTML={({__html: object.content})} className='ap-note-content text-pretty tracking-[-0.006em] text-grey-900'></div>}
{(object.preview && object.type === 'Article') ? <div className='line-clamp-3 leading-tight'>{object.preview.content}</div> : <div dangerouslySetInnerHTML={({__html: object.content ?? ''})} className='ap-note-content text-pretty tracking-[-0.006em] text-grey-900'></div>}
{(object.type === 'Note') && renderFeedAttachment(object, layout)}
{(object.type === 'Article') && <Button
className={`mt-3 self-start text-grey-900 transition-all hover:opacity-60`}
@ -423,11 +423,11 @@ const FeedItem: React.FC<FeedItemProps> = ({actor, object, layout, type, comment
<Heading className='w-full max-w-[600px] text-pretty text-[1.6rem] font-semibold leading-tight' level={5} data-test-activity-heading>
{object.name ? object.name : (
<span dangerouslySetInnerHTML={{
__html: stripHtml(object.content)
__html: stripHtml(object.content || '')
}}></span>
)}
</Heading>
<div dangerouslySetInnerHTML={({__html: stripHtml(object.preview?.content ?? object.content)})} className='ap-note-content line-clamp-2 w-full max-w-[600px] text-pretty text-base leading-normal text-grey-800'></div>
<div dangerouslySetInnerHTML={({__html: stripHtml(object.preview?.content ?? object.content ?? '')})} className='ap-note-content line-clamp-2 w-full max-w-[600px] text-pretty text-base leading-normal text-grey-800'></div>
<span className='mt-1 shrink-0 whitespace-nowrap text-sm leading-none text-grey-600'>{object.content && `${getReadingTime(object.content)}`}</span>
</div>
<div className='invisible absolute right-4 top-1/2 z-[49] flex -translate-y-1/2 flex-col rounded-full bg-white p-1 shadow-md group-hover/article:visible'>

View file

@ -11,7 +11,7 @@ export type ObjectProperties = {
'@context': string | (string | object)[];
type: 'Article' | 'Link' | 'Note';
name: string;
content: string;
content: string | null;
url?: string | undefined;
attributedTo?: object | string | object[] | undefined;
image?: string | {
@ -20,7 +20,7 @@ export type ObjectProperties = {
type?: string;
};
published?: string;
preview?: {type: string, content: string};
preview?: {type: string, content: string | null};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[x: string]: any;
}