sanity-plugin-markdown 4.1.2 → 5.0.0-canary.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 +56 -55
- package/lib/_chunks-cjs/plugin.js +160 -0
- package/lib/_chunks-cjs/plugin.js.map +1 -0
- package/lib/_chunks-es/plugin.mjs +146 -0
- package/lib/_chunks-es/plugin.mjs.map +1 -0
- package/lib/_legacy/plugin.esm.js +146 -0
- package/lib/_legacy/plugin.esm.js.map +1 -0
- package/lib/index.d.mts +107 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.esm.js +8 -2
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +4 -7
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +9 -0
- package/lib/index.mjs.map +1 -0
- package/lib/indexNext.d.mts +107 -0
- package/lib/indexNext.d.ts +107 -0
- package/lib/indexNext.esm.js +7 -1
- package/lib/indexNext.esm.js.map +1 -1
- package/lib/indexNext.js +3 -6
- package/lib/indexNext.js.map +1 -1
- package/lib/indexNext.mjs +8 -0
- package/lib/indexNext.mjs.map +1 -0
- package/package.json +32 -36
- package/src/components/MarkdownInput.tsx +36 -26
- package/src/components/MarkdownInputStyles.tsx +61 -63
- package/lib/_chunks/plugin-0fd9aa65.js +0 -112
- package/lib/_chunks/plugin-0fd9aa65.js.map +0 -1
- package/lib/_chunks/plugin-fb6e236d.js +0 -123
- package/lib/_chunks/plugin-fb6e236d.js.map +0 -1
- package/src/components/useSimpleMdeReact.tsx +0 -12
package/README.md
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
## What is it?
|
|
7
7
|
|
|
8
|
-
A Markdown editor with preview for Sanity Studio.
|
|
8
|
+
A Markdown editor with preview for Sanity Studio.
|
|
9
9
|
|
|
10
|
-
Supports Github flavored markdown and image uploads.
|
|
11
|
-
You can either drag image(s) into the editor or click the bottom bar to bring up a file selector.
|
|
10
|
+
Supports Github flavored markdown and image uploads.
|
|
11
|
+
You can either drag image(s) into the editor or click the bottom bar to bring up a file selector.
|
|
12
12
|
The resulting image URL(s) are inserted with a default width parameter which you can change to your liking using the [Sanity image pipeline parameters](https://www.sanity.io/docs/image-urls).
|
|
13
13
|
|
|
14
14
|
The current version is a wrapper around [React SimpleMDE (EasyMDE) Markdown Editor](https://github.com/RIP21/react-simplemde-editor#react-simplemde-easymde-markdown-editor),
|
|
@@ -17,6 +17,7 @@ and by extension, [EasyMDE](https://github.com/Ionaru/easy-markdown-editor).
|
|
|
17
17
|

|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
|
+
|
|
20
21
|
Install `sanity-plugin-markdown` and `easymde@2` (peer dependency).
|
|
21
22
|
|
|
22
23
|
```
|
|
@@ -28,13 +29,11 @@ npm install --save sanity-plugin-markdown easymde@2
|
|
|
28
29
|
Add it as a plugin in sanity.config.ts (or .js):
|
|
29
30
|
|
|
30
31
|
```js
|
|
31
|
-
import {
|
|
32
|
+
import {markdownSchema} from 'sanity-plugin-markdown'
|
|
32
33
|
|
|
33
34
|
export default defineConfig({
|
|
34
35
|
// ...
|
|
35
|
-
plugins: [
|
|
36
|
-
markdownSchema(),
|
|
37
|
-
]
|
|
36
|
+
plugins: [markdownSchema()],
|
|
38
37
|
})
|
|
39
38
|
```
|
|
40
39
|
|
|
@@ -42,61 +41,65 @@ Then, declare a field in your schema to be `markdown`
|
|
|
42
41
|
|
|
43
42
|
```javascript
|
|
44
43
|
const myDocument = {
|
|
45
|
-
type:
|
|
46
|
-
name:
|
|
44
|
+
type: 'document',
|
|
45
|
+
name: 'myDocument',
|
|
47
46
|
fields: [
|
|
48
47
|
{
|
|
49
|
-
type:
|
|
50
|
-
description:
|
|
51
|
-
name:
|
|
52
|
-
}
|
|
53
|
-
]
|
|
48
|
+
type: 'markdown',
|
|
49
|
+
description: 'A Github flavored markdown field with image uploading',
|
|
50
|
+
name: 'bio',
|
|
51
|
+
},
|
|
52
|
+
],
|
|
54
53
|
}
|
|
55
54
|
```
|
|
55
|
+
|
|
56
56
|
### Next.js compatability
|
|
57
|
-
|
|
57
|
+
|
|
58
|
+
Next.js _without_ Next 13 app directory does not support css imports from `node_modules`.
|
|
58
59
|
|
|
59
60
|
To use this plugin in this context (`pages` directory), use the `sanity-plugin-markdown/next` import instead of `sanity-plugin-markdown`:
|
|
61
|
+
|
|
60
62
|
```js
|
|
61
|
-
import {
|
|
63
|
+
import {markdownSchema} from 'sanity-plugin-markdown/next'
|
|
62
64
|
```
|
|
63
65
|
|
|
64
|
-
Then, make sure to add
|
|
66
|
+
Then, make sure to add
|
|
67
|
+
|
|
65
68
|
```js
|
|
66
69
|
import 'easymde/dist/easymde.min.css'
|
|
67
70
|
```
|
|
68
71
|
|
|
69
|
-
to
|
|
72
|
+
to the top of `pages/_app.tsx`.
|
|
70
73
|
|
|
71
74
|
### Customizing the default markdown input editor
|
|
72
75
|
|
|
73
76
|
The plugin takes an `input` config option that can be used in combination with the `MarkdownInput` export
|
|
74
77
|
to configure the underlying React SimpleMDE component:
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
- Create a custom component that wraps MarkdownInput
|
|
80
|
+
- Memoize reactMdeProps and pass along
|
|
78
81
|
|
|
79
82
|
```tsx
|
|
80
83
|
// CustomMarkdownInput.tsx
|
|
81
|
-
import {
|
|
84
|
+
import {MarkdownInput, MarkdownInputProps} from 'sanity-plugin-markdown'
|
|
82
85
|
|
|
83
86
|
export function CustomMarkdownInput(props) {
|
|
84
|
-
const reactMdeProps: MarkdownInputProps['reactMdeProps'] =
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}, [])
|
|
87
|
+
const reactMdeProps: MarkdownInputProps['reactMdeProps'] = useMemo(() => {
|
|
88
|
+
return {
|
|
89
|
+
options: {
|
|
90
|
+
toolbar: ['bold', 'italic'],
|
|
91
|
+
// more options available, see:
|
|
92
|
+
// https://github.com/Ionaru/easy-markdown-editor#options-list
|
|
93
|
+
},
|
|
94
|
+
// more props available, see:
|
|
95
|
+
// https://github.com/RIP21/react-simplemde-editor#react-simplemde-easymde-markdown-editor
|
|
96
|
+
}
|
|
97
|
+
}, [])
|
|
96
98
|
|
|
97
99
|
return <MarkdownInput {...props} reactMdeProps={reactMdeProps} />
|
|
98
100
|
}
|
|
99
101
|
```
|
|
102
|
+
|
|
100
103
|
Set the plugin input option:
|
|
101
104
|
|
|
102
105
|
```ts
|
|
@@ -106,9 +109,7 @@ import {CustomMarkdownInput} from './CustomMarkdownInput'
|
|
|
106
109
|
|
|
107
110
|
export default defineConfig({
|
|
108
111
|
// ... rest of the config
|
|
109
|
-
plugins: [
|
|
110
|
-
markdownSchema({input: CustomMarkdownInput}),
|
|
111
|
-
]
|
|
112
|
+
plugins: [markdownSchema({input: CustomMarkdownInput})],
|
|
112
113
|
})
|
|
113
114
|
```
|
|
114
115
|
|
|
@@ -121,13 +122,13 @@ defineField({
|
|
|
121
122
|
type: 'markdown',
|
|
122
123
|
name: 'markdown',
|
|
123
124
|
title: 'Markdown',
|
|
124
|
-
components: {input: CustomMarkdownInput}
|
|
125
|
+
components: {input: CustomMarkdownInput},
|
|
125
126
|
})
|
|
126
127
|
```
|
|
127
128
|
|
|
128
129
|
### Customizing editor preview
|
|
129
130
|
|
|
130
|
-
One way to customize the preview that does not involve ReactDOMServer
|
|
131
|
+
One way to customize the preview that does not involve ReactDOMServer
|
|
131
132
|
(used by React SimpleMDE) is to install [marked](https://github.com/markedjs/marked) and
|
|
132
133
|
[DOMPurify](https://github.com/cure53/DOMPurify) and create a custom preview:
|
|
133
134
|
|
|
@@ -137,24 +138,23 @@ Then use these to create a custom editor:
|
|
|
137
138
|
|
|
138
139
|
```tsx
|
|
139
140
|
// MarkdownInputCustomPreview.tsx
|
|
140
|
-
import {
|
|
141
|
+
import {MarkdownInput, MarkdownInputProps} from 'sanity-plugin-markdown'
|
|
141
142
|
import DOMPurify from 'dompurify'
|
|
142
143
|
import {marked} from 'marked'
|
|
143
144
|
|
|
144
145
|
export function CustomMarkdownInput(props) {
|
|
145
|
-
const reactMdeProps: MarkdownInputProps['reactMdeProps'] =
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return DOMPurify.sanitize(marked.parse(markdownText))
|
|
153
|
-
}
|
|
154
|
-
//customizing using renderingConfig is also an option
|
|
146
|
+
const reactMdeProps: MarkdownInputProps['reactMdeProps'] = useMemo(() => {
|
|
147
|
+
return {
|
|
148
|
+
options: {
|
|
149
|
+
previewRender: (markdownText) => {
|
|
150
|
+
// configure as needed according to
|
|
151
|
+
// https://github.com/markedjs/marked#docs
|
|
152
|
+
return DOMPurify.sanitize(marked.parse(markdownText))
|
|
155
153
|
},
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
//customizing using renderingConfig is also an option
|
|
155
|
+
},
|
|
156
|
+
}
|
|
157
|
+
}, [])
|
|
158
158
|
|
|
159
159
|
return <MarkdownInput {...props} reactMdeProps={reactMdeProps} />
|
|
160
160
|
}
|
|
@@ -166,12 +166,13 @@ Use the component as described in previous sections.
|
|
|
166
166
|
|
|
167
167
|
Provide a function to options.imageUrl that takes a SanityImageAssetDocument and returns a string.
|
|
168
168
|
|
|
169
|
-
The function will be invoked whenever an image is pasted or dragged into the markdown editor,
|
|
169
|
+
The function will be invoked whenever an image is pasted or dragged into the markdown editor,
|
|
170
170
|
after upload completes.
|
|
171
171
|
|
|
172
172
|
The default implementation uses
|
|
173
|
+
|
|
173
174
|
```js
|
|
174
|
-
imageAsset => `${imageAsset.url}?w=450`
|
|
175
|
+
;(imageAsset) => `${imageAsset.url}?w=450`
|
|
175
176
|
```
|
|
176
177
|
|
|
177
178
|
#### Example imageUrl option
|
|
@@ -182,8 +183,8 @@ defineField({
|
|
|
182
183
|
name: 'markdown',
|
|
183
184
|
title: 'Markdown',
|
|
184
185
|
options: {
|
|
185
|
-
imageUrl: imageAsset => `${imageAsset.url}?w=400&h=400
|
|
186
|
-
}
|
|
186
|
+
imageUrl: (imageAsset) => `${imageAsset.url}?w=400&h=400`,
|
|
187
|
+
},
|
|
187
188
|
})
|
|
188
189
|
```
|
|
189
190
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __copyProps = (to, from, except, desc) => {
|
|
8
|
+
if (from && typeof from == "object" || typeof from == "function")
|
|
9
|
+
for (let key of __getOwnPropNames(from))
|
|
10
|
+
!__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
return to;
|
|
12
|
+
};
|
|
13
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
14
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
15
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
16
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
17
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
18
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target,
|
|
19
|
+
mod
|
|
20
|
+
));
|
|
21
|
+
var sanity = require("sanity"), jsxRuntime = require("react/jsx-runtime"), react = require("react"), ui = require("@sanity/ui"), styledComponents = require("styled-components");
|
|
22
|
+
const MarkdownInputStyles = styledComponents.styled(ui.Box)`
|
|
23
|
+
& .CodeMirror.CodeMirror {
|
|
24
|
+
color: ${({ theme }) => theme.sanity.color.card.enabled.fg};
|
|
25
|
+
border-color: ${({ theme }) => theme.sanity.color.card.enabled.border};
|
|
26
|
+
background-color: inherit;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
& .cm-s-easymde .CodeMirror-cursor {
|
|
30
|
+
border-color: ${({ theme }) => theme.sanity.color.card.enabled.fg};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
& .editor-toolbar,
|
|
34
|
+
.editor-preview-side {
|
|
35
|
+
border-color: ${({ theme }) => theme.sanity.color.card.enabled.border};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
& .CodeMirror-focused .CodeMirror-selected.CodeMirror-selected.CodeMirror-selected {
|
|
39
|
+
background-color: ${({ theme }) => theme.sanity.color.selectable?.primary?.hovered?.bg};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
& .CodeMirror-selected.CodeMirror-selected.CodeMirror-selected {
|
|
43
|
+
background-color: ${({ theme }) => theme.sanity.color.card.enabled.bg};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
& .editor-toolbar > * {
|
|
47
|
+
color: ${({ theme }) => theme.sanity.color.card.enabled.fg};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
& .editor-toolbar > .active,
|
|
51
|
+
.editor-toolbar > button:hover,
|
|
52
|
+
.editor-preview pre,
|
|
53
|
+
.cm-s-easymde .cm-comment {
|
|
54
|
+
background-color: ${({ theme }) => theme.sanity.color.card.enabled.bg};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
& .editor-preview {
|
|
58
|
+
background-color: ${({ theme }) => theme.sanity.color.card.enabled.bg};
|
|
59
|
+
|
|
60
|
+
& h1,
|
|
61
|
+
h2,
|
|
62
|
+
h3,
|
|
63
|
+
h4,
|
|
64
|
+
h5,
|
|
65
|
+
h6 {
|
|
66
|
+
font-size: revert;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
& ul,
|
|
70
|
+
li {
|
|
71
|
+
list-style: revert;
|
|
72
|
+
padding: revert;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
& a {
|
|
76
|
+
text-decoration: revert;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
`, SimpleMdeReact = react.lazy(() => import("react-simplemde-editor")), defaultMdeTools = [
|
|
80
|
+
"heading",
|
|
81
|
+
"bold",
|
|
82
|
+
"italic",
|
|
83
|
+
"|",
|
|
84
|
+
"quote",
|
|
85
|
+
"unordered-list",
|
|
86
|
+
"ordered-list",
|
|
87
|
+
"|",
|
|
88
|
+
"link",
|
|
89
|
+
"image",
|
|
90
|
+
"code",
|
|
91
|
+
"|",
|
|
92
|
+
"preview",
|
|
93
|
+
"side-by-side"
|
|
94
|
+
];
|
|
95
|
+
function MarkdownInput(props) {
|
|
96
|
+
const {
|
|
97
|
+
value = "",
|
|
98
|
+
onChange,
|
|
99
|
+
elementProps: { onBlur, onFocus, ref },
|
|
100
|
+
reactMdeProps: { options: mdeCustomOptions, ...reactMdeProps } = {},
|
|
101
|
+
schemaType
|
|
102
|
+
} = props, client = sanity.useClient({ apiVersion: "2022-01-01" }), { imageUrl } = schemaType.options ?? {}, imageUpload = react.useCallback(
|
|
103
|
+
(file, onSuccess, onError) => {
|
|
104
|
+
client.assets.upload("image", file).then((doc) => onSuccess(imageUrl ? imageUrl(doc) : `${doc.url}?w=450`)).catch((e) => {
|
|
105
|
+
console.error(e), onError(e.message);
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
[client, imageUrl]
|
|
109
|
+
), mdeOptions = react.useMemo(() => ({
|
|
110
|
+
autofocus: !1,
|
|
111
|
+
spellChecker: !1,
|
|
112
|
+
sideBySideFullscreen: !1,
|
|
113
|
+
uploadImage: !0,
|
|
114
|
+
imageUploadFunction: imageUpload,
|
|
115
|
+
toolbar: defaultMdeTools,
|
|
116
|
+
status: !1,
|
|
117
|
+
...mdeCustomOptions
|
|
118
|
+
}), [imageUpload, mdeCustomOptions]), handleChange = react.useCallback(
|
|
119
|
+
(newValue) => {
|
|
120
|
+
onChange(sanity.PatchEvent.from(newValue ? sanity.set(newValue) : sanity.unset()));
|
|
121
|
+
},
|
|
122
|
+
[onChange]
|
|
123
|
+
);
|
|
124
|
+
return react.useSyncExternalStore(
|
|
125
|
+
noop,
|
|
126
|
+
() => !0,
|
|
127
|
+
() => !1
|
|
128
|
+
) ? /* @__PURE__ */ jsxRuntime.jsx(MarkdownInputStyles, { children: /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
129
|
+
SimpleMdeReact,
|
|
130
|
+
{
|
|
131
|
+
...reactMdeProps,
|
|
132
|
+
ref,
|
|
133
|
+
value,
|
|
134
|
+
onChange: handleChange,
|
|
135
|
+
onBlur,
|
|
136
|
+
onFocus,
|
|
137
|
+
options: mdeOptions,
|
|
138
|
+
spellCheck: !1
|
|
139
|
+
}
|
|
140
|
+
) }) }) : /* @__PURE__ */ jsxRuntime.jsx(MarkdownInputStyles, { children: fallback });
|
|
141
|
+
}
|
|
142
|
+
const noop = () => () => {
|
|
143
|
+
}, fallback = /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading editor..." }) }), markdownTypeName = "markdown", markdownSchemaType = sanity.defineType({
|
|
144
|
+
type: "string",
|
|
145
|
+
name: markdownTypeName,
|
|
146
|
+
title: "Markdown",
|
|
147
|
+
components: { input: MarkdownInput }
|
|
148
|
+
}), markdownSchema = sanity.definePlugin((config) => ({
|
|
149
|
+
name: "markdown-editor",
|
|
150
|
+
schema: {
|
|
151
|
+
types: [
|
|
152
|
+
config && config.input ? { ...markdownSchemaType, components: { input: config.input } } : markdownSchemaType
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
}));
|
|
156
|
+
exports.MarkdownInput = MarkdownInput;
|
|
157
|
+
exports.defaultMdeTools = defaultMdeTools;
|
|
158
|
+
exports.markdownSchema = markdownSchema;
|
|
159
|
+
exports.markdownSchemaType = markdownSchemaType;
|
|
160
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["../../src/components/MarkdownInputStyles.tsx","../../src/components/MarkdownInput.tsx","../../src/schema.ts","../../src/plugin.tsx"],"sourcesContent":["import {Box} from '@sanity/ui'\nimport {styled} from 'styled-components'\n\nexport const MarkdownInputStyles = styled(Box)`\n & .CodeMirror.CodeMirror {\n color: ${({theme}) => theme.sanity.color.card.enabled.fg};\n border-color: ${({theme}) => theme.sanity.color.card.enabled.border};\n background-color: inherit;\n }\n\n & .cm-s-easymde .CodeMirror-cursor {\n border-color: ${({theme}) => theme.sanity.color.card.enabled.fg};\n }\n\n & .editor-toolbar,\n .editor-preview-side {\n border-color: ${({theme}) => theme.sanity.color.card.enabled.border};\n }\n\n & .CodeMirror-focused .CodeMirror-selected.CodeMirror-selected.CodeMirror-selected {\n background-color: ${({theme}) => theme.sanity.color.selectable?.primary?.hovered?.bg};\n }\n\n & .CodeMirror-selected.CodeMirror-selected.CodeMirror-selected {\n background-color: ${({theme}) => theme.sanity.color.card.enabled.bg};\n }\n\n & .editor-toolbar > * {\n color: ${({theme}) => theme.sanity.color.card.enabled.fg};\n }\n\n & .editor-toolbar > .active,\n .editor-toolbar > button:hover,\n .editor-preview pre,\n .cm-s-easymde .cm-comment {\n background-color: ${({theme}) => theme.sanity.color.card.enabled.bg};\n }\n\n & .editor-preview {\n background-color: ${({theme}) => theme.sanity.color.card.enabled.bg};\n\n & h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n font-size: revert;\n }\n\n & ul,\n li {\n list-style: revert;\n padding: revert;\n }\n\n & a {\n text-decoration: revert;\n }\n }\n`\n","import {type Options as EasyMdeOptions} from 'easymde'\nimport {lazy, Suspense, useCallback, useMemo, useSyncExternalStore} from 'react'\n// dont import non-types here, it will break SSR on next\nimport type {SimpleMDEReactProps} from 'react-simplemde-editor'\nimport {PatchEvent, set, StringInputProps, unset, useClient} from 'sanity'\nimport {MarkdownOptions} from '../schema'\nimport {MarkdownInputStyles} from './MarkdownInputStyles'\nimport {Box, Text} from '@sanity/ui'\n\nconst SimpleMdeReact = lazy(() => import('react-simplemde-editor'))\n\nexport interface MarkdownInputProps extends StringInputProps {\n /**\n * These are passed along directly to\n *\n * Note: MarkdownInput sets certain reactMdeProps.options by default.\n * These will be merged with any custom options.\n */\n reactMdeProps?: Omit<SimpleMDEReactProps, 'value' | 'onChange'>\n}\n\nexport const defaultMdeTools: EasyMdeOptions['toolbar'] = [\n 'heading',\n 'bold',\n 'italic',\n '|',\n 'quote',\n 'unordered-list',\n 'ordered-list',\n '|',\n 'link',\n 'image',\n 'code',\n '|',\n 'preview',\n 'side-by-side',\n]\n\nexport function MarkdownInput(props: MarkdownInputProps) {\n const {\n value = '',\n onChange,\n elementProps: {onBlur, onFocus, ref},\n reactMdeProps: {options: mdeCustomOptions, ...reactMdeProps} = {},\n schemaType,\n } = props\n const client = useClient({apiVersion: '2022-01-01'})\n const {imageUrl} = (schemaType.options as MarkdownOptions | undefined) ?? {}\n\n const imageUpload = useCallback(\n (file: File, onSuccess: (url: string) => void, onError: (error: string) => void) => {\n client.assets\n .upload('image', file)\n .then((doc) => onSuccess(imageUrl ? imageUrl(doc) : `${doc.url}?w=450`))\n .catch((e) => {\n console.error(e)\n onError(e.message)\n })\n },\n [client, imageUrl],\n )\n\n const mdeOptions: EasyMdeOptions = useMemo(() => {\n return {\n autofocus: false,\n spellChecker: false,\n sideBySideFullscreen: false,\n uploadImage: true,\n imageUploadFunction: imageUpload,\n toolbar: defaultMdeTools,\n status: false,\n ...mdeCustomOptions,\n }\n }, [imageUpload, mdeCustomOptions])\n\n const handleChange = useCallback(\n (newValue: string) => {\n onChange(PatchEvent.from(newValue ? set(newValue) : unset()))\n },\n [onChange],\n )\n\n const mounted = useSyncExternalStore(\n noop,\n () => true,\n () => false,\n )\n\n if (!mounted) {\n return <MarkdownInputStyles>{fallback}</MarkdownInputStyles>\n }\n\n return (\n <MarkdownInputStyles>\n <Suspense fallback={fallback}>\n <SimpleMdeReact\n {...reactMdeProps}\n ref={ref}\n value={value}\n onChange={handleChange}\n onBlur={onBlur}\n onFocus={onFocus}\n options={mdeOptions}\n spellCheck={false}\n />\n </Suspense>\n </MarkdownInputStyles>\n )\n}\n\n// eslint-disable-next-line no-empty-function\nconst noop = () => () => {}\n\nconst fallback = (\n <Box padding={3}>\n <Text>Loading editor...</Text>\n </Box>\n)\n","import {defineType, StringDefinition} from 'sanity'\nimport {MarkdownInput} from './components/MarkdownInput'\nimport {SanityImageAssetDocument} from '@sanity/client'\n\nexport const markdownTypeName = 'markdown' as const\n\nexport interface MarkdownOptions {\n /**\n * Used to create image url for any uploaded image.\n * The function will be invoked whenever an image is pasted or dragged into the\n * markdown editor, after upload completes.\n *\n * The default implementation uses\n * ```js\n * imageAsset => `${imageAsset.url}?w=450`\n * ```\n * ## Example\n * ```js\n * {\n * imageUrl: imageAsset => `${imageAsset.url}?w=400&h=400`\n * }\n * ```\n * @param imageAsset\n */\n imageUrl?: (imageAsset: SanityImageAssetDocument) => string\n}\n\n/**\n * @public\n */\nexport interface MarkdownDefinition extends Omit<StringDefinition, 'type' | 'fields' | 'options'> {\n type: typeof markdownTypeName\n options?: MarkdownOptions\n}\n\ndeclare module '@sanity/types' {\n // makes type: 'markdown' narrow correctly when using defineType/defineField/defineArrayMember\n export interface IntrinsicDefinitions {\n markdown: MarkdownDefinition\n }\n}\n\nexport const markdownSchemaType = defineType({\n type: 'string',\n name: markdownTypeName,\n title: 'Markdown',\n components: {input: MarkdownInput},\n})\n","import {definePlugin, StringInputProps} from 'sanity'\nimport {markdownSchemaType} from './schema'\nimport {ReactElement} from 'react'\n\nexport interface MarkdownConfig {\n /**\n * When provided, will replace the default input component.\n *\n * Use this to customize MarkdownInput by wrapping it in a custom component,\n * and provide any custom props for https://github.com/RIP21/react-simplemde-editor#react-simplemde-easymde-markdown-editor\n * via the `reactMdeProps` prop.\n *\n * ### Example\n *\n * ```tsx\n * // CustomMarkdownInput.tsx\n * import { MarkdownInput, MarkdownInputProps } from 'sanity-plugin-markdown'\n *\n * export function CustomMarkdownInput(props) {\n * const reactMdeProps: MarkdownInputProps['reactMdeProps'] =\n * useMemo(() => {\n * return {\n * options: {\n * toolbar: ['bold', 'italic'],\n * // more options available, see:\n * // https://github.com/Ionaru/easy-markdown-editor#options-list\n * },\n * // more props available, see:\n * // https://github.com/RIP21/react-simplemde-editor#react-simplemde-easymde-markdown-editor\n * }\n * }, [])\n *\n * return <MarkdownInput {...props} reactMdeProps={reactMdeProps} />\n * }\n *\n * // studio.config.ts\n * markdownSchema({input: CustomMarkdownInput})\n * ```\n */\n input?: (props: StringInputProps) => ReactElement\n}\n\nexport const markdownSchema = definePlugin((config: MarkdownConfig | void) => {\n return {\n name: 'markdown-editor',\n schema: {\n types: [\n config && config.input\n ? {...markdownSchemaType, components: {input: config.input}}\n : markdownSchemaType,\n ],\n },\n }\n})\n"],"names":["styled","Box","lazy","useClient","useCallback","useMemo","PatchEvent","set","unset","useSyncExternalStore","jsx","Suspense","Text","defineType","definePlugin"],"mappings":"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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { useClient, PatchEvent, set, unset, defineType, definePlugin } from "sanity";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { lazy, useCallback, useMemo, useSyncExternalStore, Suspense } from "react";
|
|
4
|
+
import { Box, Text } from "@sanity/ui";
|
|
5
|
+
import { styled } from "styled-components";
|
|
6
|
+
const MarkdownInputStyles = styled(Box)`
|
|
7
|
+
& .CodeMirror.CodeMirror {
|
|
8
|
+
color: ${({ theme }) => theme.sanity.color.card.enabled.fg};
|
|
9
|
+
border-color: ${({ theme }) => theme.sanity.color.card.enabled.border};
|
|
10
|
+
background-color: inherit;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
& .cm-s-easymde .CodeMirror-cursor {
|
|
14
|
+
border-color: ${({ theme }) => theme.sanity.color.card.enabled.fg};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
& .editor-toolbar,
|
|
18
|
+
.editor-preview-side {
|
|
19
|
+
border-color: ${({ theme }) => theme.sanity.color.card.enabled.border};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
& .CodeMirror-focused .CodeMirror-selected.CodeMirror-selected.CodeMirror-selected {
|
|
23
|
+
background-color: ${({ theme }) => theme.sanity.color.selectable?.primary?.hovered?.bg};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
& .CodeMirror-selected.CodeMirror-selected.CodeMirror-selected {
|
|
27
|
+
background-color: ${({ theme }) => theme.sanity.color.card.enabled.bg};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
& .editor-toolbar > * {
|
|
31
|
+
color: ${({ theme }) => theme.sanity.color.card.enabled.fg};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
& .editor-toolbar > .active,
|
|
35
|
+
.editor-toolbar > button:hover,
|
|
36
|
+
.editor-preview pre,
|
|
37
|
+
.cm-s-easymde .cm-comment {
|
|
38
|
+
background-color: ${({ theme }) => theme.sanity.color.card.enabled.bg};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
& .editor-preview {
|
|
42
|
+
background-color: ${({ theme }) => theme.sanity.color.card.enabled.bg};
|
|
43
|
+
|
|
44
|
+
& h1,
|
|
45
|
+
h2,
|
|
46
|
+
h3,
|
|
47
|
+
h4,
|
|
48
|
+
h5,
|
|
49
|
+
h6 {
|
|
50
|
+
font-size: revert;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
& ul,
|
|
54
|
+
li {
|
|
55
|
+
list-style: revert;
|
|
56
|
+
padding: revert;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
& a {
|
|
60
|
+
text-decoration: revert;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
`, SimpleMdeReact = lazy(() => import("react-simplemde-editor")), defaultMdeTools = [
|
|
64
|
+
"heading",
|
|
65
|
+
"bold",
|
|
66
|
+
"italic",
|
|
67
|
+
"|",
|
|
68
|
+
"quote",
|
|
69
|
+
"unordered-list",
|
|
70
|
+
"ordered-list",
|
|
71
|
+
"|",
|
|
72
|
+
"link",
|
|
73
|
+
"image",
|
|
74
|
+
"code",
|
|
75
|
+
"|",
|
|
76
|
+
"preview",
|
|
77
|
+
"side-by-side"
|
|
78
|
+
];
|
|
79
|
+
function MarkdownInput(props) {
|
|
80
|
+
const {
|
|
81
|
+
value = "",
|
|
82
|
+
onChange,
|
|
83
|
+
elementProps: { onBlur, onFocus, ref },
|
|
84
|
+
reactMdeProps: { options: mdeCustomOptions, ...reactMdeProps } = {},
|
|
85
|
+
schemaType
|
|
86
|
+
} = props, client = useClient({ apiVersion: "2022-01-01" }), { imageUrl } = schemaType.options ?? {}, imageUpload = useCallback(
|
|
87
|
+
(file, onSuccess, onError) => {
|
|
88
|
+
client.assets.upload("image", file).then((doc) => onSuccess(imageUrl ? imageUrl(doc) : `${doc.url}?w=450`)).catch((e) => {
|
|
89
|
+
console.error(e), onError(e.message);
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
[client, imageUrl]
|
|
93
|
+
), mdeOptions = useMemo(() => ({
|
|
94
|
+
autofocus: !1,
|
|
95
|
+
spellChecker: !1,
|
|
96
|
+
sideBySideFullscreen: !1,
|
|
97
|
+
uploadImage: !0,
|
|
98
|
+
imageUploadFunction: imageUpload,
|
|
99
|
+
toolbar: defaultMdeTools,
|
|
100
|
+
status: !1,
|
|
101
|
+
...mdeCustomOptions
|
|
102
|
+
}), [imageUpload, mdeCustomOptions]), handleChange = useCallback(
|
|
103
|
+
(newValue) => {
|
|
104
|
+
onChange(PatchEvent.from(newValue ? set(newValue) : unset()));
|
|
105
|
+
},
|
|
106
|
+
[onChange]
|
|
107
|
+
);
|
|
108
|
+
return useSyncExternalStore(
|
|
109
|
+
noop,
|
|
110
|
+
() => !0,
|
|
111
|
+
() => !1
|
|
112
|
+
) ? /* @__PURE__ */ jsx(MarkdownInputStyles, { children: /* @__PURE__ */ jsx(Suspense, { fallback, children: /* @__PURE__ */ jsx(
|
|
113
|
+
SimpleMdeReact,
|
|
114
|
+
{
|
|
115
|
+
...reactMdeProps,
|
|
116
|
+
ref,
|
|
117
|
+
value,
|
|
118
|
+
onChange: handleChange,
|
|
119
|
+
onBlur,
|
|
120
|
+
onFocus,
|
|
121
|
+
options: mdeOptions,
|
|
122
|
+
spellCheck: !1
|
|
123
|
+
}
|
|
124
|
+
) }) }) : /* @__PURE__ */ jsx(MarkdownInputStyles, { children: fallback });
|
|
125
|
+
}
|
|
126
|
+
const noop = () => () => {
|
|
127
|
+
}, fallback = /* @__PURE__ */ jsx(Box, { padding: 3, children: /* @__PURE__ */ jsx(Text, { children: "Loading editor..." }) }), markdownTypeName = "markdown", markdownSchemaType = defineType({
|
|
128
|
+
type: "string",
|
|
129
|
+
name: markdownTypeName,
|
|
130
|
+
title: "Markdown",
|
|
131
|
+
components: { input: MarkdownInput }
|
|
132
|
+
}), markdownSchema = definePlugin((config) => ({
|
|
133
|
+
name: "markdown-editor",
|
|
134
|
+
schema: {
|
|
135
|
+
types: [
|
|
136
|
+
config && config.input ? { ...markdownSchemaType, components: { input: config.input } } : markdownSchemaType
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
}));
|
|
140
|
+
export {
|
|
141
|
+
MarkdownInput,
|
|
142
|
+
defaultMdeTools,
|
|
143
|
+
markdownSchema,
|
|
144
|
+
markdownSchemaType
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=plugin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.mjs","sources":["../../src/components/MarkdownInputStyles.tsx","../../src/components/MarkdownInput.tsx","../../src/schema.ts","../../src/plugin.tsx"],"sourcesContent":["import {Box} from '@sanity/ui'\nimport {styled} from 'styled-components'\n\nexport const MarkdownInputStyles = styled(Box)`\n & .CodeMirror.CodeMirror {\n color: ${({theme}) => theme.sanity.color.card.enabled.fg};\n border-color: ${({theme}) => theme.sanity.color.card.enabled.border};\n background-color: inherit;\n }\n\n & .cm-s-easymde .CodeMirror-cursor {\n border-color: ${({theme}) => theme.sanity.color.card.enabled.fg};\n }\n\n & .editor-toolbar,\n .editor-preview-side {\n border-color: ${({theme}) => theme.sanity.color.card.enabled.border};\n }\n\n & .CodeMirror-focused .CodeMirror-selected.CodeMirror-selected.CodeMirror-selected {\n background-color: ${({theme}) => theme.sanity.color.selectable?.primary?.hovered?.bg};\n }\n\n & .CodeMirror-selected.CodeMirror-selected.CodeMirror-selected {\n background-color: ${({theme}) => theme.sanity.color.card.enabled.bg};\n }\n\n & .editor-toolbar > * {\n color: ${({theme}) => theme.sanity.color.card.enabled.fg};\n }\n\n & .editor-toolbar > .active,\n .editor-toolbar > button:hover,\n .editor-preview pre,\n .cm-s-easymde .cm-comment {\n background-color: ${({theme}) => theme.sanity.color.card.enabled.bg};\n }\n\n & .editor-preview {\n background-color: ${({theme}) => theme.sanity.color.card.enabled.bg};\n\n & h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n font-size: revert;\n }\n\n & ul,\n li {\n list-style: revert;\n padding: revert;\n }\n\n & a {\n text-decoration: revert;\n }\n }\n`\n","import {type Options as EasyMdeOptions} from 'easymde'\nimport {lazy, Suspense, useCallback, useMemo, useSyncExternalStore} from 'react'\n// dont import non-types here, it will break SSR on next\nimport type {SimpleMDEReactProps} from 'react-simplemde-editor'\nimport {PatchEvent, set, StringInputProps, unset, useClient} from 'sanity'\nimport {MarkdownOptions} from '../schema'\nimport {MarkdownInputStyles} from './MarkdownInputStyles'\nimport {Box, Text} from '@sanity/ui'\n\nconst SimpleMdeReact = lazy(() => import('react-simplemde-editor'))\n\nexport interface MarkdownInputProps extends StringInputProps {\n /**\n * These are passed along directly to\n *\n * Note: MarkdownInput sets certain reactMdeProps.options by default.\n * These will be merged with any custom options.\n */\n reactMdeProps?: Omit<SimpleMDEReactProps, 'value' | 'onChange'>\n}\n\nexport const defaultMdeTools: EasyMdeOptions['toolbar'] = [\n 'heading',\n 'bold',\n 'italic',\n '|',\n 'quote',\n 'unordered-list',\n 'ordered-list',\n '|',\n 'link',\n 'image',\n 'code',\n '|',\n 'preview',\n 'side-by-side',\n]\n\nexport function MarkdownInput(props: MarkdownInputProps) {\n const {\n value = '',\n onChange,\n elementProps: {onBlur, onFocus, ref},\n reactMdeProps: {options: mdeCustomOptions, ...reactMdeProps} = {},\n schemaType,\n } = props\n const client = useClient({apiVersion: '2022-01-01'})\n const {imageUrl} = (schemaType.options as MarkdownOptions | undefined) ?? {}\n\n const imageUpload = useCallback(\n (file: File, onSuccess: (url: string) => void, onError: (error: string) => void) => {\n client.assets\n .upload('image', file)\n .then((doc) => onSuccess(imageUrl ? imageUrl(doc) : `${doc.url}?w=450`))\n .catch((e) => {\n console.error(e)\n onError(e.message)\n })\n },\n [client, imageUrl],\n )\n\n const mdeOptions: EasyMdeOptions = useMemo(() => {\n return {\n autofocus: false,\n spellChecker: false,\n sideBySideFullscreen: false,\n uploadImage: true,\n imageUploadFunction: imageUpload,\n toolbar: defaultMdeTools,\n status: false,\n ...mdeCustomOptions,\n }\n }, [imageUpload, mdeCustomOptions])\n\n const handleChange = useCallback(\n (newValue: string) => {\n onChange(PatchEvent.from(newValue ? set(newValue) : unset()))\n },\n [onChange],\n )\n\n const mounted = useSyncExternalStore(\n noop,\n () => true,\n () => false,\n )\n\n if (!mounted) {\n return <MarkdownInputStyles>{fallback}</MarkdownInputStyles>\n }\n\n return (\n <MarkdownInputStyles>\n <Suspense fallback={fallback}>\n <SimpleMdeReact\n {...reactMdeProps}\n ref={ref}\n value={value}\n onChange={handleChange}\n onBlur={onBlur}\n onFocus={onFocus}\n options={mdeOptions}\n spellCheck={false}\n />\n </Suspense>\n </MarkdownInputStyles>\n )\n}\n\n// eslint-disable-next-line no-empty-function\nconst noop = () => () => {}\n\nconst fallback = (\n <Box padding={3}>\n <Text>Loading editor...</Text>\n </Box>\n)\n","import {defineType, StringDefinition} from 'sanity'\nimport {MarkdownInput} from './components/MarkdownInput'\nimport {SanityImageAssetDocument} from '@sanity/client'\n\nexport const markdownTypeName = 'markdown' as const\n\nexport interface MarkdownOptions {\n /**\n * Used to create image url for any uploaded image.\n * The function will be invoked whenever an image is pasted or dragged into the\n * markdown editor, after upload completes.\n *\n * The default implementation uses\n * ```js\n * imageAsset => `${imageAsset.url}?w=450`\n * ```\n * ## Example\n * ```js\n * {\n * imageUrl: imageAsset => `${imageAsset.url}?w=400&h=400`\n * }\n * ```\n * @param imageAsset\n */\n imageUrl?: (imageAsset: SanityImageAssetDocument) => string\n}\n\n/**\n * @public\n */\nexport interface MarkdownDefinition extends Omit<StringDefinition, 'type' | 'fields' | 'options'> {\n type: typeof markdownTypeName\n options?: MarkdownOptions\n}\n\ndeclare module '@sanity/types' {\n // makes type: 'markdown' narrow correctly when using defineType/defineField/defineArrayMember\n export interface IntrinsicDefinitions {\n markdown: MarkdownDefinition\n }\n}\n\nexport const markdownSchemaType = defineType({\n type: 'string',\n name: markdownTypeName,\n title: 'Markdown',\n components: {input: MarkdownInput},\n})\n","import {definePlugin, StringInputProps} from 'sanity'\nimport {markdownSchemaType} from './schema'\nimport {ReactElement} from 'react'\n\nexport interface MarkdownConfig {\n /**\n * When provided, will replace the default input component.\n *\n * Use this to customize MarkdownInput by wrapping it in a custom component,\n * and provide any custom props for https://github.com/RIP21/react-simplemde-editor#react-simplemde-easymde-markdown-editor\n * via the `reactMdeProps` prop.\n *\n * ### Example\n *\n * ```tsx\n * // CustomMarkdownInput.tsx\n * import { MarkdownInput, MarkdownInputProps } from 'sanity-plugin-markdown'\n *\n * export function CustomMarkdownInput(props) {\n * const reactMdeProps: MarkdownInputProps['reactMdeProps'] =\n * useMemo(() => {\n * return {\n * options: {\n * toolbar: ['bold', 'italic'],\n * // more options available, see:\n * // https://github.com/Ionaru/easy-markdown-editor#options-list\n * },\n * // more props available, see:\n * // https://github.com/RIP21/react-simplemde-editor#react-simplemde-easymde-markdown-editor\n * }\n * }, [])\n *\n * return <MarkdownInput {...props} reactMdeProps={reactMdeProps} />\n * }\n *\n * // studio.config.ts\n * markdownSchema({input: CustomMarkdownInput})\n * ```\n */\n input?: (props: StringInputProps) => ReactElement\n}\n\nexport const markdownSchema = definePlugin((config: MarkdownConfig | void) => {\n return {\n name: 'markdown-editor',\n schema: {\n types: [\n config && config.input\n ? {...markdownSchemaType, components: {input: config.input}}\n : markdownSchemaType,\n ],\n },\n }\n})\n"],"names":[],"mappings":"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"}
|