diff --git a/lib/routes/theverge/index.ts b/lib/routes/theverge/index.ts
index 607949f7fe47b0..6d9a6b725ed6d1 100644
--- a/lib/routes/theverge/index.ts
+++ b/lib/routes/theverge/index.ts
@@ -1,8 +1,13 @@
import { Route } from '@/types';
import cache from '@/utils/cache';
-import got from '@/utils/got';
+import ofetch from '@/utils/ofetch';
import parser from '@/utils/rss-parser';
import { load } from 'cheerio';
+import path from 'node:path';
+import { art } from '@/utils/render';
+import { getCurrentPath } from '@/utils/helpers';
+
+const __dirname = getCurrentPath(import.meta.url);
export const route: Route = {
path: '/:hub?',
@@ -22,7 +27,7 @@ export const route: Route = {
source: ['theverge.com/:hub', 'theverge.com/'],
},
],
- name: 'The Verge',
+ name: 'Category',
maintainers: ['HenryQW', 'vbali'],
handler,
description: `| Hub | Hub name |
@@ -43,6 +48,37 @@ export const route: Route = {
Provides a better reading experience (full text articles) over the official one.`,
};
+const renderBlock = (b) => {
+ switch (b.__typename) {
+ case 'CoreEmbedBlockType':
+ return b.embedHtml;
+ case 'CoreGalleryBlockType':
+ return b.images.map((i) => `
${i.caption.html}`).join('');
+ case 'CoreHeadingBlockType':
+ return `${b.contents.html}`;
+ case 'CoreHTMLBlockType':
+ return b.markup;
+ case 'CoreImageBlockType':
+ return `
${b.caption.html}`;
+ case 'CoreListBlockType':
+ return `${b.ordered ? '
' : ''}${b.items.map((i) => `- ${i.contents.html}
`).join('')}${b.ordered ? '
' : ''}`;
+ case 'CoreParagraphBlockType':
+ return b.contents.html;
+ case 'CorePullquoteBlockType':
+ return `${b.contents.html}
`;
+ case 'CoreQuoteBlockType':
+ return `${b.children.map((child) => renderBlock(child)).join('')}
`;
+ case 'CoreSeparatorBlockType':
+ return '
';
+ case 'HighlightBlockType':
+ return b.children.map((c) => renderBlock(c)).join('');
+ case 'MethodologyAccordionBlockType':
+ return `${b.heading.html}
${b.sections.map((s) => `${s.heading.html}
${s.content.html}`).join('')}`;
+ default:
+ throw new Error(`Unsupported block type: ${b.__typename}`);
+ }
+};
+
async function handler(ctx) {
const link = ctx.req.param('hub') ? `https://www.theverge.com/${ctx.req.param('hub')}/rss/index.xml` : 'https://www.theverge.com/rss/index.xml';
@@ -51,73 +87,48 @@ async function handler(ctx) {
const items = await Promise.all(
feed.items.map((item) =>
cache.tryGet(item.link, async () => {
- const response = await got(item.link);
-
- const $ = load(response.data);
-
- const content = $('#content');
- const body = $('.duet--article--article-body-component-container');
-
- // 处理封面图片
-
- const cover = $('meta[property="og:image"]');
-
- if (cover.length > 0) {
- $(`
`).insertBefore(body[0].childNodes[0]);
- }
+ const response = await ofetch(item.link);
- // 处理封面视频
- $('div.l-col__main > div.c-video-embed, div.c-entry-hero > div.c-video-embed').each((i, e) => {
- const src = `https://volume.vox-cdn.com/embed/${e.attribs['data-volume-uuid']}?autoplay=false`;
+ const $ = load(response);
- $(``).insertBefore(body[0].childNodes[0]);
- });
+ const nextData = JSON.parse($('script#__NEXT_DATA__').text());
+ const node = nextData.props.pageProps.hydration.responses.find((x) => x.operationName === 'PostLayoutQuery' || x.operationName === 'StreamLayoutQuery').data.node;
- // 处理封面视频
- $('div.l-col__main > div.c-video-embed--media iframe').each((i, e) => {
- $(e).insertBefore(body[0].childNodes[0]);
+ let description = art(path.join(__dirname, 'templates/header.art'), {
+ featuredImage: node.featuredImage,
+ ledeMediaData: node.ledeMediaData,
});
- // 处理文章图片
- content.find('figure.e-image').each((i, e) => {
- let src, caption;
-
- // 处理 jpeg, png
- if ($(e).find('picture > source').length > 0) {
- src = $(e)
- .find('picture > img')[0]
- .attribs.srcset.match(/(?<=320w,).*?(?=520w)/g)[0]
- .trim();
- } else if ($(e).find('img.c-dynamic-image').length > 0) {
- // 处理 gif
- src = $(e).find('span.e-image__image')[0].attribs['data-original'];
- }
-
- // 处理 caption
- if ($(e).find('span.e-image__meta').length > 0) {
- caption = $(e).find('span.e-image__meta').text();
- }
-
- const figure = `
${caption ? `
${caption}` : ''}`;
-
- $(figure).insertBefore(e);
-
- $(e).remove();
- });
-
- const lede = $('.duet--article--lede h2:first');
- if (lede[0]) {
- lede.insertBefore(body[0].childNodes[0]);
+ description += node.blocks
+ .filter((b) => b.__typename !== 'NewsletterBlockType' && b.__typename !== 'RelatedPostsBlockType' && b.__typename !== 'ProductBlockType' && b.__typename !== 'TableOfContentsBlockType')
+ .map((b) => renderBlock(b))
+ .join('
');
+
+ if (node.__typename === 'StreamResourceType') {
+ description += node.posts.edges
+ .map(({ node: n }) => {
+ let d =
+ `` +
+ art(path.join(__dirname, 'templates/header.art'), {
+ ledeMediaData: n.ledeMediaData,
+ });
+ switch (n.__typename) {
+ case 'PostResourceType':
+ d += n.excerpt.map((e) => e.contents.html).join('
');
+ break;
+ case 'QuickPostResourceType':
+ d += n.blocks.map((b) => renderBlock(b)).join('
');
+ break;
+ default:
+ break;
+ }
+ return d;
+ })
+ .join('
');
}
- // 移除无用 DOM
- content.find('.duet--article--comments-join-the-conversation').remove();
- content.find('.duet--recirculation--related-list').remove();
- delete item.content;
- delete item.contentSnippet;
- delete item.isoDate;
-
- item.description = body.html();
+ item.description = description;
+ item.category = node.categories;
return item;
})
diff --git a/lib/routes/theverge/templates/header.art b/lib/routes/theverge/templates/header.art
new file mode 100644
index 00000000000000..e57a1dbf595134
--- /dev/null
+++ b/lib/routes/theverge/templates/header.art
@@ -0,0 +1,19 @@
+{{ if featuredImage }}
+
+
+ {{ featuredImage.image.title }}
+
+{{ /if }}
+
+{{ if ledeMediaData }}
+ {{ if ledeMediaData.__typename === 'LedeMediaEmbedType'}}
+ {{@ ledeMediaData.embedHtml }}
+ {{ else if ledeMediaData.__typename === 'LedeMediaImageType' && !featuredImage }}
+
+
+ {{ ledeMediaData.image.credit.plaintext || ledeMediaData.image.title }}
+
+ {{ else if ledeMediaData.__typename === 'LedeMediaVideoType'}}
+
+ {{ /if }}
+{{ /if }}