html.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. define(["require", "exports"], function (require, exports) {
  6. 'use strict';
  7. Object.defineProperty(exports, "__esModule", { value: true });
  8. // Allow for running under nodejs/requirejs in tests
  9. var _monaco = (typeof monaco === 'undefined' ? self.monaco : monaco);
  10. var EMPTY_ELEMENTS = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
  11. exports.conf = {
  12. wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,
  13. comments: {
  14. blockComment: ['<!--', '-->']
  15. },
  16. brackets: [
  17. ['<!--', '-->'],
  18. ['<', '>'],
  19. ['{', '}'],
  20. ['(', ')']
  21. ],
  22. autoClosingPairs: [
  23. { open: '{', close: '}' },
  24. { open: '[', close: ']' },
  25. { open: '(', close: ')' },
  26. { open: '"', close: '"' },
  27. { open: '\'', close: '\'' }
  28. ],
  29. surroundingPairs: [
  30. { open: '"', close: '"' },
  31. { open: '\'', close: '\'' },
  32. { open: '{', close: '}' },
  33. { open: '[', close: ']' },
  34. { open: '(', close: ')' },
  35. { open: '<', close: '>' },
  36. ],
  37. onEnterRules: [
  38. {
  39. beforeText: new RegExp("<(?!(?:" + EMPTY_ELEMENTS.join('|') + "))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$", 'i'),
  40. afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>$/i,
  41. action: { indentAction: _monaco.languages.IndentAction.IndentOutdent }
  42. },
  43. {
  44. beforeText: new RegExp("<(?!(?:" + EMPTY_ELEMENTS.join('|') + "))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$", 'i'),
  45. action: { indentAction: _monaco.languages.IndentAction.Indent }
  46. }
  47. ],
  48. folding: {
  49. markers: {
  50. start: new RegExp("^\\s*<!--\\s*#region\\b.*-->"),
  51. end: new RegExp("^\\s*<!--\\s*#endregion\\b.*-->")
  52. }
  53. }
  54. };
  55. exports.language = {
  56. defaultToken: '',
  57. tokenPostfix: '.html',
  58. ignoreCase: true,
  59. // The main tokenizer for our languages
  60. tokenizer: {
  61. root: [
  62. [/<!DOCTYPE/, 'metatag', '@doctype'],
  63. [/<!--/, 'comment', '@comment'],
  64. [/(<)((?:[\w\-]+:)?[\w\-]+)(\s*)(\/>)/, ['delimiter', 'tag', '', 'delimiter']],
  65. [/(<)(script)/, ['delimiter', { token: 'tag', next: '@script' }]],
  66. [/(<)(style)/, ['delimiter', { token: 'tag', next: '@style' }]],
  67. [/(<)((?:[\w\-]+:)?[\w\-]+)/, ['delimiter', { token: 'tag', next: '@otherTag' }]],
  68. [/(<\/)((?:[\w\-]+:)?[\w\-]+)/, ['delimiter', { token: 'tag', next: '@otherTag' }]],
  69. [/</, 'delimiter'],
  70. [/[^<]+/],
  71. ],
  72. doctype: [
  73. [/[^>]+/, 'metatag.content'],
  74. [/>/, 'metatag', '@pop'],
  75. ],
  76. comment: [
  77. [/-->/, 'comment', '@pop'],
  78. [/[^-]+/, 'comment.content'],
  79. [/./, 'comment.content']
  80. ],
  81. otherTag: [
  82. [/\/?>/, 'delimiter', '@pop'],
  83. [/"([^"]*)"/, 'attribute.value'],
  84. [/'([^']*)'/, 'attribute.value'],
  85. [/[\w\-]+/, 'attribute.name'],
  86. [/=/, 'delimiter'],
  87. [/[ \t\r\n]+/],
  88. ],
  89. // -- BEGIN <script> tags handling
  90. // After <script
  91. script: [
  92. [/type/, 'attribute.name', '@scriptAfterType'],
  93. [/"([^"]*)"/, 'attribute.value'],
  94. [/'([^']*)'/, 'attribute.value'],
  95. [/[\w\-]+/, 'attribute.name'],
  96. [/=/, 'delimiter'],
  97. [/>/, { token: 'delimiter', next: '@scriptEmbedded', nextEmbedded: 'text/javascript' }],
  98. [/[ \t\r\n]+/],
  99. [/(<\/)(script\s*)(>)/, ['delimiter', 'tag', { token: 'delimiter', next: '@pop' }]]
  100. ],
  101. // After <script ... type
  102. scriptAfterType: [
  103. [/=/, 'delimiter', '@scriptAfterTypeEquals'],
  104. [/>/, { token: 'delimiter', next: '@scriptEmbedded', nextEmbedded: 'text/javascript' }],
  105. [/[ \t\r\n]+/],
  106. [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
  107. ],
  108. // After <script ... type =
  109. scriptAfterTypeEquals: [
  110. [/"([^"]*)"/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' }],
  111. [/'([^']*)'/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' }],
  112. [/>/, { token: 'delimiter', next: '@scriptEmbedded', nextEmbedded: 'text/javascript' }],
  113. [/[ \t\r\n]+/],
  114. [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
  115. ],
  116. // After <script ... type = $S2
  117. scriptWithCustomType: [
  118. [/>/, { token: 'delimiter', next: '@scriptEmbedded.$S2', nextEmbedded: '$S2' }],
  119. [/"([^"]*)"/, 'attribute.value'],
  120. [/'([^']*)'/, 'attribute.value'],
  121. [/[\w\-]+/, 'attribute.name'],
  122. [/=/, 'delimiter'],
  123. [/[ \t\r\n]+/],
  124. [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
  125. ],
  126. scriptEmbedded: [
  127. [/<\/script/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
  128. [/[^<]+/, '']
  129. ],
  130. // -- END <script> tags handling
  131. // -- BEGIN <style> tags handling
  132. // After <style
  133. style: [
  134. [/type/, 'attribute.name', '@styleAfterType'],
  135. [/"([^"]*)"/, 'attribute.value'],
  136. [/'([^']*)'/, 'attribute.value'],
  137. [/[\w\-]+/, 'attribute.name'],
  138. [/=/, 'delimiter'],
  139. [/>/, { token: 'delimiter', next: '@styleEmbedded', nextEmbedded: 'text/css' }],
  140. [/[ \t\r\n]+/],
  141. [/(<\/)(style\s*)(>)/, ['delimiter', 'tag', { token: 'delimiter', next: '@pop' }]]
  142. ],
  143. // After <style ... type
  144. styleAfterType: [
  145. [/=/, 'delimiter', '@styleAfterTypeEquals'],
  146. [/>/, { token: 'delimiter', next: '@styleEmbedded', nextEmbedded: 'text/css' }],
  147. [/[ \t\r\n]+/],
  148. [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
  149. ],
  150. // After <style ... type =
  151. styleAfterTypeEquals: [
  152. [/"([^"]*)"/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' }],
  153. [/'([^']*)'/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' }],
  154. [/>/, { token: 'delimiter', next: '@styleEmbedded', nextEmbedded: 'text/css' }],
  155. [/[ \t\r\n]+/],
  156. [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
  157. ],
  158. // After <style ... type = $S2
  159. styleWithCustomType: [
  160. [/>/, { token: 'delimiter', next: '@styleEmbedded.$S2', nextEmbedded: '$S2' }],
  161. [/"([^"]*)"/, 'attribute.value'],
  162. [/'([^']*)'/, 'attribute.value'],
  163. [/[\w\-]+/, 'attribute.name'],
  164. [/=/, 'delimiter'],
  165. [/[ \t\r\n]+/],
  166. [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
  167. ],
  168. styleEmbedded: [
  169. [/<\/style/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
  170. [/[^<]+/, '']
  171. ],
  172. },
  173. };
  174. });
  175. // TESTED WITH:
  176. // <!DOCTYPE html>
  177. // <html>
  178. // <head>
  179. // <title>Monarch Workbench</title>
  180. // <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  181. // <!----
  182. // -- -- -- a comment -- -- --
  183. // ---->
  184. // <style bah="bah">
  185. // body { font-family: Consolas; } /* nice */
  186. // </style>
  187. // </head
  188. // >
  189. // a = "asd"
  190. // <body>
  191. // <br/>
  192. // <div
  193. // class
  194. // =
  195. // "test"
  196. // >
  197. // <script>
  198. // function() {
  199. // alert("hi </ script>"); // javascript
  200. // };
  201. // </script>
  202. // <script
  203. // bah="asdfg"
  204. // type="text/css"
  205. // >
  206. // .bar { text-decoration: underline; }
  207. // </script>
  208. // </div>
  209. // </body>
  210. // </html>