瀏覽代碼

Add html colorizer

Alex Dima 8 年之前
父節點
當前提交
0eadaef95c
共有 5 個文件被更改,包括 216 次插入1 次删除
  1. 2 1
      README.md
  2. 1 0
      gulpfile.js
  3. 205 0
      src/html.ts
  4. 7 0
      src/monaco.contribution.ts
  5. 1 0
      tsconfig.json

+ 2 - 1
README.md

@@ -10,6 +10,7 @@ Colorization and configuration supports for multiple languages for the Monaco Ed
 * csharp
 * fsharp
 * go
+* html
 * ini
 * jade
 * lua
@@ -24,7 +25,7 @@ Colorization and configuration supports for multiple languages for the Monaco Ed
 * vb
 * xml
 
-Also `css` dialects: 
+Also `css` dialects:
 
 * css
 * less

+ 1 - 0
gulpfile.js

@@ -53,6 +53,7 @@ gulp.task('release', ['clean-release','compile'], function() {
 			bundleOne('src/dockerfile'),
 			bundleOne('src/fsharp'),
 			bundleOne('src/go'),
+			bundleOne('src/html'),
 			bundleOne('src/ini'),
 			bundleOne('src/jade'),
 			bundleOne('src/java'),

+ 205 - 0
src/html.ts

@@ -0,0 +1,205 @@
+/*---------------------------------------------------------------------------------------------
+ *  Copyright (c) Microsoft Corporation. All rights reserved.
+ *  Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
+import ILanguage = monaco.languages.IMonarchLanguage;
+
+const EMPTY_ELEMENTS:string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
+
+export var conf:IRichLanguageConfiguration = {
+	wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,
+
+	comments: {
+		blockComment: ['<!--', '-->']
+	},
+
+	brackets: [
+		['<!--', '-->'],
+		['<', '>'],
+	],
+
+	__electricCharacterSupport: {
+		embeddedElectricCharacters: ['*', '}', ']', ')']
+	},
+
+	autoClosingPairs: [
+		{ open: '{', close: '}' },
+		{ open: '[', close: ']' },
+		{ open: '(', close: ')' },
+		{ open: '"', close: '"' },
+		{ open: '\'', close: '\'' }
+	],
+
+	surroundingPairs: [
+		{ open: '"', close: '"' },
+		{ open: '\'', close: '\'' }
+	],
+
+	onEnterRules: [
+		{
+			beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
+			afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>$/i,
+			action: { indentAction: monaco.languages.IndentAction.IndentOutdent }
+		},
+		{
+			beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
+			action: { indentAction: monaco.languages.IndentAction.Indent }
+		}
+	],
+};
+
+export var language = <ILanguage> {
+	defaultToken: '',
+	tokenPostfix: '.html',
+
+	// The main tokenizer for our languages
+	tokenizer: {
+		root: [
+			[/<!DOCTYPE/, 'metatag', '@doctype'],
+			[/<!--/, 'comment', '@comment'],
+			[/<\w+\/>/, 'tag'],
+			[/<script/, 'tag', '@script'],
+			[/<style/, 'tag', '@style'],
+			[/<\w+/, 'tag', '@otherTag'],
+			[/<\/\w+/, 'tag', '@otherTag']
+		],
+
+		doctype: [
+			[/[^>]+/, 'metatag.content' ],
+			[/>/, 'metatag', '@pop' ],
+		],
+
+		comment: [
+			[/-->/, 'comment', '@pop'],
+			[/[^-]+/, 'comment'],
+			[/./, 'comment']
+		],
+
+		otherTag: [
+			[/\/?>/, 'tag', '@pop'],
+			[/"([^"]*)"/, 'attribute.value'],
+			[/'([^']*)'/, 'attribute.value'],
+			[/[\w\-]+/, 'attribute.name'],
+			[/=/, 'delimiter']
+		],
+
+		// -- BEGIN <script> tags handling
+
+		// After <script
+		script: [
+			[/type/, 'attribute.name', '@scriptAfterType'],
+			[/"([^"]*)"/, 'attribute.value'],
+			[/'([^']*)'/, 'attribute.value'],
+			[/[\w\-]+/, 'attribute.name'],
+			[/=/, 'delimiter'],
+			[/>/, { token: 'tag', next: '@scriptEmbedded', nextEmbedded: 'text/javascript'} ],
+			[/<\/script\s*>/, 'tag', '@pop']
+		],
+
+		// After <script ... type
+		scriptAfterType: [
+			[/=/,'delimiter', '@scriptAfterTypeEquals'],
+			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
+		],
+
+		// After <script ... type =
+		scriptAfterTypeEquals: [
+			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' } ],
+			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' } ],
+			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
+		],
+
+		// After <script ... type = $S2
+		scriptWithCustomType: [
+			[/>/, { token: 'tag', next: '@scriptEmbedded', nextEmbedded: '$S2'}],
+			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
+		],
+
+		scriptEmbedded: [
+			[/<\/script/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }]
+		],
+
+		// -- END <script> tags handling
+
+
+		// -- BEGIN <style> tags handling
+
+		// After <style
+		style: [
+			[/type/, 'attribute.name', '@styleAfterType'],
+			[/"([^"]*)"/, 'attribute.value'],
+			[/'([^']*)'/, 'attribute.value'],
+			[/[\w\-]+/, 'attribute.name'],
+			[/=/, 'delimiter'],
+			[/>/, { token: 'tag', next: '@styleEmbedded', nextEmbedded: 'text/css'} ],
+			[/<\/style\s*>/, 'tag', '@pop']
+		],
+
+		// After <style ... type
+		styleAfterType: [
+			[/=/,'delimiter', '@styleAfterTypeEquals'],
+			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
+		],
+
+		// After <style ... type =
+		styleAfterTypeEquals: [
+			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' } ],
+			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' } ],
+			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
+		],
+
+		// After <style ... type = $S2
+		styleWithCustomType: [
+			[/>/, { token: 'tag', next: '@styleEmbedded', nextEmbedded: '$S2'}],
+			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
+		],
+
+		styleEmbedded: [
+			[/<\/style/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }]
+		],
+
+	// -- END <style> tags handling
+	},
+};
+
+// TESTED WITH:
+
+// <!DOCTYPE html>
+// <html>
+// <head>
+//   <title>Monarch Workbench</title>
+//   <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+//   <!----
+//   -- -- -- a comment -- -- --
+//   ---->
+//   <style bah="bah">
+//     body { font-family: Consolas; } /* nice */
+//   </style>
+// </head
+// >
+// a = "asd"
+// <body>
+//   <br/>
+//   <div
+//   class
+//   =
+//   "test"
+//   >
+//     <script>
+//       function() {
+//         alert("hi </ script>"); // javascript
+//       };
+//     </script>
+//     <script
+// 	bah="asdfg"
+// 	type="text/css"
+// 	>
+//   .bar { text-decoration: underline; }
+//     </script>
+//   </div>
+// </body>
+// </html>

+ 7 - 0
src/monaco.contribution.ts

@@ -92,6 +92,13 @@ registerLanguage({
 	aliases: [ 'Go' ],
 	module: './go'
 });
+registerLanguage({
+	id: 'html',
+	extensions: ['.html', '.htm', '.shtml', '.xhtml', '.mdoc', '.jsp', '.asp', '.aspx', '.jshtm'],
+	aliases: ['HTML', 'htm', 'html', 'xhtml'],
+	mimetypes: ['text/html', 'text/x-jshtm', 'text/template', 'text/ng-template'],
+	module: './html'
+});
 registerLanguage({
 	id: 'ini',
 	extensions: [ '.ini', '.properties', '.gitconfig' ],

+ 1 - 0
tsconfig.json

@@ -18,6 +18,7 @@
     "src/dockerfile.ts",
     "src/fsharp.ts",
     "src/go.ts",
+    "src/html.ts",
     "src/ini.ts",
     "src/jade.ts",
     "src/java.ts",