feedscout 1.4.0 → 1.5.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 (73) hide show
  1. package/dist/common/discover/index.cjs +45 -14
  2. package/dist/common/discover/index.js +46 -15
  3. package/dist/common/discover/utils.cjs +12 -1
  4. package/dist/common/discover/utils.js +11 -1
  5. package/dist/common/locales.cjs +75 -0
  6. package/dist/common/locales.js +70 -1
  7. package/dist/common/types.cjs +11 -0
  8. package/dist/common/types.d.cts +15 -2
  9. package/dist/common/types.d.ts +15 -2
  10. package/dist/common/types.js +10 -0
  11. package/dist/common/uris/guess/index.d.cts +2 -1
  12. package/dist/common/uris/guess/index.d.ts +2 -1
  13. package/dist/common/uris/guess/types.d.cts +3 -1
  14. package/dist/common/uris/guess/types.d.ts +3 -1
  15. package/dist/common/uris/guess/utils.cjs +4 -1
  16. package/dist/common/uris/guess/utils.d.cts +3 -1
  17. package/dist/common/uris/guess/utils.d.ts +3 -1
  18. package/dist/common/uris/guess/utils.js +4 -1
  19. package/dist/common/uris/index.cjs +13 -10
  20. package/dist/common/uris/index.js +13 -10
  21. package/dist/common/uris/platform/types.d.cts +3 -1
  22. package/dist/common/uris/platform/types.d.ts +3 -1
  23. package/dist/common/utils.cjs +6 -0
  24. package/dist/common/utils.js +7 -1
  25. package/dist/feeds/defaults.cjs +12 -13
  26. package/dist/feeds/defaults.d.cts +2 -2
  27. package/dist/feeds/defaults.d.ts +2 -2
  28. package/dist/feeds/defaults.js +12 -13
  29. package/dist/feeds/platform/handlers/behance.cjs +8 -2
  30. package/dist/feeds/platform/handlers/behance.js +9 -3
  31. package/dist/feeds/platform/handlers/blogspot.cjs +13 -3
  32. package/dist/feeds/platform/handlers/blogspot.js +14 -3
  33. package/dist/feeds/platform/handlers/bluesky.cjs +4 -1
  34. package/dist/feeds/platform/handlers/bluesky.js +5 -2
  35. package/dist/feeds/platform/handlers/dailymotion.cjs +8 -2
  36. package/dist/feeds/platform/handlers/dailymotion.js +9 -3
  37. package/dist/feeds/platform/handlers/deviantart.cjs +16 -4
  38. package/dist/feeds/platform/handlers/deviantart.js +17 -5
  39. package/dist/feeds/platform/handlers/devto.cjs +8 -2
  40. package/dist/feeds/platform/handlers/devto.js +9 -3
  41. package/dist/feeds/platform/handlers/github.cjs +32 -12
  42. package/dist/feeds/platform/handlers/github.js +33 -13
  43. package/dist/feeds/platform/handlers/githubGist.cjs +13 -13
  44. package/dist/feeds/platform/handlers/githubGist.js +14 -14
  45. package/dist/feeds/platform/handlers/gitlab.cjs +16 -4
  46. package/dist/feeds/platform/handlers/gitlab.js +17 -5
  47. package/dist/feeds/platform/handlers/kickstarter.cjs +8 -2
  48. package/dist/feeds/platform/handlers/kickstarter.js +9 -3
  49. package/dist/feeds/platform/handlers/lobsters.cjs +32 -8
  50. package/dist/feeds/platform/handlers/lobsters.js +33 -9
  51. package/dist/feeds/platform/handlers/medium.cjs +24 -6
  52. package/dist/feeds/platform/handlers/medium.js +25 -7
  53. package/dist/feeds/platform/handlers/pinterest.cjs +12 -3
  54. package/dist/feeds/platform/handlers/pinterest.js +13 -4
  55. package/dist/feeds/platform/handlers/producthunt.cjs +12 -3
  56. package/dist/feeds/platform/handlers/producthunt.js +13 -4
  57. package/dist/feeds/platform/handlers/reddit.cjs +32 -8
  58. package/dist/feeds/platform/handlers/reddit.js +33 -9
  59. package/dist/feeds/platform/handlers/soundcloud.cjs +4 -1
  60. package/dist/feeds/platform/handlers/soundcloud.js +5 -2
  61. package/dist/feeds/platform/handlers/substack.cjs +4 -1
  62. package/dist/feeds/platform/handlers/substack.js +5 -2
  63. package/dist/feeds/platform/handlers/tumblr.cjs +8 -2
  64. package/dist/feeds/platform/handlers/tumblr.js +9 -3
  65. package/dist/feeds/platform/handlers/wordpress.cjs +44 -8
  66. package/dist/feeds/platform/handlers/wordpress.js +45 -9
  67. package/dist/feeds/platform/handlers/wpengine.cjs +13 -0
  68. package/dist/feeds/platform/handlers/wpengine.js +13 -0
  69. package/dist/feeds/platform/handlers/youtube.cjs +20 -9
  70. package/dist/feeds/platform/handlers/youtube.js +21 -10
  71. package/dist/index.d.cts +2 -2
  72. package/dist/index.d.ts +2 -2
  73. package/package.json +1 -1
