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.
@@ -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<CollectionKey>
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
- <div class='flex gap-x-2 sm:min-w-16 sm:flex-col'>
55
- <span>Published at</span>
56
- <span class='text-sm text-foreground max-sm:place-self-center'
57
- >{
58
- getFormattedDate(publishDate, {
59
- month: 'long'
60
- })
61
- }</span
62
- >
63
- </div>
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 { type CollectionKey, type InferEntrySchema } from 'astro:content'
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<CollectionKey>
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
- src={heroImage.src}
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
- <aside class={className} id='sidebar' {...props}>
18
- <toc-heading>
19
- <h2 class='font-semibold'>TABLE OF CONTENTS</h2>
20
- <ul class='mt-4 max-h-[70vh] overflow-y-scroll text-card-foreground'>
21
- {toc.map((heading) => <TOCHeading heading={heading} />)}
22
- </ul>
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
- <div class={className}>
15
- {
16
- collapse ? (
17
- <Collapse title={title} class='not-prose'>
18
- <CardListChildren children={list} />
19
- </Collapse>
20
- ) : (
21
- <div class='not-prose my-3 flex flex-col gap-y-2 rounded-xl border px-4 py-3 sm:py-4'>
22
- <p class='text-lg font-medium text-foreground'>{title}</p>
23
- <CardListChildren children={list} />
24
- </div>
25
- )
26
- }
27
- </div>
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='ms-5 flex list-disc flex-col gap-y-1'>
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 href={child.link} class={cn('block', Tag == 'a' && 'text-foreground')}>
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 starlight integration'
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-pure",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "description": "A simple, clean but powerful blog theme build by astro.",
5
5
  "type": "module",
6
6
  "author": "CWorld",
package/schemas/links.ts CHANGED
@@ -9,20 +9,20 @@ export const FriendLinksSchema = () =>
9
9
  content: z.string()
10
10
  })
11
11
  ),
12
- applyTip: z.object({
13
- name: z.string(),
14
- desc: z.string(),
15
- url: z.string(),
16
- avatar: z.string()
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
- desc: 'Stay hungry, stay foolish.',
24
- url: 'https://astro-pure.js.org',
25
- avatar: 'https://astro-pure.js.org/favicon/favicon.ico'
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 = new Date(collection.data.updatedDate ?? collection.data.publishDate).getFullYear()
20
- if (!acc.has(year)) {
21
- acc.set(year, [])
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
  }