Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/mq4-hover-shim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Rebert <code@rebertia.com>2015-01-19 04:10:51 +0300
committerChris Rebert <code@rebertia.com>2015-01-19 04:12:56 +0300
commit5b3cac92b9abb5a150c6afc9efbba0da324186a6 (patch)
tree38485ce475b0d095aeed20e1b113661e3a21a708
parent9d035dd8ce8301982f3f28b6017625c29f0f59da (diff)
postprocessor => postprocessorFor()
Don't use postcss options because they can't be passed along when using grunt-postcss.
-rw-r--r--README.md9
-rw-r--r--src/nodejs/index.js2
-rw-r--r--src/nodejs/postprocessor.js76
-rw-r--r--test/postprocessor_test.js38
4 files changed, 67 insertions, 58 deletions
diff --git a/README.md b/README.md
index 56afeb2..aa87295 100644
--- a/README.md
+++ b/README.md
@@ -99,7 +99,13 @@ Unofficially supported:
## API
### Node.js module; CSS postprocessor
The npm module has the following properties:
-* `postprocessor` - CSS postprocessor that transforms the source CSS as described above. A [PostCSS](https://github.com/postcss/postcss) processor object (that was returned from a call to the `postcss()` function). It requires that a `hoverSelectorPrefix` string option be provided; this string will be prepended to all selectors within `@media (hover: hover) {...}` blocks within the source CSS.
+* `postprocessorFor`
+ * Arguments: an options object with one property:
+ * `hoverSelectorPrefix` - This string will be prepended to all selectors within `@media (hover: hover) {...}` blocks within the source CSS.
+ * Type: `string`
+ * Side-effects: none
+ * Return type: A [PostCSS](https://github.com/postcss/postcss) processor object (that was returned from a call to the `postcss()` function).
+ * Returns a CSS postprocessor that transforms the source CSS as described above.
* `featureDetector` - Each of this object's properties is a string filepath to a JavaScript file containing the browser-side feature detector in a particular JavaScript module format.
* `es6` - [ECMAScript 6 module](http://www.2ality.com/2014/09/es6-modules-final.html) format (this is the original from which the other versions are generated)
* `cjs` - [CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1) module format
@@ -143,6 +149,7 @@ _Also, please don't edit files in the `dist` subdirectory as they are generated
## Release History
See the [GitHub Releases page](https://github.com/cvrebert/mq4-hover-hover-shim/releases) for detailed changelogs.
* (next release) - `master`
+* 2015-01-18 - v0.0.4: Fix crash when CSS contains a media-type-only media query. Replaced `postprocessor` with `postprocessorFor()`.
* 2015-01-14 - v0.0.3: Add jspm metadata. Improve docs.
* 2015-01-09 - v0.0.2: Many improvements. jQuery is now a dependency on the client side.
* 2014-12-31 - v0.0.1: Initial release
diff --git a/src/nodejs/index.js b/src/nodejs/index.js
index 96f0772..7bfa81f 100644
--- a/src/nodejs/index.js
+++ b/src/nodejs/index.js
@@ -6,7 +6,7 @@ var CLIENT_SIDE_FEATURE_DETECTOR_FILENAME = 'mq4-hover-hover-shim.js';
module.exports = {
- postprocessor: require('./postprocessor'),
+ postprocessorFor: require('./postprocessor'),
featureDetector: {
es6: path.join(__dirname, '../browser', CLIENT_SIDE_FEATURE_DETECTOR_FILENAME),
cjs: path.join(__dirname, '../../dist/cjs', CLIENT_SIDE_FEATURE_DETECTOR_FILENAME),
diff --git a/src/nodejs/postprocessor.js b/src/nodejs/postprocessor.js
index c0c5163..9597ee7 100644
--- a/src/nodejs/postprocessor.js
+++ b/src/nodejs/postprocessor.js
@@ -68,46 +68,48 @@ function prefixSelectorsWith(rule, selectorPrefix) {
}
-module.exports = postcss(function process(css, opts) {
- var hoverSelectorPrefix = opts.hoverSelectorPrefix;
- if ((typeof hoverSelectorPrefix) !== 'string') {
- throw new Error('hoverSelectorPrefix option must be a string');
- }
+module.exports = function (opts) {
+ return postcss(function process(css) {
+ var hoverSelectorPrefix = opts.hoverSelectorPrefix;
+ if ((typeof hoverSelectorPrefix) !== 'string') {
+ throw new Error('hoverSelectorPrefix option must be a string');
+ }
- css.eachAtRule('media', function (atRule) {
- var mediaType = mediaTypeIfSimpleHoverHover(atRule);
- switch (mediaType) {
- case 'all':
- /* falls through */
- case 'screen': {
- atRule.eachRule(function (rule) {
- prefixSelectorsWith(rule, hoverSelectorPrefix);
- });
- if (mediaType === 'screen') {
- atRule.params = 'screen';
- }
- else {
- // Remove tautological @media all {...} wrapper
- replaceWithItsChildren(atRule);
+ css.eachAtRule('media', function (atRule) {
+ var mediaType = mediaTypeIfSimpleHoverHover(atRule);
+ switch (mediaType) {
+ case 'all':
+ /* falls through */
+ case 'screen': {
+ atRule.eachRule(function (rule) {
+ prefixSelectorsWith(rule, hoverSelectorPrefix);
+ });
+ if (mediaType === 'screen') {
+ atRule.params = 'screen';
+ }
+ else {
+ // Remove tautological @media all {...} wrapper
+ replaceWithItsChildren(atRule);
+ }
+ return;
}
- return;
- }
- case 'print':
- /* falls through */
- case 'speech': {
- // These media types never support hovering
- // Delete always-false media query
- atRule.removeSelf();
- return;
- }
+ case 'print':
+ /* falls through */
+ case 'speech': {
+ // These media types never support hovering
+ // Delete always-false media query
+ atRule.removeSelf();
+ return;
+ }
- case undefined: {
- return; // Media query irrelevant or too complicated
- }
- default: {
- return; // Deprecated media type; take no action.
+ case undefined: {
+ return; // Media query irrelevant or too complicated
+ }
+ default: {
+ return; // Deprecated media type; take no action.
+ }
}
- }
+ });
});
-});
+};
diff --git a/test/postprocessor_test.js b/test/postprocessor_test.js
index 2878ed6..3a9e36d 100644
--- a/test/postprocessor_test.js
+++ b/test/postprocessor_test.js
@@ -28,7 +28,7 @@ exports.mq4HoverShim = {
'has no effect when there are no media queries': function (test) {
test.expect(1);
test.deepEqual(
- postprocessor.process(".foobar { display: none; }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process(".foobar { display: none; }").css,
".foobar { display: none; }"
);
test.done();
@@ -36,7 +36,7 @@ exports.mq4HoverShim = {
'skips non-media at-rules': function (test) {
test.expect(1);
test.deepEqual(
- postprocessor.process("@quux (hover: hover) { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@quux (hover: hover) { .foobar { display: none; } }").css,
"@quux (hover: hover) { .foobar { display: none; } }"
);
test.done();
@@ -44,7 +44,7 @@ exports.mq4HoverShim = {
'skips media queries with only a media type': function (test) {
test.expect(1);
test.deepEqual(
- postprocessor.process("@media screen { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media screen { .foobar { display: none; } }").css,
"@media screen { .foobar { display: none; } }"
);
test.done();
@@ -52,11 +52,11 @@ exports.mq4HoverShim = {
'skips media queries with ORs': function (test) {
test.expect(2);
test.deepEqual(
- postprocessor.process("@media (hover: hover), (orientation: landscape) { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media (hover: hover), (orientation: landscape) { .foobar { display: none; } }").css,
"@media (hover: hover), (orientation: landscape) { .foobar { display: none; } }"
);
test.deepEqual(
- postprocessor.process("@media screen (hover: hover), (orientation: landscape) { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media screen (hover: hover), (orientation: landscape) { .foobar { display: none; } }").css,
"@media screen (hover: hover), (orientation: landscape) { .foobar { display: none; } }"
);
test.done();
@@ -64,11 +64,11 @@ exports.mq4HoverShim = {
'skips media queries with ANDs': function (test) {
test.expect(2);
test.deepEqual(
- postprocessor.process("@media (hover: hover) and (orientation: landscape) { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media (hover: hover) and (orientation: landscape) { .foobar { display: none; } }").css,
"@media (hover: hover) and (orientation: landscape) { .foobar { display: none; } }"
);
test.deepEqual(
- postprocessor.process("@media screen (hover: hover) and (orientation: landscape) { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media screen (hover: hover) and (orientation: landscape) { .foobar { display: none; } }").css,
"@media screen (hover: hover) and (orientation: landscape) { .foobar { display: none; } }"
);
test.done();
@@ -76,7 +76,7 @@ exports.mq4HoverShim = {
'skips media queries that are not about the hover media feature': function (test) {
test.expect(1);
test.deepEqual(
- postprocessor.process("@media (orientation: landscape) { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media (orientation: landscape) { .foobar { display: none; } }").css,
"@media (orientation: landscape) { .foobar { display: none; } }"
);
test.done();
@@ -84,11 +84,11 @@ exports.mq4HoverShim = {
'skips media queries about the hover media feature with a non-hover value': function (test) {
test.expect(2);
test.deepEqual(
- postprocessor.process("@media (hover: none) { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media (hover: none) { .foobar { display: none; } }").css,
"@media (hover: none) { .foobar { display: none; } }"
);
test.deepEqual(
- postprocessor.process("@media (hover: on-demand) { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media (hover: on-demand) { .foobar { display: none; } }").css,
"@media (hover: on-demand) { .foobar { display: none; } }"
);
test.done();
@@ -96,7 +96,7 @@ exports.mq4HoverShim = {
'works correctly on a representative example': function (test) {
test.expect(1);
test.deepEqual(
- postprocessor.process("@media (hover: hover) { .foobar { color: white; background: red; } div .quux > input { color: blue; background: white; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media (hover: hover) { .foobar { color: white; background: red; } div .quux > input { color: blue; background: white; } }").css,
"PREFIX>.foobar {\n color: white;\n background: red;\n}\nPREFIX>div .quux > input {\n color: blue;\n background: white;\n}"
);
test.done();
@@ -104,19 +104,19 @@ exports.mq4HoverShim = {
'handles nested at-rules': function (test) {
test.expect(4);
test.deepEqual(
- postprocessor.process("@media (orientation: landscape) { @media (hover: hover) { .foobar { display: none; } } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media (orientation: landscape) { @media (hover: hover) { .foobar { display: none; } } }").css,
"@media (orientation: landscape) { PREFIX>.foobar { display: none; } }"
);
test.deepEqual(
- postprocessor.process("@media screen (orientation: landscape) { @media (hover: hover) { .foobar { display: none; } } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media screen (orientation: landscape) { @media (hover: hover) { .foobar { display: none; } } }").css,
"@media screen (orientation: landscape) { PREFIX>.foobar { display: none; } }"
);
test.deepEqual(
- postprocessor.process("@media (hover: hover) { @media (orientation: landscape) { .foobar { display: none; } } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media (hover: hover) { @media (orientation: landscape) { .foobar { display: none; } } }").css,
"@media (orientation: landscape) {\n PREFIX>.foobar {\n display: none;\n }\n}"
);
test.deepEqual(
- postprocessor.process("@media (hover: hover) { @media screen (orientation: landscape) { .foobar { display: none; } } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media (hover: hover) { @media screen (orientation: landscape) { .foobar { display: none; } } }").css,
"@media screen (orientation: landscape) {\n PREFIX>.foobar {\n display: none;\n }\n}"
);
test.done();
@@ -124,7 +124,7 @@ exports.mq4HoverShim = {
'handles applicable media types': function (test) {
test.expect(1);
test.deepEqual(
- postprocessor.process("@media screen (hover: hover) { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media screen (hover: hover) { .foobar { display: none; } }").css,
"@media screen { PREFIX>.foobar { display: none; } }"
);
test.done();
@@ -132,7 +132,7 @@ exports.mq4HoverShim = {
'handles non-applicable media types': function (test) {
test.expect(1);
test.deepEqual(
- postprocessor.process("@media print (hover: hover) { .foobar { display: none; } }", {hoverSelectorPrefix: 'PREFIX>'}).css,
+ postprocessor({hoverSelectorPrefix: 'PREFIX>'}).process("@media print (hover: hover) { .foobar { display: none; } }").css,
""
);
test.done();
@@ -141,7 +141,7 @@ exports.mq4HoverShim = {
test.expect(1);
test.throws(function () {
/*eslint-disable no-unused-expressions */
- postprocessor.process("@media (hover: hover) { .foobar { display: none; } }", {}).css;// jshint ignore:line
+ postprocessor({}).process("@media (hover: hover) { .foobar { display: none; } }").css;// jshint ignore:line
/*eslint-enable no-unused-expressions */
}, Error, 'hoverSelectorPrefix option must be a string');
test.done();
@@ -150,7 +150,7 @@ exports.mq4HoverShim = {
test.expect(1);
test.throws(function () {
/*eslint-disable no-unused-expressions */
- postprocessor.process("@media (hover: hover) { .foobar { display: none; } }", {hoverSelectorPrefix: 42}).css;// jshint ignore:line
+ postprocessor({hoverSelectorPrefix: 42}).process("@media (hover: hover) { .foobar { display: none; } }").css;// jshint ignore:line
/*eslint-enable no-unused-expressions */
}, Error, 'hoverSelectorPrefix option must be a string');
test.done();