stylelint-no-px
Advanced tools
Comparing version
124
index.js
@@ -1,123 +0,1 @@ | ||
'use strict' | ||
const stylelint = require('stylelint') | ||
const valueParser = require('postcss-value-parser') | ||
const ruleName = 'meowtec/no-px' | ||
const messages = stylelint.utils.ruleMessages(ruleName, { | ||
rem() { | ||
return `Use rem instead of px` | ||
}, | ||
}) | ||
const defaultSecondaryOptions = { | ||
ignore: [ '1px' ] | ||
} | ||
const post1px = /\s+1px/ | ||
const propInList = (prop, list) => { | ||
return prop && list.some(item => { | ||
return !post1px.test(item) && prop.indexOf(item) > -1 | ||
}) | ||
} | ||
const propAdd1pxInList = (prop, list) => { | ||
return prop && list.some(item => { | ||
if (!post1px.test(item)) return | ||
return prop.indexOf(item.replace(post1px, '')) > -1 | ||
}) | ||
} | ||
/** | ||
* check if a value has forbidden `px` | ||
* @param {string} value | ||
*/ | ||
const hasForbiddenPX = (node, options) => { | ||
const type = node.type | ||
const value = type === 'decl' ? node.value : node.params | ||
const prop = type === 'decl' ? node.prop : null | ||
const parsed = valueParser(value) | ||
let hasPX = false | ||
const ignore = options.ignore || defaultSecondaryOptions.ignore | ||
const ignore1px = ignore.indexOf('1px') > -1 | ||
if (type === 'decl' && propInList(node.prop, ignore)) return | ||
parsed.walk(node => { | ||
// if node is `url(xxx)`, prevent the traversal | ||
if (node.type === 'function' && node.value === 'url') { | ||
return false | ||
} | ||
let matched | ||
if (node.type === 'word' && (matched = node.value.match(/^(\d+(\.\d+)?)px$/))) { | ||
const px = matched[1] | ||
if (px === '0') { | ||
return | ||
} | ||
if (px !== '1') { | ||
hasPX = true | ||
return | ||
} | ||
if (!propAdd1pxInList(prop, ignore) && !ignore1px) { | ||
hasPX = true | ||
} | ||
} else if (node.type === 'string' && /(@\{[\w-]+\})px\b/.test(node.value)) { | ||
// eg. ~'@{width}px' | ||
hasPX = true | ||
} | ||
}) | ||
return hasPX | ||
} | ||
module.exports = stylelint.createPlugin(ruleName, (primaryOption, secondaryOptionObject) => { | ||
primaryOption = primaryOption || '' | ||
return (root, result) => { | ||
if (!primaryOption) return | ||
secondaryOptionObject = secondaryOptionObject || defaultSecondaryOptions | ||
// const validOptions = stylelint.utils.validateOptions({ | ||
// ruleName: ruleName, | ||
// result: result, | ||
// actual: primaryOption, | ||
// }) | ||
// if (!validOptions) { | ||
// return | ||
// } | ||
root.walkDecls(declaration => { | ||
if (hasForbiddenPX(declaration, secondaryOptionObject)) { | ||
stylelint.utils.report({ | ||
ruleName: ruleName, | ||
result: result, | ||
node: declaration, | ||
message: messages.rem(), | ||
}) | ||
} | ||
}) | ||
root.walkAtRules(atRule => { | ||
if (hasForbiddenPX(atRule, secondaryOptionObject)) { | ||
stylelint.utils.report({ | ||
ruleName: ruleName, | ||
result: result, | ||
node: atRule, | ||
message: messages.rem(), | ||
}) | ||
} | ||
}) | ||
} | ||
}) | ||
module.exports.ruleName = ruleName | ||
module.exports.messages = messages | ||
module.exports = require('./lib/') |
{ | ||
"name": "stylelint-no-px", | ||
"version": "0.11.0", | ||
"version": "0.12.0", | ||
"description": "A stylelint custom rule to ensure using rem instead of px", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -32,3 +32,3 @@ # stylelint-no-px | ||
// ... | ||
"meowtec/no-px": [true, { "ignore": ["1px", "font"] }], | ||
"meowtec/no-px": [true, { "ignore": ["1px"] }], | ||
// or just: | ||
@@ -35,0 +35,0 @@ "meowtec/no-px": true, |
@@ -157,1 +157,22 @@ 'use strict' | ||
}) | ||
// ignoreFunctions | ||
testRule(useRem.rule, { | ||
ruleName: useRem.ruleName, | ||
config: [true, {ignoreFunctions: ['rem', 'rem-calc']}], | ||
skipBasicChecks: true, | ||
accept: [ | ||
{ code: '.foo { font-size: rem(15px); border-left: rem-calc(12px) solid #333; }' }, | ||
], | ||
reject: [ | ||
{ | ||
code: '.foo { width: calc(100% - 12px); }', | ||
line: 1, | ||
column: 8, | ||
}, | ||
], | ||
}) |
9848
5.78%252
10.53%