yaml.js 4.9 KB

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