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,
}
}