feedscout 1.7.1 → 1.8.1
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/blogrolls/extractors.cjs +2 -2
- package/dist/blogrolls/extractors.d.cts +2 -2
- package/dist/blogrolls/extractors.d.ts +2 -2
- package/dist/blogrolls/extractors.js +2 -2
- package/dist/blogrolls/index.cjs +9 -10
- package/dist/blogrolls/index.js +4 -5
- package/dist/blogrolls.cjs +1 -1
- package/dist/blogrolls.d.cts +2 -2
- package/dist/blogrolls.d.ts +2 -2
- package/dist/blogrolls.js +2 -2
- package/dist/common/discover/defaults.cjs +46 -0
- package/dist/common/discover/defaults.d.cts +6 -0
- package/dist/common/discover/defaults.d.ts +6 -0
- package/dist/common/discover/defaults.js +44 -0
- package/dist/common/discover/index.cjs +7 -7
- package/dist/common/discover/index.js +2 -2
- package/dist/common/discover/utils.cjs +9 -35
- package/dist/common/discover/utils.d.cts +1 -3
- package/dist/common/discover/utils.d.ts +1 -3
- package/dist/common/discover/utils.js +10 -34
- package/dist/common/locales.cjs +11 -4
- package/dist/common/locales.js +11 -4
- package/dist/common/types.d.cts +5 -4
- package/dist/common/types.d.ts +5 -4
- 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/common/utils.cjs +0 -8
- package/dist/common/utils.js +1 -8
- package/dist/favicons/defaults.cjs +6 -1
- package/dist/favicons/defaults.js +6 -1
- package/dist/favicons/extractors.cjs +2 -2
- package/dist/favicons/extractors.d.cts +2 -2
- package/dist/favicons/extractors.d.ts +2 -2
- package/dist/favicons/extractors.js +2 -2
- package/dist/favicons/index.cjs +11 -12
- package/dist/favicons/index.js +4 -5
- 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/favicons.cjs +1 -1
- package/dist/favicons.d.cts +2 -2
- package/dist/favicons.d.ts +2 -2
- package/dist/favicons.js +2 -2
- package/dist/feeds/defaults.cjs +4 -2
- package/dist/feeds/defaults.js +4 -2
- package/dist/feeds/extractors.cjs +6 -6
- package/dist/feeds/extractors.d.cts +2 -2
- package/dist/feeds/extractors.d.ts +2 -2
- package/dist/feeds/extractors.js +4 -4
- package/dist/feeds/index.cjs +9 -10
- package/dist/feeds/index.js +4 -5
- 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/feeds.cjs +1 -1
- package/dist/feeds.d.cts +2 -2
- package/dist/feeds.d.ts +2 -2
- package/dist/feeds.js +2 -2
- package/dist/hubs/discover/index.cjs +4 -5
- package/dist/hubs/discover/index.js +3 -4
- package/dist/hubs/feed/index.cjs +2 -2
- package/dist/hubs/feed/index.js +2 -2
- package/dist/hubs/headers/index.cjs +2 -2
- package/dist/hubs/headers/index.js +2 -2
- package/dist/hubs/html/index.cjs +2 -2
- package/dist/hubs/html/index.js +2 -2
- package/dist/index.cjs +2 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/package.json +3 -2
- package/dist/hubs/discover/utils.cjs +0 -18
- package/dist/hubs/discover/utils.js +0 -18
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { DiscoverFetchFn, DiscoverUriEntry } from "../../types.js";
|
|
1
|
+
import { DiscoverFetchFn, DiscoverUriEntry, MaybePromise } from "../../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/common/uris/platform/types.d.ts
|
|
4
4
|
type PlatformHandler = {
|
|
5
5
|
match: (url: string, content?: string, headers?: Headers) => boolean;
|
|
6
|
-
resolve: (url: string, content?: string, headers?: Headers, fetchFn?: DiscoverFetchFn) =>
|
|
6
|
+
resolve: (url: string, content?: string, headers?: Headers, fetchFn?: DiscoverFetchFn) => MaybePromise<Array<DiscoverUriEntry>>;
|
|
7
7
|
};
|
|
8
8
|
type PlatformMethodOptions = {
|
|
9
9
|
baseUrl: string;
|
package/dist/common/utils.cjs
CHANGED
|
@@ -52,13 +52,6 @@ const omitEmpty = (array) => {
|
|
|
52
52
|
for (const item of array) if (item != null && item !== "") result.push(item);
|
|
53
53
|
return result;
|
|
54
54
|
};
|
|
55
|
-
const resolveUrl = (url, baseUrl) => {
|
|
56
|
-
try {
|
|
57
|
-
return new URL(url, baseUrl).href;
|
|
58
|
-
} catch {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
55
|
const matchesAnyOfLinkSelectors = (rel, type, selectors) => {
|
|
63
56
|
return selectors.some((selector) => {
|
|
64
57
|
if (!anyWordMatchesAnyOf(rel, [selector.rel])) return false;
|
|
@@ -94,4 +87,3 @@ exports.isSubdomainOf = isSubdomainOf;
|
|
|
94
87
|
exports.matchesAnyOfLinkSelectors = matchesAnyOfLinkSelectors;
|
|
95
88
|
exports.omitEmpty = omitEmpty;
|
|
96
89
|
exports.processConcurrently = processConcurrently;
|
|
97
|
-
exports.resolveUrl = resolveUrl;
|
package/dist/common/utils.js
CHANGED
|
@@ -52,13 +52,6 @@ const omitEmpty = (array) => {
|
|
|
52
52
|
for (const item of array) if (item != null && item !== "") result.push(item);
|
|
53
53
|
return result;
|
|
54
54
|
};
|
|
55
|
-
const resolveUrl = (url, baseUrl) => {
|
|
56
|
-
try {
|
|
57
|
-
return new URL(url, baseUrl).href;
|
|
58
|
-
} catch {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
55
|
const matchesAnyOfLinkSelectors = (rel, type, selectors) => {
|
|
63
56
|
return selectors.some((selector) => {
|
|
64
57
|
if (!anyWordMatchesAnyOf(rel, [selector.rel])) return false;
|
|
@@ -83,4 +76,4 @@ const processConcurrently = async (items, processFn, options) => {
|
|
|
83
76
|
}
|
|
84
77
|
};
|
|
85
78
|
//#endregion
|
|
86
|
-
export { anyWordMatchesAnyOf, composeHint, endsWithAnyOf, hasMetaContent, includesAnyOf, isAnyOf, isHostOf, isSubdomainOf, matchesAnyOfLinkSelectors, omitEmpty, processConcurrently
|
|
79
|
+
export { anyWordMatchesAnyOf, composeHint, endsWithAnyOf, hasMetaContent, includesAnyOf, isAnyOf, isHostOf, isSubdomainOf, matchesAnyOfLinkSelectors, omitEmpty, processConcurrently };
|
|
@@ -2,8 +2,10 @@ const require_utils = require("../common/utils.cjs");
|
|
|
2
2
|
const require_bluesky = require("./platform/handlers/bluesky.cjs");
|
|
3
3
|
const require_codeberg = require("./platform/handlers/codeberg.cjs");
|
|
4
4
|
const require_deviantart = require("./platform/handlers/deviantart.cjs");
|
|
5
|
+
const require_devto = require("./platform/handlers/devto.cjs");
|
|
5
6
|
const require_github = require("./platform/handlers/github.cjs");
|
|
6
7
|
const require_githubGist = require("./platform/handlers/githubGist.cjs");
|
|
8
|
+
const require_gitlab = require("./platform/handlers/gitlab.cjs");
|
|
7
9
|
const require_lobsters = require("./platform/handlers/lobsters.cjs");
|
|
8
10
|
const require_mastodon = require("./platform/handlers/mastodon.cjs");
|
|
9
11
|
const require_reddit = require("./platform/handlers/reddit.cjs");
|
|
@@ -13,6 +15,7 @@ const require_tumblr = require("./platform/handlers/tumblr.cjs");
|
|
|
13
15
|
const defaultIconRels = [
|
|
14
16
|
"icon",
|
|
15
17
|
"shortcut",
|
|
18
|
+
"alternate icon",
|
|
16
19
|
"apple-touch-icon",
|
|
17
20
|
"apple-touch-icon-precomposed"
|
|
18
21
|
];
|
|
@@ -40,6 +43,7 @@ const defaultGuessOptions = { uris: defaultGuessPaths };
|
|
|
40
43
|
const defaultPlatformOptions = { handlers: [
|
|
41
44
|
require_github.githubHandler,
|
|
42
45
|
require_githubGist.githubGistHandler,
|
|
46
|
+
require_gitlab.gitlabHandler,
|
|
43
47
|
require_mastodon.mastodonHandler,
|
|
44
48
|
require_bluesky.blueskyHandler,
|
|
45
49
|
require_reddit.redditHandler,
|
|
@@ -47,7 +51,8 @@ const defaultPlatformOptions = { handlers: [
|
|
|
47
51
|
require_codeberg.codebergHandler,
|
|
48
52
|
require_lobsters.lobstersHandler,
|
|
49
53
|
require_sourceforge.sourceforgeHandler,
|
|
50
|
-
require_deviantart.deviantartHandler
|
|
54
|
+
require_deviantart.deviantartHandler,
|
|
55
|
+
require_devto.devtoHandler
|
|
51
56
|
] };
|
|
52
57
|
//#endregion
|
|
53
58
|
exports.defaultFeedOptions = defaultFeedOptions;
|
|
@@ -2,8 +2,10 @@ import { omitEmpty } from "../common/utils.js";
|
|
|
2
2
|
import { blueskyHandler } from "./platform/handlers/bluesky.js";
|
|
3
3
|
import { codebergHandler } from "./platform/handlers/codeberg.js";
|
|
4
4
|
import { deviantartHandler } from "./platform/handlers/deviantart.js";
|
|
5
|
+
import { devtoHandler } from "./platform/handlers/devto.js";
|
|
5
6
|
import { githubHandler } from "./platform/handlers/github.js";
|
|
6
7
|
import { githubGistHandler } from "./platform/handlers/githubGist.js";
|
|
8
|
+
import { gitlabHandler } from "./platform/handlers/gitlab.js";
|
|
7
9
|
import { lobstersHandler } from "./platform/handlers/lobsters.js";
|
|
8
10
|
import { mastodonHandler } from "./platform/handlers/mastodon.js";
|
|
9
11
|
import { redditHandler } from "./platform/handlers/reddit.js";
|
|
@@ -13,6 +15,7 @@ import { tumblrHandler } from "./platform/handlers/tumblr.js";
|
|
|
13
15
|
const defaultIconRels = [
|
|
14
16
|
"icon",
|
|
15
17
|
"shortcut",
|
|
18
|
+
"alternate icon",
|
|
16
19
|
"apple-touch-icon",
|
|
17
20
|
"apple-touch-icon-precomposed"
|
|
18
21
|
];
|
|
@@ -40,6 +43,7 @@ const defaultGuessOptions = { uris: defaultGuessPaths };
|
|
|
40
43
|
const defaultPlatformOptions = { handlers: [
|
|
41
44
|
githubHandler,
|
|
42
45
|
githubGistHandler,
|
|
46
|
+
gitlabHandler,
|
|
43
47
|
mastodonHandler,
|
|
44
48
|
blueskyHandler,
|
|
45
49
|
redditHandler,
|
|
@@ -47,7 +51,8 @@ const defaultPlatformOptions = { handlers: [
|
|
|
47
51
|
codebergHandler,
|
|
48
52
|
lobstersHandler,
|
|
49
53
|
sourceforgeHandler,
|
|
50
|
-
deviantartHandler
|
|
54
|
+
deviantartHandler,
|
|
55
|
+
devtoHandler
|
|
51
56
|
] };
|
|
52
57
|
//#endregion
|
|
53
58
|
export { defaultFeedOptions, defaultGuessOptions, defaultGuessPaths, defaultHeadersOptions, defaultHtmlOptions, defaultIconRels, defaultPlatformOptions, linkSelectors };
|
|
@@ -11,7 +11,7 @@ const isImageContent = (content) => {
|
|
|
11
11
|
const isSuccessStatus = (status) => {
|
|
12
12
|
return status !== void 0 && status >= 200 && status < 400;
|
|
13
13
|
};
|
|
14
|
-
const
|
|
14
|
+
const defaultExtractFn = (input) => {
|
|
15
15
|
if (isImageContentType(input.headers) || isImageContent(input.content) || isSuccessStatus(input.status)) return {
|
|
16
16
|
url: input.url,
|
|
17
17
|
isValid: true
|
|
@@ -22,4 +22,4 @@ const defaultExtractor = (input) => {
|
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
//#endregion
|
|
25
|
-
exports.
|
|
25
|
+
exports.defaultExtractFn = defaultExtractFn;
|
|
@@ -2,6 +2,6 @@ import { DiscoverExtractFn } from "../common/types.cjs";
|
|
|
2
2
|
import { FaviconResult } from "./types.cjs";
|
|
3
3
|
|
|
4
4
|
//#region src/favicons/extractors.d.ts
|
|
5
|
-
declare const
|
|
5
|
+
declare const defaultExtractFn: DiscoverExtractFn<FaviconResult>;
|
|
6
6
|
//#endregion
|
|
7
|
-
export {
|
|
7
|
+
export { defaultExtractFn };
|
|
@@ -2,6 +2,6 @@ import { DiscoverExtractFn } from "../common/types.js";
|
|
|
2
2
|
import { FaviconResult } from "./types.js";
|
|
3
3
|
|
|
4
4
|
//#region src/favicons/extractors.d.ts
|
|
5
|
-
declare const
|
|
5
|
+
declare const defaultExtractFn: DiscoverExtractFn<FaviconResult>;
|
|
6
6
|
//#endregion
|
|
7
|
-
export {
|
|
7
|
+
export { defaultExtractFn };
|
|
@@ -11,7 +11,7 @@ const isImageContent = (content) => {
|
|
|
11
11
|
const isSuccessStatus = (status) => {
|
|
12
12
|
return status !== void 0 && status >= 200 && status < 400;
|
|
13
13
|
};
|
|
14
|
-
const
|
|
14
|
+
const defaultExtractFn = (input) => {
|
|
15
15
|
if (isImageContentType(input.headers) || isImageContent(input.content) || isSuccessStatus(input.status)) return {
|
|
16
16
|
url: input.url,
|
|
17
17
|
isValid: true
|
|
@@ -22,4 +22,4 @@ const defaultExtractor = (input) => {
|
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
//#endregion
|
|
25
|
-
export {
|
|
25
|
+
export { defaultExtractFn };
|
package/dist/favicons/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
const
|
|
2
|
-
const require_utils$1 = require("../common/discover/utils.cjs");
|
|
1
|
+
const require_defaults = require("../common/discover/defaults.cjs");
|
|
3
2
|
const require_index = require("../common/discover/index.cjs");
|
|
4
|
-
const require_defaults = require("./defaults.cjs");
|
|
3
|
+
const require_defaults$1 = require("./defaults.cjs");
|
|
5
4
|
const require_extractors = require("./extractors.cjs");
|
|
6
5
|
//#region src/favicons/index.ts
|
|
7
6
|
const discoverFavicons = (input, options = {}) => {
|
|
@@ -14,16 +13,16 @@ const discoverFavicons = (input, options = {}) => {
|
|
|
14
13
|
"headers",
|
|
15
14
|
"guess"
|
|
16
15
|
],
|
|
17
|
-
fetchFn: options.fetchFn ??
|
|
18
|
-
extractFn: options.extractFn ?? require_extractors.
|
|
19
|
-
resolveUrlFn: options.resolveUrlFn ??
|
|
20
|
-
resolveSiteUrlFn: options.resolveSiteUrlFn ??
|
|
16
|
+
fetchFn: options.fetchFn ?? require_defaults.defaultFetchFn,
|
|
17
|
+
extractFn: options.extractFn ?? require_extractors.defaultExtractFn,
|
|
18
|
+
resolveUrlFn: options.resolveUrlFn ?? require_defaults.defaultResolveUrlFn,
|
|
19
|
+
resolveSiteUrlFn: options.resolveSiteUrlFn ?? require_defaults.defaultResolveSiteUrlFn
|
|
21
20
|
}, {
|
|
22
|
-
platform: require_defaults.defaultPlatformOptions,
|
|
23
|
-
feed: require_defaults.defaultFeedOptions,
|
|
24
|
-
html: require_defaults.defaultHtmlOptions,
|
|
25
|
-
headers: require_defaults.defaultHeadersOptions,
|
|
26
|
-
guess: require_defaults.defaultGuessOptions
|
|
21
|
+
platform: require_defaults$1.defaultPlatformOptions,
|
|
22
|
+
feed: require_defaults$1.defaultFeedOptions,
|
|
23
|
+
html: require_defaults$1.defaultHtmlOptions,
|
|
24
|
+
headers: require_defaults$1.defaultHeadersOptions,
|
|
25
|
+
guess: require_defaults$1.defaultGuessOptions
|
|
27
26
|
});
|
|
28
27
|
};
|
|
29
28
|
//#endregion
|
package/dist/favicons/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { defaultFetchFn, defaultResolveSiteUrlFn } from "../common/discover/utils.js";
|
|
1
|
+
import { defaultFetchFn, defaultResolveSiteUrlFn, defaultResolveUrlFn } from "../common/discover/defaults.js";
|
|
3
2
|
import { discover } from "../common/discover/index.js";
|
|
4
3
|
import { defaultFeedOptions, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions } from "./defaults.js";
|
|
5
|
-
import {
|
|
4
|
+
import { defaultExtractFn } from "./extractors.js";
|
|
6
5
|
//#region src/favicons/index.ts
|
|
7
6
|
const discoverFavicons = (input, options = {}) => {
|
|
8
7
|
return discover(input, {
|
|
@@ -15,8 +14,8 @@ const discoverFavicons = (input, options = {}) => {
|
|
|
15
14
|
"guess"
|
|
16
15
|
],
|
|
17
16
|
fetchFn: options.fetchFn ?? defaultFetchFn,
|
|
18
|
-
extractFn: options.extractFn ??
|
|
19
|
-
resolveUrlFn: options.resolveUrlFn ??
|
|
17
|
+
extractFn: options.extractFn ?? defaultExtractFn,
|
|
18
|
+
resolveUrlFn: options.resolveUrlFn ?? defaultResolveUrlFn,
|
|
20
19
|
resolveSiteUrlFn: options.resolveSiteUrlFn ?? defaultResolveSiteUrlFn
|
|
21
20
|
}, {
|
|
22
21
|
platform: defaultPlatformOptions,
|
|
@@ -9,7 +9,7 @@ const isProfilePath = (pathname) => {
|
|
|
9
9
|
const blueskyHandler = {
|
|
10
10
|
match: (url) => {
|
|
11
11
|
try {
|
|
12
|
-
return
|
|
12
|
+
return isProfilePath(new URL(url).pathname) && require_utils.isHostOf(url, hosts);
|
|
13
13
|
} catch {}
|
|
14
14
|
return false;
|
|
15
15
|
},
|
|
@@ -9,7 +9,7 @@ const isProfilePath = (pathname) => {
|
|
|
9
9
|
const blueskyHandler = {
|
|
10
10
|
match: (url) => {
|
|
11
11
|
try {
|
|
12
|
-
return
|
|
12
|
+
return isProfilePath(new URL(url).pathname) && isHostOf(url, hosts);
|
|
13
13
|
} catch {}
|
|
14
14
|
return false;
|
|
15
15
|
},
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
const require_codeberg = require("../../../feeds/platform/handlers/codeberg.cjs");
|
|
3
3
|
//#region src/favicons/platform/handlers/codeberg.ts
|
|
4
|
+
const userRegex = /^\/([^/.]+)/;
|
|
4
5
|
const codebergHandler = {
|
|
5
6
|
match: (url) => {
|
|
6
7
|
return require_utils.isHostOf(url, require_codeberg.hosts);
|
|
7
8
|
},
|
|
8
9
|
resolve: (url) => {
|
|
9
10
|
const { origin, pathname } = new URL(url);
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
const username =
|
|
11
|
+
const match = pathname.match(userRegex);
|
|
12
|
+
if (!match?.[1]) return [];
|
|
13
|
+
const username = match[1];
|
|
13
14
|
if (require_utils.isAnyOf(username, require_codeberg.excludedPaths)) return [];
|
|
14
15
|
return [{ uri: `${origin}/user/avatar/${username}/512` }];
|
|
15
16
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
2
|
import { excludedPaths, hosts } from "../../../feeds/platform/handlers/codeberg.js";
|
|
3
3
|
//#region src/favicons/platform/handlers/codeberg.ts
|
|
4
|
+
const userRegex = /^\/([^/.]+)/;
|
|
4
5
|
const codebergHandler = {
|
|
5
6
|
match: (url) => {
|
|
6
7
|
return isHostOf(url, hosts);
|
|
7
8
|
},
|
|
8
9
|
resolve: (url) => {
|
|
9
10
|
const { origin, pathname } = new URL(url);
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
const username =
|
|
11
|
+
const match = pathname.match(userRegex);
|
|
12
|
+
if (!match?.[1]) return [];
|
|
13
|
+
const username = match[1];
|
|
13
14
|
if (isAnyOf(username, excludedPaths)) return [];
|
|
14
15
|
return [{ uri: `${origin}/user/avatar/${username}/512` }];
|
|
15
16
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const require_utils = require("../../../common/utils.cjs");
|
|
2
|
+
const require_utils$1 = require("../../utils.cjs");
|
|
3
|
+
const require_devto = require("../../../feeds/platform/handlers/devto.cjs");
|
|
4
|
+
//#region src/favicons/platform/handlers/devto.ts
|
|
5
|
+
const userRegex = /^\/([^/.]+)/;
|
|
6
|
+
const devtoHandler = {
|
|
7
|
+
match: (url) => {
|
|
8
|
+
try {
|
|
9
|
+
const { pathname } = new URL(url);
|
|
10
|
+
const match = pathname.match(userRegex);
|
|
11
|
+
if (!require_utils.isHostOf(url, require_devto.hosts) || !match?.[1]) return false;
|
|
12
|
+
if (match[1] === "t") return false;
|
|
13
|
+
return !require_utils.isAnyOf(match[1], require_devto.excludedPaths);
|
|
14
|
+
} catch {}
|
|
15
|
+
return false;
|
|
16
|
+
},
|
|
17
|
+
resolve: async (url, _content, _headers, fetchFn) => {
|
|
18
|
+
if (!fetchFn) return [];
|
|
19
|
+
try {
|
|
20
|
+
const { pathname } = new URL(url);
|
|
21
|
+
const match = pathname.match(userRegex);
|
|
22
|
+
if (!match?.[1] || match[1] === "t") return [];
|
|
23
|
+
const username = match[1];
|
|
24
|
+
const profileImage = require_utils$1.parseBodyJson((await fetchFn(`https://dev.to/api/users/by_username?url=${encodeURIComponent(username)}`)).body)?.profile_image;
|
|
25
|
+
if (require_utils$1.isNonEmptyString(profileImage)) return [{ uri: profileImage }];
|
|
26
|
+
} catch {}
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
exports.devtoHandler = devtoHandler;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
import { isNonEmptyString, parseBodyJson } from "../../utils.js";
|
|
3
|
+
import { excludedPaths, hosts } from "../../../feeds/platform/handlers/devto.js";
|
|
4
|
+
//#region src/favicons/platform/handlers/devto.ts
|
|
5
|
+
const userRegex = /^\/([^/.]+)/;
|
|
6
|
+
const devtoHandler = {
|
|
7
|
+
match: (url) => {
|
|
8
|
+
try {
|
|
9
|
+
const { pathname } = new URL(url);
|
|
10
|
+
const match = pathname.match(userRegex);
|
|
11
|
+
if (!isHostOf(url, hosts) || !match?.[1]) return false;
|
|
12
|
+
if (match[1] === "t") return false;
|
|
13
|
+
return !isAnyOf(match[1], excludedPaths);
|
|
14
|
+
} catch {}
|
|
15
|
+
return false;
|
|
16
|
+
},
|
|
17
|
+
resolve: async (url, _content, _headers, fetchFn) => {
|
|
18
|
+
if (!fetchFn) return [];
|
|
19
|
+
try {
|
|
20
|
+
const { pathname } = new URL(url);
|
|
21
|
+
const match = pathname.match(userRegex);
|
|
22
|
+
if (!match?.[1] || match[1] === "t") return [];
|
|
23
|
+
const username = match[1];
|
|
24
|
+
const profileImage = parseBodyJson((await fetchFn(`https://dev.to/api/users/by_username?url=${encodeURIComponent(username)}`)).body)?.profile_image;
|
|
25
|
+
if (isNonEmptyString(profileImage)) return [{ uri: profileImage }];
|
|
26
|
+
} catch {}
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
export { devtoHandler };
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
const require_github = require("../../../feeds/platform/handlers/github.cjs");
|
|
3
3
|
//#region src/favicons/platform/handlers/github.ts
|
|
4
|
+
const userRegex = /^\/([^/.]+)/;
|
|
4
5
|
const githubHandler = {
|
|
5
6
|
match: (url) => {
|
|
6
7
|
return require_utils.isHostOf(url, require_github.hosts);
|
|
7
8
|
},
|
|
8
9
|
resolve: (url) => {
|
|
9
10
|
const { pathname } = new URL(url);
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
const user =
|
|
11
|
+
const match = pathname.match(userRegex);
|
|
12
|
+
if (!match?.[1]) return [];
|
|
13
|
+
const user = match[1];
|
|
13
14
|
if (require_utils.isAnyOf(user, require_github.excludedPaths)) return [];
|
|
14
15
|
return [{ uri: `https://github.com/${user}.png` }];
|
|
15
16
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
2
|
import { excludedPaths, hosts } from "../../../feeds/platform/handlers/github.js";
|
|
3
3
|
//#region src/favicons/platform/handlers/github.ts
|
|
4
|
+
const userRegex = /^\/([^/.]+)/;
|
|
4
5
|
const githubHandler = {
|
|
5
6
|
match: (url) => {
|
|
6
7
|
return isHostOf(url, hosts);
|
|
7
8
|
},
|
|
8
9
|
resolve: (url) => {
|
|
9
10
|
const { pathname } = new URL(url);
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
const user =
|
|
11
|
+
const match = pathname.match(userRegex);
|
|
12
|
+
if (!match?.[1]) return [];
|
|
13
|
+
const user = match[1];
|
|
13
14
|
if (isAnyOf(user, excludedPaths)) return [];
|
|
14
15
|
return [{ uri: `https://github.com/${user}.png` }];
|
|
15
16
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
const require_githubGist = require("../../../feeds/platform/handlers/githubGist.cjs");
|
|
3
3
|
//#region src/favicons/platform/handlers/githubGist.ts
|
|
4
|
+
const userRegex = /^\/([^/.]+)/;
|
|
4
5
|
const githubGistHandler = {
|
|
5
6
|
match: (url) => {
|
|
6
7
|
return require_utils.isHostOf(url, require_githubGist.hosts);
|
|
7
8
|
},
|
|
8
9
|
resolve: (url) => {
|
|
9
10
|
const { pathname } = new URL(url);
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
const user =
|
|
11
|
+
const match = pathname.match(userRegex);
|
|
12
|
+
if (!match?.[1]) return [];
|
|
13
|
+
const user = match[1];
|
|
13
14
|
if (require_utils.isAnyOf(user, require_githubGist.excludedPaths)) return [];
|
|
14
15
|
return [{ uri: `https://github.com/${user}.png` }];
|
|
15
16
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
2
|
import { excludedPaths, hosts } from "../../../feeds/platform/handlers/githubGist.js";
|
|
3
3
|
//#region src/favicons/platform/handlers/githubGist.ts
|
|
4
|
+
const userRegex = /^\/([^/.]+)/;
|
|
4
5
|
const githubGistHandler = {
|
|
5
6
|
match: (url) => {
|
|
6
7
|
return isHostOf(url, hosts);
|
|
7
8
|
},
|
|
8
9
|
resolve: (url) => {
|
|
9
10
|
const { pathname } = new URL(url);
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
const user =
|
|
11
|
+
const match = pathname.match(userRegex);
|
|
12
|
+
if (!match?.[1]) return [];
|
|
13
|
+
const user = match[1];
|
|
13
14
|
if (isAnyOf(user, excludedPaths)) return [];
|
|
14
15
|
return [{ uri: `https://github.com/${user}.png` }];
|
|
15
16
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const require_utils = require("../../../common/utils.cjs");
|
|
2
|
+
const require_utils$1 = require("../../utils.cjs");
|
|
3
|
+
const require_gitlab = require("../../../feeds/platform/handlers/gitlab.cjs");
|
|
4
|
+
//#region src/favicons/platform/handlers/gitlab.ts
|
|
5
|
+
const userRegex = /^\/([^/]+?)(?:\.atom)?(?:\/|$)/;
|
|
6
|
+
const fetchAvatarUrl = async (apiUrl, fetchFn) => {
|
|
7
|
+
const data = require_utils$1.parseBodyJson((await fetchFn(apiUrl)).body);
|
|
8
|
+
const entry = Array.isArray(data) ? data[0] : data;
|
|
9
|
+
if (require_utils$1.isNonEmptyString(entry?.avatar_url)) return entry.avatar_url;
|
|
10
|
+
};
|
|
11
|
+
const gitlabHandler = {
|
|
12
|
+
match: (url, content, headers) => {
|
|
13
|
+
try {
|
|
14
|
+
if (require_utils.isHostOf(url, require_gitlab.hosts)) return true;
|
|
15
|
+
const { pathname } = new URL(url);
|
|
16
|
+
if (!userRegex.test(pathname)) return false;
|
|
17
|
+
if (content && require_gitlab.isGitlabHtml(content)) return true;
|
|
18
|
+
if (headers && require_gitlab.isGitlabHeaders(headers)) return true;
|
|
19
|
+
} catch {}
|
|
20
|
+
return false;
|
|
21
|
+
},
|
|
22
|
+
resolve: async (url, _content, _headers, fetchFn) => {
|
|
23
|
+
if (!fetchFn) return [];
|
|
24
|
+
try {
|
|
25
|
+
const { origin, pathname } = new URL(url);
|
|
26
|
+
const match = pathname.match(userRegex);
|
|
27
|
+
if (!match?.[1]) return [];
|
|
28
|
+
const username = match[1];
|
|
29
|
+
if (require_utils.isAnyOf(username, require_gitlab.excludedPaths)) return [];
|
|
30
|
+
const encodedName = encodeURIComponent(username);
|
|
31
|
+
const avatarUrl = await fetchAvatarUrl(`${origin}/api/v4/users?username=${encodedName}`, fetchFn) ?? await fetchAvatarUrl(`${origin}/api/v4/groups/${encodedName}`, fetchFn);
|
|
32
|
+
if (avatarUrl) return [{ uri: avatarUrl }];
|
|
33
|
+
} catch {}
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
exports.gitlabHandler = gitlabHandler;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
import { isNonEmptyString, parseBodyJson } from "../../utils.js";
|
|
3
|
+
import { excludedPaths, hosts, isGitlabHeaders, isGitlabHtml } from "../../../feeds/platform/handlers/gitlab.js";
|
|
4
|
+
//#region src/favicons/platform/handlers/gitlab.ts
|
|
5
|
+
const userRegex = /^\/([^/]+?)(?:\.atom)?(?:\/|$)/;
|
|
6
|
+
const fetchAvatarUrl = async (apiUrl, fetchFn) => {
|
|
7
|
+
const data = parseBodyJson((await fetchFn(apiUrl)).body);
|
|
8
|
+
const entry = Array.isArray(data) ? data[0] : data;
|
|
9
|
+
if (isNonEmptyString(entry?.avatar_url)) return entry.avatar_url;
|
|
10
|
+
};
|
|
11
|
+
const gitlabHandler = {
|
|
12
|
+
match: (url, content, headers) => {
|
|
13
|
+
try {
|
|
14
|
+
if (isHostOf(url, hosts)) return true;
|
|
15
|
+
const { pathname } = new URL(url);
|
|
16
|
+
if (!userRegex.test(pathname)) return false;
|
|
17
|
+
if (content && isGitlabHtml(content)) return true;
|
|
18
|
+
if (headers && isGitlabHeaders(headers)) return true;
|
|
19
|
+
} catch {}
|
|
20
|
+
return false;
|
|
21
|
+
},
|
|
22
|
+
resolve: async (url, _content, _headers, fetchFn) => {
|
|
23
|
+
if (!fetchFn) return [];
|
|
24
|
+
try {
|
|
25
|
+
const { origin, pathname } = new URL(url);
|
|
26
|
+
const match = pathname.match(userRegex);
|
|
27
|
+
if (!match?.[1]) return [];
|
|
28
|
+
const username = match[1];
|
|
29
|
+
if (isAnyOf(username, excludedPaths)) return [];
|
|
30
|
+
const encodedName = encodeURIComponent(username);
|
|
31
|
+
const avatarUrl = await fetchAvatarUrl(`${origin}/api/v4/users?username=${encodedName}`, fetchFn) ?? await fetchAvatarUrl(`${origin}/api/v4/groups/${encodedName}`, fetchFn);
|
|
32
|
+
if (avatarUrl) return [{ uri: avatarUrl }];
|
|
33
|
+
} catch {}
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
export { gitlabHandler };
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
const require_utils = require("../../../common/utils.cjs");
|
|
2
2
|
const require_lobsters = require("../../../feeds/platform/handlers/lobsters.cjs");
|
|
3
3
|
//#region src/favicons/platform/handlers/lobsters.ts
|
|
4
|
-
const
|
|
4
|
+
const userRegex = /^\/~([a-zA-Z0-9_-]+)/;
|
|
5
5
|
const lobstersHandler = {
|
|
6
6
|
match: (url) => {
|
|
7
7
|
try {
|
|
8
8
|
const { pathname } = new URL(url);
|
|
9
|
-
return require_utils.isHostOf(url, require_lobsters.hosts) &&
|
|
9
|
+
return require_utils.isHostOf(url, require_lobsters.hosts) && userRegex.test(pathname);
|
|
10
10
|
} catch {}
|
|
11
11
|
return false;
|
|
12
12
|
},
|
|
13
13
|
resolve: (url) => {
|
|
14
14
|
const { pathname } = new URL(url);
|
|
15
|
-
const match = pathname.match(
|
|
15
|
+
const match = pathname.match(userRegex);
|
|
16
16
|
if (!match?.[1]) return [];
|
|
17
17
|
return [{ uri: `https://lobste.rs/avatars/${match[1]}-100.png` }];
|
|
18
18
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { isHostOf } from "../../../common/utils.js";
|
|
2
2
|
import { hosts } from "../../../feeds/platform/handlers/lobsters.js";
|
|
3
3
|
//#region src/favicons/platform/handlers/lobsters.ts
|
|
4
|
-
const
|
|
4
|
+
const userRegex = /^\/~([a-zA-Z0-9_-]+)/;
|
|
5
5
|
const lobstersHandler = {
|
|
6
6
|
match: (url) => {
|
|
7
7
|
try {
|
|
8
8
|
const { pathname } = new URL(url);
|
|
9
|
-
return isHostOf(url, hosts) &&
|
|
9
|
+
return isHostOf(url, hosts) && userRegex.test(pathname);
|
|
10
10
|
} catch {}
|
|
11
11
|
return false;
|
|
12
12
|
},
|
|
13
13
|
resolve: (url) => {
|
|
14
14
|
const { pathname } = new URL(url);
|
|
15
|
-
const match = pathname.match(
|
|
15
|
+
const match = pathname.match(userRegex);
|
|
16
16
|
if (!match?.[1]) return [];
|
|
17
17
|
return [{ uri: `https://lobste.rs/avatars/${match[1]}-100.png` }];
|
|
18
18
|
}
|
|
@@ -2,9 +2,9 @@ const require_utils = require("../../../common/utils.cjs");
|
|
|
2
2
|
const require_utils$1 = require("../../utils.cjs");
|
|
3
3
|
//#region src/favicons/platform/handlers/mastodon.ts
|
|
4
4
|
const mastodonRegex = /mastodon/i;
|
|
5
|
+
const profileRegex = /^\/@([^/.]+(?:@[^/.]+\.[^/.]+)?)(?:\.rss)?\/?$/;
|
|
5
6
|
const isProfilePath = (pathname) => {
|
|
6
|
-
|
|
7
|
-
return segments.length === 1 && segments[0].startsWith("@");
|
|
7
|
+
return profileRegex.test(pathname);
|
|
8
8
|
};
|
|
9
9
|
const isMastodonHtml = (content) => {
|
|
10
10
|
return require_utils.hasMetaContent(content, "generator", "Mastodon");
|
|
@@ -26,7 +26,9 @@ const mastodonHandler = {
|
|
|
26
26
|
if (!fetchFn) return [];
|
|
27
27
|
try {
|
|
28
28
|
const { hostname, pathname } = new URL(url);
|
|
29
|
-
const
|
|
29
|
+
const match = pathname.match(profileRegex);
|
|
30
|
+
if (!match?.[1]) return [];
|
|
31
|
+
const data = require_utils$1.parseBodyJson((await fetchFn(`https://${hostname}/api/v1/accounts/lookup?acct=${match[1]}`)).body);
|
|
30
32
|
if (require_utils$1.isNonEmptyString(data.avatar)) return [{ uri: data.avatar }];
|
|
31
33
|
} catch {}
|
|
32
34
|
return [];
|
|
@@ -2,9 +2,9 @@ import { hasMetaContent } from "../../../common/utils.js";
|
|
|
2
2
|
import { isNonEmptyString, parseBodyJson } from "../../utils.js";
|
|
3
3
|
//#region src/favicons/platform/handlers/mastodon.ts
|
|
4
4
|
const mastodonRegex = /mastodon/i;
|
|
5
|
+
const profileRegex = /^\/@([^/.]+(?:@[^/.]+\.[^/.]+)?)(?:\.rss)?\/?$/;
|
|
5
6
|
const isProfilePath = (pathname) => {
|
|
6
|
-
|
|
7
|
-
return segments.length === 1 && segments[0].startsWith("@");
|
|
7
|
+
return profileRegex.test(pathname);
|
|
8
8
|
};
|
|
9
9
|
const isMastodonHtml = (content) => {
|
|
10
10
|
return hasMetaContent(content, "generator", "Mastodon");
|
|
@@ -26,7 +26,9 @@ const mastodonHandler = {
|
|
|
26
26
|
if (!fetchFn) return [];
|
|
27
27
|
try {
|
|
28
28
|
const { hostname, pathname } = new URL(url);
|
|
29
|
-
const
|
|
29
|
+
const match = pathname.match(profileRegex);
|
|
30
|
+
if (!match?.[1]) return [];
|
|
31
|
+
const data = parseBodyJson((await fetchFn(`https://${hostname}/api/v1/accounts/lookup?acct=${match[1]}`)).body);
|
|
30
32
|
if (isNonEmptyString(data.avatar)) return [{ uri: data.avatar }];
|
|
31
33
|
} catch {}
|
|
32
34
|
return [];
|