@ai-react-markdown/core 1.4.5 → 1.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { JSX, ComponentType, PropsWithChildren, CSSProperties, FC } from 'react';
3
3
  import { Element, ElementContent } from 'hast';
4
4
  import { defaultSchema } from 'rehype-sanitize';
@@ -238,6 +238,27 @@ interface AIMarkdownRenderState<TConfig extends AIMarkdownRenderConfig = AIMarkd
238
238
  * always win.
239
239
  */
240
240
  documentId: string;
241
+ /**
242
+ * Whether {@link documentId} was EXPLICITLY supplied by the consumer (vs.
243
+ * auto-generated via `useId()`). This is the coordination signal — NOT
244
+ * `documentId` truthiness, which is always `true` because the provider
245
+ * auto-fills a fallback id for HTML/`clobberPrefix` purposes.
246
+ *
247
+ * `useDocumentRegistry` gates on this: an auto-generated id is unique by
248
+ * construction, so a chunk that didn't receive a `documentId` has nothing
249
+ * to coordinate with even when it sits inside `<AIMarkdownDocuments>`. It
250
+ * must take the standalone (registry === null) path, and this flag is the
251
+ * only thing that lets the registry hook tell "consumer wants coordination"
252
+ * apart from "we fabricated an id so the markup stays valid".
253
+ *
254
+ * Optional in the type ONLY so external callers that construct an
255
+ * `AIMarkdownRenderState` literal directly (mocks, fixtures) aren't broken
256
+ * by this internally-added field — the provider ALWAYS sets a concrete
257
+ * boolean, and internal consumers coerce a missing value to `false`
258
+ * (safe default: no coordination). Keeping it `?:` preserves source-level
259
+ * backward compatibility for the publicly-exported state type.
260
+ */
261
+ documentIdExplicit?: boolean;
241
262
  /**
242
263
  * Per-document URI-safe id prefix used by all clobberable attributes
243
264
  * (`id="…"` / `href="#…"`). Derived once by the provider and exposed here
@@ -818,8 +839,10 @@ type SanitizeSchema = typeof defaultSchema;
818
839
  * });
819
840
  * ```
820
841
  *
821
- * @remarks Allowing a protocol on `protocols.href` lets the URL through the
822
- * SECOND sanitize gate. The FIRST gate (`urlTransform`) must permit the
842
+ * @remarks Allowing a protocol on `protocols.href` lets the URL through
843
+ * Gate 1 (the schema-level per-protocol allowlist, which runs inside the
844
+ * rehype plugin chain). Gate 2 (`urlTransform`, the per-attribute rewriter
845
+ * that runs later at render time in `renderHastSubtree`) must permit the
823
846
  * same protocol independently — see the `urlTransform` prop on
824
847
  * `<AIMarkdown>` and the exported {@link defaultUrlTransform} for
825
848
  * composition. Keep the two protocol lists in sync.
@@ -1022,11 +1045,23 @@ declare const AIMarkdownDocuments: FC<AIMarkdownDocumentsProps>;
1022
1045
  /**
1023
1046
  * Returns the registry for the given `documentId`, or `null` if:
1024
1047
  * - `<AIMarkdown>` is not inside an `<AIMarkdownDocuments>` wrapper, OR
1025
- * - `documentId` is undefined / empty string.
1048
+ * - `documentId` is undefined / empty string, OR
1049
+ * - `documentIdExplicit` is `false` — i.e. the id was auto-generated rather
1050
+ * than supplied by the consumer.
1051
+ *
1052
+ * The `documentIdExplicit` gate is the crux of the standalone-vs-coordinated
1053
+ * decision. An auto-generated id (`useId()` fallback) is non-empty and unique
1054
+ * by construction, so a chunk carrying one has nothing to coordinate with even
1055
+ * inside the wrapper — it must run standalone. Without this gate, the mere
1056
+ * presence of `<AIMarkdownDocuments>` would drag every uncoordinated chunk
1057
+ * onto the cross-chunk registry path (subscribe / allocate / evict overhead)
1058
+ * for no behavioral gain. The flag defaults to `true` so external callers who
1059
+ * pass an id directly are treated as explicit (passing an id IS the intent to
1060
+ * coordinate); the internal renderer threads through `state.documentIdExplicit`.
1026
1061
  *
1027
1062
  * Callers should treat `null` as "no coordination; run standalone path."
1028
1063
  */
