Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improve locales #25

Merged
merged 1 commit into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Chrome",
"request": "launch",
"type": "chrome",
"url": "http://localhost:5173",
"webRoot": "${workspaceFolder}"
},
{
"name": "Launch Edge",
"request": "launch",
"type": "msedge",
"url": "http://localhost:5173",
"webRoot": "${workspaceFolder}"
},
{
"name": "Run and debug",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["run", "dev"]
}
]
}
17 changes: 6 additions & 11 deletions src/components/VPHeader.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useData } from 'vitepress'
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
import VPImage from 'vitepress/dist/client/theme-default/components/VPImage.vue'
Expand All @@ -8,6 +7,7 @@ import VPNavBarSearch from 'vitepress/dist/client/theme-default/components/VPNav
import VPNavBarTranslations from 'vitepress/dist/client/theme-default/components/VPNavBarTranslations.vue'
import VPNavBarSocialLinks from 'vitepress/dist/client/theme-default/components/VPNavBarSocialLinks.vue'
import VPNavBarHamburger from 'vitepress/dist/client/theme-default/components/VPNavBarHamburger.vue'
import { useLangs } from '../composables/index'
import VPAppearance from './VPAppearance.vue'
import type { HeaderSlots, Theme } from '../types/index'

Expand All @@ -19,22 +19,16 @@ defineEmits<{
}>()
defineSlots<HeaderSlots>()

const { site, theme, localeIndex } = useData<Theme>()

const homeLink = computed(() => {
return (
site.value.locales[localeIndex.value]?.link ||
(localeIndex.value === 'root' ? '/' : `/${localeIndex.value}/`)
)
})
const { site, theme } = useData<Theme>()
const { prefix } = useLangs()
</script>

