@ansidev-oss/vitepress-theme-ansidev 1.1.0 → 1.3.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.
Files changed (59) hide show
  1. package/dist/client/{Swetrix-k7SUudua.js → Swetrix-GKEyGNrV.js} +29 -6
  2. package/dist/client/index.js +54 -54
  3. package/dist/client/styles.css +1 -1
  4. package/dist/client/types/index.d.ts +8 -0
  5. package/dist/node/composables/excerpt.d.ts +9 -0
  6. package/dist/node/composables/excerpt.test.d.ts +1 -0
  7. package/dist/node/composables/index.d.ts +1 -0
  8. package/dist/node/composables.d.mts +9 -0
  9. package/dist/node/composables.mjs +33 -1
  10. package/package.json +20 -24
  11. package/src/client/components/DonationWidget.vue +9 -3
  12. package/src/client/components/Footer.vue +11 -4
  13. package/src/client/components/Link.vue +11 -5
  14. package/src/client/components/LocaleSwitcher.vue +5 -5
  15. package/src/client/components/PostDate.test.ts +16 -7
  16. package/src/client/components/PostDate.vue +16 -7
  17. package/src/client/components/PostItem.vue +17 -7
  18. package/src/client/components/PostList.vue +7 -4
  19. package/src/client/components/ProjectCard.vue +42 -14
  20. package/src/client/components/ProjectList.vue +12 -5
  21. package/src/client/components/RouterLink.vue +3 -3
  22. package/src/client/components/SharingWidget.vue +3 -1
  23. package/src/client/components/StatusBadge.vue +10 -10
  24. package/src/client/components/TermBadge.vue +11 -7
  25. package/src/client/components/TermLink.vue +4 -4
  26. package/src/client/composables/date.ts +1 -1
  27. package/src/client/composables/lang.test.ts +6 -2
  28. package/src/client/composables/lang.ts +12 -5
  29. package/src/client/composables/locale.ts +4 -1
  30. package/src/client/composables/project.ts +3 -3
  31. package/src/client/composables/rank.ts +5 -2
  32. package/src/client/index.ts +1 -1
  33. package/src/client/layouts/Layout.vue +2 -2
  34. package/src/client/pages/ArchivesPage.vue +10 -5
  35. package/src/client/pages/CategoriesPage.vue +13 -5
  36. package/src/client/pages/HomePage.vue +3 -3
  37. package/src/client/pages/Page.vue +13 -11
  38. package/src/client/pages/PostsPage.vue +4 -4
  39. package/src/client/pages/ProjectsPage.vue +10 -7
  40. package/src/client/pages/TagsPage.vue +10 -4
  41. package/src/client/plugins/donation/components/Donation.vue +5 -3
  42. package/src/client/plugins/donation/components/DonationButton.vue +3 -1
  43. package/src/client/plugins/donation/index.ts +11 -8
  44. package/src/client/plugins/i18n/index.ts +2 -2
  45. package/src/client/plugins/sharing/components/Sharing.vue +39 -15
  46. package/src/client/plugins/sharing/components/SharingButton.vue +34 -14
  47. package/src/client/plugins/sharing/index.ts +3 -1
  48. package/src/client/styles/base.css +1 -1
  49. package/src/client/styles/blog.css +38 -14
  50. package/src/client/styles/index.css +2 -3
  51. package/src/client/types/index.ts +8 -0
  52. package/src/node/composables/excerpt.test.ts +88 -0
  53. package/src/node/composables/excerpt.ts +57 -0
  54. package/src/node/composables/index.ts +1 -0
  55. package/src/node/composables/markdown.ts +8 -2
  56. package/src/node/composables/route.ts +15 -7
  57. package/src/node/composables/slug.ts +12 -4
  58. package/src/node/config.ts +20 -14
  59. package/src/shared/composables/useSlug.ts +2 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ansidev-oss/vitepress-theme-ansidev",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "The VitePress theme for ansidev's blog",
5
5
  "type": "module",
6
6
  "main": "dist/node/index.js",
@@ -27,7 +27,10 @@
27
27
  "import": "./dist/client/index.js",
28
28
  "types": "./dist/client/index.d.ts"
29
29
  },
