mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
Centralize surface route normalization (#600)
Consolidate explicit and inferred surface route canonicalization behind one private rule, with characterization coverage for equivalent and invalid inputs.\n\nAI assistance: OpenAI Codex prepared this change under pbakaus's scheduled architecture-simplification authorization.
This commit is contained in:
@@ -8,6 +8,12 @@ export function getSurfaceBriefDir(projectRoot) {
|
||||
return path.join(projectRoot, '.impeccable', 'surfaces');
|
||||
}
|
||||
|
||||
function normalizeRouteTarget(route) {
|
||||
if (!route.startsWith('/') || route.includes('..')) return null;
|
||||
const normalized = route.split(/[?#]/, 1)[0].replace(/\/{2,}/g, '/').replace(/\/$/, '') || '/';
|
||||
return `route:${normalized}`;
|
||||
}
|
||||
|
||||
export function normalizeSurfaceTarget(target, { projectRoot = process.cwd() } = {}) {
|
||||
if (!target || typeof target !== 'string' || !target.trim()) return null;
|
||||
const trimmed = target.trim();
|
||||
@@ -21,21 +27,13 @@ export function normalizeSurfaceTarget(target, { projectRoot = process.cwd() } =
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (/^route:/i.test(trimmed)) {
|
||||
const route = trimmed.slice(trimmed.indexOf(':') + 1).trim();
|
||||
if (!route.startsWith('/') || route.includes('..')) return null;
|
||||
const normalizedRoute = route.split(/[?#]/, 1)[0].replace(/\/{2,}/g, '/').replace(/\/$/, '') || '/';
|
||||
return `route:${normalizedRoute}`;
|
||||
}
|
||||
if (trimmed === '/') return 'route:/';
|
||||
if (/^route:/i.test(trimmed)) return normalizeRouteTarget(trimmed.slice(trimmed.indexOf(':') + 1).trim());
|
||||
if (trimmed === '/') return normalizeRouteTarget(trimmed);
|
||||
if (trimmed.startsWith('/')) {
|
||||
const absolute = path.resolve(trimmed);
|
||||
const relativeToProject = path.relative(projectRoot, absolute);
|
||||
const isProjectFile = relativeToProject && !relativeToProject.startsWith('..') && !path.isAbsolute(relativeToProject);
|
||||
if (!isProjectFile && !fs.existsSync(absolute) && !trimmed.includes('..')) {
|
||||
const normalizedRoute = trimmed.split(/[?#]/, 1)[0].replace(/\/{2,}/g, '/').replace(/\/$/, '') || '/';
|
||||
return `route:${normalizedRoute}`;
|
||||
}
|
||||
if (!isProjectFile && !fs.existsSync(absolute)) return normalizeRouteTarget(trimmed);
|
||||
}
|
||||
const abs = path.isAbsolute(trimmed) ? trimmed : path.resolve(projectRoot, trimmed);
|
||||
const rel = path.relative(projectRoot, abs);
|
||||
|
||||
@@ -6,6 +6,7 @@ import path from 'node:path';
|
||||
|
||||
import {
|
||||
listSurfaceBriefs,
|
||||
normalizeSurfaceTarget,
|
||||
resolveSurfaceBrief,
|
||||
writeSurfaceBrief,
|
||||
} from '../skill/scripts/lib/surface-briefs.mjs';
|
||||
@@ -69,6 +70,13 @@ describe('surface briefs', () => {
|
||||
assert.equal(result.brief?.primaryTarget, 'route:/pricing');
|
||||
});
|
||||
|
||||
it('canonicalizes explicit and inferred route identifiers consistently', () => {
|
||||
assert.equal(normalizeSurfaceTarget('route:/docs//intro/?from=nav#top', { projectRoot: cwd }), 'route:/docs/intro');
|
||||
assert.equal(normalizeSurfaceTarget('/docs//intro/?from=nav#top', { projectRoot: cwd }), 'route:/docs/intro');
|
||||
assert.equal(normalizeSurfaceTarget('route:/docs/../admin', { projectRoot: cwd }), null);
|
||||
assert.equal(normalizeSurfaceTarget('/docs/../admin', { projectRoot: cwd }), null);
|
||||
});
|
||||
|
||||
it('supports the root route even though the filesystem root exists', () => {
|
||||
const filePath = writeSurfaceBrief({
|
||||
projectRoot: cwd,
|
||||
|
||||
Reference in New Issue
Block a user