@aiquants/markdown 6.0.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -5
- package/dist/{abnfDiagram-VRR7QNED-D7Rp9EaV.js → abnfDiagram-VRR7QNED-0ow9i3L-.js} +3 -3
- package/dist/{abnfDiagram-VRR7QNED-KTGT9TWM.cjs → abnfDiagram-VRR7QNED-DRNsVB-u.cjs} +1 -1
- package/dist/{arc-D5T_urCC.cjs → arc-BWR9_qMf.cjs} +1 -1
- package/dist/{arc-DzZml7Bc.js → arc-Bh12k776.js} +1 -1
- package/dist/{architectureDiagram-ZJ3FMSHR-DLrGYTYy.js → architectureDiagram-ZJ3FMSHR-CsFXQcxx.js} +2 -2
- package/dist/{architectureDiagram-ZJ3FMSHR-BOo3y9aD.cjs → architectureDiagram-ZJ3FMSHR-DtrqDlxV.cjs} +1 -1
- package/dist/{blockDiagram-677ZJIJ3-DnjCjo0a.cjs → blockDiagram-677ZJIJ3-CoZEeE0C.cjs} +1 -1
- package/dist/{blockDiagram-677ZJIJ3-B60l5Fpl.js → blockDiagram-677ZJIJ3-CqQ43viF.js} +3 -3
- package/dist/{c4Diagram-LMCZKHZV-bd8fWQ1F.cjs → c4Diagram-LMCZKHZV-DGA2gxp-.cjs} +1 -1
- package/dist/{c4Diagram-LMCZKHZV-BmbplKCu.js → c4Diagram-LMCZKHZV-QPgNg4El.js} +2 -2
- package/dist/{channel-DJ_PyD9w.cjs → channel-Jkgg7NV4.cjs} +1 -1
- package/dist/{channel-B3oXm84X.js → channel-PnA15jK3.js} +1 -1
- package/dist/{chunk-2Q5K7J3B-CWLCO342.cjs → chunk-2Q5K7J3B-1iQ5h7FK.cjs} +1 -1
- package/dist/{chunk-2Q5K7J3B-C0hbxO3D.js → chunk-2Q5K7J3B-DOWfHP5s.js} +1 -1
- package/dist/{chunk-32BRIVSS-DUWtkDEY.js → chunk-32BRIVSS-94iTIA-u.js} +1 -1
- package/dist/{chunk-32BRIVSS-Cb9nTxqN.cjs → chunk-32BRIVSS-XUAL4SUU.cjs} +1 -1
- package/dist/{chunk-5VM5RSS4-DHA5n_Ls.cjs → chunk-5VM5RSS4-CKgpuXOS.cjs} +1 -1
- package/dist/{chunk-5VM5RSS4-C3mSh-gE.js → chunk-5VM5RSS4-OANQKmQE.js} +1 -1
- package/dist/{chunk-EX3LRPZG-DCF1zjtT.js → chunk-EX3LRPZG-BQDQ1MdS.js} +4 -4
- package/dist/{chunk-EX3LRPZG-ByY6_kep.cjs → chunk-EX3LRPZG-BrRRbskW.cjs} +1 -1
- package/dist/{chunk-JWPE2WC7-CUBzYD4G.cjs → chunk-JWPE2WC7-Bz9dXsLZ.cjs} +1 -1
- package/dist/{chunk-JWPE2WC7-CPLOunIL.js → chunk-JWPE2WC7-Djg6Qi23.js} +1 -1
- package/dist/{chunk-MOJQB5TN-CmOhW6SK.js → chunk-MOJQB5TN-1pZNp2Wl.js} +1 -1
- package/dist/{chunk-MOJQB5TN-P8-yb3-j.cjs → chunk-MOJQB5TN-DUk2Jy4_.cjs} +1 -1
- package/dist/{chunk-PUDLZKDR-pKdIELvz.cjs → chunk-PUDLZKDR-CVedetzB.cjs} +1 -1
- package/dist/{chunk-PUDLZKDR-DH7B7ZTK.js → chunk-PUDLZKDR-G5JYyEiR.js} +6 -6
- package/dist/{chunk-RYQCIY6F-C7ytn_QX.js → chunk-RYQCIY6F-Crmt36sO.js} +1 -1
- package/dist/{chunk-RYQCIY6F-DcvQCEoc.cjs → chunk-RYQCIY6F-D0y50t5B.cjs} +1 -1
- package/dist/{chunk-V7JOEXUC-BgLcssUF.js → chunk-V7JOEXUC-BNo-X7NC.js} +5 -5
- package/dist/{chunk-V7JOEXUC-CtXgqODy.cjs → chunk-V7JOEXUC-DXSQM1ea.cjs} +1 -1
- package/dist/{chunk-VR4S4FIN-BK6xeIQk.js → chunk-VR4S4FIN-BGGITgpQ.js} +1 -1
- package/dist/{chunk-VR4S4FIN-Cc4GDi2Z.cjs → chunk-VR4S4FIN-Bc567umS.cjs} +1 -1
- package/dist/{chunk-XXDRQBXY-D1OixGzR.cjs → chunk-XXDRQBXY-DOuLpiJ4.cjs} +1 -1
- package/dist/{chunk-XXDRQBXY-COtZ25Ez.js → chunk-XXDRQBXY-Drnpl-KK.js} +1 -1
- package/dist/{classDiagram-v2-EOCWNBFH-Jc-IwOm0.js → classDiagram-OUVF2IWQ-Cneye7qT.js} +2 -2
- package/dist/{classDiagram-OUVF2IWQ-DDLmqaG6.cjs → classDiagram-OUVF2IWQ-mmjBEYmN.cjs} +1 -1
- package/dist/{classDiagram-OUVF2IWQ-Jc-IwOm0.js → classDiagram-v2-EOCWNBFH-Cneye7qT.js} +2 -2
- package/dist/{classDiagram-v2-EOCWNBFH-DDLmqaG6.cjs → classDiagram-v2-EOCWNBFH-mmjBEYmN.cjs} +1 -1
- package/dist/components/embeds/LinkCard.d.ts +14 -3
- package/dist/{cose-bilkent-JH36ORCC-DaucPocG.js → cose-bilkent-JH36ORCC-BQWfGE1G.js} +1 -1
- package/dist/{cose-bilkent-JH36ORCC-OwiXHdQY.cjs → cose-bilkent-JH36ORCC-BaEdcRlX.cjs} +1 -1
- package/dist/{cynefinDiagram-TSTJHNR4-Dkmz7gDw.js → cynefinDiagram-TSTJHNR4-CTDDSUz7.js} +2 -2
- package/dist/{cynefinDiagram-TSTJHNR4-Ag-HcuUm.cjs → cynefinDiagram-TSTJHNR4-DPQl09kC.cjs} +1 -1
- package/dist/{dagre-VKFMJZFB-BHGdcjt3.js → dagre-VKFMJZFB-BMRdJgZy.js} +2 -2
- package/dist/{dagre-VKFMJZFB-Q4CcAQ09.cjs → dagre-VKFMJZFB-DZ4E-Szs.cjs} +1 -1
- package/dist/{diagram-FQU43EPY-DBASKnKu.js → diagram-FQU43EPY-CmEpNw5i.js} +2 -2
- package/dist/{diagram-FQU43EPY-jWCrN_AW.cjs → diagram-FQU43EPY-mK9YHIy1.cjs} +1 -1
- package/dist/{diagram-G47NLZAW-B4XMStX7.cjs → diagram-G47NLZAW-BX8Lj_uD.cjs} +1 -1
- package/dist/{diagram-G47NLZAW-BY1mmnYA.js → diagram-G47NLZAW-eJRQFjAg.js} +3 -3
- package/dist/{diagram-NH7WQ7WH-BS1eEa9R.cjs → diagram-NH7WQ7WH-3r1_3TrC.cjs} +1 -1
- package/dist/{diagram-NH7WQ7WH-BXFvYRtm.js → diagram-NH7WQ7WH-BOOj_4-N.js} +2 -2
- package/dist/{diagram-OA4YK3LP-CTaL_2Nc.cjs → diagram-OA4YK3LP-CkDJzLOy.cjs} +1 -1
- package/dist/{diagram-OA4YK3LP-DgGrzezu.js → diagram-OA4YK3LP-DnDIHtcW.js} +3 -3
- package/dist/{diagram-WEI45ONY-BHxWKH3v.js → diagram-WEI45ONY-BHpuPTt-.js} +2 -2
- package/dist/{diagram-WEI45ONY-DX7BGSMI.cjs → diagram-WEI45ONY-BpCCo_Ty.cjs} +1 -1
- package/dist/{ebnfDiagram-CCIWWBDH-BUK_anpV.js → ebnfDiagram-CCIWWBDH-BDLB-AVF.js} +3 -3
- package/dist/{ebnfDiagram-CCIWWBDH-BpDmVVJY.cjs → ebnfDiagram-CCIWWBDH-CfdalXdM.cjs} +1 -1
- package/dist/embeds/linkCards.d.ts +32 -0
- package/dist/embeds.cjs +1 -1
- package/dist/embeds.d.ts +1 -1
- package/dist/embeds.js +53 -74
- package/dist/{erDiagram-Q63AITRT-Cd9H9BtP.cjs → erDiagram-Q63AITRT-CviOyQsx.cjs} +1 -1
- package/dist/{erDiagram-Q63AITRT-Qb2bmkNp.js → erDiagram-Q63AITRT-DZlcgZfp.js} +4 -4
- package/dist/{extractHeadings-B2pUyEPa.js → extractHeadings-CtiYkq2z.js} +3955 -3990
- package/dist/extractHeadings-D1A8WzVy.cjs +311 -0
- package/dist/flowDiagram-23GEKE2U-C_FW0q38.js +7 -0
- package/dist/flowDiagram-23GEKE2U-Cb0U58EU.cjs +1 -0
- package/dist/{ganttDiagram-NO4QXBWP-C6-ExcDz.cjs → ganttDiagram-NO4QXBWP-CJa-hKPU.cjs} +1 -1
- package/dist/{ganttDiagram-NO4QXBWP-BVISsrzr.js → ganttDiagram-NO4QXBWP-DO0HAbYg.js} +2 -2
- package/dist/{gitGraphDiagram-IHSO6WYX-BDVA2TFP.js → gitGraphDiagram-IHSO6WYX-CXStgPQs.js} +3 -3
- package/dist/{gitGraphDiagram-IHSO6WYX-DLzPc702.cjs → gitGraphDiagram-IHSO6WYX-CXcPHbkt.cjs} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.client.cjs +1 -1
- package/dist/index.client.js +1 -1
- package/dist/index.js +1 -1
- package/dist/index.server.cjs +1 -1
- package/dist/index.server.d.ts +1 -0
- package/dist/index.server.js +598 -151
- package/dist/{infoDiagram-FWYZ7A6U-DMF_wb2h.cjs → infoDiagram-FWYZ7A6U-BByoHihL.cjs} +1 -1
- package/dist/{infoDiagram-FWYZ7A6U-D31UwqjR.js → infoDiagram-FWYZ7A6U-K0__ySEG.js} +1 -1
- package/dist/{ishikawaDiagram-FXEZZL3T-XA6-gyHY.js → ishikawaDiagram-FXEZZL3T-C8QlwQP1.js} +1 -1
- package/dist/{ishikawaDiagram-FXEZZL3T-DUlnwraq.cjs → ishikawaDiagram-FXEZZL3T-DZOMdeTI.cjs} +1 -1
- package/dist/{journeyDiagram-5HDEW3XC-B8sfsWpu.js → journeyDiagram-5HDEW3XC-CZ9PFNNN.js} +4 -4
- package/dist/{journeyDiagram-5HDEW3XC-CwQyFcYa.cjs → journeyDiagram-5HDEW3XC-RvC77rKo.cjs} +1 -1
- package/dist/{kanban-definition-HUTT4EX6-BjPlt2-E.cjs → kanban-definition-HUTT4EX6-BL1jihGl.cjs} +1 -1
- package/dist/{kanban-definition-HUTT4EX6-FTrTBare.js → kanban-definition-HUTT4EX6-Q12F4vHx.js} +2 -2
- package/dist/{linear-DI9P_z72.js → linear-LWjATjog.js} +1 -1
- package/dist/{linear-D3AJM3sY.cjs → linear-lDvPoqlB.cjs} +1 -1
- package/dist/linkCardServer/addressGuard.server.d.ts +25 -0
- package/dist/linkCardServer/htmlEncoding.server.d.ts +6 -0
- package/dist/linkCardServer/linkCardHandler.server.d.ts +7 -0
- package/dist/linkCardServer/metadataCache.server.d.ts +5 -0
- package/dist/linkCardServer/pageFetch.server.d.ts +37 -0
- package/dist/linkCardServer/pageMetadata.server.d.ts +11 -0
- package/dist/linkCards-1JxY8wdm.js +48 -0
- package/dist/linkCards-Bjd_vW39.cjs +1 -0
- package/dist/markdown.css +1 -1
- package/dist/{mindmap-definition-LN4V7U3C-YW4YcL9x.js → mindmap-definition-LN4V7U3C-CM1XvwJX.js} +3 -3
- package/dist/{mindmap-definition-LN4V7U3C-CxgWZidl.cjs → mindmap-definition-LN4V7U3C-TVYKONRm.cjs} +1 -1
- package/dist/{pegDiagram-2B236MQR-sJjLKeF3.js → pegDiagram-2B236MQR-Dlrnikqd.js} +3 -3
- package/dist/{pegDiagram-2B236MQR-CUo7q5bl.cjs → pegDiagram-2B236MQR-a9Up0ERY.cjs} +1 -1
- package/dist/{pieDiagram-ENE6RG2P-Cy_sUuLQ.cjs → pieDiagram-ENE6RG2P-ClakmSma.cjs} +1 -1
- package/dist/{pieDiagram-ENE6RG2P-D4VanIOv.js → pieDiagram-ENE6RG2P-WYrEJp8U.js} +3 -3
- package/dist/{quadrantDiagram-ABIIQ3AL-ubxphjb_.js → quadrantDiagram-ABIIQ3AL-BkgMVDaX.js} +2 -2
- package/dist/{quadrantDiagram-ABIIQ3AL-D3c8xLpt.cjs → quadrantDiagram-ABIIQ3AL-Cb01YcqR.cjs} +1 -1
- package/dist/{railroadDiagram-RFXS5EU6-_Q4W5hB-.cjs → railroadDiagram-RFXS5EU6-Bob4WSMz.cjs} +1 -1
- package/dist/{railroadDiagram-RFXS5EU6-DvpD4C_A.js → railroadDiagram-RFXS5EU6-RfCtZGUR.js} +3 -3
- package/dist/{requirementDiagram-TGXJPOKE-DdYIO-wU.cjs → requirementDiagram-TGXJPOKE-BP5h9mCj.cjs} +1 -1
- package/dist/{requirementDiagram-TGXJPOKE-Dk_6BuX9.js → requirementDiagram-TGXJPOKE-C1yJPMp1.js} +3 -3
- package/dist/{sankeyDiagram-HTMAVEWB-s3Kd7T8n.js → sankeyDiagram-HTMAVEWB-D5G9Dcmr.js} +1 -1
- package/dist/{sankeyDiagram-HTMAVEWB-zuYg6LTg.cjs → sankeyDiagram-HTMAVEWB-shq9WK4t.cjs} +1 -1
- package/dist/{sequenceDiagram-DBY2YBRQ-YQic4wxL.js → sequenceDiagram-DBY2YBRQ-8EJMQxiB.js} +3 -3
- package/dist/{sequenceDiagram-DBY2YBRQ-BvNPCevg.cjs → sequenceDiagram-DBY2YBRQ-BRxcK5-5.cjs} +1 -1
- package/dist/simple-logger-9yf7ypyB.cjs +1 -0
- package/dist/simple-logger-DwH1YQvq.js +103 -0
- package/dist/{sizeCapture-X5ZJPWSS-BqrdzzsI.cjs → sizeCapture-X5ZJPWSS-BtBRJO2R.cjs} +1 -1
- package/dist/{sizeCapture-X5ZJPWSS-qMsWGfjy.js → sizeCapture-X5ZJPWSS-DJG85IuR.js} +1 -1
- package/dist/{stateDiagram-2N3HPSRC-D1Ub8LYq.js → stateDiagram-2N3HPSRC-CAd-NU-f.js} +2 -2
- package/dist/{stateDiagram-2N3HPSRC-Ds8f-scd.cjs → stateDiagram-2N3HPSRC-Czgkv_ey.cjs} +1 -1
- package/dist/{stateDiagram-v2-6OUMAXLB-PmrsPXuZ.cjs → stateDiagram-v2-6OUMAXLB-BNP5Lx0Y.cjs} +1 -1
- package/dist/{stateDiagram-v2-6OUMAXLB-DW8wjtk3.js → stateDiagram-v2-6OUMAXLB-x_Zps-d5.js} +2 -2
- package/dist/styles/markdown.css +1 -1
- package/dist/{swimlanes-5IMT3BWC-jZhcesRT.cjs → swimlanes-5IMT3BWC-CfdkDd3q.cjs} +1 -1
- package/dist/{swimlanes-5IMT3BWC-C8P8vU0w.js → swimlanes-5IMT3BWC-D8brzzxb.js} +3 -3
- package/dist/{swimlanesDiagram-G3AALYLV-B9FKeJRf.js → swimlanesDiagram-G3AALYLV-Bc9-lR2e.js} +2 -2
- package/dist/{swimlanesDiagram-G3AALYLV-M5Cg2MHU.cjs → swimlanesDiagram-G3AALYLV-dvJpSdGV.cjs} +1 -1
- package/dist/{timeline-definition-FHXFAJF6-DZm1-KlQ.cjs → timeline-definition-FHXFAJF6-BSqACati.cjs} +1 -1
- package/dist/{timeline-definition-FHXFAJF6-Ch-He--D.js → timeline-definition-FHXFAJF6-CKW3NJOF.js} +2 -2
- package/dist/utils/simple-logger.d.ts +1 -0
- package/dist/{vennDiagram-L72KCM5P-mUSI238J.cjs → vennDiagram-L72KCM5P-ChKxsFyJ.cjs} +1 -1
- package/dist/{vennDiagram-L72KCM5P-CaoPscCM.js → vennDiagram-L72KCM5P-vPmq984y.js} +1 -1
- package/dist/{wardleyDiagram-EHGQE667-CSAqF366.js → wardleyDiagram-EHGQE667-CwN9zwBX.js} +2 -2
- package/dist/{wardleyDiagram-EHGQE667-CkKP97H-.cjs → wardleyDiagram-EHGQE667-CxzlR7km.cjs} +1 -1
- package/dist/{xychartDiagram-FW5EYKEG-OEsTD_k4.js → xychartDiagram-FW5EYKEG-DBSKTLuc.js} +2 -2
- package/dist/{xychartDiagram-FW5EYKEG-BivGpkVk.cjs → xychartDiagram-FW5EYKEG-wJqYRInm.cjs} +1 -1
- package/package.json +11 -8
- package/dist/extractHeadings-DgefF9l1.cjs +0 -311
- package/dist/flowDiagram-23GEKE2U-BOmNlv7X.cjs +0 -1
- package/dist/flowDiagram-23GEKE2U-DMZnRz-6.js +0 -7
package/README.md
CHANGED
|
@@ -204,12 +204,12 @@ Every renderer of the package — `MarkdownRenderer` (and so `MarkdownViewer`) f
|
|
|
204
204
|
|
|
205
205
|
### Embeds
|
|
206
206
|
|
|
207
|
-
Embeds are opt in. `MarkdownRenderer` and `MarkdownViewer` take `embeds={{ providers, linkCardEndpoint }}` (type `MarkdownEmbeds` from `@aiquants/markdown/embeds`); the default `NO_EMBEDS` renders every link alone in a paragraph as that paragraph. Pass the value from a module constant (the viewer also compares it by value). An unknown provider id
|
|
207
|
+
Embeds are opt in. `MarkdownRenderer` and `MarkdownViewer` take `embeds={{ providers, linkCardEndpoint, linkCardSize }}` (type `MarkdownEmbeds` from `@aiquants/markdown/embeds`; `linkCardSize` is optional); the default `NO_EMBEDS` renders every link alone in a paragraph as that paragraph. Pass the value from a module constant (the viewer also compares it by value). An unknown provider id, a bad endpoint or an unknown card size throws a `RangeError` at render.
|
|
208
208
|
|
|
209
209
|
```tsx
|
|
210
210
|
import type { MarkdownEmbeds } from "@aiquants/markdown/embeds"
|
|
211
211
|
|
|
212
|
-
const EMBEDS: MarkdownEmbeds = { providers: ["youtube", "x", "instagram", "bluesky"], linkCardEndpoint: "/api/
|
|
212
|
+
const EMBEDS: MarkdownEmbeds = { providers: ["youtube", "x", "instagram", "bluesky"], linkCardEndpoint: "/api/link-card", linkCardSize: "banner" }
|
|
213
213
|
|
|
214
214
|
<MarkdownViewer {...props} embeds={EMBEDS} iFrameAllowedDomains={["www.youtube.com"]} />
|
|
215
215
|
```
|
|
@@ -242,13 +242,27 @@ The server HTML holds the link and a reserved box (`width: 100%` up to the provi
|
|
|
242
242
|
Frames that report their height (X, Instagram, Threads, Bluesky, Reddit, note) are sized through one `message` listener that accepts only the frame's own window from its exact provider origin.
|
|
243
243
|
|
|
244
244
|
**Link cards.** A card asks `GET <linkCardEndpoint>?url=<href>` (same-origin credentials, `redirect: "error"`) once an IntersectionObserver rooted at the viewer's scroller sees it, through a page-wide queue (two requests at once, 256 answers kept, aborted when no card needs the answer).
|
|
245
|
-
It links to the written `href` (never `og:url`), takes the host name from the `href`, and shows the image and the icon only when the endpoint gives absolute `http(s)` URLs that are not on the page's own host, whatever the scheme or port (a browser loads an `http:` image of an `https:` page over `https:`, and cookies ignore the port), with no referrer. The package asks no favicon service.
|
|
245
|
+
It links to the written `href` (never `og:url`), takes the host name from the `href`, and shows the image and the icon only when the endpoint gives absolute `http(s)` URLs of at most 2048 characters (`LINK_CARD_URL_LIMIT`) that are not on the page's own host, whatever the scheme or port (a browser loads an `http:` image of an `https:` page over `https:`, and cookies ignore the port), with no referrer. The package asks no favicon service.
|
|
246
|
+
|
|
247
|
+
`linkCardSize` picks the size of every card:
|
|
248
|
+
|
|
249
|
+
| `linkCardSize` | The card |
|
|
250
|
+
| --- | --- |
|
|
251
|
+
| `"banner"` (default) | Image, title (two lines), description (one line) and `site · host`, 7.5rem tall, as wide as the column up to 37.5rem (600px) and left-aligned. The image is 1.91:1 from a card width of 32rem, square from 22rem, hidden below. |
|
|
252
|
+
| `"full"` | Image, title and description (two lines each) and `site · host`, 8.5rem tall, across the column. The image is 1.91:1 from 40rem, square from 22rem, hidden below. |
|
|
253
|
+
| `"compact"` | The favicon (or a neutral link icon), the title on one line and `site · host`, 3.75rem tall, as wide as its text up to 37.5rem. No image and no description. |
|
|
254
|
+
|
|
255
|
+
A pending card has the height of the chosen size, so an answer never shifts the page. A link the endpoint gives no card (a `204 No Content` with a reason, below) becomes a compact card whatever the size: a leading icon — a building for `private-network`, a globe otherwise — then the host name and the URL, marked `data-link-card="compact"` and `data-link-card-reason="<reason>"`. It may shrink a pending banner or full card; Chromium's scroll anchoring keeps the visible content in place when that happens above the viewport. An error answer renders the paragraph.
|
|
256
|
+
Every link that gets no full card writes one `console.info` line naming the link and the reason, for example `[markdown] No link card for <href> (private-network)`; an error answer names its cause instead — `HTTP <status>` for another status, `HTTP 204 without a known skip reason` for a 204 whose `X-Link-Card-Skip` is missing or unknown, `HTTP 200, not JSON` or `HTTP 200, not a JSON object` for a 200 that is not a JSON object, `network error` for a failed request — and a card that unmounts before its answer writes nothing.
|
|
257
|
+
The card's look — light and dark (`data-theme`), hover, keyboard focus ring — comes from `styles/markdown.css`, outside every cascade layer, so the GitHub and Zenn display styles cannot override it; every size shares that one frame.
|
|
246
258
|
|
|
247
259
|
The endpoint contract:
|
|
248
260
|
|
|
249
261
|
- `GET <endpoint>?url=<href>` answers JSON `{ title?, description?, site_name?, image?, icon? }`; other fields (`url` included) are ignored.
|
|
262
|
+
- A link that gets no card is answered `204 No Content` with the reason in `X-Link-Card-Skip` (`LINK_CARD_SKIP_HEADER`): `private-network`, `forbidden-url`, `unreachable` or `not-html` (`LINK_CARD_SKIP_REASONS`, read with `linkCardSkipReasonOf`). A 204 without one of them is an error answer.
|
|
250
263
|
- It must not set cookies or refresh credentials: the request runs in the background and can be in flight during a sign-out.
|
|
251
|
-
- A redirect,
|
|
264
|
+
- A redirect, any other non-OK status or a non-JSON answer is an error answer: no card, the paragraph.
|
|
265
|
+
- `createLinkCardHandler` from `@aiquants/markdown/server` implements this contract (see [Link-card endpoint](#link-card-endpoint)).
|
|
252
266
|
|
|
253
267
|
**Iframes written in documents.** `iFrameAllowedDomains` lists the hostnames such an iframe may load from: the `src` must be `https:`, without a user name, a password or an explicit port, and its hostname must match an entry exactly. Every other iframe is removed (fail closed), including an iframe without `src` (`srcdoc`). An allowed iframe is rendered from validated values and keeps only `title`, `width`, `height`, `allow`, `allowfullscreen`, `sandbox`, `referrerpolicy`, `loading`, `frameborder` and `scrolling` (no `id` or `class`).
|
|
254
268
|
An iframe without a `title` gets `"<embeddedFrame>: <host>"` (for example `Embedded content: www.youtube.com`), marked with the built-in label's language.
|
|
@@ -258,12 +272,81 @@ An iframe plugin (`data-plugin-type="dify"`) receives the validated iframe as st
|
|
|
258
272
|
|
|
259
273
|
**Labels.** `embedLabels` (`embeddedVideo`, `embeddedPost`, `embeddedFrame`; built-in "embedded video", "embedded post", "Embedded content", in `DEFAULT_MARKDOWN_EMBED_LABELS`) name the frames; `MarkdownViewer` takes the same keys in `labels`.
|
|
260
274
|
|
|
261
|
-
**DOM hooks.** `figure[data-embed-provider][data-embed-state="pending|frame"]` with its box `[data-embed-box]`, the width probe `[data-embed-measure]`, `span[data-embed-frame]` for iframes written in documents, and `a[data-link-card="pending|ready"]
|
|
275
|
+
**DOM hooks.** `figure[data-embed-provider][data-embed-state="pending|frame"]` with its box `[data-embed-box]`, the width probe `[data-embed-measure]`, `span[data-embed-frame]` for iframes written in documents, and `a[data-link-card="pending|ready|compact"][data-link-card-size="compact|banner|full"]` (a compact card of a skipped link also carries `data-link-card-reason`).
|
|
262
276
|
|
|
263
277
|
**Content Security Policy.** Put `embedFrameHostsOf(embeds.providers)` and the hosts of `iFrameAllowedDomains` in `frame-src`, `embedConnectOriginsOf(embeds.providers)` in `connect-src` (Bluesky handles), and allow `https:` images in `img-src` for card images and icons. Provider frames may open popups that escape their sandbox, so a host that enables providers should send `Cross-Origin-Opener-Policy: same-origin`.
|
|
264
278
|
|
|
265
279
|
`@aiquants/markdown/embeds` holds the placeholder contract, the frame policy, the provider registry and the card contract without React, for host sanitizers, configuration and CSP. `@aiquants/markdown/embeds/testing` holds captured provider messages and `embedProviderStubPage(url)` for offline end-to-end tests.
|
|
266
280
|
|
|
281
|
+
### Link-card endpoint
|
|
282
|
+
|
|
283
|
+
`createLinkCardHandler(options)` from `@aiquants/markdown/server` (Node only) is the card endpoint as a standard handler, `(request: Request) => Promise<Response>`. It reads only the request's method and its `url` search parameter, never its path, so mount it on any path and pass that path as `embeds.linkCardEndpoint`. Create it once, at module scope: each handler owns its cache and its connection pool. It uses `undici` and `htmlparser2`, which no client entry loads (`@aiquants/markdown/embeds` stays free of React and Node).
|
|
284
|
+
|
|
285
|
+
A React Router resource route (`app/routes/api.link-card.ts`, for example):
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
import { createLinkCardHandler } from "@aiquants/markdown/server"
|
|
289
|
+
import type { LoaderFunctionArgs } from "react-router"
|
|
290
|
+
import { readSignedInReader } from "~/session.server" // the host's read-only session lookup
|
|
291
|
+
|
|
292
|
+
const linkCards = createLinkCardHandler({ authorize: async (request) => (await readSignedInReader(request)) !== undefined })
|
|
293
|
+
|
|
294
|
+
export const loader = ({ request }: LoaderFunctionArgs) => linkCards(request)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Any server whose handlers take a `Request` and return a `Response`:
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
import { createLinkCardHandler } from "@aiquants/markdown/server"
|
|
301
|
+
|
|
302
|
+
const linkCards = createLinkCardHandler({ authorize: () => true }) // a public site: every reader may ask
|
|
303
|
+
|
|
304
|
+
export const handle = (request: Request): Promise<Response> =>
|
|
305
|
+
new URL(request.url).pathname === "/api/link-card" ? linkCards(request) : Promise.resolve(new Response(null, { status: 404 }))
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
The handler can also be called from inside another loader, for example a data route that dispatches several operations: it answers the request it is given.
|
|
309
|
+
|
|
310
|
+
**Options.** `authorize: (request) => boolean | Promise<boolean>` is the only option, and it is required. Anything but `true` answers 401 before anything is fetched; a host that serves everyone passes `() => true`. It must only read the request — no cookie writes, no token refresh — because cards ask in the background and a request can still be in flight while the reader signs out. A rejection propagates to the host. `createLinkCardHandler` throws a `TypeError` when `authorize` is not a function and for any other option.
|
|
311
|
+
|
|
312
|
+
**Answers.** Every answer carries `X-Content-Type-Options: nosniff` and never `Set-Cookie`; a `HEAD` answer has the `GET` answer's status and headers and no body.
|
|
313
|
+
|
|
314
|
+
| Request | Status | Body | `Cache-Control` |
|
|
315
|
+
| --- | --- | --- | --- |
|
|
316
|
+
| A method other than `GET` and `HEAD` | 405 (with `Allow: GET, HEAD`) | `{"error":"Method Not Allowed"}` | `no-store` |
|
|
317
|
+
| `authorize` does not return `true` | 401 | `{"error":"Unauthorized"}` | `no-store` |
|
|
318
|
+
| No or an empty `url` | 400 | `{"error":"Missing 'url' parameter"}` | `no-store` |
|
|
319
|
+
| A link that gets no card | 204 (with `X-Link-Card-Skip: <reason>`) | none | per reason, below |
|
|
320
|
+
| An unexpected exception | 500 | `{"error":"Internal Server Error"}` | `no-store` |
|
|
321
|
+
| A card | 200 | `{ title?, description?, site_name?, image?, icon? }` (`LinkCardResponseBody`) | `private, max-age=1800` |
|
|
322
|
+
|
|
323
|
+
The JSON answers are `application/json; charset=utf-8`. The reasons of a 204:
|
|
324
|
+
|
|
325
|
+
| Reason | When | `Cache-Control` |
|
|
326
|
+
| --- | --- | --- |
|
|
327
|
+
| `private-network` | The host is internal by name or by IP literal, it resolves to or connects to a private or special-use address, or a redirect leads to such a host | `private, max-age=1800` |
|
|
328
|
+
| `forbidden-url` | The URL or a redirect target is not `http(s)`, carries a user name or password, or does not parse | `private, max-age=1800` |
|
|
329
|
+
| `unreachable` | A network error, a timeout, a non-OK answer of the linked site, too many redirects or an unparsable `Location` | `private, max-age=300` |
|
|
330
|
+
| `not-html` | The page's `Content-Type` is missing or not HTML | `private, max-age=300` |
|
|
331
|
+
|
|
332
|
+
**Internal addresses never become cards**, in any environment; there is no switch. Internal is decided by address, never by the company's domain:
|
|
333
|
+
|
|
334
|
+
- a loopback, private, link-local, CGNAT, multicast, documentation, benchmarking, discard-only or reserved IPv4 or IPv6 address (every IANA special-purpose range that is not globally reachable) written as the host, in every form the URL parser normalizes (`2130706433`, `0x7f.1`, `127.1`, `[::ffff:127.0.0.1]`, and the NAT64, 6to4, Teredo and IPv4-translated forms);
|
|
335
|
+
- an internal name: `localhost`, `*.localhost`, a single-label name, one without a dot (the server's DNS search list would complete it to an internal name), and names under `.local`, `.internal` and `.home.arpa`, with or without a trailing dot;
|
|
336
|
+
- a name that resolves to an internal address: every connection resolves through a lookup that refuses a name when any of its A or AAAA answers is private, and a `net.BlockList` (honoured by `net.connect` from Node 22.13, which `engines` requires) checks the very address connected to — for `https` too, whose TLS handshake runs over a TCP socket opened with the block list — so DNS rebinding cannot slip past;
|
|
337
|
+
- every redirect hop, checked again before it is followed.
|
|
338
|
+
|
|
339
|
+
**What the card shows.** The title is the last `og:title`, falling back to the first `<title>` of the document's head when that `og:title` is blank; the description is the last `og:description` or `<meta name="description">`; the site name the last `og:site_name`; the image the last `og:image`; the icon the first `<link rel>` holding the token `icon` (no `/favicon.ico` is guessed). A later blank `<meta>` clears an earlier one.
|
|
340
|
+
Only the head is read: parsing stops at the first body content, skips the content of a `<noscript>`, `<template>` or `<noframes>` in the head as a browser with scripting does, and stops at an element nesting deeper than 256, after 4096 start tags and at a tag with more than 64 attributes, so a hostile page costs time and memory linear in the bytes read. Text is trimmed and cut at the card's limits (title 300, description 1000, site name 200 code points), so `linkCardMetadataOf` reads every body back unchanged.
|
|
341
|
+
The image and the icon are resolved against the first `<base href>` — itself resolved against the page's URL, as a browser does, and used when it is `http(s)` and at most 2048 characters — else against the page's URL after redirects, and kept only when they are at most 2048 characters (`LINK_CARD_URL_LIMIT`) and the URL check accepts them.
|
|
342
|
+
Only `text/html` and `application/xhtml+xml` answers are read, decoded by WHATWG encoding sniffing: a byte order mark, then the `charset` of `Content-Type`, then a `<meta charset>` or `<meta http-equiv="Content-Type">` in the first 1024 bytes, else UTF-8 (Shift_JIS, EUC-JP, ISO-2022-JP and every other label `TextDecoder` knows; an unknown label is ignored).
|
|
343
|
+
|
|
344
|
+
**Limits.** 5 s per page for the headers, the body and its parsing; 5 redirects, each followed by hand and checked again; 64 KiB of response headers; at most the first 8 MiB of the body, read as a stream and parsed as it arrives, yielding to the event loop between chunks, and the download stops once the head has been read.
|
|
345
|
+
DNS goes through c-ares, never through `getaddrinfo` on libuv's threadpool, so a name whose DNS never answers holds none of the threads the host's `fs`, `zlib` and `crypto` share: A and AAAA queries to the DNS servers of the system's resolver configuration (the hosts file is not read), 1 s for the first attempt and 2 attempts per server; a name connects over IPv4 when it has an A record, else over IPv6.
|
|
346
|
+
Each handler caches cards per URL for 1 hour and skips as long as their `Cache-Control`, 1000 URLs at most; the key is the URL as the URL parser serializes it without its fragment, so spellings of one URL share one entry, and concurrent requests for one URL share one fetch.
|
|
347
|
+
|
|
348
|
+
**Logs.** The handler logs through the package's logger, never with a URL's user name or password (a refused URL that is not `http(s)` is logged by its scheme alone): policy refusals (`private-network`, `forbidden-url`) at info, network errors, unparsable `Location`s, too many redirects and unexpected exceptions at error, and a body cut at the size limit at warn.
|
|
349
|
+
|
|
267
350
|
### Links
|
|
268
351
|
|
|
269
352
|
- A link is external when its `href` names a scheme in any case (`https:`, `HTTPS:`, `mailto:`) or another host (`//host/…`, `/\host/…`), whatever its `data-link-kind` says, and when `data-link-kind` is `external`. An external link opens in a new tab with `rel="noreferrer"` and is never handed to `linkComponent`. The author's `target` and `rel` never survive.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { g as p, r as u, d as a } from "./chunk-MOJQB5TN-
|
|
2
|
-
import { p as f } from "./chunk-JWPE2WC7-
|
|
3
|
-
import { _ as n, O as o } from "./extractHeadings-
|
|
1
|
+
import { g as p, r as u, d as a } from "./chunk-MOJQB5TN-1pZNp2Wl.js";
|
|
2
|
+
import { p as f } from "./chunk-JWPE2WC7-Djg6Qi23.js";
|
|
3
|
+
import { _ as n, O as o } from "./extractHeadings-CtiYkq2z.js";
|
|
4
4
|
import { M as c, b as d } from "./cynefin-VYW2F7L2-Bkk-F_Js.js";
|
|
5
5
|
var v = d().RailroadAbnf.parser.LangiumParser, i = /* @__PURE__ */ n((e) => {
|
|
6
6
|
const r = e.alternatives.map(g);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./chunk-MOJQB5TN-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./chunk-MOJQB5TN-DUk2Jy4_.cjs"),u=require("./chunk-JWPE2WC7-Bz9dXsLZ.cjs"),n=require("./extractHeadings-D1A8WzVy.cjs"),i=require("./cynefin-VYW2F7L2-MpAliYy9.cjs");var p=i.createRailroadAbnfServices().RailroadAbnf.parser.LangiumParser,o=n.__name(e=>{const r=e.alternatives.map(c);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),c=n.__name(e=>{const r=e.elements.map(d);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),f=n.__name(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),d=n.__name(e=>{const r=b(e.primary);if(!e.repeat)return r;const{min:t,max:s}=f(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),b=n.__name(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return o(e.element);case"AbnfOptionalGroup":return{type:"optional",element:o(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),g=n.__name(e=>({name:e.name,definition:o(e.definition)}),"transformRule"),v=n.__name(e=>{u.populateCommonDb(e,a.db),e.title&&a.db.setTitle(e.title),e.rules.map(r=>a.db.addRule(g(r)))},"populateDb"),y={parse:n.__name(e=>{a.db.clear(),n.log.debug("[ABNF Parser] Starting Langium parse");const r=p.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new i.MermaidParseError(r);const t=r.value;n.log.debug("[ABNF Parser] Parsed rules:",t.rules.length),v(t),n.log.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a.db}},_={parser:y,db:a.db,renderer:a.renderer,styles:a.getStyles};exports.diagram=_;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const n=require("./extractHeadings-
|
|
1
|
+
"use strict";const n=require("./extractHeadings-D1A8WzVy.cjs");function $(o){return o.innerRadius}function b(o){return o.outerRadius}function k(o){return o.startAngle}function _(o){return o.endAngle}function nn(o){return o&&o.padAngle}function en(o,x,D,P,h,v,S,s){var E=D-o,r=P-x,e=S-h,p=s-v,i=p*E-e*r;if(!(i*i<n.epsilon))return i=(e*(x-v)-p*(o-h))/i,[o+i*E,x+i*r]}function M(o,x,D,P,h,v,S){var s=o-D,E=x-P,r=(S?v:-v)/n.sqrt(s*s+E*E),e=r*E,p=-r*s,i=o+e,u=x+p,c=D+e,f=P+p,j=(i+c)/2,l=(u+f)/2,y=c-i,g=f-u,A=y*y+g*g,R=h-v,T=i*f-c*u,H=(g<0?-1:1)*n.sqrt(n.max(0,R*R*A-T*T)),I=(T*g-y*H)/A,O=(-T*y-g*H)/A,q=(T*g+y*H)/A,d=(-T*y+g*H)/A,m=I-j,a=O-l,t=q-j,z=d-l;return m*m+a*a>t*t+z*z&&(I=q,O=d),{cx:I,cy:O,x01:-e,y01:-p,x11:I*(h/R-1),y11:O*(h/R-1)}}function an(){var o=$,x=b,D=n.constant(0),P=null,h=k,v=_,S=nn,s=null,E=n.withPath(r);function r(){var e,p,i=+o.apply(this,arguments),u=+x.apply(this,arguments),c=h.apply(this,arguments)-n.halfPi,f=v.apply(this,arguments)-n.halfPi,j=n.abs(f-c),l=f>c;if(s||(s=e=E()),u<i&&(p=u,u=i,i=p),!(u>n.epsilon))s.moveTo(0,0);else if(j>n.tau-n.epsilon)s.moveTo(u*n.cos(c),u*n.sin(c)),s.arc(0,0,u,c,f,!l),i>n.epsilon&&(s.moveTo(i*n.cos(f),i*n.sin(f)),s.arc(0,0,i,f,c,l));else{var y=c,g=f,A=c,R=f,T=j,H=j,I=S.apply(this,arguments)/2,O=I>n.epsilon&&(P?+P.apply(this,arguments):n.sqrt(i*i+u*u)),q=n.min(n.abs(u-i)/2,+D.apply(this,arguments)),d=q,m=q,a,t;if(O>n.epsilon){var z=n.asin(O/i*n.sin(I)),F=n.asin(O/u*n.sin(I));(T-=z*2)>n.epsilon?(z*=l?1:-1,A+=z,R-=z):(T=0,A=R=(c+f)/2),(H-=F*2)>n.epsilon?(F*=l?1:-1,y+=F,g-=F):(H=0,y=g=(c+f)/2)}var B=u*n.cos(y),C=u*n.sin(y),G=i*n.cos(R),J=i*n.sin(R);if(q>n.epsilon){var K=u*n.cos(g),L=u*n.sin(g),N=i*n.cos(A),Q=i*n.sin(A),w;if(j<n.pi)if(w=en(B,C,N,Q,K,L,G,J)){var U=B-w[0],V=C-w[1],W=K-w[0],X=L-w[1],Y=1/n.sin(n.acos((U*W+V*X)/(n.sqrt(U*U+V*V)*n.sqrt(W*W+X*X)))/2),Z=n.sqrt(w[0]*w[0]+w[1]*w[1]);d=n.min(q,(i-Z)/(Y-1)),m=n.min(q,(u-Z)/(Y+1))}else d=m=0}H>n.epsilon?m>n.epsilon?(a=M(N,Q,B,C,u,m,l),t=M(K,L,G,J,u,m,l),s.moveTo(a.cx+a.x01,a.cy+a.y01),m<q?s.arc(a.cx,a.cy,m,n.atan2(a.y01,a.x01),n.atan2(t.y01,t.x01),!l):(s.arc(a.cx,a.cy,m,n.atan2(a.y01,a.x01),n.atan2(a.y11,a.x11),!l),s.arc(0,0,u,n.atan2(a.cy+a.y11,a.cx+a.x11),n.atan2(t.cy+t.y11,t.cx+t.x11),!l),s.arc(t.cx,t.cy,m,n.atan2(t.y11,t.x11),n.atan2(t.y01,t.x01),!l))):(s.moveTo(B,C),s.arc(0,0,u,y,g,!l)):s.moveTo(B,C),!(i>n.epsilon)||!(T>n.epsilon)?s.lineTo(G,J):d>n.epsilon?(a=M(G,J,K,L,i,-d,l),t=M(B,C,N,Q,i,-d,l),s.lineTo(a.cx+a.x01,a.cy+a.y01),d<q?s.arc(a.cx,a.cy,d,n.atan2(a.y01,a.x01),n.atan2(t.y01,t.x01),!l):(s.arc(a.cx,a.cy,d,n.atan2(a.y01,a.x01),n.atan2(a.y11,a.x11),!l),s.arc(0,0,i,n.atan2(a.cy+a.y11,a.cx+a.x11),n.atan2(t.cy+t.y11,t.cx+t.x11),l),s.arc(t.cx,t.cy,d,n.atan2(t.y11,t.x11),n.atan2(t.y01,t.x01),!l))):s.arc(0,0,i,R,A,l)}if(s.closePath(),e)return s=null,e+""||null}return r.centroid=function(){var e=(+o.apply(this,arguments)+ +x.apply(this,arguments))/2,p=(+h.apply(this,arguments)+ +v.apply(this,arguments))/2-n.pi/2;return[n.cos(p)*e,n.sin(p)*e]},r.innerRadius=function(e){return arguments.length?(o=typeof e=="function"?e:n.constant(+e),r):o},r.outerRadius=function(e){return arguments.length?(x=typeof e=="function"?e:n.constant(+e),r):x},r.cornerRadius=function(e){return arguments.length?(D=typeof e=="function"?e:n.constant(+e),r):D},r.padRadius=function(e){return arguments.length?(P=e==null?null:typeof e=="function"?e:n.constant(+e),r):P},r.startAngle=function(e){return arguments.length?(h=typeof e=="function"?e:n.constant(+e),r):h},r.endAngle=function(e){return arguments.length?(v=typeof e=="function"?e:n.constant(+e),r):v},r.padAngle=function(e){return arguments.length?(S=typeof e=="function"?e:n.constant(+e),r):S},r.context=function(e){return arguments.length?(s=e??null,r):s},r}exports.d3arc=an;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { aC as ln, aD as an, aE as y, aF as tn, aG as M, aH as D, aI as _, aJ as un, aK as rn, aL as S, aM as o, aN as H, aO as sn, aP as on, aQ as fn } from "./extractHeadings-
|
|
1
|
+
import { aC as ln, aD as an, aE as y, aF as tn, aG as M, aH as D, aI as _, aJ as un, aK as rn, aL as S, aM as o, aN as H, aO as sn, aP as on, aQ as fn } from "./extractHeadings-CtiYkq2z.js";
|
|
2
2
|
function cn(l) {
|
|
3
3
|
return l.innerRadius;
|
|
4
4
|
}
|
package/dist/{architectureDiagram-ZJ3FMSHR-DLrGYTYy.js → architectureDiagram-ZJ3FMSHR-CsFXQcxx.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { p as Ze } from "./chunk-JWPE2WC7-
|
|
2
|
-
import { bK as qe, _ as gt, ak as Qe, aA as Je, O as Fe, G as Ke, A as je, a5 as _e, a6 as tr, z as er, y as rr, ab as ir, ah as ar, af as nr, ai as or, J as Ee, bD as Te, aW as pe, V as sr, K as hr, aa as lr, aX as fr, bL as cr } from "./extractHeadings-
|
|
1
|
+
import { p as Ze } from "./chunk-JWPE2WC7-Djg6Qi23.js";
|
|
2
|
+
import { bK as qe, _ as gt, ak as Qe, aA as Je, O as Fe, G as Ke, A as je, a5 as _e, a6 as tr, z as er, y as rr, ab as ir, ah as ar, af as nr, ai as or, J as Ee, bD as Te, aW as pe, V as sr, K as hr, aa as lr, aX as fr, bL as cr } from "./extractHeadings-CtiYkq2z.js";
|
|
3
3
|
import { p as gr } from "./cynefin-VYW2F7L2-Bkk-F_Js.js";
|
|
4
4
|
import { c as be } from "./cytoscape.esm-kVAWcYoG.js";
|
|
5
5
|
var he = { exports: {} }, le = { exports: {} }, fe = { exports: {} }, ur = fe.exports, Oe;
|