index.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*!
  2. * koa-ejs - index.js
  3. * Copyright(c) 2014 dead_horse <dead_horse@qq.com>
  4. * MIT Licensed
  5. */
  6. 'use strict';
  7. /**
  8. * Module dependencies.
  9. */
  10. var copy = require('copy-to');
  11. var path = require('path');
  12. var fs = require('co-fs');
  13. var ejs = require('ejs');
  14. /**
  15. * default render options
  16. * @type {Object}
  17. */
  18. var defaultSettings = {
  19. cache: true,
  20. layout: 'layout',
  21. viewExt: 'html',
  22. locals: {},
  23. debug: false,
  24. writeResp: true
  25. };
  26. /**
  27. * set app.context.render
  28. *
  29. * usage:
  30. * ```
  31. * yield *this.render('user', {name: 'dead_horse'});
  32. * ```
  33. * @param {Application} app koa application instance
  34. * @param {Object} settings user settings
  35. */
  36. exports = module.exports = function (app, settings) {
  37. if (app.context.render) {
  38. return;
  39. }
  40. if (!settings || !settings.root) {
  41. throw new Error('settings.root required');
  42. }
  43. settings.root = path.resolve(process.cwd(), settings.root);
  44. /**
  45. * cache the generate package
  46. * @type {Object}
  47. */
  48. var cache = Object.create(null);
  49. copy(defaultSettings).to(settings);
  50. settings.viewExt = settings.viewExt
  51. ? '.' + settings.viewExt.replace(/^\./, '')
  52. : '';
  53. /**
  54. * generate html with view name and options
  55. * @param {String} view
  56. * @param {Object} options
  57. * @return {String} html
  58. */
  59. function *render(view, options) {
  60. view += settings.viewExt;
  61. var viewPath = path.join(settings.root, view);
  62. // get from cache
  63. if (settings.cache && cache[viewPath]) {
  64. return cache[viewPath].call(options.scope, options);
  65. }
  66. var tpl = yield fs.readFile(viewPath, 'utf8');
  67. var fn = ejs.compile(tpl, {
  68. filename: viewPath,
  69. _with: settings._with,
  70. compileDebug: settings.debug,
  71. delimiter: settings.delimiter
  72. });
  73. if (settings.cache) {
  74. cache[viewPath] = fn;
  75. }
  76. return fn.call(options.scope, options);
  77. }
  78. app.context.render = function *(view, _context) {
  79. var context = {};
  80. merge(context, this.state);
  81. merge(context, _context);
  82. var html = yield *render(view, context);
  83. var layout = context.layout === false ? false : (context.layout || settings.layout);
  84. if (layout) {
  85. // if using layout
  86. context.body = html;
  87. html = yield *render(layout, context);
  88. }
  89. var writeResp = context.writeResp === false ? false : (context.writeResp || settings.writeResp);
  90. if (writeResp) {
  91. //normal operation
  92. this.type = 'html';
  93. this.body = html;
  94. }else{
  95. //only return the html
  96. return html;
  97. }
  98. };
  99. };
  100. /**
  101. * Expose ejs
  102. */
  103. exports.ejs = ejs;
  104. /**
  105. * merge source to target
  106. *
  107. * @param {Object} target
  108. * @param {Object} source
  109. * @return {Object}
  110. * @api private
  111. */
  112. function merge(target, source) {
  113. for (var key in source) {
  114. target[key] = source[key];
  115. }
  116. }