@roottale/cms-core 0.57.0 → 0.59.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/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @roottale/cms-core
2
2
 
3
+ ## 0.59.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c0b3679: 공통 블록 배치 규칙의 유형 키를 컬렉션(`collectionKey`)에서 콘텐츠 모델(`modelKey`)로 바꾼다
8
+ (ADR-0109 Amendment 1 · ADR-0105). `SitePatternPlacementRule.modelKey`,
9
+ `findSitePatternPlacementRule`/`setSitePatternPlacementRule`/`resolvePatternSlots` 가 `modelKey` 를
10
+ 받는다. 저장된 옛 규칙의 `collectionKey` 필드는 `readSitePatternPlacements` 가 `modelKey` 로 읽는다.
11
+ 공개 API 응답 모양(`pattern_slots`)은 그대로이며, 계산 근거가 글의 `model_key` 로 바뀐다 —
12
+ 컬렉션 설정이 없는 사이트 글·2단계 분류 모델(FAQ)·모델 key 와 컬렉션 key 가 다른 글도 유형별
13
+ 규칙을 받는다. cms-mcp `api-reference.md` 의 `pattern_slots` 설명을 맞춘다.
14
+
15
+ ## 0.58.0
16
+
17
+ ### Minor Changes
18
+
19
+ - dd82c92: 공통 블록 표시 형태(presentation) — 블록의 모양(본문처럼/카드·배경색·링크 버튼·버튼 색)을 어드민이
20
+ 정해 공개 API `presentation` 으로 내려준다. 사이트는 색·모양을 CSS 에 고정하지 않는다.
21
+ - `@roottale/cms-core`: `readSitePatternPresentation`·`sitePatternPresentationAttributes`·
22
+ `DEFAULT_SITE_PATTERN_PRESENTATION`.
23
+ - `@roottale/cms-client`: `CmsSitePattern.presentation`(구 서버는 기본값), `sitePatternPresentationAttributes`
24
+ (래퍼 data 속성 + `--rt-pattern-bg`·`--rt-pattern-btn-n` CSS 변수).
25
+ - `@roottale/cms-renderer-next`: `RootTaleBlogPost`·`RootTalePostPattern` 이 data 속성·변수를 얹고,
26
+ `cms-public.css` 가 카드/버튼 모양을 그 값으로만 그린다.
27
+
3
28
  ## 0.57.0
4
29
 
5
30
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  BLOCK_NAME_PATTERN: () => BLOCK_NAME_PATTERN,
34
+ DEFAULT_SITE_PATTERN_PRESENTATION: () => DEFAULT_SITE_PATTERN_PRESENTATION,
34
35
  EMPTY_SITE_PATTERN_PLACEMENTS: () => EMPTY_SITE_PATTERN_PLACEMENTS,
35
36
  FIELD_BINDING_SOURCE: () => FIELD_BINDING_SOURCE,
36
37
  FIELD_BINDING_SOURCE_ALIAS: () => FIELD_BINDING_SOURCE_ALIAS,