1029
- declare function useDocumentRegistry(documentId: string | undefined): Registry | null;
1064
+ declare function useDocumentRegistry(documentId: string | undefined, documentIdExplicit?: boolean): Registry | null;
1030
1065
 
1031
1066
  /**
1032
1067
  * Props for the `<AIMarkdown>` component.
@@ -1099,10 +1134,14 @@ interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRen
1099
1134
  */
1100
1135
  documentId?: string;
1101
1136
  /**
1102
- * Override the function that decides which URL protocols are allowed
1103
- * through the FIRST sanitization gate. The default allowlist mirrors
1104
- * `react-markdown` / GitHub: `http`, `https`, `irc`, `ircs`, `mailto`,
1105
- * `xmpp`. Anything else is rewritten to `''`.
1137
+ * Override the per-attribute URL rewriter (Gate 2 of the two-gate model).
1138
+ * Runs at render time during the hast traversal in `renderHastSubtree`,
1139
+ * after Gate 1 (`rehype-sanitize` schema) has already filtered URLs by
1140
+ * protocol allowlist in the rehype plugin chain.
1141
+ *
1142
+ * The default allowlist mirrors `react-markdown` / GitHub: `http`,
1143
+ * `https`, `irc`, `ircs`, `mailto`, `xmpp`. Anything else is rewritten
1144
+ * to `''`.
1106
1145
  *
1107
1146
  * **Recommended pattern**: compose with the exported
1108
1147
  * {@link defaultUrlTransform} so the built-in XSS protections survive,
@@ -1131,13 +1170,13 @@ interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRen
1131
1170
  * as a dependency. Defining the function inline (`urlTransform={(url) =>
1132
1171
  * …}`) creates a new closure on every parent render, discards the cache
1133
1172
  * for the entire markdown document on each render, and effectively
1134
- * disables Phase 5 memoization. In development the library will
1173
+ * disables block-level memoization. In development the library will
1135
1174
  * `console.warn` if it detects this pattern.
1136
1175
  *
1137
1176
  * Allowing a protocol here is necessary but **not sufficient** to render
1138
- * a link — the second gate (`rehype-sanitize`) also enforces its own
1139
- * protocol allowlist. See the `sanitizeSchema` prop on this component
1140
- * and the {@link extendSanitizeSchema} helper for the second gate.
1177
+ * a link — Gate 1 (`rehype-sanitize` schema) also enforces its own
1178
+ * protocol allowlist and runs first. See the `sanitizeSchema` prop on
1179
+ * this component and the {@link extendSanitizeSchema} helper for Gate 1.
1141
1180
  *
1142
1181
  * **API stability**: the `UrlTransform` type tracks the upstream
1143
1182
  * `react-markdown` shape and may change with its major versions.
@@ -1146,10 +1185,13 @@ interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRen
1146
1185
  /**
1147
1186
  * Override the `rehype-sanitize` schema applied to the rendered output.
1148
1187
  * The library default extends `rehype-sanitize`'s own `defaultSchema`
1149
- * with the `<mark>` tag, KaTeX class names, and the cross-chunk
1150
- * coordination tags (`cross-chunk-link`, `cross-chunk-image`,
1151
- * `footnote-sup`). The default is not exported as a value — see
1152
- * {@link extendSanitizeSchema} for how to inspect or extend it safely.
1188
+ * with the `<mark>` tag, the `math-inline` / `math-display` className
1189
+ * markers `remark-math` emits on `<code>` (KaTeX's own output classes
1190
+ * survive separately because `rehype-katex` runs after `rehype-sanitize`),
1191
+ * and the cross-chunk coordination tags (`cross-chunk-link`,
1192
+ * `cross-chunk-image`, `footnote-sup`). The default is not exported as a
1193
+ * value — see {@link extendSanitizeSchema} for how to inspect or extend
1194
+ * it safely.
1153
1195
  *
1154
1196
  * **Recommended pattern**: build the schema with {@link extendSanitizeSchema}
1155
1197
  * (mutate-and-return form) so those library additions stay intact, and
@@ -1189,7 +1231,7 @@ interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRen
1189
1231
  * Root component that preprocesses markdown content and renders it through
1190
1232
  * a configurable remark/rehype pipeline wrapped in typography and style layers.
1191
1233
  */