30
- "./styles.css": "./dist/client/styles.css",
30
+ "./styles.css": {
31
+ "import": "./dist/client/styles.css",
32
+ "types": "./styles.d.ts"
33
+ },
31
34
  "./config": {
32
35
  "import": "./dist/node/config.mjs",
33
36
  "types": "./dist/node/config.d.ts"
@@ -39,49 +42,46 @@
39
42
  },
40
43
  "files": [
41
44
  "dist",
45
+ "!dist/.pack",
42
46
  "src",
43
47
  "README.md",
44
48
  "LICENSE"
45
49
  ],
46
50
  "dependencies": {
47
51
  "@tailwindcss/vite": "^4.2.0",
48
- "@vueuse/core": "^14.2.1",
52
+ "@vueuse/core": "^15.0.0",
53
+ "markdown-it": "^15.0.3",
49
54
  "vue-i18n": "^11.2.8"
50
55
  },
51
56
  "devDependencies": {
52
- "@biomejs/biome": "2.6.3",
53
57
  "@iconify/vue": "^5.0.0",
54
58
  "@tailwindcss/postcss": "^4.2.0",
55
- "@types/node": "^25.3.0",
59
+ "@types/markdown-it": "^14.2.0",
60
+ "@types/node": "^26.0.0",
56
61
  "@vitejs/plugin-vue": "^6.0.4",
57
62
  "@vue/test-utils": "^2.5.1",
58
63
  "autoprefixer": "^10.4.24",
59
- "concurrently": "^10.0.0",
60
- "glob": "^13.0.6",
64
+ "glob": "^14.0.0",
61
65
  "gray-matter": "^4.0.3",
62
66
  "happy-dom": "^21.0.4",
63
67
  "medium-zoom": "^1.1.0",
64
68
  "postcss": "^8.5.6",
65
- "prettier": "^3.8.1",
66
69
  "rimraf": "^6.1.3",
67
70
  "swetrix": "^4.1.0",
68
71
  "tailwindcss": "^4.2.0",
69
- "ts-node": "^10.9.2",
70
- "tsdown": "^0.23.0",
71
72
  "typescript": "^6.0.0",
72
- "vite": "^8.0.0",
73
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.4.0",
73
74
  "vitepress": "^2.0.0-alpha.16",
74
- "vitest": "^5.0.5",
75
75
  "vue": "^3.5.28",
76
- "vue-tsc": "^3.2.5"
76
+ "vue-tsc": "^3.2.5",
77
+ "vite-plus": "1.4.0"
77
78
  },
78
79
  "peerDependencies": {
79
80
  "@iconify/vue": "^5.0.0",
80
- "glob": "^13.0.6",
81
+ "glob": "^13.0.6 || ^14.0.0",
81
82
  "gray-matter": "^4.0.3",
82
83
  "medium-zoom": "^1.1.0",
83
84
  "swetrix": "^4.1.0",
84
- "ts-node": "^10.9.2",
85
85
  "typescript": "^5.9.3",
86
86
  "vitepress": "^2.0.0-alpha.16",
87
87
  "vue": "^3.5.28"
@@ -92,15 +92,11 @@
92
92
  },
93
93
  "scripts": {
94
94
  "typecheck": "tsc --noEmit",
95
- "test": "vitest run",
96
- "lint:check": "biome check",
97
- "lint": "biome check --write",
98
- "dev:client": "vite build --watch",
99
- "dev:node": "tsdown --watch",
100
- "dev": "concurrently --kill-others \"pnpm dev:client\" \"pnpm dev:node\"",
95
+ "test": "vp test run",
96
+ "lint:check": "vp check",
97
+ "lint": "vp check --fix",
101
98
  "clean": "rimraf dist",
102
- "build:client": "vite build && tsc --emitDeclarationOnly",
103
- "build:node": "tsdown",
104
- "build": "pnpm clean && concurrently \"pnpm build:client\" \"pnpm build:node\""
99
+ "build": "vp run build:all",
100
+ "dev": "vp build --watch & vp pack --watch --on-success \"node ../../scripts/publish-node.mjs && node ../../scripts/touch-demo.mjs\" & wait"
105
101
  }
106
102
  }
@@ -8,15 +8,21 @@ const props = defineProps<{
8
8
  direction?: 'horizontal' | 'vertical'
9
9
  }>()
10
10
 
11
- const directionCssClass = props.direction === 'vertical' ? 'space-y-4' : 'space-x-4'
11
+ const directionCssClass =
12
+ props.direction === 'vertical' ? 'space-y-4' : 'space-x-4'
12
13
 
