@roottale/cms-renderer-next 0.41.1 → 0.42.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 (60) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/before-after-client.d.ts +15 -0
  3. package/dist/before-after-client.js +8 -0
  4. package/dist/before-after-client.js.map +1 -0
  5. package/dist/chunk-4LQPZDXZ.js +75 -0
  6. package/dist/chunk-4LQPZDXZ.js.map +1 -0
  7. package/dist/chunk-6GQCFFHU.js +540 -0
  8. package/dist/chunk-6GQCFFHU.js.map +1 -0
  9. package/dist/chunk-F3G6RVIR.js +220 -0
  10. package/dist/chunk-F3G6RVIR.js.map +1 -0
  11. package/dist/chunk-H46JUIHZ.js +79 -0
  12. package/dist/chunk-H46JUIHZ.js.map +1 -0
  13. package/dist/chunk-K62RR4UQ.js +53 -0
  14. package/dist/chunk-K62RR4UQ.js.map +1 -0
  15. package/dist/chunk-NUUTTSGT.js +916 -0
  16. package/dist/chunk-NUUTTSGT.js.map +1 -0
  17. package/dist/chunk-RSNUZ4BF.js +3378 -0
  18. package/dist/chunk-RSNUZ4BF.js.map +1 -0
  19. package/dist/chunk-U5AKACPN.js +113 -0
  20. package/dist/chunk-U5AKACPN.js.map +1 -0
  21. package/dist/chunk-WWS43XCT.js +206 -0
  22. package/dist/chunk-WWS43XCT.js.map +1 -0
  23. package/dist/cms-public.css +164 -51
  24. package/dist/concerns-client.d.ts +12 -0
  25. package/dist/concerns-client.js +8 -0
  26. package/dist/concerns-client.js.map +1 -0
  27. package/dist/expertise-client.d.ts +10 -0
  28. package/dist/expertise-client.js +8 -0
  29. package/dist/expertise-client.js.map +1 -0
  30. package/dist/hero-carousel-client.d.ts +36 -0
  31. package/dist/hero-carousel-client.js +8 -0
  32. package/dist/hero-carousel-client.js.map +1 -0
  33. package/dist/routes.d.ts +51 -5
  34. package/dist/routes.js +109 -62
  35. package/dist/routes.js.map +1 -1
  36. package/dist/seo-checks.d.ts +87 -0
  37. package/dist/seo-checks.js +27 -0
  38. package/dist/seo-checks.js.map +1 -0
  39. package/dist/server.d.ts +51 -2
  40. package/dist/server.js +8 -2
  41. package/dist/site-config-DgYGGwu1.d.ts +3910 -0
  42. package/dist/spaces-client.d.ts +10 -0
  43. package/dist/spaces-client.js +8 -0
  44. package/dist/spaces-client.js.map +1 -0
  45. package/dist/templates.css +3246 -194
  46. package/dist/templates.d.ts +20 -1028
  47. package/dist/templates.js +70 -2
  48. package/dist/templates.js.map +1 -1
  49. package/dist/{theme-css-vars-BiyHBsJG.d.ts → theme-css-vars-CD3jcEkp.d.ts} +2 -2
  50. package/dist/ui-react-motion-client.d.ts +73 -0
  51. package/dist/ui-react-motion-client.js +14 -0
  52. package/dist/ui-react-motion-client.js.map +1 -0
  53. package/dist/validate.d.ts +15 -1
  54. package/dist/validate.js +806 -17
  55. package/dist/validate.js.map +1 -1
  56. package/package.json +18 -6
  57. package/dist/chunk-GOHP7RWD.js +0 -1647
  58. package/dist/chunk-GOHP7RWD.js.map +0 -1
  59. package/dist/chunk-IOYBEH6E.js +0 -271
  60. package/dist/chunk-IOYBEH6E.js.map +0 -1
