list_archives.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. 'use strict';
  2. const { toMomentLocale } = require('./date');
  3. const { url_for } = require('hexo-util');
  4. function listArchivesHelper(options = {}) {
  5. const { config } = this;
  6. const archiveDir = config.archive_dir;
  7. const { timezone } = config;
  8. const lang = toMomentLocale(this.page.lang || this.page.language || config.language);
  9. let { format } = options;
  10. const type = options.type || 'monthly';
  11. const { style = 'list', transform, separator = ', ' } = options;
  12. const showCount = Object.prototype.hasOwnProperty.call(options, 'show_count') ? options.show_count : true;
  13. const className = options.class || 'archive';
  14. const order = options.order || -1;
  15. const compareFunc = type === 'monthly'
  16. ? (yearA, monthA, yearB, monthB) => yearA === yearB && monthA === monthB
  17. : (yearA, monthA, yearB, monthB) => yearA === yearB;
  18. let result = '';
  19. if (!format) {
  20. format = type === 'monthly' ? 'MMMM YYYY' : 'YYYY';
  21. }
  22. const posts = this.site.posts.sort('date', order);
  23. if (!posts.length) return result;
  24. const data = [];
  25. let length = 0;
  26. posts.forEach(post => {
  27. // Clone the date object to avoid pollution
  28. let date = post.date.clone();
  29. if (timezone) date = date.tz(timezone);
  30. const year = date.year();
  31. const month = date.month() + 1;
  32. const lastData = data[length - 1];
  33. if (!lastData || !compareFunc(lastData.year, lastData.month, year, month)) {
  34. if (lang) date = date.locale(lang);
  35. const name = date.format(format);
  36. length = data.push({
  37. name,
  38. year,
  39. month,
  40. count: 1
  41. });
  42. } else {
  43. lastData.count++;
  44. }
  45. });
  46. const link = item => {
  47. let url = `${archiveDir}/${item.year}/`;
  48. if (type === 'monthly') {
  49. if (item.month < 10) url += '0';
  50. url += `${item.month}/`;
  51. }
  52. return url_for.call(this, url);
  53. };
  54. if (style === 'list') {
  55. result += `<ul class="${className}-list">`;
  56. for (let i = 0, len = data.length; i < len; i++) {
  57. const item = data[i];
  58. result += `<li class="${className}-list-item">`;
  59. result += `<a class="${className}-list-link" href="${link(item)}">`;
  60. result += transform ? transform(item.name) : item.name;
  61. result += '</a>';
  62. if (showCount) {
  63. result += `<span class="${className}-list-count">${item.count}</span>`;
  64. }
  65. result += '</li>';
  66. }
  67. result += '</ul>';
  68. } else {
  69. for (let i = 0, len = data.length; i < len; i++) {
  70. const item = data[i];
  71. if (i) result += separator;
  72. result += `<a class="${className}-link" href="${link(item)}">`;
  73. result += transform ? transform(item.name) : item.name;
  74. if (showCount) {
  75. result += `<span class="${className}-count">${item.count}</span>`;
  76. }
  77. result += '</a>';
  78. }
  79. }
  80. return result;
  81. }
  82. module.exports = listArchivesHelper;