@asteroidcms/core-utils 0.1.0 → 0.1.1

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/dist/index.d.cts CHANGED
@@ -217,6 +217,38 @@ declare function cmsImage(id: string | undefined, options: {
217
217
  /** Hook variant that pulls `cmsUrl`/`mediaPath` from the provider. */
218
218
  declare function useCmsImage(): (id?: string) => string;
219
219
 
220
+ type ReadTimeUnit = "short" | "long";
221
+ interface GetContentReadTimeOptions {
222
+ /**
223
+ * Average words read per minute
224
+ * @default 200
225
+ */
226
+ wordsPerMinute?: number;
227
+ /**
228
+ * Output style
229
+ * short => "3 min read"
230
+ * long => "3 minutes read"
231
+ *
232
+ * @default "short"
233
+ */
234
+ format?: ReadTimeUnit;
235
+ /**
236
+ * Round mode for minutes
237
+ * ceil => always round up
238
+ * round => normal rounding
239
+ * floor => round down
240
+ *
241
+ * @default "ceil"
242
+ */
243
+ round?: "ceil" | "round" | "floor";
244
+ /**
245
+ * Minimum minutes returned
246
+ * @default 1
247
+ */
248
+ minMinutes?: number;
249
+ }
250
+ declare function getContentReadTime(content: string, options?: GetContentReadTimeOptions): string;
251
+
220
252
  /**
221
253
  * Portable rich-text parser for CMS content.
222
254
  *
@@ -263,4 +295,4 @@ declare function RichTextContent({ html, classMap, as, className, }: RichTextCon
263
295
  };
264
296
  }, HTMLElement>;
265
297
 
266
- export { type AsteroidCMSConfig, AsteroidCMSProvider, type AsteroidCMSProviderProps, type ParseRichTextOptions, type ResolvedAsteroidCMSConfig, type RichTextClassKey, type RichTextClassMap, RichTextContent, type UseCmsContentOptions, type UseCmsMutateOptions, cmsImage, createApolloClient, parseRichText, removeEmptyParagraphs, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
298
+ export { type AsteroidCMSConfig, AsteroidCMSProvider, type AsteroidCMSProviderProps, type ParseRichTextOptions, type ResolvedAsteroidCMSConfig, type RichTextClassKey, type RichTextClassMap, RichTextContent, type UseCmsContentOptions, type UseCmsMutateOptions, cmsImage, createApolloClient, getContentReadTime, parseRichText, removeEmptyParagraphs, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
package/dist/index.d.ts CHANGED
@@ -217,6 +217,38 @@ declare function cmsImage(id: string | undefined, options: {
217
217
  /** Hook variant that pulls `cmsUrl`/`mediaPath` from the provider. */
218
218
  declare function useCmsImage(): (id?: string) => string;
219
219
 
220
+ type ReadTimeUnit = "short" | "long";
221
+ interface GetContentReadTimeOptions {
222
+ /**
223
+ * Average words read per minute
224
+ * @default 200
225
+ */
226
+ wordsPerMinute?: number;
227
+ /**
228
+ * Output style
229
+ * short => "3 min read"
230
+ * long => "3 minutes read"
231
+ *
232
+ * @default "short"
233
+ */
234
+ format?: ReadTimeUnit;
235
+ /**
236
+ * Round mode for minutes
237
+ * ceil => always round up
238
+ * round => normal rounding
239
+ * floor => round down
240
+ *
241
+ * @default "ceil"
242
+ */
243
+ round?: "ceil" | "round" | "floor";
244
+ /**
245
+ * Minimum minutes returned
246
+ * @default 1
247
+ */
248
+ minMinutes?: number;
249
+ }
250
+ declare function getContentReadTime(content: string, options?: GetContentReadTimeOptions): string;
251
+
220
252
  /**
221
253
  * Portable rich-text parser for CMS content.
222
254
  *
@@ -263,4 +295,4 @@ declare function RichTextContent({ html, classMap, as, className, }: RichTextCon
263
295
  };
264
296
  }, HTMLElement>;
265
297
 
266
- export { type AsteroidCMSConfig, AsteroidCMSProvider, type AsteroidCMSProviderProps, type ParseRichTextOptions, type ResolvedAsteroidCMSConfig, type RichTextClassKey, type RichTextClassMap, RichTextContent, type UseCmsContentOptions, type UseCmsMutateOptions, cmsImage, createApolloClient, parseRichText, removeEmptyParagraphs, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
298
+ export { type AsteroidCMSConfig, AsteroidCMSProvider, type AsteroidCMSProviderProps, type ParseRichTextOptions, type ResolvedAsteroidCMSConfig, type RichTextClassKey, type RichTextClassMap, RichTextContent, type UseCmsContentOptions, type UseCmsMutateOptions, cmsImage, createApolloClient, getContentReadTime, parseRichText, removeEmptyParagraphs, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
package/dist/index.js CHANGED
@@ -318,6 +318,35 @@ function useCmsImage() {
318
318
  return (id) => cmsImage(id, { cmsUrl, mediaPath });
319
319
  }
320
320
 
321
+ // src/utils/getContentReadTime.ts
322
+ function getContentReadTime(content, options = {}) {
323
+ const {
324
+ wordsPerMinute = 200,
325
+ format = "short",
326
+ round = "ceil",
327
+ minMinutes = 1
328
+ } = options;
329
+ if (!content || typeof content !== "string") {
330
+ return format === "short" ? `${minMinutes} min read` : `${minMinutes} minute read`;
331
+ }
332
+ let text = content.replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<style[\s\S]*?<\/style>/gi, " ");
333
+ text = text.replace(/<\/(p|div|h[1-6]|li|blockquote|pre|code|br|tr)>/gi, " ").replace(/<[^>]+>/g, " ");
334
+ text = text.replace(/&nbsp;/gi, " ").replace(/&amp;/gi, "&").replace(/&lt;/gi, "<").replace(/&gt;/gi, ">").replace(/&#39;/gi, "'").replace(/&quot;/gi, '"');
335
+ text = text.replace(/\s+/g, " ").trim();
336
+ const words = text.split(" ").filter(Boolean).length;
337
+ const rawMinutes = words / wordsPerMinute;
338
+ const roundMap = {
339
+ ceil: Math.ceil,
340
+ round: Math.round,
341
+ floor: Math.floor
342
+ };
343
+ const minutes = Math.max(minMinutes, roundMap[round](rawMinutes));
344
+ if (format === "long") {
345
+ return `${minutes} ${minutes === 1 ? "minute" : "minutes"} read`;
346
+ }
347
+ return `${minutes} min read`;
348
+ }
349
+
321
350
  // src/components/richTextParser.ts
322
351
  var DEFAULT_ALLOWLIST = [
323
352
  "p",
@@ -1450,6 +1479,6 @@ function RichTextContent({
1450
1479
  });
1451
1480
  }
1452
1481
 
1453
- export { AsteroidCMSProvider, RichTextContent, cmsImage, createApolloClient, parseRichText, removeEmptyParagraphs, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
1482
+ export { AsteroidCMSProvider, RichTextContent, cmsImage, createApolloClient, getContentReadTime, parseRichText, removeEmptyParagraphs, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
1454
1483
  //# sourceMappingURL=index.js.map
1455
1484
  //# sourceMappingURL=index.js.map