stylehacks 5.0.2 → 5.0.3

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 (43) hide show
  1. package/package.json +3 -7
  2. package/src/dictionary/browsers.js +9 -0
  3. package/src/dictionary/identifiers.js +7 -0
  4. package/src/dictionary/postcss.js +6 -0
  5. package/src/dictionary/tags.js +5 -0
  6. package/src/exists.js +6 -0
  7. package/src/index.js +50 -0
  8. package/src/isMixin.js +11 -0
  9. package/src/plugin.js +60 -0
  10. package/src/plugins/bodyEmpty.js +40 -0
  11. package/src/plugins/htmlCombinatorCommentBody.js +46 -0
  12. package/src/plugins/htmlFirstChild.js +41 -0
  13. package/src/plugins/important.js +21 -0
  14. package/src/plugins/index.js +28 -0
  15. package/src/plugins/leadingStar.js +50 -0
  16. package/src/plugins/leadingUnderscore.js +42 -0
  17. package/src/plugins/mediaSlash0.js +22 -0
  18. package/src/plugins/mediaSlash0Slash9.js +22 -0
  19. package/src/plugins/mediaSlash9.js +22 -0
  20. package/src/plugins/slash9.js +21 -0
  21. package/src/plugins/starHtml.js +41 -0
  22. package/src/plugins/trailingSlashComma.js +31 -0
  23. package/dist/dictionary/browsers.js +0 -18
  24. package/dist/dictionary/identifiers.js +0 -14
  25. package/dist/dictionary/postcss.js +0 -12
  26. package/dist/dictionary/tags.js +0 -10
  27. package/dist/exists.js +0 -13
  28. package/dist/index.js +0 -69
  29. package/dist/isMixin.js +0 -20
  30. package/dist/plugin.js +0 -71
  31. package/dist/plugins/bodyEmpty.js +0 -48
  32. package/dist/plugins/htmlCombinatorCommentBody.js +0 -50
  33. package/dist/plugins/htmlFirstChild.js +0 -48
  34. package/dist/plugins/important.js +0 -29
  35. package/dist/plugins/index.js +0 -36
  36. package/dist/plugins/leadingStar.js +0 -67
  37. package/dist/plugins/leadingUnderscore.js +0 -49
  38. package/dist/plugins/mediaSlash0.js +0 -30
  39. package/dist/plugins/mediaSlash0Slash9.js +0 -30
  40. package/dist/plugins/mediaSlash9.js +0 -30
  41. package/dist/plugins/slash9.js +0 -30
  42. package/dist/plugins/starHtml.js +0 -48
  43. package/dist/plugins/trailingSlashComma.js +0 -39
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "stylehacks",
3
- "version": "5.0.2",
3
+ "version": "5.0.3",
4
4
  "description": "Detect/remove browser hacks from CSS files.",
5
- "main": "dist/index.js",
5
+ "main": "src/index.js",
6
6
  "files": [
7
7
  "LICENSE-MIT",
8
- "dist"
8
+ "src"
9
9
  ],
10
10
  "keywords": [
11
11
  "browsers",
@@ -41,9 +41,5 @@
41
41
  "peerDependencies": {
42
42
  "postcss": "^8.2.15"
43
43
  },
44
- "scripts": {
45
- "prebuild": "rimraf dist",
46
- "build": "babel src --config-file ../../babel.config.json --out-dir dist --ignore \"**/__tests__/\""
47
- },
48
44
  "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"
49
45
  }
