172 lines
4.3 KiB
TypeScript
172 lines
4.3 KiB
TypeScript
import { computed } from 'vue'
|
|
import { useRoute } from '#app'
|
|
import content from '~/assets/content.yaml'
|
|
|
|
const specializations: Record<string, object> = {}
|
|
|
|
function buildSpecialization(locale: string, variant: string): object {
|
|
const config = useAppConfig()
|
|
const locales = config.content.locales.map(l => l.code)
|
|
const variants = config.content.variants.map(v => v.code)
|
|
const allTags = new Set([...locales, ...variants])
|
|
|
|
function split(key: string): {base?: string; tags: string[]} {
|
|
const parts = key.split('@')
|
|
|
|
if (allTags.has(parts[0])) {
|
|
return {base: undefined, tags: parts}
|
|
}
|
|
|
|
return {base: parts[0], tags: parts.slice(1)}
|
|
}
|
|
|
|
function relevant(tags: string[]): boolean {
|
|
if (tags.length < 1) {
|
|
return true
|
|
}
|
|
|
|
for (const tag of tags) {
|
|
if (tag !== locale && tag !== variant) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
function filterObject(object: any): any {
|
|
if (Array.isArray(object)) {
|
|
return object.map(e => filterObject(e)).filter(e => e !== undefined)
|
|
}
|
|
|
|
if (typeof object !== 'object') {
|
|
return object
|
|
}
|
|
|
|
const copy: Record<string, any> = {}
|
|
let anonymous: [number, any][] = []
|
|
|
|
for (const key in object) {
|
|
const {base, tags} = split(key)
|
|
|
|
if (!relevant(tags)) {
|
|
continue
|
|
}
|
|
|
|
const value = filterObject(object[key])
|
|
|
|
if (base === undefined) {
|
|
anonymous.push([tags.length, value])
|
|
} else {
|
|
copy[base] = value
|
|
}
|
|
}
|
|
|
|
if (Object.keys(copy).length > 0 && anonymous.length > 0) {
|
|
console.warn(`Invalid mixing of keys in object ${object}`)
|
|
}
|
|
|
|
if (Object.keys(copy).length > 0) {
|
|
return copy
|
|
}
|
|
|
|
anonymous.sort((a, b) => b[0] - a[0])
|
|
|
|
if (anonymous[0][0] > 2) {
|
|
console.warn(`More than two tags per key in object ${object}`)
|
|
}
|
|
|
|
return anonymous[0][1]
|
|
}
|
|
|
|
return filterObject(content)
|
|
}
|
|
|
|
function getSpecialization(locale: string, variant: string): object {
|
|
const key = locale + '/' + variant
|
|
|
|
if (!(key in specializations)) {
|
|
specializations[key] = buildSpecialization(locale, variant)
|
|
}
|
|
|
|
return specializations[key]
|
|
}
|
|
|
|
export function useContent() {
|
|
const config = useAppConfig()
|
|
const route = useRoute()
|
|
console.log("miau")
|
|
console.log(route)
|
|
|
|
const locales = config.content.locales.map(l => l.code)
|
|
const variants = config.content.variants.map(v => v.code)
|
|
|
|
const localeCookie = useCookie<string>('locale', {
|
|
sameSite: 'lax',
|
|
maxAge: config.content.cookieMaxAge
|
|
})
|
|
|
|
const variantCookie = useCookie<string>('variant', {
|
|
sameSite: 'lax',
|
|
maxAge: config.content.cookieMaxAge
|
|
})
|
|
|
|
const currentLocale = computed<string>(() => route.params.locale || localeCookie.value || config.content.defaultLocale)
|
|
const currentVariant = computed<string>(() => route.params.variant || variantCookie.value || config.content.defaultVariant)
|
|
|
|
function preferLocale(locale: string) {
|
|
if (locale in locales) {
|
|
localeCookie.value = locale
|
|
}
|
|
}
|
|
|
|
function preferVariant(variant: string) {
|
|
if (variant in variants) {
|
|
variantCookie.value = variant
|
|
}
|
|
}
|
|
|
|
function matrixPath(options: { page?: string; anchor?: string; locale?: string; variant?: string }): string {
|
|
let prefix: string[] = []
|
|
|
|
const showLocale = locales.length > 1
|
|
const showVariant = variants.length > 1
|
|
|
|
if (showLocale) {
|
|
prefix.push(options.locale ?? currentLocale.value)
|
|
}
|
|
|
|
if (showVariant) {
|
|
prefix.push(options.variant ?? currentVariant.value)
|
|
}
|
|
|
|
// TODO preserve anchor when taking route.path
|
|
let page = (options.page ?? route.path).split('/').filter(Boolean)
|
|
|
|
if (!options.page) {
|
|
page = page.slice([showLocale, showVariant].filter(Boolean).length)
|
|
}
|
|
|
|
const base = '/' + [...prefix, ...page].join('/')
|
|
return options.anchor ? `${base}#${options.anchor}` : base
|
|
}
|
|
|
|
function p(page: string, anchor?: string): string {
|
|
return matrixPath({page: page, anchor: anchor})
|
|
}
|
|
|
|
const specialization = computed<any>(() => getSpecialization(currentLocale.value, currentVariant.value))
|
|
|
|
return {
|
|
locale: currentLocale,
|
|
locales: locales,
|
|
preferLocale: preferLocale,
|
|
variant: currentVariant,
|
|
variants: variants,
|
|
preferVariant: preferVariant,
|
|
matrixPath: matrixPath,
|
|
p: p,
|
|
c: specialization,
|
|
}
|
|
}
|