feedscout 1.7.1 → 1.8.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.
- package/dist/common/discover/utils.cjs +9 -6
- package/dist/common/discover/utils.js +9 -6
- package/dist/common/locales.cjs +11 -4
- package/dist/common/locales.js +11 -4
- package/dist/common/types.d.cts +4 -3
- package/dist/common/types.d.ts +4 -3
- package/dist/common/uris/headers/index.cjs +1 -1
- package/dist/common/uris/headers/index.js +1 -1
- package/dist/common/uris/platform/types.d.cts +2 -2
- package/dist/common/uris/platform/types.d.ts +2 -2
- package/dist/favicons/defaults.cjs +6 -1
- package/dist/favicons/defaults.js +6 -1
- package/dist/favicons/platform/handlers/bluesky.cjs +1 -1
- package/dist/favicons/platform/handlers/bluesky.js +1 -1
- package/dist/favicons/platform/handlers/codeberg.cjs +4 -3
- package/dist/favicons/platform/handlers/codeberg.js +4 -3
- package/dist/favicons/platform/handlers/devto.cjs +31 -0
- package/dist/favicons/platform/handlers/devto.js +31 -0
- package/dist/favicons/platform/handlers/github.cjs +4 -3
- package/dist/favicons/platform/handlers/github.js +4 -3
- package/dist/favicons/platform/handlers/githubGist.cjs +4 -3
- package/dist/favicons/platform/handlers/githubGist.js +4 -3
- package/dist/favicons/platform/handlers/gitlab.cjs +38 -0
- package/dist/favicons/platform/handlers/gitlab.js +38 -0
- package/dist/favicons/platform/handlers/lobsters.cjs +3 -3
- package/dist/favicons/platform/handlers/lobsters.js +3 -3
- package/dist/favicons/platform/handlers/mastodon.cjs +5 -3
- package/dist/favicons/platform/handlers/mastodon.js +5 -3
- package/dist/favicons/platform/handlers/reddit.cjs +10 -8
- package/dist/favicons/platform/handlers/reddit.js +10 -8
- package/dist/feeds/defaults.cjs +4 -2
- package/dist/feeds/defaults.js +4 -2
- package/dist/feeds/platform/handlers/applePodcasts.cjs +26 -0
- package/dist/feeds/platform/handlers/applePodcasts.js +26 -0
- package/dist/feeds/platform/handlers/behance.cjs +2 -2
- package/dist/feeds/platform/handlers/behance.js +2 -2
- package/dist/feeds/platform/handlers/dailymotion.cjs +4 -4
- package/dist/feeds/platform/handlers/dailymotion.js +4 -4
- package/dist/feeds/platform/handlers/devto.cjs +6 -4
- package/dist/feeds/platform/handlers/devto.js +5 -5
- package/dist/feeds/platform/handlers/gitlab.cjs +4 -0
- package/dist/feeds/platform/handlers/gitlab.js +1 -1
- package/dist/feeds/platform/handlers/hatenablog.cjs +4 -4
- package/dist/feeds/platform/handlers/hatenablog.js +4 -4
- package/dist/feeds/platform/handlers/itchio.cjs +10 -10
- package/dist/feeds/platform/handlers/itchio.js +10 -10
- package/dist/feeds/platform/handlers/lobsters.cjs +8 -8
- package/dist/feeds/platform/handlers/lobsters.js +8 -8
- package/dist/feeds/platform/handlers/mastodon.cjs +4 -4
- package/dist/feeds/platform/handlers/mastodon.js +4 -4
- package/dist/feeds/platform/handlers/medium.cjs +10 -10
- package/dist/feeds/platform/handlers/medium.js +10 -10
- package/dist/feeds/platform/handlers/paragraph.cjs +2 -2
- package/dist/feeds/platform/handlers/paragraph.js +2 -2
- package/dist/feeds/platform/handlers/producthunt.cjs +4 -4
- package/dist/feeds/platform/handlers/producthunt.js +4 -4
- package/dist/feeds/platform/handlers/reddit.cjs +10 -10
- package/dist/feeds/platform/handlers/reddit.js +10 -10
- package/dist/feeds/platform/handlers/stackExchange.cjs +6 -6
- package/dist/feeds/platform/handlers/stackExchange.js +6 -6
- package/dist/feeds/platform/handlers/steam.cjs +4 -4
- package/dist/feeds/platform/handlers/steam.js +4 -4
- package/dist/feeds/platform/handlers/substack.cjs +10 -3
- package/dist/feeds/platform/handlers/substack.js +11 -4
- package/dist/feeds/platform/handlers/tumblr.cjs +2 -2
- package/dist/feeds/platform/handlers/tumblr.js +2 -2
- package/dist/feeds/platform/handlers/v2ex.cjs +4 -4
- package/dist/feeds/platform/handlers/v2ex.js +4 -4
- package/dist/feeds/platform/handlers/vimeo.cjs +2 -2
- package/dist/feeds/platform/handlers/vimeo.js +2 -2
- package/dist/feeds/platform/handlers/wordpress.cjs +6 -6
- package/dist/feeds/platform/handlers/wordpress.js +6 -6
- package/dist/feeds/platform/handlers/ximalaya.cjs +2 -2
- package/dist/feeds/platform/handlers/ximalaya.js +2 -2
- package/dist/feeds/platform/handlers/youtube.cjs +36 -21
- package/dist/feeds/platform/handlers/youtube.js +36 -21
- package/dist/hubs/discover/index.cjs +1 -2
- package/dist/hubs/discover/index.js +1 -2
- package/package.json +3 -2
- package/dist/hubs/discover/utils.cjs +0 -18
- package/dist/hubs/discover/utils.js +0 -18
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import { composeHint, isHostOf } from "../../../common/utils.js";
|
|
2
2
|
//#region src/feeds/platform/handlers/lobsters.ts
|
|
3
3
|
const hosts = ["lobste.rs"];
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
4
|
+
const tagRegex = /^\/t\/([a-zA-Z0-9,_-]+)/;
|
|
5
|
+
const domainRegex = /^\/domains\/([^/]+)/;
|
|
6
|
+
const userRegex = /^\/~([a-zA-Z0-9_-]+)/;
|
|
7
|
+
const topRegex = /^\/top(?:\/(1d|3d|1w|1m|1y))?\/?$/;
|
|
8
8
|
const lobstersHandler = {
|
|
9
9
|
match: (url) => {
|
|
10
10
|
return isHostOf(url, hosts);
|
|
11
11
|
},
|
|
12
12
|
resolve: (url) => {
|
|
13
13
|
const { pathname } = new URL(url);
|
|
14
|
-
const tagMatch = pathname.match(
|
|
14
|
+
const tagMatch = pathname.match(tagRegex);
|
|
15
15
|
if (tagMatch?.[1]) return [{
|
|
16
16
|
uri: `https://lobste.rs/t/${tagMatch[1]}.rss`,
|
|
17
17
|
hint: composeHint("lobsters:tag")
|
|
18
18
|
}];
|
|
19
|
-
const domainMatch = pathname.match(
|
|
19
|
+
const domainMatch = pathname.match(domainRegex);
|
|
20
20
|
if (domainMatch?.[1]) return [{
|
|
21
21
|
uri: `https://lobste.rs/domains/${domainMatch[1]}.rss`,
|
|
22
22
|
hint: composeHint("lobsters:domain")
|
|
23
23
|
}];
|
|
24
|
-
const userMatch = pathname.match(
|
|
24
|
+
const userMatch = pathname.match(userRegex);
|
|
25
25
|
if (userMatch?.[1]) return [{
|
|
26
26
|
uri: `https://lobste.rs/~${userMatch[1]}/stories.rss`,
|
|
27
27
|
hint: composeHint("lobsters:stories")
|
|
28
28
|
}];
|
|
29
|
-
const topMatch = pathname.match(
|
|
29
|
+
const topMatch = pathname.match(topRegex);
|
|
30
30
|
if (topMatch) {
|
|
31
31
|
const period = topMatch[1];
|
|
32
32
|
if (period) return [{
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
const require_mastodon = require("../../../favicons/platform/handlers/mastodon.cjs");
|
|
3
3
|
//#region src/feeds/platform/handlers/mastodon.ts
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const profileRegex = /^\/@([^/]+)/;
|
|
5
|
+
const tagRegex = /^\/tags\/([^/]+)/;
|
|
6
6
|
const isProfilePath = (pathname) => {
|
|
7
7
|
const segments = pathname.split("/").filter(Boolean);
|
|
8
8
|
return segments.length > 0 && segments[0].startsWith("@");
|
|
@@ -24,12 +24,12 @@ const mastodonHandler = {
|
|
|
24
24
|
resolve: (url) => {
|
|
25
25
|
try {
|
|
26
26
|
const { origin, pathname } = new URL(url);
|
|
27
|
-
const userMatch = pathname.match(
|
|
27
|
+
const userMatch = pathname.match(profileRegex);
|
|
28
28
|
if (userMatch?.[1]) return [{
|
|
29
29
|
uri: `${origin}/@${userMatch[1]}.rss`,
|
|
30
30
|
hint: require_utils.composeHint("mastodon:posts")
|
|
31
31
|
}];
|
|
32
|
-
const tagMatch = pathname.match(
|
|
32
|
+
const tagMatch = pathname.match(tagRegex);
|
|
33
33
|
if (tagMatch?.[1]) return [{
|
|
34
34
|
uri: `${origin}/tags/${tagMatch[1]}.rss`,
|
|
35
35
|
hint: require_utils.composeHint("mastodon:tag")
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { composeHint } from "../../../common/utils.js";
|
|
2
2
|
import { isMastodonHeaders, isMastodonHtml } from "../../../favicons/platform/handlers/mastodon.js";
|
|
3
3
|
//#region src/feeds/platform/handlers/mastodon.ts
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const profileRegex = /^\/@([^/]+)/;
|
|
5
|
+
const tagRegex = /^\/tags\/([^/]+)/;
|
|
6
6
|
const isProfilePath = (pathname) => {
|
|
7
7
|
const segments = pathname.split("/").filter(Boolean);
|
|
8
8
|
return segments.length > 0 && segments[0].startsWith("@");
|
|
@@ -24,12 +24,12 @@ const mastodonHandler = {
|
|
|
24
24
|
resolve: (url) => {
|
|
25
25
|
try {
|
|
26
26
|
const { origin, pathname } = new URL(url);
|
|
27
|
-
const userMatch = pathname.match(
|
|
27
|
+
const userMatch = pathname.match(profileRegex);
|
|
28
28
|
if (userMatch?.[1]) return [{
|
|
29
29
|
uri: `${origin}/@${userMatch[1]}.rss`,
|
|
30
30
|
hint: composeHint("mastodon:posts")
|
|
31
31
|
}];
|
|
32
|
-
const tagMatch = pathname.match(
|
|
32
|
+
const tagMatch = pathname.match(tagRegex);
|
|
33
33
|
if (tagMatch?.[1]) return [{
|
|
34
34
|
uri: `${origin}/tags/${tagMatch[1]}.rss`,
|
|
35
35
|
hint: composeHint("mastodon:tag")
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
//#region src/feeds/platform/handlers/medium.ts
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
3
|
+
const userRegex = /^\/@([^/]+)/;
|
|
4
|
+
const tagRegex = /^\/tag\/([^/]+)/;
|
|
5
|
+
const publicationTagRegex = /^\/([^/@][^/]+)\/tagged\/([^/]+)/;
|
|
6
|
+
const publicationRegex = /^\/([^/@][^/]+)/;
|
|
7
|
+
const subdomainTagRegex = /^\/tagged\/([^/]+)/;
|
|
8
8
|
const hosts = ["medium.com", "www.medium.com"];
|
|
9
9
|
const excludedPaths = [
|
|
10
10
|
"search",
|
|
@@ -21,17 +21,17 @@ const mediumHandler = {
|
|
|
21
21
|
const { hostname, pathname } = new URL(url);
|
|
22
22
|
const lowerHostname = hostname.toLowerCase();
|
|
23
23
|
if (hosts.includes(lowerHostname)) {
|
|
24
|
-
const userMatch = pathname.match(
|
|
24
|
+
const userMatch = pathname.match(userRegex);
|
|
25
25
|
if (userMatch?.[1]) return [{
|
|
26
26
|
uri: `https://medium.com/feed/@${userMatch[1]}`,
|
|
27
27
|
hint: require_utils.composeHint("medium:posts")
|
|
28
28
|
}];
|
|
29
|
-
const tagMatch = pathname.match(
|
|
29
|
+
const tagMatch = pathname.match(tagRegex);
|
|
30
30
|
if (tagMatch?.[1]) return [{
|
|
31
31
|
uri: `https://medium.com/feed/tag/${tagMatch[1]}`,
|
|
32
32
|
hint: require_utils.composeHint("medium:tag")
|
|
33
33
|
}];
|
|
34
|
-
const pubTagMatch = pathname.match(
|
|
34
|
+
const pubTagMatch = pathname.match(publicationTagRegex);
|
|
35
35
|
if (pubTagMatch?.[1] && pubTagMatch?.[2]) {
|
|
36
36
|
const publication = pubTagMatch[1];
|
|
37
37
|
const tag = pubTagMatch[2];
|
|
@@ -40,7 +40,7 @@ const mediumHandler = {
|
|
|
40
40
|
hint: require_utils.composeHint("medium:tagged")
|
|
41
41
|
}];
|
|
42
42
|
}
|
|
43
|
-
const pubMatch = pathname.match(
|
|
43
|
+
const pubMatch = pathname.match(publicationRegex);
|
|
44
44
|
if (pubMatch?.[1]) {
|
|
45
45
|
const publication = pubMatch[1];
|
|
46
46
|
if (!require_utils.isAnyOf(publication, excludedPaths)) return [{
|
|
@@ -51,7 +51,7 @@ const mediumHandler = {
|
|
|
51
51
|
}
|
|
52
52
|
if (lowerHostname.endsWith(".medium.com") && lowerHostname !== "medium.com" && lowerHostname !== "www.medium.com") {
|
|
53
53
|
const subdomain = lowerHostname.replace(".medium.com", "");
|
|
54
|
-
const tagMatch = pathname.match(
|
|
54
|
+
const tagMatch = pathname.match(subdomainTagRegex);
|
|
55
55
|
if (tagMatch?.[1]) return [{
|
|
56
56
|
uri: `https://medium.com/feed/${subdomain}/tagged/${tagMatch[1]}`,
|
|
57
57
|
hint: require_utils.composeHint("medium:tagged")
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { composeHint, isAnyOf, isHostOf, isSubdomainOf } from "../../../common/utils.js";
|
|
2
2
|
//#region src/feeds/platform/handlers/medium.ts
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
3
|
+
const userRegex = /^\/@([^/]+)/;
|
|
4
|
+
const tagRegex = /^\/tag\/([^/]+)/;
|
|
5
|
+
const publicationTagRegex = /^\/([^/@][^/]+)\/tagged\/([^/]+)/;
|
|
6
|
+
const publicationRegex = /^\/([^/@][^/]+)/;
|
|
7
|
+
const subdomainTagRegex = /^\/tagged\/([^/]+)/;
|
|
8
8
|
const hosts = ["medium.com", "www.medium.com"];
|
|
9
9
|
const excludedPaths = [
|
|
10
10
|
"search",
|
|
@@ -21,17 +21,17 @@ const mediumHandler = {
|
|
|
21
21
|
const { hostname, pathname } = new URL(url);
|
|
22
22
|
const lowerHostname = hostname.toLowerCase();
|
|
23
23
|
if (hosts.includes(lowerHostname)) {
|
|
24
|
-
const userMatch = pathname.match(
|
|
24
|
+
const userMatch = pathname.match(userRegex);
|
|
25
25
|
if (userMatch?.[1]) return [{
|
|
26
26
|
uri: `https://medium.com/feed/@${userMatch[1]}`,
|
|
27
27
|
hint: composeHint("medium:posts")
|
|
28
28
|
}];
|
|
29
|
-
const tagMatch = pathname.match(
|
|
29
|
+
const tagMatch = pathname.match(tagRegex);
|
|
30
30
|
if (tagMatch?.[1]) return [{
|
|
31
31
|
uri: `https://medium.com/feed/tag/${tagMatch[1]}`,
|
|
32
32
|
hint: composeHint("medium:tag")
|
|
33
33
|
}];
|
|
34
|
-
const pubTagMatch = pathname.match(
|
|
34
|
+
const pubTagMatch = pathname.match(publicationTagRegex);
|
|
35
35
|
if (pubTagMatch?.[1] && pubTagMatch?.[2]) {
|
|
36
36
|
const publication = pubTagMatch[1];
|
|
37
37
|
const tag = pubTagMatch[2];
|
|
@@ -40,7 +40,7 @@ const mediumHandler = {
|
|
|
40
40
|
hint: composeHint("medium:tagged")
|
|
41
41
|
}];
|
|
42
42
|
}
|
|
43
|
-
const pubMatch = pathname.match(
|
|
43
|
+
const pubMatch = pathname.match(publicationRegex);
|
|
44
44
|
if (pubMatch?.[1]) {
|
|
45
45
|
const publication = pubMatch[1];
|
|
46
46
|
if (!isAnyOf(publication, excludedPaths)) return [{
|
|
@@ -51,7 +51,7 @@ const mediumHandler = {
|
|
|
51
51
|
}
|
|
52
52
|
if (lowerHostname.endsWith(".medium.com") && lowerHostname !== "medium.com" && lowerHostname !== "www.medium.com") {
|
|
53
53
|
const subdomain = lowerHostname.replace(".medium.com", "");
|
|
54
|
-
const tagMatch = pathname.match(
|
|
54
|
+
const tagMatch = pathname.match(subdomainTagRegex);
|
|
55
55
|
if (tagMatch?.[1]) return [{
|
|
56
56
|
uri: `https://medium.com/feed/${subdomain}/tagged/${tagMatch[1]}`,
|
|
57
57
|
hint: composeHint("medium:tagged")
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
//#region src/feeds/platform/handlers/paragraph.ts
|
|
3
3
|
const hosts = ["paragraph.com", "www.paragraph.com"];
|
|
4
|
-
const
|
|
4
|
+
const userRegex = /^\/@([^/]+)/;
|
|
5
5
|
const paragraphHandler = {
|
|
6
6
|
match: (url) => {
|
|
7
7
|
return require_utils.isHostOf(url, hosts);
|
|
8
8
|
},
|
|
9
9
|
resolve: (url) => {
|
|
10
10
|
const { pathname } = new URL(url);
|
|
11
|
-
const userMatch = pathname.match(
|
|
11
|
+
const userMatch = pathname.match(userRegex);
|
|
12
12
|
if (!userMatch?.[1]) return [];
|
|
13
13
|
const username = userMatch[1];
|
|
14
14
|
return [{
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { composeHint, isHostOf } from "../../../common/utils.js";
|
|
2
2
|
//#region src/feeds/platform/handlers/paragraph.ts
|
|
3
3
|
const hosts = ["paragraph.com", "www.paragraph.com"];
|
|
4
|
-
const
|
|
4
|
+
const userRegex = /^\/@([^/]+)/;
|
|
5
5
|
const paragraphHandler = {
|
|
6
6
|
match: (url) => {
|
|
7
7
|
return isHostOf(url, hosts);
|
|
8
8
|
},
|
|
9
9
|
resolve: (url) => {
|
|
10
10
|
const { pathname } = new URL(url);
|
|
11
|
-
const userMatch = pathname.match(
|
|
11
|
+
const userMatch = pathname.match(userRegex);
|
|
12
12
|
if (!userMatch?.[1]) return [];
|
|
13
13
|
const username = userMatch[1];
|
|
14
14
|
return [{
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
//#region src/feeds/platform/handlers/producthunt.ts
|
|
3
3
|
const hosts = ["producthunt.com", "www.producthunt.com"];
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const topicRegex = /^\/topics\/([a-zA-Z0-9_-]+)/;
|
|
5
|
+
const categoryRegex = /^\/categories\/([a-zA-Z0-9_-]+)/;
|
|
6
6
|
const producthuntHandler = {
|
|
7
7
|
match: (url) => {
|
|
8
8
|
return require_utils.isHostOf(url, hosts);
|
|
9
9
|
},
|
|
10
10
|
resolve: (url) => {
|
|
11
11
|
const { pathname } = new URL(url);
|
|
12
|
-
const topicMatch = pathname.match(
|
|
12
|
+
const topicMatch = pathname.match(topicRegex);
|
|
13
13
|
if (topicMatch?.[1]) return [{
|
|
14
14
|
uri: `https://www.producthunt.com/feed?topic=${topicMatch[1]}`,
|
|
15
15
|
hint: require_utils.composeHint("producthunt:topic")
|
|
16
16
|
}];
|
|
17
|
-
const categoryMatch = pathname.match(
|
|
17
|
+
const categoryMatch = pathname.match(categoryRegex);
|
|
18
18
|
if (categoryMatch?.[1]) return [{
|
|
19
19
|
uri: `https://www.producthunt.com/feed?category=${categoryMatch[1]}`,
|
|
20
20
|
hint: require_utils.composeHint("producthunt:category")
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { composeHint, isHostOf } from "../../../common/utils.js";
|
|
2
2
|
//#region src/feeds/platform/handlers/producthunt.ts
|
|
3
3
|
const hosts = ["producthunt.com", "www.producthunt.com"];
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const topicRegex = /^\/topics\/([a-zA-Z0-9_-]+)/;
|
|
5
|
+
const categoryRegex = /^\/categories\/([a-zA-Z0-9_-]+)/;
|
|
6
6
|
const producthuntHandler = {
|
|
7
7
|
match: (url) => {
|
|
8
8
|
return isHostOf(url, hosts);
|
|
9
9
|
},
|
|
10
10
|
resolve: (url) => {
|
|
11
11
|
const { pathname } = new URL(url);
|
|
12
|
-
const topicMatch = pathname.match(
|
|
12
|
+
const topicMatch = pathname.match(topicRegex);
|
|
13
13
|
if (topicMatch?.[1]) return [{
|
|
14
14
|
uri: `https://www.producthunt.com/feed?topic=${topicMatch[1]}`,
|
|
15
15
|
hint: composeHint("producthunt:topic")
|
|
16
16
|
}];
|
|
17
|
-
const categoryMatch = pathname.match(
|
|
17
|
+
const categoryMatch = pathname.match(categoryRegex);
|
|
18
18
|
if (categoryMatch?.[1]) return [{
|
|
19
19
|
uri: `https://www.producthunt.com/feed?category=${categoryMatch[1]}`,
|
|
20
20
|
hint: composeHint("producthunt:category")
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
//#region src/feeds/platform/handlers/reddit.ts
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
3
|
+
const commentsRegex = /^\/r\/([^/]+)\/comments\/([^/]+)/;
|
|
4
|
+
const subredditRegex = /^\/r\/([^/]+)(?:\/([^/]+))?/;
|
|
5
|
+
const multiredditRegex = /^\/user\/([^/]+)\/m\/([^/]+)/;
|
|
6
|
+
const userRegex = /^\/(u|user)\/([^/]+)/;
|
|
7
|
+
const domainRegex = /^\/domain\/([^/]+)/;
|
|
8
8
|
const hosts = [
|
|
9
9
|
"reddit.com",
|
|
10
10
|
"www.reddit.com",
|
|
@@ -28,12 +28,12 @@ const redditHandler = {
|
|
|
28
28
|
uri: "https://www.reddit.com/.rss",
|
|
29
29
|
hint: require_utils.composeHint("reddit:posts")
|
|
30
30
|
}];
|
|
31
|
-
const commentsMatch = pathname.match(
|
|
31
|
+
const commentsMatch = pathname.match(commentsRegex);
|
|
32
32
|
if (commentsMatch?.[1] && commentsMatch?.[2]) return [{
|
|
33
33
|
uri: `https://www.reddit.com/r/${commentsMatch[1]}/comments/${commentsMatch[2]}/.rss`,
|
|
34
34
|
hint: require_utils.composeHint("reddit:post-comments")
|
|
35
35
|
}];
|
|
36
|
-
const subredditMatch = pathname.match(
|
|
36
|
+
const subredditMatch = pathname.match(subredditRegex);
|
|
37
37
|
if (subredditMatch?.[1]) {
|
|
38
38
|
const subreddit = subredditMatch[1];
|
|
39
39
|
const sort = subredditMatch[2];
|
|
@@ -52,17 +52,17 @@ const redditHandler = {
|
|
|
52
52
|
});
|
|
53
53
|
return uris;
|
|
54
54
|
}
|
|
55
|
-
const multiredditMatch = pathname.match(
|
|
55
|
+
const multiredditMatch = pathname.match(multiredditRegex);
|
|
56
56
|
if (multiredditMatch?.[1] && multiredditMatch?.[2]) return [{
|
|
57
57
|
uri: `https://www.reddit.com/user/${multiredditMatch[1]}/m/${multiredditMatch[2]}/.rss`,
|
|
58
58
|
hint: require_utils.composeHint("reddit:multireddit")
|
|
59
59
|
}];
|
|
60
|
-
const userMatch = pathname.match(
|
|
60
|
+
const userMatch = pathname.match(userRegex);
|
|
61
61
|
if (userMatch?.[2]) return [{
|
|
62
62
|
uri: `https://www.reddit.com/user/${userMatch[2]}/.rss`,
|
|
63
63
|
hint: require_utils.composeHint("reddit:posts")
|
|
64
64
|
}];
|
|
65
|
-
const domainMatch = pathname.match(
|
|
65
|
+
const domainMatch = pathname.match(domainRegex);
|
|
66
66
|
if (domainMatch?.[1]) return [{
|
|
67
67
|
uri: `https://www.reddit.com/domain/${domainMatch[1]}/.rss`,
|
|
68
68
|
hint: require_utils.composeHint("reddit:posts")
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { composeHint, isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
2
|
//#region src/feeds/platform/handlers/reddit.ts
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
3
|
+
const commentsRegex = /^\/r\/([^/]+)\/comments\/([^/]+)/;
|
|
4
|
+
const subredditRegex = /^\/r\/([^/]+)(?:\/([^/]+))?/;
|
|
5
|
+
const multiredditRegex = /^\/user\/([^/]+)\/m\/([^/]+)/;
|
|
6
|
+
const userRegex = /^\/(u|user)\/([^/]+)/;
|
|
7
|
+
const domainRegex = /^\/domain\/([^/]+)/;
|
|
8
8
|
const hosts = [
|
|
9
9
|
"reddit.com",
|
|
10
10
|
"www.reddit.com",
|
|
@@ -28,12 +28,12 @@ const redditHandler = {
|
|
|
28
28
|
uri: "https://www.reddit.com/.rss",
|
|
29
29
|
hint: composeHint("reddit:posts")
|
|
30
30
|
}];
|
|
31
|
-
const commentsMatch = pathname.match(
|
|
31
|
+
const commentsMatch = pathname.match(commentsRegex);
|
|
32
32
|
if (commentsMatch?.[1] && commentsMatch?.[2]) return [{
|
|
33
33
|
uri: `https://www.reddit.com/r/${commentsMatch[1]}/comments/${commentsMatch[2]}/.rss`,
|
|
34
34
|
hint: composeHint("reddit:post-comments")
|
|
35
35
|
}];
|
|
36
|
-
const subredditMatch = pathname.match(
|
|
36
|
+
const subredditMatch = pathname.match(subredditRegex);
|
|
37
37
|
if (subredditMatch?.[1]) {
|
|
38
38
|
const subreddit = subredditMatch[1];
|
|
39
39
|
const sort = subredditMatch[2];
|
|
@@ -52,17 +52,17 @@ const redditHandler = {
|
|
|
52
52
|
});
|
|
53
53
|
return uris;
|
|
54
54
|
}
|
|
55
|
-
const multiredditMatch = pathname.match(
|
|
55
|
+
const multiredditMatch = pathname.match(multiredditRegex);
|
|
56
56
|
if (multiredditMatch?.[1] && multiredditMatch?.[2]) return [{
|
|
57
57
|
uri: `https://www.reddit.com/user/${multiredditMatch[1]}/m/${multiredditMatch[2]}/.rss`,
|
|
58
58
|
hint: composeHint("reddit:multireddit")
|
|
59
59
|
}];
|
|
60
|
-
const userMatch = pathname.match(
|
|
60
|
+
const userMatch = pathname.match(userRegex);
|
|
61
61
|
if (userMatch?.[2]) return [{
|
|
62
62
|
uri: `https://www.reddit.com/user/${userMatch[2]}/.rss`,
|
|
63
63
|
hint: composeHint("reddit:posts")
|
|
64
64
|
}];
|
|
65
|
-
const domainMatch = pathname.match(
|
|
65
|
+
const domainMatch = pathname.match(domainRegex);
|
|
66
66
|
if (domainMatch?.[1]) return [{
|
|
67
67
|
uri: `https://www.reddit.com/domain/${domainMatch[1]}/.rss`,
|
|
68
68
|
hint: composeHint("reddit:posts")
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
//#region src/feeds/platform/handlers/stackExchange.ts
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
3
|
+
const tagRegex = /^\/questions\/tagged\/([\w.+-]+)/;
|
|
4
|
+
const questionRegex = /^\/questions\/(\d+)/;
|
|
5
|
+
const userRegex = /^\/users\/(\d+)/;
|
|
6
6
|
const domains = [
|
|
7
7
|
"stackoverflow.com",
|
|
8
8
|
"serverfault.com",
|
|
@@ -18,17 +18,17 @@ const stackExchangeHandler = {
|
|
|
18
18
|
},
|
|
19
19
|
resolve: (url) => {
|
|
20
20
|
const { origin, pathname } = new URL(url);
|
|
21
|
-
const tagMatch = pathname.match(
|
|
21
|
+
const tagMatch = pathname.match(tagRegex);
|
|
22
22
|
if (tagMatch?.[1]) return [{
|
|
23
23
|
uri: `${origin}/feeds/tag/${tagMatch[1]}`,
|
|
24
24
|
hint: require_utils.composeHint("stackexchange:tag")
|
|
25
25
|
}];
|
|
26
|
-
const questionMatch = pathname.match(
|
|
26
|
+
const questionMatch = pathname.match(questionRegex);
|
|
27
27
|
if (questionMatch?.[1]) return [{
|
|
28
28
|
uri: `${origin}/feeds/question/${questionMatch[1]}`,
|
|
29
29
|
hint: require_utils.composeHint("stackexchange:question")
|
|
30
30
|
}];
|
|
31
|
-
const userMatch = pathname.match(
|
|
31
|
+
const userMatch = pathname.match(userRegex);
|
|
32
32
|
if (userMatch?.[1]) return [{
|
|
33
33
|
uri: `${origin}/feeds/user/${userMatch[1]}`,
|
|
34
34
|
hint: require_utils.composeHint("stackexchange:user")
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { composeHint, isHostOf, isSubdomainOf } from "../../../common/utils.js";
|
|
2
2
|
//#region src/feeds/platform/handlers/stackExchange.ts
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
3
|
+
const tagRegex = /^\/questions\/tagged\/([\w.+-]+)/;
|
|
4
|
+
const questionRegex = /^\/questions\/(\d+)/;
|
|
5
|
+
const userRegex = /^\/users\/(\d+)/;
|
|
6
6
|
const domains = [
|
|
7
7
|
"stackoverflow.com",
|
|
8
8
|
"serverfault.com",
|
|
@@ -18,17 +18,17 @@ const stackExchangeHandler = {
|
|
|
18
18
|
},
|
|
19
19
|
resolve: (url) => {
|
|
20
20
|
const { origin, pathname } = new URL(url);
|
|
21
|
-
const tagMatch = pathname.match(
|
|
21
|
+
const tagMatch = pathname.match(tagRegex);
|
|
22
22
|
if (tagMatch?.[1]) return [{
|
|
23
23
|
uri: `${origin}/feeds/tag/${tagMatch[1]}`,
|
|
24
24
|
hint: composeHint("stackexchange:tag")
|
|
25
25
|
}];
|
|
26
|
-
const questionMatch = pathname.match(
|
|
26
|
+
const questionMatch = pathname.match(questionRegex);
|
|
27
27
|
if (questionMatch?.[1]) return [{
|
|
28
28
|
uri: `${origin}/feeds/question/${questionMatch[1]}`,
|
|
29
29
|
hint: composeHint("stackexchange:question")
|
|
30
30
|
}];
|
|
31
|
-
const userMatch = pathname.match(
|
|
31
|
+
const userMatch = pathname.match(userRegex);
|
|
32
32
|
if (userMatch?.[1]) return [{
|
|
33
33
|
uri: `${origin}/feeds/user/${userMatch[1]}`,
|
|
34
34
|
hint: composeHint("stackexchange:user")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
//#region src/feeds/platform/handlers/steam.ts
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const appRegex = /^\/(?:news\/)?app\/(\d+)/;
|
|
4
|
+
const groupRegex = /^\/groups\/([^/]+)/;
|
|
5
5
|
const hosts = ["store.steampowered.com", "steamcommunity.com"];
|
|
6
6
|
const steamHandler = {
|
|
7
7
|
match: (url) => {
|
|
@@ -9,13 +9,13 @@ const steamHandler = {
|
|
|
9
9
|
},
|
|
10
10
|
resolve: (url) => {
|
|
11
11
|
const { hostname, pathname } = new URL(url);
|
|
12
|
-
const appMatch = pathname.match(
|
|
12
|
+
const appMatch = pathname.match(appRegex);
|
|
13
13
|
if (appMatch?.[1]) return [{
|
|
14
14
|
uri: `https://store.steampowered.com/feeds/news/app/${appMatch[1]}/`,
|
|
15
15
|
hint: require_utils.composeHint("steam:news")
|
|
16
16
|
}];
|
|
17
17
|
if (hostname === "steamcommunity.com") {
|
|
18
|
-
const groupMatch = pathname.match(
|
|
18
|
+
const groupMatch = pathname.match(groupRegex);
|
|
19
19
|
if (groupMatch?.[1]) return [{
|
|
20
20
|
uri: `https://steamcommunity.com/groups/${groupMatch[1]}/rss`,
|
|
21
21
|
hint: require_utils.composeHint("steam:group")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { composeHint, isHostOf } from "../../../common/utils.js";
|
|
2
2
|
//#region src/feeds/platform/handlers/steam.ts
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const appRegex = /^\/(?:news\/)?app\/(\d+)/;
|
|
4
|
+
const groupRegex = /^\/groups\/([^/]+)/;
|
|
5
5
|
const hosts = ["store.steampowered.com", "steamcommunity.com"];
|
|
6
6
|
const steamHandler = {
|
|
7
7
|
match: (url) => {
|
|
@@ -9,13 +9,13 @@ const steamHandler = {
|
|
|
9
9
|
},
|
|
10
10
|
resolve: (url) => {
|
|
11
11
|
const { hostname, pathname } = new URL(url);
|
|
12
|
-
const appMatch = pathname.match(
|
|
12
|
+
const appMatch = pathname.match(appRegex);
|
|
13
13
|
if (appMatch?.[1]) return [{
|
|
14
14
|
uri: `https://store.steampowered.com/feeds/news/app/${appMatch[1]}/`,
|
|
15
15
|
hint: composeHint("steam:news")
|
|
16
16
|
}];
|
|
17
17
|
if (hostname === "steamcommunity.com") {
|
|
18
|
-
const groupMatch = pathname.match(
|
|
18
|
+
const groupMatch = pathname.match(groupRegex);
|
|
19
19
|
if (groupMatch?.[1]) return [{
|
|
20
20
|
uri: `https://steamcommunity.com/groups/${groupMatch[1]}/rss`,
|
|
21
21
|
hint: composeHint("steam:group")
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
//#region src/feeds/platform/handlers/substack.ts
|
|
3
|
+
const profileRegex = /^\/@([\w-]+)/;
|
|
3
4
|
const substackHandler = {
|
|
4
5
|
match: (url) => {
|
|
5
|
-
|
|
6
|
+
if (require_utils.isSubdomainOf(url, "substack.com")) return true;
|
|
7
|
+
return require_utils.isHostOf(url, "substack.com") && profileRegex.test(new URL(url).pathname);
|
|
6
8
|
},
|
|
7
9
|
resolve: (url) => {
|
|
8
|
-
const
|
|
10
|
+
const parsed = new URL(url);
|
|
11
|
+
const profileMatch = parsed.pathname.match(profileRegex);
|
|
12
|
+
if (require_utils.isHostOf(url, "substack.com") && profileMatch?.[1]) return [{
|
|
13
|
+
uri: `https://${profileMatch[1]}.substack.com/feed`,
|
|
14
|
+
hint: require_utils.composeHint("substack:newsletter")
|
|
15
|
+
}];
|
|
9
16
|
return [{
|
|
10
|
-
uri: `${origin}/feed`,
|
|
17
|
+
uri: `${parsed.origin}/feed`,
|
|
11
18
|
hint: require_utils.composeHint("substack:newsletter")
|
|
12
19
|
}];
|
|
13
20
|
}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import { composeHint, isSubdomainOf } from "../../../common/utils.js";
|
|
1
|
+
import { composeHint, isHostOf, isSubdomainOf } from "../../../common/utils.js";
|
|
2
2
|
//#region src/feeds/platform/handlers/substack.ts
|
|
3
|
+
const profileRegex = /^\/@([\w-]+)/;
|
|
3
4
|
const substackHandler = {
|
|
4
5
|
match: (url) => {
|
|
5
|
-
|
|
6
|
+
if (isSubdomainOf(url, "substack.com")) return true;
|
|
7
|
+
return isHostOf(url, "substack.com") && profileRegex.test(new URL(url).pathname);
|
|
6
8
|
},
|
|
7
9
|
resolve: (url) => {
|
|
8
|
-
const
|
|
10
|
+
const parsed = new URL(url);
|
|
11
|
+
const profileMatch = parsed.pathname.match(profileRegex);
|
|
12
|
+
if (isHostOf(url, "substack.com") && profileMatch?.[1]) return [{
|
|
13
|
+
uri: `https://${profileMatch[1]}.substack.com/feed`,
|
|
14
|
+
hint: composeHint("substack:newsletter")
|
|
15
|
+
}];
|
|
9
16
|
return [{
|
|
10
|
-
uri: `${origin}/feed`,
|
|
17
|
+
uri: `${parsed.origin}/feed`,
|
|
11
18
|
hint: composeHint("substack:newsletter")
|
|
12
19
|
}];
|
|
13
20
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
//#region src/feeds/platform/handlers/tumblr.ts
|
|
3
3
|
const domains = ["tumblr.com"];
|
|
4
|
-
const
|
|
4
|
+
const tagRegex = /^\/tagged\/([^/]+)/;
|
|
5
5
|
const tumblrHandler = {
|
|
6
6
|
match: (url) => {
|
|
7
7
|
return require_utils.isSubdomainOf(url, domains);
|
|
8
8
|
},
|
|
9
9
|
resolve: (url) => {
|
|
10
10
|
const { origin, pathname } = new URL(url);
|
|
11
|
-
const tagMatch = pathname.match(
|
|
11
|
+
const tagMatch = pathname.match(tagRegex);
|
|
12
12
|
if (tagMatch?.[1]) return [{
|
|
13
13
|
uri: `${origin}/tagged/${tagMatch[1]}/rss`,
|
|
14
14
|
hint: require_utils.composeHint("tumblr:tag")
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { composeHint, isSubdomainOf } from "../../../common/utils.js";
|
|
2
2
|
//#region src/feeds/platform/handlers/tumblr.ts
|
|
3
3
|
const domains = ["tumblr.com"];
|
|
4
|
-
const
|
|
4
|
+
const tagRegex = /^\/tagged\/([^/]+)/;
|
|
5
5
|
const tumblrHandler = {
|
|
6
6
|
match: (url) => {
|
|
7
7
|
return isSubdomainOf(url, domains);
|
|
8
8
|
},
|
|
9
9
|
resolve: (url) => {
|
|
10
10
|
const { origin, pathname } = new URL(url);
|
|
11
|
-
const tagMatch = pathname.match(
|
|
11
|
+
const tagMatch = pathname.match(tagRegex);
|
|
12
12
|
if (tagMatch?.[1]) return [{
|
|
13
13
|
uri: `${origin}/tagged/${tagMatch[1]}/rss`,
|
|
14
14
|
hint: composeHint("tumblr:tag")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
//#region src/feeds/platform/handlers/v2ex.ts
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const nodeRegex = /^\/go\/([^/]+)/;
|
|
4
|
+
const memberRegex = /^\/member\/([^/]+)/;
|
|
5
5
|
const hosts = ["www.v2ex.com", "v2ex.com"];
|
|
6
6
|
const v2exHandler = {
|
|
7
7
|
match: (url) => {
|
|
@@ -9,12 +9,12 @@ const v2exHandler = {
|
|
|
9
9
|
},
|
|
10
10
|
resolve: (url) => {
|
|
11
11
|
const { pathname, searchParams } = new URL(url);
|
|
12
|
-
const nodeMatch = pathname.match(
|
|
12
|
+
const nodeMatch = pathname.match(nodeRegex);
|
|
13
13
|
if (nodeMatch?.[1]) return [{
|
|
14
14
|
uri: `https://www.v2ex.com/feed/${nodeMatch[1]}.xml`,
|
|
15
15
|
hint: require_utils.composeHint("v2ex:node")
|
|
16
16
|
}];
|
|
17
|
-
const memberMatch = pathname.match(
|
|
17
|
+
const memberMatch = pathname.match(memberRegex);
|
|
18
18
|
if (memberMatch?.[1]) return [{
|
|
19
19
|
uri: `https://www.v2ex.com/feed/member/${memberMatch[1]}.xml`,
|
|
20
20
|
hint: require_utils.composeHint("v2ex:member")
|