@uniweb/kit 0.9.18 → 0.9.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/kit",
3
- "version": "0.9.18",
3
+ "version": "0.9.20",
4
4
  "description": "Standard component library for Uniweb foundations",
5
5
  "type": "module",
6
6
  "exports": {
@@ -38,15 +38,15 @@
38
38
  "clsx": "^2.1.0",
39
39
  "fuse.js": "^7.0.0",
40
40
  "shiki": "^3.0.0",
41
- "tailwind-merge": "^2.6.0",
42
- "@uniweb/scene": "0.1.2",
43
- "@uniweb/core": "0.7.14"
41
+ "tailwind-merge": "^3.6.0",
42
+ "@uniweb/core": "0.7.16",
43
+ "@uniweb/scene": "0.1.2"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "react": "^19.0.0",
47
47
  "react-dom": "^19.0.0"
48
48
  },
49
49
  "devDependencies": {
50
- "tailwindcss": "^3.4.0"
50
+ "tailwindcss": "^4.0.0"
51
51
  }
52
52
  }
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * SafeHtml Component
3
3
  *
4
- * Safely renders HTML content with topic link resolution.
5
- * Handles the `topic:` protocol for internal content references.
4
+ * Safely renders HTML content with internal-reference link resolution.
5
+ * Handles the `page:` (stable page reference) and `topic:` (legacy) protocols
6
+ * for internal content references — the same protocols kit's <Link> resolves,
7
+ * so inline link marks inside rich-text bodies resolve identically.
6
8
  *
7
9
  * @module @uniweb/kit/SafeHtml
8
10
  */
@@ -10,33 +12,27 @@
10
12
  import React, { Suspense, useMemo } from 'react'
11
13
  import { useWebsite } from '../../hooks/useWebsite.js'
12
14
 
15
+ // Matches an <a> tag's href attribute when it carries a page:/topic: internal
16
+ // reference. Regex-based (not DOMParser) so it runs identically in the browser
17
+ // SPA and during SSR/prerender, where no DOM is available.
18
+ const INTERNAL_HREF_RE = /(<a\b[^>]*?\shref=)(["'])((?:page|topic):[^"']*)\2/gi
19
+
13
20
  /**
14
- * Resolve topic: links in HTML content
15
- * @param {string} html - HTML string with potential topic: links
21
+ * Resolve page:/topic: internal-reference hrefs in an HTML string to real
22
+ * routes via website.makeHref(). Leaves everything else untouched; an
23
+ * unresolvable reference is returned by makeHref unchanged.
24
+ * @param {string} html - HTML string with potential page:/topic: links
16
25
  * @param {Object} website - Website instance
17
- * @returns {string} HTML with resolved links
26
+ * @returns {string} HTML with resolved link hrefs
18
27
  */
19
- function resolveTopicLinks(html, website) {
28
+ function resolveInternalLinks(html, website) {
20
29
  if (!html || typeof html !== 'string') return html
21
- if (!html.includes('topic:')) return html
22
-
23
- try {
24
- const parser = new DOMParser()
25
- const doc = parser.parseFromString(html, 'text/html')
26
- const links = doc.querySelectorAll('a[href^="topic:"]')
27
-
28
- links.forEach((link) => {
29
- const href = link.getAttribute('href')
30
- if (href) {
31
- link.setAttribute('href', website.makeHref(href))
32
- }
33
- })
30
+ if (!html.includes('page:') && !html.includes('topic:')) return html
34
31
 
35
- return doc.body.innerHTML
36
- } catch (error) {
37
- console.warn('[SafeHtml] Error resolving topic links:', error)
38
- return html
39
- }
32
+ return html.replace(
33
+ INTERNAL_HREF_RE,
34
+ (_m, prefix, quote, href) => `${prefix}${quote}${website.makeHref(href)}${quote}`
35
+ )
40
36
  }
41
37
 
42
38
  /**
@@ -51,8 +47,8 @@ function resolveTopicLinks(html, website) {
51
47
  * <SafeHtml value="<p>Hello <strong>World</strong></p>" />
52
48
  *
53
49
  * @example
54
- * // With topic links
55
- * <SafeHtml value='<a href="topic:about">About</a>' />
50
+ * // With internal reference links (page: stable ref, or legacy topic:)
51
+ * <SafeHtml value='<a href="page:93dc5359">About</a>' />
56
52
  */
57
53
  export function SafeHtml({ value, className, as: Component = 'div', ...props }) {
58
54
  const { website, getRoutingComponents } = useWebsite()
@@ -67,8 +63,8 @@ export function SafeHtml({ value, className, as: Component = 'div', ...props })
67
63
  // Handle array of HTML strings
68
64
  const html = Array.isArray(value) ? value.join('') : value
69
65
 
70
- // Resolve topic: links
71
- return website ? resolveTopicLinks(html, website) : html
66
+ // Resolve page:/topic: internal-reference links
67
+ return website ? resolveInternalLinks(html, website) : html
72
68
  }, [value, website])
73
69
 
74
70
  // Use runtime SafeHtml if available (recommended for proper sanitization)