@risali/react 0.2.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/README.md +156 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +29 -0
- package/dist/config.js.map +1 -0
- package/dist/content.d.ts +19 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +77 -0
- package/dist/content.js.map +1 -0
- package/dist/image.d.ts +306 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +29 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/rich-text.d.ts +14 -0
- package/dist/rich-text.d.ts.map +1 -0
- package/dist/rich-text.js +26 -0
- package/dist/rich-text.js.map +1 -0
- package/dist/sanitize.d.ts +2 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +130 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/style.d.ts +6 -0
- package/dist/style.d.ts.map +1 -0
- package/dist/style.js +28 -0
- package/dist/style.js.map +1 -0
- package/dist/text.d.ts +15 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +23 -0
- package/dist/text.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# @risali/react
|
|
2
|
+
|
|
3
|
+
React Server Components for [Risali.app](https://risali.app) — fetch editable text/image/rich-text blocks from a client's Risali site at SSR time.
|
|
4
|
+
|
|
5
|
+
Built for Next.js 15 App Router (React 19). Zero client-side JavaScript: every block is rendered server-side, the editable markers ship in plain HTML.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @risali/react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Configure
|
|
14
|
+
|
|
15
|
+
Set the site slug once, in your project's `.env`:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
RISALI_SITE_SLUG=mojweb
|
|
19
|
+
# Optional — defaults to https://app.risali.app
|
|
20
|
+
RISALI_API_BASE=https://app.risali.app
|
|
21
|
+
# Optional — Next.js fetch revalidate seconds (default 60)
|
|
22
|
+
RISALI_REVALIDATE_SECONDS=60
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`NEXT_PUBLIC_RISALI_SITE_SLUG` is also accepted if you'd rather expose it.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
### Text
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
// app/page.tsx
|
|
33
|
+
import { RisaliText } from "@risali/react";
|
|
34
|
+
|
|
35
|
+
export default function HomePage() {
|
|
36
|
+
return (
|
|
37
|
+
<section>
|
|
38
|
+
<RisaliText
|
|
39
|
+
as="h1"
|
|
40
|
+
pageKey="hero_title"
|
|
41
|
+
defaultValue="Vitajte na našom webe"
|
|
42
|
+
path="/"
|
|
43
|
+
className="text-5xl font-bold"
|
|
44
|
+
/>
|
|
45
|
+
<RisaliText
|
|
46
|
+
pageKey="hero_subtitle"
|
|
47
|
+
defaultValue="Robíme weby, ktoré klient sám upravuje."
|
|
48
|
+
path="/"
|
|
49
|
+
/>
|
|
50
|
+
</section>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The component fetches once per `(slug, path)` pair — Next.js's built-in `fetch` cache deduplicates identical URLs in a request, so multiple `<RisaliText>` calls on the same page share one network call.
|
|
56
|
+
|
|
57
|
+
### Image
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { RisaliImage } from "@risali/react";
|
|
61
|
+
|
|
62
|
+
<RisaliImage
|
|
63
|
+
pageKey="hero_photo"
|
|
64
|
+
defaultSrc="/hero-fallback.jpg"
|
|
65
|
+
defaultAlt="Naša prevádzka"
|
|
66
|
+
path="/"
|
|
67
|
+
width={1200}
|
|
68
|
+
height={600}
|
|
69
|
+
className="rounded-2xl"
|
|
70
|
+
/>;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Only `http(s)://…` and `/local-path` sources from the Risali block are honoured; anything else falls back to `defaultSrc`.
|
|
74
|
+
|
|
75
|
+
### Rich text (bold / italic / palette colour)
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { RisaliRichText } from "@risali/react";
|
|
79
|
+
|
|
80
|
+
<RisaliRichText
|
|
81
|
+
as="div"
|
|
82
|
+
pageKey="about_body"
|
|
83
|
+
defaultValue="<p>Sme tu už <strong>10 rokov</strong>.</p>"
|
|
84
|
+
path="/o-nas"
|
|
85
|
+
/>;
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Block HTML is sanitised on the server before render. Whitelisted tags: `span`, `strong`, `b`, `em`, `i`, `u`, `br`, `a`, `p`. Whitelisted attributes: `style` (only `color:#RRGGBB` + `font-size:<n>px|rem|em`) and `href` (only `http(s)://`, `mailto:`, `tel:`, or `/local`). Everything else — `<script>`, `<img>` (use `<RisaliImage>` instead), `onerror`, `javascript:`, `style="background: url(…)"` — is stripped.
|
|
89
|
+
|
|
90
|
+
### Sharing one fetch across many components
|
|
91
|
+
|
|
92
|
+
If a page renders many Risali blocks, you can pull content once and thread it down — the components skip their own fetch when `content` is provided:
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
import { getRisaliContent, RisaliText, RisaliImage } from "@risali/react";
|
|
96
|
+
|
|
97
|
+
export default async function HomePage() {
|
|
98
|
+
const content = await getRisaliContent("/");
|
|
99
|
+
return (
|
|
100
|
+
<>
|
|
101
|
+
<RisaliText content={content} pageKey="hero_title" defaultValue="Vitajte" />
|
|
102
|
+
<RisaliImage content={content} pageKey="hero_photo" defaultSrc="/h.jpg" />
|
|
103
|
+
</>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Pure helpers for client components (`"use client"`)
|
|
109
|
+
|
|
110
|
+
The `<Risali*>` components are async server components — they can't be used directly inside a `"use client"` boundary. For those cases, fetch `content` once in your server page and use the pure helpers inline:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
// app/page.tsx — server component
|
|
114
|
+
import { getRisaliContent } from "@risali/react";
|
|
115
|
+
import { HomePage } from "@/components/HomePage";
|
|
116
|
+
|
|
117
|
+
export default async function Page() {
|
|
118
|
+
const content = await getRisaliContent("/");
|
|
119
|
+
return <HomePage content={content} />;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// components/HomePage.tsx — client component
|
|
123
|
+
"use client";
|
|
124
|
+
import { getBlockValue, getBlockImage, getBlockRichText } from "@risali/react";
|
|
125
|
+
import type { RisaliContent } from "@risali/react";
|
|
126
|
+
|
|
127
|
+
export function HomePage({ content }: { content: RisaliContent | null }) {
|
|
128
|
+
const heroTitle = getBlockValue(content, "hero_title", "Vitajte");
|
|
129
|
+
const heroPhoto = getBlockImage(content, "hero_photo", { src: "/h.jpg", alt: "Hero" });
|
|
130
|
+
const aboutHtml = getBlockRichText(content, "about_body", "<p>O nás</p>");
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<>
|
|
134
|
+
<h1 data-risali-key="hero_title">{heroTitle}</h1>
|
|
135
|
+
<img data-risali-key="hero_photo" src={heroPhoto.src} alt={heroPhoto.alt} />
|
|
136
|
+
<div data-risali-key="about_body" dangerouslySetInnerHTML={{ __html: aboutHtml }} />
|
|
137
|
+
</>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Helpers always validate the block type (a block typed `image` will return `defaultValue` from `getBlockValue`) and `getBlockRichText` always sanitises — including the fallback HTML — so a stored XSS payload can't reach the browser even if the block is missing.
|
|
143
|
+
|
|
144
|
+
## Editor mode
|
|
145
|
+
|
|
146
|
+
Every rendered block carries a `data-risali-key="<pageKey>"` attribute. The Risali editor iframe (`/risali.js?site=<slug>&risali_edit=1`) uses that marker to wire up click-to-edit — no CSS selector generation, no content-hash drift, no fragile DOM scanning.
|
|
147
|
+
|
|
148
|
+
## What this package does NOT do
|
|
149
|
+
|
|
150
|
+
- **No client-side DOM patching.** Content lives in the server-rendered HTML; the visitor browser never re-renders Risali content.
|
|
151
|
+
- **No analytics or form capture.** Those still ship via `<script async src="https://app.risali.app/risali.js?site=…"></script>` (the Risali snippet handles pageview events, form beacons, the cookie banner, and the editor iframe).
|
|
152
|
+
- **No widgets (booking, pricelist, contact form) — yet.** Coming in a follow-up package release.
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
Closed-source. Used by Risali.app clients under their SaaS subscription.
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAYrD;AAED,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAQjD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const DEFAULT_API_BASE = "https://app.risali.app";
|
|
2
|
+
export function resolveSlug(explicit) {
|
|
3
|
+
if (explicit && explicit.trim())
|
|
4
|
+
return explicit.trim();
|
|
5
|
+
const fromEnv = process.env.RISALI_SITE_SLUG ||
|
|
6
|
+
process.env.NEXT_PUBLIC_RISALI_SITE_SLUG ||
|
|
7
|
+
"";
|
|
8
|
+
if (!fromEnv) {
|
|
9
|
+
throw new Error("@risali/react: missing site slug — set RISALI_SITE_SLUG in your environment or pass `siteSlug` prop.");
|
|
10
|
+
}
|
|
11
|
+
return fromEnv.trim();
|
|
12
|
+
}
|
|
13
|
+
export function resolveApiBase() {
|
|
14
|
+
const base = process.env.RISALI_API_BASE ||
|
|
15
|
+
process.env.NEXT_PUBLIC_RISALI_API_BASE ||
|
|
16
|
+
DEFAULT_API_BASE;
|
|
17
|
+
return base.replace(/\/+$/, "");
|
|
18
|
+
}
|
|
19
|
+
export function resolveRevalidateSeconds() {
|
|
20
|
+
const raw = process.env.RISALI_REVALIDATE_SECONDS ||
|
|
21
|
+
process.env.NEXT_PUBLIC_RISALI_REVALIDATE_SECONDS;
|
|
22
|
+
if (!raw)
|
|
23
|
+
return 60;
|
|
24
|
+
const n = Number.parseInt(raw, 10);
|
|
25
|
+
if (!Number.isFinite(n) || n < 0)
|
|
26
|
+
return 60;
|
|
27
|
+
return Math.min(n, 3600);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AAElD,MAAM,UAAU,WAAW,CAAC,QAAiB;IAC3C,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE;QAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,OAAO,GACX,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAC5B,OAAO,CAAC,GAAG,CAAC,4BAA4B;QACxC,EAAE,CAAC;IACL,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,sGAAsG,CACvG,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,IAAI,GACR,OAAO,CAAC,GAAG,CAAC,eAAe;QAC3B,OAAO,CAAC,GAAG,CAAC,2BAA2B;QACvC,gBAAgB,CAAC;IACnB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,MAAM,GAAG,GACP,OAAO,CAAC,GAAG,CAAC,yBAAyB;QACrC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC;IACpD,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RisaliBlock, RisaliContent, RisaliStyleOverrides } from "./types.js";
|
|
2
|
+
export type GetRisaliContentOptions = {
|
|
3
|
+
siteSlug?: string;
|
|
4
|
+
apiBase?: string;
|
|
5
|
+
revalidate?: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function getRisaliContent(path: string, options?: GetRisaliContentOptions): Promise<RisaliContent | null>;
|
|
8
|
+
export declare function findBlock(content: RisaliContent | null, pageKey: string): RisaliBlock | null;
|
|
9
|
+
export declare function getBlockValue(content: RisaliContent | null, pageKey: string, defaultValue: string): string;
|
|
10
|
+
export declare function getBlockImage(content: RisaliContent | null, pageKey: string, defaults: {
|
|
11
|
+
src: string;
|
|
12
|
+
alt?: string;
|
|
13
|
+
}): {
|
|
14
|
+
src: string;
|
|
15
|
+
alt: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function getBlockRichText(content: RisaliContent | null, pageKey: string, defaultHtml: string): string;
|
|
18
|
+
export declare function getBlockStyleOverrides(content: RisaliContent | null, pageKey: string): RisaliStyleOverrides | null;
|
|
19
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EAEb,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAsB/B;AAED,wBAAgB,SAAS,CACvB,OAAO,EAAE,aAAa,GAAG,IAAI,EAC7B,OAAO,EAAE,MAAM,GACd,WAAW,GAAG,IAAI,CAMpB;AAOD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,aAAa,GAAG,IAAI,EAC7B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,MAAM,CASR;AAID,wBAAgB,aAAa,CAC3B,OAAO,EAAE,aAAa,GAAG,IAAI,EAC7B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAe9B;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,GAAG,IAAI,EAC7B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,MAAM,CASR;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,aAAa,GAAG,IAAI,EAC7B,OAAO,EAAE,MAAM,GACd,oBAAoB,GAAG,IAAI,CAG7B"}
|
package/dist/content.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { resolveApiBase, resolveRevalidateSeconds, resolveSlug } from "./config.js";
|
|
2
|
+
import { sanitiseRichText } from "./sanitize.js";
|
|
3
|
+
export async function getRisaliContent(path, options = {}) {
|
|
4
|
+
const slug = resolveSlug(options.siteSlug);
|
|
5
|
+
const apiBase = options.apiBase
|
|
6
|
+
? options.apiBase.replace(/\/+$/, "")
|
|
7
|
+
: resolveApiBase();
|
|
8
|
+
const revalidate = typeof options.revalidate === "number"
|
|
9
|
+
? Math.max(0, Math.min(3600, options.revalidate))
|
|
10
|
+
: resolveRevalidateSeconds();
|
|
11
|
+
const url = new URL(`/api/public/sites/${encodeURIComponent(slug)}/content`, apiBase);
|
|
12
|
+
if (path)
|
|
13
|
+
url.searchParams.set("path", path);
|
|
14
|
+
try {
|
|
15
|
+
const res = await fetch(url.toString(), {
|
|
16
|
+
next: { revalidate, tags: [`risali:${slug}`, `risali:${slug}:${path || "*"}`] },
|
|
17
|
+
});
|
|
18
|
+
if (!res.ok)
|
|
19
|
+
return null;
|
|
20
|
+
return (await res.json());
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function findBlock(content, pageKey) {
|
|
27
|
+
if (!content)
|
|
28
|
+
return null;
|
|
29
|
+
for (const b of content.blocks) {
|
|
30
|
+
if (b.key === pageKey)
|
|
31
|
+
return b;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
// Pure helpers — usable from client components that received `content`
|
|
36
|
+
// via prop (the server page does `await getRisaliContent(...)` and threads
|
|
37
|
+
// it down). They mirror what <RisaliText> / <RisaliImage> / <RisaliRichText>
|
|
38
|
+
// pull out of a block, without requiring an async boundary.
|
|
39
|
+
export function getBlockValue(content, pageKey, defaultValue) {
|
|
40
|
+
const block = findBlock(content, pageKey);
|
|
41
|
+
if (!block)
|
|
42
|
+
return defaultValue;
|
|
43
|
+
const isTextLike = block.type === "text" ||
|
|
44
|
+
block.type === "rich_text" ||
|
|
45
|
+
block.type === "html";
|
|
46
|
+
if (!isTextLike)
|
|
47
|
+
return defaultValue;
|
|
48
|
+
return typeof block.value === "string" ? block.value : defaultValue;
|
|
49
|
+
}
|
|
50
|
+
const SAFE_SRC_RE = /^(https?:\/\/|\/)/;
|
|
51
|
+
export function getBlockImage(content, pageKey, defaults) {
|
|
52
|
+
const block = findBlock(content, pageKey);
|
|
53
|
+
const empty = block?.type === "image" && block.value && typeof block.value === "object"
|
|
54
|
+
? block.value
|
|
55
|
+
: {};
|
|
56
|
+
const src = typeof empty.src === "string" && empty.src && SAFE_SRC_RE.test(empty.src)
|
|
57
|
+
? empty.src
|
|
58
|
+
: defaults.src;
|
|
59
|
+
const alt = typeof empty.alt === "string" && empty.alt
|
|
60
|
+
? empty.alt
|
|
61
|
+
: (defaults.alt ?? "");
|
|
62
|
+
return { src, alt };
|
|
63
|
+
}
|
|
64
|
+
export function getBlockRichText(content, pageKey, defaultHtml) {
|
|
65
|
+
const block = findBlock(content, pageKey);
|
|
66
|
+
const raw = block &&
|
|
67
|
+
(block.type === "rich_text" || block.type === "html") &&
|
|
68
|
+
typeof block.value === "string"
|
|
69
|
+
? block.value
|
|
70
|
+
: defaultHtml;
|
|
71
|
+
return sanitiseRichText(raw);
|
|
72
|
+
}
|
|
73
|
+
export function getBlockStyleOverrides(content, pageKey) {
|
|
74
|
+
const block = findBlock(content, pageKey);
|
|
75
|
+
return block?.style_overrides ?? null;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"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"}
|
package/dist/image.d.ts
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import type { CSSProperties, ImgHTMLAttributes } from "react";
|
|
2
|
+
import type { RisaliContent } from "./types.js";
|
|
3
|
+
export type RisaliImageProps = Omit<ImgHTMLAttributes<HTMLImageElement>, "src" | "alt"> & {
|
|
4
|
+
pageKey: string;
|
|
5
|
+
defaultSrc: string;
|
|
6
|
+
defaultAlt?: string;
|
|
7
|
+
path?: string;
|
|
8
|
+
content?: RisaliContent | null;
|
|
9
|
+
siteSlug?: string;
|
|
10
|
+
style?: CSSProperties;
|
|
11
|
+
};
|
|
12
|
+
export declare function RisaliImage(props: RisaliImageProps): Promise<import("react").DetailedReactHTMLElement<{
|
|
13
|
+
src: string;
|
|
14
|
+
alt: string;
|
|
15
|
+
"data-risali-key": string;
|
|
16
|
+
style?: CSSProperties;
|
|
17
|
+
crossOrigin?: "" | "anonymous" | "use-credentials" | undefined;
|
|
18
|
+
decoding?: "async" | "auto" | "sync" | undefined | undefined;
|
|
19
|
+
fetchPriority?: "high" | "low" | "auto" | undefined | undefined;
|
|
20
|
+
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
|
+
width?: number | string | undefined | undefined;
|
|
27
|
+
defaultChecked?: boolean | undefined | undefined;
|
|
28
|
+
defaultValue?: string | number | readonly string[] | undefined;
|
|
29
|
+
suppressContentEditableWarning?: boolean | undefined | undefined;
|
|
30
|
+
suppressHydrationWarning?: boolean | undefined | undefined;
|
|
31
|
+
accessKey?: string | undefined | undefined;
|
|
32
|
+
autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters" | undefined | (string & {}) | undefined;
|
|
33
|
+
autoFocus?: boolean | undefined | undefined;
|
|
34
|
+
className?: string | undefined | undefined;
|
|
35
|
+
contentEditable?: (boolean | "true" | "false") | "inherit" | "plaintext-only" | undefined;
|
|
36
|
+
contextMenu?: string | undefined | undefined;
|
|
37
|
+
dir?: string | undefined | undefined;
|
|
38
|
+
draggable?: (boolean | "true" | "false") | undefined;
|
|
39
|
+
enterKeyHint?: "enter" | "done" | "go" | "next" | "previous" | "search" | "send" | undefined | undefined;
|
|
40
|
+
hidden?: boolean | undefined | undefined;
|
|
41
|
+
id?: string | undefined | undefined;
|
|
42
|
+
lang?: string | undefined | undefined;
|
|
43
|
+
nonce?: string | undefined | undefined;
|
|
44
|
+
slot?: string | undefined | undefined;
|
|
45
|
+
spellCheck?: (boolean | "true" | "false") | undefined;
|
|
46
|
+
tabIndex?: number | undefined | undefined;
|
|
47
|
+
title?: string | undefined | undefined;
|
|
48
|
+
translate?: "yes" | "no" | undefined | undefined;
|
|
49
|
+
radioGroup?: string | undefined | undefined;
|
|
50
|
+
role?: import("react").AriaRole | undefined;
|
|
51
|
+
about?: string | undefined | undefined;
|
|
52
|
+
datatype?: string | undefined | undefined;
|
|
53
|
+
inlist?: any;
|
|
54
|
+
prefix?: string | undefined | undefined;
|
|
55
|
+
property?: string | undefined | undefined;
|
|
56
|
+
rel?: string | undefined | undefined;
|
|
57
|
+
resource?: string | undefined | undefined;
|
|
58
|
+
rev?: string | undefined | undefined;
|
|
59
|
+
typeof?: string | undefined | undefined;
|
|
60
|
+
vocab?: string | undefined | undefined;
|
|
61
|
+
autoCorrect?: string | undefined | undefined;
|
|
62
|
+
autoSave?: string | undefined | undefined;
|
|
63
|
+
color?: string | undefined | undefined;
|
|
64
|
+
itemProp?: string | undefined | undefined;
|
|
65
|
+
itemScope?: boolean | undefined | undefined;
|
|
66
|
+
itemType?: string | undefined | undefined;
|
|
67
|
+
itemID?: string | undefined | undefined;
|
|
68
|
+
itemRef?: string | undefined | undefined;
|
|
69
|
+
results?: number | undefined | undefined;
|
|
70
|
+
security?: string | undefined | undefined;
|
|
71
|
+
unselectable?: "on" | "off" | undefined | undefined;
|
|
72
|
+
popover?: "" | "auto" | "manual" | "hint" | undefined | undefined;
|
|
73
|
+
popoverTargetAction?: "toggle" | "show" | "hide" | undefined | undefined;
|
|
74
|
+
popoverTarget?: string | undefined | undefined;
|
|
75
|
+
inert?: boolean | undefined | undefined;
|
|
76
|
+
inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined | undefined;
|
|
77
|
+
is?: string | undefined | undefined;
|
|
78
|
+
exportparts?: string | undefined | undefined;
|
|
79
|
+
part?: string | undefined | undefined;
|
|
80
|
+
"aria-activedescendant"?: string | undefined | undefined;
|
|
81
|
+
"aria-atomic"?: (boolean | "true" | "false") | undefined;
|
|
82
|
+
"aria-autocomplete"?: "none" | "inline" | "list" | "both" | undefined | undefined;
|
|
83
|
+
"aria-braillelabel"?: string | undefined | undefined;
|
|
84
|
+
"aria-brailleroledescription"?: string | undefined | undefined;
|
|
85
|
+
"aria-busy"?: (boolean | "true" | "false") | undefined;
|
|
86
|
+
"aria-checked"?: boolean | "false" | "mixed" | "true" | undefined | undefined;
|
|
87
|
+
"aria-colcount"?: number | undefined | undefined;
|
|
88
|
+
"aria-colindex"?: number | undefined | undefined;
|
|
89
|
+
"aria-colindextext"?: string | undefined | undefined;
|
|
90
|
+
"aria-colspan"?: number | undefined | undefined;
|
|
91
|
+
"aria-controls"?: string | undefined | undefined;
|
|
92
|
+
"aria-current"?: boolean | "false" | "true" | "page" | "step" | "location" | "date" | "time" | undefined | undefined;
|
|
93
|
+
"aria-describedby"?: string | undefined | undefined;
|
|
94
|
+
"aria-description"?: string | undefined | undefined;
|
|
95
|
+
"aria-details"?: string | undefined | undefined;
|
|
96
|
+
"aria-disabled"?: (boolean | "true" | "false") | undefined;
|
|
97
|
+
"aria-dropeffect"?: "none" | "copy" | "execute" | "link" | "move" | "popup" | undefined | undefined;
|
|
98
|
+
"aria-errormessage"?: string | undefined | undefined;
|
|
99
|
+
"aria-expanded"?: (boolean | "true" | "false") | undefined;
|
|
100
|
+
"aria-flowto"?: string | undefined | undefined;
|
|
101
|
+
"aria-grabbed"?: (boolean | "true" | "false") | undefined;
|
|
102
|
+
"aria-haspopup"?: boolean | "false" | "true" | "menu" | "listbox" | "tree" | "grid" | "dialog" | undefined | undefined;
|
|
103
|
+
"aria-hidden"?: (boolean | "true" | "false") | undefined;
|
|
104
|
+
"aria-invalid"?: boolean | "false" | "true" | "grammar" | "spelling" | undefined | undefined;
|
|
105
|
+
"aria-keyshortcuts"?: string | undefined | undefined;
|
|
106
|
+
"aria-label"?: string | undefined | undefined;
|
|
107
|
+
"aria-labelledby"?: string | undefined | undefined;
|
|
108
|
+
"aria-level"?: number | undefined | undefined;
|
|
109
|
+
"aria-live"?: "off" | "assertive" | "polite" | undefined | undefined;
|
|
110
|
+
"aria-modal"?: (boolean | "true" | "false") | undefined;
|
|
111
|
+
"aria-multiline"?: (boolean | "true" | "false") | undefined;
|
|
112
|
+
"aria-multiselectable"?: (boolean | "true" | "false") | undefined;
|
|
113
|
+
"aria-orientation"?: "horizontal" | "vertical" | undefined | undefined;
|
|
114
|
+
"aria-owns"?: string | undefined | undefined;
|
|
115
|
+
"aria-placeholder"?: string | undefined | undefined;
|
|
116
|
+
"aria-posinset"?: number | undefined | undefined;
|
|
117
|
+
"aria-pressed"?: boolean | "false" | "mixed" | "true" | undefined | undefined;
|
|
118
|
+
"aria-readonly"?: (boolean | "true" | "false") | undefined;
|
|
119
|
+
"aria-relevant"?: "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text" | "text additions" | "text removals" | undefined | undefined;
|
|
120
|
+
"aria-required"?: (boolean | "true" | "false") | undefined;
|
|
121
|
+
"aria-roledescription"?: string | undefined | undefined;
|
|
122
|
+
"aria-rowcount"?: number | undefined | undefined;
|
|
123
|
+
"aria-rowindex"?: number | undefined | undefined;
|
|
124
|
+
"aria-rowindextext"?: string | undefined | undefined;
|
|
125
|
+
"aria-rowspan"?: number | undefined | undefined;
|
|
126
|
+
"aria-selected"?: (boolean | "true" | "false") | undefined;
|
|
127
|
+
"aria-setsize"?: number | undefined | undefined;
|
|
128
|
+
"aria-sort"?: "none" | "ascending" | "descending" | "other" | undefined | undefined;
|
|
129
|
+
"aria-valuemax"?: number | undefined | undefined;
|
|
130
|
+
"aria-valuemin"?: number | undefined | undefined;
|
|
131
|
+
"aria-valuenow"?: number | undefined | undefined;
|
|
132
|
+
"aria-valuetext"?: string | undefined | undefined;
|
|
133
|
+
children?: import("react").ReactNode;
|
|
134
|
+
dangerouslySetInnerHTML?: {
|
|
135
|
+
__html: string | TrustedHTML;
|
|
136
|
+
} | undefined | undefined;
|
|
137
|
+
onCopy?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
|
|
138
|
+
onCopyCapture?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
|
|
139
|
+
onCut?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
|
|
140
|
+
onCutCapture?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
|
|
141
|
+
onPaste?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
|
|
142
|
+
onPasteCapture?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
|
|
143
|
+
onCompositionEnd?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
|
|
144
|
+
onCompositionEndCapture?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
|
|
145
|
+
onCompositionStart?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
|
|
146
|
+
onCompositionStartCapture?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
|
|
147
|
+
onCompositionUpdate?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
|
|
148
|
+
onCompositionUpdateCapture?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
|
|
149
|
+
onFocus?: import("react").FocusEventHandler<HTMLImageElement> | undefined;
|
|
150
|
+
onFocusCapture?: import("react").FocusEventHandler<HTMLImageElement> | undefined;
|
|
151
|
+
onBlur?: import("react").FocusEventHandler<HTMLImageElement> | undefined;
|
|
152
|
+
onBlurCapture?: import("react").FocusEventHandler<HTMLImageElement> | undefined;
|
|
153
|
+
onChange?: import("react").ChangeEventHandler<HTMLImageElement, Element> | undefined;
|
|
154
|
+
onChangeCapture?: import("react").ChangeEventHandler<HTMLImageElement, Element> | undefined;
|
|
155
|
+
onBeforeInput?: import("react").InputEventHandler<HTMLImageElement> | undefined;
|
|
156
|
+
onBeforeInputCapture?: import("react").InputEventHandler<HTMLImageElement> | undefined;
|
|
157
|
+
onInput?: import("react").InputEventHandler<HTMLImageElement> | undefined;
|
|
158
|
+
onInputCapture?: import("react").InputEventHandler<HTMLImageElement> | undefined;
|
|
159
|
+
onReset?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
160
|
+
onResetCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
161
|
+
onSubmit?: import("react").SubmitEventHandler<HTMLImageElement> | undefined;
|
|
162
|
+
onSubmitCapture?: import("react").SubmitEventHandler<HTMLImageElement> | undefined;
|
|
163
|
+
onInvalid?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
164
|
+
onInvalidCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
165
|
+
onLoad?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
166
|
+
onLoadCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
167
|
+
onError?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
168
|
+
onErrorCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
169
|
+
onKeyDown?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
|
|
170
|
+
onKeyDownCapture?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
|
|
171
|
+
onKeyPress?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
|
|
172
|
+
onKeyPressCapture?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
|
|
173
|
+
onKeyUp?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
|
|
174
|
+
onKeyUpCapture?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
|
|
175
|
+
onAbort?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
176
|
+
onAbortCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
177
|
+
onCanPlay?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
178
|
+
onCanPlayCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
179
|
+
onCanPlayThrough?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
180
|
+
onCanPlayThroughCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
181
|
+
onDurationChange?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
182
|
+
onDurationChangeCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
183
|
+
onEmptied?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
184
|
+
onEmptiedCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
185
|
+
onEncrypted?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
186
|
+
onEncryptedCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
187
|
+
onEnded?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
188
|
+
onEndedCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
189
|
+
onLoadedData?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
190
|
+
onLoadedDataCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
191
|
+
onLoadedMetadata?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
192
|
+
onLoadedMetadataCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
193
|
+
onLoadStart?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
194
|
+
onLoadStartCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
195
|
+
onPause?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
196
|
+
onPauseCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
197
|
+
onPlay?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
198
|
+
onPlayCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
199
|
+
onPlaying?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
200
|
+
onPlayingCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
201
|
+
onProgress?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
202
|
+
onProgressCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
203
|
+
onRateChange?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
204
|
+
onRateChangeCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
205
|
+
onSeeked?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
206
|
+
onSeekedCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
207
|
+
onSeeking?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
208
|
+
onSeekingCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
209
|
+
onStalled?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
210
|
+
onStalledCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
211
|
+
onSuspend?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
212
|
+
onSuspendCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
213
|
+
onTimeUpdate?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
214
|
+
onTimeUpdateCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
215
|
+
onVolumeChange?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
216
|
+
onVolumeChangeCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
217
|
+
onWaiting?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
218
|
+
onWaitingCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
219
|
+
onAuxClick?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
220
|
+
onAuxClickCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
221
|
+
onClick?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
222
|
+
onClickCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
223
|
+
onContextMenu?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
224
|
+
onContextMenuCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
225
|
+
onDoubleClick?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
226
|
+
onDoubleClickCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
227
|
+
onDrag?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
228
|
+
onDragCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
229
|
+
onDragEnd?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
230
|
+
onDragEndCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
231
|
+
onDragEnter?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
232
|
+
onDragEnterCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
233
|
+
onDragExit?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
234
|
+
onDragExitCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
235
|
+
onDragLeave?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
236
|
+
onDragLeaveCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
237
|
+
onDragOver?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
238
|
+
onDragOverCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
239
|
+
onDragStart?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
240
|
+
onDragStartCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
241
|
+
onDrop?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
242
|
+
onDropCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
|
|
243
|
+
onMouseDown?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
244
|
+
onMouseDownCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
245
|
+
onMouseEnter?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
246
|
+
onMouseLeave?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
247
|
+
onMouseMove?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
248
|
+
onMouseMoveCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
249
|
+
onMouseOut?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
250
|
+
onMouseOutCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
251
|
+
onMouseOver?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
252
|
+
onMouseOverCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
253
|
+
onMouseUp?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
254
|
+
onMouseUpCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
|
|
255
|
+
onSelect?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
256
|
+
onSelectCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
|
|
257
|
+
onTouchCancel?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
|
|
258
|
+
onTouchCancelCapture?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
|
|
259
|
+
onTouchEnd?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
|
|
260
|
+
onTouchEndCapture?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
|
|
261
|
+
onTouchMove?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
|
|
262
|
+
onTouchMoveCapture?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
|
|
263
|
+
onTouchStart?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
|
|
264
|
+
onTouchStartCapture?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
|
|
265
|
+
onPointerDown?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
266
|
+
onPointerDownCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
267
|
+
onPointerMove?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
268
|
+
onPointerMoveCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
269
|
+
onPointerUp?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
270
|
+
onPointerUpCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
271
|
+
onPointerCancel?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
272
|
+
onPointerCancelCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
273
|
+
onPointerEnter?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
274
|
+
onPointerLeave?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
275
|
+
onPointerOver?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
276
|
+
onPointerOverCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
277
|
+
onPointerOut?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
278
|
+
onPointerOutCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
279
|
+
onGotPointerCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
280
|
+
onGotPointerCaptureCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
281
|
+
onLostPointerCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
282
|
+
onLostPointerCaptureCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
|
|
283
|
+
onScroll?: import("react").UIEventHandler<HTMLImageElement> | undefined;
|
|
284
|
+
onScrollCapture?: import("react").UIEventHandler<HTMLImageElement> | undefined;
|
|
285
|
+
onScrollEnd?: import("react").UIEventHandler<HTMLImageElement> | undefined;
|
|
286
|
+
onScrollEndCapture?: import("react").UIEventHandler<HTMLImageElement> | undefined;
|
|
287
|
+
onWheel?: import("react").WheelEventHandler<HTMLImageElement> | undefined;
|
|
288
|
+
onWheelCapture?: import("react").WheelEventHandler<HTMLImageElement> | undefined;
|
|
289
|
+
onAnimationStart?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
|
|
290
|
+
onAnimationStartCapture?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
|
|
291
|
+
onAnimationEnd?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
|
|
292
|
+
onAnimationEndCapture?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
|
|
293
|
+
onAnimationIteration?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
|
|
294
|
+
onAnimationIterationCapture?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
|
|
295
|
+
onToggle?: import("react").ToggleEventHandler<HTMLImageElement> | undefined;
|
|
296
|
+
onBeforeToggle?: import("react").ToggleEventHandler<HTMLImageElement> | undefined;
|
|
297
|
+
onTransitionCancel?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
298
|
+
onTransitionCancelCapture?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
299
|
+
onTransitionEnd?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
300
|
+
onTransitionEndCapture?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
301
|
+
onTransitionRun?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
302
|
+
onTransitionRunCapture?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
303
|
+
onTransitionStart?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
304
|
+
onTransitionStartCapture?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
|
|
305
|
+
}, HTMLElement>>;
|
|
306
|
+
//# sourceMappingURL=image.d.ts.map
|
|
@@ -0,0 +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;;;;YAR/C,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0CtB"}
|
package/dist/image.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createElement } from "react";
|
|
2
|
+
import { findBlock, getRisaliContent } from "./content.js";
|
|
3
|
+
const SAFE_SRC_RE = /^(https?:\/\/|\/)/;
|
|
4
|
+
function safeSrc(value, fallback) {
|
|
5
|
+
if (typeof value !== "string" || !value)
|
|
6
|
+
return fallback;
|
|
7
|
+
return SAFE_SRC_RE.test(value) ? value : fallback;
|
|
8
|
+
}
|
|
9
|
+
export async function RisaliImage(props) {
|
|
10
|
+
const { pageKey, defaultSrc, defaultAlt, path, content: providedContent, siteSlug, ...rest } = props;
|
|
11
|
+
const content = providedContent !== undefined
|
|
12
|
+
? providedContent
|
|
13
|
+
: await getRisaliContent(path ?? "/", { siteSlug });
|
|
14
|
+
const block = findBlock(content, pageKey);
|
|
15
|
+
const value = block?.type === "image" && block.value && typeof block.value === "object"
|
|
16
|
+
? block.value
|
|
17
|
+
: {};
|
|
18
|
+
const src = safeSrc(value.src, defaultSrc);
|
|
19
|
+
const alt = typeof value.alt === "string" && value.alt
|
|
20
|
+
? value.alt
|
|
21
|
+
: (defaultAlt ?? "");
|
|
22
|
+
return createElement("img", {
|
|
23
|
+
...rest,
|
|
24
|
+
src,
|
|
25
|
+
alt,
|
|
26
|
+
"data-risali-key": pageKey,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAG3D,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAexC,SAAS,OAAO,CAAC,KAAc,EAAE,QAAgB;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IACzD,OAAO,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAuB;IACvD,MAAM,EACJ,OAAO,EACP,UAAU,EACV,UAAU,EACV,IAAI,EACJ,OAAO,EAAE,eAAe,EACxB,QAAQ,EACR,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IAEV,MAAM,OAAO,GACX,eAAe,KAAK,SAAS;QAC3B,CAAC,CAAC,eAAe;QACjB,CAAC,CAAC,MAAM,gBAAgB,CAAC,IAAI,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAExD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,KAAK,GACT,KAAK,EAAE,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;QACvE,CAAC,CAAE,KAAK,CAAC,KAA0B;QACnC,CAAC,CAAC,EAAE,CAAC;IAET,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC3C,MAAM,GAAG,GACP,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG;QACxC,CAAC,CAAC,KAAK,CAAC,GAAG;QACX,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;IAEzB,OAAO,aAAa,CAAC,KAAK,EAAE;QAC1B,GAAG,IAAI;QACP,GAAG;QACH,GAAG;QACH,iBAAiB,EAAE,OAAO;KAC3B,CAAC,CAAC;AACL,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { getRisaliContent, findBlock, getBlockValue, getBlockImage, getBlockRichText, getBlockStyleOverrides, } from "./content.js";
|
|
2
|
+
export type { GetRisaliContentOptions } from "./content.js";
|
|
3
|
+
export { applyStyleOverrides } from "./style.js";
|
|
4
|
+
export { RisaliText } from "./text.js";
|
|
5
|
+
export type { RisaliTextProps } from "./text.js";
|
|
6
|
+
export { RisaliImage } from "./image.js";
|
|
7
|
+
export type { RisaliImageProps } from "./image.js";
|
|
8
|
+
export { RisaliRichText } from "./rich-text.js";
|
|
9
|
+
export type { RisaliRichTextProps } from "./rich-text.js";
|
|
10
|
+
export { sanitiseRichText } from "./sanitize.js";
|
|
11
|
+
export type { RisaliBlock, RisaliBlockType, RisaliContent, RisaliImageValue, RisaliStyleOverrides, } from "./types.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { getRisaliContent, findBlock, getBlockValue, getBlockImage, getBlockRichText, getBlockStyleOverrides, } from "./content.js";
|
|
2
|
+
export { applyStyleOverrides } from "./style.js";
|
|
3
|
+
export { RisaliText } from "./text.js";
|
|
4
|
+
export { RisaliImage } from "./image.js";
|
|
5
|
+
export { RisaliRichText } from "./rich-text.js";
|
|
6
|
+
export { sanitiseRichText } from "./sanitize.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CSSProperties, ElementType } from "react";
|
|
2
|
+
import type { RisaliContent } from "./types.js";
|
|
3
|
+
export type RisaliRichTextProps = {
|
|
4
|
+
pageKey: string;
|
|
5
|
+
defaultValue: string;
|
|
6
|
+
path?: string;
|
|
7
|
+
content?: RisaliContent | null;
|
|
8
|
+
as?: ElementType;
|
|
9
|
+
className?: string;
|
|
10
|
+
style?: CSSProperties;
|
|
11
|
+
siteSlug?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function RisaliRichText(props: RisaliRichTextProps): Promise<import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>>;
|
|
14
|
+
//# sourceMappingURL=rich-text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rich-text.d.ts","sourceRoot":"","sources":["../src/rich-text.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAKxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAsB,cAAc,CAAC,KAAK,EAAE,mBAAmB,mGAmC9D"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createElement } from "react";
|
|
2
|
+
import { findBlock, getRisaliContent } from "./content.js";
|
|
3
|
+
import { sanitiseRichText } from "./sanitize.js";
|
|
4
|
+
import { applyStyleOverrides } from "./style.js";
|
|
5
|
+
export async function RisaliRichText(props) {
|
|
6
|
+
const { pageKey, defaultValue, path, content: providedContent, as, className, style, siteSlug, } = props;
|
|
7
|
+
const Tag = as || "div";
|
|
8
|
+
const content = providedContent !== undefined
|
|
9
|
+
? providedContent
|
|
10
|
+
: await getRisaliContent(path ?? "/", { siteSlug });
|
|
11
|
+
const block = findBlock(content, pageKey);
|
|
12
|
+
const rawValue = block &&
|
|
13
|
+
(block.type === "rich_text" || block.type === "html") &&
|
|
14
|
+
typeof block.value === "string"
|
|
15
|
+
? block.value
|
|
16
|
+
: defaultValue;
|
|
17
|
+
const safeHtml = sanitiseRichText(rawValue);
|
|
18
|
+
const mergedStyle = applyStyleOverrides(style, block?.style_overrides);
|
|
19
|
+
return createElement(Tag, {
|
|
20
|
+
className,
|
|
21
|
+
style: mergedStyle,
|
|
22
|
+
"data-risali-key": pageKey,
|
|
23
|
+
dangerouslySetInnerHTML: { __html: safeHtml },
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=rich-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rich-text.js","sourceRoot":"","sources":["../src/rich-text.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAcjD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAA0B;IAC7D,MAAM,EACJ,OAAO,EACP,YAAY,EACZ,IAAI,EACJ,OAAO,EAAE,eAAe,EACxB,EAAE,EACF,SAAS,EACT,KAAK,EACL,QAAQ,GACT,GAAG,KAAK,CAAC;IAEV,MAAM,GAAG,GAAgB,EAAE,IAAI,KAAK,CAAC;IACrC,MAAM,OAAO,GACX,eAAe,KAAK,SAAS;QAC3B,CAAC,CAAC,eAAe;QACjB,CAAC,CAAC,MAAM,gBAAgB,CAAC,IAAI,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAExD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,QAAQ,GACZ,KAAK;QACL,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;QACrD,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;QAC7B,CAAC,CAAC,KAAK,CAAC,KAAK;QACb,CAAC,CAAC,YAAY,CAAC;IAEnB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,mBAAmB,CAAC,KAAK,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;IAEvE,OAAO,aAAa,CAAC,GAAG,EAAE;QACxB,SAAS;QACT,KAAK,EAAE,WAAW;QAClB,iBAAiB,EAAE,OAAO;QAC1B,uBAAuB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;KAC9C,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAqFA,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA+CtD"}
|
package/dist/sanitize.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Minimal HTML sanitiser for Risali rich-text blocks.
|
|
2
|
+
// Pure (no DOM, no external deps) so it runs in RSC / Node / tests alike.
|
|
3
|
+
// Defense-in-depth over the editor-side sanitiser planned for PR 26.
|
|
4
|
+
const ALLOWED_TAGS = new Set([
|
|
5
|
+
"span",
|
|
6
|
+
"strong",
|
|
7
|
+
"b",
|
|
8
|
+
"em",
|
|
9
|
+
"i",
|
|
10
|
+
"u",
|
|
11
|
+
"br",
|
|
12
|
+
"a",
|
|
13
|
+
"p",
|
|
14
|
+
]);
|
|
15
|
+
const VOID_TAGS = new Set(["br"]);
|
|
16
|
+
const ALLOWED_ATTRS = {
|
|
17
|
+
a: new Set(["href"]),
|
|
18
|
+
span: new Set(["style"]),
|
|
19
|
+
p: new Set(["style"]),
|
|
20
|
+
strong: new Set(["style"]),
|
|
21
|
+
em: new Set(["style"]),
|
|
22
|
+
b: new Set(["style"]),
|
|
23
|
+
i: new Set(["style"]),
|
|
24
|
+
u: new Set(["style"]),
|
|
25
|
+
};
|
|
26
|
+
const SAFE_HREF_RE = /^(https?:\/\/|mailto:|tel:|\/)/i;
|
|
27
|
+
const STYLE_COLOR_RE = /(?:^|;)\s*color\s*:\s*(#[0-9a-fA-F]{6})\s*(?:;|$)/;
|
|
28
|
+
const STYLE_FONT_SIZE_RE = /(?:^|;)\s*font-size\s*:\s*([0-9]+(?:\.[0-9]+)?)(px|rem|em)\s*(?:;|$)/i;
|
|
29
|
+
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;
|
|
31
|
+
function sanitiseStyle(raw) {
|
|
32
|
+
const out = [];
|
|
33
|
+
const colorMatch = raw.match(STYLE_COLOR_RE);
|
|
34
|
+
if (colorMatch && colorMatch[1]) {
|
|
35
|
+
out.push(`color:${colorMatch[1]}`);
|
|
36
|
+
}
|
|
37
|
+
const fontMatch = raw.match(STYLE_FONT_SIZE_RE);
|
|
38
|
+
if (fontMatch && fontMatch[1] && fontMatch[2]) {
|
|
39
|
+
const num = Number.parseFloat(fontMatch[1]);
|
|
40
|
+
const unit = fontMatch[2].toLowerCase();
|
|
41
|
+
if (Number.isFinite(num) && num > 0 && num < 200) {
|
|
42
|
+
out.push(`font-size:${num}${unit}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return out.join(";");
|
|
46
|
+
}
|
|
47
|
+
function sanitiseAttrs(tag, raw) {
|
|
48
|
+
const allowed = ALLOWED_ATTRS[tag];
|
|
49
|
+
if (!allowed || !raw.trim())
|
|
50
|
+
return "";
|
|
51
|
+
const parts = [];
|
|
52
|
+
ATTR_RE.lastIndex = 0;
|
|
53
|
+
let match;
|
|
54
|
+
while ((match = ATTR_RE.exec(raw)) !== null) {
|
|
55
|
+
const name = match[1]?.toLowerCase();
|
|
56
|
+
if (!name || !allowed.has(name))
|
|
57
|
+
continue;
|
|
58
|
+
const value = match[3] ?? match[4] ?? match[5] ?? "";
|
|
59
|
+
if (name === "href") {
|
|
60
|
+
if (SAFE_HREF_RE.test(value)) {
|
|
61
|
+
parts.push(`href="${escapeAttr(value)}"`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else if (name === "style") {
|
|
65
|
+
const safe = sanitiseStyle(value);
|
|
66
|
+
if (safe)
|
|
67
|
+
parts.push(`style="${escapeAttr(safe)}"`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return parts.length ? " " + parts.join(" ") : "";
|
|
71
|
+
}
|
|
72
|
+
function escapeAttr(value) {
|
|
73
|
+
return value
|
|
74
|
+
.replace(/&/g, "&")
|
|
75
|
+
.replace(/"/g, """)
|
|
76
|
+
.replace(/</g, "<")
|
|
77
|
+
.replace(/>/g, ">");
|
|
78
|
+
}
|
|
79
|
+
export function sanitiseRichText(input) {
|
|
80
|
+
if (typeof input !== "string" || !input)
|
|
81
|
+
return "";
|
|
82
|
+
const stack = [];
|
|
83
|
+
const pieces = [];
|
|
84
|
+
let lastIndex = 0;
|
|
85
|
+
TAG_RE.lastIndex = 0;
|
|
86
|
+
let match;
|
|
87
|
+
while ((match = TAG_RE.exec(input)) !== null) {
|
|
88
|
+
if (match.index > lastIndex) {
|
|
89
|
+
pieces.push(escapeText(input.slice(lastIndex, match.index)));
|
|
90
|
+
}
|
|
91
|
+
lastIndex = match.index + match[0].length;
|
|
92
|
+
if (match[0].startsWith("<!--"))
|
|
93
|
+
continue;
|
|
94
|
+
const tag = (match[1] || "").toLowerCase();
|
|
95
|
+
const isClose = match[0].startsWith("</");
|
|
96
|
+
if (!ALLOWED_TAGS.has(tag))
|
|
97
|
+
continue;
|
|
98
|
+
if (isClose) {
|
|
99
|
+
const idx = stack.lastIndexOf(tag);
|
|
100
|
+
if (idx === -1)
|
|
101
|
+
continue;
|
|
102
|
+
while (stack.length > idx) {
|
|
103
|
+
const popped = stack.pop();
|
|
104
|
+
if (popped)
|
|
105
|
+
pieces.push(`</${popped}>`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (VOID_TAGS.has(tag)) {
|
|
109
|
+
pieces.push(`<${tag}/>`);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const attrs = sanitiseAttrs(tag, match[2] || "");
|
|
113
|
+
pieces.push(`<${tag}${attrs}>`);
|
|
114
|
+
stack.push(tag);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (lastIndex < input.length) {
|
|
118
|
+
pieces.push(escapeText(input.slice(lastIndex)));
|
|
119
|
+
}
|
|
120
|
+
while (stack.length) {
|
|
121
|
+
const popped = stack.pop();
|
|
122
|
+
if (popped)
|
|
123
|
+
pieces.push(`</${popped}>`);
|
|
124
|
+
}
|
|
125
|
+
return pieces.join("");
|
|
126
|
+
}
|
|
127
|
+
function escapeText(value) {
|
|
128
|
+
return value.replace(/</g, "<").replace(/>/g, ">");
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=sanitize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"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"}
|
package/dist/style.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
import type { RisaliStyleOverrides } from "./types.js";
|
|
3
|
+
export declare function safeColor(value: unknown): string | undefined;
|
|
4
|
+
export declare function safeFontSizeMultiplier(value: unknown): number | undefined;
|
|
5
|
+
export declare function applyStyleOverrides(base: CSSProperties | undefined, overrides: RisaliStyleOverrides | null | undefined): CSSProperties | undefined;
|
|
6
|
+
//# sourceMappingURL=style.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../src/style.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIvD,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAG5D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIzE;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,aAAa,GAAG,SAAS,EAC/B,SAAS,EAAE,oBAAoB,GAAG,IAAI,GAAG,SAAS,GACjD,aAAa,GAAG,SAAS,CAS3B"}
|
package/dist/style.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const HEX_RE = /^#[0-9a-fA-F]{6}$/;
|
|
2
|
+
export function safeColor(value) {
|
|
3
|
+
if (typeof value !== "string")
|
|
4
|
+
return undefined;
|
|
5
|
+
return HEX_RE.test(value) ? value : undefined;
|
|
6
|
+
}
|
|
7
|
+
export function safeFontSizeMultiplier(value) {
|
|
8
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
9
|
+
return undefined;
|
|
10
|
+
if (value < 0.5 || value > 2)
|
|
11
|
+
return undefined;
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
export function applyStyleOverrides(base, overrides) {
|
|
15
|
+
if (!overrides)
|
|
16
|
+
return base;
|
|
17
|
+
const color = safeColor(overrides.color);
|
|
18
|
+
const mult = safeFontSizeMultiplier(overrides.font_size_multiplier);
|
|
19
|
+
if (!color && !mult)
|
|
20
|
+
return base;
|
|
21
|
+
const next = { ...(base || {}) };
|
|
22
|
+
if (color)
|
|
23
|
+
next.color = color;
|
|
24
|
+
if (mult)
|
|
25
|
+
next.fontSize = `${mult}em`;
|
|
26
|
+
return next;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=style.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.js","sourceRoot":"","sources":["../src/style.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAG,mBAAmB,CAAC;AAEnC,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3E,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,IAA+B,EAC/B,SAAkD;IAElD,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,sBAAsB,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;IACpE,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,IAAI,GAAkB,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;IAChD,IAAI,KAAK;QAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IAC9B,IAAI,IAAI;QAAE,IAAI,CAAC,QAAQ,GAAG,GAAG,IAAI,IAAI,CAAC;IACtC,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/text.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CSSProperties, ElementType, ReactNode } from "react";
|
|
2
|
+
import type { RisaliContent } from "./types.js";
|
|
3
|
+
export type RisaliTextProps = {
|
|
4
|
+
pageKey: string;
|
|
5
|
+
defaultValue: string;
|
|
6
|
+
path?: string;
|
|
7
|
+
content?: RisaliContent | null;
|
|
8
|
+
as?: ElementType;
|
|
9
|
+
className?: string;
|
|
10
|
+
style?: CSSProperties;
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
siteSlug?: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function RisaliText(props: RisaliTextProps): Promise<import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>>;
|
|
15
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../src/text.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAInE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,mGAsCtD"}
|
package/dist/text.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createElement } from "react";
|
|
2
|
+
import { findBlock, getRisaliContent } from "./content.js";
|
|
3
|
+
import { applyStyleOverrides } from "./style.js";
|
|
4
|
+
export async function RisaliText(props) {
|
|
5
|
+
const { pageKey, defaultValue, path, content: providedContent, as, className, style, siteSlug, } = props;
|
|
6
|
+
const Tag = as || "span";
|
|
7
|
+
const content = providedContent !== undefined
|
|
8
|
+
? providedContent
|
|
9
|
+
: await getRisaliContent(path ?? "/", { siteSlug });
|
|
10
|
+
const block = findBlock(content, pageKey);
|
|
11
|
+
const isTextLike = !block ||
|
|
12
|
+
block.type === "text" ||
|
|
13
|
+
block.type === "rich_text" ||
|
|
14
|
+
block.type === "html";
|
|
15
|
+
const value = isTextLike && typeof block?.value === "string" ? block.value : defaultValue;
|
|
16
|
+
const mergedStyle = applyStyleOverrides(style, block?.style_overrides);
|
|
17
|
+
return createElement(Tag, {
|
|
18
|
+
className,
|
|
19
|
+
style: mergedStyle,
|
|
20
|
+
"data-risali-key": pageKey,
|
|
21
|
+
}, value);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=text.js.map
|
package/dist/text.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../src/text.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAejD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAsB;IACrD,MAAM,EACJ,OAAO,EACP,YAAY,EACZ,IAAI,EACJ,OAAO,EAAE,eAAe,EACxB,EAAE,EACF,SAAS,EACT,KAAK,EACL,QAAQ,GACT,GAAG,KAAK,CAAC;IAEV,MAAM,GAAG,GAAgB,EAAE,IAAI,MAAM,CAAC;IACtC,MAAM,OAAO,GACX,eAAe,KAAK,SAAS;QAC3B,CAAC,CAAC,eAAe;QACjB,CAAC,CAAC,MAAM,gBAAgB,CAAC,IAAI,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAExD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,UAAU,GACd,CAAC,KAAK;QACN,KAAK,CAAC,IAAI,KAAK,MAAM;QACrB,KAAK,CAAC,IAAI,KAAK,WAAW;QAC1B,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;IACxB,MAAM,KAAK,GACT,UAAU,IAAI,OAAO,KAAK,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC;IAE9E,MAAM,WAAW,GAAG,mBAAmB,CAAC,KAAK,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;IAEvE,OAAO,aAAa,CAClB,GAAG,EACH;QACE,SAAS;QACT,KAAK,EAAE,WAAW;QAClB,iBAAiB,EAAE,OAAO;KAC3B,EACD,KAAK,CACN,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type RisaliBlockType = "text" | "image" | "rich_text" | "html";
|
|
2
|
+
export type RisaliStyleOverrides = {
|
|
3
|
+
color?: string;
|
|
4
|
+
font_size_multiplier?: number;
|
|
5
|
+
};
|
|
6
|
+
export type RisaliBlock = {
|
|
7
|
+
key: string;
|
|
8
|
+
type: RisaliBlockType | string;
|
|
9
|
+
value: unknown;
|
|
10
|
+
selector?: string | null;
|
|
11
|
+
content_hash?: string | null;
|
|
12
|
+
style_overrides?: RisaliStyleOverrides | null;
|
|
13
|
+
is_global?: boolean;
|
|
14
|
+
label?: string | null;
|
|
15
|
+
};
|
|
16
|
+
export type RisaliContent = {
|
|
17
|
+
site: {
|
|
18
|
+
slug: string;
|
|
19
|
+
show_badge: boolean;
|
|
20
|
+
favicon_url: string | null;
|
|
21
|
+
jsonld: unknown;
|
|
22
|
+
};
|
|
23
|
+
page: {
|
|
24
|
+
title: string | null;
|
|
25
|
+
seo_title: string | null;
|
|
26
|
+
seo_description: string | null;
|
|
27
|
+
og_image_url: string | null;
|
|
28
|
+
} | null;
|
|
29
|
+
blocks: RisaliBlock[];
|
|
30
|
+
};
|
|
31
|
+
export type RisaliImageValue = {
|
|
32
|
+
src?: string;
|
|
33
|
+
alt?: string;
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,MAAM,CAAC;AAEtE,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,OAAO,CAAC;QACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B,GAAG,IAAI,CAAC;IACT,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@risali/react",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "React server components for Risali.app — SSR-fetch editable text/image/rich-text blocks from a client's Risali site.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"private": false,
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc -p tsconfig.json",
|
|
23
|
+
"clean": "rimraf dist",
|
|
24
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"react": ">=18.0.0",
|
|
28
|
+
"react-dom": ">=18.0.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/react": "^19.0.0",
|
|
32
|
+
"@types/react-dom": "^19.0.0",
|
|
33
|
+
"react": "^19.0.0",
|
|
34
|
+
"react-dom": "^19.0.0",
|
|
35
|
+
"rimraf": "^6.0.1",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18.17.0"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/Patress1989/Risali.app.git",
|
|
44
|
+
"directory": "packages/risali-react"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://risali.app",
|
|
47
|
+
"keywords": [
|
|
48
|
+
"risali",
|
|
49
|
+
"cms",
|
|
50
|
+
"headless",
|
|
51
|
+
"react",
|
|
52
|
+
"nextjs",
|
|
53
|
+
"rsc"
|
|
54
|
+
]
|
|
55
|
+
}
|