import { isTemplate, expandTemplate } from '../utils/content-template' import { computed } from 'vue' import { useRoute } from '#app' const specializations: Record = {} function buildSpecialization(locale: string, variant: string): object { const config = useAppConfig() const locales = config.content.matrix.locale.list.map(l => l.code) const variants = config.content.matrix.variant.list.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 = {} 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 } if (anonymous.length < 1) { console.warn("Unable to parse object", object) } 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] } const filtered = filterObject(config.content) function deepReplace(obj: any, predicate: (node: any) => boolean, replacer: (node: any) => any): void { if (Array.isArray(obj)) { for (let i = 0; i < obj.length; i++) { if (predicate(obj[i])) { obj[i] = replacer(obj[i]); } else if (typeof obj[i] === 'object' && obj[i] !== null) { deepReplace(obj[i], predicate, replacer); } } } else if (typeof obj === 'object' && obj !== null) { for (const key of Object.keys(obj)) { if (predicate(obj[key])) { obj[key] = replacer(obj[key]); } else if (typeof obj[key] === 'object' && obj[key] !== null) { deepReplace(obj[key], predicate, replacer); } } } } deepReplace(filtered, (node: any) => isTemplate(node), (node: any) => expandTemplate(node, filtered)) return filtered } 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() const {getLocaleVariant, buildPrefix} = useContentPrefix() const locales = config.content.matrix.locale.list.map(l => l.code) const variants = config.content.matrix.variant.list.map(v => v.code) const localeVariant = computed(() => getLocaleVariant(route.path)!) const currentLocale = computed(() => localeVariant.value[0]) const currentVariant = computed(() => localeVariant.value[1]) function matrixPath(options: { page?: string; anchor?: string; locale?: string; variant?: string }): string { let page = options.page if (page && !page.startsWith('/')) { page = '/' + page } if (page === undefined) { page = route.fullPath const [locale, variant] = getLocaleVariant(page)! const length = buildPrefix(locale, variant).length page = page.slice(length) } const prefix = buildPrefix(options.locale ?? currentLocale.value, options.variant ?? currentVariant.value) let base = prefix + page if (base.endsWith('/')) { base = base.slice(base.length - 1) } return options.anchor ? `${base}#${options.anchor}` : base } function p(page: string, anchor?: string): string { return matrixPath({page: page, anchor: anchor}) } const specialization = computed(() => getSpecialization(currentLocale.value, currentVariant.value)) return { locale: currentLocale, locales: config.content.matrix.locale.list, localeCodes: locales, variant: currentVariant, variants: config.content.matrix.variant.list, variantCodes: variants, matrixPath: matrixPath, p: p, c: specialization, } }