main.js 4.5 KB

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