parseNestedPropRoot.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports["default"] = parseNestedPropRoot;
  6. /**
  7. * Attempts to parse a selector as if it"s a root for a group of nested props
  8. * E.g.: `margin: {`, `font: 10px/1.1 Arial {` ("{" excluded)
  9. */
  10. function parseNestedPropRoot(propString) {
  11. var modesEntered = [{
  12. mode: "normal",
  13. character: null,
  14. isCalculationEnabled: true
  15. }];
  16. var result = {};
  17. var lastModeIndex = 0;
  18. var propName = "";
  19. for (var i = 0; i < propString.length; i++) {
  20. var character = propString[i];
  21. var prevCharacter = propString[i - 1];
  22. // If entering/exiting a string
  23. if (character === '"' || character === "'") {
  24. if (modesEntered[lastModeIndex].isCalculationEnabled === true) {
  25. modesEntered.push({
  26. mode: "string",
  27. isCalculationEnabled: false,
  28. character: character
  29. });
  30. lastModeIndex++;
  31. } else if (modesEntered[lastModeIndex].mode === "string" && modesEntered[lastModeIndex].character === character && prevCharacter !== "\\") {
  32. modesEntered.pop();
  33. lastModeIndex--;
  34. }
  35. }
  36. // If entering/exiting interpolation
  37. if (character === "{") {
  38. modesEntered.push({
  39. mode: "interpolation",
  40. isCalculationEnabled: true
  41. });
  42. lastModeIndex++;
  43. } else if (character === "}") {
  44. modesEntered.pop();
  45. lastModeIndex--;
  46. }
  47. // Check for : outside fn call, string or interpolation. It must be at the
  48. // end of a string or have a whitespace between it and following value
  49. if (modesEntered[lastModeIndex].mode === "normal" && character === ":" && prevCharacter !== "\\") {
  50. var propValueStr = propString.substring(i + 1);
  51. if (propValueStr.length) {
  52. var propValue = {
  53. before: /^(\s*)/.exec(propValueStr)[1],
  54. value: propValueStr.trim()
  55. };
  56. // It's a declaration if 1) there is a whitespace after :, or
  57. // 2) the value is a number with/without a unit (starts with a number
  58. // or a dot), or
  59. // 3) the value is a variable (starts with $), or
  60. // 4) the value a string, surprisingly
  61. if (propValue.before === "" && !/^[\d.$'"]/.test(propValue.value)) {
  62. return null;
  63. }
  64. // +1 for the colon
  65. propValue.sourceIndex = propValue.before.length + i + 1;
  66. result.propValue = propValue;
  67. }
  68. result.propName = {
  69. after: /(\s*)$/.exec(propName)[1],
  70. value: propName.trim()
  71. };
  72. return result;
  73. }
  74. propName += character;
  75. }
  76. return null;
  77. }