@terrazzo/parser
Version:
Parser/validator for the Design Tokens Community Group (DTCG) standard.
69 lines • 2.65 kB
JavaScript
import { isAlias } from '@terrazzo/token-tools';
import { docsLink } from '../lib/docs.js';
import { cachedLintMatcher } from '../lib/matchers.js';
export const DUPLICATE_VALUES = 'core/duplicate-values';
const ERROR_DUPLICATE_VALUE = 'ERROR_DUPLICATE_VALUE';
const rule = {
meta: {
messages: {
[ERROR_DUPLICATE_VALUE]: '{{ id }} declared a duplicate value',
},
docs: {
description: 'Enforce tokens can’t redeclare the same value (excludes aliases).',
url: docsLink(DUPLICATE_VALUES),
},
},
defaultOptions: {},
create({ report, tokens, options }) {
const values = {};
const shouldIgnore = options.ignore ? cachedLintMatcher.tokenIDMatch(options.ignore) : null;
for (const t of Object.values(tokens)) {
// skip ignored tokens
if (shouldIgnore?.(t.id)) {
continue;
}
if (!values[t.$type]) {
values[t.$type] = new Set();
}
// primitives: direct comparison is easy
if (t.$type === 'boolean' ||
t.$type === 'duration' ||
t.$type === 'fontWeight' ||
t.$type === 'link' ||
t.$type === 'number' ||
t.$type === 'string') {
// skip aliases (note: $value will be resolved)
if (typeof t.aliasOf === 'string' && isAlias(t.aliasOf)) {
continue;
}
if (values[t.$type]?.has(t.$value)) {
report({
messageId: ERROR_DUPLICATE_VALUE,
data: { id: t.id },
node: t.source.node,
filename: t.source.filename,
});
}
values[t.$type]?.add(t.$value);
}
else {
// everything else: use deepEqual
for (const v of values[t.$type].values() ?? []) {
// TODO: don’t JSON.stringify
if (JSON.stringify(t.$value) === JSON.stringify(v)) {
report({
messageId: ERROR_DUPLICATE_VALUE,
data: { id: t.id },
node: t.source.node,
filename: t.source.filename,
});
break;
}
}
values[t.$type].add(t.$value);
}
}
},
};
export default rule;
//# sourceMappingURL=duplicate-values.js.map