UNPKG

2.52 kBJavaScriptView Raw
1'use strict';
2
3const declarationValueIndex = require('../../utils/declarationValueIndex');
4const findFontFamily = require('../../utils/findFontFamily');
5const keywordSets = require('../../reference/keywordSets');
6const optionsMatches = require('../../utils/optionsMatches');
7const report = require('../../utils/report');
8const ruleMessages = require('../../utils/ruleMessages');
9const validateOptions = require('../../utils/validateOptions');
10const { isRegExp, isString } = require('../../utils/validateTypes');
11
12const ruleName = 'font-family-no-duplicate-names';
13
14const messages = ruleMessages(ruleName, {
15 rejected: (name) => `Unexpected duplicate name ${name}`,
16});
17
18/**
19 * @param {import('postcss-value-parser').Node} node
20 */
21const isFamilyNameKeyword = (node) =>
22 !('quote' in node) && keywordSets.fontFamilyKeywords.has(node.value.toLowerCase());
23
24/** @type {import('stylelint').Rule} */
25const rule = (primary, secondaryOptions) => {
26 return (root, result) => {
27 const validOptions = validateOptions(
28 result,
29 ruleName,
30 { actual: primary },
31 {
32 actual: secondaryOptions,
33 possible: {
34 ignoreFontFamilyNames: [isString, isRegExp],
35 },
36 optional: true,
37 },
38 );
39
40 if (!validOptions) {
41 return;
42 }
43
44 root.walkDecls(/^font(-family)?$/i, (decl) => {
45 const keywords = new Set();
46 const familyNames = new Set();
47
48 const fontFamilies = findFontFamily(decl.value);
49
50 if (fontFamilies.length === 0) {
51 return;
52 }
53
54 fontFamilies.forEach((fontFamilyNode) => {
55 const family = fontFamilyNode.value.trim();
56
57 if (optionsMatches(secondaryOptions, 'ignoreFontFamilyNames', family)) {
58 return;
59 }
60
61 if (isFamilyNameKeyword(fontFamilyNode)) {
62 if (keywords.has(family.toLowerCase())) {
63 complain(
64 messages.rejected(family),
65 declarationValueIndex(decl) + fontFamilyNode.sourceIndex,
66 decl,
67 );
68
69 return;
70 }
71
72 keywords.add(family);
73
74 return;
75 }
76
77 if (familyNames.has(family)) {
78 complain(
79 messages.rejected(family),
80 declarationValueIndex(decl) + fontFamilyNode.sourceIndex,
81 decl,
82 );
83
84 return;
85 }
86
87 familyNames.add(family);
88 });
89 });
90
91 /**
92 * @param {string} message
93 * @param {number} index
94 * @param {import('postcss').Declaration} decl
95 */
96 function complain(message, index, decl) {
97 report({
98 result,
99 ruleName,
100 message,
101 node: decl,
102 index,
103 });
104 }
105 };
106};
107
108rule.ruleName = ruleName;
109rule.messages = messages;
110module.exports = rule;