feedscout 1.5.0 → 1.6.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 (193) hide show
  1. package/README.md +12 -17
  2. package/dist/blogrolls/defaults.cjs +1 -3
  3. package/dist/blogrolls/defaults.js +1 -2
  4. package/dist/blogrolls/extractors.cjs +6 -9
  5. package/dist/blogrolls/extractors.js +6 -9
  6. package/dist/blogrolls/index.cjs +6 -9
  7. package/dist/blogrolls/index.d.cts +1 -1
  8. package/dist/blogrolls/index.d.ts +1 -1
  9. package/dist/blogrolls/index.js +1 -4
  10. package/dist/blogrolls.cjs +4 -5
  11. package/dist/blogrolls.js +1 -2
  12. package/dist/common/discover/index.cjs +24 -16
  13. package/dist/common/discover/index.js +20 -12
  14. package/dist/common/discover/utils.cjs +19 -9
  15. package/dist/common/discover/utils.js +18 -8
  16. package/dist/common/locales.cjs +59 -15
  17. package/dist/common/locales.js +49 -4
  18. package/dist/common/types.cjs +2 -3
  19. package/dist/common/types.d.cts +11 -6
  20. package/dist/common/types.d.ts +11 -6
  21. package/dist/common/types.js +2 -2
  22. package/dist/common/uris/feed/index.cjs +12 -0
  23. package/dist/common/uris/feed/index.d.cts +6 -0
  24. package/dist/common/uris/feed/index.d.ts +6 -0
  25. package/dist/common/uris/feed/index.js +12 -0
  26. package/dist/common/uris/feed/types.d.cts +9 -0
  27. package/dist/common/uris/feed/types.d.ts +9 -0
  28. package/dist/common/uris/guess/index.cjs +2 -4
  29. package/dist/common/uris/guess/index.js +1 -3
  30. package/dist/common/uris/guess/utils.cjs +1 -3
  31. package/dist/common/uris/guess/utils.js +1 -2
  32. package/dist/common/uris/headers/index.cjs +2 -4
  33. package/dist/common/uris/headers/index.js +1 -3
  34. package/dist/common/uris/html/handlers.cjs +2 -4
  35. package/dist/common/uris/html/handlers.js +1 -3
  36. package/dist/common/uris/html/index.cjs +2 -4
  37. package/dist/common/uris/html/index.js +1 -3
  38. package/dist/common/uris/index.cjs +15 -12
  39. package/dist/common/uris/index.js +8 -5
  40. package/dist/common/uris/platform/index.cjs +3 -5
  41. package/dist/common/uris/platform/index.d.cts +7 -0
  42. package/dist/common/uris/platform/index.d.ts +7 -0
  43. package/dist/common/uris/platform/index.js +3 -4
  44. package/dist/common/uris/platform/types.d.cts +3 -3
  45. package/dist/common/uris/platform/types.d.ts +3 -3
  46. package/dist/common/utils.cjs +20 -9
  47. package/dist/common/utils.d.cts +2 -2
  48. package/dist/common/utils.d.ts +2 -2
  49. package/dist/common/utils.js +18 -8
  50. package/dist/favicons/defaults.cjs +60 -0
  51. package/dist/favicons/defaults.d.cts +18 -0
  52. package/dist/favicons/defaults.d.ts +18 -0
  53. package/dist/favicons/defaults.js +53 -0
  54. package/dist/favicons/extractors.cjs +13 -0
  55. package/dist/favicons/extractors.d.cts +7 -0
  56. package/dist/favicons/extractors.d.ts +7 -0
  57. package/dist/favicons/extractors.js +13 -0
  58. package/dist/favicons/index.cjs +29 -0
  59. package/dist/favicons/index.d.cts +7 -0
  60. package/dist/favicons/index.d.ts +7 -0
  61. package/dist/favicons/index.js +29 -0
  62. package/dist/favicons/platform/handlers/bluesky.cjs +27 -0
  63. package/dist/favicons/platform/handlers/bluesky.js +27 -0
  64. package/dist/favicons/platform/handlers/codeberg.cjs +18 -0
  65. package/dist/favicons/platform/handlers/codeberg.js +18 -0
  66. package/dist/favicons/platform/handlers/deviantart.cjs +29 -0
  67. package/dist/favicons/platform/handlers/deviantart.js +29 -0
  68. package/dist/favicons/platform/handlers/github.cjs +18 -0
  69. package/dist/favicons/platform/handlers/github.js +18 -0
  70. package/dist/favicons/platform/handlers/githubGist.cjs +18 -0
  71. package/dist/favicons/platform/handlers/githubGist.js +18 -0
  72. package/dist/favicons/platform/handlers/lobsters.cjs +21 -0
  73. package/dist/favicons/platform/handlers/lobsters.js +21 -0
  74. package/dist/favicons/platform/handlers/mastodon.cjs +36 -0
  75. package/dist/favicons/platform/handlers/mastodon.js +34 -0
  76. package/dist/favicons/platform/handlers/reddit.cjs +41 -0
  77. package/dist/favicons/platform/handlers/reddit.js +41 -0
  78. package/dist/favicons/platform/handlers/sourceforge.cjs +21 -0
  79. package/dist/favicons/platform/handlers/sourceforge.js +21 -0
  80. package/dist/favicons/platform/handlers/tumblr.cjs +16 -0
  81. package/dist/favicons/platform/handlers/tumblr.js +16 -0
  82. package/dist/favicons/types.d.cts +4 -0
  83. package/dist/favicons/types.d.ts +4 -0
  84. package/dist/favicons.cjs +12 -0
  85. package/dist/favicons.d.cts +4 -0
  86. package/dist/favicons.d.ts +4 -0
  87. package/dist/favicons.js +3 -0
  88. package/dist/feeds/defaults.cjs +55 -25
  89. package/dist/feeds/defaults.js +40 -10
  90. package/dist/feeds/extractors.cjs +1 -3
  91. package/dist/feeds/extractors.js +1 -3
  92. package/dist/feeds/index.cjs +6 -8
  93. package/dist/feeds/index.d.cts +1 -1
  94. package/dist/feeds/index.d.ts +1 -1
  95. package/dist/feeds/index.js +1 -3
  96. package/dist/feeds/platform/handlers/behance.cjs +2 -4
  97. package/dist/feeds/platform/handlers/behance.js +1 -3
  98. package/dist/feeds/platform/handlers/blogspot.cjs +7 -6
  99. package/dist/feeds/platform/handlers/blogspot.js +6 -5
  100. package/dist/feeds/platform/handlers/bluesky.cjs +3 -5
  101. package/dist/feeds/platform/handlers/bluesky.js +2 -4
  102. package/dist/feeds/platform/handlers/codeberg.cjs +69 -0
  103. package/dist/feeds/platform/handlers/codeberg.js +67 -0
  104. package/dist/feeds/platform/handlers/csdn.cjs +19 -0
  105. package/dist/feeds/platform/handlers/csdn.js +19 -0
  106. package/dist/feeds/platform/handlers/dailymotion.cjs +2 -4
  107. package/dist/feeds/platform/handlers/dailymotion.js +1 -3
  108. package/dist/feeds/platform/handlers/deviantart.cjs +4 -4
  109. package/dist/feeds/platform/handlers/deviantart.js +1 -3
  110. package/dist/feeds/platform/handlers/devto.cjs +2 -4
  111. package/dist/feeds/platform/handlers/devto.js +1 -3
  112. package/dist/feeds/platform/handlers/douban.cjs +54 -0
  113. package/dist/feeds/platform/handlers/douban.js +54 -0
  114. package/dist/feeds/platform/handlers/github.cjs +5 -4
  115. package/dist/feeds/platform/handlers/github.js +2 -3
  116. package/dist/feeds/platform/handlers/githubGist.cjs +4 -4
  117. package/dist/feeds/platform/handlers/githubGist.js +1 -3
  118. package/dist/feeds/platform/handlers/gitlab.cjs +2 -4
  119. package/dist/feeds/platform/handlers/gitlab.js +1 -3
  120. package/dist/feeds/platform/handlers/goodreads.cjs +39 -0
  121. package/dist/feeds/platform/handlers/goodreads.js +39 -0
  122. package/dist/feeds/platform/handlers/hashnode.cjs +16 -0
  123. package/dist/feeds/platform/handlers/hashnode.js +16 -0
  124. package/dist/feeds/platform/handlers/hatenablog.cjs +53 -0
  125. package/dist/feeds/platform/handlers/hatenablog.js +53 -0
  126. package/dist/feeds/platform/handlers/itchio.cjs +88 -0
  127. package/dist/feeds/platform/handlers/itchio.js +88 -0
  128. package/dist/feeds/platform/handlers/kickstarter.cjs +2 -4
  129. package/dist/feeds/platform/handlers/kickstarter.js +1 -3
  130. package/dist/feeds/platform/handlers/letterboxd.cjs +42 -0
  131. package/dist/feeds/platform/handlers/letterboxd.js +42 -0
  132. package/dist/feeds/platform/handlers/lobsters.cjs +3 -4
  133. package/dist/feeds/platform/handlers/lobsters.js +1 -3
  134. package/dist/feeds/platform/handlers/mastodon.cjs +40 -0
  135. package/dist/feeds/platform/handlers/mastodon.js +40 -0
  136. package/dist/feeds/platform/handlers/medium.cjs +2 -4
  137. package/dist/feeds/platform/handlers/medium.js +1 -3
  138. package/dist/feeds/platform/handlers/paragraph.cjs +21 -0
  139. package/dist/feeds/platform/handlers/paragraph.js +21 -0
  140. package/dist/feeds/platform/handlers/pinterest.cjs +2 -15
  141. package/dist/feeds/platform/handlers/pinterest.js +1 -14
  142. package/dist/feeds/platform/handlers/producthunt.cjs +2 -4
  143. package/dist/feeds/platform/handlers/producthunt.js +1 -3
  144. package/dist/feeds/platform/handlers/reddit.cjs +3 -4
  145. package/dist/feeds/platform/handlers/reddit.js +1 -3
  146. package/dist/feeds/platform/handlers/soundcloud.cjs +2 -4
  147. package/dist/feeds/platform/handlers/soundcloud.js +1 -3
  148. package/dist/feeds/platform/handlers/sourceforge.cjs +20 -0
  149. package/dist/feeds/platform/handlers/sourceforge.js +19 -0
  150. package/dist/feeds/platform/handlers/stackExchange.cjs +37 -0
  151. package/dist/feeds/platform/handlers/stackExchange.js +37 -0
  152. package/dist/feeds/platform/handlers/steam.cjs +26 -0
  153. package/dist/feeds/platform/handlers/steam.js +26 -0
  154. package/dist/feeds/platform/handlers/substack.cjs +2 -4
  155. package/dist/feeds/platform/handlers/substack.js +1 -3
  156. package/dist/feeds/platform/handlers/tumblr.cjs +5 -5
  157. package/dist/feeds/platform/handlers/tumblr.js +3 -4
  158. package/dist/feeds/platform/handlers/v2ex.cjs +33 -0
  159. package/dist/feeds/platform/handlers/v2ex.js +33 -0
  160. package/dist/feeds/platform/handlers/vimeo.cjs +68 -0
  161. package/dist/feeds/platform/handlers/vimeo.js +68 -0
  162. package/dist/feeds/platform/handlers/wordpress.cjs +5 -7
  163. package/dist/feeds/platform/handlers/wordpress.js +4 -6
  164. package/dist/feeds/platform/handlers/wpengine.cjs +4 -7
  165. package/dist/feeds/platform/handlers/wpengine.js +2 -4
  166. package/dist/feeds/platform/handlers/ximalaya.cjs +19 -0
  167. package/dist/feeds/platform/handlers/ximalaya.js +19 -0
  168. package/dist/feeds/platform/handlers/youtube.cjs +19 -8
  169. package/dist/feeds/platform/handlers/youtube.js +18 -7
  170. package/dist/feeds.cjs +4 -5
  171. package/dist/feeds.js +1 -2
  172. package/dist/hubs/discover/index.cjs +7 -9
  173. package/dist/hubs/discover/index.js +1 -3
  174. package/dist/hubs/discover/utils.cjs +1 -3
  175. package/dist/hubs/discover/utils.js +1 -2
  176. package/dist/hubs/feed/index.cjs +1 -3
  177. package/dist/hubs/feed/index.js +1 -3
  178. package/dist/hubs/headers/index.cjs +3 -5
  179. package/dist/hubs/headers/index.js +1 -3
  180. package/dist/hubs/html/index.cjs +3 -5
  181. package/dist/hubs/html/index.js +1 -3
  182. package/dist/hubs.js +1 -1
  183. package/dist/index.cjs +8 -7
  184. package/dist/index.d.cts +3 -2
  185. package/dist/index.d.ts +3 -2
  186. package/dist/index.js +2 -2
  187. package/dist/methods.cjs +13 -10
  188. package/dist/methods.d.cts +3 -1
  189. package/dist/methods.d.ts +3 -1
  190. package/dist/methods.js +3 -2
  191. package/dist/utils.cjs +3 -4
  192. package/dist/utils.js +1 -2
  193. package/package.json +15 -5
