|
@@ -5,8 +5,6 @@
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
-import { conf as htmlConf, language as htmlLanguage } from '../html/html';
|
|
|
-
|
|
|
import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
|
|
|
import ILanguage = monaco.languages.IMonarchLanguage;
|
|
|
|
|
@@ -23,7 +21,10 @@ export const conf: IRichLanguageConfiguration = {
|
|
|
['{{', '}}'],
|
|
|
['(', ')'],
|
|
|
['[', ']'],
|
|
|
- ...htmlConf.brackets,
|
|
|
+
|
|
|
+ // HTML
|
|
|
+ ['<!--', '-->'],
|
|
|
+ ['<', '>'],
|
|
|
],
|
|
|
|
|
|
autoClosingPairs: [
|
|
@@ -39,7 +40,9 @@ export const conf: IRichLanguageConfiguration = {
|
|
|
surroundingPairs: [
|
|
|
{ open: '"', close: '"' },
|
|
|
{ open: '\'', close: '\'' },
|
|
|
- ...htmlConf.surroundingPairs,
|
|
|
+
|
|
|
+ // HTML
|
|
|
+ { open: '<', close: '>' },
|
|
|
],
|
|
|
}
|
|
|
|
|
@@ -61,13 +64,25 @@ export const language = <ILanguage>{
|
|
|
],
|
|
|
|
|
|
tokenizer: {
|
|
|
- ...htmlLanguage.tokenizer,
|
|
|
-
|
|
|
root: [
|
|
|
+ // whitespace
|
|
|
+ [/\s+/],
|
|
|
+
|
|
|
+ // Twig Tag Delimiters
|
|
|
[/{#/, 'comment.twig', '@commentState'],
|
|
|
[/{%[-~]?/, 'delimiter.twig', '@blockState'],
|
|
|
[/{{[-~]?/, 'delimiter.twig', '@variableState'],
|
|
|
- ...htmlLanguage.tokenizer.root,
|
|
|
+
|
|
|
+ // HTML
|
|
|
+ [/<!DOCTYPE/, 'metatag.html', '@doctype'],
|
|
|
+ [/<!--/, 'comment.html', '@comment'],
|
|
|
+ [/(<)((?:[\w\-]+:)?[\w\-]+)(\s*)(\/>)/, ['delimiter.html', 'tag.html', '', 'delimiter.html']],
|
|
|
+ [/(<)(script)/, ['delimiter.html', { token: 'tag.html', next: '@script' }]],
|
|
|
+ [/(<)(style)/, ['delimiter.html', { token: 'tag.html', next: '@style' }]],
|
|
|
+ [/(<)((?:[\w\-]+:)?[\w\-]+)/, ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]],
|
|
|
+ [/(<\/)((?:[\w\-]+:)?[\w\-]+)/, ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]],
|
|
|
+ [/</, 'delimiter.html'],
|
|
|
+ [/[^<]+/], // text
|
|
|
],
|
|
|
|
|
|
/**
|
|
@@ -175,5 +190,125 @@ export const language = <ILanguage>{
|
|
|
// assignment
|
|
|
[/=/, 'operators.twig'],
|
|
|
],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * HTML
|
|
|
+ */
|
|
|
+ doctype: [
|
|
|
+ [/[^>]+/, 'metatag.content.html'],
|
|
|
+ [/>/, 'metatag.html', '@pop'],
|
|
|
+ ],
|
|
|
+
|
|
|
+ comment: [
|
|
|
+ [/-->/, 'comment.html', '@pop'],
|
|
|
+ [/[^-]+/, 'comment.content.html'],
|
|
|
+ [/./, 'comment.content.html']
|
|
|
+ ],
|
|
|
+
|
|
|
+ otherTag: [
|
|
|
+ [/\/?>/, 'delimiter.html', '@pop'],
|
|
|
+ [/"([^"]*)"/, 'attribute.value.html'],
|
|
|
+ [/'([^']*)'/, 'attribute.value.html'],
|
|
|
+ [/[\w\-]+/, 'attribute.name.html'],
|
|
|
+ [/=/, 'delimiter.html'],
|
|
|
+ [/[ \t\r\n]+/], // whitespace
|
|
|
+ ],
|
|
|
+
|
|
|
+ // -- BEGIN <script> tags handling
|
|
|
+
|
|
|
+ // After <script
|
|
|
+ script: [
|
|
|
+ [/type/, 'attribute.name.html', '@scriptAfterType'],
|
|
|
+ [/"([^"]*)"/, 'attribute.value.html'],
|
|
|
+ [/'([^']*)'/, 'attribute.value.html'],
|
|
|
+ [/[\w\-]+/, 'attribute.name.html'],
|
|
|
+ [/=/, 'delimiter.html'],
|
|
|
+ [/>/, { token: 'delimiter.html', next: '@scriptEmbedded', nextEmbedded: 'text/javascript' }],
|
|
|
+ [/[ \t\r\n]+/], // whitespace
|
|
|
+ [/(<\/)(script\s*)(>)/, ['delimiter.html', 'tag.html', { token: 'delimiter.html', next: '@pop' }]]
|
|
|
+ ],
|
|
|
+
|
|
|
+ // After <script ... type
|
|
|
+ scriptAfterType: [
|
|
|
+ [/=/, 'delimiter.html', '@scriptAfterTypeEquals'],
|
|
|
+ [/>/, { token: 'delimiter.html', next: '@scriptEmbedded', nextEmbedded: 'text/javascript' }], // cover invalid e.g. <script type>
|
|
|
+ [/[ \t\r\n]+/], // whitespace
|
|
|
+ [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
|
|
|
+ ],
|
|
|
+
|
|
|
+ // After <script ... type =
|
|
|
+ scriptAfterTypeEquals: [
|
|
|
+ [/"([^"]*)"/, { token: 'attribute.value.html', switchTo: '@scriptWithCustomType.$1' }],
|
|
|
+ [/'([^']*)'/, { token: 'attribute.value.html', switchTo: '@scriptWithCustomType.$1' }],
|
|
|
+ [/>/, { token: 'delimiter.html', next: '@scriptEmbedded', nextEmbedded: 'text/javascript' }], // cover invalid e.g. <script type=>
|
|
|
+ [/[ \t\r\n]+/], // whitespace
|
|
|
+ [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
|
|
|
+ ],
|
|
|
+
|
|
|
+ // After <script ... type = $S2
|
|
|
+ scriptWithCustomType: [
|
|
|
+ [/>/, { token: 'delimiter.html', next: '@scriptEmbedded.$S2', nextEmbedded: '$S2' }],
|
|
|
+ [/"([^"]*)"/, 'attribute.value.html'],
|
|
|
+ [/'([^']*)'/, 'attribute.value.html'],
|
|
|
+ [/[\w\-]+/, 'attribute.name.html'],
|
|
|
+ [/=/, 'delimiter.html'],
|
|
|
+ [/[ \t\r\n]+/], // whitespace
|
|
|
+ [/<\/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.html', '@styleAfterType'],
|
|
|
+ [/"([^"]*)"/, 'attribute.value.html'],
|
|
|
+ [/'([^']*)'/, 'attribute.value.html'],
|
|
|
+ [/[\w\-]+/, 'attribute.name.html'],
|
|
|
+ [/=/, 'delimiter.html'],
|
|
|
+ [/>/, { token: 'delimiter.html', next: '@styleEmbedded', nextEmbedded: 'text/css' }],
|
|
|
+ [/[ \t\r\n]+/], // whitespace
|
|
|
+ [/(<\/)(style\s*)(>)/, ['delimiter.html', 'tag.html', { token: 'delimiter.html', next: '@pop' }]]
|
|
|
+ ],
|
|
|
+
|
|
|
+ // After <style ... type
|
|
|
+ styleAfterType: [
|
|
|
+ [/=/, 'delimiter.html', '@styleAfterTypeEquals'],
|
|
|
+ [/>/, { token: 'delimiter.html', next: '@styleEmbedded', nextEmbedded: 'text/css' }], // cover invalid e.g. <style type>
|
|
|
+ [/[ \t\r\n]+/], // whitespace
|
|
|
+ [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
|
|
|
+ ],
|
|
|
+
|
|
|
+ // After <style ... type =
|
|
|
+ styleAfterTypeEquals: [
|
|
|
+ [/"([^"]*)"/, { token: 'attribute.value.html', switchTo: '@styleWithCustomType.$1' }],
|
|
|
+ [/'([^']*)'/, { token: 'attribute.value.html', switchTo: '@styleWithCustomType.$1' }],
|
|
|
+ [/>/, { token: 'delimiter.html', next: '@styleEmbedded', nextEmbedded: 'text/css' }], // cover invalid e.g. <style type=>
|
|
|
+ [/[ \t\r\n]+/], // whitespace
|
|
|
+ [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
|
|
|
+ ],
|
|
|
+
|
|
|
+ // After <style ... type = $S2
|
|
|
+ styleWithCustomType: [
|
|
|
+ [/>/, { token: 'delimiter.html', next: '@styleEmbedded.$S2', nextEmbedded: '$S2' }],
|
|
|
+ [/"([^"]*)"/, 'attribute.value.html'],
|
|
|
+ [/'([^']*)'/, 'attribute.value.html'],
|
|
|
+ [/[\w\-]+/, 'attribute.name.html'],
|
|
|
+ [/=/, 'delimiter.html'],
|
|
|
+ [/[ \t\r\n]+/], // whitespace
|
|
|
+ [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
|
|
|
+ ],
|
|
|
+
|
|
|
+ styleEmbedded: [
|
|
|
+ [/<\/style/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
|
|
|
+ [/[^<]+/, '']
|
|
|
+ ],
|
|
|
}
|
|
|
};
|