@sanity/agent-directives 0.0.17 → 0.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 +33 -8
- package/dist/_chunks-dts/index.d.ts +6 -0
- package/dist/_chunks-dts/index.d.ts.map +1 -1
- package/dist/_chunks-es/formatters.js +1 -0
- package/dist/_chunks-es/formatters.js.map +1 -1
- package/dist/lib/react.d.ts +41 -4
- package/dist/lib/react.d.ts.map +1 -1
- package/dist/lib/react.js +24 -8
- package/dist/lib/react.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,9 +14,10 @@ pnpm add @sanity/agent-directives
|
|
|
14
14
|
// kit.ts
|
|
15
15
|
import { createDirectiveKit } from "@sanity/agent-directives/react";
|
|
16
16
|
|
|
17
|
-
export const { defineDirective } =
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
export const { defineDirective, remarkPlugin } =
|
|
18
|
+
createDirectiveKit<Application>({
|
|
19
|
+
useApplication: (source) => useThreadApplication(source),
|
|
20
|
+
});
|
|
20
21
|
|
|
21
22
|
// directives/Document.tsx
|
|
22
23
|
export const DocumentDirective = defineDirective(
|
|
@@ -36,7 +37,7 @@ export const ChangesDirective = defineDirective(
|
|
|
36
37
|
);
|
|
37
38
|
|
|
38
39
|
// AgentMessage.tsx
|
|
39
|
-
import {
|
|
40
|
+
import { remarkPlugin } from "./kit";
|
|
40
41
|
import ReactMarkdown from "react-markdown";
|
|
41
42
|
|
|
42
43
|
const components = {
|
|
@@ -47,16 +48,40 @@ const components = {
|
|
|
47
48
|
|
|
48
49
|
function AgentMessage({ content }: { content: string }) {
|
|
49
50
|
return (
|
|
50
|
-
<ReactMarkdown
|
|
51
|
-
remarkPlugins={[remarkAgentDirectives]}
|
|
52
|
-
components={components}
|
|
53
|
-
>
|
|
51
|
+
<ReactMarkdown remarkPlugins={[remarkPlugin]} components={components}>
|
|
54
52
|
{content}
|
|
55
53
|
</ReactMarkdown>
|
|
56
54
|
);
|
|
57
55
|
}
|
|
58
56
|
```
|
|
59
57
|
|
|
58
|
+
### Excluding Directives from Stack Grouping
|
|
59
|
+
|
|
60
|
+
By default, consecutive leaf directives are grouped into a `DirectivesStack` for layout purposes. You can exclude specific directives from this grouping:
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
// kit.ts
|
|
64
|
+
export const { defineDirective, remarkPlugin } =
|
|
65
|
+
createDirectiveKit<Application>({
|
|
66
|
+
useApplication: (source) => useThreadApplication(source),
|
|
67
|
+
excludeFromStack: ["set"], // These directives won't be grouped
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Excluded directives will render individually instead of being grouped together. This is useful for directives that need special layout treatment or shouldn't be visually grouped with other directives.
|
|
72
|
+
|
|
73
|
+
**Alternative approach:** You can also configure this directly on the remark plugin:
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import { remarkAgentDirectives } from "@sanity/agent-directives/react";
|
|
77
|
+
|
|
78
|
+
<ReactMarkdown
|
|
79
|
+
remarkPlugins={[[remarkAgentDirectives, { excludeFromStack: ["set"] }]]}
|
|
80
|
+
>
|
|
81
|
+
{content}
|
|
82
|
+
</ReactMarkdown>;
|
|
83
|
+
```
|
|
84
|
+
|
|
60
85
|
## Server-side Usage
|
|
61
86
|
|
|
62
87
|
```ts
|
|
@@ -58,14 +58,17 @@ declare const ConfirmDirectiveSchema: z.ZodObject<{
|
|
|
58
58
|
toolCallId: z.ZodString;
|
|
59
59
|
runId: z.ZodString;
|
|
60
60
|
toolName: z.ZodString;
|
|
61
|
+
source: z.ZodString;
|
|
61
62
|
data: z.ZodString;
|
|
62
63
|
}, "strip", z.ZodTypeAny, {
|
|
64
|
+
source: string;
|
|
63
65
|
status: "pending" | "approved" | "cancelled";
|
|
64
66
|
toolCallId: string;
|
|
65
67
|
runId: string;
|
|
66
68
|
toolName: string;
|
|
67
69
|
data: string;
|
|
68
70
|
}, {
|
|
71
|
+
source: string;
|
|
69
72
|
status: "pending" | "approved" | "cancelled";
|
|
70
73
|
toolCallId: string;
|
|
71
74
|
runId: string;
|
|
@@ -132,14 +135,17 @@ declare const DirectiveSchemas: {
|
|
|
132
135
|
toolCallId: z.ZodString;
|
|
133
136
|
runId: z.ZodString;
|
|
134
137
|
toolName: z.ZodString;
|
|
138
|
+
source: z.ZodString;
|
|
135
139
|
data: z.ZodString;
|
|
136
140
|
}, "strip", z.ZodTypeAny, {
|
|
141
|
+
source: string;
|
|
137
142
|
status: "pending" | "approved" | "cancelled";
|
|
138
143
|
toolCallId: string;
|
|
139
144
|
runId: string;
|
|
140
145
|
toolName: string;
|
|
141
146
|
data: string;
|
|
142
147
|
}, {
|
|
148
|
+
source: string;
|
|
143
149
|
status: "pending" | "approved" | "cancelled";
|
|
144
150
|
toolCallId: string;
|
|
145
151
|
runId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/_internal/index.ts"],"mappings":";cAKa,uBAAA,EAAuB,CAAA,CAAA,SAAA;;;;;;;;;;;;;cAMvB,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;;;;;;cAKtB,uBAAA,EAAuB,CAAA,CAAA,SAAA;;;;;;;cAIvB,mCAAA,EAAmC,CAAA,CAAA,SAAA;;;;;;;cAInC,kBAAA,EAAkB,CAAA,CAAA,SAAA;;;;;;;cAIlB,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;;;;;;cAKtB,sBAAA,EAAsB,CAAA,CAAA,SAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/_internal/index.ts"],"mappings":";cAKa,uBAAA,EAAuB,CAAA,CAAA,SAAA;;;;;;;;;;;;;cAMvB,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;;;;;;cAKtB,uBAAA,EAAuB,CAAA,CAAA,SAAA;;;;;;;cAIvB,mCAAA,EAAmC,CAAA,CAAA,SAAA;;;;;;;cAInC,kBAAA,EAAkB,CAAA,CAAA,SAAA;;;;;;;cAIlB,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;;;;;;cAKtB,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;cAStB,gBAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAUA,eAAA;EAAA;;;;;;;;KAcD,aAAA,WAAwB,eAAA,eAA8B,eAAA;AAAA,KAEtD,sBAAA,GAAyB,CAAA,CAAE,KAAA,QAAa,uBAAA;AAAA,KACxC,qBAAA,GAAwB,CAAA,CAAE,KAAA,QAAa,sBAAA;AAAA,KACvC,sBAAA,GAAyB,CAAA,CAAE,KAAA,QAAa,uBAAA;AAAA,KACxC,iBAAA,GAAoB,CAAA,CAAE,KAAA,QAAa,kBAAA;AAAA,KACnC,qBAAA,GAAwB,CAAA,CAAE,KAAA,QAAa,sBAAA;AAAA,KACvC,kCAAA,GAAqC,CAAA,CAAE,KAAA,QAAa,mCAAA;AAAA,KACpD,qBAAA,GAAwB,CAAA,CAAE,KAAA,QAAa,sBAAA;AAAA,UAElC,iBAAA;EACf,QAAA,EAAU,sBAAA;EACV,OAAA,EAAS,qBAAA;EACT,QAAA,EAAU,sBAAA;EACV,GAAA,EAAK,iBAAA;EACL,OAAA,EAAS,qBAAA;EACT,oBAAA,EAAsB,kCAAA;EACtB,OAAA,EAAS,qBAAA;AAAA;AAAA,UAGM,sBAAA;;;;;EAKf,eAAA;;EAEA,mBAAA;AAAA;AAAA,iBA8Bc,eAAA,CACd,IAAA,EAAM,aAAA,EACN,KAAA,EAAO,MAAA,mBACP,KAAA;AAAA,iBASc,uBAAA,CAAwB,KAAA,EAAO,sBAAA,EAAwB,KAAA;AAAA,iBAIvD,sBAAA,CAAuB,KAAA,EAAO,qBAAA,EAAuB,KAAA;AAAA,iBAIrD,uBAAA,CAAwB,KAAA,EAAO,sBAAA;AAAA,iBAI/B,kBAAA,CAAmB,KAAA,EAAO,iBAAA;AAAA,iBAI1B,sBAAA,CAAuB,KAAA,EAAO,qBAAA;AAAA,iBAI9B,mCAAA,CACd,KAAA,EAAO,kCAAA;AAAA,iBAKO,sBAAA,CAAuB,KAAA,EAAO,qBAAA,EAAuB,KAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatters.js","sources":["../../src/_internal/index.ts"],"sourcesContent":["// This internal module contains all shared code that both the main index\n// and sub-exports can import without causing self-referencing issues with pkg-utils\n\nimport { z } from 'zod'\n\nexport const DocumentDirectiveSchema = z.object({\n id: z.string(),\n type: z.string().optional(),\n source: z.string().optional(),\n})\n\nexport const ReleaseDirectiveSchema = z.object({\n id: z.string(),\n source: z.string().optional(),\n})\n\nexport const ResourceDirectiveSchema = z.object({\n source: z.string(),\n})\n\nexport const RequestProjectAccessDirectiveSchema = z.object({\n source: z.string(),\n})\n\nexport const SetDirectiveSchema = z.object({\n id: z.string(),\n})\n\nexport const ChangesDirectiveSchema = z.object({\n createdCount: z.coerce.number().min(0),\n updatedCount: z.coerce.number().min(0),\n})\n\nexport const ConfirmDirectiveSchema = z.object({\n status: z.enum(['pending', 'approved', 'cancelled']),\n toolCallId: z.string(),\n runId: z.string(),\n toolName: z.string(),\n data: z.string(), // base64-encoded JSON, typed per toolName\n})\n\nexport const DirectiveSchemas = {\n document: DocumentDirectiveSchema,\n release: ReleaseDirectiveSchema,\n resource: ResourceDirectiveSchema,\n set: SetDirectiveSchema,\n changes: ChangesDirectiveSchema,\n requestProjectAccess: RequestProjectAccessDirectiveSchema,\n confirm: ConfirmDirectiveSchema,\n} as const\n\nexport const DIRECTIVE_NAMES = {\n document: 'document',\n release: 'release',\n resource: 'resource',\n set: 'set',\n changes: 'changes',\n requestProjectAccess: 'requestProjectAccess',\n confirm: 'confirm',\n} as const\n\nexport const DIRECTIVE_TYPES = ['textDirective', 'leafDirective', 'containerDirective'] as const\n\nexport type DirectiveType = (typeof DIRECTIVE_TYPES)[number]\n\nexport type DirectiveName = (typeof DIRECTIVE_NAMES)[keyof typeof DIRECTIVE_NAMES]\n\nexport type DocumentDirectiveProps = z.infer<typeof DocumentDirectiveSchema>\nexport type ReleaseDirectiveProps = z.infer<typeof ReleaseDirectiveSchema>\nexport type ResourceDirectiveProps = z.infer<typeof ResourceDirectiveSchema>\nexport type SetDirectiveProps = z.infer<typeof SetDirectiveSchema>\nexport type ChangesDirectiveProps = z.infer<typeof ChangesDirectiveSchema>\nexport type RequestProjectAccessDirectiveProps = z.infer<typeof RequestProjectAccessDirectiveSchema>\nexport type ConfirmDirectiveProps = z.infer<typeof ConfirmDirectiveSchema>\n\nexport interface DirectivePropsMap {\n document: DocumentDirectiveProps\n release: ReleaseDirectiveProps\n resource: ResourceDirectiveProps\n set: SetDirectiveProps\n changes: ChangesDirectiveProps\n requestProjectAccess: RequestProjectAccessDirectiveProps\n confirm: ConfirmDirectiveProps\n}\n\nexport interface DefineDirectiveOptions {\n /**\n * Whether this directive requires context/application to render.\n * If true (default), the directive won't render without context.\n */\n requiresContext?: boolean\n /** @deprecated Use `requiresContext` instead */\n requiresApplication?: boolean\n}\n\n// Label content pattern: matches non-bracket chars or single-level nested [...]\n// e.g. \"Guide [E-commerce edition]\" matches, but won't span across \"] other text [\"\nconst LABEL = '(?:[^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])*'\n\n// Matches block directives: ::name{attrs} or ::name[label]{attrs}\n// Captures: (1) name, (2) label or undefined, (3) attribute string\nexport const BLOCK_DIRECTIVE = new RegExp(`::([a-zA-Z]\\\\w*)(?:\\\\[(${LABEL})\\\\])?\\\\{([^}]*)\\\\}`)\n\n// Matches inline directives: :name[label]{attrs}\n// Captures: (1) name, (2) label, (3) attribute string\nexport const INLINE_DIRECTIVE = new RegExp(`:([a-zA-Z]\\\\w*)\\\\[(${LABEL})\\\\]\\\\{([^}]*)\\\\}`)\n\nexport function parseDirectiveAttributes(attrString: string): Record<string, string> {\n const attrs: Record<string, string> = {}\n for (const match of attrString.matchAll(/(\\w+)=\"([^\"]*)\"/g)) {\n attrs[match[1]] = match[2]\n }\n return attrs\n}\n\nfunction buildAttributes(params: Record<string, unknown>): string {\n return Object.entries(params)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([key, value]) => `${key}=\"${value}\"`)\n .join(' ')\n}\n\nexport function formatDirective(\n name: DirectiveName,\n props: Record<string, unknown>,\n label?: string,\n): string {\n const attrs = buildAttributes(props)\n if (label) {\n return attrs ? `:${name}[${label}]{${attrs}}` : `:${name}[${label}]`\n }\n return attrs ? `::${name}{${attrs}}` : `::${name}`\n}\n\nexport function createDocumentDirective(props: DocumentDirectiveProps, label?: string): string {\n return formatDirective(DIRECTIVE_NAMES.document, props, label)\n}\n\nexport function createReleaseDirective(props: ReleaseDirectiveProps, label?: string): string {\n return formatDirective(DIRECTIVE_NAMES.release, props, label)\n}\n\nexport function createResourceDirective(props: ResourceDirectiveProps): string {\n return formatDirective(DIRECTIVE_NAMES.resource, props)\n}\n\nexport function createSetDirective(props: SetDirectiveProps): string {\n return formatDirective(DIRECTIVE_NAMES.set, props)\n}\n\nexport function createChangesDirective(props: ChangesDirectiveProps): string {\n return formatDirective(DIRECTIVE_NAMES.changes, props)\n}\n\nexport function createRequestProjectAccessDirective(\n props: RequestProjectAccessDirectiveProps,\n): string {\n return formatDirective(DIRECTIVE_NAMES.requestProjectAccess, props)\n}\n\nexport function createConfirmDirective(props: ConfirmDirectiveProps, label?: string): string {\n return formatDirective(DIRECTIVE_NAMES.confirm, props, label)\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"formatters.js","sources":["../../src/_internal/index.ts"],"sourcesContent":["// This internal module contains all shared code that both the main index\n// and sub-exports can import without causing self-referencing issues with pkg-utils\n\nimport { z } from 'zod'\n\nexport const DocumentDirectiveSchema = z.object({\n id: z.string(),\n type: z.string().optional(),\n source: z.string().optional(),\n})\n\nexport const ReleaseDirectiveSchema = z.object({\n id: z.string(),\n source: z.string().optional(),\n})\n\nexport const ResourceDirectiveSchema = z.object({\n source: z.string(),\n})\n\nexport const RequestProjectAccessDirectiveSchema = z.object({\n source: z.string(),\n})\n\nexport const SetDirectiveSchema = z.object({\n id: z.string(),\n})\n\nexport const ChangesDirectiveSchema = z.object({\n createdCount: z.coerce.number().min(0),\n updatedCount: z.coerce.number().min(0),\n})\n\nexport const ConfirmDirectiveSchema = z.object({\n status: z.enum(['pending', 'approved', 'cancelled']),\n toolCallId: z.string(),\n runId: z.string(),\n toolName: z.string(),\n source: z.string(),\n data: z.string(), // base64-encoded JSON, typed per toolName\n})\n\nexport const DirectiveSchemas = {\n document: DocumentDirectiveSchema,\n release: ReleaseDirectiveSchema,\n resource: ResourceDirectiveSchema,\n set: SetDirectiveSchema,\n changes: ChangesDirectiveSchema,\n requestProjectAccess: RequestProjectAccessDirectiveSchema,\n confirm: ConfirmDirectiveSchema,\n} as const\n\nexport const DIRECTIVE_NAMES = {\n document: 'document',\n release: 'release',\n resource: 'resource',\n set: 'set',\n changes: 'changes',\n requestProjectAccess: 'requestProjectAccess',\n confirm: 'confirm',\n} as const\n\nexport const DIRECTIVE_TYPES = ['textDirective', 'leafDirective', 'containerDirective'] as const\n\nexport type DirectiveType = (typeof DIRECTIVE_TYPES)[number]\n\nexport type DirectiveName = (typeof DIRECTIVE_NAMES)[keyof typeof DIRECTIVE_NAMES]\n\nexport type DocumentDirectiveProps = z.infer<typeof DocumentDirectiveSchema>\nexport type ReleaseDirectiveProps = z.infer<typeof ReleaseDirectiveSchema>\nexport type ResourceDirectiveProps = z.infer<typeof ResourceDirectiveSchema>\nexport type SetDirectiveProps = z.infer<typeof SetDirectiveSchema>\nexport type ChangesDirectiveProps = z.infer<typeof ChangesDirectiveSchema>\nexport type RequestProjectAccessDirectiveProps = z.infer<typeof RequestProjectAccessDirectiveSchema>\nexport type ConfirmDirectiveProps = z.infer<typeof ConfirmDirectiveSchema>\n\nexport interface DirectivePropsMap {\n document: DocumentDirectiveProps\n release: ReleaseDirectiveProps\n resource: ResourceDirectiveProps\n set: SetDirectiveProps\n changes: ChangesDirectiveProps\n requestProjectAccess: RequestProjectAccessDirectiveProps\n confirm: ConfirmDirectiveProps\n}\n\nexport interface DefineDirectiveOptions {\n /**\n * Whether this directive requires context/application to render.\n * If true (default), the directive won't render without context.\n */\n requiresContext?: boolean\n /** @deprecated Use `requiresContext` instead */\n requiresApplication?: boolean\n}\n\n// Label content pattern: matches non-bracket chars or single-level nested [...]\n// e.g. \"Guide [E-commerce edition]\" matches, but won't span across \"] other text [\"\nconst LABEL = '(?:[^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])*'\n\n// Matches block directives: ::name{attrs} or ::name[label]{attrs}\n// Captures: (1) name, (2) label or undefined, (3) attribute string\nexport const BLOCK_DIRECTIVE = new RegExp(`::([a-zA-Z]\\\\w*)(?:\\\\[(${LABEL})\\\\])?\\\\{([^}]*)\\\\}`)\n\n// Matches inline directives: :name[label]{attrs}\n// Captures: (1) name, (2) label, (3) attribute string\nexport const INLINE_DIRECTIVE = new RegExp(`:([a-zA-Z]\\\\w*)\\\\[(${LABEL})\\\\]\\\\{([^}]*)\\\\}`)\n\nexport function parseDirectiveAttributes(attrString: string): Record<string, string> {\n const attrs: Record<string, string> = {}\n for (const match of attrString.matchAll(/(\\w+)=\"([^\"]*)\"/g)) {\n attrs[match[1]] = match[2]\n }\n return attrs\n}\n\nfunction buildAttributes(params: Record<string, unknown>): string {\n return Object.entries(params)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([key, value]) => `${key}=\"${value}\"`)\n .join(' ')\n}\n\nexport function formatDirective(\n name: DirectiveName,\n props: Record<string, unknown>,\n label?: string,\n): string {\n const attrs = buildAttributes(props)\n if (label) {\n return attrs ? `:${name}[${label}]{${attrs}}` : `:${name}[${label}]`\n }\n return attrs ? `::${name}{${attrs}}` : `::${name}`\n}\n\nexport function createDocumentDirective(props: DocumentDirectiveProps, label?: string): string {\n return formatDirective(DIRECTIVE_NAMES.document, props, label)\n}\n\nexport function createReleaseDirective(props: ReleaseDirectiveProps, label?: string): string {\n return formatDirective(DIRECTIVE_NAMES.release, props, label)\n}\n\nexport function createResourceDirective(props: ResourceDirectiveProps): string {\n return formatDirective(DIRECTIVE_NAMES.resource, props)\n}\n\nexport function createSetDirective(props: SetDirectiveProps): string {\n return formatDirective(DIRECTIVE_NAMES.set, props)\n}\n\nexport function createChangesDirective(props: ChangesDirectiveProps): string {\n return formatDirective(DIRECTIVE_NAMES.changes, props)\n}\n\nexport function createRequestProjectAccessDirective(\n props: RequestProjectAccessDirectiveProps,\n): string {\n return formatDirective(DIRECTIVE_NAMES.requestProjectAccess, props)\n}\n\nexport function createConfirmDirective(props: ConfirmDirectiveProps, label?: string): string {\n return formatDirective(DIRECTIVE_NAMES.confirm, props, label)\n}\n"],"names":[],"mappings":"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"}
|
package/dist/lib/react.d.ts
CHANGED
|
@@ -16,6 +16,18 @@ type DirectiveRenderProps<TName extends DirectiveName, TApplication = undefined,
|
|
|
16
16
|
type DirectiveComponentProps<TName extends DirectiveName> = DirectiveProps<TName> & {
|
|
17
17
|
source?: string;
|
|
18
18
|
} & NodeProps;
|
|
19
|
+
interface RemarkAgentDirectivesOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Directive names to exclude from DirectivesStack grouping.
|
|
22
|
+
* These directives will be rendered separately instead of grouped with consecutive leaf directives.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* remarkAgentDirectives({ excludeFromStack: ['thinking', 'resource'] })
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
excludeFromStack?: DirectiveName[];
|
|
30
|
+
}
|
|
19
31
|
/**
|
|
20
32
|
* Remark plugin for agent directive support.
|
|
21
33
|
* Parses and transforms directive syntax into React components.
|
|
@@ -28,25 +40,49 @@ type DirectiveComponentProps<TName extends DirectiveName> = DirectiveProps<TName
|
|
|
28
40
|
* {content}
|
|
29
41
|
* </ReactMarkdown>
|
|
30
42
|
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* // Exclude specific directives from DirectivesStack grouping
|
|
47
|
+
* <ReactMarkdown remarkPlugins={[[remarkAgentDirectives, { excludeFromStack: ['thinking'] }]]}>
|
|
48
|
+
* {content}
|
|
49
|
+
* </ReactMarkdown>
|
|
50
|
+
* ```
|
|
31
51
|
*/
|
|
32
|
-
declare function remarkAgentDirectives(this: Processor): (tree: Node) => void;
|
|
52
|
+
declare function remarkAgentDirectives(this: Processor, options?: RemarkAgentDirectivesOptions): (tree: Node) => void;
|
|
33
53
|
interface DirectiveKitOptions<TApplication> {
|
|
34
54
|
useApplication?: (source: string | undefined) => TApplication | undefined;
|
|
35
55
|
renderApplicationUnavailable?: ComponentType<{
|
|
36
56
|
name: DirectiveName;
|
|
37
57
|
source?: string;
|
|
38
58
|
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Directive names to exclude from DirectivesStack grouping.
|
|
61
|
+
* These directives will be rendered separately instead of grouped with consecutive leaf directives.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* createDirectiveKit({ excludeFromStack: ['thinking', 'resource'] })
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
excludeFromStack?: DirectiveName[];
|
|
39
69
|
}
|
|
40
70
|
/**
|
|
41
|
-
* Creates a directive kit with application injection.
|
|
71
|
+
* Creates a directive kit with application injection and a pre-configured remark plugin.
|
|
42
72
|
*
|
|
43
73
|
* @example
|
|
44
74
|
* ```tsx
|
|
45
75
|
* // kit.ts
|
|
46
|
-
* export const { defineDirective } = createDirectiveKit<Application>({
|
|
76
|
+
* export const { defineDirective, remarkPlugin } = createDirectiveKit<Application>({
|
|
47
77
|
* useApplication: (source) => useThreadApplication(source),
|
|
78
|
+
* excludeFromStack: ['thinking'],
|
|
48
79
|
* })
|
|
49
80
|
*
|
|
81
|
+
* // Usage in component
|
|
82
|
+
* <ReactMarkdown remarkPlugins={[remarkPlugin]}>
|
|
83
|
+
* {content}
|
|
84
|
+
* </ReactMarkdown>
|
|
85
|
+
*
|
|
50
86
|
* // Document.tsx
|
|
51
87
|
* export const DocumentDirective = defineDirective('document', ({ id, application }) => {
|
|
52
88
|
* return <DocumentCard id={id} app={application} />
|
|
@@ -55,6 +91,7 @@ interface DirectiveKitOptions<TApplication> {
|
|
|
55
91
|
*/
|
|
56
92
|
declare function createDirectiveKit<TApplication = undefined>(options?: DirectiveKitOptions<TApplication>): {
|
|
57
93
|
defineDirective: <TName extends DirectiveName, TRequiresApplication extends boolean = true>(name: TName, render: (props: DirectiveRenderProps<TName, TApplication, TRequiresApplication>) => ReactNode, directiveOptions?: DefineDirectiveOptions) => ComponentType<DirectiveComponentProps<TName>>;
|
|
94
|
+
remarkPlugin: (this: Processor) => (tree: Node) => void;
|
|
58
95
|
};
|
|
59
|
-
export { type DefineDirectiveOptions, DirectiveComponentProps, DirectiveKitOptions, DirectiveRenderProps, NodeProps, createDirectiveKit, remarkAgentDirectives };
|
|
96
|
+
export { type DefineDirectiveOptions, DirectiveComponentProps, DirectiveKitOptions, DirectiveRenderProps, NodeProps, RemarkAgentDirectivesOptions, createDirectiveKit, remarkAgentDirectives };
|
|
60
97
|
//# sourceMappingURL=react.d.ts.map
|
package/dist/lib/react.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.ts","names":[],"sources":["../../src/lib/react.tsx"],"mappings":";;;;KAuBK,cAAA,WAAyB,aAAA,IAAiB,iBAAA,CAAkB,CAAA;AAAA,UAEhD,SAAA;EACf,IAAA;IAAS,UAAA,GAAa,MAAA;EAAA;AAAA;AAAA,KAGZ,oBAAA,eACI,aAAA,2EAGZ,cAAA,CAAe,KAAA;EACjB,QAAA;AAAA,KACG,oBAAA,gBACC,YAAA;EAEI,WAAA,EAAa,YAAA;AAAA;AAAA,KAKX,uBAAA,eAAsC,aAAA,IAAiB,cAAA,CAAe,KAAA;EAChF,MAAA;AAAA,IACE,SAAA;
|
|
1
|
+
{"version":3,"file":"react.d.ts","names":[],"sources":["../../src/lib/react.tsx"],"mappings":";;;;KAuBK,cAAA,WAAyB,aAAA,IAAiB,iBAAA,CAAkB,CAAA;AAAA,UAEhD,SAAA;EACf,IAAA;IAAS,UAAA,GAAa,MAAA;EAAA;AAAA;AAAA,KAGZ,oBAAA,eACI,aAAA,2EAGZ,cAAA,CAAe,KAAA;EACjB,QAAA;AAAA,KACG,oBAAA,gBACC,YAAA;EAEI,WAAA,EAAa,YAAA;AAAA;AAAA,KAKX,uBAAA,eAAsC,aAAA,IAAiB,cAAA,CAAe,KAAA;EAChF,MAAA;AAAA,IACE,SAAA;AAAA,UA0Ca,4BAAA;EA9DS;;;;;;;;AAI1B;EAoEE,gBAAA,GAAmB,aAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;iBAuPL,qBAAA,CAAsB,IAAA,EAAM,SAAA,EAAW,OAAA,GAAU,4BAAA,IAA4B,IAAA,EAtO7E,IAAA;AAAA,UAwPC,mBAAA;EACf,cAAA,IAAkB,MAAA,yBAA+B,YAAA;EACjD,4BAAA,GAA+B,aAAA;IAC7B,IAAA,EAAM,aAAA;IACN,MAAA;EAAA;EAjUS;;;;;;;;;EA4UX,gBAAA,GAAmB,aAAA;AAAA;;;;;AAjCrB;;;;;;;;;;;;;;;;AAkBA;;iBAwCgB,kBAAA,0BAAA,CACd,OAAA,GAAS,mBAAA,CAAoB,YAAA;kCAKb,aAAA,+CACsB,IAAA,EAE9B,KAAA,EAAK,MAAA,GACF,KAAA,EAAO,oBAAA,CAAqB,KAAA,EAAO,YAAA,EAAc,oBAAA,MAA0B,SAAA,EAAS,gBAAA,GAC3E,sBAAA,KACjB,aAAA,CAAc,uBAAA,CAAwB,KAAA;uBA0Cb,SAAA,MAAS,IAAA,EAtVvB,IAAA;AAAA"}
|
package/dist/lib/react.js
CHANGED
|
@@ -12,7 +12,8 @@ const isDirectiveNode = (node) => "name" in node && typeof node.name == "string"
|
|
|
12
12
|
function getTextContent(node) {
|
|
13
13
|
return typeof node.value == "string" ? node.value : node.children ? node.children.map((child) => getTextContent(child)).join("") : "";
|
|
14
14
|
}
|
|
15
|
-
function remarkDirectivesTransform() {
|
|
15
|
+
function remarkDirectivesTransform(options = {}) {
|
|
16
|
+
const { excludeFromStack = [] } = options, excludeSet = new Set(excludeFromStack);
|
|
16
17
|
return (tree) => {
|
|
17
18
|
visit(
|
|
18
19
|
tree,
|
|
@@ -39,7 +40,13 @@ function remarkDirectivesTransform() {
|
|
|
39
40
|
type: "leafDirective",
|
|
40
41
|
name,
|
|
41
42
|
attributes: parseDirectiveAttributes(attrsString),
|
|
42
|
-
children: label ? [
|
|
43
|
+
children: label ? [
|
|
44
|
+
{
|
|
45
|
+
type: "text",
|
|
46
|
+
name: "",
|
|
47
|
+
value: label
|
|
48
|
+
}
|
|
49
|
+
] : []
|
|
43
50
|
}, parentNode = parent;
|
|
44
51
|
parentNode?.children && typeof index == "number" && (parentNode.children[index] = directiveNode);
|
|
45
52
|
}), visit(tree, "tableCell", (node) => {
|
|
@@ -55,7 +62,13 @@ function remarkDirectivesTransform() {
|
|
|
55
62
|
type: "textDirective",
|
|
56
63
|
name,
|
|
57
64
|
attributes: parseDirectiveAttributes(attrsString),
|
|
58
|
-
children: label ? [
|
|
65
|
+
children: label ? [
|
|
66
|
+
{
|
|
67
|
+
type: "text",
|
|
68
|
+
name: "",
|
|
69
|
+
value: label
|
|
70
|
+
}
|
|
71
|
+
] : []
|
|
59
72
|
});
|
|
60
73
|
}
|
|
61
74
|
}), visit(tree, "tableCell", (node) => {
|
|
@@ -83,7 +96,7 @@ function remarkDirectivesTransform() {
|
|
|
83
96
|
const newChildren = [];
|
|
84
97
|
let group = [];
|
|
85
98
|
for (const child of dirNode.children)
|
|
86
|
-
isDirectiveNode(child) && child.type === "leafDirective" ? group.push(child) : (group.length > 0 && (newChildren.push({
|
|
99
|
+
isDirectiveNode(child) && child.type === "leafDirective" && !excludeSet.has(child.name) ? group.push(child) : (group.length > 0 && (newChildren.push({
|
|
87
100
|
type: "leafDirective",
|
|
88
101
|
name: "DirectivesStack",
|
|
89
102
|
data: { hName: "DirectivesStack" },
|
|
@@ -106,12 +119,12 @@ function remarkDirectivesTransform() {
|
|
|
106
119
|
});
|
|
107
120
|
};
|
|
108
121
|
}
|
|
109
|
-
function remarkAgentDirectives() {
|
|
122
|
+
function remarkAgentDirectives(options) {
|
|
110
123
|
const data = this.data();
|
|
111
|
-
return data.micromarkExtensions || (data.micromarkExtensions = []), data.fromMarkdownExtensions || (data.fromMarkdownExtensions = []), data.toMarkdownExtensions || (data.toMarkdownExtensions = []), data.micromarkExtensions.push(directive()), data.fromMarkdownExtensions.push(directiveFromMarkdown()), data.toMarkdownExtensions.push(directiveToMarkdown()), remarkDirectivesTransform();
|
|
124
|
+
return data.micromarkExtensions || (data.micromarkExtensions = []), data.fromMarkdownExtensions || (data.fromMarkdownExtensions = []), data.toMarkdownExtensions || (data.toMarkdownExtensions = []), data.micromarkExtensions.push(directive()), data.fromMarkdownExtensions.push(directiveFromMarkdown()), data.toMarkdownExtensions.push(directiveToMarkdown()), remarkDirectivesTransform(options);
|
|
112
125
|
}
|
|
113
126
|
function createDirectiveKit(options = {}) {
|
|
114
|
-
const { useApplication, renderApplicationUnavailable: Unavailable } = options;
|
|
127
|
+
const { useApplication, renderApplicationUnavailable: Unavailable, excludeFromStack } = options;
|
|
115
128
|
function defineDirective(name, render, directiveOptions = {}) {
|
|
116
129
|
const requiresContext = directiveOptions.requiresContext ?? directiveOptions.requiresApplication ?? !0;
|
|
117
130
|
function Directive(props) {
|
|
@@ -134,7 +147,10 @@ function createDirectiveKit(options = {}) {
|
|
|
134
147
|
}
|
|
135
148
|
return Directive.displayName = `Directive(${name})`, Directive;
|
|
136
149
|
}
|
|
137
|
-
|
|
150
|
+
function remarkPlugin() {
|
|
151
|
+
return remarkAgentDirectives.call(this, { excludeFromStack });
|
|
152
|
+
}
|
|
153
|
+
return { defineDirective, remarkPlugin };
|
|
138
154
|
}
|
|
139
155
|
export {
|
|
140
156
|
createDirectiveKit,
|
package/dist/lib/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","sources":["../../src/lib/react.tsx"],"sourcesContent":["import { pascalCase } from 'es-toolkit'\nimport { directiveFromMarkdown, directiveToMarkdown } from 'mdast-util-directive'\nimport { directive } from 'micromark-extension-directive'\nimport type { ComponentType, ReactNode } from 'react'\nimport type { Processor } from 'unified'\nimport type { Node } from 'unist'\nimport { visit } from 'unist-util-visit'\nimport {\n BLOCK_DIRECTIVE,\n type DefineDirectiveOptions,\n DIRECTIVE_NAMES,\n DIRECTIVE_TYPES,\n type DirectiveName,\n type DirectivePropsMap,\n DirectiveSchemas,\n type DirectiveType,\n parseDirectiveAttributes,\n} from '../_internal'\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype DirectiveProps<T extends DirectiveName> = DirectivePropsMap[T]\n\nexport interface NodeProps {\n node?: { properties?: Record<string, unknown> }\n}\n\nexport type DirectiveRenderProps<\n TName extends DirectiveName,\n TApplication = undefined,\n TRequiresApplication extends boolean = true,\n> = DirectiveProps<TName> & {\n isInline: boolean\n} & (TRequiresApplication extends true\n ? TApplication extends undefined\n ? {}\n : { application: TApplication }\n : {})\n\nexport type { DefineDirectiveOptions }\n\nexport type DirectiveComponentProps<TName extends DirectiveName> = DirectiveProps<TName> & {\n source?: string\n} & NodeProps\n\n// ============================================================================\n// Remark Plugin Types\n// ============================================================================\n\ninterface DirectiveNode extends Node {\n type: 'textDirective' | 'leafDirective' | 'containerDirective'\n name: string\n attributes?: Record<string, string>\n children?: DirectiveNode[]\n value?: string\n data?: {\n hName?: string\n hProperties?: Record<string, unknown>\n }\n}\n\nconst isDirectiveNode = (node: Node): node is DirectiveNode =>\n 'name' in node &&\n typeof (node as DirectiveNode).name === 'string' &&\n /^[a-zA-Z-]+$/.test((node as DirectiveNode).name) &&\n DIRECTIVE_TYPES.includes(node.type as DirectiveType)\n\nconst isListItemWithOnlyDirective = (node: Node): boolean => {\n if (node.type !== 'listItem') return false\n const children = (node as DirectiveNode).children || []\n return children.length === 1 && children[0].type === 'leafDirective'\n}\n\nconst KNOWN_DIRECTIVE_NAMES: Set<string> = new Set(Object.values(DIRECTIVE_NAMES))\n\nfunction getTextContent(node: DirectiveNode): string {\n if (typeof node.value === 'string') return node.value\n if (!node.children) return ''\n return node.children.map((child) => getTextContent(child)).join('')\n}\n\n// ============================================================================\n// Remark Plugin\n// ============================================================================\n\n/**\n * Remark plugin that transforms directive syntax into React components.\n *\n * - Validates directive names (letters and hyphens only)\n * - Rescues unparsed block directives from paragraph text (lists, trailing text, streaming junk)\n * - Extracts directives from list items\n * - Groups consecutive leaf directives into DirectivesStack wrappers\n * - Filters incomplete streaming directives\n * - Converts directive names to PascalCase component names\n */\nfunction remarkDirectivesTransform() {\n return (tree: Node) => {\n // Remove invalid directive nodes (e.g., \":02\" in \"14:02\")\n visit(\n tree,\n DIRECTIVE_TYPES,\n (node: Node, index: number | undefined, parent: Node | undefined) => {\n if (!isDirectiveNode(node)) {\n const parentNode = parent as DirectiveNode | undefined\n if (parentNode?.children && typeof index === 'number') {\n const nodeName = 'name' in node ? String((node as DirectiveNode).name) : ''\n parentNode.children[index] = {\n type: 'text' as DirectiveType,\n name: '',\n value: `:${nodeName}`,\n } as DirectiveNode\n }\n }\n },\n )\n\n // Rescue unparsed block directives from paragraph text.\n // When the LLM outputs directives inside lists, with trailing text, or when\n // the streaming preprocessor appends junk characters (e.g. closing a `_`),\n // micromark cannot parse them as leaf directives because they require their\n // own line with no surrounding content. This step finds block directive\n // patterns in paragraph text and promotes them to proper directive nodes,\n // discarding any surrounding text on the same line.\n visit(tree, 'paragraph', (node: Node, index: number | undefined, parent: Node | undefined) => {\n const paragraphNode = node as DirectiveNode\n const text = getTextContent(paragraphNode)\n const match = text.match(BLOCK_DIRECTIVE)\n if (!match) return\n\n const [, name, label, attrsString] = match\n if (!KNOWN_DIRECTIVE_NAMES.has(name)) return\n\n const directiveNode: DirectiveNode = {\n type: 'leafDirective',\n name,\n attributes: parseDirectiveAttributes(attrsString),\n children: label\n ? [{ type: 'text' as DirectiveType, name: '', value: label } as DirectiveNode]\n : [],\n }\n\n const parentNode = parent as DirectiveNode | undefined\n if (parentNode?.children && typeof index === 'number') {\n parentNode.children[index] = directiveNode\n }\n })\n\n // Rescue unparsed block directives from table cells.\n // Leaf directives (::name{attrs}) are registered as flow content in micromark,\n // but GFM table cells only contain text (phrasing) content. This means ::\n // directives render as plain text inside tables. We rescue them here and\n // convert to textDirective (inline) so they render with isInline=true.\n visit(tree, 'tableCell', (node: Node) => {\n const cellNode = node as DirectiveNode\n if (!cellNode.children) return\n\n for (let i = 0; i < cellNode.children.length; i++) {\n const child = cellNode.children[i]\n if (typeof child.value !== 'string') continue\n\n const match = child.value.match(BLOCK_DIRECTIVE)\n if (!match) continue\n\n const [, name, label, attrsString] = match\n if (!KNOWN_DIRECTIVE_NAMES.has(name)) continue\n\n cellNode.children[i] = {\n type: 'textDirective',\n name,\n attributes: parseDirectiveAttributes(attrsString),\n children: label\n ? [{ type: 'text' as DirectiveType, name: '', value: label } as DirectiveNode]\n : [],\n }\n }\n })\n\n // Downgrade any leafDirective inside a table cell to textDirective (inline).\n // This handles cases where a directive was already parsed but as the wrong\n // type for inline context (e.g. from a prior rescue pass or future parser changes).\n visit(tree, 'tableCell', (node: Node) => {\n const cellNode = node as DirectiveNode\n if (!cellNode.children) return\n\n for (const child of cellNode.children) {\n if (child.type === 'leafDirective') {\n child.type = 'textDirective'\n }\n }\n })\n\n // Extract directives from list items\n visit(\n tree,\n 'list',\n (node: Node, index: number | undefined, parent: Node | undefined): number | undefined => {\n const listNode = node as DirectiveNode\n if (!listNode.children) return undefined\n\n const transformed: DirectiveNode[] = []\n let hasTransformed = false\n\n for (const child of listNode.children) {\n if (isListItemWithOnlyDirective(child) && child.children?.[0]) {\n transformed.push(child.children[0])\n hasTransformed = true\n } else {\n transformed.push(child)\n }\n }\n\n const parentNode = parent as DirectiveNode | undefined\n if (hasTransformed && transformed.every((n) => isDirectiveNode(n))) {\n if (parentNode?.children && typeof index === 'number') {\n parentNode.children.splice(index, 1, ...transformed)\n return index + transformed.length\n }\n }\n return undefined\n },\n )\n\n // Group consecutive leaf directives into DirectivesStack\n visit(tree, (node: Node) => {\n const dirNode = node as DirectiveNode\n if (!dirNode.children?.length || dirNode.data?.hName === 'DirectivesStack') return\n\n const newChildren: DirectiveNode[] = []\n let group: DirectiveNode[] = []\n\n for (const child of dirNode.children) {\n if (isDirectiveNode(child) && child.type === 'leafDirective') {\n group.push(child)\n } else {\n if (group.length > 0) {\n newChildren.push({\n type: 'leafDirective',\n name: 'DirectivesStack',\n data: { hName: 'DirectivesStack' },\n children: group,\n })\n group = []\n }\n newChildren.push(child)\n }\n }\n\n if (group.length > 0) {\n newChildren.push({\n type: 'leafDirective',\n name: 'DirectivesStack',\n data: { hName: 'DirectivesStack' },\n children: group,\n })\n }\n\n dirNode.children = newChildren\n })\n\n // Filter incomplete streaming directives\n visit(tree, 'text', (node: Node) => {\n const textNode = node as DirectiveNode\n if (typeof textNode.value === 'string') {\n if (textNode.value.match(/::?\\w+[{[]/) && !textNode.value.match(/::?\\w+[{[].+[}\\]]/)) {\n textNode.value = ''\n }\n }\n })\n\n // Transform directives to React components\n visit(tree, DIRECTIVE_TYPES, (node: Node) => {\n if (!isDirectiveNode(node)) return\n\n node.data = node.data || {}\n node.data.hName = pascalCase(node.name)\n node.data.hProperties = {\n ...node.attributes,\n isInline: node.type === 'textDirective',\n }\n })\n }\n}\n\ninterface RemarkData {\n micromarkExtensions?: unknown[]\n fromMarkdownExtensions?: unknown[]\n toMarkdownExtensions?: unknown[]\n}\n\n/**\n * Remark plugin for agent directive support.\n * Parses and transforms directive syntax into React components.\n *\n * @example\n * ```tsx\n * import { remarkAgentDirectives } from '@sanity/agent-directives/react'\n *\n * <ReactMarkdown remarkPlugins={[remarkAgentDirectives]}>\n * {content}\n * </ReactMarkdown>\n * ```\n */\nexport function remarkAgentDirectives(this: Processor) {\n const data = this.data() as RemarkData\n\n if (!data.micromarkExtensions) data.micromarkExtensions = []\n if (!data.fromMarkdownExtensions) data.fromMarkdownExtensions = []\n if (!data.toMarkdownExtensions) data.toMarkdownExtensions = []\n\n data.micromarkExtensions.push(directive())\n data.fromMarkdownExtensions.push(directiveFromMarkdown())\n data.toMarkdownExtensions.push(directiveToMarkdown())\n\n return remarkDirectivesTransform()\n}\n\n// ============================================================================\n// Directive Kit\n// ============================================================================\n\nexport interface DirectiveKitOptions<TApplication> {\n useApplication?: (source: string | undefined) => TApplication | undefined\n renderApplicationUnavailable?: ComponentType<{ name: DirectiveName; source?: string }>\n}\n\n/**\n * Creates a directive kit with application injection.\n *\n * @example\n * ```tsx\n * // kit.ts\n * export const { defineDirective } = createDirectiveKit<Application>({\n * useApplication: (source) => useThreadApplication(source),\n * })\n *\n * // Document.tsx\n * export const DocumentDirective = defineDirective('document', ({ id, application }) => {\n * return <DocumentCard id={id} app={application} />\n * })\n * ```\n */\nexport function createDirectiveKit<TApplication = undefined>(\n options: DirectiveKitOptions<TApplication> = {},\n) {\n const { useApplication, renderApplicationUnavailable: Unavailable } = options\n\n function defineDirective<\n TName extends DirectiveName,\n TRequiresApplication extends boolean = true,\n >(\n name: TName,\n render: (props: DirectiveRenderProps<TName, TApplication, TRequiresApplication>) => ReactNode,\n directiveOptions: DefineDirectiveOptions = {},\n ): ComponentType<DirectiveComponentProps<TName>> {\n const requiresContext =\n directiveOptions.requiresContext ?? directiveOptions.requiresApplication ?? true\n\n function Directive(props: DirectiveComponentProps<TName>): ReactNode {\n const { node, source, ...rest } = props\n\n const application = useApplication?.(source)\n if (requiresContext && useApplication && !application) {\n return Unavailable ? <Unavailable name={name} source={source} /> : null\n }\n\n const merged = {\n ...(node?.properties ?? {}),\n ...rest,\n ...(source !== undefined && { source }),\n }\n\n const schema = DirectiveSchemas[name]\n const result = schema.safeParse(merged)\n if (!result.success) {\n console.error(`Directive \"${name}\" validation error:`, result.error.format())\n return null\n }\n\n const renderProps = {\n ...(result.data as DirectiveProps<TName>),\n ...(requiresContext && useApplication ? { application } : {}),\n isInline: merged.isInline === true,\n } as DirectiveRenderProps<TName, TApplication, TRequiresApplication>\n\n return render(renderProps)\n }\n\n Directive.displayName = `Directive(${name})`\n return Directive\n }\n\n return { defineDirective }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"react.js","sources":["../../src/lib/react.tsx"],"sourcesContent":["import { pascalCase } from 'es-toolkit'\nimport { directiveFromMarkdown, directiveToMarkdown } from 'mdast-util-directive'\nimport { directive } from 'micromark-extension-directive'\nimport type { ComponentType, ReactNode } from 'react'\nimport type { Processor } from 'unified'\nimport type { Node } from 'unist'\nimport { visit } from 'unist-util-visit'\nimport {\n BLOCK_DIRECTIVE,\n type DefineDirectiveOptions,\n DIRECTIVE_NAMES,\n DIRECTIVE_TYPES,\n type DirectiveName,\n type DirectivePropsMap,\n DirectiveSchemas,\n type DirectiveType,\n parseDirectiveAttributes,\n} from '../_internal'\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype DirectiveProps<T extends DirectiveName> = DirectivePropsMap[T]\n\nexport interface NodeProps {\n node?: { properties?: Record<string, unknown> }\n}\n\nexport type DirectiveRenderProps<\n TName extends DirectiveName,\n TApplication = undefined,\n TRequiresApplication extends boolean = true,\n> = DirectiveProps<TName> & {\n isInline: boolean\n} & (TRequiresApplication extends true\n ? TApplication extends undefined\n ? {}\n : { application: TApplication }\n : {})\n\nexport type { DefineDirectiveOptions }\n\nexport type DirectiveComponentProps<TName extends DirectiveName> = DirectiveProps<TName> & {\n source?: string\n} & NodeProps\n\n// ============================================================================\n// Remark Plugin Types\n// ============================================================================\n\ninterface DirectiveNode extends Node {\n type: 'textDirective' | 'leafDirective' | 'containerDirective'\n name: string\n attributes?: Record<string, string>\n children?: DirectiveNode[]\n value?: string\n data?: {\n hName?: string\n hProperties?: Record<string, unknown>\n }\n}\n\nconst isDirectiveNode = (node: Node): node is DirectiveNode =>\n 'name' in node &&\n typeof (node as DirectiveNode).name === 'string' &&\n /^[a-zA-Z-]+$/.test((node as DirectiveNode).name) &&\n DIRECTIVE_TYPES.includes(node.type as DirectiveType)\n\nconst isListItemWithOnlyDirective = (node: Node): boolean => {\n if (node.type !== 'listItem') return false\n const children = (node as DirectiveNode).children || []\n return children.length === 1 && children[0].type === 'leafDirective'\n}\n\nconst KNOWN_DIRECTIVE_NAMES: Set<string> = new Set(Object.values(DIRECTIVE_NAMES))\n\nfunction getTextContent(node: DirectiveNode): string {\n if (typeof node.value === 'string') return node.value\n if (!node.children) return ''\n return node.children.map((child) => getTextContent(child)).join('')\n}\n\n// ============================================================================\n// Remark Plugin\n// ============================================================================\n\nexport interface RemarkAgentDirectivesOptions {\n /**\n * Directive names to exclude from DirectivesStack grouping.\n * These directives will be rendered separately instead of grouped with consecutive leaf directives.\n *\n * @example\n * ```ts\n * remarkAgentDirectives({ excludeFromStack: ['thinking', 'resource'] })\n * ```\n */\n excludeFromStack?: DirectiveName[]\n}\n\n/**\n * Remark plugin that transforms directive syntax into React components.\n *\n * - Validates directive names (letters and hyphens only)\n * - Rescues unparsed block directives from paragraph text (lists, trailing text, streaming junk)\n * - Extracts directives from list items\n * - Groups consecutive leaf directives into DirectivesStack wrappers\n * - Filters incomplete streaming directives\n * - Converts directive names to PascalCase component names\n */\nfunction remarkDirectivesTransform(options: RemarkAgentDirectivesOptions = {}) {\n const { excludeFromStack = [] } = options\n const excludeSet = new Set(excludeFromStack)\n\n return (tree: Node) => {\n // Remove invalid directive nodes (e.g., \":02\" in \"14:02\")\n visit(\n tree,\n DIRECTIVE_TYPES,\n (node: Node, index: number | undefined, parent: Node | undefined) => {\n if (!isDirectiveNode(node)) {\n const parentNode = parent as DirectiveNode | undefined\n if (parentNode?.children && typeof index === 'number') {\n const nodeName = 'name' in node ? String((node as DirectiveNode).name) : ''\n parentNode.children[index] = {\n type: 'text' as DirectiveType,\n name: '',\n value: `:${nodeName}`,\n } as DirectiveNode\n }\n }\n },\n )\n\n // Rescue unparsed block directives from paragraph text.\n // When the LLM outputs directives inside lists, with trailing text, or when\n // the streaming preprocessor appends junk characters (e.g. closing a `_`),\n // micromark cannot parse them as leaf directives because they require their\n // own line with no surrounding content. This step finds block directive\n // patterns in paragraph text and promotes them to proper directive nodes,\n // discarding any surrounding text on the same line.\n visit(tree, 'paragraph', (node: Node, index: number | undefined, parent: Node | undefined) => {\n const paragraphNode = node as DirectiveNode\n const text = getTextContent(paragraphNode)\n const match = text.match(BLOCK_DIRECTIVE)\n if (!match) return\n\n const [, name, label, attrsString] = match\n if (!KNOWN_DIRECTIVE_NAMES.has(name)) return\n\n const directiveNode: DirectiveNode = {\n type: 'leafDirective',\n name,\n attributes: parseDirectiveAttributes(attrsString),\n children: label\n ? [\n {\n type: 'text' as DirectiveType,\n name: '',\n value: label,\n } as DirectiveNode,\n ]\n : [],\n }\n\n const parentNode = parent as DirectiveNode | undefined\n if (parentNode?.children && typeof index === 'number') {\n parentNode.children[index] = directiveNode\n }\n })\n\n // Rescue unparsed block directives from table cells.\n // Leaf directives (::name{attrs}) are registered as flow content in micromark,\n // but GFM table cells only contain text (phrasing) content. This means ::\n // directives render as plain text inside tables. We rescue them here and\n // convert to textDirective (inline) so they render with isInline=true.\n visit(tree, 'tableCell', (node: Node) => {\n const cellNode = node as DirectiveNode\n if (!cellNode.children) return\n\n for (let i = 0; i < cellNode.children.length; i++) {\n const child = cellNode.children[i]\n if (typeof child.value !== 'string') continue\n\n const match = child.value.match(BLOCK_DIRECTIVE)\n if (!match) continue\n\n const [, name, label, attrsString] = match\n if (!KNOWN_DIRECTIVE_NAMES.has(name)) continue\n\n cellNode.children[i] = {\n type: 'textDirective',\n name,\n attributes: parseDirectiveAttributes(attrsString),\n children: label\n ? [\n {\n type: 'text' as DirectiveType,\n name: '',\n value: label,\n } as DirectiveNode,\n ]\n : [],\n }\n }\n })\n\n // Downgrade any leafDirective inside a table cell to textDirective (inline).\n // This handles cases where a directive was already parsed but as the wrong\n // type for inline context (e.g. from a prior rescue pass or future parser changes).\n visit(tree, 'tableCell', (node: Node) => {\n const cellNode = node as DirectiveNode\n if (!cellNode.children) return\n\n for (const child of cellNode.children) {\n if (child.type === 'leafDirective') {\n child.type = 'textDirective'\n }\n }\n })\n\n // Extract directives from list items\n visit(\n tree,\n 'list',\n (node: Node, index: number | undefined, parent: Node | undefined): number | undefined => {\n const listNode = node as DirectiveNode\n if (!listNode.children) return undefined\n\n const transformed: DirectiveNode[] = []\n let hasTransformed = false\n\n for (const child of listNode.children) {\n if (isListItemWithOnlyDirective(child) && child.children?.[0]) {\n transformed.push(child.children[0])\n hasTransformed = true\n } else {\n transformed.push(child)\n }\n }\n\n const parentNode = parent as DirectiveNode | undefined\n if (hasTransformed && transformed.every((n) => isDirectiveNode(n))) {\n if (parentNode?.children && typeof index === 'number') {\n parentNode.children.splice(index, 1, ...transformed)\n return index + transformed.length\n }\n }\n return undefined\n },\n )\n\n // Group consecutive leaf directives into DirectivesStack\n visit(tree, (node: Node) => {\n const dirNode = node as DirectiveNode\n if (!dirNode.children?.length || dirNode.data?.hName === 'DirectivesStack') return\n\n const newChildren: DirectiveNode[] = []\n let group: DirectiveNode[] = []\n\n for (const child of dirNode.children) {\n if (\n isDirectiveNode(child) &&\n child.type === 'leafDirective' &&\n !excludeSet.has(child.name as DirectiveName)\n ) {\n group.push(child)\n } else {\n if (group.length > 0) {\n newChildren.push({\n type: 'leafDirective',\n name: 'DirectivesStack',\n data: { hName: 'DirectivesStack' },\n children: group,\n })\n group = []\n }\n newChildren.push(child)\n }\n }\n\n if (group.length > 0) {\n newChildren.push({\n type: 'leafDirective',\n name: 'DirectivesStack',\n data: { hName: 'DirectivesStack' },\n children: group,\n })\n }\n\n dirNode.children = newChildren\n })\n\n // Filter incomplete streaming directives\n visit(tree, 'text', (node: Node) => {\n const textNode = node as DirectiveNode\n if (typeof textNode.value === 'string') {\n if (textNode.value.match(/::?\\w+[{[]/) && !textNode.value.match(/::?\\w+[{[].+[}\\]]/)) {\n textNode.value = ''\n }\n }\n })\n\n // Transform directives to React components\n visit(tree, DIRECTIVE_TYPES, (node: Node) => {\n if (!isDirectiveNode(node)) return\n\n node.data = node.data || {}\n node.data.hName = pascalCase(node.name)\n node.data.hProperties = {\n ...node.attributes,\n isInline: node.type === 'textDirective',\n }\n })\n }\n}\n\ninterface RemarkData {\n micromarkExtensions?: unknown[]\n fromMarkdownExtensions?: unknown[]\n toMarkdownExtensions?: unknown[]\n}\n\n/**\n * Remark plugin for agent directive support.\n * Parses and transforms directive syntax into React components.\n *\n * @example\n * ```tsx\n * import { remarkAgentDirectives } from '@sanity/agent-directives/react'\n *\n * <ReactMarkdown remarkPlugins={[remarkAgentDirectives]}>\n * {content}\n * </ReactMarkdown>\n * ```\n *\n * @example\n * ```tsx\n * // Exclude specific directives from DirectivesStack grouping\n * <ReactMarkdown remarkPlugins={[[remarkAgentDirectives, { excludeFromStack: ['thinking'] }]]}>\n * {content}\n * </ReactMarkdown>\n * ```\n */\nexport function remarkAgentDirectives(this: Processor, options?: RemarkAgentDirectivesOptions) {\n const data = this.data() as RemarkData\n\n if (!data.micromarkExtensions) data.micromarkExtensions = []\n if (!data.fromMarkdownExtensions) data.fromMarkdownExtensions = []\n if (!data.toMarkdownExtensions) data.toMarkdownExtensions = []\n\n data.micromarkExtensions.push(directive())\n data.fromMarkdownExtensions.push(directiveFromMarkdown())\n data.toMarkdownExtensions.push(directiveToMarkdown())\n\n return remarkDirectivesTransform(options)\n}\n\n// ============================================================================\n// Directive Kit\n// ============================================================================\n\nexport interface DirectiveKitOptions<TApplication> {\n useApplication?: (source: string | undefined) => TApplication | undefined\n renderApplicationUnavailable?: ComponentType<{\n name: DirectiveName\n source?: string\n }>\n /**\n * Directive names to exclude from DirectivesStack grouping.\n * These directives will be rendered separately instead of grouped with consecutive leaf directives.\n *\n * @example\n * ```ts\n * createDirectiveKit({ excludeFromStack: ['thinking', 'resource'] })\n * ```\n */\n excludeFromStack?: DirectiveName[]\n}\n\n/**\n * Creates a directive kit with application injection and a pre-configured remark plugin.\n *\n * @example\n * ```tsx\n * // kit.ts\n * export const { defineDirective, remarkPlugin } = createDirectiveKit<Application>({\n * useApplication: (source) => useThreadApplication(source),\n * excludeFromStack: ['thinking'],\n * })\n *\n * // Usage in component\n * <ReactMarkdown remarkPlugins={[remarkPlugin]}>\n * {content}\n * </ReactMarkdown>\n *\n * // Document.tsx\n * export const DocumentDirective = defineDirective('document', ({ id, application }) => {\n * return <DocumentCard id={id} app={application} />\n * })\n * ```\n */\nexport function createDirectiveKit<TApplication = undefined>(\n options: DirectiveKitOptions<TApplication> = {},\n) {\n const { useApplication, renderApplicationUnavailable: Unavailable, excludeFromStack } = options\n\n function defineDirective<\n TName extends DirectiveName,\n TRequiresApplication extends boolean = true,\n >(\n name: TName,\n render: (props: DirectiveRenderProps<TName, TApplication, TRequiresApplication>) => ReactNode,\n directiveOptions: DefineDirectiveOptions = {},\n ): ComponentType<DirectiveComponentProps<TName>> {\n const requiresContext =\n directiveOptions.requiresContext ?? directiveOptions.requiresApplication ?? true\n\n function Directive(props: DirectiveComponentProps<TName>): ReactNode {\n const { node, source, ...rest } = props\n\n const application = useApplication?.(source)\n if (requiresContext && useApplication && !application) {\n return Unavailable ? <Unavailable name={name} source={source} /> : null\n }\n\n const merged = {\n ...(node?.properties ?? {}),\n ...rest,\n ...(source !== undefined && { source }),\n }\n\n const schema = DirectiveSchemas[name]\n const result = schema.safeParse(merged)\n if (!result.success) {\n console.error(`Directive \"${name}\" validation error:`, result.error.format())\n return null\n }\n\n const renderProps = {\n ...(result.data as DirectiveProps<TName>),\n ...(requiresContext && useApplication ? { application } : {}),\n isInline: merged.isInline === true,\n } as DirectiveRenderProps<TName, TApplication, TRequiresApplication>\n\n return render(renderProps)\n }\n\n Directive.displayName = `Directive(${name})`\n return Directive\n }\n\n /**\n * Pre-configured remark plugin with the kit's excludeFromStack option.\n * Use this in your markdown processor instead of calling remarkAgentDirectives directly.\n */\n function remarkPlugin(this: Processor) {\n return remarkAgentDirectives.call(this, { excludeFromStack })\n }\n\n return { defineDirective, remarkPlugin }\n}\n"],"names":[],"mappings":"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"}
|