@@ -0,0 +1,39 @@
1
+ import { composeHint, isHostOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/goodreads.ts
3
+ const hosts = ["goodreads.com", "www.goodreads.com"];
4
+ const parseUserId = (segment) => {
5
+ const id = Number.parseInt(segment, 10);
6
+ return Number.isNaN(id) ? void 0 : id;
7
+ };
8
+ const goodreadsHandler = {
9
+ match: (url) => {
10
+ return isHostOf(url, hosts);
11
+ },
12
+ resolve: (url) => {
13
+ const { origin, pathname } = new URL(url);
14
+ const pathSegments = pathname.split("/").filter(Boolean);
15
+ if (pathSegments[0] === "user" && pathSegments[1] === "show" && pathSegments[2]) {
16
+ const userId = parseUserId(pathSegments[2]);
17
+ if (userId) return [{
18
+ uri: `${origin}/user/updates_rss/${userId}`,
19
+ hint: composeHint("goodreads:updates")
20
+ }, {
21
+ uri: `${origin}/review/list_rss/${userId}`,
22
+ hint: composeHint("goodreads:reviews")
23
+ }];
24
+ }
25
+ if (pathSegments[0] === "review" && pathSegments[1] === "list" && pathSegments[2]) {
26
+ const userId = parseUserId(pathSegments[2]);
27
+ if (userId) return [{
28
+ uri: `${origin}/review/list_rss/${userId}`,
29
+ hint: composeHint("goodreads:reviews")
30
+ }, {
31
+ uri: `${origin}/user/updates_rss/${userId}`,
32
+ hint: composeHint("goodreads:updates")
33
+ }];
34
+ }
35
+ return [];
36
+ }
37
+ };
38
+ //#endregion
39
+ export { goodreadsHandler };
@@ -0,0 +1,16 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/hashnode.ts
3
+ const hashnodeHandler = {
4
+ match: (url) => {
5
+ return require_utils.isSubdomainOf(url, "hashnode.dev");
6
+ },
7
+ resolve: (url) => {
8
+ const { origin } = new URL(url);
9
+ return [{
10
+ uri: `${origin}/rss.xml`,
11
+ hint: require_utils.composeHint("hashnode:blog")
12
+ }];
13
+ }
14
+ };
15
+ //#endregion
16
+ exports.hashnodeHandler = hashnodeHandler;
@@ -0,0 +1,16 @@
1
+ import { composeHint, isSubdomainOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/hashnode.ts
3
+ const hashnodeHandler = {
4
+ match: (url) => {
5
+ return isSubdomainOf(url, "hashnode.dev");
6
+ },
7
+ resolve: (url) => {
8
+ const { origin } = new URL(url);
9
+ return [{
10
+ uri: `${origin}/rss.xml`,
11
+ hint: composeHint("hashnode:blog")
12
+ }];
13
+ }
14
+ };
15
+ //#endregion
16
+ export { hashnodeHandler };
@@ -0,0 +1,53 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/hatenablog.ts
3
+ const domains = [
4
+ "hatenablog.com",
5
+ "hatenablog.jp",
6
+ "hateblo.jp"
7
+ ];
8
+ const categoryPathRegex = /^\/archive\/category\/([^/]+)/;
9
+ const authorPathRegex = /^\/archive\/author\/([^/]+)/;
10
+ const hatenablogHandler = {
11
+ match: (url) => {
12
+ return require_utils.isSubdomainOf(url, domains);
13
+ },
14
+ resolve: (url) => {
15
+ const { origin, pathname } = new URL(url);
16
+ const uris = [];
17
+ const categoryMatch = pathname.match(categoryPathRegex);
18
+ if (categoryMatch?.[1]) {
19
+ const category = categoryMatch[1];
20
+ uris.push({
21
+ uri: `${origin}/rss/category/${category}`,
22
+ hint: require_utils.composeHint("hatenablog:category-rss")
23
+ });
24
+ uris.push({
25
+ uri: `${origin}/feed/category/${category}`,
26
+ hint: require_utils.composeHint("hatenablog:category-atom")
27
+ });
28
+ }
29
+ const authorMatch = pathname.match(authorPathRegex);
30
+ if (authorMatch?.[1]) {
31
+ const author = authorMatch[1];
32
+ uris.push({
33
+ uri: `${origin}/rss/author/${author}`,
34
+ hint: require_utils.composeHint("hatenablog:author-rss")
35
+ });
36
+ uris.push({
37
+ uri: `${origin}/feed/author/${author}`,
38
+ hint: require_utils.composeHint("hatenablog:author-atom")
39
+ });
40
+ }
41
+ uris.push({
42
+ uri: `${origin}/rss`,
43
+ hint: require_utils.composeHint("hatenablog:posts-rss")
44
+ });
45
+ uris.push({
46
+ uri: `${origin}/feed`,
47
+ hint: require_utils.composeHint("hatenablog:posts-atom")
48
+ });
49
+ return uris;
50
+ }
51
+ };
52
+ //#endregion
53
+ exports.hatenablogHandler = hatenablogHandler;
@@ -0,0 +1,53 @@
1
+ import { composeHint, isSubdomainOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/hatenablog.ts
3
+ const domains = [
4
+ "hatenablog.com",
5
+ "hatenablog.jp",
6
+ "hateblo.jp"
7
+ ];
8
+ const categoryPathRegex = /^\/archive\/category\/([^/]+)/;
9
+ const authorPathRegex = /^\/archive\/author\/([^/]+)/;
10
+ const hatenablogHandler = {
11
+ match: (url) => {
12
+ return isSubdomainOf(url, domains);
13
+ },
14
+ resolve: (url) => {
15
+ const { origin, pathname } = new URL(url);
16
+ const uris = [];
17
+ const categoryMatch = pathname.match(categoryPathRegex);
18
+ if (categoryMatch?.[1]) {
19
+ const category = categoryMatch[1];
20
+ uris.push({
21
+ uri: `${origin}/rss/category/${category}`,
22
+ hint: composeHint("hatenablog:category-rss")
23
+ });
24
+ uris.push({
25
+ uri: `${origin}/feed/category/${category}`,
26
+ hint: composeHint("hatenablog:category-atom")
27
+ });
28
+ }
29
+ const authorMatch = pathname.match(authorPathRegex);
30
+ if (authorMatch?.[1]) {
31
+ const author = authorMatch[1];
32
+ uris.push({
33
+ uri: `${origin}/rss/author/${author}`,
34
+ hint: composeHint("hatenablog:author-rss")
35
+ });
36
+ uris.push({
37
+ uri: `${origin}/feed/author/${author}`,
38
+ hint: composeHint("hatenablog:author-atom")
39
+ });
40
+ }
41
+ uris.push({
42
+ uri: `${origin}/rss`,
43
+ hint: composeHint("hatenablog:posts-rss")
44
+ });
45
+ uris.push({
46
+ uri: `${origin}/feed`,
47
+ hint: composeHint("hatenablog:posts-atom")
48
+ });
49
+ return uris;
50
+ }
51
+ };
52
+ //#endregion
53
+ export { hatenablogHandler };
@@ -0,0 +1,88 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/itchio.ts
3
+ const mainHosts = ["itch.io", "www.itch.io"];
4
+ const sections = [
5
+ "tools",
6
+ "game-assets",
7
+ "soundtracks",
8
+ "physical-games",
9
+ "books",
10
+ "comics",
11
+ "misc"
12
+ ];
13
+ const sorts = [
14
+ "newest",
15
+ "top-rated",
16
+ "top-sellers",
17
+ "on-sale"
18
+ ];
19
+ const byUserPathRegex = /^\/games\/by-([^/]+)/;
20
+ const tagPathRegex = /^\/games\/tag-([^/]+)/;
21
+ const sortPathRegex = /^\/games\/([^/.]+)/;
22
+ const sectionPathRegex = /^\/([^/.]+)/;
23
+ const gamePathRegex = /^\/([^/]+)/;
24
+ const itchioHandler = {
25
+ match: (url) => {
26
+ return require_utils.isHostOf(url, mainHosts) || require_utils.isSubdomainOf(url, "itch.io");
27
+ },
28
+ resolve: (url) => {
29
+ const { hostname, pathname } = new URL(url);
30
+ const lowerHostname = hostname.toLowerCase();
31
+ if (!mainHosts.includes(lowerHostname) && lowerHostname.endsWith(".itch.io")) {
32
+ const creator = lowerHostname.replace(".itch.io", "");
33
+ const gameMatch = pathname.match(gamePathRegex);
34
+ if (gameMatch?.[1]) return [{
35
+ uri: `https://${creator}.itch.io/${gameMatch[1]}/devlog.rss`,
36
+ hint: require_utils.composeHint("itchio:devlog")
37
+ }];
38
+ return [{
39
+ uri: `https://itch.io/games/by-${creator}.xml`,
40
+ hint: require_utils.composeHint("itchio:games")
41
+ }];
42
+ }
43
+ const byUserMatch = pathname.match(byUserPathRegex);
44
+ if (byUserMatch?.[1]) return [{
45
+ uri: `https://itch.io/games/by-${byUserMatch[1]}.xml`,
46
+ hint: require_utils.composeHint("itchio:games")
47
+ }];
48
+ const tagMatch = pathname.match(tagPathRegex);
49
+ if (tagMatch?.[1]) return [{
50
+ uri: `https://itch.io/games/tag-${tagMatch[1]}.xml`,
51
+ hint: require_utils.composeHint("itchio:tag")
52
+ }];
53
+ const sortMatch = pathname.match(sortPathRegex);
54
+ if (sortMatch?.[1] && require_utils.isAnyOf(sortMatch[1], sorts)) return [{
55
+ uri: `https://itch.io/games/${sortMatch[1]}.xml`,
56
+ hint: require_utils.composeHint("itchio:games")
57
+ }];
58
+ if (pathname === "/games" || pathname === "/games/") return [{
59
+ uri: "https://itch.io/games.xml",
60
+ hint: require_utils.composeHint("itchio:games")
61
+ }];
62
+ if (pathname === "/devlogs" || pathname === "/devlogs/") return [{
63
+ uri: "https://itch.io/devlogs.xml",
64
+ hint: require_utils.composeHint("itchio:devlog")
65
+ }];
66
+ const sectionMatch = pathname.match(sectionPathRegex);
67
+ if (sectionMatch?.[1] && require_utils.isAnyOf(sectionMatch[1], sections)) return [{
68
+ uri: `https://itch.io/${sectionMatch[1]}.xml`,
69
+ hint: require_utils.composeHint("itchio:section")
70
+ }];
71
+ const uris = [];
72
+ uris.push({
73
+ uri: "https://itch.io/feed/featured.xml",
74
+ hint: require_utils.composeHint("itchio:featured")
75
+ });
76
+ uris.push({
77
+ uri: "https://itch.io/feed/new.xml",
78
+ hint: require_utils.composeHint("itchio:new")
79
+ });
80
+ uris.push({
81
+ uri: "https://itch.io/feed/sales.xml",
82
+ hint: require_utils.composeHint("itchio:sales")
83
+ });
84
+ return uris;
85
+ }
86
+ };
87
+ //#endregion
88
+ exports.itchioHandler = itchioHandler;
@@ -0,0 +1,88 @@
1
+ import { composeHint, isAnyOf, isHostOf, isSubdomainOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/itchio.ts
3
+ const mainHosts = ["itch.io", "www.itch.io"];
4
+ const sections = [
5
+ "tools",
6
+ "game-assets",
7
+ "soundtracks",
8
+ "physical-games",
9
+ "books",
10
+ "comics",
11
+ "misc"
12
+ ];
13
+ const sorts = [
14
+ "newest",
15
+ "top-rated",
16
+ "top-sellers",
17
+ "on-sale"
18
+ ];
19
+ const byUserPathRegex = /^\/games\/by-([^/]+)/;
20
+ const tagPathRegex = /^\/games\/tag-([^/]+)/;
21
+ const sortPathRegex = /^\/games\/([^/.]+)/;
22
+ const sectionPathRegex = /^\/([^/.]+)/;
23
+ const gamePathRegex = /^\/([^/]+)/;
24
+ const itchioHandler = {
25
+ match: (url) => {
26
+ return isHostOf(url, mainHosts) || isSubdomainOf(url, "itch.io");
27
+ },
28
+ resolve: (url) => {
29
+ const { hostname, pathname } = new URL(url);
30
+ const lowerHostname = hostname.toLowerCase();
31
+ if (!mainHosts.includes(lowerHostname) && lowerHostname.endsWith(".itch.io")) {
32
+ const creator = lowerHostname.replace(".itch.io", "");
33
+ const gameMatch = pathname.match(gamePathRegex);
34
+ if (gameMatch?.[1]) return [{
35
+ uri: `https://${creator}.itch.io/${gameMatch[1]}/devlog.rss`,
36
+ hint: composeHint("itchio:devlog")
37
+ }];
38
+ return [{
39
+ uri: `https://itch.io/games/by-${creator}.xml`,
40
+ hint: composeHint("itchio:games")
41
+ }];
42
+ }
43
+ const byUserMatch = pathname.match(byUserPathRegex);
44
+ if (byUserMatch?.[1]) return [{
45
+ uri: `https://itch.io/games/by-${byUserMatch[1]}.xml`,
46
+ hint: composeHint("itchio:games")
47
+ }];
48
+ const tagMatch = pathname.match(tagPathRegex);
49
+ if (tagMatch?.[1]) return [{
50
+ uri: `https://itch.io/games/tag-${tagMatch[1]}.xml`,
51
+ hint: composeHint("itchio:tag")
52
+ }];
53
+ const sortMatch = pathname.match(sortPathRegex);
54
+ if (sortMatch?.[1] && isAnyOf(sortMatch[1], sorts)) return [{
55
+ uri: `https://itch.io/games/${sortMatch[1]}.xml`,
56
+ hint: composeHint("itchio:games")
57
+ }];
58
+ if (pathname === "/games" || pathname === "/games/") return [{
59
+ uri: "https://itch.io/games.xml",
60
+ hint: composeHint("itchio:games")
61
+ }];
62
+ if (pathname === "/devlogs" || pathname === "/devlogs/") return [{
63
+ uri: "https://itch.io/devlogs.xml",
64
+ hint: composeHint("itchio:devlog")
65
+ }];
66
+ const sectionMatch = pathname.match(sectionPathRegex);
67
+ if (sectionMatch?.[1] && isAnyOf(sectionMatch[1], sections)) return [{
68
+ uri: `https://itch.io/${sectionMatch[1]}.xml`,
69
+ hint: composeHint("itchio:section")
70
+ }];
71
+ const uris = [];
72
+ uris.push({
73
+ uri: "https://itch.io/feed/featured.xml",
74
+ hint: composeHint("itchio:featured")
75
+ });
76
+ uris.push({
77
+ uri: "https://itch.io/feed/new.xml",
78
+ hint: composeHint("itchio:new")
79
+ });
80
+ uris.push({
81
+ uri: "https://itch.io/feed/sales.xml",
82
+ hint: composeHint("itchio:sales")
83
+ });
84
+ return uris;
85
+ }
86
+ };
87
+ //#endregion
88
+ export { itchioHandler };
@@ -1,5 +1,4 @@
1
- const require_utils = require('../../../common/utils.cjs');
2
-
1
+ const require_utils = require("../../../common/utils.cjs");
3
2
  //#region src/feeds/platform/handlers/kickstarter.ts
4
3
  const hosts = ["kickstarter.com", "www.kickstarter.com"];
5
4
  const kickstarterHandler = {
@@ -19,6 +18,5 @@ const kickstarterHandler = {
19
18
  }];
20
19
  }
21
20
  };
22
-
23
21
  //#endregion
24
- exports.kickstarterHandler = kickstarterHandler;
22
+ exports.kickstarterHandler = kickstarterHandler;
@@ -1,5 +1,4 @@
1
1
  import { composeHint, isHostOf } from "../../../common/utils.js";
2
-
3
2
  //#region src/feeds/platform/handlers/kickstarter.ts
4
3
  const hosts = ["kickstarter.com", "www.kickstarter.com"];
5
4
  const kickstarterHandler = {
@@ -19,6 +18,5 @@ const kickstarterHandler = {
19
18
  }];
20
19
  }
21
20
  };
