refactor: fix lint issues

This commit is contained in:
TonyRL
2026-08-24 18:26:07 +08:00
parent 4f68c11adf
commit 0b9995bfbe
6 changed files with 30 additions and 88 deletions
+1 -1
View File
@@ -54,7 +54,7 @@ async function handler() {
link: currentUrl,
guid: `${currentUrl}#${device}-${matchVersion?.[1] ?? title}`,
description: $item.next().html(),
pubDate: parseDate(matchDate?.[1].replace(/(st|nd|rd|th)?,/, '')!, ['MMMM D YYYY', 'MMM D YYYY']),
pubDate: parseDate(matchDate![1].replace(/(st|nd|rd|th)?,/, ''), ['MMMM D YYYY', 'MMM D YYYY']),
};
});
+1 -1
View File
@@ -52,7 +52,7 @@ async function handler(ctx) {
const posts = await getPostByAccountId(account.id);
const items = posts.map((p) => ({
title: p.body?.replaceAll('\r\n', ' ').trim().split(' ', 1)[0]!,
title: p.body!.replaceAll('\r\n', ' ').trim().split(' ', 1)[0],
description: renderDescription(p.post_images, p.body!.replaceAll('\r\n', '<br>')),
pubDate: parseDate(p.published_at),
link: `${baseUrl}/posts/${p.id}`,
+1 -1
View File
@@ -115,7 +115,7 @@ async function handler(ctx) {
const baseUrl = 'https://www.patreon.com';
const link = `${baseUrl}/${creator}`;
const creatorData = await cache.tryGet<Pick<CreatorData, 'id' | 'attributes'>>(`patreon:creator:${creator}`, async () => {
const creatorData = await cache.tryGet<CreatorData>(`patreon:creator:${creator}`, async () => {
const response = await ofetch(link);
const $ = load(response);
+18 -53
View File
@@ -5,7 +5,7 @@ interface NodeAttrs {
href?: string;
level?: number;
src?: string;
alt?: string;
alt?: string | null;
}
interface ContentNode {
@@ -18,6 +18,8 @@ interface ContentNode {
const headingTags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const;
const blockTags = { paragraph: 'p', bulletList: 'ul', orderedList: 'ol', listItem: 'li' } as const;
const TextNode = ({ node }: { node: ContentNode }) => {
let content: JSX.Element | string = node.text ?? '';
const marks = node.marks ?? [];
@@ -25,78 +27,41 @@ const TextNode = ({ node }: { node: ContentNode }) => {
if (mark.type === 'bold') {
content = <strong>{content}</strong>;
} else if (mark.type === 'link' && mark.attrs?.href) {
content = <a href={String(mark.attrs.href)}>{content}</a>;
content = <a href={mark.attrs.href}>{content}</a>;
}
}
return <>{content}</>;
};
const ContentNode = ({ node }: { node: ContentNode }) => {
const Content = ({ node }: { node: ContentNode }) => {
switch (node.type) {
case 'doc':
return (
<>
{node.content?.map((child, index) => (
<ContentNode key={index} node={child} />
))}
</>
);
case 'paragraph':
return (
<p>
{node.content?.map((child, index) => (
<ContentNode key={index} node={child} />
))}
</p>
);
case 'text':
return <TextNode node={node} />;
case 'hardBreak':
return <br />;
case 'heading': {
const level = Math.min(6, Math.max(1, Number(node.attrs?.level) || 3));
const Tag = headingTags[level - 1];
case 'horizontalRule':
return <hr />;
case 'image':
return node.attrs?.src ? <img src={node.attrs.src} alt={node.attrs.alt ?? ''} /> : null;
case 'heading':
case 'paragraph':
case 'bulletList':
case 'orderedList':
case 'listItem': {
const Tag = node.type === 'heading' ? headingTags[Math.min(6, Math.max(1, node.attrs?.level ?? 3)) - 1] : blockTags[node.type];
return (
<Tag>
{node.content?.map((child, index) => (
<ContentNode key={index} node={child} />
<Content key={index} node={child} />
))}
</Tag>
);
}
case 'image':
return node.attrs?.src ? <img src={String(node.attrs.src)} alt={String(node.attrs.alt ?? '')} /> : null;
case 'bulletList':
return (
<ul>
{node.content?.map((child, index) => (
<ContentNode key={index} node={child} />
))}
</ul>
);
case 'orderedList':
return (
<ol>
{node.content?.map((child, index) => (
<ContentNode key={index} node={child} />
))}
</ol>
);
case 'listItem':
return (
<li>
{node.content?.map((child, index) => (
<ContentNode key={index} node={child} />
))}
</li>
);
case 'horizontalRule':
return <hr />;
default:
return (
<>
{node.content?.map((child, index) => (
<ContentNode key={index} node={child} />
<Content key={index} node={child} />
))}
</>
);
@@ -108,5 +73,5 @@ export const renderContentJson = (jsonString?: string | null): string => {
return '';
}
const doc: ContentNode = JSON.parse(jsonString);
return renderToString(<ContentNode node={doc} />);
return renderToString(<Content node={doc} />);
};
+8 -31
View File
@@ -1,28 +1,8 @@
export interface CreatorData {
meta: {
// desc: string;
// height: null;
imageUrl: string;
isPrivate: boolean;
// key: string;
// openGraph: OpenGraph;
// title: string;
url: string;
videoHeight: null;
// videoUrl: null;
videoWidth: null;
// viewport: string;
};
id: string;
attributes: IncludedAttributes;
}
// interface OpenGraph {
// desc: null;
// imageUrl: null;
// title: null;
// }
export interface PostData {
data: Datum[];
included: IncludedItem[];
@@ -39,7 +19,7 @@ interface Datum {
interface Attributes {
change_visibility_at: null;
comment_count: number;
comment_count?: number;
commenter_count: number;
created_at: string;
current_user_can_comment: boolean;
@@ -48,7 +28,7 @@ interface Attributes {
current_user_can_view: boolean;
current_user_comment_disallowed_reason: string;
has_ti_violation: boolean;
image: Image;
image: Image | null;
is_new_to_current_user: boolean;
is_paid: boolean;
like_count: number;
@@ -59,20 +39,20 @@ interface Attributes {
pledge_url: string;
pls_one_liners_by_category: any[]; // Items are `false`, so an empty array
post_level_suspension_removal_date: null;
post_metadata: PostMetadata;
post_metadata: PostMetadata | null;
post_type: string;
preview_asset_type: string | null;
published_at: string;
teaser_text_json_string?: string | null;
teaser_text_json_string: string | null;
title: string;
upgrade_url: string;
url: string;
video_preview: VideoPreview | null;
was_posted_by_campaign_owner: boolean;
thumbnail?: Thumbnail;
thumbnail: Thumbnail | null;
content_json_string?: string | null;
embed?: null;
post_file?: PostFile;
post_file?: PostFile | null;
}
interface Image {
@@ -170,8 +150,6 @@ interface Relationships {
user_defined_tags: UserDefinedTags;
video: MediaRelation;
attachments_media?: AttachmentsMedia;
// Custom relationships
video_preview?: MediaRelation;
}
interface AccessRules {
@@ -183,7 +161,7 @@ interface AccessRuleData {
type: string;
}
export interface MediaRelation {
interface MediaRelation {
data: MediaData | null;
links?: RelatedLink;
}
@@ -239,7 +217,6 @@ interface UserData {
interface UserDefinedTags {
data: UserDefinedTagData[];
attributes: IncludedAttributes;
}
interface UserDefinedTagData {
@@ -288,7 +265,7 @@ interface IncludedAttributes {
file_name?: string | null;
image_urls?: Image | null;
metadata?: Metadata;
download_url?: string;
download_url?: string | null;
// For 'tier'
access_rule_type?: string;
amount_cents?: number | null;
+1 -1
View File
@@ -20,7 +20,7 @@ function parseItems(tid: string, $: CheerioAPI) {
const pid = footer.find('.tipad a[title]').attr('id')?.slice(2);
return {
title: content?.split('<br>', 1)[0]!,
title: content!.split('<br>', 1)[0],
description: content,
author: $item
.find('b')