Bladeren bron

Merge pull request #12 from Hirse/feature/yaml

YAML colorization
Alexandru Dima 8 jaren geleden
bovenliggende
commit
27c7315d4b
6 gewijzigde bestanden met toevoegingen van 493 en 1 verwijderingen
  1. 2 1
      gulpfile.js
  2. 7 0
      src/monaco.contribution.ts
  3. 193 0
      src/yaml.ts
  4. 1 0
      test/all.js
  5. 288 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'
+});

+ 193 - 0
src/yaml.ts

@@ -0,0 +1,193 @@
+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> {
+	tokenPostfix: '.yaml',
+
+	brackets: [
+		{ token: 'delimiter.bracket', open: '{', close: '}' },
+		{ token: 'delimiter.square', open: '[', close: ']' }
+	],
+
+	keywords: ['true', 'True', 'TRUE', 'false', 'False', 'FALSE', 'null', 'Null', 'Null', '~'],
+
+	numberInteger: /(?:0|[+-]?[0-9]+)/,
+	numberFloat: /(?:0|[+-]?[0-9]+)(?:\.[0-9]+)?(?:e[-+][1-9][0-9]*)?/,
+	numberOctal: /0o[0-7]+/,
+	numberHex: /0x[0-9a-fA-F]+/,
+	numberInfinity: /[+-]?\.(?:inf|Inf|INF)/,
+	numberNaN: /\.(?:nan|Nan|NAN)/,
+	numberDate: /\d{4}-\d\d-\d\d([Tt ]\d\d:\d\d:\d\d(\.\d+)?(( ?[+-]\d\d?(:\d\d)?)|Z)?)?/,
+
+	escapes: /\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,
+
+	tokenizer: {
+		root: [
+			{include: '@whitespace'},
+			{include: '@comment'},
+
+			// Directive
+			[/%[^ ]+.*$/, 'meta.directive'],
+
+			// Document Markers
+			[/---/, 'operators.directivesEnd'],
+			[/\.{3}/, 'operators.documentEnd'],
+
+			// Block Structure Indicators
+			[/[-?:](?= )/, 'operators'],
+
+			{include: '@anchor'},
+			{include: '@tagHandle'},
+			{include: '@flowCollections'},
+			{include: '@blockStyle'},
+
+			// Numbers
+			[/@numberInteger(?![ \t]*\S+)/,  'number'],
+			[/@numberFloat(?![ \t]*\S+)/,    'number.float'],
+			[/@numberOctal(?![ \t]*\S+)/,    'number.octal'],
+			[/@numberHex(?![ \t]*\S+)/,      'number.hex'],
+			[/@numberInfinity(?![ \t]*\S+)/, 'number.infinity'],
+			[/@numberNaN(?![ \t]*\S+)/,      'number.nan'],
+			[/@numberDate(?![ \t]*\S+)/,     'number.date'],
+
+			// Key:Value pair
+			[/(".*?"|'.*?'|.*?)([ \t]*)(:)( |$)/, ['type', 'white', 'operators', 'white']],
+
+			{include: '@flowScalars'},
+
+			// String nodes
+			[/.+$/, {cases: {'@keywords': 'keyword', '@default': 'string'}}]
+		],
+
+		// 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: '@flowNumber'},
+
+			// 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: '@flowNumber'},
+
+			// 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']
+		],
+
+		// Numbers in Flow Collections (terminate with ,]})
+		flowNumber: [
+			[/@numberInteger(?=[ \t]*[,\]\}])/,  'number'],
+			[/@numberFloat(?=[ \t]*[,\]\}])/,    'number.float'],
+			[/@numberOctal(?=[ \t]*[,\]\}])/,    'number.octal'],
+			[/@numberHex(?=[ \t]*[,\]\}])/,      'number.hex'],
+			[/@numberInfinity(?=[ \t]*[,\]\}])/, 'number.infinity'],
+			[/@numberNaN(?=[ \t]*[,\]\}])/,      'number.nan'],
+			[/@numberDate(?=[ \t]*[,\]\}])/,     'number.date']
+		],
+
+		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!
 	});

