@primer/stylelint-config 13.0.0-rc.fe9ab86 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +324 -90
- package/dist/index.mjs +324 -90
- package/package.json +10 -16
- package/plugins/box-shadow.js +97 -21
- package/plugins/lib/utils.js +8 -0
- package/plugins/typography.js +185 -23
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import valueParser from 'postcss-value-parser';
|
|
|
5
5
|
import { createRequire } from 'node:module';
|
|
6
6
|
import anymatch from 'anymatch';
|
|
7
7
|
import TapMap from 'tap-map';
|
|
8
|
-
import variables$
|
|
8
|
+
import variables$3 from '@primer/css/dist/variables.json' with { type: 'json' };
|
|
9
9
|
import matchAll from 'string.prototype.matchall';
|
|
10
10
|
|
|
11
11
|
var propertyOrder = [
|
|
@@ -194,6 +194,14 @@ function primitivesVariables(type) {
|
|
|
194
194
|
case 'border':
|
|
195
195
|
files.push('functional/size/border.json');
|
|
196
196
|
break
|
|
197
|
+
case 'typography':
|
|
198
|
+
files.push('base/typography/typography.json');
|
|
199
|
+
files.push('functional/typography/typography.json');
|
|
200
|
+
break
|
|
201
|
+
case 'box-shadow':
|
|
202
|
+
files.push('functional/themes/light.json');
|
|
203
|
+
files.push('functional/size/border.json');
|
|
204
|
+
break
|
|
197
205
|
}
|
|
198
206
|
|
|
199
207
|
for (const file of files) {
|
|
@@ -226,12 +234,12 @@ function walkGroups$1(root, validate) {
|
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
const {
|
|
229
|
-
createPlugin: createPlugin$
|
|
230
|
-
utils: {report: report$
|
|
237
|
+
createPlugin: createPlugin$3,
|
|
238
|
+
utils: {report: report$3, ruleMessages: ruleMessages$3, validateOptions: validateOptions$3},
|
|
231
239
|
} = stylelint;
|
|
232
240
|
|
|
233
|
-
const ruleName$
|
|
234
|
-
const messages$
|
|
241
|
+
const ruleName$5 = 'primer/borders';
|
|
242
|
+
const messages$5 = ruleMessages$3(ruleName$5, {
|
|
235
243
|
rejected: (value, replacement, propName) => {
|
|
236
244
|
if (propName && propName.includes('radius') && value.includes('borderWidth')) {
|
|
237
245
|
return `Border radius variables can not be used for border widths`
|
|
@@ -249,19 +257,19 @@ const messages$3 = ruleMessages$1(ruleName$3, {
|
|
|
249
257
|
},
|
|
250
258
|
});
|
|
251
259
|
|
|
252
|
-
const variables = primitivesVariables('border');
|
|
260
|
+
const variables$2 = primitivesVariables('border');
|
|
253
261
|
const sizes$1 = [];
|
|
254
262
|
const radii = [];
|
|
255
263
|
|
|
256
264
|
// Props that we want to check
|
|
257
|
-
const propList$
|
|
265
|
+
const propList$2 = ['border', 'border-width', 'border-radius'];
|
|
258
266
|
// Values that we want to ignore
|
|
259
267
|
const valueList$1 = ['${'];
|
|
260
268
|
|
|
261
269
|
const borderShorthand = prop =>
|
|
262
270
|
/^border(-(top|right|bottom|left|block-start|block-end|inline-start|inline-end))?$/.test(prop);
|
|
263
271
|
|
|
264
|
-
for (const variable of variables) {
|
|
272
|
+
for (const variable of variables$2) {
|
|
265
273
|
const name = variable['name'];
|
|
266
274
|
|
|
267
275
|
if (name.includes('borderWidth')) {
|
|
@@ -281,9 +289,9 @@ for (const variable of variables) {
|
|
|
281
289
|
}
|
|
282
290
|
|
|
283
291
|
/** @type {import('stylelint').Rule} */
|
|
284
|
-
const ruleFunction$
|
|
292
|
+
const ruleFunction$3 = (primary, secondaryOptions, context) => {
|
|
285
293
|
return (root, result) => {
|
|
286
|
-
const validOptions = validateOptions$
|
|
294
|
+
const validOptions = validateOptions$3(result, ruleName$5, {
|
|
287
295
|
actual: primary,
|
|
288
296
|
possible: [true],
|
|
289
297
|
});
|
|
@@ -293,7 +301,7 @@ const ruleFunction$1 = (primary, secondaryOptions, context) => {
|
|
|
293
301
|
root.walkDecls(declNode => {
|
|
294
302
|
const {prop, value} = declNode;
|
|
295
303
|
|
|
296
|
-
if (!propList$
|
|
304
|
+
if (!propList$2.some(borderProp => prop.startsWith(borderProp))) return
|
|
297
305
|
if (/^border(-(top|right|bottom|left|block-start|block-end|inline-start|inline-end))?-color$/.test(prop)) return
|
|
298
306
|
if (valueList$1.some(valueToIgnore => value.includes(valueToIgnore))) return
|
|
299
307
|
|
|
@@ -383,7 +391,7 @@ const ruleFunction$1 = (primary, secondaryOptions, context) => {
|
|
|
383
391
|
problems.push({
|
|
384
392
|
index: declarationValueIndex(declNode) + node.sourceIndex,
|
|
385
393
|
endIndex: declarationValueIndex(declNode) + node.sourceIndex + node.value.length,
|
|
386
|
-
message: messages$
|
|
394
|
+
message: messages$5.rejected(node.value, replacement, prop),
|
|
387
395
|
});
|
|
388
396
|
}
|
|
389
397
|
|
|
@@ -396,13 +404,13 @@ const ruleFunction$1 = (primary, secondaryOptions, context) => {
|
|
|
396
404
|
|
|
397
405
|
if (problems.length) {
|
|
398
406
|
for (const err of problems) {
|
|
399
|
-
report$
|
|
407
|
+
report$3({
|
|
400
408
|
index: err.index,
|
|
401
409
|
endIndex: err.endIndex,
|
|
402
410
|
message: err.message,
|
|
403
411
|
node: declNode,
|
|
404
412
|
result,
|
|
405
|
-
ruleName: ruleName$
|
|
413
|
+
ruleName: ruleName$5,
|
|
406
414
|
});
|
|
407
415
|
}
|
|
408
416
|
}
|
|
@@ -410,13 +418,108 @@ const ruleFunction$1 = (primary, secondaryOptions, context) => {
|
|
|
410
418
|
}
|
|
411
419
|
};
|
|
412
420
|
|
|
413
|
-
ruleFunction$
|
|
414
|
-
ruleFunction$
|
|
415
|
-
ruleFunction$
|
|
421
|
+
ruleFunction$3.ruleName = ruleName$5;
|
|
422
|
+
ruleFunction$3.messages = messages$5;
|
|
423
|
+
ruleFunction$3.meta = {
|
|
424
|
+
fixable: true,
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
var borders = createPlugin$3(ruleName$5, ruleFunction$3);
|
|
428
|
+
|
|
429
|
+
const {
|
|
430
|
+
createPlugin: createPlugin$2,
|
|
431
|
+
utils: {report: report$2, ruleMessages: ruleMessages$2, validateOptions: validateOptions$2},
|
|
432
|
+
} = stylelint;
|
|
433
|
+
|
|
434
|
+
const ruleName$4 = 'primer/box-shadow';
|
|
435
|
+
const messages$4 = ruleMessages$2(ruleName$4, {
|
|
436
|
+
rejected: (value, replacement) => {
|
|
437
|
+
if (!replacement) {
|
|
438
|
+
return `Please use a Primer box-shadow variable instead of '${value}'. Consult the primer docs for a suitable replacement. https://primer.style/foundations/primitives/color#shadow or https://primer.style/foundations/primitives/size#border-size`
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return `Please replace '${value}' with a Primer box-shadow variable '${replacement['name']}'. https://primer.style/foundations/primitives/color#shadow or https://primer.style/foundations/primitives/size#border-size`
|
|
442
|
+
},
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
const variables$1 = primitivesVariables('box-shadow');
|
|
446
|
+
const shadows = [];
|
|
447
|
+
|
|
448
|
+
for (const variable of variables$1) {
|
|
449
|
+
const name = variable['name'];
|
|
450
|
+
|
|
451
|
+
// TODO: Decide if this is safe. Someday we might have variables that
|
|
452
|
+
// have 'shadow' in the name but aren't full box-shadows.
|
|
453
|
+
if (name.includes('shadow') || name.includes('boxShadow')) {
|
|
454
|
+
shadows.push(variable);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/** @type {import('stylelint').Rule} */
|
|
459
|
+
const ruleFunction$2 = (primary, secondaryOptions, context) => {
|
|
460
|
+
return (root, result) => {
|
|
461
|
+
const validOptions = validateOptions$2(result, ruleName$4, {
|
|
462
|
+
actual: primary,
|
|
463
|
+
possible: [true],
|
|
464
|
+
});
|
|
465
|
+
const validValues = shadows;
|
|
466
|
+
|
|
467
|
+
if (!validOptions) return
|
|
468
|
+
|
|
469
|
+
root.walkDecls(declNode => {
|
|
470
|
+
const {prop, value} = declNode;
|
|
471
|
+
|
|
472
|
+
if (prop !== 'box-shadow') return
|
|
473
|
+
|
|
474
|
+
if (value === 'none') return
|
|
475
|
+
|
|
476
|
+
const problems = [];
|
|
477
|
+
|
|
478
|
+
const checkForVariable = (vars, nodeValue) => {
|
|
479
|
+
return vars.some(variable =>
|
|
480
|
+
new RegExp(`${variable['name'].replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`).test(nodeValue),
|
|
481
|
+
)
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
if (checkForVariable(validValues, value)) {
|
|
485
|
+
return
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const replacement = validValues.find(variable => variable.values.includes(value));
|
|
489
|
+
|
|
490
|
+
if (replacement && context.fix) {
|
|
491
|
+
declNode.value = value.replace(value, `var(${replacement['name']})`);
|
|
492
|
+
} else {
|
|
493
|
+
problems.push({
|
|
494
|
+
index: declarationValueIndex(declNode),
|
|
495
|
+
endIndex: declarationValueIndex(declNode) + value.length,
|
|
496
|
+
message: messages$4.rejected(value, replacement),
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (problems.length) {
|
|
501
|
+
for (const err of problems) {
|
|
502
|
+
report$2({
|
|
503
|
+
index: err.index,
|
|
504
|
+
endIndex: err.endIndex,
|
|
505
|
+
message: err.message,
|
|
506
|
+
node: declNode,
|
|
507
|
+
result,
|
|
508
|
+
ruleName: ruleName$4,
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
ruleFunction$2.ruleName = ruleName$4;
|
|
517
|
+
ruleFunction$2.messages = messages$4;
|
|
518
|
+
ruleFunction$2.meta = {
|
|
416
519
|
fixable: true,
|
|
417
520
|
};
|
|
418
521
|
|
|
419
|
-
var
|
|
522
|
+
var boxShadow = createPlugin$2(ruleName$4, ruleFunction$2);
|
|
420
523
|
|
|
421
524
|
const SKIP_VALUE_NODE_TYPES = new Set(['space', 'div']);
|
|
422
525
|
const SKIP_AT_RULE_NAMES = new Set(['each', 'for', 'function', 'mixin']);
|
|
@@ -662,18 +765,18 @@ function createVariableRule(ruleName, rules, url) {
|
|
|
662
765
|
let actualRules = rules;
|
|
663
766
|
let overrides = options.rules;
|
|
664
767
|
if (typeof rules === 'function') {
|
|
665
|
-
actualRules = rules({variables: variables$
|
|
768
|
+
actualRules = rules({variables: variables$3, options, ruleName});
|
|
666
769
|
} else {
|
|
667
770
|
actualRules = Object.assign({}, rules);
|
|
668
771
|
}
|
|
669
772
|
if (typeof overrides === 'function') {
|
|
670
773
|
delete options.rules;
|
|
671
|
-
overrides = overrides({rules: actualRules, options, ruleName, variables: variables$
|
|
774
|
+
overrides = overrides({rules: actualRules, options, ruleName, variables: variables$3});
|
|
672
775
|
}
|
|
673
776
|
if (overrides) {
|
|
674
777
|
Object.assign(actualRules, overrides);
|
|
675
778
|
}
|
|
676
|
-
const validate = declarationValidator(actualRules, {variables: variables$
|
|
779
|
+
const validate = declarationValidator(actualRules, {variables: variables$3});
|
|
677
780
|
|
|
678
781
|
// The stylelint docs suggest respecting a "disableFix" rule option that
|
|
679
782
|
// overrides the "global" context.fix (--fix) linting option.
|
|
@@ -707,10 +810,9 @@ function createVariableRule(ruleName, rules, url) {
|
|
|
707
810
|
const message = stylelint.utils
|
|
708
811
|
.ruleMessages(ruleName, {
|
|
709
812
|
rejected: m => {
|
|
710
|
-
|
|
813
|
+
{
|
|
711
814
|
return `${m}. See ${url}.`
|
|
712
815
|
}
|
|
713
|
-
return `${m}.`
|
|
714
816
|
},
|
|
715
817
|
})
|
|
716
818
|
.rejected(error);
|
|
@@ -735,27 +837,6 @@ function createVariableRule(ruleName, rules, url) {
|
|
|
735
837
|
|
|
736
838
|
function noop$2() {}
|
|
737
839
|
|
|
738
|
-
var boxShadow = createVariableRule(
|
|
739
|
-
'primer/box-shadow',
|
|
740
|
-
{
|
|
741
|
-
'box shadow': {
|
|
742
|
-
expects: 'a box-shadow variable',
|
|
743
|
-
props: 'box-shadow',
|
|
744
|
-
values: [
|
|
745
|
-
'$box-shadow*',
|
|
746
|
-
'$*-shadow',
|
|
747
|
-
'none',
|
|
748
|
-
// Match variables in any of the following formats: --color-shadow-*, --color-*-shadow-*, --color-*-shadow, --shadow-*, *shadow*
|
|
749
|
-
/var\(--color-(.+-)*shadow(-.+)*\)/,
|
|
750
|
-
/var\(--shadow(-.+)*\)/,
|
|
751
|
-
/var\((.+-)*shadow(-.+)*\)/,
|
|
752
|
-
],
|
|
753
|
-
singular: true,
|
|
754
|
-
},
|
|
755
|
-
},
|
|
756
|
-
'https://primer.style/css/utilities/box-shadow',
|
|
757
|
-
);
|
|
758
|
-
|
|
759
840
|
const bgVars = [
|
|
760
841
|
'$bg-*',
|
|
761
842
|
'$tooltip-background-color',
|
|
@@ -798,9 +879,9 @@ var colors = createVariableRule(
|
|
|
798
879
|
'https://primer.style/primitives/colors',
|
|
799
880
|
);
|
|
800
881
|
|
|
801
|
-
const ruleName$
|
|
882
|
+
const ruleName$3 = 'primer/responsive-widths';
|
|
802
883
|
|
|
803
|
-
const messages$
|
|
884
|
+
const messages$3 = stylelint.utils.ruleMessages(ruleName$3, {
|
|
804
885
|
rejected: value => {
|
|
805
886
|
return `A value larger than the smallest viewport could break responsive pages. Use a width value smaller than ${value}. https://primer.style/css/support/breakpoints`
|
|
806
887
|
},
|
|
@@ -820,7 +901,7 @@ const walkGroups = (root, validate) => {
|
|
|
820
901
|
};
|
|
821
902
|
|
|
822
903
|
// eslint-disable-next-line no-unused-vars
|
|
823
|
-
var responsiveWidths = stylelint.createPlugin(ruleName$
|
|
904
|
+
var responsiveWidths = stylelint.createPlugin(ruleName$3, (enabled, options = {}, context) => {
|
|
824
905
|
if (!enabled) {
|
|
825
906
|
return noop$1
|
|
826
907
|
}
|
|
@@ -856,7 +937,7 @@ var responsiveWidths = stylelint.createPlugin(ruleName$2, (enabled, options = {}
|
|
|
856
937
|
if (parseInt(valueUnit.number) > 320) {
|
|
857
938
|
problems.push({
|
|
858
939
|
index: declarationValueIndex(decl) + node.sourceIndex,
|
|
859
|
-
message: messages$
|
|
940
|
+
message: messages$3.rejected(node.value),
|
|
860
941
|
});
|
|
861
942
|
}
|
|
862
943
|
break
|
|
@@ -864,7 +945,7 @@ var responsiveWidths = stylelint.createPlugin(ruleName$2, (enabled, options = {}
|
|
|
864
945
|
if (parseInt(valueUnit.number) > 100) {
|
|
865
946
|
problems.push({
|
|
866
947
|
index: declarationValueIndex(decl) + node.sourceIndex,
|
|
867
|
-
message: messages$
|
|
948
|
+
message: messages$3.rejected(node.value),
|
|
868
949
|
});
|
|
869
950
|
}
|
|
870
951
|
break
|
|
@@ -878,7 +959,7 @@ var responsiveWidths = stylelint.createPlugin(ruleName$2, (enabled, options = {}
|
|
|
878
959
|
message: err.message,
|
|
879
960
|
node: decl,
|
|
880
961
|
result,
|
|
881
|
-
ruleName: ruleName$
|
|
962
|
+
ruleName: ruleName$3,
|
|
882
963
|
});
|
|
883
964
|
}
|
|
884
965
|
}
|
|
@@ -891,12 +972,12 @@ var responsiveWidths = stylelint.createPlugin(ruleName$2, (enabled, options = {}
|
|
|
891
972
|
function noop$1() {}
|
|
892
973
|
|
|
893
974
|
const {
|
|
894
|
-
createPlugin,
|
|
895
|
-
utils: {report, ruleMessages, validateOptions},
|
|
975
|
+
createPlugin: createPlugin$1,
|
|
976
|
+
utils: {report: report$1, ruleMessages: ruleMessages$1, validateOptions: validateOptions$1},
|
|
896
977
|
} = stylelint;
|
|
897
978
|
|
|
898
|
-
const ruleName$
|
|
899
|
-
const messages$
|
|
979
|
+
const ruleName$2 = 'primer/spacing';
|
|
980
|
+
const messages$2 = ruleMessages$1(ruleName$2, {
|
|
900
981
|
rejected: (value, replacement) => {
|
|
901
982
|
if (!replacement) {
|
|
902
983
|
return `Please use a primer size variable instead of '${value}'. Consult the primer docs for a suitable replacement. https://primer.style/foundations/primitives/size`
|
|
@@ -907,7 +988,7 @@ const messages$1 = ruleMessages(ruleName$1, {
|
|
|
907
988
|
});
|
|
908
989
|
|
|
909
990
|
// Props that we want to check
|
|
910
|
-
const propList = ['padding', 'margin', 'top', 'right', 'bottom', 'left'];
|
|
991
|
+
const propList$1 = ['padding', 'margin', 'top', 'right', 'bottom', 'left'];
|
|
911
992
|
// Values that we want to ignore
|
|
912
993
|
const valueList = ['${'];
|
|
913
994
|
|
|
@@ -924,9 +1005,9 @@ for (const size of sizes) {
|
|
|
924
1005
|
}
|
|
925
1006
|
|
|
926
1007
|
/** @type {import('stylelint').Rule} */
|
|
927
|
-
const ruleFunction = (primary, secondaryOptions, context) => {
|
|
1008
|
+
const ruleFunction$1 = (primary, secondaryOptions, context) => {
|
|
928
1009
|
return (root, result) => {
|
|
929
|
-
const validOptions = validateOptions(result, ruleName$
|
|
1010
|
+
const validOptions = validateOptions$1(result, ruleName$2, {
|
|
930
1011
|
actual: primary,
|
|
931
1012
|
possible: [true],
|
|
932
1013
|
});
|
|
@@ -936,7 +1017,7 @@ const ruleFunction = (primary, secondaryOptions, context) => {
|
|
|
936
1017
|
root.walkDecls(declNode => {
|
|
937
1018
|
const {prop, value} = declNode;
|
|
938
1019
|
|
|
939
|
-
if (!propList.some(spacingProp => prop.startsWith(spacingProp))) return
|
|
1020
|
+
if (!propList$1.some(spacingProp => prop.startsWith(spacingProp))) return
|
|
940
1021
|
if (valueList.some(valueToIgnore => value.includes(valueToIgnore))) return
|
|
941
1022
|
|
|
942
1023
|
const problems = [];
|
|
@@ -981,7 +1062,7 @@ const ruleFunction = (primary, secondaryOptions, context) => {
|
|
|
981
1062
|
problems.push({
|
|
982
1063
|
index: declarationValueIndex(declNode) + node.sourceIndex,
|
|
983
1064
|
endIndex: declarationValueIndex(declNode) + node.sourceIndex + node.value.length,
|
|
984
|
-
message: messages$
|
|
1065
|
+
message: messages$2.rejected(node.value, replacement),
|
|
985
1066
|
});
|
|
986
1067
|
}
|
|
987
1068
|
|
|
@@ -992,6 +1073,189 @@ const ruleFunction = (primary, secondaryOptions, context) => {
|
|
|
992
1073
|
declNode.value = parsedValue.toString();
|
|
993
1074
|
}
|
|
994
1075
|
|
|
1076
|
+
if (problems.length) {
|
|
1077
|
+
for (const err of problems) {
|
|
1078
|
+
report$1({
|
|
1079
|
+
index: err.index,
|
|
1080
|
+
endIndex: err.endIndex,
|
|
1081
|
+
message: err.message,
|
|
1082
|
+
node: declNode,
|
|
1083
|
+
result,
|
|
1084
|
+
ruleName: ruleName$2,
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
};
|
|
1091
|
+
|
|
1092
|
+
ruleFunction$1.ruleName = ruleName$2;
|
|
1093
|
+
ruleFunction$1.messages = messages$2;
|
|
1094
|
+
ruleFunction$1.meta = {
|
|
1095
|
+
fixable: true,
|
|
1096
|
+
};
|
|
1097
|
+
|
|
1098
|
+
var spacing = createPlugin$1(ruleName$2, ruleFunction$1);
|
|
1099
|
+
|
|
1100
|
+
const {
|
|
1101
|
+
createPlugin,
|
|
1102
|
+
utils: {report, ruleMessages, validateOptions},
|
|
1103
|
+
} = stylelint;
|
|
1104
|
+
|
|
1105
|
+
const ruleName$1 = 'primer/typography';
|
|
1106
|
+
const messages$1 = ruleMessages(ruleName$1, {
|
|
1107
|
+
rejected: (value, replacement) => {
|
|
1108
|
+
// no possible replacement
|
|
1109
|
+
if (!replacement) {
|
|
1110
|
+
return `Please use a Primer typography variable instead of '${value}'. Consult the primer docs for a suitable replacement. https://primer.style/foundations/primitives/typography`
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
// multiple possible replacements
|
|
1114
|
+
if (replacement.length) {
|
|
1115
|
+
return `Please use one of the following Primer typography variables instead of '${value}': ${replacement.map(replacementObj => `'${replacementObj.name}'`).join(', ')}. https://primer.style/foundations/primitives/typography`
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
// one possible replacement
|
|
1119
|
+
return `Please replace '${value}' with Primer typography variable '${replacement['name']}'. https://primer.style/foundations/primitives/typography`
|
|
1120
|
+
},
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
const fontWeightKeywordMap = {
|
|
1124
|
+
normal: 400,
|
|
1125
|
+
bold: 600,
|
|
1126
|
+
bolder: 600,
|
|
1127
|
+
lighter: 300,
|
|
1128
|
+
};
|
|
1129
|
+
const getClosestFontWeight = (goalWeightNumber, fontWeightsTokens) => {
|
|
1130
|
+
return fontWeightsTokens.reduce((prev, curr) =>
|
|
1131
|
+
Math.abs(curr.values - goalWeightNumber) < Math.abs(prev.values - goalWeightNumber) ? curr : prev,
|
|
1132
|
+
).values
|
|
1133
|
+
};
|
|
1134
|
+
|
|
1135
|
+
const variables = primitivesVariables('typography');
|
|
1136
|
+
const fontSizes = [];
|
|
1137
|
+
const fontWeights = [];
|
|
1138
|
+
const lineHeights = [];
|
|
1139
|
+
const fontStacks = [];
|
|
1140
|
+
const fontShorthands = [];
|
|
1141
|
+
|
|
1142
|
+
// Props that we want to check for typography variables
|
|
1143
|
+
const propList = ['font-size', 'font-weight', 'line-height', 'font-family', 'font'];
|
|
1144
|
+
|
|
1145
|
+
for (const variable of variables) {
|
|
1146
|
+
const name = variable['name'];
|
|
1147
|
+
|
|
1148
|
+
if (name.includes('size')) {
|
|
1149
|
+
fontSizes.push(variable);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
if (name.includes('weight')) {
|
|
1153
|
+
fontWeights.push(variable);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
if (name.includes('lineHeight')) {
|
|
1157
|
+
lineHeights.push(variable);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
if (name.includes('fontStack')) {
|
|
1161
|
+
fontStacks.push(variable);
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
if (name.includes('shorthand')) {
|
|
1165
|
+
fontShorthands.push(variable);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
/** @type {import('stylelint').Rule} */
|
|
1170
|
+
const ruleFunction = (primary, secondaryOptions, context) => {
|
|
1171
|
+
return (root, result) => {
|
|
1172
|
+
const validOptions = validateOptions(result, ruleName$1, {
|
|
1173
|
+
actual: primary,
|
|
1174
|
+
possible: [true],
|
|
1175
|
+
});
|
|
1176
|
+
let validValues = [];
|
|
1177
|
+
|
|
1178
|
+
if (!validOptions) return
|
|
1179
|
+
|
|
1180
|
+
root.walkDecls(declNode => {
|
|
1181
|
+
const {prop, value} = declNode;
|
|
1182
|
+
|
|
1183
|
+
if (!propList.some(typographyProp => prop.startsWith(typographyProp))) return
|
|
1184
|
+
|
|
1185
|
+
const problems = [];
|
|
1186
|
+
|
|
1187
|
+
const checkForVariable = (vars, nodeValue) =>
|
|
1188
|
+
vars.some(variable =>
|
|
1189
|
+
new RegExp(`${variable['name'].replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`).test(nodeValue),
|
|
1190
|
+
);
|
|
1191
|
+
|
|
1192
|
+
// Exact values to ignore.
|
|
1193
|
+
if (value === 'inherit') {
|
|
1194
|
+
return
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
switch (prop) {
|
|
1198
|
+
case 'font-size':
|
|
1199
|
+
validValues = fontSizes;
|
|
1200
|
+
break
|
|
1201
|
+
case 'font-weight':
|
|
1202
|
+
validValues = fontWeights;
|
|
1203
|
+
break
|
|
1204
|
+
case 'line-height':
|
|
1205
|
+
validValues = lineHeights;
|
|
1206
|
+
break
|
|
1207
|
+
case 'font-family':
|
|
1208
|
+
validValues = fontStacks;
|
|
1209
|
+
break
|
|
1210
|
+
case 'font':
|
|
1211
|
+
validValues = fontShorthands;
|
|
1212
|
+
break
|
|
1213
|
+
default:
|
|
1214
|
+
validValues = [];
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
if (checkForVariable(validValues, value)) {
|
|
1218
|
+
return
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
const getReplacements = () => {
|
|
1222
|
+
const replacementTokens = validValues.filter(variable => {
|
|
1223
|
+
if (!(variable.values instanceof Array)) {
|
|
1224
|
+
let nodeValue = value;
|
|
1225
|
+
|
|
1226
|
+
if (prop === 'font-weight') {
|
|
1227
|
+
nodeValue = getClosestFontWeight(fontWeightKeywordMap[value] || value, fontWeights);
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
return variable.values.toString() === nodeValue.toString()
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
return variable.values.includes(value.replace('-', ''))
|
|
1234
|
+
});
|
|
1235
|
+
|
|
1236
|
+
if (!replacementTokens.length) {
|
|
1237
|
+
return
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
if (replacementTokens.length > 1) {
|
|
1241
|
+
return replacementTokens
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
return replacementTokens[0]
|
|
1245
|
+
};
|
|
1246
|
+
const replacement = getReplacements();
|
|
1247
|
+
const fixable = replacement && !replacement.length;
|
|
1248
|
+
|
|
1249
|
+
if (fixable && context.fix) {
|
|
1250
|
+
declNode.value = value.replace(value, `var(${replacement['name']})`);
|
|
1251
|
+
} else {
|
|
1252
|
+
problems.push({
|
|
1253
|
+
index: declarationValueIndex(declNode),
|
|
1254
|
+
endIndex: declarationValueIndex(declNode) + value.length,
|
|
1255
|
+
message: messages$1.rejected(value, replacement, prop),
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
|
|
995
1259
|
if (problems.length) {
|
|
996
1260
|
for (const err of problems) {
|
|
997
1261
|
report({
|
|
@@ -1014,30 +1278,7 @@ ruleFunction.meta = {
|
|
|
1014
1278
|
fixable: true,
|
|
1015
1279
|
};
|
|
1016
1280
|
|
|
1017
|
-
var
|
|
1018
|
-
|
|
1019
|
-
var typography = createVariableRule(
|
|
1020
|
-
'primer/typography',
|
|
1021
|
-
{
|
|
1022
|
-
'font-size': {
|
|
1023
|
-
expects: 'a font-size variable',
|
|
1024
|
-
values: ['$body-font-size', '$h{000,00,0,1,2,3,4,5,6}-size', '$font-size-*', '1', '1em', 'inherit'],
|
|
1025
|
-
},
|
|
1026
|
-
'font-weight': {
|
|
1027
|
-
props: 'font-weight',
|
|
1028
|
-
values: ['$font-weight-*', 'inherit'],
|
|
1029
|
-
replacements: {
|
|
1030
|
-
bold: '$font-weight-bold',
|
|
1031
|
-
normal: '$font-weight-normal',
|
|
1032
|
-
},
|
|
1033
|
-
},
|
|
1034
|
-
'line-height': {
|
|
1035
|
-
props: 'line-height',
|
|
1036
|
-
values: ['$body-line-height', '$lh-*', '0', '1', '1em', 'inherit'],
|
|
1037
|
-
},
|
|
1038
|
-
},
|
|
1039
|
-
'https://primer.style/css/utilities/typography',
|
|
1040
|
-
);
|
|
1281
|
+
var typography = createPlugin(ruleName$1, ruleFunction);
|
|
1041
1282
|
|
|
1042
1283
|
const ruleName = 'primer/no-display-colors';
|
|
1043
1284
|
const messages = stylelint.utils.ruleMessages(ruleName, {
|
|
@@ -1222,8 +1463,6 @@ var index = {
|
|
|
1222
1463
|
'length-zero-no-unit': null,
|
|
1223
1464
|
'selector-max-type': null,
|
|
1224
1465
|
'primer/colors': null,
|
|
1225
|
-
'primer/typography': null,
|
|
1226
|
-
'primer/box-shadow': null,
|
|
1227
1466
|
},
|
|
1228
1467
|
},
|
|
1229
1468
|
{
|
|
@@ -1248,7 +1487,6 @@ var index = {
|
|
|
1248
1487
|
},
|
|
1249
1488
|
{
|
|
1250
1489
|
files: ['**/*.module.css'],
|
|
1251
|
-
plugins: ['stylelint-css-modules-no-global-scoped-selector'],
|
|
1252
1490
|
rules: {
|
|
1253
1491
|
'property-no-unknown': [
|
|
1254
1492
|
true,
|
|
@@ -1273,10 +1511,6 @@ var index = {
|
|
|
1273
1511
|
ignoreFunctions: ['global'],
|
|
1274
1512
|
},
|
|
1275
1513
|
],
|
|
1276
|
-
'css-modules/no-global-scoped-selector': true,
|
|
1277
|
-
// temporarily disabiling Primer plugins while we work on upgrades https://github.com/github/primer/issues/3165
|
|
1278
|
-
'primer/typography': null,
|
|
1279
|
-
'primer/box-shadow': null,
|
|
1280
1514
|
},
|
|
1281
1515
|
},
|
|
1282
1516
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primer/stylelint-config",
|
|
3
|
-
"version": "13.0.0
|
|
3
|
+
"version": "13.0.0",
|
|
4
4
|
"description": "Sharable stylelint config used by GitHub's CSS",
|
|
5
5
|
"author": "GitHub, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@github/browserslist-config": "^1.0.0",
|
|
47
47
|
"@primer/css": "^21.0.8",
|
|
48
|
-
"@primer/primitives": "^
|
|
48
|
+
"@primer/primitives": "^9.0.1",
|
|
49
49
|
"anymatch": "^3.1.1",
|
|
50
50
|
"postcss-scss": "^4.0.2",
|
|
51
51
|
"postcss-styled-syntax": "^0.6.4",
|
|
@@ -53,38 +53,32 @@
|
|
|
53
53
|
"string.prototype.matchall": "^4.0.2",
|
|
54
54
|
"stylelint": "^16.3.1",
|
|
55
55
|
"stylelint-config-standard": "^36.0.0",
|
|
56
|
-
"stylelint-css-modules-no-global-scoped-selector": "^1.0.2",
|
|
57
56
|
"stylelint-no-unsupported-browser-features": "^8.0.0",
|
|
58
57
|
"stylelint-order": "^6.0.4",
|
|
59
58
|
"stylelint-scss": "^6.2.0",
|
|
60
59
|
"stylelint-value-no-unknown-custom-properties": "^6.0.1",
|
|
61
60
|
"tap-map": "^1.0.0"
|
|
62
61
|
},
|
|
63
|
-
"overrides": {
|
|
64
|
-
"stylelint-css-modules-no-global-scoped-selector": {
|
|
65
|
-
"stylelint": "$stylelint",
|
|
66
|
-
"postcss-modules-local-by-default": "^4.0.0"
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
62
|
"prettier": "@github/prettier-config",
|
|
70
63
|
"devDependencies": {
|
|
71
64
|
"@changesets/changelog-github": "^0.5.0",
|
|
72
|
-
"@changesets/cli": "2.27.
|
|
65
|
+
"@changesets/cli": "2.27.7",
|
|
73
66
|
"@github/prettier-config": "^0.0.6",
|
|
74
|
-
"@rollup/plugin-commonjs": "^
|
|
67
|
+
"@rollup/plugin-commonjs": "^26.0.1",
|
|
75
68
|
"@rollup/plugin-json": "^6.1.0",
|
|
76
69
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
77
|
-
"@typescript-eslint/parser": "^
|
|
70
|
+
"@typescript-eslint/parser": "^8.0.1",
|
|
78
71
|
"dedent": "^1.5.3",
|
|
79
|
-
"eslint": "^8.0
|
|
80
|
-
"eslint-plugin-github": "^
|
|
72
|
+
"eslint": "^8.57.0",
|
|
73
|
+
"eslint-plugin-github": "^5.0.1",
|
|
74
|
+
"eslint-plugin-import": "^2.29.1",
|
|
81
75
|
"eslint-plugin-jest": "^28.2.0",
|
|
82
76
|
"eslint-plugin-prettier": "^5.1.3",
|
|
83
77
|
"jest": "^29.7.0",
|
|
84
78
|
"jest-preset-stylelint": "^7.0.0",
|
|
85
79
|
"prettier": "^3.2.5",
|
|
86
|
-
"rimraf": "^
|
|
87
|
-
"rollup": "^4.
|
|
80
|
+
"rimraf": "^6.0.1",
|
|
81
|
+
"rollup": "^4.21.1"
|
|
88
82
|
},
|
|
89
83
|
"jest": {
|
|
90
84
|
"transform": {},
|