Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 19 additions & 22 deletions docs/plugins/development/reading-time.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ icon: book-open-text

<NpmBadge package="@vuepress/plugin-reading-time" />

This plugin will generate word count and estimated reading time for each page.
This plugin generates word count and estimated reading time for each page.

## Usage

Expand All @@ -26,20 +26,20 @@ export default {
}
```

The plugin will inject reading time information into the `readingTime` of the page data, where:
The plugin injects reading time information into the `readingTime` field of page data:

- `readingTime.minutes`: estimated reading time (minutes) `number`
- `readingTime.words`: word count `number`
- `readingTime.minutes`: estimated reading time in minutes (`number`)
- `readingTime.words`: word count (`number`)

### Getting data on Node Side
### Getting Data on Node Side

For any page, you can get estimated reading time and word count from `page.data.readingTime`:

```ts
page.data.readingTime // { minutes: 3.2, words: 934 }
```

You can access it for further processing in the `extendsPage` lifecycle and other lifecycle:
You can access it for further processing in the `extendsPage` lifecycle and other lifecycles:

```js
export default {
Expand All @@ -56,7 +56,7 @@ export default {
}
```

### Getting data on Client Side
### Getting Data on Client Side

You can import `useReadingTimeData` and `useReadingTimeLocale` from `@vuepress/plugin-reading-time/client` to get the reading time data and locale data of the current page:

Expand All @@ -78,8 +78,7 @@ const readingTimeLocale = useReadingTimeLocale() // { time: "1 minute", words: "

- Type: `number`
- Default: `300`
- Details:
Reading speed (words per minute)
- Details: Reading speed in words per minute.

### locales

Expand All @@ -98,7 +97,7 @@ const readingTimeLocale = useReadingTimeLocale() // { time: "1 minute", words: "
less1Minute: string

/**
* Time template
* Time template, `$time` will be automatically replaced by actual time
*/
time: string
}
Expand All @@ -108,9 +107,7 @@ const readingTimeLocale = useReadingTimeLocale() // { time: "1 minute", words: "
}
```

- Details:

Locales config for reading-time plugin.
- Details: Locale config for reading time text and word count text.

::: details Built-in Supported Languages

Expand Down Expand Up @@ -139,15 +136,15 @@ const readingTimeLocale = useReadingTimeLocale() // { time: "1 minute", words: "

You can import and use these APIs from `@vuepress/plugin-reading-time/client`:

::: tip These APIs won't throw even you disable the plugin.
::: tip These APIs won't throw errors even if you disable the plugin.

:::

### useReadingTimeData

```ts
interface ReadingTime {
/** Expect reading time in minute unit */
/** Expected reading time in minutes */
minutes: number
/** Words count of content */
words: number
Expand All @@ -156,13 +153,13 @@ interface ReadingTime {
const useReadingTimeData: () => ComputedRef<ReadingTime | null>
```

`null` is returned when the plugin is disabled.
Returns `null` when the plugin is disabled.

### useReadingTimeLocale

```ts
interface ReadingTimeLocale {
/** Expect reading time text in locale */
/** Expected reading time text in locale */
time: string
/** Word count text in locale */
words: string
Expand All @@ -173,7 +170,7 @@ const useReadingTimeLocale: () => ComputedRef<ReadingTimeLocale>

## Advanced Usage

This plugin is targeting plugin and theme developers mostly, so we provide a "Use API":
This plugin targets plugin and theme developers, so we provide a "Use API":

```js title="your plugin or theme entry"
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
Expand All @@ -189,14 +186,14 @@ export default (options) => (app) => {
}
```

::: tip Why you should use "Use API"
::: tip Why you should use the "Use API"

1. When you register a plugin multiple times, vuepress will gives you warning about that telling you only the first one takes effect. The `useReadingTimePlugin` automatically detects if the plugin is registered and avoid registering multiple times.
1. If you access reading time data in `extendsPage` lifecycle, then `@vuepress/plugin-reading-time` must be called before your theme or plugin, otherwise you will get `undefined` for `page.data.readingTime`. The `useReadingTimePlugin` ensures that `@vuepress/plugin-reading-time` is called before your theme or plugin.
1. When you register a plugin multiple times, VuePress gives you a warning that only the first one takes effect. The `useReadingTimePlugin` automatically detects if the plugin is registered and avoids registering multiple times.
1. If you access reading time data in the `extendsPage` lifecycle, then `@vuepress/plugin-reading-time` must be called before your theme or plugin, otherwise you will get `undefined` for `page.data.readingTime`. The `useReadingTimePlugin` ensures that `@vuepress/plugin-reading-time` is called before your theme or plugin.

:::

We also provides a `removeReadingTimePlugin` api to remove the plugin.You can use this to ensure your call take effect or clear the plugin:
We also provide a `removeReadingTimePlugin` API to remove the plugin. You can use this to ensure your call takes effect or clear the plugin:

```js title="your plugin or theme entry"
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
Expand Down
31 changes: 14 additions & 17 deletions docs/zh/plugins/development/reading-time.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ icon: book-open-text

<NpmBadge package="@vuepress/plugin-reading-time" />

此插件会为每个页面生成字数统计与预计阅读时间
此插件为每个页面生成字数统计与预计阅读时间

## 使用方法

Expand All @@ -26,20 +26,20 @@ export default {
}
```

插件会将相关信息注入到页面数据的 `readingTime`,其中
插件将相关信息注入到页面数据的 `readingTime` 字段

- `readingTime.minutes`:为预计阅读时间(分钟)`number`
- `readingTime.words`:字数统计`number`
- `readingTime.minutes`:预计阅读时间(分钟)(`number`)
- `readingTime.words`:字数统计 (`number`)

### 在 Node 侧获取数据

对于任何页面,你可以从 `page.data.readingTime` 获取预计阅读时间与字数统计:
对于任何页面,你可以从 `page.data.readingTime` 获取预计阅读时间与字数统计

```ts
page.data.readingTime // { minutes: 3.2, words: 934 }
```

你可以在 `extendsPage` 以及其他生命周期获取它做进一步处理:
你可以在 `extendsPage` 以及其他生命周期中获取它做进一步处理:

```js
export default {
Expand Down Expand Up @@ -78,8 +78,7 @@ const readingTimeLocale = useReadingTimeLocale() // { time: "1 分钟", words: "

- 类型:`number`
- 默认值:`300`
- 详情:
每分钟阅读字数
- 详情:每分钟阅读的字数。

### locales

Expand All @@ -98,7 +97,7 @@ const readingTimeLocale = useReadingTimeLocale() // { time: "1 分钟", words: "
less1Minute: string

/**
* 时间模板
* 时间模板,模板中 `$time` 会被自动替换为实际时间
*/
time: string
}
Expand All @@ -108,9 +107,7 @@ const readingTimeLocale = useReadingTimeLocale() // { time: "1 分钟", words: "
}
```

- 详情:

阅读时间插件的国际化配置。
- 详情:阅读时间和字数文本的多语言配置。

::: details 内置支持语言

Expand Down Expand Up @@ -156,7 +153,7 @@ interface ReadingTime {
const useReadingTimeData: () => ComputedRef<ReadingTime | null>
```

