From 51c4783864bdaac3d0c341d4969ff2fc8f6645d7 Mon Sep 17 00:00:00 2001 From: jiaziling Date: Thu, 12 Sep 2024 14:01:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=87=E6=A1=A3=E5=A2=9E=E5=8A=A0asi?= =?UTF-8?q?de=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astro.config.ts | 3 + package.json | 5 + pnpm-lock.yaml | 70 ++++++++++ src/components/BlogAside.astro | 83 +++++++++++ src/components/CommentAside.astro | 44 ++++++ src/consts.ts | 207 ++++++++++++++++++++++++++++ src/content/blog/welcome.md | 16 +++ src/i18n/cs.ts | 48 +++++++ src/i18n/en.ts | 47 +++++++ src/i18n/utils.ts | 18 +++ src/i18n/zhCn.ts | 46 +++++++ src/remark-plugins/remark-asides.ts | 160 +++++++++++++++++++++ src/styles/global.css | 3 + src/styles/remark-aside.css | 110 +++++++++++++++ src/utils/formatDate.ts | 19 +++ src/utils/getCollectionByName.ts | 13 ++ src/utils/getCountByCategory.ts | 21 +++ src/utils/getUniqueTags.ts | 19 +++ src/utils/sortPostsByDate.ts | 9 ++ 19 files changed, 941 insertions(+) create mode 100644 src/components/BlogAside.astro create mode 100644 src/components/CommentAside.astro create mode 100644 src/consts.ts create mode 100644 src/i18n/cs.ts create mode 100644 src/i18n/en.ts create mode 100644 src/i18n/utils.ts create mode 100644 src/i18n/zhCn.ts create mode 100644 src/remark-plugins/remark-asides.ts create mode 100644 src/styles/remark-aside.css create mode 100644 src/utils/formatDate.ts create mode 100644 src/utils/getCollectionByName.ts create mode 100644 src/utils/getCountByCategory.ts create mode 100644 src/utils/getUniqueTags.ts create mode 100644 src/utils/sortPostsByDate.ts diff --git a/astro.config.ts b/astro.config.ts index 80d2494..836c6ef 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -3,6 +3,8 @@ import mdx from '@astrojs/mdx' import sitemap from '@astrojs/sitemap' import UnoCSS from 'unocss/astro' import vue from '@astrojs/vue' +import remarkDirective from 'remark-directive' +import { remarkAsides } from './src/remark-plugins/remark-asides.js' export default defineConfig({ site: 'https://jzllove9.github.io', @@ -25,5 +27,6 @@ export default defineConfig({ }, wrap: true, }, + remarkPlugins: [remarkDirective, remarkAsides({})], }, }) diff --git a/package.json b/package.json index c37775a..39ed96d 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,12 @@ "@astrojs/vue": "^4.5.0", "@unocss/reset": "^0.61.0", "astro": "^4.11.3", + "dayjs": "^1.11.13", + "hastscript": "^9.0.0", "nprogress": "^0.2.0", + "remark-directive": "^3.0.0", + "unist-util-remove": "^4.0.0", + "unist-util-visit": "^5.0.0", "unocss": "^0.61.0", "vue": "^3.4.31" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e5e6bf8..fa55fba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,15 +13,20 @@ specifiers: '@vueuse/core': ^10.11.0 astro: ^4.11.3 bumpp: ^9.4.1 + dayjs: ^1.11.13 eslint: ^8.57.0 eslint-plugin-astro: ^0.31.4 eslint-plugin-format: ^0.1.2 + hastscript: ^9.0.0 lint-staged: ^15.2.7 lodash-es: ^4.17.21 nprogress: ^0.2.0 prettier-plugin-astro: ^0.13.0 + remark-directive: ^3.0.0 simple-git-hooks: ^2.11.1 typescript: ^5.5.4 + unist-util-remove: ^4.0.0 + unist-util-visit: ^5.0.0 unocss: ^0.61.0 vue: ^3.4.31 @@ -32,7 +37,12 @@ dependencies: '@astrojs/vue': 4.5.0_astro@4.15.4+vue@3.5.3 '@unocss/reset': 0.61.9 astro: 4.15.4_typescript@5.5.4 + dayjs: 1.11.13 + hastscript: 9.0.0 nprogress: 0.2.0 + remark-directive: 3.0.0 + unist-util-remove: 4.0.0 + unist-util-visit: 5.0.0 unocss: 0.61.9 vue: 3.5.3_typescript@5.5.4 @@ -2976,6 +2986,10 @@ packages: /csstype/3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + /dayjs/1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + dev: false + /debug/3.2.7: resolution: {integrity: sha1-clgLfpFF+zm2Z2+cXl+xALk0F5o=} peerDependencies: @@ -4168,6 +4182,16 @@ packages: space-separated-tokens: 2.0.2 dev: false + /hastscript/9.0.0: + resolution: {integrity: sha512-jzaLBGavEDKHrc5EfFImKN7nZKKBdSLIdGvCwDZ9TfzbF2ffXiov8CKE445L2Z1Ek2t/m4SKQ2j6Ipv7NyUolw==} + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + dev: false + /hookable/5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} dev: false @@ -4694,6 +4718,21 @@ packages: unist-util-visit: 5.0.0 dev: false + /mdast-util-directive/3.0.0: + resolution: {integrity: sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==} + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + parse-entities: 4.0.1 + stringify-entities: 4.0.4 + unist-util-visit-parents: 6.0.1 + transitivePeerDependencies: + - supports-color + dev: false + /mdast-util-find-and-replace/3.0.1: resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} dependencies: @@ -4936,6 +4975,18 @@ packages: micromark-util-types: 2.0.0 dev: false + /micromark-extension-directive/3.0.1: + resolution: {integrity: sha512-VGV2uxUzhEZmaP7NSFo2vtq7M2nUD+WfmYQD+d8i/1nHbzE+rMy9uzTvUybBbNiVbrhOZibg3gbyoARGqgDWyg==} + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-factory-whitespace: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + parse-entities: 4.0.1 + dev: false + /micromark-extension-gfm-autolink-literal/2.1.0: resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} dependencies: @@ -5851,6 +5902,17 @@ packages: unified: 11.0.5 dev: false + /remark-directive/3.0.0: + resolution: {integrity: sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==} + dependencies: + '@types/mdast': 4.0.4 + mdast-util-directive: 3.0.0 + micromark-extension-directive: 3.0.1 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + dev: false + /remark-gfm/4.0.0: resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} dependencies: @@ -6576,6 +6638,14 @@ packages: unist-util-visit: 5.0.0 dev: false + /unist-util-remove/4.0.0: + resolution: {integrity: sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==} + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: false + /unist-util-stringify-position/2.0.3: resolution: {integrity: sha1-zOO/oc34W6c3XR1bF73Eytqb2do=} dependencies: diff --git a/src/components/BlogAside.astro b/src/components/BlogAside.astro new file mode 100644 index 0000000..845583f --- /dev/null +++ b/src/components/BlogAside.astro @@ -0,0 +1,83 @@ +--- +import CommentAside from './CommentAside.astro' +import { comment } from '../consts' +import { getCollectionByName } from '../utils/getCollectionByName' +import getUniqueTags from '../utils/getUniqueTags' +import getCountByCategory from '../utils/getCountByCategory' +import { sortPostsByDate } from '../utils/sortPostsByDate' +import { site } from '../consts' +import { t } from '../i18n/utils' +const blogs = await getCollectionByName('blog') +let tagArr = getUniqueTags(blogs) +let categoryCount = getCountByCategory(blogs) +let sortPosts = await sortPostsByDate(blogs) +let resultPosts = sortPosts.splice(0, site.recentBlogSize) +--- + +
+ { + Object.keys(categoryCount).length > 0 && ( +
+ + {t('sidebar.categories')} +
+ ) + } + { + Object.keys(categoryCount).map((category) => ( + + {(category === 'uncategorized' ? t('sidebar.uncategorized') : category) + ' (' + categoryCount[category] + ')'} + + )) + } +
+
+ { + tagArr.length > 0 && ( +
+ + {t('sidebar.tags')} +
+ ) + } +
+ { + tagArr && + tagArr.map((tag: any) => ( + + {tag} + + )) + } +
+
+ +
+
+ + {t('sidebar.recentArticle')} +
+
+ { + resultPosts.map((post: any) => ( + + {post.data.title} + + )) + } +
+
+ +{comment.enable && comment.type === 'waline' && } diff --git a/src/components/CommentAside.astro b/src/components/CommentAside.astro new file mode 100644 index 0000000..0b51320 --- /dev/null +++ b/src/components/CommentAside.astro @@ -0,0 +1,44 @@ +--- +import { comment } from '../consts' +import { t } from '../i18n/utils' +--- + +{ + comment.enable && comment.type === 'waline' && ( +
+
+ + {t('sidebar.recentComments')} +
+
+
+ ) +} + + diff --git a/src/consts.ts b/src/consts.ts new file mode 100644 index 0000000..06b1463 --- /dev/null +++ b/src/consts.ts @@ -0,0 +1,207 @@ +// Place any global data in this file. +// You can import this data from anywhere in your site by using the `import` keyword. + +/** + * title {string} website title + * favicon {string} website favicon url + * description {string} website description + * author {string} author + * avatar {string} Avatar used in the profile + * motto {string} used in the profile + * url {string} Website link + * recentBlogSize {number} Number of recent articles displayed in the sidebar + * archivePageSize {number} Number of articles on archive pages + * postPageSize {number} Number of articles on blog pages + * feedPageSize {number} Number of articles on feed pages + * beian {string} Chinese policy + */ +export const site = { + title: 'Astro Theme Yi', // required + favicon: '/favicon.svg', // required + description: 'Welcome to my independent blog website! ', + author: 'Astro-Yi', // required + avatar: '/avatar.png', // required + url: 'https://xxxxxx.com', // required + motto: 'Actions speak louder than words.', + recentBlogSize: 5, + archivePageSize: 25, + postPageSize: 10, + feedPageSize: 20, + beian: '', +} + +/** + * busuanzi {boolean} link: https://busuanzi.ibruce.info/ + * lang {string} Default website language + * codeFoldingStartLines {number} + * ga {string|false} + */ +export const config = { + busuanzi: false, + lang: 'en', // en | zh-cn | cs + codeFoldingStartLines: 16, // Need to re-run the project to take effect + ga: false, // If you want to integrate with Google Analytics, just enter your GA-ID here. +} + +/** + * Navigator + * name {string} + * iconClass {string} icon style + * href {string} link url + * target {string} optional "_self|_blank" open in current window / open in new window + */ +export const categories = [ + { + name: 'Blog', + iconClass: 'ri-draft-line', + href: '/blog/1', + }, + { + name: 'Feed', + iconClass: 'ri-lightbulb-flash-line', + href: '/feed/1', + }, + { + name: 'Archive', + iconClass: 'ri-archive-line', + href: '/archive/1', + }, + { + name: 'Message', + iconClass: 'ri-chat-1-line', + href: '/message', + }, + { + name: 'Search', + iconClass: 'ri-search-line', + href: '/search', + }, + { + name: 'More', + iconClass: 'ri-more-fill', + href: 'javascript:void(0);', + children: [ + { + name: 'About', + iconClass: 'ri-information-line', + href: '/about', + }, + { + name: 'Friends', + iconClass: 'ri-user-5-line', + href: '/friends', + target: '_self', + }, + ], + }, +] + +/** + * Personal link address + */ +export const infoLinks = [ + { + icon: 'ri-telegram-fill', + name: 'telegram', + outlink: 'xxxxxxx', + }, + { + icon: 'ri-twitter-fill', + name: 'twitter', + outlink: 'xxxxxxx', + }, + { + icon: 'ri-instagram-fill', + name: 'instagram', + outlink: 'xxxxxxx', + }, + { + icon: 'ri-github-fill', + name: 'github', + outlink: 'xxxxxxx', + }, + { + icon: 'ri-rss-fill', + name: 'rss', + outlink: 'xxxxxxx', + }, +] + +/** + * donate + * enable {boolean} + * tip {string} + * wechatQRCode: Image addresses should be placed in the public directory. + * alipayQRCode: Image addresses should be placed in the public directory. + * paypalUrl {string} + */ +export const donate = { + enable: false, + tip: 'Thanks for the coffee !!!☕', + wechatQRCode: '/WeChatQR.png', + alipayQRCode: '/AliPayQR.png', + paypalUrl: 'https://paypal.me/xxxxxxxxxx', +} + +/** + * Friendship Links Page + * name {string} + * url {string} + * avatar {string} + * description {string} + */ +export const friendshipLinks + = [ + // { + // name: "Cirry's Blog", + // url: 'https://cirry.cn', + // avatar: "https://cirry.cn/avatar.png", + // description: '前端开发的日常' + // }, + ] + +/** + * Comment Feature + * enable {boolean} + * type {string} required waline | giscus + * walineConfig.serverUrl {string} server link + * walineConfig.lang {string} link: https://waline.js.org/guide/features/i18n.html + * walineConfig.pageSize {number} number of comments per page. default 10 + * walineConfig.wordLimit {number} Comment word s limit. When a single number is filled in, it 's the maximum number of comment words. No limit when set to 0 + * walineConfig.count {number} recent comment numbers + * walineConfig.pageview {boolean} display the number of page views and comments of the article + * walineConfig.reaction {string | string[]} Add emoji interaction function to the article + * walineConfig.requiredMeta {string[]} Set required fields, default anonymous + * walineConfig.whiteList {string[]} set some pages not to display reaction + */ +export const comment = { + enable: false, + type: 'giscus', // waline | giscus, + walineConfig: { + serverUrl: '', + lang: 'en', + pageSize: 20, + wordLimit: '', + count: 5, + pageview: true, + reaction: true, + requiredMeta: ['nick', 'mail'], + whiteList: ['/message/', '/friends/'], + }, + + // giscus config + giscusConfig: { + 'data-repo': '', + 'data-repo-id': '', + 'data-category': '', + 'data-category-id': '', + 'data-mapping': '', + 'data-strict': '', + 'data-reactions-enabled': '', + 'data-emit-metadata': '', + 'data-input-position': '', + 'data-theme': '', + 'data-lang': '', + 'crossorigin': '', + }, +} diff --git a/src/content/blog/welcome.md b/src/content/blog/welcome.md index 82a40b3..8edf775 100644 --- a/src/content/blog/welcome.md +++ b/src/content/blog/welcome.md @@ -7,3 +7,19 @@ date: 2024-09-09 ### 欢迎 欢迎来到我的博客,这里将分享一些我学习的心得体会,以及一些生活中的感悟。 + +:::tip[Customized Title] +hello world +::: + +:::danger[Customized Title] +hello world +::: + +:::note[Customized Title] +hello world +::: + +:::warning[Customized Title] +hello world +::: \ No newline at end of file diff --git a/src/i18n/cs.ts b/src/i18n/cs.ts new file mode 100644 index 0000000..9d2e530 --- /dev/null +++ b/src/i18n/cs.ts @@ -0,0 +1,48 @@ +import 'dayjs/locale/cs' + +export const cs = { + 'aside.caution': 'varování', + 'aside.danger': 'nouze', + 'aside.note': 'vzít na vědomí', + 'aside.tip': 'upozornit na něco', + 'blog.tableOfContent': 'Obsah', + 'feed.next': 'Další', + 'feed.previous': 'Předchozí', + 'feed.publishedIn': 'Publikováno v', + 'footer.articleAuthor': 'Autor článku', + 'footer.articleTitle': 'Název článku', + 'footer.busuanziSitePV': 'Zobrazení stránky:', + 'footer.busuanziSitePVUnit': '', + 'footer.busuanziSiteUV': 'Celkový počet návštěvníků:', + 'footer.busuanziSiteUVUnit': '', + 'footer.copyrightOne': 'Oznámení o autorských právech: Tento článek je licencován pod', + 'footer.copyrightThree': '', + 'footer.copyrightTwo': '„Attribution-NonCommercial-ShareAlike 4.0 International“', + 'footer.originalLink': 'Původní odkaz', + 'footer.releaseTime': 'Čas vydání', + 'footer.sitemap': 'Mapa stránek', + 'home.goBack': 'Jít zpět', + 'home.moreArticles': 'Více článků', + 'home.readMore': 'Číst dál', + 'home.sticky': 'Připíchnuto', + 'message.welcomeTips': 'Zanechte stopu!', + 'message.welcome': 'Vítejte', + 'pagination.total': 'Celkem', + 'pagination.unit': 'Stránky', + 'post.dateFormat': 'D. MMMM YYYY', + 'post.lastUpdated': 'Poslední aktualizace', + 'search.labelOne': 'Zobrazení článků pod', + 'search.labelTwo': '', + 'search.placeholder': 'Zadejte klíčová slova názvu nebo abstraktu', + 'search.searchLabelOne': 'Nalezeno ', + 'search.searchLabelTwo': ' článek(ů) celkem', + 'search.search': 'Hledat', + 'sidebar.categories': 'Kategorie', + 'sidebar.recentArticle': 'Nedávné články', + 'sidebar.recentComments': 'Nedávné komentáře', + 'sidebar.tags': 'Štítky', + 'sidebar.uncategorized': 'nekategorizované', + 'title.draft': 'návrh', + 'title.minutes': ' Minut', + 'title.words': ' Slov', +} diff --git a/src/i18n/en.ts b/src/i18n/en.ts new file mode 100644 index 0000000..68c9b3f --- /dev/null +++ b/src/i18n/en.ts @@ -0,0 +1,47 @@ +export const en = { + 'aside.caution': 'Caution', + 'aside.danger': 'Danger', + 'aside.note': 'Note', + 'aside.tip': 'Tip', + 'blog.tableOfContent': 'Table of Contents', + 'feed.next': 'Next', + 'feed.previous': 'Previous', + 'feed.publishedIn': 'Published in', + 'footer.articleAuthor': 'Article author', + 'footer.articleTitle': 'Article title', + 'footer.busuanziSitePV': 'Page views:', + 'footer.busuanziSitePVUnit': '', + 'footer.busuanziSiteUV': 'Total visitors:', + 'footer.busuanziSiteUVUnit': '', + 'footer.copyrightOne': 'Copyright notice: This article is licensed under the', + 'footer.copyrightThree': '', + 'footer.copyrightTwo': '「Attribution-NonCommercial-ShareAlike 4.0 International」', + 'footer.originalLink': 'Original link', + 'footer.releaseTime': 'Release time', + 'footer.sitemap': 'Sitemap', + 'home.goBack': 'Go back', + 'home.moreArticles': 'More articles', + 'home.readMore': 'Read more', + 'home.sticky': 'Sticky', + 'message.welcome': 'Welcome', + 'message.welcomeTips': 'Leave a footprint!', + 'pagination.total': 'Total', + 'pagination.unit': 'Pages', + 'post.dateFormat': 'Do MMMM YYYY', + 'post.lastUpdated': 'Last updated', + 'remark.open': 'Open', + 'search.labelOne': 'Viewing articles under the ', + 'search.labelTwo': '', + 'search.placeholder': 'Enter title or abstract keywords', + 'search.search': 'Search', + 'search.searchLabelOne': 'Found ', + 'search.searchLabelTwo': ' article(s) in total', + 'sidebar.categories': 'Categories', + 'sidebar.recentArticle': 'Recent Articles', + 'sidebar.recentComments': 'Recent Comments', + 'sidebar.tags': 'Tags', + 'sidebar.uncategorized': 'uncategorized', + 'title.draft': 'draft', + 'title.minutes': ' Minutes', + 'title.words': ' Words', +} diff --git a/src/i18n/utils.ts b/src/i18n/utils.ts new file mode 100644 index 0000000..04db0f9 --- /dev/null +++ b/src/i18n/utils.ts @@ -0,0 +1,18 @@ +import { config } from '../consts.ts' +import { en } from './en' +import { zhCn } from './zhCn' +import { cs } from './cs' + +const ui: any = { + en, + 'zh-cn': zhCn, + cs, +} + +export function useTranslations(lang: keyof typeof ui) { + return function t(key: string) { + return ui[lang][key] || ui[config.lang][key] + } +} + +export const t = useTranslations(config.lang) diff --git a/src/i18n/zhCn.ts b/src/i18n/zhCn.ts new file mode 100644 index 0000000..3436030 --- /dev/null +++ b/src/i18n/zhCn.ts @@ -0,0 +1,46 @@ +export const zhCn = { + 'aside.note': '注意', + 'aside.tip': '提示', + 'aside.caution': '警告', + 'aside.danger': '危险', + 'home.sticky': '置顶', + 'home.goBack': '返回', + 'home.moreArticles': '更多文章', + 'home.readMore': '阅读全文', + 'message.welcome': '欢迎留言', + 'message.welcomeTips': '既然来了就留个脚印吧!', + 'post.lastUpdated': '最后更新', + 'remark.open': '展开', + 'sidebar.categories': '分类', + 'sidebar.uncategorized': '未分类', + 'sidebar.tags': '标签', + 'sidebar.recentArticle': '最近文章', + 'sidebar.recentComments': '最近评论', + 'footer.articleTitle': '本文标题', + 'footer.articleAuthor': '文章作者', + 'footer.releaseTime': '发布时间', + 'footer.originalLink': '原始链接', + 'footer.copyrightOne': '版权声明:本作品采用', + 'footer.copyrightTwo': '「署名-非商业性使用-相同方式共享 4.0 国际」', + 'footer.copyrightThree': '许可协议进行许可', + 'footer.sitemap': '站点地图', + 'footer.busuanziSitePV': '总访问量', + 'footer.busuanziSitePVUnit': '次', + 'footer.busuanziSiteUV': '总访客数', + 'footer.busuanziSiteUVUnit': '人次', + 'feed.publishedIn': '发表于', + 'pagination.total': '共', + 'pagination.unit': '页', + 'title.minutes': '分钟', + 'title.words': '字', + 'title.draft': '草稿', + 'blog.tableOfContent': '文章目录', + 'search.labelOne': '正在查看', + 'search.labelTwo': '下的文章', + 'search.search': '搜索', + 'search.searchLabelOne': '共找到 ', + 'search.searchLabelTwo': ' 篇文章', + 'search.placeholder': '输入标题或摘要关键字', + 'feed.previous': '上一条动态', + 'feed.next': '下一条动态', +} diff --git a/src/remark-plugins/remark-asides.ts b/src/remark-plugins/remark-asides.ts new file mode 100644 index 0000000..b7b4b41 --- /dev/null +++ b/src/remark-plugins/remark-asides.ts @@ -0,0 +1,160 @@ +import { h as _h, s as _s } from 'hastscript' +import { remove } from 'unist-util-remove' +import { visit } from 'unist-util-visit' +import { t } from '../i18n/utils.ts' + +const variants = new Set(['note', 'tip', 'warning', 'danger']) + +function defaultLabel(v: any) { + switch (v) { + case 'note': + return t('aside.note') || 'Note' + case 'tip': + return t('aside.tip') || 'Tip' + case 'warning': + return t('aside.warning') || 'Warning' + case 'danger': + return t('aside.danger') || 'Danger' + default: + return '' + } +} + +/** Hacky function that generates an mdast HTML tree ready for conversion to HTML by rehype. */ +function h(el: any, attrs: any = {}, children: any[] = []) { + const { tagName, properties } = _h(el, attrs) as any + return { + type: 'paragraph', + data: { hName: tagName, hProperties: properties }, + children, + } +} + +/** Hacky function that generates an mdast SVG tree ready for conversion to HTML by rehype. */ +function s(el: any, attrs = {}, children = []) { + const { tagName, properties } = _s(el, attrs) + return { + type: 'paragraph', + data: { hName: tagName, hProperties: properties }, + children, + } +} + +/** + * remark plugin that converts blocks delimited with `:::` into styled + * asides (a.k.a. “callouts”, “admonitions”, etc.). Depends on the + * `remark-directive` module for the core parsing logic. + * + * For example, this Markdown + * + * ```md + * :::tip[Did you know?] + * Astro helps you build faster websites with “Islands Architecture”. + * ::: + * ``` + * + * will produce this output + * + * ```astro + * + * ``` + */ +export function remarkAsides(options: any) { + options = { + label: defaultLabel, + ...options, + } + const isAsideVariant = (s: any) => variants.has(s) + + const iconPaths: any = { + // Information icon + note: [ + s('path', { + d: 'M12 11C11.7348 11 11.4804 11.1054 11.2929 11.2929C11.1054 11.4804 11 11.7348 11 12V16C11 16.2652 11.1054 16.5196 11.2929 16.7071C11.4804 16.8946 11.7348 17 12 17C12.2652 17 12.5196 16.8946 12.7071 16.7071C12.8946 16.5196 13 16.2652 13 16V12C13 11.7348 12.8946 11.4804 12.7071 11.2929C12.5196 11.1054 12.2652 11 12 11ZM12.38 7.08C12.1365 6.97998 11.8635 6.97998 11.62 7.08C11.4973 7.12759 11.3851 7.19896 11.29 7.29C11.2017 7.3872 11.1306 7.49882 11.08 7.62C11.024 7.73868 10.9966 7.86882 11 8C10.9992 8.13161 11.0245 8.26207 11.0742 8.38391C11.124 8.50574 11.1973 8.61656 11.29 8.71C11.3872 8.79833 11.4988 8.86936 11.62 8.92C11.7715 8.98224 11.936 9.00632 12.099 8.99011C12.2619 8.97391 12.4184 8.91792 12.5547 8.82707C12.691 8.73622 12.8029 8.61328 12.8805 8.46907C12.9582 8.32486 12.9992 8.16378 13 8C12.9963 7.73523 12.8927 7.48163 12.71 7.29C12.6149 7.19896 12.5028 7.12759 12.38 7.08ZM12 2C10.0222 2 8.08879 2.58649 6.4443 3.6853C4.79981 4.78412 3.51809 6.3459 2.76121 8.17317C2.00433 10.0004 1.8063 12.0111 2.19215 13.9509C2.578 15.8907 3.53041 17.6725 4.92894 19.0711C6.32746 20.4696 8.10929 21.422 10.0491 21.8079C11.9889 22.1937 13.9996 21.9957 15.8268 21.2388C17.6541 20.4819 19.2159 19.2002 20.3147 17.5557C21.4135 15.9112 22 13.9778 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7363 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2ZM12 20C10.4178 20 8.87104 19.5308 7.55544 18.6518C6.23985 17.7727 5.21447 16.5233 4.60897 15.0615C4.00347 13.5997 3.84504 11.9911 4.15372 10.4393C4.4624 8.88743 5.22433 7.46197 6.34315 6.34315C7.46197 5.22433 8.88743 4.4624 10.4393 4.15372C11.9911 3.84504 13.5997 4.00346 15.0615 4.60896C16.5233 5.21447 17.7727 6.23984 18.6518 7.55544C19.5308 8.87103 20 10.4177 20 12C20 14.1217 19.1572 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20Z', + }), + ], + // Rocket icon + tip: [ + s('path', { + 'fill-rule': 'evenodd', + 'clip-rule': 'evenodd', + 'd': 'M1.43909 8.85483L1.44039 8.85354L4.96668 5.33815C5.30653 4.99386 5.7685 4.79662 6.2524 4.78972L6.26553 4.78963L12.9014 4.78962L13.8479 3.84308C16.9187 0.772319 20.0546 0.770617 21.4678 0.975145C21.8617 1.02914 22.2271 1.21053 22.5083 1.4917C22.7894 1.77284 22.9708 2.13821 23.0248 2.53199C23.2294 3.94517 23.2278 7.08119 20.1569 10.1521L19.2107 11.0983V17.7338L19.2106 17.7469C19.2037 18.2308 19.0067 18.6933 18.6624 19.0331L15.1456 22.5608C14.9095 22.7966 14.6137 22.964 14.29 23.0449C13.9663 23.1259 13.6267 23.1174 13.3074 23.0204C12.9881 22.9235 12.7011 22.7417 12.4771 22.4944C12.2533 22.2473 12.1006 21.9441 12.0355 21.6171L11.1783 17.3417L6.65869 12.822L4.34847 12.3589L2.38351 11.965C2.05664 11.8998 1.75272 11.747 1.50564 11.5232C1.25835 11.2992 1.07653 11.0122 0.979561 10.6929C0.882595 10.3736 0.874125 10.034 0.955057 9.7103C1.03599 9.38659 1.20328 9.09092 1.43909 8.85483ZM6.8186 10.8724L2.94619 10.096L6.32006 6.73268H10.9583L6.8186 10.8724ZM15.2219 5.21703C17.681 2.75787 20.0783 2.75376 21.1124 2.8876C21.2462 3.92172 21.2421 6.31895 18.783 8.77812L12.0728 15.4883L8.51172 11.9272L15.2219 5.21703ZM13.9042 21.0538L13.1279 17.1811L17.2676 13.0414V17.68L13.9042 21.0538Z', + }), + s('path', { + d: 'M9.31827 18.3446C9.45046 17.8529 9.17864 17.3369 8.68945 17.1724C8.56178 17.1294 8.43145 17.1145 8.30512 17.1243C8.10513 17.1398 7.91519 17.2172 7.76181 17.3434C7.62613 17.455 7.51905 17.6048 7.45893 17.7835C6.97634 19.2186 5.77062 19.9878 4.52406 20.4029C4.08525 20.549 3.6605 20.644 3.29471 20.7053C3.35607 20.3395 3.45098 19.9148 3.59711 19.476C4.01221 18.2294 4.78141 17.0237 6.21648 16.5411C6.39528 16.481 6.54504 16.3739 6.65665 16.2382C6.85126 16.0016 6.92988 15.678 6.84417 15.3647C6.83922 15.3466 6.83373 15.3286 6.82767 15.3106C6.74106 15.053 6.55701 14.8557 6.33037 14.7459C6.10949 14.6389 5.84816 14.615 5.59715 14.6994C5.47743 14.7397 5.36103 14.7831 5.24786 14.8294C3.22626 15.6569 2.2347 17.4173 1.75357 18.8621C1.49662 19.6337 1.36993 20.3554 1.30679 20.8818C1.27505 21.1464 1.25893 21.3654 1.25072 21.5213C1.24662 21.5993 1.24448 21.6618 1.24337 21.7066L1.243 21.7226L1.24235 21.7605L1.2422 21.7771L1.24217 21.7827L1.24217 21.7856C1.24217 22.3221 1.67703 22.7579 2.2137 22.7579L2.2155 22.7579L2.22337 22.7578L2.23956 22.7577C2.25293 22.7575 2.27096 22.7572 2.29338 22.7567C2.33821 22.7555 2.40073 22.7534 2.47876 22.7493C2.63466 22.7411 2.85361 22.725 3.11822 22.6932C3.64462 22.6301 4.36636 22.5034 5.13797 22.2464C6.58274 21.7653 8.3431 20.7738 9.17063 18.7522C9.21696 18.639 9.26037 18.5226 9.30064 18.4029C9.30716 18.3835 9.31304 18.364 9.31827 18.3446Z', + }), + ], + // Warning triangle icon + warning: [ + s('path', { + d: 'M12 16C11.8022 16 11.6089 16.0587 11.4444 16.1686C11.28 16.2784 11.1518 16.4346 11.0761 16.6173C11.0004 16.8001 10.9806 17.0011 11.0192 17.1951C11.0578 17.3891 11.153 17.5673 11.2929 17.7071C11.4327 17.847 11.6109 17.9422 11.8049 17.9808C11.9989 18.0194 12.2 17.9996 12.3827 17.9239C12.5654 17.8482 12.7216 17.72 12.8315 17.5556C12.9413 17.3911 13 17.1978 13 17C13 16.7348 12.8946 16.4805 12.7071 16.2929C12.5196 16.1054 12.2652 16 12 16ZM22.67 17.47L14.62 3.47003C14.3598 3.00354 13.9798 2.61498 13.5192 2.3445C13.0586 2.07401 12.5341 1.9314 12 1.9314C11.4659 1.9314 10.9414 2.07401 10.4808 2.3445C10.0202 2.61498 9.64019 3.00354 9.38 3.47003L1.38 17.47C1.11079 17.924 0.966141 18.441 0.960643 18.9688C0.955144 19.4966 1.089 20.0166 1.34868 20.4761C1.60837 20.9356 1.9847 21.3185 2.43968 21.5861C2.89466 21.8536 3.41218 21.9964 3.94 22H20.06C20.5921 22.0053 21.1159 21.8689 21.5779 21.6049C22.0399 21.341 22.4234 20.9589 22.689 20.4978C22.9546 20.0368 23.0928 19.5134 23.0895 18.9814C23.0862 18.4493 22.9414 17.9277 22.67 17.47ZM20.94 19.47C20.8523 19.626 20.7245 19.7556 20.5697 19.8453C20.4149 19.935 20.2389 19.9815 20.06 19.98H3.94C3.76111 19.9815 3.5851 19.935 3.43032 19.8453C3.27553 19.7556 3.14765 19.626 3.06 19.47C2.97223 19.318 2.92602 19.1456 2.92602 18.97C2.92602 18.7945 2.97223 18.622 3.06 18.47L11.06 4.47003C11.1439 4.30623 11.2714 4.16876 11.4284 4.07277C11.5855 3.97678 11.766 3.92599 11.95 3.92599C12.134 3.92599 12.3145 3.97678 12.4716 4.07277C12.6286 4.16876 12.7561 4.30623 12.84 4.47003L20.89 18.47C20.9892 18.6199 21.0462 18.7937 21.055 18.9732C21.0638 19.1527 21.0241 19.3312 20.94 19.49V19.47ZM12 8.00003C11.7348 8.00003 11.4804 8.10538 11.2929 8.29292C11.1054 8.48046 11 8.73481 11 9.00003V13C11 13.2652 11.1054 13.5196 11.2929 13.7071C11.4804 13.8947 11.7348 14 12 14C12.2652 14 12.5196 13.8947 12.7071 13.7071C12.8946 13.5196 13 13.2652 13 13V9.00003C13 8.73481 12.8946 8.48046 12.7071 8.29292C12.5196 8.10538 12.2652 8.00003 12 8.00003Z', + }), + ], + // Error shield icon + danger: [ + s('path', { + d: 'M12 7C11.7348 7 11.4804 7.10536 11.2929 7.29289C11.1054 7.48043 11 7.73478 11 8V12C11 12.2652 11.1054 12.5196 11.2929 12.7071C11.4804 12.8946 11.7348 13 12 13C12.2652 13 12.5196 12.8946 12.7071 12.7071C12.8946 12.5196 13 12.2652 13 12V8C13 7.73478 12.8946 7.48043 12.7071 7.29289C12.5196 7.10536 12.2652 7 12 7ZM12 15C11.8022 15 11.6089 15.0586 11.4444 15.1685C11.28 15.2784 11.1518 15.4346 11.0761 15.6173C11.0004 15.8 10.9806 16.0011 11.0192 16.1951C11.0578 16.3891 11.153 16.5673 11.2929 16.7071C11.4327 16.847 11.6109 16.9422 11.8049 16.9808C11.9989 17.0194 12.2 16.9996 12.3827 16.9239C12.5654 16.8482 12.7216 16.72 12.8315 16.5556C12.9414 16.3911 13 16.1978 13 16C13 15.7348 12.8946 15.4804 12.7071 15.2929C12.5196 15.1054 12.2652 15 12 15ZM21.71 7.56L16.44 2.29C16.2484 2.10727 15.9948 2.00368 15.73 2H8.27C8.00523 2.00368 7.75163 2.10727 7.56 2.29L2.29 7.56C2.10727 7.75163 2.00368 8.00523 2 8.27V15.73C2.00368 15.9948 2.10727 16.2484 2.29 16.44L7.56 21.71C7.75163 21.8927 8.00523 21.9963 8.27 22H15.73C15.9948 21.9963 16.2484 21.8927 16.44 21.71L21.71 16.44C21.8927 16.2484 21.9963 15.9948 22 15.73V8.27C21.9963 8.00523 21.8927 7.75163 21.71 7.56ZM20 15.31L15.31 20H8.69L4 15.31V8.69L8.69 4H15.31L20 8.69V15.31Z', + }), + ], + } + + const transformer = (tree: any) => { + visit(tree, (node, index, parent) => { + if (!parent || index === undefined || node.type !== 'containerDirective') { + return + } + const variant = node.name + if (!isAsideVariant(variant)) + return + + // remark-directive converts a container’s “label” to a paragraph in + // its children, but we want to pass it as the title prop to