module.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import moment from 'moment';
  2. import { extract } from 'keyword-extractor';
  3. import { stripHTML } from 'hexo-util';
  4. var defaults = {
  5. pages: {
  6. raw: false,
  7. content: false,
  8. title: true,
  9. slug: true,
  10. date: true,
  11. updated: true,
  12. comments: true,
  13. path: true,
  14. link: true,
  15. permalink: true,
  16. excerpt: true,
  17. text: true,
  18. keywords: true,
  19. author: true
  20. },
  21. posts: {
  22. raw: false,
  23. content: false,
  24. title: true,
  25. slug: true,
  26. date: true,
  27. updated: true,
  28. comments: true,
  29. path: true,
  30. link: true,
  31. permalink: true,
  32. excerpt: true,
  33. text: true,
  34. categories: true,
  35. tags: true,
  36. keywords: true,
  37. author: true
  38. }
  39. };
  40. function ignoreSettings (cfg) {
  41. const ignore = cfg.ignore ? cfg.ignore : {};
  42. ignore.paths = ignore.paths ? ignore.paths.map(path => path.toLowerCase()) : [];
  43. ignore.tags = ignore.tags ? ignore.tags.map(tag => tag.replace('#', '').toLowerCase()) : [];
  44. return ignore
  45. }
  46. function isIgnored (content, settings) {
  47. if (content.hidden === false) { return false }
  48. if (content.password || content.hidden) { return true }
  49. const pathIgnored = settings.paths.find(path => content.path.includes(path));
  50. if (pathIgnored) { return true }
  51. const tags = content.tags ? content.tags.map(mapTags) : [];
  52. const tagIgnored = tags.filter(tag => settings.tags.includes(tag)).length;
  53. if (tagIgnored) { return true }
  54. return false
  55. }
  56. function mapTags (tag) {
  57. return typeof tag === 'object' ? tag.name.toLowerCase() : tag
  58. }
  59. function minify (str) {
  60. return stripHTML(str).trim().replace(/\s+/g, ' ')
  61. }
  62. function getProps (ref) {
  63. return Object.getOwnPropertyNames(ref).filter(item => ref[item])
  64. }
  65. function catags ({ name, slug, permalink }) {
  66. return { name, slug, permalink }
  67. }
  68. function getKeywords (str, language) {
  69. const keywords = extract(str, {
  70. language,
  71. remove_digits: true,
  72. return_changed_case: true,
  73. remove_duplicates: true
  74. });
  75. return keywords.join(' ')
  76. }
  77. function setContent (obj, item, ref, cfg) {
  78. switch (item) {
  79. case 'excerpt':
  80. obj.excerpt = minify(ref.excerpt);
  81. break
  82. case 'text':
  83. obj.text = minify(ref.content);
  84. break
  85. case 'keywords':
  86. if (cfg.keywords) {
  87. const excerpt = minify(ref.excerpt);
  88. obj.keywords = getKeywords(excerpt, cfg.keywords);
  89. }
  90. break
  91. case 'categories':
  92. obj.categories = ref.categories.map(catags);
  93. break
  94. case 'tags':
  95. obj.tags = ref.tags.map(catags);
  96. break
  97. case 'date':
  98. obj.date = cfg.dateFormat ? moment(ref.date).format(cfg.dateFormat) : ref.date;
  99. break
  100. case 'updated':
  101. obj.updated = cfg.dateFormat ? moment(ref.updated).format(cfg.dateFormat) : ref.updated;
  102. break
  103. default:
  104. obj[item] = ref[item];
  105. }
  106. return obj
  107. }
  108. function reduceContent (names, content, cfg) {
  109. return names.reduce((obj, item) => setContent(obj, item, content, cfg), {})
  110. }
  111. const { config } = hexo;
  112. const json = config.jsonContent || { meta: true };
  113. const pages = json.hasOwnProperty('pages') ? json.pages : defaults.pages;
  114. const posts = json.hasOwnProperty('posts') ? json.posts : defaults.posts;
  115. const ignore = ignoreSettings(json);
  116. let output = json.meta ? {
  117. meta: {
  118. title: config.title,
  119. subtitle: config.subtitle,
  120. description: config.description,
  121. author: config.author,
  122. url: config.url,
  123. root: config.root
  124. }
  125. } : {};
  126. hexo.extend.generator.register('json-content', site => {
  127. if (pages) {
  128. const pagesNames = getProps(pages);
  129. const pagesValid = site.pages.filter(page => !isIgnored(page, ignore));
  130. const pagesContent = pagesValid.map(page => reduceContent(pagesNames, page, json));
  131. if (posts || json.meta) {
  132. output.pages = pagesContent;
  133. } else {
  134. output = pagesContent;
  135. }
  136. }
  137. if (posts) {
  138. const postsNames = getProps(posts);
  139. const postsSorted = site.posts.sort('-date');
  140. const postsValid = postsSorted.filter(post => {
  141. const include = json.drafts || post.published;
  142. return include && !isIgnored(post, ignore)
  143. });
  144. const postsContent = postsValid.map(post => reduceContent(postsNames, post, json));
  145. if (pages || json.meta) {
  146. output.posts = postsContent;
  147. } else {
  148. output = postsContent;
  149. }
  150. }
  151. return {
  152. path: json.file || 'content.json',
  153. data: JSON.stringify(output)
  154. }
  155. });