@risali/react 0.2.0 → 0.6.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.
Files changed (63) hide show
  1. package/README.md +22 -0
  2. package/dist/blog-jsonld.d.ts +74 -0
  3. package/dist/blog-jsonld.d.ts.map +1 -0
  4. package/dist/blog-jsonld.js +111 -0
  5. package/dist/blog-jsonld.js.map +1 -0
  6. package/dist/blog-list.d.ts +29 -0
  7. package/dist/blog-list.d.ts.map +1 -0
  8. package/dist/blog-list.js +113 -0
  9. package/dist/blog-list.js.map +1 -0
  10. package/dist/blog-post.d.ts +40 -0
  11. package/dist/blog-post.d.ts.map +1 -0
  12. package/dist/blog-post.js +109 -0
  13. package/dist/blog-post.js.map +1 -0
  14. package/dist/blog.d.ts +69 -0
  15. package/dist/blog.d.ts.map +1 -0
  16. package/dist/blog.js +79 -0
  17. package/dist/blog.js.map +1 -0
  18. package/dist/brand.d.ts +9 -0
  19. package/dist/brand.d.ts.map +1 -0
  20. package/dist/brand.js +68 -0
  21. package/dist/brand.js.map +1 -0
  22. package/dist/event-marker.d.ts +35 -0
  23. package/dist/event-marker.d.ts.map +1 -0
  24. package/dist/event-marker.js +17 -0
  25. package/dist/event-marker.js.map +1 -0
  26. package/dist/image.d.ts +34 -34
  27. package/dist/image.d.ts.map +1 -1
  28. package/dist/index.d.ts +22 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +15 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/page.d.ts +18 -0
  33. package/dist/page.d.ts.map +1 -0
  34. package/dist/page.js +41 -0
  35. package/dist/page.js.map +1 -0
  36. package/dist/rich-text.d.ts.map +1 -1
  37. package/dist/rich-text.js +3 -0
  38. package/dist/rich-text.js.map +1 -1
  39. package/dist/sanitize.d.ts.map +1 -1
  40. package/dist/sanitize.js +154 -10
  41. package/dist/sanitize.js.map +1 -1
  42. package/dist/sections/blocks.d.ts +10 -0
  43. package/dist/sections/blocks.d.ts.map +1 -0
  44. package/dist/sections/blocks.js +164 -0
  45. package/dist/sections/blocks.js.map +1 -0
  46. package/dist/sections/index.d.ts +12 -0
  47. package/dist/sections/index.d.ts.map +1 -0
  48. package/dist/sections/index.js +104 -0
  49. package/dist/sections/index.js.map +1 -0
  50. package/dist/style.d.ts.map +1 -1
  51. package/dist/style.js +2 -1
  52. package/dist/style.js.map +1 -1
  53. package/dist/tracking-component.d.ts +29 -0
  54. package/dist/tracking-component.d.ts.map +1 -0
  55. package/dist/tracking-component.js +100 -0
  56. package/dist/tracking-component.js.map +1 -0
  57. package/dist/tracking.d.ts +27 -0
  58. package/dist/tracking.d.ts.map +1 -0
  59. package/dist/tracking.js +49 -0
  60. package/dist/tracking.js.map +1 -0
  61. package/dist/types.d.ts +37 -1
  62. package/dist/types.d.ts.map +1 -1
  63. package/package.json +1 -1
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
- const SAFE_HREF_RE = /^(https?:\/\/|mailto:|tel:|\/)/i;
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
- const name = match[1]?.toLowerCase();
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 value = match[3] ?? match[4] ?? match[5] ?? "";
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(value)) {
61
- parts.push(`href="${escapeAttr(value)}"`);
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(value);
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,28 @@ export function sanitiseRichText(input) {
106
233
  }
107
234
  }
108
235
  else if (VOID_TAGS.has(tag)) {
109
- pieces.push(`<${tag}/>`);
236
+ const attrs = sanitiseAttrs(tag, match[2] || "");
237
+ // img requires a valid src; if sanitiseAttrs dropped it (rejected URL
238
+ // or an XSS payload like `src=x onerror=…`), drop the element entirely
239
+ // — a src-less img is useless and keeps "<img" out of the output.
240
+ // Mirrors the iframe-without-src rule below.
241
+ if (tag === "img" && !/\ssrc=/.test(attrs))
242
+ continue;
243
+ pieces.push(`<${tag}${attrs}/>`);
110
244
  }
