@dxos/plugin-magazine 0.10.0 → 0.11.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/dist/lib/MagazinePlugin.mjs +36 -0
- package/dist/lib/MagazinePlugin.mjs.map +1 -0
- package/dist/lib/MagazinePlugin.workerd.mjs +26 -0
- package/dist/lib/MagazinePlugin.workerd.mjs.map +1 -0
- package/dist/lib/atoms.mjs +175 -0
- package/dist/lib/atoms.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +12 -0
- package/dist/lib/capabilities.mjs.map +1 -0
- package/dist/lib/chunk-FeedArticle.mjs +70 -0
- package/dist/lib/chunk-FeedArticle.mjs.map +1 -0
- package/dist/lib/chunk-FeedProperties.mjs +78 -0
- package/dist/lib/chunk-FeedProperties.mjs.map +1 -0
- package/dist/lib/chunk-MagazineArticle.mjs +267 -0
- package/dist/lib/chunk-MagazineArticle.mjs.map +1 -0
- package/dist/lib/chunk-PostArticle.mjs +174 -0
- package/dist/lib/chunk-PostArticle.mjs.map +1 -0
- package/dist/lib/chunk-PostCard.mjs +62 -0
- package/dist/lib/chunk-PostCard.mjs.map +1 -0
- package/dist/lib/chunk-app-graph-builder.mjs +91 -0
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
- package/dist/lib/chunk-clear-magazine.mjs +37 -0
- package/dist/lib/chunk-clear-magazine.mjs.map +1 -0
- package/dist/lib/chunk-create-object.mjs +59 -0
- package/dist/lib/chunk-create-object.mjs.map +1 -0
- package/dist/lib/chunk-curate-magazine.mjs +164 -0
- package/dist/lib/chunk-curate-magazine.mjs.map +1 -0
- package/dist/lib/chunk-date.mjs +25 -0
- package/dist/lib/chunk-date.mjs.map +1 -0
- package/dist/lib/chunk-fetch-article-content.mjs +26 -0
- package/dist/lib/chunk-fetch-article-content.mjs.map +1 -0
- package/dist/lib/chunk-load-post-content.mjs +57 -0
- package/dist/lib/chunk-load-post-content.mjs.map +1 -0
- package/dist/lib/{neutral/chunk-JFPR6OV4.mjs → chunk-meta.mjs} +19 -26
- package/dist/lib/chunk-meta.mjs.map +1 -0
- package/dist/lib/chunk-operation-handler.mjs +13 -0
- package/dist/lib/chunk-operation-handler.mjs.map +1 -0
- package/dist/lib/chunk-paths.mjs +8 -0
- package/dist/lib/chunk-paths.mjs.map +1 -0
- package/dist/lib/chunk-post-content.mjs +14 -0
- package/dist/lib/chunk-post-content.mjs.map +1 -0
- package/dist/lib/chunk-react-surface.mjs +60 -0
- package/dist/lib/chunk-react-surface.mjs.map +1 -0
- package/dist/lib/chunk-routine-templates.mjs +52 -0
- package/dist/lib/chunk-routine-templates.mjs.map +1 -0
- package/dist/lib/chunk-skill-definition.mjs +12 -0
- package/dist/lib/chunk-skill-definition.mjs.map +1 -0
- package/dist/lib/chunk-sources.mjs +576 -0
- package/dist/lib/chunk-sources.mjs.map +1 -0
- package/dist/lib/chunk-sync-feed.mjs +86 -0
- package/dist/lib/chunk-sync-feed.mjs.map +1 -0
- package/dist/lib/chunk-text.mjs +52 -0
- package/dist/lib/chunk-text.mjs.map +1 -0
- package/dist/lib/chunk-types.mjs +607 -0
- package/dist/lib/chunk-types.mjs.map +1 -0
- package/dist/lib/components.mjs +323 -0
- package/dist/lib/components.mjs.map +1 -0
- package/dist/lib/containers.mjs +11 -0
- package/dist/lib/containers.mjs.map +1 -0
- package/dist/lib/index.mjs +3 -0
- package/dist/lib/meta.mjs +2 -0
- package/dist/lib/operations.mjs +7 -0
- package/dist/lib/operations.mjs.map +1 -0
- package/dist/lib/plugin.mjs +9 -0
- package/dist/lib/plugin.mjs.map +1 -0
- package/dist/lib/plugin.workerd.mjs +3 -0
- package/dist/lib/{neutral/skills/index.mjs → skills.mjs} +15 -28
- package/dist/lib/skills.mjs.map +1 -0
- package/dist/lib/testing.mjs +71 -0
- package/dist/lib/testing.mjs.map +1 -0
- package/dist/lib/translations.mjs +74 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/lib/types.mjs +2 -0
- package/dist/types/src/MagazinePlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
- package/dist/types/src/capabilities/create-object.d.ts +1 -1
- package/dist/types/src/capabilities/index.d.ts +0 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/routine-templates.d.ts +1 -1
- package/dist/types/src/components/PostContent/PostContent.d.ts +1 -13
- package/dist/types/src/components/PostContent/PostContent.d.ts.map +1 -1
- package/dist/types/src/components/PostContent/dedupe-images.d.ts +13 -0
- package/dist/types/src/components/PostContent/dedupe-images.d.ts.map +1 -0
- package/dist/types/src/components/PostContent/index.d.ts +1 -0
- package/dist/types/src/components/PostContent/index.d.ts.map +1 -1
- package/dist/types/src/components/PostStack/PostStack.d.ts +1 -1
- package/dist/types/src/components/PostStack/PostStack.d.ts.map +1 -1
- package/dist/types/src/components/SubscriptionStack/SubscriptionStack.d.ts +1 -1
- package/dist/types/src/components/SubscriptionStack/SubscriptionStack.d.ts.map +1 -1
- package/dist/types/src/containers/FeedArticle/FeedArticle.d.ts +4 -1
- package/dist/types/src/containers/FeedArticle/FeedArticle.d.ts.map +1 -1
- package/dist/types/src/containers/FeedProperties/FeedProperties.d.ts +4 -1
- package/dist/types/src/containers/FeedProperties/FeedProperties.d.ts.map +1 -1
- package/dist/types/src/containers/MagazineArticle/MagazineArticle.d.ts +4 -1
- package/dist/types/src/containers/MagazineArticle/MagazineArticle.d.ts.map +1 -1
- package/dist/types/src/containers/MagazineArticle/MagazineArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/MagazineArticle/MagazineTile.d.ts +4 -1
- package/dist/types/src/containers/MagazineArticle/MagazineTile.d.ts.map +1 -1
- package/dist/types/src/containers/MagazineArticle/useToolbar.d.ts +4 -8
- package/dist/types/src/containers/MagazineArticle/useToolbar.d.ts.map +1 -1
- package/dist/types/src/containers/PostArticle/PostArticle.d.ts +4 -1
- package/dist/types/src/containers/PostArticle/PostArticle.d.ts.map +1 -1
- package/dist/types/src/containers/PostArticle/PostArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/PostArticle/PostToolbar.d.ts +1 -1
- package/dist/types/src/containers/PostArticle/PostToolbar.d.ts.map +1 -1
- package/dist/types/src/containers/PostCard/PostCard.d.ts +4 -6
- package/dist/types/src/containers/PostCard/PostCard.d.ts.map +1 -1
- package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.d.ts +4 -1
- package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.d.ts.map +1 -1
- package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.d.ts.map +1 -1
- package/dist/types/src/stories/ArticleExtractor.stories.d.ts +1 -0
- package/dist/types/src/stories/ArticleExtractor.stories.d.ts.map +1 -1
- package/dist/types/src/stories/MagazineCurate.stories.d.ts.map +1 -1
- package/dist/types/src/templates/magazine-curation.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +1 -1
- package/package.json +57 -60
- package/src/MagazinePlugin.tsx +0 -3
- package/src/atoms/atoms.test.ts +5 -4
- package/src/capabilities/app-graph-builder.ts +8 -6
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/{react-surface.tsx → react-surface.ts} +10 -12
- package/src/components/PostContent/PostContent.test.ts +1 -1
- package/src/components/PostContent/PostContent.tsx +1 -41
- package/src/components/PostContent/dedupe-images.ts +48 -0
- package/src/components/PostContent/index.ts +1 -0
- package/src/containers/FeedArticle/FeedArticle.stories.tsx +2 -2
- package/src/containers/FeedArticle/FeedArticle.tsx +4 -2
- package/src/containers/FeedProperties/FeedProperties.tsx +6 -4
- package/src/containers/MagazineArticle/MagazineArticle.stories.tsx +2 -1
- package/src/containers/MagazineArticle/MagazineArticle.tsx +8 -6
- package/src/containers/MagazineArticle/MagazineTile.tsx +2 -0
- package/src/containers/MagazineArticle/useToolbar.tsx +2 -0
- package/src/containers/PostArticle/PostArticle.stories.tsx +2 -1
- package/src/containers/PostArticle/PostArticle.tsx +6 -3
- package/src/containers/PostArticle/PostToolbar.tsx +1 -1
- package/src/containers/PostCard/PostCard.tsx +3 -1
- package/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.tsx +2 -1
- package/src/containers/SubscriptionsArticle/SubscriptionsArticle.tsx +5 -3
- package/src/operations/curate-magazine.test.ts +108 -4
- package/src/operations/sync-feed.test.ts +1 -1
- package/src/operations/sync-feed.ts +1 -1
- package/src/paths.ts +3 -3
- package/src/stories/ArticleExtractor.stories.tsx +1 -1
- package/src/stories/MagazineCurate.stories.tsx +3 -2
- package/src/templates/magazine-curation.ts +3 -2
- package/src/types/Magazine.test.ts +1 -1
- package/src/types/Subscription.ts +1 -1
- package/dist/lib/neutral/FeedArticle-PEWCFFSP.mjs +0 -90
- package/dist/lib/neutral/FeedArticle-PEWCFFSP.mjs.map +0 -7
- package/dist/lib/neutral/FeedProperties-EIO7IZOA.mjs +0 -97
- package/dist/lib/neutral/FeedProperties-EIO7IZOA.mjs.map +0 -7
- package/dist/lib/neutral/MagazineArticle-5T7RTIPS.mjs +0 -325
- package/dist/lib/neutral/MagazineArticle-5T7RTIPS.mjs.map +0 -7
- package/dist/lib/neutral/MagazinePlugin.mjs +0 -62
- package/dist/lib/neutral/MagazinePlugin.mjs.map +0 -7
- package/dist/lib/neutral/MagazinePlugin.workerd.mjs +0 -12
- package/dist/lib/neutral/MagazinePlugin.workerd.mjs.map +0 -7
- package/dist/lib/neutral/PostArticle-BGIPU7XA.mjs +0 -230
- package/dist/lib/neutral/PostArticle-BGIPU7XA.mjs.map +0 -7
- package/dist/lib/neutral/PostCard-VDGN7BBA.mjs +0 -60
- package/dist/lib/neutral/PostCard-VDGN7BBA.mjs.map +0 -7
- package/dist/lib/neutral/app-graph-builder-JDPRBVHL.mjs +0 -121
- package/dist/lib/neutral/app-graph-builder-JDPRBVHL.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/index.mjs +0 -21
- package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
- package/dist/lib/neutral/chunk-3K4AQKBZ.mjs +0 -12
- package/dist/lib/neutral/chunk-3K4AQKBZ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-AFPBWBTK.mjs +0 -591
- package/dist/lib/neutral/chunk-AFPBWBTK.mjs.map +0 -7
- package/dist/lib/neutral/chunk-APQRTYT3.mjs +0 -57
- package/dist/lib/neutral/chunk-APQRTYT3.mjs.map +0 -7
- package/dist/lib/neutral/chunk-GU725ZF4.mjs +0 -11
- package/dist/lib/neutral/chunk-GU725ZF4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-JFPR6OV4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-KTYLUOUG.mjs +0 -36
- package/dist/lib/neutral/chunk-KTYLUOUG.mjs.map +0 -7
- package/dist/lib/neutral/chunk-LFSQMLPK.mjs +0 -8
- package/dist/lib/neutral/chunk-LFSQMLPK.mjs.map +0 -7
- package/dist/lib/neutral/chunk-MBPX7RPI.mjs +0 -14
- package/dist/lib/neutral/chunk-MBPX7RPI.mjs.map +0 -7
- package/dist/lib/neutral/chunk-OYCDRSWB.mjs +0 -624
- package/dist/lib/neutral/chunk-OYCDRSWB.mjs.map +0 -7
- package/dist/lib/neutral/chunk-SAWKLGJU.mjs +0 -28
- package/dist/lib/neutral/chunk-SAWKLGJU.mjs.map +0 -7
- package/dist/lib/neutral/chunk-XCNCK47N.mjs +0 -15
- package/dist/lib/neutral/chunk-XCNCK47N.mjs.map +0 -7
- package/dist/lib/neutral/clear-magazine-KNY4OWY4.mjs +0 -59
- package/dist/lib/neutral/clear-magazine-KNY4OWY4.mjs.map +0 -7
- package/dist/lib/neutral/components/index.mjs +0 -338
- package/dist/lib/neutral/components/index.mjs.map +0 -7
- package/dist/lib/neutral/containers/index.mjs +0 -17
- package/dist/lib/neutral/containers/index.mjs.map +0 -7
- package/dist/lib/neutral/create-object-SYZMRR4H.mjs +0 -98
- package/dist/lib/neutral/create-object-SYZMRR4H.mjs.map +0 -7
- package/dist/lib/neutral/curate-magazine-7RMKSJC5.mjs +0 -184
- package/dist/lib/neutral/curate-magazine-7RMKSJC5.mjs.map +0 -7
- package/dist/lib/neutral/fetch-article-content-CXPKXIMR.mjs +0 -31
- package/dist/lib/neutral/fetch-article-content-CXPKXIMR.mjs.map +0 -7
- package/dist/lib/neutral/index.mjs +0 -18
- package/dist/lib/neutral/index.mjs.map +0 -7
- package/dist/lib/neutral/load-post-content-H3S4TKVM.mjs +0 -65
- package/dist/lib/neutral/load-post-content-H3S4TKVM.mjs.map +0 -7
- package/dist/lib/neutral/meta.json +0 -1
- package/dist/lib/neutral/meta.mjs +0 -8
- package/dist/lib/neutral/meta.mjs.map +0 -7
- package/dist/lib/neutral/navigation-resolver-IN4OMCDR.mjs +0 -18
- package/dist/lib/neutral/navigation-resolver-IN4OMCDR.mjs.map +0 -7
- package/dist/lib/neutral/operation-handler-JE3743BU.mjs +0 -8
- package/dist/lib/neutral/operation-handler-JE3743BU.mjs.map +0 -7
- package/dist/lib/neutral/operations/index.mjs +0 -8
- package/dist/lib/neutral/operations/index.mjs.map +0 -7
- package/dist/lib/neutral/plugin.mjs +0 -16
- package/dist/lib/neutral/plugin.mjs.map +0 -7
- package/dist/lib/neutral/plugin.workerd.mjs +0 -16
- package/dist/lib/neutral/plugin.workerd.mjs.map +0 -7
- package/dist/lib/neutral/react-surface-TZESAMG2.mjs +0 -60
- package/dist/lib/neutral/react-surface-TZESAMG2.mjs.map +0 -7
- package/dist/lib/neutral/routine-templates-D5A2L4KL.mjs +0 -52
- package/dist/lib/neutral/routine-templates-D5A2L4KL.mjs.map +0 -7
- package/dist/lib/neutral/skill-definition-3KLMUEC5.mjs +0 -8
- package/dist/lib/neutral/skill-definition-3KLMUEC5.mjs.map +0 -7
- package/dist/lib/neutral/skills/index.mjs.map +0 -7
- package/dist/lib/neutral/sync-feed-SDXYF7HU.mjs +0 -99
- package/dist/lib/neutral/sync-feed-SDXYF7HU.mjs.map +0 -7
- package/dist/lib/neutral/translations.mjs +0 -81
- package/dist/lib/neutral/translations.mjs.map +0 -7
- package/dist/lib/neutral/types/index.mjs +0 -14
- package/dist/lib/neutral/types/index.mjs.map +0 -7
- package/dist/types/src/capabilities/navigation-resolver.d.ts +0 -5
- package/dist/types/src/capabilities/navigation-resolver.d.ts.map +0 -1
- package/dist/types/src/operations/curate-magazine.skill.test.d.ts +0 -2
- package/dist/types/src/operations/curate-magazine.skill.test.d.ts.map +0 -1
- package/src/capabilities/navigation-resolver.ts +0 -21
- package/src/operations/curate-magazine.skill.conversations.json +0 -1
- package/src/operations/curate-magazine.skill.test.ts +0 -167
|
@@ -1,591 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
decodeEntities,
|
|
3
|
-
makeSnippet
|
|
4
|
-
} from "./chunk-APQRTYT3.mjs";
|
|
5
|
-
|
|
6
|
-
// src/operations/sources/cors.ts
|
|
7
|
-
var CORS_PROXY = "/api/rss?url=";
|
|
8
|
-
var browserCorsProxy = () => typeof window !== "undefined" ? CORS_PROXY : void 0;
|
|
9
|
-
var applyCorsProxy = (url, proxy) => proxy ? `${proxy}${encodeURIComponent(url)}` : url;
|
|
10
|
-
|
|
11
|
-
// src/operations/extraction/article.ts
|
|
12
|
-
import Defuddle from "defuddle/full";
|
|
13
|
-
var isDocumentParserAvailable = () => typeof DOMParser !== "undefined";
|
|
14
|
-
var collectImageUrls = (lead, contentHtml) => {
|
|
15
|
-
const seen = /* @__PURE__ */ new Set();
|
|
16
|
-
const urls = [];
|
|
17
|
-
const push = (url) => {
|
|
18
|
-
if (!url || url.startsWith("data:") || seen.has(url)) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
seen.add(url);
|
|
22
|
-
urls.push(url);
|
|
23
|
-
};
|
|
24
|
-
push(lead);
|
|
25
|
-
const imgRegex = /<img\b[^>]+src=["']([^"']+)["']/gi;
|
|
26
|
-
let match;
|
|
27
|
-
while ((match = imgRegex.exec(contentHtml)) != null) {
|
|
28
|
-
push(match[1]);
|
|
29
|
-
}
|
|
30
|
-
return urls;
|
|
31
|
-
};
|
|
32
|
-
var CHROME_CLASS_PATTERN = /(?:^|[\s_-])(?:tag|topic|related|recirc|footer|sidebar|widget|share|social|comments?|disqus|recommend|more[-_]from|read[-_]next|outbrain|taboola)(?:[\s_-]|$)/i;
|
|
33
|
-
var CHROME_HREF_PATTERN = /\/(?:tags?|topics?|categor(?:y|ies)|authors?|related|recommended)\//i;
|
|
34
|
-
var isHeading = (el) => /^H[1-6]$/i.test(el.tagName);
|
|
35
|
-
var isLinkOnlyList = (el) => {
|
|
36
|
-
if (el.tagName !== "UL" && el.tagName !== "OL") {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
const items = Array.from(el.children).filter((child) => child.tagName === "LI");
|
|
40
|
-
if (items.length === 0) {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
return items.every((li) => {
|
|
44
|
-
const links = li.querySelectorAll("a");
|
|
45
|
-
if (links.length !== 1) {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
const text2 = (li.textContent ?? "").trim();
|
|
49
|
-
const linkText = (links[0].textContent ?? "").trim();
|
|
50
|
-
return text2.length > 0 && Math.abs(text2.length - linkText.length) <= 4;
|
|
51
|
-
});
|
|
52
|
-
};
|
|
53
|
-
var isTagURLBlock = (el) => {
|
|
54
|
-
const links = Array.from(el.querySelectorAll("a[href]"));
|
|
55
|
-
if (links.length < 2) {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
const matching = links.filter((anchor) => CHROME_HREF_PATTERN.test(anchor.getAttribute("href") ?? ""));
|
|
59
|
-
return matching.length / links.length > 0.6;
|
|
60
|
-
};
|
|
61
|
-
var hasNoBodyContent = (el) => el.querySelector("p, blockquote, pre, code, figure, img, table") == null;
|
|
62
|
-
var isChromeElement = (el) => {
|
|
63
|
-
const tag = el.tagName;
|
|
64
|
-
if (tag === "ASIDE" || tag === "NAV" || tag === "FOOTER") {
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
const role = el.getAttribute("role");
|
|
68
|
-
if (role === "navigation" || role === "complementary" || role === "contentinfo") {
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
if (isLinkOnlyList(el)) {
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
if (!hasNoBodyContent(el)) {
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
if (isTagURLBlock(el)) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
const classNameAndId = `${(el.getAttribute("class") ?? "").toString()} ${el.id ?? ""}`;
|
|
81
|
-
if (CHROME_CLASS_PATTERN.test(classNameAndId)) {
|
|
82
|
-
return true;
|
|
83
|
-
}
|
|
84
|
-
return false;
|
|
85
|
-
};
|
|
86
|
-
var findContentRoot = (doc) => doc.querySelector("article") ?? doc.querySelector("main") ?? doc.querySelector('[role="main"]') ?? doc.body;
|
|
87
|
-
var pruneChromeDescendants = (root) => {
|
|
88
|
-
const candidates = Array.from(root.querySelectorAll("*"));
|
|
89
|
-
for (const el of candidates) {
|
|
90
|
-
if (!root.contains(el)) {
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
if (isChromeElement(el)) {
|
|
94
|
-
el.remove();
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
var trimDanglingTrailingHeading = (root) => {
|
|
99
|
-
let cursor = root.lastElementChild;
|
|
100
|
-
while (cursor && isHeading(cursor) && cursor.nextElementSibling == null) {
|
|
101
|
-
const previous = cursor.previousElementSibling;
|
|
102
|
-
cursor.remove();
|
|
103
|
-
cursor = previous;
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
var pruneTrailingChrome = (doc) => {
|
|
107
|
-
const root = findContentRoot(doc);
|
|
108
|
-
if (!root) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
const originalLastChild = root.lastElementChild;
|
|
112
|
-
pruneChromeDescendants(root);
|
|
113
|
-
if (originalLastChild && !root.contains(originalLastChild)) {
|
|
114
|
-
trimDanglingTrailingHeading(root);
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
var mapResult = (result) => {
|
|
118
|
-
const lead = result.image || void 0;
|
|
119
|
-
return {
|
|
120
|
-
markdown: result.contentMarkdown ?? "",
|
|
121
|
-
html: result.content ?? "",
|
|
122
|
-
title: result.title || void 0,
|
|
123
|
-
author: result.author || void 0,
|
|
124
|
-
description: result.description || void 0,
|
|
125
|
-
published: result.published || void 0,
|
|
126
|
-
image: lead,
|
|
127
|
-
domain: result.domain || void 0,
|
|
128
|
-
imageUrls: collectImageUrls(lead, result.content ?? ""),
|
|
129
|
-
wordCount: result.wordCount
|
|
130
|
-
};
|
|
131
|
-
};
|
|
132
|
-
var extractArticle = async (html, url) => {
|
|
133
|
-
if (!html) {
|
|
134
|
-
return {
|
|
135
|
-
markdown: "",
|
|
136
|
-
html: "",
|
|
137
|
-
imageUrls: []
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
if (isDocumentParserAvailable()) {
|
|
141
|
-
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
142
|
-
pruneTrailingChrome(doc);
|
|
143
|
-
return mapResult(new Defuddle(doc, {
|
|
144
|
-
url,
|
|
145
|
-
separateMarkdown: true
|
|
146
|
-
}).parse());
|
|
147
|
-
}
|
|
148
|
-
const { Defuddle: DefuddleNode } = await import("defuddle/node");
|
|
149
|
-
return mapResult(await DefuddleNode(html, url, {
|
|
150
|
-
separateMarkdown: true
|
|
151
|
-
}));
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
// src/operations/sources/article.ts
|
|
155
|
-
var FETCH_TIMEOUT_MS = 1e4;
|
|
156
|
-
var MAX_RESPONSE_BYTES = 2e6;
|
|
157
|
-
var MAX_RESPONSE_BYTES_HEADER = 5e6;
|
|
158
|
-
var BLOCKED_HOSTS = /* @__PURE__ */ new Set([
|
|
159
|
-
"localhost",
|
|
160
|
-
"127.0.0.1",
|
|
161
|
-
"0.0.0.0",
|
|
162
|
-
"::1",
|
|
163
|
-
"169.254.169.254",
|
|
164
|
-
"metadata.google.internal"
|
|
165
|
-
]);
|
|
166
|
-
var validateUrl = (link) => {
|
|
167
|
-
const url = new URL(link);
|
|
168
|
-
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
169
|
-
throw new Error(`Unsupported protocol: ${url.protocol}`);
|
|
170
|
-
}
|
|
171
|
-
const host = url.hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
172
|
-
if (BLOCKED_HOSTS.has(host)) {
|
|
173
|
-
throw new Error(`Blocked host: ${host}`);
|
|
174
|
-
}
|
|
175
|
-
return url;
|
|
176
|
-
};
|
|
177
|
-
var readCapped = async (response, limit) => {
|
|
178
|
-
const reader = response.body?.getReader();
|
|
179
|
-
if (!reader) {
|
|
180
|
-
throw new Error("Response body stream unavailable.");
|
|
181
|
-
}
|
|
182
|
-
const decoder = new TextDecoder("utf-8");
|
|
183
|
-
let received = 0;
|
|
184
|
-
let out = "";
|
|
185
|
-
while (received < limit) {
|
|
186
|
-
const { value, done } = await reader.read();
|
|
187
|
-
if (done) {
|
|
188
|
-
break;
|
|
189
|
-
}
|
|
190
|
-
if (value) {
|
|
191
|
-
received += value.byteLength;
|
|
192
|
-
out += decoder.decode(value, {
|
|
193
|
-
stream: true
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
try {
|
|
198
|
-
await reader.cancel();
|
|
199
|
-
} catch {
|
|
200
|
-
}
|
|
201
|
-
return (out + decoder.decode()).slice(0, limit);
|
|
202
|
-
};
|
|
203
|
-
var fetchArticle = async (link, options = {}) => {
|
|
204
|
-
try {
|
|
205
|
-
const url = validateUrl(link);
|
|
206
|
-
const fetchTarget = applyCorsProxy(url.toString(), options.corsProxy);
|
|
207
|
-
const response = await fetch(fetchTarget, {
|
|
208
|
-
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
209
|
-
redirect: "follow"
|
|
210
|
-
});
|
|
211
|
-
if (!response.ok) {
|
|
212
|
-
throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);
|
|
213
|
-
}
|
|
214
|
-
const contentLength = response.headers.get("content-length");
|
|
215
|
-
if (contentLength && Number(contentLength) > MAX_RESPONSE_BYTES_HEADER) {
|
|
216
|
-
throw new Error(`Response too large: ${contentLength} bytes`);
|
|
217
|
-
}
|
|
218
|
-
const html = await readCapped(response, MAX_RESPONSE_BYTES);
|
|
219
|
-
const article = await extractArticle(html, url.toString());
|
|
220
|
-
return {
|
|
221
|
-
text: article.markdown,
|
|
222
|
-
imageUrls: article.imageUrls
|
|
223
|
-
};
|
|
224
|
-
} catch (error) {
|
|
225
|
-
throw new Error(`Failed to fetch article: ${String(error)}`, {
|
|
226
|
-
cause: error instanceof Error ? error : void 0
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
// src/operations/sources/rss.ts
|
|
232
|
-
import * as FetchHttpClient from "@effect/platform/FetchHttpClient";
|
|
233
|
-
import * as Effect2 from "effect/Effect";
|
|
234
|
-
import { XMLParser } from "fast-xml-parser";
|
|
235
|
-
import { normalizeText } from "@dxos/markdown";
|
|
236
|
-
import { Subscription } from "#types";
|
|
237
|
-
|
|
238
|
-
// src/operations/sources/feed-fetcher.ts
|
|
239
|
-
import * as Data from "effect/Data";
|
|
240
|
-
var FeedFetchError = class extends Data.TaggedError("FeedFetchError") {
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
// src/operations/sources/http.ts
|
|
244
|
-
import * as HttpClient from "@effect/platform/HttpClient";
|
|
245
|
-
import * as HttpClientRequest from "@effect/platform/HttpClientRequest";
|
|
246
|
-
import * as HttpClientResponse from "@effect/platform/HttpClientResponse";
|
|
247
|
-
import * as Effect from "effect/Effect";
|
|
248
|
-
import * as Schedule from "effect/Schedule";
|
|
249
|
-
var retryPolicy = Schedule.exponential("500 millis").pipe(Schedule.compose(Schedule.recurs(2)));
|
|
250
|
-
var getJson = (schema, url, proxy) => HttpClientRequest.get(applyCorsProxy(url, proxy)).pipe(HttpClient.execute, Effect.flatMap(HttpClientResponse.schemaBodyJson(schema)), Effect.timeout("10 seconds"), Effect.retry(retryPolicy), Effect.scoped, Effect.mapError((cause) => new FeedFetchError({
|
|
251
|
-
message: `Fetch failed: ${url}`,
|
|
252
|
-
cause
|
|
253
|
-
})));
|
|
254
|
-
var getText = (url, proxy) => HttpClientRequest.get(applyCorsProxy(url, proxy)).pipe(HttpClient.execute, Effect.flatMap((response) => response.text), Effect.timeout("10 seconds"), Effect.retry(retryPolicy), Effect.scoped, Effect.mapError((cause) => new FeedFetchError({
|
|
255
|
-
message: `Fetch failed: ${url}`,
|
|
256
|
-
cause
|
|
257
|
-
})));
|
|
258
|
-
|
|
259
|
-
// src/operations/sources/rss.ts
|
|
260
|
-
var stripCdata = (value) => value.replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g, "$1");
|
|
261
|
-
var text = (value) => {
|
|
262
|
-
if (value == null) {
|
|
263
|
-
return void 0;
|
|
264
|
-
}
|
|
265
|
-
if (typeof value === "string") {
|
|
266
|
-
return decodeEntities(stripCdata(value));
|
|
267
|
-
}
|
|
268
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
269
|
-
return String(value);
|
|
270
|
-
}
|
|
271
|
-
if (typeof value === "object") {
|
|
272
|
-
const t = value["#text"];
|
|
273
|
-
if (typeof t === "string") {
|
|
274
|
-
return decodeEntities(stripCdata(t));
|
|
275
|
-
}
|
|
276
|
-
if (typeof t === "number" || typeof t === "boolean") {
|
|
277
|
-
return String(t);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return void 0;
|
|
281
|
-
};
|
|
282
|
-
var markdown = (value) => value != null ? normalizeText(value) : void 0;
|
|
283
|
-
var fetchRss = (url, options) => Effect2.gen(function* () {
|
|
284
|
-
const xml = yield* getText(url, options?.corsProxy);
|
|
285
|
-
return yield* Effect2.try({
|
|
286
|
-
try: () => parseFeed(url, xml),
|
|
287
|
-
catch: (cause) => new FeedFetchError({
|
|
288
|
-
message: `Unrecognized feed format: ${url}`,
|
|
289
|
-
cause
|
|
290
|
-
})
|
|
291
|
-
});
|
|
292
|
-
}).pipe(Effect2.provide(FetchHttpClient.layer));
|
|
293
|
-
var parseFeed = (url, xml) => {
|
|
294
|
-
const parser = new XMLParser({
|
|
295
|
-
ignoreAttributes: false,
|
|
296
|
-
attributeNamePrefix: "@_",
|
|
297
|
-
// RSS/Atom feeds frequently embed HTML (sometimes un-escaped, without CDATA) in content fields,
|
|
298
|
-
// which can blow past fast-xml-parser's default 100-tag nesting cap.
|
|
299
|
-
maxNestedTags: 1e4,
|
|
300
|
-
// Treat known HTML-bearing fields as opaque text so embedded markup isn't parsed as XML.
|
|
301
|
-
stopNodes: [
|
|
302
|
-
"*.description",
|
|
303
|
-
"*.summary",
|
|
304
|
-
"*.content",
|
|
305
|
-
"*.content:encoded"
|
|
306
|
-
]
|
|
307
|
-
});
|
|
308
|
-
const parsed = parser.parse(xml);
|
|
309
|
-
const channel = parsed.rss?.channel ?? parsed.feed;
|
|
310
|
-
if (!channel) {
|
|
311
|
-
throw new Error("Unrecognized feed format");
|
|
312
|
-
}
|
|
313
|
-
const isAtom = !parsed.rss;
|
|
314
|
-
const feedName = text(channel.title) ?? "";
|
|
315
|
-
const feedDescription = markdown(text(isAtom ? channel.subtitle : channel.description)) ?? "";
|
|
316
|
-
const items = (isAtom ? channel.entry : channel.item) ?? [];
|
|
317
|
-
const itemList = Array.isArray(items) ? items : [
|
|
318
|
-
items
|
|
319
|
-
];
|
|
320
|
-
const posts = itemList.map((item) => {
|
|
321
|
-
const link = isAtom ? (Array.isArray(item.link) ? item.link.find((l) => l["@_rel"] === "alternate")?.["@_href"] : item.link?.["@_href"] ?? text(item.link)) ?? "" : text(item.link) ?? "";
|
|
322
|
-
const author = isAtom ? text(item.author?.name) ?? text(item.author) : text(item["dc:creator"]) ?? text(item.author);
|
|
323
|
-
const description = markdown(text(item.description));
|
|
324
|
-
const content = isAtom ? markdown(text(item.summary)) ?? markdown(text(item.content)) : markdown(text(item["content:encoded"]));
|
|
325
|
-
return Subscription.makePost({
|
|
326
|
-
title: text(item.title),
|
|
327
|
-
link,
|
|
328
|
-
description,
|
|
329
|
-
content,
|
|
330
|
-
author,
|
|
331
|
-
published: text(item.pubDate) ?? text(item.published) ?? text(item.updated),
|
|
332
|
-
guid: (isAtom ? text(item.id) : text(item.guid)) ?? link
|
|
333
|
-
});
|
|
334
|
-
});
|
|
335
|
-
const feed = Subscription.makeSubscription({
|
|
336
|
-
name: feedName,
|
|
337
|
-
url,
|
|
338
|
-
description: feedDescription
|
|
339
|
-
});
|
|
340
|
-
return {
|
|
341
|
-
feed,
|
|
342
|
-
posts
|
|
343
|
-
};
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
// src/operations/sources/standard-site.ts
|
|
347
|
-
import * as FetchHttpClient2 from "@effect/platform/FetchHttpClient";
|
|
348
|
-
import * as Effect3 from "effect/Effect";
|
|
349
|
-
import * as Schema from "effect/Schema";
|
|
350
|
-
import { Subscription as Subscription2 } from "#types";
|
|
351
|
-
var BSKY_PUBLIC_API = "https://public.api.bsky.app/xrpc";
|
|
352
|
-
var PLC_DIRECTORY = "https://plc.directory";
|
|
353
|
-
var DOCUMENT_COLLECTION = "site.standard.document";
|
|
354
|
-
var MARKDOWN_CONTENT_TYPE = "site.standard.content.markdown";
|
|
355
|
-
var endpoints = {
|
|
356
|
-
resolveHandle: (handle) => `${BSKY_PUBLIC_API}/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(handle)}`,
|
|
357
|
-
getProfile: (actor) => `${BSKY_PUBLIC_API}/app.bsky.actor.getProfile?actor=${encodeURIComponent(actor)}`,
|
|
358
|
-
searchActors: (query, limit) => `${BSKY_PUBLIC_API}/app.bsky.actor.searchActorsTypeahead?q=${encodeURIComponent(query)}&limit=${limit}`,
|
|
359
|
-
plcDoc: (did) => `${PLC_DIRECTORY}/${did}`,
|
|
360
|
-
listRecords: (pds, did, collection, limit) => `${pds}/xrpc/com.atproto.repo.listRecords?repo=${encodeURIComponent(did)}&collection=${encodeURIComponent(collection)}&limit=${limit}`,
|
|
361
|
-
getRecord: (pds, did, collection, rkey) => `${pds}/xrpc/com.atproto.repo.getRecord?repo=${encodeURIComponent(did)}&collection=${encodeURIComponent(collection)}&rkey=${encodeURIComponent(rkey)}`
|
|
362
|
-
};
|
|
363
|
-
var parseStandardSiteActor = (url) => {
|
|
364
|
-
const match = url.match(/bsky\.app\/profile\/([^/?#]+)/);
|
|
365
|
-
if (match) {
|
|
366
|
-
return match[1];
|
|
367
|
-
}
|
|
368
|
-
return url.replace(/^@/, "").trim();
|
|
369
|
-
};
|
|
370
|
-
var listStandardSitePublications = (actorOrUrl, options) => Effect3.gen(function* () {
|
|
371
|
-
const proxy = options?.corsProxy;
|
|
372
|
-
const actor = parseStandardSiteActor(actorOrUrl);
|
|
373
|
-
const did = yield* resolveDid(actor, proxy);
|
|
374
|
-
const pds = yield* resolvePds(did, proxy);
|
|
375
|
-
const records = yield* listDocuments(pds, did, proxy);
|
|
376
|
-
const sites = distinct(records.map((record) => record.value.site).filter(isString));
|
|
377
|
-
return yield* Effect3.forEach(sites, (site) => resolvePublication(site, proxy).pipe(Effect3.catchAll(() => Effect3.succeed({
|
|
378
|
-
site
|
|
379
|
-
}))), {
|
|
380
|
-
concurrency: "unbounded"
|
|
381
|
-
});
|
|
382
|
-
}).pipe(Effect3.provide(FetchHttpClient2.layer));
|
|
383
|
-
var searchStandardSiteHandles = (query, options) => query.trim().length === 0 ? Effect3.succeed([]) : getJson(SearchActorsResponse, endpoints.searchActors(query.trim(), 8), options?.corsProxy).pipe(Effect3.map((response) => (response.actors ?? []).map((actor) => ({
|
|
384
|
-
handle: actor.handle,
|
|
385
|
-
displayName: actor.displayName
|
|
386
|
-
}))), Effect3.orElseSucceed(() => []), Effect3.provide(FetchHttpClient2.layer));
|
|
387
|
-
var fetchStandardSite = (url, options) => Effect3.gen(function* () {
|
|
388
|
-
const proxy = options?.corsProxy;
|
|
389
|
-
const did = yield* resolveDidFromSite(url, proxy);
|
|
390
|
-
const pds = yield* resolvePds(did, proxy);
|
|
391
|
-
const allRecords = yield* listDocuments(pds, did, proxy);
|
|
392
|
-
const records = allRecords.filter((record) => record.value.site === url);
|
|
393
|
-
const profile = yield* fetchProfile(did, proxy);
|
|
394
|
-
const authorName = profile?.displayName ?? profile?.handle ?? did;
|
|
395
|
-
const publication = yield* resolvePublication(url, proxy).pipe(Effect3.catchAll(() => Effect3.succeed({
|
|
396
|
-
site: url
|
|
397
|
-
})));
|
|
398
|
-
const posts = records.map((record) => {
|
|
399
|
-
const value = record.value;
|
|
400
|
-
const content = value.content?.$type === MARKDOWN_CONTENT_TYPE ? value.content.text : void 0;
|
|
401
|
-
const description = value.description ?? (value.textContent ? makeSnippet(value.textContent) : void 0);
|
|
402
|
-
return Subscription2.makePost({
|
|
403
|
-
title: value.title,
|
|
404
|
-
link: joinUrl(publication.url, value.path),
|
|
405
|
-
description,
|
|
406
|
-
content,
|
|
407
|
-
author: authorName,
|
|
408
|
-
published: value.publishedAt,
|
|
409
|
-
// The record's AT-URI is the stable dedup key (see `sync-feed.ts` `postKey`).
|
|
410
|
-
guid: record.uri
|
|
411
|
-
});
|
|
412
|
-
});
|
|
413
|
-
posts.sort((postA, postB) => (postB.published ?? "").localeCompare(postA.published ?? ""));
|
|
414
|
-
const feed = Subscription2.makeSubscription({
|
|
415
|
-
name: publication.name ?? authorName,
|
|
416
|
-
url,
|
|
417
|
-
description: profile?.description ?? `Standard.site articles from @${profile?.handle ?? did}`,
|
|
418
|
-
iconUrl: profile?.avatar,
|
|
419
|
-
type: "standard-site"
|
|
420
|
-
});
|
|
421
|
-
return {
|
|
422
|
-
feed,
|
|
423
|
-
posts
|
|
424
|
-
};
|
|
425
|
-
}).pipe(Effect3.provide(FetchHttpClient2.layer));
|
|
426
|
-
var ResolveHandleResponse = Schema.Struct({
|
|
427
|
-
did: Schema.optional(Schema.String)
|
|
428
|
-
});
|
|
429
|
-
var SearchActorsResponse = Schema.Struct({
|
|
430
|
-
actors: Schema.optional(Schema.Array(Schema.Struct({
|
|
431
|
-
handle: Schema.String,
|
|
432
|
-
displayName: Schema.optional(Schema.String)
|
|
433
|
-
})))
|
|
434
|
-
});
|
|
435
|
-
var DidDocument = Schema.Struct({
|
|
436
|
-
service: Schema.optional(Schema.Array(Schema.Struct({
|
|
437
|
-
id: Schema.optional(Schema.String),
|
|
438
|
-
type: Schema.optional(Schema.String),
|
|
439
|
-
serviceEndpoint: Schema.optional(Schema.String)
|
|
440
|
-
})))
|
|
441
|
-
});
|
|
442
|
-
var Profile = Schema.Struct({
|
|
443
|
-
handle: Schema.optional(Schema.String),
|
|
444
|
-
displayName: Schema.optional(Schema.String),
|
|
445
|
-
avatar: Schema.optional(Schema.String),
|
|
446
|
-
description: Schema.optional(Schema.String)
|
|
447
|
-
});
|
|
448
|
-
var StandardSiteDocument = Schema.Struct({
|
|
449
|
-
site: Schema.optional(Schema.String),
|
|
450
|
-
title: Schema.optional(Schema.String),
|
|
451
|
-
publishedAt: Schema.optional(Schema.String),
|
|
452
|
-
path: Schema.optional(Schema.String),
|
|
453
|
-
description: Schema.optional(Schema.String),
|
|
454
|
-
content: Schema.optional(Schema.Struct({
|
|
455
|
-
$type: Schema.optional(Schema.String),
|
|
456
|
-
text: Schema.optional(Schema.String)
|
|
457
|
-
})),
|
|
458
|
-
textContent: Schema.optional(Schema.String)
|
|
459
|
-
});
|
|
460
|
-
var ListRecordsResponse = Schema.Struct({
|
|
461
|
-
records: Schema.optional(Schema.Array(Schema.Struct({
|
|
462
|
-
uri: Schema.String,
|
|
463
|
-
value: StandardSiteDocument
|
|
464
|
-
}))),
|
|
465
|
-
cursor: Schema.optional(Schema.String)
|
|
466
|
-
});
|
|
467
|
-
var PublicationRecord = Schema.Struct({
|
|
468
|
-
value: Schema.optional(Schema.Struct({
|
|
469
|
-
url: Schema.optional(Schema.String),
|
|
470
|
-
name: Schema.optional(Schema.String)
|
|
471
|
-
}))
|
|
472
|
-
});
|
|
473
|
-
var resolveDidFromSite = (site, proxy) => {
|
|
474
|
-
if (site.startsWith("at://")) {
|
|
475
|
-
const parsed = parseAtUri(site);
|
|
476
|
-
return parsed ? Effect3.succeed(parsed.did) : Effect3.fail(new FeedFetchError({
|
|
477
|
-
message: `Malformed at:// site reference: ${site}`
|
|
478
|
-
}));
|
|
479
|
-
}
|
|
480
|
-
if (site.startsWith("https://")) {
|
|
481
|
-
const { hostname } = new URL(site);
|
|
482
|
-
return getJson(Schema.Struct({
|
|
483
|
-
did: Schema.optional(Schema.String)
|
|
484
|
-
}), `https://${hostname}/.well-known/atproto-did`, proxy).pipe(Effect3.flatMap((result) => result.did ? Effect3.succeed(result.did) : Effect3.fail(new FeedFetchError({
|
|
485
|
-
message: `No atproto DID found at ${hostname}/.well-known/atproto-did`
|
|
486
|
-
}))));
|
|
487
|
-
}
|
|
488
|
-
return Effect3.fail(new FeedFetchError({
|
|
489
|
-
message: `Cannot resolve DID from site reference: ${site}`
|
|
490
|
-
}));
|
|
491
|
-
};
|
|
492
|
-
var resolveDid = (actor, proxy) => actor.startsWith("did:") ? Effect3.succeed(actor) : getJson(ResolveHandleResponse, endpoints.resolveHandle(actor), proxy).pipe(Effect3.flatMap((resolved) => resolved.did ? Effect3.succeed(resolved.did) : Effect3.fail(new FeedFetchError({
|
|
493
|
-
message: `Could not resolve handle to DID: ${actor}`
|
|
494
|
-
}))));
|
|
495
|
-
var resolvePds = (did, proxy) => {
|
|
496
|
-
if (did.startsWith("did:plc:")) {
|
|
497
|
-
return getJson(DidDocument, endpoints.plcDoc(did), proxy).pipe(Effect3.flatMap((doc) => extractPds(doc, did)));
|
|
498
|
-
}
|
|
499
|
-
if (did.startsWith("did:web:")) {
|
|
500
|
-
const [host, ...segments] = did.slice("did:web:".length).split(":").map((segment) => decodeURIComponent(segment));
|
|
501
|
-
if (!host) {
|
|
502
|
-
return Effect3.fail(new FeedFetchError({
|
|
503
|
-
message: `Invalid did:web identifier: ${did}`
|
|
504
|
-
}));
|
|
505
|
-
}
|
|
506
|
-
const path = segments.length > 0 ? `/${segments.join("/")}/did.json` : "/.well-known/did.json";
|
|
507
|
-
return getJson(DidDocument, `https://${host}${path}`, proxy).pipe(Effect3.flatMap((doc) => extractPds(doc, did)));
|
|
508
|
-
}
|
|
509
|
-
return Effect3.fail(new FeedFetchError({
|
|
510
|
-
message: `Unsupported DID method: ${did}`
|
|
511
|
-
}));
|
|
512
|
-
};
|
|
513
|
-
var extractPds = (doc, did) => {
|
|
514
|
-
const service = doc.service?.find((entry) => entry.id === "#atproto_pds" || entry.type === "AtprotoPersonalDataServer");
|
|
515
|
-
const endpoint = service?.serviceEndpoint;
|
|
516
|
-
return typeof endpoint === "string" && endpoint.length > 0 ? Effect3.succeed(endpoint.replace(/\/$/, "")) : Effect3.fail(new FeedFetchError({
|
|
517
|
-
message: `No PDS endpoint found for DID: ${did}`
|
|
518
|
-
}));
|
|
519
|
-
};
|
|
520
|
-
var listDocuments = (pds, did, proxy) => Effect3.gen(function* () {
|
|
521
|
-
const all = [];
|
|
522
|
-
let cursor;
|
|
523
|
-
do {
|
|
524
|
-
const url = endpoints.listRecords(pds, did, DOCUMENT_COLLECTION, 100) + (cursor ? `&cursor=${encodeURIComponent(cursor)}` : "");
|
|
525
|
-
const page = yield* getJson(ListRecordsResponse, url, proxy);
|
|
526
|
-
all.push(...page.records ?? []);
|
|
527
|
-
cursor = page.cursor;
|
|
528
|
-
} while (cursor);
|
|
529
|
-
return all;
|
|
530
|
-
});
|
|
531
|
-
var fetchProfile = (actor, proxy) => getJson(Profile, endpoints.getProfile(actor), proxy).pipe(Effect3.catchAll(() => Effect3.succeed(void 0)));
|
|
532
|
-
var resolvePublication = (site, proxy) => {
|
|
533
|
-
if (site.startsWith("http")) {
|
|
534
|
-
return Effect3.succeed({
|
|
535
|
-
site,
|
|
536
|
-
url: site.replace(/\/$/, "")
|
|
537
|
-
});
|
|
538
|
-
}
|
|
539
|
-
if (site.startsWith("at://")) {
|
|
540
|
-
const parsed = parseAtUri(site);
|
|
541
|
-
if (!parsed) {
|
|
542
|
-
return Effect3.succeed({
|
|
543
|
-
site
|
|
544
|
-
});
|
|
545
|
-
}
|
|
546
|
-
return Effect3.gen(function* () {
|
|
547
|
-
const pds = yield* resolvePds(parsed.did, proxy);
|
|
548
|
-
const record = yield* getJson(PublicationRecord, endpoints.getRecord(pds, parsed.did, parsed.collection, parsed.rkey), proxy);
|
|
549
|
-
const value = record.value ?? {};
|
|
550
|
-
return {
|
|
551
|
-
site,
|
|
552
|
-
url: value.url ? value.url.replace(/\/$/, "") : void 0,
|
|
553
|
-
name: value.name
|
|
554
|
-
};
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
return Effect3.succeed({
|
|
558
|
-
site
|
|
559
|
-
});
|
|
560
|
-
};
|
|
561
|
-
var parseAtUri = (uri) => {
|
|
562
|
-
const match = uri.match(/^at:\/\/([^/]+)\/([^/]+)\/([^/]+)$/);
|
|
563
|
-
return match ? {
|
|
564
|
-
did: match[1],
|
|
565
|
-
collection: match[2],
|
|
566
|
-
rkey: match[3]
|
|
567
|
-
} : void 0;
|
|
568
|
-
};
|
|
569
|
-
var joinUrl = (base, path) => {
|
|
570
|
-
if (!base) {
|
|
571
|
-
return void 0;
|
|
572
|
-
}
|
|
573
|
-
if (!path) {
|
|
574
|
-
return base;
|
|
575
|
-
}
|
|
576
|
-
return `${base}${path.startsWith("/") ? "" : "/"}${path}`;
|
|
577
|
-
};
|
|
578
|
-
var isString = (value) => typeof value === "string";
|
|
579
|
-
var distinct = (values) => [
|
|
580
|
-
...new Set(values)
|
|
581
|
-
];
|
|
582
|
-
|
|
583
|
-
export {
|
|
584
|
-
browserCorsProxy,
|
|
585
|
-
fetchArticle,
|
|
586
|
-
fetchRss,
|
|
587
|
-
listStandardSitePublications,
|
|
588
|
-
searchStandardSiteHandles,
|
|
589
|
-
fetchStandardSite
|
|
590
|
-
};
|
|
591
|
-
//# sourceMappingURL=chunk-AFPBWBTK.mjs.map
|