Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 120 additions & 77 deletions src/languages/yaml.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function(hljs) {
var LITERALS = 'true false yes no null';

// YAML spec allows non-reserved URI characters in tags.
var URI_CHARACTERS = '[\\w#;/?:@&=+$,.~*\\\'()[\\]]+'
var URI_CHARACTERS = '[\\w#;/?:@&=+$,.~*\\\'()[\\]]+';

// Define keys as starting with a word character
// ...containing word chars, spaces, colons, forward-slashes, hyphens and periods
Expand All @@ -21,111 +21,154 @@ export default function(hljs) {
className: 'attr',
variants: [
{ begin: '\\w[\\w :\\/.-]*:(?=[ \t]|$)' },
{ begin: '"\\w[\\w :\\/.-]*":(?=[ \t]|$)' }, //double quoted keys
{ begin: '\'\\w[\\w :\\/.-]*\':(?=[ \t]|$)' } //single quoted keys
{ begin: '"\\w[\\w :\\/.-]*":(?=[ \t]|$)' }, // double quoted keys
{ begin: '\'\\w[\\w :\\/.-]*\':(?=[ \t]|$)' } // single quoted keys
]
};

var TEMPLATE_VARIABLES = {
className: 'template-variable',
variants: [
{ begin: '\{\{', end: '\}\}' }, // jinja templates Ansible
{ begin: '%\{', end: '\}' } // Ruby i18n
{ begin: '{{', end: '}}' }, // jinja templates Ansible
{ begin: '%{', end: '}' } // Ruby i18n
]
};
var STRING = {
className: 'string',
relevance: 0,
variants: [
{begin: /'/, end: /'/},
{begin: /"/, end: /"/},
{begin: /\S+/}
{ begin: /'/, end: /'/ },
{ begin: /"/, end: /"/ },
{ begin: /\S+/ }
],
contains: [
hljs.BACKSLASH_ESCAPE,
TEMPLATE_VARIABLES
]
};

// Strings inside of value containers (objects) can't contain braces,
// brackets, or commas
var CONTAINER_STRING = hljs.inherit(STRING, {
variants: [
{ begin: /'/, end: /'/ },
{ begin: /"/, end: /"/ },
{ begin: /[^\s,{}[\]]+/ }
]
});

var DATE_RE = '[0-9]{4}(-[0-9][0-9]){0,2}';
var TIME_RE = '([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?';
var FRACTION_RE = '(\\.[0-9]*)?';
var ZONE_RE = '([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?';
var TIMESTAMP = {
className: 'number',
begin: '\\b' + DATE_RE + TIME_RE + FRACTION_RE + ZONE_RE + '\\b',
}
begin: '\\b' + DATE_RE + TIME_RE + FRACTION_RE + ZONE_RE + '\\b'
};

var VALUE_CONTAINER = {
end: ',',
endsWithParent: true,
excludeEnd: true,
contains: [],
keywords: LITERALS,
relevance: 0
};
var OBJECT = {
begin: '{',
end: '}',
contains: [VALUE_CONTAINER],
illegal: '\\n',
relevance: 0
};
var ARRAY = {
begin: '\\[',
end: '\\]',
contains: [VALUE_CONTAINER],
illegal: '\\n',
relevance: 0
};