@@ -4,22 +4,25 @@ import { discoverUrisFromHtml } from "./html/index.js";
4
4
  import { discoverUrisFromPlatform } from "./platform/index.js";
5
5
 
6
6
  //#region src/common/uris/index.ts
7
- const discoverUris = (config, stopOnFirstMethod = false) => {
8
- const uris = /* @__PURE__ */ new Set();
7
+ const discoverUris = (config) => {
8
+ const result = {};
9
9
  if (config.platform) {
10
- for (const uri of discoverUrisFromPlatform(config.platform.html, config.platform.options)) uris.add(uri);
11
- if (stopOnFirstMethod && uris.size > 0) return Array.from(uris);
10
+ const uris = discoverUrisFromPlatform(config.platform.html, config.platform.options);
11
+ if (uris.length > 0) result.platform = uris;
12
12
  }
13
13
  if (config.html) {
14
- for (const uri of discoverUrisFromHtml(config.html.html, config.html.options)) uris.add(uri);
15
- if (stopOnFirstMethod && uris.size > 0) return Array.from(uris);
14
+ const uris = discoverUrisFromHtml(config.html.html, config.html.options);
15
+ if (uris.length > 0) result.html = uris.map((uri) => ({ uri }));
16
16
  }
17
17
  if (config.headers) {
18
- for (const uri of discoverUrisFromHeaders(config.headers.headers, config.headers.options)) uris.add(uri);
19
- if (stopOnFirstMethod && uris.size > 0) return Array.from(uris);
18
+ const uris = discoverUrisFromHeaders(config.headers.headers, config.headers.options);
19
+ if (uris.length > 0) result.headers = uris.map((uri) => ({ uri }));
20
20
  }
21
- if (config.guess) for (const uri of discoverUrisFromGuess(config.guess.options)) uris.add(uri);
22
- return Array.from(uris);
21
+ if (config.guess) {
22
+ const uris = discoverUrisFromGuess(config.guess.options);
23
+ if (uris.length > 0) result.guess = uris.map((uri) => ({ uri }));
24
+ }
25
+ return result;
23
26
  };
24
27
 
25
28
  //#endregion
@@ -1,7 +1,9 @@
1
+ import { DiscoverUriEntry } from "../../types.cjs";
2
+
1
3
  //#region src/common/uris/platform/types.d.ts
2
4
  type PlatformHandler = {
3
5
  match: (url: string) => boolean;
4
- resolve: (url: string, content?: string) => Array<string>;
6
+ resolve: (url: string, content?: string) => Array<DiscoverUriEntry>;
5
7
  };
6
8
  type PlatformMethodOptions = {
7
9
  baseUrl: string;
@@ -1,7 +1,9 @@
1
+ import { DiscoverUriEntry } from "../../types.js";
2
+
1
3
  //#region src/common/uris/platform/types.d.ts
2
4
  type PlatformHandler = {
3
5
  match: (url: string) => boolean;
4
- resolve: (url: string, content?: string) => Array<string>;
6
+ resolve: (url: string, content?: string) => Array<DiscoverUriEntry>;
5
7
  };
6
8
  type PlatformMethodOptions = {
7
9
  baseUrl: string;
@@ -1,5 +1,10 @@
1
+ const require_locales = require('./locales.cjs');
1
2
 
2
3
  //#region src/common/utils.ts
4
+ const composeHint = (key) => ({
5
+ key,
6
+ label: require_locales.hints[key]
7
+ });
3
8
  const normalizeMimeType = (type) => {
4
9
  return type.split(";")[0].trim().toLowerCase();
5
10
  };
@@ -57,6 +62,7 @@ const processConcurrently = async (items, processFn, options) => {
57
62
 
58
63
  //#endregion
59
64
  exports.anyWordMatchesAnyOf = anyWordMatchesAnyOf;
65
+ exports.composeHint = composeHint;
60
66
  exports.endsWithAnyOf = endsWithAnyOf;
61
67
  exports.includesAnyOf = includesAnyOf;
62
68
  exports.isAnyOf = isAnyOf;
@@ -1,4 +1,10 @@
1
+ import { hints } from "./locales.js";
2
+
1
3
  //#region src/common/utils.ts
4
+ const composeHint = (key) => ({
5
+ key,
6
+ label: hints[key]
7
+ });
2
8
  const normalizeMimeType = (type) => {
3
9
  return type.split(";")[0].trim().toLowerCase();
4
10
  };
@@ -55,4 +61,4 @@ const processConcurrently = async (items, processFn, options) => {
55
61
  };
56
62
 
57
63
  //#endregion
58
- export { anyWordMatchesAnyOf, endsWithAnyOf, includesAnyOf, isAnyOf, isHostOf, isSubdomainOf, matchesAnyOfLinkSelectors, normalizeUrl, processConcurrently };
64
+ export { anyWordMatchesAnyOf, composeHint, endsWithAnyOf, includesAnyOf, isAnyOf, isHostOf, isSubdomainOf, matchesAnyOfLinkSelectors, normalizeUrl, processConcurrently };
@@ -17,6 +17,7 @@ const require_soundcloud = require('./platform/handlers/soundcloud.cjs');
17
17
  const require_substack = require('./platform/handlers/substack.cjs');
18
18
  const require_tumblr = require('./platform/handlers/tumblr.cjs');
19
19
  const require_wordpress = require('./platform/handlers/wordpress.cjs');
20
+ const require_wpengine = require('./platform/handlers/wpengine.cjs');
20
21
  const require_youtube = require('./platform/handlers/youtube.cjs');
21
22
 
22
23
  //#region src/feeds/defaults.ts
@@ -59,19 +60,13 @@ const urisComprehensive = [
59
60
  "/feed.atom",
60
61
  "/feed.rss.xml",
61
62
  "/feed.atom.xml",
62
- "/feed/atom/",
63
- "/feed/rss/",
64
- "/feed/rss2/",
65
- "/feed/rdf",
66
- "/feed/rdf/",
63
+ ["/feed/atom/", "?feed=atom"],
64
+ ["/feed/rss/", "?feed=rss"],
65
+ ["/feed/rss2/", "?feed=rss2"],
66
+ ["/feed/rdf", "?feed=rdf"],
67
+ ["/feed/rdf/", "?feed=rdf"],
67
68
  "/index.rss.xml",
68
69
  "/index.atom.xml",
69
- "?feed=rss",
70
- "?feed=rss2",
71
- "?feed=atom",
72
- "?feed=rdf",
73
- "?feed=comments-rss2",
74
- "?feed=comments-atom",
75
70
  "?format=rss",
76
71
  "?format=atom",
77
72
  "?rss=1",
@@ -81,7 +76,10 @@ const urisComprehensive = [
81
76
  "/f.rss",
82
77
  "/json",
83
78
  "/.feed",
84
- "/comments/feed",
79
+ ["/comments/feed", "?feed=comments-rss2"],
80
+ ["/comments/feed/rss2/", "?feed=comments-rss2"],
81
+ ["/comments/feed/rdf/", "?feed=comments-rdf"],
82
+ ["/comments/feed/atom/", "?feed=comments-atom"],
85
83
  "/feeds/posts/default",
86
84
  "/feeds/posts/default?alt=rss",
87
85
  "/feeds/comments/default"
@@ -102,7 +100,7 @@ const linkSelectors = [{
102
100
  }, { rel: "feed" }];
103
101
  const defaultHtmlOptions = {
104
102
  linkSelectors,
105
- anchorUris: urisComprehensive,
103
+ anchorUris: urisComprehensive.flat(),
106
104
  anchorIgnoredUris: ignoredUris,
107
105
  anchorLabels
108
106
  };
@@ -128,6 +126,7 @@ const defaultPlatformOptions = { handlers: [
128
126
  require_substack.substackHandler,
129
127
  require_tumblr.tumblrHandler,
130
128
  require_wordpress.wordpressHandler,
129
+ require_wpengine.wpengineHandler,
131
130
  require_youtube.youtubeHandler
132
131
  ] };
133
132
 
@@ -2,13 +2,13 @@ import { GuessMethodOptions } from "../common/uris/guess/types.cjs";
2
2
  import { HeadersMethodOptions } from "../common/uris/headers/types.cjs";
3
3
  import { HtmlMethodOptions } from "../common/uris/html/types.cjs";
4
4
  import { PlatformMethodOptions } from "../common/uris/platform/types.cjs";
5
- import { LinkSelector } from "../common/types.cjs";
5
+ import { LinkSelector, UriEntry } from "../common/types.cjs";
6
6
 
7
7
  //#region src/feeds/defaults.d.ts
8
8
  declare const mimeTypes: string[];
9
9
  declare const urisMinimal: string[];
10
10
  declare const urisBalanced: string[];
11
- declare const urisComprehensive: string[];
11
+ declare const urisComprehensive: Array<UriEntry>;
12
12
  declare const ignoredUris: string[];
13
13
  declare const anchorLabels: string[];
14
14
  declare const linkSelectors: Array<LinkSelector>;
@@ -2,13 +2,13 @@ import { GuessMethodOptions } from "../common/uris/guess/types.js";
2
2
  import { HeadersMethodOptions } from "../common/uris/headers/types.js";
3
3
  import { HtmlMethodOptions } from "../common/uris/html/types.js";
4
4
  import { PlatformMethodOptions } from "../common/uris/platform/types.js";
5
- import { LinkSelector } from "../common/types.js";
5
+ import { LinkSelector, UriEntry } from "../common/types.js";
6
6
 
7
7
  //#region src/feeds/defaults.d.ts
8
8
  declare const mimeTypes: string[];
9
9
  declare const urisMinimal: string[];
10
10
  declare const urisBalanced: string[];
11
- declare const urisComprehensive: string[];
11
+ declare const urisComprehensive: Array<UriEntry>;
12
12
  declare const ignoredUris: string[];
13
13
  declare const anchorLabels: string[];
14
14
  declare const linkSelectors: Array<LinkSelector>;
@@ -17,6 +17,7 @@ import { soundcloudHandler } from "./platform/handlers/soundcloud.js";
17
17
  import { substackHandler } from "./platform/handlers/substack.js";
18
18
  import { tumblrHandler } from "./platform/handlers/tumblr.js";
19
19
  import { wordpressHandler } from "./platform/handlers/wordpress.js";
20
+ import { wpengineHandler } from "./platform/handlers/wpengine.js";
20
21
  import { youtubeHandler } from "./platform/handlers/youtube.js";
21
22
 
22
23
  //#region src/feeds/defaults.ts
@@ -59,19 +60,13 @@ const urisComprehensive = [
59
60
  "/feed.atom",
60
61
  "/feed.rss.xml",
61
62
  "/feed.atom.xml",
62
- "/feed/atom/",
63
- "/feed/rss/",
64
- "/feed/rss2/",
65
- "/feed/rdf",
66
- "/feed/rdf/",
63
+ ["/feed/atom/", "?feed=atom"],
64
+ ["/feed/rss/", "?feed=rss"],
65
+ ["/feed/rss2/", "?feed=rss2"],
66
+ ["/feed/rdf", "?feed=rdf"],
67
+ ["/feed/rdf/", "?feed=rdf"],
67
68
  "/index.rss.xml",
68
69
  "/index.atom.xml",
69
- "?feed=rss",
70
- "?feed=rss2",
71
- "?feed=atom",
72
- "?feed=rdf",
73
- "?feed=comments-rss2",
74
- "?feed=comments-atom",
75
70
  "?format=rss",
76
71
  "?format=atom",
77
72
  "?rss=1",
@@ -81,7 +76,10 @@ const urisComprehensive = [
81
76
  "/f.rss",
82
77
  "/json",
83
78
  "/.feed",
84
- "/comments/feed",
79
+ ["/comments/feed", "?feed=comments-rss2"],
80
+ ["/comments/feed/rss2/", "?feed=comments-rss2"],
81
+ ["/comments/feed/rdf/", "?feed=comments-rdf"],
82
+ ["/comments/feed/atom/", "?feed=comments-atom"],
85
83
  "/feeds/posts/default",
86
84
  "/feeds/posts/default?alt=rss",
87
85
  "/feeds/comments/default"
@@ -102,7 +100,7 @@ const linkSelectors = [{
102
100
  }, { rel: "feed" }];
103
101
  const defaultHtmlOptions = {
104
102
  linkSelectors,
105
- anchorUris: urisComprehensive,
103
+ anchorUris: urisComprehensive.flat(),
106
104
  anchorIgnoredUris: ignoredUris,
107
105
  anchorLabels
108
106
  };
@@ -128,6 +126,7 @@ const defaultPlatformOptions = { handlers: [
128
126
  substackHandler,
129
127
  tumblrHandler,
130
128
  wordpressHandler,
129
+ wpengineHandler,
131
130
  youtubeHandler
132
131
  ] };
133
132
 
@@ -33,8 +33,14 @@ const behanceHandler = {
33
33
  const username = userMatch[1];
34
34
  const subpage = userMatch[2];
35
35
  if (!require_utils.isAnyOf(username, excludedPaths)) {
36
- if (subpage === "appreciated") return [`https://www.behance.net/feeds/user?username=${username}&content=appreciated`];
37
- return [`https://www.behance.net/feeds/user?username=${username}`];
36
+ if (subpage === "appreciated") return [{
37
+ uri: `https://www.behance.net/feeds/user?username=${username}&content=appreciated`,
38
+ hint: require_utils.composeHint("behance:appreciated")
39
+ }];
40
+ return [{
41
+ uri: `https://www.behance.net/feeds/user?username=${username}`,
42
+ hint: require_utils.composeHint("behance:portfolio")
43
+ }];
38
44
  }
39
45
  }
40
46
  return [];
@@ -1,4 +1,4 @@
1
- import { isAnyOf, isHostOf } from "../../../common/utils.js";
1
+ import { composeHint, isAnyOf, isHostOf } from "../../../common/utils.js";
2
2
 
3
3
  //#region src/feeds/platform/handlers/behance.ts
4
4
  const hosts = ["behance.net", "www.behance.net"];
@@ -33,8 +33,14 @@ const behanceHandler = {
33
33
  const username = userMatch[1];
34
34
  const subpage = userMatch[2];
35
35
  if (!isAnyOf(username, excludedPaths)) {
36
- if (subpage === "appreciated") return [`https://www.behance.net/feeds/user?username=${username}&content=appreciated`];
37
- return [`https://www.behance.net/feeds/user?username=${username}`];
36
+ if (subpage === "appreciated") return [{
37
+ uri: `https://www.behance.net/feeds/user?username=${username}&content=appreciated`,
38
+ hint: composeHint("behance:appreciated")
39
+ }];
40
+ return [{
41
+ uri: `https://www.behance.net/feeds/user?username=${username}`,
42
+ hint: composeHint("behance:portfolio")
43
+ }];
38
44
  }
39
45
  }
40
46
  return [];
@@ -1,3 +1,4 @@
1
+ const require_utils = require('../../../common/utils.cjs');
1
2
 
2
3
  //#region src/feeds/platform/handlers/blogspot.ts
3
4
  const blogspotDomainRegex = /^.+\.blogspot\.(?:com|co\.[a-z]{2}|com\.[a-z]{2}|[a-z]{2,3})$/;
@@ -12,10 +13,19 @@ const blogspotHandler = {
12
13
  const labelMatch = pathname.match(/^\/search\/label\/([^/]+)/);
13
14
  if (labelMatch?.[1]) {
14
15
  const label = labelMatch[1];
15
- uris.push(`${origin}/feeds/posts/default/-/${label}`);
16
+ uris.push({
17
+ uri: `${origin}/feeds/posts/default/-/${label}`,
18
+ hint: require_utils.composeHint("blogspot:label")
19
+ });
16
20
  }
17
- uris.push(`${origin}/feeds/posts/default`);
18
- uris.push(`${origin}/feeds/posts/default?alt=rss`);
21
+ uris.push({
22
+ uri: `${origin}/feeds/posts/default`,
23
+ hint: require_utils.composeHint("blogspot:posts-atom")
24
+ });
25
+ uris.push({
26
+ uri: `${origin}/feeds/posts/default?alt=rss`,
27
+ hint: require_utils.composeHint("blogspot:posts-rss")
28
+ });
19
29
  return uris;
20
30
  }
21
31
  };
@@ -1,3 +1,5 @@
1
+ import { composeHint } from "../../../common/utils.js";
2
+
1
3
  //#region src/feeds/platform/handlers/blogspot.ts
2
4
  const blogspotDomainRegex = /^.+\.blogspot\.(?:com|co\.[a-z]{2}|com\.[a-z]{2}|[a-z]{2,3})$/;
3
5
  const blogspotHandler = {
@@ -11,10 +13,19 @@ const blogspotHandler = {
11
13
  const labelMatch = pathname.match(/^\/search\/label\/([^/]+)/);
12
14
  if (labelMatch?.[1]) {
13
15
  const label = labelMatch[1];
14
- uris.push(`${origin}/feeds/posts/default/-/${label}`);
16
+ uris.push({
17
+ uri: `${origin}/feeds/posts/default/-/${label}`,
18
+ hint: composeHint("blogspot:label")
19
+ });
15
20
  }
16
- uris.push(`${origin}/feeds/posts/default`);
17
- uris.push(`${origin}/feeds/posts/default?alt=rss`);
21
+ uris.push({
22
+ uri: `${origin}/feeds/posts/default`,
23
+ hint: composeHint("blogspot:posts-atom")
24
+ });
25
+ uris.push({
26
+ uri: `${origin}/feeds/posts/default?alt=rss`,
27
+ hint: composeHint("blogspot:posts-rss")
28
+ });
18
29
  return uris;
19
30
  }
20
31
  };
@@ -10,7 +10,10 @@ const blueskyHandler = {
10
10
  const { pathname } = new URL(url);
11
11
  const handle = pathname.match(/^\/profile\/([^/]+)/)?.[1];
12
12
  if (!handle) return [];
13
- return [`https://bsky.app/profile/${handle}/rss`];
13
+ return [{
14
+ uri: `https://bsky.app/profile/${handle}/rss`,
15
+ hint: require_utils.composeHint("bluesky:posts")
16
+ }];
14
17
  }
15
18
  };
16
19
 
@@ -1,4 +1,4 @@
1
- import { isHostOf } from "../../../common/utils.js";
1
+ import { composeHint, isHostOf } from "../../../common/utils.js";
2
2
 
3
3
  //#region src/feeds/platform/handlers/bluesky.ts
4
4
  const hosts = ["bsky.app"];
@@ -10,7 +10,10 @@ const blueskyHandler = {
10
10
  const { pathname } = new URL(url);
11
11
  const handle = pathname.match(/^\/profile\/([^/]+)/)?.[1];
12
12
  if (!handle) return [];
13
- return [`https://bsky.app/profile/${handle}/rss`];
13
+ return [{
14
+ uri: `https://bsky.app/profile/${handle}/rss`,
15
+ hint: composeHint("bluesky:posts")
16
+ }];
14
17
  }
15
18
  };
16
19
 
@@ -52,11 +52,17 @@ const dailymotionHandler = {
52
52
  resolve: (url) => {
53
53
  const { pathname } = new URL(url);
54
54
  const playlistMatch = pathname.match(playlistPathRegex);
55
- if (playlistMatch?.[1]) return [`https://www.dailymotion.com/rss/playlist/${playlistMatch[1]}`];
55
+ if (playlistMatch?.[1]) return [{
56
+ uri: `https://www.dailymotion.com/rss/playlist/${playlistMatch[1]}`,
57
+ hint: require_utils.composeHint("dailymotion:playlist")
58
+ }];
56
59
  const userMatch = pathname.match(userPathRegex);
57
60
  if (userMatch?.[1]) {
58
61
  const username = userMatch[1];
59
- if (!require_utils.isAnyOf(username, excludedPaths)) return [`https://www.dailymotion.com/rss/${username}`];
62
+ if (!require_utils.isAnyOf(username, excludedPaths)) return [{
63
+ uri: `https://www.dailymotion.com/rss/${username}`,
64
+ hint: require_utils.composeHint("dailymotion:videos")
65
+ }];
60
66
  }
61
67
  return [];
62
68
  }
@@ -1,4 +1,4 @@
1
- import { isAnyOf, isHostOf } from "../../../common/utils.js";
1
+ import { composeHint, isAnyOf, isHostOf } from "../../../common/utils.js";
2
2
 
3
3
  //#region src/feeds/platform/handlers/dailymotion.ts
4
4
  const hosts = ["dailymotion.com", "www.dailymotion.com"];
@@ -52,11 +52,17 @@ const dailymotionHandler = {
52
52
  resolve: (url) => {
53
53
  const { pathname } = new URL(url);
54
54
  const playlistMatch = pathname.match(playlistPathRegex);
55
- if (playlistMatch?.[1]) return [`https://www.dailymotion.com/rss/playlist/${playlistMatch[1]}`];
55
+ if (playlistMatch?.[1]) return [{
56
+ uri: `https://www.dailymotion.com/rss/playlist/${playlistMatch[1]}`,
57
+ hint: composeHint("dailymotion:playlist")
58
+ }];
56
59
  const userMatch = pathname.match(userPathRegex);
57
60
  if (userMatch?.[1]) {
58
61
  const username = userMatch[1];
59
- if (!isAnyOf(username, excludedPaths)) return [`https://www.dailymotion.com/rss/${username}`];
62
+ if (!isAnyOf(username, excludedPaths)) return [{
63
+ uri: `https://www.dailymotion.com/rss/${username}`,
64
+ hint: composeHint("dailymotion:videos")
65
+ }];
60
66
  }
61
67
  return [];
62
68
  }
@@ -26,23 +26,35 @@ const deviantartHandler = {
26
26
  const tagMatch = pathname.match(/^\/tag\/([^/]+)/);
27
27
  if (tagMatch?.[1]) {
28
28
  const tag = tagMatch[1];
29
- return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`tag:${tag}`)}`];
29
+ return [{
30
+ uri: `${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`tag:${tag}`)}`,
31
+ hint: require_utils.composeHint("deviantart:tag")
32
+ }];
30
33
  }
31
34
  const favMatch = pathname.match(/^\/([a-zA-Z0-9_-]+)\/favourites\/?$/);
32
35
  if (favMatch?.[1]) {
33
36
  const username = favMatch[1];
34
- if (!require_utils.isAnyOf(username, excludedPaths)) return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`favby:${username}`)}`];
37
+ if (!require_utils.isAnyOf(username, excludedPaths)) return [{
38
+ uri: `${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`favby:${username}`)}`,
39
+ hint: require_utils.composeHint("deviantart:favorites")
40
+ }];
35
41
  }
36
42
  const folderMatch = pathname.match(/^\/([a-zA-Z0-9_-]+)\/gallery\/(\d+)(?:\/|$)/);
37
43
  if (folderMatch?.[1] && folderMatch?.[2]) {
38
44
  const username = folderMatch[1];
39
45
  const folderId = folderMatch[2];
40
- if (!require_utils.isAnyOf(username, excludedPaths)) return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`gallery:${username}/${folderId}`)}`];
46
+ if (!require_utils.isAnyOf(username, excludedPaths)) return [{
47
+ uri: `${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`gallery:${username}/${folderId}`)}`,
48
+ hint: require_utils.composeHint("deviantart:gallery")
49
+ }];
41
50
  }
42
51
  const username = pathname.match(/^\/([a-zA-Z0-9_-]+)(?:\/gallery(?:\/all)?)?(?:\/|$)/)?.[1];
43
52
  if (!username || require_utils.isAnyOf(username, excludedPaths)) return [];
44
53
  const query = `by:${username} sort:time meta:all`;
45
- return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(query)}`];
54
+ return [{
55
+ uri: `${feedBaseUrl}?type=deviation&q=${encodeURIComponent(query)}`,
56
+ hint: require_utils.composeHint("deviantart:deviations")
57
+ }];
46
58
  }