1192
- declare const AIMarkdownComponent: <TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig, TRenderData extends AIMarkdownMetadata = AIMarkdownMetadata>({ streaming, content, fontSize, contentPreprocessors, customComponents, defaultConfig, config, metadata, Typography, ExtraStyles, variant, colorScheme, documentId, urlTransform, sanitizeSchema, }: AIMarkdownProps<TConfig, TRenderData>) => react_jsx_runtime.JSX.Element;
1234
+ declare const AIMarkdownComponent: <TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig, TRenderData extends AIMarkdownMetadata = AIMarkdownMetadata>({ streaming, content, fontSize, contentPreprocessors, customComponents, defaultConfig, config, metadata, Typography, ExtraStyles, variant, colorScheme, documentId, urlTransform, sanitizeSchema, }: AIMarkdownProps<TConfig, TRenderData>) => react.JSX.Element;
1193
1235
  declare const _default: typeof AIMarkdownComponent;
1194
1236
 
1195
1237
  export { type AIMDContentPreprocessor, type AIMarkdownColorScheme, type AIMarkdownCustomComponents, AIMarkdownDocuments, type AIMarkdownDocumentsProps, type AIMarkdownExtraStylesComponent, type AIMarkdownExtraStylesProps, type AIMarkdownMetadata, type AIMarkdownProps, type AIMarkdownRenderConfig, AIMarkdownRenderDisplayOptimizeAbility, AIMarkdownRenderExtraSyntax, type AIMarkdownRenderState, type AIMarkdownTypographyComponent, type AIMarkdownTypographyProps, type AIMarkdownVariant, type ChunkData, type FootnoteDef, type LinkDef, type PartialDeep, type RefKind, type RefRecord, type Registry, type SanitizeSchema, type UrlTransform, _default as default, defaultAIMarkdownRenderConfig, defaultUrlTransform, extendSanitizeSchema, useAIMarkdownMetadata, useAIMarkdownRenderState, useDocumentRegistry, useStableValue };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { JSX, ComponentType, PropsWithChildren, CSSProperties, FC } from 'react';
3
3
  import { Element, ElementContent } from 'hast';
4
4
  import { defaultSchema } from 'rehype-sanitize';
@@ -238,6 +238,27 @@ interface AIMarkdownRenderState<TConfig extends AIMarkdownRenderConfig = AIMarkd
238
238
  * always win.
239
239
  */
240
240
  documentId: string;
