asset.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. 'use strict';
  2. const common = require('./common');
  3. const Promise = require('bluebird');
  4. const yfm = require('hexo-front-matter');
  5. const pathFn = require('path');
  6. const util = require('hexo-util');
  7. const Pattern = util.Pattern;
  8. module.exports = ctx => {
  9. function processPage(file) {
  10. const Page = ctx.model('Page');
  11. const path = file.path;
  12. const doc = Page.findOne({source: path});
  13. const config = ctx.config;
  14. const timezone = config.timezone;
  15. if (file.type === 'skip' && doc) {
  16. return;
  17. }
  18. if (file.type === 'delete') {
  19. if (doc) {
  20. return doc.remove();
  21. }
  22. return;
  23. }
  24. return Promise.all([
  25. file.stat(),
  26. file.read()
  27. ]).spread((stats, content) => {
  28. const data = yfm(content);
  29. const output = ctx.render.getOutput(path);
  30. data.source = path;
  31. data.raw = content;
  32. data.date = common.toDate(data.date);
  33. if (data.date) {
  34. if (timezone) data.date = common.timezone(data.date, timezone);
  35. } else {
  36. data.date = stats.ctime;
  37. }
  38. data.updated = common.toDate(data.updated);
  39. if (data.updated) {
  40. if (timezone) data.updated = common.timezone(data.updated, timezone);
  41. } else {
  42. data.updated = stats.mtime;
  43. }
  44. if (data.permalink) {
  45. data.path = data.permalink;
  46. delete data.permalink;
  47. if (data.path[data.path.length - 1] === '/') {
  48. data.path += 'index';
  49. }
  50. if (!pathFn.extname(data.path)) {
  51. data.path += `.${output}`;
  52. }
  53. } else {
  54. const extname = pathFn.extname(path);
  55. data.path = `${path.substring(0, path.length - extname.length)}.${output}`;
  56. }
  57. if (!data.layout && output !== 'html' && output !== 'htm') {
  58. data.layout = false;
  59. }
  60. // FIXME: Data may be inserted when reading files. Load it again to prevent
  61. // race condition. We have to solve this in warehouse.
  62. const doc = Page.findOne({source: path});
  63. if (doc) {
  64. return doc.replace(data);
  65. }
  66. return Page.insert(data);
  67. });
  68. }
  69. function processAsset(file) {
  70. const id = file.source.substring(ctx.base_dir.length).replace(/\\/g, '/');
  71. const Asset = ctx.model('Asset');
  72. const doc = Asset.findById(id);
  73. if (file.type === 'delete') {
  74. if (doc) {
  75. return doc.remove();
  76. }
  77. return;
  78. }
  79. return Asset.save({
  80. _id: id,
  81. path: file.path,
  82. modified: file.type !== 'skip',
  83. renderable: file.params.renderable
  84. });
  85. }
  86. return {
  87. pattern: new Pattern(path => {
  88. if (common.isTmpFile(path) || common.isMatch(path, ctx.config.exclude)) return;
  89. if (common.isHiddenFile(path) && !common.isMatch(path, ctx.config.include)) {
  90. return;
  91. }
  92. return {
  93. renderable: ctx.render.isRenderable(path) && !common.isMatch(path, ctx.config.skip_render)
  94. };
  95. }),
  96. process: function assetProcessor(file) {
  97. if (file.params.renderable) {
  98. return processPage(file);
  99. }
  100. return processAsset(file);
  101. }
  102. };
  103. };