47
59
  };
48
60
 
@@ -1,4 +1,4 @@
1
- import { isAnyOf, isHostOf } from "../../../common/utils.js";
1
+ import { composeHint, isAnyOf, isHostOf } from "../../../common/utils.js";
2
2
 
3
3
  //#region src/feeds/platform/handlers/deviantart.ts
4
4
  const hosts = ["deviantart.com", "www.deviantart.com"];
@@ -26,23 +26,35 @@ const deviantartHandler = {
26
26
  const tagMatch = pathname.match(/^\/tag\/([^/]+)/);
27
27
  if (tagMatch?.[1]) {
28
28
  const tag = tagMatch[1];
29
- return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`tag:${tag}`)}`];
29
+ return [{
30
+ uri: `${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`tag:${tag}`)}`,
31
+ hint: composeHint("deviantart:tag")
32
+ }];
30
33
  }
31
34
  const favMatch = pathname.match(/^\/([a-zA-Z0-9_-]+)\/favourites\/?$/);
32
35
  if (favMatch?.[1]) {
33
36
  const username = favMatch[1];
34
- if (!isAnyOf(username, excludedPaths)) return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`favby:${username}`)}`];
37
+ if (!isAnyOf(username, excludedPaths)) return [{
38
+ uri: `${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`favby:${username}`)}`,
39
+ hint: composeHint("deviantart:favorites")
40
+ }];
35
41
  }
