@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.
|
|
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": "^
|
|
42
|
-
"@uniweb/
|
|
43
|
-
"@uniweb/
|
|
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": "^
|
|
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
|
|
5
|
-
* Handles the `
|
|
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:
|
|
15
|
-
*
|
|
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
|
|
26
|
+
* @returns {string} HTML with resolved link hrefs
|
|
18
27
|
*/
|
|
19
|
-
function
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
|
55
|
-
* <SafeHtml value='<a href="
|
|
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 ?
|
|
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)
|