astro-pure 1.2.3 → 1.2.4
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/components/pages/ArticleBottom.astro +1 -1
- package/components/pages/Copyright.astro +14 -12
- package/components/pages/Hero.astro +4 -4
- package/components/pages/PostPreview.astro +1 -1
- package/components/pages/TOC.astro +7 -8
- package/components/user/CardList.astro +21 -15
- package/components/user/CardListChildren.astro +11 -4
- package/index.ts +2 -2
- package/package.json +1 -1
- package/schemas/links.ts +12 -12
- package/scripts/check.mjs +39 -0
- package/scripts/index.js +4 -0
- package/types/index.ts +1 -1
- package/utils/server.ts +15 -7
|
@@ -61,7 +61,7 @@ const next = collections[index + 1]
|
|
|
61
61
|
next && (
|
|
62
62
|
<a
|
|
63
63
|
href={`${path}/${next.id}`}
|
|
64
|
-
class='group inline-flex items-center gap-x-2 rounded-xl px-4 py-2 text-right no-underline transition-colors duration-300 hover:bg-muted max-sm:max-w-[80%] sm:flex'
|
|
64
|
+
class='group inline-flex items-center gap-x-2 rounded-xl px-4 py-2 text-right no-underline transition-colors duration-300 hover:bg-muted max-sm:float-end max-sm:max-w-[80%] sm:flex'
|
|
65
65
|
>
|
|
66
66
|
<p class='truncate font-medium transition-colors'>{next.data.title}</p>
|
|
67
67
|
<svg
|
|
@@ -6,8 +6,8 @@ import { cn, getFormattedDate } from '../../utils'
|
|
|
6
6
|
import { QRCode } from '../advanced'
|
|
7
7
|
import { Icon } from '../user'
|
|
8
8
|
|
|
9
|
-
interface Props {
|
|
10
|
-
data: InferEntrySchema<
|
|
9
|
+
interface Props<T extends CollectionKey> {
|
|
10
|
+
data: InferEntrySchema<T>
|
|
11
11
|
class?: string
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -51,16 +51,18 @@ const shares = {
|
|
|
51
51
|
<span>Author</span>
|
|
52
52
|
<span class='text-sm text-foreground max-sm:place-self-center'>{config.author}</span>
|
|
53
53
|
</div>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
{
|
|
55
|
+
publishDate && (
|
|
56
|
+
<div class='flex gap-x-2 sm:min-w-16 sm:flex-col'>
|
|
57
|
+
<span>Published at</span>
|
|
58
|
+
<span class='text-sm text-foreground max-sm:place-self-center'>
|
|
59
|
+
{getFormattedDate(publishDate, {
|
|
60
|
+
month: 'long'
|
|
61
|
+
})}
|
|
62
|
+
</span>
|
|
63
|
+
</div>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
64
66
|
<div class='flex gap-x-2 sm:flex-col'>
|
|
65
67
|
<span>Copyright</span>
|
|
66
68
|
<a
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { Image } from 'astro:assets'
|
|
3
|
-
import
|
|
3
|
+
import type { InferEntrySchema } from 'astro:content'
|
|
4
4
|
|
|
5
5
|
import { PageInfo } from '.'
|
|
6
6
|
import { FormattedDate, Icon } from '../user'
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
9
|
-
data: InferEntrySchema<
|
|
9
|
+
data: InferEntrySchema<'blog'>
|
|
10
10
|
remarkPluginFrontmatter: Record<string, unknown>
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -38,15 +38,15 @@ const dateTimeOptions: Intl.DateTimeFormatOptions = {
|
|
|
38
38
|
class='cover-image relative z-10 h-auto w-full max-w-[65ch] rounded-2xl object-contain'
|
|
39
39
|
fetchpriority='high'
|
|
40
40
|
loading='eager'
|
|
41
|
-
|
|
41
|
+
{...heroImage}
|
|
42
42
|
/>
|
|
43
43
|
<Image
|
|
44
44
|
alt='Blur image'
|
|
45
45
|
fetchpriority='high'
|
|
46
46
|
loading='eager'
|
|
47
|
-
src={heroImage.src}
|
|
48
47
|
id='blurImage'
|
|
49
48
|
class='absolute end-0 top-4 z-0 mt-0 h-full max-w-[65ch] rounded-3xl opacity-60 blur-xl transition-opacity duration-300'
|
|
49
|
+
{...heroImage}
|
|
50
50
|
/>
|
|
51
51
|
</div>
|
|
52
52
|
)
|
|
@@ -43,10 +43,10 @@ const postDate = data.updatedDate ?? data.publishDate
|
|
|
43
43
|
{
|
|
44
44
|
detailed && data.heroImage && (
|
|
45
45
|
<Image
|
|
46
|
-
src={data.heroImage.src}
|
|
47
46
|
alt={data.heroImage.alt || data.title}
|
|
48
47
|
class='cover-image absolute end-0 top-0 z-0 h-2/3 w-full rounded-2xl object-cover opacity-50 transition-opacity duration-300 group-hover/card:opacity-70 md:h-full md:w-3/5'
|
|
49
48
|
loading='eager'
|
|
49
|
+
{...data.heroImage}
|
|
50
50
|
/>
|
|
51
51
|
)
|
|
52
52
|
}
|
|
@@ -7,6 +7,7 @@ import TOCHeading from './TOCHeading.astro'
|
|
|
7
7
|
interface Props {
|
|
8
8
|
headings: MarkdownHeading[]
|
|
9
9
|
class?: string
|
|
10
|
+
id?: string
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const { headings, class: className, ...props } = Astro.props
|
|
@@ -14,14 +15,12 @@ const { headings, class: className, ...props } = Astro.props
|
|
|
14
15
|
const toc = generateToc(headings)
|
|
15
16
|
---
|
|
16
17
|
|
|
17
|
-
<
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
</toc-heading>
|
|
24
|
-
</aside>
|
|
18
|
+
<toc-heading class={className} {...props}>
|
|
19
|
+
<h2 class='font-semibold'>TABLE OF CONTENTS</h2>
|
|
20
|
+
<ul class='mt-4 text-card-foreground'>
|
|
21
|
+
{toc.map((heading) => <TOCHeading heading={heading} />)}
|
|
22
|
+
</ul>
|
|
23
|
+
</toc-heading>
|
|
25
24
|
|
|
26
25
|
<script>
|
|
27
26
|
// This script tag is useful only if you want to display the TOC alongside the blog post...
|
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { CardListData } from '../../types'
|
|
3
|
+
import { cn } from '../../utils'
|
|
3
4
|
import Collapse from '../user/Collapse.astro'
|
|
4
5
|
import CardListChildren from './CardListChildren.astro'
|
|
5
6
|
|
|
6
7
|
type Props = CardListData & {
|
|
7
8
|
collapse?: boolean
|
|
8
9
|
class?: string
|
|
10
|
+
style?: string | Record<string, string>
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
const { title, list, collapse, class: className } = Astro.props
|
|
13
|
+
const { title, list, collapse, class: className, ...props } = Astro.props
|
|
12
14
|
---
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
</
|
|
16
|
+
{
|
|
17
|
+
collapse ? (
|
|
18
|
+
<Collapse title={title} class={cn('not-prose', className)} {...props}>
|
|
19
|
+
<CardListChildren children={list} main />
|
|
20
|
+
</Collapse>
|
|
21
|
+
) : (
|
|
22
|
+
<div
|
|
23
|
+
class={cn(
|
|
24
|
+
'not-prose my-3 flex flex-col gap-y-2 rounded-xl border px-4 py-3 sm:py-4',
|
|
25
|
+
className
|
|
26
|
+
)}
|
|
27
|
+
{...props}
|
|
28
|
+
>
|
|
29
|
+
<p class='text-lg font-medium text-foreground'>{title}</p>
|
|
30
|
+
<CardListChildren children={list} main />
|
|
31
|
+
</div>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
@@ -2,17 +2,24 @@
|
|
|
2
2
|
import type { CardList } from '../../types'
|
|
3
3
|
import { cn } from '../../utils'
|
|
4
4
|
|
|
5
|
-
type Props = { children: CardList }
|
|
6
|
-
const { children } = Astro.props
|
|
5
|
+
type Props = { main?: boolean; children: CardList }
|
|
6
|
+
const { main = false, children } = Astro.props
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
<ul class='
|
|
9
|
+
<ul class={cn('flex flex-col gap-y-1', !main && 'list-disc ms-5')}>
|
|
10
10
|
{
|
|
11
11
|
children.map((child) => {
|
|
12
12
|
const Tag = child.link ? 'a' : 'p'
|
|
13
13
|
return (
|
|
14
14
|
<li>
|
|
15
|
-
<Tag
|
|
15
|
+
<Tag
|
|
16
|
+
href={child.link}
|
|
17
|
+
class={cn(
|
|
18
|
+
'block',
|
|
19
|
+
main ? 'text-foreground' : 'text-muted-foreground',
|
|
20
|
+
Tag == 'p' && 'mb-2 mt-1'
|
|
21
|
+
)}
|
|
22
|
+
>
|
|
16
23
|
{child.title}
|
|
17
24
|
</Tag>
|
|
18
25
|
{child.children && child.children.length > 0 && <Astro.self children={child.children} />}
|
package/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process'
|
|
2
|
-
import { dirname, relative } from 'node:path'
|
|
2
|
+
import path, { dirname, relative } from 'node:path'
|
|
3
3
|
import { fileURLToPath } from 'node:url'
|
|
4
4
|
// Astro
|
|
5
5
|
import type { AstroIntegration, RehypePlugins, RemarkPlugins } from 'astro'
|
|
@@ -25,7 +25,7 @@ export default function AstroPureIntegration(opts: UserInputConfig): AstroIntegr
|
|
|
25
25
|
let userConfig = parseWithFriendlyErrors(
|
|
26
26
|
UserConfigSchema,
|
|
27
27
|
opts,
|
|
28
|
-
'Invalid config passed to
|
|
28
|
+
'Invalid config passed to astro-pure integration'
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
// Add built-in integrations only if they are not already added by the user through the
|
package/package.json
CHANGED
package/schemas/links.ts
CHANGED
|
@@ -9,20 +9,20 @@ export const FriendLinksSchema = () =>
|
|
|
9
9
|
content: z.string()
|
|
10
10
|
})
|
|
11
11
|
),
|
|
12
|
-
applyTip: z.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
applyTip: z.array(
|
|
13
|
+
z.object({
|
|
14
|
+
name: z.string(),
|
|
15
|
+
val: z.string()
|
|
16
|
+
})
|
|
17
|
+
)
|
|
18
18
|
})
|
|
19
19
|
.default({
|
|
20
20
|
logbook: [],
|
|
21
|
-
applyTip:
|
|
22
|
-
name: 'Astro Pure',
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
applyTip: [
|
|
22
|
+
{ name: 'Name', val: 'Astro Pure' },
|
|
23
|
+
{ name: 'Desc', val: 'Null' },
|
|
24
|
+
{ name: 'Link', val: 'https://astro-pure.js.org/' },
|
|
25
|
+
{ name: 'Avatar', val: 'https://astro-pure.js.org/favicon/favicon.ico' }
|
|
26
|
+
]
|
|
27
27
|
})
|
|
28
28
|
.describe('Friend links for your website.')
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { exec } from 'child_process'
|
|
2
|
+
|
|
3
|
+
const runCommand = (command, cwd, timeout = 5000) => {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const child = exec(command, { cwd, timeout }, (error, stdout, stderr) => {
|
|
6
|
+
if (error) {
|
|
7
|
+
reject(`Error: ${stderr}`)
|
|
8
|
+
} else {
|
|
9
|
+
resolve(stdout)
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
child.on('error', (error) => {
|
|
14
|
+
reject(`Execution error: ${error.message}`)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
child.on('exit', (code) => {
|
|
18
|
+
if (code !== 0) {
|
|
19
|
+
reject(`Command exited with code ${code}`)
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default async function main() {
|
|
26
|
+
if (process.env.BUN_LINK_PKG === 'true') {
|
|
27
|
+
try {
|
|
28
|
+
console.log('Running "bun link" at "./packages/pure"')
|
|
29
|
+
console.log(await runCommand('bun link', './packages/pure'))
|
|
30
|
+
console.log('Running "bun link astro-pure" at "."')
|
|
31
|
+
console.log(await runCommand('bun link astro-pure', '.'))
|
|
32
|
+
console.log('Commands executed successfully.')
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error(error)
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
console.log('BUN_LINK_PKG is not set to true. Skipping commands.')
|
|
38
|
+
}
|
|
39
|
+
}
|
package/scripts/index.js
CHANGED
|
@@ -5,12 +5,16 @@ import { readFileSync } from 'fs'
|
|
|
5
5
|
import { dirname, join } from 'path'
|
|
6
6
|
import { fileURLToPath } from 'url'
|
|
7
7
|
|
|
8
|
+
import checkFunc from './check.mjs'
|
|
8
9
|
import minimist from './libs/minimist.cjs'
|
|
9
10
|
import newFunc from './new.mjs'
|
|
10
11
|
|
|
11
12
|
const args = minimist(process.argv.slice(2))
|
|
12
13
|
|
|
13
14
|
switch (args._[0]) {
|
|
15
|
+
case 'check':
|
|
16
|
+
await checkFunc()
|
|
17
|
+
break
|
|
14
18
|
case 'new':
|
|
15
19
|
const newArgs = process.argv.slice(3)
|
|
16
20
|
newFunc(newArgs)
|
package/types/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Icons } from '../libs/icons'
|
|
|
2
2
|
|
|
3
3
|
export type { IntegrationUserConfig } from './integrations-config'
|
|
4
4
|
export type { ThemeUserConfig } from './theme-config'
|
|
5
|
-
export type { UserInputConfig as Config } from './user-config'
|
|
5
|
+
export type { UserInputConfig as Config, UserConfig as ConfigOutput } from './user-config'
|
|
6
6
|
|
|
7
7
|
export interface SiteMeta {
|
|
8
8
|
title: string
|
package/utils/server.ts
CHANGED
|
@@ -12,15 +12,23 @@ export async function getBlogCollection(contentType: CollectionKey = 'blog') {
|
|
|
12
12
|
})
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
function getYearFromCollection<T extends CollectionKey>(
|
|
16
|
+
collection: CollectionEntry<T>
|
|
17
|
+
): number | undefined {
|
|
18
|
+
const dateStr = collection.data.updatedDate ?? collection.data.publishDate
|
|
19
|
+
return dateStr ? new Date(dateStr).getFullYear() : undefined
|
|
20
|
+
}
|
|
15
21
|
export function groupCollectionsByYear<T extends CollectionKey>(
|
|
16
22
|
collections: Collections
|
|
17
23
|
): [number, CollectionEntry<T>[]][] {
|
|
18
24
|
const collectionsByYear = collections.reduce((acc, collection) => {
|
|
19
|
-
const year =
|
|
20
|
-
if (
|
|
21
|
-
acc.
|
|
25
|
+
const year = getYearFromCollection(collection)
|
|
26
|
+
if (year !== undefined) {
|
|
27
|
+
if (!acc.has(year)) {
|
|
28
|
+
acc.set(year, [])
|
|
29
|
+
}
|
|
30
|
+
acc.get(year)!.push(collection)
|
|
22
31
|
}
|
|
23
|
-
acc.get(year)!.push(collection)
|
|
24
32
|
return acc
|
|
25
33
|
}, new Map<number, Collections>())
|
|
26
34
|
|
|
@@ -29,10 +37,10 @@ export function groupCollectionsByYear<T extends CollectionKey>(
|
|
|
29
37
|
).sort((a, b) => b[0] - a[0])
|
|
30
38
|
}
|
|
31
39
|
|
|
32
|
-
export function sortMDByDate(collections: Collections) {
|
|
40
|
+
export function sortMDByDate(collections: Collections): Collections {
|
|
33
41
|
return collections.sort((a, b) => {
|
|
34
|
-
const aDate = new Date(a.data.updatedDate ?? a.data.publishDate).valueOf()
|
|
35
|
-
const bDate = new Date(b.data.updatedDate ?? b.data.publishDate).valueOf()
|
|
42
|
+
const aDate = new Date(a.data.updatedDate ?? a.data.publishDate ?? 0).valueOf()
|
|
43
|
+
const bDate = new Date(b.data.updatedDate ?? b.data.publishDate ?? 0).valueOf()
|
|
36
44
|
return bDate - aDate
|
|
37
45
|
})
|
|
38
46
|
}
|