@roottale/cms-renderer-next 0.47.0 → 0.48.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,29 @@
1
1
  # @roottale/cms-renderer-next
2
2
 
3
+ ## 0.48.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a4c7070: avcd 구조 — `RootTaleBlogPost`에 opt-in `breadcrumb` prop(시각 브레드크럼 +
8
+ `BreadcrumbList` JSON-LD) 추가, `author_slug` 있으면 작성자 이름을
9
+ `/blog/author/{slug}`로 자동 링크(`authorHref`로 override 가능). 헤더 발행일
10
+ 마크업이 `<span>`에서 `dateTime` 속성을 가진 `<time>`으로 변경(class·
11
+ data-rt-cms-meta 속성은 유지). `buildPostMetadata`에 Twitter Card 자동 emit,
12
+ RSS alternate(`feedPath`, 기본 `/feed.xml`), og article 확장(`modified`·
13
+ `section`·`tags`·`authors`) 추가.
14
+
15
+ ⚠️ 카테고리 칩·`RootTaleBlogCategories`·브레드크럼 카테고리 링크가 모두
16
+ `/blog/categories/{slug}`를 기본 링크한다 — 단일 블로그 사이트도 이 라우트를
17
+ 구현해야 404가 나지 않는다(참조 구현: `@roottale/cms-mcp` 예시
18
+ `app/blog/categories/[slug]/page.tsx`).
19
+
20
+ - ab5241a: 읽기 표면 조판 개선 — 네이버 프리미엄 콘텐츠·avcd 기준: 문단 간격 확대(1.35em), h2 섹션 대여백, h3/h4 크기 위계 수정, 리스트 간격·액센트 마커, 인용구 라운드 카드화, 이미지 여백·캡션 스타일, 표 라운드 외곽+수평 구분선, hr 여백 확대
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies [a4c7070]
25
+ - @roottale/cms-client@0.48.0
26
+
3
27
  ## 0.47.0
4
28
 
5
29
  ### Minor Changes
@@ -31,8 +31,9 @@ import {
31
31
  collectCategoriesWithCounts,
32
32
  collectCollectionCategories,
33
33
  defaultCategoryHref,
34
- filterPostsByCategory
35
- } from "./chunk-FUA5H6JE.js";
34
+ filterPostsByCategory,
35
+ trimSlash
36
+ } from "./chunk-U2IM6OCQ.js";
36
37
  import {
37
38
  SectionSchema
38
39
  } from "./chunk-UM37DOIK.js";