<template>
<header class="header">
<div class="main header-content">
<slot name="header-left" />
<VPLink
:href="homeLink"
:href="prefix"
class="header-logo"
>
<VPImage
Expand Down Expand Up @@ -124,7 +118,8 @@ const homeLink = computed(() => {
flex-grow: 0;
}

.VPNavBarAppearance {
.VPNavBarAppearance,
.VPNavBarTranslations {
display: flex;
align-items: center;
}
Expand Down
13 changes: 7 additions & 6 deletions src/components/VPPagination.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<script setup lang="ts">
import { computed } from 'vue'
import { type DefaultTheme, useData, useRoute, withBase } from 'vitepress'
import { usePagination } from '../composables/index'
import { useLangs, usePagination } from '../composables/index'
import { isActive } from 'vitepress/dist/client/shared'
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
import type { Theme, PaginationParams } from '../types'

const route = useRoute()
const { page } = useData<Theme>()
const { config, posts } = usePagination()
const { prefix } = useLangs()

const pagination = computed(() => {
const params = page.value.params as PaginationParams | undefined
Expand Down Expand Up @@ -70,19 +71,19 @@ const prev = computed(() => findPageInfo(-1))
const next = computed(() => findPageInfo(1))

function formatPage(index: number): DefaultTheme.NavItemWithLink {
const link = index === 1 ? '/' : `/page-${index}`
let prefix: string | undefined
const link = index === 1 ? '' : `page-${index}`
let dir: string | undefined

if (config.value?.dir) {
if (Array.isArray(config.value.dir) && config.value.dir.length === 1) {
prefix = config.value.dir[0]
dir = config.value.dir[0]
} else if (!Array.isArray(config.value.dir)) {
prefix = config.value.dir
dir = config.value.dir
}
}

return {
link: `${prefix ? `/${prefix}` : ''}${link}`,
link: `${prefix.value}${dir ? `${dir}/` : ''}${link}`,
text: String(index),
}
}
Expand Down
1 change: 1 addition & 0 deletions src/composables/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './langs'
export * from './pagination'
export * from './prevNext'
export * from './tag'
27 changes: 27 additions & 0 deletions src/composables/langs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useData } from 'vitepress'
import { computed } from 'vue'

export function useLangs() {
const { site, localeIndex } = useData()

const prefix = computed(() => {
return (
site.value.locales[localeIndex.value]?.link ||
(localeIndex.value === 'root' ? '/' : `/${localeIndex.value}/`)
)
})

function isLocaleUrl(url: string) {
if (localeIndex.value === 'root') {
const locales = Object.keys(site.value.locales).filter(
(lang) => lang !== 'root',
)
const regExp = new RegExp(`^/(${locales.join('|')})/`)
return !regExp.test(url)
} else {
return url.startsWith(prefix.value)
}
}

return { prefix, isLocaleUrl }
}
8 changes: 6 additions & 2 deletions src/composables/pagination.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { computed } from 'vue'
import { useData, useRoute } from 'vitepress'
import { useLangs } from './index'
import { data } from '../posts.data'
import { isFunction, toArray } from '../utils/index'
import type { Theme, PaginationParams } from '../types/index'

export function usePagination() {
const route = useRoute()
const { theme, page } = useData<Theme>()
const { prefix, isLocaleUrl } = useLangs()

/** Obtain the pagination config that matches the current route from the config file */
const config = computed(() => {
Expand All @@ -18,7 +20,9 @@ export function usePagination() {
if (isFunction(item.match)) {
return item.match(route.path)
} else if (item.dir) {
const regExp = new RegExp(`^/(${toArray(item.dir).join('|')})/`)
const regExp = new RegExp(
`^${prefix.value}(${toArray(item.dir).join('|')})/`,
)
return regExp.test(route.path)
}
})
Expand All @@ -27,7 +31,7 @@ export function usePagination() {
/** Get all posts */
const posts = computed(() => {
if (!data.length) return []
let list = data
let list = data.filter((item) => isLocaleUrl(item.url))

if (config.value?.filter) {
list = list.filter(config.value.filter)
Expand Down
14 changes: 10 additions & 4 deletions src/composables/tag.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { computed, ref, watch } from 'vue'
import { useData, inBrowser, useRoute } from 'vitepress'
import { useLangs } from './index'
import { data } from '../posts.data'
import { Classifiable } from '../utils/index'
import type { Theme } from '../types/index'
Expand All @@ -9,15 +10,16 @@ const classifiable = new Classifiable(data)
export function useTag() {
const route = useRoute()
const { frontmatter, theme } = useData<Theme>()
const { isLocaleUrl } = useLangs()

const current = ref<string>(getQuery())

const list = computed(() => {
switch (frontmatter.value.layout) {
case 'tag':
return classifiable.allTags
return classifiable.getAllTags((item) => isLocaleUrl(item.url))
case 'category':
return classifiable.allCategories
return classifiable.getAllCategories((item) => isLocaleUrl(item.url))
default:
return undefined
}
Expand All @@ -28,9 +30,13 @@ export function useTag() {

switch (frontmatter.value.layout) {
case 'tag':
return classifiable.getPostsByTag(current.value)
return classifiable.getPostsByTag(current.value, (item) =>
isLocaleUrl(item.url),
)
case 'category':
return classifiable.getPostsByCategory(current.value)
return classifiable.getPostsByCategory(current.value, (item) =>
isLocaleUrl(item.url),
)
default:
return undefined
}
Expand Down
28 changes: 17 additions & 11 deletions src/utils/Classifiable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,34 @@ export class Classifiable {
this.categories = _categories
}

get allTags() {
return this.toCountMap('tags')
getAllTags(filter: (item: PostsItem) => boolean) {
return this.toCountMap('tags', filter)
}

get allCategories() {
return this.toCountMap('categories')
getAllCategories(filter: (item: PostsItem) => boolean) {
return this.toCountMap('categories', filter)
}

getPostsByTag(tag: string) {
return this.tags[tag]
getPostsByTag(tag: string, filter: (item: PostsItem) => boolean) {
return this.tags[tag]?.filter(filter)
}

getPostsByCategory(category: string) {
return this.categories[category]
getPostsByCategory(category: string, filter: (item: PostsItem) => boolean) {
return this.categories[category]?.filter(filter)
}

toCountMap(type: 'tags' | 'categories') {
toCountMap(
type: 'tags' | 'categories',
filter: (item: PostsItem) => boolean,
) {
const obj: Record<string, number> = {}

for (const key in this[type]) {
const len = this[type][key]?.length
obj[key] = len || 0
const len = this[type][key]?.filter(filter)?.length ?? 0

if (len) {
obj[key] = len
}
}

return obj
Expand Down