feat: support frontmatter excerpt_type, close #67

This commit is contained in:
YunYouJun 2023-01-28 22:56:20 +08:00
parent 632c09c38a
commit f07b74c613
11 changed files with 95 additions and 21 deletions

View File

@ -0,0 +1,12 @@
---
title: 'excerpt_type: html'
excerpt_type: html
---
## Header
![yun-bg](https://cdn.yunyoujun.cn/img/bg/stars-timing-0-blur-30px.jpg)
<!-- more -->
Main Content

View File

@ -0,0 +1,12 @@
---
title: 'excerpt_type: md'
excerpt_type: md
---
## Header
![yun-bg](https://cdn.yunyoujun.cn/img/bg/stars-timing-0-blur-30px.jpg)
<!-- more -->
Main Content

View File

@ -0,0 +1,12 @@
---
title: 'excerpt_type: text'
excerpt_type: text
---
## Header
![yun-bg](https://cdn.yunyoujun.cn/img/bg/stars-timing-0-blur-30px.jpg)
<!-- more -->
Main Content

View File

@ -24,14 +24,20 @@ hide: true
- `hide`: 你可以在文章头部添加 hide 属性,来临时隐藏某篇文章。(该文章仍然会被渲染)
- `true` / `all`: 当设置为 `true``all` 时,该文章仍然会被渲染,你可以直接访问链接进行查看。但不会被显示在展示的文章卡片与归档中。
- `index`: 设置为 `index` 时,将只在首页隐藏,归档中仍然展示。(譬如放一些没有必要放在首页的笔记,并在归档中方便自己查看。)
- `excerpt_type`: 预览列表**摘要**的渲染类型(与 `<!-- more -->` 配合使用)
- `md`: 展示原始 Markdown
- `html`: 以 HTML 形式展示
- `text`: 以纯文本形式展示(去除 HTML 标签)
## 摘要
你可以通过插入 `<!-- more -->` 的方式生成摘要excerpt
可通过设置 `excerpt_type` 设置摘要渲染类型。
```md
---
title: 嘿嘿嘿
excerpt_type: text
---
这里是摘要

View File

@ -38,7 +38,8 @@ const { icon, styles } = usePostProperty(props.post.type)
<YunPostMeta :frontmatter="post" />
<div v-if="post.excerpt" class="markdown-body" text="left" w="full" p="x-6 lt-sm:4" v-html="post.excerpt" />
<div v-if="post.excerpt_type === 'text'" py="1" />
<div v-if="post.excerpt" class="markdown-body" text="left" w="full" p="x-6 lt-sm:4 y-1" v-html="post.excerpt" />
<div m="b-5" />
<a

View File

@ -5,38 +5,38 @@ import { useI18n } from 'vue-i18n'
defineProps<{
// FrontMatter
fm: Post
frontmatter: Post
}>()
const { t } = useI18n()
</script>
<template>
<div v-if="fm.draft" class="post-draft-icon" title="draft">
<div v-if="frontmatter.draft" class="post-draft-icon" title="draft">
<div i-ri-draft-line />
</div>
<div v-if="fm.hide" class="post-top-icon" color="$va-c-danger" :title="`hide:${fm.hide}`">
<div v-if="fm.hide === 'index'" i-ri-eye-close-line />
<div i-ri-eye-off-line />
<div v-if="frontmatter.hide" class="post-top-icon" color="$va-c-danger" :title="`hide:${frontmatter.hide}`">
<div v-if="frontmatter.hide === 'index'" i-ri-eye-close-line />
<div v-else i-ri-eye-off-line />
</div>
<div v-if="fm.top" class="post-top-icon" color="$va-c-warning">
<div v-if="frontmatter.top" class="post-top-icon" color="$va-c-warning">
<div i-ri-pushpin-line />
</div>
<div v-if="fm" class="post-meta justify-center" flex="~" text="sm" py="1">
<div v-if="fm.date" class="post-time flex items-center">
<div v-if="frontmatter" class="post-meta justify-center" flex="~" text="sm" py="1">
<div v-if="frontmatter.date" class="post-time flex items-center">
<span class="inline-flex-center" :title="t('post.posted')">
<div class="inline-block" i-ri-calendar-line />
<time m="l-1">{{ formatDate(fm.date) }}</time>
<time m="l-1">{{ formatDate(frontmatter.date) }}</time>
</span>
<span
v-if="fm.updated && fm.updated !== fm.date"
v-if="frontmatter.updated && frontmatter.updated !== frontmatter.date"
class="inline-flex-center" :title="t('post.edited')"
>
<span m="x-2">-</span>
<div i-ri-calendar-2-line />
<time m="l-1">{{ formatDate(fm.updated) }}</time>
<time m="l-1">{{ formatDate(frontmatter.updated) }}</time>
</span>
</div>
</div>

View File

@ -40,4 +40,8 @@ html.dark {
img {
margin: auto;
}
p {
overflow: unset;
}
}

View File

@ -1,2 +1,4 @@
export const EXCERPT_SEPARATOR = '<!-- more -->'
export const EXTERNAL_URL_RE = /^https?:/i
export const PATHNAME_PROTOCOL_RE = /^pathname:\/\//

View File

@ -12,18 +12,37 @@ import Components from 'unplugin-vue-components/vite'
import VueI18n from '@intlify/unplugin-vue-i18n/vite'
import dayjs from 'dayjs'
// import { convert } from 'html-to-text'
import { convert } from 'html-to-text'
import type { ValaxyExtendConfig } from '../types'
import type { ResolvedValaxyOptions, ValaxyServerOptions } from '../options'
import { setupMarkdownPlugins } from '../markdown'
// import { createMarkdownPlugin, excerpt_separator } from './markdown'
// import { formatMdDate } from '../utils/date'
import { EXCERPT_SEPARATOR } from '../constants'
import { createUnocssPlugin } from './unocss'
import { createConfigPlugin } from './extendConfig'
import { createClientSetupPlugin } from './setupClient'
import { createFixPlugins } from './patchTransform'
import { createValaxyPlugin } from '.'
// for render markdown excerpt
const mdIt = new MarkdownIt({ html: true })
/**
* get excerpt by type
* @param excerpt
* @param type
* @returns
*/
const getExcerptByType = (excerpt = '', type: 'md' | 'html' | 'text' = 'html') => {
switch (type) {
case 'md':
return excerpt
case 'html':
return mdIt.render(excerpt)
case 'text':
return convert(mdIt.render(excerpt))
}
}
export async function ViteValaxyPlugins(
options: ResolvedValaxyOptions,
serverOptions: ValaxyServerOptions = {},
@ -35,9 +54,7 @@ export async function ViteValaxyPlugins(
const ValaxyPlugin = createValaxyPlugin(options, serverOptions)
// for render markdown excerpt
const mdIt = new MarkdownIt({ html: true })
// setup mdIt
await setupMarkdownPlugins(mdIt, valaxyConfig.markdown, true)
const customElements = new Set([
@ -136,7 +153,7 @@ export async function ViteValaxyPlugins(
if (path.endsWith('.md')) {
const md = fs.readFileSync(path, 'utf-8')
const { data, excerpt, content } = matter(md, {
excerpt_separator: '<!-- more -->',
excerpt_separator: EXCERPT_SEPARATOR,
})
// todo, optimize it to cache or on demand
@ -166,8 +183,7 @@ export async function ViteValaxyPlugins(
// set route meta
route.meta = Object.assign(route.meta, {
frontmatter: Object.assign(defaultFrontmatter, data),
excerpt: excerpt ? mdIt.render(excerpt) : '',
// excerpt: convert(excerpt ? mdIt.render(excerpt) : '') || '',
excerpt: excerpt ? getExcerptByType(excerpt, data.excerpt_type) : '',
})
// set layout

View File

@ -11,6 +11,7 @@ import consola from 'consola'
import type { ResolvedValaxyOptions } from './options'
import { formatMdDate } from './utils/date'
import { ensurePrefix, isExternal } from './utils'
import { EXCERPT_SEPARATOR } from './constants'
const markdown = MarkdownIt({
html: true,
@ -65,7 +66,7 @@ export async function build(options: ResolvedValaxyOptions) {
for await (const i of files) {
const raw = fs.readFileSync(i, 'utf-8')
const { data, content, excerpt } = matter(raw, { excerpt_separator: '<!-- more -->' })
const { data, content, excerpt } = matter(raw, { excerpt_separator: EXCERPT_SEPARATOR })
if (data.draft) {
consola.warn(`Ignore draft post: ${dim(i)}`)

View File

@ -34,6 +34,14 @@ export interface Post extends Record<string, any> {
* @description
*/
excerpt?: string
/**
* @default 'html'
* render type of excerpt
* - md: render as raw markdown
* - html: render as html
* - text: render as text
*/
excerpt_type?: 'md' | 'text' | 'html'
/**
* @description Author
* @description:zh-CN