@@ -43,6 +44,7 @@ import {
43
44
  // src/server.tsx
44
45
  import {
45
46
  DEFAULT_BLOG_SETTINGS,
47
+ breadcrumbSchema,
46
48
  fetchBlogSettings,
47
49
  fetchPost,
48
50
  fetchPosts,
@@ -2966,7 +2968,9 @@ async function RootTaleBlogPost(props) {
2966
2968
  relatedPostsTitle = t(locale, "relatedPostsTitle"),
2967
2969
  collections,
2968
2970
  showFieldFacts = false,
2969
- theme: themeProp
2971
+ theme: themeProp,
2972
+ authorHref = defaultAuthorHref,
2973
+ breadcrumb
2970
2974
  } = props;
2971
2975
  const [post, themeStyle, blogSettings] = await Promise.all([
2972
2976
  fetchPost({ apiKey, slugOrId, baseUrl, ...locale ? { locale } : {} }),
@@ -3003,6 +3007,7 @@ async function RootTaleBlogPost(props) {
3003
3007
  const authorName = post.authorName;
3004
3008
  const authorImageUrl = post.authorImageUrl;
3005
3009
  const postAuthorBio = post.authorBio;
3010
+ const authorSlug = post.authorSlug;
3006
3011
  const views = typeof post.viewCount === "number" ? post.viewCount : null;
3007
3012
  const publishedDate = display.showDate ? formatPublishedDate2(post.publishedAt) : "";
3008
3013
  const showTopAuthor = display.showAuthor && Boolean(authorName);
@@ -3022,14 +3027,24 @@ async function RootTaleBlogPost(props) {
3022
3027
  className: "rt-cms-article",
3023
3028
  style: themeStyle ?? void 0,
3024
3029
  children: [
3030
+ renderBreadcrumb(post, collections, relatedHref, breadcrumb),
3025
3031
  /* @__PURE__ */ jsxs9("header", { className: "rt-cms-post-header", children: [
3026
3032
  showTitle ? /* @__PURE__ */ jsx9("h1", { className: "rt-cms-title", children: post.title }) : null,
3027
3033
  post.excerpt ? /* @__PURE__ */ jsx9("p", { className: "rt-cms-excerpt", children: post.excerpt }) : null,
3028
3034
  publishedDate || showTopAuthor || views !== null ? /* @__PURE__ */ jsxs9("p", { className: "rt-cms-meta", children: [
3029
- publishedDate ? /* @__PURE__ */ jsx9("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "date", children: publishedDate }) : null,
3035
+ publishedDate ? /* @__PURE__ */ jsx9(
3036
+ "time",
3037
+ {
3038
+ dateTime: post.publishedAt ?? void 0,
3039
+ className: "rt-cms-meta-item",
3040
+ "data-rt-cms-meta": "date",
3041
+ children: publishedDate
3042
+ }
3043
+ ) : null,
3030
3044
  showTopAuthor ? /* @__PURE__ */ jsxs9("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "author", children: [
3031
- "\uC791\uC131\uC790 ",
3032
- authorName
3045
+ "\uC791\uC131\uC790",
3046
+ " ",
3047
+ authorSlug ? /* @__PURE__ */ jsx9("a", { className: "rt-cms-author-link", href: authorHref(authorSlug), children: authorName }) : authorName
3033
3048
  ] }) : null,
3034
3049
  views !== null ? /* @__PURE__ */ jsxs9("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "views", children: [
3035
3050
  "\uC870\uD68C ",
@@ -3074,7 +3089,7 @@ async function RootTaleBlogPost(props) {
3074
3089
  ) : /* @__PURE__ */ jsx9("div", { className: "rt-cms-author-card__avatar", "aria-hidden": "true", children: authorInitials(displayAuthorName) }),
3075
3090
  /* @__PURE__ */ jsxs9("div", { className: "rt-cms-author-card__body", children: [
3076
3091
  /* @__PURE__ */ jsx9("p", { className: "rt-cms-author-card__eyebrow", children: display.authorCardEyebrow }),
3077
- /* @__PURE__ */ jsx9("p", { className: "rt-cms-author-card__name", children: displayAuthorName }),
3092
+ /* @__PURE__ */ jsx9("p", { className: "rt-cms-author-card__name", children: authorSlug ? /* @__PURE__ */ jsx9("a", { className: "rt-cms-author-link", href: authorHref(authorSlug), children: displayAuthorName }) : displayAuthorName }),
3078
3093
  authorBio ? /* @__PURE__ */ jsx9("p", { className: "rt-cms-author-card__description", children: authorBio }) : null
3079
3094
  ] })
3080
3095
  ] }) : null,
@@ -3085,6 +3100,46 @@ async function RootTaleBlogPost(props) {
3085
3100
  }
3086
3101
  );
3087
3102
  }
3103
+ function renderBreadcrumb(post, collections, postHref, options) {
3104
+ if (!options) return null;
3105
+ const {
3106
+ siteUrl,
3107
+ homeLabel = "\uD648",
3108
+ homeHref = "/",
3109
+ listLabel = "\uBE14\uB85C\uADF8",
3110
+ showCategory = true,
3111
+ categoryHref = defaultCategoryHref
3112
+ } = options;
3113
+ const listHref = options.listHref ?? (collections ? resolvePostCollection(post, collections)?.basePath || "/blog" : "/blog");
3114
+ const categoryTerm = showCategory ? post.terms.find((t2) => t2.taxonomy === "category") : void 0;
3115
+ const crumbs = [
3116
+ { label: homeLabel, href: homeHref },
3117
+ { label: listLabel, href: listHref }
3118
+ ];
3119
+ if (categoryTerm) {
3120
+ crumbs.push({ label: categoryTerm.name, href: categoryHref(categoryTerm.slug) });
3121
+ }
3122
+ crumbs.push({ label: post.title, href: postHref(post) });
3123
+ const jsonLd = siteUrl ? breadcrumbSchema(
3124
+ crumbs.map((c) => ({ name: c.label, url: absoluteUrl(siteUrl, c.href) }))
3125
+ ) : null;
3126
+ return /* @__PURE__ */ jsxs9(Fragment3, { children: [
3127
+ /* @__PURE__ */ jsx9("nav", { "aria-label": "\uBE0C\uB808\uB4DC\uD06C\uB7FC", className: "rt-cms-breadcrumb", children: /* @__PURE__ */ jsx9("ol", { children: crumbs.map(
3128
+ (c, i) => i === crumbs.length - 1 ? /* @__PURE__ */ jsx9("li", { "aria-current": "page", children: c.label }, i) : /* @__PURE__ */ jsx9("li", { children: /* @__PURE__ */ jsx9("a", { href: c.href, children: c.label }) }, i)
3129
+ ) }) }),
3130
+ jsonLd ? /* @__PURE__ */ jsx9(
3131
+ "script",
3132
+ {
3133
+ type: "application/ld+json",
3134
+ dangerouslySetInnerHTML: { __html: jsonLdJson(jsonLd) }
3135
+ }
3136
+ ) : null
3137
+ ] });
3138
+ }
3139
+ function absoluteUrl(siteUrl, path) {
3140
+ const normalized = path.startsWith("/") ? path : `/${path}`;
3141
+ return `${trimSlash(siteUrl)}${normalized}`;
3142
+ }
3088
3143
  function renderArchiveRelated(groups, collections) {
3089
3144
  const visible = groups.filter((group) => group.items.length > 0);
3090
3145
  if (visible.length === 0) return null;
@@ -3284,6 +3339,9 @@ async function resolveThemeStyle(input) {
3284
3339
  function defaultPostHref(post) {
3285
3340
  return `/blog/${post.slug}`;
3286
3341
  }
3342
+ function defaultAuthorHref(slug) {
3343
+ return `/blog/author/${slug}`;
3344
+ }
3287
3345
  function makeCollectionPostHref(collections) {
3288
3346
  return (post) => {
3289
3347
  const path = resolvePostPath(post, collections);
@@ -3581,4 +3639,4 @@ export {
3581
3639
  RootTalePage,
3582
3640
  RenderTiptap
3583
3641
  };
3584
- //# sourceMappingURL=chunk-ZHXYCABN.js.map
3642
+ //# sourceMappingURL=chunk-LIBSVC4M.js.map