feedscout 2.0.0-next.2 → 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/README.md +1 -1
- package/dist/blogrolls.d.ts +4 -4
- package/dist/blogrolls.js +3 -3
- package/dist/favicons.d.ts +3 -3
- package/dist/favicons.js +2 -2
- package/dist/feeds.d.ts +4 -4
- package/dist/feeds.js +3 -3
- package/dist/hubs.d.ts +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +6 -6
- package/dist/methods.d.ts +7 -7
- package/dist/methods.js +7 -7
- package/dist/node_modules/trousse/dist/arrays.js +9 -0
- package/dist/node_modules/trousse/dist/is.js +19 -0
- package/dist/node_modules/trousse/dist/matching.js +37 -0
- package/dist/node_modules/trousse/dist/urls.js +23 -0
- package/dist/{blogrolls → src/blogrolls}/defaults.d.ts +1 -2
- package/dist/{blogrolls → src/blogrolls}/defaults.js +19 -11
- package/dist/{blogrolls → src/blogrolls}/extractors.js +3 -2
- package/dist/{common → src/common}/discover/defaults.js +1 -3
- package/dist/{common → src/common}/discover/index.js +23 -10
- package/dist/{common → src/common}/discover/utils.js +10 -3
- package/dist/src/common/locales.js +337 -0
- package/dist/{common → src/common}/types.d.ts +9 -1
- package/dist/{common → src/common}/uris/feed/index.js +1 -1
- package/dist/src/common/uris/guess/index.js +16 -0
- package/dist/{common → src/common}/uris/guess/types.d.ts +3 -0
- package/dist/{common → src/common}/uris/guess/utils.d.ts +2 -1
- package/dist/src/common/uris/guess/utils.js +83 -0
- package/dist/src/common/uris/headers/index.js +14 -0
- package/dist/{common → src/common}/uris/html/handlers.js +18 -1
- package/dist/{common → src/common}/uris/html/index.js +17 -1
- package/dist/src/common/uris/html/types.d.ts +14 -0
- package/dist/src/common/utils.js +51 -0
- package/dist/{favicons → src/favicons}/defaults.js +1 -1
- package/dist/{favicons → src/favicons}/extractors.js +3 -8
- package/dist/{favicons → src/favicons}/platform/handlers/bluesky.js +3 -2
- package/dist/{favicons → src/favicons}/platform/handlers/codeberg.js +2 -1
- package/dist/{favicons → src/favicons}/platform/handlers/deviantart.js +2 -1
- package/dist/{favicons → src/favicons}/platform/handlers/devto.js +4 -2
- package/dist/{favicons → src/favicons}/platform/handlers/github.js +2 -1
- package/dist/{favicons → src/favicons}/platform/handlers/githubGist.js +2 -1
- package/dist/{favicons → src/favicons}/platform/handlers/gitlab.js +4 -2
- package/dist/{favicons → src/favicons}/platform/handlers/lobsters.js +1 -1
- package/dist/{favicons → src/favicons}/platform/handlers/mastodon.js +2 -1
- package/dist/{favicons → src/favicons}/platform/handlers/reddit.js +3 -2
- package/dist/{favicons → src/favicons}/platform/handlers/sourceforge.js +1 -1
- package/dist/{favicons → src/favicons}/platform/handlers/tumblr.js +1 -1
- package/dist/{favicons → src/favicons}/utils.js +1 -4
- package/dist/{feeds → src/feeds}/defaults.d.ts +6 -3
- package/dist/src/feeds/defaults.js +300 -0
- package/dist/{feeds → src/feeds}/extractors.js +3 -2
- package/dist/src/feeds/platform/handlers/acast.js +28 -0
- package/dist/src/feeds/platform/handlers/ameblo.js +38 -0
- package/dist/{feeds → src/feeds}/platform/handlers/applePodcasts.js +3 -2
- package/dist/src/feeds/platform/handlers/arena.js +44 -0
- package/dist/src/feeds/platform/handlers/artstation.js +54 -0
- package/dist/src/feeds/platform/handlers/audioboom.js +24 -0
- package/dist/src/feeds/platform/handlers/bearblog.js +46 -0
- package/dist/{feeds → src/feeds}/platform/handlers/behance.js +10 -1
- package/dist/src/feeds/platform/handlers/blogspot.js +72 -0
- package/dist/{feeds → src/feeds}/platform/handlers/bluesky.js +2 -1
- package/dist/src/feeds/platform/handlers/bookwyrm.js +48 -0
- package/dist/src/feeds/platform/handlers/buttondown.js +45 -0
- package/dist/src/feeds/platform/handlers/buzzsprout.js +23 -0
- package/dist/{feeds → src/feeds}/platform/handlers/codeberg.js +8 -6
- package/dist/{feeds → src/feeds}/platform/handlers/csdn.js +2 -1
- package/dist/{feeds → src/feeds}/platform/handlers/dailymotion.js +19 -1
- package/dist/{feeds → src/feeds}/platform/handlers/deviantart.js +28 -7
- package/dist/{feeds → src/feeds}/platform/handlers/devto.js +11 -1
- package/dist/src/feeds/platform/handlers/discourse.js +66 -0
- package/dist/{feeds → src/feeds}/platform/handlers/douban.js +2 -1
- package/dist/src/feeds/platform/handlers/dreamwidth.js +49 -0
- package/dist/src/feeds/platform/handlers/exblog.js +36 -0
- package/dist/src/feeds/platform/handlers/fireside.js +25 -0
- package/dist/src/feeds/platform/handlers/friendica.js +44 -0
- package/dist/src/feeds/platform/handlers/ghost.js +31 -0
- package/dist/{feeds → src/feeds}/platform/handlers/github.js +9 -1
- package/dist/{feeds → src/feeds}/platform/handlers/githubGist.js +19 -6
- package/dist/{feeds → src/feeds}/platform/handlers/gitlab.js +34 -14
- package/dist/{feeds → src/feeds}/platform/handlers/goodreads.js +20 -9
- package/dist/src/feeds/platform/handlers/hackernews.js +22 -0
- package/dist/{feeds → src/feeds}/platform/handlers/hashnode.js +3 -2
- package/dist/{feeds → src/feeds}/platform/handlers/hatenablog.js +6 -2
- package/dist/src/feeds/platform/handlers/hearthis.js +34 -0
- package/dist/src/feeds/platform/handlers/heyWorld.js +19 -0
- package/dist/src/feeds/platform/handlers/insanejournal.js +70 -0
- package/dist/{feeds → src/feeds}/platform/handlers/itchio.js +27 -2
- package/dist/{feeds → src/feeds}/platform/handlers/kickstarter.js +2 -1
- package/dist/src/feeds/platform/handlers/lemmy.js +88 -0
- package/dist/{feeds → src/feeds}/platform/handlers/letterboxd.js +7 -1
- package/dist/src/feeds/platform/handlers/libsyn.js +26 -0
- package/dist/src/feeds/platform/handlers/listed.js +21 -0
- package/dist/src/feeds/platform/handlers/livejournal.js +69 -0
- package/dist/{feeds → src/feeds}/platform/handlers/lobsters.js +2 -1
- package/dist/{feeds → src/feeds}/platform/handlers/mastodon.js +32 -0
- package/dist/src/feeds/platform/handlers/mataroa.js +17 -0
- package/dist/{feeds → src/feeds}/platform/handlers/medium.js +5 -3
- package/dist/src/feeds/platform/handlers/microblog.js +56 -0
- package/dist/src/feeds/platform/handlers/misskey.js +40 -0
- package/dist/src/feeds/platform/handlers/myanimelist.js +44 -0
- package/dist/src/feeds/platform/handlers/naverBlog.js +22 -0
- package/dist/src/feeds/platform/handlers/nebula.js +70 -0
- package/dist/src/feeds/platform/handlers/note.js +55 -0
- package/dist/src/feeds/platform/handlers/observable.js +35 -0
- package/dist/src/feeds/platform/handlers/odysee.js +21 -0
- package/dist/src/feeds/platform/handlers/pagecord.js +17 -0
- package/dist/{feeds → src/feeds}/platform/handlers/paragraph.js +3 -3
- package/dist/src/feeds/platform/handlers/pika.js +36 -0
- package/dist/{feeds → src/feeds}/platform/handlers/pinterest.js +16 -1
- package/dist/src/feeds/platform/handlers/pixelfed.js +46 -0
- package/dist/src/feeds/platform/handlers/pleroma.js +34 -0
- package/dist/src/feeds/platform/handlers/podbean.js +30 -0
- package/dist/src/feeds/platform/handlers/podigee.js +30 -0
- package/dist/src/feeds/platform/handlers/posthaven.js +25 -0
- package/dist/{feeds → src/feeds}/platform/handlers/producthunt.js +2 -1
- package/dist/src/feeds/platform/handlers/prose.js +27 -0
- package/dist/src/feeds/platform/handlers/qiita.js +60 -0
- package/dist/src/feeds/platform/handlers/reddit.js +150 -0
- package/dist/src/feeds/platform/handlers/rssCom.js +21 -0
- package/dist/src/feeds/platform/handlers/seesaa.js +23 -0
- package/dist/{feeds → src/feeds}/platform/handlers/soundcloud.js +3 -1
- package/dist/src/feeds/platform/handlers/sourceforge.js +53 -0
- package/dist/src/feeds/platform/handlers/spreaker.js +22 -0
- package/dist/{feeds → src/feeds}/platform/handlers/stackExchange.js +28 -3
- package/dist/{feeds → src/feeds}/platform/handlers/steam.js +9 -1
- package/dist/{feeds → src/feeds}/platform/handlers/substack.js +2 -1
- package/dist/src/feeds/platform/handlers/tildes.js +42 -0
- package/dist/src/feeds/platform/handlers/tistory.js +17 -0
- package/dist/src/feeds/platform/handlers/transistor.js +30 -0
- package/dist/{feeds → src/feeds}/platform/handlers/tumblr.js +2 -1
- package/dist/{feeds → src/feeds}/platform/handlers/v2ex.js +2 -1
- package/dist/src/feeds/platform/handlers/velog.js +25 -0
- package/dist/{feeds → src/feeds}/platform/handlers/vimeo.js +9 -1
- package/dist/src/feeds/platform/handlers/weblogLol.js +27 -0
- package/dist/src/feeds/platform/handlers/weebly.js +26 -0
- package/dist/src/feeds/platform/handlers/wordpress.js +210 -0
- package/dist/{feeds → src/feeds}/platform/handlers/wpengine.js +1 -1
- package/dist/src/feeds/platform/handlers/writeas.js +53 -0
- package/dist/{feeds → src/feeds}/platform/handlers/ximalaya.js +3 -2
- package/dist/{feeds → src/feeds}/platform/handlers/youtube.js +6 -2
- package/dist/src/feeds/platform/handlers/zenn.js +56 -0
- package/package.json +10 -11
- package/dist/common/locales.js +0 -133
- package/dist/common/uris/guess/index.js +0 -8
- package/dist/common/uris/guess/utils.js +0 -40
- package/dist/common/uris/headers/index.js +0 -26
- package/dist/common/uris/html/types.d.ts +0 -12
- package/dist/common/utils.d.ts +0 -10
- package/dist/common/utils.js +0 -79
- package/dist/feeds/defaults.js +0 -168
- package/dist/feeds/platform/handlers/blogspot.js +0 -36
- package/dist/feeds/platform/handlers/lemmy.js +0 -46
- package/dist/feeds/platform/handlers/reddit.js +0 -74
- package/dist/feeds/platform/handlers/sourceforge.js +0 -19
- package/dist/feeds/platform/handlers/wordpress.js +0 -64
- package/dist/utils.d.ts +0 -2
- package/dist/utils.js +0 -2
- /package/dist/{blogrolls → src/blogrolls}/extractors.d.ts +0 -0
- /package/dist/{blogrolls → src/blogrolls}/index.d.ts +0 -0
- /package/dist/{blogrolls → src/blogrolls}/index.js +0 -0
- /package/dist/{blogrolls → src/blogrolls}/types.d.ts +0 -0
- /package/dist/{common → src/common}/discover/defaults.d.ts +0 -0
- /package/dist/{common → src/common}/discover/utils.d.ts +0 -0
- /package/dist/{common → src/common}/types.js +0 -0
- /package/dist/{common → src/common}/uris/feed/index.d.ts +0 -0
- /package/dist/{common → src/common}/uris/feed/types.d.ts +0 -0
- /package/dist/{common → src/common}/uris/guess/index.d.ts +0 -0
- /package/dist/{common → src/common}/uris/headers/index.d.ts +0 -0
- /package/dist/{common → src/common}/uris/headers/types.d.ts +0 -0
- /package/dist/{common → src/common}/uris/html/index.d.ts +0 -0
- /package/dist/{common → src/common}/uris/index.js +0 -0
- /package/dist/{common → src/common}/uris/platform/index.d.ts +0 -0
- /package/dist/{common → src/common}/uris/platform/index.js +0 -0
- /package/dist/{common → src/common}/uris/platform/types.d.ts +0 -0
- /package/dist/{favicons → src/favicons}/defaults.d.ts +0 -0
- /package/dist/{favicons → src/favicons}/extractors.d.ts +0 -0
- /package/dist/{favicons → src/favicons}/index.d.ts +0 -0
- /package/dist/{favicons → src/favicons}/index.js +0 -0
- /package/dist/{favicons → src/favicons}/types.d.ts +0 -0
- /package/dist/{feeds → src/feeds}/extractors.d.ts +0 -0
- /package/dist/{feeds → src/feeds}/index.d.ts +0 -0
- /package/dist/{feeds → src/feeds}/index.js +0 -0
- /package/dist/{feeds → src/feeds}/types.d.ts +0 -0
- /package/dist/{hubs → src/hubs}/discover/index.d.ts +0 -0
- /package/dist/{hubs → src/hubs}/discover/index.js +0 -0
- /package/dist/{hubs → src/hubs}/discover/types.d.ts +0 -0
- /package/dist/{hubs → src/hubs}/feed/index.js +0 -0
- /package/dist/{hubs → src/hubs}/headers/index.js +0 -0
- /package/dist/{hubs → src/hubs}/html/index.js +0 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
//#region src/common/locales.json
|
|
2
|
+
var errors = {
|
|
3
|
+
"platformMethodRequiresUrl": "Platform method requires url to be provided in input",
|
|
4
|
+
"feedMethodRequiresContent": "Feed method requires content to be provided in input",
|
|
5
|
+
"htmlMethodRequiresContent": "HTML method requires content to be provided in input",
|
|
6
|
+
"headersMethodRequiresHeaders": "Headers method requires headers to be provided in input",
|
|
7
|
+
"guessMethodRequiresUrl": "Guess method requires url to be provided in input"
|
|
8
|
+
};
|
|
9
|
+
var hints = {
|
|
10
|
+
"youtube:all": "All uploads",
|
|
11
|
+
"youtube:videos": "Videos",
|
|
12
|
+
"youtube:shorts": "Shorts",
|
|
13
|
+
"youtube:live": "Live streams",
|
|
14
|
+
"youtube:popular-videos": "Popular videos",
|
|
15
|
+
"youtube:popular-shorts": "Popular shorts",
|
|
16
|
+
"youtube:popular-live": "Popular live streams",
|
|
17
|
+
"youtube:member-videos": "Member videos",
|
|
18
|
+
"youtube:member-shorts": "Member shorts",
|
|
19
|
+
"youtube:member-live": "Member live streams",
|
|
20
|
+
"youtube:playlist": "Playlist",
|
|
21
|
+
"github:activity": "Activity",
|
|
22
|
+
"github:releases": "Releases",
|
|
23
|
+
"github:commits": "Commits",
|
|
24
|
+
"github:tags": "Tags",
|
|
25
|
+
"github:wiki": "Wiki",
|
|
26
|
+
"github:discussions": "Discussions",
|
|
27
|
+
"github:discussion-category": "Discussion category",
|
|
28
|
+
"github:branch-commits": "Branch commits",
|
|
29
|
+
"github:file-history": "File history",
|
|
30
|
+
"reddit:posts": "Posts",
|
|
31
|
+
"reddit:post-comments": "Post comments",
|
|
32
|
+
"reddit:comments": "Comments",
|
|
33
|
+
"reddit:multireddit": "Multireddit",
|
|
34
|
+
"reddit:user-submitted": "Submitted",
|
|
35
|
+
"reddit:user-comments": "Comments",
|
|
36
|
+
"reddit:search": "Search",
|
|
37
|
+
"reddit:wiki": "Wiki",
|
|
38
|
+
"reddit:subreddits": "Subreddits",
|
|
39
|
+
"gitlab:activity": "Activity",
|
|
40
|
+
"gitlab:releases": "Releases",
|
|
41
|
+
"gitlab:tags": "Tags",
|
|
42
|
+
"gitlab:issues": "Issues",
|
|
43
|
+
"gitlab:merge-requests": "Merge requests",
|
|
44
|
+
"gitlab:branch-commits": "Branch commits",
|
|
45
|
+
"codeberg:activity": "Activity",
|
|
46
|
+
"codeberg:releases": "Releases",
|
|
47
|
+
"codeberg:tags": "Tags",
|
|
48
|
+
"codeberg:branch-commits": "Branch commits",
|
|
49
|
+
"codeberg:file-history": "File history",
|
|
50
|
+
"wordpress:category-rss": "Category (RSS)",
|
|
51
|
+
"wordpress:category-atom": "Category (Atom)",
|
|
52
|
+
"wordpress:category-rdf": "Category (RDF)",
|
|
53
|
+
"wordpress:tag-rss": "Tag (RSS)",
|
|
54
|
+
"wordpress:tag-atom": "Tag (Atom)",
|
|
55
|
+
"wordpress:tag-rdf": "Tag (RDF)",
|
|
56
|
+
"wordpress:author-rss": "Author (RSS)",
|
|
57
|
+
"wordpress:author-atom": "Author (Atom)",
|
|
58
|
+
"wordpress:author-rdf": "Author (RDF)",
|
|
59
|
+
"wordpress:date-archive-rss": "Date archive (RSS)",
|
|
60
|
+
"wordpress:date-archive-atom": "Date archive (Atom)",
|
|
61
|
+
"wordpress:date-archive-rdf": "Date archive (RDF)",
|
|
62
|
+
"wordpress:posts-rss": "Posts (RSS)",
|
|
63
|
+
"wordpress:posts-rdf": "Posts (RDF)",
|
|
64
|
+
"wordpress:posts-atom": "Posts (Atom)",
|
|
65
|
+
"wordpress:comments-rss": "Comments (RSS)",
|
|
66
|
+
"wordpress:comments-rdf": "Comments (RDF)",
|
|
67
|
+
"wordpress:comments-atom": "Comments (Atom)",
|
|
68
|
+
"wordpress:post-comments-rss": "Post comments (RSS)",
|
|
69
|
+
"wordpress:post-comments-rdf": "Post comments (RDF)",
|
|
70
|
+
"wordpress:post-comments-atom": "Post comments (Atom)",
|
|
71
|
+
"blogspot:posts-atom": "Posts (Atom)",
|
|
72
|
+
"blogspot:posts-rss": "Posts (RSS)",
|
|
73
|
+
"blogspot:posts-summary-atom": "Posts summary (Atom)",
|
|
74
|
+
"blogspot:posts-summary-rss": "Posts summary (RSS)",
|
|
75
|
+
"blogspot:comments-atom": "Comments (Atom)",
|
|
76
|
+
"blogspot:comments-rss": "Comments (RSS)",
|
|
77
|
+
"blogspot:label-atom": "Label (Atom)",
|
|
78
|
+
"blogspot:label-rss": "Label (RSS)",
|
|
79
|
+
"blogspot:post-comments-atom": "Post comments (Atom)",
|
|
80
|
+
"blogspot:post-comments-rss": "Post comments (RSS)",
|
|
81
|
+
"behance:portfolio": "Portfolio",
|
|
82
|
+
"behance:appreciated": "Appreciated",
|
|
83
|
+
"behance:projects": "Featured projects",
|
|
84
|
+
"behance:featured": "Featured by Adobe",
|
|
85
|
+
"bluesky:posts": "Posts",
|
|
86
|
+
"dailymotion:videos": "Videos",
|
|
87
|
+
"dailymotion:playlist": "Playlist",
|
|
88
|
+
"dailymotion:channel": "Channel",
|
|
89
|
+
"dailymotion:trending": "Trending",
|
|
90
|
+
"dailymotion:search": "Search",
|
|
91
|
+
"deviantart:tag": "Tag",
|
|
92
|
+
"deviantart:favorites": "Favorites",
|
|
93
|
+
"deviantart:gallery": "Gallery",
|
|
94
|
+
"deviantart:deviations": "Deviations",
|
|
95
|
+
"deviantart:journal": "Journal",
|
|
96
|
+
"deviantart:daily-deviations": "Daily Deviations",
|
|
97
|
+
"deviantart:popular": "Popular",
|
|
98
|
+
"devto:posts": "Posts",
|
|
99
|
+
"devto:tag": "Tag",
|
|
100
|
+
"devto:community": "Community",
|
|
101
|
+
"devto:latest": "Latest",
|
|
102
|
+
"github-gist:gists": "Gists",
|
|
103
|
+
"github-gist:starred": "Starred",
|
|
104
|
+
"github-gist:forks": "Forks",
|
|
105
|
+
"github-gist:discover": "Discover",
|
|
106
|
+
"kickstarter:updates": "Updates",
|
|
107
|
+
"kickstarter:projects": "Projects",
|
|
108
|
+
"letterboxd:diary": "Diary",
|
|
109
|
+
"letterboxd:journal": "Journal",
|
|
110
|
+
"lobsters:tag": "Tag",
|
|
111
|
+
"lobsters:domain": "Domain",
|
|
112
|
+
"lobsters:stories": "Stories",
|
|
113
|
+
"lobsters:top": "Top stories",
|
|
114
|
+
"lobsters:newest": "Newest",
|
|
115
|
+
"lobsters:comments": "Comments",
|
|
116
|
+
"mastodon:posts": "Posts",
|
|
117
|
+
"mastodon:tag": "Tag",
|
|
118
|
+
"mastodon:tagged": "Tagged",
|
|
119
|
+
"mastodon:replies": "Posts with replies",
|
|
120
|
+
"mastodon:media": "Media",
|
|
121
|
+
"medium:posts": "Posts",
|
|
122
|
+
"medium:tag": "Tag",
|
|
123
|
+
"medium:tagged": "Tagged",
|
|
124
|
+
"medium:publication": "Publication",
|
|
125
|
+
"pinterest:pins": "Pins",
|
|
126
|
+
"pinterest:board": "Board",
|
|
127
|
+
"producthunt:topic": "Topic",
|
|
128
|
+
"producthunt:category": "Category",
|
|
129
|
+
"producthunt:products": "Products",
|
|
130
|
+
"soundcloud:tracks": "Tracks",
|
|
131
|
+
"stackexchange:tag": "Tag",
|
|
132
|
+
"stackexchange:question": "Question",
|
|
133
|
+
"stackexchange:user": "User",
|
|
134
|
+
"stackexchange:newest": "Newest questions",
|
|
135
|
+
"stackexchange:collective": "Collective",
|
|
136
|
+
"steam:news": "News",
|
|
137
|
+
"steam:news-global": "News (global)",
|
|
138
|
+
"steam:daily-deals": "Daily deals",
|
|
139
|
+
"steam:group": "Group",
|
|
140
|
+
"substack:newsletter": "Newsletter",
|
|
141
|
+
"tumblr:posts": "Posts",
|
|
142
|
+
"tumblr:tag": "Tag",
|
|
143
|
+
"goodreads:updates": "Updates",
|
|
144
|
+
"goodreads:reviews": "Reviews",
|
|
145
|
+
"goodreads:shelf": "Shelf",
|
|
146
|
+
"sourceforge:activity": "Recent activity",
|
|
147
|
+
"sourceforge:files": "File releases",
|
|
148
|
+
"sourceforge:news-rss": "News (RSS)",
|
|
149
|
+
"sourceforge:news-atom": "News (Atom)",
|
|
150
|
+
"sourceforge:discussion": "Discussion",
|
|
151
|
+
"sourceforge:discussion-atom": "Discussion (Atom)",
|
|
152
|
+
"sourceforge:project-feed": "Project feed",
|
|
153
|
+
"sourceforge:bugs": "Bugs",
|
|
154
|
+
"velog:posts": "Posts",
|
|
155
|
+
"velog:trending": "Trending",
|
|
156
|
+
"vimeo:videos": "Videos",
|
|
157
|
+
"vimeo:likes": "Likes",
|
|
158
|
+
"vimeo:channel": "Channel",
|
|
159
|
+
"vimeo:group": "Group",
|
|
160
|
+
"vimeo:album": "Album",
|
|
161
|
+
"hashnode:blog": "Blog",
|
|
162
|
+
"paragraph:blog": "Blog",
|
|
163
|
+
"hatenablog:posts-rss": "Posts (RSS)",
|
|
164
|
+
"hatenablog:posts-atom": "Posts (Atom)",
|
|
165
|
+
"hatenablog:category-rss": "Category (RSS)",
|
|
166
|
+
"hatenablog:category-atom": "Category (Atom)",
|
|
167
|
+
"hatenablog:author-rss": "Author (RSS)",
|
|
168
|
+
"hatenablog:author-atom": "Author (Atom)",
|
|
169
|
+
"itchio:devlog": "Devlog",
|
|
170
|
+
"itchio:games": "Games",
|
|
171
|
+
"itchio:tag": "Tag",
|
|
172
|
+
"itchio:platform": "Platform",
|
|
173
|
+
"itchio:genre": "Genre",
|
|
174
|
+
"itchio:made-with": "Made with",
|
|
175
|
+
"itchio:section": "Section",
|
|
176
|
+
"itchio:featured": "Featured",
|
|
177
|
+
"itchio:new": "New",
|
|
178
|
+
"itchio:sales": "Sales",
|
|
179
|
+
"itchio:blog": "Blog",
|
|
180
|
+
"csdn:blog": "Blog",
|
|
181
|
+
"douban:interests": "Interests",
|
|
182
|
+
"douban:reviews": "Reviews",
|
|
183
|
+
"douban:notes": "Notes",
|
|
184
|
+
"douban:subjectReviews": "Subject reviews",
|
|
185
|
+
"v2ex:index": "Index",
|
|
186
|
+
"v2ex:node": "Node",
|
|
187
|
+
"v2ex:member": "Member",
|
|
188
|
+
"v2ex:tab": "Tab",
|
|
189
|
+
"ximalaya:album": "Album",
|
|
190
|
+
"lemmy:community": "Community",
|
|
191
|
+
"lemmy:user": "User",
|
|
192
|
+
"lemmy:all": "All",
|
|
193
|
+
"lemmy:local": "Local",
|
|
194
|
+
"apple-podcasts:podcast": "Podcast",
|
|
195
|
+
"writeas:blog": "Blog",
|
|
196
|
+
"writeas:tag": "Tag",
|
|
197
|
+
"prose:blog": "Blog",
|
|
198
|
+
"prose:tag": "Tag",
|
|
199
|
+
"prose:discovery": "Discovery",
|
|
200
|
+
"pagecord:blog": "Blog",
|
|
201
|
+
"listed:blog": "Blog",
|
|
202
|
+
"fireside:podcast-rss": "Podcast (RSS)",
|
|
203
|
+
"fireside:podcast-json": "Podcast (JSON)",
|
|
204
|
+
"exblog:posts-rss": "Posts (RSS)",
|
|
205
|
+
"exblog:posts-atom": "Posts (Atom)",
|
|
206
|
+
"exblog:category-rss": "Category (RSS)",
|
|
207
|
+
"exblog:category-atom": "Category (Atom)",
|
|
208
|
+
"dreamwidth:posts-rss": "Posts (RSS)",
|
|
209
|
+
"dreamwidth:posts-atom": "Posts (Atom)",
|
|
210
|
+
"dreamwidth:posts-tag-rss": "Tag (RSS)",
|
|
211
|
+
"dreamwidth:posts-tag-atom": "Tag (Atom)",
|
|
212
|
+
"dreamwidth:userpics-atom": "Userpics (Atom)",
|
|
213
|
+
"buttondown:newsletter": "Newsletter",
|
|
214
|
+
"bearblog:posts-atom": "Posts (Atom)",
|
|
215
|
+
"bearblog:posts-rss": "Posts (RSS)",
|
|
216
|
+
"bearblog:tag-atom": "Tag (Atom)",
|
|
217
|
+
"bearblog:tag-rss": "Tag (RSS)",
|
|
218
|
+
"bearblog:discover-atom": "Trending (Atom)",
|
|
219
|
+
"bearblog:discover-rss": "Trending (RSS)",
|
|
220
|
+
"transistor:podcast": "Podcast",
|
|
221
|
+
"odysee:videos": "Videos",
|
|
222
|
+
"myanimelist:anime": "Anime list",
|
|
223
|
+
"myanimelist:manga": "Manga list",
|
|
224
|
+
"myanimelist:recently-watched": "Recently watched",
|
|
225
|
+
"myanimelist:recently-read": "Recently read",
|
|
226
|
+
"myanimelist:news": "News",
|
|
227
|
+
"myanimelist:featured": "Featured",
|
|
228
|
+
"hackernews:front": "Front page",
|
|
229
|
+
"hackernews:show": "Show HN",
|
|
230
|
+
"tistory:blog": "Blog",
|
|
231
|
+
"note:blog": "Blog",
|
|
232
|
+
"note:hashtag": "Hashtag",
|
|
233
|
+
"note:magazine": "Magazine",
|
|
234
|
+
"note:featured": "Featured",
|
|
235
|
+
"artstation:portfolio": "Portfolio",
|
|
236
|
+
"artstation:artwork": "Artwork",
|
|
237
|
+
"artstation:artwork-trending": "Artwork (Trending)",
|
|
238
|
+
"nebula:videos": "Videos",
|
|
239
|
+
"nebula:videos-plus": "Videos (Plus)",
|
|
240
|
+
"nebula:videos-all": "All Videos",
|
|
241
|
+
"nebula:videos-all-plus": "All Videos (Plus)",
|
|
242
|
+
"nebula:category": "Category",
|
|
243
|
+
"nebula:category-plus": "Category (Plus)",
|
|
244
|
+
"nebula:channels": "Recently Added Channels",
|
|
245
|
+
"acast:podcast": "Podcast",
|
|
246
|
+
"ameblo:posts-rss": "Posts (RSS)",
|
|
247
|
+
"ameblo:posts-atom": "Posts (Atom)",
|
|
248
|
+
"ameblo:posts-rdf": "Posts (RDF)",
|
|
249
|
+
"arena:profile": "Profile",
|
|
250
|
+
"arena:channel": "Channel",
|
|
251
|
+
"arena:editorial": "Editorial",
|
|
252
|
+
"audioboom:podcast": "Podcast",
|
|
253
|
+
"bookwyrm:activity": "Activity",
|
|
254
|
+
"bookwyrm:reviews": "Reviews",
|
|
255
|
+
"bookwyrm:quotes": "Quotes",
|
|
256
|
+
"bookwyrm:comments": "Comments",
|
|
257
|
+
"bookwyrm:shelf": "Shelf",
|
|
258
|
+
"buzzsprout:podcast": "Podcast",
|
|
259
|
+
"discourse:latest": "Latest",
|
|
260
|
+
"discourse:posts": "Latest posts",
|
|
261
|
+
"discourse:top": "Top",
|
|
262
|
+
"discourse:category": "Category",
|
|
263
|
+
"discourse:topic": "Topic",
|
|
264
|
+
"discourse:activity": "Activity",
|
|
265
|
+
"friendica:posts": "Posts",
|
|
266
|
+
"friendica:comments": "Comments",
|
|
267
|
+
"friendica:replies": "Replies",
|
|
268
|
+
"friendica:activity": "Activity",
|
|
269
|
+
"ghost:blog": "Blog",
|
|
270
|
+
"ghost:tag": "Tag",
|
|
271
|
+
"ghost:author": "Author",
|
|
272
|
+
"hearthis:tracks": "Tracks",
|
|
273
|
+
"hey-world:blog": "Blog",
|
|
274
|
+
"insanejournal:posts-rss": "Posts (RSS)",
|
|
275
|
+
"insanejournal:posts-atom": "Posts (Atom)",
|
|
276
|
+
"insanejournal:posts-tag-rss": "Tag (RSS)",
|
|
277
|
+
"insanejournal:posts-tag-atom": "Tag (Atom)",
|
|
278
|
+
"insanejournal:userpics-atom": "Userpics (Atom)",
|
|
279
|
+
"libsyn:podcast": "Podcast",
|
|
280
|
+
"livejournal:posts-rss": "Posts (RSS)",
|
|
281
|
+
"livejournal:posts-atom": "Posts (Atom)",
|
|
282
|
+
"livejournal:posts-tag-rss": "Tag (RSS)",
|
|
283
|
+
"livejournal:posts-tag-atom": "Tag (Atom)",
|
|
284
|
+
"livejournal:userpics-atom": "Userpics (Atom)",
|
|
285
|
+
"mataroa:blog": "Blog",
|
|
286
|
+
"microblog:posts-rss": "Posts (RSS)",
|
|
287
|
+
"microblog:posts-json": "Posts (JSON)",
|
|
288
|
+
"microblog:podcast": "Podcast",
|
|
289
|
+
"microblog:podcast-json": "Podcast (JSON)",
|
|
290
|
+
"microblog:category-rss": "Category (RSS)",
|
|
291
|
+
"microblog:category-json": "Category (JSON)",
|
|
292
|
+
"microblog:archive": "Archive",
|
|
293
|
+
"microblog:photos": "Photos",
|
|
294
|
+
"microblog:replies": "Replies",
|
|
295
|
+
"misskey:posts-atom": "Posts (Atom)",
|
|
296
|
+
"misskey:posts-rss": "Posts (RSS)",
|
|
297
|
+
"misskey:posts-json": "Posts (JSON)",
|
|
298
|
+
"naver-blog:blog": "Blog",
|
|
299
|
+
"observable:notebooks": "Notebooks",
|
|
300
|
+
"observable:collection": "Collection",
|
|
301
|
+
"observable:recent": "Recent",
|
|
302
|
+
"observable:trending": "Trending",
|
|
303
|
+
"pika:posts-atom": "Posts (Atom)",
|
|
304
|
+
"pika:posts-rss": "Posts (RSS)",
|
|
305
|
+
"pika:tag-atom": "Tag (Atom)",
|
|
306
|
+
"pika:tag-rss": "Tag (RSS)",
|
|
307
|
+
"pixelfed:posts": "Posts",
|
|
308
|
+
"pleroma:posts": "Posts",
|
|
309
|
+
"pleroma:posts-rss": "Posts (RSS)",
|
|
310
|
+
"podbean:podcast": "Podcast",
|
|
311
|
+
"podigee:podcast": "Podcast",
|
|
312
|
+
"posthaven:posts": "Posts",
|
|
313
|
+
"posthaven:tag": "Tag",
|
|
314
|
+
"qiita:posts": "Posts",
|
|
315
|
+
"qiita:tag": "Tag",
|
|
316
|
+
"qiita:organization": "Organization",
|
|
317
|
+
"qiita:popular": "Popular items",
|
|
318
|
+
"qiita:zine": "Qiita Zine",
|
|
319
|
+
"rss-com:podcast": "Podcast",
|
|
320
|
+
"seesaa:posts-rss2": "Posts (RSS 2.0)",
|
|
321
|
+
"seesaa:posts-rdf": "Posts (RDF)",
|
|
322
|
+
"spreaker:podcast": "Podcast",
|
|
323
|
+
"tildes:topics-rss": "Topics (RSS)",
|
|
324
|
+
"tildes:topics-atom": "Topics (Atom)",
|
|
325
|
+
"tildes:group-rss": "Group (RSS)",
|
|
326
|
+
"tildes:group-atom": "Group (Atom)",
|
|
327
|
+
"weblog-lol:posts-rss": "Posts (RSS)",
|
|
328
|
+
"weblog-lol:posts-atom": "Posts (Atom)",
|
|
329
|
+
"weblog-lol:posts-json": "Posts (JSON)",
|
|
330
|
+
"weebly:blog": "Blog",
|
|
331
|
+
"zenn:posts": "Posts",
|
|
332
|
+
"zenn:topic": "Topic",
|
|
333
|
+
"zenn:publication": "Publication",
|
|
334
|
+
"zenn:trending": "Trending"
|
|
335
|
+
};
|
|
336
|
+
//#endregion
|
|
337
|
+
export { errors, hints };
|
|
@@ -6,6 +6,7 @@ import { PlatformMethodOptions } from "./uris/platform/types.js";
|
|
|
6
6
|
|
|
7
7
|
//#region src/common/types.d.ts
|
|
8
8
|
type MaybePromise<T> = T | Promise<T>;
|
|
9
|
+
type Pattern = string | RegExp;
|
|
9
10
|
type UriEntry = string | Array<string>;
|
|
10
11
|
type DiscoverUriHint = {
|
|
11
12
|
key: string;
|
|
@@ -42,6 +43,11 @@ type DiscoverProgress = {
|
|
|
42
43
|
current: string;
|
|
43
44
|
};
|
|
44
45
|
type DiscoverOnProgressFn = (progress: DiscoverProgress) => void;
|
|
46
|
+
type DiscoverErrorContext = {
|
|
47
|
+
phase: 'fetchInput' | 'resolveSiteUrl';
|
|
48
|
+
url?: string;
|
|
49
|
+
};
|
|
50
|
+
type DiscoverOnErrorFn = (error: unknown, context: DiscoverErrorContext) => void;
|
|
45
51
|
type DiscoverResult<TValid = object> = ({
|
|
46
52
|
url: string;
|
|
47
53
|
isValid: true;
|
|
@@ -82,8 +88,10 @@ type DiscoverOptions<TValid, TMethods extends DiscoverMethod = DiscoverMethod> =
|
|
|
82
88
|
stopOnFirstMethod?: boolean;
|
|
83
89
|
stopOnFirstResult?: boolean;
|
|
84
90
|
concurrency?: number;
|
|
91
|
+
maxUris?: number;
|
|
85
92
|
onProgress?: DiscoverOnProgressFn;
|
|
93
|
+
onError?: DiscoverOnErrorFn;
|
|
86
94
|
includeInvalid?: boolean;
|
|
87
95
|
};
|
|
88
96
|
//#endregion
|
|
89
|
-
export { DiscoverExtractFn, DiscoverFetchFn, DiscoverFetchFnOptions, DiscoverFetchFnResponse, DiscoverInput, DiscoverInputObject, DiscoverMethod, DiscoverMethodsConfig, DiscoverOnProgressFn, DiscoverOptions, DiscoverProgress, DiscoverResolveSiteUrlFn, DiscoverResolveUrlFn, DiscoverResult, DiscoverUriEntry, DiscoverUriHint, LinkSelector, MaybePromise, UriEntry };
|
|
97
|
+
export { DiscoverExtractFn, DiscoverFetchFn, DiscoverFetchFnOptions, DiscoverFetchFnResponse, DiscoverInput, DiscoverInputObject, DiscoverMethod, DiscoverMethodsConfig, DiscoverOnProgressFn, DiscoverOptions, DiscoverProgress, DiscoverResolveSiteUrlFn, DiscoverResolveUrlFn, DiscoverResult, DiscoverUriEntry, DiscoverUriHint, LinkSelector, MaybePromise, Pattern, UriEntry };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { extractSectionBaseUrls, generatePathUrlCombinations, generateUrlCombinations, getAncestorPathBases } from "./utils.js";
|
|
2
|
+
//#region src/common/uris/guess/index.ts
|
|
3
|
+
const discoverUrisFromGuess = (options) => {
|
|
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;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { discoverUrisFromGuess };
|
|
@@ -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 };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { getPathSegments, parseUrl } from "../../../../node_modules/trousse/dist/urls.js";
|
|
2
|
+
import { Parser } from "htmlparser2";
|
|
3
|
+
//#region src/common/uris/guess/utils.ts
|
|
4
|
+
const ipAddressRegex = /^\d+\.\d+\.\d+\.\d+$/;
|
|
5
|
+
const resolveUri = (uri, base, origin, pathname) => {
|
|
6
|
+
if (uri.startsWith("/")) return `${origin}${uri}`;
|
|
7
|
+
if (uri.startsWith("?")) return `${origin}${pathname}${uri}`;
|
|
8
|
+
return new URL(uri, base).href;
|
|
9
|
+
};
|
|
10
|
+
const generateUrlCombinations = (baseUrls, uris) => {
|
|
11
|
+
return baseUrls.flatMap((base) => {
|
|
12
|
+
const parsed = new URL(base);
|
|
13
|
+
const origin = parsed.origin;
|
|
14
|
+
const pathname = parsed.pathname;
|
|
15
|
+
return uris.map((uri) => {
|
|
16
|
+
if (typeof uri === "string") return resolveUri(uri, base, origin, pathname);
|
|
17
|
+
return uri.map((alternative) => resolveUri(alternative, base, origin, pathname));
|
|
18
|
+
});
|
|
19
|
+
});
|
|
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
|
+
};
|
|
62
|
+
const getWwwCounterpart = (baseUrl) => {
|
|
63
|
+
const url = new URL(baseUrl);
|
|
64
|
+
const port = url.port ? `:${url.port}` : "";
|
|
65
|
+
if (url.hostname.startsWith("www.")) return `${url.protocol}//${url.hostname.slice(4)}${port}`;
|
|
66
|
+
return `${url.protocol}//www.${url.hostname}${port}`;
|
|
67
|
+
};
|
|
68
|
+
const getSubdomainVariants = (baseUrl, prefixes) => {
|
|
69
|
+
const url = new URL(baseUrl);
|
|
70
|
+
const hostname = url.hostname;
|
|
71
|
+
const isIpAddress = ipAddressRegex.test(hostname);
|
|
72
|
+
if (hostname === "localhost" || isIpAddress) return [];
|
|
73
|
+
const hostnameParts = hostname.split(".");
|
|
74
|
+
if (hostnameParts.length < 2) return [];
|
|
75
|
+
const rootDomain = hostnameParts.slice(-2).join(".");
|
|
76
|
+
const protocol = url.protocol;
|
|
77
|
+
const port = url.port ? `:${url.port}` : "";
|
|
78
|
+
return prefixes.map((prefix) => {
|
|
79
|
+
return `${protocol}//${prefix === "" ? rootDomain : `${prefix}.${rootDomain}`}${port}`;
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
//#endregion
|
|
83
|
+
export { extractSectionBaseUrls, generatePathUrlCombinations, generateUrlCombinations, getAncestorPathBases, getSubdomainVariants, getWwwCounterpart };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { matchesAnyOfLinkSelectors } from "../../utils.js";
|
|
2
|
+
import LinkHeader from "http-link-header";
|
|
3
|
+
//#region src/common/uris/headers/index.ts
|
|
4
|
+
const discoverUrisFromHeaders = (headers, options) => {
|
|
5
|
+
const linkHeader = headers.get("link");
|
|
6
|
+
if (!linkHeader) return [];
|
|
7
|
+
const uris = /* @__PURE__ */ new Set();
|
|
8
|
+
try {
|
|
9
|
+
for (const ref of LinkHeader.parse(linkHeader).refs) if (ref.rel && matchesAnyOfLinkSelectors(ref.rel, ref.type, options.linkSelectors)) uris.add(ref.uri);
|
|
10
|
+
} catch {}
|
|
11
|
+
return [...uris];
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { discoverUrisFromHeaders };
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { endsWithAnyOf, includesAnyOf
|
|
1
|
+
import { endsWithAnyOf, includesAnyOf } from "../../../../node_modules/trousse/dist/matching.js";
|
|
2
|
+
import { parseUrl } from "../../../../node_modules/trousse/dist/urls.js";
|
|
3
|
+
import { matchesAnyOfLinkSelectors } from "../../utils.js";
|
|
2
4
|
//#region src/common/uris/html/handlers.ts
|
|
3
5
|
const handleOpenTag = (context, name, attribs, _isImplied) => {
|
|
6
|
+
if (name === "base" && context.baseHref === void 0) {
|
|
7
|
+
const href = attribs.href?.trim();
|
|
8
|
+
if (href) context.baseHref = href;
|
|
9
|
+
}
|
|
4
10
|
if (name === "link" && attribs.href) {
|
|
5
11
|
const rel = attribs.rel?.toLowerCase();
|
|
6
12
|
if (!rel) return;
|
|
@@ -16,6 +22,17 @@ const handleOpenTag = (context, name, attribs, _isImplied) => {
|
|
|
16
22
|
context.currentAnchor.href = attribs.href;
|
|
17
23
|
context.currentAnchor.text = "";
|
|
18
24
|
if (endsWithAnyOf(lowerHref, context.options.anchorUris)) context.discoveredUris.add(attribs.href);
|
|
25
|
+
if (context.options.anchorPathSegments?.length) {
|
|
26
|
+
const pathname = parseUrl(attribs.href, "https://feedscout.invalid")?.pathname;
|
|
27
|
+
if (pathname && includesAnyOf(pathname, context.options.anchorPathSegments)) context.discoveredUris.add(attribs.href);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (context.currentAnchor.href && context.options.anchorAttributes?.length) for (const attribute of context.options.anchorAttributes) {
|
|
31
|
+
const value = attribs[attribute];
|
|
32
|
+
if (value && includesAnyOf(value, context.options.anchorLabels)) {
|
|
33
|
+
context.discoveredUris.add(context.currentAnchor.href);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
19
36
|
}
|
|
20
37
|
};
|
|
21
38
|
const handleText = (context, text) => {
|
|
@@ -13,7 +13,23 @@ const discoverUrisFromHtml = (html, options) => {
|
|
|
13
13
|
const parser = new Parser(createHtmlUrisHandlers(context), { decodeEntities: true });
|
|
14
14
|
parser.write(html);
|
|
15
15
|
parser.end();
|
|
16
|
-
|
|
16
|
+
const uris = [...context.discoveredUris];
|
|
17
|
+
if (context.baseHref) {
|
|
18
|
+
let base;
|
|
19
|
+
try {
|
|
20
|
+
base = options.baseUrl ? new URL(context.baseHref, options.baseUrl).href : context.baseHref;
|
|
21
|
+
} catch {
|
|
22
|
+
base = options.baseUrl;
|
|
23
|
+
}
|
|
24
|
+
return uris.map((uri) => {
|
|
25
|
+
try {
|
|
26
|
+
return new URL(uri, base).href;
|
|
27
|
+
} catch {
|
|
28
|
+
return uri;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return uris;
|
|
17
33
|
};
|
|
18
34
|
//#endregion
|
|
19
35
|
export { discoverUrisFromHtml };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LinkSelector, Pattern } from "../../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/common/uris/html/types.d.ts
|
|
4
|
+
type HtmlMethodOptions = {
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
linkSelectors: Array<LinkSelector>;
|
|
7
|
+
anchorUris: Array<Pattern>;
|
|
8
|
+
anchorPathSegments?: Array<Pattern>;
|
|
9
|
+
anchorIgnoredUris: Array<Pattern>;
|
|
10
|
+
anchorLabels: Array<Pattern>;
|
|
11
|
+
anchorAttributes?: Array<string>;
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { HtmlMethodOptions };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { anyWordMatchesAnyOf, isAnyOf } from "../../node_modules/trousse/dist/matching.js";
|
|
2
|
+
import { hints } from "./locales.js";
|
|
3
|
+
//#region src/common/utils.ts
|
|
4
|
+
const composeHint = (key) => ({
|
|
5
|
+
key,
|
|
6
|
+
label: hints[key]
|
|
7
|
+
});
|
|
8
|
+
const isSuccessfulStatus = (status) => {
|
|
9
|
+
return status === void 0 || status >= 200 && status < 300;
|
|
10
|
+
};
|
|
11
|
+
const toPositiveInteger = (value, fallback) => {
|
|
12
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 1 ? value : fallback;
|
|
13
|
+
};
|
|
14
|
+
const normalizeMimeType = (type) => {
|
|
15
|
+
return type.split(";")[0].trim().toLowerCase();
|
|
16
|
+
};
|
|
17
|
+
const isOfAllowedMimeType = (type, allowedTypes) => {
|
|
18
|
+
if (allowedTypes.length === 0) return true;
|
|
19
|
+
if (!type) return false;
|
|
20
|
+
return isAnyOf(type, allowedTypes, normalizeMimeType);
|
|
21
|
+
};
|
|
22
|
+
const hasMetaContent = (content, name, value) => {
|
|
23
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24
|
+
const escapedValue = value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
25
|
+
return new RegExp(`<meta(?=[^>]*(?:name|property)=["']${escapedName}["'])(?=[^>]*content=["']${escapedValue})`, "i").test(content);
|
|
26
|
+
};
|
|
27
|
+
const matchesAnyOfLinkSelectors = (rel, type, selectors) => {
|
|
28
|
+
return selectors.some((selector) => {
|
|
29
|
+
if (!anyWordMatchesAnyOf(rel, [selector.rel])) return false;
|
|
30
|
+
if (!selector.types) return true;
|
|
31
|
+
return isOfAllowedMimeType(type, selector.types);
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
const processConcurrently = async (items, processFn, options) => {
|
|
35
|
+
if (!(options.concurrency >= 1)) return;
|
|
36
|
+
const active = /* @__PURE__ */ new Set();
|
|
37
|
+
let index = 0;
|
|
38
|
+
while (index < items.length || active.size > 0) {
|
|
39
|
+
if (options.shouldStop?.()) break;
|
|
40
|
+
while (active.size < options.concurrency && index < items.length) {
|
|
41
|
+
const item = items[index++];
|
|
42
|
+
const promise = processFn(item).catch(() => {}).finally(() => {
|
|
43
|
+
active.delete(promise);
|
|
44
|
+
});
|
|
45
|
+
active.add(promise);
|
|
46
|
+
}
|
|
47
|
+
if (active.size > 0) await Promise.race(active);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
export { composeHint, hasMetaContent, isSuccessfulStatus, matchesAnyOfLinkSelectors, processConcurrently, toPositiveInteger };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { omitEmpty } from "
|
|
1
|
+
import { omitEmpty } from "../../node_modules/trousse/dist/arrays.js";
|
|
2
2
|
import { blueskyHandler } from "./platform/handlers/bluesky.js";
|
|
3
3
|
import { codebergHandler } from "./platform/handlers/codeberg.js";
|
|
4
4
|
import { deviantartHandler } from "./platform/handlers/deviantart.js";
|