feedscout 1.0.0 → 1.1.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/README.md +2 -1
- package/dist/blogrolls/index.cjs +1 -0
- package/dist/blogrolls/index.js +1 -0
- package/dist/common/discover/utils.cjs +12 -0
- package/dist/common/discover/utils.js +12 -0
- package/dist/common/locales.cjs +1 -0
- package/dist/common/locales.js +1 -0
- package/dist/common/types.d.cts +3 -1
- package/dist/common/types.d.ts +3 -1
- package/dist/common/uris/index.cjs +2 -0
- package/dist/common/uris/index.js +2 -0
- package/dist/common/uris/platform/index.cjs +12 -0
- package/dist/common/uris/platform/index.js +11 -0
- package/dist/common/uris/platform/types.d.cts +11 -0
- package/dist/common/uris/platform/types.d.ts +11 -0
- package/dist/common/utils.cjs +9 -0
- package/dist/common/utils.js +7 -1
- package/dist/feeds/defaults.cjs +25 -0
- package/dist/feeds/defaults.d.cts +3 -1
- package/dist/feeds/defaults.d.ts +3 -1
- package/dist/feeds/defaults.js +26 -1
- package/dist/feeds/index.cjs +1 -0
- package/dist/feeds/index.js +2 -1
- package/dist/feeds/platform/handlers/blogspot.cjs +15 -0
- package/dist/feeds/platform/handlers/blogspot.js +15 -0
- package/dist/feeds/platform/handlers/bluesky.cjs +18 -0
- package/dist/feeds/platform/handlers/bluesky.js +18 -0
- package/dist/feeds/platform/handlers/github.cjs +83 -0
- package/dist/feeds/platform/handlers/github.js +83 -0
- package/dist/feeds/platform/handlers/gitlab.cjs +19 -0
- package/dist/feeds/platform/handlers/gitlab.js +19 -0
- package/dist/feeds/platform/handlers/kickstarter.cjs +21 -0
- package/dist/feeds/platform/handlers/kickstarter.js +21 -0
- package/dist/feeds/platform/handlers/reddit.cjs +44 -0
- package/dist/feeds/platform/handlers/reddit.js +44 -0
- package/dist/feeds/platform/handlers/soundcloud.cjs +37 -0
- package/dist/feeds/platform/handlers/soundcloud.js +37 -0
- package/dist/feeds/platform/handlers/substack.cjs +15 -0
- package/dist/feeds/platform/handlers/substack.js +15 -0
- package/dist/feeds/platform/handlers/tumblr.cjs +15 -0
- package/dist/feeds/platform/handlers/tumblr.js +15 -0
- package/dist/feeds/platform/handlers/wordpress.cjs +19 -0
- package/dist/feeds/platform/handlers/wordpress.js +19 -0
- package/dist/feeds/platform/handlers/youtube.cjs +44 -0
- package/dist/feeds/platform/handlers/youtube.js +44 -0
- package/dist/feeds.cjs +1 -0
- package/dist/feeds.d.cts +2 -2
- package/dist/feeds.d.ts +2 -2
- package/dist/feeds.js +2 -2
- package/package.json +16 -15
package/README.md
CHANGED
|
@@ -24,6 +24,7 @@ Finds feeds by scanning links and anchors in HTML content, parsing HTTP headers,
|
|
|
24
24
|
|
|
25
25
|
### Discovery Methods
|
|
26
26
|
|
|
27
|
+
- **Platform** — Generates feed URLs for YouTube, GitHub, WordPress, and other popular platforms using URL pattern matching.
|
|
27
28
|
- **HTML** — Scans `<link>` elements with feed MIME types and `<a>` elements matching feed patterns or labels like "RSS", "Subscribe".
|
|
28
29
|
- **Headers** — Parses HTTP `Link` headers for `rel="alternate"` with feed MIME types per RFC 8288.
|
|
29
30
|
- **Guess** — Tests common paths (e.g. `/feed`, `/rss.xml`, `/atom.xml`) against the base URL as a fallback.
|
|
@@ -32,7 +33,7 @@ Finds feeds by scanning links and anchors in HTML content, parsing HTTP headers,
|
|
|
32
33
|
|
|
33
34
|
- **Custom extractors** — Override the default parser to extract additional metadata from feeds and blogrolls.
|
|
34
35
|
- **Configurable methods** — Enable/disable discovery methods or customize their options.
|
|
35
|
-
- **Adapter system** — Use native fetch or integrate with Axios, Got, or Ky.
|
|
36
|
+
- **Adapter system** — Use native fetch or easily integrate with Axios, Got, or Ky.
|
|
36
37
|
- **Concurrency control** — Limit parallel requests during validation.
|
|
37
38
|
- **Progress tracking** — Monitor discovery progress with callbacks.
|
|
38
39
|
- **Type-safe** — Full TypeScript support with exported types.
|
package/dist/blogrolls/index.cjs
CHANGED
|
@@ -12,6 +12,7 @@ const discoverBlogrolls = async (input, options) => {
|
|
|
12
12
|
extractFn: options.extractFn ?? require_extractors.defaultExtractor,
|
|
13
13
|
normalizeUrlFn: options.normalizeUrlFn ?? require_utils.normalizeUrl
|
|
14
14
|
}, {
|
|
15
|
+
platform: { handlers: [] },
|
|
15
16
|
html: require_defaults.defaultHtmlOptions,
|
|
16
17
|
headers: require_defaults.defaultHeadersOptions,
|
|
17
18
|
guess: require_defaults.defaultGuessOptions
|
package/dist/blogrolls/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const discoverBlogrolls = async (input, options) => {
|
|
|
12
12
|
extractFn: options.extractFn ?? defaultExtractor,
|
|
13
13
|
normalizeUrlFn: options.normalizeUrlFn ?? normalizeUrl
|
|
14
14
|
}, {
|
|
15
|
+
platform: { handlers: [] },
|
|
15
16
|
html: defaultHtmlOptions,
|
|
16
17
|
headers: defaultHeadersOptions,
|
|
17
18
|
guess: defaultGuessOptions
|
|
@@ -13,6 +13,18 @@ const normalizeInput = async (input, fetchFn) => {
|
|
|
13
13
|
const normalizeMethodsConfig = (input, methods, defaults) => {
|
|
14
14
|
const methodsObj = Array.isArray(methods) ? Object.fromEntries(methods.map((method) => [method, true])) : methods;
|
|
15
15
|
const methodsConfig = {};
|
|
16
|
+
if (methodsObj.platform) {
|
|
17
|
+
if (!input.url || input.url === "") throw new Error(require_locales.errors.platformMethodRequiresUrl);
|
|
18
|
+
const platformOptions = methodsObj.platform === true ? {} : methodsObj.platform;
|
|
19
|
+
methodsConfig.platform = {
|
|
20
|
+
html: input.content ?? "",
|
|
21
|
+
options: {
|
|
22
|
+
...defaults.platform,
|
|
23
|
+
...platformOptions,
|
|
24
|
+
baseUrl: input.url
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
16
28
|
if (methodsObj.html) {
|
|
17
29
|
if (input.content === void 0) throw new Error(require_locales.errors.htmlMethodRequiresContent);
|
|
18
30
|
const htmlOptions = methodsObj.html === true ? {} : methodsObj.html;
|
|
@@ -13,6 +13,18 @@ const normalizeInput = async (input, fetchFn) => {
|
|
|
13
13
|
const normalizeMethodsConfig = (input, methods, defaults) => {
|
|
14
14
|
const methodsObj = Array.isArray(methods) ? Object.fromEntries(methods.map((method) => [method, true])) : methods;
|
|
15
15
|
const methodsConfig = {};
|
|
16
|
+
if (methodsObj.platform) {
|
|
17
|
+
if (!input.url || input.url === "") throw new Error(errors.platformMethodRequiresUrl);
|
|
18
|
+
const platformOptions = methodsObj.platform === true ? {} : methodsObj.platform;
|
|
19
|
+
methodsConfig.platform = {
|
|
20
|
+
html: input.content ?? "",
|
|
21
|
+
options: {
|
|
22
|
+
...defaults.platform,
|
|
23
|
+
...platformOptions,
|
|
24
|
+
baseUrl: input.url
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
16
28
|
if (methodsObj.html) {
|
|
17
29
|
if (input.content === void 0) throw new Error(errors.htmlMethodRequiresContent);
|
|
18
30
|
const htmlOptions = methodsObj.html === true ? {} : methodsObj.html;
|
package/dist/common/locales.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
//#region src/common/locales.json
|
|
3
3
|
var errors = {
|
|
4
|
+
"platformMethodRequiresUrl": "Platform method requires url to be provided in input",
|
|
4
5
|
"htmlMethodRequiresContent": "HTML method requires content to be provided in input",
|
|
5
6
|
"headersMethodRequiresHeaders": "Headers method requires headers to be provided in input",
|
|
6
7
|
"guessMethodRequiresUrl": "Guess method requires url to be provided in input"
|
package/dist/common/locales.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
//#region src/common/locales.json
|
|
2
2
|
var errors = {
|
|
3
|
+
"platformMethodRequiresUrl": "Platform method requires url to be provided in input",
|
|
3
4
|
"htmlMethodRequiresContent": "HTML method requires content to be provided in input",
|
|
4
5
|
"headersMethodRequiresHeaders": "Headers method requires headers to be provided in input",
|
|
5
6
|
"guessMethodRequiresUrl": "Guess method requires url to be provided in input"
|
package/dist/common/types.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GuessMethodOptions } from "./uris/guess/types.cjs";
|
|
2
2
|
import { HeadersMethodOptions } from "./uris/headers/types.cjs";
|
|
3
3
|
import { HtmlMethodOptions } from "./uris/html/types.cjs";
|
|
4
|
+
import { PlatformMethodOptions } from "./uris/platform/types.cjs";
|
|
4
5
|
|
|
5
6
|
//#region src/common/types.d.ts
|
|
6
7
|
type LinkSelector = {
|
|
@@ -46,7 +47,8 @@ type DiscoverInputObject = {
|
|
|
46
47
|
headers?: Headers;
|
|
47
48
|
};
|
|
48
49
|
type DiscoverInput = string | DiscoverInputObject;
|
|
49
|
-
type DiscoverMethodsConfig = Array<'html' | 'headers' | 'guess'> | {
|
|
50
|
+
type DiscoverMethodsConfig = Array<'platform' | 'html' | 'headers' | 'guess'> | {
|
|
51
|
+
platform?: true | Partial<PlatformMethodOptions>;
|
|
50
52
|
html?: true | Partial<Omit<HtmlMethodOptions, 'baseUrl'>>;
|
|
51
53
|
headers?: true | Partial<Omit<HeadersMethodOptions, 'baseUrl'>>;
|
|
52
54
|
guess?: true | Partial<Omit<GuessMethodOptions, 'baseUrl'>>;
|
package/dist/common/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GuessMethodOptions } from "./uris/guess/types.js";
|
|
2
2
|
import { HeadersMethodOptions } from "./uris/headers/types.js";
|
|
3
3
|
import { HtmlMethodOptions } from "./uris/html/types.js";
|
|
4
|
+
import { PlatformMethodOptions } from "./uris/platform/types.js";
|
|
4
5
|
|
|
5
6
|
//#region src/common/types.d.ts
|
|
6
7
|
type LinkSelector = {
|
|
@@ -46,7 +47,8 @@ type DiscoverInputObject = {
|
|
|
46
47
|
headers?: Headers;
|
|
47
48
|
};
|
|
48
49
|
type DiscoverInput = string | DiscoverInputObject;
|
|
49
|
-
type DiscoverMethodsConfig = Array<'html' | 'headers' | 'guess'> | {
|
|
50
|
+
type DiscoverMethodsConfig = Array<'platform' | 'html' | 'headers' | 'guess'> | {
|
|
51
|
+
platform?: true | Partial<PlatformMethodOptions>;
|
|
50
52
|
html?: true | Partial<Omit<HtmlMethodOptions, 'baseUrl'>>;
|
|
51
53
|
headers?: true | Partial<Omit<HeadersMethodOptions, 'baseUrl'>>;
|
|
52
54
|
guess?: true | Partial<Omit<GuessMethodOptions, 'baseUrl'>>;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
const require_index = require('./guess/index.cjs');
|
|
2
2
|
const require_index$1 = require('./headers/index.cjs');
|
|
3
3
|
const require_index$2 = require('./html/index.cjs');
|
|
4
|
+
const require_index$3 = require('./platform/index.cjs');
|
|
4
5
|
|
|
5
6
|
//#region src/common/uris/index.ts
|
|
6
7
|
const discoverUris = (config) => {
|
|
7
8
|
const uris = /* @__PURE__ */ new Set();
|
|
9
|
+
if (config.platform) for (const uri of require_index$3.discoverUrisFromPlatform(config.platform.html, config.platform.options)) uris.add(uri);
|
|
8
10
|
if (config.html) for (const uri of require_index$2.discoverUrisFromHtml(config.html.html, config.html.options)) uris.add(uri);
|
|
9
11
|
if (config.headers) for (const uri of require_index$1.discoverUrisFromHeaders(config.headers.headers, config.headers.options)) uris.add(uri);
|
|
10
12
|
if (config.guess) for (const uri of require_index.discoverUrisFromGuess(config.guess.options)) uris.add(uri);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { discoverUrisFromGuess } from "./guess/index.js";
|
|
2
2
|
import { discoverUrisFromHeaders } from "./headers/index.js";
|
|
3
3
|
import { discoverUrisFromHtml } from "./html/index.js";
|
|
4
|
+
import { discoverUrisFromPlatform } from "./platform/index.js";
|
|
4
5
|
|
|
5
6
|
//#region src/common/uris/index.ts
|
|
6
7
|
const discoverUris = (config) => {
|
|
7
8
|
const uris = /* @__PURE__ */ new Set();
|
|
9
|
+
if (config.platform) for (const uri of discoverUrisFromPlatform(config.platform.html, config.platform.options)) uris.add(uri);
|
|
8
10
|
if (config.html) for (const uri of discoverUrisFromHtml(config.html.html, config.html.options)) uris.add(uri);
|
|
9
11
|
if (config.headers) for (const uri of discoverUrisFromHeaders(config.headers.headers, config.headers.options)) uris.add(uri);
|
|
10
12
|
if (config.guess) for (const uri of discoverUrisFromGuess(config.guess.options)) uris.add(uri);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/common/uris/platform/index.ts
|
|
3
|
+
const discoverUrisFromPlatform = (html, options) => {
|
|
4
|
+
const { baseUrl, handlers } = options;
|
|
5
|
+
for (const handler of handlers) try {
|
|
6
|
+
if (handler.match(baseUrl)) return handler.resolve(baseUrl, html);
|
|
7
|
+
} catch {}
|
|
8
|
+
return [];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
exports.discoverUrisFromPlatform = discoverUrisFromPlatform;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/common/uris/platform/index.ts
|
|
2
|
+
const discoverUrisFromPlatform = (html, options) => {
|
|
3
|
+
const { baseUrl, handlers } = options;
|
|
4
|
+
for (const handler of handlers) try {
|
|
5
|
+
if (handler.match(baseUrl)) return handler.resolve(baseUrl, html);
|
|
6
|
+
} catch {}
|
|
7
|
+
return [];
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { discoverUrisFromPlatform };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/common/uris/platform/types.d.ts
|
|
2
|
+
type PlatformHandler = {
|
|
3
|
+
match: (url: string) => boolean;
|
|
4
|
+
resolve: (url: string, content?: string) => Array<string>;
|
|
5
|
+
};
|
|
6
|
+
type PlatformMethodOptions = {
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
handlers: Array<PlatformHandler>;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { PlatformMethodOptions };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/common/uris/platform/types.d.ts
|
|
2
|
+
type PlatformHandler = {
|
|
3
|
+
match: (url: string) => boolean;
|
|
4
|
+
resolve: (url: string, content?: string) => Array<string>;
|
|
5
|
+
};
|
|
6
|
+
type PlatformMethodOptions = {
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
handlers: Array<PlatformHandler>;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { PlatformMethodOptions };
|
package/dist/common/utils.cjs
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
const normalizeMimeType = (type) => {
|
|
4
4
|
return type.split(";")[0].trim().toLowerCase();
|
|
5
5
|
};
|
|
6
|
+
const isSubdomainOf = (url, domain) => {
|
|
7
|
+
return new URL(url).hostname.toLowerCase().endsWith(`.${domain}`);
|
|
8
|
+
};
|
|
9
|
+
const isHostOf = (url, hosts) => {
|
|
10
|
+
return isAnyOf(new URL(url).hostname, hosts);
|
|
11
|
+
};
|
|
6
12
|
const includesAnyOf = (value, patterns, parser) => {
|
|
7
13
|
const parsedValue = parser ? parser(value) : value?.toLowerCase();
|
|
8
14
|
return patterns.map((pattern) => pattern.toLowerCase()).some((pattern) => parsedValue?.includes(pattern));
|
|
@@ -52,6 +58,9 @@ const processConcurrently = async (items, processFn, options) => {
|
|
|
52
58
|
//#endregion
|
|
53
59
|
exports.endsWithAnyOf = endsWithAnyOf;
|
|
54
60
|
exports.includesAnyOf = includesAnyOf;
|
|
61
|
+
exports.isAnyOf = isAnyOf;
|
|
62
|
+
exports.isHostOf = isHostOf;
|
|
63
|
+
exports.isSubdomainOf = isSubdomainOf;
|
|
55
64
|
exports.matchesAnyOfLinkSelectors = matchesAnyOfLinkSelectors;
|
|
56
65
|
exports.normalizeUrl = normalizeUrl;
|
|
57
66
|
exports.processConcurrently = processConcurrently;
|
package/dist/common/utils.js
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
const normalizeMimeType = (type) => {
|
|
3
3
|
return type.split(";")[0].trim().toLowerCase();
|
|
4
4
|
};
|
|
5
|
+
const isSubdomainOf = (url, domain) => {
|
|
6
|
+
return new URL(url).hostname.toLowerCase().endsWith(`.${domain}`);
|
|
7
|
+
};
|
|
8
|
+
const isHostOf = (url, hosts) => {
|
|
9
|
+
return isAnyOf(new URL(url).hostname, hosts);
|
|
10
|
+
};
|
|
5
11
|
const includesAnyOf = (value, patterns, parser) => {
|
|
6
12
|
const parsedValue = parser ? parser(value) : value?.toLowerCase();
|
|
7
13
|
return patterns.map((pattern) => pattern.toLowerCase()).some((pattern) => parsedValue?.includes(pattern));
|
|
@@ -49,4 +55,4 @@ const processConcurrently = async (items, processFn, options) => {
|
|
|
49
55
|
};
|
|
50
56
|
|
|
51
57
|
//#endregion
|
|
52
|
-
export { endsWithAnyOf, includesAnyOf, matchesAnyOfLinkSelectors, normalizeUrl, processConcurrently };
|
|
58
|
+
export { endsWithAnyOf, includesAnyOf, isAnyOf, isHostOf, isSubdomainOf, matchesAnyOfLinkSelectors, normalizeUrl, processConcurrently };
|
package/dist/feeds/defaults.cjs
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
const require_blogspot = require('./platform/handlers/blogspot.cjs');
|
|
2
|
+
const require_bluesky = require('./platform/handlers/bluesky.cjs');
|
|
3
|
+
const require_github = require('./platform/handlers/github.cjs');
|
|
4
|
+
const require_gitlab = require('./platform/handlers/gitlab.cjs');
|
|
5
|
+
const require_kickstarter = require('./platform/handlers/kickstarter.cjs');
|
|
6
|
+
const require_reddit = require('./platform/handlers/reddit.cjs');
|
|
7
|
+
const require_soundcloud = require('./platform/handlers/soundcloud.cjs');
|
|
8
|
+
const require_substack = require('./platform/handlers/substack.cjs');
|
|
9
|
+
const require_tumblr = require('./platform/handlers/tumblr.cjs');
|
|
10
|
+
const require_wordpress = require('./platform/handlers/wordpress.cjs');
|
|
11
|
+
const require_youtube = require('./platform/handlers/youtube.cjs');
|
|
1
12
|
|
|
2
13
|
//#region src/feeds/defaults.ts
|
|
3
14
|
const mimeTypes = [
|
|
@@ -75,12 +86,26 @@ const defaultHtmlOptions = {
|
|
|
75
86
|
};
|
|
76
87
|
const defaultHeadersOptions = { linkSelectors };
|
|
77
88
|
const defaultGuessOptions = { uris: urisBalanced };
|
|
89
|
+
const defaultPlatformOptions = { handlers: [
|
|
90
|
+
require_blogspot.blogspotHandler,
|
|
91
|
+
require_bluesky.blueskyHandler,
|
|
92
|
+
require_github.githubHandler,
|
|
93
|
+
require_gitlab.gitlabHandler,
|
|
94
|
+
require_kickstarter.kickstarterHandler,
|
|
95
|
+
require_reddit.redditHandler,
|
|
96
|
+
require_soundcloud.soundcloudHandler,
|
|
97
|
+
require_substack.substackHandler,
|
|
98
|
+
require_tumblr.tumblrHandler,
|
|
99
|
+
require_wordpress.wordpressHandler,
|
|
100
|
+
require_youtube.youtubeHandler
|
|
101
|
+
] };
|
|
78
102
|
|
|
79
103
|
//#endregion
|
|
80
104
|
exports.anchorLabels = anchorLabels;
|
|
81
105
|
exports.defaultGuessOptions = defaultGuessOptions;
|
|
82
106
|
exports.defaultHeadersOptions = defaultHeadersOptions;
|
|
83
107
|
exports.defaultHtmlOptions = defaultHtmlOptions;
|
|
108
|
+
exports.defaultPlatformOptions = defaultPlatformOptions;
|
|
84
109
|
exports.ignoredUris = ignoredUris;
|
|
85
110
|
exports.linkSelectors = linkSelectors;
|
|
86
111
|
exports.mimeTypes = mimeTypes;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
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
|
+
import { PlatformMethodOptions } from "../common/uris/platform/types.cjs";
|
|
4
5
|
import { LinkSelector } from "../common/types.cjs";
|
|
5
6
|
|
|
6
7
|
//#region src/feeds/defaults.d.ts
|
|
@@ -14,5 +15,6 @@ declare const linkSelectors: Array<LinkSelector>;
|
|
|
14
15
|
declare const defaultHtmlOptions: Omit<HtmlMethodOptions, 'baseUrl'>;
|
|
15
16
|
declare const defaultHeadersOptions: Omit<HeadersMethodOptions, 'baseUrl'>;
|
|
16
17
|
declare const defaultGuessOptions: Omit<GuessMethodOptions, 'baseUrl'>;
|
|
18
|
+
declare const defaultPlatformOptions: Omit<PlatformMethodOptions, 'baseUrl'>;
|
|
17
19
|
//#endregion
|
|
18
|
-
export { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
|
20
|
+
export { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
package/dist/feeds/defaults.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
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
|
+
import { PlatformMethodOptions } from "../common/uris/platform/types.js";
|
|
4
5
|
import { LinkSelector } from "../common/types.js";
|
|
5
6
|
|
|
6
7
|
//#region src/feeds/defaults.d.ts
|
|
@@ -14,5 +15,6 @@ declare const linkSelectors: Array<LinkSelector>;
|
|
|
14
15
|
declare const defaultHtmlOptions: Omit<HtmlMethodOptions, 'baseUrl'>;
|
|
15
16
|
declare const defaultHeadersOptions: Omit<HeadersMethodOptions, 'baseUrl'>;
|
|
16
17
|
declare const defaultGuessOptions: Omit<GuessMethodOptions, 'baseUrl'>;
|
|
18
|
+
declare const defaultPlatformOptions: Omit<PlatformMethodOptions, 'baseUrl'>;
|
|
17
19
|
//#endregion
|
|
18
|
-
export { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
|
20
|
+
export { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
package/dist/feeds/defaults.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
import { blogspotHandler } from "./platform/handlers/blogspot.js";
|
|
2
|
+
import { blueskyHandler } from "./platform/handlers/bluesky.js";
|
|
3
|
+
import { githubHandler } from "./platform/handlers/github.js";
|
|
4
|
+
import { gitlabHandler } from "./platform/handlers/gitlab.js";
|
|
5
|
+
import { kickstarterHandler } from "./platform/handlers/kickstarter.js";
|
|
6
|
+
import { redditHandler } from "./platform/handlers/reddit.js";
|
|
7
|
+
import { soundcloudHandler } from "./platform/handlers/soundcloud.js";
|
|
8
|
+
import { substackHandler } from "./platform/handlers/substack.js";
|
|
9
|
+
import { tumblrHandler } from "./platform/handlers/tumblr.js";
|
|
10
|
+
import { wordpressHandler } from "./platform/handlers/wordpress.js";
|
|
11
|
+
import { youtubeHandler } from "./platform/handlers/youtube.js";
|
|
12
|
+
|
|
1
13
|
//#region src/feeds/defaults.ts
|
|
2
14
|
const mimeTypes = [
|
|
3
15
|
"application/rss+xml",
|
|
@@ -74,6 +86,19 @@ const defaultHtmlOptions = {
|
|
|
74
86
|
};
|
|
75
87
|
const defaultHeadersOptions = { linkSelectors };
|
|
76
88
|
const defaultGuessOptions = { uris: urisBalanced };
|
|
89
|
+
const defaultPlatformOptions = { handlers: [
|
|
90
|
+
blogspotHandler,
|
|
91
|
+
blueskyHandler,
|
|
92
|
+
githubHandler,
|
|
93
|
+
gitlabHandler,
|
|
94
|
+
kickstarterHandler,
|
|
95
|
+
redditHandler,
|
|
96
|
+
soundcloudHandler,
|
|
97
|
+
substackHandler,
|
|
98
|
+
tumblrHandler,
|
|
99
|
+
wordpressHandler,
|
|
100
|
+
youtubeHandler
|
|
101
|
+
] };
|
|
77
102
|
|
|
78
103
|
//#endregion
|
|
79
|
-
export { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
|
104
|
+
export { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
package/dist/feeds/index.cjs
CHANGED
|
@@ -12,6 +12,7 @@ const discoverFeeds = async (input, options) => {
|
|
|
12
12
|
extractFn: options.extractFn ?? require_extractors.defaultExtractor,
|
|
13
13
|
normalizeUrlFn: options.normalizeUrlFn ?? require_utils.normalizeUrl
|
|
14
14
|
}, {
|
|
15
|
+
platform: require_defaults.defaultPlatformOptions,
|
|
15
16
|
html: require_defaults.defaultHtmlOptions,
|
|
16
17
|
headers: require_defaults.defaultHeadersOptions,
|
|
17
18
|
guess: require_defaults.defaultGuessOptions
|
package/dist/feeds/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createNativeFetchAdapter } from "../common/discover/adapters.js";
|
|
2
2
|
import { normalizeUrl } from "../common/utils.js";
|
|
3
3
|
import { discover } from "../common/discover/index.js";
|
|
4
|
-
import { defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions } from "./defaults.js";
|
|
4
|
+
import { defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions } from "./defaults.js";
|
|
5
5
|
import { defaultExtractor } from "./extractors.js";
|
|
6
6
|
|
|
7
7
|
//#region src/feeds/index.ts
|
|
@@ -12,6 +12,7 @@ const discoverFeeds = async (input, options) => {
|
|
|
12
12
|
extractFn: options.extractFn ?? defaultExtractor,
|
|
13
13
|
normalizeUrlFn: options.normalizeUrlFn ?? normalizeUrl
|
|
14
14
|
}, {
|
|
15
|
+
platform: defaultPlatformOptions,
|
|
15
16
|
html: defaultHtmlOptions,
|
|
16
17
|
headers: defaultHeadersOptions,
|
|
17
18
|
guess: defaultGuessOptions
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/blogspot.ts
|
|
4
|
+
const blogspotHandler = {
|
|
5
|
+
match: (url) => {
|
|
6
|
+
return require_utils.isSubdomainOf(url, "blogspot.com");
|
|
7
|
+
},
|
|
8
|
+
resolve: (url) => {
|
|
9
|
+
const { origin } = new URL(url);
|
|
10
|
+
return [`${origin}/feeds/posts/default`, `${origin}/feeds/posts/default?alt=rss`];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
exports.blogspotHandler = blogspotHandler;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isSubdomainOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/blogspot.ts
|
|
4
|
+
const blogspotHandler = {
|
|
5
|
+
match: (url) => {
|
|
6
|
+
return isSubdomainOf(url, "blogspot.com");
|
|
7
|
+
},
|
|
8
|
+
resolve: (url) => {
|
|
9
|
+
const { origin } = new URL(url);
|
|
10
|
+
return [`${origin}/feeds/posts/default`, `${origin}/feeds/posts/default?alt=rss`];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { blogspotHandler };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/bluesky.ts
|
|
4
|
+
const hosts = ["bsky.app"];
|
|
5
|
+
const blueskyHandler = {
|
|
6
|
+
match: (url) => {
|
|
7
|
+
return require_utils.isHostOf(url, hosts);
|
|
8
|
+
},
|
|
9
|
+
resolve: (url) => {
|
|
10
|
+
const { pathname } = new URL(url);
|
|
11
|
+
const handle = pathname.match(/^\/profile\/([^/]+)/)?.[1];
|
|
12
|
+
if (!handle) return [];
|
|
13
|
+
return [`https://bsky.app/profile/${handle}/rss`];
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
exports.blueskyHandler = blueskyHandler;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/bluesky.ts
|
|
4
|
+
const hosts = ["bsky.app"];
|
|
5
|
+
const blueskyHandler = {
|
|
6
|
+
match: (url) => {
|
|
7
|
+
return isHostOf(url, hosts);
|
|
8
|
+
},
|
|
9
|
+
resolve: (url) => {
|
|
10
|
+
const { pathname } = new URL(url);
|
|
11
|
+
const handle = pathname.match(/^\/profile\/([^/]+)/)?.[1];
|
|
12
|
+
if (!handle) return [];
|
|
13
|
+
return [`https://bsky.app/profile/${handle}/rss`];
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { blueskyHandler };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/github.ts
|
|
4
|
+
const hosts = ["github.com", "www.github.com"];
|
|
5
|
+
const excludedPaths = [
|
|
6
|
+
"about",
|
|
7
|
+
"account",
|
|
8
|
+
"apps",
|
|
9
|
+
"blog",
|
|
10
|
+
"careers",
|
|
11
|
+
"codespaces",
|
|
12
|
+
"collections",
|
|
13
|
+
"contact",
|
|
14
|
+
"copilot",
|
|
15
|
+
"customer-stories",
|
|
16
|
+
"dashboard",
|
|
17
|
+
"education",
|
|
18
|
+
"enterprise",
|
|
19
|
+
"events",
|
|
20
|
+
"explore",
|
|
21
|
+
"features",
|
|
22
|
+
"feed",
|
|
23
|
+
"home",
|
|
24
|
+
"issues",
|
|
25
|
+
"join",
|
|
26
|
+
"login",
|
|
27
|
+
"marketplace",
|
|
28
|
+
"new",
|
|
29
|
+
"nonprofit",
|
|
30
|
+
"notifications",
|
|
31
|
+
"organizations",
|
|
32
|
+
"orgs",
|
|
33
|
+
"password_reset",
|
|
34
|
+
"premium-support",
|
|
35
|
+
"pricing",
|
|
36
|
+
"pulls",
|
|
37
|
+
"readme",
|
|
38
|
+
"resources",
|
|
39
|
+
"search",
|
|
40
|
+
"security",
|
|
41
|
+
"sessions",
|
|
42
|
+
"settings",
|
|
43
|
+
"site",
|
|
44
|
+
"sponsors",
|
|
45
|
+
"stars",
|
|
46
|
+
"team",
|
|
47
|
+
"topics",
|
|
48
|
+
"trending",
|
|
49
|
+
"watching"
|
|
50
|
+
];
|
|
51
|
+
const githubHandler = {
|
|
52
|
+
match: (url) => {
|
|
53
|
+
return require_utils.isHostOf(url, hosts);
|
|
54
|
+
},
|
|
55
|
+
resolve: (url) => {
|
|
56
|
+
const { pathname } = new URL(url);
|
|
57
|
+
const uris = [];
|
|
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
|
+
}
|
|
64
|
+
const repoMatch = pathname.match(/^\/([^/]+)\/([^/]+)/);
|
|
65
|
+
const owner = repoMatch?.[1];
|
|
66
|
+
const repo = repoMatch?.[2];
|
|
67
|
+
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 (pathname.includes("/wiki")) uris.push(`https://github.com/${owner}/${repo}/wiki.atom`);
|
|
72
|
+
if (pathname.includes("/discussions")) uris.push(`https://github.com/${owner}/${repo}/discussions.atom`);
|
|
73
|
+
const branchMatch = pathname.match(/^\/[^/]+\/[^/]+\/tree\/([^/]+)/);
|
|
74
|
+
if (branchMatch?.[1]) {
|
|
75
|
+
const branch = branchMatch[1];
|
|
76
|
+
uris.push(`https://github.com/${owner}/${repo}/commits/${branch}.atom`);
|
|
77
|
+
}
|
|
78
|
+
return uris;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
exports.githubHandler = githubHandler;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/github.ts
|
|
4
|
+
const hosts = ["github.com", "www.github.com"];
|
|
5
|
+
const excludedPaths = [
|
|
6
|
+
"about",
|
|
7
|
+
"account",
|
|
8
|
+
"apps",
|
|
9
|
+
"blog",
|
|
10
|
+
"careers",
|
|
11
|
+
"codespaces",
|
|
12
|
+
"collections",
|
|
13
|
+
"contact",
|
|
14
|
+
"copilot",
|
|
15
|
+
"customer-stories",
|
|
16
|
+
"dashboard",
|
|
17
|
+
"education",
|
|
18
|
+
"enterprise",
|
|
19
|
+
"events",
|
|
20
|
+
"explore",
|
|
21
|
+
"features",
|
|
22
|
+
"feed",
|
|
23
|
+
"home",
|
|
24
|
+
"issues",
|
|
25
|
+
"join",
|
|
26
|
+
"login",
|
|
27
|
+
"marketplace",
|
|
28
|
+
"new",
|
|
29
|
+
"nonprofit",
|
|
30
|
+
"notifications",
|
|
31
|
+
"organizations",
|
|
32
|
+
"orgs",
|
|
33
|
+
"password_reset",
|
|
34
|
+
"premium-support",
|
|
35
|
+
"pricing",
|
|
36
|
+
"pulls",
|
|
37
|
+
"readme",
|
|
38
|
+
"resources",
|
|
39
|
+
"search",
|
|
40
|
+
"security",
|
|
41
|
+
"sessions",
|
|
42
|
+
"settings",
|
|
43
|
+
"site",
|
|
44
|
+
"sponsors",
|
|
45
|
+
"stars",
|
|
46
|
+
"team",
|
|
47
|
+
"topics",
|
|
48
|
+
"trending",
|
|
49
|
+
"watching"
|
|
50
|
+
];
|
|
51
|
+
const githubHandler = {
|
|
52
|
+
match: (url) => {
|
|
53
|
+
return isHostOf(url, hosts);
|
|
54
|
+
},
|
|
55
|
+
resolve: (url) => {
|
|
56
|
+
const { pathname } = new URL(url);
|
|
57
|
+
const uris = [];
|
|
58
|
+
const userMatch = pathname.match(/^\/([^/]+)\/?$/);
|
|
59
|
+
if (userMatch?.[1] && !isAnyOf(userMatch[1], excludedPaths)) {
|
|
60
|
+
const user = userMatch[1];
|
|
61
|
+
uris.push(`https://github.com/${user}.atom`);
|
|
62
|
+
return uris;
|
|
63
|
+
}
|
|
64
|
+
const repoMatch = pathname.match(/^\/([^/]+)\/([^/]+)/);
|
|
65
|
+
const owner = repoMatch?.[1];
|
|
66
|
+
const repo = repoMatch?.[2];
|
|
67
|
+
if (!owner || !repo || 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 (pathname.includes("/wiki")) uris.push(`https://github.com/${owner}/${repo}/wiki.atom`);
|
|
72
|
+
if (pathname.includes("/discussions")) uris.push(`https://github.com/${owner}/${repo}/discussions.atom`);
|
|
73
|
+
const branchMatch = pathname.match(/^\/[^/]+\/[^/]+\/tree\/([^/]+)/);
|
|
74
|
+
if (branchMatch?.[1]) {
|
|
75
|
+
const branch = branchMatch[1];
|
|
76
|
+
uris.push(`https://github.com/${owner}/${repo}/commits/${branch}.atom`);
|
|
77
|
+
}
|
|
78
|
+
return uris;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
export { githubHandler };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/gitlab.ts
|
|
4
|
+
const hosts = ["gitlab.com", "www.gitlab.com"];
|
|
5
|
+
const gitlabHandler = {
|
|
6
|
+
match: (url) => {
|
|
7
|
+
return require_utils.isHostOf(url, hosts);
|
|
8
|
+
},
|
|
9
|
+
resolve: (url) => {
|
|
10
|
+
const { origin, pathname } = new URL(url);
|
|
11
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
12
|
+
if (pathSegments.length === 1) return [`${origin}/${pathSegments[0]}.atom`];
|
|
13
|
+
if (pathSegments.length >= 2) return [`${origin}/${pathSegments[0]}/${pathSegments[1]}.atom`];
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
exports.gitlabHandler = gitlabHandler;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/gitlab.ts
|
|
4
|
+
const hosts = ["gitlab.com", "www.gitlab.com"];
|
|
5
|
+
const gitlabHandler = {
|
|
6
|
+
match: (url) => {
|
|
7
|
+
return isHostOf(url, hosts);
|
|
8
|
+
},
|
|
9
|
+
resolve: (url) => {
|
|
10
|
+
const { origin, pathname } = new URL(url);
|
|
11
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
12
|
+
if (pathSegments.length === 1) return [`${origin}/${pathSegments[0]}.atom`];
|
|
13
|
+
if (pathSegments.length >= 2) return [`${origin}/${pathSegments[0]}/${pathSegments[1]}.atom`];
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { gitlabHandler };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/kickstarter.ts
|
|
4
|
+
const hosts = ["kickstarter.com", "www.kickstarter.com"];
|
|
5
|
+
const kickstarterHandler = {
|
|
6
|
+
match: (url) => {
|
|
7
|
+
if (!require_utils.isHostOf(url, hosts)) return false;
|
|
8
|
+
const { pathname } = new URL(url);
|
|
9
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
10
|
+
return pathSegments.length >= 3 && pathSegments[0] === "projects";
|
|
11
|
+
},
|
|
12
|
+
resolve: (url) => {
|
|
13
|
+
const { origin, pathname } = new URL(url);
|
|
14
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
15
|
+
if (pathSegments.length >= 3 && pathSegments[0] === "projects") return [`${origin}/projects/${pathSegments[1]}/${pathSegments[2]}/posts.atom`];
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
exports.kickstarterHandler = kickstarterHandler;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/kickstarter.ts
|
|
4
|
+
const hosts = ["kickstarter.com", "www.kickstarter.com"];
|
|
5
|
+
const kickstarterHandler = {
|
|
6
|
+
match: (url) => {
|
|
7
|
+
if (!isHostOf(url, hosts)) return false;
|
|
8
|
+
const { pathname } = new URL(url);
|
|
9
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
10
|
+
return pathSegments.length >= 3 && pathSegments[0] === "projects";
|
|
11
|
+
},
|
|
12
|
+
resolve: (url) => {
|
|
13
|
+
const { origin, pathname } = new URL(url);
|
|
14
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
15
|
+
if (pathSegments.length >= 3 && pathSegments[0] === "projects") return [`${origin}/projects/${pathSegments[1]}/${pathSegments[2]}/posts.atom`];
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
export { kickstarterHandler };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/reddit.ts
|
|
4
|
+
const hosts = [
|
|
5
|
+
"reddit.com",
|
|
6
|
+
"www.reddit.com",
|
|
7
|
+
"old.reddit.com",
|
|
8
|
+
"new.reddit.com"
|
|
9
|
+
];
|
|
10
|
+
const sortOptions = [
|
|
11
|
+
"hot",
|
|
12
|
+
"new",
|
|
13
|
+
"rising",
|
|
14
|
+
"controversial",
|
|
15
|
+
"top"
|
|
16
|
+
];
|
|
17
|
+
const redditHandler = {
|
|
18
|
+
match: (url) => {
|
|
19
|
+
return require_utils.isHostOf(url, hosts);
|
|
20
|
+
},
|
|
21
|
+
resolve: (url) => {
|
|
22
|
+
const { pathname } = new URL(url);
|
|
23
|
+
const commentsMatch = pathname.match(/^\/r\/([^/]+)\/comments\/([^/]+)/);
|
|
24
|
+
if (commentsMatch?.[1] && commentsMatch?.[2]) return [`https://www.reddit.com/r/${commentsMatch[1]}/comments/${commentsMatch[2]}/.rss`];
|
|
25
|
+
const subredditMatch = pathname.match(/^\/r\/([^/]+)(?:\/([^/]+))?/);
|
|
26
|
+
if (subredditMatch?.[1]) {
|
|
27
|
+
const subreddit = subredditMatch[1];
|
|
28
|
+
const sort = subredditMatch[2];
|
|
29
|
+
const uris = [];
|
|
30
|
+
if (sort && require_utils.isAnyOf(sort, sortOptions)) uris.push(`https://www.reddit.com/r/${subreddit}/${sort}/.rss`);
|
|
31
|
+
else uris.push(`https://www.reddit.com/r/${subreddit}/.rss`);
|
|
32
|
+
uris.push(`https://www.reddit.com/r/${subreddit}/comments/.rss`);
|
|
33
|
+
return uris;
|
|
34
|
+
}
|
|
35
|
+
const userMatch = pathname.match(/^\/(u|user)\/([^/]+)/);
|
|
36
|
+
if (userMatch?.[2]) return [`https://www.reddit.com/user/${userMatch[2]}/.rss`];
|
|
37
|
+
const domainMatch = pathname.match(/^\/domain\/([^/]+)/);
|
|
38
|
+
if (domainMatch?.[1]) return [`https://www.reddit.com/domain/${domainMatch[1]}/.rss`];
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
exports.redditHandler = redditHandler;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/reddit.ts
|
|
4
|
+
const hosts = [
|
|
5
|
+
"reddit.com",
|
|
6
|
+
"www.reddit.com",
|
|
7
|
+
"old.reddit.com",
|
|
8
|
+
"new.reddit.com"
|
|
9
|
+
];
|
|
10
|
+
const sortOptions = [
|
|
11
|
+
"hot",
|
|
12
|
+
"new",
|
|
13
|
+
"rising",
|
|
14
|
+
"controversial",
|
|
15
|
+
"top"
|
|
16
|
+
];
|
|
17
|
+
const redditHandler = {
|
|
18
|
+
match: (url) => {
|
|
19
|
+
return isHostOf(url, hosts);
|
|
20
|
+
},
|
|
21
|
+
resolve: (url) => {
|
|
22
|
+
const { pathname } = new URL(url);
|
|
23
|
+
const commentsMatch = pathname.match(/^\/r\/([^/]+)\/comments\/([^/]+)/);
|
|
24
|
+
if (commentsMatch?.[1] && commentsMatch?.[2]) return [`https://www.reddit.com/r/${commentsMatch[1]}/comments/${commentsMatch[2]}/.rss`];
|
|
25
|
+
const subredditMatch = pathname.match(/^\/r\/([^/]+)(?:\/([^/]+))?/);
|
|
26
|
+
if (subredditMatch?.[1]) {
|
|
27
|
+
const subreddit = subredditMatch[1];
|
|
28
|
+
const sort = subredditMatch[2];
|
|
29
|
+
const uris = [];
|
|
30
|
+
if (sort && isAnyOf(sort, sortOptions)) uris.push(`https://www.reddit.com/r/${subreddit}/${sort}/.rss`);
|
|
31
|
+
else uris.push(`https://www.reddit.com/r/${subreddit}/.rss`);
|
|
32
|
+
uris.push(`https://www.reddit.com/r/${subreddit}/comments/.rss`);
|
|
33
|
+
return uris;
|
|
34
|
+
}
|
|
35
|
+
const userMatch = pathname.match(/^\/(u|user)\/([^/]+)/);
|
|
36
|
+
if (userMatch?.[2]) return [`https://www.reddit.com/user/${userMatch[2]}/.rss`];
|
|
37
|
+
const domainMatch = pathname.match(/^\/domain\/([^/]+)/);
|
|
38
|
+
if (domainMatch?.[1]) return [`https://www.reddit.com/domain/${domainMatch[1]}/.rss`];
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { redditHandler };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/soundcloud.ts
|
|
4
|
+
const hosts = [
|
|
5
|
+
"soundcloud.com",
|
|
6
|
+
"www.soundcloud.com",
|
|
7
|
+
"m.soundcloud.com"
|
|
8
|
+
];
|
|
9
|
+
const excludedPaths = [
|
|
10
|
+
"discover",
|
|
11
|
+
"stream",
|
|
12
|
+
"search",
|
|
13
|
+
"upload",
|
|
14
|
+
"you",
|
|
15
|
+
"settings",
|
|
16
|
+
"messages"
|
|
17
|
+
];
|
|
18
|
+
const extractUserIdFromContent = (content) => {
|
|
19
|
+
return content.match(/soundcloud:\/\/users:(\d+)/)?.[1];
|
|
20
|
+
};
|
|
21
|
+
const soundcloudHandler = {
|
|
22
|
+
match: (url) => {
|
|
23
|
+
if (!require_utils.isHostOf(url, hosts)) return false;
|
|
24
|
+
const { pathname } = new URL(url);
|
|
25
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
26
|
+
return pathSegments.length >= 1 && !excludedPaths.includes(pathSegments[0]);
|
|
27
|
+
},
|
|
28
|
+
resolve: (_url, content) => {
|
|
29
|
+
if (!content) return [];
|
|
30
|
+
const userId = extractUserIdFromContent(content);
|
|
31
|
+
if (!userId) return [];
|
|
32
|
+
return [`https://feeds.soundcloud.com/users/soundcloud:users:${userId}/sounds.rss`];
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
exports.soundcloudHandler = soundcloudHandler;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/soundcloud.ts
|
|
4
|
+
const hosts = [
|
|
5
|
+
"soundcloud.com",
|
|
6
|
+
"www.soundcloud.com",
|
|
7
|
+
"m.soundcloud.com"
|
|
8
|
+
];
|
|
9
|
+
const excludedPaths = [
|
|
10
|
+
"discover",
|
|
11
|
+
"stream",
|
|
12
|
+
"search",
|
|
13
|
+
"upload",
|
|
14
|
+
"you",
|
|
15
|
+
"settings",
|
|
16
|
+
"messages"
|
|
17
|
+
];
|
|
18
|
+
const extractUserIdFromContent = (content) => {
|
|
19
|
+
return content.match(/soundcloud:\/\/users:(\d+)/)?.[1];
|
|
20
|
+
};
|
|
21
|
+
const soundcloudHandler = {
|
|
22
|
+
match: (url) => {
|
|
23
|
+
if (!isHostOf(url, hosts)) return false;
|
|
24
|
+
const { pathname } = new URL(url);
|
|
25
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
26
|
+
return pathSegments.length >= 1 && !excludedPaths.includes(pathSegments[0]);
|
|
27
|
+
},
|
|
28
|
+
resolve: (_url, content) => {
|
|
29
|
+
if (!content) return [];
|
|
30
|
+
const userId = extractUserIdFromContent(content);
|
|
31
|
+
if (!userId) return [];
|
|
32
|
+
return [`https://feeds.soundcloud.com/users/soundcloud:users:${userId}/sounds.rss`];
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { soundcloudHandler };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/substack.ts
|
|
4
|
+
const substackHandler = {
|
|
5
|
+
match: (url) => {
|
|
6
|
+
return require_utils.isSubdomainOf(url, "substack.com");
|
|
7
|
+
},
|
|
8
|
+
resolve: (url) => {
|
|
9
|
+
const { origin } = new URL(url);
|
|
10
|
+
return [`${origin}/feed`];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
exports.substackHandler = substackHandler;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isSubdomainOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/substack.ts
|
|
4
|
+
const substackHandler = {
|
|
5
|
+
match: (url) => {
|
|
6
|
+
return isSubdomainOf(url, "substack.com");
|
|
7
|
+
},
|
|
8
|
+
resolve: (url) => {
|
|
9
|
+
const { origin } = new URL(url);
|
|
10
|
+
return [`${origin}/feed`];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { substackHandler };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/tumblr.ts
|
|
4
|
+
const tumblrHandler = {
|
|
5
|
+
match: (url) => {
|
|
6
|
+
return require_utils.isSubdomainOf(url, "tumblr.com");
|
|
7
|
+
},
|
|
8
|
+
resolve: (url) => {
|
|
9
|
+
const { origin } = new URL(url);
|
|
10
|
+
return [`${origin}/rss`];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
exports.tumblrHandler = tumblrHandler;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isSubdomainOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/tumblr.ts
|
|
4
|
+
const tumblrHandler = {
|
|
5
|
+
match: (url) => {
|
|
6
|
+
return isSubdomainOf(url, "tumblr.com");
|
|
7
|
+
},
|
|
8
|
+
resolve: (url) => {
|
|
9
|
+
const { origin } = new URL(url);
|
|
10
|
+
return [`${origin}/rss`];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { tumblrHandler };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/wordpress.ts
|
|
4
|
+
const wordpressHandler = {
|
|
5
|
+
match: (url) => {
|
|
6
|
+
return require_utils.isSubdomainOf(url, "wordpress.com");
|
|
7
|
+
},
|
|
8
|
+
resolve: (url) => {
|
|
9
|
+
const { origin } = new URL(url);
|
|
10
|
+
return [
|
|
11
|
+
`${origin}/feed/`,
|
|
12
|
+
`${origin}/feed/atom/`,
|
|
13
|
+
`${origin}/comments/feed/`
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
exports.wordpressHandler = wordpressHandler;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isSubdomainOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/wordpress.ts
|
|
4
|
+
const wordpressHandler = {
|
|
5
|
+
match: (url) => {
|
|
6
|
+
return isSubdomainOf(url, "wordpress.com");
|
|
7
|
+
},
|
|
8
|
+
resolve: (url) => {
|
|
9
|
+
const { origin } = new URL(url);
|
|
10
|
+
return [
|
|
11
|
+
`${origin}/feed/`,
|
|
12
|
+
`${origin}/feed/atom/`,
|
|
13
|
+
`${origin}/comments/feed/`
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { wordpressHandler };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/youtube.ts
|
|
4
|
+
const hosts = [
|
|
5
|
+
"youtube.com",
|
|
6
|
+
"www.youtube.com",
|
|
7
|
+
"m.youtube.com"
|
|
8
|
+
];
|
|
9
|
+
const extractChannelIdFromContent = (content) => {
|
|
10
|
+
return content.match(/"channelId":"(UC[a-zA-Z0-9_-]+)"/)?.[1];
|
|
11
|
+
};
|
|
12
|
+
const getVideosOnlyPlaylistId = (channelId) => {
|
|
13
|
+
return channelId.replace(/^UC/, "UULF");
|
|
14
|
+
};
|
|
15
|
+
const youtubeHandler = {
|
|
16
|
+
match: (url) => {
|
|
17
|
+
return require_utils.isHostOf(url, hosts);
|
|
18
|
+
},
|
|
19
|
+
resolve: (url, content) => {
|
|
20
|
+
const parsedUrl = new URL(url);
|
|
21
|
+
const uris = [];
|
|
22
|
+
const channelMatch = parsedUrl.pathname.match(/^\/channel\/(UC[a-zA-Z0-9_-]+)/);
|
|
23
|
+
if (channelMatch?.[1]) {
|
|
24
|
+
const channelId = channelMatch[1];
|
|
25
|
+
uris.push(`https://www.youtube.com/feeds/videos.xml?channel_id=${channelId}`);
|
|
26
|
+
uris.push(`https://www.youtube.com/feeds/videos.xml?playlist_id=${getVideosOnlyPlaylistId(channelId)}`);
|
|
27
|
+
}
|
|
28
|
+
const playlistId = parsedUrl.searchParams.get("list");
|
|
29
|
+
if (playlistId) uris.push(`https://www.youtube.com/feeds/videos.xml?playlist_id=${playlistId}`);
|
|
30
|
+
if (uris.length === 0 && content) {
|
|
31
|
+
if (parsedUrl.pathname.match(/^\/@([^/]+)/) || parsedUrl.pathname.match(/^\/user\/([^/]+)/) || parsedUrl.pathname.match(/^\/c\/([^/]+)/)) {
|
|
32
|
+
const channelId = extractChannelIdFromContent(content);
|
|
33
|
+
if (channelId) {
|
|
34
|
+
uris.push(`https://www.youtube.com/feeds/videos.xml?channel_id=${channelId}`);
|
|
35
|
+
uris.push(`https://www.youtube.com/feeds/videos.xml?playlist_id=${getVideosOnlyPlaylistId(channelId)}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return uris;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
exports.youtubeHandler = youtubeHandler;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/youtube.ts
|
|
4
|
+
const hosts = [
|
|
5
|
+
"youtube.com",
|
|
6
|
+
"www.youtube.com",
|
|
7
|
+
"m.youtube.com"
|
|
8
|
+
];
|
|
9
|
+
const extractChannelIdFromContent = (content) => {
|
|
10
|
+
return content.match(/"channelId":"(UC[a-zA-Z0-9_-]+)"/)?.[1];
|
|
11
|
+
};
|
|
12
|
+
const getVideosOnlyPlaylistId = (channelId) => {
|
|
13
|
+
return channelId.replace(/^UC/, "UULF");
|
|
14
|
+
};
|
|
15
|
+
const youtubeHandler = {
|
|
16
|
+
match: (url) => {
|
|
17
|
+
return isHostOf(url, hosts);
|
|
18
|
+
},
|
|
19
|
+
resolve: (url, content) => {
|
|
20
|
+
const parsedUrl = new URL(url);
|
|
21
|
+
const uris = [];
|
|
22
|
+
const channelMatch = parsedUrl.pathname.match(/^\/channel\/(UC[a-zA-Z0-9_-]+)/);
|
|
23
|
+
if (channelMatch?.[1]) {
|
|
24
|
+
const channelId = channelMatch[1];
|
|
25
|
+
uris.push(`https://www.youtube.com/feeds/videos.xml?channel_id=${channelId}`);
|
|
26
|
+
uris.push(`https://www.youtube.com/feeds/videos.xml?playlist_id=${getVideosOnlyPlaylistId(channelId)}`);
|
|
27
|
+
}
|
|
28
|
+
const playlistId = parsedUrl.searchParams.get("list");
|
|
29
|
+
if (playlistId) uris.push(`https://www.youtube.com/feeds/videos.xml?playlist_id=${playlistId}`);
|
|
30
|
+
if (uris.length === 0 && content) {
|
|
31
|
+
if (parsedUrl.pathname.match(/^\/@([^/]+)/) || parsedUrl.pathname.match(/^\/user\/([^/]+)/) || parsedUrl.pathname.match(/^\/c\/([^/]+)/)) {
|
|
32
|
+
const channelId = extractChannelIdFromContent(content);
|
|
33
|
+
if (channelId) {
|
|
34
|
+
uris.push(`https://www.youtube.com/feeds/videos.xml?channel_id=${channelId}`);
|
|
35
|
+
uris.push(`https://www.youtube.com/feeds/videos.xml?playlist_id=${getVideosOnlyPlaylistId(channelId)}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return uris;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { youtubeHandler };
|
package/dist/feeds.cjs
CHANGED
|
@@ -6,6 +6,7 @@ exports.defaultExtractor = require_extractors.defaultExtractor;
|
|
|
6
6
|
exports.defaultGuessOptions = require_defaults.defaultGuessOptions;
|
|
7
7
|
exports.defaultHeadersOptions = require_defaults.defaultHeadersOptions;
|
|
8
8
|
exports.defaultHtmlOptions = require_defaults.defaultHtmlOptions;
|
|
9
|
+
exports.defaultPlatformOptions = require_defaults.defaultPlatformOptions;
|
|
9
10
|
exports.ignoredUris = require_defaults.ignoredUris;
|
|
10
11
|
exports.linkSelectors = require_defaults.linkSelectors;
|
|
11
12
|
exports.mimeTypes = require_defaults.mimeTypes;
|
package/dist/feeds.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal } from "./feeds/defaults.cjs";
|
|
1
|
+
import { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal } from "./feeds/defaults.cjs";
|
|
2
2
|
import { FeedResult } from "./feeds/types.cjs";
|
|
3
3
|
import { defaultExtractor } from "./feeds/extractors.cjs";
|
|
4
|
-
export { FeedResult, anchorLabels, defaultExtractor, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
|
4
|
+
export { FeedResult, anchorLabels, defaultExtractor, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
package/dist/feeds.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal } from "./feeds/defaults.js";
|
|
1
|
+
import { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal } from "./feeds/defaults.js";
|
|
2
2
|
import { FeedResult } from "./feeds/types.js";
|
|
3
3
|
import { defaultExtractor } from "./feeds/extractors.js";
|
|
4
|
-
export { FeedResult, anchorLabels, defaultExtractor, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
|
4
|
+
export { FeedResult, anchorLabels, defaultExtractor, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
package/dist/feeds.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal } from "./feeds/defaults.js";
|
|
1
|
+
import { anchorLabels, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal } from "./feeds/defaults.js";
|
|
2
2
|
import { defaultExtractor } from "./feeds/extractors.js";
|
|
3
3
|
|
|
4
|
-
export { anchorLabels, defaultExtractor, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
|
4
|
+
export { anchorLabels, defaultExtractor, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
|
package/package.json
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feedscout",
|
|
3
3
|
"description": "Advanced feed autodiscovery for JavaScript. Collect feed information from any webpage using multiple discovery methods.",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/macieklamberski/feedscout.git"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://feedscout.dev",
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/macieklamberski/feedscout/issues"
|
|
11
|
+
},
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Maciej Lamberski",
|
|
14
|
+
"sideEffects": false,
|
|
4
15
|
"keywords": [
|
|
5
16
|
"rss",
|
|
6
17
|
"rss-autodiscovery",
|
|
@@ -12,20 +23,7 @@
|
|
|
12
23
|
"rss-discovery",
|
|
13
24
|
"feed-locator"
|
|
14
25
|
],
|
|
15
|
-
"repository": {
|
|
16
|
-
"type": "git",
|
|
17
|
-
"url": "https://github.com/macieklamberski/feedscout.git"
|
|
18
|
-
},
|
|
19
|
-
"homepage": "https://github.com/macieklamberski/feedscout",
|
|
20
|
-
"bugs": {
|
|
21
|
-
"url": "https://github.com/macieklamberski/feedscout/issues"
|
|
22
|
-
},
|
|
23
|
-
"author": "Maciej Lamberski",
|
|
24
|
-
"license": "MIT",
|
|
25
26
|
"type": "module",
|
|
26
|
-
"files": [
|
|
27
|
-
"dist"
|
|
28
|
-
],
|
|
29
27
|
"exports": {
|
|
30
28
|
".": {
|
|
31
29
|
"import": {
|
|
@@ -89,6 +87,9 @@
|
|
|
89
87
|
},
|
|
90
88
|
"./package.json": "./package.json"
|
|
91
89
|
},
|
|
90
|
+
"files": [
|
|
91
|
+
"dist"
|
|
92
|
+
],
|
|
92
93
|
"scripts": {
|
|
93
94
|
"prepare": "lefthook install",
|
|
94
95
|
"build": "tsdown src/exports/index.ts src/exports/feeds.ts src/exports/blogrolls.ts src/exports/hubs.ts src/exports/adapters.ts src/exports/methods.ts --format cjs,esm --dts --clean --unbundle --no-fixed-extension",
|
|
@@ -103,8 +104,8 @@
|
|
|
103
104
|
"devDependencies": {
|
|
104
105
|
"@types/bun": "^1.3.4",
|
|
105
106
|
"kvalita": "1.8.0",
|
|
106
|
-
"tsdown": "^0.17.
|
|
107
|
+
"tsdown": "^0.17.2",
|
|
107
108
|
"vitepress": "^1.6.4"
|
|
108
109
|
},
|
|
109
|
-
"version": "1.
|
|
110
|
+
"version": "1.1.0"
|
|
110
111
|
}
|