@@ -43,6 +44,7 @@ __export(src_exports, {
43
44
  PHASE_1_CORE_BLOCKS: () => PHASE_1_CORE_BLOCKS,
44
45
  PHASE_1_CSP: () => PHASE_1_CSP,
45
46
  POST_FOOTER_SLOT: () => POST_FOOTER_SLOT,
47
+ SITE_PATTERN_BUTTON_COLORS_MAX: () => SITE_PATTERN_BUTTON_COLORS_MAX,
46
48
  SITE_PATTERN_KEY_PATTERN: () => SITE_PATTERN_KEY_PATTERN,
47
49
  SITE_PATTERN_PLACEMENTS_KEY: () => SITE_PATTERN_PLACEMENTS_KEY,
48
50
  SITE_PATTERN_SLOTS: () => SITE_PATTERN_SLOTS,
@@ -73,12 +75,14 @@ __export(src_exports, {
73
75
  isValidSitePatternKey: () => isValidSitePatternKey,
74
76
  issuePreviewToken: () => issuePreviewToken,
75
77
  normalizeEmbed: () => normalizeEmbed,
78
+ normalizeHexColor: () => normalizeHexColor,
76
79
  normalizeImageAlt: () => normalizeImageAlt,
77
80
  parseBlock: () => parseBlock,
78
81
  postsForCollection: () => postsForCollection,
79
82
  postsInAnyCollection: () => postsInAnyCollection,
80
83
  postsNotInAnyCollection: () => postsNotInAnyCollection,
81
84
  readSitePatternPlacements: () => readSitePatternPlacements,
85
+ readSitePatternPresentation: () => readSitePatternPresentation,
82
86
  referencedSitePatternKeys: () => referencedSitePatternKeys,
83
87
  renderInternalContentLinksInHtml: () => renderInternalContentLinksInHtml,
84
88
  renderInternalContentLinksInText: () => renderInternalContentLinksInText,
@@ -98,6 +102,8 @@ __export(src_exports, {
98
102
  scopeImportedCss: () => scopeImportedCss,
99
103
  serializeBlock: () => serializeBlock,
100
104
  setSitePatternPlacementRule: () => setSitePatternPlacementRule,
105
+ sitePatternButtonColor: () => sitePatternButtonColor,
106
+ sitePatternPresentationAttributes: () => sitePatternPresentationAttributes,
101
107
  validateCollections: () => validateCollections,
102
108
  verifyPreviewToken: () => verifyPreviewToken
103
109
  });
@@ -1560,34 +1566,31 @@ function readSitePatternPlacements(raw) {
1560
1566
  if (!isRecord(item)) continue;
1561
1567
  const slot = typeof item.slot === "string" ? item.slot : "";
1562
1568
  if (!isSitePatternSlotKey(slot)) continue;
1563
- const collectionKey = readNullableKey(item.collectionKey);
1564
- if (collectionKey === void 0) continue;
1569
+ const modelKey = readNullableKey(
1570
+ item.modelKey === void 0 ? item.collectionKey : item.modelKey
1571
+ );
1572
+ if (modelKey === void 0) continue;
1565
1573
  const patternKey = readNullableKey(item.patternKey);
1566
1574
  if (patternKey === void 0) continue;
1567
1575
  if (patternKey !== null && !isValidSitePatternKey(patternKey)) continue;
1568
- byTarget.set(`${slot}\0${collectionKey ?? ""}`, {
1576
+ byTarget.set(`${slot}\0${modelKey ?? ""}`, {
1569
1577
  slot,
1570
- collectionKey,
1578
+ modelKey,
1571
1579
  patternKey
1572
1580
  });
1573
1581
  }
1574
1582
  return { rules: [...byTarget.values()] };
1575
1583
  }
1576
- function findSitePatternPlacementRule(placements, slot, collectionKey) {
1577
- return placements.rules.find(
1578
- (rule) => rule.slot === slot && rule.collectionKey === collectionKey
1579
- );
1584
+ function findSitePatternPlacementRule(placements, slot, modelKey) {
1585
+ return placements.rules.find((rule) => rule.slot === slot && rule.modelKey === modelKey);
1580
1586
  }
1581
1587
  function setSitePatternPlacementRule(placements, target, patternKey) {
1582
1588
  const rest = placements.rules.filter(
1583
- (rule) => !(rule.slot === target.slot && rule.collectionKey === target.collectionKey)
1589
+ (rule) => !(rule.slot === target.slot && rule.modelKey === target.modelKey)
1584
1590
  );
1585
1591
  if (patternKey === void 0) return { rules: rest };
1586
1592
  return {
1587
- rules: [
1588
- ...rest,
1589
- { slot: target.slot, collectionKey: target.collectionKey, patternKey }
1590
- ]
1593
+ rules: [...rest, { slot: target.slot, modelKey: target.modelKey, patternKey }]
1591
1594
  };
1592
1595
  }
1593
1596
  function emptyPatternSlots() {
@@ -1596,7 +1599,7 @@ function emptyPatternSlots() {
1596
1599
  function resolvePatternSlots(post, placements, publishedKeys) {
1597
1600
  const slots = emptyPatternSlots();
1598
1601
  for (const slot of SITE_PATTERN_SLOTS) {
1599
- const specific = post.collectionKey !== null ? findSitePatternPlacementRule(placements, slot.key, post.collectionKey) : void 0;
1602
+ const specific = post.modelKey !== null ? findSitePatternPlacementRule(placements, slot.key, post.modelKey) : void 0;
1600
1603
  const rule = specific ?? findSitePatternPlacementRule(placements, slot.key, null);
1601
1604
  const key = rule?.patternKey ?? null;
1602
1605
  slots[slot.key] = key !== null && publishedKeys.has(key) ? key : null;
@@ -1608,9 +1611,63 @@ function referencedSitePatternKeys(placements) {
1608
1611
  placements.rules.map((rule) => rule.patternKey).filter((key) => key !== null)
1609
1612
  );
1610
1613
  }
1614
+ var DEFAULT_SITE_PATTERN_PRESENTATION = {
1615
+ layout: "plain",
1616
+ background: "#f8f9fa",
1617
+ linkStyle: "text",
1618
+ buttonColors: ["#03c75a", "#1a1a1a", "#666666"]
1619
+ };
1620
+ var SITE_PATTERN_BUTTON_COLORS_MAX = 4;
1621
+ var HEX_COLOR_RE2 = /^#[0-9a-f]{6}$/;
1622
+ function normalizeHexColor(value) {
1623
+ if (typeof value !== "string") return null;
1624
+ let hex = value.trim().toLowerCase();
1625
+ if (/^#[0-9a-f]{3}$/.test(hex)) hex = `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`;
1626
+ return HEX_COLOR_RE2.test(hex) ? hex : null;
1627
+ }
1628
+ function readSitePatternPresentation(raw) {
1629
+ let value = raw;
1630
+ if (typeof value === "string") {
1631
+ try {
1632
+ value = JSON.parse(value);
1633
+ } catch {
1634
+ value = null;
1635
+ }
1636
+ }
1637
+ const base = DEFAULT_SITE_PATTERN_PRESENTATION;
1638
+ if (!isRecord(value)) return base;
1639
+ const layout = value.layout === "card" ? "card" : "plain";
1640
+ const linkStyle = value.linkStyle === "buttons" ? "buttons" : "text";
1641
+ const background = normalizeHexColor(value.background) ?? base.background;
1642
+ const colors = Array.isArray(value.buttonColors) ? value.buttonColors.map(normalizeHexColor).filter((c) => c !== null).slice(0, SITE_PATTERN_BUTTON_COLORS_MAX) : [];
1643
+ return {
1644
+ layout,
1645
+ background,
1646
+ linkStyle,
1647
+ buttonColors: colors.length > 0 ? colors : base.buttonColors
1648
+ };
1649
+ }
1650
+ function sitePatternButtonColor(presentation, index) {
1651
+ const colors = presentation.buttonColors;
1652
+ return colors[Math.min(index, colors.length - 1)] ?? DEFAULT_SITE_PATTERN_PRESENTATION.buttonColors[0];
1653
+ }
1654
+ function sitePatternPresentationAttributes(presentation) {
1655
+ const cssVariables = { "--rt-pattern-bg": presentation.background };
1656
+ presentation.buttonColors.forEach((color, index) => {
1657
+ cssVariables[`--rt-pattern-btn-${index + 1}`] = color;
1658
+ });
1659
+ return {
1660
+ dataset: {
1661
+ "data-pattern-layout": presentation.layout,
1662
+ "data-pattern-link-style": presentation.linkStyle
1663
+ },
1664
+ cssVariables
1665
+ };
1666
+ }
1611
1667
  // Annotate the CommonJS export names for ESM import in node:
1612
1668
  0 && (module.exports = {
1613
1669
  BLOCK_NAME_PATTERN,
1670
+ DEFAULT_SITE_PATTERN_PRESENTATION,
1614
1671
  EMPTY_SITE_PATTERN_PLACEMENTS,
1615
1672
  FIELD_BINDING_SOURCE,
1616
1673
  FIELD_BINDING_SOURCE_ALIAS,
@@ -1623,6 +1680,7 @@ function referencedSitePatternKeys(placements) {
1623
1680
  PHASE_1_CORE_BLOCKS,
1624
1681
  PHASE_1_CSP,
1625
1682
  POST_FOOTER_SLOT,
1683
+ SITE_PATTERN_BUTTON_COLORS_MAX,
1626
1684
  SITE_PATTERN_KEY_PATTERN,
1627
1685
  SITE_PATTERN_PLACEMENTS_KEY,
1628
1686
  SITE_PATTERN_SLOTS,
@@ -1653,12 +1711,14 @@ function referencedSitePatternKeys(placements) {
1653
1711
  isValidSitePatternKey,
1654
1712
  issuePreviewToken,
1655
1713
  normalizeEmbed,
1714
+ normalizeHexColor,
1656
1715
  normalizeImageAlt,
1657
1716
  parseBlock,
1658
1717
  postsForCollection,
1659
1718
  postsInAnyCollection,
1660
1719
  postsNotInAnyCollection,
1661
1720
  readSitePatternPlacements,
1721
+ readSitePatternPresentation,
1662
1722
  referencedSitePatternKeys,
1663
1723
  renderInternalContentLinksInHtml,
1664
1724
  renderInternalContentLinksInText,
@@ -1678,6 +1738,8 @@ function referencedSitePatternKeys(placements) {
1678
1738
  scopeImportedCss,
1679
1739
  serializeBlock,
1680
1740
  setSitePatternPlacementRule,
1741
+ sitePatternButtonColor,
1742
+ sitePatternPresentationAttributes,
1681
1743
  validateCollections,
1682
1744
  verifyPreviewToken
1683
1745
  });