something.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /* @flow */
  2. const validDivisionCharRE = /[\w).+\-_$\]]/
  3. export function parseFilters (exp: string): string {
  4. let inSingle = false
  5. let inDouble = false
  6. let inTemplateString = false
  7. let inRegex = false
  8. let curly = 0
  9. let square = 0
  10. let paren = 0
  11. let lastFilterIndex = 0
  12. let c, prev, i, expression, filters
  13. for (i = 0; i < exp.length; i++) {
  14. prev = c
  15. c = exp.charCodeAt(i)
  16. if (inSingle) {
  17. if (c === 0x27 && prev !== 0x5C) inSingle = false
  18. } else if (inDouble) {
  19. if (c === 0x22 && prev !== 0x5C) inDouble = false
  20. } else if (inTemplateString) {
  21. if (c === 0x60 && prev !== 0x5C) inTemplateString = false
  22. } else if (inRegex) {
  23. if (c === 0x2f && prev !== 0x5C) inRegex = false
  24. } else if (
  25. c === 0x7C && // pipe
  26. exp.charCodeAt(i + 1) !== 0x7C &&
  27. exp.charCodeAt(i - 1) !== 0x7C &&
  28. !curly && !square && !paren
  29. ) {
  30. if (expression === undefined) {
  31. // first filter, end of expression
  32. lastFilterIndex = i + 1
  33. expression = exp.slice(0, i).trim()
  34. } else {
  35. pushFilter()
  36. }
  37. } else {
  38. switch (c) {
  39. case 0x22: inDouble = true; break // "
  40. case 0x27: inSingle = true; break // '
  41. case 0x60: inTemplateString = true; break // `
  42. case 0x28: paren++; break // (
  43. case 0x29: paren--; break // )
  44. case 0x5B: square++; break // [
  45. case 0x5D: square--; break // ]
  46. case 0x7B: curly++; break // {
  47. case 0x7D: curly--; break // }
  48. }
  49. if (c === 0x2f) { // /
  50. let j = i - 1
  51. let p
  52. // find first non-whitespace prev char
  53. for (; j >= 0; j--) {
  54. p = exp.charAt(j)
  55. if (p !== ' ') break
  56. }
  57. if (!p || !validDivisionCharRE.test(p)) {
  58. inRegex = true
  59. }
  60. }
  61. }
  62. }
  63. if (expression === undefined) {
  64. expression = exp.slice(0, i).trim()
  65. } else if (lastFilterIndex !== 0) {
  66. pushFilter()
  67. }
  68. function pushFilter () {
  69. (filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim())
  70. lastFilterIndex = i + 1
  71. }
  72. if (filters) {
  73. for (i = 0; i < filters.length; i++) {
  74. expression = wrapFilter(expression, filters[i])
  75. }
  76. }
  77. return expression
  78. }
  79. function wrapFilter (exp: string, filter: string): string {
  80. const i = filter.indexOf('(')
  81. if (i < 0) {
  82. // _f: resolveFilter
  83. return `_f("${filter}")(${exp})`
  84. } else {
  85. const name = filter.slice(0, i)
  86. const args = filter.slice(i + 1)
  87. return `_f("${name}")(${exp}${args !== ')' ? ',' + args : args}`
  88. }
  89. }