feedscout 2.0.0-rc.1 → 2.0.0-rc.2

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/feeds.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { anchorAttributes, anchorLabels, anchorPathSegments, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal } from "./src/feeds/defaults.js";
1
+ import { anchorAttributes, anchorLabels, anchorPathSegments, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, sectionNames, urisBalanced, urisComprehensive, urisMinimal } from "./src/feeds/defaults.js";
2
2
  import { FeedResult } from "./src/feeds/types.js";
3
3
  import { defaultExtractFn } from "./src/feeds/extractors.js";
4
- export { FeedResult, anchorAttributes, anchorLabels, anchorPathSegments, defaultExtractFn, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
4
+ export { FeedResult, anchorAttributes, anchorLabels, anchorPathSegments, defaultExtractFn, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, sectionNames, urisBalanced, urisComprehensive, urisMinimal };
package/dist/feeds.js CHANGED
@@ -1,3 +1,3 @@
1
- import { anchorAttributes, anchorLabels, anchorPathSegments, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal } from "./src/feeds/defaults.js";
1
+ import { anchorAttributes, anchorLabels, anchorPathSegments, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, sectionNames, urisBalanced, urisComprehensive, urisMinimal } from "./src/feeds/defaults.js";
2
2
  import { defaultExtractFn } from "./src/feeds/extractors.js";
3
- export { anchorAttributes, anchorLabels, anchorPathSegments, defaultExtractFn, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
3
+ export { anchorAttributes, anchorLabels, anchorPathSegments, defaultExtractFn, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, sectionNames, urisBalanced, urisComprehensive, urisMinimal };
package/dist/methods.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { discoverUrisFromFeed } from "./src/common/uris/feed/index.js";
2
2
  import { discoverUrisFromGuess } from "./src/common/uris/guess/index.js";
3
- import { generateUrlCombinations, getSubdomainVariants, getWwwCounterpart } from "./src/common/uris/guess/utils.js";
3
+ import { extractSectionBaseUrls, generateUrlCombinations, getSubdomainVariants, getWwwCounterpart } from "./src/common/uris/guess/utils.js";
4
4
  import { discoverUrisFromHeaders } from "./src/common/uris/headers/index.js";
5
5
  import { discoverUrisFromHtml } from "./src/common/uris/html/index.js";
6
6
  import { discoverUrisFromPlatform } from "./src/common/uris/platform/index.js";
7
- export { discoverUrisFromFeed, discoverUrisFromGuess, discoverUrisFromHeaders, discoverUrisFromHtml, discoverUrisFromPlatform, generateUrlCombinations, getSubdomainVariants, getWwwCounterpart };
7
+ export { discoverUrisFromFeed, discoverUrisFromGuess, discoverUrisFromHeaders, discoverUrisFromHtml, discoverUrisFromPlatform, extractSectionBaseUrls, generateUrlCombinations, getSubdomainVariants, getWwwCounterpart };
package/dist/methods.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { discoverUrisFromFeed } from "./src/common/uris/feed/index.js";
2
- import { generateUrlCombinations, getSubdomainVariants, getWwwCounterpart } from "./src/common/uris/guess/utils.js";
2
+ import { extractSectionBaseUrls, generateUrlCombinations, getSubdomainVariants, getWwwCounterpart } from "./src/common/uris/guess/utils.js";
3
3
  import { discoverUrisFromGuess } from "./src/common/uris/guess/index.js";
4
4
  import { discoverUrisFromHeaders } from "./src/common/uris/headers/index.js";
5
5
  import { discoverUrisFromHtml } from "./src/common/uris/html/index.js";
6
6
  import { discoverUrisFromPlatform } from "./src/common/uris/platform/index.js";
7
- export { discoverUrisFromFeed, discoverUrisFromGuess, discoverUrisFromHeaders, discoverUrisFromHtml, discoverUrisFromPlatform, generateUrlCombinations, getSubdomainVariants, getWwwCounterpart };
7
+ export { discoverUrisFromFeed, discoverUrisFromGuess, discoverUrisFromHeaders, discoverUrisFromHtml, discoverUrisFromPlatform, extractSectionBaseUrls, generateUrlCombinations, getSubdomainVariants, getWwwCounterpart };
@@ -6,6 +6,9 @@ const parseUrl = (value, base) => {
6
6
  return new URL(value, base);
7
7
  } catch {}
8
8
  };
9
+ const getPathSegments = (value) => {
10
+ return parseUrl(value)?.pathname.split("/").filter(Boolean) ?? [];
11
+ };
9
12
  const isHostOf = (url, hosts) => {
10
13
  const hostname = parseUrl(url)?.hostname;
11
14
  if (!hostname) return false;
@@ -17,4 +20,4 @@ const isSubdomainOf = (url, domains) => {
17
20
  return endsWithAnyOf(hostname, (Array.isArray(domains) ? domains : [domains]).map((domain) => `.${domain}`));
18
21
  };
19
22
  //#endregion
20
- export { isHostOf, isSubdomainOf, parseUrl };
23
+ export { getPathSegments, isHostOf, isSubdomainOf, parseUrl };
@@ -94,6 +94,7 @@ const normalizeMethodsConfig = (sourceInput, siteInput, methods, defaults) => {
94
94
  const guessOptions = methodsObj.guess === true ? {} : methodsObj.guess;
95
95
  methodsConfig.guess = { options: {
96
96
  ...defaults.guess,
97
+ content: resolvedInput.content,
97
98
  ...guessOptions,
98
99
  baseUrl: resolvedInput.url
99
100
  } };
@@ -1,8 +1,16 @@
1
- import { generateUrlCombinations } from "./utils.js";
1
+ import { extractSectionBaseUrls, generatePathUrlCombinations, generateUrlCombinations, getAncestorPathBases } from "./utils.js";
2
2
  //#region src/common/uris/guess/index.ts
3
3
  const discoverUrisFromGuess = (options) => {
4
- const { baseUrl, uris, additionalBaseUrls = [] } = options;
5
- return generateUrlCombinations([baseUrl, ...additionalBaseUrls], uris);
4
+ const { baseUrl, uris, additionalBaseUrls = [], maxAncestorDepth = 0 } = options;
5
+ const { content, sectionNames } = options;
6
+ const combinations = generateUrlCombinations([baseUrl, ...additionalBaseUrls], uris);
7
+ const pathBases = [];
8
+ if (maxAncestorDepth > 0) pathBases.push(...getAncestorPathBases(baseUrl, maxAncestorDepth));
9
+ if (content && sectionNames && sectionNames.length > 0) {
10
+ for (const sectionBase of extractSectionBaseUrls(content, baseUrl, sectionNames)) if (!pathBases.includes(sectionBase)) pathBases.push(sectionBase);
11
+ }
12
+ if (pathBases.length > 0) combinations.push(...generatePathUrlCombinations(pathBases, uris));
13
+ return combinations;
6
14
  };
7
15
  //#endregion
8
16
  export { discoverUrisFromGuess };
@@ -5,6 +5,9 @@ type GuessMethodOptions = {
5
5
  baseUrl: string;
6
6
  uris: Array<UriEntry>;
7
7
  additionalBaseUrls?: Array<string>;
8
+ maxAncestorDepth?: number;
9
+ content?: string;
10
+ sectionNames?: Array<string>;
8
11
  };
9
12
  //#endregion
10
13
  export { GuessMethodOptions };
@@ -2,7 +2,8 @@ import { UriEntry } from "../../types.js";
2
2
 
3
3
  //#region src/common/uris/guess/utils.d.ts
4
4
  declare const generateUrlCombinations: (baseUrls: Array<string>, uris: Array<UriEntry>) => Array<UriEntry>;
5
+ declare const extractSectionBaseUrls: (content: string, baseUrl: string, sectionNames: Array<string>) => Array<string>;
5
6
  declare const getWwwCounterpart: (baseUrl: string) => string;
6
7
  declare const getSubdomainVariants: (baseUrl: string, prefixes: Array<string>) => Array<string>;
7
8
  //#endregion
8
- export { generateUrlCombinations, getSubdomainVariants, getWwwCounterpart };
9
+ export { extractSectionBaseUrls, generateUrlCombinations, getSubdomainVariants, getWwwCounterpart };
@@ -1,3 +1,5 @@
1
+ import { getPathSegments, parseUrl } from "../../../../node_modules/trousse/dist/urls.js";
2
+ import { Parser } from "htmlparser2";
1
3
  //#region src/common/uris/guess/utils.ts
2
4
  const ipAddressRegex = /^\d+\.\d+\.\d+\.\d+$/;
3
5
  const resolveUri = (uri, base, origin, pathname) => {
@@ -16,6 +18,47 @@ const generateUrlCombinations = (baseUrls, uris) => {
16
18
  });
17
19
  });
18
20
  };
