@portabletext/markdown 1.0.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 +429 -0
- package/dist/index.d.ts +599 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1098 -0
- package/dist/index.js.map +1 -0
- package/package.json +70 -0
- package/src/default-schema.ts +166 -0
- package/src/example-document.md +237 -0
- package/src/example-document.out.md +235 -0
- package/src/example-document.terse-pt.json +124 -0
- package/src/example-document.test.ts +87 -0
- package/src/from-portable-text/build-list-index-map.ts +133 -0
- package/src/from-portable-text/portable-text-to-markdown.ts +135 -0
- package/src/from-portable-text/render-node.ts +176 -0
- package/src/from-portable-text/renderers/block-spacing.ts +39 -0
- package/src/from-portable-text/renderers/hard-break.ts +4 -0
- package/src/from-portable-text/renderers/list-item.ts +32 -0
- package/src/from-portable-text/renderers/marks.ts +113 -0
- package/src/from-portable-text/renderers/style.ts +79 -0
- package/src/from-portable-text/renderers/type.ts +126 -0
- package/src/from-portable-text/types.ts +240 -0
- package/src/index.ts +51 -0
- package/src/key-generator.ts +32 -0
- package/src/markdown-to-portable-text.test.ts +3273 -0
- package/src/portable-text-to-markdown.test.ts +803 -0
- package/src/to-portable-text/markdown-to-portable-text.ts +1204 -0
- package/src/to-portable-text/matchers.ts +192 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
PortableTextObject,
|
|
3
|
+
Schema,
|
|
4
|
+
SchemaDefinition,
|
|
5
|
+
} from '@portabletext/schema'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Matcher function for mapping markdown elements to Portable Text block styles.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export type StyleMatcher = ({
|
|
13
|
+
context,
|
|
14
|
+
}: {
|
|
15
|
+
context: {schema: Schema}
|
|
16
|
+
}) => string | undefined
|
|
17
|
+
|
|
18
|
+
export function buildStyleMatcher<TDefinition extends {name: string}>(
|
|
19
|
+
definition: TDefinition,
|
|
20
|
+
): StyleMatcher {
|
|
21
|
+
return ({context}) => {
|
|
22
|
+
const schemaDefinition = context.schema.styles.find(
|
|
23
|
+
(item) => item.name === definition.name,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if (!schemaDefinition) {
|
|
27
|
+
return undefined
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return schemaDefinition.name
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Matcher function for mapping markdown list items to Portable Text list types.
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
export type ListItemMatcher = ({
|
|
40
|
+
context,
|
|
41
|
+
}: {
|
|
42
|
+
context: {schema: Schema}
|
|
43
|
+
}) => string | undefined
|
|
44
|
+
|
|
45
|
+
export function buildListItemMatcher<TDefinition extends {name: string}>(
|
|
46
|
+
definition: TDefinition,
|
|
47
|
+
): ListItemMatcher {
|
|
48
|
+
return ({context}) => {
|
|
49
|
+
const schemaDefinition = context.schema.lists.find(
|
|
50
|
+
(item) => item.name === definition.name,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
if (!schemaDefinition) {
|
|
54
|
+
return undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return schemaDefinition.name
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Matcher function for mapping markdown inline formatting to Portable Text decorators.
|
|
63
|
+
*
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
export type DecoratorMatcher = ({
|
|
67
|
+
context,
|
|
68
|
+
}: {
|
|
69
|
+
context: {schema: Schema}
|
|
70
|
+
}) => string | undefined
|
|
71
|
+
|
|
72
|
+
export function buildDecoratorMatcher<TDefinition extends {name: string}>(
|
|
73
|
+
definition: TDefinition,
|
|
74
|
+
): DecoratorMatcher {
|
|
75
|
+
return ({context}) => {
|
|
76
|
+
const schemaDefinition = context.schema.decorators.find(
|
|
77
|
+
(item) => item.name === definition.name,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if (!schemaDefinition) {
|
|
81
|
+
return undefined
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return schemaDefinition.name
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Matcher function for mapping markdown links to Portable Text annotations.
|
|
90
|
+
*
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
export type AnnotationMatcher<
|
|
94
|
+
TValue extends Record<string, unknown> = Record<string, never>,
|
|
95
|
+
> = ({
|
|
96
|
+
context,
|
|
97
|
+
value,
|
|
98
|
+
}: {
|
|
99
|
+
context: {schema: Schema; keyGenerator: () => string}
|
|
100
|
+
value: TValue
|
|
101
|
+
}) => PortableTextObject | undefined
|
|
102
|
+
|
|
103
|
+
export function buildAnnotationMatcher<TDefinition extends {name: string}>(
|
|
104
|
+
definition: TDefinition,
|
|
105
|
+
): AnnotationMatcher<ExtractValue<TDefinition>> {
|
|
106
|
+
return ({context, value}) => {
|
|
107
|
+
const schemaDefinition = context.schema.annotations.find(
|
|
108
|
+
(item) => item.name === definition.name,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if (!schemaDefinition) {
|
|
112
|
+
return undefined
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const filteredValue = schemaDefinition.fields.reduce<
|
|
116
|
+
Record<string, unknown>
|
|
117
|
+
>((filteredValue, field) => {
|
|
118
|
+
const fieldValue = value[field.name as keyof typeof value]
|
|
119
|
+
|
|
120
|
+
if (fieldValue !== undefined) {
|
|
121
|
+
filteredValue[field.name] = fieldValue
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return filteredValue
|
|
125
|
+
}, {})
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
_key: context.keyGenerator(),
|
|
129
|
+
_type: schemaDefinition.name,
|
|
130
|
+
...filteredValue,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Matcher function for mapping markdown objects to Portable Text block or inline objects.
|
|
137
|
+
*
|
|
138
|
+
* @public
|
|
139
|
+
*/
|
|
140
|
+
export type ObjectMatcher<
|
|
141
|
+
TValue extends Record<string, unknown> = Record<string, never>,
|
|
142
|
+
> = ({
|
|
143
|
+
context,
|
|
144
|
+
value,
|
|
145
|
+
isInline,
|
|
146
|
+
}: {
|
|
147
|
+
context: {schema: Schema; keyGenerator: () => string}
|
|
148
|
+
value: TValue
|
|
149
|
+
isInline: boolean
|
|
150
|
+
}) => PortableTextObject | undefined
|
|
151
|
+
|
|
152
|
+
export function buildObjectMatcher<TDefinition extends {name: string}>(
|
|
153
|
+
definition: TDefinition,
|
|
154
|
+
): ObjectMatcher<ExtractValue<TDefinition>> {
|
|
155
|
+
return ({context, value, isInline}) => {
|
|
156
|
+
const schemaCollection = isInline
|
|
157
|
+
? context.schema.inlineObjects
|
|
158
|
+
: context.schema.blockObjects
|
|
159
|
+
|
|
160
|
+
const schemaDefinition = schemaCollection.find(
|
|
161
|
+
(item) => item.name === definition.name,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
if (!schemaDefinition) {
|
|
165
|
+
return undefined
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const filteredValue = schemaDefinition.fields.reduce<
|
|
169
|
+
Record<string, unknown>
|
|
170
|
+
>((filteredValue, field) => {
|
|
171
|
+
const fieldValue = value[field.name as keyof typeof value]
|
|
172
|
+
|
|
173
|
+
if (fieldValue !== undefined) {
|
|
174
|
+
filteredValue[field.name] = fieldValue
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return filteredValue
|
|
178
|
+
}, {})
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
_key: context.keyGenerator(),
|
|
182
|
+
_type: schemaDefinition.name,
|
|
183
|
+
...filteredValue,
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export type ExtractValue<
|
|
189
|
+
TDefinition extends NonNullable<SchemaDefinition['blockObjects']>[0],
|
|
190
|
+
> = TDefinition extends {fields: ReadonlyArray<{name: infer TNames}>}
|
|
191
|
+
? Record<TNames & string, unknown>
|
|
192
|
+
: Record<string, never>
|