22
-
23
21
  //#endregion
24
- export { kickstarterHandler };
22
+ export { kickstarterHandler };
@@ -0,0 +1,42 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/letterboxd.ts
3
+ const hosts = ["letterboxd.com", "www.letterboxd.com"];
4
+ const excludedPaths = [
5
+ "about",
6
+ "activity",
7
+ "api-beta",
8
+ "apps",
9
+ "contact",
10
+ "create-account",
11
+ "films",
12
+ "journal",
13
+ "legal",
14
+ "lists",
15
+ "members",
16
+ "news",
17
+ "pro",
18
+ "search",
19
+ "settings",
20
+ "showdown",
21
+ "sign-in",
22
+ "welcome",
23
+ "year-in-review"
24
+ ];
25
+ const letterboxdHandler = {
26
+ match: (url) => {
27
+ return require_utils.isHostOf(url, hosts);
28
+ },
29
+ resolve: (url) => {
30
+ const { pathname } = new URL(url);
31
+ const pathSegments = pathname.split("/").filter(Boolean);
32
+ if (pathSegments.length === 0) return [];
33
+ const username = pathSegments[0];
34
+ if (require_utils.isAnyOf(username, excludedPaths)) return [];
35
+ return [{
36
+ uri: `https://letterboxd.com/${username}/rss/`,
37
+ hint: require_utils.composeHint("letterboxd:diary")
38
+ }];
39
+ }
40
+ };
41
+ //#endregion
42
+ exports.letterboxdHandler = letterboxdHandler;
@@ -0,0 +1,42 @@
1
+ import { composeHint, isAnyOf, isHostOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/letterboxd.ts
3
+ const hosts = ["letterboxd.com", "www.letterboxd.com"];
4
+ const excludedPaths = [
5
+ "about",
6
+ "activity",
7
+ "api-beta",
8
+ "apps",
9
+ "contact",
10
+ "create-account",
11
+ "films",
12
+ "journal",
13
+ "legal",
14
+ "lists",
15
+ "members",
16
+ "news",
17
+ "pro",
18
+ "search",
19
+ "settings",
20
+ "showdown",
21
+ "sign-in",
22
+ "welcome",
23
+ "year-in-review"
24
+ ];
25
+ const letterboxdHandler = {
26
+ match: (url) => {
27
+ return isHostOf(url, hosts);
28
+ },
29
+ resolve: (url) => {
30
+ const { pathname } = new URL(url);
31
+ const pathSegments = pathname.split("/").filter(Boolean);
32
+ if (pathSegments.length === 0) return [];
33
+ const username = pathSegments[0];
34
+ if (isAnyOf(username, excludedPaths)) return [];
35
+ return [{
36
+ uri: `https://letterboxd.com/${username}/rss/`,
37
+ hint: composeHint("letterboxd:diary")
38
+ }];
39
+ }
40
+ };
41
+ //#endregion
42
+ export { letterboxdHandler };
@@ -1,5 +1,4 @@
1
- const require_utils = require('../../../common/utils.cjs');
2
-
1
+ const require_utils = require("../../../common/utils.cjs");
3
2
  //#region src/feeds/platform/handlers/lobsters.ts
4
3
  const hosts = ["lobste.rs"];
5
4
  const tagPathRegex = /^\/t\/([a-zA-Z0-9,_-]+)/;
@@ -53,6 +52,6 @@ const lobstersHandler = {
53
52
  }];
