create-riebeckite 0.0.22 → 0.0.23

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/src/index.js CHANGED
@@ -297,7 +297,6 @@ var seo = np("@riebeckite/plugin-seo", "seo", {
297
297
  });
298
298
  var toc = np("@riebeckite/plugin-toc", "tocPlugin");
299
299
  var properties = np("@riebeckite/plugin-properties", "properties", {
300
- render: { depth: 1, value: '"slot"' },
301
300
  include: { depth: 2, value: '["created", "modified", "tags", "status"]' },
302
301
  order: { depth: 2, value: '["created", "modified", "tags", "status"]' }
303
302
  });
@@ -330,7 +329,6 @@ var relatedPosts = np("@riebeckite/plugin-related-posts", "relatedPosts", {
330
329
  className: { depth: 3, value: '"rb-related-posts"' }
331
330
  });
332
331
  var share = np("@riebeckite/plugin-share", "share", {
333
- placement: { depth: 2, value: '"bottom"' },
334
332
  services: {
335
333
  depth: 3,
336
334
  value: '["x", "bluesky", "mastodon", "facebook", "linkedin", "hatena", "copy"]'
@@ -2593,7 +2591,7 @@ function referenceThemesContent(preset) {
2593
2591
  }
2594
2592
 
2595
2593
  // src/scaffold/version.ts
2596
- var RIEBECKITE_VERSION = "^0.0.22";
2594
+ var RIEBECKITE_VERSION = "^0.0.23";
2597
2595
 
2598
2596
  // src/scaffold/templates.ts
2599
2597
  function siteTemplateFiles(preset, variables, options = {}) {
@@ -3510,8 +3508,17 @@ async function scaffoldRiebeckiteSite(options) {
3510
3508
  await fs2.mkdir(path3.dirname(filePath), { recursive: true });
3511
3509
  await fs2.writeFile(filePath, file.content);
3512
3510
  }
3511
+ await ensureContentDirectory(targetDirectory, files);
3513
3512
  return { targetDirectory, files: files.map((file) => file.path) };
3514
3513
  }
3514
+ async function ensureContentDirectory(targetDirectory, files) {
3515
+ if (files.some(
3516
+ (file) => file.path === "content" || file.path.startsWith("content/")
3517
+ )) {
3518
+ return;
3519
+ }
3520
+ await fs2.mkdir(path3.join(targetDirectory, "content"), { recursive: true });
3521
+ }
3515
3522
  function externalContentSource(deployment) {
3516
3523
  if (deployment.type !== "github-actions") return void 0;
3517
3524
  return deployment.content.type === "external" ? deployment.content : void 0;
@@ -297,7 +297,6 @@ var seo = np("@riebeckite/plugin-seo", "seo", {
297
297
  });
298
298
  var toc = np("@riebeckite/plugin-toc", "tocPlugin");
299
299
  var properties = np("@riebeckite/plugin-properties", "properties", {
300
- render: { depth: 1, value: '"slot"' },
301
300
  include: { depth: 2, value: '["created", "modified", "tags", "status"]' },
302
301
  order: { depth: 2, value: '["created", "modified", "tags", "status"]' }
303
302
  });
@@ -330,7 +329,6 @@ var relatedPosts = np("@riebeckite/plugin-related-posts", "relatedPosts", {
330
329
  className: { depth: 3, value: '"rb-related-posts"' }
331
330
  });
332
331
  var share = np("@riebeckite/plugin-share", "share", {
333
- placement: { depth: 2, value: '"bottom"' },
334
332
  services: {
335
333
  depth: 3,
336
334
  value: '["x", "bluesky", "mastodon", "facebook", "linkedin", "hatena", "copy"]'
@@ -2263,7 +2261,7 @@ function utilityTemplateFiles(utilities) {
2263
2261
  }
2264
2262
 
2265
2263
  // src/scaffold/version.ts
2266
- var RIEBECKITE_VERSION = "^0.0.22";
2264
+ var RIEBECKITE_VERSION = "^0.0.23";
2267
2265
 
2268
2266
  // src/scaffold/templates.ts
2269
2267
  function siteTemplateFiles(preset, variables, options = {}) {
@@ -3180,8 +3178,17 @@ async function scaffoldRiebeckiteSite(options) {
3180
3178
  await fs2.mkdir(path3.dirname(filePath), { recursive: true });
3181
3179
  await fs2.writeFile(filePath, file.content);
3182
3180
  }
3181
+ await ensureContentDirectory(targetDirectory, files);
3183
3182
  return { targetDirectory, files: files.map((file) => file.path) };
3184
3183
  }
3184
+ async function ensureContentDirectory(targetDirectory, files) {
3185
+ if (files.some(
3186
+ (file) => file.path === "content" || file.path.startsWith("content/")
3187
+ )) {
3188
+ return;
3189
+ }
3190
+ await fs2.mkdir(path3.join(targetDirectory, "content"), { recursive: true });
3191
+ }
3185
3192
  function externalContentSource(deployment) {
3186
3193
  if (deployment.type !== "github-actions") return void 0;
3187
3194
  return deployment.content.type === "external" ? deployment.content : void 0;
@@ -1 +1 @@
1
- export declare const RIEBECKITE_VERSION = "^0.0.22";
1
+ export declare const RIEBECKITE_VERSION = "^0.0.23";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-riebeckite",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "esbuild": "^0.28.2",
42
- "@riebeckite/test": "0.0.22"
42
+ "@riebeckite/test": "0.0.23"
43
43
  },
44
44
  "repository": {
45
45
  "type": "git",
@@ -1,48 +1,12 @@
1
- import type { ContentBodySlots, PostContent } from "@riebeckite/core";
2
- import {
3
- Article,
4
- ArticleBody,
5
- ArticleContent,
6
- ArticleLayout,
7
- ContentSlot,
8
- } from "@riebeckite/honox/ui";
1
+ import type { PostContent } from "@riebeckite/core";
2
+ import { Article, ArticleBody, ArticleContent } from "@riebeckite/honox/ui";
9
3
 
10
- export function SiteArticle({
11
- post,
12
- bodySlots,
13
- asideContent,
14
- }: {
15
- post: PostContent;
16
- bodySlots?: ContentBodySlots;
17
- asideContent?: unknown;
18
- }) {
4
+ export function SiteArticle({ post }: { post: PostContent }) {
19
5
  return (
20
6
  <Article class="site-article">
21
- <ArticleLayout>
22
- {asideContent}
23
-
24
- <ContentSlot
25
- slots={bodySlots}
26
- name="article.aside"
27
- class="site-article__aside"
28
- />
29
-
30
- <ArticleContent>
31
- <ContentSlot slots={bodySlots} name="article.header" />
32
- <ContentSlot slots={bodySlots} name="article.metadata" />
33
- <ContentSlot slots={bodySlots} name="article.before-content" />
34
-
35
- <ArticleBody html={post.html ?? ""} />
36
-
37
- <ContentSlot slots={bodySlots} name="article.after-content" />
38
- </ArticleContent>
39
-
40
- <ContentSlot
41
- slots={bodySlots}
42
- name="article.footer"
43
- class="site-article__footer"
44
- />
45
- </ArticleLayout>
7
+ <ArticleContent>
8
+ <ArticleBody html={post.html ?? ""} />
9
+ </ArticleContent>
46
10
  </Article>
47
11
  );
48
12
  }
@@ -20,10 +20,7 @@ export default createRoute(
20
20
  }
21
21
 
22
22
  return c.render(
23
- <SiteArticle
24
- post={resolved.post}
25
- bodySlots={resolved.entry.bodySlots}
26
- />,
23
+ <SiteArticle post={resolved.post} />,
27
24
  );
28
25
  },
29
26
  );
@@ -14,6 +14,6 @@ export default createRoute(async (c) => {
14
14
  }
15
15
 
16
16
  return c.render(
17
- <SiteArticle post={home.post} bodySlots={home.entry.bodySlots} />,
17
+ <SiteArticle post={home.post} />,
18
18
  );
19
19
  });
@@ -29,45 +29,11 @@ body {
29
29
  margin: 0 auto;
30
30
  }
31
31
 
32
- .rb-article-body,
33
- .site-article__footer {
32
+ .rb-article-body {
34
33
  min-width: 0;
35
34
  padding-inline: var(--rb-space-2, 1rem);
36
35
  }
37
36
 
38
- .site-article__aside {
39
- display: none;
40
- }
41
-
42
- @media (min-width: 48rem) {
43
- .site-article__aside {
44
- display: block;
45
- min-width: 0;
46
- margin-block: var(--rb-space-4, 2rem);
47
- }
48
- }
49
-
50
- @media (min-width: 88rem) {
51
- :is(:root, .rb-theme-root)[data-article-layout="article"] .site-article__footer {
52
- grid-column: 1;
53
- }
54
-
55
- :is(:root, .rb-theme-root)[data-article-layout="article"] .site-article__aside {
56
- display: block;
57
- grid-column: 1;
58
- grid-row: 1;
59
- align-self: start;
60
- width: var(--rb-layout-sidebar, 14rem);
61
- margin-inline-start: calc(
62
- -1 * var(--rb-layout-sidebar, 14rem) -
63
- var(--rb-layout-gap, 2rem)
64
- );
65
- padding-inline-end: 1rem;
66
- border-inline-end: 1px solid
67
- color-mix(in oklab, currentColor 18%, transparent);
68
- }
69
- }
70
-
71
37
  .not-found {
72
38
  width: min(100% - 2rem, var(--rb-layout-article-max, 48rem));
73
39
  margin-block: auto;
@@ -1,57 +1,32 @@
1
- import type { ContentBodySlots, PostContent } from "@riebeckite/core";
2
- import {
3
- Article,
4
- ArticleBody,
5
- ArticleContent,
6
- ArticleFooter,
7
- ArticleLayout,
8
- ContentSlot,
9
- hasSlot,
10
- } from "@riebeckite/honox/ui";
1
+ import type { PostContent } from "@riebeckite/core";
2
+ import { Article, ArticleBody, ArticleContent, ArticleFooter } from "@riebeckite/honox/ui";
11
3
 
12
- export function SiteArticle({
13
- post,
14
- bodySlots,
15
- asideContent,
16
- afterContent,
17
- footerContent,
18
- }: {
4
+ type SiteArticleProps = {
19
5
  post: PostContent;
20
- bodySlots?: ContentBodySlots;
21
- asideContent?: unknown;
6
+ header?: unknown;
7
+ metadata?: unknown;
8
+ aside?: unknown;
22
9
  afterContent?: unknown;
23
- footerContent?: unknown;
24
- }) {
10
+ footer?: unknown;
11
+ };
12
+
13
+ export function SiteArticle(props: SiteArticleProps) {
25
14
  return (
26
15
  <Article class="site-article">
27
- <ArticleLayout>
28
- {asideContent}
29
-
30
- <ContentSlot
31
- slots={bodySlots}
32
- name="article.aside"
33
- class="site-article__aside"
34
- />
35
-
16
+ <div class="site-article__layout">
36
17
  <ArticleContent>
37
- <ContentSlot slots={bodySlots} name="article.header" />
38
- <ContentSlot slots={bodySlots} name="article.metadata" />
39
- <ContentSlot slots={bodySlots} name="article.before-content" />
40
-
41
- <ArticleBody html={post.html ?? ""} />
42
-
43
- {afterContent}
44
-
45
- <ContentSlot slots={bodySlots} name="article.after-content" />
18
+ {props.header}
19
+ {props.metadata}
20
+ <ArticleBody html={props.post.html ?? ""} />
21
+ {props.afterContent}
22
+ {props.footer ? (
23
+ <ArticleFooter class="site-article__footer">
24
+ {props.footer}
25
+ </ArticleFooter>
26
+ ) : null}
46
27
  </ArticleContent>
47
-
48
- {hasSlot(bodySlots, "article.footer") || footerContent ? (
49
- <ArticleFooter class="site-article__footer">
50
- <ContentSlot slots={bodySlots} name="article.footer" />
51
- {footerContent}
52
- </ArticleFooter>
53
- ) : null}
54
- </ArticleLayout>
28
+ {props.aside ? <aside class="site-article__aside">{props.aside}</aside> : null}
29
+ </div>
55
30
  </Article>
56
31
  );
57
32
  }
@@ -4,9 +4,16 @@ import {
4
4
  riebeckiteSsgParams,
5
5
  } from "@riebeckite/honox/server";
6
6
  import { PageBody } from "@riebeckite/honox/ui";
7
+ import { createPublicContentView } from "@riebeckite/core";
8
+ import { Backlinks, getBacklinks } from "@riebeckite/plugin-backlinks";
9
+ import { Breadcrumbs, getBreadcrumbs } from "@riebeckite/plugin-breadcrumbs";
10
+ import { Properties, getProperties } from "@riebeckite/plugin-properties";
11
+ import { getRelatedPosts, RelatedPosts, resolveRelatedPostsOptions } from "@riebeckite/plugin-related-posts";
12
+ import { getShareLinks, ShareControls } from "@riebeckite/plugin-share";
7
13
  import { extractTableOfContents, TableOfContents } from "@riebeckite/plugin-toc";
8
14
  import { createRoute } from "honox/factory";
9
15
  import { SiteArticle } from "../components/article";
16
+ import { config } from "virtual:riebeckite/config";
10
17
  import { content } from "virtual:riebeckite/content";
11
18
 
12
19
  export default createRoute(
@@ -21,12 +28,19 @@ export default createRoute(
21
28
  }
22
29
 
23
30
  const tableOfContents = extractTableOfContents(resolved.post.html ?? "");
31
+ const manifest = await content.getManifest();
32
+ const view = createPublicContentView(manifest);
33
+ const entry = view.findRoutableBySlug(resolved.entry.slug);
34
+ if (!entry) return c.notFound();
35
+ const relatedOptions = resolveRelatedPostsOptions({});
24
36
 
25
37
  return c.render(
26
38
  <SiteArticle
27
39
  post={resolved.post}
28
- bodySlots={resolved.entry.bodySlots}
29
- asideContent={<TableOfContents className="rr-table-of-contents--desktop" items={tableOfContents} />}
40
+ header={<Breadcrumbs items={getBreadcrumbs({ view, entry, homeLabel: config.site.title })} />}
41
+ metadata={<Properties data={getProperties({ view, frontmatter: resolved.post.frontmatter, options: { include: ["created", "modified", "tags", "status"], order: ["created", "modified", "tags", "status"] } })} />}
42
+ aside={<TableOfContents className="rr-table-of-contents--desktop" items={tableOfContents} />}
43
+ footer={<><ShareControls {...getShareLinks({ entry, site: config })} /><Backlinks backlinks={getBacklinks({ view, slug: entry.slug })} /><RelatedPosts entries={getRelatedPosts({ view, entry, options: relatedOptions })} options={relatedOptions} /></>}
30
44
  />,
31
45
  );
32
46
  },
@@ -1,7 +1,13 @@
1
1
  import { resolveRiebeckiteHomeRequest } from "@riebeckite/honox/server";
2
2
  import { PageBody } from "@riebeckite/honox/ui";
3
+ import { createPublicContentView } from "@riebeckite/core";
4
+ import { Backlinks, getBacklinks } from "@riebeckite/plugin-backlinks";
5
+ import { Breadcrumbs, getBreadcrumbs } from "@riebeckite/plugin-breadcrumbs";
6
+ import { Properties, getProperties } from "@riebeckite/plugin-properties";
7
+ import { getRelatedPosts, RelatedPosts, resolveRelatedPostsOptions } from "@riebeckite/plugin-related-posts";
3
8
  import { DailyNotes, getDailyNotes } from "@riebeckite/plugin-daily-notes";
4
9
  import { getRecentPosts, RecentPosts } from "@riebeckite/plugin-recent-posts";
10
+ import { getShareLinks, ShareControls } from "@riebeckite/plugin-share";
5
11
  import { extractTableOfContents, TableOfContents } from "@riebeckite/plugin-toc";
6
12
  import { createRoute } from "honox/factory";
7
13
  import { SiteArticle } from "../components/article";
@@ -21,13 +27,19 @@ export default createRoute(async (c) => {
21
27
  const recentPosts = getRecentPosts({ manifest });
22
28
  const dailyNotes = getDailyNotes({ manifest, config });
23
29
  const tableOfContents = extractTableOfContents(home.post.html ?? "");
30
+ const view = createPublicContentView(manifest);
31
+ const entry = view.findRoutableBySlug(home.entry.slug);
32
+ if (!entry) return c.notFound();
33
+ const relatedOptions = resolveRelatedPostsOptions({});
24
34
 
25
35
  return c.render(
26
36
  <SiteArticle
27
37
  post={home.post}
28
- bodySlots={home.entry.bodySlots}
29
- asideContent={<TableOfContents className="rr-table-of-contents--desktop" items={tableOfContents} />}
38
+ header={<Breadcrumbs items={getBreadcrumbs({ view, entry, homeLabel: config.site.title })} />}
39
+ metadata={<Properties data={getProperties({ view, frontmatter: home.post.frontmatter, options: { include: ["created", "modified", "tags", "status"], order: ["created", "modified", "tags", "status"] } })} />}
40
+ aside={<TableOfContents className="rr-table-of-contents--desktop" items={tableOfContents} />}
30
41
  afterContent={<><RecentPosts posts={recentPosts} /><DailyNotes notes={dailyNotes} /></>}
42
+ footer={<><ShareControls {...getShareLinks({ entry, site: config })} /><Backlinks backlinks={getBacklinks({ view, slug: entry.slug })} /><RelatedPosts entries={getRelatedPosts({ view, entry, options: relatedOptions })} options={relatedOptions} /></>}
31
43
  />,
32
44
  );
33
45
  });
@@ -14,6 +14,7 @@ body {
14
14
  }
15
15
 
16
16
  .riebeckite-page {
17
+ --site-toc-sticky-top: var(--rb-space-3, 1.5rem);
17
18
  display: flex;
18
19
  min-height: 100vh;
19
20
  width: 100%;
@@ -165,9 +166,12 @@ body {
165
166
  }
166
167
 
167
168
  .site-article {
168
- display: block;
169
- width: min(100% - 2rem, var(--rb-layout-article-max, 48rem));
169
+ width: min(100% - 2rem, var(--rb-layout-page-max, 80rem));
170
170
  padding-block: 2rem;
171
+ }
172
+
173
+ .site-article__layout {
174
+ width: min(100%, var(--rb-layout-article-max, 48rem));
171
175
  margin: 0 auto;
172
176
  }
173
177
 
@@ -181,32 +185,29 @@ body {
181
185
  display: none;
182
186
  }
183
187
 
184
- @media (min-width: 48rem) {
188
+ @media (min-width: 64rem) {
189
+ .site-article__layout {
190
+ display: grid;
191
+ width: 100%;
192
+ grid-template-columns: minmax(0, var(--rb-layout-article-max, 48rem)) minmax(0, var(--rb-layout-sidebar, 14rem));
193
+ gap: var(--rb-layout-gap, 2rem);
194
+ align-items: start;
195
+ }
196
+
185
197
  .site-article__aside {
186
198
  display: block;
187
199
  min-width: 0;
188
- margin-block: var(--rb-space-4, 2rem);
200
+ align-self: stretch;
189
201
  }
190
- }
191
202
 
192
- @media (min-width: 88rem) {
193
- :is(:root, .rb-theme-root)[data-article-layout="article"] .site-article__footer {
194
- grid-column: 1;
195
- }
196
-
197
- :is(:root, .rb-theme-root)[data-article-layout="article"] .site-article__aside {
198
- display: block;
199
- grid-column: 1;
200
- grid-row: 1;
201
- align-self: start;
202
- width: var(--rb-layout-sidebar, 14rem);
203
- margin-inline-start: calc(
204
- -1 * var(--rb-layout-sidebar, 14rem) -
205
- var(--rb-layout-gap, 2rem)
206
- );
207
- padding-inline-end: 1rem;
208
- border-inline-end: 1px solid
209
- color-mix(in oklab, currentColor 18%, transparent);
203
+ .site-article__aside > .rr-table-of-contents--desktop {
204
+ position: sticky;
205
+ top: var(--site-toc-sticky-top);
206
+ max-height: calc(100dvh - var(--site-toc-sticky-top) - var(--rb-space-4, 2rem));
207
+ overflow-y: auto;
208
+ overscroll-behavior: contain;
209
+ border-inline-start: 1px solid color-mix(in oklab, currentColor 18%, transparent);
210
+ padding-inline-start: 1rem;
210
211
  }
211
212
  }
212
213
 
@@ -1,57 +1,32 @@
1
- import type { ContentBodySlots, PostContent } from "@riebeckite/core";
2
- import {
3
- Article,
4
- ArticleBody,
5
- ArticleContent,
6
- ArticleFooter,
7
- ArticleLayout,
8
- ContentSlot,
9
- hasSlot,
10
- } from "@riebeckite/honox/ui";
1
+ import type { PostContent } from "@riebeckite/core";
2
+ import { Article, ArticleBody, ArticleContent, ArticleFooter } from "@riebeckite/honox/ui";
11
3
 
12
- export function SiteArticle({
13
- post,
14
- bodySlots,
15
- asideContent,
16
- afterContent,
17
- footerContent,
18
- }: {
4
+ type SiteArticleProps = {
19
5
  post: PostContent;
20
- bodySlots?: ContentBodySlots;
21
- asideContent?: unknown;
6
+ header?: unknown;
7
+ metadata?: unknown;
8
+ aside?: unknown;
22
9
  afterContent?: unknown;
23
- footerContent?: unknown;
24
- }) {
10
+ footer?: unknown;
11
+ };
12
+
13
+ export function SiteArticle(props: SiteArticleProps) {
25
14
  return (
26
15
  <Article class="site-article">
27
- <ArticleLayout>
28
- {asideContent}
29
-
30
- <ContentSlot
31
- slots={bodySlots}
32
- name="article.aside"
33
- class="site-article__aside"
34
- />
35
-
16
+ <div class="site-article__layout">
36
17
  <ArticleContent>
37
- <ContentSlot slots={bodySlots} name="article.header" />
38
- <ContentSlot slots={bodySlots} name="article.metadata" />
39
- <ContentSlot slots={bodySlots} name="article.before-content" />
40
-
41
- <ArticleBody html={post.html ?? ""} />
42
-
43
- {afterContent}
44
-
45
- <ContentSlot slots={bodySlots} name="article.after-content" />
18
+ {props.header}
19
+ {props.metadata}
20
+ <ArticleBody html={props.post.html ?? ""} />
21
+ {props.afterContent}
22
+ {props.footer ? (
23
+ <ArticleFooter class="site-article__footer">
24
+ {props.footer}
25
+ </ArticleFooter>
26
+ ) : null}
46
27
  </ArticleContent>
47
-
48
- {hasSlot(bodySlots, "article.footer") || footerContent ? (
49
- <ArticleFooter class="site-article__footer">
50
- <ContentSlot slots={bodySlots} name="article.footer" />
51
- {footerContent}
52
- </ArticleFooter>
53
- ) : null}
54
- </ArticleLayout>
28
+ {props.aside ? <aside class="site-article__aside">{props.aside}</aside> : null}
29
+ </div>
55
30
  </Article>
56
31
  );
57
32
  }
@@ -4,9 +4,15 @@ import {
4
4
  riebeckiteSsgParams,
5
5
  } from "@riebeckite/honox/server";
6
6
  import { PageBody } from "@riebeckite/honox/ui";
7
+ import { createPublicContentView } from "@riebeckite/core";
8
+ import { Backlinks, getBacklinks } from "@riebeckite/plugin-backlinks";
9
+ import { Breadcrumbs, getBreadcrumbs } from "@riebeckite/plugin-breadcrumbs";
10
+ import { Properties, getProperties } from "@riebeckite/plugin-properties";
11
+ import { getRelatedPosts, RelatedPosts, resolveRelatedPostsOptions } from "@riebeckite/plugin-related-posts";
7
12
  import { extractTableOfContents, TableOfContents } from "@riebeckite/plugin-toc";
8
13
  import { createRoute } from "honox/factory";
9
14
  import { SiteArticle } from "../components/article";
15
+ import { config } from "virtual:riebeckite/config";
10
16
  import { content } from "virtual:riebeckite/content";
11
17
 
12
18
  export default createRoute(
@@ -21,12 +27,19 @@ export default createRoute(
21
27
  }
22
28
 
23
29
  const tableOfContents = extractTableOfContents(resolved.post.html ?? "");
30
+ const manifest = await content.getManifest();
31
+ const view = createPublicContentView(manifest);
32
+ const entry = view.findRoutableBySlug(resolved.entry.slug);
33
+ if (!entry) return c.notFound();
34
+ const relatedOptions = resolveRelatedPostsOptions({});
24
35
 
25
36
  return c.render(
26
37
  <SiteArticle
27
38
  post={resolved.post}
28
- bodySlots={resolved.entry.bodySlots}
29
- asideContent={<TableOfContents className="rr-table-of-contents--desktop" items={tableOfContents} />}
39
+ header={<Breadcrumbs items={getBreadcrumbs({ view, entry, homeLabel: config.site.title })} />}
40
+ metadata={<Properties data={getProperties({ view, frontmatter: resolved.post.frontmatter, options: { include: ["created", "modified", "tags", "status"], order: ["created", "modified", "tags", "status"] } })} />}
41
+ aside={<TableOfContents className="rr-table-of-contents--desktop" items={tableOfContents} />}
42
+ footer={<><Backlinks backlinks={getBacklinks({ view, slug: entry.slug })} /><RelatedPosts entries={getRelatedPosts({ view, entry, options: relatedOptions })} options={relatedOptions} /></>}
30
43
  />,
31
44
  );
32
45
  },
@@ -1,9 +1,15 @@
1
1
  import { resolveRiebeckiteHomeRequest } from "@riebeckite/honox/server";
2
2
  import { PageBody } from "@riebeckite/honox/ui";
3
+ import { createPublicContentView } from "@riebeckite/core";
4
+ import { Backlinks, getBacklinks } from "@riebeckite/plugin-backlinks";
5
+ import { Breadcrumbs, getBreadcrumbs } from "@riebeckite/plugin-breadcrumbs";
6
+ import { Properties, getProperties } from "@riebeckite/plugin-properties";
7
+ import { getRelatedPosts, RelatedPosts, resolveRelatedPostsOptions } from "@riebeckite/plugin-related-posts";
3
8
  import { getRecentPosts, RecentPosts } from "@riebeckite/plugin-recent-posts";
4
9
  import { extractTableOfContents, TableOfContents } from "@riebeckite/plugin-toc";
5
10
  import { createRoute } from "honox/factory";
6
11
  import { SiteArticle } from "../components/article";
12
+ import { config } from "virtual:riebeckite/config";
7
13
  import { content } from "virtual:riebeckite/content";
8
14
 
9
15
  export default createRoute(async (c) => {
@@ -15,15 +21,22 @@ export default createRoute(async (c) => {
15
21
  return c.render(<PageBody html={home.page.body} />);
16
22
  }
17
23
 
18
- const recentPosts = getRecentPosts({ manifest: await content.getManifest() });
24
+ const manifest = await content.getManifest();
25
+ const recentPosts = getRecentPosts({ manifest });
19
26
  const tableOfContents = extractTableOfContents(home.post.html ?? "");
27
+ const view = createPublicContentView(manifest);
28
+ const entry = view.findRoutableBySlug(home.entry.slug);
29
+ if (!entry) return c.notFound();
30
+ const relatedOptions = resolveRelatedPostsOptions({});
20
31
 
21
32
  return c.render(
22
33
  <SiteArticle
23
34
  post={home.post}
24
- bodySlots={home.entry.bodySlots}
25
- asideContent={<TableOfContents className="rr-table-of-contents--desktop" items={tableOfContents} />}
26
- afterContent={<><RecentPosts posts={recentPosts} /></>}
35
+ header={<Breadcrumbs items={getBreadcrumbs({ view, entry, homeLabel: config.site.title })} />}
36
+ metadata={<Properties data={getProperties({ view, frontmatter: home.post.frontmatter, options: { include: ["created", "modified", "tags", "status"], order: ["created", "modified", "tags", "status"] } })} />}
37
+ aside={<TableOfContents className="rr-table-of-contents--desktop" items={tableOfContents} />}
38
+ afterContent={<RecentPosts posts={recentPosts} />}
39
+ footer={<><Backlinks backlinks={getBacklinks({ view, slug: entry.slug })} /><RelatedPosts entries={getRelatedPosts({ view, entry, options: relatedOptions })} options={relatedOptions} /></>}
27
40
  />,
28
41
  );
29
42
  });
@@ -14,6 +14,7 @@ body {
14
14
  }
15
15
 
16
16
  .riebeckite-page {
17
+ --site-toc-sticky-top: var(--rb-space-3, 1.5rem);
17
18
  display: flex;
18
19
  min-height: 100vh;
19
20
  width: 100%;
@@ -165,9 +166,12 @@ body {
165
166
  }
166
167
 
167
168
  .site-article {
168
- display: block;
169
- width: min(100% - 2rem, var(--rb-layout-article-max, 48rem));
169
+ width: min(100% - 2rem, var(--rb-layout-page-max, 80rem));
170
170
  padding-block: 2rem;
171
+ }
172
+
173
+ .site-article__layout {
174
+ width: min(100%, var(--rb-layout-article-max, 48rem));
171
175
  margin: 0 auto;
172
176
  }
173
177
 
@@ -181,32 +185,29 @@ body {
181
185
  display: none;
182
186
  }
183
187
 
184
- @media (min-width: 48rem) {
188
+ @media (min-width: 64rem) {
189
+ .site-article__layout {
190
+ display: grid;
191
+ width: 100%;
192
+ grid-template-columns: minmax(0, var(--rb-layout-article-max, 48rem)) minmax(0, var(--rb-layout-sidebar, 14rem));
193
+ gap: var(--rb-layout-gap, 2rem);
194
+ align-items: start;
195
+ }
196
+
185
197
  .site-article__aside {
186
198
  display: block;
187
199
  min-width: 0;
188
- margin-block: var(--rb-space-4, 2rem);
200
+ align-self: stretch;
189
201
  }
190
- }
191
202
 
192
- @media (min-width: 88rem) {
193
- :is(:root, .rb-theme-root)[data-article-layout="article"] .site-article__footer {
194
- grid-column: 1;
195
- }
196
-
197
- :is(:root, .rb-theme-root)[data-article-layout="article"] .site-article__aside {
198
- display: block;
199
- grid-column: 1;
200
- grid-row: 1;
201
- align-self: start;
202
- width: var(--rb-layout-sidebar, 14rem);
203
- margin-inline-start: calc(
204
- -1 * var(--rb-layout-sidebar, 14rem) -
205
- var(--rb-layout-gap, 2rem)
206
- );
207
- padding-inline-end: 1rem;
208
- border-inline-end: 1px solid
209
- color-mix(in oklab, currentColor 18%, transparent);
203
+ .site-article__aside > .rr-table-of-contents--desktop {
204
+ position: sticky;
205
+ top: var(--site-toc-sticky-top);
206
+ max-height: calc(100dvh - var(--site-toc-sticky-top) - var(--rb-space-4, 2rem));
207
+ overflow-y: auto;
208
+ overscroll-behavior: contain;
209
+ border-inline-start: 1px solid color-mix(in oklab, currentColor 18%, transparent);
210
+ padding-inline-start: 1rem;
210
211
  }
211
212
  }
212
213