111
245
  else {
112
246
  const attrs = sanitiseAttrs(tag, match[2] || "");
247
+ // iframe with no src is useless and could confuse readers; drop.
248
+ if (tag === "iframe" && !/\ssrc=/.test(attrs))
249
+ continue;
113
250
  pieces.push(`<${tag}${attrs}>`);
251
+ if (FORCED_PAIRED.has(tag)) {
252
+ // Always close iframe — the source may have written
253
+ // `<iframe ...></iframe>` (good) or `<iframe ... />` (sloppy
254
+ // but accepted here). We push the open tag and rely on the
255
+ // close tag in the source. If none arrives, the trailing
256
+ // stack drain below closes it for us.
257
+ }
114
258
  stack.push(tag);
115
259
  }
116
260
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ReactNode } from "react";
2
+ import type { RisaliBlock } from "../types.js";
3
+ export declare function safeButtonHref(href: unknown): string | null;
4
+ /** Sorts builder children by sparse position; blocks without one go last. */
5
+ export declare function sortByPosition<T extends {
6
+ position?: number | null;
7
+ }>(items: readonly T[]): T[];
8
+ export declare function renderBlock(block: RisaliBlock): ReactNode;
9
+ export declare function renderBlocks(blocks: readonly RisaliBlock[]): ReactNode;
10
+ //# sourceMappingURL=blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../../src/sections/blocks.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAItD,OAAO,KAAK,EAAE,WAAW,EAAuC,MAAM,aAAa,CAAC;AAUpF,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAK3D;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACnE,KAAK,EAAE,SAAS,CAAC,EAAE,GAClB,CAAC,EAAE,CAML;AAmDD,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,CA6GzD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,CAMtE"}
@@ -0,0 +1,164 @@
1
+ // Child-block renderer shared by every builder section (PR 40b).
2
+ //
3
+ // Deliberately SYNC (plain createElement, no async components) so the tree
4
+ // returned by an awaited <RisaliPage> can be rendered with
5
+ // react-dom/server's renderToStaticMarkup in tests. Styles use only inline
6
+ // CSS + the --risali-* CSS variables emitted by <RisaliBrand> — zero
7
+ // dependency on the client site's Tailwind setup.
8
+ import { createElement, Fragment } from "react";
9
+ import { sanitiseRichText } from "../sanitize.js";
10
+ import { applyStyleOverrides } from "../style.js";
11
+ const SAFE_SRC_RE = /^(https?:\/\/|\/)/;
12
+ // Mirror of src/lib/editor/href.ts on the dashboard side — buttons accept
13
+ // only https://, mailto:, tel: and root-relative paths (never "//", http:,
14
+ // javascript:, data:). Keep the two in sync.
15
+ const SAFE_BUTTON_HREF_RE = /^(https:\/\/[^\s]+|mailto:[^\s]+|tel:[+0-9() -]+|\/(?!\/)[^\s]*)$/i;
16
+ const CONTROL_CHARS_RE = /[\u0000-\u001F\u007F]/;
17
+ export function safeButtonHref(href) {
18
+ if (typeof href !== "string" || !href || href.length > 1000)
19
+ return null;
20
+ if (CONTROL_CHARS_RE.test(href))
21
+ return null;
22
+ if (/["'<>`\\]/.test(href))
23
+ return null;
24
+ return SAFE_BUTTON_HREF_RE.test(href) ? href : null;
25
+ }
26
+ /** Sorts builder children by sparse position; blocks without one go last. */
27
+ export function sortByPosition(items) {
28
+ return [...items].sort((a, b) => (typeof a.position === "number" ? a.position : Number.MAX_SAFE_INTEGER) -
29
+ (typeof b.position === "number" ? b.position : Number.MAX_SAFE_INTEGER));
30
+ }
31
+ const HEADING_STYLE = {
32
+ fontFamily: "var(--risali-font-heading, inherit)",
33
+ fontSize: "2em",
34
+ lineHeight: 1.2,
35
+ margin: "0 0 0.5em",
36
+ };
37
+ const TEXT_STYLE = {
38
+ margin: "0 0 1em",
39
+ };
40
+ const IMG_STYLE = {
41
+ maxWidth: "100%",
42
+ height: "auto",
43
+ display: "block",
44
+ borderRadius: "8px",
45
+ };
46
+ const HR_STYLE = {
47
+ border: "none",
48
+ borderTop: "1px solid var(--risali-color-secondary, #e5e7eb)",
49
+ margin: "1.5em 0",
50
+ };
51
+ const BUTTON_BASE_STYLE = {
52
+ display: "inline-block",
53
+ padding: "0.75em 1.5em",
54
+ borderRadius: "8px",
55
+ textDecoration: "none",
56
+ fontWeight: 600,
57
+ cursor: "pointer",
58
+ };
59
+ function buttonStyle(variant) {
60
+ if (variant === "secondary") {
61
+ return {
62
+ ...BUTTON_BASE_STYLE,
63
+ border: "2px solid var(--risali-color-primary, #111827)",
64
+ color: "var(--risali-color-primary, #111827)",
65
+ background: "transparent",
66
+ };
67
+ }
68
+ return {
69
+ ...BUTTON_BASE_STYLE,
70
+ background: "var(--risali-color-primary, #111827)",
71
+ color: "#ffffff",
72
+ };
73
+ }
74
+ export function renderBlock(block) {
75
+ const overrides = block.style_overrides;
76
+ switch (block.type) {
77
+ case "text": {
78
+ const value = typeof block.value === "string" ? block.value : "";
79
+ if (block.variant === "heading") {
80
+ return createElement("h2", {
81
+ key: block.key,
82
+ "data-risali-key": block.key,
83
+ style: applyStyleOverrides(HEADING_STYLE, overrides),
84
+ }, value);
85
+ }
86
+ return createElement("p", {
87
+ key: block.key,
88
+ "data-risali-key": block.key,
89
+ style: applyStyleOverrides(TEXT_STYLE, overrides),
90
+ }, value);
91
+ }
92
+ case "rich_text": {
93
+ const raw = typeof block.value === "string" ? block.value : "";
94
+ return createElement("div", {
95
+ key: block.key,
96
+ "data-risali-key": block.key,
97
+ "data-risali-type": "rich_text",
98
+ style: applyStyleOverrides(undefined, overrides),
99
+ dangerouslySetInnerHTML: { __html: sanitiseRichText(raw) },
100
+ });
101
+ }
102
+ case "image": {
103
+ const value = block.value && typeof block.value === "object"
104
+ ? block.value
105
+ : {};
106
+ const src = typeof value.src === "string" && value.src && SAFE_SRC_RE.test(value.src)
107
+ ? value.src
108
+ : null;
109
+ if (!src)
110
+ return null;
111
+ return createElement("img", {
112
+ key: block.key,
113
+ "data-risali-key": block.key,
114
+ src,
115
+ alt: typeof value.alt === "string" ? value.alt : "",
116
+ loading: "lazy",
117
+ style: IMG_STYLE,
118
+ });
119
+ }
120
+ case "button": {
121
+ const value = block.value && typeof block.value === "object"
122
+ ? block.value
123
+ : {};
124
+ const text = typeof value.text === "string" ? value.text : "";
125
+ if (!text)
126
+ return null;
127
+ const href = safeButtonHref(value.href);
128
+ const style = applyStyleOverrides(buttonStyle(block.variant), overrides);
129
+ // An unsafe/missing href degrades to a non-link span — the text stays
130
+ // visible and editable, the navigation does not happen.
131
+ if (!href) {
132
+ return createElement("span", {
133
+ key: block.key,
134
+ "data-risali-key": block.key,
135
+ "data-risali-type": "button",
136
+ "data-risali-variant": block.variant ?? "primary",
137
+ style,
138
+ }, text);
139
+ }
140
+ return createElement("a", {
141
+ key: block.key,
142
+ "data-risali-key": block.key,
143
+ "data-risali-type": "button",
144
+ "data-risali-variant": block.variant ?? "primary",
145
+ href,
146
+ style,
147
+ }, text);
148
+ }
149
+ case "divider":
150
+ return createElement("hr", {
151
+ key: block.key,
152
+ "data-risali-key": block.key,
153
+ "data-risali-type": "divider",
154
+ style: HR_STYLE,
155
+ });
156
+ default:
157
+ // html blocks (and any future type) are not builder children — skip.
158
+ return null;
159
+ }
160
+ }
161
+ export function renderBlocks(blocks) {
162
+ return createElement(Fragment, null, sortByPosition(blocks).map((b) => renderBlock(b)));
163
+ }
164
+ //# sourceMappingURL=blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../src/sections/blocks.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { CSSProperties, ReactNode } from "react";
2
+ import type { RisaliBlock, RisaliSection } from "../types.js";
3
+ export type RisaliSectionProps = {
4
+ section: RisaliSection;
5
+ /** Child blocks already sorted by position. */
6
+ blocks: RisaliBlock[];
7
+ };
8
+ export type RisaliSectionComponent = (props: RisaliSectionProps) => ReactNode;
9
+ export declare const RISALI_SECTION_COMPONENTS: Record<string, RisaliSectionComponent>;
10
+ /** Wrapper style for the <section> element from whitelisted settings. */
11
+ export declare function sectionWrapperStyle(section: RisaliSection): CSSProperties;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sections/index.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG9D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,aAAa,CAAC;IACvB,+CAA+C;IAC/C,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,kBAAkB,KAAK,SAAS,CAAC;AAoH9E,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAQ5E,CAAC;AAYF,yEAAyE;AACzE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAWzE"}
@@ -0,0 +1,104 @@
1
+ // Builder section catalog v1 (PR 40b) — render side of
2
+ // src/lib/sections/catalog.ts in the dashboard repo (gallery/defaults).
3
+ // Keep the `type` keys of the two in sync.
4
+ //
5
+ // Every component is SYNC and content-driven: it lays out the ordered child
6
+ // blocks it receives, nothing more. Signature sections a client repo ships
7
+ // in code are passed to <RisaliPage customSections={{...}}> and take
8
+ // precedence over this registry on a type-key collision.
9
+ import { createElement } from "react";
10
+ import { renderBlock, renderBlocks, sortByPosition } from "./blocks.js";
11
+ const CONTAINER_STYLE = {
12
+ maxWidth: "1100px",
13
+ margin: "0 auto",
14
+ };
15
+ function gridStyle(columns) {
16
+ const n = typeof columns === "number" && [2, 3, 4].includes(columns) ? columns : 3;
17
+ return {
18
+ display: "grid",
19
+ gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))`,
20
+ gap: "24px",
21
+ };
22
+ }
23
+ function HeroSection({ section, blocks }) {
24
+ const centered = section.variant !== "left";
25
+ return createElement("div", {
26
+ style: {
27
+ ...CONTAINER_STYLE,
28
+ textAlign: centered ? "center" : "left",
29
+ },
30
+ }, renderBlocks(blocks));
31
+ }
32
+ function TextImageSection({ section, blocks }) {
33
+ const sorted = sortByPosition(blocks);
34
+ const images = sorted.filter((b) => b.type === "image");
35
+ const rest = sorted.filter((b) => b.type !== "image");
36
+ const imageLeft = section.settings?.image_side === "left";
37
+ const textCol = createElement("div", { key: "text" }, rest.map((b) => renderBlock(b)));
38
+ const imageCol = createElement("div", { key: "image" }, images.map((b) => renderBlock(b)));
39
+ return createElement("div", {
40
+ style: {
41
+ ...CONTAINER_STYLE,
42
+ display: "grid",
43
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
44
+ gap: "48px",
45
+ alignItems: "center",
46
+ },
47
+ }, imageLeft ? [imageCol, textCol] : [textCol, imageCol]);
48
+ }
49
+ // Flow model v1: the first heading spans the full width, every following
50
+ // block is one grid cell. Grouped feature items (icon+title+text as a unit)
51
+ // are a planned follow-up.
52
+ function FeaturesSection({ section, blocks }) {
53
+ const sorted = sortByPosition(blocks);
54
+ const [first, ...rest] = sorted;
55
+ const headingFirst = first && first.type === "text" && first.variant === "heading";
56
+ const headOut = headingFirst ? renderBlock(first) : null;
57
+ const cells = (headingFirst ? rest : sorted).map((b) => createElement("div", { key: b.key }, renderBlock(b)));
58
+ return createElement("div", { style: CONTAINER_STYLE }, headOut, createElement("div", { style: gridStyle(section.settings?.columns) }, cells));
59
+ }
60
+ function GallerySection({ section, blocks }) {
61
+ const sorted = sortByPosition(blocks);
62
+ const images = sorted.filter((b) => b.type === "image");
63
+ const rest = sorted.filter((b) => b.type !== "image");
64
+ return createElement("div", { style: CONTAINER_STYLE }, rest.map((b) => renderBlock(b)), createElement("div", { style: gridStyle(section.settings?.columns) }, images.map((b) => createElement("div", { key: b.key }, renderBlock(b)))));
65
+ }
66
+ function CtaSection({ blocks }) {
67
+ return createElement("div", { style: { ...CONTAINER_STYLE, textAlign: "center" } }, renderBlocks(blocks));
68
+ }
69
+ function ContactSection({ blocks }) {
70
+ return createElement("div", { style: { ...CONTAINER_STYLE, maxWidth: "720px" } }, renderBlocks(blocks));
71
+ }
72
+ function PlainSection({ blocks }) {
73
+ return createElement("div", { style: CONTAINER_STYLE }, renderBlocks(blocks));
74
+ }
75
+ export const RISALI_SECTION_COMPONENTS = {
76
+ hero: HeroSection,
77
+ text_image: TextImageSection,
78
+ features: FeaturesSection,
79
+ gallery: GallerySection,
80
+ cta: CtaSection,
81
+ contact: ContactSection,
82
+ plain: PlainSection,
83
+ };
84
+ // Palette KEY shape — mirrors the content API + dashboard catalog guard.
85
+ // Anything else would be a CSS-variable injection through settings.
86
+ const PALETTE_KEY_RE = /^[a-z][a-z0-9_]{0,40}$/;
87
+ const SPACING_PADDING = {
88
+ compact: "24px 16px",
89
+ normal: "48px 16px",
90
+ spacious: "96px 16px",
91
+ };
92
+ /** Wrapper style for the <section> element from whitelisted settings. */
93
+ export function sectionWrapperStyle(section) {
94
+ const style = {
95
+ padding: SPACING_PADDING[section.settings?.spacing ?? ""] ?? SPACING_PADDING.normal,
96
+ fontFamily: "var(--risali-font-body, inherit)",
97
+ };
98
+ const bg = section.settings?.background;
99
+ if (typeof bg === "string" && PALETTE_KEY_RE.test(bg)) {
100
+ style.backgroundColor = `var(--risali-color-${bg})`;
101
+ }
102
+ return style;
103
+ }
104
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sections/index.tsx"],"names":[],"mappings":"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"}
@@ -1 +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"}
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,CAKzE;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 CHANGED
@@ -7,7 +7,8 @@ export function safeColor(value) {
7
7
  export function safeFontSizeMultiplier(value) {
8
8
  if (typeof value !== "number" || !Number.isFinite(value))
9
9
  return undefined;
10
- if (value < 0.5 || value > 2)
10
+ // Mirrors the editor's slider bounds (PR 40a) values outside are dropped.
11
+ if (value < 0.5 || value > 3)
11
12
  return undefined;
12
13
  return value;
13
14
  }
package/dist/style.js.map CHANGED
@@ -1 +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"}
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,4EAA4E;IAC5E,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"}
@@ -0,0 +1,29 @@
1
+ import { type GetTrackingConfigOptions } from "./tracking.js";
2
+ export type RisaliTrackingProps = GetTrackingConfigOptions;
3
+ /**
4
+ * Server component that emits Risali-managed tracking tags into <head>.
5
+ * Render once inside the root layout's <head> (Next.js App Router):
6
+ *
7
+ * import { RisaliTracking } from "@risali/react";
8
+ * export default function RootLayout({ children }) {
9
+ * return (
10
+ * <html>
11
+ * <head>
12
+ * <RisaliTracking />
13
+ * </head>
14
+ * <body>{children}</body>
15
+ * </html>
16
+ * );
17
+ * }
18
+ *
19
+ * Behaviour mirrors the Lovable /risali.js snippet: every tag ships as a
20
+ * <script type="text/plain" data-risali-consent="analytics|marketing"> so it
21
+ * stays inert until the GDPR banner (rendered by the host or by the Risali
22
+ * snippet itself) flips it to executable JS via gdprApplyConsentToScripts.
23
+ *
24
+ * Pro custom HTML is rendered raw (server-sanitized whitelist already runs at
25
+ * save time). Because Next.js needs dangerouslySetInnerHTML for raw <script>
26
+ * tags inside the React tree, we wrap the entire payload in a single block.
27
+ */
28
+ export declare function RisaliTracking(props?: RisaliTrackingProps): Promise<import("react/jsx-runtime").JSX.Element>;
29
+ //# sourceMappingURL=tracking-component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracking-component.d.ts","sourceRoot":"","sources":["../src/tracking-component.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,mBAAmB,GAAG,wBAAwB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,cAAc,CAAC,KAAK,GAAE,mBAAwB,oDA+JnE"}