Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(yaml) Add support for inline sequences and mappings #2513

Merged
merged 8 commits into from
Apr 30, 2020
169 changes: 102 additions & 67 deletions src/languages/yaml.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ export default function(hljs) {
]
};

// Strings inside objects can't start with { or } or [ or ] or ,
// and can't end with } or ] or ,
var INSIDE_OBJECT_STRING = {
className: 'string',
relevance: 0,
variants: [
{begin: /'/, end: /'/},
{begin: /"/, end: /"/},
{begin: /[^\s,{}[\]](\S*[^\s,\]}])?/}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would a simple repeated negation not work:

[^\s,{}[\]]+

That's the simplest thing I came up with playing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was attempting to still allow these characters in strings, just not as the first or last character.

Copy link
Member

@joshgoebel joshgoebel Apr 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my testing in Ruby at least that is not allowed (I got a hard error). So I'd first confirm that's actually allowed before we spend any effort on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you're right, its the same way in Python. I guess I shouldn't have assumed. I'll use the repeated negation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never assume with YAML. :-) Although it's a good rule in other context also. :-)

],
contains: [
hljs.BACKSLASH_ESCAPE,
TEMPLATE_VARIABLES
]
};

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]*)?';
Expand All @@ -56,76 +72,95 @@ export default function(hljs) {
begin: '\\b' + DATE_RE + TIME_RE + FRACTION_RE + ZONE_RE + '\\b',
}

var TYPES = [
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'
},
];
var VALUE_CONTAINER = {
end: ',', excludeEnd: true,
contains: TYPES.concat([INSIDE_OBJECT_STRING]),
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
};
TYPES.push(OBJECT, ARRAY);
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: TYPES.concat([STRING]),
};
}
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