当插件被禁用时会返回 `null`。
当插件被禁用时返回 `null`。

### useReadingTimeLocale

Expand All @@ -173,7 +170,7 @@ const useReadingTimeLocale: () => ComputedRef<ReadingTimeLocale>

## 高级使用

由于此插件主要面向插件和主题开发者,所以提供了 "使用 API":
由于此插件主要面向插件和主题开发者,所以提供了"使用 API":

```js title="你插件或主题的入口"
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
Expand All @@ -189,15 +186,15 @@ export default (options) => (app) => {
}
```

::: tip 为什么你应该使用 "使用 API"
::: tip 为什么你应该使用"使用 API"

1. 当你多次注册一个插件时,vuepress 会给你一个警告,告诉你只有第一个插件会生效。`useReadingTimePlugin` 会自动检测插件是否已经注册,避免多次注册。
1. 当你多次注册一个插件时,VuePress 会给你一个警告,告诉你只有第一个插件会生效。`useReadingTimePlugin` 会自动检测插件是否已经注册,避免多次注册。

1. 如果你在 `extendsPage` 生命周期访问阅读时间数据,那么 `@vuepress/plugin-reading-time` 必须在你的主题或插件之前被调用,否则你会得到未定义的 `page.data.readingTime`。`useReadingTimePlugin` 确保了 `@vuepress/plugin-reading-time` 在你的主题或插件之前被调用。

:::