36
42
  const folderMatch = pathname.match(/^\/([a-zA-Z0-9_-]+)\/gallery\/(\d+)(?:\/|$)/);
37
43
  if (folderMatch?.[1] && folderMatch?.[2]) {
38
44
  const username = folderMatch[1];
39
45
  const folderId = folderMatch[2];
40
- if (!isAnyOf(username, excludedPaths)) return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`gallery:${username}/${folderId}`)}`];
46
+ if (!isAnyOf(username, excludedPaths)) return [{
47
+ uri: `${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`gallery:${username}/${folderId}`)}`,
48
+ hint: composeHint("deviantart:gallery")
49
+ }];
41
50
  }
42
51
  const username = pathname.match(/^\/([a-zA-Z0-9_-]+)(?:\/gallery(?:\/all)?)?(?:\/|$)/)?.[1];
43
52
  if (!username || isAnyOf(username, excludedPaths)) return [];
44
53
  const query = `by:${username} sort:time meta:all`;
45
- return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(query)}`];
54
+ return [{
55
+ uri: `${feedBaseUrl}?type=deviation&q=${encodeURIComponent(query)}`,
56
+ hint: composeHint("deviantart:deviations")
57
+ }];
46
58
  }
47
59
  };
48
60
 
@@ -32,10 +32,16 @@ const devtoHandler = {
32
32
  const userMatch = pathname.match(userPathRegex);
33
33
  if (userMatch?.[1]) {
34
34
  const username = userMatch[1];
35
- if (!require_utils.isAnyOf(username, excludedPaths)) return [`https://dev.to/feed/${username}`];
35
+ if (!require_utils.isAnyOf(username, excludedPaths)) return [{
36
+ uri: `https://dev.to/feed/${username}`,
37
+ hint: require_utils.composeHint("devto:posts")
38
+ }];
36
39
  }
37
40
  const tagMatch = pathname.match(tagPathRegex);
38
- if (tagMatch?.[1]) return [`https://dev.to/feed/tag/${tagMatch[1]}`];
41
+ if (tagMatch?.[1]) return [{
42
+ uri: `https://dev.to/feed/tag/${tagMatch[1]}`,
43
+ hint: require_utils.composeHint("devto:tag")
44
+ }];
39
45
  return [];
40
46
  }