@@ -1,1647 +0,0 @@
1
- import {
2
- collectCategories,
3
- collectCategoriesWithCounts,
4
- collectCollectionCategories,
5
- defaultCategoryHref,
6
- filterPostsByCategory
7
- } from "./chunk-FUA5H6JE.js";
8
- import {
9
- SectionSchema
10
- } from "./chunk-IOYBEH6E.js";
11
-
12
- // src/server.tsx
13
- import {
14
- DEFAULT_BLOG_SETTINGS,
15
- fetchBlogSettings,
16
- fetchPost,
17
- fetchPosts,
18
- fetchTheme,
19
- resolvePostDisplay,
20
- selectRelatedPosts
21
- } from "@roottale/cms-client/server";
22
- import {
23
- bindingSrcValue,
24
- bindingTextValue,
25
- boundFieldValue,
26
- extractFaqEntries,
27
- faqPageJsonLd,
28
- isAllowedEmbedSrc as isAllowedEmbedSrc2,
29
- postsForCollection,
30
- resolvePostPath
31
- } from "@roottale/cms-core";
32
-
33
- // src/LeadForm.tsx
34
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
35
- var VERTICAL_LABEL = {
36
- consulting: "\uCEE8\uC124\uD305",
37
- medical: "\uC758\uB8CC",
38
- tax: "\uC138\uBB34",
39
- legal: "\uBC95\uB960"
40
- };
41
- var VERTICAL_OPTIONS = [
42
- { value: "consulting", label: "\uCEE8\uC124\uD305 / \uC77C\uBC18" },
43
- { value: "medical", label: "\uC758\uB8CC (\uBCD1\uC758\uC6D0\xB7\uCE58\uACFC\xB7\uD55C\uC758\uC6D0)" },
44
- { value: "tax", label: "\uC138\uBB34 (\uC138\uBB34\uC0AC\xB7\uD68C\uACC4\uC0AC)" },
45
- { value: "legal", label: "\uBC95\uB960 (\uBC95\uBB34\uBC95\uC778\xB7\uBCC0\uD638\uC0AC)" }
46
- ];
47
- function RootTaleLeadForm(props) {
48
- const {
49
- action,
50
- vertical,
51
- redirectUrl,
52
- heading,
53
- description,
54
- submitLabel = "\uC9C4\uB2E8 \uC2E0\uCCAD",
55
- turnstileSiteKey,
56
- className
57
- } = props;
58
- const formClass = ["rt-cms-lead-form", className].filter(Boolean).join(" ");
59
- return /* @__PURE__ */ jsxs(
60
- "form",
61
- {
62
- method: "post",
63
- action,
64
- "data-roottale-cms": "lead-form",
65
- className: formClass,
66
- children: [
67
- heading ? /* @__PURE__ */ jsx("h2", { className: "rt-cms-lead-heading", children: heading }) : null,
68
- description ? /* @__PURE__ */ jsx("p", { className: "rt-cms-lead-description", children: description }) : null,
69
- redirectUrl ? /* @__PURE__ */ jsx("input", { type: "hidden", name: "_redirect_url", value: redirectUrl }) : null,
70
- vertical ? /* @__PURE__ */ jsxs(Fragment, { children: [
71
- /* @__PURE__ */ jsx("input", { type: "hidden", name: "vertical", value: vertical }),
72
- /* @__PURE__ */ jsxs("p", { className: "rt-cms-lead-vertical-label", children: [
73
- "\uBD84\uC57C: ",
74
- /* @__PURE__ */ jsx("strong", { children: VERTICAL_LABEL[vertical] })
75
- ] })
76
- ] }) : /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
77
- /* @__PURE__ */ jsxs("span", { className: "rt-cms-field-label", children: [
78
- "\uBD84\uC57C ",
79
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "*" })
80
- ] }),
81
- /* @__PURE__ */ jsxs(
82
- "select",
83
- {
84
- name: "vertical",
85
- required: true,
86
- className: "rt-cms-field-input rt-cms-field-select",
87
- defaultValue: "",
88
- children: [
89
- /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "\uC120\uD0DD\uD558\uC138\uC694" }),
90
- VERTICAL_OPTIONS.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
91
- ]
92
- }
93
- )
94
- ] }),
95
- /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
96
- /* @__PURE__ */ jsxs("span", { className: "rt-cms-field-label", children: [
97
- "\uC774\uB984 ",
98
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "*" })
99
- ] }),
100
- /* @__PURE__ */ jsx(
101
- "input",
102
- {
103
- type: "text",
104
- name: "contact_name",
105
- required: true,
106
- autoComplete: "name",
107
- className: "rt-cms-field-input"
108
- }
109
- )
110
- ] }),
111
- /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
112
- /* @__PURE__ */ jsxs("span", { className: "rt-cms-field-label", children: [
113
- "\uC0AC\uC5C5\uCCB4\uBA85 ",
114
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "*" })
115
- ] }),
116
- /* @__PURE__ */ jsx(
117
- "input",
118
- {
119
- type: "text",
120
- name: "business_name",
121
- required: true,
122
- autoComplete: "organization",
123
- className: "rt-cms-field-input"
124
- }
125
- )
126
- ] }),
127
- /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
128
- /* @__PURE__ */ jsxs("span", { className: "rt-cms-field-label", children: [
129
- "\uC774\uBA54\uC77C ",
130
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "*" })
131
- ] }),
132
- /* @__PURE__ */ jsx(
133
- "input",
134
- {
135
- type: "email",
136
- name: "email",
137
- required: true,
138
- autoComplete: "email",
139
- className: "rt-cms-field-input"
140
- }
141
- )
142
- ] }),
143
- /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
144
- /* @__PURE__ */ jsxs("span", { className: "rt-cms-field-label", children: [
145
- "\uC804\uD654\uBC88\uD638 ",
146
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "*" })
147
- ] }),
148
- /* @__PURE__ */ jsx(
149
- "input",
150
- {
151
- type: "tel",
152
- name: "phone",
153
- required: true,
154
- autoComplete: "tel",
155
- inputMode: "tel",
156
- pattern: "0\\d{1,2}-?\\d{3,4}-?\\d{4}",
157
- placeholder: "010-1234-5678",
158
- className: "rt-cms-field-input"
159
- }
160
- )
161
- ] }),
162
- /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
163
- /* @__PURE__ */ jsx("span", { className: "rt-cms-field-label", children: "\uD604\uC7AC \uC0AC\uC774\uD2B8 URL (\uC120\uD0DD)" }),
164
- /* @__PURE__ */ jsx(
165
- "input",
166
- {
167
- type: "url",
168
- name: "current_site_url",
169
- placeholder: "https://",
170
- className: "rt-cms-field-input"
171
- }
172
- ),
173
- /* @__PURE__ */ jsx("span", { className: "rt-cms-field-hint", children: "\uC5C6\uC73C\uBA74 \uBE44\uC6CC\uB450\uC138\uC694." })
174
- ] }),
175
- /* @__PURE__ */ jsxs("label", { className: "rt-cms-lead-consent", children: [
176
- /* @__PURE__ */ jsx("input", { type: "checkbox", name: "privacy_consent", required: true }),
177
- /* @__PURE__ */ jsxs("span", { children: [
178
- /* @__PURE__ */ jsx("strong", { children: "(\uD544\uC218)" }),
179
- " \uAC1C\uC778\uC815\uBCF4 \uC218\uC9D1\xB7\uC774\uC6A9\uC5D0 \uB3D9\uC758\uD569\uB2C8\uB2E4. (\uC218\uC9D1 \uD56D\uBAA9: \uC774\uB984\xB7\uC5F0\uB77D\uCC98\xB7\uC774\uBA54\uC77C\xB7\uC0AC\uC5C5\uCCB4\uBA85. \uBCF4\uAD00 \uAE30\uAC04: \uBB38\uC758 \uC885\uB8CC \uD6C4 3\uB144)"
180
- ] })
181
- ] }),
182
- vertical === "medical" ? /* @__PURE__ */ jsxs("label", { className: "rt-cms-lead-consent", children: [
183
- /* @__PURE__ */ jsx(
184
- "input",
185
- {
186
- type: "checkbox",
187
- name: "overseas_transfer_consent",
188
- required: true
189
- }
190
- ),
191
- /* @__PURE__ */ jsxs("span", { children: [
192
- /* @__PURE__ */ jsx("strong", { children: "(\uD544\uC218, \uC758\uB8CC)" }),
193
- " \uC758\uB8CC PII \uC758 \uAD6D\uC678\uC774\uC804(\uBCF4\uAD00\xB7\uCC98\uB9AC)\uC5D0 \uB3D9\uC758\uD569\uB2C8\uB2E4. (\uC758\uB8CC\uBC95 \xA721\xB7\uAC1C\uC778\uC815\uBCF4\uBCF4\uD638\uBC95 \xA728 \u2014 ADR-0018)"
194
- ] })
195
- ] }) : null,
196
- turnstileSiteKey ? /* @__PURE__ */ jsxs(Fragment, { children: [
197
- /* @__PURE__ */ jsx(
198
- "script",
199
- {
200
- src: "https://challenges.cloudflare.com/turnstile/v0/api.js",
201
- async: true,
202
- defer: true
203
- }
204
- ),
205
- /* @__PURE__ */ jsx(
206
- "div",
207
- {
208
- className: "cf-turnstile",
209
- "data-sitekey": turnstileSiteKey,
210
- "data-action": "turnstile-spin-v1"
211
- }
212
- )
213
- ] }) : null,
214
- /* @__PURE__ */ jsx("div", { className: "rt-cms-lead-actions", children: /* @__PURE__ */ jsx("button", { type: "submit", className: "rt-cms-lead-submit", children: submitLabel }) })
215
- ]
216
- }
217
- );
218
- }
219
-
220
- // src/templates/sections.tsx
221
- import { isAllowedEmbedSrc } from "@roottale/cms-core";
222
- import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
223
- function sectionThemeStyle(theme) {
224
- if (!theme) return void 0;
225
- const style = {};
226
- for (const [key, value] of Object.entries(theme)) {
227
- if (key.startsWith("--")) style[key] = value;
228
- }
229
- return Object.keys(style).length > 0 ? style : void 0;
230
- }
231
- function CtaLink({
232
- cta,
233
- className,
234
- track
235
- }) {
236
- return /* @__PURE__ */ jsx2(
237
- "a",
238
- {
239
- className: className ?? "rt-tpl-btn rt-tpl-btn--primary",
240
- href: cta.href,
241
- "data-track": track,
242
- children: cta.label
243
- }
244
- );
245
- }
246
- function TemplateHero(section) {
247
- const { eyebrow, title, description, imageSrc, imageAlt, cta } = section.props;
248
- const variant = section.variant;
249
- const showImage = variant !== "minimal" && imageSrc;
250
- return /* @__PURE__ */ jsx2(
251
- "section",
252
- {
253
- "data-roottale-tpl": "hero",
254
- "data-variant": variant,
255
- id: section.id,
256
- className: "rt-tpl-section rt-tpl-hero",
257
- style: sectionThemeStyle(section.theme),
258
- children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container rt-tpl-hero-inner", children: [
259
- /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-hero-copy", children: [
260
- eyebrow ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-hero-eyebrow", children: eyebrow }) : null,
261
- /* @__PURE__ */ jsx2("h1", { className: "rt-tpl-hero-title", children: title.split("\n").map((line, i) => /* @__PURE__ */ jsx2("span", { className: "rt-tpl-hero-title-line", children: line }, i)) }),
262
- description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-hero-desc", children: description }) : null,
263
- cta ? /* @__PURE__ */ jsx2(CtaLink, { cta, track: "cta_hero" }) : null
264
- ] }),
265
- showImage ? /* @__PURE__ */ jsx2("div", { className: "rt-tpl-hero-media", children: /* @__PURE__ */ jsx2(
266
- "img",
267
- {
268
- className: "rt-tpl-hero-img",
269
- src: imageSrc,
270
- alt: imageAlt ?? "",
271
- loading: "eager"
272
- }
273
- ) }) : null
274
- ] })
275
- }
276
- );
277
- }
278
- function TemplateRichText(section) {
279
- const { heading, body } = section.props;
280
- return /* @__PURE__ */ jsx2(
281
- "section",
282
- {
283
- "data-roottale-tpl": "rich-text",
284
- id: section.id,
285
- className: "rt-tpl-section rt-tpl-rich-text",
286
- style: sectionThemeStyle(section.theme),
287
- children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
288
- heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
289
- body.split("\n\n").map((para, i) => /* @__PURE__ */ jsx2("p", { className: "rt-tpl-rich-text-p", children: para }, i))
290
- ] })
291
- }
292
- );
293
- }
294
- function TemplateServices(section) {
295
- const { heading, description, items } = section.props;
296
- return /* @__PURE__ */ jsx2(
297
- "section",
298
- {
299
- "data-roottale-tpl": "services",
300
- "data-variant": section.variant,
301
- id: section.id,
302
- className: "rt-tpl-section rt-tpl-services",
303
- style: sectionThemeStyle(section.theme),
304
- children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
305
- heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
306
- description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
307
- /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-services-list", children: items.map((item, i) => {
308
- const body = /* @__PURE__ */ jsxs2(Fragment2, { children: [
309
- /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-services-title", children: item.title }),
310
- item.description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-services-desc", children: item.description }) : null
311
- ] });
312
- return /* @__PURE__ */ jsx2("li", { className: "rt-tpl-services-item", children: item.href ? /* @__PURE__ */ jsx2(
313
- "a",
314
- {
315
- className: "rt-tpl-services-link",
316
- href: item.href,
317
- "data-track": "service_card",
318
- children: body
319
- }
320
- ) : body }, i);
321
- }) })
322
- ] })
323
- }
324
- );
325
- }
326
- function TemplateFaq(section) {
327
- const { heading, items, jsonLd } = section.props;
328
- return /* @__PURE__ */ jsxs2(
329
- "section",
330
- {
331
- "data-roottale-tpl": "faq",
332
- id: section.id,
333
- className: "rt-tpl-section rt-tpl-faq",
334
- style: sectionThemeStyle(section.theme),
335
- children: [
336
- /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
337
- heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
338
- /* @__PURE__ */ jsx2("div", { className: "rt-tpl-faq-list", children: items.map((item, i) => /* @__PURE__ */ jsxs2("details", { className: "rt-tpl-faq-item", children: [
339
- /* @__PURE__ */ jsx2("summary", { className: "rt-tpl-faq-q", children: item.question }),
340
- /* @__PURE__ */ jsx2("p", { className: "rt-tpl-faq-a", children: item.answer })
341
- ] }, i)) })
342
- ] }),
343
- jsonLd ? /* @__PURE__ */ jsx2(
344
- "script",
345
- {
346
- type: "application/ld+json",
347
- dangerouslySetInnerHTML: {
348
- __html: JSON.stringify({
349
- "@context": "https://schema.org",
350
- "@type": "FAQPage",
351
- mainEntity: items.map((item) => ({
352
- "@type": "Question",
353
- name: item.question,
354
- acceptedAnswer: { "@type": "Answer", text: item.answer }
355
- }))
356
- })
357
- }
358
- }
359
- ) : null
360
- ]
361
- }
362
- );
363
- }
364
- function TemplateCtaBanner(section) {
365
- const { title, description, cta } = section.props;
366
- return /* @__PURE__ */ jsx2(
367
- "section",
368
- {
369
- "data-roottale-tpl": "cta-banner",
370
- id: section.id,
371
- className: "rt-tpl-section rt-tpl-cta-banner",
372
- style: sectionThemeStyle(section.theme),
373
- children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container rt-tpl-cta-banner-inner", children: [
374
- /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-cta-banner-title", children: title }),
375
- description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-cta-banner-desc", children: description }) : null,
376
- cta ? /* @__PURE__ */ jsx2(CtaLink, { cta, track: "cta_banner" }) : null
377
- ] })
378
- }
379
- );
380
- }
381
- function TrustCredentialIcon() {
382
- return /* @__PURE__ */ jsxs2(
383
- "svg",
384
- {
385
- className: "rt-cred__icon",
386
- viewBox: "0 0 16 16",
387
- "aria-hidden": "true",
388
- focusable: "false",
389
- children: [
390
- /* @__PURE__ */ jsx2("path", { d: "M8 1.75 13 3.5v3.75c0 3-2 5.45-5 7-3-1.55-5-4-5-7V3.5z" }),
391
- /* @__PURE__ */ jsx2("path", { d: "m5.75 8 1.45 1.45 3.2-3.4" })
392
- ]
393
- }
394
- );
395
- }
396
- function TemplateTrust(section) {
397
- const { heading, metrics, credentials, logos, disclaimer } = section.props;
398
- return /* @__PURE__ */ jsx2(
399
- "section",
400
- {
401
- "data-roottale-tpl": "trust",
402
- "data-variant": section.variant,
403
- id: section.id,
404
- className: "rt-tpl-section rt-tpl-trust",
405
- style: sectionThemeStyle(section.theme),
406
- children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container rt-tpl-trust-inner", children: [
407
- heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
408
- section.variant === "stat-band" ? /* @__PURE__ */ jsx2("div", { className: "rt-tpl-trust-stat-band", children: (metrics ?? []).map((metric) => /* @__PURE__ */ jsxs2(
409
- "div",
410
- {
411
- className: "rt-stat",
412
- "data-variant": "band-item",
413
- children: [
414
- /* @__PURE__ */ jsxs2("span", { className: "rt-stat__value", children: [
415
- metric.value,
416
- metric.unit ? /* @__PURE__ */ jsx2("span", { className: "rt-stat__unit", children: metric.unit }) : null
417
- ] }),
418
- /* @__PURE__ */ jsx2("span", { className: "rt-stat__label", children: metric.label }),
419
- metric.source ? /* @__PURE__ */ jsx2("span", { className: "rt-stat__source", children: metric.source }) : null
420
- ]
421
- },
422
- `${metric.value}-${metric.label}`
423
- )) }) : null,
424
- section.variant === "logo-cloud" ? /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-trust-logo-list", children: (logos ?? []).map((logo) => /* @__PURE__ */ jsx2("li", { className: "rt-tpl-trust-logo-item", children: logo.href ? /* @__PURE__ */ jsx2("a", { className: "rt-tpl-trust-logo-link", href: logo.href, children: /* @__PURE__ */ jsx2(
425
- "img",
426
- {
427
- className: "rt-tpl-trust-logo",
428
- src: logo.src,
429
- alt: logo.alt,
430
- loading: "lazy"
431
- }
432
- ) }) : /* @__PURE__ */ jsx2(
433
- "img",
434
- {
435
- className: "rt-tpl-trust-logo",
436
- src: logo.src,
437
- alt: logo.alt,
438
- loading: "lazy"
439
- }
440
- ) }, `${logo.src}-${logo.alt}`)) }) : null,
441
- section.variant === "feature-grid" ? /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-trust-cred-list", children: (credentials ?? []).map((credential) => /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsxs2("span", { className: "rt-cred", "data-kind": credential.kind, children: [
442
- /* @__PURE__ */ jsx2(TrustCredentialIcon, {}),
443
- /* @__PURE__ */ jsx2("span", { className: "rt-cred__label", children: credential.name }),
444
- credential.issuer ? /* @__PURE__ */ jsx2("span", { className: "rt-cred__issuer", children: credential.issuer }) : null
445
- ] }) }, `${credential.name}-${credential.issuer ?? ""}`)) }) : null,
446
- disclaimer ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-trust-disclaimer", children: disclaimer }) : null
447
- ] })
448
- }
449
- );
450
- }
451
- function telHref(phone) {
452
- return `tel:${phone.replace(/[^\d+]/g, "")}`;
453
- }
454
- function ContactMap({ url }) {
455
- if (isAllowedEmbedSrc(url)) {
456
- return /* @__PURE__ */ jsx2("div", { className: "rt-tpl-contact-map", children: /* @__PURE__ */ jsx2(
457
- "iframe",
458
- {
459
- src: url,
460
- title: "\uC624\uC2DC\uB294\uAE38 \uC9C0\uB3C4",
461
- loading: "lazy",
462
- referrerPolicy: "no-referrer-when-downgrade"
463
- }
464
- ) });
465
- }
466
- return /* @__PURE__ */ jsx2("p", { className: "rt-tpl-contact-map-fallback", children: /* @__PURE__ */ jsx2("a", { href: url, rel: "noopener noreferrer", target: "_blank", children: "\uAE38\uCC3E\uAE30" }) });
467
- }
468
- function TemplateContact(section) {
469
- const { heading, form, phone, address, hours, mapEmbedUrl } = section.props;
470
- return /* @__PURE__ */ jsx2(
471
- "section",
472
- {
473
- "data-roottale-tpl": "contact",
474
- "data-variant": section.variant,
475
- id: section.id,
476
- className: "rt-tpl-section rt-tpl-contact",
477
- style: sectionThemeStyle(section.theme),
478
- children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container rt-tpl-contact-inner", children: [
479
- /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-contact-info", children: [
480
- heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
481
- phone ? /* @__PURE__ */ jsx2("a", { className: "rt-tpl-contact-phone", href: telHref(phone), "data-track": "cta_call", children: phone }) : null,
482
- address ? /* @__PURE__ */ jsx2("address", { className: "rt-tpl-contact-address", children: address }) : null,
483
- hours ? /* @__PURE__ */ jsxs2("table", { className: "rt-tpl-contact-hours", children: [
484
- /* @__PURE__ */ jsx2("caption", { className: "rt-tpl-sr-only", children: "\uC9C4\uB8CC\uC2DC\uAC04" }),
485
- /* @__PURE__ */ jsx2("tbody", { children: hours.map((row) => /* @__PURE__ */ jsxs2("tr", { children: [
486
- /* @__PURE__ */ jsx2("th", { scope: "row", children: row.day }),
487
- /* @__PURE__ */ jsxs2("td", { children: [
488
- /* @__PURE__ */ jsx2("span", { children: row.open }),
489
- /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: "-" }),
490
- /* @__PURE__ */ jsx2("span", { children: row.close }),
491
- row.note ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-contact-hours-note", children: row.note }) : null
492
- ] })
493
- ] }, `${row.day}-${row.open}-${row.close}`)) })
494
- ] }) : null,
495
- mapEmbedUrl ? /* @__PURE__ */ jsx2(ContactMap, { url: mapEmbedUrl }) : null
496
- ] }),
497
- form.enabled ? /* @__PURE__ */ jsx2("div", { className: "rt-tpl-contact-form", children: /* @__PURE__ */ jsx2(RootTaleLeadForm, { action: "/api/inquiry", vertical: form.vertical }) }) : null
498
- ] })
499
- }
500
- );
501
- }
502
-
503
- // src/render-section-node.tsx
504
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
505
- function warnSkippedCmsBound(sectionType, isDev) {
506
- if (isDev()) {
507
- console.warn(
508
- `[cms-renderer-next] section \uB178\uB4DC sectionType=${sectionType} \uB294 apiKey \uCEE8\uD14D\uC2A4\uD2B8\uAC00 \uC5C6\uC5B4 \uB80C\uB354 skip`
509
- );
510
- }
511
- }
512
- function renderSectionNode(node, key, context) {
513
- const attrs = node.attrs ?? {};
514
- const input = {
515
- type: typeof attrs.sectionType === "string" ? attrs.sectionType : "",
516
- variant: attrs.variant ?? void 0,
517
- theme: attrs.theme ?? void 0,
518
- props: attrs.props ?? {}
519
- };
520
- const parsed = SectionSchema.safeParse(input);
521
- if (!parsed.success) {
522
- if (context.isDev()) {
523
- console.warn(
524
- `[cms-renderer-next] section \uB178\uB4DC parse \uC2E4\uD328 (sectionType=${input.type}) \u2014 \uB80C\uB354 skip:`,
525
- parsed.error.issues
526
- );
527
- }
528
- return null;
529
- }
530
- const section = parsed.data;
531
- switch (section.type) {
532
- case "hero":
533
- return /* @__PURE__ */ jsx3(TemplateHero, { ...section }, key);
534
- case "rich-text":
535
- return /* @__PURE__ */ jsx3(TemplateRichText, { ...section }, key);
536
- case "services":
537
- return /* @__PURE__ */ jsx3(TemplateServices, { ...section }, key);
538
- case "faq":
539
- return /* @__PURE__ */ jsx3(TemplateFaq, { ...section }, key);
540
- case "cta-banner":
541
- return /* @__PURE__ */ jsx3(TemplateCtaBanner, { ...section }, key);
542
- case "trust":
543
- return /* @__PURE__ */ jsx3(TemplateTrust, { ...section }, key);
544
- case "contact":
545
- if (!context.cms) {
546
- warnSkippedCmsBound(section.type, context.isDev);
547
- return null;
548
- }
549
- return /* @__PURE__ */ jsx3(TemplateContact, { ...section }, key);
550
- case "blog-list": {
551
- if (!context.cms) {
552
- warnSkippedCmsBound(section.type, context.isDev);
553
- return null;
554
- }
555
- const s = section;
556
- const base = s.props.blogBasePath ?? "/blog";
557
- return /* @__PURE__ */ jsx3(
558
- "section",
559
- {
560
- "data-roottale-tpl": "blog-list",
561
- "data-roottale-cms": "list",
562
- id: s.id,
563
- className: "rt-tpl-section rt-tpl-blog-list",
564
- style: sectionThemeStyle(s.theme),
565
- children: /* @__PURE__ */ jsxs3("div", { className: "rt-tpl-container", children: [
566
- s.props.heading ? /* @__PURE__ */ jsx3("h2", { className: "rt-tpl-heading", children: s.props.heading }) : null,
567
- context.renderBlogList({
568
- apiKey: context.cms.apiKey,
569
- baseUrl: context.cms.baseUrl,
570
- limit: s.props.limit,
571
- emptyMessage: s.props.emptyMessage,
572
- postHref: (post) => `${base}/${post.slug}`
573
- })
574
- ] })
575
- },
576
- key
577
- );
578
- }
579
- case "lead-form": {
580
- if (!context.cms) {
581
- warnSkippedCmsBound(section.type, context.isDev);
582
- return null;
583
- }
584
- const s = section;
585
- return /* @__PURE__ */ jsx3(
586
- "section",
587
- {
588
- "data-roottale-tpl": "lead-form",
589
- "data-roottale-cms": "lead-form",
590
- id: s.id,
591
- className: "rt-tpl-section rt-tpl-lead-form",
592
- style: sectionThemeStyle(s.theme),
593
- children: /* @__PURE__ */ jsx3("div", { className: "rt-tpl-container", children: /* @__PURE__ */ jsx3(
594
- RootTaleLeadForm,
595
- {
596
- action: s.props.action,
597
- vertical: s.props.vertical,
598
- heading: s.props.heading,
599
- description: s.props.description,
600
- submitLabel: s.props.submitLabel
601
- }
602
- ) })
603
- },
604
- key
605
- );
606
- }
607
- default:
608
- if (context.isDev()) {
609
- console.warn(
610
- `[cms-renderer-next] section \uB178\uB4DC sectionType=${section.type} \uB294 renderNode \uC704\uC784 \uB300\uC0C1\uC774 \uC544\uB2D8(cms-bound/\uBBF8\uC9C0) \u2014 skip`
611
- );
612
- }
613
- return null;
614
- }
615
- }
616
-
617
- // src/PostCard.tsx
618
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
619
- function firstCategoryName(terms) {
620
- if (!terms) return null;
621
- const cat = terms.find((t) => t.taxonomy === "category");
622
- return cat ? cat.name : null;
623
- }
624
- function RootTalePostCard(props) {
625
- const { post, href = defaultHref, display } = props;
626
- const showDate = display ? display.showDate : true;
627
- const showAuthor = display ? display.showAuthor : false;
628
- const showImage = display?.showImage !== false;
629
- const showCategory = display?.showCategory !== false;
630
- const authorName = post.authorName;
631
- const publishedDate = showDate ? formatPublishedDate(post.publishedAt) : "";
632
- const views = typeof post.viewCount === "number" ? post.viewCount : null;
633
- const imageUrl = showImage ? post.featuredImageUrl : null;
634
- const category = showCategory ? firstCategoryName(post.terms) : null;
635
- return /* @__PURE__ */ jsx4("article", { "data-roottale-cms": "card", className: "rt-cms-card", children: /* @__PURE__ */ jsxs4("a", { className: "rt-cms-card-link", href: href(post), children: [
636
- imageUrl ? (
637
- // eslint-disable-next-line @next/next/no-img-element -- SSR string URL, framework-agnostic
638
- /* @__PURE__ */ jsx4(
639
- "img",
640
- {
641
- className: "rt-cms-card-image",
642
- src: imageUrl,
643
- alt: "",
644
- loading: "lazy",
645
- decoding: "async"
646
- }
647
- )
648
- ) : null,
649
- category ? /* @__PURE__ */ jsx4("span", { className: "rt-cms-card-category", children: category }) : null,
650
- publishedDate || showAuthor && authorName || views !== null ? /* @__PURE__ */ jsxs4("p", { className: "rt-cms-meta", children: [
651
- publishedDate ? /* @__PURE__ */ jsx4("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "date", children: publishedDate }) : null,
652
- showAuthor && authorName ? /* @__PURE__ */ jsxs4("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "author", children: [
653
- "\uC791\uC131\uC790 ",
654
- authorName
655
- ] }) : null,
656
- views !== null ? /* @__PURE__ */ jsxs4("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "views", children: [
657
- "\uC870\uD68C ",
658
- views.toLocaleString("ko-KR")
659
- ] }) : null
660
- ] }) : null,
661
- /* @__PURE__ */ jsx4("h2", { className: "rt-cms-title", children: post.title }),
662
- post.excerpt ? /* @__PURE__ */ jsx4("p", { className: "rt-cms-excerpt", children: post.excerpt }) : null,
663
- /* @__PURE__ */ jsx4("span", { className: "rt-cms-card-action", "aria-hidden": "true", children: "\uC77D\uAE30" })
664
- ] }) });
665
- }
666
- function defaultHref(post) {
667
- return `/blog/${post.slug}`;
668
- }
669
- function formatPublishedDate(iso) {
670
- const d = new Date(iso);
671
- if (Number.isNaN(d.getTime())) return "";
672
- return new Intl.DateTimeFormat("ko-KR", {
673
- year: "numeric",
674
- month: "2-digit",
675
- day: "2-digit"
676
- }).format(d);
677
- }
678
-
679
- // src/TableOfContents.tsx
680
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
681
- function RootTaleTableOfContents(props) {
682
- const { entries, title = "\uBAA9\uCC28" } = props;
683
- if (entries.length === 0) return null;
684
- return /* @__PURE__ */ jsx5("nav", { "data-roottale-cms": "toc", className: "rt-cms-toc", "aria-label": title, children: /* @__PURE__ */ jsxs5("details", { className: "rt-cms-toc-details", open: true, children: [
685
- /* @__PURE__ */ jsxs5("summary", { className: "rt-cms-toc-summary", children: [
686
- title ? /* @__PURE__ */ jsx5("span", { className: "rt-cms-toc-title", children: title }) : null,
687
- /* @__PURE__ */ jsx5("span", { className: "rt-cms-toc-toggle", "aria-hidden": "true" })
688
- ] }),
689
- /* @__PURE__ */ jsx5("ol", { className: "rt-cms-toc-list", children: entries.map((entry) => /* @__PURE__ */ jsx5(
690
- "li",
691
- {
692
- className: `rt-cms-toc-item rt-cms-toc-level-${entry.level}`,
693
- children: /* @__PURE__ */ jsx5("a", { href: `#${entry.id}`, children: entry.text })
694
- },
695
- entry.id
696
- )) })
697
- ] }) });
698
- }
699
-
700
- // src/theme-css-vars.ts
701
- function themeToCssVars(theme) {
702
- if (!theme) return null;
703
- const vars = {};
704
- const c = theme.colors ?? {};
705
- if (c.primary) vars["--rt-color-primary"] = c.primary;
706
- if (c.primaryForeground) vars["--rt-color-primary-foreground"] = c.primaryForeground;
707
- if (c.foreground) vars["--rt-color-foreground"] = c.foreground;
708
- if (c.background) vars["--rt-color-background"] = c.background;
709
- if (c.secondary) vars["--rt-color-secondary"] = c.secondary;
710
- if (c.secondaryForeground) vars["--rt-color-secondary-foreground"] = c.secondaryForeground;
711
- if (c.accent) vars["--rt-color-accent"] = c.accent;
712
- if (c.accentForeground) vars["--rt-color-accent-foreground"] = c.accentForeground;
713
- if (c.muted) vars["--rt-color-muted"] = c.muted;
714
- if (c.mutedForeground) vars["--rt-color-muted-foreground"] = c.mutedForeground;
715
- if (c.destructive) vars["--rt-color-destructive"] = c.destructive;
716
- if (c.destructiveForeground) vars["--rt-color-destructive-foreground"] = c.destructiveForeground;
717
- if (c.border) vars["--rt-color-border"] = c.border;
718
- if (c.input) vars["--rt-color-input"] = c.input;
719
- if (c.ring) vars["--rt-color-ring"] = c.ring;
720
- const f = theme.fonts ?? {};
721
- if (f.body) vars["--rt-font-body"] = f.body;
722
- if (f.display) vars["--rt-font-display"] = f.display;
723
- const r = theme.radius ?? {};
724
- if (r.sm) vars["--rt-radius-sm"] = r.sm;
725
- if (r.md) vars["--rt-radius-md"] = r.md;
726
- if (r.lg) vars["--rt-radius-lg"] = r.lg;
727
- if (r.xl) vars["--rt-radius-xl"] = r.xl;
728
- if (Object.keys(vars).length === 0) return null;
729
- return vars;
730
- }
731
-
732
- // src/toc.ts
733
- function tocLevel(rawLevel) {
734
- if (rawLevel < 1 || rawLevel > 4) return null;
735
- if (rawLevel < 3) return 2;
736
- return rawLevel === 3 ? 3 : 4;
737
- }
738
- function headingToId(text) {
739
- return text.trim().toLowerCase().replace(/[^\p{L}\p{N}\s-]/gu, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
740
- }
741
- function textOf(node) {
742
- if (typeof node.text === "string") return node.text;
743
- if (!Array.isArray(node.content)) return "";
744
- return node.content.map(textOf).join("");
745
- }
746
- function extractToc(doc) {
747
- const root = doc;
748
- const content = Array.isArray(root.content) ? root.content : [];
749
- const entries = [];
750
- const idCounts = /* @__PURE__ */ new Map();
751
- for (const node of content) {
752
- if (node?.type !== "heading") continue;
753
- const rawLevel = Number(node.attrs?.level ?? 2);
754
- const level = tocLevel(rawLevel);
755
- if (level === null) continue;
756
- const text = textOf(node).trim();
757
- if (!text) continue;
758
- const base = headingToId(text) || "heading";
759
- const count = idCounts.get(base) ?? 0;
760
- const id = count === 0 ? base : `${base}-${count}`;
761
- idCounts.set(base, count + 1);
762
- entries.push({ level, text, id });
763
- }
764
- return entries;
765
- }
766
- function attachHeadingIds(doc, entries) {
767
- const root = doc;
768
- const content = Array.isArray(root.content) ? root.content : [];
769
- let cursor = 0;
770
- const nextContent = content.map((node) => {
771
- if (node?.type !== "heading") return node;
772
- const rawLevel = Number(node.attrs?.level ?? 2);
773
- if (rawLevel < 1 || rawLevel > 4) return node;
774
- if (!textOf(node).trim()) return node;
775
- const entry = entries[cursor++];
776
- if (!entry) return node;
777
- return {
778
- ...node,
779
- attrs: { ...node.attrs ?? {}, id: entry.id }
780
- };
781
- });
782
- return { ...root, content: nextContent };
783
- }
784
-
785
- // src/FloatingCta.tsx
786
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
787
- function RootTaleFloatingCta(props) {
788
- const { buttons, position = "bottom-right" } = props;
789
- if (!buttons || buttons.length === 0) return null;
790
- return /* @__PURE__ */ jsx6(
791
- "div",
792
- {
793
- "data-roottale-cms": "floating-cta",
794
- className: `rt-cms-floating-cta rt-cms-floating-cta--${position}`,
795
- children: buttons.map((btn, idx) => {
796
- const isExternal = btn.type === "kakao" || btn.type === "custom";
797
- return /* @__PURE__ */ jsxs6(
798
- "a",
799
- {
800
- href: btn.href,
801
- className: `rt-cms-floating-cta__btn rt-cms-floating-cta__btn--${btn.type}`,
802
- target: isExternal ? "_blank" : void 0,
803
- rel: isExternal ? "noopener noreferrer" : void 0,
804
- children: [
805
- /* @__PURE__ */ jsx6("span", { "aria-hidden": "true", className: "rt-cms-floating-cta__icon", children: btn.icon ?? defaultIcon(btn.type) }),
806
- /* @__PURE__ */ jsx6("span", { className: "rt-cms-floating-cta__label", children: btn.label })
807
- ]
808
- },
809
- `${btn.type}-${idx}`
810
- );
811
- })
812
- }
813
- );
814
- }
815
- function defaultIcon(type) {
816
- switch (type) {
817
- case "phone":
818
- return "\u260E";
819
- case "contact":
820
- return "\u2709";
821
- case "kakao":
822
- return "\u{1F4AC}";
823
- case "custom":
824
- return "\u2192";
825
- }
826
- }
827
-
828
- // src/block-to-react.tsx
829
- import {
830
- applyBlockBindings,
831
- createFieldBindingResolver,
832
- sanitizeHtml
833
- } from "@roottale/cms-core";
834
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
835
- function isString(value) {
836
- return typeof value === "string";
837
- }
838
- function htmlContent(html) {
839
- return { __html: sanitizeHtml(html) };
840
- }
841
- function renderInner(blocks) {
842
- return blocks.map((b, i) => renderBlock(b, i));
843
- }
844
- function renderBlock(block, key = 0) {
845
- const dataBlockId = block._id;
846
- switch (block.name) {
847
- case "core/paragraph": {
848
- const text = isString(block.attributes.content) ? block.attributes.content : block.rawHtml ?? "";
849
- return /* @__PURE__ */ jsx7(
850
- "p",
851
- {
852
- "data-block-id": dataBlockId,
853
- dangerouslySetInnerHTML: htmlContent(text)
854
- },
855
- key
856
- );
857
- }
858
- case "core/heading": {
859
- const levelRaw = block.attributes.level;
860
- const level = typeof levelRaw === "number" && levelRaw >= 2 && levelRaw <= 4 ? levelRaw : 2;
861
- const text = isString(block.attributes.content) ? block.attributes.content : block.rawHtml ?? "";
862
- const props = {
863
- "data-block-id": dataBlockId,
864
- dangerouslySetInnerHTML: htmlContent(text)
865
- };
866
- if (level === 2) return /* @__PURE__ */ jsx7("h2", { ...props }, key);
867
- if (level === 3) return /* @__PURE__ */ jsx7("h3", { ...props }, key);
868
- return /* @__PURE__ */ jsx7("h4", { ...props }, key);
869
- }
870
- case "core/image": {
871
- const src = isString(block.attributes.url) ? block.attributes.url : "";
872
- const alt = isString(block.attributes.alt) ? block.attributes.alt : "";
873
- const caption = isString(block.attributes.caption) ? block.attributes.caption : null;
874
- return /* @__PURE__ */ jsxs7("figure", { "data-block-id": dataBlockId, children: [
875
- /* @__PURE__ */ jsx7("img", { src, alt, loading: "lazy" }),
876
- caption && /* @__PURE__ */ jsx7("figcaption", { children: caption })
877
- ] }, key);
878
- }
879
- case "core/list": {
880
- const ordered = block.attributes.ordered === true;
881
- const items = (block.innerBlocks ?? []).map(
882
- (item, i) => item.rawHtml ? /* @__PURE__ */ jsx7(
883
- "li",
884
- {
885
- dangerouslySetInnerHTML: htmlContent(item.rawHtml)
886
- },
887
- i
888
- ) : /* @__PURE__ */ jsx7("li", { children: renderInner(item.innerBlocks ?? []) }, i)
889
- );
890
- return ordered ? /* @__PURE__ */ jsx7("ol", { "data-block-id": dataBlockId, children: items }, key) : /* @__PURE__ */ jsx7("ul", { "data-block-id": dataBlockId, children: items }, key);
891
- }
892
- case "core/quote": {
893
- const inner = renderInner(block.innerBlocks ?? []);
894
- const citation = isString(block.attributes.citation) ? block.attributes.citation : null;
895
- return /* @__PURE__ */ jsxs7("blockquote", { "data-block-id": dataBlockId, children: [
896
- inner,
897
- citation && /* @__PURE__ */ jsx7("cite", { children: citation })
898
- ] }, key);
899
- }
900
- case "core/code": {
901
- const code = isString(block.attributes.content) ? block.attributes.content : block.rawHtml ?? "";
902
- const lang = isString(block.attributes.language) ? block.attributes.language : void 0;
903
- return /* @__PURE__ */ jsx7(
904
- "pre",
905
- {
906
- "data-block-id": dataBlockId,
907
- "data-language": lang,
908
- children: /* @__PURE__ */ jsx7("code", { children: code })
909
- },
910
- key
911
- );
912
- }
913
- case "core/columns": {
914
- return /* @__PURE__ */ jsx7(
915
- "div",
916
- {
917
- className: "rt-columns",
918
- "data-block-id": dataBlockId,
919
- children: renderInner(block.innerBlocks ?? [])
920
- },
921
- key
922
- );
923
- }
924
- case "core/separator":
925
- return /* @__PURE__ */ jsx7("hr", { "data-block-id": dataBlockId }, key);
926
- case "core/spacer": {
927
- const heightRaw = block.attributes.height;
928
- const height = isString(heightRaw) ? heightRaw : "32px";
929
- return /* @__PURE__ */ jsx7(
930
- "div",
931
- {
932
- className: "rt-spacer",
933
- "data-block-id": dataBlockId,
934
- style: { height }
935
- },
936
- key
937
- );
938
- }
939
- case "core/group": {
940
- return /* @__PURE__ */ jsx7(
941
- "div",
942
- {
943
- className: "rt-group",
944
- "data-block-id": dataBlockId,
945
- children: renderInner(block.innerBlocks ?? [])
946
- },
947
- key
948
- );
949
- }
950
- default: {
951
- const rawHtml = block.rawHtml;
952
- return /* @__PURE__ */ jsx7(
953
- "div",
954
- {
955
- className: "rt-unknown-block",
956
- "data-block-id": dataBlockId,
957
- "data-block-name": block.name,
958
- "data-rawhtml-suppressed": rawHtml ? "true" : void 0,
959
- children: renderInner(block.innerBlocks ?? [])
960
- },
961
- key
962
- );
963
- }
964
- }
965
- }
966
- function renderBlocks(blocks) {
967
- return blocks.map((b, i) => renderBlock(b, i));
968
- }
969
- function renderBoundBlocks(blocks, opts = {}) {
970
- const resolver = opts.resolver ?? createFieldBindingResolver(opts.fields);
971
- return renderBlocks(applyBlockBindings(blocks, resolver));
972
- }
973
-
974
- // src/server.tsx
975
- import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
976
- function authorImageRadiusCss(radius) {
977
- if (radius === "circle") return "999px";
978
- if (radius === "rounded") return "0.875rem";
979
- return "0";
980
- }
981
- function RootTaleThemeProvider(props) {
982
- const style = themeToCssVars(props.theme ?? null);
983
- if (!style) return /* @__PURE__ */ jsx8(Fragment3, { children: props.children });
984
- return /* @__PURE__ */ jsx8("div", { "data-roottale-cms": "theme-root", "data-rt-theme": "", style, children: props.children });
985
- }
986
- async function RootTaleBlogList(props) {
987
- const {
988
- apiKey,
989
- baseUrl,
990
- limit,
991
- type = "post",
992
- collection,
993
- collections,
994
- emptyMessage = "\uC544\uC9C1 \uBC1C\uD589\uB41C \uAE00\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
995
- showCategoryFilter = false,
996
- activeCategory,
997
- categoryHref = defaultCategoryHref,
998
- allCategoriesLabel = "\uC804\uCCB4",
999
- author,
1000
- theme: themeProp
1001
- } = props;
1002
- const postHref = props.postHref ?? (collections ? makeCollectionPostHref(collections) : defaultPostHref);
1003
- const [page, themeStyle, blogSettings] = await Promise.all([
1004
- fetchPosts({ apiKey, baseUrl, limit, type, ...author ? { author } : {} }),
1005
- resolveThemeStyle({ themeProp, apiKey, baseUrl }),
1006
- fetchBlogSettings({ apiKey, baseUrl }).catch(() => DEFAULT_BLOG_SETTINGS)
1007
- ]);
1008
- const items = collection && collections ? postsForCollection(page.items, collections, collection) : page.items;
1009
- if (items.length === 0) {
1010
- return /* @__PURE__ */ jsx8("div", { "data-roottale-cms": "list", style: themeStyle ?? void 0, children: /* @__PURE__ */ jsx8("p", { className: "rt-cms-empty", children: emptyMessage }) });
1011
- }
1012
- const categories = showCategoryFilter ? collectCategories(items) : [];
1013
- const visiblePosts = showCategoryFilter ? filterPostsByCategory(items, activeCategory) : items;
1014
- return /* @__PURE__ */ jsxs8("div", { "data-roottale-cms": "list", style: themeStyle ?? void 0, children: [
1015
- showCategoryFilter && categories.length > 0 ? /* @__PURE__ */ jsxs8("nav", { className: "rt-cms-filter", "aria-label": "\uCE74\uD14C\uACE0\uB9AC \uD544\uD130", children: [
1016
- /* @__PURE__ */ jsx8(
1017
- "a",
1018
- {
1019
- className: "rt-cms-filter-chip",
1020
- href: categoryHref(null),
1021
- "data-active": !activeCategory ? "" : void 0,
1022
- "aria-current": !activeCategory ? "true" : void 0,
1023
- children: allCategoriesLabel
1024
- }
1025
- ),
1026
- categories.map((c) => /* @__PURE__ */ jsx8(
1027
- "a",
1028
- {
1029
- className: "rt-cms-filter-chip",
1030
- href: categoryHref(c.slug),
1031
- "data-active": activeCategory === c.slug ? "" : void 0,
1032
- "aria-current": activeCategory === c.slug ? "true" : void 0,
1033
- children: c.name
1034
- },
1035
- c.slug
1036
- ))
1037
- ] }) : null,
1038
- visiblePosts.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "rt-cms-empty", children: emptyMessage }) : /* @__PURE__ */ jsx8("ul", { className: "rt-cms-list", children: visiblePosts.map((post) => /* @__PURE__ */ jsx8("li", { className: "rt-cms-list-item", children: /* @__PURE__ */ jsx8(
1039
- RootTalePostCard,
1040
- {
1041
- post,
1042
- href: postHref,
1043
- display: resolvePostDisplay(post, blogSettings)
1044
- }
1045
- ) }, post.id)) })
1046
- ] });
1047
- }
1048
- async function RootTaleBlogCategories(props) {
1049
- const {
1050
- apiKey,
1051
- baseUrl,
1052
- limit,
1053
- collection,
1054
- collections,
1055
- categoryHref = (slug) => defaultCategoryHref(slug),
1056
- emptyMessage = "\uC544\uC9C1 \uCE74\uD14C\uACE0\uB9AC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
1057
- theme: themeProp
1058
- } = props;
1059
- const [page, themeStyle] = await Promise.all([
1060
- fetchPosts({ apiKey, baseUrl, limit, type: "post" }),
1061
- resolveThemeStyle({ themeProp, apiKey, baseUrl })
1062
- ]);
1063
- const categories = collection && collections ? collectCollectionCategories(page.items, collections, collection) : collectCategoriesWithCounts(page.items);
1064
- return /* @__PURE__ */ jsx8(
1065
- "nav",
1066
- {
1067
- "data-roottale-cms": "categories",
1068
- className: "rt-cms-categories",
1069
- "aria-label": "\uBE14\uB85C\uADF8 \uCE74\uD14C\uACE0\uB9AC",
1070
- style: themeStyle ?? void 0,
1071
- children: categories.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "rt-cms-empty", children: emptyMessage }) : /* @__PURE__ */ jsx8("ul", { className: "rt-cms-category-list", children: categories.map((category) => /* @__PURE__ */ jsx8("li", { className: "rt-cms-category-list-item", children: /* @__PURE__ */ jsxs8(
1072
- "a",
1073
- {
1074
- className: "rt-cms-category-link",
1075
- href: categoryHref(category.slug),
1076
- children: [
1077
- /* @__PURE__ */ jsx8("span", { className: "rt-cms-category-name", children: category.name }),
1078
- /* @__PURE__ */ jsx8("span", { className: "rt-cms-category-count", children: category.count })
1079
- ]
1080
- }
1081
- ) }, category.slug)) })
1082
- }
1083
- );
1084
- }
1085
- async function RootTaleBlogPost(props) {
1086
- const {
1087
- apiKey,
1088
- slugOrId,
1089
- baseUrl,
1090
- notFoundElement,
1091
- showTableOfContents,
1092
- tableOfContentsTitle,
1093
- relatedPostsCount = 0,
1094
- relatedPostsTitle = "\uAD00\uB828 \uAE00",
1095
- collections,
1096
- theme: themeProp
1097
- } = props;
1098
- const [post, themeStyle, blogSettings] = await Promise.all([
1099
- fetchPost({ apiKey, slugOrId, baseUrl }),
1100
- resolveThemeStyle({ themeProp, apiKey, baseUrl }),
1101
- // 사이트 기본 표시 설정 — 실패해도 렌더는 진행 (안전 기본값).
1102
- fetchBlogSettings({ apiKey, baseUrl }).catch(() => DEFAULT_BLOG_SETTINGS)
1103
- ]);
1104
- if (!post) {
1105
- return notFoundElement ?? /* @__PURE__ */ jsx8("div", { "data-roottale-cms": "post-missing", style: themeStyle ?? void 0, children: /* @__PURE__ */ jsx8("p", { className: "rt-cms-empty", children: "\uAE00\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4." }) });
1106
- }
1107
- const display = resolvePostDisplay(post, blogSettings, {
1108
- showTableOfContents,
1109
- tableOfContentsTitle
1110
- });
1111
- const toc = display.showTableOfContents ? extractToc(post.bodyJson) : [];
1112
- const renderDoc = toc.length > 0 ? attachHeadingIds(post.bodyJson, toc) : post.bodyJson;
1113
- let related = [];
1114
- if (relatedPostsCount > 0) {
1115
- try {
1116
- const candidates = await fetchPosts({
1117
- apiKey,
1118
- baseUrl,
1119
- type: "post",
1120
- limit: 30
1121
- });
1122
- related = selectRelatedPosts(post, candidates.items, relatedPostsCount);
1123
- } catch {
1124
- }
1125
- }
1126
- const relatedHref = props.postHref ?? (collections ? makeCollectionPostHref(collections) : defaultPostHref);
1127
- const authorName = post.authorName;
1128
- const authorImageUrl = post.authorImageUrl;
1129
- const postAuthorBio = post.authorBio;
1130
- const views = typeof post.viewCount === "number" ? post.viewCount : null;
1131
- const publishedDate = display.showDate ? formatPublishedDate2(post.publishedAt) : "";
1132
- const showTopAuthor = display.showAuthor && Boolean(authorName);
1133
- const displayAuthorName = authorName ?? display.authorProfileName;
1134
- const authorBio = postAuthorBio ?? display.authorProfileBio ?? display.authorCardDescription;
1135
- const authorImageUrlForCard = authorImageUrl ?? display.authorProfileImageUrl;
1136
- const authorImageAlt = `${displayAuthorName ?? ""} \uD504\uB85C\uD544 \uC0AC\uC9C4`.trim();
1137
- const authorImageStyle = {
1138
- borderRadius: authorImageRadiusCss(display.authorProfileImageRadius),
1139
- objectPosition: `${display.authorProfileImagePositionX}% ${display.authorProfileImagePositionY}%`
1140
- };
1141
- const showAuthorCard = display.showAuthorCard && Boolean(displayAuthorName);
1142
- return /* @__PURE__ */ jsxs8(
1143
- "article",
1144
- {
1145
- "data-roottale-cms": "post",
1146
- className: "rt-cms-article",
1147
- style: themeStyle ?? void 0,
1148
- children: [
1149
- /* @__PURE__ */ jsxs8("header", { className: "rt-cms-post-header", children: [
1150
- publishedDate || showTopAuthor || views !== null ? /* @__PURE__ */ jsxs8("p", { className: "rt-cms-meta", children: [
1151
- publishedDate ? /* @__PURE__ */ jsx8("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "date", children: publishedDate }) : null,
1152
- showTopAuthor ? /* @__PURE__ */ jsxs8("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "author", children: [
1153
- "\uC791\uC131\uC790 ",
1154
- authorName
1155
- ] }) : null,
1156
- views !== null ? /* @__PURE__ */ jsxs8("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "views", children: [
1157
- "\uC870\uD68C ",
1158
- views.toLocaleString("ko-KR")
1159
- ] }) : null
1160
- ] }) : null,
1161
- /* @__PURE__ */ jsx8("h1", { className: "rt-cms-title", children: post.title }),
1162
- post.excerpt ? /* @__PURE__ */ jsx8("p", { className: "rt-cms-excerpt", children: post.excerpt }) : null
1163
- ] }),
1164
- renderArchiveRelated(post.archiveRelated, collections),
1165
- (() => {
1166
- const tocEl = toc.length > 0 ? /* @__PURE__ */ jsx8(RootTaleTableOfContents, { entries: toc, title: display.tocTitle }) : null;
1167
- const bodyEl = /* @__PURE__ */ jsx8("div", { "data-roottale-cms": "body", className: "rt-cms-body", children: /* @__PURE__ */ jsx8(
1168
- RenderTiptap,
1169
- {
1170
- doc: renderDoc,
1171
- fields: post.fields,
1172
- apiKey,
1173
- baseUrl
1174
- }
1175
- ) });
1176
- if (display.tocPosition === "sidebar" && tocEl) {
1177
- return /* @__PURE__ */ jsxs8("div", { className: "rt-cms-layout rt-cms-layout--toc-side", children: [
1178
- bodyEl,
1179
- /* @__PURE__ */ jsx8("aside", { className: "rt-cms-toc-side", children: tocEl })
1180
- ] });
1181
- }
1182
- return /* @__PURE__ */ jsxs8(Fragment3, { children: [
1183
- tocEl,
1184
- bodyEl
1185
- ] });
1186
- })(),
1187
- showAuthorCard && displayAuthorName ? /* @__PURE__ */ jsxs8("section", { className: "rt-cms-author-card", "aria-label": "\uC791\uC131\uC790", children: [
1188
- authorImageUrlForCard ? /* @__PURE__ */ jsx8(
1189
- "img",
1190
- {
1191
- className: "rt-cms-author-card__image",
1192
- src: authorImageUrlForCard,
1193
- alt: authorImageAlt,
1194
- loading: "lazy",
1195
- style: authorImageStyle
1196
- }
1197
- ) : /* @__PURE__ */ jsx8("div", { className: "rt-cms-author-card__avatar", "aria-hidden": "true", children: authorInitials(displayAuthorName) }),
1198
- /* @__PURE__ */ jsxs8("div", { className: "rt-cms-author-card__body", children: [
1199
- /* @__PURE__ */ jsx8("p", { className: "rt-cms-author-card__eyebrow", children: display.authorCardEyebrow }),
1200
- /* @__PURE__ */ jsx8("p", { className: "rt-cms-author-card__name", children: displayAuthorName }),
1201
- authorBio ? /* @__PURE__ */ jsx8("p", { className: "rt-cms-author-card__description", children: authorBio }) : null
1202
- ] })
1203
- ] }) : null,
1204
- renderRelated(related, relatedHref, relatedPostsTitle),
1205
- renderPostCta(blogSettings.postCta),
1206
- renderFaqJsonLd(post.bodyJson)
1207
- ]
1208
- }
1209
- );
1210
- }
1211
- function renderArchiveRelated(groups, collections) {
1212
- const visible = groups.filter((group) => group.items.length > 0);
1213
- if (visible.length === 0) return null;
1214
- return /* @__PURE__ */ jsx8("aside", { className: "rt-archive-related", "aria-label": "\uC5F0\uAD00 \uC815\uBCF4", children: visible.map((group) => /* @__PURE__ */ jsxs8("section", { className: "rt-archive-related__group", children: [
1215
- /* @__PURE__ */ jsx8("h2", { className: "rt-archive-related__title", children: archiveGroupTitle(group) }),
1216
- /* @__PURE__ */ jsx8("ul", { className: "rt-archive-related__list", children: group.items.map((item) => /* @__PURE__ */ jsx8("li", { className: "rt-archive-related__item", children: /* @__PURE__ */ jsxs8(
1217
- "a",
1218
- {
1219
- className: "rt-archive-related__link",
1220
- href: archivePostHref(item.collectionKey, item.slug, collections),
1221
- children: [
1222
- /* @__PURE__ */ jsx8("span", { className: "rt-archive-related__item-title", children: item.title }),
1223
- item.excerpt ? /* @__PURE__ */ jsx8("span", { className: "rt-archive-related__item-excerpt", children: item.excerpt }) : null
1224
- ]
1225
- }
1226
- ) }, item.id)) })
1227
- ] }, group.collectionKey)) });
1228
- }
1229
- function archiveGroupTitle(group) {
1230
- if (group.collectionKey === "conditions") {
1231
- return `\uC774 \uC99D\uC0C1\uACFC \uAD00\uB828\uB41C \uC9C8\uD658 ${group.items.length}`;
1232
- }
1233
- if (group.collectionKey === "treatments") {
1234
- return `\uAD00\uB828 \uCE58\uB8CC\uBC95 ${group.items.length}`;
1235
- }
1236
- if (group.collectionKey === "symptoms") {
1237
- return `\uAD00\uB828 \uC99D\uC0C1 ${group.items.length}`;
1238
- }
1239
- return `${group.label} ${group.items.length}`;
1240
- }
1241
- function archivePostHref(collectionKey, slug, collections) {
1242
- const collection = collections?.find((item) => item.key === collectionKey);
1243
- const basePath = collection?.basePath ?? defaultArchiveBasePath(collectionKey);
1244
- return `${basePath.replace(/\/+$/, "")}/${slug}`;
1245
- }
1246
- function defaultArchiveBasePath(collectionKey) {
1247
- if (collectionKey === "symptoms") return "/symptoms";
1248
- if (collectionKey === "conditions") return "/conditions";
1249
- if (collectionKey === "treatments") return "/treatments";
1250
- return "/blog";
1251
- }
1252
- function renderPostCta(cta) {
1253
- if (!cta) return null;
1254
- const href = cta.buttonHref.trim();
1255
- const safe = href.startsWith("/") || href.startsWith("#") || /^(https?:|mailto:|tel:)/i.test(href);
1256
- if (!safe) return null;
1257
- const external = /^https?:/i.test(href);
1258
- return /* @__PURE__ */ jsxs8("aside", { "data-roottale-cms": "post-cta", className: "rt-cms-post-cta", children: [
1259
- cta.title ? /* @__PURE__ */ jsx8("p", { className: "rt-cms-post-cta__title", children: cta.title }) : null,
1260
- cta.description ? /* @__PURE__ */ jsx8("p", { className: "rt-cms-post-cta__desc", children: cta.description }) : null,
1261
- /* @__PURE__ */ jsx8(
1262
- "a",
1263
- {
1264
- className: "rt-cms-post-cta__btn",
1265
- href,
1266
- target: external ? "_blank" : void 0,
1267
- rel: external ? "noopener noreferrer" : void 0,
1268
- children: cta.buttonLabel
1269
- }
1270
- )
1271
- ] });
1272
- }
1273
- function renderRelated(posts, href, title) {
1274
- if (posts.length === 0) return null;
1275
- return /* @__PURE__ */ jsxs8("nav", { "data-roottale-cms": "related", className: "rt-cms-related", "aria-label": title, children: [
1276
- /* @__PURE__ */ jsx8("h2", { className: "rt-cms-related-title", children: title }),
1277
- /* @__PURE__ */ jsx8("ul", { className: "rt-cms-related-list", children: posts.map((p) => /* @__PURE__ */ jsx8("li", { className: "rt-cms-related-item", children: /* @__PURE__ */ jsxs8("a", { className: "rt-cms-related-link", href: href(p), children: [
1278
- p.featuredImageUrl ? /* @__PURE__ */ jsx8(
1279
- "img",
1280
- {
1281
- className: "rt-cms-related-thumb",
1282
- src: p.featuredImageUrl,
1283
- alt: "",
1284
- loading: "lazy"
1285
- }
1286
- ) : null,
1287
- /* @__PURE__ */ jsx8("span", { className: "rt-cms-related-post-title", children: p.title })
1288
- ] }) }, p.id)) })
1289
- ] });
1290
- }
1291
- function renderFaqJsonLd(doc) {
1292
- const ld = faqPageJsonLd(extractFaqEntries(doc));
1293
- if (!ld) return null;
1294
- const json = JSON.stringify(ld).replace(/</g, "\\u003c");
1295
- return /* @__PURE__ */ jsx8(
1296
- "script",
1297
- {
1298
- type: "application/ld+json",
1299
- dangerouslySetInnerHTML: { __html: json }
1300
- }
1301
- );
1302
- }
1303
- function RootTaleFaqJsonLd({
1304
- doc
1305
- }) {
1306
- return renderFaqJsonLd(doc);
1307
- }
1308
- async function RootTalePage(props) {
1309
- const {
1310
- apiKey,
1311
- slugOrId,
1312
- baseUrl,
1313
- notFoundElement,
1314
- showTitle = true,
1315
- theme: themeProp
1316
- } = props;
1317
- const [post, themeStyle] = await Promise.all([
1318
- fetchPost({ apiKey, slugOrId, baseUrl }),
1319
- resolveThemeStyle({ themeProp, apiKey, baseUrl })
1320
- ]);
1321
- if (!post) {
1322
- return notFoundElement ?? /* @__PURE__ */ jsx8("div", { "data-roottale-cms": "page-missing", style: themeStyle ?? void 0, children: /* @__PURE__ */ jsx8("p", { className: "rt-cms-empty", children: "\uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4." }) });
1323
- }
1324
- return /* @__PURE__ */ jsxs8(
1325
- "article",
1326
- {
1327
- "data-roottale-cms": "page",
1328
- className: "rt-cms-article",
1329
- style: themeStyle ?? void 0,
1330
- children: [
1331
- showTitle ? /* @__PURE__ */ jsx8("header", { className: "rt-cms-post-header", children: /* @__PURE__ */ jsx8("h1", { className: "rt-cms-title", children: post.title }) }) : null,
1332
- /* @__PURE__ */ jsx8("div", { "data-roottale-cms": "body", className: "rt-cms-body", children: /* @__PURE__ */ jsx8(
1333
- RenderTiptap,
1334
- {
1335
- doc: post.bodyJson,
1336
- fields: post.fields,
1337
- apiKey,
1338
- baseUrl
1339
- }
1340
- ) })
1341
- ]
1342
- }
1343
- );
1344
- }
1345
- function authorInitials(name) {
1346
- const trimmed = name.trim();
1347
- if (!trimmed) return "";
1348
- const parts = trimmed.split(/\s+/).filter(Boolean);
1349
- if (parts.length >= 2) {
1350
- return `${parts[0]?.[0] ?? ""}${parts[1]?.[0] ?? ""}`.toUpperCase();
1351
- }
1352
- return [...trimmed].slice(0, 2).join("").toUpperCase();
1353
- }
1354
- async function resolveThemeStyle(input) {
1355
- const { themeProp, apiKey, baseUrl } = input;
1356
- if (themeProp === null) return null;
1357
- if (themeProp !== void 0) return themeToCssVars(themeProp);
1358
- try {
1359
- const fetched = await fetchTheme({ apiKey, baseUrl });
1360
- return themeToCssVars(fetched);
1361
- } catch {
1362
- return null;
1363
- }
1364
- }
1365
- function defaultPostHref(post) {
1366
- return `/blog/${post.slug}`;
1367
- }
1368
- function makeCollectionPostHref(collections) {
1369
- return (post) => resolvePostPath(post, collections) ?? defaultPostHref(post);
1370
- }
1371
- function formatPublishedDate2(iso) {
1372
- const d = new Date(iso);
1373
- if (Number.isNaN(d.getTime())) return "";
1374
- return new Intl.DateTimeFormat("ko-KR", {
1375
- year: "numeric",
1376
- month: "2-digit",
1377
- day: "2-digit"
1378
- }).format(d);
1379
- }
1380
- function RenderTiptap({
1381
- doc,
1382
- fields,
1383
- apiKey,
1384
- baseUrl
1385
- }) {
1386
- const rawContent = doc.content;
1387
- const content = Array.isArray(rawContent) ? rawContent : [];
1388
- const hasToc = content.some((n) => n?.type === "tableOfContents");
1389
- const docRecord = doc;
1390
- const entries = hasToc ? extractToc(docRecord) : [];
1391
- const renderDoc = hasToc && entries.length > 0 ? attachHeadingIds(docRecord, entries) : docRecord;
1392
- const nodes = Array.isArray(renderDoc.content) ? renderDoc.content : content;
1393
- const cms = apiKey ? { apiKey, baseUrl } : null;
1394
- const context = {
1395
- fields: fields ?? null,
1396
- section: {
1397
- cms,
1398
- isDev: isDevEnv,
1399
- renderBlogList: (props) => /* @__PURE__ */ jsx8(RootTaleBlogList, { ...props })
1400
- }
1401
- };
1402
- return /* @__PURE__ */ jsx8(Fragment3, { children: nodes.map(
1403
- (node, i) => node?.type === "tableOfContents" ? /* @__PURE__ */ jsx8(
1404
- RootTaleTableOfContents,
1405
- {
1406
- entries,
1407
- title: typeof node.attrs?.title === "string" ? node.attrs.title : "\uBAA9\uCC28"
1408
- },
1409
- i
1410
- ) : renderNode(node, i, context)
1411
- ) });
1412
- }
1413
- function boundContentText(node, fields) {
1414
- return bindingTextValue(
1415
- boundFieldValue(node.attrs?.bindings, "content", fields)
1416
- );
1417
- }
1418
- function isSafeHref(value) {
1419
- if (typeof value !== "string") return false;
1420
- const v = value.trim();
1421
- if (v.length === 0) return false;
1422
- if (v.startsWith("/") || v.startsWith("#") || v.startsWith("?")) return true;
1423
- return /^(https?:|mailto:|tel:)/i.test(v);
1424
- }
1425
- function alignStyle(node) {
1426
- const align = node.attrs?.textAlign;
1427
- if (typeof align !== "string" || align === "" || align === "left") return void 0;
1428
- if (align === "center" || align === "right" || align === "justify") {
1429
- return { textAlign: align };
1430
- }
1431
- return void 0;
1432
- }
1433
- function tableCellSpans(node) {
1434
- const colspan = Number(node.attrs?.colspan);
1435
- const rowspan = Number(node.attrs?.rowspan);
1436
- return {
1437
- colSpan: Number.isFinite(colspan) && colspan > 1 ? colspan : void 0,
1438
- rowSpan: Number.isFinite(rowspan) && rowspan > 1 ? rowspan : void 0
1439
- };
1440
- }
1441
- function isDevEnv() {
1442
- const env = globalThis.process?.env ?? {};
1443
- return env.NODE_ENV !== "production";
1444
- }
1445
- function renderNode(node, key, context = {
1446
- fields: null,
1447
- section: {
1448
- cms: null,
1449
- isDev: isDevEnv,
1450
- renderBlogList: (props) => /* @__PURE__ */ jsx8(RootTaleBlogList, { ...props })
1451
- }
1452
- }) {
1453
- if (!node || typeof node !== "object") return null;
1454
- const children = Array.isArray(node.content) ? node.content.map((child, i) => renderNode(child, i, context)) : void 0;
1455
- switch (node.type) {
1456
- case "paragraph": {
1457
- const bound = boundContentText(node, context.fields);
1458
- return /* @__PURE__ */ jsx8("p", { style: alignStyle(node), children: bound ?? children }, key);
1459
- }
1460
- case "heading": {
1461
- const rawLevel = Number(node.attrs?.level ?? 2);
1462
- const level = Math.min(Math.max(Number.isFinite(rawLevel) ? rawLevel : 2, 2), 4);
1463
- const idAttr = node.attrs?.id;
1464
- const id = typeof idAttr === "string" && idAttr.length > 0 ? idAttr : void 0;
1465
- const style = alignStyle(node);
1466
- const inner = boundContentText(node, context.fields) ?? children;
1467
- if (level === 2) return /* @__PURE__ */ jsx8("h2", { id, style, children: inner }, key);
1468
- if (level === 3) return /* @__PURE__ */ jsx8("h3", { id, style, children: inner }, key);
1469
- return /* @__PURE__ */ jsx8("h4", { id, style, children: inner }, key);
1470
- }
1471
- case "bulletList":
1472
- return /* @__PURE__ */ jsx8("ul", { children }, key);
1473
- case "orderedList":
1474
- return /* @__PURE__ */ jsx8("ol", { children }, key);
1475
- case "listItem":
1476
- return /* @__PURE__ */ jsx8("li", { children }, key);
1477
- case "blockquote":
1478
- return /* @__PURE__ */ jsx8("blockquote", { children }, key);
1479
- case "codeBlock":
1480
- return /* @__PURE__ */ jsx8("pre", { children: /* @__PURE__ */ jsx8("code", { children }) }, key);
1481
- case "horizontalRule":
1482
- return /* @__PURE__ */ jsx8("hr", {}, key);
1483
- case "hardBreak":
1484
- return /* @__PURE__ */ jsx8("br", {}, key);
1485
- case "image": {
1486
- const boundSrc = bindingSrcValue(
1487
- boundFieldValue(node.attrs?.bindings, "src", context.fields)
1488
- );
1489
- const src = boundSrc ?? node.attrs?.src;
1490
- if (typeof src !== "string" || src.length === 0) return null;
1491
- const alt = typeof node.attrs?.alt === "string" ? node.attrs.alt : "";
1492
- const title = typeof node.attrs?.title === "string" ? node.attrs.title : void 0;
1493
- const width = typeof node.attrs?.width === "number" && node.attrs.width > 0 ? node.attrs.width : void 0;
1494
- const height = typeof node.attrs?.height === "number" && node.attrs.height > 0 ? node.attrs.height : void 0;
1495
- return /* @__PURE__ */ jsx8(
1496
- "img",
1497
- {
1498
- src,
1499
- alt,
1500
- title,
1501
- width,
1502
- height,
1503
- loading: "lazy"
1504
- },
1505
- key
1506
- );
1507
- }
1508
- case "columns":
1509
- return /* @__PURE__ */ jsx8("div", { className: "rt-columns", children }, key);
1510
- case "column":
1511
- return /* @__PURE__ */ jsx8("div", { className: "rt-column", children }, key);
1512
- case "table":
1513
- return /* @__PURE__ */ jsx8("div", { className: "rt-table-wrap", children: /* @__PURE__ */ jsx8("table", { className: "rt-table", children: /* @__PURE__ */ jsx8("tbody", { children }) }) }, key);
1514
- case "tableRow":
1515
- return /* @__PURE__ */ jsx8("tr", { children }, key);
1516
- case "tableHeader": {
1517
- const { colSpan, rowSpan } = tableCellSpans(node);
1518
- return /* @__PURE__ */ jsx8("th", { colSpan, rowSpan, children }, key);
1519
- }
1520
- case "tableCell": {
1521
- const { colSpan, rowSpan } = tableCellSpans(node);
1522
- return /* @__PURE__ */ jsx8("td", { colSpan, rowSpan, children }, key);
1523
- }
1524
- case "embed":
1525
- return renderEmbed(node, key);
1526
- case "faq":
1527
- return /* @__PURE__ */ jsx8("div", { "data-roottale-cms": "faq", className: "rt-cms-faq", children }, key);
1528
- case "faqItem":
1529
- return /* @__PURE__ */ jsx8("details", { className: "rt-cms-faq-item", children }, key);
1530
- case "faqQuestion":
1531
- return /* @__PURE__ */ jsx8("summary", { className: "rt-cms-faq-q", children }, key);
1532
- case "faqAnswer":
1533
- return /* @__PURE__ */ jsx8("div", { className: "rt-cms-faq-a", children }, key);
1534
- case "tableOfContents":
1535
- return null;
1536
- case "section":
1537
- return renderSectionNode(node, key, context.section);
1538
- case "text":
1539
- return renderText(node, key);
1540
- default:
1541
- return children ? /* @__PURE__ */ jsx8("span", { children }, key) : null;
1542
- }
1543
- }
1544
- function renderEmbed(node, key) {
1545
- const src = node.attrs?.src;
1546
- if (isAllowedEmbedSrc2(src)) {
1547
- const provider = typeof node.attrs?.provider === "string" ? node.attrs.provider : void 0;
1548
- return /* @__PURE__ */ jsx8(
1549
- "div",
1550
- {
1551
- className: "rt-embed",
1552
- "data-provider": provider,
1553
- style: { aspectRatio: "16 / 9" },
1554
- children: /* @__PURE__ */ jsx8(
1555
- "iframe",
1556
- {
1557
- src,
1558
- title: "\uC784\uBCA0\uB4DC\uB41C \uC601\uC0C1",
1559
- loading: "lazy",
1560
- allowFullScreen: true,
1561
- referrerPolicy: "strict-origin-when-cross-origin",
1562
- allow: "accelerometer; clipboard-write; encrypted-media; picture-in-picture; web-share",
1563
- style: { width: "100%", height: "100%", border: 0 }
1564
- }
1565
- )
1566
- },
1567
- key
1568
- );
1569
- }
1570
- const orig = node.attrs?.originalUrl;
1571
- if (isSafeHref(orig)) {
1572
- return /* @__PURE__ */ jsx8("p", { className: "rt-embed-fallback", children: /* @__PURE__ */ jsx8("a", { href: orig, rel: "noopener noreferrer", target: "_blank", children: orig }) }, key);
1573
- }
1574
- return null;
1575
- }
1576
- function renderText(node, key) {
1577
- const text = node.text ?? "";
1578
- const marks = node.marks ?? [];
1579
- if (marks.length === 0) return text;
1580
- let element = text;
1581
- for (const mark of marks) {
1582
- element = applyMark(mark, element);
1583
- }
1584
- return /* @__PURE__ */ jsx8("span", { children: element }, key);
1585
- }
1586
- function applyMark(mark, child) {
1587
- switch (mark.type) {
1588
- case "bold":
1589
- return /* @__PURE__ */ jsx8("strong", { children: child });
1590
- case "italic":
1591
- return /* @__PURE__ */ jsx8("em", { children: child });
1592
- case "underline":
1593
- return /* @__PURE__ */ jsx8("u", { children: child });
1594
- case "strike":
1595
- return /* @__PURE__ */ jsx8("s", { children: child });
1596
- case "code":
1597
- return /* @__PURE__ */ jsx8("code", { children: child });
1598
- case "highlight": {
1599
- const color = mark.attrs?.color;
1600
- const style = typeof color === "string" && color.length > 0 ? { background: color } : void 0;
1601
- return /* @__PURE__ */ jsx8("mark", { style, children: child });
1602
- }
1603
- case "textStyle": {
1604
- const color = mark.attrs?.color;
1605
- const style = typeof color === "string" && color.length > 0 ? { color } : void 0;
1606
- if (!style) return /* @__PURE__ */ jsx8(Fragment3, { children: child });
1607
- return /* @__PURE__ */ jsx8("span", { style, children: child });
1608
- }
1609
- case "link": {
1610
- const raw = mark.attrs?.href;
1611
- const href = isSafeHref(raw) ? raw : "#";
1612
- return /* @__PURE__ */ jsx8("a", { href, rel: "noopener noreferrer", target: "_blank", children: child });
1613
- }
1614
- default:
1615
- return /* @__PURE__ */ jsx8("span", { children: child });
1616
- }
1617
- }
1618
-
1619
- export {
1620
- RootTaleLeadForm,
1621
- sectionThemeStyle,
1622
- TemplateHero,
1623
- TemplateRichText,
1624
- TemplateServices,
1625
- TemplateFaq,
1626
- TemplateCtaBanner,
1627
- TemplateTrust,
1628
- TemplateContact,
1629
- RootTalePostCard,
1630
- RootTaleTableOfContents,
1631
- themeToCssVars,
1632
- headingToId,
1633
- extractToc,
1634
- attachHeadingIds,
1635
- RootTaleFloatingCta,
1636
- renderBlock,
1637
- renderBlocks,
1638
- renderBoundBlocks,
1639
- RootTaleThemeProvider,
1640
- RootTaleBlogList,
1641
- RootTaleBlogCategories,
1642
- RootTaleBlogPost,
1643
- RootTaleFaqJsonLd,
1644
- RootTalePage,
1645
- RenderTiptap
1646
- };
1647
- //# sourceMappingURL=chunk-GOHP7RWD.js.map