@immediately-run/sdk 0.50.0 → 0.51.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 (55) hide show
  1. package/dist/generated/protocol.d.cts +1 -0
  2. package/dist/generated/protocol.d.ts +1 -0
  3. package/dist/index.d.cts +3 -6
  4. package/dist/index.d.ts +3 -6
  5. package/dist/linkSpace.cjs +4 -36
  6. package/dist/linkSpace.cjs.map +1 -1
  7. package/dist/linkSpace.d.cts +3 -60
  8. package/dist/linkSpace.d.ts +3 -60
  9. package/dist/linkSpace.js +1 -33
  10. package/dist/linkSpace.js.map +1 -1
  11. package/dist/safeContent/SafeContent.cjs +2 -27
  12. package/dist/safeContent/SafeContent.cjs.map +1 -1
  13. package/dist/safeContent/SafeContent.d.cts +1 -13
  14. package/dist/safeContent/SafeContent.d.ts +1 -13
  15. package/dist/safeContent/SafeContent.js +1 -26
  16. package/dist/safeContent/SafeContent.js.map +1 -1
  17. package/dist/safeContent/index.cjs +3 -23
  18. package/dist/safeContent/index.cjs.map +1 -1
  19. package/dist/safeContent/index.d.cts +1 -6
  20. package/dist/safeContent/index.d.ts +1 -6
  21. package/dist/safeContent/index.js +1 -14
  22. package/dist/safeContent/index.js.map +1 -1
  23. package/dist/safeContent/mdastDeps.cjs +7 -2
  24. package/dist/safeContent/mdastDeps.js +7 -2
  25. package/dist/safeContent/parseSafeMdast.cjs +2 -53
  26. package/dist/safeContent/parseSafeMdast.cjs.map +1 -1
  27. package/dist/safeContent/parseSafeMdast.d.cts +1 -45
  28. package/dist/safeContent/parseSafeMdast.d.ts +1 -45
  29. package/dist/safeContent/parseSafeMdast.js +1 -42
  30. package/dist/safeContent/parseSafeMdast.js.map +1 -1
  31. package/dist/safeContent/renderMdast.cjs +2 -133
  32. package/dist/safeContent/renderMdast.cjs.map +1 -1
  33. package/dist/safeContent/renderMdast.d.cts +1 -27
  34. package/dist/safeContent/renderMdast.d.ts +1 -27
  35. package/dist/safeContent/renderMdast.js +1 -132
  36. package/dist/safeContent/renderMdast.js.map +1 -1
  37. package/dist/safeContent/sanitizeUrl.cjs +2 -12
  38. package/dist/safeContent/sanitizeUrl.cjs.map +1 -1
  39. package/dist/safeContent/sanitizeUrl.d.cts +1 -9
  40. package/dist/safeContent/sanitizeUrl.d.ts +1 -9
  41. package/dist/safeContent/sanitizeUrl.js +1 -11
  42. package/dist/safeContent/sanitizeUrl.js.map +1 -1
  43. package/dist/safeContent/wikilink.cjs +3 -35
  44. package/dist/safeContent/wikilink.cjs.map +1 -1
  45. package/dist/safeContent/wikilink.d.cts +1 -21
  46. package/dist/safeContent/wikilink.d.ts +1 -21
  47. package/dist/safeContent/wikilink.js +1 -33
  48. package/dist/safeContent/wikilink.js.map +1 -1
  49. package/dist/version.cjs +1 -1
  50. package/dist/version.cjs.map +1 -1
  51. package/dist/version.d.cts +1 -1
  52. package/dist/version.d.ts +1 -1
  53. package/dist/version.js +1 -1
  54. package/dist/version.js.map +1 -1
  55. package/package.json +6 -4
@@ -1 +1,2 @@
1
1
  export * from '@immediately-run/sandbox-protocol/sdk';
2
+ import '@immediately-run/safe-content';
@@ -1 +1,2 @@
1
1
  export * from '@immediately-run/sandbox-protocol/sdk';
2
+ import '@immediately-run/safe-content';
package/dist/index.d.cts CHANGED
@@ -5,7 +5,7 @@ export { Include, RenderExportedComponent } from './components/Include.cjs';
5
5
  export { SafeInclude } from './components/SafeInclude.cjs';
6
6
  export { SourceCache, SourceReader, createSourceCache } from './sourceCache.cjs';
7
7
  export { DEFAULT_MDX_COMPONENTS } from './components/MDXComponents.cjs';
8
- export { FS_PREFIX, LinkSpace, LinkSpaceContext, ResolvedLinkTarget, normalizeAbsolute, resolveLinkTarget } from './linkSpace.cjs';
8
+ export { LinkSpaceContext } from './linkSpace.cjs';
9
9
  export { MountImage, MountImageProps } from './components/MountImage.cjs';
10
10
  export { Route, RouteProps, Routes } from './components/Routes.cjs';
11
11
  export { ObjectUrlState, useAllMetadata, useFileMetadata, useMetadataQuery, useObjectUrl } from './hooks.cjs';
