sidecar-path.mjs
38 lines · archify/renderers/shared/sidecar-path.mjs at a406594
1import { createHash } from 'node:crypto';
3const SIDECAR_STEM_NAMESPACE = /\.~archify-[0-9a-f]{64}$/iu;
5export function sidecarStemNeedsBounding(stem, suffixes) {
6 const fits = (value) => value.length <= 255 && Buffer.byteLength(value, 'utf8') <= 255;
7 return !suffixes.every((suffix) => fits(`${stem}${suffix}`));
8}
10export function boundedSidecarStem(stem, suffixes, { force = false, hashDomain } = {}) {
11 if (!force && !sidecarStemNeedsBounding(stem, suffixes)
12 && !SIDECAR_STEM_NAMESPACE.test(stem)) return stem;
13 const hashInput = hashDomain ? `${hashDomain}\0${stem}` : stem;
14 const marker = `.~archify-${createHash('sha256').update(hashInput).digest('hex')}`;
15 const codePoints = [...stem];
16 while (codePoints.length
17 && sidecarStemNeedsBounding(`${codePoints.join('')}${marker}`, suffixes)) {
18 codePoints.pop();
19 }
20 return `${codePoints.join('')}${marker}`;
21}
23export function sidecarStemFromComponent(component) {
24 if (component.endsWith('.html')) {
25 return {
26 stem: component.slice(0, -'.html'.length),
27 options: undefined,
28 };
29 }
30 return {
31 stem: component,
32 options: { force: true, hashDomain: 'full-component' },
33 };
34}
36export function isBoundedSidecarStem(stem) {
37 return SIDECAR_STEM_NAMESPACE.test(stem);
38}