54
53
  }
55
54
  };
56
-
57
55
  //#endregion
58
- exports.lobstersHandler = lobstersHandler;
56
+ exports.hosts = hosts;
57
+ exports.lobstersHandler = lobstersHandler;
@@ -1,5 +1,4 @@
1
1
  import { composeHint, isHostOf } from "../../../common/utils.js";
2
-
3
2
  //#region src/feeds/platform/handlers/lobsters.ts
4
3
  const hosts = ["lobste.rs"];
5
4
  const tagPathRegex = /^\/t\/([a-zA-Z0-9,_-]+)/;
@@ -53,6 +52,5 @@ const lobstersHandler = {
53
52
  }];
54
53
  }
55
54
  };
56
-
57
55
  //#endregion
58
- export { lobstersHandler };
56
+ export { hosts, lobstersHandler };
@@ -0,0 +1,40 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ const require_mastodon = require("../../../favicons/platform/handlers/mastodon.cjs");
3
+ //#region src/feeds/platform/handlers/mastodon.ts
4
+ const isProfilePath = (pathname) => {
5
+ const segments = pathname.split("/").filter(Boolean);
6
+ return segments.length >= 1 && segments[0].startsWith("@");
7
+ };
8
+ const isTagPath = (pathname) => {
9
+ const segments = pathname.split("/").filter(Boolean);
10
+ return segments.length >= 2 && segments[0] === "tags";
11
+ };
12
+ const mastodonHandler = {
13
+ match: (url, content, headers) => {
14
+ try {
15
+ const { pathname } = new URL(url);
16
+ if (!isProfilePath(pathname) && !isTagPath(pathname)) return false;
17
+ if (content && require_mastodon.isMastodonHtml(content)) return true;
18
+ if (headers && require_mastodon.isMastodonHeaders(headers)) return true;
19
+ } catch {}
20
+ return false;
21
+ },
22
+ resolve: (url) => {
23
+ try {
24
+ const { origin, pathname } = new URL(url);
25
+ const userMatch = pathname.match(/^\/@([^/]+)/);
26
+ if (userMatch?.[1]) return [{
27
+ uri: `${origin}/@${userMatch[1]}.rss`,
28
+ hint: require_utils.composeHint("mastodon:posts")
29
+ }];
30
+ const tagMatch = pathname.match(/^\/tags\/([^/]+)/);
31
+ if (tagMatch?.[1]) return [{
32
+ uri: `${origin}/tags/${tagMatch[1]}.rss`,
33
+ hint: require_utils.composeHint("mastodon:tag")
34
+ }];
35
+ } catch {}
36
+ return [];
37
+ }
38
+ };
39
+ //#endregion
40
+ exports.mastodonHandler = mastodonHandler;
@@ -0,0 +1,40 @@
1
+ import { composeHint } from "../../../common/utils.js";
2
+ import { isMastodonHeaders, isMastodonHtml } from "../../../favicons/platform/handlers/mastodon.js";
3
+ //#region src/feeds/platform/handlers/mastodon.ts
4
+ const isProfilePath = (pathname) => {
5
+ const segments = pathname.split("/").filter(Boolean);
6
+ return segments.length >= 1 && segments[0].startsWith("@");
7
+ };
8
+ const isTagPath = (pathname) => {
9
+ const segments = pathname.split("/").filter(Boolean);
10
+ return segments.length >= 2 && segments[0] === "tags";
11
+ };
12
+ const mastodonHandler = {
13
+ match: (url, content, headers) => {
14
+ try {
15
+ const { pathname } = new URL(url);
16
+ if (!isProfilePath(pathname) && !isTagPath(pathname)) return false;
17
+ if (content && isMastodonHtml(content)) return true;
18
+ if (headers && isMastodonHeaders(headers)) return true;
19
+ } catch {}
20
+ return false;
21
+ },
22
+ resolve: (url) => {
23
+ try {
24
+ const { origin, pathname } = new URL(url);
25
+ const userMatch = pathname.match(/^\/@([^/]+)/);
26
+ if (userMatch?.[1]) return [{
27
+ uri: `${origin}/@${userMatch[1]}.rss`,
28
+ hint: composeHint("mastodon:posts")
29
+ }];
30
+ const tagMatch = pathname.match(/^\/tags\/([^/]+)/);
31
+ if (tagMatch?.[1]) return [{
32
+ uri: `${origin}/tags/${tagMatch[1]}.rss`,
33
+ hint: composeHint("mastodon:tag")
34
+ }];
35
+ } catch {}
36
+ return [];
37
+ }
38
+ };
39
+ //#endregion
40
+ export { mastodonHandler };
@@ -1,5 +1,4 @@
1
- const require_utils = require('../../../common/utils.cjs');
2
-
1
+ const require_utils = require("../../../common/utils.cjs");
3
2
  //#region src/feeds/platform/handlers/medium.ts