@@ -40,12 +40,9 @@ export { LOADING_TIMINGS, LoadingRegion, Skeleton, SkeletonArchetype, SkeletonRo
40
40
  export { StreamError, StreamFrame, StreamTransport, consumeStream, protocolStream } from './protocolStream.cjs';
41
41
  export { ATTENDED_FIRST_FRAME_MS, ATTENDED_TIMEOUT_MS, Attendance, BoundedCallOptions, CallBounds, DeadlineBound, NETWORK_TIMEOUT_MS, PENDING_NOTICE_MS, PendingAttention, PendingState, ProtocolCancelledError, ProtocolTimeoutError, STREAM_IDLE_TIMEOUT_MS, SuspendableDeadline, UNATTENDED_TIMEOUT_MS, attendanceOf, attendanceReason, boundsFor, createSuspendableDeadline, firstFrameBoundsFor, firstFrameTimeoutFor, timeoutFor } from './protocolDeadline.cjs';
42
42
  export { EvaluationContext, FileQueryResult, FilesMetadata, Metadata, MetadataQueryEntry, MetadataQueryFunction, MetadataQueryRecord, MetadataQueryResult, ModuleExports } from './sandboxTypes.cjs';
43
- export { SafeContent, SafeContentProps } from './safeContent/SafeContent.cjs';
44
- export { RenderMdastOptions, SafeContentComponents, renderMdast } from './safeContent/renderMdast.cjs';
45
- export { ParseSafeMdastOptions, SafeMdastNode, SafeMdxAttribute, parseSafeMdast } from './safeContent/parseSafeMdast.cjs';
46
- export { sanitizeUrl } from './safeContent/sanitizeUrl.cjs';
47
- export { WikiLinkToken, WikiPart, parseWikiInner, splitWikiLinks } from './safeContent/wikilink.cjs';
43
+ export * from '@immediately-run/safe-content';
48
44
  export { Admonition, AdmonitionType } from './components/Admonition.cjs';
45
+ export { FS_PREFIX, LinkSpace, ResolvedLinkTarget, normalizeAbsolute, resolveLinkTarget } from '@immediately-run/mdx-plugins';
49
46
  export { GrantRecord, Member, ResolvedUser, Role, SpaceInfo, getSpaceMembers, inviteToSpace, listAllSpaces, listGrants, listSpaces, lookupUser, revokeGrant, setSpaceRole, unshareSpace } from './generated/spaces.cjs';
50
47
  export { HeadingAnchor } from './components/HeadingAnchor.cjs';
51
48
  export { ImmediatelyRunGlobal, getHostRuntime } from './hostRuntime.cjs';
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ export { Include, RenderExportedComponent } from './components/Include.js';
5
5
  export { SafeInclude } from './components/SafeInclude.js';
6
6
  export { SourceCache, SourceReader, createSourceCache } from './sourceCache.js';
7
7
  export { DEFAULT_MDX_COMPONENTS } from './components/MDXComponents.js';
8
- export { FS_PREFIX, LinkSpace, LinkSpaceContext, ResolvedLinkTarget, normalizeAbsolute, resolveLinkTarget } from './linkSpace.js';
8
+ export { LinkSpaceContext } from './linkSpace.js';
9
9
  export { MountImage, MountImageProps } from './components/MountImage.js';
10
10
  export { Route, RouteProps, Routes } from './components/Routes.js';
11
11
  export { ObjectUrlState, useAllMetadata, useFileMetadata, useMetadataQuery, useObjectUrl } from './hooks.js';
@@ -40,12 +40,9 @@ export { LOADING_TIMINGS, LoadingRegion, Skeleton, SkeletonArchetype, SkeletonRo
40
40
  export { StreamError, StreamFrame, StreamTransport, consumeStream, protocolStream } from './protocolStream.js';
41
41
  export { ATTENDED_FIRST_FRAME_MS, ATTENDED_TIMEOUT_MS, Attendance, BoundedCallOptions, CallBounds, DeadlineBound, NETWORK_TIMEOUT_MS, PENDING_NOTICE_MS, PendingAttention, PendingState, ProtocolCancelledError, ProtocolTimeoutError, STREAM_IDLE_TIMEOUT_MS, SuspendableDeadline, UNATTENDED_TIMEOUT_MS, attendanceOf, attendanceReason, boundsFor, createSuspendableDeadline, firstFrameBoundsFor, firstFrameTimeoutFor, timeoutFor } from './protocolDeadline.js';
42
42
  export { EvaluationContext, FileQueryResult, FilesMetadata, Metadata, MetadataQueryEntry, MetadataQueryFunction, MetadataQueryRecord, MetadataQueryResult, ModuleExports } from './sandboxTypes.js';
43
- export { SafeContent, SafeContentProps } from './safeContent/SafeContent.js';
44
- export { RenderMdastOptions, SafeContentComponents, renderMdast } from './safeContent/renderMdast.js';
45
- export { ParseSafeMdastOptions, SafeMdastNode, SafeMdxAttribute, parseSafeMdast } from './safeContent/parseSafeMdast.js';
46
- export { sanitizeUrl } from './safeContent/sanitizeUrl.js';
47
- export { WikiLinkToken, WikiPart, parseWikiInner, splitWikiLinks } from './safeContent/wikilink.js';
43
+ export * from '@immediately-run/safe-content';
48
44
  export { Admonition, AdmonitionType } from './components/Admonition.js';
45
+ export { FS_PREFIX, LinkSpace, ResolvedLinkTarget, normalizeAbsolute, resolveLinkTarget } from '@immediately-run/mdx-plugins';
49
46
  export { GrantRecord, Member, ResolvedUser, Role, SpaceInfo, getSpaceMembers, inviteToSpace, listAllSpaces, listGrants, listSpaces, lookupUser, revokeGrant, setSpaceRole, unshareSpace } from './generated/spaces.js';
50
47
  export { HeadingAnchor } from './components/HeadingAnchor.js';
51
48
  export { ImmediatelyRunGlobal, getHostRuntime } from './hostRuntime.js';
@@ -18,50 +18,18 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var linkSpace_exports = {};
20
20
  __export(linkSpace_exports, {
21
- FS_PREFIX: () => FS_PREFIX,
21
+ FS_PREFIX: () => import_mdx_plugins.FS_PREFIX,
22
22
  LinkSpaceContext: () => LinkSpaceContext,
23
- normalizeAbsolute: () => normalizeAbsolute,
24
- resolveLinkTarget: () => resolveLinkTarget
23
+ normalizeAbsolute: () => import_mdx_plugins.normalizeAbsolute,
24
+ resolveLinkTarget: () => import_mdx_plugins.resolveLinkTarget
25
25
  });
26
26
  module.exports = __toCommonJS(linkSpace_exports);
27
27
  var import_react = require("react");
28
- const FS_PREFIX = "$fs:";
28
+ var import_mdx_plugins = require("@immediately-run/mdx-plugins");
29
29
  const LinkSpaceContext = (0, import_react.createContext)({
30
30
  corpusRoot: null,
31
31
  bundleChrooted: false
32
32
  });
33
- const normalizeAbsolute = (path) => {
34
- const out = [];
35
- for (const seg of path.split("/")) {
36
- if (seg === "" || seg === ".") continue;
37
- if (seg === "..") out.pop();
38
- else out.push(seg);
39
- }
40
- return "/" + out.join("/");
41
- };
42
- function resolveCorpusAbsolute(path, corpusRoot) {
43
- const inner = normalizeAbsolute(path);
44
- if (corpusRoot === null || corpusRoot === "/") return { state: "resolved", path: inner };
45
- return { state: "resolved", path: normalizeAbsolute(corpusRoot + inner) };
46
- }
47
- function resolveLinkTarget(raw, opts = {}) {
48
- if (raw.startsWith(FS_PREFIX)) {
49
- const rest = raw.slice(FS_PREFIX.length);
50
- if (!rest.startsWith("/")) return { state: "invalid" };
51
- if (opts.bundleChrooted) return resolveCorpusAbsolute(rest, opts.corpusRoot ?? null);
52
- return { state: "resolved", path: normalizeAbsolute(rest) };
53
- }
54
- if (raw.startsWith("/")) {
55
- const corpusRoot = opts.corpusRoot ?? null;
56
- if (corpusRoot !== null) {
57
- return resolveCorpusAbsolute(raw, corpusRoot);
58
- }
59
- return { state: "resolved", path: normalizeAbsolute(raw) };
60
- }
61
- if (!opts.currentFile) return { state: "unresolvable" };
62
- const dir = opts.currentFile.slice(0, opts.currentFile.lastIndexOf("/"));
63
- return { state: "resolved", path: normalizeAbsolute(`${dir}/${raw}`) };
64
- }
65
33
  // Annotate the CommonJS export names for ESM import in node:
66
34
  0 && (module.exports = {
67
35
  FS_PREFIX,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/linkSpace.ts"],"sourcesContent":["// Link path spaces (R3-273; REPO_CONTENT_DISPATCH_SPEC §9 decision, 2026-08-17).\n//\n// A document link's target resolves in one of two spaces:\n//\n// - DEFAULT — the enclosing corpus's virtual filesystem. RELATIVE targets resolve\n// against the authoring file (identical in both spaces); ABSOLUTE targets\n// (`/x/y.mdx`) resolve from the corpus root when an enclosing `LinkSpaceContext`\n// declares one, else from the filesystem root. A non-corpus app declares nothing\n// and keeps today's behavior bit-for-bit (its fs root IS its only root).\n//\n// - `$fs:` — the explicit filesystem space: `$fs:/content/x.mdx` resolves from the\n// root of the filesystem the app reads, escaping corpus-relative addressing.\n//\n// `$fs:` changes ADDRESSING, never REACH: resolution is pure path arithmetic and\n// existence is checked against the same in-mount metadata the default space uses —\n// nothing is fetched, and a link can never name what the app cannot already read.\n// A malformed `$fs:` target (anything not mount-absolute — which also catches\n// scheme smuggling like `$fs:javascript:…`) is INVALID and must render as a broken\n// link, never an anchor.\n//\n// Corpus nesting: `LinkSpaceContext` providers nest, and the NEAREST one wins —\n// which is exactly the innermost-enclosing-corpus rule (bundle encapsulation): a\n// document rendered inside a nested corpus resolves against the nested corpus.\n\nimport { createContext } from 'react';\n\nexport const FS_PREFIX = '$fs:';\n\nexport interface LinkSpace {\n /** Absolute filesystem path of the enclosing corpus's root (e.g. `/app/content`),\n * or `null` when the document is not corpus-hosted (default). */\n corpusRoot: string | null;\n /**\n * True when the filesystem this document resolves against is **chroot'd to the\n * bundle** — i.e. the port the app holds was scoped to the bundle's subtree, so\n * the mount root and the bundle root are the same directory\n * (`BUNDLE_LAYERS_SPEC §9`; the `T2`/`T4` wrapper, R3-319 / BL-2).\n *\n * Under that grant `$fs:` **collapses to the scoped root**: `$fs:/p` and `/p`\n * name the same byte, because there is no longer any \"mount-absolute\" space\n * outside the bundle for `$fs:` to reach into. Without this flag the resolver\n * would hand back a mount-absolute path that the chroot then re-roots anyway —\n * a link that renders as valid and resolves somewhere the author did not mean.\n *\n * **This is an invariant to CREATE, not one to inherit** (`BUNDLE_LAYERS_SPEC\n * §11`): the shipped resolver reads `{currentFile, corpusRoot}` and nothing\n * else, so `$fs:` is bundle-anchored only if something says so. It lives here,\n * in the resolver, rather than as a rule each caller applies by passing\n * `corpusRoot: '/'` — an invariant the arithmetic carries cannot be forgotten\n * at one call site out of five.\n */\n bundleChrooted?: boolean;\n}\n\n/** Ambient link space. A corpus-rendering app wraps its document tree in\n * `<LinkSpaceContext value={{ corpusRoot }}>`; nesting a second provider inside a\n * rendered sub-corpus makes the innermost root win. */\nexport const LinkSpaceContext = createContext<LinkSpace>({\n corpusRoot: null,\n bundleChrooted: false,\n});\n\n/** Collapse `.`/`..`/empty segments into a clean absolute path. `..` can never\n * climb above the root — a (virtual) root's parent is itself, which is what keeps\n * both the mount space and the corpus space closed under traversal. */\nexport const normalizeAbsolute = (path: string): string => {\n const out: string[] = [];\n for (const seg of path.split('/')) {\n if (seg === '' || seg === '.') continue;\n if (seg === '..') out.pop();\n else out.push(seg);\n }\n return '/' + out.join('/');\n};\n\nexport type ResolvedLinkTarget =\n /** Resolved to an absolute filesystem path (existence NOT checked here). */\n | { state: 'resolved'; path: string }\n /** A relative target with no known authoring file — the caller may route\n * optimistically (it cannot check existence or self-ness generically). */\n | { state: 'unresolvable' }\n /** A malformed `$fs:` target (not mount-absolute; includes scheme smuggling).\n * Callers MUST render this broken/inert — never as an anchor. */\n | { state: 'invalid' };\n\n/** Anchor a corpus-absolute path at `corpusRoot`, clamping the corpus-relative\n * half FIRST so the virtual corpus space stays closed under traversal. Shared by\n * the `/p` branch and — under a bundle chroot — the `$fs:/p` branch, so the two\n * spellings cannot drift into resolving differently. */\nfunction resolveCorpusAbsolute(path: string, corpusRoot: string | null): ResolvedLinkTarget {\n const inner = normalizeAbsolute(path);\n if (corpusRoot === null || corpusRoot === '/') return { state: 'resolved', path: inner };\n return { state: 'resolved', path: normalizeAbsolute(corpusRoot + inner) };\n}\n\n/**\n * Resolve a raw link target (a wikilink target or an in-app href's path half —\n * fragment already split off) to an absolute filesystem path. THE shared resolver:\n * the default `WikiLink`, the markdown `a` override, and safe-content consumers\n * all route through this one function so the two render pipelines cannot drift.\n */\nexport function resolveLinkTarget(\n raw: string,\n opts: {\n currentFile?: string;\n corpusRoot?: string | null;\n /** See `LinkSpace.bundleChrooted`. Under a bundle-chroot'd grant `$fs:`\n * resolves in the corpus space, because they are the same space. */\n bundleChrooted?: boolean;\n } = {},\n): ResolvedLinkTarget {\n if (raw.startsWith(FS_PREFIX)) {\n const rest = raw.slice(FS_PREFIX.length);\n // Must be mount-absolute. This single rule also fails `$fs:javascript:…`,\n // `$fs:https://…`, and every other smuggled scheme closed.\n if (!rest.startsWith('/')) return { state: 'invalid' };\n // Under a bundle chroot the mount root IS the bundle root, so `$fs:` has\n // nowhere outside to name: it takes the corpus-absolute branch below and the\n // two spellings collapse. `normalizeAbsolute` clamps `..` at the root either\n // way, so neither spelling can climb out — the collapse changes WHERE a\n // `$fs:` link points, never whether it can escape.\n if (opts.bundleChrooted) return resolveCorpusAbsolute(rest, opts.corpusRoot ?? null);\n return { state: 'resolved', path: normalizeAbsolute(rest) };\n }\n if (raw.startsWith('/')) {\n const corpusRoot = opts.corpusRoot ?? null;\n if (corpusRoot !== null) {\n // Clamp the corpus-relative half FIRST (the virtual FS is closed — `/../x`\n // stays inside the corpus), THEN anchor it at the corpus root.\n return resolveCorpusAbsolute(raw, corpusRoot);\n }\n return { state: 'resolved', path: normalizeAbsolute(raw) };\n }\n // Relative: against the authoring file's directory — the same in both spaces.\n if (!opts.currentFile) return { state: 'unresolvable' };\n const dir = opts.currentFile.slice(0, opts.currentFile.lastIndexOf('/'));\n return { state: 'resolved', path: normalizeAbsolute(`${dir}/${raw}`) };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBA,mBAA8B;AAEvB,MAAM,YAAY;AA+BlB,MAAM,uBAAmB,4BAAyB;AAAA,EACvD,YAAY;AAAA,EACZ,gBAAgB;AAClB,CAAC;AAKM,MAAM,oBAAoB,CAAC,SAAyB;AACzD,QAAM,MAAgB,CAAC;AACvB,aAAW,OAAO,KAAK,MAAM,GAAG,GAAG;AACjC,QAAI,QAAQ,MAAM,QAAQ,IAAK;AAC/B,QAAI,QAAQ,KAAM,KAAI,IAAI;AAAA,QACrB,KAAI,KAAK,GAAG;AAAA,EACnB;AACA,SAAO,MAAM,IAAI,KAAK,GAAG;AAC3B;AAgBA,SAAS,sBAAsB,MAAc,YAA+C;AAC1F,QAAM,QAAQ,kBAAkB,IAAI;AACpC,MAAI,eAAe,QAAQ,eAAe,IAAK,QAAO,EAAE,OAAO,YAAY,MAAM,MAAM;AACvF,SAAO,EAAE,OAAO,YAAY,MAAM,kBAAkB,aAAa,KAAK,EAAE;AAC1E;AAQO,SAAS,kBACd,KACA,OAMI,CAAC,GACe;AACpB,MAAI,IAAI,WAAW,SAAS,GAAG;AAC7B,UAAM,OAAO,IAAI,MAAM,UAAU,MAAM;AAGvC,QAAI,CAAC,KAAK,WAAW,GAAG,EAAG,QAAO,EAAE,OAAO,UAAU;AAMrD,QAAI,KAAK,eAAgB,QAAO,sBAAsB,MAAM,KAAK,cAAc,IAAI;AACnF,WAAO,EAAE,OAAO,YAAY,MAAM,kBAAkB,IAAI,EAAE;AAAA,EAC5D;AACA,MAAI,IAAI,WAAW,GAAG,GAAG;AACvB,UAAM,aAAa,KAAK,cAAc;AACtC,QAAI,eAAe,MAAM;AAGvB,aAAO,sBAAsB,KAAK,UAAU;AAAA,IAC9C;AACA,WAAO,EAAE,OAAO,YAAY,MAAM,kBAAkB,GAAG,EAAE;AAAA,EAC3D;AAEA,MAAI,CAAC,KAAK,YAAa,QAAO,EAAE,OAAO,eAAe;AACtD,QAAM,MAAM,KAAK,YAAY,MAAM,GAAG,KAAK,YAAY,YAAY,GAAG,CAAC;AACvE,SAAO,EAAE,OAAO,YAAY,MAAM,kBAAkB,GAAG,GAAG,IAAI,GAAG,EAAE,EAAE;AACvE;","names":[]}
1
+ {"version":3,"sources":["../src/linkSpace.ts"],"sourcesContent":["// Link path spaces (R3-273; REPO_CONTENT_DISPATCH_SPEC §9 decision, 2026-08-17).\n// R3-279: the RESOLVER CORE (resolveLinkTarget / normalizeAbsolute / FS_PREFIX /\n// ResolvedLinkTarget) moved to `@immediately-run/mdx-plugins` — beside its parity\n// fixture — and is re-exported here unchanged (API-stable). This module keeps the\n// REACT surface (LinkSpaceContext): the provider a corpus-rendering app wraps its\n// document tree in. Consumers importing from '@immediately-run/sdk/linkSpace' see\n// exactly the same names.\n//\n// A document link's target resolves in one of two spaces:\n//\n// - DEFAULT — the enclosing corpus's virtual filesystem. RELATIVE targets resolve\n// against the authoring file (identical in both spaces); ABSOLUTE targets\n// (`/x/y.mdx`) resolve from the corpus root when an enclosing `LinkSpaceContext`\n// declares one, else from the filesystem root. A non-corpus app declares nothing\n// and keeps today's behavior bit-for-bit (its fs root IS its only root).\n//\n// - `$fs:` — the explicit filesystem space: `$fs:/content/x.mdx` resolves from the\n// root of the filesystem the app reads, escaping corpus-relative addressing.\n//\n// `$fs:` changes ADDRESSING, never REACH: resolution is pure path arithmetic and\n// existence is checked against the same in-mount metadata the default space uses —\n// nothing is fetched, and a link can never name what the app cannot already read.\n// A malformed `$fs:` target (anything not mount-absolute — which also catches\n// scheme smuggling like `$fs:javascript:…`) is INVALID and must render as a broken\n// link, never an anchor.\n//\n// Corpus nesting: `LinkSpaceContext` providers nest, and the NEAREST one wins —\n// which is exactly the innermost-enclosing-corpus rule (bundle encapsulation): a\n// document rendered inside a nested corpus resolves against the nested corpus.\n\nimport { createContext } from 'react';\n\nexport { FS_PREFIX, normalizeAbsolute, resolveLinkTarget } from '@immediately-run/mdx-plugins';\nexport type { ResolvedLinkTarget, LinkSpace } from '@immediately-run/mdx-plugins';\nimport type { LinkSpace as LinkSpaceShape } from '@immediately-run/mdx-plugins';\n\n/** Ambient link space. A corpus-rendering app wraps its document tree in\n * `<LinkSpaceContext value={{ corpusRoot }}>`; nesting a second provider inside a\n * rendered sub-corpus makes the innermost root win. */\nexport const LinkSpaceContext = createContext<LinkSpaceShape>({\n corpusRoot: null,\n bundleChrooted: false,\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BA,mBAA8B;AAE9B,yBAAgE;AAOzD,MAAM,uBAAmB,4BAA8B;AAAA,EAC5D,YAAY;AAAA,EACZ,gBAAgB;AAClB,CAAC;","names":[]}
@@ -1,67 +1,10 @@
1
1
  import * as react from 'react';
2
+ import { LinkSpace } from '@immediately-run/mdx-plugins';
3
+ export { FS_PREFIX, LinkSpace, ResolvedLinkTarget, normalizeAbsolute, resolveLinkTarget } from '@immediately-run/mdx-plugins';
2
4
 
3
- declare const FS_PREFIX = "$fs:";
4
- interface LinkSpace {
5
- /** Absolute filesystem path of the enclosing corpus's root (e.g. `/app/content`),
6
- * or `null` when the document is not corpus-hosted (default). */
7
- corpusRoot: string | null;
8
- /**
9
- * True when the filesystem this document resolves against is **chroot'd to the
10
- * bundle** — i.e. the port the app holds was scoped to the bundle's subtree, so
11
- * the mount root and the bundle root are the same directory
12
- * (`BUNDLE_LAYERS_SPEC §9`; the `T2`/`T4` wrapper, R3-319 / BL-2).
13
- *
14
- * Under that grant `$fs:` **collapses to the scoped root**: `$fs:/p` and `/p`
15
- * name the same byte, because there is no longer any "mount-absolute" space
16
- * outside the bundle for `$fs:` to reach into. Without this flag the resolver
17
- * would hand back a mount-absolute path that the chroot then re-roots anyway —
18
- * a link that renders as valid and resolves somewhere the author did not mean.
19
- *
20
- * **This is an invariant to CREATE, not one to inherit** (`BUNDLE_LAYERS_SPEC
21
- * §11`): the shipped resolver reads `{currentFile, corpusRoot}` and nothing
22
- * else, so `$fs:` is bundle-anchored only if something says so. It lives here,
23
- * in the resolver, rather than as a rule each caller applies by passing
24
- * `corpusRoot: '/'` — an invariant the arithmetic carries cannot be forgotten
25
- * at one call site out of five.
26
- */
27
- bundleChrooted?: boolean;
28
- }
29
5
  /** Ambient link space. A corpus-rendering app wraps its document tree in
30
6
  * `<LinkSpaceContext value={{ corpusRoot }}>`; nesting a second provider inside a
31
7
  * rendered sub-corpus makes the innermost root win. */
32
8
  declare const LinkSpaceContext: react.Context<LinkSpace>;
33
- /** Collapse `.`/`..`/empty segments into a clean absolute path. `..` can never
34
- * climb above the root — a (virtual) root's parent is itself, which is what keeps
35
- * both the mount space and the corpus space closed under traversal. */
36
- declare const normalizeAbsolute: (path: string) => string;
37
- type ResolvedLinkTarget =
38
- /** Resolved to an absolute filesystem path (existence NOT checked here). */
39
- {
40
- state: 'resolved';
41
- path: string;
42
- }
43
- /** A relative target with no known authoring file — the caller may route
44
- * optimistically (it cannot check existence or self-ness generically). */
45
- | {
46
- state: 'unresolvable';
47
- }
48
- /** A malformed `$fs:` target (not mount-absolute; includes scheme smuggling).
49
- * Callers MUST render this broken/inert — never as an anchor. */
50
- | {
51
- state: 'invalid';
52
- };
53
- /**
54
- * Resolve a raw link target (a wikilink target or an in-app href's path half —
55
- * fragment already split off) to an absolute filesystem path. THE shared resolver:
56
- * the default `WikiLink`, the markdown `a` override, and safe-content consumers
57
- * all route through this one function so the two render pipelines cannot drift.
58
- */
59
- declare function resolveLinkTarget(raw: string, opts?: {
60
- currentFile?: string;
61
- corpusRoot?: string | null;
62
- /** See `LinkSpace.bundleChrooted`. Under a bundle-chroot'd grant `$fs:`
63
- * resolves in the corpus space, because they are the same space. */
64
- bundleChrooted?: boolean;
65
- }): ResolvedLinkTarget;
66
9
 
67
- export { FS_PREFIX, type LinkSpace, LinkSpaceContext, type ResolvedLinkTarget, normalizeAbsolute, resolveLinkTarget };
10
+ export { LinkSpaceContext };
@@ -1,67 +1,10 @@
1
1
  import * as react from 'react';
2
+ import { LinkSpace } from '@immediately-run/mdx-plugins';
3
+ export { FS_PREFIX, LinkSpace, ResolvedLinkTarget, normalizeAbsolute, resolveLinkTarget } from '@immediately-run/mdx-plugins';
2
4
 
3
- declare const FS_PREFIX = "$fs:";
4
- interface LinkSpace {
5
- /** Absolute filesystem path of the enclosing corpus's root (e.g. `/app/content`),
6
- * or `null` when the document is not corpus-hosted (default). */
7
- corpusRoot: string | null;
8
- /**
9
- * True when the filesystem this document resolves against is **chroot'd to the
10
- * bundle** — i.e. the port the app holds was scoped to the bundle's subtree, so
11
- * the mount root and the bundle root are the same directory
12
- * (`BUNDLE_LAYERS_SPEC §9`; the `T2`/`T4` wrapper, R3-319 / BL-2).
13
- *
14
- * Under that grant `$fs:` **collapses to the scoped root**: `$fs:/p` and `/p`
15
- * name the same byte, because there is no longer any "mount-absolute" space
16
- * outside the bundle for `$fs:` to reach into. Without this flag the resolver
17
- * would hand back a mount-absolute path that the chroot then re-roots anyway —
18
- * a link that renders as valid and resolves somewhere the author did not mean.
19
- *
20
- * **This is an invariant to CREATE, not one to inherit** (`BUNDLE_LAYERS_SPEC
21
- * §11`): the shipped resolver reads `{currentFile, corpusRoot}` and nothing
22
- * else, so `$fs:` is bundle-anchored only if something says so. It lives here,
23
- * in the resolver, rather than as a rule each caller applies by passing
24
- * `corpusRoot: '/'` — an invariant the arithmetic carries cannot be forgotten
25
- * at one call site out of five.
26
- */
27
- bundleChrooted?: boolean;
28
- }
29
5
  /** Ambient link space. A corpus-rendering app wraps its document tree in
30
6
  * `<LinkSpaceContext value={{ corpusRoot }}>`; nesting a second provider inside a
31
7
  * rendered sub-corpus makes the innermost root win. */
32
8
  declare const LinkSpaceContext: react.Context<LinkSpace>;
33
- /** Collapse `.`/`..`/empty segments into a clean absolute path. `..` can never
34
- * climb above the root — a (virtual) root's parent is itself, which is what keeps
35
- * both the mount space and the corpus space closed under traversal. */
36
- declare const normalizeAbsolute: (path: string) => string;
37
- type ResolvedLinkTarget =
38
- /** Resolved to an absolute filesystem path (existence NOT checked here). */
39
- {
40
- state: 'resolved';
41
- path: string;
42
- }
43
- /** A relative target with no known authoring file — the caller may route
44
- * optimistically (it cannot check existence or self-ness generically). */
45
- | {
46
- state: 'unresolvable';
47
- }
48
- /** A malformed `$fs:` target (not mount-absolute; includes scheme smuggling).
49
- * Callers MUST render this broken/inert — never as an anchor. */
50
- | {
51
- state: 'invalid';
52
- };
53
- /**
54
- * Resolve a raw link target (a wikilink target or an in-app href's path half —
55
- * fragment already split off) to an absolute filesystem path. THE shared resolver:
56
- * the default `WikiLink`, the markdown `a` override, and safe-content consumers
57
- * all route through this one function so the two render pipelines cannot drift.
58
- */
59
- declare function resolveLinkTarget(raw: string, opts?: {
60
- currentFile?: string;
61
- corpusRoot?: string | null;
62
- /** See `LinkSpace.bundleChrooted`. Under a bundle-chroot'd grant `$fs:`
63
- * resolves in the corpus space, because they are the same space. */
64
- bundleChrooted?: boolean;
65
- }): ResolvedLinkTarget;
66
9
 
67
- export { FS_PREFIX, type LinkSpace, LinkSpaceContext, type ResolvedLinkTarget, normalizeAbsolute, resolveLinkTarget };
10
+ export { LinkSpaceContext };
package/dist/linkSpace.js CHANGED
@@ -1,42 +1,10 @@
1
1
  import "./chunk-VHAA22YE.js";
2
2
  import { createContext } from "react";
3
- const FS_PREFIX = "$fs:";
3
+ import { FS_PREFIX, normalizeAbsolute, resolveLinkTarget } from "@immediately-run/mdx-plugins";
4
4
  const LinkSpaceContext = createContext({
5
5
  corpusRoot: null,
6
6
  bundleChrooted: false
7
7
  });
8
- const normalizeAbsolute = (path) => {
9
- const out = [];
10
- for (const seg of path.split("/")) {
11
- if (seg === "" || seg === ".") continue;
12
- if (seg === "..") out.pop();
13
- else out.push(seg);
14
- }
15
- return "/" + out.join("/");
16
- };
17
- function resolveCorpusAbsolute(path, corpusRoot) {
18
- const inner = normalizeAbsolute(path);
19
- if (corpusRoot === null || corpusRoot === "/") return { state: "resolved", path: inner };
20
- return { state: "resolved", path: normalizeAbsolute(corpusRoot + inner) };
21
- }
22
- function resolveLinkTarget(raw, opts = {}) {
23
- if (raw.startsWith(FS_PREFIX)) {
24
- const rest = raw.slice(FS_PREFIX.length);
25
- if (!rest.startsWith("/")) return { state: "invalid" };
26
- if (opts.bundleChrooted) return resolveCorpusAbsolute(rest, opts.corpusRoot ?? null);
27
- return { state: "resolved", path: normalizeAbsolute(rest) };
28
- }
29
- if (raw.startsWith("/")) {
30
- const corpusRoot = opts.corpusRoot ?? null;
31
- if (corpusRoot !== null) {
32
- return resolveCorpusAbsolute(raw, corpusRoot);
33
- }
34
- return { state: "resolved", path: normalizeAbsolute(raw) };
35
- }
36
- if (!opts.currentFile) return { state: "unresolvable" };
37
- const dir = opts.currentFile.slice(0, opts.currentFile.lastIndexOf("/"));
38
- return { state: "resolved", path: normalizeAbsolute(`${dir}/${raw}`) };
39
- }
40
8
  export {
41
9
  FS_PREFIX,
42
10
  LinkSpaceContext,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/linkSpace.ts"],"sourcesContent":["// Link path spaces (R3-273; REPO_CONTENT_DISPATCH_SPEC §9 decision, 2026-08-17).\n//\n// A document link's target resolves in one of two spaces:\n//\n// - DEFAULT — the enclosing corpus's virtual filesystem. RELATIVE targets resolve\n// against the authoring file (identical in both spaces); ABSOLUTE targets\n// (`/x/y.mdx`) resolve from the corpus root when an enclosing `LinkSpaceContext`\n// declares one, else from the filesystem root. A non-corpus app declares nothing\n// and keeps today's behavior bit-for-bit (its fs root IS its only root).\n//\n// - `$fs:` — the explicit filesystem space: `$fs:/content/x.mdx` resolves from the\n// root of the filesystem the app reads, escaping corpus-relative addressing.\n//\n// `$fs:` changes ADDRESSING, never REACH: resolution is pure path arithmetic and\n// existence is checked against the same in-mount metadata the default space uses —\n// nothing is fetched, and a link can never name what the app cannot already read.\n// A malformed `$fs:` target (anything not mount-absolute — which also catches\n// scheme smuggling like `$fs:javascript:…`) is INVALID and must render as a broken\n// link, never an anchor.\n//\n// Corpus nesting: `LinkSpaceContext` providers nest, and the NEAREST one wins —\n// which is exactly the innermost-enclosing-corpus rule (bundle encapsulation): a\n// document rendered inside a nested corpus resolves against the nested corpus.\n\nimport { createContext } from 'react';\n\nexport const FS_PREFIX = '$fs:';\n\nexport interface LinkSpace {\n /** Absolute filesystem path of the enclosing corpus's root (e.g. `/app/content`),\n * or `null` when the document is not corpus-hosted (default). */\n corpusRoot: string | null;\n /**\n * True when the filesystem this document resolves against is **chroot'd to the\n * bundle** — i.e. the port the app holds was scoped to the bundle's subtree, so\n * the mount root and the bundle root are the same directory\n * (`BUNDLE_LAYERS_SPEC §9`; the `T2`/`T4` wrapper, R3-319 / BL-2).\n *\n * Under that grant `$fs:` **collapses to the scoped root**: `$fs:/p` and `/p`\n * name the same byte, because there is no longer any \"mount-absolute\" space\n * outside the bundle for `$fs:` to reach into. Without this flag the resolver\n * would hand back a mount-absolute path that the chroot then re-roots anyway —\n * a link that renders as valid and resolves somewhere the author did not mean.\n *\n * **This is an invariant to CREATE, not one to inherit** (`BUNDLE_LAYERS_SPEC\n * §11`): the shipped resolver reads `{currentFile, corpusRoot}` and nothing\n * else, so `$fs:` is bundle-anchored only if something says so. It lives here,\n * in the resolver, rather than as a rule each caller applies by passing\n * `corpusRoot: '/'` — an invariant the arithmetic carries cannot be forgotten\n * at one call site out of five.\n */\n bundleChrooted?: boolean;\n}\n\n/** Ambient link space. A corpus-rendering app wraps its document tree in\n * `<LinkSpaceContext value={{ corpusRoot }}>`; nesting a second provider inside a\n * rendered sub-corpus makes the innermost root win. */\nexport const LinkSpaceContext = createContext<LinkSpace>({\n corpusRoot: null,\n bundleChrooted: false,\n});\n\n/** Collapse `.`/`..`/empty segments into a clean absolute path. `..` can never\n * climb above the root — a (virtual) root's parent is itself, which is what keeps\n * both the mount space and the corpus space closed under traversal. */\nexport const normalizeAbsolute = (path: string): string => {\n const out: string[] = [];\n for (const seg of path.split('/')) {\n if (seg === '' || seg === '.') continue;\n if (seg === '..') out.pop();\n else out.push(seg);\n }\n return '/' + out.join('/');\n};\n\nexport type ResolvedLinkTarget =\n /** Resolved to an absolute filesystem path (existence NOT checked here). */\n | { state: 'resolved'; path: string }\n /** A relative target with no known authoring file — the caller may route\n * optimistically (it cannot check existence or self-ness generically). */\n | { state: 'unresolvable' }\n /** A malformed `$fs:` target (not mount-absolute; includes scheme smuggling).\n * Callers MUST render this broken/inert — never as an anchor. */\n | { state: 'invalid' };\n\n/** Anchor a corpus-absolute path at `corpusRoot`, clamping the corpus-relative\n * half FIRST so the virtual corpus space stays closed under traversal. Shared by\n * the `/p` branch and — under a bundle chroot — the `$fs:/p` branch, so the two\n * spellings cannot drift into resolving differently. */\nfunction resolveCorpusAbsolute(path: string, corpusRoot: string | null): ResolvedLinkTarget {\n const inner = normalizeAbsolute(path);\n if (corpusRoot === null || corpusRoot === '/') return { state: 'resolved', path: inner };\n return { state: 'resolved', path: normalizeAbsolute(corpusRoot + inner) };\n}\n\n/**\n * Resolve a raw link target (a wikilink target or an in-app href's path half —\n * fragment already split off) to an absolute filesystem path. THE shared resolver:\n * the default `WikiLink`, the markdown `a` override, and safe-content consumers\n * all route through this one function so the two render pipelines cannot drift.\n */\nexport function resolveLinkTarget(\n raw: string,\n opts: {\n currentFile?: string;\n corpusRoot?: string | null;\n /** See `LinkSpace.bundleChrooted`. Under a bundle-chroot'd grant `$fs:`\n * resolves in the corpus space, because they are the same space. */\n bundleChrooted?: boolean;\n } = {},\n): ResolvedLinkTarget {\n if (raw.startsWith(FS_PREFIX)) {\n const rest = raw.slice(FS_PREFIX.length);\n // Must be mount-absolute. This single rule also fails `$fs:javascript:…`,\n // `$fs:https://…`, and every other smuggled scheme closed.\n if (!rest.startsWith('/')) return { state: 'invalid' };\n // Under a bundle chroot the mount root IS the bundle root, so `$fs:` has\n // nowhere outside to name: it takes the corpus-absolute branch below and the\n // two spellings collapse. `normalizeAbsolute` clamps `..` at the root either\n // way, so neither spelling can climb out — the collapse changes WHERE a\n // `$fs:` link points, never whether it can escape.\n if (opts.bundleChrooted) return resolveCorpusAbsolute(rest, opts.corpusRoot ?? null);\n return { state: 'resolved', path: normalizeAbsolute(rest) };\n }\n if (raw.startsWith('/')) {\n const corpusRoot = opts.corpusRoot ?? null;\n if (corpusRoot !== null) {\n // Clamp the corpus-relative half FIRST (the virtual FS is closed — `/../x`\n // stays inside the corpus), THEN anchor it at the corpus root.\n return resolveCorpusAbsolute(raw, corpusRoot);\n }\n return { state: 'resolved', path: normalizeAbsolute(raw) };\n }\n // Relative: against the authoring file's directory — the same in both spaces.\n if (!opts.currentFile) return { state: 'unresolvable' };\n const dir = opts.currentFile.slice(0, opts.currentFile.lastIndexOf('/'));\n return { state: 'resolved', path: normalizeAbsolute(`${dir}/${raw}`) };\n}\n"],"mappings":";AAwBA,SAAS,qBAAqB;AAEvB,MAAM,YAAY;AA+BlB,MAAM,mBAAmB,cAAyB;AAAA,EACvD,YAAY;AAAA,EACZ,gBAAgB;AAClB,CAAC;AAKM,MAAM,oBAAoB,CAAC,SAAyB;AACzD,QAAM,MAAgB,CAAC;AACvB,aAAW,OAAO,KAAK,MAAM,GAAG,GAAG;AACjC,QAAI,QAAQ,MAAM,QAAQ,IAAK;AAC/B,QAAI,QAAQ,KAAM,KAAI,IAAI;AAAA,QACrB,KAAI,KAAK,GAAG;AAAA,EACnB;AACA,SAAO,MAAM,IAAI,KAAK,GAAG;AAC3B;AAgBA,SAAS,sBAAsB,MAAc,YAA+C;AAC1F,QAAM,QAAQ,kBAAkB,IAAI;AACpC,MAAI,eAAe,QAAQ,eAAe,IAAK,QAAO,EAAE,OAAO,YAAY,MAAM,MAAM;AACvF,SAAO,EAAE,OAAO,YAAY,MAAM,kBAAkB,aAAa,KAAK,EAAE;AAC1E;AAQO,SAAS,kBACd,KACA,OAMI,CAAC,GACe;AACpB,MAAI,IAAI,WAAW,SAAS,GAAG;AAC7B,UAAM,OAAO,IAAI,MAAM,UAAU,MAAM;AAGvC,QAAI,CAAC,KAAK,WAAW,GAAG,EAAG,QAAO,EAAE,OAAO,UAAU;AAMrD,QAAI,KAAK,eAAgB,QAAO,sBAAsB,MAAM,KAAK,cAAc,IAAI;AACnF,WAAO,EAAE,OAAO,YAAY,MAAM,kBAAkB,IAAI,EAAE;AAAA,EAC5D;AACA,MAAI,IAAI,WAAW,GAAG,GAAG;AACvB,UAAM,aAAa,KAAK,cAAc;AACtC,QAAI,eAAe,MAAM;AAGvB,aAAO,sBAAsB,KAAK,UAAU;AAAA,IAC9C;AACA,WAAO,EAAE,OAAO,YAAY,MAAM,kBAAkB,GAAG,EAAE;AAAA,EAC3D;AAEA,MAAI,CAAC,KAAK,YAAa,QAAO,EAAE,OAAO,eAAe;AACtD,QAAM,MAAM,KAAK,YAAY,MAAM,GAAG,KAAK,YAAY,YAAY,GAAG,CAAC;AACvE,SAAO,EAAE,OAAO,YAAY,MAAM,kBAAkB,GAAG,GAAG,IAAI,GAAG,EAAE,EAAE;AACvE;","names":[]}
1
+ {"version":3,"sources":["../src/linkSpace.ts"],"sourcesContent":["// Link path spaces (R3-273; REPO_CONTENT_DISPATCH_SPEC §9 decision, 2026-08-17).\n// R3-279: the RESOLVER CORE (resolveLinkTarget / normalizeAbsolute / FS_PREFIX /\n// ResolvedLinkTarget) moved to `@immediately-run/mdx-plugins` — beside its parity\n// fixture — and is re-exported here unchanged (API-stable). This module keeps the\n// REACT surface (LinkSpaceContext): the provider a corpus-rendering app wraps its\n// document tree in. Consumers importing from '@immediately-run/sdk/linkSpace' see\n// exactly the same names.\n//\n// A document link's target resolves in one of two spaces:\n//\n// - DEFAULT — the enclosing corpus's virtual filesystem. RELATIVE targets resolve\n// against the authoring file (identical in both spaces); ABSOLUTE targets\n// (`/x/y.mdx`) resolve from the corpus root when an enclosing `LinkSpaceContext`\n// declares one, else from the filesystem root. A non-corpus app declares nothing\n// and keeps today's behavior bit-for-bit (its fs root IS its only root).\n//\n// - `$fs:` — the explicit filesystem space: `$fs:/content/x.mdx` resolves from the\n// root of the filesystem the app reads, escaping corpus-relative addressing.\n//\n// `$fs:` changes ADDRESSING, never REACH: resolution is pure path arithmetic and\n// existence is checked against the same in-mount metadata the default space uses —\n// nothing is fetched, and a link can never name what the app cannot already read.\n// A malformed `$fs:` target (anything not mount-absolute — which also catches\n// scheme smuggling like `$fs:javascript:…`) is INVALID and must render as a broken\n// link, never an anchor.\n//\n// Corpus nesting: `LinkSpaceContext` providers nest, and the NEAREST one wins —\n// which is exactly the innermost-enclosing-corpus rule (bundle encapsulation): a\n// document rendered inside a nested corpus resolves against the nested corpus.\n\nimport { createContext } from 'react';\n\nexport { FS_PREFIX, normalizeAbsolute, resolveLinkTarget } from '@immediately-run/mdx-plugins';\nexport type { ResolvedLinkTarget, LinkSpace } from '@immediately-run/mdx-plugins';\nimport type { LinkSpace as LinkSpaceShape } from '@immediately-run/mdx-plugins';\n\n/** Ambient link space. A corpus-rendering app wraps its document tree in\n * `<LinkSpaceContext value={{ corpusRoot }}>`; nesting a second provider inside a\n * rendered sub-corpus makes the innermost root win. */\nexport const LinkSpaceContext = createContext<LinkSpaceShape>({\n corpusRoot: null,\n bundleChrooted: false,\n});\n"],"mappings":";AA8BA,SAAS,qBAAqB;AAE9B,SAAS,WAAW,mBAAmB,yBAAyB;AAOzD,MAAM,mBAAmB,cAA8B;AAAA,EAC5D,YAAY;AAAA,EACZ,gBAAgB;AAClB,CAAC;","names":[]}
@@ -18,35 +18,10 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var SafeContent_exports = {};
20
20
  __export(SafeContent_exports, {
21
- SafeContent: () => SafeContent
21
+ SafeContent: () => import_safe_content.SafeContent
22
22
  });
23
23
  module.exports = __toCommonJS(SafeContent_exports);
24
- var import_react = require("react");
25
- var import_parseSafeMdast = require("./parseSafeMdast");
26
- var import_renderMdast = require("./renderMdast");
27
- function SafeContent({ source, fallback = null, ...options }) {
28
- const [tree, setTree] = (0, import_react.useState)(null);
29
- const runId = (0, import_react.useRef)(0);
30
- (0, import_react.useEffect)(() => {
31
- const id = ++runId.current;
32
- setTree(null);
33
- let cancelled = false;
34
- (0, import_parseSafeMdast.parseSafeMdast)(source).then((parsed) => {
35
- if (!cancelled && runId.current === id) setTree(parsed);
36
- }).catch(() => {
37
- if (!cancelled && runId.current === id) setTree(null);
38
- });
39
- return () => {
40
- cancelled = true;
41
- };
42
- }, [source]);
43
- const rendered = (0, import_react.useMemo)(
44
- () => tree ? (0, import_renderMdast.renderMdast)(tree, options) : null,
45
- // eslint-disable-next-line react-hooks/exhaustive-deps
46
- [tree, options.components, options.resolveWikiLink]
47
- );
48
- return tree ? rendered : fallback;
49
- }
24
+ var import_safe_content = require("@immediately-run/safe-content");
50
25
  // Annotate the CommonJS export names for ESM import in node:
51
26
  0 && (module.exports = {
52
27
  SafeContent
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/safeContent/SafeContent.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react';\nimport { parseSafeMdast } from './parseSafeMdast';\nimport { renderMdast, type RenderMdastOptions } from './renderMdast';\n\n// R3-213 — sharing the component map: `parseSafeMdast` runs the SAME kernel remark\n// plugins the compiled path uses, so it emits `<Admonition>` / `<WikiLink>` /\n// `<HeadingAnchor>` element nodes. To render them identically to the compiled path (and\n// so pick up the R3-212 fragment resolver + scroll), an interpreter app passes the SAME\n// `DEFAULT_MDX_COMPONENTS` it hands `boot({ mdxComponents })` as this component's\n// `components` — that shared map IS the uniformity (no forked second component set). We\n// deliberately do NOT import DEFAULT_MDX_COMPONENTS here: the safe renderer is a lean,\n// dep-light security primitive (render-as-data, no evaluator, ESM-clean for the e2e\n// bundle), and must not pull the full component library into its module graph.\n\n// `<SafeContent>` — the host/SDK-owned safe renderer (TRUST_MODES_SPEC §5.1,\n// AGENT_AUTHORING §10). An interpreter app renders untrusted Markdown/MDX-syntax\n// content — a shared board's body, a multi-writer wiki entry — through THIS component\n// so **no author JavaScript ever executes** while `<Component/>` syntax still reaches\n// the app's own safe components. It is the mandatory terminal for the MDX-from-mount\n// gate: a shared board is a multi-writer (M3) source, and compiled/executable MDX\n// would run board-author code with the app's authority (the WHITEBOARD §8 blast\n// radius this gate bounds).\n//\n// The parse (no-acorn, ESM-only deps) is async, so this renders a small placeholder\n// until the tree is ready, then the pure synchronous `renderMdast`. Parsing is keyed\n// on the source string; a changed source re-parses, and a stale async result is\n// discarded (the ref guard) so a fast source swap can't paint the wrong content.\n\nexport interface SafeContentProps extends RenderMdastOptions {\n /** The untrusted Markdown/MDX-syntax source to render as data. */\n source: string;\n /** Rendered while the async parse is in flight (default: nothing). */\n fallback?: ReactNode;\n}\n\nexport function SafeContent({ source, fallback = null, ...options }: SafeContentProps): ReactNode {\n const [tree, setTree] = useState<Awaited<ReturnType<typeof parseSafeMdast>> | null>(null);\n const runId = useRef(0);\n\n useEffect(() => {\n const id = ++runId.current;\n setTree(null);\n let cancelled = false;\n parseSafeMdast(source)\n .then((parsed) => {\n // Discard a stale result (source changed / unmounted) so we never paint the\n // wrong tree — the render-as-data guarantee also needs the RIGHT data shown.\n if (!cancelled && runId.current === id) setTree(parsed);\n })\n .catch(() => {\n if (!cancelled && runId.current === id) setTree(null);\n });\n return () => {\n cancelled = true;\n };\n }, [source]);\n\n // `renderMdast` is pure; memoise on the tree + the option identities the caller\n // passes. (Callers should memoise `components`/`resolveWikiLink` themselves for a\n // stable identity; changing them re-renders, which is correct.)\n const rendered = useMemo(\n () => (tree ? renderMdast(tree, options) : null),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [tree, options.components, options.resolveWikiLink],\n );\n\n return tree ? rendered : fallback;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAqE;AACrE,4BAA+B;AAC/B,yBAAqD;AAiC9C,SAAS,YAAY,EAAE,QAAQ,WAAW,MAAM,GAAG,QAAQ,GAAgC;AAChG,QAAM,CAAC,MAAM,OAAO,QAAI,uBAA4D,IAAI;AACxF,QAAM,YAAQ,qBAAO,CAAC;AAEtB,8BAAU,MAAM;AACd,UAAM,KAAK,EAAE,MAAM;AACnB,YAAQ,IAAI;AACZ,QAAI,YAAY;AAChB,8CAAe,MAAM,EAClB,KAAK,CAAC,WAAW;AAGhB,UAAI,CAAC,aAAa,MAAM,YAAY,GAAI,SAAQ,MAAM;AAAA,IACxD,CAAC,EACA,MAAM,MAAM;AACX,UAAI,CAAC,aAAa,MAAM,YAAY,GAAI,SAAQ,IAAI;AAAA,IACtD,CAAC;AACH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAKX,QAAM,eAAW;AAAA,IACf,MAAO,WAAO,gCAAY,MAAM,OAAO,IAAI;AAAA;AAAA,IAE3C,CAAC,MAAM,QAAQ,YAAY,QAAQ,eAAe;AAAA,EACpD;AAEA,SAAO,OAAO,WAAW;AAC3B;","names":[]}
1
+ {"version":3,"sources":["../../src/safeContent/SafeContent.tsx"],"sourcesContent":["// R3-279 (phase 3): re-export shim — the implementation lives in\n// `@immediately-run/safe-content`; this subpath keeps working byte-compatibly.\nexport { SafeContent } from '@immediately-run/safe-content';\nexport type { SafeContentProps } from '@immediately-run/safe-content';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,0BAA4B;","names":[]}
@@ -1,13 +1 @@
1
- import { ReactNode } from 'react';
2
- import { RenderMdastOptions } from './renderMdast.cjs';
3
- import './parseSafeMdast.cjs';
4
-
5
- interface SafeContentProps extends RenderMdastOptions {
6
- /** The untrusted Markdown/MDX-syntax source to render as data. */
7
- source: string;
8
- /** Rendered while the async parse is in flight (default: nothing). */
9
- fallback?: ReactNode;
10
- }
11
- declare function SafeContent({ source, fallback, ...options }: SafeContentProps): ReactNode;
12
-
13
- export { SafeContent, type SafeContentProps };
1
+ export { SafeContent, SafeContentProps } from '@immediately-run/safe-content';
@@ -1,13 +1 @@
1
- import { ReactNode } from 'react';
2
- import { RenderMdastOptions } from './renderMdast.js';
3
- import './parseSafeMdast.js';
4
-
5
- interface SafeContentProps extends RenderMdastOptions {
6
- /** The untrusted Markdown/MDX-syntax source to render as data. */
7
- source: string;
8
- /** Rendered while the async parse is in flight (default: nothing). */
9
- fallback?: ReactNode;
10
- }
11
- declare function SafeContent({ source, fallback, ...options }: SafeContentProps): ReactNode;
12
-
13
- export { SafeContent, type SafeContentProps };
1
+ export { SafeContent, SafeContentProps } from '@immediately-run/safe-content';
@@ -1,30 +1,5 @@
1
1
  import "../chunk-VHAA22YE.js";
2
- import { useEffect, useMemo, useRef, useState } from "react";
3
- import { parseSafeMdast } from "./parseSafeMdast";
4
- import { renderMdast } from "./renderMdast";
5
- function SafeContent({ source, fallback = null, ...options }) {
6
- const [tree, setTree] = useState(null);
7
- const runId = useRef(0);
8
- useEffect(() => {
9
- const id = ++runId.current;
10
- setTree(null);
11
- let cancelled = false;
12
- parseSafeMdast(source).then((parsed) => {
13
- if (!cancelled && runId.current === id) setTree(parsed);
14
- }).catch(() => {
15
- if (!cancelled && runId.current === id) setTree(null);
16
- });
17
- return () => {
18
- cancelled = true;
19
- };
20
- }, [source]);
21
- const rendered = useMemo(
22
- () => tree ? renderMdast(tree, options) : null,
23
- // eslint-disable-next-line react-hooks/exhaustive-deps
24
- [tree, options.components, options.resolveWikiLink]
25
- );
26
- return tree ? rendered : fallback;
27
- }
2
+ import { SafeContent } from "@immediately-run/safe-content";
28
3
  export {
29
4
  SafeContent
30
5
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/safeContent/SafeContent.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react';\nimport { parseSafeMdast } from './parseSafeMdast';\nimport { renderMdast, type RenderMdastOptions } from './renderMdast';\n\n// R3-213 — sharing the component map: `parseSafeMdast` runs the SAME kernel remark\n// plugins the compiled path uses, so it emits `<Admonition>` / `<WikiLink>` /\n// `<HeadingAnchor>` element nodes. To render them identically to the compiled path (and\n// so pick up the R3-212 fragment resolver + scroll), an interpreter app passes the SAME\n// `DEFAULT_MDX_COMPONENTS` it hands `boot({ mdxComponents })` as this component's\n// `components` — that shared map IS the uniformity (no forked second component set). We\n// deliberately do NOT import DEFAULT_MDX_COMPONENTS here: the safe renderer is a lean,\n// dep-light security primitive (render-as-data, no evaluator, ESM-clean for the e2e\n// bundle), and must not pull the full component library into its module graph.\n\n// `<SafeContent>` — the host/SDK-owned safe renderer (TRUST_MODES_SPEC §5.1,\n// AGENT_AUTHORING §10). An interpreter app renders untrusted Markdown/MDX-syntax\n// content — a shared board's body, a multi-writer wiki entry — through THIS component\n// so **no author JavaScript ever executes** while `<Component/>` syntax still reaches\n// the app's own safe components. It is the mandatory terminal for the MDX-from-mount\n// gate: a shared board is a multi-writer (M3) source, and compiled/executable MDX\n// would run board-author code with the app's authority (the WHITEBOARD §8 blast\n// radius this gate bounds).\n//\n// The parse (no-acorn, ESM-only deps) is async, so this renders a small placeholder\n// until the tree is ready, then the pure synchronous `renderMdast`. Parsing is keyed\n// on the source string; a changed source re-parses, and a stale async result is\n// discarded (the ref guard) so a fast source swap can't paint the wrong content.\n\nexport interface SafeContentProps extends RenderMdastOptions {\n /** The untrusted Markdown/MDX-syntax source to render as data. */\n source: string;\n /** Rendered while the async parse is in flight (default: nothing). */\n fallback?: ReactNode;\n}\n\nexport function SafeContent({ source, fallback = null, ...options }: SafeContentProps): ReactNode {\n const [tree, setTree] = useState<Awaited<ReturnType<typeof parseSafeMdast>> | null>(null);\n const runId = useRef(0);\n\n useEffect(() => {\n const id = ++runId.current;\n setTree(null);\n let cancelled = false;\n parseSafeMdast(source)\n .then((parsed) => {\n // Discard a stale result (source changed / unmounted) so we never paint the\n // wrong tree — the render-as-data guarantee also needs the RIGHT data shown.\n if (!cancelled && runId.current === id) setTree(parsed);\n })\n .catch(() => {\n if (!cancelled && runId.current === id) setTree(null);\n });\n return () => {\n cancelled = true;\n };\n }, [source]);\n\n // `renderMdast` is pure; memoise on the tree + the option identities the caller\n // passes. (Callers should memoise `components`/`resolveWikiLink` themselves for a\n // stable identity; changing them re-renders, which is correct.)\n const rendered = useMemo(\n () => (tree ? renderMdast(tree, options) : null),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [tree, options.components, options.resolveWikiLink],\n );\n\n return tree ? rendered : fallback;\n}\n"],"mappings":";AAAA,SAAS,WAAW,SAAS,QAAQ,gBAAgC;AACrE,SAAS,sBAAsB;AAC/B,SAAS,mBAA4C;AAiC9C,SAAS,YAAY,EAAE,QAAQ,WAAW,MAAM,GAAG,QAAQ,GAAgC;AAChG,QAAM,CAAC,MAAM,OAAO,IAAI,SAA4D,IAAI;AACxF,QAAM,QAAQ,OAAO,CAAC;AAEtB,YAAU,MAAM;AACd,UAAM,KAAK,EAAE,MAAM;AACnB,YAAQ,IAAI;AACZ,QAAI,YAAY;AAChB,mBAAe,MAAM,EAClB,KAAK,CAAC,WAAW;AAGhB,UAAI,CAAC,aAAa,MAAM,YAAY,GAAI,SAAQ,MAAM;AAAA,IACxD,CAAC,EACA,MAAM,MAAM;AACX,UAAI,CAAC,aAAa,MAAM,YAAY,GAAI,SAAQ,IAAI;AAAA,IACtD,CAAC;AACH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAKX,QAAM,WAAW;AAAA,IACf,MAAO,OAAO,YAAY,MAAM,OAAO,IAAI;AAAA;AAAA,IAE3C,CAAC,MAAM,QAAQ,YAAY,QAAQ,eAAe;AAAA,EACpD;AAEA,SAAO,OAAO,WAAW;AAC3B;","names":[]}
1
+ {"version":3,"sources":["../../src/safeContent/SafeContent.tsx"],"sourcesContent":["// R3-279 (phase 3): re-export shim — the implementation lives in\n// `@immediately-run/safe-content`; this subpath keeps working byte-compatibly.\nexport { SafeContent } from '@immediately-run/safe-content';\nexport type { SafeContentProps } from '@immediately-run/safe-content';\n"],"mappings":";AAEA,SAAS,mBAAmB;","names":[]}
@@ -3,10 +3,6 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
6
  var __copyProps = (to, from, except, desc) => {
11
7
  if (from && typeof from === "object" || typeof from === "function") {
12
8
  for (let key of __getOwnPropNames(from))
@@ -15,29 +11,13 @@ var __copyProps = (to, from, except, desc) => {
15
11
  }
16
12
  return to;
17
13
  };
14
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
18
15
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
16
  var safeContent_exports = {};
20
- __export(safeContent_exports, {
21
- SafeContent: () => import_SafeContent.SafeContent,
22
- parseSafeMdast: () => import_parseSafeMdast.parseSafeMdast,
23
- parseWikiInner: () => import_wikilink.parseWikiInner,
24
- renderMdast: () => import_renderMdast.renderMdast,
25
- sanitizeUrl: () => import_sanitizeUrl.sanitizeUrl,
26
- splitWikiLinks: () => import_wikilink.splitWikiLinks
27
- });
28
17
  module.exports = __toCommonJS(safeContent_exports);
29
- var import_SafeContent = require("./SafeContent");
30
- var import_renderMdast = require("./renderMdast");
31
- var import_parseSafeMdast = require("./parseSafeMdast");
32
- var import_sanitizeUrl = require("./sanitizeUrl");
33
- var import_wikilink = require("./wikilink");
18
+ __reExport(safeContent_exports, require("@immediately-run/safe-content"), module.exports);
34
19
  // Annotate the CommonJS export names for ESM import in node:
35
20
  0 && (module.exports = {
36
- SafeContent,
37
- parseSafeMdast,
38
- parseWikiInner,
39
- renderMdast,
40
- sanitizeUrl,
41
- splitWikiLinks
21
+ ...require("@immediately-run/safe-content")
42
22
  });
43
23
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/safeContent/index.ts"],"sourcesContent":["// Safe content rendering — non-executable MDX (TRUST_MODES_SPEC §5.1, AGENT_AUTHORING\n// §10). The host/SDK-owned renderer an INTERPRETER app uses to render untrusted\n// Markdown/MDX-syntax content as data, with **no evaluator anywhere in the pipeline**.\n// This is the mandatory terminal for the MDX-from-mount gate (§10 delta 1) — a shared\n// (multi-writer / M3) board or wiki entry MUST render through here, never compiled MDX.\n//\n// It is a **T2 tool, not a platform gate**: it stops content executing as code; it does\n// not certify anything to the host, and CO-4 data-fencing is still required for anything\n// that *reads* the content (the agent case).\n\nexport { SafeContent } from './SafeContent';\nexport type { SafeContentProps } from './SafeContent';\nexport { renderMdast } from './renderMdast';\nexport type { RenderMdastOptions, SafeContentComponents } from './renderMdast';\nexport { parseSafeMdast } from './parseSafeMdast';\nexport type { SafeMdastNode, SafeMdxAttribute, ParseSafeMdastOptions } from './parseSafeMdast';\nexport { sanitizeUrl } from './sanitizeUrl';\nexport { splitWikiLinks, parseWikiInner } from './wikilink';\nexport type { WikiLinkToken, WikiPart } from './wikilink';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,yBAA4B;AAE5B,yBAA4B;AAE5B,4BAA+B;AAE/B,yBAA4B;AAC5B,sBAA+C;","names":[]}
1
+ {"version":3,"sources":["../../src/safeContent/index.ts"],"sourcesContent":["// Safe content rendering — non-executable MDX (TRUST_MODES_SPEC §5.1, AGENT_AUTHORING\n// §10). The host/SDK-owned renderer an INTERPRETER app uses to render untrusted\n// Markdown/MDX-syntax content as data, with **no evaluator anywhere in the pipeline**.\n// This is the mandatory terminal for the MDX-from-mount gate (§10 delta 1) — a shared\n// (multi-writer / M3) board or wiki entry MUST render through here, never compiled MDX.\n//\n// It is a **T2 tool, not a platform gate**: it stops content executing as code; it does\n// not certify anything to the host, and CO-4 data-fencing is still required for anything\n// that *reads* the content (the agent case).\n//\n// R3-279 (phase 3): the implementation now lives in `@immediately-run/safe-content`\n// (the S3 content-framework tier's first extraction). This module — and every sibling\n// subpath below — is a byte-compat RE-EXPORT: `api-snapshot.json` is unchanged, every\n// existing `@immediately-run/sdk/safeContent/*` import keeps working, and no consumer\n// changes anywhere.\nexport * from '@immediately-run/safe-content';\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA;AAeA,gCAAc,0CAfd;","names":[]}
@@ -1,6 +1 @@
1
- export { SafeContent, SafeContentProps } from './SafeContent.cjs';
2
- export { RenderMdastOptions, SafeContentComponents, renderMdast } from './renderMdast.cjs';
3
- export { ParseSafeMdastOptions, SafeMdastNode, SafeMdxAttribute, parseSafeMdast } from './parseSafeMdast.cjs';
4
- export { sanitizeUrl } from './sanitizeUrl.cjs';
5
- export { WikiLinkToken, WikiPart, parseWikiInner, splitWikiLinks } from './wikilink.cjs';
6
- import 'react';
1
+ export * from '@immediately-run/safe-content';
@@ -1,6 +1 @@
1
- export { SafeContent, SafeContentProps } from './SafeContent.js';
2
- export { RenderMdastOptions, SafeContentComponents, renderMdast } from './renderMdast.js';
3
- export { ParseSafeMdastOptions, SafeMdastNode, SafeMdxAttribute, parseSafeMdast } from './parseSafeMdast.js';
4
- export { sanitizeUrl } from './sanitizeUrl.js';
5
- export { WikiLinkToken, WikiPart, parseWikiInner, splitWikiLinks } from './wikilink.js';
6
- import 'react';
1
+ export * from '@immediately-run/safe-content';
@@ -1,15 +1,2 @@
1
- import "../chunk-VHAA22YE.js";
2
- import { SafeContent } from "./SafeContent";
3
- import { renderMdast } from "./renderMdast";
4
- import { parseSafeMdast } from "./parseSafeMdast";
5
- import { sanitizeUrl } from "./sanitizeUrl";
6
- import { splitWikiLinks, parseWikiInner } from "./wikilink";
7
- export {
8
- SafeContent,
9
- parseSafeMdast,
10
- parseWikiInner,
11
- renderMdast,
12
- sanitizeUrl,
13
- splitWikiLinks
14
- };
1
+ export * from "@immediately-run/safe-content";
15
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/safeContent/index.ts"],"sourcesContent":["// Safe content rendering — non-executable MDX (TRUST_MODES_SPEC §5.1, AGENT_AUTHORING\n// §10). The host/SDK-owned renderer an INTERPRETER app uses to render untrusted\n// Markdown/MDX-syntax content as data, with **no evaluator anywhere in the pipeline**.\n// This is the mandatory terminal for the MDX-from-mount gate (§10 delta 1) — a shared\n// (multi-writer / M3) board or wiki entry MUST render through here, never compiled MDX.\n//\n// It is a **T2 tool, not a platform gate**: it stops content executing as code; it does\n// not certify anything to the host, and CO-4 data-fencing is still required for anything\n// that *reads* the content (the agent case).\n\nexport { SafeContent } from './SafeContent';\nexport type { SafeContentProps } from './SafeContent';\nexport { renderMdast } from './renderMdast';\nexport type { RenderMdastOptions, SafeContentComponents } from './renderMdast';\nexport { parseSafeMdast } from './parseSafeMdast';\nexport type { SafeMdastNode, SafeMdxAttribute, ParseSafeMdastOptions } from './parseSafeMdast';\nexport { sanitizeUrl } from './sanitizeUrl';\nexport { splitWikiLinks, parseWikiInner } from './wikilink';\nexport type { WikiLinkToken, WikiPart } from './wikilink';\n"],"mappings":";AAUA,SAAS,mBAAmB;AAE5B,SAAS,mBAAmB;AAE5B,SAAS,sBAAsB;AAE/B,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB,sBAAsB;","names":[]}
1
+ {"version":3,"sources":["../../src/safeContent/index.ts"],"sourcesContent":["// Safe content rendering — non-executable MDX (TRUST_MODES_SPEC §5.1, AGENT_AUTHORING\n// §10). The host/SDK-owned renderer an INTERPRETER app uses to render untrusted\n// Markdown/MDX-syntax content as data, with **no evaluator anywhere in the pipeline**.\n// This is the mandatory terminal for the MDX-from-mount gate (§10 delta 1) — a shared\n// (multi-writer / M3) board or wiki entry MUST render through here, never compiled MDX.\n//\n// It is a **T2 tool, not a platform gate**: it stops content executing as code; it does\n// not certify anything to the host, and CO-4 data-fencing is still required for anything\n// that *reads* the content (the agent case).\n//\n// R3-279 (phase 3): the implementation now lives in `@immediately-run/safe-content`\n// (the S3 content-framework tier's first extraction). This module — and every sibling\n// subpath below — is a byte-compat RE-EXPORT: `api-snapshot.json` is unchanged, every\n// existing `@immediately-run/sdk/safeContent/*` import keeps working, and no consumer\n// changes anywhere.\nexport * from '@immediately-run/safe-content';\n"],"mappings":"AAeA,cAAc;","names":[]}