From 36c39651a139308e799b85fd11efeee7153ad219 Mon Sep 17 00:00:00 2001 From: yeshan333 Date: Fri, 25 Apr 2025 21:28:28 +0800 Subject: [PATCH] feat(routes): add cline offcial blog route (#18892) * feat: add cline offcial blog route * refactor: try split code * refactor: reduce code and fix some desc --- lib/routes/cline/blog.ts | 80 +++++++++++++++++++++++++++++++++++ lib/routes/cline/namespace.ts | 13 ++++++ 2 files changed, 93 insertions(+) create mode 100644 lib/routes/cline/blog.ts create mode 100644 lib/routes/cline/namespace.ts diff --git a/lib/routes/cline/blog.ts b/lib/routes/cline/blog.ts new file mode 100644 index 0000000000..bcd17015d8 --- /dev/null +++ b/lib/routes/cline/blog.ts @@ -0,0 +1,80 @@ +import { load } from 'cheerio'; +import got from '@/utils/got'; +import { parseDate } from '@/utils/parse-date'; +import { Route, DataItem } from '@/types'; + +const rootUrl = 'https://cline.bot'; +const blogUrl = `${rootUrl}/blog`; + +// Extract article information from DOM +function extractArticlesFromDOM($) { + return $('article') + .toArray() + .map((article) => { + const element = $(article); + const title = element.find('h2').first().text().trim(); + const linkEl = element.find('a').first(); + const link = linkEl.attr('href'); + const fullLink = link ? (link.startsWith('http') ? link : `${rootUrl}${link.startsWith('/') ? link : `/${link}`}`) : ''; + + const metaEl = element.find('.text-xs.text-slate-500'); + const author = metaEl.find('span').first().text().trim(); + const dateStr = metaEl.find('span').eq(2).text().trim(); + const pubDate = dateStr ? parseDate(dateStr) : undefined; + + const summary = element.find('.text-slate-600').text().trim(); + const imgSrc = element.find('img').attr('src') || ''; + + return { + title, + link: fullLink, + pubDate, + author, + description: `

${summary}

`, + }; + }) + .filter((item) => item.title && item.link); +} + +async function handler() { + // Get blog homepage + const response = await got({ + method: 'get', + url: blogUrl, + }); + + const $ = load(response.data); + + const articles: DataItem[] = extractArticlesFromDOM($); + + if (articles.length === 0) { + throw new Error('No articles found.'); + } + + return { + title: 'Cline Official Blog', + link: blogUrl, + item: articles, + description: 'Cline Official Blog - AI Coding Assistant', + }; +} + +export const route: Route = { + path: '/blog', + categories: ['blog'], + example: '/cline/blog', + parameters: {}, + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + name: 'Blog', + maintainers: ['yeshan333'], + description: 'Cline Official Blog articles', + handler, + url: 'cline.bot/blog', +}; diff --git a/lib/routes/cline/namespace.ts b/lib/routes/cline/namespace.ts new file mode 100644 index 0000000000..6c47a86e12 --- /dev/null +++ b/lib/routes/cline/namespace.ts @@ -0,0 +1,13 @@ +export default { + name: 'Cline Offcial Blog', + url: 'cline.bot', + description: ` +Cline Offcial Blog. +Cline is an AI-powered coding assistant that runs in VS Code. It goes beyond simple autocompletion by reading and writing across multiple files, executing commands, and adapting to your workflow—like having a skilled developer pair-programming with you right inside your editor. +Cline understands your codebase context and can help with everything from small code edits to complex refactoring tasks. + `, + zh: { + name: 'Cline Offcial Blog', + description: 'Cline 官方博客', + }, +};