var MODES = [
KEY,
{
className: 'meta',
begin: '^---\s*$',
relevance: 10
},
{ // multi line string
// Blocks start with a | or > followed by a newline
//
// Indentation of subsequent lines must be the same to
// be considered part of the block
className: 'string',
begin: '[\\|>]([0-9]?[+-])?[ ]*\\n( *)[\\S ]+\\n(\\2[\\S ]+\\n?)*'
},
{ // Ruby/Rails erb
begin: '<%[%=-]?',
end: '[%-]?%>',
subLanguage: 'ruby',
excludeBegin: true,
excludeEnd: true,
relevance: 0
},
{ // named tags
className: 'type',
begin: '!\\w+!' + URI_CHARACTERS
},
// https://yaml.org/spec/1.2/spec.html#id2784064
{ // verbatim tags
className: 'type',
begin: '!<' + URI_CHARACTERS + ">"
},
{ // primary tags
className: 'type',
begin: '!' + URI_CHARACTERS
},
{ // secondary tags
className: 'type',
begin: '!!' + URI_CHARACTERS
},
{ // fragment id &ref
className: 'meta',
begin: '&' + hljs.UNDERSCORE_IDENT_RE + '$'
},
{ // fragment reference *ref
className: 'meta',
begin: '\\*' + hljs.UNDERSCORE_IDENT_RE + '$'
},
{ // array listing
className: 'bullet',
// TODO: remove |$ hack when we have proper look-ahead support
begin: '\\-(?=[ ]|$)',
relevance: 0
},
hljs.HASH_COMMENT_MODE,
{
beginKeywords: LITERALS,
keywords: { literal: LITERALS }
},
TIMESTAMP,
// numbers are any valid C-style number that
// sit isolated from other words
{
className: 'number',
begin: hljs.C_NUMBER_RE + '\\b'
},
OBJECT,
ARRAY,
STRING
];

var VALUE_MODES = [...MODES];
VALUE_MODES.pop();
VALUE_MODES.push(CONTAINER_STRING);
VALUE_CONTAINER.contains = VALUE_MODES;

return {
name: 'YAML',
case_insensitive: true,
aliases: ['yml', 'YAML'],
contains: [
KEY,
{
className: 'meta',
begin: '^---\s*$',
relevance: 10
},
{ // multi line string
// Blocks start with a | or > followed by a newline
//
// Indentation of subsequent lines must be the same to
// be considered part of the block
className: 'string',
begin: '[\\|>]([0-9]?[+-])?[ ]*\\n( *)[\\S ]+\\n(\\2[\\S ]+\\n?)*',
},
{ // Ruby/Rails erb
begin: '<%[%=-]?', end: '[%-]?%>',
subLanguage: 'ruby',
excludeBegin: true,
excludeEnd: true,
relevance: 0
},
{ // named tags
className: 'type',
begin: '!\\w+!' + URI_CHARACTERS,
},
// https://yaml.org/spec/1.2/spec.html#id2784064
{ // verbatim tags
className: 'type',
begin: '!<' + URI_CHARACTERS + ">",
},
{ // primary tags
className: 'type',
begin: '!' + URI_CHARACTERS,
},
{ // secondary tags
className: 'type',
begin: '!!' + URI_CHARACTERS,
},
{ // fragment id &ref
className: 'meta',
begin: '&' + hljs.UNDERSCORE_IDENT_RE + '$',
},
{ // fragment reference *ref
className: 'meta',
begin: '\\*' + hljs.UNDERSCORE_IDENT_RE + '$'
},
{ // array listing
className: 'bullet',
// TODO: remove |$ hack when we have proper look-ahead support
begin: '\\-(?=[ ]|$)',
relevance: 0
},
hljs.HASH_COMMENT_MODE,
{
beginKeywords: LITERALS,
keywords: {literal: LITERALS}
},
TIMESTAMP,
// numbers are any valid C-style number that
// sit isolated from other words
{
className: 'number',
begin: hljs.C_NUMBER_RE + '\\b'
},
STRING
]
contains: MODES
};
}
3 changes: 3 additions & 0 deletions test/markup/yaml/inline.expect.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<span class="hljs-attr">foo:</span> [<span class="hljs-string">bar</span>, <span class="hljs-string">bar2</span>, [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], <span class="hljs-number">3</span>]
<span class="hljs-attr">foo:</span> {<span class="hljs-attr">bar:</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], <span class="hljs-attr">baz:</span> {<span class="hljs-attr">inside:</span> <span class="hljs-number">3</span>}}
<span class="hljs-attr">foo:</span> <span class="hljs-string">ba{}r,ba[]z</span>
3 changes: 3 additions & 0 deletions test/markup/yaml/inline.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
foo: [bar, bar2, [1, 2], 3]
foo: {bar: [1, 2], baz: {inside: 3}}
foo: ba{}r,ba[]z