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 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
  ![example.png](./assets/example.png)
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 { markdownSchema } from "sanity-plugin-markdown";
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: "document",
46
- name: "myDocument",
44
+ type: 'document',
45
+ name: 'myDocument',
47
46
  fields: [
48
47
  {
49
- type: "markdown",
50
- description: "A Github flavored markdown field with image uploading",
51
- name: "bio"
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
- Next.js *without* Next 13 app directory does not support css imports from `node_modules`.
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 { markdownSchema } from "sanity-plugin-markdown/next";
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 the top of `pages/_app.tsx`.
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
- * Create a custom component that wraps MarkdownInput
77
- * Memoize reactMdeProps and pass along
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 { MarkdownInput, MarkdownInputProps } from 'sanity-plugin-markdown'
84
+ import {MarkdownInput, MarkdownInputProps} from 'sanity-plugin-markdown'
82
85
 
83
86
  export function CustomMarkdownInput(props) {
84
- const reactMdeProps: MarkdownInputProps['reactMdeProps'] =
85
- useMemo(() => {
86
- return {
87
- options: {
88
- toolbar: ['bold', 'italic'],
89
- // more options available, see:
90
- // https://github.com/Ionaru/easy-markdown-editor#options-list
91
- },
92
- // more props available, see:
93
- // https://github.com/RIP21/react-simplemde-editor#react-simplemde-easymde-markdown-editor
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 { MarkdownInput, MarkdownInputProps } from 'sanity-plugin-markdown'
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
- 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))
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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"}