@docusaurus/plugin-content-blog 3.7.0-canary-6313 → 3.7.0-canary-6315

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/blogUtils.js CHANGED
@@ -130,7 +130,7 @@ async function parseBlogPostMarkdownFile({ filePath, parseFrontMatter, }) {
130
130
  throw err;
131
131
  }
132
132
  }
133
- const defaultReadingTime = ({ content, options }) => (0, readingTime_1.calculateReadingTime)(content, options);
133
+ const defaultReadingTime = ({ content, locale, options }) => (0, readingTime_1.calculateReadingTime)(content, locale, options);
134
134
  async function processBlogSourceFile(blogSourceRelative, contentPaths, context, options, tagsFile, authorsMap) {
135
135
  const { siteConfig: { baseUrl, markdown: { parseFrontMatter }, }, siteDir, i18n, } = context;
136
136
  const { routeBasePath, tagsBasePath: tagsRouteBasePath, truncateMarker, showReadingTime, editUrl, } = options;
@@ -238,6 +238,7 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
238
238
  content,
239
239
  frontMatter,
240
240
  defaultReadingTime,
241
+ locale: i18n.currentLocale,
241
242
  })
242
243
  : undefined,
243
244
  hasTruncateMarker: truncateMarker.test(content),
package/lib/options.js CHANGED
@@ -51,7 +51,7 @@ exports.DEFAULT_OPTIONS = {
51
51
  path: 'blog',
52
52
  editLocalizedFiles: false,
53
53
  authorsMapPath: 'authors.yml',
54
- readingTime: ({ content, defaultReadingTime }) => defaultReadingTime({ content }),
54
+ readingTime: ({ content, defaultReadingTime, locale }) => defaultReadingTime({ content, locale }),
55
55
  sortPosts: 'descending',
56
56
  showLastUpdateTime: false,
57
57
  showLastUpdateAuthor: false,
@@ -4,13 +4,14 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- interface ReadingTimeOptions {
8
- wordsPerMinute?: number;
9
- wordBound?: (char: string) => boolean;
10
- }
11
7
  /**
12
- * Calculates the reading time for a given content string.
13
- * Uses the reading-time package under the hood.
8
+ * Calculates the reading time for a given content string using Intl.Segmenter.
9
+ * @param content The text content to calculate reading time for.
10
+ * @param locale Required locale string for Intl.Segmenter
11
+ * @param options Options for reading time calculation.
12
+ * - wordsPerMinute: number of words per minute (default 200)
13
+ * @returns Estimated reading time in minutes (float, rounded to 2 decimals)
14
14
  */
15
- export declare function calculateReadingTime(content: string, options?: ReadingTimeOptions): number;
16
- export {};
15
+ export declare function calculateReadingTime(content: string, locale: string, options?: {
16
+ wordsPerMinute?: number;
17
+ }): number;
@@ -7,16 +7,39 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.calculateReadingTime = calculateReadingTime;
10
- const tslib_1 = require("tslib");
11
- const reading_time_1 = tslib_1.__importDefault(require("reading-time"));
12
10
  const DEFAULT_WORDS_PER_MINUTE = 200;
13
11
  /**
14
- * Calculates the reading time for a given content string.
15
- * Uses the reading-time package under the hood.
12
+ * Counts the number of words in a string using Intl.Segmenter.
13
+ * @param content The text content to count words in.
14
+ * @param locale The locale to use for segmentation.
16
15
  */
17
- function calculateReadingTime(content, options = {}) {
18
- const wordsPerMinute = options.wordsPerMinute ?? DEFAULT_WORDS_PER_MINUTE;
19
- const { wordBound } = options;
20
- return (0, reading_time_1.default)(content, { wordsPerMinute, ...(wordBound && { wordBound }) })
21
- .minutes;
16
+ function countWords(content, locale) {
17
+ if (!content) {
18
+ return 0;
19
+ }
20
+ const segmenter = new Intl.Segmenter(locale, { granularity: 'word' });
21
+ let wordCount = 0;
22
+ for (const { isWordLike } of segmenter.segment(content)) {
23
+ if (isWordLike) {
24
+ wordCount += 1;
25
+ }
26
+ }
27
+ return wordCount;
28
+ }
29
+ /**
30
+ * Calculates the reading time for a given content string using Intl.Segmenter.
31
+ * @param content The text content to calculate reading time for.
32
+ * @param locale Required locale string for Intl.Segmenter
33
+ * @param options Options for reading time calculation.
34
+ * - wordsPerMinute: number of words per minute (default 200)
35
+ * @returns Estimated reading time in minutes (float, rounded to 2 decimals)
36
+ */
37
+ function calculateReadingTime(content, locale, options) {
38
+ const wordsPerMinute = options?.wordsPerMinute ?? DEFAULT_WORDS_PER_MINUTE;
39
+ const words = countWords(content, locale);
40
+ if (words === 0) {
41
+ return 0;
42
+ }
43
+ // Calculate reading time in minutes and round to 2 decimal places
44
+ return Math.round((words / wordsPerMinute) * 100) / 100;
22
45
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/plugin-content-blog",
3
- "version": "3.7.0-canary-6313",
3
+ "version": "3.7.0-canary-6315",
4
4
  "description": "Blog plugin for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/plugin-content-blog.d.ts",
@@ -31,19 +31,18 @@
31
31
  },
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
- "@docusaurus/core": "3.7.0-canary-6313",
35
- "@docusaurus/logger": "3.7.0-canary-6313",
36
- "@docusaurus/mdx-loader": "3.7.0-canary-6313",
37
- "@docusaurus/theme-common": "3.7.0-canary-6313",
38
- "@docusaurus/types": "3.7.0-canary-6313",
39
- "@docusaurus/utils": "3.7.0-canary-6313",
40
- "@docusaurus/utils-common": "3.7.0-canary-6313",
41
- "@docusaurus/utils-validation": "3.7.0-canary-6313",
34
+ "@docusaurus/core": "3.7.0-canary-6315",
35
+ "@docusaurus/logger": "3.7.0-canary-6315",
36
+ "@docusaurus/mdx-loader": "3.7.0-canary-6315",
37
+ "@docusaurus/theme-common": "3.7.0-canary-6315",
38
+ "@docusaurus/types": "3.7.0-canary-6315",
39
+ "@docusaurus/utils": "3.7.0-canary-6315",
40
+ "@docusaurus/utils-common": "3.7.0-canary-6315",
41
+ "@docusaurus/utils-validation": "3.7.0-canary-6315",
42
42
  "cheerio": "1.0.0-rc.12",
43
43
  "feed": "^4.2.2",
44
44
  "fs-extra": "^11.1.1",
45
45
  "lodash": "^4.17.21",
46
- "reading-time": "^1.5.0",
47
46
  "schema-dts": "^1.1.2",
48
47
  "srcset": "^4.0.0",
49
48
  "tslib": "^2.6.0",
@@ -63,5 +62,5 @@
63
62
  "@total-typescript/shoehorn": "^0.1.2",
64
63
  "tree-node-cli": "^1.6.0"
65
64
  },
66
- "gitHead": "9e3b01a35981d62fc38c796b6e358d488c8fe5fe"
65
+ "gitHead": "9cf2656b9b5ba64585ab220c91a0dbbac9758ae4"
67
66
  }
