@sanity/agent-directives 0.0.1
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 +109 -0
- package/dist/formatters.d.ts +8 -0
- package/dist/formatters.d.ts.map +1 -0
- package/dist/formatters.js +27 -0
- package/dist/formatters.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/react.d.ts +84 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +266 -0
- package/dist/react.js.map +1 -0
- package/dist/string.d.ts +34 -0
- package/dist/string.d.ts.map +1 -0
- package/dist/string.js +65 -0
- package/dist/string.js.map +1 -0
- package/package.json +82 -0
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# @sanity/agent-directives
|
|
2
|
+
|
|
3
|
+
Shared directive system for Sanity Agent.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pnpm add @sanity/agent-directives
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## React Usage (Ada)
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
// directives/kit.ts
|
|
15
|
+
import { createDirectiveKit } from "@sanity/agent-directives/react";
|
|
16
|
+
import { useThreadApplication } from "../hooks/useThreadResource";
|
|
17
|
+
|
|
18
|
+
export const { defineDirective } = createDirectiveKit({
|
|
19
|
+
useApplication: useThreadApplication,
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
// directives/Document.tsx
|
|
25
|
+
import { defineDirective } from "./kit";
|
|
26
|
+
|
|
27
|
+
export const Document = defineDirective("document", ({ id, application }) => {
|
|
28
|
+
const doc = useDocument(id);
|
|
29
|
+
return <DocumentCard document={doc} />;
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
That's it. Schema validation and application injection happen automatically.
|
|
34
|
+
|
|
35
|
+
## String Usage (Slack)
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
// directives/kit.ts
|
|
39
|
+
import { createDirectiveKit } from "@sanity/agent-directives/string";
|
|
40
|
+
|
|
41
|
+
interface SlackContext {
|
|
42
|
+
accessToken: string;
|
|
43
|
+
applications: Application[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface SlackOutput {
|
|
47
|
+
text?: string;
|
|
48
|
+
blocks?: SlackBlock[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const { defineDirective, renderDirective } = createDirectiveKit<
|
|
52
|
+
SlackContext,
|
|
53
|
+
SlackOutput
|
|
54
|
+
>();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
// directives/document.ts
|
|
59
|
+
import { defineDirective } from "./kit";
|
|
60
|
+
|
|
61
|
+
export const Document = defineDirective(
|
|
62
|
+
"document",
|
|
63
|
+
async ({ id, _context }) => {
|
|
64
|
+
const doc = await fetchDocument(id, _context.accessToken);
|
|
65
|
+
return { blocks: [linkButton(doc.title, url)] };
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
// Render directives from remark AST
|
|
72
|
+
import { renderDirective } from "./kit";
|
|
73
|
+
|
|
74
|
+
const output = await renderDirective(node, context);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Formatters (Agent Backend)
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import {
|
|
81
|
+
createDocumentDirective,
|
|
82
|
+
createChangesDirective,
|
|
83
|
+
} from "@sanity/agent-directives/formatters";
|
|
84
|
+
|
|
85
|
+
createDocumentDirective({ id: "doc-123", type: "article" });
|
|
86
|
+
// => '::document{id="doc-123" type="article"}'
|
|
87
|
+
|
|
88
|
+
createChangesDirective({ createdCount: 3, updatedCount: 5 });
|
|
89
|
+
// => '::changes{createdCount="3" updatedCount="5"}'
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Available Directives
|
|
93
|
+
|
|
94
|
+
| Name | Props |
|
|
95
|
+
| ---------- | ------------------------------ |
|
|
96
|
+
| `document` | `id`, `type?`, `source?` |
|
|
97
|
+
| `release` | `id`, `source?` |
|
|
98
|
+
| `resource` | `source` |
|
|
99
|
+
| `set` | `id` |
|
|
100
|
+
| `changes` | `createdCount`, `updatedCount` |
|
|
101
|
+
|
|
102
|
+
## Exports
|
|
103
|
+
|
|
104
|
+
| Path | Description |
|
|
105
|
+
| ------------------------------------- | ------------------------------------ |
|
|
106
|
+
| `@sanity/agent-directives` | Schemas and formatters |
|
|
107
|
+
| `@sanity/agent-directives/react` | `createDirectiveKit` for React |
|
|
108
|
+
| `@sanity/agent-directives/string` | `createDirectiveKit` for server-side |
|
|
109
|
+
| `@sanity/agent-directives/formatters` | Directive string formatters |
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ChangesDirectiveProps, type DirectiveName, type DocumentDirectiveProps, type ReleaseDirectiveProps, type ResourceDirectiveProps, type SetDirectiveProps } from '@sanity/agent-types';
|
|
2
|
+
export declare function formatDirective(name: DirectiveName, props: Record<string, unknown>): string;
|
|
3
|
+
export declare function createDocumentDirective(props: DocumentDirectiveProps): string;
|
|
4
|
+
export declare function createReleaseDirective(props: ReleaseDirectiveProps): string;
|
|
5
|
+
export declare function createResourceDirective(props: ResourceDirectiveProps): string;
|
|
6
|
+
export declare function createSetDirective(props: SetDirectiveProps): string;
|
|
7
|
+
export declare function createChangesDirective(props: ChangesDirectiveProps): string;
|
|
8
|
+
//# sourceMappingURL=formatters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAE1B,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAA;AAS5B,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAG3F;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAE7E;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAE3E;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAE7E;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAEnE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAE3E"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { DIRECTIVE_NAMES, } from '@sanity/agent-types';
|
|
2
|
+
function buildAttributes(params) {
|
|
3
|
+
return Object.entries(params)
|
|
4
|
+
.filter(([, value]) => value !== undefined && value !== null)
|
|
5
|
+
.map(([key, value]) => `${key}="${value}"`)
|
|
6
|
+
.join(' ');
|
|
7
|
+
}
|
|
8
|
+
export function formatDirective(name, props) {
|
|
9
|
+
const attrs = buildAttributes(props);
|
|
10
|
+
return attrs ? `::${name}{${attrs}}` : `::${name}`;
|
|
11
|
+
}
|
|
12
|
+
export function createDocumentDirective(props) {
|
|
13
|
+
return formatDirective(DIRECTIVE_NAMES.document, props);
|
|
14
|
+
}
|
|
15
|
+
export function createReleaseDirective(props) {
|
|
16
|
+
return formatDirective(DIRECTIVE_NAMES.release, props);
|
|
17
|
+
}
|
|
18
|
+
export function createResourceDirective(props) {
|
|
19
|
+
return formatDirective(DIRECTIVE_NAMES.resource, props);
|
|
20
|
+
}
|
|
21
|
+
export function createSetDirective(props) {
|
|
22
|
+
return formatDirective(DIRECTIVE_NAMES.set, props);
|
|
23
|
+
}
|
|
24
|
+
export function createChangesDirective(props) {
|
|
25
|
+
return formatDirective(DIRECTIVE_NAMES.changes, props);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=formatters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,GAMhB,MAAM,qBAAqB,CAAA;AAE5B,SAAS,eAAe,CAAC,MAA+B;IACtD,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC;SAC5D,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,GAAG,CAAC;SAC1C,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAmB,EAAE,KAA8B;IACjF,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IACpC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAA;AACpD,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAA6B;IACnE,OAAO,eAAe,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;AACzD,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAA4B;IACjE,OAAO,eAAe,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAA6B;IACnE,OAAO,eAAe,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;AACzD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAwB;IACzD,OAAO,eAAe,CAAC,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AACpD,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAA4B;IACjE,OAAO,eAAe,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;AACxD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { type ChangesDirectiveProps, ChangesDirectiveSchema, DIRECTIVE_NAMES, type DirectiveName, DirectiveSchemas, type DocumentDirectiveProps, DocumentDirectiveSchema, type ReleaseDirectiveProps, ReleaseDirectiveSchema, type ResourceDirectiveProps, ResourceDirectiveSchema, type SetDirectiveProps, SetDirectiveSchema, } from '@sanity/agent-types';
|
|
2
|
+
export { createChangesDirective, createDocumentDirective, createReleaseDirective, createResourceDirective, createSetDirective, formatDirective, } from './formatters.js';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAC1B,sBAAsB,EACtB,eAAe,EACf,KAAK,aAAa,EAClB,gBAAgB,EAChB,KAAK,sBAAsB,EAC3B,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,sBAAsB,EACtB,KAAK,sBAAsB,EAC3B,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,GAChB,MAAM,iBAAiB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { ChangesDirectiveSchema, DIRECTIVE_NAMES, DirectiveSchemas, DocumentDirectiveSchema, ReleaseDirectiveSchema, ResourceDirectiveSchema, SetDirectiveSchema, } from '@sanity/agent-types';
|
|
2
|
+
export { createChangesDirective, createDocumentDirective, createReleaseDirective, createResourceDirective, createSetDirective, formatDirective, } from './formatters.js';
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,sBAAsB,EACtB,eAAe,EAEf,gBAAgB,EAEhB,uBAAuB,EAEvB,sBAAsB,EAEtB,uBAAuB,EAEvB,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,GAChB,MAAM,iBAAiB,CAAA"}
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { type DirectiveName, type DirectivePropsMap } from '@sanity/agent-types';
|
|
2
|
+
import { type ComponentType, type ReactNode } from 'react';
|
|
3
|
+
import type { Processor } from 'unified';
|
|
4
|
+
import type { Node } from 'unist';
|
|
5
|
+
type DirectiveProps<T extends DirectiveName> = DirectivePropsMap[T];
|
|
6
|
+
export interface NodeProps {
|
|
7
|
+
node?: {
|
|
8
|
+
properties?: Record<string, unknown>;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export type DirectiveRenderProps<TName extends DirectiveName, TApplication> = DirectiveProps<TName> & {
|
|
12
|
+
application: TApplication;
|
|
13
|
+
};
|
|
14
|
+
export type DirectiveComponentProps<TName extends DirectiveName> = DirectiveProps<TName> & {
|
|
15
|
+
source?: string;
|
|
16
|
+
} & NodeProps;
|
|
17
|
+
export declare function remarkAgentDirectives(this: Processor): (tree: Node) => void;
|
|
18
|
+
interface DirectivesStackProps {
|
|
19
|
+
children?: ReactNode;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Default DirectivesStack component that groups consecutive directives.
|
|
23
|
+
* Override this in your components map if you need custom styling.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* import { DirectivesStack } from '@sanity/agent-directives/react'
|
|
28
|
+
*
|
|
29
|
+
* // Use default
|
|
30
|
+
* components={{ DirectivesStack }}
|
|
31
|
+
*
|
|
32
|
+
* // Or override with your own
|
|
33
|
+
* components={{ DirectivesStack: MyCustomStack }}
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function DirectivesStack({ children }: DirectivesStackProps): ReactNode;
|
|
37
|
+
export interface DirectiveKitOptions<TApplication> {
|
|
38
|
+
useApplication: (source: string | undefined) => TApplication | undefined;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a directive kit with application injection.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* // kit.ts
|
|
46
|
+
* import { createDirectiveKit } from '@sanity/agent-directives/react'
|
|
47
|
+
* import type { Application } from '@sanity/agent-types'
|
|
48
|
+
*
|
|
49
|
+
* export const { defineDirective } = createDirectiveKit<Application>({
|
|
50
|
+
* useApplication: (source) => useThreadApplication(source),
|
|
51
|
+
* })
|
|
52
|
+
*
|
|
53
|
+
* // Document.tsx
|
|
54
|
+
* export const DocumentDirective = defineDirective('document', ({ id, application }) => {
|
|
55
|
+
* return <DocumentCard id={id} app={application} />
|
|
56
|
+
* })
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function createDirectiveKit<TApplication>(options: DirectiveKitOptions<TApplication>): {
|
|
60
|
+
defineDirective: <TName extends DirectiveName>(name: TName, render: (props: DirectiveRenderProps<TName, TApplication>) => ReactNode) => ComponentType<DirectiveComponentProps<TName>>;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Default components map including DirectivesStack.
|
|
64
|
+
* Spread this into your components and override as needed.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```tsx
|
|
68
|
+
* import { defaultComponents } from '@sanity/agent-directives/react'
|
|
69
|
+
*
|
|
70
|
+
* <ReactMarkdown
|
|
71
|
+
* components={{
|
|
72
|
+
* ...defaultComponents,
|
|
73
|
+
* Document: DocumentDirective,
|
|
74
|
+
* }}
|
|
75
|
+
* >
|
|
76
|
+
* {content}
|
|
77
|
+
* </ReactMarkdown>
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare const defaultComponents: {
|
|
81
|
+
readonly DirectivesStack: typeof DirectivesStack;
|
|
82
|
+
};
|
|
83
|
+
export {};
|
|
84
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,iBAAiB,EAAoB,MAAM,qBAAqB,CAAA;AAIlG,OAAO,EAEL,KAAK,aAAa,EAGlB,KAAK,SAAS,EAEf,MAAM,OAAO,CAAA;AAEd,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAOjC,KAAK,cAAc,CAAC,CAAC,SAAS,aAAa,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAA;AAEnE,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAA;CAChD;AAED,MAAM,MAAM,oBAAoB,CAC9B,KAAK,SAAS,aAAa,EAC3B,YAAY,IACV,cAAc,CAAC,KAAK,CAAC,GAAG;IAC1B,WAAW,EAAE,YAAY,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,uBAAuB,CAAC,KAAK,SAAS,aAAa,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG;IACzF,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,SAAS,CAAA;AAuLb,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,SAAS,UAtIrC,IAAI,UAmJnB;AAMD,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAkCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE,oBAAoB,GAAG,SAAS,CA2B7E;AAMD,MAAM,WAAW,mBAAmB,CAAC,YAAY;IAC/C,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,YAAY,GAAG,SAAS,CAAA;CACzE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,OAAO,EAAE,mBAAmB,CAAC,YAAY,CAAC;sBAGhE,KAAK,SAAS,aAAa,QAC5C,KAAK,UACH,CAAC,KAAK,EAAE,oBAAoB,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,SAAS,KACtE,aAAa,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC;EA+BjD;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB;;CAEpB,CAAA"}
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { DirectiveSchemas } from '@sanity/agent-types';
|
|
2
|
+
import { pascalCase } from 'es-toolkit';
|
|
3
|
+
import { directiveFromMarkdown, directiveToMarkdown } from 'mdast-util-directive';
|
|
4
|
+
import { directive } from 'micromark-extension-directive';
|
|
5
|
+
import { Children, createElement, useState, } from 'react';
|
|
6
|
+
import { visit } from 'unist-util-visit';
|
|
7
|
+
const DIRECTIVE_TYPES = ['textDirective', 'leafDirective', 'containerDirective'];
|
|
8
|
+
const isDirectiveNode = (node) => 'name' in node &&
|
|
9
|
+
typeof node.name === 'string' &&
|
|
10
|
+
/^[a-zA-Z-]+$/.test(node.name) &&
|
|
11
|
+
DIRECTIVE_TYPES.includes(node.type);
|
|
12
|
+
const isListItemWithOnlyDirective = (node) => {
|
|
13
|
+
if (node.type !== 'listItem')
|
|
14
|
+
return false;
|
|
15
|
+
const children = node.children || [];
|
|
16
|
+
return children.length === 1 && children[0].type === 'leafDirective';
|
|
17
|
+
};
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Remark Plugin
|
|
20
|
+
// ============================================================================
|
|
21
|
+
/**
|
|
22
|
+
* Remark plugin that transforms directive syntax into React components.
|
|
23
|
+
*
|
|
24
|
+
* Features:
|
|
25
|
+
* - Validates directive names (letters and hyphens only)
|
|
26
|
+
* - Extracts directives from list items
|
|
27
|
+
* - Groups consecutive leaf directives into DirectivesStack wrappers
|
|
28
|
+
* - Filters incomplete streaming directives
|
|
29
|
+
* - Converts directive names to PascalCase component names
|
|
30
|
+
*/
|
|
31
|
+
function remarkDirectivesTransform() {
|
|
32
|
+
return (tree) => {
|
|
33
|
+
// Remove invalid directive nodes (e.g., ":02" in "14:02")
|
|
34
|
+
visit(tree, DIRECTIVE_TYPES, (node, index, parent) => {
|
|
35
|
+
if (!isDirectiveNode(node)) {
|
|
36
|
+
const parentNode = parent;
|
|
37
|
+
if (parentNode?.children && typeof index === 'number') {
|
|
38
|
+
const nodeName = 'name' in node ? String(node.name) : '';
|
|
39
|
+
parentNode.children[index] = {
|
|
40
|
+
type: 'text',
|
|
41
|
+
name: '',
|
|
42
|
+
value: `:${nodeName}`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
// Extract directives from list items
|
|
48
|
+
visit(tree, 'list', (node, index, parent) => {
|
|
49
|
+
const listNode = node;
|
|
50
|
+
if (!listNode.children)
|
|
51
|
+
return;
|
|
52
|
+
const transformed = [];
|
|
53
|
+
let hasTransformed = false;
|
|
54
|
+
for (const child of listNode.children) {
|
|
55
|
+
if (isListItemWithOnlyDirective(child) && child.children?.[0]) {
|
|
56
|
+
transformed.push(child.children[0]);
|
|
57
|
+
hasTransformed = true;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
transformed.push(child);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const parentNode = parent;
|
|
64
|
+
if (hasTransformed && transformed.every((n) => isDirectiveNode(n))) {
|
|
65
|
+
if (parentNode?.children && typeof index === 'number') {
|
|
66
|
+
parentNode.children.splice(index, 1, ...transformed);
|
|
67
|
+
return index + transformed.length;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
// Group consecutive leaf directives into DirectivesStack
|
|
72
|
+
visit(tree, (node) => {
|
|
73
|
+
const dirNode = node;
|
|
74
|
+
if (!dirNode.children?.length || dirNode.data?.hName === 'DirectivesStack')
|
|
75
|
+
return;
|
|
76
|
+
const newChildren = [];
|
|
77
|
+
let group = [];
|
|
78
|
+
for (const child of dirNode.children) {
|
|
79
|
+
if (isDirectiveNode(child) && child.type === 'leafDirective') {
|
|
80
|
+
group.push(child);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
if (group.length > 0) {
|
|
84
|
+
newChildren.push({
|
|
85
|
+
type: 'leafDirective',
|
|
86
|
+
name: 'DirectivesStack',
|
|
87
|
+
data: { hName: 'DirectivesStack' },
|
|
88
|
+
children: group,
|
|
89
|
+
});
|
|
90
|
+
group = [];
|
|
91
|
+
}
|
|
92
|
+
newChildren.push(child);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (group.length > 0) {
|
|
96
|
+
newChildren.push({
|
|
97
|
+
type: 'leafDirective',
|
|
98
|
+
name: 'DirectivesStack',
|
|
99
|
+
data: { hName: 'DirectivesStack' },
|
|
100
|
+
children: group,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
dirNode.children = newChildren;
|
|
104
|
+
});
|
|
105
|
+
// Filter incomplete streaming directives
|
|
106
|
+
visit(tree, 'text', (node) => {
|
|
107
|
+
const textNode = node;
|
|
108
|
+
if (typeof textNode.value === 'string') {
|
|
109
|
+
if (textNode.value.match(/::?\w+[{[]/) && !textNode.value.match(/::?\w+[{[].+[}\]]/)) {
|
|
110
|
+
textNode.value = '';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
// Transform directives to React components
|
|
115
|
+
visit(tree, DIRECTIVE_TYPES, (node) => {
|
|
116
|
+
if (!isDirectiveNode(node))
|
|
117
|
+
return;
|
|
118
|
+
node.data = node.data || {};
|
|
119
|
+
node.data.hName = pascalCase(node.name);
|
|
120
|
+
node.data.hProperties = {
|
|
121
|
+
...node.attributes,
|
|
122
|
+
isInline: node.type === 'textDirective',
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export function remarkAgentDirectives() {
|
|
128
|
+
// Set up micromark extensions for parsing directive syntax (from remark-directive)
|
|
129
|
+
const data = this.data();
|
|
130
|
+
const micromarkExtensions = data.micromarkExtensions || (data.micromarkExtensions = []);
|
|
131
|
+
const fromMarkdownExtensions = data.fromMarkdownExtensions || (data.fromMarkdownExtensions = []);
|
|
132
|
+
const toMarkdownExtensions = data.toMarkdownExtensions || (data.toMarkdownExtensions = []);
|
|
133
|
+
micromarkExtensions.push(directive());
|
|
134
|
+
fromMarkdownExtensions.push(directiveFromMarkdown());
|
|
135
|
+
toMarkdownExtensions.push(directiveToMarkdown());
|
|
136
|
+
// Return our transformer for processing the parsed directives
|
|
137
|
+
return remarkDirectivesTransform();
|
|
138
|
+
}
|
|
139
|
+
const stackStyles = {
|
|
140
|
+
display: 'flex',
|
|
141
|
+
flexDirection: 'column',
|
|
142
|
+
gap: '1px',
|
|
143
|
+
borderRadius: '8px',
|
|
144
|
+
overflow: 'hidden',
|
|
145
|
+
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
|
|
146
|
+
margin: '8px 0',
|
|
147
|
+
};
|
|
148
|
+
const collapsedStackStyles = {
|
|
149
|
+
...stackStyles,
|
|
150
|
+
maxHeight: '280px',
|
|
151
|
+
overflowY: 'auto',
|
|
152
|
+
};
|
|
153
|
+
const expandButtonStyles = {
|
|
154
|
+
display: 'flex',
|
|
155
|
+
justifyContent: 'flex-end',
|
|
156
|
+
padding: '4px 0',
|
|
157
|
+
};
|
|
158
|
+
const buttonStyles = {
|
|
159
|
+
background: 'none',
|
|
160
|
+
border: 'none',
|
|
161
|
+
padding: '4px 8px',
|
|
162
|
+
cursor: 'pointer',
|
|
163
|
+
fontSize: '12px',
|
|
164
|
+
color: 'inherit',
|
|
165
|
+
opacity: 0.7,
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Default DirectivesStack component that groups consecutive directives.
|
|
169
|
+
* Override this in your components map if you need custom styling.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```tsx
|
|
173
|
+
* import { DirectivesStack } from '@sanity/agent-directives/react'
|
|
174
|
+
*
|
|
175
|
+
* // Use default
|
|
176
|
+
* components={{ DirectivesStack }}
|
|
177
|
+
*
|
|
178
|
+
* // Or override with your own
|
|
179
|
+
* components={{ DirectivesStack: MyCustomStack }}
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export function DirectivesStack({ children }) {
|
|
183
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
184
|
+
const childrenCount = Children.count(children);
|
|
185
|
+
const shouldCollapse = childrenCount > 5;
|
|
186
|
+
if (!shouldCollapse) {
|
|
187
|
+
return createElement('div', { style: stackStyles }, children);
|
|
188
|
+
}
|
|
189
|
+
return createElement('div', null, createElement('div', { style: isExpanded ? stackStyles : collapsedStackStyles }, children), createElement('div', { style: expandButtonStyles }, createElement('button', {
|
|
190
|
+
type: 'button',
|
|
191
|
+
style: buttonStyles,
|
|
192
|
+
onClick: () => setIsExpanded((prev) => !prev),
|
|
193
|
+
}, isExpanded ? 'Show less' : `Show all ${childrenCount}`)));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Creates a directive kit with application injection.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```tsx
|
|
200
|
+
* // kit.ts
|
|
201
|
+
* import { createDirectiveKit } from '@sanity/agent-directives/react'
|
|
202
|
+
* import type { Application } from '@sanity/agent-types'
|
|
203
|
+
*
|
|
204
|
+
* export const { defineDirective } = createDirectiveKit<Application>({
|
|
205
|
+
* useApplication: (source) => useThreadApplication(source),
|
|
206
|
+
* })
|
|
207
|
+
*
|
|
208
|
+
* // Document.tsx
|
|
209
|
+
* export const DocumentDirective = defineDirective('document', ({ id, application }) => {
|
|
210
|
+
* return <DocumentCard id={id} app={application} />
|
|
211
|
+
* })
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
export function createDirectiveKit(options) {
|
|
215
|
+
const { useApplication } = options;
|
|
216
|
+
function defineDirective(name, render) {
|
|
217
|
+
function Directive(props) {
|
|
218
|
+
const { node, source, ...rest } = props;
|
|
219
|
+
const application = useApplication(source);
|
|
220
|
+
if (!application)
|
|
221
|
+
return null;
|
|
222
|
+
// Merge node properties with component props (component props take precedence)
|
|
223
|
+
const merged = { ...(node?.properties ?? {}), ...rest };
|
|
224
|
+
// Validate against schema
|
|
225
|
+
const schema = DirectiveSchemas[name];
|
|
226
|
+
const result = schema.safeParse(merged);
|
|
227
|
+
if (!result.success) {
|
|
228
|
+
console.error(`Directive "${name}" validation error:`, result.error.format());
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
const renderProps = {
|
|
232
|
+
...result.data,
|
|
233
|
+
application,
|
|
234
|
+
};
|
|
235
|
+
return render(renderProps);
|
|
236
|
+
}
|
|
237
|
+
Directive.displayName = `Directive(${name})`;
|
|
238
|
+
return Directive;
|
|
239
|
+
}
|
|
240
|
+
return { defineDirective };
|
|
241
|
+
}
|
|
242
|
+
// ============================================================================
|
|
243
|
+
// Convenience: Default Components
|
|
244
|
+
// ============================================================================
|
|
245
|
+
/**
|
|
246
|
+
* Default components map including DirectivesStack.
|
|
247
|
+
* Spread this into your components and override as needed.
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```tsx
|
|
251
|
+
* import { defaultComponents } from '@sanity/agent-directives/react'
|
|
252
|
+
*
|
|
253
|
+
* <ReactMarkdown
|
|
254
|
+
* components={{
|
|
255
|
+
* ...defaultComponents,
|
|
256
|
+
* Document: DocumentDirective,
|
|
257
|
+
* }}
|
|
258
|
+
* >
|
|
259
|
+
* {content}
|
|
260
|
+
* </ReactMarkdown>
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
export const defaultComponents = {
|
|
264
|
+
DirectivesStack,
|
|
265
|
+
};
|
|
266
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.tsx"],"names":[],"mappings":"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"}
|
package/dist/string.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type DirectiveName, type DirectivePropsMap } from '@sanity/agent-types';
|
|
2
|
+
type DirectiveProps<T extends DirectiveName> = DirectivePropsMap[T];
|
|
3
|
+
export interface DirectiveNode {
|
|
4
|
+
type: 'textDirective' | 'leafDirective' | 'containerDirective';
|
|
5
|
+
name: string;
|
|
6
|
+
attributes?: Record<string, string | null | undefined>;
|
|
7
|
+
children?: unknown[];
|
|
8
|
+
}
|
|
9
|
+
export interface DirectiveBaseProps {
|
|
10
|
+
children: string;
|
|
11
|
+
isInline: boolean;
|
|
12
|
+
}
|
|
13
|
+
export type DirectiveRenderFn<TName extends DirectiveName, TContext, TOutput> = (props: DirectiveProps<TName> & DirectiveBaseProps & {
|
|
14
|
+
_context: TContext;
|
|
15
|
+
}) => TOutput | null | Promise<TOutput | null>;
|
|
16
|
+
export interface StringDirective<TName extends DirectiveName, TContext, TOutput> {
|
|
17
|
+
name: TName;
|
|
18
|
+
render: DirectiveRenderFn<TName, TContext, TOutput>;
|
|
19
|
+
}
|
|
20
|
+
export type StringDirectiveRegistry<TContext, TOutput> = Record<string, StringDirective<DirectiveName, TContext, TOutput>>;
|
|
21
|
+
export declare function createDirectiveKit<TContext = unknown, TOutput = unknown>(): {
|
|
22
|
+
defineDirective: <TName extends DirectiveName>(name: TName, render: DirectiveRenderFn<TName, TContext, TOutput>) => StringDirective<TName, TContext, TOutput>;
|
|
23
|
+
renderDirective: (node: DirectiveNode, context: TContext) => Promise<TOutput | null>;
|
|
24
|
+
registry: StringDirectiveRegistry<TContext, TOutput>;
|
|
25
|
+
};
|
|
26
|
+
export interface DirectiveRenderResult<TBlock = unknown> {
|
|
27
|
+
text?: string;
|
|
28
|
+
blocks?: TBlock[];
|
|
29
|
+
}
|
|
30
|
+
export type DirectiveOutput<TBlock = unknown> = string | DirectiveRenderResult<TBlock> | null;
|
|
31
|
+
export declare function hasBlocks<TBlock>(output: DirectiveOutput<TBlock>): output is DirectiveRenderResult<TBlock>;
|
|
32
|
+
export declare function normalizeOutput<TBlock>(output: DirectiveOutput<TBlock>): DirectiveRenderResult<TBlock> | null;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=string.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,iBAAiB,EAAoB,MAAM,qBAAqB,CAAA;AAElG,KAAK,cAAc,CAAC,CAAC,SAAS,aAAa,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAA;AAEnE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,eAAe,GAAG,eAAe,GAAG,oBAAoB,CAAA;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;IACtD,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,MAAM,iBAAiB,CAAC,KAAK,SAAS,aAAa,EAAE,QAAQ,EAAE,OAAO,IAAI,CAC9E,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,kBAAkB,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAA;CAAE,KACvE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;AAE7C,MAAM,WAAW,eAAe,CAAC,KAAK,SAAS,aAAa,EAAE,QAAQ,EAAE,OAAO;IAC7E,IAAI,EAAE,KAAK,CAAA;IACX,MAAM,EAAE,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAA;CACpD;AAED,MAAM,MAAM,uBAAuB,CAAC,QAAQ,EAAE,OAAO,IAAI,MAAM,CAC7D,MAAM,EACN,eAAe,CAAC,aAAa,EAAE,QAAQ,EAAE,OAAO,CAAC,CAClD,CAAA;AAqBD,wBAAgB,kBAAkB,CAAC,QAAQ,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO;sBAG7C,KAAK,SAAS,aAAa,QAC5C,KAAK,UACH,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,KAClD,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC;4BAMP,aAAa,WAAW,QAAQ,KAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;;EAgChG;AAED,MAAM,WAAW,qBAAqB,CAAC,MAAM,GAAG,OAAO;IACrD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,MAAM,eAAe,CAAC,MAAM,GAAG,OAAO,IAAI,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;AAE7F,wBAAgB,SAAS,CAAC,MAAM,EAC9B,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,GAC9B,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAEzC;AAED,wBAAgB,eAAe,CAAC,MAAM,EACpC,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,GAC9B,qBAAqB,CAAC,MAAM,CAAC,GAAG,IAAI,CAQtC"}
|
package/dist/string.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { DirectiveSchemas } from '@sanity/agent-types';
|
|
2
|
+
function extractChildren(node) {
|
|
3
|
+
if (!node.children || !Array.isArray(node.children)) {
|
|
4
|
+
return '';
|
|
5
|
+
}
|
|
6
|
+
function extractText(n) {
|
|
7
|
+
if (!n || typeof n !== 'object')
|
|
8
|
+
return '';
|
|
9
|
+
if ('type' in n && n.type === 'text' && 'value' in n && typeof n.value === 'string') {
|
|
10
|
+
return n.value;
|
|
11
|
+
}
|
|
12
|
+
if ('children' in n && Array.isArray(n.children)) {
|
|
13
|
+
return n.children.map(extractText).join('');
|
|
14
|
+
}
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
return node.children.map(extractText).join('');
|
|
18
|
+
}
|
|
19
|
+
export function createDirectiveKit() {
|
|
20
|
+
const registry = {};
|
|
21
|
+
function defineDirective(name, render) {
|
|
22
|
+
const directive = { name, render };
|
|
23
|
+
registry[name] = directive;
|
|
24
|
+
return directive;
|
|
25
|
+
}
|
|
26
|
+
async function renderDirective(node, context) {
|
|
27
|
+
const directive = registry[node.name];
|
|
28
|
+
if (!directive)
|
|
29
|
+
return null;
|
|
30
|
+
const schema = DirectiveSchemas[node.name];
|
|
31
|
+
if (!schema)
|
|
32
|
+
return null;
|
|
33
|
+
const rawProps = {
|
|
34
|
+
...node.attributes,
|
|
35
|
+
children: extractChildren(node),
|
|
36
|
+
isInline: node.type === 'textDirective',
|
|
37
|
+
};
|
|
38
|
+
const result = schema.safeParse(rawProps);
|
|
39
|
+
if (!result.success) {
|
|
40
|
+
console.error(`Directive "${node.name}" validation error:`, result.error.format());
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const props = {
|
|
44
|
+
...result.data,
|
|
45
|
+
children: rawProps.children,
|
|
46
|
+
isInline: rawProps.isInline,
|
|
47
|
+
_context: context,
|
|
48
|
+
};
|
|
49
|
+
return directive.render(props);
|
|
50
|
+
}
|
|
51
|
+
return { defineDirective, renderDirective, registry };
|
|
52
|
+
}
|
|
53
|
+
export function hasBlocks(output) {
|
|
54
|
+
return output !== null && typeof output === 'object' && 'blocks' in output;
|
|
55
|
+
}
|
|
56
|
+
export function normalizeOutput(output) {
|
|
57
|
+
if (output === null) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
if (typeof output === 'string') {
|
|
61
|
+
return { text: output };
|
|
62
|
+
}
|
|
63
|
+
return output;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=string.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string.js","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sanity/agent-directives",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Shared directive system for Sanity Agent",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"sanity",
|
|
7
|
+
"sanity-agent",
|
|
8
|
+
"directives"
|
|
9
|
+
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/sanity-io/sanity-agent.git",
|
|
13
|
+
"directory": "packages/agent-directives"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"type": "module",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"import": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts"
|
|
21
|
+
},
|
|
22
|
+
"./formatters": {
|
|
23
|
+
"import": "./dist/formatters.js",
|
|
24
|
+
"types": "./dist/formatters.d.ts"
|
|
25
|
+
},
|
|
26
|
+
"./react": {
|
|
27
|
+
"import": "./dist/react.js",
|
|
28
|
+
"types": "./dist/react.d.ts"
|
|
29
|
+
},
|
|
30
|
+
"./string": {
|
|
31
|
+
"import": "./dist/string.js",
|
|
32
|
+
"types": "./dist/string.d.ts"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"main": "./dist/index.js",
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"files": [
|
|
38
|
+
"dist/**/*"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc -p tsconfig.json",
|
|
42
|
+
"clean": "rm -rf dist",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"test:watch": "vitest",
|
|
45
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@sanity/agent-types": "workspace:*",
|
|
49
|
+
"es-toolkit": "^1.32.0",
|
|
50
|
+
"mdast-util-directive": "^3.0.0",
|
|
51
|
+
"micromark-extension-directive": "^3.0.0",
|
|
52
|
+
"unist-util-visit": "^5.0.0",
|
|
53
|
+
"zod": "^3.25.76"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
57
|
+
"@testing-library/react": "^16.0.0",
|
|
58
|
+
"@types/react": "^19.0.0",
|
|
59
|
+
"@types/unist": "^3.0.0",
|
|
60
|
+
"unified": "^11.0.0",
|
|
61
|
+
"jsdom": "^26.0.0",
|
|
62
|
+
"react": "^19.0.0",
|
|
63
|
+
"react-dom": "^19.0.0",
|
|
64
|
+
"react-markdown": "^10.0.0",
|
|
65
|
+
"typescript": "^5.3.3",
|
|
66
|
+
"vitest": "^3.0.9"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
70
|
+
},
|
|
71
|
+
"peerDependenciesMeta": {
|
|
72
|
+
"react": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"engines": {
|
|
77
|
+
"node": ">=18.0.0"
|
|
78
|
+
},
|
|
79
|
+
"publishConfig": {
|
|
80
|
+
"access": "restricted"
|
|
81
|
+
}
|
|
82
|
+
}
|