html.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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('vs/basic-languages/html/html',["require", "exports", "../fillers/monaco-editor-core"], function (require, exports, monaco_editor_core_1) {
  6. "use strict";
  7. Object.defineProperty(exports, "__esModule", { value: true });
  8. exports.language = exports.conf = void 0;
  9. var EMPTY_ELEMENTS = [
  10. 'area',
  11. 'base',
  12. 'br',
  13. 'col',
  14. 'embed',
  15. 'hr',
  16. 'img',
  17. 'input',
  18. 'keygen',
  19. 'link',
  20. 'menuitem',
  21. 'meta',
  22. 'param',
  23. 'source',
  24. 'track',
  25. 'wbr'
  26. ];
  27. exports.conf = {
  28. wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,
  29. comments: {
  30. blockComment: ['<!--', '-->']
  31. },
  32. brackets: [
  33. ['<!--', '-->'],
  34. ['<', '>'],
  35. ['{', '}'],
  36. ['(', ')']
  37. ],
  38. autoClosingPairs: [
  39. { open: '{', close: '}' },
  40. { open: '[', close: ']' },
  41. { open: '(', close: ')' },
  42. { open: '"', close: '"' },
  43. { open: "'", close: "'" }
  44. ],
  45. surroundingPairs: [
  46. { open: '"', close: '"' },
  47. { open: "'", close: "'" },
  48. { open: '{', close: '}' },
  49. { open: '[', close: ']' },
  50. { open: '(', close: ')' },
  51. { open: '<', close: '>' }
  52. ],
  53. onEnterRules: [
  54. {
  55. beforeText: new RegExp("<(?!(?:" + EMPTY_ELEMENTS.join('|') + "))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$", 'i'),
  56. afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>$/i,
  57. action: {
  58. indentAction: monaco_editor_core_1.languages.IndentAction.IndentOutdent
  59. }
  60. },
  61. {
  62. beforeText: new RegExp("<(?!(?:" + EMPTY_ELEMENTS.join('|') + "))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$", 'i'),
  63. action: { indentAction: monaco_editor_core_1.languages.IndentAction.Indent }
  64. }
  65. ],
  66. folding: {
  67. markers: {
  68. start: new RegExp('^\\s*<!--\\s*#region\\b.*-->'),
  69. end: new RegExp('^\\s*<!--\\s*#endregion\\b.*-->')
  70. }
  71. }
  72. };
  73. exports.language = {
  74. defaultToken: '',
  75. tokenPostfix: '.html',
  76. ignoreCase: true,
  77. // The main tokenizer for our languages
  78. tokenizer: {
  79. root: [
  80. [/<!DOCTYPE/, 'metatag', '@doctype'],
  81. [/<!--/, 'comment', '@comment'],
  82. [/(<)((?:[\w\-]+:)?[\w\-]+)(\s*)(\/>)/, ['delimiter', 'tag', '', 'delimiter']],
  83. [/(<)(script)/, ['delimiter', { token: 'tag', next: '@script' }]],
  84. [/(<)(style)/, ['delimiter', { token: 'tag', next: '@style' }]],
  85. [/(<)((?:[\w\-]+:)?[\w\-]+)/, ['delimiter', { token: 'tag', next: '@otherTag' }]],
  86. [/(<\/)((?:[\w\-]+:)?[\w\-]+)/, ['delimiter', { token: 'tag', next: '@otherTag' }]],
  87. [/</, 'delimiter'],
  88. [/[^<]+/] // text
  89. ],
  90. doctype: [
  91. [/[^>]+/, 'metatag.content'],
  92. [/>/, 'metatag', '@pop']
  93. ],
  94. comment: [
  95. [/-->/, 'comment', '@pop'],
  96. [/[^-]+/, 'comment.content'],
  97. [/./, 'comment.content']
  98. ],
  99. otherTag: [
  100. [/\/?>/, 'delimiter', '@pop'],
  101. [/"([^"]*)"/, 'attribute.value'],
  102. [/'([^']*)'/, 'attribute.value'],
  103. [/[\w\-]+/, 'attribute.name'],
  104. [/=/, 'delimiter'],
  105. [/[ \t\r\n]+/] // whitespace
  106. ],
  107. // -- BEGIN <script> tags handling
  108. // After <script
  109. script: [
  110. [/type/, 'attribute.name', '@scriptAfterType'],
  111. [/"([^"]*)"/, 'attribute.value'],
  112. [/'([^']*)'/, 'attribute.value'],
  113. [/[\w\-]+/, 'attribute.name'],
  114. [/=/, 'delimiter'],
  115. [
  116. />/,
  117. {
  118. token: 'delimiter',
  119. next: '@scriptEmbedded',
  120. nextEmbedded: 'text/javascript'
  121. }
  122. ],
  123. [/[ \t\r\n]+/],
  124. [/(<\/)(script\s*)(>)/, ['delimiter', 'tag', { token: 'delimiter', next: '@pop' }]]
  125. ],
  126. // After <script ... type
  127. scriptAfterType: [
  128. [/=/, 'delimiter', '@scriptAfterTypeEquals'],
  129. [
  130. />/,
  131. {
  132. token: 'delimiter',
  133. next: '@scriptEmbedded',
  134. nextEmbedded: 'text/javascript'
  135. }
  136. ],
  137. [/[ \t\r\n]+/],
  138. [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
  139. ],
  140. // After <script ... type =
  141. scriptAfterTypeEquals: [
  142. [
  143. /"([^"]*)"/,
  144. {
  145. token: 'attribute.value',
  146. switchTo: '@scriptWithCustomType.$1'
  147. }
  148. ],
  149. [
  150. /'([^']*)'/,
  151. {
  152. token: 'attribute.value',
  153. switchTo: '@scriptWithCustomType.$1'
  154. }
  155. ],
  156. [
  157. />/,
  158. {
  159. token: 'delimiter',
  160. next: '@scriptEmbedded',
  161. nextEmbedded: 'text/javascript'
  162. }
  163. ],
  164. [/[ \t\r\n]+/],
  165. [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
  166. ],
  167. // After <script ... type = $S2
  168. scriptWithCustomType: [
  169. [
  170. />/,
  171. {
  172. token: 'delimiter',
  173. next: '@scriptEmbedded.$S2',
  174. nextEmbedded: '$S2'
  175. }
  176. ],
  177. [/"([^"]*)"/, 'attribute.value'],
  178. [/'([^']*)'/, 'attribute.value'],
  179. [/[\w\-]+/, 'attribute.name'],
  180. [/=/, 'delimiter'],
  181. [/[ \t\r\n]+/],
  182. [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
  183. ],
  184. scriptEmbedded: [
  185. [/<\/script/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
  186. [/[^<]+/, '']
  187. ],
  188. // -- END <script> tags handling
  189. // -- BEGIN <style> tags handling
  190. // After <style
  191. style: [
  192. [/type/, 'attribute.name', '@styleAfterType'],
  193. [/"([^"]*)"/, 'attribute.value'],
  194. [/'([^']*)'/, 'attribute.value'],
  195. [/[\w\-]+/, 'attribute.name'],
  196. [/=/, 'delimiter'],
  197. [
  198. />/,
  199. {
  200. token: 'delimiter',
  201. next: '@styleEmbedded',
  202. nextEmbedded: 'text/css'
  203. }
  204. ],
  205. [/[ \t\r\n]+/],
  206. [/(<\/)(style\s*)(>)/, ['delimiter', 'tag', { token: 'delimiter', next: '@pop' }]]
  207. ],
  208. // After <style ... type
  209. styleAfterType: [
  210. [/=/, 'delimiter', '@styleAfterTypeEquals'],
  211. [
  212. />/,
  213. {
  214. token: 'delimiter',
  215. next: '@styleEmbedded',
  216. nextEmbedded: 'text/css'
  217. }
  218. ],
  219. [/[ \t\r\n]+/],
  220. [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
  221. ],
  222. // After <style ... type =
  223. styleAfterTypeEquals: [
  224. [
  225. /"([^"]*)"/,
  226. {
  227. token: 'attribute.value',
  228. switchTo: '@styleWithCustomType.$1'
  229. }
  230. ],
  231. [
  232. /'([^']*)'/,
  233. {
  234. token: 'attribute.value',
  235. switchTo: '@styleWithCustomType.$1'
  236. }
  237. ],
  238. [
  239. />/,
  240. {
  241. token: 'delimiter',
  242. next: '@styleEmbedded',
  243. nextEmbedded: 'text/css'
  244. }
  245. ],
  246. [/[ \t\r\n]+/],
  247. [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
  248. ],
  249. // After <style ... type = $S2
  250. styleWithCustomType: [
  251. [
  252. />/,
  253. {
  254. token: 'delimiter',
  255. next: '@styleEmbedded.$S2',
  256. nextEmbedded: '$S2'
  257. }
  258. ],
  259. [/"([^"]*)"/, 'attribute.value'],
  260. [/'([^']*)'/, 'attribute.value'],
  261. [/[\w\-]+/, 'attribute.name'],
  262. [/=/, 'delimiter'],
  263. [/[ \t\r\n]+/],
  264. [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
  265. ],
  266. styleEmbedded: [
  267. [/<\/style/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
  268. [/[^<]+/, '']
  269. ]
  270. // -- END <style> tags handling
  271. }
  272. };
  273. });
  274. // TESTED WITH:
  275. // <!DOCTYPE html>
  276. // <html>
  277. // <head>
  278. // <title>Monarch Workbench</title>
  279. // <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  280. // <!----
  281. // -- -- -- a comment -- -- --
  282. // ---->
  283. // <style bah="bah">
  284. // body { font-family: Consolas; } /* nice */
  285. // </style>
  286. // </head
  287. // >
  288. // a = "asd"
  289. // <body>
  290. // <br/>
  291. // <div
  292. // class
  293. // =
  294. // "test"
  295. // >
  296. // <script>
  297. // function() {
  298. // alert("hi </ script>"); // javascript
  299. // };
  300. // </script>
  301. // <script
  302. // bah="asdfg"
  303. // type="text/css"
  304. // >
  305. // .bar { text-decoration: underline; }
  306. // </script>
  307. // </div>
  308. // </body>
  309. // </html>
  310. ;