41
47
  };
@@ -1,4 +1,4 @@
1
- import { isAnyOf, isHostOf } from "../../../common/utils.js";
1
+ import { composeHint, isAnyOf, isHostOf } from "../../../common/utils.js";
2
2
 
3
3
  //#region src/feeds/platform/handlers/devto.ts
4
4
  const hosts = ["dev.to", "www.dev.to"];
@@ -32,10 +32,16 @@ const devtoHandler = {
32
32
  const userMatch = pathname.match(userPathRegex);
33
33
  if (userMatch?.[1]) {
34
34
  const username = userMatch[1];
35
- if (!isAnyOf(username, excludedPaths)) return [`https://dev.to/feed/${username}`];
35
+ if (!isAnyOf(username, excludedPaths)) return [{
36
+ uri: `https://dev.to/feed/${username}`,
37
+ hint: composeHint("devto:posts")
38
+ }];
36
39
  }
37
40
  const tagMatch = pathname.match(tagPathRegex);
38
- if (tagMatch?.[1]) return [`https://dev.to/feed/tag/${tagMatch[1]}`];
41
+ if (tagMatch?.[1]) return [{
42
+ uri: `https://dev.to/feed/tag/${tagMatch[1]}`,
43
+ hint: composeHint("devto:tag")
44
+ }];
39
45
  return [];
40
46
  }
