@roottale/cms-core 0.57.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -543,5 +543,32 @@ declare function resolvePatternSlots(post: {
543
543
  * 삭제 전 경고할 때 쓴다.
544
544
  */
545
545
  declare function referencedSitePatternKeys(placements: SitePatternPlacements): ReadonlySet<string>;
546
+ type SitePatternLayout = "plain" | "card";
547
+ type SitePatternLinkStyle = "text" | "buttons";
548
+ interface SitePatternPresentation {
549
+ /** `plain` = 본문처럼 흐름에 놓임, `card` = 배경색이 있는 카드. */
550
+ readonly layout: SitePatternLayout;
551
+ /** 카드 배경색(hex). layout 이 card 일 때만 의미. */
552
+ readonly background: string;
553
+ /** 마지막 문단의 링크를 버튼으로 그릴지. */
554
+ readonly linkStyle: SitePatternLinkStyle;
555
+ /** 버튼 배경색(hex, 순서대로 1·2·3…; 링크가 더 많으면 마지막 색을 반복). 글자는 흰색. */
556
+ readonly buttonColors: readonly string[];
557
+ }
558
+ declare const DEFAULT_SITE_PATTERN_PRESENTATION: SitePatternPresentation;
559
+ declare const SITE_PATTERN_BUTTON_COLORS_MAX = 4;
560
+ declare function normalizeHexColor(value: unknown): string | null;
561
+ /** 저장된 값(unknown) → 표시 형태. 틀린 값은 기본값으로 채운다(절대 throw 하지 않음). */
562
+ declare function readSitePatternPresentation(raw: unknown): SitePatternPresentation;
563
+ /** 버튼 n번째(0부터)의 색 — 링크가 색 개수보다 많으면 마지막 색을 반복. */
564
+ declare function sitePatternButtonColor(presentation: SitePatternPresentation, index: number): string;
565
+ /**
566
+ * FRONT 가 래퍼 요소에 얹을 data 속성과 CSS 변수. 사이트 CSS 는 이 변수만 읽는다 —
567
+ * `data-pattern-layout`·`data-pattern-link-style`, `--rt-pattern-bg`, `--rt-pattern-btn-1..n`.
568
+ */
569
+ declare function sitePatternPresentationAttributes(presentation: SitePatternPresentation): {
570
+ readonly dataset: Readonly<Record<string, string>>;
571
+ readonly cssVariables: Readonly<Record<string, string>>;
572
+ };
546
573
 
547
- export { BLOCK_NAME_PATTERN, type BindingResolver, type Block, type BlockBinding, type BlockDefinition, type BlockRegistry, type CategoryTreeEntry, type CategoryTreePresentation, type CategoryTreeTerm, type ClientHydrationSpec, EMPTY_SITE_PATTERN_PLACEMENTS, type EmbedProvider, FIELD_BINDING_SOURCE, FIELD_BINDING_SOURCE_ALIAS, type FaqEntry, IMAGE_ALT_MAX_LENGTH, INTERNAL_CONTENT_LINK_CLASS, INTERNAL_CONTENT_LINK_PENDING_ATTR, INTERNAL_CONTENT_LINK_PENDING_CLASS, INTERNAL_CONTENT_LINK_TOKEN_SOURCE, type InternalContentLinkResolver, type InternalContentLinkToken, LEGACY_BLOG_DETAIL_PATH, type NormalizedEmbed, PHASE_1_CORE_BLOCKS, PHASE_1_CSP, POST_FOOTER_SLOT, type PatternSlots, type Phase1CoreBlockName, type PreviewTokenPayload, type PublicPathContext, type PublicPathPost, type PublicPathPresentation, type RoutablePost, type RouteCollection, SITE_PATTERN_KEY_PATTERN, SITE_PATTERN_PLACEMENTS_KEY, SITE_PATTERN_SLOTS, type SitePatternPlacementRule, type SitePatternPlacements, type SitePatternSlotKey, applyBlockBindings, bindingSrcValue, bindingTextValue, blockSchema, boundFieldValue, chainResolvers, createFieldBindingResolver, emptyPatternSlots, ensureImportedHtmlDocumentRoots, ensureStableIds, extractFaqEntries, faqPageJsonLd, findInternalContentLinkTokens, findSitePatternPlacementRule, htmlToPlainText, injectStableIdsTree, internalContentKeyFromPath, internalContentLinkResolverFrom, internalContentPathIndex, isAllowedEmbedSrc, isAllowedMapEmbedSrc, isInCollectionMode, isSitePatternSlotKey, isValidBlock, isValidSitePatternKey, issuePreviewToken, normalizeEmbed, normalizeImageAlt, parseBlock, postsForCollection, postsInAnyCollection, postsNotInAnyCollection, readSitePatternPlacements, referencedSitePatternKeys, renderInternalContentLinksInHtml, renderInternalContentLinksInText, resolveCategoryPath, resolveCategoryTreeChain, resolveCategoryTreeEntryPath, resolveCategoryTreeHubPaths, resolvePatternSlots, resolvePostCategorySlug, resolvePostCollection, resolvePostPath, resolvePostPublicPath, resolvePostUrl, sanitizeHtml, sanitizeImportedCss, sanitizeImportedHtml, scopeImportedCss, serializeBlock, setSitePatternPlacementRule, validateCollections, verifyPreviewToken };
574
+ export { BLOCK_NAME_PATTERN, type BindingResolver, type Block, type BlockBinding, type BlockDefinition, type BlockRegistry, type CategoryTreeEntry, type CategoryTreePresentation, type CategoryTreeTerm, type ClientHydrationSpec, DEFAULT_SITE_PATTERN_PRESENTATION, EMPTY_SITE_PATTERN_PLACEMENTS, type EmbedProvider, FIELD_BINDING_SOURCE, FIELD_BINDING_SOURCE_ALIAS, type FaqEntry, IMAGE_ALT_MAX_LENGTH, INTERNAL_CONTENT_LINK_CLASS, INTERNAL_CONTENT_LINK_PENDING_ATTR, INTERNAL_CONTENT_LINK_PENDING_CLASS, INTERNAL_CONTENT_LINK_TOKEN_SOURCE, type InternalContentLinkResolver, type InternalContentLinkToken, LEGACY_BLOG_DETAIL_PATH, type NormalizedEmbed, PHASE_1_CORE_BLOCKS, PHASE_1_CSP, POST_FOOTER_SLOT, type PatternSlots, type Phase1CoreBlockName, type PreviewTokenPayload, type PublicPathContext, type PublicPathPost, type PublicPathPresentation, type RoutablePost, type RouteCollection, SITE_PATTERN_BUTTON_COLORS_MAX, SITE_PATTERN_KEY_PATTERN, SITE_PATTERN_PLACEMENTS_KEY, SITE_PATTERN_SLOTS, type SitePatternLayout, type SitePatternLinkStyle, type SitePatternPlacementRule, type SitePatternPlacements, type SitePatternPresentation, type SitePatternSlotKey, applyBlockBindings, bindingSrcValue, bindingTextValue, blockSchema, boundFieldValue, chainResolvers, createFieldBindingResolver, emptyPatternSlots, ensureImportedHtmlDocumentRoots, ensureStableIds, extractFaqEntries, faqPageJsonLd, findInternalContentLinkTokens, findSitePatternPlacementRule, htmlToPlainText, injectStableIdsTree, internalContentKeyFromPath, internalContentLinkResolverFrom, internalContentPathIndex, isAllowedEmbedSrc, isAllowedMapEmbedSrc, isInCollectionMode, isSitePatternSlotKey, isValidBlock, isValidSitePatternKey, issuePreviewToken, normalizeEmbed, normalizeHexColor, normalizeImageAlt, parseBlock, postsForCollection, postsInAnyCollection, postsNotInAnyCollection, readSitePatternPlacements, readSitePatternPresentation, referencedSitePatternKeys, renderInternalContentLinksInHtml, renderInternalContentLinksInText, resolveCategoryPath, resolveCategoryTreeChain, resolveCategoryTreeEntryPath, resolveCategoryTreeHubPaths, resolvePatternSlots, resolvePostCategorySlug, resolvePostCollection, resolvePostPath, resolvePostPublicPath, resolvePostUrl, sanitizeHtml, sanitizeImportedCss, sanitizeImportedHtml, scopeImportedCss, serializeBlock, setSitePatternPlacementRule, sitePatternButtonColor, sitePatternPresentationAttributes, validateCollections, verifyPreviewToken };
package/dist/index.d.ts CHANGED
@@ -543,5 +543,32 @@ declare function resolvePatternSlots(post: {
543
543
  * 삭제 전 경고할 때 쓴다.
544
544
  */
545
545
  declare function referencedSitePatternKeys(placements: SitePatternPlacements): ReadonlySet<string>;
546
+ type SitePatternLayout = "plain" | "card";
547
+ type SitePatternLinkStyle = "text" | "buttons";
548
+ interface SitePatternPresentation {
549
+ /** `plain` = 본문처럼 흐름에 놓임, `card` = 배경색이 있는 카드. */
550
+ readonly layout: SitePatternLayout;
551
+ /** 카드 배경색(hex). layout 이 card 일 때만 의미. */
552
+ readonly background: string;
553
+ /** 마지막 문단의 링크를 버튼으로 그릴지. */
554
+ readonly linkStyle: SitePatternLinkStyle;
555
+ /** 버튼 배경색(hex, 순서대로 1·2·3…; 링크가 더 많으면 마지막 색을 반복). 글자는 흰색. */
556
+ readonly buttonColors: readonly string[];
557
+ }
558
+ declare const DEFAULT_SITE_PATTERN_PRESENTATION: SitePatternPresentation;
559
+ declare const SITE_PATTERN_BUTTON_COLORS_MAX = 4;
560
+ declare function normalizeHexColor(value: unknown): string | null;
561
+ /** 저장된 값(unknown) → 표시 형태. 틀린 값은 기본값으로 채운다(절대 throw 하지 않음). */
562
+ declare function readSitePatternPresentation(raw: unknown): SitePatternPresentation;
563
+ /** 버튼 n번째(0부터)의 색 — 링크가 색 개수보다 많으면 마지막 색을 반복. */
564
+ declare function sitePatternButtonColor(presentation: SitePatternPresentation, index: number): string;
565
+ /**
566
+ * FRONT 가 래퍼 요소에 얹을 data 속성과 CSS 변수. 사이트 CSS 는 이 변수만 읽는다 —
567
+ * `data-pattern-layout`·`data-pattern-link-style`, `--rt-pattern-bg`, `--rt-pattern-btn-1..n`.
568
+ */
569
+ declare function sitePatternPresentationAttributes(presentation: SitePatternPresentation): {
570
+ readonly dataset: Readonly<Record<string, string>>;
571
+ readonly cssVariables: Readonly<Record<string, string>>;
572
+ };
546
573
 
547
- export { BLOCK_NAME_PATTERN, type BindingResolver, type Block, type BlockBinding, type BlockDefinition, type BlockRegistry, type CategoryTreeEntry, type CategoryTreePresentation, type CategoryTreeTerm, type ClientHydrationSpec, EMPTY_SITE_PATTERN_PLACEMENTS, type EmbedProvider, FIELD_BINDING_SOURCE, FIELD_BINDING_SOURCE_ALIAS, type FaqEntry, IMAGE_ALT_MAX_LENGTH, INTERNAL_CONTENT_LINK_CLASS, INTERNAL_CONTENT_LINK_PENDING_ATTR, INTERNAL_CONTENT_LINK_PENDING_CLASS, INTERNAL_CONTENT_LINK_TOKEN_SOURCE, type InternalContentLinkResolver, type InternalContentLinkToken, LEGACY_BLOG_DETAIL_PATH, type NormalizedEmbed, PHASE_1_CORE_BLOCKS, PHASE_1_CSP, POST_FOOTER_SLOT, type PatternSlots, type Phase1CoreBlockName, type PreviewTokenPayload, type PublicPathContext, type PublicPathPost, type PublicPathPresentation, type RoutablePost, type RouteCollection, SITE_PATTERN_KEY_PATTERN, SITE_PATTERN_PLACEMENTS_KEY, SITE_PATTERN_SLOTS, type SitePatternPlacementRule, type SitePatternPlacements, type SitePatternSlotKey, applyBlockBindings, bindingSrcValue, bindingTextValue, blockSchema, boundFieldValue, chainResolvers, createFieldBindingResolver, emptyPatternSlots, ensureImportedHtmlDocumentRoots, ensureStableIds, extractFaqEntries, faqPageJsonLd, findInternalContentLinkTokens, findSitePatternPlacementRule, htmlToPlainText, injectStableIdsTree, internalContentKeyFromPath, internalContentLinkResolverFrom, internalContentPathIndex, isAllowedEmbedSrc, isAllowedMapEmbedSrc, isInCollectionMode, isSitePatternSlotKey, isValidBlock, isValidSitePatternKey, issuePreviewToken, normalizeEmbed, normalizeImageAlt, parseBlock, postsForCollection, postsInAnyCollection, postsNotInAnyCollection, readSitePatternPlacements, referencedSitePatternKeys, renderInternalContentLinksInHtml, renderInternalContentLinksInText, resolveCategoryPath, resolveCategoryTreeChain, resolveCategoryTreeEntryPath, resolveCategoryTreeHubPaths, resolvePatternSlots, resolvePostCategorySlug, resolvePostCollection, resolvePostPath, resolvePostPublicPath, resolvePostUrl, sanitizeHtml, sanitizeImportedCss, sanitizeImportedHtml, scopeImportedCss, serializeBlock, setSitePatternPlacementRule, validateCollections, verifyPreviewToken };
574
+ export { BLOCK_NAME_PATTERN, type BindingResolver, type Block, type BlockBinding, type BlockDefinition, type BlockRegistry, type CategoryTreeEntry, type CategoryTreePresentation, type CategoryTreeTerm, type ClientHydrationSpec, DEFAULT_SITE_PATTERN_PRESENTATION, EMPTY_SITE_PATTERN_PLACEMENTS, type EmbedProvider, FIELD_BINDING_SOURCE, FIELD_BINDING_SOURCE_ALIAS, type FaqEntry, IMAGE_ALT_MAX_LENGTH, INTERNAL_CONTENT_LINK_CLASS, INTERNAL_CONTENT_LINK_PENDING_ATTR, INTERNAL_CONTENT_LINK_PENDING_CLASS, INTERNAL_CONTENT_LINK_TOKEN_SOURCE, type InternalContentLinkResolver, type InternalContentLinkToken, LEGACY_BLOG_DETAIL_PATH, type NormalizedEmbed, PHASE_1_CORE_BLOCKS, PHASE_1_CSP, POST_FOOTER_SLOT, type PatternSlots, type Phase1CoreBlockName, type PreviewTokenPayload, type PublicPathContext, type PublicPathPost, type PublicPathPresentation, type RoutablePost, type RouteCollection, SITE_PATTERN_BUTTON_COLORS_MAX, SITE_PATTERN_KEY_PATTERN, SITE_PATTERN_PLACEMENTS_KEY, SITE_PATTERN_SLOTS, type SitePatternLayout, type SitePatternLinkStyle, type SitePatternPlacementRule, type SitePatternPlacements, type SitePatternPresentation, type SitePatternSlotKey, applyBlockBindings, bindingSrcValue, bindingTextValue, blockSchema, boundFieldValue, chainResolvers, createFieldBindingResolver, emptyPatternSlots, ensureImportedHtmlDocumentRoots, ensureStableIds, extractFaqEntries, faqPageJsonLd, findInternalContentLinkTokens, findSitePatternPlacementRule, htmlToPlainText, injectStableIdsTree, internalContentKeyFromPath, internalContentLinkResolverFrom, internalContentPathIndex, isAllowedEmbedSrc, isAllowedMapEmbedSrc, isInCollectionMode, isSitePatternSlotKey, isValidBlock, isValidSitePatternKey, issuePreviewToken, normalizeEmbed, normalizeHexColor, normalizeImageAlt, parseBlock, postsForCollection, postsInAnyCollection, postsNotInAnyCollection, readSitePatternPlacements, readSitePatternPresentation, referencedSitePatternKeys, renderInternalContentLinksInHtml, renderInternalContentLinksInText, resolveCategoryPath, resolveCategoryTreeChain, resolveCategoryTreeEntryPath, resolveCategoryTreeHubPaths, resolvePatternSlots, resolvePostCategorySlug, resolvePostCollection, resolvePostPath, resolvePostPublicPath, resolvePostUrl, sanitizeHtml, sanitizeImportedCss, sanitizeImportedHtml, scopeImportedCss, serializeBlock, setSitePatternPlacementRule, sitePatternButtonColor, sitePatternPresentationAttributes, validateCollections, verifyPreviewToken };
package/dist/index.js CHANGED
@@ -1503,8 +1503,62 @@ function referencedSitePatternKeys(placements) {
1503
1503
  placements.rules.map((rule) => rule.patternKey).filter((key) => key !== null)
1504
1504
  );
1505
1505
  }
1506
+ var DEFAULT_SITE_PATTERN_PRESENTATION = {
1507
+ layout: "plain",
1508
+ background: "#f8f9fa",
1509
+ linkStyle: "text",
1510
+ buttonColors: ["#03c75a", "#1a1a1a", "#666666"]
1511
+ };
1512
+ var SITE_PATTERN_BUTTON_COLORS_MAX = 4;
1513
+ var HEX_COLOR_RE2 = /^#[0-9a-f]{6}$/;
1514
+ function normalizeHexColor(value) {
1515
+ if (typeof value !== "string") return null;
1516
+ let hex = value.trim().toLowerCase();
1517
+ if (/^#[0-9a-f]{3}$/.test(hex)) hex = `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`;
1518
+ return HEX_COLOR_RE2.test(hex) ? hex : null;
1519
+ }
1520
+ function readSitePatternPresentation(raw) {
1521
+ let value = raw;
1522
+ if (typeof value === "string") {
1523
+ try {
1524
+ value = JSON.parse(value);
1525
+ } catch {
1526
+ value = null;
1527
+ }
1528
+ }
1529
+ const base = DEFAULT_SITE_PATTERN_PRESENTATION;
1530
+ if (!isRecord(value)) return base;
1531
+ const layout = value.layout === "card" ? "card" : "plain";
1532
+ const linkStyle = value.linkStyle === "buttons" ? "buttons" : "text";
1533
+ const background = normalizeHexColor(value.background) ?? base.background;
1534
+ const colors = Array.isArray(value.buttonColors) ? value.buttonColors.map(normalizeHexColor).filter((c) => c !== null).slice(0, SITE_PATTERN_BUTTON_COLORS_MAX) : [];
1535
+ return {
1536
+ layout,
1537
+ background,
1538
+ linkStyle,
1539
+ buttonColors: colors.length > 0 ? colors : base.buttonColors
1540
+ };
1541
+ }
1542
+ function sitePatternButtonColor(presentation, index) {
1543
+ const colors = presentation.buttonColors;
1544
+ return colors[Math.min(index, colors.length - 1)] ?? DEFAULT_SITE_PATTERN_PRESENTATION.buttonColors[0];
1545
+ }
1546
+ function sitePatternPresentationAttributes(presentation) {
1547
+ const cssVariables = { "--rt-pattern-bg": presentation.background };
1548
+ presentation.buttonColors.forEach((color, index) => {
1549
+ cssVariables[`--rt-pattern-btn-${index + 1}`] = color;
1550
+ });
1551
+ return {
1552
+ dataset: {
1553
+ "data-pattern-layout": presentation.layout,
1554
+ "data-pattern-link-style": presentation.linkStyle
1555
+ },
1556
+ cssVariables
1557
+ };
1558
+ }
1506
1559
  export {
1507
1560
  BLOCK_NAME_PATTERN,
1561
+ DEFAULT_SITE_PATTERN_PRESENTATION,
1508
1562
  EMPTY_SITE_PATTERN_PLACEMENTS,
1509
1563
  FIELD_BINDING_SOURCE,
1510
1564
  FIELD_BINDING_SOURCE_ALIAS,
@@ -1517,6 +1571,7 @@ export {
1517
1571
  PHASE_1_CORE_BLOCKS,
1518
1572
  PHASE_1_CSP,
1519
1573
  POST_FOOTER_SLOT,
1574
+ SITE_PATTERN_BUTTON_COLORS_MAX,
1520
1575
  SITE_PATTERN_KEY_PATTERN,
1521
1576
  SITE_PATTERN_PLACEMENTS_KEY,
1522
1577
  SITE_PATTERN_SLOTS,
@@ -1547,12 +1602,14 @@ export {
1547
1602
  isValidSitePatternKey,
1548
1603
  issuePreviewToken,
1549
1604
  normalizeEmbed,
1605
+ normalizeHexColor,
1550
1606
  normalizeImageAlt,
1551
1607
  parseBlock,
1552
1608
  postsForCollection,
1553
1609
  postsInAnyCollection,
1554
1610
  postsNotInAnyCollection,
1555
1611
  readSitePatternPlacements,
1612
+ readSitePatternPresentation,
1556
1613
  referencedSitePatternKeys,
1557
1614
  renderInternalContentLinksInHtml,
1558
1615
  renderInternalContentLinksInText,
@@ -1572,6 +1629,8 @@ export {
1572
1629
  scopeImportedCss,
1573
1630
  serializeBlock,
1574
1631
  setSitePatternPlacementRule,
1632
+ sitePatternButtonColor,
1633
+ sitePatternPresentationAttributes,
1575
1634
  validateCollections,
1576
1635
  verifyPreviewToken
1577
1636
  };