@risali/react 0.2.0 → 0.5.0
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/blog-jsonld.d.ts +74 -0
- package/dist/blog-jsonld.d.ts.map +1 -0
- package/dist/blog-jsonld.js +111 -0
- package/dist/blog-jsonld.js.map +1 -0
- package/dist/blog-list.d.ts +29 -0
- package/dist/blog-list.d.ts.map +1 -0
- package/dist/blog-list.js +113 -0
- package/dist/blog-list.js.map +1 -0
- package/dist/blog-post.d.ts +40 -0
- package/dist/blog-post.d.ts.map +1 -0
- package/dist/blog-post.js +109 -0
- package/dist/blog-post.js.map +1 -0
- package/dist/blog.d.ts +69 -0
- package/dist/blog.d.ts.map +1 -0
- package/dist/blog.js +79 -0
- package/dist/blog.js.map +1 -0
- package/dist/event-marker.d.ts +35 -0
- package/dist/event-marker.d.ts.map +1 -0
- package/dist/event-marker.js +17 -0
- package/dist/event-marker.js.map +1 -0
- package/dist/image.d.ts +33 -33
- package/dist/image.d.ts.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/sanitize.d.ts.map +1 -1
- package/dist/sanitize.js +150 -10
- package/dist/sanitize.js.map +1 -1
- package/dist/tracking-component.d.ts +29 -0
- package/dist/tracking-component.d.ts.map +1 -0
- package/dist/tracking-component.js +100 -0
- package/dist/tracking-component.js.map +1 -0
- package/dist/tracking.d.ts +27 -0
- package/dist/tracking.d.ts.map +1 -0
- package/dist/tracking.js +49 -0
- package/dist/tracking.js.map +1 -0
- package/package.json +1 -1
package/dist/blog.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Blog data helpers for @risali/react v0.3.0 (PR 36c).
|
|
2
|
+
// Pure server-side fetchers around the Risali public blog API. Server
|
|
3
|
+
// components <RisaliBlogList /> and <RisaliBlogPost /> use these.
|
|
4
|
+
// Client components (rare for blog UI) can also call them directly.
|
|
5
|
+
import { resolveApiBase, resolveRevalidateSeconds, resolveSlug, } from "./config.js";
|
|
6
|
+
/**
|
|
7
|
+
* Fetch the published blog post list for the resolved site. Returns
|
|
8
|
+
* an empty array on any failure (unknown site, plan downgrade,
|
|
9
|
+
* network) so the consumer can fall back to an empty grid without
|
|
10
|
+
* dropping the whole page.
|
|
11
|
+
*/
|
|
12
|
+
export async function getRisaliBlogPosts(opts = {}) {
|
|
13
|
+
const slug = resolveSlug(opts.siteSlug);
|
|
14
|
+
const base = resolveApiBase();
|
|
15
|
+
const revalidate = resolveRevalidateSeconds();
|
|
16
|
+
const url = new URL(`${base}/api/public/sites/${slug}/blog/posts`);
|
|
17
|
+
if (opts.limit != null)
|
|
18
|
+
url.searchParams.set("limit", String(opts.limit));
|
|
19
|
+
if (opts.offset != null)
|
|
20
|
+
url.searchParams.set("offset", String(opts.offset));
|
|
21
|
+
if (opts.category)
|
|
22
|
+
url.searchParams.set("category", opts.category);
|
|
23
|
+
try {
|
|
24
|
+
const res = await fetch(url.toString(), {
|
|
25
|
+
next: { revalidate },
|
|
26
|
+
});
|
|
27
|
+
if (!res.ok)
|
|
28
|
+
return [];
|
|
29
|
+
const body = (await res.json());
|
|
30
|
+
if (!body || !("ok" in body) || !body.ok)
|
|
31
|
+
return [];
|
|
32
|
+
return Array.isArray(body.posts) ? body.posts : [];
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Fetch a single blog post by slug. Returns null on any failure so
|
|
40
|
+
* the consumer can render a notFound() page instead of throwing.
|
|
41
|
+
* When `previewToken` is supplied, the call goes through the
|
|
42
|
+
* preview path (no cache, drafts allowed).
|
|
43
|
+
*/
|
|
44
|
+
export async function getRisaliBlogPost(postSlug, opts = {}) {
|
|
45
|
+
if (typeof postSlug !== "string" || !postSlug)
|
|
46
|
+
return null;
|
|
47
|
+
const slug = resolveSlug(opts.siteSlug);
|
|
48
|
+
const base = resolveApiBase();
|
|
49
|
+
const revalidate = resolveRevalidateSeconds();
|
|
50
|
+
const url = new URL(`${base}/api/public/sites/${slug}/blog/posts/${encodeURIComponent(postSlug)}`);
|
|
51
|
+
if (opts.previewToken) {
|
|
52
|
+
url.searchParams.set("preview", opts.previewToken);
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const res = await fetch(url.toString(), {
|
|
56
|
+
next: opts.previewToken
|
|
57
|
+
? // Preview must always be fresh; skip the static cache.
|
|
58
|
+
{ revalidate: 0 }
|
|
59
|
+
: { revalidate },
|
|
60
|
+
});
|
|
61
|
+
if (!res.ok)
|
|
62
|
+
return null;
|
|
63
|
+
const body = (await res.json());
|
|
64
|
+
if (!body || !("ok" in body) || !body.ok)
|
|
65
|
+
return null;
|
|
66
|
+
return body.post ?? null;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build a public `/blog/<slug>` URL for the client web. Helper for
|
|
74
|
+
* hand-rolled card grids that don't use `<RisaliBlogList />`.
|
|
75
|
+
*/
|
|
76
|
+
export function buildBlogPostHref(postSlug) {
|
|
77
|
+
return `/blog/${encodeURIComponent(postSlug)}`;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=blog.js.map
|
package/dist/blog.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blog.js","sourceRoot":"","sources":["../src/blog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type RisaliEventProps = {
|
|
3
|
+
/**
|
|
4
|
+
* Stable lowercase identifier — must match a tracking_events.key configured
|
|
5
|
+
* in Risali for this site. The snippet runtime fires when a click bubbles
|
|
6
|
+
* through this element AND a tracking_events row with the same key exists.
|
|
7
|
+
*
|
|
8
|
+
* Pure marker: this component does NOT subscribe to clicks itself; it only
|
|
9
|
+
* places a stable `data-risali-event="<key>"` attribute on the wrapper so
|
|
10
|
+
* the marketer can later select it from the Risali dashboard's iframe-based
|
|
11
|
+
* event picker without having to maintain CSS selectors by hand.
|
|
12
|
+
*/
|
|
13
|
+
eventKey: string;
|
|
14
|
+
/**
|
|
15
|
+
* Optional element to render around the children. Defaults to <span> for
|
|
16
|
+
* inline contexts; pass "div" for block CTAs / forms.
|
|
17
|
+
*/
|
|
18
|
+
as?: "span" | "div" | "button";
|
|
19
|
+
className?: string;
|
|
20
|
+
children: React.ReactNode;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Code-side marker for Next.js sites: place around a button, link, or form
|
|
24
|
+
* and it'll be discoverable by the Risali event picker via the
|
|
25
|
+
* `[data-risali-event="<eventKey>"]` selector.
|
|
26
|
+
*
|
|
27
|
+
* <RisaliEvent eventKey="lead-form" as="div">
|
|
28
|
+
* <ContactForm />
|
|
29
|
+
* </RisaliEvent>
|
|
30
|
+
*
|
|
31
|
+
* On Lovable sites (no Next.js render path) this component is unused — the
|
|
32
|
+
* marketer picks elements via the dashboard's iframe selector flow instead.
|
|
33
|
+
*/
|
|
34
|
+
export declare function RisaliEvent({ eventKey, as: Tag, className, children, }: RisaliEventProps): import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
//# sourceMappingURL=event-marker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-marker.d.ts","sourceRoot":"","sources":["../src/event-marker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;;;;;;OASG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,EAAE,EAAE,GAAY,EAChB,SAAS,EACT,QAAQ,GACT,EAAE,gBAAgB,2CAMlB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Code-side marker for Next.js sites: place around a button, link, or form
|
|
4
|
+
* and it'll be discoverable by the Risali event picker via the
|
|
5
|
+
* `[data-risali-event="<eventKey>"]` selector.
|
|
6
|
+
*
|
|
7
|
+
* <RisaliEvent eventKey="lead-form" as="div">
|
|
8
|
+
* <ContactForm />
|
|
9
|
+
* </RisaliEvent>
|
|
10
|
+
*
|
|
11
|
+
* On Lovable sites (no Next.js render path) this component is unused — the
|
|
12
|
+
* marketer picks elements via the dashboard's iframe selector flow instead.
|
|
13
|
+
*/
|
|
14
|
+
export function RisaliEvent({ eventKey, as: Tag = "span", className, children, }) {
|
|
15
|
+
return (_jsx(Tag, { "data-risali-event": eventKey, className: className, children: children }));
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=event-marker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-marker.js","sourceRoot":"","sources":["../src/event-marker.tsx"],"names":[],"mappings":";AAuBA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,QAAQ,EACR,EAAE,EAAE,GAAG,GAAG,MAAM,EAChB,SAAS,EACT,QAAQ,GACS;IACjB,OAAO,CACL,KAAC,GAAG,yBAAoB,QAAQ,EAAE,SAAS,EAAE,SAAS,YACnD,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
|
package/dist/image.d.ts
CHANGED
|
@@ -13,17 +13,21 @@ export declare function RisaliImage(props: RisaliImageProps): Promise<import("re
|
|
|
13
13
|
src: string;
|
|
14
14
|
alt: string;
|
|
15
15
|
"data-risali-key": string;
|
|
16
|
+
children?: import("react").ReactNode;
|
|
17
|
+
className?: string | undefined | undefined;
|
|
16
18
|
style?: CSSProperties;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
fetchPriority?: "high" | "low" | "auto" | undefined | undefined;
|
|
19
|
+
hidden?: boolean | undefined | undefined;
|
|
20
|
+
color?: string | undefined | undefined;
|
|
20
21
|
height?: number | string | undefined | undefined;
|
|
21
|
-
loading?: "eager" | "lazy" | undefined | undefined;
|
|
22
|
-
referrerPolicy?: import("react").HTMLAttributeReferrerPolicy | undefined;
|
|
23
|
-
sizes?: string | undefined | undefined;
|
|
24
|
-
srcSet?: string | undefined | undefined;
|
|
25
|
-
useMap?: string | undefined | undefined;
|
|
26
22
|
width?: number | string | undefined | undefined;
|
|
23
|
+
loading?: "eager" | "lazy" | undefined | undefined;
|
|
24
|
+
rel?: string | undefined | undefined;
|
|
25
|
+
id?: string | undefined | undefined;
|
|
26
|
+
title?: string | undefined | undefined;
|
|
27
|
+
dangerouslySetInnerHTML?: {
|
|
28
|
+
__html: string | TrustedHTML;
|
|
29
|
+
} | undefined | undefined;
|
|
30
|
+
fetchPriority?: "high" | "low" | "auto" | undefined | undefined;
|
|
27
31
|
defaultChecked?: boolean | undefined | undefined;
|
|
28
32
|
defaultValue?: string | number | readonly string[] | undefined;
|
|
29
33
|
suppressContentEditableWarning?: boolean | undefined | undefined;
|
|
@@ -31,20 +35,16 @@ export declare function RisaliImage(props: RisaliImageProps): Promise<import("re
|
|
|
31
35
|
accessKey?: string | undefined | undefined;
|
|
32
36
|
autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters" | undefined | (string & {}) | undefined;
|
|
33
37
|
autoFocus?: boolean | undefined | undefined;
|
|
34
|
-
|
|
35
|
-
contentEditable?: (boolean | "true" | "false") | "inherit" | "plaintext-only" | undefined;
|
|
38
|
+
contentEditable?: "inherit" | (boolean | "false" | "true") | "plaintext-only" | undefined;
|
|
36
39
|
contextMenu?: string | undefined | undefined;
|
|
37
40
|
dir?: string | undefined | undefined;
|
|
38
|
-
draggable?: (boolean | "
|
|
41
|
+
draggable?: (boolean | "false" | "true") | undefined;
|
|
39
42
|
enterKeyHint?: "enter" | "done" | "go" | "next" | "previous" | "search" | "send" | undefined | undefined;
|
|
40
|
-
hidden?: boolean | undefined | undefined;
|
|
41
|
-
id?: string | undefined | undefined;
|
|
42
43
|
lang?: string | undefined | undefined;
|
|
43
44
|
nonce?: string | undefined | undefined;
|
|
44
45
|
slot?: string | undefined | undefined;
|
|
45
|
-
spellCheck?: (boolean | "
|
|
46
|
+
spellCheck?: (boolean | "false" | "true") | undefined;
|
|
46
47
|
tabIndex?: number | undefined | undefined;
|
|
47
|
-
title?: string | undefined | undefined;
|
|
48
48
|
translate?: "yes" | "no" | undefined | undefined;
|
|
49
49
|
radioGroup?: string | undefined | undefined;
|
|
50
50
|
role?: import("react").AriaRole | undefined;
|
|
@@ -53,14 +53,12 @@ export declare function RisaliImage(props: RisaliImageProps): Promise<import("re
|
|
|
53
53
|
inlist?: any;
|
|
54
54
|
prefix?: string | undefined | undefined;
|
|
55
55
|
property?: string | undefined | undefined;
|
|
56
|
-
rel?: string | undefined | undefined;
|
|
57
56
|
resource?: string | undefined | undefined;
|
|
58
57
|
rev?: string | undefined | undefined;
|
|
59
58
|
typeof?: string | undefined | undefined;
|
|
60
59
|
vocab?: string | undefined | undefined;
|
|
61
60
|
autoCorrect?: string | undefined | undefined;
|
|
62
61
|
autoSave?: string | undefined | undefined;
|
|
63
|
-
color?: string | undefined | undefined;
|
|
64
62
|
itemProp?: string | undefined | undefined;
|
|
65
63
|
itemScope?: boolean | undefined | undefined;
|
|
66
64
|
itemType?: string | undefined | undefined;
|
|
@@ -78,11 +76,11 @@ export declare function RisaliImage(props: RisaliImageProps): Promise<import("re
|
|
|
78
76
|
exportparts?: string | undefined | undefined;
|
|
79
77
|
part?: string | undefined | undefined;
|
|
80
78
|
"aria-activedescendant"?: string | undefined | undefined;
|
|
81
|
-
"aria-atomic"?: (boolean | "
|
|
79
|
+
"aria-atomic"?: (boolean | "false" | "true") | undefined;
|
|
82
80
|
"aria-autocomplete"?: "none" | "inline" | "list" | "both" | undefined | undefined;
|
|
83
81
|
"aria-braillelabel"?: string | undefined | undefined;
|
|
84
82
|
"aria-brailleroledescription"?: string | undefined | undefined;
|
|
85
|
-
"aria-busy"?: (boolean | "
|
|
83
|
+
"aria-busy"?: (boolean | "false" | "true") | undefined;
|
|
86
84
|
"aria-checked"?: boolean | "false" | "mixed" | "true" | undefined | undefined;
|
|
87
85
|
"aria-colcount"?: number | undefined | undefined;
|
|
88
86
|
"aria-colindex"?: number | undefined | undefined;
|
|
@@ -93,47 +91,43 @@ export declare function RisaliImage(props: RisaliImageProps): Promise<import("re
|
|
|
93
91
|
"aria-describedby"?: string | undefined | undefined;
|
|
94
92
|
"aria-description"?: string | undefined | undefined;
|
|
95
93
|
"aria-details"?: string | undefined | undefined;
|
|
96
|
-
"aria-disabled"?: (boolean | "
|
|
94
|
+
"aria-disabled"?: (boolean | "false" | "true") | undefined;
|
|
97
95
|
"aria-dropeffect"?: "none" | "copy" | "execute" | "link" | "move" | "popup" | undefined | undefined;
|
|
98
96
|
"aria-errormessage"?: string | undefined | undefined;
|
|
99
|
-
"aria-expanded"?: (boolean | "
|
|
97
|
+
"aria-expanded"?: (boolean | "false" | "true") | undefined;
|
|
100
98
|
"aria-flowto"?: string | undefined | undefined;
|
|
101
|
-
"aria-grabbed"?: (boolean | "
|
|
99
|
+
"aria-grabbed"?: (boolean | "false" | "true") | undefined;
|
|
102
100
|
"aria-haspopup"?: boolean | "false" | "true" | "menu" | "listbox" | "tree" | "grid" | "dialog" | undefined | undefined;
|
|
103
|
-
"aria-hidden"?: (boolean | "
|
|
101
|
+
"aria-hidden"?: (boolean | "false" | "true") | undefined;
|
|
104
102
|
"aria-invalid"?: boolean | "false" | "true" | "grammar" | "spelling" | undefined | undefined;
|
|
105
103
|
"aria-keyshortcuts"?: string | undefined | undefined;
|
|
106
104
|
"aria-label"?: string | undefined | undefined;
|
|
107
105
|
"aria-labelledby"?: string | undefined | undefined;
|
|
108
106
|
"aria-level"?: number | undefined | undefined;
|
|
109
107
|
"aria-live"?: "off" | "assertive" | "polite" | undefined | undefined;
|
|
110
|
-
"aria-modal"?: (boolean | "
|
|
111
|
-
"aria-multiline"?: (boolean | "
|
|
112
|
-
"aria-multiselectable"?: (boolean | "
|
|
108
|
+
"aria-modal"?: (boolean | "false" | "true") | undefined;
|
|
109
|
+
"aria-multiline"?: (boolean | "false" | "true") | undefined;
|
|
110
|
+
"aria-multiselectable"?: (boolean | "false" | "true") | undefined;
|
|
113
111
|
"aria-orientation"?: "horizontal" | "vertical" | undefined | undefined;
|
|
114
112
|
"aria-owns"?: string | undefined | undefined;
|
|
115
113
|
"aria-placeholder"?: string | undefined | undefined;
|
|
116
114
|
"aria-posinset"?: number | undefined | undefined;
|
|
117
115
|
"aria-pressed"?: boolean | "false" | "mixed" | "true" | undefined | undefined;
|
|
118
|
-
"aria-readonly"?: (boolean | "
|
|
116
|
+
"aria-readonly"?: (boolean | "false" | "true") | undefined;
|
|
119
117
|
"aria-relevant"?: "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text" | "text additions" | "text removals" | undefined | undefined;
|
|
120
|
-
"aria-required"?: (boolean | "
|
|
118
|
+
"aria-required"?: (boolean | "false" | "true") | undefined;
|
|
121
119
|
"aria-roledescription"?: string | undefined | undefined;
|
|
122
120
|
"aria-rowcount"?: number | undefined | undefined;
|
|
123
121
|
"aria-rowindex"?: number | undefined | undefined;
|
|
124
122
|
"aria-rowindextext"?: string | undefined | undefined;
|
|
125
123
|
"aria-rowspan"?: number | undefined | undefined;
|
|
126
|
-
"aria-selected"?: (boolean | "
|
|
124
|
+
"aria-selected"?: (boolean | "false" | "true") | undefined;
|
|
127
125
|
"aria-setsize"?: number | undefined | undefined;
|
|
128
126
|
"aria-sort"?: "none" | "ascending" | "descending" | "other" | undefined | undefined;
|
|
129
127
|
"aria-valuemax"?: number | undefined | undefined;
|
|
130
128
|
"aria-valuemin"?: number | undefined | undefined;
|
|
131
129
|
"aria-valuenow"?: number | undefined | undefined;
|
|
132
130
|
"aria-valuetext"?: string | undefined | undefined;
|
|
133
|
-
children?: import("react").ReactNode;
|
|
134
|
-
dangerouslySetInnerHTML?: {
|
|
135
|
-
__html: string | TrustedHTML;
|
|
136
|
-
} | undefined | undefined;
|
|
137
131
|
onCopy?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
|
|
138
132
|
onCopyCapture?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
|
|
139
133
|
onCut?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
|
|
@@ -302,5 +296,11 @@ export declare function RisaliImage(props: RisaliImageProps): Promise<import("re
|
|
|
302
296
|
onTransitionRunCapture?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
303
297
|
onTransitionStart?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
304
298
|
onTransitionStartCapture?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
299
|
+
crossOrigin?: "" | "anonymous" | "use-credentials" | undefined;
|
|
300
|
+
decoding?: "async" | "auto" | "sync" | undefined | undefined;
|
|
301
|
+
referrerPolicy?: import("react").HTMLAttributeReferrerPolicy | undefined;
|
|
302
|
+
sizes?: string | undefined | undefined;
|
|
303
|
+
srcSet?: string | undefined | undefined;
|
|
304
|
+
useMap?: string | undefined | undefined;
|
|
305
305
|
}, HTMLElement>>;
|
|
306
306
|
//# sourceMappingURL=image.d.ts.map
|
package/dist/image.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAG9D,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,YAAY,CAAC;AAIlE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,iBAAiB,CAAC,gBAAgB,CAAC,EACnC,KAAK,GAAG,KAAK,CACd,GAAG;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAOF,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAG9D,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,YAAY,CAAC;AAIlE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,iBAAiB,CAAC,gBAAgB,CAAC,EACnC,KAAK,GAAG,KAAK,CACd,GAAG;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAOF,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB;;;;;;YAR/C,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0CtB"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,4 +9,18 @@ export { RisaliRichText } from "./rich-text.js";
|
|
|
9
9
|
export type { RisaliRichTextProps } from "./rich-text.js";
|
|
10
10
|
export { sanitiseRichText } from "./sanitize.js";
|
|
11
11
|
export type { RisaliBlock, RisaliBlockType, RisaliContent, RisaliImageValue, RisaliStyleOverrides, } from "./types.js";
|
|
12
|
+
export { getRisaliBlogPosts, getRisaliBlogPost, buildBlogPostHref, } from "./blog.js";
|
|
13
|
+
export type { GetBlogPostOptions, GetBlogPostsOptions, RisaliBlogPost as RisaliBlogPostType, RisaliBlogPostCard, RisaliBlogPostSeo, } from "./blog.js";
|
|
14
|
+
export { RisaliBlogList } from "./blog-list.js";
|
|
15
|
+
export type { RisaliBlogListProps } from "./blog-list.js";
|
|
16
|
+
export { RisaliBlogPost } from "./blog-post.js";
|
|
17
|
+
export type { RisaliBlogPostProps } from "./blog-post.js";
|
|
18
|
+
export { buildBlogPostJsonLd, buildBlogPostMetadata, } from "./blog-jsonld.js";
|
|
19
|
+
export type { BuildBlogPostJsonLdOptions } from "./blog-jsonld.js";
|
|
20
|
+
export { getRisaliTrackingConfig } from "./tracking.js";
|
|
21
|
+
export type { RisaliTrackingConfig, GetTrackingConfigOptions, } from "./tracking.js";
|
|
22
|
+
export { RisaliTracking } from "./tracking-component.js";
|
|
23
|
+
export type { RisaliTrackingProps } from "./tracking-component.js";
|
|
24
|
+
export { RisaliEvent } from "./event-marker.js";
|
|
25
|
+
export type { RisaliEventProps } from "./event-marker.js";
|
|
12
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EACV,WAAW,EACX,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EACV,WAAW,EACX,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,IAAI,kBAAkB,EACpC,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAGnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,YAAY,EACV,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGnE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,4 +4,14 @@ export { RisaliText } from "./text.js";
|
|
|
4
4
|
export { RisaliImage } from "./image.js";
|
|
5
5
|
export { RisaliRichText } from "./rich-text.js";
|
|
6
6
|
export { sanitiseRichText } from "./sanitize.js";
|
|
7
|
+
// v0.3.0 — blog module (PR 36c).
|
|
8
|
+
export { getRisaliBlogPosts, getRisaliBlogPost, buildBlogPostHref, } from "./blog.js";
|
|
9
|
+
export { RisaliBlogList } from "./blog-list.js";
|
|
10
|
+
export { RisaliBlogPost } from "./blog-post.js";
|
|
11
|
+
export { buildBlogPostJsonLd, buildBlogPostMetadata, } from "./blog-jsonld.js";
|
|
12
|
+
// v0.4.0 — marketing tracking (PR 38a).
|
|
13
|
+
export { getRisaliTrackingConfig } from "./tracking.js";
|
|
14
|
+
export { RisaliTracking } from "./tracking-component.js";
|
|
15
|
+
// v0.5.0 — event marker (PR 38b).
|
|
16
|
+
export { RisaliEvent } from "./event-marker.js";
|
|
7
17
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AASjD,iCAAiC;AACjC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AAQnB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAG1B,wCAAwC;AACxC,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAKxD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,kCAAkC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/sanitize.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAuMA,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA+DtD"}
|
package/dist/sanitize.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
// Minimal HTML sanitiser for Risali rich-text blocks.
|
|
2
2
|
// Pure (no DOM, no external deps) so it runs in RSC / Node / tests alike.
|
|
3
3
|
// Defense-in-depth over the editor-side sanitiser planned for PR 26.
|
|
4
|
+
//
|
|
5
|
+
// Tag set grew in PR 36a (blog rendering): added h2/h3/h4, ul/ol/li,
|
|
6
|
+
// blockquote, pre, code, hr, figure/figcaption, img (with src
|
|
7
|
+
// whitelist), iframe (YouTube/Vimeo embed src whitelist).
|
|
4
8
|
const ALLOWED_TAGS = new Set([
|
|
9
|
+
// Inline (original set)
|
|
5
10
|
"span",
|
|
6
11
|
"strong",
|
|
7
12
|
"b",
|
|
@@ -11,10 +16,29 @@ const ALLOWED_TAGS = new Set([
|
|
|
11
16
|
"br",
|
|
12
17
|
"a",
|
|
13
18
|
"p",
|
|
19
|
+
// Blog block tags (PR 36a)
|
|
20
|
+
"h2",
|
|
21
|
+
"h3",
|
|
22
|
+
"h4",
|
|
23
|
+
"ul",
|
|
24
|
+
"ol",
|
|
25
|
+
"li",
|
|
26
|
+
"blockquote",
|
|
27
|
+
"pre",
|
|
28
|
+
"code",
|
|
29
|
+
"hr",
|
|
30
|
+
"figure",
|
|
31
|
+
"figcaption",
|
|
32
|
+
"img",
|
|
33
|
+
"iframe",
|
|
14
34
|
]);
|
|
15
|
-
const VOID_TAGS = new Set(["br"]);
|
|
35
|
+
const VOID_TAGS = new Set(["br", "hr", "img"]);
|
|
36
|
+
// Self-closing in the source but with allowed attributes — iframe is a
|
|
37
|
+
// special case because we want to render `<iframe src=... allowfullscreen></iframe>`
|
|
38
|
+
// even though it carries no children in practice.
|
|
39
|
+
const FORCED_PAIRED = new Set(["iframe"]);
|
|
16
40
|
const ALLOWED_ATTRS = {
|
|
17
|
-
a: new Set(["href"]),
|
|
41
|
+
a: new Set(["href", "rel"]),
|
|
18
42
|
span: new Set(["style"]),
|
|
19
43
|
p: new Set(["style"]),
|
|
20
44
|
strong: new Set(["style"]),
|
|
@@ -22,12 +46,52 @@ const ALLOWED_ATTRS = {
|
|
|
22
46
|
b: new Set(["style"]),
|
|
23
47
|
i: new Set(["style"]),
|
|
24
48
|
u: new Set(["style"]),
|
|
49
|
+
// Blog tags
|
|
50
|
+
h2: new Set(["id"]),
|
|
51
|
+
h3: new Set(["id"]),
|
|
52
|
+
h4: new Set(["id"]),
|
|
53
|
+
code: new Set(["class"]), // language-<lang> only
|
|
54
|
+
img: new Set(["src", "alt", "width", "height", "loading"]),
|
|
55
|
+
iframe: new Set([
|
|
56
|
+
"src",
|
|
57
|
+
"width",
|
|
58
|
+
"height",
|
|
59
|
+
"allowfullscreen",
|
|
60
|
+
"loading",
|
|
61
|
+
"title",
|
|
62
|
+
]),
|
|
25
63
|
};
|
|
26
|
-
|
|
64
|
+
// href / a tag: http(s), mail/tel, or root-relative path.
|
|
65
|
+
const SAFE_HREF_RE = /^(https?:\/\/|mailto:|tel:|\/[^/])/i;
|
|
66
|
+
// img src: http(s) or root-relative (no protocol-relative // URLs).
|
|
67
|
+
const SAFE_IMG_SRC_RE = /^(https?:\/\/|\/[^/])/i;
|
|
68
|
+
// iframe src: only YouTube + Vimeo embed paths. Blocks everything else
|
|
69
|
+
// including data:, javascript:, and arbitrary 3rd-party embeds. The
|
|
70
|
+
// blog HTML builder (lib/blog/normalize.ts) normalises watch URLs
|
|
71
|
+
// into these embed forms server-side, so by the time we sanitise
|
|
72
|
+
// they always match.
|
|
73
|
+
const SAFE_IFRAME_SRC_RE = /^https?:\/\/(?:www\.)?(?:youtube\.com\/embed\/|youtube-nocookie\.com\/embed\/|player\.vimeo\.com\/video\/)[A-Za-z0-9_-][A-Za-z0-9_\-?&=/.]*$/i;
|
|
74
|
+
// <a rel=...> — whitelist common security/SEO tokens. Anything else
|
|
75
|
+
// (e.g. dns-prefetch via shenanigans) is dropped.
|
|
76
|
+
const ALLOWED_REL = new Set([
|
|
77
|
+
"noopener",
|
|
78
|
+
"noreferrer",
|
|
79
|
+
"nofollow",
|
|
80
|
+
"sponsored",
|
|
81
|
+
"ugc",
|
|
82
|
+
]);
|
|
83
|
+
// <code class="language-xxx">.
|
|
84
|
+
const SAFE_CODE_CLASS_RE = /^language-[A-Za-z0-9_-]{1,30}$/;
|
|
85
|
+
// Numeric width/height for img/iframe.
|
|
86
|
+
const SAFE_NUMERIC_RE = /^\d{1,5}$/;
|
|
87
|
+
// loading="lazy"|"eager".
|
|
88
|
+
const SAFE_LOADING_RE = /^(lazy|eager)$/;
|
|
89
|
+
// id="…" for heading anchors — keep tame.
|
|
90
|
+
const SAFE_ID_RE = /^[A-Za-z][A-Za-z0-9_-]{0,80}$/;
|
|
27
91
|
const STYLE_COLOR_RE = /(?:^|;)\s*color\s*:\s*(#[0-9a-fA-F]{6})\s*(?:;|$)/;
|
|
28
92
|
const STYLE_FONT_SIZE_RE = /(?:^|;)\s*font-size\s*:\s*([0-9]+(?:\.[0-9]+)?)(px|rem|em)\s*(?:;|$)/i;
|
|
29
93
|
const TAG_RE = /<\/?([a-zA-Z][a-zA-Z0-9]*)((?:\s+[^>]*)?)\/?>|<!--[\s\S]*?-->/g;
|
|
30
|
-
const ATTR_RE = /([a-zA-Z][a-zA-Z0-9_-]*)\s*=\s*("([^"]*)"|'([^']*)'|([^\s"'>]+))/g;
|
|
94
|
+
const ATTR_RE = /([a-zA-Z][a-zA-Z0-9_-]*)\s*=\s*("([^"]*)"|'([^']*)'|([^\s"'>]+))|([a-zA-Z][a-zA-Z0-9_-]*)(?=\s|$|\/)/g;
|
|
31
95
|
function sanitiseStyle(raw) {
|
|
32
96
|
const out = [];
|
|
33
97
|
const colorMatch = raw.match(STYLE_COLOR_RE);
|
|
@@ -44,6 +108,13 @@ function sanitiseStyle(raw) {
|
|
|
44
108
|
}
|
|
45
109
|
return out.join(";");
|
|
46
110
|
}
|
|
111
|
+
function sanitiseRel(raw) {
|
|
112
|
+
const tokens = raw
|
|
113
|
+
.split(/\s+/)
|
|
114
|
+
.map((t) => t.toLowerCase())
|
|
115
|
+
.filter((t) => ALLOWED_REL.has(t));
|
|
116
|
+
return Array.from(new Set(tokens)).join(" ");
|
|
117
|
+
}
|
|
47
118
|
function sanitiseAttrs(tag, raw) {
|
|
48
119
|
const allowed = ALLOWED_ATTRS[tag];
|
|
49
120
|
if (!allowed || !raw.trim())
|
|
@@ -52,20 +123,72 @@ function sanitiseAttrs(tag, raw) {
|
|
|
52
123
|
ATTR_RE.lastIndex = 0;
|
|
53
124
|
let match;
|
|
54
125
|
while ((match = ATTR_RE.exec(raw)) !== null) {
|
|
55
|
-
|
|
126
|
+
// Two variants: `name="value"` (groups 1..5) or bare `name` (group 6).
|
|
127
|
+
const name = (match[1] ?? match[6] ?? "").toLowerCase();
|
|
56
128
|
if (!name || !allowed.has(name))
|
|
57
129
|
continue;
|
|
58
|
-
const
|
|
130
|
+
const rawValue = match[3] ?? match[4] ?? match[5] ?? "";
|
|
131
|
+
const isBoolean = !match[1] && !!match[6];
|
|
59
132
|
if (name === "href") {
|
|
60
|
-
if (SAFE_HREF_RE.test(
|
|
61
|
-
parts.push(`href="${escapeAttr(
|
|
133
|
+
if (SAFE_HREF_RE.test(rawValue)) {
|
|
134
|
+
parts.push(`href="${escapeAttr(rawValue)}"`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else if (name === "rel") {
|
|
138
|
+
const safe = sanitiseRel(rawValue);
|
|
139
|
+
if (safe)
|
|
140
|
+
parts.push(`rel="${escapeAttr(safe)}"`);
|
|
141
|
+
}
|
|
142
|
+
else if (name === "src" && tag === "img") {
|
|
143
|
+
if (SAFE_IMG_SRC_RE.test(rawValue)) {
|
|
144
|
+
parts.push(`src="${escapeAttr(rawValue)}"`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else if (name === "src" && tag === "iframe") {
|
|
148
|
+
if (SAFE_IFRAME_SRC_RE.test(rawValue)) {
|
|
149
|
+
parts.push(`src="${escapeAttr(rawValue)}"`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else if (name === "alt") {
|
|
153
|
+
// alt may legitimately be empty (decorative images).
|
|
154
|
+
parts.push(`alt="${escapeAttr(rawValue.slice(0, 500))}"`);
|
|
155
|
+
}
|
|
156
|
+
else if (name === "width" || name === "height") {
|
|
157
|
+
if (SAFE_NUMERIC_RE.test(rawValue)) {
|
|
158
|
+
parts.push(`${name}="${rawValue}"`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else if (name === "loading") {
|
|
162
|
+
if (SAFE_LOADING_RE.test(rawValue)) {
|
|
163
|
+
parts.push(`${name}="${rawValue}"`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else if (name === "allowfullscreen") {
|
|
167
|
+
// Boolean attr — emit canonical form.
|
|
168
|
+
parts.push("allowfullscreen");
|
|
169
|
+
}
|
|
170
|
+
else if (name === "title") {
|
|
171
|
+
parts.push(`title="${escapeAttr(rawValue.slice(0, 200))}"`);
|
|
172
|
+
}
|
|
173
|
+
else if (name === "id") {
|
|
174
|
+
if (SAFE_ID_RE.test(rawValue)) {
|
|
175
|
+
parts.push(`id="${escapeAttr(rawValue)}"`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else if (name === "class" && tag === "code") {
|
|
179
|
+
if (SAFE_CODE_CLASS_RE.test(rawValue)) {
|
|
180
|
+
parts.push(`class="${escapeAttr(rawValue)}"`);
|
|
62
181
|
}
|
|
63
182
|
}
|
|
64
183
|
else if (name === "style") {
|
|
65
|
-
const safe = sanitiseStyle(
|
|
184
|
+
const safe = sanitiseStyle(rawValue);
|
|
66
185
|
if (safe)
|
|
67
186
|
parts.push(`style="${escapeAttr(safe)}"`);
|
|
68
187
|
}
|
|
188
|
+
// Boolean attrs without explicit value (allowfullscreen alone).
|
|
189
|
+
if (isBoolean && name === "allowfullscreen") {
|
|
190
|
+
// Already emitted above.
|
|
191
|
+
}
|
|
69
192
|
}
|
|
70
193
|
return parts.length ? " " + parts.join(" ") : "";
|
|
71
194
|
}
|
|
@@ -82,6 +205,10 @@ export function sanitiseRichText(input) {
|
|
|
82
205
|
const stack = [];
|
|
83
206
|
const pieces = [];
|
|
84
207
|
let lastIndex = 0;
|
|
208
|
+
// Inside <pre><code> we want raw text rendering (no further tag
|
|
209
|
+
// matching). We don't fully suspend the parser — that would break
|
|
210
|
+
// nested allowed tags in rare edge cases — but we leave the
|
|
211
|
+
// children-as-text fallback to the surrounding escape pass.
|
|
85
212
|
TAG_RE.lastIndex = 0;
|
|
86
213
|
let match;
|
|
87
214
|
while ((match = TAG_RE.exec(input)) !== null) {
|
|
@@ -106,11 +233,24 @@ export function sanitiseRichText(input) {
|
|
|
106
233
|
}
|
|
107
234
|
}
|
|
108
235
|
else if (VOID_TAGS.has(tag)) {
|
|
109
|
-
|
|
236
|
+
const attrs = sanitiseAttrs(tag, match[2] || "");
|
|
237
|
+
// img requires a valid src; if sanitiseAttrs dropped it, the
|
|
238
|
+
// element renders as `<img alt="">` which is benign.
|
|
239
|
+
pieces.push(`<${tag}${attrs}/>`);
|
|
110
240
|
}
|
|
111
241
|
else {
|
|
112
242
|
const attrs = sanitiseAttrs(tag, match[2] || "");
|
|
243
|
+
// iframe with no src is useless and could confuse readers; drop.
|
|
244
|
+
if (tag === "iframe" && !/\ssrc=/.test(attrs))
|
|
245
|
+
continue;
|
|
113
246
|
pieces.push(`<${tag}${attrs}>`);
|
|
247
|
+
if (FORCED_PAIRED.has(tag)) {
|
|
248
|
+
// Always close iframe — the source may have written
|
|
249
|
+
// `<iframe ...></iframe>` (good) or `<iframe ... />` (sloppy
|
|
250
|
+
// but accepted here). We push the open tag and rely on the
|
|
251
|
+
// close tag in the source. If none arrives, the trailing
|
|
252
|
+
// stack drain below closes it for us.
|
|
253
|
+
}
|
|
114
254
|
stack.push(tag);
|
|
115
255
|
}
|
|
116
256
|
}
|
package/dist/sanitize.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,0EAA0E;AAC1E,qEAAqE;
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"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"}
|