我们也提供了一个 `removeReadingTimePlugin` api 来移除插件。你可以使用它来确保你的调用生效或清除插件:
我们也提供了一个 `removeReadingTimePlugin` API 来移除插件。你可以使用它来确保你的调用生效或清除插件

```js title="你插件或主题的入口"
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ import type {
ReadingTimePluginPageData,
} from '../../shared/index.js'

/**
* Get reading time data of current page
*
* 获取当前页面的阅读时间数据
*
* @returns reading time data or null if plugin is disabled
*
* @example
* ```ts
* import { useReadingTimeData } from '@vuepress/plugin-reading-time/client'
*
* const readingTimeData = useReadingTimeData()
* // { minutes: 1.1, words: 100 } or null
* ```
*/
export const useReadingTimeData = (): ComputedRef<ReadingTime | null> => {
const page = usePage<Partial<ReadingTimePluginPageData>>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,22 @@ const readingTimeLocales =
? null
: __READING_TIME_LOCALES__

/**
* Get reading time locale config
*
* 获取阅读时间多语言配置
*
* @returns reading time locale config or null if plugin is disabled
*/
export const useReadingTimeLocaleConfig =
(): ComputedRef<ReadingTimePluginLocaleData | null> =>
readingTimeLocales ? useLocale(readingTimeLocales) : computed(() => null)

/**
* Reading time locale interface
*
* 阅读时间本地化接口
*/
export interface ReadingTimeLocale {
/**
* Reading time text
Expand All @@ -37,6 +49,21 @@ export interface ReadingTimeLocale {
words: string
}

/**
* Get reading time locale data of current page
*
* 获取当前页面的阅读时间本地化数据
*
* @returns reading time locale data
*
* @example
* ```ts
* import { useReadingTimeLocale } from '@vuepress/plugin-reading-time/client'
*
* const readingTimeLocale = useReadingTimeLocale()
* // { time: "1 minute", words: "100 words" }
* ```
*/
export const useReadingTimeLocale = (): ComputedRef<ReadingTimeLocale> => {
if (readingTimeLocales === null) return computed(() => DEFAULT_LOCALE)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,24 @@ import type {
ReadingTimePluginLocaleData,
} from '../../shared/index.js'

/**
* Get reading time locale text
*
* 获取阅读时间本地化文字
*
* @param readingTime - reading time data
* @param locale - locale config
* @returns localized reading time text
*
* @example
* ```ts
* getReadingTimeLocale(
* { minutes: 2.5, words: 500 },
* { less1Minute: "Less than 1 min", word: "$word words", time: "$time min" }
* )
* // { time: "3 min", words: "500 words" }
* ```
*/
export const getReadingTimeLocale = (
readingTime: ReadingTime,
locale: ReadingTimePluginLocaleData,
Expand Down
35 changes: 35 additions & 0 deletions plugins/development/plugin-reading-time/src/node/getReadingTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import type { ReadingTime } from '../shared/index.js'

/**
* Extract Latin words from content
*
* 从内容中提取拉丁文字
*
* @param content - content to extract words from
* @returns matched words or null
*/
const getWords = (content: string): RegExpMatchArray | null =>
// \u00C0-\u024F are Latin Supplement letters, maybe used in language like french
Expand All @@ -11,12 +16,28 @@ const getWords = (content: string): RegExpMatchArray | null =>

/**
* Extract Chinese Characters from content
*
* 从内容中提取中文字符
*
* @param content - content to extract Chinese characters from
* @returns matched Chinese characters or null
*/
const getChinese = (content: string): RegExpMatchArray | null =>
content.match(/[\u4E00-\u9FD5]/gu)

/**
* Get word number of given string
*
* 获取给定字符串的字数
*
* @param content - content to count words
* @returns word count
*
* @example
* ```ts
* getWordNumber('Hello world') // 2
* getWordNumber('你好世界') // 4
* ```
*/
export const getWordNumber = (content: string): number =>
(getWords(content)?.reduce<number>(
Expand All @@ -27,6 +48,20 @@ export const getWordNumber = (content: string): number =>

/**
* Get reading time info
*
* 获取阅读时间信息
*
* @param content - content to calculate reading time
* @param wordsPerMinute - reading speed in words per minute
* @returns reading time information
*
* @default wordsPerMinute 300
*
* @example
* ```ts
* getReadingTime('Hello world', 300)
* // { minutes: 0.01, words: 2 }
* ```
*/
export const getReadingTime = (
content: string,
Expand Down
Loading
Loading