package/src/blogUtils.ts CHANGED
@@ -210,8 +210,8 @@ async function parseBlogPostMarkdownFile({
210
210
  }
211
211
  }
212
212
 
213
- const defaultReadingTime: ReadingTimeFunction = ({content, options}) =>
214
- calculateReadingTime(content, options);
213
+ const defaultReadingTime: ReadingTimeFunction = ({content, locale, options}) =>
214
+ calculateReadingTime(content, locale, options);
215
215
 
216
216
  async function processBlogSourceFile(
217
217
  blogSourceRelative: string,
@@ -373,6 +373,7 @@ async function processBlogSourceFile(
373
373
  content,
374
374
  frontMatter,
375
375
  defaultReadingTime,
376
+ locale: i18n.currentLocale,
376
377
  })
377
378
  : undefined,
378
379
  hasTruncateMarker: truncateMarker.test(content),
package/src/options.ts CHANGED
@@ -63,7 +63,8 @@ export const DEFAULT_OPTIONS: PluginOptions = {
63
63
  path: 'blog',
64
64
  editLocalizedFiles: false,
65
65
  authorsMapPath: 'authors.yml',
66
- readingTime: ({content, defaultReadingTime}) => defaultReadingTime({content}),
66
+ readingTime: ({content, defaultReadingTime, locale}) =>
67
+ defaultReadingTime({content, locale}),
67
68
  sortPosts: 'descending',
68
69
  showLastUpdateTime: false,
69
70
  showLastUpdateAuthor: false,
@@ -387,15 +387,10 @@ declare module '@docusaurus/plugin-content-blog' {
387
387
  };
388
388
 
389
389
  /**
390
- * Duplicate from ngryman/reading-time to keep stability of API.
390
+ * Options for reading time calculation using Intl.Segmenter.
391
391
  */
392
392
  type ReadingTimeOptions = {
393
393
  wordsPerMinute?: number;
394
- /**
395
- * @param char The character to be matched.
396
- * @returns `true` if this character is a word bound.
397
- */
398
- wordBound?: (char: string) => boolean;
399
394
  };
400
395
 
401
396
  /**
@@ -405,24 +400,22 @@ declare module '@docusaurus/plugin-content-blog' {
405
400
  export type ReadingTimeFunction = (params: {
406
401
  /** Markdown content. */
407
402
  content: string;
403
+ /** Locale for word segmentation. */
404
+ locale: string;
408
405
  /** Front matter. */
409
406
  frontMatter?: BlogPostFrontMatter & {[key: string]: unknown};
410
- /** Options accepted by ngryman/reading-time. */
407
+ /** Options for reading time calculation. */
411
408
  options?: ReadingTimeOptions;
412
409
  }) => number;