13
14
  const Donation = theme.value.donation
14
- ? defineAsyncComponent(() => import('../plugins/donation/components/Donation.vue'))
15
+ ? defineAsyncComponent(
16
+ () => import('../plugins/donation/components/Donation.vue')
17
+ )
15
18
  : () => null
16
19
  </script>
17
20
 
18
21
  <template>
19
- <div class="flex flex-wrap py-4 items-center justify-center" :class="directionCssClass">
22
+ <div
23
+ class="flex flex-wrap py-4 items-center justify-center"
24
+ :class="directionCssClass"
25
+ >
20
26
  <Donation :donation="theme.donation" />
21
27
  </div>
22
28
  </template>
@@ -9,16 +9,23 @@ const { hasSidebar, hasAside } = useLayout()
9
9
 
10
10
  const copyright = computed(() => {
11
11
  return typeof theme.value.themeFooter.copyright === 'string'
12
- ? theme.value.themeFooter.copyright.replace(/#\{present\}/g, new Date().getFullYear().toString())
12
+ ? theme.value.themeFooter.copyright.replace(
13
+ /#\{present\}/g,
14
+ new Date().getFullYear().toString()
15
+ )
13
16
  : theme.value.themeFooter.copyright
14
17
  })
15
18
 
16
19
  const GoogleAnalytics = theme.value.googleAnalytics
17
- ? defineAsyncComponent(() => import('../plugins/google-analytics/components/GoogleAnalytics.vue'))
20
+ ? defineAsyncComponent(
21
+ () => import('../plugins/google-analytics/components/GoogleAnalytics.vue')
22
+ )
18
23
  : () => null
19
24
 
20
25
  const Swetrix = theme.value.swetrix
21
- ? defineAsyncComponent(() => import('../plugins/swetrix/components/Swetrix.vue'))
26
+ ? defineAsyncComponent(
27
+ () => import('../plugins/swetrix/components/Swetrix.vue')
28
+ )
22
29
  : () => null
23
30
  </script>
24
31
 
@@ -58,7 +65,7 @@ const Swetrix = theme.value.swetrix
58
65
  .VPFooter :deep(a) {
59
66
  text-decoration-line: underline;
60
67
  text-underline-offset: 2px;
61
- transition: color 0.25s;
68
+ transition: none;
62
69
  }
63
70
 
64
71
  .VPFooter :deep(a:hover) {
@@ -1,17 +1,17 @@
1
- <script setup lang='ts'>
1
+ <script setup lang="ts">
2
2
  import RouterLink from './RouterLink.vue'
3
3
 
4
4
  const props = defineProps({
5
5
  href: {
6
6
  type: String,
7
7
  required: true,
8
- default: '#',
8
+ default: '#'
9
9
  },
10
10
  disableRouterLink: {
11
11
  type: Boolean,
12
12
  required: false,
13
- default: false,
14
- },
13
+ default: false
14
+ }
15
15
  })
16
16
 
17
17
  const isInternalLink = props.href?.startsWith('/') && !props.disableRouterLink
@@ -25,7 +25,13 @@ const isAnchorLink = props.href?.startsWith('#')
25
25
  <a v-else-if="disableRouterLink" target="_self" :href="href" v-bind="$attrs">
26
26
  <slot />
27
27
  </a>
28
- <a v-else target="_blank" rel="noopener noreferrer" :href="href" v-bind="$attrs">
28
+ <a
29
+ v-else
30
+ target="_blank"
31
+ rel="noopener noreferrer"
32
+ :href="href"
33
+ v-bind="$attrs"
34
+ >
29
35
  <slot />
30
36
  </a>
31
37
  </template>
@@ -6,8 +6,8 @@ defineProps({
6
6
  size: {
7
7
  type: Number,
8
8
  required: false,
9
- default: 20,
10
- },
9
+ default: 20
10
+ }
11
11
  })
12
12
 
13
13
  const { t, availableLocales, locale } = useI18n()
@@ -33,7 +33,7 @@ const toggleLocale = () => switchLocale(availableLocales, locale)
33
33
  width: 1px;
34
34
  height: 24px;
35
35
  background-color: var(--vp-c-divider);
36
- content: "";
36
+ content: '';
37
37
  }
