sanity-plugin-markdown 3.0.0-v3-studio.0 → 3.0.0-v3-studio.2

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 Rune Botten
3
+ Copyright (c) 2022 Rune Botten
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -10,9 +10,15 @@
10
10
 
11
11
  A Markdown editor with preview for Sanity Studio.
12
12
 
13
- Supports Github flavored markdown and image uploads. You can either drag image(s) into the editor or click the bottom bar to bring up a file selector. 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
+ Supports Github flavored markdown and image uploads. You can either drag image(s) into the editor or click the bottom bar to bring up a file selector.
14
+ 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).
15
+
16
+ ### Known issues with the current v3 version
14
17
 
15
- ![Markdown input](assets/markdown-input.png)
18
+ The v2 version used react-mde for editing. The current v3 version @uiw/react-md-editor. This may change before GA.
19
+
20
+ At the moment the v3 version does not have drag-and-drop image upload support.
21
+ You can still add markdown image tags, but you will have to get the image url yourself for now.
16
22
 
17
23
  ## Installation
18
24
 
@@ -68,22 +74,15 @@ See LICENSE
68
74
 
69
75
  ## Develop & test
70
76
 
71
- Make sure to run `npm run build` once, then run
72
-
73
- ```bash
74
- npm run link-watch
75
- ```
76
-
77
- In another shell, `cd` to your test studio and run:
77
+ This plugin uses [@sanity/plugin-kit](https://github.com/sanity-io/plugin-kit)
78
+ with default configuration for build & watch scripts.
78
79
 
79
- ```bash
80
- npx yalc add sanity-plugin-markdown --link && yarn install
81
- ```
80
+ See [Testing a plugin in Sanity Studio](https://github.com/sanity-io/plugin-kit#testing-a-plugin-in-sanity-studio)
81
+ on how to run this plugin with hotreload in the studio.
82
82
 
83
- Now, changes in this repo will be automatically built and pushed to the studio,
84
- triggering hotreload. Yalc avoids issues with react-hooks that are typical when using yarn/npm link.
83
+ ### Release new version
85
84
 
86
- ### About build & watch
85
+ Run ["CI & Release" workflow](https://github.com/sanity-io/sanity-plugin-markdown/actions).
86
+ Make sure to select the main/v3 branch and check "Release new version".
87
87
 
88
- This plugin uses [@sanity/plugin-sdk](https://github.com/sanity-io/plugin-sdk)
89
- with default configuration for build & watch scripts.
88
+ Semantic release will only release on configured branches, so it is safe to run release on any branch.
package/lib/index.d.ts CHANGED
@@ -1,6 +1,4 @@
1
- import { StringInputProps } from "sanity";
2
- import React from "react";
3
- export const MarkdownEditor: React.ForwardRefExoticComponent<StringInputProps<import("sanity").StringSchemaType> & React.RefAttributes<any>>;
1
+ export const MarkdownEditor: import("react").ForwardRefExoticComponent<import("sanity").StringInputProps<import("sanity").StringSchemaType> & import("react").RefAttributes<any>>;
4
2
  export const markdownSchema: import("sanity").Plugin<void>;
5
3
 
6
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"mappings":";;ACyEA,OAAO,MAAM,+HA0FX,CAAA;AC9JF,OAAO,MAAM,6CAcX,CAAA","sources":["src/src/hooks/useDebounce.ts","src/src/components/Editor.tsx","src/src/index.ts","src/index.ts"],"sourcesContent":[null,null,null,"import {MarkdownEditor} from './components/Editor'\nimport {createPlugin, defineType} from 'sanity'\n\nexport {MarkdownEditor}\n\nexport const markdownSchema = createPlugin({\n name: 'markdown-editor',\n schema: {\n types: [\n defineType({\n type: 'string',\n name: 'markdown',\n title: 'Markdown',\n components: {\n input: MarkdownEditor,\n },\n }),\n ],\n },\n})\n"],"names":[],"version":3,"file":"index.d.ts.map","sourceRoot":"../"}
1
+ {"mappings":"AEIA,OAAA,MAAM,oKAAuB,CAAA;AAI7B,OAAO,MAAM,6CAcX,CAAA","sources":["src/src/hooks/useDebounce.ts","src/src/components/Editor.tsx","src/src/index.ts","src/index.ts"],"sourcesContent":[null,null,null,"import {MarkdownEditor as Editor} from './components/Editor'\nimport {createPlugin, defineType} from 'sanity'\n\n// re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:\nconst MarkdownEditor = Editor\n\nexport {MarkdownEditor}\n\nexport const markdownSchema = createPlugin({\n name: 'markdown-editor',\n schema: {\n types: [\n defineType({\n type: 'string' as const,\n name: 'markdown',\n title: 'Markdown',\n components: {\n input: MarkdownEditor,\n },\n }),\n ],\n },\n})\n"],"names":[],"version":3,"file":"index.d.ts.map","sourceRoot":"../"}
package/lib/index.js CHANGED
@@ -1,14 +1,10 @@
1
1
  var $3KLdq$sanity = require("sanity");
2
2
  var $3KLdq$reactjsxruntime = require("react/jsx-runtime");
3
- var $3KLdq$reactmde = require("react-mde");
4
- var $3KLdq$reactmarkdown = require("react-markdown");
5
- var $3KLdq$remarkgfm = require("remark-gfm");
6
- var $3KLdq$reachautoid = require("@reach/auto-id");
7
- require("react-mde/lib/styles/css/react-mde-all.css");
3
+ var $3KLdq$uiwreactmdeditor = require("@uiw/react-md-editor");
8
4
  var $3KLdq$sanityform = require("sanity/form");
9
5
  var $3KLdq$react = require("react");
10
- var $3KLdq$styledcomponents = require("styled-components");
11
6
  var $3KLdq$sanityui = require("@sanity/ui");
7
+ var $3KLdq$rehypesanitize = require("rehype-sanitize");
12
8
 
13
9
  function $parcel$export(e, n, v, s) {
14
10
  Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
@@ -17,11 +13,8 @@ function $parcel$interopDefault(a) {
17
13
  return a && a.__esModule ? a.default : a;
18
14
  }
19
15
 
16
+ $parcel$export(module.exports, "MarkdownEditor", () => $244e63ca53592e4d$export$18a9461578883ec4);
20
17
  $parcel$export(module.exports, "markdownSchema", () => $244e63ca53592e4d$export$f225414958dd8925);
21
- $parcel$export(module.exports, "MarkdownEditor", () => $067e75d167fd097d$export$18a9461578883ec4);
22
-
23
-
24
-
25
18
 
26
19
 
27
20
 
@@ -44,84 +37,11 @@ function $84fd43422be26bd7$export$2e2bcd8739ae039(value, delay) {
44
37
 
45
38
 
46
39
 
47
-
48
-
49
- const $067e75d167fd097d$var$Preview = ({ markdown: markdown })=>{
50
- return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, ($parcel$interopDefault($3KLdq$reactmarkdown))), {
51
- plugins: [
52
- (0, ($parcel$interopDefault($3KLdq$remarkgfm)))
53
- ],
54
- children: markdown
55
- });
56
- };
57
- const $067e75d167fd097d$var$defaultToolbarCommands = [
58
- [
59
- "header",
60
- "bold",
61
- "italic",
62
- "strikethrough"
63
- ],
64
- [
65
- "link",
66
- "quote",
67
- "code"
68
- ],
69
- [
70
- "unordered-list",
71
- "ordered-list",
72
- "checked-list"
73
- ],
74
- ];
75
- // !important is used whenever we need to override inline styles for an element
76
- const $067e75d167fd097d$var$MarkdownTheme = (0, ($parcel$interopDefault($3KLdq$styledcomponents))).div`
77
- & .react-mde {
78
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
79
- }
80
-
81
- & .mde-text {
82
- background: ${({ studioTheme: studioTheme })=>studioTheme.color.input.default.enabled.bg} !important;
83
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.input.default.enabled.fg} !important;
84
- }
85
-
86
- & .mde-header {
87
- background: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.bg};
88
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.fg};
89
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
90
-
91
- & button,
92
- .mde-header-item.mde-header-item.mde-header-item button {
93
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.button.bleed.default.enabled.fg};
94
- }
95
-
96
- & button.selected {
97
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
98
- }
99
- }
100
-
101
- & .image-tip {
102
- background: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.bg};
103
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.muted.default.enabled.fg};
104
- font-family: ${({ studioTheme: studioTheme })=>studioTheme.fonts.text.family};
105
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
106
- }
107
- `;
108
40
  const $067e75d167fd097d$export$18a9461578883ec4 = /*#__PURE__*/ (0, $3KLdq$react.forwardRef)(function MarkdownEditor(props, ref) {
109
- const { schemaType: type , value: value = "" , onBlur: onBlur , onChange: onChange , onFocus: onFocus , readOnly: readOnly } = props;
110
- const options = type.options;
111
- const [selectedTab, setSelectedTab] = (0, $3KLdq$react.useState)("write");
41
+ const { value: value = "" , onChange: onChange , elementProps: { onBlur: onBlur , onFocus: onFocus } , readOnly: readOnly , } = props;
112
42
  const [editedValue, setEditedValue] = (0, $3KLdq$react.useState)(value);
113
43
  const debouncedValue = (0, $84fd43422be26bd7$export$2e2bcd8739ae039)(editedValue, 100);
114
- const textarea = (0, $3KLdq$react.useRef)(null);
115
- const sanityClient = (0, $3KLdq$sanity.useClient)();
116
- // Conditionally update textarea styles based on read only access.
117
- // It's also possible to define inline styles via `childProps.textArea.style` on `<ReactMde />`,
118
- // but this will override any dynamically created styles provided by the component itself.
119
- (0, $3KLdq$react.useEffect)(()=>{
120
- if (textarea.current) textarea.current.style.backgroundColor = readOnly ? "rgba(240,240,240)" : "rgba(255,255,255)";
121
- }, [
122
- textarea,
123
- readOnly
124
- ]);
44
+ // const client = useClient({apiVersion: '2021-03-25'})
125
45
  (0, $3KLdq$react.useEffect)(()=>{
126
46
  setEditedValue(value);
127
47
  }, [
@@ -139,63 +59,55 @@ const $067e75d167fd097d$export$18a9461578883ec4 = /*#__PURE__*/ (0, $3KLdq$react
139
59
  debouncedValue,
140
60
  onChange
141
61
  ]);
142
- const saveImage = async function*(data) {
143
- const client = sanityClient.withConfig({
144
- apiVersion: "2021-03-25"
145
- });
146
- let success = true;
147
- const result = await client.assets.upload("image", data).then((doc)=>`${doc.url}?w=450`).catch(()=>{
148
- success = false;
149
- return `Error: Could not upload file. Only images are supported.`;
150
- });
151
- yield result;
152
- return success;
153
- };
154
- const generatePreview = (0, $3KLdq$react.useCallback)((markdown)=>Promise.resolve(/*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)($067e75d167fd097d$var$Preview, {
155
- markdown: markdown
156
- })), []);
157
- const inputId = (0, $3KLdq$reachautoid.useId)();
158
- const { sanity: studioTheme } = (0, $3KLdq$sanityui.useTheme)();
159
- /*
160
- Assign our forwarded ref to a wrapper element.
161
- Ideally, this should be assigned to the textarea inside <ReactMde /> component.
162
- Whilst `react-mde` does allow you to target individual sub-components' refs,
163
- it will complain if you try and assign a forwarded ref.
164
- */ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("div", {
62
+ /* const saveImage = async function* (data: any) {
63
+
64
+ let success = true
65
+ const result = await client.assets
66
+ .upload('image', data)
67
+ .then((doc) => `${doc.url}?w=450`)
68
+ .catch(() => {
69
+ success = false
70
+ return `Error: Could not upload file. Only images are supported.`
71
+ })
72
+
73
+ yield result
74
+ return success
75
+ }*/ const { sanity: studioTheme } = (0, $3KLdq$sanityui.useTheme)();
76
+ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("div", {
165
77
  ref: ref,
166
- children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)($067e75d167fd097d$var$MarkdownTheme, {
167
- studioTheme: studioTheme,
168
- children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, ($parcel$interopDefault($3KLdq$reactmde))), {
169
- toolbarCommands: options?.toolbar || $067e75d167fd097d$var$defaultToolbarCommands,
170
- value: editedValue,
171
- onChange: setEditedValue,
172
- selectedTab: selectedTab,
173
- onTabChange: setSelectedTab,
174
- readOnly: readOnly,
175
- generateMarkdownPreview: generatePreview,
176
- childProps: {
177
- textArea: {
178
- id: inputId,
179
- onBlur: onBlur,
180
- onFocus: onFocus
181
- },
182
- writeButton: {
183
- tabIndex: -1
184
- }
185
- },
186
- paste: {
187
- saveImage: saveImage
188
- },
189
- refs: {
190
- textarea: textarea
191
- }
78
+ "data-color-mode": studioTheme.color.dark ? "dark" : "light",
79
+ children: readOnly ? /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Card), {
80
+ border: true,
81
+ padding: 3,
82
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, ($parcel$interopDefault($3KLdq$uiwreactmdeditor))).Markdown, {
83
+ source: value,
84
+ rehypePlugins: [
85
+ [
86
+ (0, ($parcel$interopDefault($3KLdq$rehypesanitize)))
87
+ ]
88
+ ]
192
89
  })
90
+ }) : /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, ($parcel$interopDefault($3KLdq$uiwreactmdeditor))), {
91
+ value: editedValue,
92
+ onChange: setEditedValue,
93
+ onBlur: onBlur,
94
+ onFocus: onFocus,
95
+ previewOptions: {
96
+ rehypePlugins: [
97
+ [
98
+ (0, ($parcel$interopDefault($3KLdq$rehypesanitize)))
99
+ ]
100
+ ]
101
+ },
102
+ preview: "edit"
193
103
  })
194
104
  });
195
105
  });
196
106
 
197
107
 
198
108
 
109
+ // re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:
110
+ const $244e63ca53592e4d$export$18a9461578883ec4 = (0, $067e75d167fd097d$export$18a9461578883ec4);
199
111
  const $244e63ca53592e4d$export$f225414958dd8925 = (0, $3KLdq$sanity.createPlugin)({
200
112
  name: "markdown-editor",
201
113
  schema: {
@@ -205,7 +117,7 @@ const $244e63ca53592e4d$export$f225414958dd8925 = (0, $3KLdq$sanity.createPlugin
205
117
  name: "markdown",
206
118
  title: "Markdown",
207
119
  components: {
208
- input: (0, $067e75d167fd097d$export$18a9461578883ec4)
120
+ input: $244e63ca53592e4d$export$18a9461578883ec4
209
121
  }
210
122
  }),
211
123
  ]
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"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","sources":["src/index.ts","src/components/Editor.tsx","src/hooks/useDebounce.ts"],"sourcesContent":["import {MarkdownEditor} from './components/Editor'\nimport {createPlugin, defineType} from 'sanity'\n\nexport {MarkdownEditor}\n\nexport const markdownSchema = createPlugin({\n name: 'markdown-editor',\n schema: {\n types: [\n defineType({\n type: 'string',\n name: 'markdown',\n title: 'Markdown',\n components: {\n input: MarkdownEditor,\n },\n }),\n ],\n },\n})\n","import ReactMde from 'react-mde'\nimport ReactMarkdown from 'react-markdown'\nimport gfm from 'remark-gfm'\nimport {useId} from '@reach/auto-id'\n\nimport useDebounce from '../hooks/useDebounce'\nimport 'react-mde/lib/styles/css/react-mde-all.css'\nimport {PatchEvent, set, unset} from 'sanity/form'\nimport {StringInputProps, useClient} from 'sanity'\nimport React, {\n FC,\n forwardRef,\n PropsWithChildren,\n Ref,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react'\nimport {ToolbarCommands} from 'react-mde/lib/definitions/types'\nimport styled from 'styled-components'\nimport {Theme, useTheme} from '@sanity/ui'\n\nconst Preview = ({markdown}: {markdown: string}) => {\n return <ReactMarkdown plugins={[gfm]}>{markdown}</ReactMarkdown>\n}\n\nconst defaultToolbarCommands = [\n ['header', 'bold', 'italic', 'strikethrough'],\n ['link', 'quote', 'code'],\n ['unordered-list', 'ordered-list', 'checked-list'],\n]\n\ntype SanityTheme = Theme['sanity']\n\ntype Style = PropsWithChildren<{\n studioTheme: SanityTheme\n}>\n\n// !important is used whenever we need to override inline styles for an element\nconst MarkdownTheme: FC<Style> = styled.div`\n & .react-mde {\n border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};\n }\n\n & .mde-text {\n background: ${({studioTheme}: Style) => studioTheme.color.input.default.enabled.bg} !important;\n color: ${({studioTheme}: Style) => studioTheme.color.input.default.enabled.fg} !important;\n }\n\n & .mde-header {\n background: ${({studioTheme}: Style) => studioTheme.color.card.enabled.bg};\n color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.fg};\n border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};\n\n & button,\n .mde-header-item.mde-header-item.mde-header-item button {\n color: ${({studioTheme}: Style) => studioTheme.color.button.bleed.default.enabled.fg};\n }\n\n & button.selected {\n border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};\n }\n }\n\n & .image-tip {\n background: ${({studioTheme}: Style) => studioTheme.color.card.enabled.bg};\n color: ${({studioTheme}: Style) => studioTheme.color.muted.default.enabled.fg};\n font-family: ${({studioTheme}: Style) => studioTheme.fonts.text.family};\n border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};\n }\n`\n\nexport const MarkdownEditor = forwardRef(function MarkdownEditor(\n props: StringInputProps,\n ref: Ref<any>\n) {\n const {schemaType: type, value = '', onBlur, onChange, onFocus, readOnly} = props\n const options: {toolbar?: ToolbarCommands} | undefined = type.options as any\n const [selectedTab, setSelectedTab] = useState<'write' | 'preview'>('write')\n const [editedValue, setEditedValue] = useState(value)\n const debouncedValue = useDebounce(editedValue, 100)\n const textarea = useRef<HTMLTextAreaElement>(null)\n const sanityClient = useClient()\n\n // Conditionally update textarea styles based on read only access.\n // It's also possible to define inline styles via `childProps.textArea.style` on `<ReactMde />`,\n // but this will override any dynamically created styles provided by the component itself.\n useEffect(() => {\n if (textarea.current) {\n textarea.current.style.backgroundColor = readOnly ? 'rgba(240,240,240)' : 'rgba(255,255,255)'\n }\n }, [textarea, readOnly])\n\n useEffect(() => {\n setEditedValue(value)\n }, [value])\n\n useEffect(() => {\n if (!debouncedValue && value) {\n onChange(PatchEvent.from([unset()]))\n } else if (debouncedValue !== value) {\n onChange(PatchEvent.from([set(debouncedValue)]))\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debouncedValue, onChange])\n\n const saveImage = async function* (data: any) {\n const client = sanityClient.withConfig({apiVersion: '2021-03-25'})\n\n let success = true\n const result = await client.assets\n .upload('image', data)\n .then((doc) => `${doc.url}?w=450`)\n .catch(() => {\n success = false\n return `Error: Could not upload file. Only images are supported.`\n })\n\n yield result\n return success\n }\n\n const generatePreview = useCallback(\n (markdown: string) => Promise.resolve(<Preview markdown={markdown} />),\n []\n )\n\n const inputId = useId()\n const {sanity: studioTheme} = useTheme()\n /*\n Assign our forwarded ref to a wrapper element.\n Ideally, this should be assigned to the textarea inside <ReactMde /> component.\n Whilst `react-mde` does allow you to target individual sub-components' refs,\n it will complain if you try and assign a forwarded ref.\n */\n return (\n <div ref={ref}>\n <MarkdownTheme studioTheme={studioTheme}>\n <ReactMde\n toolbarCommands={options?.toolbar || defaultToolbarCommands}\n value={editedValue}\n onChange={setEditedValue}\n selectedTab={selectedTab}\n onTabChange={setSelectedTab}\n readOnly={readOnly}\n generateMarkdownPreview={generatePreview}\n childProps={{\n textArea: {\n id: inputId,\n onBlur,\n onFocus,\n },\n writeButton: {\n tabIndex: -1,\n },\n }}\n paste={{saveImage}}\n refs={{textarea}}\n />\n </MarkdownTheme>\n </div>\n )\n})\n","import {useState, useEffect} from 'react'\n\nexport default function useDebounce(value: unknown, delay: number) {\n const [debouncedValue, setDebouncedValue] = useState(value)\n useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value)\n }, delay)\n\n return () => clearTimeout(handler)\n }, [value, delay])\n\n return debouncedValue\n}\n"],"names":[],"version":3,"file":"index.js.map","sourceRoot":"../"}
1
+ {"mappings":"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","sources":["src/index.ts","src/components/Editor.tsx","src/hooks/useDebounce.ts"],"sourcesContent":["import {MarkdownEditor as Editor} from './components/Editor'\nimport {createPlugin, defineType} from 'sanity'\n\n// re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:\nconst MarkdownEditor = Editor\n\nexport {MarkdownEditor}\n\nexport const markdownSchema = createPlugin({\n name: 'markdown-editor',\n schema: {\n types: [\n defineType({\n type: 'string' as const,\n name: 'markdown',\n title: 'Markdown',\n components: {\n input: MarkdownEditor,\n },\n }),\n ],\n },\n})\n","import MDEditor from '@uiw/react-md-editor'\nimport useDebounce from '../hooks/useDebounce'\nimport {PatchEvent, set, unset} from 'sanity/form'\nimport {StringInputProps} from 'sanity'\nimport React, {forwardRef, Ref, useEffect, useState} from 'react'\nimport {Card, useTheme} from '@sanity/ui'\nimport rehypeSanitize from 'rehype-sanitize'\n\nexport const MarkdownEditor = forwardRef(function MarkdownEditor(\n props: StringInputProps,\n ref: Ref<any>\n) {\n const {\n value = '',\n onChange,\n elementProps: {onBlur, onFocus},\n readOnly,\n } = props\n const [editedValue, setEditedValue] = useState<string | undefined>(value)\n const debouncedValue = useDebounce(editedValue, 100)\n // const client = useClient({apiVersion: '2021-03-25'})\n\n useEffect(() => {\n setEditedValue(value)\n }, [value])\n\n useEffect(() => {\n if (!debouncedValue && value) {\n onChange(PatchEvent.from([unset()]))\n } else if (debouncedValue !== value) {\n onChange(PatchEvent.from([set(debouncedValue)]))\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debouncedValue, onChange])\n\n /* const saveImage = async function* (data: any) {\n\n let success = true\n const result = await client.assets\n .upload('image', data)\n .then((doc) => `${doc.url}?w=450`)\n .catch(() => {\n success = false\n return `Error: Could not upload file. Only images are supported.`\n })\n\n yield result\n return success\n }*/\n\n const {sanity: studioTheme} = useTheme()\n return (\n <div ref={ref} data-color-mode={studioTheme.color.dark ? 'dark' : 'light'}>\n {readOnly ? (\n <Card border padding={3}>\n <MDEditor.Markdown source={value} rehypePlugins={[[rehypeSanitize]]} />\n </Card>\n ) : (\n <MDEditor\n value={editedValue}\n onChange={setEditedValue}\n onBlur={onBlur}\n onFocus={onFocus}\n previewOptions={{\n rehypePlugins: [[rehypeSanitize]],\n }}\n preview=\"edit\"\n />\n )}\n </div>\n )\n})\n","import {useState, useEffect} from 'react'\n\nexport default function useDebounce(value: unknown, delay: number) {\n const [debouncedValue, setDebouncedValue] = useState(value)\n useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value)\n }, delay)\n\n return () => clearTimeout(handler)\n }, [value, delay])\n\n return debouncedValue\n}\n"],"names":[],"version":3,"file":"index.js.map","sourceRoot":"../"}
@@ -1,17 +1,10 @@
1
- import {createPlugin as $jPEKE$createPlugin, defineType as $jPEKE$defineType, useClient as $jPEKE$useClient} from "sanity";
1
+ import {createPlugin as $jPEKE$createPlugin, defineType as $jPEKE$defineType} from "sanity";
2
2
  import {jsx as $jPEKE$jsx} from "react/jsx-runtime";
3
- import $jPEKE$reactmde from "react-mde";
4
- import $jPEKE$reactmarkdown from "react-markdown";
5
- import $jPEKE$remarkgfm from "remark-gfm";
6
- import {useId as $jPEKE$useId} from "@reach/auto-id";
7
- import "react-mde/lib/styles/css/react-mde-all.css";
3
+ import $jPEKE$uiwreactmdeditor from "@uiw/react-md-editor";
8
4
  import {PatchEvent as $jPEKE$PatchEvent, unset as $jPEKE$unset, set as $jPEKE$set} from "sanity/form";
9
- import {forwardRef as $jPEKE$forwardRef, useState as $jPEKE$useState, useRef as $jPEKE$useRef, useEffect as $jPEKE$useEffect, useCallback as $jPEKE$useCallback} from "react";
10
- import $jPEKE$styledcomponents from "styled-components";
11
- import {useTheme as $jPEKE$useTheme} from "@sanity/ui";
12
-
13
-
14
-
5
+ import {forwardRef as $jPEKE$forwardRef, useState as $jPEKE$useState, useEffect as $jPEKE$useEffect} from "react";
6
+ import {useTheme as $jPEKE$useTheme, Card as $jPEKE$Card} from "@sanity/ui";
7
+ import $jPEKE$rehypesanitize from "rehype-sanitize";
15
8
 
16
9
 
17
10
 
@@ -35,84 +28,11 @@ function $a9f5cf746146e5f0$export$2e2bcd8739ae039(value, delay) {
35
28
 
36
29
 
37
30
 
38
-
39
-
40
- const $483dd42bf797352b$var$Preview = ({ markdown: markdown })=>{
41
- return /*#__PURE__*/ (0, $jPEKE$jsx)((0, $jPEKE$reactmarkdown), {
42
- plugins: [
43
- (0, $jPEKE$remarkgfm)
44
- ],
45
- children: markdown
46
- });
47
- };
48
- const $483dd42bf797352b$var$defaultToolbarCommands = [
49
- [
50
- "header",
51
- "bold",
52
- "italic",
53
- "strikethrough"
54
- ],
55
- [
56
- "link",
57
- "quote",
58
- "code"
59
- ],
60
- [
61
- "unordered-list",
62
- "ordered-list",
63
- "checked-list"
64
- ],
65
- ];
66
- // !important is used whenever we need to override inline styles for an element
67
- const $483dd42bf797352b$var$MarkdownTheme = (0, $jPEKE$styledcomponents).div`
68
- & .react-mde {
69
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
70
- }
71
-
72
- & .mde-text {
73
- background: ${({ studioTheme: studioTheme })=>studioTheme.color.input.default.enabled.bg} !important;
74
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.input.default.enabled.fg} !important;
75
- }
76
-
77
- & .mde-header {
78
- background: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.bg};
79
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.fg};
80
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
81
-
82
- & button,
83
- .mde-header-item.mde-header-item.mde-header-item button {
84
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.button.bleed.default.enabled.fg};
85
- }
86
-
87
- & button.selected {
88
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
89
- }
90
- }
91
-
92
- & .image-tip {
93
- background: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.bg};
94
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.muted.default.enabled.fg};
95
- font-family: ${({ studioTheme: studioTheme })=>studioTheme.fonts.text.family};
96
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
97
- }
98
- `;
99
31
  const $483dd42bf797352b$export$18a9461578883ec4 = /*#__PURE__*/ (0, $jPEKE$forwardRef)(function MarkdownEditor(props, ref) {
100
- const { schemaType: type , value: value = "" , onBlur: onBlur , onChange: onChange , onFocus: onFocus , readOnly: readOnly } = props;
101
- const options = type.options;
102
- const [selectedTab, setSelectedTab] = (0, $jPEKE$useState)("write");
32
+ const { value: value = "" , onChange: onChange , elementProps: { onBlur: onBlur , onFocus: onFocus } , readOnly: readOnly , } = props;
103
33
  const [editedValue, setEditedValue] = (0, $jPEKE$useState)(value);
104
34
  const debouncedValue = (0, $a9f5cf746146e5f0$export$2e2bcd8739ae039)(editedValue, 100);
105
- const textarea = (0, $jPEKE$useRef)(null);
106
- const sanityClient = (0, $jPEKE$useClient)();
107
- // Conditionally update textarea styles based on read only access.
108
- // It's also possible to define inline styles via `childProps.textArea.style` on `<ReactMde />`,
109
- // but this will override any dynamically created styles provided by the component itself.
110
- (0, $jPEKE$useEffect)(()=>{
111
- if (textarea.current) textarea.current.style.backgroundColor = readOnly ? "rgba(240,240,240)" : "rgba(255,255,255)";
112
- }, [
113
- textarea,
114
- readOnly
115
- ]);
35
+ // const client = useClient({apiVersion: '2021-03-25'})
116
36
  (0, $jPEKE$useEffect)(()=>{
117
37
  setEditedValue(value);
118
38
  }, [
@@ -130,63 +50,55 @@ const $483dd42bf797352b$export$18a9461578883ec4 = /*#__PURE__*/ (0, $jPEKE$forwa
130
50
  debouncedValue,
131
51
  onChange
132
52
  ]);
133
- const saveImage = async function*(data) {
134
- const client = sanityClient.withConfig({
135
- apiVersion: "2021-03-25"
136
- });
137
- let success = true;
138
- const result = await client.assets.upload("image", data).then((doc)=>`${doc.url}?w=450`).catch(()=>{
139
- success = false;
140
- return `Error: Could not upload file. Only images are supported.`;
141
- });
142
- yield result;
143
- return success;
144
- };
145
- const generatePreview = (0, $jPEKE$useCallback)((markdown)=>Promise.resolve(/*#__PURE__*/ (0, $jPEKE$jsx)($483dd42bf797352b$var$Preview, {
146
- markdown: markdown
147
- })), []);
148
- const inputId = (0, $jPEKE$useId)();
149
- const { sanity: studioTheme } = (0, $jPEKE$useTheme)();
150
- /*
151
- Assign our forwarded ref to a wrapper element.
152
- Ideally, this should be assigned to the textarea inside <ReactMde /> component.
153
- Whilst `react-mde` does allow you to target individual sub-components' refs,
154
- it will complain if you try and assign a forwarded ref.
155
- */ return /*#__PURE__*/ (0, $jPEKE$jsx)("div", {
53
+ /* const saveImage = async function* (data: any) {
54
+
55
+ let success = true
56
+ const result = await client.assets
57
+ .upload('image', data)
58
+ .then((doc) => `${doc.url}?w=450`)
59
+ .catch(() => {
60
+ success = false
61
+ return `Error: Could not upload file. Only images are supported.`
62
+ })
63
+
64
+ yield result
65
+ return success
66
+ }*/ const { sanity: studioTheme } = (0, $jPEKE$useTheme)();
67
+ return /*#__PURE__*/ (0, $jPEKE$jsx)("div", {
156
68
  ref: ref,
157
- children: /*#__PURE__*/ (0, $jPEKE$jsx)($483dd42bf797352b$var$MarkdownTheme, {
158
- studioTheme: studioTheme,
159
- children: /*#__PURE__*/ (0, $jPEKE$jsx)((0, $jPEKE$reactmde), {
160
- toolbarCommands: options?.toolbar || $483dd42bf797352b$var$defaultToolbarCommands,
161
- value: editedValue,
162
- onChange: setEditedValue,
163
- selectedTab: selectedTab,
164
- onTabChange: setSelectedTab,
165
- readOnly: readOnly,
166
- generateMarkdownPreview: generatePreview,
167
- childProps: {
168
- textArea: {
169
- id: inputId,
170
- onBlur: onBlur,
171
- onFocus: onFocus
172
- },
173
- writeButton: {
174
- tabIndex: -1
175
- }
176
- },
177
- paste: {
178
- saveImage: saveImage
179
- },
180
- refs: {
181
- textarea: textarea
182
- }
69
+ "data-color-mode": studioTheme.color.dark ? "dark" : "light",
70
+ children: readOnly ? /*#__PURE__*/ (0, $jPEKE$jsx)((0, $jPEKE$Card), {
71
+ border: true,
72
+ padding: 3,
73
+ children: /*#__PURE__*/ (0, $jPEKE$jsx)((0, $jPEKE$uiwreactmdeditor).Markdown, {
74
+ source: value,
75
+ rehypePlugins: [
76
+ [
77
+ (0, $jPEKE$rehypesanitize)
78
+ ]
79
+ ]
183
80
  })
81
+ }) : /*#__PURE__*/ (0, $jPEKE$jsx)((0, $jPEKE$uiwreactmdeditor), {
82
+ value: editedValue,
83
+ onChange: setEditedValue,
84
+ onBlur: onBlur,
85
+ onFocus: onFocus,
86
+ previewOptions: {
87
+ rehypePlugins: [
88
+ [
89
+ (0, $jPEKE$rehypesanitize)
90
+ ]
91
+ ]
92
+ },
93
+ preview: "edit"
184
94
  })
185
95
  });
186
96
  });
187
97
 
188
98
 
189
99
 
100
+ // re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:
101
+ const $df9eabe9bda49ea8$export$18a9461578883ec4 = (0, $483dd42bf797352b$export$18a9461578883ec4);
190
102
  const $df9eabe9bda49ea8$export$f225414958dd8925 = (0, $jPEKE$createPlugin)({
191
103
  name: "markdown-editor",
192
104
  schema: {
@@ -196,7 +108,7 @@ const $df9eabe9bda49ea8$export$f225414958dd8925 = (0, $jPEKE$createPlugin)({
196
108
  name: "markdown",
197
109
  title: "Markdown",
198
110
  components: {
199
- input: (0, $483dd42bf797352b$export$18a9461578883ec4)
111
+ input: $df9eabe9bda49ea8$export$18a9461578883ec4
200
112
  }
201
113
  }),
202
114
  ]
@@ -204,5 +116,5 @@ const $df9eabe9bda49ea8$export$f225414958dd8925 = (0, $jPEKE$createPlugin)({
204
116
  });
205
117
 
206
118
 
207
- export {$df9eabe9bda49ea8$export$f225414958dd8925 as markdownSchema, $483dd42bf797352b$export$18a9461578883ec4 as MarkdownEditor};
119
+ export {$df9eabe9bda49ea8$export$18a9461578883ec4 as MarkdownEditor, $df9eabe9bda49ea8$export$f225414958dd8925 as markdownSchema};
208
120
  //# sourceMappingURL=index.modern.js.map
@@ -1 +1 @@
1
- {"mappings":"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","sources":["src/index.ts","src/components/Editor.tsx","src/hooks/useDebounce.ts"],"sourcesContent":["import {MarkdownEditor} from './components/Editor'\nimport {createPlugin, defineType} from 'sanity'\n\nexport {MarkdownEditor}\n\nexport const markdownSchema = createPlugin({\n name: 'markdown-editor',\n schema: {\n types: [\n defineType({\n type: 'string',\n name: 'markdown',\n title: 'Markdown',\n components: {\n input: MarkdownEditor,\n },\n }),\n ],\n },\n})\n","import ReactMde from 'react-mde'\nimport ReactMarkdown from 'react-markdown'\nimport gfm from 'remark-gfm'\nimport {useId} from '@reach/auto-id'\n\nimport useDebounce from '../hooks/useDebounce'\nimport 'react-mde/lib/styles/css/react-mde-all.css'\nimport {PatchEvent, set, unset} from 'sanity/form'\nimport {StringInputProps, useClient} from 'sanity'\nimport React, {\n FC,\n forwardRef,\n PropsWithChildren,\n Ref,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react'\nimport {ToolbarCommands} from 'react-mde/lib/definitions/types'\nimport styled from 'styled-components'\nimport {Theme, useTheme} from '@sanity/ui'\n\nconst Preview = ({markdown}: {markdown: string}) => {\n return <ReactMarkdown plugins={[gfm]}>{markdown}</ReactMarkdown>\n}\n\nconst defaultToolbarCommands = [\n ['header', 'bold', 'italic', 'strikethrough'],\n ['link', 'quote', 'code'],\n ['unordered-list', 'ordered-list', 'checked-list'],\n]\n\ntype SanityTheme = Theme['sanity']\n\ntype Style = PropsWithChildren<{\n studioTheme: SanityTheme\n}>\n\n// !important is used whenever we need to override inline styles for an element\nconst MarkdownTheme: FC<Style> = styled.div`\n & .react-mde {\n border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};\n }\n\n & .mde-text {\n background: ${({studioTheme}: Style) => studioTheme.color.input.default.enabled.bg} !important;\n color: ${({studioTheme}: Style) => studioTheme.color.input.default.enabled.fg} !important;\n }\n\n & .mde-header {\n background: ${({studioTheme}: Style) => studioTheme.color.card.enabled.bg};\n color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.fg};\n border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};\n\n & button,\n .mde-header-item.mde-header-item.mde-header-item button {\n color: ${({studioTheme}: Style) => studioTheme.color.button.bleed.default.enabled.fg};\n }\n\n & button.selected {\n border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};\n }\n }\n\n & .image-tip {\n background: ${({studioTheme}: Style) => studioTheme.color.card.enabled.bg};\n color: ${({studioTheme}: Style) => studioTheme.color.muted.default.enabled.fg};\n font-family: ${({studioTheme}: Style) => studioTheme.fonts.text.family};\n border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};\n }\n`\n\nexport const MarkdownEditor = forwardRef(function MarkdownEditor(\n props: StringInputProps,\n ref: Ref<any>\n) {\n const {schemaType: type, value = '', onBlur, onChange, onFocus, readOnly} = props\n const options: {toolbar?: ToolbarCommands} | undefined = type.options as any\n const [selectedTab, setSelectedTab] = useState<'write' | 'preview'>('write')\n const [editedValue, setEditedValue] = useState(value)\n const debouncedValue = useDebounce(editedValue, 100)\n const textarea = useRef<HTMLTextAreaElement>(null)\n const sanityClient = useClient()\n\n // Conditionally update textarea styles based on read only access.\n // It's also possible to define inline styles via `childProps.textArea.style` on `<ReactMde />`,\n // but this will override any dynamically created styles provided by the component itself.\n useEffect(() => {\n if (textarea.current) {\n textarea.current.style.backgroundColor = readOnly ? 'rgba(240,240,240)' : 'rgba(255,255,255)'\n }\n }, [textarea, readOnly])\n\n useEffect(() => {\n setEditedValue(value)\n }, [value])\n\n useEffect(() => {\n if (!debouncedValue && value) {\n onChange(PatchEvent.from([unset()]))\n } else if (debouncedValue !== value) {\n onChange(PatchEvent.from([set(debouncedValue)]))\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debouncedValue, onChange])\n\n const saveImage = async function* (data: any) {\n const client = sanityClient.withConfig({apiVersion: '2021-03-25'})\n\n let success = true\n const result = await client.assets\n .upload('image', data)\n .then((doc) => `${doc.url}?w=450`)\n .catch(() => {\n success = false\n return `Error: Could not upload file. Only images are supported.`\n })\n\n yield result\n return success\n }\n\n const generatePreview = useCallback(\n (markdown: string) => Promise.resolve(<Preview markdown={markdown} />),\n []\n )\n\n const inputId = useId()\n const {sanity: studioTheme} = useTheme()\n /*\n Assign our forwarded ref to a wrapper element.\n Ideally, this should be assigned to the textarea inside <ReactMde /> component.\n Whilst `react-mde` does allow you to target individual sub-components' refs,\n it will complain if you try and assign a forwarded ref.\n */\n return (\n <div ref={ref}>\n <MarkdownTheme studioTheme={studioTheme}>\n <ReactMde\n toolbarCommands={options?.toolbar || defaultToolbarCommands}\n value={editedValue}\n onChange={setEditedValue}\n selectedTab={selectedTab}\n onTabChange={setSelectedTab}\n readOnly={readOnly}\n generateMarkdownPreview={generatePreview}\n childProps={{\n textArea: {\n id: inputId,\n onBlur,\n onFocus,\n },\n writeButton: {\n tabIndex: -1,\n },\n }}\n paste={{saveImage}}\n refs={{textarea}}\n />\n </MarkdownTheme>\n </div>\n )\n})\n","import {useState, useEffect} from 'react'\n\nexport default function useDebounce(value: unknown, delay: number) {\n const [debouncedValue, setDebouncedValue] = useState(value)\n useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value)\n }, delay)\n\n return () => clearTimeout(handler)\n }, [value, delay])\n\n return debouncedValue\n}\n"],"names":[],"version":3,"file":"index.modern.js.map","sourceRoot":"../"}
1
+ {"mappings":"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","sources":["src/index.ts","src/components/Editor.tsx","src/hooks/useDebounce.ts"],"sourcesContent":["import {MarkdownEditor as Editor} from './components/Editor'\nimport {createPlugin, defineType} from 'sanity'\n\n// re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:\nconst MarkdownEditor = Editor\n\nexport {MarkdownEditor}\n\nexport const markdownSchema = createPlugin({\n name: 'markdown-editor',\n schema: {\n types: [\n defineType({\n type: 'string' as const,\n name: 'markdown',\n title: 'Markdown',\n components: {\n input: MarkdownEditor,\n },\n }),\n ],\n },\n})\n","import MDEditor from '@uiw/react-md-editor'\nimport useDebounce from '../hooks/useDebounce'\nimport {PatchEvent, set, unset} from 'sanity/form'\nimport {StringInputProps} from 'sanity'\nimport React, {forwardRef, Ref, useEffect, useState} from 'react'\nimport {Card, useTheme} from '@sanity/ui'\nimport rehypeSanitize from 'rehype-sanitize'\n\nexport const MarkdownEditor = forwardRef(function MarkdownEditor(\n props: StringInputProps,\n ref: Ref<any>\n) {\n const {\n value = '',\n onChange,\n elementProps: {onBlur, onFocus},\n readOnly,\n } = props\n const [editedValue, setEditedValue] = useState<string | undefined>(value)\n const debouncedValue = useDebounce(editedValue, 100)\n // const client = useClient({apiVersion: '2021-03-25'})\n\n useEffect(() => {\n setEditedValue(value)\n }, [value])\n\n useEffect(() => {\n if (!debouncedValue && value) {\n onChange(PatchEvent.from([unset()]))\n } else if (debouncedValue !== value) {\n onChange(PatchEvent.from([set(debouncedValue)]))\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debouncedValue, onChange])\n\n /* const saveImage = async function* (data: any) {\n\n let success = true\n const result = await client.assets\n .upload('image', data)\n .then((doc) => `${doc.url}?w=450`)\n .catch(() => {\n success = false\n return `Error: Could not upload file. Only images are supported.`\n })\n\n yield result\n return success\n }*/\n\n const {sanity: studioTheme} = useTheme()\n return (\n <div ref={ref} data-color-mode={studioTheme.color.dark ? 'dark' : 'light'}>\n {readOnly ? (\n <Card border padding={3}>\n <MDEditor.Markdown source={value} rehypePlugins={[[rehypeSanitize]]} />\n </Card>\n ) : (\n <MDEditor\n value={editedValue}\n onChange={setEditedValue}\n onBlur={onBlur}\n onFocus={onFocus}\n previewOptions={{\n rehypePlugins: [[rehypeSanitize]],\n }}\n preview=\"edit\"\n />\n )}\n </div>\n )\n})\n","import {useState, useEffect} from 'react'\n\nexport default function useDebounce(value: unknown, delay: number) {\n const [debouncedValue, setDebouncedValue] = useState(value)\n useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value)\n }, delay)\n\n return () => clearTimeout(handler)\n }, [value, delay])\n\n return debouncedValue\n}\n"],"names":[],"version":3,"file":"index.modern.js.map","sourceRoot":"../"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sanity-plugin-markdown",
3
- "version": "3.0.0-v3-studio.0",
3
+ "version": "3.0.0-v3-studio.2",
4
4
  "description": "Markdown fields in Sanity Studio. Supports Github flavored Markdown and image uploads.",
5
5
  "scripts": {
6
6
  "clean": "rimraf lib",
@@ -39,18 +39,18 @@
39
39
  "license": "MIT",
40
40
  "dependencies": {
41
41
  "@reach/auto-id": "^0.17.0",
42
- "@sanity/incompatible-plugin": "^0.0.1-studio-v3.3",
43
- "@sanity/ui": "^0.37.9",
44
- "react-markdown": "^5.0.3",
45
- "react-mde": "^11.5.0",
46
- "remark-gfm": "^1.0.0"
42
+ "@sanity/incompatible-plugin": "^1.0.1",
43
+ "@sanity/ui": "^0.38.0",
44
+ "@uiw/react-md-editor": "^3.18.1",
45
+ "rehype-sanitize": "^5.0.1"
47
46
  },
48
47
  "devDependencies": {
49
- "@commitlint/cli": "^16.1.0",
50
- "@commitlint/config-conventional": "^15.0.0",
51
- "@parcel/packager-ts": "^2.6.0",
52
- "@parcel/transformer-typescript-types": "^2.6.0",
53
- "@sanity/plugin-kit": "^0.0.1-studio-v3.4",
48
+ "@commitlint/cli": "^17.1.2",
49
+ "@commitlint/config-conventional": "^17.1.0",
50
+ "@parcel/packager-ts": "^2.7.0",
51
+ "@parcel/transformer-typescript-types": "^2.7.0",
52
+ "@sanity/plugin-kit": "^1.1.0-ecosystem-preset.5",
53
+ "@sanity/semantic-release-preset": "^2.0.1",
54
54
  "@types/styled-components": "^5.1.25",
55
55
  "@typescript-eslint/eslint-plugin": "^5.12.0",
56
56
  "@typescript-eslint/parser": "^5.12.0",
@@ -60,15 +60,15 @@
60
60
  "eslint-plugin-prettier": "4.0.0",
61
61
  "eslint-plugin-react": "^7.28.0",
62
62
  "eslint-plugin-react-hooks": "^4.5.0",
63
- "husky": "^7.0.0",
64
- "lint-staged": "^12.3.3",
65
- "parcel": "^2.6.0",
63
+ "husky": "^8.0.1",
64
+ "lint-staged": "^13.0.3",
65
+ "parcel": "^2.7.0",
66
66
  "prettier": "^2.5.1",
67
67
  "react": "^17.0.0 || ^18.0.0",
68
68
  "rimraf": "^3.0.2",
69
- "sanity": "^3.0.0-dev-preview.7",
69
+ "sanity": "3.0.0-dev-preview.17",
70
70
  "styled-components": "^5.2.0",
71
- "typescript": "^4.7.3"
71
+ "typescript": "4.7.4"
72
72
  },
73
73
  "peerDependencies": {
74
74
  "react": "^17.0.0 || ^18.0.0",
@@ -1,96 +1,24 @@
1
- import ReactMde from 'react-mde'
2
- import ReactMarkdown from 'react-markdown'
3
- import gfm from 'remark-gfm'
4
- import {useId} from '@reach/auto-id'
5
-
1
+ import MDEditor from '@uiw/react-md-editor'
6
2
  import useDebounce from '../hooks/useDebounce'
7
- import 'react-mde/lib/styles/css/react-mde-all.css'
8
3
  import {PatchEvent, set, unset} from 'sanity/form'
9
- import {StringInputProps, useClient} from 'sanity'
10
- import React, {
11
- FC,
12
- forwardRef,
13
- PropsWithChildren,
14
- Ref,
15
- useCallback,
16
- useEffect,
17
- useRef,
18
- useState,
19
- } from 'react'
20
- import {ToolbarCommands} from 'react-mde/lib/definitions/types'
21
- import styled from 'styled-components'
22
- import {Theme, useTheme} from '@sanity/ui'
23
-
24
- const Preview = ({markdown}: {markdown: string}) => {
25
- return <ReactMarkdown plugins={[gfm]}>{markdown}</ReactMarkdown>
26
- }
27
-
28
- const defaultToolbarCommands = [
29
- ['header', 'bold', 'italic', 'strikethrough'],
30
- ['link', 'quote', 'code'],
31
- ['unordered-list', 'ordered-list', 'checked-list'],
32
- ]
33
-
34
- type SanityTheme = Theme['sanity']
35
-
36
- type Style = PropsWithChildren<{
37
- studioTheme: SanityTheme
38
- }>
39
-
40
- // !important is used whenever we need to override inline styles for an element
41
- const MarkdownTheme: FC<Style> = styled.div`
42
- & .react-mde {
43
- border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};
44
- }
45
-
46
- & .mde-text {
47
- background: ${({studioTheme}: Style) => studioTheme.color.input.default.enabled.bg} !important;
48
- color: ${({studioTheme}: Style) => studioTheme.color.input.default.enabled.fg} !important;
49
- }
50
-
51
- & .mde-header {
52
- background: ${({studioTheme}: Style) => studioTheme.color.card.enabled.bg};
53
- color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.fg};
54
- border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};
55
-
56
- & button,
57
- .mde-header-item.mde-header-item.mde-header-item button {
58
- color: ${({studioTheme}: Style) => studioTheme.color.button.bleed.default.enabled.fg};
59
- }
60
-
61
- & button.selected {
62
- border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};
63
- }
64
- }
65
-
66
- & .image-tip {
67
- background: ${({studioTheme}: Style) => studioTheme.color.card.enabled.bg};
68
- color: ${({studioTheme}: Style) => studioTheme.color.muted.default.enabled.fg};
69
- font-family: ${({studioTheme}: Style) => studioTheme.fonts.text.family};
70
- border-color: ${({studioTheme}: Style) => studioTheme.color.card.enabled.border};
71
- }
72
- `
4
+ import {StringInputProps} from 'sanity'
5
+ import React, {forwardRef, Ref, useEffect, useState} from 'react'
6
+ import {Card, useTheme} from '@sanity/ui'
7
+ import rehypeSanitize from 'rehype-sanitize'
73
8
 
74
9
  export const MarkdownEditor = forwardRef(function MarkdownEditor(
75
10
  props: StringInputProps,
76
11
  ref: Ref<any>
77
12
  ) {
78
- const {schemaType: type, value = '', onBlur, onChange, onFocus, readOnly} = props
79
- const options: {toolbar?: ToolbarCommands} | undefined = type.options as any
80
- const [selectedTab, setSelectedTab] = useState<'write' | 'preview'>('write')
81
- const [editedValue, setEditedValue] = useState(value)
13
+ const {
14
+ value = '',
15
+ onChange,
16
+ elementProps: {onBlur, onFocus},
17
+ readOnly,
18
+ } = props
19
+ const [editedValue, setEditedValue] = useState<string | undefined>(value)
82
20
  const debouncedValue = useDebounce(editedValue, 100)
83
- const textarea = useRef<HTMLTextAreaElement>(null)
84
- const sanityClient = useClient()
85
-
86
- // Conditionally update textarea styles based on read only access.
87
- // It's also possible to define inline styles via `childProps.textArea.style` on `<ReactMde />`,
88
- // but this will override any dynamically created styles provided by the component itself.
89
- useEffect(() => {
90
- if (textarea.current) {
91
- textarea.current.style.backgroundColor = readOnly ? 'rgba(240,240,240)' : 'rgba(255,255,255)'
92
- }
93
- }, [textarea, readOnly])
21
+ // const client = useClient({apiVersion: '2021-03-25'})
94
22
 
95
23
  useEffect(() => {
96
24
  setEditedValue(value)
@@ -105,8 +33,7 @@ export const MarkdownEditor = forwardRef(function MarkdownEditor(
105
33
  // eslint-disable-next-line react-hooks/exhaustive-deps
106
34
  }, [debouncedValue, onChange])
107
35
 
108
- const saveImage = async function* (data: any) {
109
- const client = sanityClient.withConfig({apiVersion: '2021-03-25'})
36
+ /* const saveImage = async function* (data: any) {
110
37
 
111
38
  let success = true
112
39
  const result = await client.assets
@@ -119,46 +46,27 @@ export const MarkdownEditor = forwardRef(function MarkdownEditor(
119
46
 
120
47
  yield result
121
48
  return success
122
- }
123
-
124
- const generatePreview = useCallback(
125
- (markdown: string) => Promise.resolve(<Preview markdown={markdown} />),
126
- []
127
- )
49
+ }*/
128
50
 
129
- const inputId = useId()
130
51
  const {sanity: studioTheme} = useTheme()
131
- /*
132
- Assign our forwarded ref to a wrapper element.
133
- Ideally, this should be assigned to the textarea inside <ReactMde /> component.
134
- Whilst `react-mde` does allow you to target individual sub-components' refs,
135
- it will complain if you try and assign a forwarded ref.
136
- */
137
52
  return (
138
- <div ref={ref}>
139
- <MarkdownTheme studioTheme={studioTheme}>
140
- <ReactMde
141
- toolbarCommands={options?.toolbar || defaultToolbarCommands}
53
+ <div ref={ref} data-color-mode={studioTheme.color.dark ? 'dark' : 'light'}>
54
+ {readOnly ? (
55
+ <Card border padding={3}>
56
+ <MDEditor.Markdown source={value} rehypePlugins={[[rehypeSanitize]]} />
57
+ </Card>
58
+ ) : (
59
+ <MDEditor
142
60
  value={editedValue}
143
61
  onChange={setEditedValue}
144
- selectedTab={selectedTab}
145
- onTabChange={setSelectedTab}
146
- readOnly={readOnly}
147
- generateMarkdownPreview={generatePreview}
148
- childProps={{
149
- textArea: {
150
- id: inputId,
151
- onBlur,
152
- onFocus,
153
- },
154
- writeButton: {
155
- tabIndex: -1,
156
- },
62
+ onBlur={onBlur}
63
+ onFocus={onFocus}
64
+ previewOptions={{
65
+ rehypePlugins: [[rehypeSanitize]],
157
66
  }}
158
- paste={{saveImage}}
159
- refs={{textarea}}
67
+ preview="edit"
160
68
  />
161
- </MarkdownTheme>
69
+ )}
162
70
  </div>
163
71
  )
164
72
  })
package/src/index.ts CHANGED
@@ -1,6 +1,9 @@
1
- import {MarkdownEditor} from './components/Editor'
1
+ import {MarkdownEditor as Editor} from './components/Editor'
2
2
  import {createPlugin, defineType} from 'sanity'
3
3
 
4
+ // re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:
5
+ const MarkdownEditor = Editor
6
+
4
7
  export {MarkdownEditor}
5
8
 
6
9
  export const markdownSchema = createPlugin({
@@ -8,7 +11,7 @@ export const markdownSchema = createPlugin({
8
11
  schema: {
9
12
  types: [
10
13
  defineType({
11
- type: 'string',
14
+ type: 'string' as const,
12
15
  name: 'markdown',
13
16
  title: 'Markdown',
14
17
  components: {