@dxos/plugin-magazine 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/LICENSE +105 -0
  2. package/PLUGIN.mdl +653 -0
  3. package/dist/lib/neutral/FeedArticle-PEWCFFSP.mjs +90 -0
  4. package/dist/lib/neutral/FeedArticle-PEWCFFSP.mjs.map +7 -0
  5. package/dist/lib/neutral/FeedProperties-EIO7IZOA.mjs +97 -0
  6. package/dist/lib/neutral/FeedProperties-EIO7IZOA.mjs.map +7 -0
  7. package/dist/lib/neutral/MagazineArticle-DEUTR23F.mjs +325 -0
  8. package/dist/lib/neutral/MagazineArticle-DEUTR23F.mjs.map +7 -0
  9. package/dist/lib/neutral/MagazinePlugin.mjs +62 -0
  10. package/dist/lib/neutral/MagazinePlugin.mjs.map +7 -0
  11. package/dist/lib/neutral/MagazinePlugin.workerd.mjs +12 -0
  12. package/dist/lib/neutral/MagazinePlugin.workerd.mjs.map +7 -0
  13. package/dist/lib/neutral/PostArticle-RERHXPXC.mjs +230 -0
  14. package/dist/lib/neutral/PostArticle-RERHXPXC.mjs.map +7 -0
  15. package/dist/lib/neutral/PostCard-VDGN7BBA.mjs +60 -0
  16. package/dist/lib/neutral/PostCard-VDGN7BBA.mjs.map +7 -0
  17. package/dist/lib/neutral/app-graph-builder-JDPRBVHL.mjs +121 -0
  18. package/dist/lib/neutral/app-graph-builder-JDPRBVHL.mjs.map +7 -0
  19. package/dist/lib/neutral/capabilities/index.mjs +21 -0
  20. package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
  21. package/dist/lib/neutral/chunk-3K4AQKBZ.mjs +12 -0
  22. package/dist/lib/neutral/chunk-3K4AQKBZ.mjs.map +7 -0
  23. package/dist/lib/neutral/chunk-AFPBWBTK.mjs +591 -0
  24. package/dist/lib/neutral/chunk-AFPBWBTK.mjs.map +7 -0
  25. package/dist/lib/neutral/chunk-APQRTYT3.mjs +57 -0
  26. package/dist/lib/neutral/chunk-APQRTYT3.mjs.map +7 -0
  27. package/dist/lib/neutral/chunk-GU725ZF4.mjs +11 -0
  28. package/dist/lib/neutral/chunk-GU725ZF4.mjs.map +7 -0
  29. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
  30. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +7 -0
  31. package/dist/lib/neutral/chunk-JFPR6OV4.mjs +60 -0
  32. package/dist/lib/neutral/chunk-JFPR6OV4.mjs.map +7 -0
  33. package/dist/lib/neutral/chunk-KTYLUOUG.mjs +36 -0
  34. package/dist/lib/neutral/chunk-KTYLUOUG.mjs.map +7 -0
  35. package/dist/lib/neutral/chunk-MBPX7RPI.mjs +14 -0
  36. package/dist/lib/neutral/chunk-MBPX7RPI.mjs.map +7 -0
  37. package/dist/lib/neutral/chunk-MJ2AY2CK.mjs +8 -0
  38. package/dist/lib/neutral/chunk-MJ2AY2CK.mjs.map +7 -0
  39. package/dist/lib/neutral/chunk-OYCDRSWB.mjs +624 -0
  40. package/dist/lib/neutral/chunk-OYCDRSWB.mjs.map +7 -0
  41. package/dist/lib/neutral/chunk-SAWKLGJU.mjs +28 -0
  42. package/dist/lib/neutral/chunk-SAWKLGJU.mjs.map +7 -0
  43. package/dist/lib/neutral/chunk-XCNCK47N.mjs +15 -0
  44. package/dist/lib/neutral/chunk-XCNCK47N.mjs.map +7 -0
  45. package/dist/lib/neutral/clear-magazine-KNY4OWY4.mjs +59 -0
  46. package/dist/lib/neutral/clear-magazine-KNY4OWY4.mjs.map +7 -0
  47. package/dist/lib/neutral/components/index.mjs +338 -0
  48. package/dist/lib/neutral/components/index.mjs.map +7 -0
  49. package/dist/lib/neutral/containers/index.mjs +17 -0
  50. package/dist/lib/neutral/containers/index.mjs.map +7 -0
  51. package/dist/lib/neutral/create-object-SYZMRR4H.mjs +98 -0
  52. package/dist/lib/neutral/create-object-SYZMRR4H.mjs.map +7 -0
  53. package/dist/lib/neutral/curate-magazine-MA6OLK2X.mjs +184 -0
  54. package/dist/lib/neutral/curate-magazine-MA6OLK2X.mjs.map +7 -0
  55. package/dist/lib/neutral/fetch-article-content-CZO6D3QD.mjs +31 -0
  56. package/dist/lib/neutral/fetch-article-content-CZO6D3QD.mjs.map +7 -0
  57. package/dist/lib/neutral/index.mjs +18 -0
  58. package/dist/lib/neutral/index.mjs.map +7 -0
  59. package/dist/lib/neutral/load-post-content-XGL6VFF6.mjs +65 -0
  60. package/dist/lib/neutral/load-post-content-XGL6VFF6.mjs.map +7 -0
  61. package/dist/lib/neutral/meta.json +1 -0
  62. package/dist/lib/neutral/meta.mjs +8 -0
  63. package/dist/lib/neutral/meta.mjs.map +7 -0
  64. package/dist/lib/neutral/navigation-resolver-IN4OMCDR.mjs +18 -0
  65. package/dist/lib/neutral/navigation-resolver-IN4OMCDR.mjs.map +7 -0
  66. package/dist/lib/neutral/operation-handler-JE3743BU.mjs +8 -0
  67. package/dist/lib/neutral/operation-handler-JE3743BU.mjs.map +7 -0
  68. package/dist/lib/neutral/operations/index.mjs +8 -0
  69. package/dist/lib/neutral/operations/index.mjs.map +7 -0
  70. package/dist/lib/neutral/plugin.mjs +16 -0
  71. package/dist/lib/neutral/plugin.mjs.map +7 -0
  72. package/dist/lib/neutral/plugin.workerd.mjs +16 -0
  73. package/dist/lib/neutral/plugin.workerd.mjs.map +7 -0
  74. package/dist/lib/neutral/react-surface-TZESAMG2.mjs +60 -0
  75. package/dist/lib/neutral/react-surface-TZESAMG2.mjs.map +7 -0
  76. package/dist/lib/neutral/routine-templates-A2XTJOZO.mjs +52 -0
  77. package/dist/lib/neutral/routine-templates-A2XTJOZO.mjs.map +7 -0
  78. package/dist/lib/neutral/skill-definition-3KLMUEC5.mjs +8 -0
  79. package/dist/lib/neutral/skill-definition-3KLMUEC5.mjs.map +7 -0
  80. package/dist/lib/neutral/skills/index.mjs +46 -0
  81. package/dist/lib/neutral/skills/index.mjs.map +7 -0
  82. package/dist/lib/neutral/sync-feed-UZX2XHSQ.mjs +99 -0
  83. package/dist/lib/neutral/sync-feed-UZX2XHSQ.mjs.map +7 -0
  84. package/dist/lib/neutral/translations.mjs +81 -0
  85. package/dist/lib/neutral/translations.mjs.map +7 -0
  86. package/dist/lib/neutral/types/index.mjs +14 -0
  87. package/dist/lib/neutral/types/index.mjs.map +7 -0
  88. package/dist/types/dx.config.d.ts +28 -0
  89. package/dist/types/dx.config.d.ts.map +1 -0
  90. package/dist/types/src/MagazinePlugin.d.ts +4 -0
  91. package/dist/types/src/MagazinePlugin.d.ts.map +1 -0
  92. package/dist/types/src/MagazinePlugin.test.d.ts +2 -0
  93. package/dist/types/src/MagazinePlugin.test.d.ts.map +1 -0
  94. package/dist/types/src/MagazinePlugin.workerd.d.ts +4 -0
  95. package/dist/types/src/MagazinePlugin.workerd.d.ts.map +1 -0
  96. package/dist/types/src/atoms/atoms.test.d.ts +2 -0
  97. package/dist/types/src/atoms/atoms.test.d.ts.map +1 -0
  98. package/dist/types/src/atoms/index.d.ts +7 -0
  99. package/dist/types/src/atoms/index.d.ts.map +1 -0
  100. package/dist/types/src/atoms/magazine-posts.d.ts +16 -0
  101. package/dist/types/src/atoms/magazine-posts.d.ts.map +1 -0
  102. package/dist/types/src/atoms/post-content.d.ts +7 -0
  103. package/dist/types/src/atoms/post-content.d.ts.map +1 -0
  104. package/dist/types/src/atoms/post-curation.d.ts +16 -0
  105. package/dist/types/src/atoms/post-curation.d.ts.map +1 -0
  106. package/dist/types/src/atoms/post-display.d.ts +22 -0
  107. package/dist/types/src/atoms/post-display.d.ts.map +1 -0
  108. package/dist/types/src/atoms/post-read.d.ts +14 -0
  109. package/dist/types/src/atoms/post-read.d.ts.map +1 -0
  110. package/dist/types/src/atoms/post-tags.d.ts +16 -0
  111. package/dist/types/src/atoms/post-tags.d.ts.map +1 -0
  112. package/dist/types/src/capabilities/app-graph-builder.d.ts +5 -0
  113. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  114. package/dist/types/src/capabilities/create-object.d.ts +5 -0
  115. package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
  116. package/dist/types/src/capabilities/index.d.ts +10 -0
  117. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  118. package/dist/types/src/capabilities/navigation-resolver.d.ts +5 -0
  119. package/dist/types/src/capabilities/navigation-resolver.d.ts.map +1 -0
  120. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  121. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  122. package/dist/types/src/capabilities/react-surface.d.ts +5 -0
  123. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  124. package/dist/types/src/capabilities/routine-templates.d.ts +5 -0
  125. package/dist/types/src/capabilities/routine-templates.d.ts.map +1 -0
  126. package/dist/types/src/capabilities/skill-definition.d.ts +5 -0
  127. package/dist/types/src/capabilities/skill-definition.d.ts.map +1 -0
  128. package/dist/types/src/components/PostContent/PostContent.d.ts +30 -0
  129. package/dist/types/src/components/PostContent/PostContent.d.ts.map +1 -0
  130. package/dist/types/src/components/PostContent/PostContent.test.d.ts +2 -0
  131. package/dist/types/src/components/PostContent/PostContent.test.d.ts.map +1 -0
  132. package/dist/types/src/components/PostContent/index.d.ts +2 -0
  133. package/dist/types/src/components/PostContent/index.d.ts.map +1 -0
  134. package/dist/types/src/components/PostStack/PostStack.d.ts +17 -0
  135. package/dist/types/src/components/PostStack/PostStack.d.ts.map +1 -0
  136. package/dist/types/src/components/PostStack/PostStack.stories.d.ts +10 -0
  137. package/dist/types/src/components/PostStack/PostStack.stories.d.ts.map +1 -0
  138. package/dist/types/src/components/PostStack/index.d.ts +2 -0
  139. package/dist/types/src/components/PostStack/index.d.ts.map +1 -0
  140. package/dist/types/src/components/SubscriptionStack/SubscriptionStack.d.ts +23 -0
  141. package/dist/types/src/components/SubscriptionStack/SubscriptionStack.d.ts.map +1 -0
  142. package/dist/types/src/components/SubscriptionStack/SubscriptionStack.stories.d.ts +8 -0
  143. package/dist/types/src/components/SubscriptionStack/SubscriptionStack.stories.d.ts.map +1 -0
  144. package/dist/types/src/components/SubscriptionStack/index.d.ts +2 -0
  145. package/dist/types/src/components/SubscriptionStack/index.d.ts.map +1 -0
  146. package/dist/types/src/components/index.d.ts +4 -0
  147. package/dist/types/src/components/index.d.ts.map +1 -0
  148. package/dist/types/src/containers/FeedArticle/FeedArticle.d.ts +6 -0
  149. package/dist/types/src/containers/FeedArticle/FeedArticle.d.ts.map +1 -0
  150. package/dist/types/src/containers/FeedArticle/FeedArticle.stories.d.ts +12 -0
  151. package/dist/types/src/containers/FeedArticle/FeedArticle.stories.d.ts.map +1 -0
  152. package/dist/types/src/containers/FeedArticle/FeedToolbar.d.ts +10 -0
  153. package/dist/types/src/containers/FeedArticle/FeedToolbar.d.ts.map +1 -0
  154. package/dist/types/src/containers/FeedArticle/index.d.ts +2 -0
  155. package/dist/types/src/containers/FeedArticle/index.d.ts.map +1 -0
  156. package/dist/types/src/containers/FeedProperties/FeedProperties.d.ts +6 -0
  157. package/dist/types/src/containers/FeedProperties/FeedProperties.d.ts.map +1 -0
  158. package/dist/types/src/containers/FeedProperties/index.d.ts +2 -0
  159. package/dist/types/src/containers/FeedProperties/index.d.ts.map +1 -0
  160. package/dist/types/src/containers/MagazineArticle/MagazineArticle.d.ts +6 -0
  161. package/dist/types/src/containers/MagazineArticle/MagazineArticle.d.ts.map +1 -0
  162. package/dist/types/src/containers/MagazineArticle/MagazineArticle.stories.d.ts +9 -0
  163. package/dist/types/src/containers/MagazineArticle/MagazineArticle.stories.d.ts.map +1 -0
  164. package/dist/types/src/containers/MagazineArticle/MagazineTile.d.ts +11 -0
  165. package/dist/types/src/containers/MagazineArticle/MagazineTile.d.ts.map +1 -0
  166. package/dist/types/src/containers/MagazineArticle/index.d.ts +2 -0
  167. package/dist/types/src/containers/MagazineArticle/index.d.ts.map +1 -0
  168. package/dist/types/src/containers/MagazineArticle/useToolbar.d.ts +18 -0
  169. package/dist/types/src/containers/MagazineArticle/useToolbar.d.ts.map +1 -0
  170. package/dist/types/src/containers/PostArticle/PostArticle.d.ts +6 -0
  171. package/dist/types/src/containers/PostArticle/PostArticle.d.ts.map +1 -0
  172. package/dist/types/src/containers/PostArticle/PostArticle.stories.d.ts +8 -0
  173. package/dist/types/src/containers/PostArticle/PostArticle.stories.d.ts.map +1 -0
  174. package/dist/types/src/containers/PostArticle/PostToolbar.d.ts +19 -0
  175. package/dist/types/src/containers/PostArticle/PostToolbar.d.ts.map +1 -0
  176. package/dist/types/src/containers/PostArticle/index.d.ts +2 -0
  177. package/dist/types/src/containers/PostArticle/index.d.ts.map +1 -0
  178. package/dist/types/src/containers/PostCard/PostCard.d.ts +11 -0
  179. package/dist/types/src/containers/PostCard/PostCard.d.ts.map +1 -0
  180. package/dist/types/src/containers/PostCard/index.d.ts +2 -0
  181. package/dist/types/src/containers/PostCard/index.d.ts.map +1 -0
  182. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.d.ts +5 -0
  183. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.d.ts.map +1 -0
  184. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.d.ts +8 -0
  185. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.d.ts.map +1 -0
  186. package/dist/types/src/containers/SubscriptionsArticle/index.d.ts +2 -0
  187. package/dist/types/src/containers/SubscriptionsArticle/index.d.ts.map +1 -0
  188. package/dist/types/src/containers/index.d.ts +7 -0
  189. package/dist/types/src/containers/index.d.ts.map +1 -0
  190. package/dist/types/src/index.d.ts +3 -0
  191. package/dist/types/src/index.d.ts.map +1 -0
  192. package/dist/types/src/meta.d.ts +33 -0
  193. package/dist/types/src/meta.d.ts.map +1 -0
  194. package/dist/types/src/operations/clear-magazine.d.ts +10 -0
  195. package/dist/types/src/operations/clear-magazine.d.ts.map +1 -0
  196. package/dist/types/src/operations/curate-magazine.d.ts +25 -0
  197. package/dist/types/src/operations/curate-magazine.d.ts.map +1 -0
  198. package/dist/types/src/operations/curate-magazine.skill.test.d.ts +2 -0
  199. package/dist/types/src/operations/curate-magazine.skill.test.d.ts.map +1 -0
  200. package/dist/types/src/operations/curate-magazine.test.d.ts +2 -0
  201. package/dist/types/src/operations/curate-magazine.test.d.ts.map +1 -0
  202. package/dist/types/src/operations/extraction/article.d.ts +37 -0
  203. package/dist/types/src/operations/extraction/article.d.ts.map +1 -0
  204. package/dist/types/src/operations/extraction/article.test.d.ts +2 -0
  205. package/dist/types/src/operations/extraction/article.test.d.ts.map +1 -0
  206. package/dist/types/src/operations/extraction/index.d.ts +2 -0
  207. package/dist/types/src/operations/extraction/index.d.ts.map +1 -0
  208. package/dist/types/src/operations/fetch-article-content.d.ts +5 -0
  209. package/dist/types/src/operations/fetch-article-content.d.ts.map +1 -0
  210. package/dist/types/src/operations/index.d.ts +3 -0
  211. package/dist/types/src/operations/index.d.ts.map +1 -0
  212. package/dist/types/src/operations/load-post-content.d.ts +8 -0
  213. package/dist/types/src/operations/load-post-content.d.ts.map +1 -0
  214. package/dist/types/src/operations/sources/article.d.ts +24 -0
  215. package/dist/types/src/operations/sources/article.d.ts.map +1 -0
  216. package/dist/types/src/operations/sources/cors.d.ts +12 -0
  217. package/dist/types/src/operations/sources/cors.d.ts.map +1 -0
  218. package/dist/types/src/operations/sources/feed-fetcher.d.ts +22 -0
  219. package/dist/types/src/operations/sources/feed-fetcher.d.ts.map +1 -0
  220. package/dist/types/src/operations/sources/feed-fetcher.test.d.ts +2 -0
  221. package/dist/types/src/operations/sources/feed-fetcher.test.d.ts.map +1 -0
  222. package/dist/types/src/operations/sources/http.d.ts +9 -0
  223. package/dist/types/src/operations/sources/http.d.ts.map +1 -0
  224. package/dist/types/src/operations/sources/index.d.ts +6 -0
  225. package/dist/types/src/operations/sources/index.d.ts.map +1 -0
  226. package/dist/types/src/operations/sources/rss.d.ts +4 -0
  227. package/dist/types/src/operations/sources/rss.d.ts.map +1 -0
  228. package/dist/types/src/operations/sources/rss.test.d.ts +2 -0
  229. package/dist/types/src/operations/sources/rss.test.d.ts.map +1 -0
  230. package/dist/types/src/operations/sources/standard-site.d.ts +33 -0
  231. package/dist/types/src/operations/sources/standard-site.d.ts.map +1 -0
  232. package/dist/types/src/operations/sync-feed.d.ts +5 -0
  233. package/dist/types/src/operations/sync-feed.d.ts.map +1 -0
  234. package/dist/types/src/operations/sync-feed.test.d.ts +2 -0
  235. package/dist/types/src/operations/sync-feed.test.d.ts.map +1 -0
  236. package/dist/types/src/operations/util.d.ts +25 -0
  237. package/dist/types/src/operations/util.d.ts.map +1 -0
  238. package/dist/types/src/operations/util.test.d.ts +2 -0
  239. package/dist/types/src/operations/util.test.d.ts.map +1 -0
  240. package/dist/types/src/paths.d.ts +3 -0
  241. package/dist/types/src/paths.d.ts.map +1 -0
  242. package/dist/types/src/plugin.d.ts +4 -0
  243. package/dist/types/src/plugin.d.ts.map +1 -0
  244. package/dist/types/src/plugin.workerd.d.ts +3 -0
  245. package/dist/types/src/plugin.workerd.d.ts.map +1 -0
  246. package/dist/types/src/skills/index.d.ts +2 -0
  247. package/dist/types/src/skills/index.d.ts.map +1 -0
  248. package/dist/types/src/skills/magazine-skill.d.ts +4 -0
  249. package/dist/types/src/skills/magazine-skill.d.ts.map +1 -0
  250. package/dist/types/src/stories/ArticleExtractor.stories.d.ts +267 -0
  251. package/dist/types/src/stories/ArticleExtractor.stories.d.ts.map +1 -0
  252. package/dist/types/src/stories/MagazineCurate.stories.d.ts +32 -0
  253. package/dist/types/src/stories/MagazineCurate.stories.d.ts.map +1 -0
  254. package/dist/types/src/stories/theregister-fixture.test.d.ts +2 -0
  255. package/dist/types/src/stories/theregister-fixture.test.d.ts.map +1 -0
  256. package/dist/types/src/templates/magazine-curation.d.ts +7 -0
  257. package/dist/types/src/templates/magazine-curation.d.ts.map +1 -0
  258. package/dist/types/src/testing/builder.d.ts +28 -0
  259. package/dist/types/src/testing/builder.d.ts.map +1 -0
  260. package/dist/types/src/testing/index.d.ts +2 -0
  261. package/dist/types/src/testing/index.d.ts.map +1 -0
  262. package/dist/types/src/translations.d.ts +247 -0
  263. package/dist/types/src/translations.d.ts.map +1 -0
  264. package/dist/types/src/types/CreateSubscription.d.ts +29 -0
  265. package/dist/types/src/types/CreateSubscription.d.ts.map +1 -0
  266. package/dist/types/src/types/FeedOperation.d.ts +52 -0
  267. package/dist/types/src/types/FeedOperation.d.ts.map +1 -0
  268. package/dist/types/src/types/Magazine.d.ts +87 -0
  269. package/dist/types/src/types/Magazine.d.ts.map +1 -0
  270. package/dist/types/src/types/Magazine.test.d.ts +2 -0
  271. package/dist/types/src/types/Magazine.test.d.ts.map +1 -0
  272. package/dist/types/src/types/Subscription.d.ts +144 -0
  273. package/dist/types/src/types/Subscription.d.ts.map +1 -0
  274. package/dist/types/src/types/Subscription.test.d.ts +2 -0
  275. package/dist/types/src/types/Subscription.test.d.ts.map +1 -0
  276. package/dist/types/src/types/index.d.ts +5 -0
  277. package/dist/types/src/types/index.d.ts.map +1 -0
  278. package/dist/types/src/util/date.d.ts +8 -0
  279. package/dist/types/src/util/date.d.ts.map +1 -0
  280. package/dist/types/src/util/index.d.ts +4 -0
  281. package/dist/types/src/util/index.d.ts.map +1 -0
  282. package/dist/types/src/util/post-content.d.ts +14 -0
  283. package/dist/types/src/util/post-content.d.ts.map +1 -0
  284. package/dist/types/src/util/text.d.ts +18 -0
  285. package/dist/types/src/util/text.d.ts.map +1 -0
  286. package/dist/types/tsconfig.tsbuildinfo +1 -0
  287. package/dx.config.ts +48 -0
  288. package/package.json +164 -0
  289. package/src/MagazinePlugin.test.ts +36 -0
  290. package/src/MagazinePlugin.tsx +61 -0
  291. package/src/MagazinePlugin.workerd.ts +31 -0
  292. package/src/atoms/atoms.test.ts +323 -0
  293. package/src/atoms/index.ts +10 -0
  294. package/src/atoms/magazine-posts.ts +70 -0
  295. package/src/atoms/post-content.ts +34 -0
  296. package/src/atoms/post-curation.ts +36 -0
  297. package/src/atoms/post-display.ts +59 -0
  298. package/src/atoms/post-read.ts +40 -0
  299. package/src/atoms/post-tags.ts +66 -0
  300. package/src/capabilities/app-graph-builder.ts +125 -0
  301. package/src/capabilities/create-object.ts +127 -0
  302. package/src/capabilities/index.ts +17 -0
  303. package/src/capabilities/navigation-resolver.ts +21 -0
  304. package/src/capabilities/operation-handler.ts +16 -0
  305. package/src/capabilities/react-surface.tsx +53 -0
  306. package/src/capabilities/routine-templates.ts +16 -0
  307. package/src/capabilities/skill-definition.ts +14 -0
  308. package/src/components/PostContent/PostContent.test.ts +81 -0
  309. package/src/components/PostContent/PostContent.tsx +111 -0
  310. package/src/components/PostContent/index.ts +5 -0
  311. package/src/components/PostStack/PostStack.stories.tsx +39 -0
  312. package/src/components/PostStack/PostStack.tsx +151 -0
  313. package/src/components/PostStack/index.ts +5 -0
  314. package/src/components/SubscriptionStack/SubscriptionStack.stories.tsx +52 -0
  315. package/src/components/SubscriptionStack/SubscriptionStack.tsx +161 -0
  316. package/src/components/SubscriptionStack/index.ts +5 -0
  317. package/src/components/index.ts +7 -0
  318. package/src/containers/FeedArticle/FeedArticle.stories.tsx +102 -0
  319. package/src/containers/FeedArticle/FeedArticle.tsx +68 -0
  320. package/src/containers/FeedArticle/FeedToolbar.tsx +47 -0
  321. package/src/containers/FeedArticle/index.ts +5 -0
  322. package/src/containers/FeedProperties/FeedProperties.tsx +107 -0
  323. package/src/containers/FeedProperties/index.ts +5 -0
  324. package/src/containers/MagazineArticle/MagazineArticle.stories.tsx +244 -0
  325. package/src/containers/MagazineArticle/MagazineArticle.tsx +146 -0
  326. package/src/containers/MagazineArticle/MagazineTile.tsx +88 -0
  327. package/src/containers/MagazineArticle/index.ts +5 -0
  328. package/src/containers/MagazineArticle/useToolbar.tsx +145 -0
  329. package/src/containers/PostArticle/PostArticle.stories.tsx +117 -0
  330. package/src/containers/PostArticle/PostArticle.tsx +140 -0
  331. package/src/containers/PostArticle/PostToolbar.tsx +120 -0
  332. package/src/containers/PostArticle/index.ts +5 -0
  333. package/src/containers/PostCard/PostCard.tsx +70 -0
  334. package/src/containers/PostCard/index.ts +5 -0
  335. package/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.tsx +80 -0
  336. package/src/containers/SubscriptionsArticle/SubscriptionsArticle.tsx +99 -0
  337. package/src/containers/SubscriptionsArticle/index.ts +5 -0
  338. package/src/containers/index.ts +11 -0
  339. package/src/index.ts +6 -0
  340. package/src/meta.ts +9 -0
  341. package/src/operations/clear-magazine.ts +83 -0
  342. package/src/operations/curate-magazine.skill.conversations.json +1 -0
  343. package/src/operations/curate-magazine.skill.test.ts +167 -0
  344. package/src/operations/curate-magazine.test.ts +91 -0
  345. package/src/operations/curate-magazine.ts +178 -0
  346. package/src/operations/extraction/article.test.ts +154 -0
  347. package/src/operations/extraction/article.ts +270 -0
  348. package/src/operations/extraction/index.ts +5 -0
  349. package/src/operations/fetch-article-content.ts +27 -0
  350. package/src/operations/index.ts +13 -0
  351. package/src/operations/load-post-content.ts +76 -0
  352. package/src/operations/sources/article.ts +122 -0
  353. package/src/operations/sources/cors.ts +19 -0
  354. package/src/operations/sources/feed-fetcher.test.ts +200 -0
  355. package/src/operations/sources/feed-fetcher.ts +26 -0
  356. package/src/operations/sources/http.ts +42 -0
  357. package/src/operations/sources/index.ts +9 -0
  358. package/src/operations/sources/rss.test.ts +201 -0
  359. package/src/operations/sources/rss.ts +138 -0
  360. package/src/operations/sources/standard-site.ts +381 -0
  361. package/src/operations/sources/testing/feed.xml +477 -0
  362. package/src/operations/sync-feed.test.ts +146 -0
  363. package/src/operations/sync-feed.ts +140 -0
  364. package/src/operations/util.test.ts +67 -0
  365. package/src/operations/util.ts +65 -0
  366. package/src/paths.ts +14 -0
  367. package/src/plugin.ts +11 -0
  368. package/src/plugin.workerd.ts +6 -0
  369. package/src/skills/index.ts +5 -0
  370. package/src/skills/magazine-skill.ts +45 -0
  371. package/src/stories/ArticleExtractor.stories.tsx +204 -0
  372. package/src/stories/MagazineCurate.stories.tsx +217 -0
  373. package/src/stories/fixtures/theregister-ai.xml +45 -0
  374. package/src/stories/theregister-fixture.test.ts +35 -0
  375. package/src/templates/magazine-curation.ts +47 -0
  376. package/src/testing/builder.ts +77 -0
  377. package/src/testing/index.ts +5 -0
  378. package/src/translations.ts +81 -0
  379. package/src/types/CreateSubscription.ts +61 -0
  380. package/src/types/FeedOperation.ts +134 -0
  381. package/src/types/Magazine.test.ts +69 -0
  382. package/src/types/Magazine.ts +214 -0
  383. package/src/types/Subscription.test.ts +171 -0
  384. package/src/types/Subscription.ts +366 -0
  385. package/src/types/index.ts +8 -0
  386. package/src/util/date.ts +27 -0
  387. package/src/util/index.ts +7 -0
  388. package/src/util/post-content.ts +19 -0
  389. package/src/util/text.ts +98 -0
  390. package/src/vite-env.d.ts +10 -0
@@ -0,0 +1,591 @@
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