4
3
  const hosts = ["medium.com", "www.medium.com"];
5
4
  const excludedPaths = [
@@ -60,6 +59,5 @@ const mediumHandler = {
60
59
  return [];
61
60
  }
62
61
  };
63
-
64
62
  //#endregion
65
- exports.mediumHandler = mediumHandler;
63
+ exports.mediumHandler = mediumHandler;
@@ -1,5 +1,4 @@
1
1
  import { composeHint, isAnyOf, isHostOf, isSubdomainOf } from "../../../common/utils.js";
2
-
3
2
  //#region src/feeds/platform/handlers/medium.ts
4
3
  const hosts = ["medium.com", "www.medium.com"];
5
4
  const excludedPaths = [
@@ -60,6 +59,5 @@ const mediumHandler = {
60
59
  return [];
61
60
  }
62
61
  };
63
-
64
62
  //#endregion
65
- export { mediumHandler };
63
+ export { mediumHandler };
@@ -0,0 +1,21 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/paragraph.ts
3
+ const hosts = ["paragraph.com", "www.paragraph.com"];
4
+ const userPathRegex = /^\/@([^/]+)/;
5
+ const paragraphHandler = {
6
+ match: (url) => {
7
+ return require_utils.isHostOf(url, hosts);
8
+ },
9
+ resolve: (url) => {
10
+ const { pathname } = new URL(url);
11
+ const userMatch = pathname.match(userPathRegex);
12
+ if (!userMatch?.[1]) return [];
13
+ const username = userMatch[1];
14
+ return [{
15
+ uri: [`https://paragraph.com/@${username}/feed`, `https://paragraph.com/@${username}/rss`],
16
+ hint: require_utils.composeHint("paragraph:blog")
17
+ }];
18
+ }
19
+ };
20
+ //#endregion
21
+ exports.paragraphHandler = paragraphHandler;
@@ -0,0 +1,21 @@
1
+ import { composeHint, isHostOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/paragraph.ts
3
+ const hosts = ["paragraph.com", "www.paragraph.com"];
4
+ const userPathRegex = /^\/@([^/]+)/;
5
+ const paragraphHandler = {
6
+ match: (url) => {
7
+ return isHostOf(url, hosts);
8
+ },
9
+ resolve: (url) => {
10
+ const { pathname } = new URL(url);
11
+ const userMatch = pathname.match(userPathRegex);
12
+ if (!userMatch?.[1]) return [];
13
+ const username = userMatch[1];
14
+ return [{
15
+ uri: [`https://paragraph.com/@${username}/feed`, `https://paragraph.com/@${username}/rss`],
16
+ hint: composeHint("paragraph:blog")
17
+ }];
18
+ }
19
+ };
20
+ //#endregion
21
+ export { paragraphHandler };