41
47
  };
@@ -56,30 +56,50 @@ const githubHandler = {
56
56
  const { pathname } = new URL(url);
57
57
  const uris = [];
58
58
  const userMatch = pathname.match(/^\/([^/]+)\/?$/);
59
- if (userMatch?.[1] && !require_utils.isAnyOf(userMatch[1], excludedPaths)) {
60
- const user = userMatch[1];
61
- uris.push(`https://github.com/${user}.atom`);
62
- return uris;
63
- }
59
+ if (userMatch?.[1] && !require_utils.isAnyOf(userMatch[1], excludedPaths)) return [{
60
+ uri: `https://github.com/${userMatch[1]}.atom`,
61
+ hint: require_utils.composeHint("github:activity")
62
+ }];
64
63
  const repoMatch = pathname.match(/^\/([^/]+)\/([^/]+)/);
65
64
  const owner = repoMatch?.[1];
66
65
  const repo = repoMatch?.[2];
67
66
  if (!owner || !repo || require_utils.isAnyOf(owner, excludedPaths)) return [];
68
- uris.push(`https://github.com/${owner}/${repo}/releases.atom`);
69
- uris.push(`https://github.com/${owner}/${repo}/commits.atom`);
70
- uris.push(`https://github.com/${owner}/${repo}/tags.atom`);
71
- if (/\/wiki(\/|$)/.test(pathname)) uris.push(`https://github.com/${owner}/${repo}/wiki.atom`);
72
- if (/\/discussions(\/|$)/.test(pathname)) uris.push(`https://github.com/${owner}/${repo}/discussions.atom`);
67
+ uris.push({
68
+ uri: `https://github.com/${owner}/${repo}/releases.atom`,
69
+ hint: require_utils.composeHint("github:releases")
70
+ });
71
+ uris.push({
72
+ uri: `https://github.com/${owner}/${repo}/commits.atom`,
73
+ hint: require_utils.composeHint("github:commits")
74
+ });
75
+ uris.push({
76
+ uri: `https://github.com/${owner}/${repo}/tags.atom`,
77
+ hint: require_utils.composeHint("github:tags")
78
+ });
79
+ if (/\/wiki(\/|$)/.test(pathname)) uris.push({
80
+ uri: `https://github.com/${owner}/${repo}/wiki.atom`,
81
+ hint: require_utils.composeHint("github:wiki")
82
+ });
83
+ if (/\/discussions(\/|$)/.test(pathname)) uris.push({
84
+ uri: `https://github.com/${owner}/${repo}/discussions.atom`,
85
+ hint: require_utils.composeHint("github:discussions")
86
+ });
73
87
  const branchMatch = pathname.match(/^\/[^/]+\/[^/]+\/tree\/([^/]+)\/?$/);
74
88
  if (branchMatch?.[1]) {
75
89
  const branch = branchMatch[1];
76
- uris.push(`https://github.com/${owner}/${repo}/commits/${branch}.atom`);
90
+ uris.push({
91
+ uri: `https://github.com/${owner}/${repo}/commits/${branch}.atom`,
92
+ hint: require_utils.composeHint("github:branch-commits")
93
+ });
77
94
  }
78
95
  const fileMatch = pathname.match(/^\/[^/]+\/[^/]+\/(?:blob|commits)\/([^/]+)\/(.+)/);
79
96
  if (fileMatch?.[1] && fileMatch?.[2]) {
80
97
  const branch = fileMatch[1];
81
98
  const filePath = fileMatch[2];
82
- uris.push(`https://github.com/${owner}/${repo}/commits/${branch}/${filePath}.atom`);
99
+ uris.push({
100
+ uri: `https://github.com/${owner}/${repo}/commits/${branch}/${filePath}.atom`,
101
+ hint: require_utils.composeHint("github:file-history")
102
+ });
83
103
  }
84
104
  return uris;
85
105
  }