@asteroidcms/core-utils 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -356,18 +356,20 @@ getContentReadTime(article.body, {
356
356
 
357
357
  ## `<RichTextContent>`
358
358
 
359
- Render Asteroid CMS rich-text JSON/HTML with syntax-highlighted code blocks (via `highlight.js`).
359
+ Render Asteroid CMS rich-text HTML with syntax-highlighted code blocks (via `highlight.js`), self-healing enhancements (copy buttons, blockquote decorations), and slugified heading IDs out of the box.
360
360
 
361
361
  ```tsx
362
- import { RichTextContent } from "@asteroidcms/core-utils";
362
+ import { RichTextContent } from "@asteroidcms/core-utils/client";
363
363
 
364
364
  <RichTextContent
365
- content={article.body}
365
+ html={article.body}
366
+ as="article"
367
+ className="prose"
366
368
  classMap={{ p: "my-2 leading-relaxed", h2: "text-2xl font-bold" }}
367
369
  />;
368
370
  ```
369
371
 
370
- Or use the parser directly:
372
+ Or use the parser directly (server-safe, no `highlight.js`):
371
373
 
372
374
  ```ts
373
375
  import { parseRichText } from "@asteroidcms/core-utils";
@@ -379,6 +381,59 @@ const html = parseRichText(article.body, {
379
381
  });
380
382
  ```
381
383
 
384
+ ### Table of contents
385
+
386
+ Build a live, scroll-tracked ToC from rendered content with `useTableOfContents`. Pair it with `RichTextContent`'s `contentRef` prop:
387
+
388
+ ```tsx
389
+ import { useRef } from "react";
390
+ import {
391
+ RichTextContent,
392
+ useTableOfContents,
393
+ } from "@asteroidcms/core-utils/client";
394
+
395
+ function Article({ slug, html }: { slug: string; html: string }) {
396
+ const contentRef = useRef<HTMLElement | null>(null);
397
+ const { items, activeId } = useTableOfContents(contentRef, {
398
+ levels: [2, 3],
399
+ contentKey: slug, // re-collect when content swaps
400
+ activationOffset: 96, // px from viewport top
401
+ });
402
+
403
+ return (
404
+ <div className="flex gap-8">
405
+ <RichTextContent
406
+ html={html}
407
+ as="article"
408
+ className="prose"
409
+ contentRef={contentRef}
410
+ />
411
+ <nav>
412
+ {items.map((it) => (
413
+ <a
414
+ key={it.id}
415
+ href={`#${it.id}`}
416
+ className={it.id === activeId ? "font-semibold" : ""}
417
+ >
418
+ {it.text}
419
+ </a>
420
+ ))}
421
+ </nav>
422
+ </div>
423
+ );
424
+ }
425
+ ```
426
+
427
+ For a static, server-side outline (RSC layouts, sitemaps, RSS), use `extractHeadingsFromHtml`:
428
+
429
+ ```ts
430
+ import { extractHeadingsFromHtml } from "@asteroidcms/core-utils";
431
+
432
+ const toc = extractHeadingsFromHtml(article.body, { levels: [2, 3] });
433
+ ```
434
+
435
+ See the [full rich-text docs](./docs/web-sdk-react/10-rich-text.md) for `classMap` variants, parser options, and `useTableOfContents` tuning.
436
+
382
437
  ---
383
438
 
384
439
  ## Advanced - bring your own Apollo client