merge-non-adjacent-by-body.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. var stringifyBody = require('../stringifier/one-time').body;
  2. var stringifySelectors = require('../stringifier/one-time').selectors;
  3. var cleanUpSelectors = require('./clean-up').selectors;
  4. var isSpecial = require('./is-special');
  5. function unsafeSelector(value) {
  6. return /\.|\*| :/.test(value);
  7. }
  8. function isBemElement(token) {
  9. var asString = stringifySelectors(token[1]);
  10. return asString.indexOf('__') > -1 || asString.indexOf('--') > -1;
  11. }
  12. function withoutModifier(selector) {
  13. return selector.replace(/--[^ ,>\+~:]+/g, '');
  14. }
  15. function removeAnyUnsafeElements(left, candidates) {
  16. var leftSelector = withoutModifier(stringifySelectors(left[1]));
  17. for (var body in candidates) {
  18. var right = candidates[body];
  19. var rightSelector = withoutModifier(stringifySelectors(right[1]));
  20. if (rightSelector.indexOf(leftSelector) > -1 || leftSelector.indexOf(rightSelector) > -1)
  21. delete candidates[body];
  22. }
  23. }
  24. function mergeNonAdjacentByBody(tokens, options) {
  25. var candidates = {};
  26. var adjacentSpace = options.compatibility.selectors.adjacentSpace;
  27. for (var i = tokens.length - 1; i >= 0; i--) {
  28. var token = tokens[i];
  29. if (token[0] != 'selector')
  30. continue;
  31. if (token[2].length > 0 && (!options.semanticMerging && unsafeSelector(stringifySelectors(token[1]))))
  32. candidates = {};
  33. if (token[2].length > 0 && options.semanticMerging && isBemElement(token))
  34. removeAnyUnsafeElements(token, candidates);
  35. var candidateBody = stringifyBody(token[2]);
  36. var oldToken = candidates[candidateBody];
  37. if (oldToken && !isSpecial(options, stringifySelectors(token[1])) && !isSpecial(options, stringifySelectors(oldToken[1]))) {
  38. token[1] = token[2].length > 0 ?
  39. cleanUpSelectors(oldToken[1].concat(token[1]), false, adjacentSpace) :
  40. oldToken[1].concat(token[1]);
  41. oldToken[2] = [];
  42. candidates[candidateBody] = null;
  43. }
  44. candidates[stringifyBody(token[2])] = token;
  45. }
  46. }
  47. module.exports = mergeNonAdjacentByBody;