prism-ftl.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. (function (Prism) {
  2. // https://freemarker.apache.org/docs/dgui_template_exp.html
  3. // FTL expression with 4 levels of nesting supported
  4. var FTL_EXPR = /[^<()"']|\((?:<expr>)*\)|<(?!#--)|<#--(?:[^-]|-(?!->))*-->|"(?:[^\\"]|\\.)*"|'(?:[^\\']|\\.)*'/.source;
  5. for (var i = 0; i < 2; i++) {
  6. FTL_EXPR = FTL_EXPR.replace(/<expr>/g, function () { return FTL_EXPR; });
  7. }
  8. FTL_EXPR = FTL_EXPR.replace(/<expr>/g, /[^\s\S]/.source);
  9. var ftl = {
  10. 'comment': /<#--[\s\S]*?-->/,
  11. 'string': [
  12. {
  13. // raw string
  14. pattern: /\br("|')(?:(?!\1)[^\\]|\\.)*\1/,
  15. greedy: true
  16. },
  17. {
  18. pattern: RegExp(/("|')(?:(?!\1|\$\{)[^\\]|\\.|\$\{(?:<expr>)*?\})*\1/.source.replace(/<expr>/g, function () { return FTL_EXPR; })),
  19. greedy: true,
  20. inside: {
  21. 'interpolation': {
  22. pattern: RegExp(/((?:^|[^\\])(?:\\\\)*)\$\{(?:<expr>)*?\}/.source.replace(/<expr>/g, function () { return FTL_EXPR; })),
  23. lookbehind: true,
  24. inside: {
  25. 'interpolation-punctuation': {
  26. pattern: /^\$\{|\}$/,
  27. alias: 'punctuation'
  28. },
  29. rest: null
  30. }
  31. }
  32. }
  33. }
  34. ],
  35. 'keyword': /\b(?:as)\b/,
  36. 'boolean': /\b(?:true|false)\b/,
  37. 'builtin-function': {
  38. pattern: /((?:^|[^?])\?\s*)\w+/,
  39. lookbehind: true,
  40. alias: 'function'
  41. },
  42. 'function': /\w+(?=\s*\()/,
  43. 'number': /\d+(?:\.\d+)?/,
  44. 'operator': /\.\.[<*!]?|->|--|\+\+|&&|\|\||\?{1,2}|[-+*/%!=<>]=?|\b(?:gt|gte|lt|lte)\b/,
  45. 'punctuation': /[,;.:()[\]{}]/
  46. };
  47. ftl.string[1].inside.interpolation.inside.rest = ftl;
  48. Prism.languages.ftl = {
  49. 'ftl-comment': {
  50. // the pattern is shortened to be more efficient
  51. pattern: /^<#--[\s\S]*/,
  52. alias: 'comment'
  53. },
  54. 'ftl-directive': {
  55. pattern: /^<[\s\S]+>$/,
  56. inside: {
  57. 'directive': {
  58. pattern: /(^<\/?)[#@][a-z]\w*/i,
  59. lookbehind: true,
  60. alias: 'keyword'
  61. },
  62. 'punctuation': /^<\/?|\/?>$/,
  63. 'content': {
  64. pattern: /[\s\S]*\S[\s\S]*/,
  65. alias: 'ftl',
  66. inside: ftl
  67. }
  68. }
  69. },
  70. 'ftl-interpolation': {
  71. pattern: /^\$\{[\s\S]*\}$/,
  72. inside: {
  73. 'punctuation': /^\$\{|\}$/,
  74. 'content': {
  75. pattern: /[\s\S]*\S[\s\S]*/,
  76. alias: 'ftl',
  77. inside: ftl
  78. }
  79. }
  80. }
  81. };
  82. Prism.hooks.add('before-tokenize', function (env) {
  83. var pattern = RegExp(/<#--[\s\S]*?-->|<\/?[#@][a-zA-Z](?:<expr>)*?>|\$\{(?:<expr>)*?\}/.source.replace(/<expr>/g, function () { return FTL_EXPR; }), 'gi');
  84. Prism.languages['markup-templating'].buildPlaceholders(env, 'ftl', pattern);
  85. });
  86. Prism.hooks.add('after-tokenize', function (env) {
  87. Prism.languages['markup-templating'].tokenizePlaceholders(env, 'ftl');
  88. });
  89. }(Prism));