+ 288 - 0
test/yaml.test.ts

@@ -0,0 +1,288 @@
+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:
+	[{
+		line: 'key:',
+		tokens: [{
+			startIndex: 0,
+			type: 'type.yaml'
+		}, {
+			startIndex: 3,
+			type: 'operators.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'
+		}]
+	}],
+
+	// Tag Handles
+	[{
+		line: '!!str string',
+		tokens: [{
+			startIndex: 0,
+			type: 'tag.yaml'
+		}, {
+			startIndex: 5,
+			type: 'white.yaml'
+		}, {
+			startIndex: 6,
+			type: 'string.yaml'
+		}]
+	}],
+
+	// Anchor
+	[{
+		line: 'anchor: &anchor',
+		tokens: [{
+			startIndex: 0,
+			type: 'type.yaml'
+		}, {
+			startIndex: 6,
+			type: 'operators.yaml'
+		}, {
+			startIndex: 7,
+			type: 'white.yaml'
+		}, {
+			startIndex: 8,
+			type: 'namespace.yaml'
+		}]
+	}],
+
+	// Alias
+	[{
+		line: 'alias: *alias',
+		tokens: [{
+			startIndex: 0,
+			type: 'type.yaml'
+		}, {
+			startIndex: 5,
+			type: 'operators.yaml'
+		}, {
+			startIndex: 6,
+			type: 'white.yaml'
+		}, {
+			startIndex: 7,
+			type: 'namespace.yaml'
+		}]
+	}],
+
+	// Block Scalar
+	[{
+		line: '>',
+		tokens: [{
+			startIndex: 0,
+			type: 'operators.yaml'
+		}]
+	}, {
+		line: '  String',
+		tokens: [{
+			startIndex: 0,
+			type: 'string.yaml'
+		}]
+	}],
+
+	// Block Structure
+	[{
+		line: '- one',
+		tokens: [{
+			startIndex: 0,
+			type: 'operators.yaml'
+		}, {
+			startIndex: 1,
+			type: 'white.yaml'
+		}, {
+			startIndex: 2,
+			type: 'string.yaml'
+		}]
+	}, {
+		line: '? two',
+		tokens: [{
+			startIndex: 0,
+			type: 'operators.yaml'
+		}, {
+			startIndex: 1,
+			type: 'white.yaml'
+		}, {
+			startIndex: 2,
+			type: 'string.yaml'
+		}]
+	}, {
+		line: ': three',
+		tokens: [{
+			startIndex: 0,
+			type: 'operators.yaml'
+		}, {
+			startIndex: 1,
+			type: 'white.yaml'
+		}, {
+			startIndex: 2,
+			type: 'string.yaml'
+		}]
+	}],
+
+	// Flow Mapping
+	[{
+		line: '{key: value, number: 123}',
+		tokens: [{
+			startIndex: 0,
+			type: 'delimiter.bracket.yaml'
+		}, {
+			startIndex: 1,
+			type: 'type.yaml'
+		}, {
+			startIndex: 4,
+			type: 'operators.yaml'
+		}, {
+			startIndex: 5,
+			type: 'white.yaml'
+		}, {
+			startIndex: 6,
+			type: 'string.yaml'
+		}, {
+			startIndex: 11,
+			type: 'delimiter.comma.yaml'
+		}, {
+			startIndex: 12,
+			type: 'white.yaml'
+		}, {
+			startIndex: 13,
+			type: 'type.yaml'
+		}, {
+			startIndex: 19,
+			type: 'operators.yaml'
+		}, {
+			startIndex: 20,
+			type: 'white.yaml'
+		}, {
+			startIndex: 21,
+			type: 'number.yaml'
+		}, {
+			startIndex: 24,
+			type: 'delimiter.bracket.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"
   ]
 }