@@ -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,6 @@
1
+ 'use strict';
2
+ module.exports = function exists(selector, index, value) {
3
+ const node = selector.at(index);
4
+
5
+ return node && node.value && node.value.toLowerCase() === value;
6
+ };
package/src/index.js ADDED
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+ const browserslist = require('browserslist');
3
+ const plugins = require('./plugins');
4
+
5
+ function pluginCreator(opts = {}) {
6
+ return {
7
+ postcssPlugin: 'stylehacks',
8
+
9
+ OnceExit(css, { result }) {
10
+ const resultOpts = result.opts || {};
11
+ const browsers = browserslist(null, {
12
+ stats: resultOpts.stats,
13
+ path: __dirname,
14
+ env: resultOpts.env,
15
+ });
16
+
17
+ const processors = [];
18
+ for (const Plugin of plugins) {
19
+ const hack = new Plugin(result);
20
+ if (!browsers.some((browser) => hack.targets.has(browser))) {
21
+ processors.push(hack);
22
+ }
23
+ }
24
+ css.walk((node) => {
25
+ processors.forEach((proc) => {
26
+ if (!proc.nodeTypes.has(node.type)) {
27
+ return;
28
+ }
29
+
30
+ if (opts.lint) {
31
+ return proc.detectAndWarn(node);
32
+ }
33
+
34
+ return proc.detectAndResolve(node);
35
+ });
36
+ });
37
+ },
38
+ };
39
+ }
40
+
41
+ pluginCreator.detect = (node) => {
42
+ return plugins.some((Plugin) => {
43
+ const hack = new Plugin();
44
+
45
+ return hack.any(node);
46
+ });
47
+ };
48
+
49
+ pluginCreator.postcss = true;
50
+ module.exports = pluginCreator;
package/src/isMixin.js ADDED
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+ module.exports = function isMixin(node) {
3
+ const { selector } = node;
4
+
5
+ // If the selector ends with a ':' it is likely a part of a custom mixin.
6
+ if (!selector || selector[selector.length - 1] === ':') {
7
+ return true;
8
+ }
9
+
10
+ return false;
11
+ };
package/src/plugin.js ADDED
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+ module.exports = class BasePlugin {
3
+ constructor(targets, nodeTypes, result) {
4
+ this.nodes = [];
5
+ this.targets = new Set(targets);
6
+ this.nodeTypes = new Set(nodeTypes);
7
+ this.result = result;
8
+ }
9
+
10
+ push(node, metadata) {
11
+ node._stylehacks = Object.assign({}, metadata, {
12
+ message: `Bad ${metadata.identifier}: ${metadata.hack}`,
13
+ browsers: this.targets,
14
+ });
15
+
16
+ this.nodes.push(node);
17
+ }
18
+
19
+ any(node) {
20
+ if (this.nodeTypes.has(node.type)) {
21
+ this.detect(node);
22
+
23
+ return !!node._stylehacks;
24
+ }
25
+
26
+ return false;
27
+ }
28
+
29
+ detectAndResolve(node) {
30
+ this.nodes = [];
31
+
32
+ this.detect(node);
33
+
34
+ return this.resolve();
35
+ }
36
+
37
+ detectAndWarn(node) {
38
+ this.nodes = [];
39
+
40
+ this.detect(node);
41
+
42
+ return this.warn();
43
+ }
44
+ // eslint-disable-next-line no-unused-vars
45
+ detect(node) {
46
+ throw new Error('You need to implement this method in a subclass.');
47
+ }
48
+
49
+ resolve() {
50
+ return this.nodes.forEach((node) => node.remove());
51
+ }
52
+
53
+ warn() {
54
+ return this.nodes.forEach((node) => {
55
+ const { message, browsers, identifier, hack } = node._stylehacks;
56
+
57
+ return node.warn(this.result, message, { browsers, identifier, hack });
58
+ });
59
+ }
60
+ };
@@ -0,0 +1,40 @@
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
+ constructor(result) {
13
+ super([FF_2], [RULE], result);
14
+ }
15
+
16
+ detect(rule) {
17
+ if (isMixin(rule)) {
18
+ return;
19
+ }
20
+ parser(this.analyse(rule)).processSync(rule.selector);
21
+ }
22
+
23
+ analyse(rule) {
24
+ return (selectors) => {
25
+ selectors.each((selector) => {
26
+ if (
27
+ exists(selector, 0, BODY) &&
28
+ exists(selector, 1, ':empty') &&
29
+ exists(selector, 2, ' ') &&
30
+ selector.at(3)
31
+ ) {
32
+ this.push(rule, {
33
+ identifier: SELECTOR,
34
+ hack: selector.toString(),
35
+ });
36
+ }
37
+ });
38
+ };
39
+ }
40
+ };
@@ -0,0 +1,46 @@
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
+ constructor(result) {
13
+ super([IE_5_5, IE_6, IE_7], [RULE], result);
14
+ }
15
+
16
+ detect(rule) {
17
+ if (isMixin(rule)) {
18
+ return;
19
+ }
20
+ if (rule.raws.selector && rule.raws.selector.raw) {
21
+ parser(this.analyse(rule)).processSync(rule.raws.selector.raw);
22
+ }
23
+ }
24
+
25
+ analyse(rule) {
26
+ return (selectors) => {
27
+ selectors.each((selector) => {
28
+ if (
29
+ exists(selector, 0, HTML) &&
30
+ (exists(selector, 1, '>') || exists(selector, 1, '~')) &&
31
+ selector.at(2) &&
32
+ selector.at(2).type === 'comment' &&
33
+ exists(selector, 3, ' ') &&
34
+ exists(selector, 4, BODY) &&
35
+ exists(selector, 5, ' ') &&
36
+ selector.at(6)
37
+ ) {
38
+ this.push(rule, {
39
+ identifier: SELECTOR,
40
+ hack: selector.toString(),
41
+ });
42
+ }
43
+ });
44
+ };
45
+ }
46
+ };
@@ -0,0 +1,41 @@
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
+ constructor(result) {
13
+ super([OP_9], [RULE], result);
14
+ }
15
+
16
+ detect(rule) {
17
+ if (isMixin(rule)) {
18
+ return;
19
+ }
20
+
21
+ parser(this.analyse(rule)).processSync(rule.selector);
22
+ }
23
+
24
+ analyse(rule) {
25
+ return (selectors) => {
26
+ selectors.each((selector) => {
27
+ if (
28
+ exists(selector, 0, HTML) &&
29
+ exists(selector, 1, ':first-child') &&
30
+ exists(selector, 2, ' ') &&
31
+ selector.at(3)
32
+ ) {
33
+ this.push(rule, {
34
+ identifier: SELECTOR,
35
+ hack: selector.toString(),
36
+ });
37
+ }
38
+ });
39
+ };
40
+ }
41
+ };
@@ -0,0 +1,21 @@
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
+ constructor(result) {
8
+ super([IE_5_5, IE_6, IE_7], [DECL], result);
9
+ }
10
+
11
+ detect(decl) {
12
+ const match = decl.value.match(/!\w/);
13
+ if (match) {
14
+ const hack = decl.value.substr(match.index, decl.value.length - 1);
15
+ this.push(decl, {
16
+ identifier: '!important',
17
+ hack,
18
+ });
19
+ }
20
+ }
21
+ };
@@ -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,50 @@
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
+ constructor(result) {
11
+ super([IE_5_5, IE_6, IE_7], [ATRULE, DECL], result);
12
+ }
13
+
14
+ detect(node) {
15
+ if (node.type === DECL) {
16
+ // some values are not picked up by before, so ensure they are
17
+ // at the beginning of the value
18
+ hacks.forEach((hack) => {
19
+ if (!node.prop.indexOf(hack)) {
20
+ this.push(node, {
21
+ identifier: PROPERTY,
22
+ hack: node.prop,
23
+ });
24
+ }
25
+ });
26
+ let { before } = node.raws;
27
+ if (!before) {
28
+ return;
29
+ }
30
+ hacks.forEach((hack) => {
31
+ if (before.includes(hack)) {
32
+ this.push(node, {
33
+ identifier: PROPERTY,
34
+ hack: `${before.trim()}${node.prop}`,
35
+ });
36
+ }
37
+ });
38
+ } else {
39
+ // test for the @property: value; hack
40
+ let { name } = node;
41
+ let len = name.length - 1;
42
+ if (name.lastIndexOf(':') === len) {
43
+ this.push(node, {
44
+ identifier: PROPERTY,
45
+ hack: `@${name.substr(0, len)}`,
46
+ });
47
+ }
48
+ }
49
+ }
50
+ };
@@ -0,0 +1,42 @@
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
+ function vendorPrefix(prop) {
8
+ let match = prop.match(/^(-\w+-)/);
9
+ if (match) {
10
+ return match[0];
11
+ }
12
+
13
+ return '';
14
+ }
15
+
16
+ module.exports = class LeadingUnderscore extends BasePlugin {
17
+ constructor(result) {
18
+ super([IE_6], [DECL], result);
19
+ }
20
+
21
+ detect(decl) {
22
+ const { before } = decl.raws;
23
+
24
+ if (before && before.includes('_')) {
25
+ this.push(decl, {
26
+ identifier: PROPERTY,
27
+ hack: `${before.trim()}${decl.prop}`,
28
+ });
29
+ }
30
+
31
+ if (
32
+ decl.prop[0] === '-' &&
33
+ decl.prop[1] !== '-' &&
34
+ vendorPrefix(decl.prop) === ''
35
+ ) {
36
+ this.push(decl, {
37
+ identifier: PROPERTY,
38
+ hack: decl.prop,
39
+ });
40
+ }
41
+ }
42
+ };
@@ -0,0 +1,22 @@
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
+ constructor(result) {
9
+ super([IE_8], [ATRULE], result);
10
+ }
11
+
12
+ detect(rule) {
13
+ const params = rule.params.trim();
14
+
15
+ if (params.toLowerCase() === '\\0screen') {
16
+ this.push(rule, {
17
+ identifier: MEDIA_QUERY,
18
+ hack: params,
19
+ });
20
+ }
21
+ }
22
+ };
@@ -0,0 +1,22 @@
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
+ constructor(result) {
9
+ super([IE_5_5, IE_6, IE_7, IE_8], [ATRULE], result);
10
+ }
11
+
12
+ detect(rule) {
13
+ const params = rule.params.trim();
14
+
15
+ if (params.toLowerCase() === '\\0screen\\,screen\\9') {
16
+ this.push(rule, {
17
+ identifier: MEDIA_QUERY,
18
+ hack: params,
19
+ });
20
+ }
21
+ }
22
+ };
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+ const BasePlugin = require('../plugin');
3
+ const { IE_5_5, IE_6, IE_7 } = require('../dictionary/browsers');
4
+ const { MEDIA_QUERY } = require('../dictionary/identifiers');
5
+ const { ATRULE } = require('../dictionary/postcss');
6
+
7
+ module.exports = class MediaSlash9 extends BasePlugin {
8
+ constructor(result) {
9
+ super([IE_5_5, IE_6, IE_7], [ATRULE], result);
10
+ }
11
+
12
+ detect(rule) {
13
+ const params = rule.params.trim();
14
+
15
+ if (params.toLowerCase() === 'screen\\9') {
16
+ this.push(rule, {
17
+ identifier: MEDIA_QUERY,
18
+ hack: params,
19
+ });
20
+ }
21
+ }
22
+ };
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+ const BasePlugin = require('../plugin.js');
3
+ const { IE_6, IE_7, IE_8 } = require('../dictionary/browsers');
4
+ const { VALUE } = require('../dictionary/identifiers');
5
+ const { DECL } = require('../dictionary/postcss');
6
+
7
+ module.exports = class Slash9 extends BasePlugin {
8
+ constructor(result) {
9
+ super([IE_6, IE_7, IE_8], [DECL], result);
10
+ }
11
+
12
+ detect(decl) {
13
+ let v = decl.value;
14
+ if (v && v.length > 2 && v.indexOf('\\9') === v.length - 2) {
15
+ this.push(decl, {
16
+ identifier: VALUE,
17
+ hack: v,
18
+ });
19
+ }
20
+ }
21
+ };
@@ -0,0 +1,41 @@
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 } = 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 StarHtml extends BasePlugin {
12
+ constructor(result) {
13
+ super([IE_5_5, IE_6], [RULE], result);
14
+ }
15
+
16
+ detect(rule) {
17
+ if (isMixin(rule)) {
18
+ return;
19
+ }
20
+ parser(this.analyse(rule)).processSync(rule.selector);
21
+ }
22
+
23
+ analyse(rule) {
24
+ return (selectors) => {
25
+ selectors.each((selector) => {
26
+ if (
27
+ exists(selector, 0, '*') &&
28
+ exists(selector, 1, ' ') &&
29
+ exists(selector, 2, HTML) &&
30
+ exists(selector, 3, ' ') &&
31
+ selector.at(4)
32
+ ) {
33
+ this.push(rule, {
34
+ identifier: SELECTOR,
35
+ hack: selector.toString(),
36
+ });
37
+ }
38
+ });
39
+ };
40
+ }
41
+ };
@@ -0,0 +1,31 @@
1
+ 'use strict';
2
+ const BasePlugin = require('../plugin');
3
+ const isMixin = require('../isMixin');
4
+ const { IE_5_5, IE_6, IE_7 } = require('../dictionary/browsers');
5
+ const { SELECTOR } = require('../dictionary/identifiers');
6
+ const { RULE } = require('../dictionary/postcss');
7
+
8
+ module.exports = class TrailingSlashComma extends BasePlugin {
9
+ constructor(result) {
10
+ super([IE_5_5, IE_6, IE_7], [RULE], result);
11
+ }
12
+
13
+ detect(rule) {
14
+ if (isMixin(rule)) {
15
+ return;
16
+ }
17
+
18
+ const { selector } = rule;
19
+ const trim = selector.trim();
20
+
21
+ if (
22
+ trim.lastIndexOf(',') === selector.length - 1 ||
23
+ trim.lastIndexOf('\\') === selector.length - 1
24
+ ) {
25
+ this.push(rule, {
26
+ identifier: SELECTOR,
27
+ hack: selector,
28
+ });
29
+ }
30
+ }
31
+ };
@@ -1,18 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.OP_9 = exports.IE_8 = exports.IE_7 = exports.IE_6 = exports.IE_5_5 = exports.FF_2 = void 0;
7
- const FF_2 = 'firefox 2';
8
- exports.FF_2 = FF_2;
9
- const IE_5_5 = 'ie 5.5';
10
- exports.IE_5_5 = IE_5_5;
11
- const IE_6 = 'ie 6';
12
- exports.IE_6 = IE_6;
13
- const IE_7 = 'ie 7';
14
- exports.IE_7 = IE_7;
15
- const IE_8 = 'ie 8';
16
- exports.IE_8 = IE_8;
17
- const OP_9 = 'opera 9';
18
- exports.OP_9 = OP_9;
@@ -1,14 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.VALUE = exports.SELECTOR = exports.PROPERTY = exports.MEDIA_QUERY = void 0;
7
- const MEDIA_QUERY = 'media query';
8
- exports.MEDIA_QUERY = MEDIA_QUERY;
9
- const PROPERTY = 'property';
10
- exports.PROPERTY = PROPERTY;
11
- const SELECTOR = 'selector';
12
- exports.SELECTOR = SELECTOR;
13
- const VALUE = 'value';
14
- exports.VALUE = VALUE;
@@ -1,12 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.RULE = exports.DECL = exports.ATRULE = void 0;
7
- const ATRULE = 'atrule';
8
- exports.ATRULE = ATRULE;
9
- const DECL = 'decl';
10
- exports.DECL = DECL;
11
- const RULE = 'rule';
12
- exports.RULE = RULE;