-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Creating stylelint plugin for no deprecated color vars (#99)
* Creating stylelint plugin for no deprecated color vars * Fix import * Need primitives for dev mode * Create cyan-gifts-rule.md * Adding docs * Adding unfixable test * Adding plugin * Lint fix * Update .changeset/cyan-gifts-rule.md Co-authored-by: Cole Bemis <colebemis@github.com> * Use colors main path and config passing in deprecations location. * Updating warning messages for null, arrays, and normal * Use caret * Unused variable Co-authored-by: Cole Bemis <colebemis@github.com>
- Loading branch information
Showing
8 changed files
with
166 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"stylelint-config-primer": patch | ||
--- | ||
|
||
Create `no-deprecated-colors` rule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"text.primary": "fg.default", | ||
"text.secondary": ["fg.one", "fg.two"], | ||
"text.white": null | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
const path = require('path') | ||
const {ruleName} = require('../plugins/no-deprecated-colors') | ||
|
||
// eslint-disable-next-line no-undef | ||
testRule({ | ||
plugins: ['./plugins/no-deprecated-colors.js'], | ||
ruleName, | ||
config: [ | ||
true, | ||
{ | ||
deprecatedFile: path.join(__dirname, '__fixtures__/deprecations.json') | ||
} | ||
], | ||
fix: true, | ||
accept: [{code: '.x { color: var(--color-fg-default, var(--color-text-primary)); }'}], | ||
reject: [ | ||
{ | ||
code: '.x { border: 1px solid var(--color-text-primary); }', | ||
fixed: '.x { border: 1px solid var(--color-fg-default); }', | ||
message: `--color-text-primary is a deprecated color variable. Please use the replacement --color-fg-default. (primer/no-deprecated-colors)`, | ||
line: 1, | ||
column: 6 | ||
}, | ||
{ | ||
code: '.x { border: 1px solid var(--color-text-secondary); }', | ||
unfixable: true, | ||
message: `--color-text-secondary is a deprecated color variable. Please use one of (--color-fg-one, --color-fg-two). (primer/no-deprecated-colors)`, | ||
line: 1, | ||
column: 6 | ||
}, | ||
{ | ||
code: '.x { border: 1px solid var(--color-text-white); }', | ||
unfixable: true, | ||
message: `--color-text-white is a deprecated color variable. Please consult the primer color docs for a replacement. https://primer.style/primitives (primer/no-deprecated-colors)`, | ||
line: 1, | ||
column: 6 | ||
} | ||
] | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
const stylelint = require('stylelint') | ||
const kebabCase = require('lodash.kebabcase') | ||
const matchAll = require('string.prototype.matchall') | ||
|
||
const ruleName = 'primer/no-deprecated-colors' | ||
const messages = stylelint.utils.ruleMessages(ruleName, { | ||
rejected: (varName, replacement) => { | ||
if (replacement === null) { | ||
return `${varName} is a deprecated color variable. Please consult the primer color docs for a replacement. https://primer.style/primitives` | ||
} | ||
|
||
if (Array.isArray(replacement)) { | ||
replacement = replacement.map(r => `--color-${kebabCase(r)}`) | ||
return `${varName} is a deprecated color variable. Please use one of (${replacement.join(', ')}).` | ||
} | ||
|
||
replacement = `--color-${kebabCase(replacement)}` | ||
return `${varName} is a deprecated color variable. Please use the replacement ${replacement}.` | ||
} | ||
}) | ||
|
||
// Match CSS variable references (e.g var(--color-text-primary)) | ||
// eslint-disable-next-line no-useless-escape | ||
const variableReferenceRegex = /var\(([^\),]+)(,.*)?\)/g | ||
|
||
module.exports = stylelint.createPlugin(ruleName, (enabled, options = {}, context) => { | ||
if (!enabled) { | ||
return noop | ||
} | ||
|
||
const {verbose = false} = options | ||
// eslint-disable-next-line no-console | ||
const log = verbose ? (...args) => console.warn(...args) : noop | ||
|
||
// Keep track of declarations we've already seen | ||
const seen = new WeakMap() | ||
|
||
// eslint-disable-next-line import/no-dynamic-require | ||
const deprecatedColors = require(options.deprecatedFile || '@primer/primitives/dist/deprecations/colors.json') | ||
|
||
const convertedCSSVars = Object.entries(deprecatedColors) | ||
.map(([k, v]) => { | ||
return [`--color-${kebabCase(k)}`, v] | ||
}) | ||
.reduce((acc, [key, value]) => { | ||
acc[key] = value | ||
return acc | ||
}, {}) | ||
|
||
return (root, result) => { | ||
root.walkRules(rule => { | ||
rule.walkDecls(decl => { | ||
if (seen.has(decl)) { | ||
return | ||
} else { | ||
seen.set(decl, true) | ||
} | ||
|
||
for (const [, variableName] of matchAll(decl.value, variableReferenceRegex)) { | ||
log(`Found variable reference ${variableName}`) | ||
if (variableName in convertedCSSVars) { | ||
let replacement = convertedCSSVars[variableName] | ||
|
||
if (context.fix && replacement !== null && !Array.isArray(replacement)) { | ||
replacement = `--color-${kebabCase(replacement)}` | ||
decl.value = decl.value.replace(variableName, replacement) | ||
return | ||
} | ||
|
||
stylelint.utils.report({ | ||
message: messages.rejected(variableName, replacement), | ||
node: decl, | ||
ruleName, | ||
result | ||
}) | ||
} | ||
} | ||
}) | ||
}) | ||
} | ||
}) | ||
|
||
function noop() {} | ||
|
||
module.exports.ruleName = ruleName | ||
module.exports.messages = messages |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters