stylehacks 5.0.1 → 5.1.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.
Files changed (66) hide show
  1. package/README.md +5 -8
  2. package/package.json +8 -11
  3. package/src/dictionary/browsers.js +9 -0
  4. package/src/dictionary/identifiers.js +7 -0
  5. package/src/dictionary/postcss.js +6 -0
  6. package/src/dictionary/tags.js +5 -0
  7. package/src/exists.js +13 -0
  8. package/src/index.js +60 -0
  9. package/src/isMixin.js +15 -0
  10. package/src/plugin.js +108 -0
  11. package/src/plugins/bodyEmpty.js +49 -0
  12. package/src/plugins/htmlCombinatorCommentBody.js +54 -0
  13. package/src/plugins/htmlFirstChild.js +50 -0
  14. package/src/plugins/important.js +25 -0
  15. package/src/plugins/index.js +28 -0
  16. package/src/plugins/leadingStar.js +55 -0
  17. package/src/plugins/leadingUnderscore.js +51 -0
  18. package/src/plugins/mediaSlash0.js +26 -0
  19. package/src/plugins/mediaSlash0Slash9.js +27 -0
  20. package/src/plugins/mediaSlash9.js +27 -0
  21. package/src/plugins/slash9.js +26 -0
  22. package/src/plugins/starHtml.js +50 -0
  23. package/src/plugins/trailingSlashComma.js +36 -0
  24. package/types/dictionary/browsers.d.ts +6 -0
  25. package/types/dictionary/identifiers.d.ts +4 -0
  26. package/types/dictionary/postcss.d.ts +3 -0
  27. package/types/dictionary/tags.d.ts +2 -0
  28. package/types/exists.d.ts +2 -0
  29. package/types/index.d.ts +16 -0
  30. package/types/isMixin.d.ts +2 -0
  31. package/types/plugin.d.ts +60 -0
  32. package/types/plugins/bodyEmpty.d.ts +17 -0
  33. package/types/plugins/htmlCombinatorCommentBody.d.ts +16 -0
  34. package/types/plugins/htmlFirstChild.d.ts +17 -0
  35. package/types/plugins/important.d.ts +11 -0
  36. package/types/plugins/index.d.ts +365 -0
  37. package/types/plugins/leadingStar.d.ts +11 -0
  38. package/types/plugins/leadingUnderscore.d.ts +11 -0
  39. package/types/plugins/mediaSlash0.d.ts +11 -0
  40. package/types/plugins/mediaSlash0Slash9.d.ts +11 -0
  41. package/types/plugins/mediaSlash9.d.ts +11 -0
  42. package/types/plugins/slash9.d.ts +11 -0
  43. package/types/plugins/starHtml.d.ts +17 -0
  44. package/types/plugins/trailingSlashComma.d.ts +11 -0
  45. package/CHANGELOG.md +0 -81
  46. package/dist/dictionary/browsers.js +0 -18
  47. package/dist/dictionary/identifiers.js +0 -14
  48. package/dist/dictionary/postcss.js +0 -12
  49. package/dist/dictionary/tags.js +0 -10
  50. package/dist/exists.js +0 -13
  51. package/dist/index.js +0 -69
  52. package/dist/isMixin.js +0 -20
  53. package/dist/plugin.js +0 -71
  54. package/dist/plugins/bodyEmpty.js +0 -48
  55. package/dist/plugins/htmlCombinatorCommentBody.js +0 -50
  56. package/dist/plugins/htmlFirstChild.js +0 -48
  57. package/dist/plugins/important.js +0 -29
  58. package/dist/plugins/index.js +0 -36
  59. package/dist/plugins/leadingStar.js +0 -67
  60. package/dist/plugins/leadingUnderscore.js +0 -49
  61. package/dist/plugins/mediaSlash0.js +0 -30
  62. package/dist/plugins/mediaSlash0Slash9.js +0 -30
  63. package/dist/plugins/mediaSlash9.js +0 -30
  64. package/dist/plugins/slash9.js +0 -30
  65. package/dist/plugins/starHtml.js +0 -48
  66. package/dist/plugins/trailingSlashComma.js +0 -39
package/README.md CHANGED
@@ -52,7 +52,11 @@ it will return `false` instead.
52
52
  h1 { _color: red }
53
53
  ```
54
54
 
55
- ### `stylehacks.process(css, [options]).then(function(result) {})`
55
+ ### `postcss([ stylehacks(opts) ])`
56
+
57
+ stylehacks can also be consumed as a PostCSS plugin. See the
58
+ [documentation](https://github.com/postcss/postcss#usage) for examples for
59
+ your environment.
56
60
 
57
61
  #### options
58
62
 
@@ -65,13 +69,6 @@ If lint mode is enabled, stylehacks will not remove hacks from the CSS; instead,
65
69
  it will add warnings to `Result#messages`.
66
70
 
67
71
 
68
- ### `postcss([ stylehacks(opts) ])`
69
-
70
- stylehacks can also be consumed as a PostCSS plugin. See the
71
- [documentation](https://github.com/postcss/postcss#usage) for examples for
72
- your environment.
73
-
74
-
75
72
  ## Related
76
73
 
77
74
  stylehacks works well with your existing PostCSS setup:
package/package.json CHANGED
@@ -1,17 +1,14 @@
1
1
  {
2
2
  "name": "stylehacks",
3
- "version": "5.0.1",
3
+ "version": "5.1.0",
4
4
  "description": "Detect/remove browser hacks from CSS files.",
5
- "main": "dist/index.js",
5
+ "main": "src/index.js",
6
+ "types": "types/index.d.ts",
6
7
  "files": [
7
8
  "LICENSE-MIT",
8
- "dist"
9
+ "src",
10
+ "types"
9
11
  ],
10
- "scripts": {
11
- "prebuild": "del-cli dist",
12
- "build": "cross-env BABEL_ENV=publish babel src --config-file ../../babel.config.json --out-dir dist --ignore \"**/__tests__/\"",
13
- "prepublish": "yarn build"
14
- },
15
12
  "keywords": [
16
13
  "browsers",
17
14
  "css",
@@ -31,7 +28,7 @@
31
28
  },
32
29
  "repository": "cssnano/cssnano",
33
30
  "dependencies": {
34
- "browserslist": "^4.16.0",
31
+ "browserslist": "^4.16.6",
35
32
  "postcss-selector-parser": "^6.0.4"
36
33
  },
37
34
  "bugs": {
@@ -46,5 +43,5 @@
46
43
  "peerDependencies": {
47
44
  "postcss": "^8.2.15"
48
45
  },
49
- "gitHead": "28c247175032fa03f04911cde56ad82d74d211cc"
50
- }
46
+ "readme": "# stylehacks\n\n> Detect/remove browser hacks from CSS files.\n\n\n## Install\n\nWith [npm](https://npmjs.org/package/stylehacks) do:\n\n```\nnpm install stylehacks --save\n```\n\n\n## Example\n\nIn its default mode, stylehacks will remove hacks from your CSS file, based on\nthe browsers that you wish to support.\n\n### Input\n\n```css\nh1 {\n _color: white;\n color: rgba(255, 255, 255, 0.5);\n}\n```\n\n### Output\n\n```css\nh1 {\n color: rgba(255, 255, 255, 0.5);\n}\n```\n\n\n## API\n\n### `stylehacks.detect(node)`\n\nType: `function` \nReturns: `boolean`\n\nThis method will take any PostCSS *node*, run applicable plugins depending on\nits type, then will return a boolean depending on whether it found any of\nthe supported hacks. For example, if the `decl` node found below is passed to\nthe `detect` function, it will return `true`. But if the `rule` node is passed,\nit will return `false` instead.\n\n```css\nh1 { _color: red }\n```\n\n### `postcss([ stylehacks(opts) ])`\n\nstylehacks can also be consumed as a PostCSS plugin. See the\n[documentation](https://github.com/postcss/postcss#usage) for examples for\nyour environment.\n\n#### options\n\n##### lint\n\nType: `boolean` \nDefault: `false`\n\nIf lint mode is enabled, stylehacks will not remove hacks from the CSS; instead,\nit will add warnings to `Result#messages`.\n\n\n## Related\n\nstylehacks works well with your existing PostCSS setup:\n\n* [stylelint] - Comprehensive & modern CSS linter, to ensure that your code\n style rules are respected.\n\n\n## Contributing\n\nPull requests are welcome. If you add functionality, then please add unit tests\nto cover it.\n\n\n## License\n\nMIT © [Ben Briggs](http://beneb.info)\n\n\n[stylelint]: https://github.com/stylelint/stylelint\n"
47
+ }
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+ const FF_2 = 'firefox 2';
3
+ const IE_5_5 = 'ie 5.5';
4
+ const IE_6 = 'ie 6';
5
+ const IE_7 = 'ie 7';
6
+ const IE_8 = 'ie 8';
7
+ const OP_9 = 'opera 9';
8
+
9
+ module.exports = { FF_2, IE_5_5, IE_6, IE_7, IE_8, OP_9 };
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+ const MEDIA_QUERY = 'media query';
3
+ const PROPERTY = 'property';
4
+ const SELECTOR = 'selector';
5
+ const VALUE = 'value';
6
+
7
+ module.exports = { MEDIA_QUERY, PROPERTY, SELECTOR, VALUE };
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+ const ATRULE = 'atrule';
3
+ const DECL = 'decl';
4
+ const RULE = 'rule';
5
+
6
+ module.exports = { ATRULE, DECL, RULE };
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+ const BODY = 'body';
3
+ const HTML = 'html';
4
+
5
+ module.exports = { BODY, HTML };
package/src/exists.js ADDED
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * @param {import('postcss-selector-parser').Selector} selector
5
+ * @param {number} index
6
+ * @param {string} value
7
+ * @return {boolean | undefined | ''}
8
+ */
9
+ module.exports = function exists(selector, index, value) {
10
+ const node = selector.at(index);
11
+
12
+ return node && node.value && node.value.toLowerCase() === value;
13
+ };
package/src/index.js ADDED
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+ const browserslist = require('browserslist');
3
+ const plugins = require('./plugins');
4
+
5
+ /** @typedef {{lint?: boolean}} Options */
6
+
7
+ /**
8
+ * @type {import('postcss').PluginCreator<Options>}
9
+ * @param {Options} opts
10
+ * @return {import('postcss').Plugin}
11
+ */
12
+ function pluginCreator(opts = {}) {
13
+ return {
14
+ postcssPlugin: 'stylehacks',
15
+
16
+ OnceExit(css, { result }) {
17
+ /** @type {typeof result.opts & browserslist.Options} */
18
+ const resultOpts = result.opts || {};
19
+ const browsers = browserslist(null, {
20
+ stats: resultOpts.stats,
21
+ path: __dirname,
22
+ env: resultOpts.env,
23
+ });
24
+
25
+ /** @type {import('./plugin').Plugin[]} */
26
+ const processors = [];
27
+ for (const Plugin of plugins) {
28
+ const hack = new Plugin(result);
29
+ if (!browsers.some((browser) => hack.targets.has(browser))) {
30
+ processors.push(hack);
31
+ }
32
+ }
33
+ css.walk((node) => {
34
+ processors.forEach((proc) => {
35
+ if (!proc.nodeTypes.has(node.type)) {
36
+ return;
37
+ }
38
+
39
+ if (opts.lint) {
40
+ return proc.detectAndWarn(node);
41
+ }
42
+
43
+ return proc.detectAndResolve(node);
44
+ });
45
+ });
46
+ },
47
+ };
48
+ }
49
+
50
+ /** @type {(node: import('postcss').Node) => boolean} */
51
+ pluginCreator.detect = (node) => {
52
+ return plugins.some((Plugin) => {
53
+ const hack = new Plugin();
54
+
55
+ return hack.any(node);
56
+ });
57
+ };
58
+
59
+ pluginCreator.postcss = true;
60
+ module.exports = pluginCreator;
package/src/isMixin.js ADDED
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+ /**
3
+ * @param {import('postcss').Rule} node
4
+ * @return {boolean}
5
+ */
6
+ module.exports = function isMixin(node) {
7
+ const { selector } = node;
8
+
9
+ // If the selector ends with a ':' it is likely a part of a custom mixin.
10
+ if (!selector || selector[selector.length - 1] === ':') {
11
+ return true;
12
+ }
13
+
14
+ return false;
15
+ };
package/src/plugin.js ADDED
@@ -0,0 +1,108 @@
1
+ 'use strict';
2
+ /**
3
+ * @typedef {object} Plugin
4
+ * @prop {Set<string>} targets
5
+ * @prop {Set<string>} nodeTypes
6
+ * @prop {(node: import('postcss').Node) => void} detectAndResolve
7
+ * @prop {(node: import('postcss').Node) => void} detectAndWarn
8
+ */
9
+
10
+ /**
11
+ * @typedef {import('postcss').Node & {_stylehacks: {
12
+ message: string,
13
+ browsers: Set<string>,
14
+ identifier: string,
15
+ hack: string }}} NodeWithInfo
16
+ */
17
+
18
+ module.exports = class BasePlugin {
19
+ /**
20
+ * @param {string[]} targets
21
+ * @param {string[]} nodeTypes
22
+ * @param {import('postcss').Result=} result
23
+ */
24
+ constructor(targets, nodeTypes, result) {
25
+ /** @type {NodeWithInfo[]} */
26
+ this.nodes = [];
27
+ this.targets = new Set(targets);
28
+ this.nodeTypes = new Set(nodeTypes);
29
+ this.result = result;
30
+ }
31
+
32
+ /**
33
+ * @param {import('postcss').Node} node
34
+ * @param {{identifier: string, hack: string}} metadata
35
+ * @return {void}
36
+ */
37
+ push(node, metadata) {
38
+ /** @type {NodeWithInfo} */ (node)._stylehacks = Object.assign(
39
+ {},
40
+ metadata,
41
+ {
42
+ message: `Bad ${metadata.identifier}: ${metadata.hack}`,
43
+ browsers: this.targets,
44
+ }
45
+ );
46
+
47
+ this.nodes.push(/** @type {NodeWithInfo} */ (node));
48
+ }
49
+
50
+ /**
51
+ * @param {import('postcss').Node} node
52
+ * @return {boolean}
53
+ */
54
+ any(node) {
55
+ if (this.nodeTypes.has(node.type)) {
56
+ this.detect(node);
57
+
58
+ return /** @type {NodeWithInfo} */ (node)._stylehacks !== undefined;
59
+ }
60
+
61
+ return false;
62
+ }
63
+
64
+ /**
65
+ * @param {import('postcss').Node} node
66
+ * @return {void}
67
+ */
68
+ detectAndResolve(node) {
69
+ this.nodes = [];
70
+
71
+ this.detect(node);
72
+
73
+ return this.resolve();
74
+ }
75
+
76
+ /**
77
+ * @param {import('postcss').Node} node
78
+ * @return {void}
79
+ */
80
+ detectAndWarn(node) {
81
+ this.nodes = [];
82
+
83
+ this.detect(node);
84
+
85
+ return this.warn();
86
+ }
87
+ /** @param {import('postcss').Node} node */
88
+ // eslint-disable-next-line no-unused-vars
89
+ detect(node) {
90
+ throw new Error('You need to implement this method in a subclass.');
91
+ }
92
+
93
+ /** @return {void} */
94
+ resolve() {
95
+ return this.nodes.forEach((node) => node.remove());
96
+ }
97
+
98
+ warn() {
99
+ return this.nodes.forEach((node) => {
100
+ const { message, browsers, identifier, hack } = node._stylehacks;
101
+
102
+ return node.warn(
103
+ /** @type {import('postcss').Result} */ (this.result),
104
+ message + JSON.stringify({ browsers, identifier, hack })
105
+ );
106
+ });
107
+ }
108
+ };
@@ -0,0 +1,49 @@
1
+ 'use strict';
2
+ const parser = require('postcss-selector-parser');
3
+ const exists = require('../exists');
4
+ const isMixin = require('../isMixin');
5
+ const BasePlugin = require('../plugin');
6
+ const { FF_2 } = require('../dictionary/browsers');
7
+ const { SELECTOR } = require('../dictionary/identifiers');
8
+ const { RULE } = require('../dictionary/postcss');
9
+ const { BODY } = require('../dictionary/tags');
10
+
11
+ module.exports = class BodyEmpty extends BasePlugin {
12
+ /** @param {import('postcss').Result} result */
13
+ constructor(result) {
14
+ super([FF_2], [RULE], result);
15
+ }
16
+
17
+ /**
18
+ * @param {import('postcss').Rule} rule
19
+ * @return {void}
20
+ */
21
+ detect(rule) {
22
+ if (isMixin(rule)) {
23
+ return;
24
+ }
25
+ parser(this.analyse(rule)).processSync(rule.selector);
26
+ }
27
+
28
+ /**
29
+ * @param {import('postcss').Rule} rule
30
+ * @return {parser.SyncProcessor<void>}
31
+ */
32
+ analyse(rule) {
33
+ return (selectors) => {
34
+ selectors.each((selector) => {
35
+ if (
36
+ exists(selector, 0, BODY) &&
37
+ exists(selector, 1, ':empty') &&
38
+ exists(selector, 2, ' ') &&
39
+ selector.at(3)
40
+ ) {
41
+ this.push(rule, {
42
+ identifier: SELECTOR,
43
+ hack: selector.toString(),
44
+ });
45
+ }
46
+ });
47
+ };
48
+ }
49
+ };
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+ const parser = require('postcss-selector-parser');
3
+ const exists = require('../exists');
4
+ const isMixin = require('../isMixin');
5
+ const BasePlugin = require('../plugin');
6
+ const { IE_5_5, IE_6, IE_7 } = require('../dictionary/browsers');
7
+ const { SELECTOR } = require('../dictionary/identifiers');
8
+ const { RULE } = require('../dictionary/postcss');
9
+ const { BODY, HTML } = require('../dictionary/tags');
10
+
11
+ module.exports = class HtmlCombinatorCommentBody extends BasePlugin {
12
+ /** @param {import('postcss').Result} result */
13
+ constructor(result) {
14
+ super([IE_5_5, IE_6, IE_7], [RULE], result);
15
+ }
16
+
17
+ /**
18
+ * @param {import('postcss').Rule} rule
19
+ * @return {void}
20
+ */
21
+ detect(rule) {
22
+ if (isMixin(rule)) {
23
+ return;
24
+ }
25
+ if (rule.raws.selector && rule.raws.selector.raw) {
26
+ parser(this.analyse(rule)).processSync(rule.raws.selector.raw);
27
+ }
28
+ }
29
+
30
+ /** @param {import('postcss').Rule} rule
31
+ * @return {parser.SyncProcessor<void>}
32
+ */
33
+ analyse(rule) {
34
+ return (selectors) => {
35
+ selectors.each((selector) => {
36
+ if (
37
+ exists(selector, 0, HTML) &&
38
+ (exists(selector, 1, '>') || exists(selector, 1, '~')) &&
39
+ selector.at(2) &&
40
+ selector.at(2).type === 'comment' &&
41
+ exists(selector, 3, ' ') &&
42
+ exists(selector, 4, BODY) &&
43
+ exists(selector, 5, ' ') &&
44
+ selector.at(6)
45
+ ) {
46
+ this.push(rule, {
47
+ identifier: SELECTOR,
48
+ hack: selector.toString(),
49
+ });
50
+ }
51
+ });
52
+ };
53
+ }
54
+ };
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+ const parser = require('postcss-selector-parser');
3
+ const exists = require('../exists');
4
+ const isMixin = require('../isMixin');
5
+ const BasePlugin = require('../plugin');
6
+ const { OP_9 } = require('../dictionary/browsers');
7
+ const { SELECTOR } = require('../dictionary/identifiers');
8
+ const { RULE } = require('../dictionary/postcss');
9
+ const { HTML } = require('../dictionary/tags');
10
+
11
+ module.exports = class HtmlFirstChild extends BasePlugin {
12
+ /** @param {import('postcss').Result} result */
13
+ constructor(result) {
14
+ super([OP_9], [RULE], result);
15
+ }
16
+
17
+ /**
18
+ * @param {import('postcss').Rule} rule
19
+ * @return {void}
20
+ */
21
+ detect(rule) {
22
+ if (isMixin(rule)) {
23
+ return;
24
+ }
25
+
26
+ parser(this.analyse(rule)).processSync(rule.selector);
27
+ }
28
+
29
+ /**
30
+ * @param {import('postcss').Rule} rule
31
+ * @return {parser.SyncProcessor<void>}
32
+ */
33
+ analyse(rule) {
34
+ return (selectors) => {
35
+ selectors.each((selector) => {
36
+ if (
37
+ exists(selector, 0, HTML) &&
38
+ exists(selector, 1, ':first-child') &&
39
+ exists(selector, 2, ' ') &&
40
+ selector.at(3)
41
+ ) {
42
+ this.push(rule, {
43
+ identifier: SELECTOR,
44
+ hack: selector.toString(),
45
+ });
46
+ }
47
+ });
48
+ };
49
+ }
50
+ };
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+ const BasePlugin = require('../plugin');
3
+ const { IE_5_5, IE_6, IE_7 } = require('../dictionary/browsers');
4
+ const { DECL } = require('../dictionary/postcss');
5
+
6
+ module.exports = class Important extends BasePlugin {
7
+ /** @param {import('postcss').Result=} result */
8
+ constructor(result) {
9
+ super([IE_5_5, IE_6, IE_7], [DECL], result);
10
+ }
11
+ /**
12
+ * @param {import('postcss').Declaration} decl
13
+ * @return {void}
14
+ */
15
+ detect(decl) {
16
+ const match = decl.value.match(/!\w/);
17
+ if (match && match.index) {
18
+ const hack = decl.value.substr(match.index, decl.value.length - 1);
19
+ this.push(decl, {
20
+ identifier: '!important',
21
+ hack,
22
+ });
23
+ }
24
+ }
25
+ };
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+ const bodyEmpty = require('./bodyEmpty');
3
+ const htmlCombinatorCommentBody = require('./htmlCombinatorCommentBody');
4
+ const htmlFirstChild = require('./htmlFirstChild');
5
+ const important = require('./important');
6
+ const leadingStar = require('./leadingStar');
7
+ const leadingUnderscore = require('./leadingUnderscore');
8
+ const mediaSlash0 = require('./mediaSlash0');
9
+ const mediaSlash0Slash9 = require('./mediaSlash0Slash9');
10
+ const mediaSlash9 = require('./mediaSlash9');
11
+ const slash9 = require('./slash9');
12
+ const starHtml = require('./starHtml');
13
+ const trailingSlashComma = require('./trailingSlashComma');
14
+
15
+ module.exports = [
16
+ bodyEmpty,
17
+ htmlCombinatorCommentBody,
18
+ htmlFirstChild,
19
+ important,
20
+ leadingStar,
21
+ leadingUnderscore,
22
+ mediaSlash0,
23
+ mediaSlash0Slash9,
24
+ mediaSlash9,
25
+ slash9,
26
+ starHtml,
27
+ trailingSlashComma,
28
+ ];
@@ -0,0 +1,55 @@
1
+ 'use strict';
2
+ const BasePlugin = require('../plugin');
3
+ const { IE_5_5, IE_6, IE_7 } = require('../dictionary/browsers');
4
+ const { PROPERTY } = require('../dictionary/identifiers');
5
+ const { ATRULE, DECL } = require('../dictionary/postcss');
6
+
7
+ const hacks = '!_$_&_*_)_=_%_+_,_._/_`_]_#_~_?_:_|'.split('_');
8
+
9
+ module.exports = class LeadingStar extends BasePlugin {
10
+ /** @param {import('postcss').Result=} result */
11
+ constructor(result) {
12
+ super([IE_5_5, IE_6, IE_7], [ATRULE, DECL], result);
13
+ }
14
+
15
+ /**
16
+ * @param {import('postcss').Declaration | import('postcss').AtRule} node
17
+ * @return {void}
18
+ */
19
+ detect(node) {
20
+ if (node.type === DECL) {
21
+ // some values are not picked up by before, so ensure they are
22
+ // at the beginning of the value
23
+ hacks.forEach((hack) => {
24
+ if (!node.prop.indexOf(hack)) {
25
+ this.push(node, {
26
+ identifier: PROPERTY,
27
+ hack: node.prop,
28
+ });
29
+ }
30
+ });
31
+ const { before } = node.raws;
32
+ if (!before) {
33
+ return;
34
+ }
35
+ hacks.forEach((hack) => {
36
+ if (before.includes(hack)) {
37
+ this.push(node, {
38
+ identifier: PROPERTY,
39
+ hack: `${before.trim()}${node.prop}`,
40
+ });
41
+ }
42
+ });
43
+ } else {
44
+ // test for the @property: value; hack
45
+ const { name } = node;
46
+ const len = name.length - 1;
47
+ if (name.lastIndexOf(':') === len) {
48
+ this.push(node, {
49
+ identifier: PROPERTY,
50
+ hack: `@${name.substr(0, len)}`,
51
+ });
52
+ }
53
+ }
54
+ }
55
+ };
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+ const BasePlugin = require('../plugin');
3
+ const { IE_6 } = require('../dictionary/browsers');
4
+ const { PROPERTY } = require('../dictionary/identifiers');
5
+ const { DECL } = require('../dictionary/postcss');
6
+
7
+ /**
8
+ * @param {string} prop
9
+ * @return {string}
10
+ */
11
+ function vendorPrefix(prop) {
12
+ let match = prop.match(/^(-\w+-)/);
13
+ if (match) {
14
+ return match[0];
15
+ }
16
+
17
+ return '';
18
+ }
19
+
20
+ module.exports = class LeadingUnderscore extends BasePlugin {
21
+ /** @param {import('postcss').Result=} result */
22
+ constructor(result) {
23
+ super([IE_6], [DECL], result);
24
+ }
25
+
26
+ /**
27
+ * @param {import('postcss').Declaration} decl
28
+ * @return {void}
29
+ */
30
+ detect(decl) {
31
+ const { before } = decl.raws;
32
+
33
+ if (before && before.includes('_')) {
34
+ this.push(decl, {
35
+ identifier: PROPERTY,
36
+ hack: `${before.trim()}${decl.prop}`,
37
+ });
38
+ }
39
+
40
+ if (
41
+ decl.prop[0] === '-' &&
42
+ decl.prop[1] !== '-' &&
43
+ vendorPrefix(decl.prop) === ''
44
+ ) {
45
+ this.push(decl, {
46
+ identifier: PROPERTY,
47
+ hack: decl.prop,
48
+ });
49
+ }
50
+ }
51
+ };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+ const BasePlugin = require('../plugin');
3
+ const { IE_8 } = require('../dictionary/browsers');
4
+ const { MEDIA_QUERY } = require('../dictionary/identifiers');
5
+ const { ATRULE } = require('../dictionary/postcss');
6
+
7
+ module.exports = class MediaSlash0 extends BasePlugin {
8
+ /** @param {import('postcss').Result} result */
9
+ constructor(result) {
10
+ super([IE_8], [ATRULE], result);
11
+ }
12
+ /**
13
+ * @param {import('postcss').AtRule} rule
14
+ * @return {void}
15
+ */
16
+ detect(rule) {
17
+ const params = rule.params.trim();
18
+
19
+ if (params.toLowerCase() === '\\0screen') {
20
+ this.push(rule, {
21
+ identifier: MEDIA_QUERY,
22
+ hack: params,
23
+ });
24
+ }
25
+ }
26
+ };
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+ const BasePlugin = require('../plugin');
3
+ const { IE_5_5, IE_6, IE_7, IE_8 } = require('../dictionary/browsers');
4
+ const { MEDIA_QUERY } = require('../dictionary/identifiers');
5
+ const { ATRULE } = require('../dictionary/postcss');
6
+
7
+ module.exports = class MediaSlash0Slash9 extends BasePlugin {
8
+ /** @param {import('postcss').Result} result */
9
+ constructor(result) {
10
+ super([IE_5_5, IE_6, IE_7, IE_8], [ATRULE], result);
11
+ }
12
+
13
+ /**
14
+ * @param {import('postcss').AtRule} rule
15
+ * @return {void}
16
+ */
17
+ detect(rule) {
18
+ const params = rule.params.trim();
19
+
20
+ if (params.toLowerCase() === '\\0screen\\,screen\\9') {
21
+ this.push(rule, {
22
+ identifier: MEDIA_QUERY,
23
+ hack: params,
24
+ });
25
+ }
26
+ }
27
+ };