All checks were successful
Build and deploy updated apps / Build & deploy (push) Successful in 1m46s
179 lines
4.8 KiB
TypeScript
179 lines
4.8 KiB
TypeScript
import { isTemplate, expandTemplate } from '../utils/content-template'
|
|
import { computed } from 'vue'
|
|
import { useRoute } from '#app'
|
|
|
|
const specializations: Record<string, object> = {}
|
|
|
|
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<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
|
|
}
|
|
|
|
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(0, -1)
|
|
}
|
|
|
|
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: config.content.matrix.locale.list,
|
|
localeCodes: locales,
|
|
variant: currentVariant,
|
|
variants: config.content.matrix.variant.list,
|
|
variantCodes: variants,
|
|
matrixPath: matrixPath,
|
|
p: p,
|
|
c: specialization,
|
|
}
|
|
}
|