21
+ const resolvePathUri = (uri, base) => {
22
+ if (uri.startsWith("/")) return new URL(uri.slice(1), base).href;
23
+ return new URL(uri, base).href;
24
+ };
25
+ const generatePathUrlCombinations = (pathBases, uris) => {
26
+ return pathBases.flatMap((base) => {
27
+ const normalizedBase = base.endsWith("/") ? base : `${base}/`;
28
+ return uris.map((uri) => {
29
+ if (typeof uri === "string") return resolvePathUri(uri, normalizedBase);
30
+ return uri.map((alternative) => resolvePathUri(alternative, normalizedBase));
31
+ });
32
+ });
33
+ };
34
+ const getAncestorPathBases = (baseUrl, maxDepth) => {
35
+ const url = parseUrl(baseUrl);
36
+ if (!url) return [];
37
+ const segments = url.pathname.split("/").slice(1, -1).filter((segment) => segment !== "");
38
+ const bases = [];
39
+ let base = `${url.origin}/`;
40
+ for (const segment of segments.slice(0, maxDepth)) {
41
+ base += `${segment}/`;
42
+ bases.push(base);
43
+ }
44
+ return bases;
45
+ };
46
+ const extractSectionBaseUrls = (content, baseUrl, sectionNames) => {
47
+ const base = parseUrl(baseUrl);
48
+ if (!base) return [];
49
+ const bases = /* @__PURE__ */ new Set();
50
+ const parser = new Parser({ onopentag: (name, attributes) => {
51
+ if (name !== "a" || !attributes.href) return;
52
+ const url = parseUrl(attributes.href, base);
53
+ if (!url || url.origin !== base.origin) return;
54
+ const segments = getPathSegments(url);
55
+ const segment = segments.length === 1 ? segments[0] : void 0;
56
+ if (segment && sectionNames.includes(segment.toLowerCase())) bases.add(`${url.origin}/${segment}/`);
57
+ } }, { decodeEntities: true });
58
+ parser.write(content);
59
+ parser.end();
60
+ return [...bases];
61
+ };
19
62
  const getWwwCounterpart = (baseUrl) => {
20
63
  const url = new URL(baseUrl);
21
64
  const port = url.port ? `:${url.port}` : "";
@@ -37,4 +80,4 @@ const getSubdomainVariants = (baseUrl, prefixes) => {
37
80
  });
