prism-cooklang.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. (function (Prism) {
  2. // see https://github.com/cooklang/spec/blob/main/EBNF.md
  3. var single_token_suffix = /(?:(?!\s)[\d$+<=a-zA-Z\x80-\uFFFF])+/.source;
  4. var multi_token_infix = /[^{}@#]+/.source;
  5. var multi_token_suffix = /\{[^}#@]*\}/.source;
  6. var multi_token = multi_token_infix + multi_token_suffix;
  7. var timer_units = /(?:h|hours|hrs|m|min|minutes)/.source;
  8. var amount_group_impl = {
  9. pattern: /\{[^{}]*\}/,
  10. inside: {
  11. 'amount': {
  12. pattern: /([\{|])[^{}|*%]+/,
  13. lookbehind: true,
  14. alias: 'number',
  15. },
  16. 'unit': {
  17. pattern: /(%)[^}]+/,
  18. lookbehind: true,
  19. alias: 'symbol',
  20. },
  21. 'servings-scaler': {
  22. pattern: /\*/,
  23. alias: 'operator',
  24. },
  25. 'servings-alternative-separator': {
  26. pattern: /\|/,
  27. alias: 'operator',
  28. },
  29. 'unit-separator': {
  30. pattern: /(?:%|(\*)%)/,
  31. lookbehind: true,
  32. alias: 'operator',
  33. },
  34. 'punctuation': /[{}]/,
  35. }
  36. };
  37. Prism.languages.cooklang = {
  38. 'comment': {
  39. // [- comment -]
  40. // -- comment
  41. pattern: /\[-[\s\S]*?-\]|--.*/,
  42. greedy: true,
  43. },
  44. 'meta': { // >> key: value
  45. pattern: />>.*:.*/,
  46. inside: {
  47. 'property': { // key:
  48. pattern: /(>>\s*)[^\s:](?:[^:]*[^\s:])?/,
  49. lookbehind: true,
  50. }
  51. }
  52. },
  53. 'cookware-group': { // #...{...}, #...
  54. pattern: new RegExp('#(?:'
  55. + multi_token
  56. + '|'
  57. + single_token_suffix
  58. + ')'
  59. ),
  60. inside: {
  61. 'cookware': {
  62. pattern: new RegExp('(^#)(?:'
  63. + multi_token_infix
  64. + ')'
  65. ),
  66. lookbehind: true,
  67. alias: 'variable',
  68. },
  69. 'cookware-keyword': {
  70. pattern: /^#/,
  71. alias: 'keyword',
  72. },
  73. 'quantity-group': {
  74. pattern: new RegExp(/\{[^{}@#]*\}/),
  75. inside: {
  76. 'quantity': {
  77. pattern: new RegExp(/(^\{)/.source + multi_token_infix),
  78. lookbehind: true,
  79. alias: 'number',
  80. },
  81. 'punctuation': /[{}]/,
  82. }
  83. }
  84. },
  85. },
  86. 'ingredient-group': { // @...{...}, @...
  87. pattern: new RegExp('@(?:'
  88. + multi_token
  89. + '|'
  90. + single_token_suffix
  91. + ')'),
  92. inside: {
  93. 'ingredient': {
  94. pattern: new RegExp('(^@)(?:'
  95. + multi_token_infix
  96. + ')'),
  97. lookbehind: true,
  98. alias: 'variable',
  99. },
  100. 'ingredient-keyword': {
  101. pattern: /^@/,
  102. alias: 'keyword',
  103. },
  104. 'amount-group': amount_group_impl,
  105. }
  106. },
  107. 'timer-group': { // ~timer{...}
  108. // eslint-disable-next-line regexp/sort-alternatives
  109. pattern: /~(?!\s)[^@#~{}]*\{[^{}]*\}/,
  110. inside: {
  111. 'timer': {
  112. pattern: /(^~)[^{]+/,
  113. lookbehind: true,
  114. alias: 'variable',
  115. },
  116. 'duration-group': { // {...}
  117. pattern: /\{[^{}]*\}/,
  118. inside: {
  119. 'punctuation': /[{}]/,
  120. 'unit': {
  121. pattern: new RegExp(/(%\s*)/.source + timer_units + /\b/.source),
  122. lookbehind: true,
  123. alias: 'symbol',
  124. },
  125. 'operator': /%/,
  126. 'duration': {
  127. pattern: /\d+/,
  128. alias: 'number',
  129. },
  130. }
  131. },
  132. 'timer-keyword': {
  133. pattern: /^~/,
  134. alias: 'keyword',
  135. },
  136. }
  137. }
  138. };
  139. }(Prism));