413
410
 
414
411
  /**
415
- * @returns The reading time directly plugged into metadata. `undefined` to
416
- * hide reading time for a specific post.
412
+ * @returns The reading time directly plugged into metadata.
413
+ * `undefined` to hide reading time for a specific post.
417
414
  */
418
415
  export type ReadingTimeFunctionOption = (
419
- /**
420
- * The `options` is not provided by the caller; the user can inject their
421
- * own option values into `defaultReadingTime`
422
- */
423
416
  params: Required<Omit<Parameters<ReadingTimeFunction>[0], 'options'>> & {
424
417
  /**
425
- * The default reading time implementation from ngryman/reading-time.
418
+ * The default reading time implementation.
426
419
  */
427
420
  defaultReadingTime: ReadingTimeFunction;
428
421
  },
@@ -5,25 +5,45 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import readingTime from 'reading-time';
9
-
10
8
  const DEFAULT_WORDS_PER_MINUTE = 200;
11
9
 
12
- interface ReadingTimeOptions {
13
- wordsPerMinute?: number;
14
- wordBound?: (char: string) => boolean;
10
+ /**
11
+ * Counts the number of words in a string using Intl.Segmenter.
12
+ * @param content The text content to count words in.
13
+ * @param locale The locale to use for segmentation.
14
+ */
15
+ function countWords(content: string, locale: string): number {
16
+ if (!content) {
17
+ return 0;
18
+ }
19
+ const segmenter = new Intl.Segmenter(locale, {granularity: 'word'});
20
+ let wordCount = 0;
21
+ for (const {isWordLike} of segmenter.segment(content)) {
22
+ if (isWordLike) {
23
+ wordCount += 1;
24
+ }
25
+ }
26
+ return wordCount;
15
27
  }
16
28
 
17
29
  /**
18
- * Calculates the reading time for a given content string.
19
- * Uses the reading-time package under the hood.
30
+ * Calculates the reading time for a given content string using Intl.Segmenter.
31
+ * @param content The text content to calculate reading time for.
32
+ * @param locale Required locale string for Intl.Segmenter
33
+ * @param options Options for reading time calculation.
34
+ * - wordsPerMinute: number of words per minute (default 200)
35
+ * @returns Estimated reading time in minutes (float, rounded to 2 decimals)
20
36
  */
21
37
  export function calculateReadingTime(
22
38
  content: string,
23
- options: ReadingTimeOptions = {},
39
+ locale: string,
40
+ options?: {wordsPerMinute?: number},
24
41
  ): number {
25
- const wordsPerMinute = options.wordsPerMinute ?? DEFAULT_WORDS_PER_MINUTE;
26
- const {wordBound} = options;
27
- return readingTime(content, {wordsPerMinute, ...(wordBound && {wordBound})})
28
- .minutes;
42
+ const wordsPerMinute = options?.wordsPerMinute ?? DEFAULT_WORDS_PER_MINUTE;
43
+ const words = countWords(content, locale);
44
+ if (words === 0) {
45
+ return 0;
46
+ }
47
+ // Calculate reading time in minutes and round to 2 decimal places
48
+ return Math.round((words / wordsPerMinute) * 100) / 100;
29
49
  }