prism-pug.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. (function (Prism) {
  2. // TODO:
  3. // - Add CSS highlighting inside <style> tags
  4. // - Add support for multi-line code blocks
  5. // - Add support for interpolation #{} and !{}
  6. // - Add support for tag interpolation #[]
  7. // - Add explicit support for plain text using |
  8. // - Add support for markup embedded in plain text
  9. Prism.languages.pug = {
  10. // Multiline stuff should appear before the rest
  11. // This handles both single-line and multi-line comments
  12. 'comment': {
  13. pattern: /(^([\t ]*))\/\/.*(?:(?:\r?\n|\r)\2[\t ].+)*/m,
  14. lookbehind: true
  15. },
  16. // All the tag-related part is in lookbehind
  17. // so that it can be highlighted by the "tag" pattern
  18. 'multiline-script': {
  19. pattern: /(^([\t ]*)script\b.*\.[\t ]*)(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/m,
  20. lookbehind: true,
  21. inside: Prism.languages.javascript
  22. },
  23. // See at the end of the file for known filters
  24. 'filter': {
  25. pattern: /(^([\t ]*)):.+(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/m,
  26. lookbehind: true,
  27. inside: {
  28. 'filter-name': {
  29. pattern: /^:[\w-]+/,
  30. alias: 'variable'
  31. },
  32. 'text': /\S[\s\S]*/,
  33. }
  34. },
  35. 'multiline-plain-text': {
  36. pattern: /(^([\t ]*)[\w\-#.]+\.[\t ]*)(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/m,
  37. lookbehind: true
  38. },
  39. 'markup': {
  40. pattern: /(^[\t ]*)<.+/m,
  41. lookbehind: true,
  42. inside: Prism.languages.markup
  43. },
  44. 'doctype': {
  45. pattern: /((?:^|\n)[\t ]*)doctype(?: .+)?/,
  46. lookbehind: true
  47. },
  48. // This handle all conditional and loop keywords
  49. 'flow-control': {
  50. pattern: /(^[\t ]*)(?:case|default|each|else|if|unless|when|while)\b(?: .+)?/m,
  51. lookbehind: true,
  52. inside: {
  53. 'each': {
  54. pattern: /^each .+? in\b/,
  55. inside: {
  56. 'keyword': /\b(?:each|in)\b/,
  57. 'punctuation': /,/
  58. }
  59. },
  60. 'branch': {
  61. pattern: /^(?:case|default|else|if|unless|when|while)\b/,
  62. alias: 'keyword'
  63. },
  64. rest: Prism.languages.javascript
  65. }
  66. },
  67. 'keyword': {
  68. pattern: /(^[\t ]*)(?:append|block|extends|include|prepend)\b.+/m,
  69. lookbehind: true
  70. },
  71. 'mixin': [
  72. // Declaration
  73. {
  74. pattern: /(^[\t ]*)mixin .+/m,
  75. lookbehind: true,
  76. inside: {
  77. 'keyword': /^mixin/,
  78. 'function': /\w+(?=\s*\(|\s*$)/,
  79. 'punctuation': /[(),.]/
  80. }
  81. },
  82. // Usage
  83. {
  84. pattern: /(^[\t ]*)\+.+/m,
  85. lookbehind: true,
  86. inside: {
  87. 'name': {
  88. pattern: /^\+\w+/,
  89. alias: 'function'
  90. },
  91. rest: Prism.languages.javascript
  92. }
  93. }
  94. ],
  95. 'script': {
  96. pattern: /(^[\t ]*script(?:(?:&[^(]+)?\([^)]+\))*[\t ]).+/m,
  97. lookbehind: true,
  98. inside: Prism.languages.javascript
  99. },
  100. 'plain-text': {
  101. pattern: /(^[\t ]*(?!-)[\w\-#.]*[\w\-](?:(?:&[^(]+)?\([^)]+\))*\/?[\t ]).+/m,
  102. lookbehind: true
  103. },
  104. 'tag': {
  105. pattern: /(^[\t ]*)(?!-)[\w\-#.]*[\w\-](?:(?:&[^(]+)?\([^)]+\))*\/?:?/m,
  106. lookbehind: true,
  107. inside: {
  108. 'attributes': [
  109. {
  110. pattern: /&[^(]+\([^)]+\)/,
  111. inside: Prism.languages.javascript
  112. },
  113. {
  114. pattern: /\([^)]+\)/,
  115. inside: {
  116. 'attr-value': {
  117. pattern: /(=\s*(?!\s))(?:\{[^}]*\}|[^,)\r\n]+)/,
  118. lookbehind: true,
  119. inside: Prism.languages.javascript
  120. },
  121. 'attr-name': /[\w-]+(?=\s*!?=|\s*[,)])/,
  122. 'punctuation': /[!=(),]+/
  123. }
  124. }
  125. ],
  126. 'punctuation': /:/,
  127. 'attr-id': /#[\w\-]+/,
  128. 'attr-class': /\.[\w\-]+/
  129. }
  130. },
  131. 'code': [
  132. {
  133. pattern: /(^[\t ]*(?:-|!?=)).+/m,
  134. lookbehind: true,
  135. inside: Prism.languages.javascript
  136. }
  137. ],
  138. 'punctuation': /[.\-!=|]+/
  139. };
  140. var filter_pattern = /(^([\t ]*)):<filter_name>(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/.source;
  141. // Non exhaustive list of available filters and associated languages
  142. var filters = [
  143. { filter: 'atpl', language: 'twig' },
  144. { filter: 'coffee', language: 'coffeescript' },
  145. 'ejs',
  146. 'handlebars',
  147. 'less',
  148. 'livescript',
  149. 'markdown',
  150. { filter: 'sass', language: 'scss' },
  151. 'stylus'
  152. ];
  153. var all_filters = {};
  154. for (var i = 0, l = filters.length; i < l; i++) {
  155. var filter = filters[i];
  156. filter = typeof filter === 'string' ? { filter: filter, language: filter } : filter;
  157. if (Prism.languages[filter.language]) {
  158. all_filters['filter-' + filter.filter] = {
  159. pattern: RegExp(filter_pattern.replace('<filter_name>', function () { return filter.filter; }), 'm'),
  160. lookbehind: true,
  161. inside: {
  162. 'filter-name': {
  163. pattern: /^:[\w-]+/,
  164. alias: 'variable'
  165. },
  166. 'text': {
  167. pattern: /\S[\s\S]*/,
  168. alias: [filter.language, 'language-' + filter.language],
  169. inside: Prism.languages[filter.language]
  170. }
  171. }
  172. };
  173. }
  174. }
  175. Prism.languages.insertBefore('pug', 'filter', all_filters);
  176. }(Prism));