yaml.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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
  22. { begin: /\w[\w :()\./-]*:(?=[ \t]|$)/ },
  23. { // double quoted keys - with brackets
  24. begin: /"\w[\w :()\./-]*":(?=[ \t]|$)/ },
  25. { // single quoted keys - with brackets
  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 STRING = {
  43. className: 'string',
  44. relevance: 0,
  45. variants: [
  46. {
  47. begin: /'/,
  48. end: /'/
  49. },
  50. {
  51. begin: /"/,
  52. end: /"/
  53. },
  54. { begin: /\S+/ }
  55. ],
  56. contains: [
  57. hljs.BACKSLASH_ESCAPE,
  58. TEMPLATE_VARIABLES
  59. ]
  60. };
  61. // Strings inside of value containers (objects) can't contain braces,
  62. // brackets, or commas
  63. const CONTAINER_STRING = hljs.inherit(STRING, { variants: [
  64. {
  65. begin: /'/,
  66. end: /'/
  67. },
  68. {
  69. begin: /"/,
  70. end: /"/
  71. },
  72. { begin: /[^\s,{}[\]]+/ }
  73. ] });
  74. const DATE_RE = '[0-9]{4}(-[0-9][0-9]){0,2}';
  75. const TIME_RE = '([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?';
  76. const FRACTION_RE = '(\\.[0-9]*)?';
  77. const ZONE_RE = '([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?';
  78. const TIMESTAMP = {
  79. className: 'number',
  80. begin: '\\b' + DATE_RE + TIME_RE + FRACTION_RE + ZONE_RE + '\\b'
  81. };
  82. const VALUE_CONTAINER = {
  83. end: ',',
  84. endsWithParent: true,
  85. excludeEnd: true,
  86. keywords: LITERALS,
  87. relevance: 0
  88. };
  89. const OBJECT = {
  90. begin: /\{/,
  91. end: /\}/,
  92. contains: [ VALUE_CONTAINER ],
  93. illegal: '\\n',
  94. relevance: 0
  95. };
  96. const ARRAY = {
  97. begin: '\\[',
  98. end: '\\]',
  99. contains: [ VALUE_CONTAINER ],
  100. illegal: '\\n',
  101. relevance: 0
  102. };
  103. const MODES = [
  104. KEY,
  105. {
  106. className: 'meta',
  107. begin: '^---\\s*$',
  108. relevance: 10
  109. },
  110. { // multi line string
  111. // Blocks start with a | or > followed by a newline
  112. //
  113. // Indentation of subsequent lines must be the same to
  114. // be considered part of the block
  115. className: 'string',
  116. begin: '[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*'
  117. },
  118. { // Ruby/Rails erb
  119. begin: '<%[%=-]?',
  120. end: '[%-]?%>',
  121. subLanguage: 'ruby',
  122. excludeBegin: true,
  123. excludeEnd: true,
  124. relevance: 0
  125. },
  126. { // named tags
  127. className: 'type',
  128. begin: '!\\w+!' + URI_CHARACTERS
  129. },
  130. // https://yaml.org/spec/1.2/spec.html#id2784064
  131. { // verbatim tags
  132. className: 'type',
  133. begin: '!<' + URI_CHARACTERS + ">"
  134. },
  135. { // primary tags
  136. className: 'type',
  137. begin: '!' + URI_CHARACTERS
  138. },
  139. { // secondary tags
  140. className: 'type',
  141. begin: '!!' + URI_CHARACTERS
  142. },
  143. { // fragment id &ref
  144. className: 'meta',
  145. begin: '&' + hljs.UNDERSCORE_IDENT_RE + '$'
  146. },
  147. { // fragment reference *ref
  148. className: 'meta',
  149. begin: '\\*' + hljs.UNDERSCORE_IDENT_RE + '$'
  150. },
  151. { // array listing
  152. className: 'bullet',
  153. // TODO: remove |$ hack when we have proper look-ahead support
  154. begin: '-(?=[ ]|$)',
  155. relevance: 0
  156. },
  157. hljs.HASH_COMMENT_MODE,
  158. {
  159. beginKeywords: LITERALS,
  160. keywords: { literal: LITERALS }
  161. },
  162. TIMESTAMP,
  163. // numbers are any valid C-style number that
  164. // sit isolated from other words
  165. {
  166. className: 'number',
  167. begin: hljs.C_NUMBER_RE + '\\b',
  168. relevance: 0
  169. },
  170. OBJECT,
  171. ARRAY,
  172. STRING
  173. ];
  174. const VALUE_MODES = [ ...MODES ];
  175. VALUE_MODES.pop();
  176. VALUE_MODES.push(CONTAINER_STRING);
  177. VALUE_CONTAINER.contains = VALUE_MODES;
  178. return {
  179. name: 'YAML',
  180. case_insensitive: true,
  181. aliases: [ 'yml' ],
  182. contains: MODES
  183. };
  184. }
  185. export { yaml as default };