241
+ /**
242
+ * Whether {@link documentId} was EXPLICITLY supplied by the consumer (vs.
243
+ * auto-generated via `useId()`). This is the coordination signal — NOT
244
+ * `documentId` truthiness, which is always `true` because the provider
245
+ * auto-fills a fallback id for HTML/`clobberPrefix` purposes.
246
+ *
247
+ * `useDocumentRegistry` gates on this: an auto-generated id is unique by
248
+ * construction, so a chunk that didn't receive a `documentId` has nothing
249
+ * to coordinate with even when it sits inside `<AIMarkdownDocuments>`. It
250
+ * must take the standalone (registry === null) path, and this flag is the
251
+ * only thing that lets the registry hook tell "consumer wants coordination"
252
+ * apart from "we fabricated an id so the markup stays valid".
253
+ *
254
+ * Optional in the type ONLY so external callers that construct an
255
+ * `AIMarkdownRenderState` literal directly (mocks, fixtures) aren't broken
256
+ * by this internally-added field — the provider ALWAYS sets a concrete
257
+ * boolean, and internal consumers coerce a missing value to `false`
258
+ * (safe default: no coordination). Keeping it `?:` preserves source-level
259
+ * backward compatibility for the publicly-exported state type.
260
+ */
261
+ documentIdExplicit?: boolean;
241
262
  /**
242
263
  * Per-document URI-safe id prefix used by all clobberable attributes
243
264
  * (`id="…"` / `href="#…"`). Derived once by the provider and exposed here
@@ -818,8 +839,10 @@ type SanitizeSchema = typeof defaultSchema;
818
839
  * });
819
840
  * ```
820
841
  *
821
- * @remarks Allowing a protocol on `protocols.href` lets the URL through the
822
- * SECOND sanitize gate. The FIRST gate (`urlTransform`) must permit the
842
+ * @remarks Allowing a protocol on `protocols.href` lets the URL through
843
+ * Gate 1 (the schema-level per-protocol allowlist, which runs inside the
844
+ * rehype plugin chain). Gate 2 (`urlTransform`, the per-attribute rewriter
845
+ * that runs later at render time in `renderHastSubtree`) must permit the
823
846
  * same protocol independently — see the `urlTransform` prop on
824
847
  * `<AIMarkdown>` and the exported {@link defaultUrlTransform} for
825
848
  * composition. Keep the two protocol lists in sync.
@@ -1022,11 +1045,23 @@ declare const AIMarkdownDocuments: FC<AIMarkdownDocumentsProps>;
1022
1045
  /**
1023
1046
  * Returns the registry for the given `documentId`, or `null` if:
1024
1047
  * - `<AIMarkdown>` is not inside an `<AIMarkdownDocuments>` wrapper, OR
1025
- * - `documentId` is undefined / empty string.
1048
+ * - `documentId` is undefined / empty string, OR
1049
+ * - `documentIdExplicit` is `false` — i.e. the id was auto-generated rather
1050
+ * than supplied by the consumer.
1051
+ *
1052
+ * The `documentIdExplicit` gate is the crux of the standalone-vs-coordinated
1053
+ * decision. An auto-generated id (`useId()` fallback) is non-empty and unique
1054
+ * by construction, so a chunk carrying one has nothing to coordinate with even
1055
+ * inside the wrapper — it must run standalone. Without this gate, the mere
1056
+ * presence of `<AIMarkdownDocuments>` would drag every uncoordinated chunk
1057
+ * onto the cross-chunk registry path (subscribe / allocate / evict overhead)
1058
+ * for no behavioral gain. The flag defaults to `true` so external callers who
1059
+ * pass an id directly are treated as explicit (passing an id IS the intent to
1060
+ * coordinate); the internal renderer threads through `state.documentIdExplicit`.
1026
1061
  *
1027
1062
  * Callers should treat `null` as "no coordination; run standalone path."
1028
1063
  */
1029
- declare function useDocumentRegistry(documentId: string | undefined): Registry | null;
1064
+ declare function useDocumentRegistry(documentId: string | undefined, documentIdExplicit?: boolean): Registry | null;
1030
1065
 
1031
1066
  /**
1032
1067
  * Props for the `<AIMarkdown>` component.
@@ -1099,10 +1134,14 @@ interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRen
1099
1134
  */
1100
1135
  documentId?: string;
