forked from angular/components
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Removes `gulp-autoprefixer` in order to avoid issues with Google's internal build system. * Switches to adding vendor prefixes via SCSS mixins. * Adds a custom Stylelint plugin that utilizies Autoprefixer to find unprefixed properties, values, @rules etc. Fixes angular#3536.
- Loading branch information
Showing
14 changed files
with
198 additions
and
31 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
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 |
---|---|---|
@@ -1,7 +1,9 @@ | ||
@import './prefixes'; | ||
|
||
// Mixin overriding default button styles like the gray background, the border, and the outline. | ||
@mixin mat-button-reset { | ||
@include user-select(none); | ||
cursor: pointer; | ||
user-select: none; | ||
outline: none; | ||
border: none; | ||
} |
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,31 @@ | ||
/* stylelint-disable material/no-prefixes */ | ||
@mixin user-select($value) { | ||
-webkit-user-select: none; | ||
-moz-user-select: none; | ||
-ms-user-select: none; | ||
user-select: none; | ||
} | ||
|
||
@mixin placeholder { | ||
&::placeholder { | ||
@content; | ||
} | ||
|
||
&::-moz-placeholder { | ||
@content; | ||
} | ||
|
||
&::-webkit-input-placeholder { | ||
@content; | ||
} | ||
|
||
&:-ms-input-placeholder { | ||
@content; | ||
} | ||
} | ||
|
||
@mixin cursor-grab { | ||
cursor: -webkit-grab; | ||
cursor: grab; | ||
} | ||
/* stylelint-enable */ |
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
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,59 @@ | ||
const autoprefixer = require('autoprefixer'); | ||
const Browsers = require('autoprefixer/lib/browsers'); | ||
const Prefixes = require('autoprefixer/lib/prefixes'); | ||
|
||
/** | ||
* Utility to be used when checking whether a CSS declaration needs to be prefixed. | ||
* Based on https://github.com/stylelint/stylelint/blob/master/lib/utils/isAutoprefixable.js | ||
*/ | ||
module.exports = class NeedsPrefix { | ||
constructor(browsers) { | ||
this._prefixes = new Prefixes( | ||
autoprefixer.data.prefixes, | ||
new Browsers(autoprefixer.data.browsers, browsers) | ||
); | ||
} | ||
|
||
/** Checks whether an @-rule needs to be prefixed. */ | ||
atRule(identifier) { | ||
return this._prefixes.add[`@${identifier.toLowerCase()}`]; | ||
} | ||
|
||
/** Checks whether a selector needs to be prefixed. */ | ||
selector(identifier) { | ||
return this._prefixes.add.selectors.some(selectorObj => { | ||
return identifier.toLowerCase() === selectorObj.name; | ||
}); | ||
} | ||
|
||
/** Checks whether a media query value needs to be prefixed. */ | ||
mediaFeature(identifier) { | ||
return identifier.toLowerCase().indexOf('device-pixel-ratio') > -1; | ||
} | ||
|
||
/** Checks whether a property needs to be prefixed. */ | ||
property(identifier) { | ||
// `fill` is an edge case since it was part of a proposal that got renamed to `stretch`. | ||
// see: https://www.w3.org/TR/css-sizing-3/#changes | ||
if (!identifier || identifier === 'fill') return false; | ||
|
||
const needsPrefix = autoprefixer.data.prefixes[identifier.toLowerCase()]; | ||
const browsersThatNeedPrefix = needsPrefix ? needsPrefix.browsers : null; | ||
|
||
return !!browsersThatNeedPrefix && !!this._prefixes.browsers.selected.find(browser => { | ||
return browsersThatNeedPrefix.indexOf(browser) > -1; | ||
}); | ||
} | ||
|
||
/** Checks whether a CSS property value needs to be prefixed. */ | ||
value(prop, value) { | ||
if (!prop || !value) return false; | ||
|
||
const possiblePrefixableValues = this._prefixes.add[prop.toLowerCase()] && | ||
this._prefixes.add[prop.toLowerCase()].values; | ||
|
||
return !!possiblePrefixableValues && possiblePrefixableValues.some(valueObj => { | ||
return value.toLowerCase() === valueObj.name; | ||
}); | ||
} | ||
}; |
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,88 @@ | ||
const stylelint = require('stylelint'); | ||
const NeedsPrefix = require('./needs-prefix'); | ||
const parseSelector = require('stylelint/lib/utils/parseSelector'); | ||
|
||
const ruleName = 'material/no-prefixes'; | ||
const messages = stylelint.utils.ruleMessages(ruleName, { | ||
property: property => `Unprefixed property "${property}".`, | ||
value: (property, value) => `Unprefixed value in "${property}: ${value}".`, | ||
atRule: name => `Unprefixed @rule "${name}".`, | ||
mediaFeature: value => `Unprefixed media feature "${value}".`, | ||
selector: selector => `Unprefixed selector "${selector}".` | ||
}); | ||
|
||
/** | ||
* Stylelint plugin that warns for unprefixed CSS. | ||
*/ | ||
const plugin = stylelint.createPlugin(ruleName, browsers => { | ||
return (root, result) => { | ||
if (!stylelint.utils.validateOptions(result, ruleName, {})) return; | ||
|
||
const needsPrefix = new NeedsPrefix(browsers); | ||
|
||
// Check all of the `property: value` pairs. | ||
root.walkDecls(decl => { | ||
if (needsPrefix.property(decl.prop)) { | ||
stylelint.utils.report({ | ||
result, | ||
ruleName, | ||
message: messages.property(decl.prop), | ||
node: decl, | ||
index: (decl.raws.before || '').length | ||
}); | ||
} else if (needsPrefix.value(decl.prop, decl.value)) { | ||
stylelint.utils.report({ | ||
result, | ||
ruleName, | ||
message: messages.value(decl.prop, decl.value), | ||
node: decl, | ||
index: (decl.raws.before || '').length | ||
}); | ||
} | ||
}); | ||
|
||
// Check all of the @-rules and their values. | ||
root.walkAtRules(rule => { | ||
if (needsPrefix.atRule(rule.name)) { | ||
stylelint.utils.report({ | ||
result, | ||
ruleName, | ||
message: messages.atRule(rule.name), | ||
node: rule | ||
}); | ||
} else if (needsPrefix.mediaFeature(rule.params)) { | ||
stylelint.utils.report({ | ||
result, | ||
ruleName, | ||
message: messages.mediaFeature(rule.name), | ||
node: rule | ||
}); | ||
} | ||
}); | ||
|
||
// Walk the rules and check if the selector needs prefixes. | ||
root.walkRules(rule => { | ||
// Silence warnings for SASS selectors. Stylelint does this in their own rules as well: | ||
// https://github.com/stylelint/stylelint/blob/master/lib/utils/isStandardSyntaxSelector.js | ||
parseSelector(rule.selector, { warn: () => {} }, rule, selectorTree => { | ||
selectorTree.walkPseudos(pseudoNode => { | ||
if (needsPrefix.selector(pseudoNode.value)) { | ||
stylelint.utils.report({ | ||
result, | ||
ruleName, | ||
message: messages.selector(pseudoNode.value), | ||
node: rule, | ||
index: (rule.raws.before || '').length + pseudoNode.sourceIndex, | ||
}); | ||
} | ||
}); | ||
}); | ||
}); | ||
|
||
}; | ||
}); | ||
|
||
|
||
plugin.ruleName = ruleName; | ||
plugin.messages = messages; | ||
module.exports = plugin; |