feat: implement Theme Builder concept and Display Conditions resolver system
This commit is contained in:
67
src/utils/conditionResolver.ts
Normal file
67
src/utils/conditionResolver.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
export interface DisplayCondition {
|
||||
type: 'include' | 'exclude';
|
||||
scope: 'entire_site' | 'singular' | 'archive' | 'page_404';
|
||||
entity?: 'page' | 'post' | 'category';
|
||||
entityId?: string;
|
||||
}
|
||||
|
||||
export interface TemplateMeta {
|
||||
id: string;
|
||||
name: string;
|
||||
type: 'header' | 'footer' | 'single' | 'archive' | '404';
|
||||
status: 'draft' | 'published';
|
||||
priority: number;
|
||||
conditions: DisplayCondition[];
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves which template to use based on target type and request context conditions.
|
||||
* Specific matches (singular/page_404) take precedence over general 'entire_site' matches.
|
||||
*/
|
||||
export function resolveTemplate(
|
||||
templates: TemplateMeta[],
|
||||
targetType: TemplateMeta['type'],
|
||||
context: { url: string; routeType: 'singular' | 'archive' | '404' | 'home'; entityId?: string }
|
||||
): TemplateMeta | null {
|
||||
const candidates = templates.filter(t => t.type === targetType && t.status === 'published');
|
||||
let bestMatch: TemplateMeta | null = null;
|
||||
let highestScore = -1;
|
||||
|
||||
for (const tpl of candidates) {
|
||||
let isIncluded = false;
|
||||
let isExcluded = false;
|
||||
let score = 0;
|
||||
|
||||
for (const cond of tpl.conditions) {
|
||||
if (cond.type === 'exclude') {
|
||||
if (cond.scope === 'entire_site') isExcluded = true;
|
||||
if (cond.scope === 'singular' && context.routeType === 'singular' && (!cond.entityId || cond.entityId === context.entityId)) {
|
||||
isExcluded = true;
|
||||
}
|
||||
if (cond.scope === 'page_404' && context.routeType === '404') isExcluded = true;
|
||||
} else if (cond.type === 'include') {
|
||||
if (cond.scope === 'entire_site') {
|
||||
isIncluded = true;
|
||||
score = Math.max(score, tpl.priority || 1);
|
||||
} else if (cond.scope === 'singular' && context.routeType === 'singular') {
|
||||
if (!cond.entityId || cond.entityId === context.entityId) {
|
||||
isIncluded = true;
|
||||
score = Math.max(score, (tpl.priority || 1) + 10);
|
||||
}
|
||||
} else if (cond.scope === 'page_404' && context.routeType === '404') {
|
||||
isIncluded = true;
|
||||
score = Math.max(score, (tpl.priority || 1) + 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isIncluded && !isExcluded && score > highestScore) {
|
||||
highestScore = score;
|
||||
bestMatch = tpl;
|
||||
}
|
||||
}
|
||||
|
||||
return bestMatch;
|
||||
}
|
||||
Reference in New Issue
Block a user