sort.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. var css_what_1 = require("css-what");
  4. var procedure_1 = require("./procedure");
  5. var attributes = {
  6. exists: 10,
  7. equals: 8,
  8. not: 7,
  9. start: 6,
  10. end: 6,
  11. any: 5,
  12. hyphen: 4,
  13. element: 4,
  14. };
  15. /**
  16. * Sort the parts of the passed selector,
  17. * as there is potential for optimization
  18. * (some types of selectors are faster than others)
  19. *
  20. * @param arr Selector to sort
  21. */
  22. function sortByProcedure(arr) {
  23. var procs = arr.map(getProcedure);
  24. for (var i = 1; i < arr.length; i++) {
  25. var procNew = procs[i];
  26. if (procNew < 0)
  27. continue;
  28. for (var j = i - 1; j >= 0 && procNew < procs[j]; j--) {
  29. var token = arr[j + 1];
  30. arr[j + 1] = arr[j];
  31. arr[j] = token;
  32. procs[j + 1] = procs[j];
  33. procs[j] = procNew;
  34. }
  35. }
  36. }
  37. exports.default = sortByProcedure;
  38. function getProcedure(token) {
  39. var proc = procedure_1.procedure[token.type];
  40. if (token.type === css_what_1.SelectorType.Attribute) {
  41. proc = attributes[token.action];
  42. if (proc === attributes.equals && token.name === "id") {
  43. // Prefer ID selectors (eg. #ID)
  44. proc = 9;
  45. }
  46. if (token.ignoreCase) {
  47. /*
  48. * IgnoreCase adds some overhead, prefer "normal" token
  49. * this is a binary operation, to ensure it's still an int
  50. */
  51. proc >>= 1;
  52. }
  53. }
  54. else if (token.type === css_what_1.SelectorType.Pseudo) {
  55. if (!token.data) {
  56. proc = 3;
  57. }
  58. else if (token.name === "has" || token.name === "contains") {
  59. proc = 0; // Expensive in any case
  60. }
  61. else if (Array.isArray(token.data)) {
  62. // "matches" and "not"
  63. proc = 0;
  64. for (var i = 0; i < token.data.length; i++) {
  65. // TODO better handling of complex selectors
  66. if (token.data[i].length !== 1)
  67. continue;
  68. var cur = getProcedure(token.data[i][0]);
  69. // Avoid executing :has or :contains
  70. if (cur === 0) {
  71. proc = 0;
  72. break;
  73. }
  74. if (cur > proc)
  75. proc = cur;
  76. }
  77. if (token.data.length > 1 && proc > 0)
  78. proc -= 1;
  79. }
  80. else {
  81. proc = 1;
  82. }
  83. }
  84. return proc;
  85. }