hexo-component-inferno 4.0.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +159 -8
  3. package/asset/js/algolia.js +27 -10
  4. package/asset/js/insight.js +62 -44
  5. package/lib/core/migrate.js +23 -4
  6. package/lib/core/schema.js +31 -9
  7. package/lib/core/view.js +1 -1
  8. package/lib/hexo/filter/locals.js +5 -2
  9. package/lib/hexo/generator/category.js +8 -1
  10. package/lib/hexo/generator/insight.js +8 -15
  11. package/lib/hexo/generator/manifest.js +6 -0
  12. package/lib/hexo/helper/cdn.js +11 -3
  13. package/lib/hexo/tag/message.js +11 -1
  14. package/lib/hexo/tag/tabs.js +28 -5
  15. package/lib/schema/comment/artalk.json +37 -0
  16. package/lib/schema/comment/beaudar.json +62 -0
  17. package/lib/schema/comment/cusdis.json +34 -0
  18. package/lib/schema/comment/giscus.json +12 -1
  19. package/lib/schema/comment/gitment.json +1 -1
  20. package/lib/schema/comment/utterances.json +15 -1
  21. package/lib/schema/comment/valine.json +1 -1
  22. package/lib/schema/comment/waline.json +2 -2
  23. package/lib/schema/misc/open_graph.json +0 -1
  24. package/lib/schema/plugin/waline_pageview.json +14 -0
  25. package/lib/schema/share/addthis.json +1 -1
  26. package/lib/schema/widget/archives.json +28 -0
  27. package/lib/schema/widget/categories.json +32 -0
  28. package/lib/schema/widget/recent_posts.json +5 -0
  29. package/lib/schema/widget/subscribe_email.json +1 -1
  30. package/lib/schema/widget/tags.json +1 -1
  31. package/lib/util/appearance.js +40 -0
  32. package/lib/util/classname.js +1 -1
  33. package/lib/util/deprecate.js +28 -0
  34. package/lib/util/html.js +51 -0
  35. package/lib/util/i18n.js +24 -0
  36. package/lib/util/script.js +73 -5
  37. package/lib/view/comment/artalk.js +119 -0
  38. package/lib/view/comment/beaudar.js +134 -0
  39. package/lib/view/comment/changyan.js +2 -1
  40. package/lib/view/comment/cusdis.js +120 -0
  41. package/lib/view/comment/disqus.js +3 -1
  42. package/lib/view/comment/disqusjs.js +3 -2
  43. package/lib/view/comment/facebook.js +3 -1
  44. package/lib/view/comment/giscus.js +32 -21
  45. package/lib/view/comment/gitalk.js +4 -2
  46. package/lib/view/comment/gitment.js +7 -2
  47. package/lib/view/comment/isso.js +5 -1
  48. package/lib/view/comment/twikoo.js +5 -1
  49. package/lib/view/comment/utterances.js +26 -16
  50. package/lib/view/comment/valine.js +7 -1
  51. package/lib/view/comment/waline.js +31 -21
  52. package/lib/view/donate/afdian.js +1 -1
  53. package/lib/view/donate/alipay.js +1 -1
  54. package/lib/view/donate/buymeacoffee.js +1 -1
  55. package/lib/view/donate/patreon.js +1 -1
  56. package/lib/view/donate/wechat.js +1 -1
  57. package/lib/view/misc/meta.js +9 -3
  58. package/lib/view/misc/open_graph.js +12 -15
  59. package/lib/view/misc/structured_data.js +8 -9
  60. package/lib/view/misc/web_app.js +15 -6
  61. package/lib/view/plugin/baidu_analytics.js +3 -1
  62. package/lib/view/plugin/cookie_consent.js +3 -1
  63. package/lib/view/plugin/google_analytics.js +3 -1
  64. package/lib/view/plugin/hotjar.js +3 -1
  65. package/lib/view/plugin/matomo.js +3 -1
  66. package/lib/view/plugin/outdated_browser.js +1 -1
  67. package/lib/view/plugin/statcounter.js +3 -1
  68. package/lib/view/plugin/twitter_conversion_tracking.js +3 -1
  69. package/lib/view/plugin/waline_pageview.js +100 -0
  70. package/lib/view/search/algolia.js +3 -1
  71. package/lib/view/search/baidu.js +3 -1
  72. package/lib/view/search/google_cse.js +3 -1
  73. package/lib/view/search/insight.js +4 -2
  74. package/lib/view/share/addthis.js +4 -0
  75. package/lib/view/widget/archives.js +37 -9
  76. package/lib/view/widget/categories.js +41 -15
  77. package/lib/view/widget/links.js +1 -1
  78. package/lib/view/widget/subscribe_email.js +5 -0
  79. package/lib/view/widget/tags.js +18 -5
  80. package/package.json +4 -2
