Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | 3x 3x 3x 3x 3x 3x 3x 245x 216x 216x 216x 216x 216x 216x 216x 216x 214x 216x 216x 252x 252x 252x 182x 182x 182x 182x 182x 178x 182x 252x 252x 252x 142x 252x 250x 250x 250x 392x 392x 250x 250x 44x 308x 44x 44x 302x 1x 301x 301x 1x 300x 1x 299x 299x 41x 287x 1x 40x 19x 19x 19x 105x 105x 105x 105x 105x 19x 33x 31x 15x | import crypto from 'node:crypto';
import { CORE_CSS_ARTIFACTS } from './core-css-artifacts.js';
const VERSION_TOKEN = String.raw`\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?`;
const GENERATED_STAMP = new RegExp(
String.raw`^ \* design-system ${VERSION_TOKEN} \([^\s()]+\)(?=\r?$)`,
'm',
);
const LDS_BANNER_STAMP = new RegExp(
String.raw`/\*! Lightning Design System ${VERSION_TOKEN} \*/`,
);
const GENERATED_STAMP_PREFIX = Buffer.from(' * design-system ');
const LDS_BANNER_STAMP_PREFIX = Buffer.from('/*! Lightning Design System ');
const LDS_BANNER_STAMP_END = Buffer.from(' */');
const NORMALIZED_STAMP = Buffer.from('<core-css-release-stamp>');
export function hashCoreCss(content) {
return crypto.createHash('sha256').update(content).digest('hex');
}
function findGeneratedStamp(content) {
const stamps = [];
let start = content.indexOf(GENERATED_STAMP_PREFIX);
while (start !== -1) {
Eif (start === 0 || content[start - 1] === 0x0a) {
const newline = content.indexOf(0x0a, start);
const lineEnd = newline === -1 ? content.length : newline;
const match = GENERATED_STAMP.exec(content.subarray(start, lineEnd).toString('latin1'));
if (match) {
stamps.push({ start, end: start + match[0].length });
}
}
start = content.indexOf(GENERATED_STAMP_PREFIX, start + 1);
}
return stamps;
}
function findLdsBannerStamps(content) {
const stamps = [];
let start = content.indexOf(LDS_BANNER_STAMP_PREFIX);
while (start !== -1) {
const end = content.indexOf(LDS_BANNER_STAMP_END, start + LDS_BANNER_STAMP_PREFIX.length);
Iif (end === -1) break;
const tokenEnd = end + LDS_BANNER_STAMP_END.length;
const match = LDS_BANNER_STAMP.exec(content.subarray(start, tokenEnd).toString('latin1'));
if (match?.index === 0 && match[0].length === tokenEnd - start) {
stamps.push({ start, end: tokenEnd });
}
start = content.indexOf(LDS_BANNER_STAMP_PREFIX, start + 1);
}
return stamps;
}
export function normalizeCoreCssStamp(content, artifactId) {
const generatedStamps = artifactId === 'sldsTouch' ? [] : findGeneratedStamp(content);
const stamps = [...generatedStamps, ...findLdsBannerStamps(content)].sort(
(left, right) => left.start - right.start,
);
if (stamps.length === 0) return Buffer.from(content);
const normalized = [];
let offset = 0;
for (const stamp of stamps) {
normalized.push(content.subarray(offset, stamp.start), NORMALIZED_STAMP);
offset = stamp.end;
}
normalized.push(content.subarray(offset));
return Buffer.concat(normalized);
}
export function validateCoreCssArtifactSet(artifactSet, label = 'artifact set') {
Iif (!Array.isArray(artifactSet)) {
throw new Error(`${label} must be an array`);
}
const expectedById = new Map(CORE_CSS_ARTIFACTS.map((artifact) => [artifact.id, artifact]));
const artifactsById = new Map();
for (const artifact of artifactSet) {
if (artifactsById.has(artifact.id)) {
throw new Error(`${label} has duplicate artifact id: ${artifact.id}`);
}
const expected = expectedById.get(artifact.id);
if (!expected) {
throw new Error(`${label} has unexpected artifact: ${artifact.id}`);
}
if (artifact.path !== expected.gitcorePath) {
throw new Error(
`${label} path mismatch for ${artifact.id}: expected ${expected.gitcorePath}, received ${artifact.path}`,
);
}
Iif (!Buffer.isBuffer(artifact.content)) {
throw new Error(`${label} content for ${artifact.id} must be a Buffer`);
}
artifactsById.set(artifact.id, artifact);
}
for (const { id } of CORE_CSS_ARTIFACTS) {
if (!artifactsById.has(id)) {
throw new Error(`${label} is missing artifact: ${id}`);
}
}
return artifactsById;
}
export function classifyCoreCssArtifacts(baselineArtifacts, candidateArtifacts) {
const baselineById = validateCoreCssArtifactSet(baselineArtifacts, 'baseline artifact set');
const candidateById = validateCoreCssArtifactSet(candidateArtifacts, 'candidate artifact set');
const artifacts = CORE_CSS_ARTIFACTS.map(({ id, gitcorePath }) => {
const baseline = baselineById.get(id).content;
const candidate = candidateById.get(id).content;
const rawEqual = baseline.equals(candidate);
const stampNormalizedEqual = normalizeCoreCssStamp(baseline, id).equals(
normalizeCoreCssStamp(candidate, id),
);
return {
id,
path: gitcorePath,
rawEqual,
stampNormalizedEqual,
baselineSha256: hashCoreCss(baseline),
candidateSha256: hashCoreCss(candidate),
};
});
let verdict = 'no-change';
if (artifacts.some(({ rawEqual }) => !rawEqual)) {
verdict = artifacts.every(({ stampNormalizedEqual }) => stampNormalizedEqual)
? 'version-only'
: 'content-change';
}
return { verdict, artifacts };
}
|