d056950 8 年之前
父节点
当前提交
f4d3d312db
共有 6 个文件被更改,包括 354 次插入1 次删除
  1. 2 1
      gulpfile.js
  2. 7 0
      src/monaco.contribution.ts
  3. 213 0
      src/yaml.ts
  4. 1 0
      test/all.js
  5. 129 0
      test/yaml.test.ts
  6. 2 0
      tsconfig.json

+ 2 - 1
gulpfile.js

@@ -73,7 +73,8 @@ gulp.task('release', ['clean-release','compile'], function() {
 			bundleOne('src/sql'),
 			bundleOne('src/swift'),
 			bundleOne('src/vb'),
-			bundleOne('src/xml')
+			bundleOne('src/xml'),
+			bundleOne('src/yaml')
 		)
 		.pipe(uglify({
 			preserveComments: 'some'

+ 7 - 0
src/monaco.contribution.ts

@@ -247,3 +247,10 @@ registerLanguage({
 	mimetypes: ['text/css'],
 	module: './css'
 });
+registerLanguage({
+	id: 'yaml',
+	extensions: ['.yaml', '.yml'],
+	aliases: ['YAML', 'yaml', 'YML', 'yml'],
+	mimetypes: ['application/x-yaml'],
+	module: './yaml'
+});

+ 213 - 0
src/yaml.ts

@@ -0,0 +1,213 @@
+import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
+import ILanguage = monaco.languages.IMonarchLanguage;
+
+export const conf: IRichLanguageConfiguration = {
+	comments: {
+		lineComment: '#'
+	},
+	brackets: [['{', '}'], ['[', ']']],
+	autoClosingPairs: [
+		{ open: '"', close: '"', notIn: ['string', 'comment'] },
+		{ open: '\'', close: '\'', notIn: ['string', 'comment'] },
+		{ open: '{', close: '}', notIn: ['string', 'comment'] },
+		{ open: '[', close: ']', notIn: ['string', 'comment'] }
+	]
+};
+
+export const language = <ILanguage> {
+	defaultToken: '',
+	ignoreCase: true,
+	tokenPostfix: '.yaml',
+
+	brackets: [
+		{ token: 'delimiter.bracket', open: '{', close: '}' },
+		{ token: 'delimiter.square', open: '[', close: ']' }
+	],
+
+	keywords: ['true', 'false', 'null', '~'],
+
+	// we include these common regular expressions
+	escapes: /\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,
+
+	// The main tokenizer for our languages
+	tokenizer: {
+		root: [
+			{include: '@whitespace'},
+			{include: '@comment'},
+
+			// Directive
+			[/%[^ ]+.*$/, 'meta.directive'],
+
+			// Document Markers
+			[/---/, 'operators.directivesEnd'],
+			[/\.{3}/, 'operators.documentEnd'],
+
+			// Block Structure Indicators
+			[/[-?:](?= )/, 'operators'],
+
+			{include: '@tagHandle'},
+			{include: '@flowCollections'},
+			{include: '@blockStyle'},
+
+			// Key of a Key:Value pair
+			[/(?:".*?"|'.*?'|.*?)(?=\s*: \S+)/, 'type', '@value'],
+			[/(".*?"|'.*?'|.*?)(\s*)(:)(\s*)/, ['type', 'white', 'operators', 'white']],
+
+			// string nodes
+			[/.+$/, 'string']
+		],
+
+		// Value of a Key:Value pair
+		value: [
+			{include: '@whitespace'},
+			{include: '@comment'},
+
+			// Key:Value separator
+			[/:(?= )/, 'operators'],
+
+			{include: '@flowCollections'},
+			{include: '@flowScalars'},
+			{include: '@blockStyle'},
+
+			[/[&*][^\[\]\{\}, ]+\s*$/, 'namespace', '@pop'], // Anchor copy to ensure it leaves the state with line-break
+			{include: '@anchor'},
+			{include: '@tagHandle'},
+
+			// Numbers, cannot reuse as these terminate with the end of the line and pop the state
+			[/\d{4}-\d\d-\d\d([Tt ]\d\d:\d\d:\d\d(\.\d+)?(( ?[+-]\d\d?(:\d\d)?)|Z)?)?$/, 'number.date', '@pop'],
+			[/\d*\.\d+([eE][\-+]?\d+)?$/,   'number.float', '@pop'],
+			[/0[xX][0-9a-fA-F]+[lL]?$/,     'number.hex', '@pop'],
+			[/0[bB][0-1]+[lL]?$/,           'number.binary', '@pop'],
+			[/(0[oO][0-7]+|0[0-7]+)[lL]?$/, 'number.octal', '@pop'],
+			[/-?.(inf|NaN)$/,               'number.other', '@pop'],
+			[/[+-]?(0|[1-9]\d*)[lL]?$/,     'number', '@pop'],
+
+			// Other value (keyword or string)
+			[/.+/, {cases: {'@keywords': { token: 'keyword', next: '@pop' },
+											'@default': { token: 'string', next: '@pop' }}}]
+		],
+
+		// Flow Collection: Flow Mapping
+		object: [
+			{include: '@whitespace'},
+			{include: '@comment'},
+
+			// Flow Mapping termination
+			[/\}/, '@brackets', '@pop'],
+
+			// Flow Mapping delimiter
+			[/,/, 'delimiter.comma'],
+
+			// Flow Mapping Key:Value delimiter
+			[/:(?= )/, 'operators'],
+
+			// Flow Mapping Key:Value key
+			[/(?:".*?"|'.*?'|[^,\{\[]+?)(?=: )/, 'type'],
+
+			// Start Flow Style
+			{include: '@flowCollections'},
+			{include: '@flowScalars'},
+
+			// Scalar Data types
+			{include: '@tagHandle'},
+			{include: '@anchor'},
+			{include: '@number'},
+
+			// Other value (keyword or string)
+			[/[^\},]+/, {cases: {'@keywords': 'keyword',
+													'@default': 'string'}}]
+		],
+
+		// Flow Collection: Flow Sequence
+		array: [
+			{include: '@whitespace'},
+			{include: '@comment'},
+
+			// Flow Sequence termination
+			[/\]/, '@brackets', '@pop'],
+
+			// Flow Sequence delimiter
+			[/,/, 'delimiter.comma'],
+
+			// Start Flow Style
+			{include: '@flowCollections'},
+			{include: '@flowScalars'},
+
+			// Scalar Data types
+			{include: '@tagHandle'},
+			{include: '@anchor'},
+			{include: '@number'},
+
+			// Other value (keyword or string)
+			[/[^\],]+/, {cases: {'@keywords': 'keyword',
+													'@default': 'string'}}]
+		],
+
+		// Flow Scalars (quoted strings)
+		string: [
+			[/[^\\"']+/, 'string'],
+			[/@escapes/, 'string.escape'],
+			[/\\./,      'string.escape.invalid'],
+			[/["']/,     { cases: { '$#==$S2' : { token: 'string', next: '@pop' },
+															'@default': 'string' }} ]
+		],
+
+		// First line of a Block Style
+		multiString: [
+			[/^( +).+$/, 'string', '@multiStringContinued.$1']
+		],
+
+		// Further lines of a Block Style
+		//   Workaround for indentation detection
+		multiStringContinued: [
+			[/^( *).+$/, {cases: {'$1==$S2': 'string',
+														'@default': {token: '@rematch', next: '@popall'}}}]
+		],
+
+		whitespace: [
+			[/[ \t\r\n]+/, 'white']
+		],
+
+		// Only line comments
+		comment: [
+			[/#.*$/, 'comment']
+		],
+
+		// Start Flow Collections
+		flowCollections: [
+			[/\[/, '@brackets', '@array'],
+			[/\{/, '@brackets', '@object']
+		],
+
+		// Start Flow Scalars (quoted strings)
+		flowScalars: [
+			[/"/,  'string', '@string."' ],
+			[/'/,  'string', '@string.\'' ]
+		],
+
+		// Start Block Scalar
+		blockStyle: [
+			[/[>|][0-9]*[+-]?$/, 'operators', '@multiString']
+		],
+
+		number: [
+			// Date format (does not test validity)
+			[/\d{4}-\d\d-\d\d([Tt ]\d\d:\d\d:\d\d(\.\d+)?(( ?[+-]\d\d?(:\d\d)?)|Z)?)?/, 'number.date'],
+
+			[/\d*\.\d+([eE][\-+]?\d+)?/,   'number.float'],
+			[/0[xX][0-9a-fA-F]+[lL]?/,     'number.hex'],
+			[/0[bB][0-1]+[lL]?/,           'number.binary'],
+			[/(0[oO][0-7]+|0[0-7]+)[lL]?/, 'number.octal'],
+			[/-?.(inf|NaN)/,               'number.other'],
+			[/[+-]?(0|[1-9]\d*)[lL]?/,     'number']
+		],
+
+		tagHandle: [
+			[/\![^ ]*/, 'tag']
+		],
+
+		anchor: [
+			[/[&*][^ ]+/, 'namespace']
+		]
+	}
+};

+ 1 - 0
test/all.js

@@ -48,6 +48,7 @@ requirejs([
 		'out/test/sql.test',
 		'out/test/vb.test',
 		'out/test/xml.test',
+		'out/test/yaml.test'
 	], function() {
 		run(); // We can launch the tests!
 	});

+ 129 - 0
test/yaml.test.ts

@@ -0,0 +1,129 @@
+import {testTokenization} from './testRunner';
+
+testTokenization('yaml', [
+	// YAML directive
+	[{
+		line: '%YAML 1.2',
+		tokens: [{
+			startIndex: 0,
+			type: 'meta.directive.yaml'
+		}]
+	}],
+
+	// Comments
+	[{
+		line: '#Comment',
+		tokens: [{
+			startIndex: 0,
+			type: 'comment.yaml'
+		}]
+	}],
+
+	// Document Marker - Directives End
+	[{
+		line: '---',
+		tokens: [{
+			startIndex: 0,
+			type: 'operators.directivesEnd.yaml'
+		}]
+	}],
+
+	// Document Marker - Document End
+	[{
+		line: '...',
+		tokens: [{
+			startIndex: 0,
+			type: 'operators.documentEnd.yaml'
+		}]
+	}],
+
+	// Tag Handle
+	[{
+		line: '!<tag:clarkevans.com,2002:invoice>',
+		tokens: [{
+			startIndex: 0,
+			type: 'tag.yaml'
+		}]
+	}],
+
+	// Key:Value
+	[{
+		line: 'key: value',
+		tokens: [{
+			startIndex: 0,
+			type: 'type.yaml'
+		}, {
+			startIndex: 3,
+			type: 'operators.yaml'
+		}, {
+			startIndex: 4,
+			type: 'white.yaml'
+		}, {
+			startIndex: 5,
+			type: 'string.yaml'
+		}]
+	}],
+
+	// Key:Value - Quoted Keys
+	[{
+		line: '":": value',
+		tokens: [{
+			startIndex: 0,
+			type: 'type.yaml'
+		}, {
+			startIndex: 3,
+			type: 'operators.yaml'
+		}, {
+			startIndex: 4,
+			type: 'white.yaml'
+		}, {
+			startIndex: 5,
+			type: 'string.yaml'
+		}]
+	}],
+
+	// Flow Sequence - Data types
+	[{
+		line: '[string,"double",\'single\',1,1.1,2002-04-28]',
+		tokens: [{
+			startIndex: 0,
+			type: 'delimiter.square.yaml'
+		}, {
+			startIndex: 1,
+			type: 'string.yaml'
+		}, {
+			startIndex: 7,
+			type: 'delimiter.comma.yaml'
+		}, {
+			startIndex: 8,
+			type: 'string.yaml'
+		}, {
+			startIndex: 16,
+			type: 'delimiter.comma.yaml'
+		}, {
+			startIndex: 17,
+			type: 'string.yaml'
+		}, {
+			startIndex: 25,
+			type: 'delimiter.comma.yaml'
+		}, {
+			startIndex: 26,
+			type: 'number.yaml'
+		}, {
+			startIndex: 27,
+			type: 'delimiter.comma.yaml'
+		}, {
+			startIndex: 28,
+			type: 'number.float.yaml'
+		}, {
+			startIndex: 31,
+			type: 'delimiter.comma.yaml'
+		}, {
+			startIndex: 32,
+			type: 'number.date.yaml'
+		}, {
+			startIndex: 42,
+			type: 'delimiter.square.yaml'
+		}]
+	}]
+]);

+ 2 - 0
tsconfig.json

@@ -40,6 +40,7 @@
     "src/swift.ts",
     "src/vb.ts",
     "src/xml.ts",
+    "test/yaml.ts",
     "test/assert.d.ts",
     "test/bat.test.ts",
     "test/coffee.test.ts",
@@ -68,6 +69,7 @@
     "test/testRunner.ts",
     "test/vb.test.ts",
     "test/xml.test.ts",
+    "test/yaml.test.ts",
     "node_modules/monaco-editor-core/monaco.d.ts"
   ]
 }