@@ -38,6 +38,12 @@ module.exports = function (hexo) {
38
38
  if (!manifest.start_url) {
39
39
  manifest.start_url = url_for('/index.html');
40
40
  }
41
+ if (Array.isArray(manifest.icons)) {
42
+ // Resolve the icons against the root of the site, like start_url
43
+ manifest.icons = manifest.icons.map(icon => icon && icon.src ? Object.assign({}, icon, {
44
+ src: url_for(icon.src)
45
+ }) : icon);
46
+ }
41
47
  return {
42
48
  path: '/manifest.json',
43
49
  data: JSON.stringify(manifest)
@@ -59,13 +59,18 @@ const UNPKG_FIXTURES = {
59
59
  * cdn('jquery', '3.3.1', 'dist/jquery.min.js');
60
60
  * // -> https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js
61
61
  *
62
+ * // Set providers.cdn_overrides, e.g., { jquery: 'unpkg' }, to use a different CDN provider or URL
63
+ * // template for some packages
64
+ * cdn('jquery', '3.3.1', 'dist/jquery.min.js');
65
+ * // -> https://unpkg.com/jquery@3.3.1/dist/jquery.min.js
66
+ *
62
67
  * // Use the function below to resolve the CDN URL web font files
63
68
  * fontcdn('Ubuntu:400,600|Source+Code+Pro', 'css');
64
69
  * // -> https://fonts.googleapis.com/css?family=Ubuntu:400,600|Source+Code+Pro
65
70
  *
66
71
  * // Use the function below to insert FontAwesome icon font CSS URL.
67
72
  * iconcdn();
68
- * // -> https://use.fontawesome.com/releases/v5.15.2/css/all.css
73
+ * // -> https://use.fontawesome.com/releases/v6.0.0/css/all.css
69
74
  */
70
75
  module.exports = function (hexo) {
71
76
  function applyFixture(fixture, _package, version, filename) {
@@ -80,9 +85,12 @@ module.exports = function (hexo) {
80
85
  return [_package, version, filename];
81
86
  }
82
87
  hexo.extend.helper.register('cdn', function (_package, version, filename) {
88
+ const providers = typeof this.config.providers === 'object' ? this.config.providers : {};
83
89
  const {
84
- cdn = 'jsdelivr'
85
- } = typeof this.config.providers === 'object' ? this.config.providers : {};
90
+ cdn_overrides: overrides
91
+ } = providers;
92
+ // A package can use a different provider or URL than the rest in providers.cdn_overrides
93
+ const cdn = typeof overrides === 'object' && overrides !== null && overrides[_package] ? overrides[_package] : providers.cdn || 'jsdelivr';
86
94
  let _cdn = cdn;
87
95
  if (_cdn in PROVIDERS.LIBRARY) {
88
96
  _cdn = PROVIDERS.LIBRARY[_cdn];
@@ -3,6 +3,16 @@
3
3
  * @module hexo/tag/message
4
4
  */
5
5
 
6
+ /**
7
+ * Split a tag option at its first colon, so that the value can contain colons, as in
8
+ * <code>'title:Step 1: Install'</code>.
9
+ * @private
10
+ */
11
+ function splitOption(option) {
12
+ const index = option.indexOf(':');
13
+ return index === -1 ? [option] : [option.slice(0, index), option.slice(index + 1)];
14
+ }
15
+
6
16
  /**
7
17
  * Register custom Hexo tag {% message %}.
8
18
  * <p>
@@ -53,7 +63,7 @@ module.exports = function (hexo) {
53
63
  let classes = '';
54
64
  let header = '';
55
65
  for (const option of options) {
56
- const [key, value] = option.split(':');
66
+ const [key, value] = splitOption(option);
57
67
  switch (key) {
58
68
  case 'size':
59
69
  classes += ` is-${value}`;
@@ -3,6 +3,16 @@
3
3
  * @module hexo/tag/tabs
4
4
  */
5
5
 
6
+ /**
7
+ * Split a tag option at its first colon, so that the value can contain colons, as in
8
+ * <code>'title:Step 1: Install'</code>.
9
+ * @private
10
+ */
11
+ function splitOption(option) {
12
+ const index = option.indexOf(':');
13
+ return index === -1 ? [option] : [option.slice(0, index), option.slice(index + 1)];
14
+ }
15
+
6
16
  /**
7
17
  * Register custom Hexo tag {% tabs %}.
8
18
  * <p>
@@ -151,10 +161,11 @@ module.exports = function (hexo) {
151
161
  }
152
162
  return options;
153
163
  }
164
+ let tabCount = 0;
154
165
  function processTag(options, content) {
155
166
  let classes = '';
156
167
  for (const option of options) {
157
- const [key, value] = option.split(':');
168
+ const [key, value] = splitOption(option);
158
169
  switch (key) {
159
170
  case 'align':
160
171
  classes += ` is-${value}`;
@@ -176,12 +187,14 @@ module.exports = function (hexo) {
176
187
  let contentElements = '';
177
188
  while ((match = pattern.exec(content)) !== null) {
178
189
  const [, tabOptions, tabContent] = match;
179
- let id = 'tab-' + Date.now() + (Math.random() * 1000 | 0);
190
+
191
+ // A counter, as random numbers in the same millisecond could be the same
192
+ let id = 'tab-' + Date.now() + '-' + tabCount++;
180
193
  let icon = '';
181
194
  let title = '';
182
195
  let active = false;
183
196
  for (const option of splitTabOptions(tabOptions)) {
184
- const [key, value] = option.split(':');
197
+ const [key, value] = splitOption(option);
185
198
  switch (key) {
186
199
  case 'id':
187
200
  id = value;
@@ -228,7 +241,12 @@ module.exports = function (hexo) {
228
241
  return;
229
242
  }
230
243
 
231
- const id = '#' + CSS.escape(location.hash.substring(1));
244
+ let hash = location.hash.substring(1);
245
+ try {
246
+ // Non-ASCII IDs are percent-encoded in the URL
247
+ hash = decodeURIComponent(hash);
248
+ } catch (e) {}
249
+ const id = '#' + CSS.escape(hash);
232
250
  const $tabMenu = document.querySelector(\`.tabs a[href="\${id}"]\`);
233
251
  if (!$tabMenu) {
234
252
  return;
@@ -248,7 +266,12 @@ module.exports = function (hexo) {
248
266
  $activeTab.classList.remove('is-hidden');
249
267
  }
250
268
  }
251
- switchTab();
269
+ // The script is in <head>, so wait for the tabs to switch to the tab in the URL
270
+ if (document.readyState === 'loading') {
271
+ document.addEventListener('DOMContentLoaded', switchTab);
272
+ } else {
273
+ switchTab();
274
+ }
252
275
  window.addEventListener('hashchange', switchTab, false);
253
276
  })();
254
277
  </script>`;
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "/comment/artalk.json",
4
+ "description": "Artalk comment plugin configurations\nhttps://artalk.js.org/guide/frontend/config.html",
5
+ "type": "object",
6
+ "properties": {
7
+ "type": {
8
+ "type": "string",
9
+ "const": "artalk"
10
+ },
11
+ "server": {
12
+ "type": "string",
13
+ "description": "URL of your Artalk server"
14
+ },
15
+ "site": {
16
+ "type": "string",
17
+ "description": "Name of the site on the Artalk server",
18
+ "nullable": true
19
+ },
20
+ "page_key": {
21
+ "type": "string",
22
+ "description": "Unique identifier of the page. Uses the path of the page if not set",
23
+ "nullable": true
24
+ },
25
+ "locale": {
26
+ "type": "string",
27
+ "description": "Language of Artalk, e.g., en, zh-CN, or auto",
28
+ "nullable": true
29
+ },
30
+ "dark_mode": {
31
+ "type": ["boolean", "string"],
32
+ "description": "Dark mode: true, false, or 'auto' to follow the system color scheme. Follows the appearance of the theme (the data-appearance attribute of <html>) if not set",
33
+ "nullable": true
34
+ }
35
+ },
36
+ "required": ["type", "server"]
37
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "/comment/beaudar.json",
4
+ "description": "Beaudar comment plugin configurations\nhttps://github.com/beaudar/beaudar",
5
+ "type": "object",
6
+ "properties": {
7
+ "type": {
8
+ "type": "string",
9
+ "const": "beaudar"
10
+ },
11
+ "repo": {
12
+ "type": "string",
13
+ "description": "Name of the GitHub repository for the comments, e.g., user/repo"
14
+ },
15
+ "branch": {
16
+ "type": "string",
17
+ "description": "Branch of the repository that has beaudar.json",
18
+ "nullable": true
19
+ },
20
+ "label": {
21
+ "type": "string",
22
+ "description": "Label of the issues created by Beaudar",
23
+ "nullable": true
24
+ },
25
+ "theme": {
26
+ "type": "string",
27
+ "description": "Beaudar look and feel when the page looks light, e.g., github-light, github-dark, or preferred-color-scheme",
28
+ "default": "github-light",
29
+ "nullable": true
30
+ },
31
+ "dark_theme": {
32
+ "type": "string",
33
+ "description": "Beaudar look and feel when the page looks dark, e.g., with the dark or auto appearance of the theme. For example github-dark, github-dark-orange, classic-dark, dark-blue, icy-dark, or photon-dark",
34
+ "default": "github-dark",
35
+ "nullable": true
36
+ }
37
+ },
38
+ "required": ["type", "repo"],
39
+ "oneOf": [
40
+ {
41
+ "type": "object",
42
+ "properties": {
43
+ "issue_term": {
44
+ "type": "string",
45
+ "description": "The mapping between blog posts and GitHub issues, e.g., pathname, url, or title",
46
+ "default": "pathname"
47
+ }
48
+ },
49
+ "required": ["issue_term"]
50
+ },
51
+ {
52
+ "type": "object",
53
+ "properties": {
54
+ "issue_number": {
55
+ "type": "integer",
56
+ "description": "Configure Beaudar to load a specific issue by number"
57
+ }
58
+ },
59
+ "required": ["issue_number"]
60
+ }
61
+ ]
62
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "/comment/cusdis.json",
4
+ "description": "Cusdis comment plugin configurations\nhttps://cusdis.com/doc",
5
+ "type": "object",
6
+ "properties": {
7
+ "type": {
8
+ "type": "string",
9
+ "const": "cusdis"
10
+ },
11
+ "app_id": {
12
+ "type": "string",
13
+ "description": "App ID of the website in the embed code from the Cusdis dashboard"
14
+ },
15
+ "host": {
16
+ "type": "string",
17
+ "description": "URL of your Cusdis server if you host it yourself",
18
+ "default": "https://cusdis.com",
19
+ "nullable": true
20
+ },
21
+ "theme": {
22
+ "type": "string",
23
+ "description": "Theme of Cusdis: light, dark, or auto to follow the system color scheme. Follows the appearance of the theme (the data-appearance attribute of <html>) if not set",
24
+ "enum": ["light", "dark", "auto"],
25
+ "nullable": true
26
+ },
27
+ "lang": {
28
+ "type": "string",
29
+ "description": "Language of Cusdis, e.g., zh-cn, zh-tw, es, or fi. Uses English if not set",
30
+ "nullable": true
31
+ }
32
+ },
33
+ "required": ["type", "app_id"]
34
+ }
@@ -33,6 +33,11 @@
33
33
  "default": "pathname",
34
34
  "nullable": true
35
35
  },
36
+ "term": {
37
+ "type": ["string", "number"],
38
+ "description": "The search term of the discussion when mapping is specific, or the discussion number when mapping is number",
39
+ "nullable": true
40
+ },
36
41
  "strict": {
37
42
  "type": "boolean",
38
43
  "description": "Avoid mismatches due to GitHub's fuzzy searching method when there are multiple discussions with similar titles",
@@ -60,7 +65,7 @@
60
65
  },
61
66
  "theme": {
62
67
  "type": "string",
63
- "description": "Giscus look and feel",
68
+ "description": "Giscus look and feel when the page looks light",
64
69
  "enum": [
65
70
  "light",
66
71
  "light_high_contrast",
@@ -83,6 +88,12 @@
83
88
  "default": "noborder_light",
84
89
  "nullable": true
85
90
  },
91
+ "darkTheme": {
92
+ "type": "string",
93
+ "description": "Giscus look and feel when the page looks dark, e.g., with the dark or auto appearance of the theme. Not used when theme is custom",
94
+ "default": "noborder_dark",
95
+ "nullable": true
96
+ },
86
97
  "customThemeCss": {
87
98
  "type": "string",
88
99
  "description": "The url of custom Giscus theme css, only affect when theme is set to custom",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "/comment/gitment.json",
4
- "description": "Gitment comment plugin configurations",
4
+ "description": "Gitment comment plugin configurations\nDEPRECATED: Gitment is no longer maintained, and the GitHub sign-in proxy it uses no longer works. Use Giscus, Utterances or Gitalk instead.",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "type": {
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "theme": {
21
21
  "type": "string",
22
- "description": "Utterances look and feel",
22
+ "description": "Utterances look and feel when the page looks light",
23
23
  "enum": [
24
24
  "github-light",
25
25
  "github-dark",
@@ -30,6 +30,20 @@
30
30
  ],
31
31
  "default": "github-light",
32
32
  "nullable": true
33
+ },
34
+ "dark_theme": {
35
+ "type": "string",
36
+ "description": "Utterances look and feel when the page looks dark, e.g., with the dark or auto appearance of the theme",
37
+ "enum": [
38
+ "github-light",
39
+ "github-dark",
40
+ "github-dark-orange",
41
+ "icy-dark",
42
+ "dark-blue",
43
+ "photon-dark"
44
+ ],
45
+ "default": "github-dark",
46
+ "nullable": true
33
47
  }
34
48
  },
35
49
  "required": ["type", "repo"],
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "/comment/valine.json",
4
- "description": "Valine comment plugin configurations\nWARNING: Valine saves comments, including the commenters' email addresses, in a LeanCloud class that anyone with your public app ID and key can read. Consider Waline or another comment system instead.",
4
+ "description": "Valine comment plugin configurations\nDEPRECATED: LeanCloud, where Valine stores the comments, shuts down on January 12, 2027. Use Waline, Twikoo or another comment system instead.\nWARNING: Valine saves comments, including the commenters' email addresses, in a LeanCloud class that anyone with your public app ID and key can read. Consider Waline or another comment system instead.",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "type": {
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "path": {
16
16
  "type": "string",
17
- "description": "Article path id."
17
+ "description": "Article path id. A path, such as /posts/hello/, or a JavaScript expression, such as window.location.pathname, which is the default."
18
18
  },
19
19
  "lang": {
20
20
  "type": "string",
@@ -77,7 +77,7 @@
77
77
  },
78
78
  "dark": {
79
79
  "type": ["string", "boolean"],
80
- "description": "Darkmode support.",
80
+ "description": "Darkmode support. Can be true, false, 'auto' to follow the system color scheme, or a CSS selector that enables the dark mode when it matches an ancestor of Waline. Follows the appearance of the theme (the data-appearance attribute of <html>) if not set",
81
81
  "nullable": true
82
82
  },
83
83
  "meta": {
@@ -12,7 +12,6 @@
12
12
  "type": {
13
13
  "type": "string",
14
14
  "description": "Page type (og:type) (optional)\nYou should leave this blank for most of the time",
15
- "default": "blog",
16
15
  "nullable": true
17
16
  },
18
17
  "url": {
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "/plugin/waline_pageview.json",
4
+ "description": "Waline page view counter, true to use the server of the Waline comments. Do not also enable the pageview option of the Waline comments, which would count the views twice\nhttps://waline.js.org/en/guide/features/pageview.html",
5
+ "type": ["boolean", "object"],
6
+ "properties": {
7
+ "server_url": {
8
+ "type": "string",
9
+ "description": "URL of the Waline server. Uses the server of the Waline comments if not set",
10
+ "nullable": true
11
+ }
12
+ },
13
+ "default": false
14
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "/share/addthis.json",
4
- "description": "Enable AddThis share buttons\nhttps://www.addthis.com/",
4
+ "description": "Enable AddThis share buttons\nDEPRECATED: AddThis shut down on May 31, 2023. Use AddToAny or ShareThis instead.",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "type": {
@@ -7,6 +7,34 @@
7
7
  "type": {
8
8
  "type": "string",
9
9
  "const": "archives"
10
+ },
11
+ "amount": {
12
+ "type": "integer",
13
+ "description": "Amount of archives to show, with a link to the archive page for the rest. Will show all if not set",
14
+ "nullable": true
15
+ },
16
+ "group_by": {
17
+ "type": "string",
18
+ "enum": ["monthly", "yearly"],
19
+ "description": "Whether to group the archives by month or by year. Groups by month if not set",
20
+ "nullable": true
21
+ },
22
+ "order": {
23
+ "type": "integer",
24
+ "enum": [1, -1],
25
+ "description": "1 to show the oldest archives first, or -1 to show the newest first. Shows the newest first if not set",
26
+ "nullable": true
27
+ },
28
+ "format": {
29
+ "type": "string",
30
+ "description": "Moment.js format of the archive names, such as 'MMMM YYYY' (by month) or 'YYYY' (by year), which are used if not set",
31
+ "nullable": true
32
+ },
33
+ "show_count": {
34
+ "type": "boolean",
35
+ "default": true,
36
+ "description": "Whether to show the number of posts of each archive",
37
+ "nullable": true
10
38
  }
11
39
  },
12
40
  "required": ["type"]
@@ -7,6 +7,38 @@
7
7
  "type": {
8
8
  "type": "string",
9
9
  "const": "categories"
10
+ },
11
+ "amount": {
12
+ "type": "integer",
13
+ "description": "Amount of top-level categories to show, with a link to the category page for the rest. Will show all if not set",
14
+ "nullable": true
15
+ },
16
+ "order_by": {
17
+ "type": "string",
18
+ "description": "How to order the categories. For example 'name' to order by name, and 'length' to order by number of posts. Orders by name if not set",
19
+ "nullable": true
20
+ },
21
+ "order": {
22
+ "type": "integer",
23
+ "enum": [1, -1],
24
+ "description": "1 for ascending order, or -1 for descending order. Ascending if not set",
25
+ "nullable": true
26
+ },
27
+ "depth": {
28
+ "type": "integer",
29
+ "description": "Levels of categories to show, for example 1 for the top-level categories only. Shows all levels if not set or 0",
30
+ "nullable": true
31
+ },
32
+ "show_current": {
33
+ "type": "boolean",
34
+ "description": "Whether to highlight the categories of the current post",
35
+ "nullable": true
36
+ },
37
+ "show_count": {
38
+ "type": "boolean",
39
+ "default": true,
40
+ "description": "Whether to show the number of posts of each category",
41
+ "nullable": true
10
42
  }
11
43
  },
12
44
  "required": ["type"]
@@ -7,6 +7,11 @@
7
7
  "type": {
8
8
  "type": "string",
9
9
  "const": "recent_posts"
10
+ },
11
+ "limit": {
12
+ "type": "integer",
13
+ "description": "Number of recent posts to show. Shows 5 if not set",
14
+ "nullable": true
10
15
  }
11
16
  },
12
17
  "required": ["type"]
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "/widget/subscribe_email.json",
4
- "description": "Google FeedBurner email subscription widget configurations",
4
+ "description": "Google FeedBurner email subscription widget configurations\nDEPRECATED: Google FeedBurner stopped email subscriptions in July 2021. Use the follow.it widget instead.",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "type": {
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "amount": {
18
18
  "type": "integer",
19
- "description": "Amount of tags to show. Will show all if not set.",
19
+ "description": "Amount of tags to show, with a link to the tag page for the rest. Will show all if not set.",
20
20
  "nullable": true
21
21
  },
22
22
  "show_count": {
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Utility functions for inline scripts that follow the appearance of the page.
3
+ * @module util/appearance
4
+ */
5
+
6
+ /**
7
+ * Get a JavaScript expression that is true when the page looks dark.
8
+ * <p>
9
+ * A theme can set the appearance of a page with the <code>data-appearance</code> attribute of
10
+ * <code>&lt;html&gt;</code>: <code>dark</code> always looks dark, <code>auto</code> looks dark when
11
+ * the system prefers a dark color scheme, and any other value, or no attribute, looks light.
12
+ *
13
+ * @returns {string} The JavaScript expression.
14
+ *
15
+ * @example
16
+ * const js = `var theme = ${isDark()} ? 'dark' : 'light';`;
17
+ */
18
+ function isDark() {
19
+ return `(function (appearance) {
20
+ return appearance === 'dark' || (appearance === 'auto' && !!window.matchMedia &&
21
+ window.matchMedia('(prefers-color-scheme: dark)').matches);
22
+ })(document.documentElement.getAttribute('data-appearance'))`;
23
+ }
24
+
25
+ /**
26
+ * Get a JavaScript expression for the appearance of the page: <code>'dark'</code>,
27
+ * <code>'auto'</code>, or <code>'light'</code>.
28
+ *
29
+ * @returns {string} The JavaScript expression.
30
+ * @see module:util/appearance.isDark
31
+ */
32
+ function getAppearance() {
33
+ return `(function (appearance) {
34
+ return appearance === 'dark' || appearance === 'auto' ? appearance : 'light';
35
+ })(document.documentElement.getAttribute('data-appearance'))`;
36
+ }
37
+ module.exports = {
38
+ isDark,
39
+ getAppearance
40
+ };
@@ -19,7 +19,7 @@ module.exports = function (classname) {
19
19
  if (Array.isArray(classname)) {
20
20
  return classname.join(' ');
21
21
  }
22
- if (typeof classname === 'object') {
22
+ if (classname !== null && typeof classname === 'object') {
23
23
  return Object.keys(classname).filter(key => !!classname[key]).join(' ');
24
24
  }
25
25
  throw new Error('Cannot process class name ' + JSON.stringify(classname));
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Utility functions for warning about deprecated components.
3
+ * @module util/deprecate
4
+ */
5
+
6
+ const warned = new Set();
7
+
8
+ /**
9
+ * Print a warning about a deprecated component, once per component.
10
+ * <p>
11
+ * Components are rendered for every page, so the warning is only printed the first time.
12
+ *
13
+ * @param {string} name Name of the component, such as <code>share.addthis</code>.
14
+ * @param {string} message Why the component is deprecated, and what to use instead.
15
+ * @example
16
+ * deprecate('share.addthis', 'AddThis shut down on May 31, 2023. Use AddToAny or ShareThis instead.');
17
+ */
18
+ function deprecate(name, message) {
19
+ if (warned.has(name)) {
20
+ return;
21
+ }
22
+ warned.add(name);
23
+ // eslint-disable-next-line no-console
24
+ console.warn(`hexo-component-inferno: ${name} is deprecated. ${message}`);
25
+ }
26
+ module.exports = {
27
+ deprecate
28
+ };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Utility functions for HTML text.
3
+ * @module util/html
4
+ */
5
+ const {
6
+ stripHTML
7
+ } = require('hexo-util');
8
+ const ENTITIES = {
9
+ amp: '&',
10
+ lt: '<',
11
+ gt: '>',
12
+ quot: '"',
13
+ apos: "'",
14
+ nbsp: ' '
15
+ };
16
+
17
+ /**
18
+ * Decode the character references in HTML text, such as <code>&amp;amp;</code>,
19
+ * <code>&amp;#39;</code> and <code>&amp;#x1F600;</code>.
20
+ * <p>
21
+ * Numeric references and the named ones that Markdown renderers output are decoded. Other named
22
+ * references are kept as they are.
23
+ *
24
+ * @param {string} str HTML text.
25
+ * @returns {string} The text.
26
+ */
27
+ function decodeHTML(str) {
28
+ return str.replace(/&(#x[\da-f]+|#\d+|[a-z]+);/gi, (match, entity) => {
29
+ if (entity[0] === '#') {
30
+ const code = entity[1] === 'x' || entity[1] === 'X' ? parseInt(entity.slice(2), 16) : parseInt(entity.slice(1), 10);
31
+ return code <= 0x10ffff ? String.fromCodePoint(code) : match;
32
+ }
33
+ const char = ENTITIES[entity.toLowerCase()];
34
+ return char === undefined ? match : char;
35
+ });
36
+ }
37
+
38
+ /**
39
+ * Convert HTML to plain text on one line, for example to index or describe a page.
40
+ *
41
+ * @param {string} html HTML.
42
+ * @returns {string} The text, with the tags removed, the character references decoded, and the
43
+ * whitespace collapsed.
44
+ */
45
+ function toPlainText(html) {
46
+ return decodeHTML(stripHTML(html || '')).replace(/\s+/g, ' ').trim();
47
+ }
48
+ module.exports = {
49
+ decodeHTML,
50
+ toPlainText
51
+ };