-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
blog.server.js
86 lines (80 loc) · 2.29 KB
/
blog.server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import React, {createElement} from 'react'
import {apStyleTitleCase} from 'ap-style-title-case'
import {toH} from 'hast-to-hyperscript'
import {sortItems} from './sort.js'
const dateTimeFormat = new Intl.DateTimeFormat('en', {dateStyle: 'long'})
export function BlogEntry(props) {
const {item} = props
const {name, data = {}} = item
const {matter = {}, meta = {}} = data
const title = matter.title || meta.title
const defaultTitle = apStyleTitleCase(
name.replace(/\/$/, '').split('/').pop()
)
const description = matter.description || meta.description
const time = (
meta.readingTime
? Array.isArray(meta.readingTime)
? meta.readingTime
: [meta.readingTime, meta.readingTime]
: []
).map((d) => Math.ceil(d))
let timeLabel
if (time.length > 1 && time[0] !== time[1]) {
timeLabel = time[0] + '-' + time[1] + ' minutes'
} else if (time[0]) {
timeLabel = time[0] + ' minute' + (time[0] > 1 ? 's' : '')
}
return (
<div className="card">
<h3>
<a href={name}>{title || defaultTitle}</a>
</h3>
<div>
{meta.descriptionHast ? (
toH(createElement, meta.descriptionHast)
) : description ? (
<p>{description}</p>
) : null}
<span>
<a href={name}>Continue reading »</a>
</span>
</div>
<div
style={{display: 'flex', justifyContent: 'space-between'}}
className="block"
>
<div>
{meta.author ? (
<>
<small>By {meta.author}</small>
<br />
</>
) : undefined}
<small>Reading time: {timeLabel}</small>
</div>
{meta.published ? (
<div style={{marginLeft: 'auto', textAlign: 'right'}}>
<small>
Published on{' '}
<time dateTime={meta.published.toISOString()}>
{dateTimeFormat.format(meta.published)}
</time>
</small>
</div>
) : undefined}
</div>
</div>
)
}
export function BlogGroup(props) {
const {items, className, sort = 'navSortSelf,meta.title', ...rest} = props
const sorted = sortItems(items, sort)
return (
<>
{sorted.map((d) => (
<BlogEntry key={d.name} {...rest} item={d} />
))}
</>
)
}