selector.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. (function() {
  2. var Browsers, OldSelector, Prefixer, Selector, utils,
  3. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  4. hasProp = {}.hasOwnProperty;
  5. OldSelector = require('./old-selector');
  6. Prefixer = require('./prefixer');
  7. Browsers = require('./browsers');
  8. utils = require('./utils');
  9. Selector = (function(superClass) {
  10. extend(Selector, superClass);
  11. function Selector(name1, prefixes, all) {
  12. this.name = name1;
  13. this.prefixes = prefixes;
  14. this.all = all;
  15. this.regexpCache = {};
  16. }
  17. Selector.prototype.check = function(rule) {
  18. if (rule.selector.indexOf(this.name) !== -1) {
  19. return !!rule.selector.match(this.regexp());
  20. } else {
  21. return false;
  22. }
  23. };
  24. Selector.prototype.prefixed = function(prefix) {
  25. return this.name.replace(/^([^\w]*)/, '$1' + prefix);
  26. };
  27. Selector.prototype.regexp = function(prefix) {
  28. var name;
  29. if (this.regexpCache[prefix]) {
  30. return this.regexpCache[prefix];
  31. }
  32. name = prefix ? this.prefixed(prefix) : this.name;
  33. return this.regexpCache[prefix] = RegExp("(^|[^:\"'=])" + (utils.escapeRegexp(name)), "gi");
  34. };
  35. Selector.prototype.possible = function() {
  36. return Browsers.prefixes();
  37. };
  38. Selector.prototype.prefixeds = function(rule) {
  39. var i, len, prefix, prefixeds, ref;
  40. if (rule._autoprefixerPrefixeds) {
  41. return rule._autoprefixerPrefixeds;
  42. }
  43. prefixeds = {};
  44. ref = this.possible();
  45. for (i = 0, len = ref.length; i < len; i++) {
  46. prefix = ref[i];
  47. prefixeds[prefix] = this.replace(rule.selector, prefix);
  48. }
  49. return rule._autoprefixerPrefixeds = prefixeds;
  50. };
  51. Selector.prototype.already = function(rule, prefixeds, prefix) {
  52. var before, index, key, prefixed, some;
  53. index = rule.parent.index(rule) - 1;
  54. while (index >= 0) {
  55. before = rule.parent.nodes[index];
  56. if (before.type !== 'rule') {
  57. return false;
  58. }
  59. some = false;
  60. for (key in prefixeds) {
  61. prefixed = prefixeds[key];
  62. if (before.selector === prefixed) {
  63. if (prefix === key) {
  64. return true;
  65. } else {
  66. some = true;
  67. break;
  68. }
  69. }
  70. }
  71. if (!some) {
  72. return false;
  73. }
  74. index -= 1;
  75. }
  76. return false;
  77. };
  78. Selector.prototype.replace = function(selector, prefix) {
  79. return selector.replace(this.regexp(), '$1' + this.prefixed(prefix));
  80. };
  81. Selector.prototype.add = function(rule, prefix) {
  82. var cloned, prefixeds;
  83. prefixeds = this.prefixeds(rule);
  84. if (this.already(rule, prefixeds, prefix)) {
  85. return;
  86. }
  87. cloned = this.clone(rule, {
  88. selector: prefixeds[prefix]
  89. });
  90. return rule.parent.insertBefore(rule, cloned);
  91. };
  92. Selector.prototype.old = function(prefix) {
  93. return new OldSelector(this, prefix);
  94. };
  95. return Selector;
  96. })(Prefixer);
  97. module.exports = Selector;
  98. }).call(this);