38
81
  };
39
82
  //#endregion
40
- export { generateUrlCombinations, getSubdomainVariants, getWwwCounterpart };
83
+ export { extractSectionBaseUrls, generatePathUrlCombinations, generateUrlCombinations, getAncestorPathBases, getSubdomainVariants, getWwwCounterpart };
@@ -16,7 +16,8 @@ declare const anchorPathSegments: RegExp[];
16
16
  declare const anchorAttributes: string[];
17
17
  declare const defaultHtmlOptions: Omit<HtmlMethodOptions, 'baseUrl'>;
18
18
  declare const defaultHeadersOptions: Omit<HeadersMethodOptions, 'baseUrl'>;
19
+ declare const sectionNames: string[];
19
20
  declare const defaultGuessOptions: Omit<GuessMethodOptions, 'baseUrl'>;
20
21
  declare const defaultPlatformOptions: Omit<PlatformMethodOptions, 'baseUrl'>;
21
22
  //#endregion
22
- export { anchorAttributes, anchorLabels, anchorPathSegments, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
23
+ export { anchorAttributes, anchorLabels, anchorPathSegments, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, sectionNames, urisBalanced, urisComprehensive, urisMinimal };
@@ -188,7 +188,22 @@ const defaultHtmlOptions = {
188
188
  anchorAttributes
189
189
  };
190
190
  const defaultHeadersOptions = { linkSelectors };
191
- const defaultGuessOptions = { uris: urisBalanced };
191
+ const sectionNames = [
192
+ "blog",
193
+ "news",
194
+ "posts",
195
+ "articles",
196
+ "writing",
197
+ "notes",
198
+ "journal",
199
+ "podcast",
200
+ "changelog"
201
+ ];
202
+ const defaultGuessOptions = {
203
+ uris: urisBalanced,
204
+ maxAncestorDepth: 2,
205
+ sectionNames
206
+ };
192
207
  const defaultPlatformOptions = { handlers: [
193
208
  acastHandler,
194
209
  amebloHandler,
@@ -282,4 +297,4 @@ const defaultPlatformOptions = { handlers: [
282
297
  zennHandler
283
298
  ] };
284
299
  //#endregion
285
- export { anchorAttributes, anchorLabels, anchorPathSegments, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, urisBalanced, urisComprehensive, urisMinimal };
300
+ export { anchorAttributes, anchorLabels, anchorPathSegments, defaultGuessOptions, defaultHeadersOptions, defaultHtmlOptions, defaultPlatformOptions, ignoredUris, linkSelectors, mimeTypes, sectionNames, urisBalanced, urisComprehensive, urisMinimal };
package/package.json CHANGED
@@ -76,5 +76,5 @@
76
76
  "tsdown": "^0.22.2",
77
77
  "vitepress": "^2.0.0-alpha.17"
78
78
  },
79
- "version": "2.0.0-rc.1"
79
+ "version": "2.0.0-rc.2"
80
80
  }