yaml.js (4411B)
1 /* 2 Language: YAML 3 Description: Yet Another Markdown Language 4 Author: Stefan Wienert <stwienert@gmail.com> 5 Contributors: Carl Baxter <carl@cbax.tech> 6 Requires: ruby.js 7 Website: https://yaml.org 8 Category: common, config 9 */ 10 function yaml(hljs) { 11 var LITERALS = 'true false yes no null'; 12 13 // YAML spec allows non-reserved URI characters in tags. 14 var URI_CHARACTERS = '[\\w#;/?:@&=+$,.~*\\\'()[\\]]+'; 15 16 // Define keys as starting with a word character 17 // ...containing word chars, spaces, colons, forward-slashes, hyphens and periods 18 // ...and ending with a colon followed immediately by a space, tab or newline. 19 // The YAML spec allows for much more than this, but this covers most use-cases. 20 var KEY = { 21 className: 'attr', 22 variants: [ 23 { begin: '\\w[\\w :\\/.-]*:(?=[ \t]|$)' }, 24 { begin: '"\\w[\\w :\\/.-]*":(?=[ \t]|$)' }, // double quoted keys 25 { begin: '\'\\w[\\w :\\/.-]*\':(?=[ \t]|$)' } // single quoted keys 26 ] 27 }; 28 29 var TEMPLATE_VARIABLES = { 30 className: 'template-variable', 31 variants: [ 32 { begin: '{{', end: '}}' }, // jinja templates Ansible 33 { begin: '%{', end: '}' } // Ruby i18n 34 ] 35 }; 36 var STRING = { 37 className: 'string', 38 relevance: 0, 39 variants: [ 40 { begin: /'/, end: /'/ }, 41 { begin: /"/, end: /"/ }, 42 { begin: /\S+/ } 43 ], 44 contains: [ 45 hljs.BACKSLASH_ESCAPE, 46 TEMPLATE_VARIABLES 47 ] 48 }; 49 50 // Strings inside of value containers (objects) can't contain braces, 51 // brackets, or commas 52 var CONTAINER_STRING = hljs.inherit(STRING, { 53 variants: [ 54 { begin: /'/, end: /'/ }, 55 { begin: /"/, end: /"/ }, 56 { begin: /[^\s,{}[\]]+/ } 57 ] 58 }); 59 60 var DATE_RE = '[0-9]{4}(-[0-9][0-9]){0,2}'; 61 var TIME_RE = '([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?'; 62 var FRACTION_RE = '(\\.[0-9]*)?'; 63 var ZONE_RE = '([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?'; 64 var TIMESTAMP = { 65 className: 'number', 66 begin: '\\b' + DATE_RE + TIME_RE + FRACTION_RE + ZONE_RE + '\\b' 67 }; 68 69 var VALUE_CONTAINER = { 70 end: ',', 71 endsWithParent: true, 72 excludeEnd: true, 73 contains: [], 74 keywords: LITERALS, 75 relevance: 0 76 }; 77 var OBJECT = { 78 begin: '{', 79 end: '}', 80 contains: [VALUE_CONTAINER], 81 illegal: '\\n', 82 relevance: 0 83 }; 84 var ARRAY = { 85 begin: '\\[', 86 end: '\\]', 87 contains: [VALUE_CONTAINER], 88 illegal: '\\n', 89 relevance: 0 90 }; 91 92 var MODES = [ 93 KEY, 94 { 95 className: 'meta', 96 begin: '^---\s*$', 97 relevance: 10 98 }, 99 { // multi line string 100 // Blocks start with a | or > followed by a newline 101 // 102 // Indentation of subsequent lines must be the same to 103 // be considered part of the block 104 className: 'string', 105 begin: '[\\|>]([0-9]?[+-])?[ ]*\\n( *)[\\S ]+\\n(\\2[\\S ]+\\n?)*' 106 }, 107 { // Ruby/Rails erb 108 begin: '<%[%=-]?', 109 end: '[%-]?%>', 110 subLanguage: 'ruby', 111 excludeBegin: true, 112 excludeEnd: true, 113 relevance: 0 114 }, 115 { // named tags 116 className: 'type', 117 begin: '!\\w+!' + URI_CHARACTERS 118 }, 119 // https://yaml.org/spec/1.2/spec.html#id2784064 120 { // verbatim tags 121 className: 'type', 122 begin: '!<' + URI_CHARACTERS + ">" 123 }, 124 { // primary tags 125 className: 'type', 126 begin: '!' + URI_CHARACTERS 127 }, 128 { // secondary tags 129 className: 'type', 130 begin: '!!' + URI_CHARACTERS 131 }, 132 { // fragment id &ref 133 className: 'meta', 134 begin: '&' + hljs.UNDERSCORE_IDENT_RE + '$' 135 }, 136 { // fragment reference *ref 137 className: 'meta', 138 begin: '\\*' + hljs.UNDERSCORE_IDENT_RE + '$' 139 }, 140 { // array listing 141 className: 'bullet', 142 // TODO: remove |$ hack when we have proper look-ahead support 143 begin: '\\-(?=[ ]|$)', 144 relevance: 0 145 }, 146 hljs.HASH_COMMENT_MODE, 147 { 148 beginKeywords: LITERALS, 149 keywords: { literal: LITERALS } 150 }, 151 TIMESTAMP, 152 // numbers are any valid C-style number that 153 // sit isolated from other words 154 { 155 className: 'number', 156 begin: hljs.C_NUMBER_RE + '\\b' 157 }, 158 OBJECT, 159 ARRAY, 160 STRING 161 ]; 162 163 var VALUE_MODES = [...MODES]; 164 VALUE_MODES.pop(); 165 VALUE_MODES.push(CONTAINER_STRING); 166 VALUE_CONTAINER.contains = VALUE_MODES; 167 168 return { 169 name: 'YAML', 170 case_insensitive: true, 171 aliases: ['yml', 'YAML'], 172 contains: MODES 173 }; 174 } 175 176 module.exports = yaml;