nunjucks.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. 'use strict';
  2. const nunjucks = require('nunjucks');
  3. const { readFileSync } = require('hexo-fs');
  4. const { dirname } = require('path');
  5. function toArray(value) {
  6. if (Array.isArray(value)) {
  7. // Return if given value is an Array
  8. return value;
  9. } else if (typeof value.toArray === 'function') {
  10. return value.toArray();
  11. } else if (value instanceof Map) {
  12. const arr = [];
  13. value.forEach(v => arr.push(v));
  14. return arr;
  15. } else if (value instanceof Set || typeof value === 'string') {
  16. return [...value];
  17. } else if (typeof value === 'object' && value instanceof Object && Boolean(value)) {
  18. return Object.values(value);
  19. }
  20. return [];
  21. }
  22. function safeJsonStringify(json, spacer = undefined) {
  23. if (typeof json !== 'undefined' && json !== null) {
  24. return JSON.stringify(json, null, spacer);
  25. }
  26. return '""';
  27. }
  28. const nunjucksCfg = {
  29. autoescape: false,
  30. throwOnUndefined: false,
  31. trimBlocks: false,
  32. lstripBlocks: false
  33. };
  34. const nunjucksAddFilter = env => {
  35. env.addFilter('toarray', toArray);
  36. env.addFilter('safedump', safeJsonStringify);
  37. };
  38. function njkCompile(data) {
  39. let env;
  40. if (data.path) {
  41. env = nunjucks.configure(dirname(data.path), nunjucksCfg);
  42. } else {
  43. env = nunjucks.configure(nunjucksCfg);
  44. }
  45. nunjucksAddFilter(env);
  46. const text = 'text' in data ? data.text : readFileSync(data.path);
  47. return nunjucks.compile(text, env, data.path);
  48. }
  49. function njkRenderer(data, locals) {
  50. return njkCompile(data).render(locals);
  51. }
  52. njkRenderer.compile = data => {
  53. // Need a closure to keep the compiled template.
  54. return locals => njkCompile(data).render(locals);
  55. };
  56. module.exports = njkRenderer;