1
0

smarty.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. CodeMirror.defineMode("smarty", function(config) {
  2. var keyFuncs = ["debug", "extends", "function", "include", "literal"];
  3. var last;
  4. var regs = {
  5. operatorChars: /[+\-*&%=<>!?]/,
  6. validIdentifier: /[a-zA-Z0-9\_]/,
  7. stringChar: /[\'\"]/
  8. };
  9. var leftDelim = (typeof config.mode.leftDelimiter != 'undefined') ? config.mode.leftDelimiter : "{";
  10. var rightDelim = (typeof config.mode.rightDelimiter != 'undefined') ? config.mode.rightDelimiter : "}";
  11. function ret(style, lst) { last = lst; return style; }
  12. function tokenizer(stream, state) {
  13. function chain(parser) {
  14. state.tokenize = parser;
  15. return parser(stream, state);
  16. }
  17. if (stream.match(leftDelim, true)) {
  18. if (stream.eat("*")) {
  19. return chain(inBlock("comment", "*" + rightDelim));
  20. }
  21. else {
  22. state.tokenize = inSmarty;
  23. return "tag";
  24. }
  25. }
  26. else {
  27. // I'd like to do an eatWhile() here, but I can't get it to eat only up to the rightDelim string/char
  28. stream.next();
  29. return null;
  30. }
  31. }
  32. function inSmarty(stream, state) {
  33. if (stream.match(rightDelim, true)) {
  34. state.tokenize = tokenizer;
  35. return ret("tag", null);
  36. }
  37. var ch = stream.next();
  38. if (ch == "$") {
  39. stream.eatWhile(regs.validIdentifier);
  40. return ret("variable-2", "variable");
  41. }
  42. else if (ch == ".") {
  43. return ret("operator", "property");
  44. }
  45. else if (regs.stringChar.test(ch)) {
  46. state.tokenize = inAttribute(ch);
  47. return ret("string", "string");
  48. }
  49. else if (regs.operatorChars.test(ch)) {
  50. stream.eatWhile(regs.operatorChars);
  51. return ret("operator", "operator");
  52. }
  53. else if (ch == "[" || ch == "]") {
  54. return ret("bracket", "bracket");
  55. }
  56. else if (/\d/.test(ch)) {
  57. stream.eatWhile(/\d/);
  58. return ret("number", "number");
  59. }
  60. else {
  61. if (state.last == "variable") {
  62. if (ch == "@") {
  63. stream.eatWhile(regs.validIdentifier);
  64. return ret("property", "property");
  65. }
  66. else if (ch == "|") {
  67. stream.eatWhile(regs.validIdentifier);
  68. return ret("qualifier", "modifier");
  69. }
  70. }
  71. else if (state.last == "whitespace") {
  72. stream.eatWhile(regs.validIdentifier);
  73. return ret("attribute", "modifier");
  74. }
  75. else if (state.last == "property") {
  76. stream.eatWhile(regs.validIdentifier);
  77. return ret("property", null);
  78. }
  79. else if (/\s/.test(ch)) {
  80. last = "whitespace";
  81. return null;
  82. }
  83. var str = "";
  84. if (ch != "/") {
  85. str += ch;
  86. }
  87. var c = "";
  88. while ((c = stream.eat(regs.validIdentifier))) {
  89. str += c;
  90. }
  91. var i, j;
  92. for (i=0, j=keyFuncs.length; i<j; i++) {
  93. if (keyFuncs[i] == str) {
  94. return ret("keyword", "keyword");
  95. }
  96. }
  97. if (/\s/.test(ch)) {
  98. return null;
  99. }
  100. return ret("tag", "tag");
  101. }
  102. }
  103. function inAttribute(quote) {
  104. return function(stream, state) {
  105. while (!stream.eol()) {
  106. if (stream.next() == quote) {
  107. state.tokenize = inSmarty;
  108. break;
  109. }
  110. }
  111. return "string";
  112. };
  113. }
  114. function inBlock(style, terminator) {
  115. return function(stream, state) {
  116. while (!stream.eol()) {
  117. if (stream.match(terminator)) {
  118. state.tokenize = tokenizer;
  119. break;
  120. }
  121. stream.next();
  122. }
  123. return style;
  124. };
  125. }
  126. return {
  127. startState: function() {
  128. return { tokenize: tokenizer, mode: "smarty", last: null };
  129. },
  130. token: function(stream, state) {
  131. var style = state.tokenize(stream, state);
  132. state.last = last;
  133. return style;
  134. },
  135. electricChars: ""
  136. };
  137. });
  138. CodeMirror.defineMIME("text/x-smarty", "smarty");