1101
1136
  /**
1102
- * Override the function that decides which URL protocols are allowed
1103
- * through the FIRST sanitization gate. The default allowlist mirrors
1104
- * `react-markdown` / GitHub: `http`, `https`, `irc`, `ircs`, `mailto`,
1105
- * `xmpp`. Anything else is rewritten to `''`.
1137
+ * Override the per-attribute URL rewriter (Gate 2 of the two-gate model).
1138
+ * Runs at render time during the hast traversal in `renderHastSubtree`,
1139
+ * after Gate 1 (`rehype-sanitize` schema) has already filtered URLs by
1140
+ * protocol allowlist in the rehype plugin chain.
1141
+ *
1142
+ * The default allowlist mirrors `react-markdown` / GitHub: `http`,
1143
+ * `https`, `irc`, `ircs`, `mailto`, `xmpp`. Anything else is rewritten
1144
+ * to `''`.
1106
1145
  *
1107
1146
  * **Recommended pattern**: compose with the exported
1108
1147
  * {@link defaultUrlTransform} so the built-in XSS protections survive,
@@ -1131,13 +1170,13 @@ interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRen
1131
1170
  * as a dependency. Defining the function inline (`urlTransform={(url) =>
1132
1171
  * …}`) creates a new closure on every parent render, discards the cache
1133
1172
  * for the entire markdown document on each render, and effectively
1134
- * disables Phase 5 memoization. In development the library will
1173
+ * disables block-level memoization. In development the library will
1135
1174
  * `console.warn` if it detects this pattern.
1136
1175
  *
1137
1176
  * Allowing a protocol here is necessary but **not sufficient** to render
1138
- * a link — the second gate (`rehype-sanitize`) also enforces its own
1139
- * protocol allowlist. See the `sanitizeSchema` prop on this component
1140
- * and the {@link extendSanitizeSchema} helper for the second gate.
1177
+ * a link — Gate 1 (`rehype-sanitize` schema) also enforces its own
1178
+ * protocol allowlist and runs first. See the `sanitizeSchema` prop on
1179
+ * this component and the {@link extendSanitizeSchema} helper for Gate 1.
1141
1180
  *
1142
1181
  * **API stability**: the `UrlTransform` type tracks the upstream
1143
1182
  * `react-markdown` shape and may change with its major versions.
@@ -1146,10 +1185,13 @@ interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRen
1146
1185
  /**
1147
1186
  * Override the `rehype-sanitize` schema applied to the rendered output.
1148
1187
  * The library default extends `rehype-sanitize`'s own `defaultSchema`
1149
- * with the `<mark>` tag, KaTeX class names, and the cross-chunk
1150
- * coordination tags (`cross-chunk-link`, `cross-chunk-image`,
1151
- * `footnote-sup`). The default is not exported as a value — see
1152
- * {@link extendSanitizeSchema} for how to inspect or extend it safely.
1188
+ * with the `<mark>` tag, the `math-inline` / `math-display` className
1189
+ * markers `remark-math` emits on `<code>` (KaTeX's own output classes
1190
+ * survive separately because `rehype-katex` runs after `rehype-sanitize`),
1191
+ * and the cross-chunk coordination tags (`cross-chunk-link`,
1192
+ * `cross-chunk-image`, `footnote-sup`). The default is not exported as a
1193
+ * value — see {@link extendSanitizeSchema} for how to inspect or extend
1194
+ * it safely.
1153
1195
  *
1154
1196
  * **Recommended pattern**: build the schema with {@link extendSanitizeSchema}
1155
1197
  * (mutate-and-return form) so those library additions stay intact, and
@@ -1189,7 +1231,7 @@ interface AIMarkdownProps<TConfig extends AIMarkdownRenderConfig = AIMarkdownRen
1189
1231
  * Root component that preprocesses markdown content and renders it through
1190
1232
  * a configurable remark/rehype pipeline wrapped in typography and style layers.
1191
1233
  */
1192
- declare const AIMarkdownComponent: <TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig, TRenderData extends AIMarkdownMetadata = AIMarkdownMetadata>({ streaming, content, fontSize, contentPreprocessors, customComponents, defaultConfig, config, metadata, Typography, ExtraStyles, variant, colorScheme, documentId, urlTransform, sanitizeSchema, }: AIMarkdownProps<TConfig, TRenderData>) => react_jsx_runtime.JSX.Element;
1234
+ declare const AIMarkdownComponent: <TConfig extends AIMarkdownRenderConfig = AIMarkdownRenderConfig, TRenderData extends AIMarkdownMetadata = AIMarkdownMetadata>({ streaming, content, fontSize, contentPreprocessors, customComponents, defaultConfig, config, metadata, Typography, ExtraStyles, variant, colorScheme, documentId, urlTransform, sanitizeSchema, }: AIMarkdownProps<TConfig, TRenderData>) => react.JSX.Element;
1193
1235
  declare const _default: typeof AIMarkdownComponent;
1194
1236
 
1195
1237
  export { type AIMDContentPreprocessor, type AIMarkdownColorScheme, type AIMarkdownCustomComponents, AIMarkdownDocuments, type AIMarkdownDocumentsProps, type AIMarkdownExtraStylesComponent, type AIMarkdownExtraStylesProps, type AIMarkdownMetadata, type AIMarkdownProps, type AIMarkdownRenderConfig, AIMarkdownRenderDisplayOptimizeAbility, AIMarkdownRenderExtraSyntax, type AIMarkdownRenderState, type AIMarkdownTypographyComponent, type AIMarkdownTypographyProps, type AIMarkdownVariant, type ChunkData, type FootnoteDef, type LinkDef, type PartialDeep, type RefKind, type RefRecord, type Registry, type SanitizeSchema, type UrlTransform, _default as default, defaultAIMarkdownRenderConfig, defaultUrlTransform, extendSanitizeSchema, useAIMarkdownMetadata, useAIMarkdownRenderState, useDocumentRegistry, useStableValue };