38
38
 
39
39
  .VPLocaleSwitcher {
@@ -43,12 +43,12 @@ const toggleLocale = () => switchLocale(availableLocales, locale)
43
43
  width: 36px;
44
44
  height: 36px;
45
45
  color: var(--vp-c-text-2);
46
- transition: color 0.5s;
46
+ transition: none;
47
47
  }
48
48
 
49
49
  .VPLocaleSwitcher:hover {
50
50
  color: var(--vp-c-text-1);
51
- transition: color 0.25s;
51
+ transition: none;
52
52
  }
53
53
 
54
54
  .VPLocaleSwitcher > :deep(svg) {
@@ -1,19 +1,24 @@
1
1
  import { mount } from '@vue/test-utils'
2
- import { afterEach, describe, expect, it, vi } from 'vitest'
2
+ import { afterEach, describe, expect, it, vi } from 'vite-plus/test'
3
3
  import { createI18n } from 'vue-i18n'
4
4
  import PostDate from './PostDate.vue'
5
5
 
6
- const data = vi.hoisted(() => ({ frontmatter: { value: {} as Record<string, unknown> }, lang: { value: 'en-US' } }))
6
+ const data = vi.hoisted(() => ({
7
+ frontmatter: { value: {} as Record<string, unknown> },
8
+ lang: { value: 'en-US' }
9
+ }))
7
10
  vi.mock('vitepress', () => ({ useData: () => data }))
8
11
 
9
12
  const i18n = createI18n({
10
13
  legacy: false,
11
14
  locale: 'en',
12
- messages: { en: { posted_on: 'Posted on' } },
15
+ messages: { en: { posted_on: 'Posted on' } }
13
16
  })
14
17
 
15
- const render = (date?: Date | string) => mount(PostDate, { props: { date }, global: { plugins: [i18n] } })
16
- const datetimeOf = (date?: Date | string) => render(date).get('time').attributes('datetime')
18
+ const render = (date?: Date | string) =>
19
+ mount(PostDate, { props: { date }, global: { plugins: [i18n] } })
20
+ const datetimeOf = (date?: Date | string) =>
21
+ render(date).get('time').attributes('datetime')
17
22
 
18
23
  describe('PostDate locale', () => {
19
24
  afterEach(() => {
@@ -56,14 +61,18 @@ describe('PostDate datetime', () => {
56
61
  })
57
62
 
58
63
  it('matches the date prop when given a string', () => {
59
- expect(datetimeOf('2023-04-05T06:07:08.000Z')).toBe('2023-04-05T06:07:08.000Z')
64
+ expect(datetimeOf('2023-04-05T06:07:08.000Z')).toBe(
65
+ '2023-04-05T06:07:08.000Z'
66
+ )
60
67
  expect(datetimeOf('2023-04-05')).toBe(new Date('2023-04-05').toISOString())
61
68
  })
62
69
 
63
70
  it('does not depend on render time', () => {
64
71
  vi.useFakeTimers()
65
72
  vi.setSystemTime(new Date('2030-01-01T00:00:00.000Z'))
66
- expect(datetimeOf('2023-04-05T06:07:08.000Z')).toBe('2023-04-05T06:07:08.000Z')
73
+ expect(datetimeOf('2023-04-05T06:07:08.000Z')).toBe(
74
+ '2023-04-05T06:07:08.000Z'
75
+ )
67
76
  })
68
77
 
69
78
  it('omits datetime and does not throw for a missing or invalid date', () => {
@@ -1,4 +1,4 @@
1
- <script setup lang='ts'>
1
+ <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
3
  import { useI18n } from 'vue-i18n'
4
4
  import { usePageLang } from '../composables/lang'
@@ -10,15 +10,20 @@ const props = defineProps({
10
10
  date: [Date, String],
11
11
  textSize: {
12
12
  type: String,
13
- default: null,
14
- },
13
+ default: null
14
+ }
15
15
  })
16
16
 
17
17
  const { t } = useI18n()
18
18
  const pageLang = usePageLang()
19
19
 
20
20
  const formatDate = (date: Date, locale: string) => {
21
- const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' }
21
+ const options: Intl.DateTimeFormatOptions = {
22
+ year: 'numeric',
23
+ month: 'long',
24
+ day: 'numeric',
25
+ timeZone: 'UTC'
26
+ }
22
27
  try {
23
28
  return date.toLocaleDateString(locale, options)
24
29
  } catch {
@@ -28,14 +33,15 @@ const formatDate = (date: Date, locale: string) => {
28
33
  }
29
34
 
30
35
  const dateObject = computed(() => {
31
- const date = props.date instanceof Date ? props.date : new Date(props.date as string)
36
+ const date =
37
+ props.date instanceof Date ? props.date : new Date(props.date as string)
32
38
 
33
39
  const isValid = !Number.isNaN(+date)
34
40
 
35
41
  return {
36
42
  time: +date,
37
43
  iso: isValid ? date.toISOString() : undefined,
38
- string: formatDate(date, pageLang.value),
44
+ string: formatDate(date, pageLang.value)
39
45
  }
40
46
  })
41
47
  </script>
@@ -45,7 +51,10 @@ const dateObject = computed(() => {
45
51
  <dt class="sr-only">
46
52
  {{ t('posted_on') }}
47
53
  </dt>
48
- <dd class="font-medium leading-6" :class="[textSize ? `text-${textSize}` : 'text-base']">
54
+ <dd
55
+ class="font-medium leading-6"
56
+ :class="[textSize ? `text-${textSize}` : 'text-base']"
57
+ >
49
58
  <time :datetime="dateObject.iso">{{ dateObject.string }}</time>
50
59
  </dd>
51
60
  </dl>
@@ -1,4 +1,4 @@
1
- <script setup lang='ts'>
1
+ <script setup lang="ts">
2
2
  import { computed, type PropType } from 'vue'
3
3
  import { usePostDate } from '../composables'
4
4
  import type { Post } from '../types'
@@ -7,8 +7,8 @@ import TermLink from './TermLink.vue'
7
7
  const props = defineProps({
8
8
  post: {
9
9
  type: Object as PropType<Post>,
10
- required: true,
11
- },
10
+ required: true
11
+ }
12
12
  })
13
13
 
14
14
  const postDate = computed(() => usePostDate(props.post.date))
@@ -16,18 +16,28 @@ const postDate = computed(() => usePostDate(props.post.date))
16
16
 
17
17
  <template>
18
18
  <div class="flex p-4 component-border">
19
- <div class="text-center" style="min-width: 80px;">
19
+ <div class="text-center" style="min-width: 80px">
20
20
  <div class="text-6xl font-bold">{{ postDate?.day }}</div>
21
21
  <div>{{ postDate?.month }}, {{ postDate?.year }}</div>
22
22
  </div>
23
23
  <div class="pl-8">
24
24
  <div class="flex flex-wrap mb-3">
25
- <a class="text-2xl font-bold leading-8 tracking-tight" :href="post?.url" :title="post.title">{{ post.title }}</a>
25
+ <a
26
+ class="text-2xl font-bold leading-8 tracking-tight"
27
+ :href="post?.url"
28
+ :title="post.title"
29
+ >{{ post.title }}</a
30
+ >
26
31
  </div>
27
32
  <div class="flex flex-wrap mb-3">
28
- <TermLink v-for="category in post.categories" :key="category" :text="category" basePath="/categories/" />
33
+ <TermLink
34
+ v-for="category in post.categories"
35
+ :key="category"
36
+ :text="category"
37
+ basePath="/categories/"
38
+ />
29
39
  </div>
30
- <p v-html="post?.excerpt" />
40
+ <div v-html="post?.excerpt" />
31
41
  </div>
32
42
  </div>
33
43
  </template>
@@ -1,4 +1,4 @@
1
- <script setup lang='ts'>
1
+ <script setup lang="ts">
2
2
  import type { PropType } from 'vue'
3
3
  import { useI18n } from 'vue-i18n'
4
4
  import type { Post } from '../types'
@@ -8,15 +8,18 @@ defineProps({
8
8
  posts: {
9
9
  type: Object as PropType<Post[]>,
10
10
  required: true,
11
- default: [],
12
- },
11
+ default: []
12
+ }
13
13
  })
14
14
 
15
15
  const { t } = useI18n()
16
16
  </script>
17
17
 
18
18
  <template>
19
- <div v-if="posts.length > 0" class="grid grid-cols-1 lg:grid-cols-2 gap-4 mt-4">
19
+ <div
20
+ v-if="posts.length > 0"
21
+ class="grid grid-cols-1 lg:grid-cols-2 gap-4 mt-4"
22
+ >
20
23
  <PostItem v-for="post of posts" :key="post?.url" :post="post" />
21
24
  </div>
22
25
  <p v-if="posts.length === 0">{{ t('no_post') }}</p>
@@ -1,4 +1,4 @@
1
- <script setup lang='ts'>
1
+ <script setup lang="ts">
2
2
  import { computed, type PropType } from 'vue'
3
3
  import { useI18n } from 'vue-i18n'
4
4
  import { useProjectStatusStyle } from '../composables'
@@ -11,28 +11,46 @@ import TermLink from './TermLink.vue'
11
11
  const props = defineProps({
12
12
  project: {
13
13
  type: Object as PropType<Project>,
14
- required: true,
15
- },
14
+ required: true
15
+ }
16
16
  })
17
17
 
18
18
  const { t } = useI18n()
19
- const projectStatusStyles = computed(() => useProjectStatusStyle(props.project.developmentStatus))
19
+ const projectStatusStyles = computed(() =>
20
+ useProjectStatusStyle(props.project.developmentStatus)
21
+ )
20
22
  </script>
21
23
 
22
24
  <template>
23
25
  <div class="flex flex-col p-4 component-border">
24
26
  <div class="flex flex-row justify-between items-center mb-4">
25
- <a :href="project.url" class="text-2xl font-bold leading-8 tracking-tight">
27
+ <a
28
+ :href="project.url"
29
+ class="text-2xl font-bold leading-8 tracking-tight"
30
+ >
26
31
  {{ project.title }}
27
32
  </a>
28
33
  <div class="flex flex-row">
29
- <a v-if="project.showcaseUrl" class="mx-1 text-gray-500 transition hover:text-gray-600" target="_blank"
30
- rel="noopener noreferrer" :href="project.showcaseUrl">
34
+ <a
35
+ v-if="project.showcaseUrl"
36
+ class="mx-1 text-gray-500 hover:text-gray-600"
37
+ target="_blank"
38
+ rel="noopener noreferrer"
39
+ :href="project.showcaseUrl"
40
+ >
31
41
  <span class="sr-only">external-link</span>
32
- <Icon icon="bi:box-arrow-up-right" class="text-dark dark:text-white ml-2" />
42
+ <Icon
43
+ icon="bi:box-arrow-up-right"
44
+ class="text-dark dark:text-white ml-2"
45
+ />
33
46
  </a>
34
- <a v-if="project.repositoryUrl" class="mx-1 text-gray-500 transition hover:text-gray-600" target="_blank"
35
- rel="noopener noreferrer" :href="project.repositoryUrl">
47
+ <a
48
+ v-if="project.repositoryUrl"
49
+ class="mx-1 text-gray-500 hover:text-gray-600"
50
+ target="_blank"
51
+ rel="noopener noreferrer"
52
+ :href="project.repositoryUrl"
53
+ >
36
54
  <span class="sr-only">github</span>
37
55
  <Icon icon="bi:github" class="text-dark dark:text-white ml-2" />
38
56
  </a>
@@ -43,18 +61,28 @@ const projectStatusStyles = computed(() => useProjectStatusStyle(props.project.d
43
61
  <div class="flex flex-col justify-between">
44
62
  <div v-if="project.license" class="mb-3">
45
63
  {{ t('license') }}:
46
- <Link v-if="project.licenseUrl" :href="project.licenseUrl" class="link-alt">
47
- {{ project.license }}
64
+ <Link
65
+ v-if="project.licenseUrl"
66
+ :href="project.licenseUrl"
67
+ class="link-alt"
68
+ >
69
+ {{ project.license }}
48
70
  </Link>
49
71
  <span v-else>{{ project.license }}</span>
50
72
  </div>
51
73
  <div class="mb-3">
52
- {{ t('development_status.title') }}: <StatusBadge v-bind="projectStatusStyles">
74
+ {{ t('development_status.title') }}:
75
+ <StatusBadge v-bind="projectStatusStyles">
53
76
  {{ $t(`development_status.${project.developmentStatus}`) }}
54
77
  </StatusBadge>
55
78
  </div>
56
79
  <div class="flex flex-wrap mb-3">
57
- <TermLink v-for="tech in project.techs" :key="tech" :text="tech" basePath="/projects?tech=" />
80
+ <TermLink
81
+ v-for="tech in project.techs"
82
+ :key="tech"
83
+ :text="tech"
84
+ basePath="/projects?tech="
85
+ />
58
86
  </div>
59
87
  <PostDate :date="project.date" text-size="sm" />
60
88
  </div>
@@ -1,4 +1,4 @@
1
- <script setup lang='ts'>
1
+ <script setup lang="ts">
2
2
  import type { PropType } from 'vue'
3
3
  import { useI18n } from 'vue-i18n'
4
4
  import type { Project } from '../types'
@@ -8,16 +8,23 @@ defineProps({
8
8
  projects: {
9
9
  type: Object as PropType<Project[]>,
10
10
  required: true,
11
- default: [],
12
- },
11
+ default: []
12
+ }
13
13
  })
14
14
 
15
15
  const { t } = useI18n()
16
16
  </script>
17
17
 
18
18
  <template>
19
- <div v-if="projects.length > 0" class="grid grid-cols-1 lg:grid-cols-2 gap-4 mt-4">
20
- <ProjectCard v-for="project of projects" :key="project?.url" :project="project" />
19
+ <div
20
+ v-if="projects.length > 0"
21
+ class="grid grid-cols-1 lg:grid-cols-2 gap-4 mt-4"
22
+ >
23
+ <ProjectCard
24
+ v-for="project of projects"
25
+ :key="project?.url"
26
+ :project="project"
27
+ />
21
28
  </div>
22
29
  <p v-if="projects.length === 0">{{ t('no_post') }}</p>
23
30
  </template>
@@ -1,12 +1,12 @@
1
- <script setup lang='ts'>
1
+ <script setup lang="ts">
2
2
  import { useRouter } from 'vitepress'
3
3
 
4
4
  defineProps({
5
5
  to: {
6
6
  type: String,
7
7
  required: true,
8
- default: '#',
9
- },
8
+ default: '#'
9
+ }
10
10
  })
11
11
 
12
12
  const router = useRouter()
@@ -7,7 +7,9 @@ const route = useRoute()
7
7
  const { theme, frontmatter, page } = useData()
8
8
 
9
9
  const Sharing = theme.value.sharing
10
- ? defineAsyncComponent(() => import('../plugins/sharing/components/Sharing.vue'))
10
+ ? defineAsyncComponent(
11
+ () => import('../plugins/sharing/components/Sharing.vue')
12
+ )
11
13
  : () => null
12
14
 
13
15
  const postURL = new URL(route.path, theme.value.siteURL).href
@@ -1,40 +1,40 @@
1
- <script setup lang='ts'>
1
+ <script setup lang="ts">
2
2
  defineProps({
3
3
  backgroundColor: {
4
4
  type: String,
5
5
  required: false,
6
- default: 'bg-blue-100',
6
+ default: 'bg-blue-100'
7
7
  },
8
8
  darkBackgroundColor: {
9
9
  type: String,
10
10
  required: false,
11
- default: 'dark:bg-blue-800',
11
+ default: 'dark:bg-blue-800'
12
12
  },
13
13
  textColor: {
14
14
  type: String,
15
15
  required: false,
16
- default: 'text-blue-800',
16
+ default: 'text-blue-800'
17
17
  },
18
18
  darkTextColor: {
19
19
  type: String,
20
20
  required: false,
21
- default: 'dark:text-blue-100',
21
+ default: 'dark:text-blue-100'
22
22
  },
23
23
  fontSize: {
24
24
  type: String,
25
25
  required: false,
26
- default: 'text-base',
26
+ default: 'text-base'
27
27
  },
28
28
  fontWeight: {
29
29
  type: String,
30
30
  required: false,
31
- default: 'font-normal',
31
+ default: 'font-normal'
32
32
  },
33
33
  rounded: {
34
34
  type: Boolean,
35
35
  required: false,
36
- default: true,
37
- },
36
+ default: true
37
+ }
38
38
  })
39
39
  </script>
40
40
 
@@ -48,7 +48,7 @@ defineProps({
48
48
  darkTextColor,
49
49
  fontSize,
50
50
  fontWeight,
51
- rounded ? 'rounded' : '',
51
+ rounded ? 'rounded' : ''
52
52
  ]"
53
53
  >
54
54
  <slot />