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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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
 
@@ -27,7 +33,21 @@ yarn add sanity-plugin-markdown@studio-v3
27
33
  ```
28
34
 
29
35
  ## Usage
30
- Declare a field in your schema to be `markdown`
36
+
37
+ Add it as a plugin in sanity.config.ts (or .js):
38
+
39
+ ```js
40
+ import { markdownSchema } from "sanity-plugin-markdown";
41
+
42
+ export default createConfig({
43
+ // ...
44
+ plugins: [
45
+ markdownSchema(),
46
+ ]
47
+ })
48
+ ```
49
+
50
+ Then, declare a field in your schema to be `markdown`
31
51
 
32
52
  ```javascript
33
53
  const myDocument = {
@@ -54,22 +74,15 @@ See LICENSE
54
74
 
55
75
  ## Develop & test
56
76
 
57
- Make sure to run `npm run build` once, then run
58
-
59
- ```bash
60
- npm run link-watch
61
- ```
62
-
63
- 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.
64
79
 
65
- ```bash
66
- npx yalc add sanity-plugin-markdown --link && yarn install
67
- ```
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.
68
82
 
69
- Now, changes in this repo will be automatically built and pushed to the studio,
70
- triggering hotreload. Yalc avoids issues with react-hooks that are typical when using yarn/npm link.
83
+ ### Release new version
71
84
 
72
- ### 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".
73
87
 
74
- This plugin uses [@sanity/plugin-sdk](https://github.com/sanity-io/plugin-sdk)
75
- 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,3 +1,4 @@
1
+ export const MarkdownEditor: import("react").ForwardRefExoticComponent<import("sanity").StringInputProps<import("sanity").StringSchemaType> & import("react").RefAttributes<any>>;
1
2
  export const markdownSchema: import("sanity").Plugin<void>;
2
3
 
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"mappings":"AEGA,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 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',\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,13 +13,11 @@ 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
18
 
22
19
 
23
20
 
24
-
25
-
26
-
27
21
  function $84fd43422be26bd7$export$2e2bcd8739ae039(value, delay) {
28
22
  const [debouncedValue, setDebouncedValue] = (0, $3KLdq$react.useState)(value);
29
23
  (0, $3KLdq$react.useEffect)(()=>{
@@ -43,84 +37,11 @@ function $84fd43422be26bd7$export$2e2bcd8739ae039(value, delay) {
43
37
 
44
38
 
45
39
 
46
-
47
-
48
- const $067e75d167fd097d$var$Preview = ({ markdown: markdown })=>{
49
- return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, ($parcel$interopDefault($3KLdq$reactmarkdown))), {
50
- plugins: [
51
- (0, ($parcel$interopDefault($3KLdq$remarkgfm)))
52
- ],
53
- children: markdown
54
- });
55
- };
56
- const $067e75d167fd097d$var$defaultToolbarCommands = [
57
- [
58
- "header",
59
- "bold",
60
- "italic",
61
- "strikethrough"
62
- ],
63
- [
64
- "link",
65
- "quote",
66
- "code"
67
- ],
68
- [
69
- "unordered-list",
70
- "ordered-list",
71
- "checked-list"
72
- ],
73
- ];
74
- // !important is used whenever we need to override inline styles for an element
75
- const $067e75d167fd097d$var$MarkdownTheme = (0, ($parcel$interopDefault($3KLdq$styledcomponents))).div`
76
- & .react-mde {
77
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
78
- }
79
-
80
- & .mde-text {
81
- background: ${({ studioTheme: studioTheme })=>studioTheme.color.input.default.enabled.bg} !important;
82
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.input.default.enabled.fg} !important;
83
- }
84
-
85
- & .mde-header {
86
- background: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.bg};
87
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.fg};
88
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
89
-
90
- & button,
91
- .mde-header-item.mde-header-item.mde-header-item button {
92
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.button.bleed.default.enabled.fg};
93
- }
94
-
95
- & button.selected {
96
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
97
- }
98
- }
99
-
100
- & .image-tip {
101
- background: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.bg};
102
- color: ${({ studioTheme: studioTheme })=>studioTheme.color.muted.default.enabled.fg};
103
- font-family: ${({ studioTheme: studioTheme })=>studioTheme.fonts.text.family};
104
- border-color: ${({ studioTheme: studioTheme })=>studioTheme.color.card.enabled.border};
105
- }
106
- `;
107
40
  const $067e75d167fd097d$export$18a9461578883ec4 = /*#__PURE__*/ (0, $3KLdq$react.forwardRef)(function MarkdownEditor(props, ref) {
108
- const { schemaType: type , value: value = "" , onBlur: onBlur , onChange: onChange , onFocus: onFocus , readOnly: readOnly } = props;
109
- const options = type.options;
110
- const [selectedTab, setSelectedTab] = (0, $3KLdq$react.useState)("write");
41
+ const { value: value = "" , onBlur: onBlur , onChange: onChange , onFocus: onFocus , readOnly: readOnly } = props;
111
42
  const [editedValue, setEditedValue] = (0, $3KLdq$react.useState)(value);
112
43
  const debouncedValue = (0, $84fd43422be26bd7$export$2e2bcd8739ae039)(editedValue, 100);
113
- const textarea = (0, $3KLdq$react.useRef)(null);
114
- const sanityClient = (0, $3KLdq$sanity.useClient)();
115
- // Conditionally update textarea styles based on read only access.
116
- // It's also possible to define inline styles via `childProps.textArea.style` on `<ReactMde />`,
117
- // but this will override any dynamically created styles provided by the component itself.
118
- (0, $3KLdq$react.useEffect)(()=>{
119
- if (textarea.current) textarea.current.style.backgroundColor = readOnly ? "rgba(240,240,240)" : "rgba(255,255,255)";
120
- }, [
121
- textarea,
122
- readOnly
123
- ]);
44
+ // const sanityClient = useClient()
124
45
  (0, $3KLdq$react.useEffect)(()=>{
125
46
  setEditedValue(value);
126
47
  }, [
@@ -138,63 +59,56 @@ const $067e75d167fd097d$export$18a9461578883ec4 = /*#__PURE__*/ (0, $3KLdq$react
138
59
  debouncedValue,
139
60
  onChange
140
61
  ]);
141
- const saveImage = async function*(data) {
142
- const client = sanityClient.withConfig({
143
- apiVersion: "2021-03-25"
144
- });
145
- let success = true;
146
- const result = await client.assets.upload("image", data).then((doc)=>`${doc.url}?w=450`).catch(()=>{
147
- success = false;
148
- return `Error: Could not upload file. Only images are supported.`;
149
- });
150
- yield result;
151
- return success;
152
- };
153
- const generatePreview = (0, $3KLdq$react.useCallback)((markdown)=>Promise.resolve(/*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)($067e75d167fd097d$var$Preview, {
154
- markdown: markdown
155
- })), []);
156
- const inputId = (0, $3KLdq$reachautoid.useId)();
157
- const { sanity: studioTheme } = (0, $3KLdq$sanityui.useTheme)();
158
- /*
159
- Assign our forwarded ref to a wrapper element.
160
- Ideally, this should be assigned to the textarea inside <ReactMde /> component.
161
- Whilst `react-mde` does allow you to target individual sub-components' refs,
162
- it will complain if you try and assign a forwarded ref.
163
- */ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("div", {
62
+ /* const saveImage = async function* (data: any) {
63
+ const client = sanityClient.withConfig({apiVersion: '2021-03-25'})
64
+
65
+ let success = true
66
+ const result = await client.assets
67
+ .upload('image', data)
68
+ .then((doc) => `${doc.url}?w=450`)
69
+ .catch(() => {
70
+ success = false
71
+ return `Error: Could not upload file. Only images are supported.`
72
+ })
73
+
74
+ yield result
75
+ return success
76
+ }*/ const { sanity: studioTheme } = (0, $3KLdq$sanityui.useTheme)();
77
+ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("div", {
164
78
  ref: ref,
165
- children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)($067e75d167fd097d$var$MarkdownTheme, {
166
- studioTheme: studioTheme,
167
- children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, ($parcel$interopDefault($3KLdq$reactmde))), {
168
- toolbarCommands: options?.toolbar || $067e75d167fd097d$var$defaultToolbarCommands,
169
- value: editedValue,
170
- onChange: setEditedValue,
171
- selectedTab: selectedTab,
172
- onTabChange: setSelectedTab,
173
- readOnly: readOnly,
174
- generateMarkdownPreview: generatePreview,
175
- childProps: {
176
- textArea: {
177
- id: inputId,
178
- onBlur: onBlur,
179
- onFocus: onFocus
180
- },
181
- writeButton: {
182
- tabIndex: -1
183
- }
184
- },
185
- paste: {
186
- saveImage: saveImage
187
- },
188
- refs: {
189
- textarea: textarea
190
- }
79
+ "data-color-mode": studioTheme.color.dark ? "dark" : "light",
80
+ children: readOnly ? /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Card), {
81
+ border: true,
82
+ padding: 3,
83
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, ($parcel$interopDefault($3KLdq$uiwreactmdeditor))).Markdown, {
84
+ source: value,
85
+ rehypePlugins: [
86
+ [
87
+ (0, ($parcel$interopDefault($3KLdq$rehypesanitize)))
88
+ ]
89
+ ]
191
90
  })
91
+ }) : /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, ($parcel$interopDefault($3KLdq$uiwreactmdeditor))), {
92
+ value: editedValue,
93
+ onChange: setEditedValue,
94
+ onBlur: onBlur,
95
+ onFocus: onFocus,
96
+ previewOptions: {
97
+ rehypePlugins: [
98
+ [
99
+ (0, ($parcel$interopDefault($3KLdq$rehypesanitize)))
100
+ ]
101
+ ]
102
+ },
103
+ preview: "edit"
192
104
  })
193
105
  });
194
106
  });
195
107
 
196
108
 
197
109
 
110
+ // re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:
111
+ const $244e63ca53592e4d$export$18a9461578883ec4 = (0, $067e75d167fd097d$export$18a9461578883ec4);
198
112
  const $244e63ca53592e4d$export$f225414958dd8925 = (0, $3KLdq$sanity.createPlugin)({
199
113
  name: "markdown-editor",
200
114
  schema: {
@@ -204,7 +118,7 @@ const $244e63ca53592e4d$export$f225414958dd8925 = (0, $3KLdq$sanity.createPlugin
204
118
  name: "markdown",
205
119
  title: "Markdown",
206
120
  components: {
207
- input: (0, $067e75d167fd097d$export$18a9461578883ec4)
121
+ input: $244e63ca53592e4d$export$18a9461578883ec4
208
122
  }
209
123
  }),
210
124
  ]
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":";;;;;;;;;;;;;;;;;;;;ACAA;;;;;ACAA;AAEe,kDAAqB,KAAc,EAAE,KAAa,EAAE;IACjE,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,CAAA,GAAA,qBAAQ,CAAA,CAAC,KAAK,CAAC;IAC3D,CAAA,GAAA,sBAAS,CAAA,CAAC,IAAM;QACd,MAAM,OAAO,GAAG,UAAU,CAAC,IAAM;YAC/B,iBAAiB,CAAC,KAAK,CAAC;SACzB,EAAE,KAAK,CAAC;QAET,OAAO,IAAM,YAAY,CAAC,OAAO,CAAC,CAAA;KACnC,EAAE;QAAC,KAAK;QAAE,KAAK;KAAC,CAAC;IAElB,OAAO,cAAc,CAAA;CACtB;;;;;;;;;ADUD,MAAM,6BAAO,GAAG,CAAC,YAAC,QAAQ,CAAA,EAAqB,GAAK;IAClD,qBAAO,gCAAC,CAAA,GAAA,8CAAa,CAAA;QAAC,OAAO,EAAE;YAAC,CAAA,GAAA,0CAAG,CAAA;SAAC;kBAAG,QAAQ;MAAiB,CAAA;CACjE;AAED,MAAM,4CAAsB,GAAG;IAC7B;QAAC,QAAQ;QAAE,MAAM;QAAE,QAAQ;QAAE,eAAe;KAAC;IAC7C;QAAC,MAAM;QAAE,OAAO;QAAE,MAAM;KAAC;IACzB;QAAC,gBAAgB;QAAE,cAAc;QAAE,cAAc;KAAC;CACnD;AAQD,+EAA+E;AAC/E,MAAM,mCAAa,GAAc,CAAA,GAAA,iDAAM,CAAA,CAAC,GAAG,CAAC;;kBAE1B,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;;;;gBAIpE,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;WAC5E,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;;;;gBAIlE,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;WACnE,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;kBACvD,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;;;;aAIvE,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;;;;oBAIvE,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;;;;;gBAKtE,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;WACnE,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;iBACjE,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;kBACzD,EAAE,CAAC,eAAC,WAAW,CAAA,EAAQ,GAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;;AAEpF,CAAC;AAEM,MAAM,yCAAc,iBAAG,CAAA,GAAA,uBAAU,CAAA,CAAC,SAAS,cAAc,CAC9D,KAAuB,EACvB,GAAa,EACb;IACA,MAAM,EAAC,UAAU,EAAE,IAAI,CAAA,SAAE,KAAK,GAAG,EAAE,WAAE,MAAM,CAAA,YAAE,QAAQ,CAAA,WAAE,OAAO,CAAA,YAAE,QAAQ,CAAA,EAAC,GAAG,KAAK;IACjF,MAAM,OAAO,GAA4C,IAAI,CAAC,OAAO,AAAO;IAC5E,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,CAAA,GAAA,qBAAQ,CAAA,CAAsB,OAAO,CAAC;IAC5E,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,CAAA,GAAA,qBAAQ,CAAA,CAAC,KAAK,CAAC;IACrD,MAAM,cAAc,GAAG,CAAA,GAAA,wCAAW,CAAA,CAAC,WAAW,EAAE,GAAG,CAAC;IACpD,MAAM,QAAQ,GAAG,CAAA,GAAA,mBAAM,CAAA,CAAsB,IAAI,CAAC;IAClD,MAAM,YAAY,GAAG,CAAA,GAAA,uBAAS,CAAA,EAAE;IAEhC,kEAAkE;IAClE,gGAAgG;IAChG,0FAA0F;IAC1F,CAAA,GAAA,sBAAS,CAAA,CAAC,IAAM;QACd,IAAI,QAAQ,CAAC,OAAO,EAClB,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,GAAG,QAAQ,GAAG,mBAAmB,GAAG,mBAAmB;KAEhG,EAAE;QAAC,QAAQ;QAAE,QAAQ;KAAC,CAAC;IAExB,CAAA,GAAA,sBAAS,CAAA,CAAC,IAAM;QACd,cAAc,CAAC,KAAK,CAAC;KACtB,EAAE;QAAC,KAAK;KAAC,CAAC;IAEX,CAAA,GAAA,sBAAS,CAAA,CAAC,IAAM;QACd,IAAI,CAAC,cAAc,IAAI,KAAK,EAC1B,QAAQ,CAAC,CAAA,GAAA,4BAAU,CAAA,CAAC,IAAI,CAAC;YAAC,CAAA,GAAA,uBAAK,CAAA,EAAE;SAAC,CAAC,CAAC;aAC/B,IAAI,cAAc,KAAK,KAAK,EACjC,QAAQ,CAAC,CAAA,GAAA,4BAAU,CAAA,CAAC,IAAI,CAAC;YAAC,CAAA,GAAA,qBAAG,CAAA,CAAC,cAAc,CAAC;SAAC,CAAC,CAAC;IAElD,uDAAuD;KACxD,EAAE;QAAC,cAAc;QAAE,QAAQ;KAAC,CAAC;IAE9B,MAAM,SAAS,GAAG,gBAAiB,IAAS,EAAE;QAC5C,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,CAAC;YAAC,UAAU,EAAE,YAAY;SAAC,CAAC;QAElE,IAAI,OAAO,GAAG,IAAI;QAClB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAC/B,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CACrB,IAAI,CAAC,CAAC,GAAG,GAAK,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CACjC,KAAK,CAAC,IAAM;YACX,OAAO,GAAG,KAAK;YACf,OAAO,CAAC,wDAAwD,CAAC,CAAA;SAClE,CAAC;QAEJ,MAAM,MAAM;QACZ,OAAO,OAAO,CAAA;KACf;IAED,MAAM,eAAe,GAAG,CAAA,GAAA,wBAAW,CAAA,CACjC,CAAC,QAAgB,GAAK,OAAO,CAAC,OAAO,eAAC,gCAAC,6BAAO;YAAC,QAAQ,EAAE,QAAQ;UAAI,CAAC,EACtE,EAAE,CACH;IAED,MAAM,OAAO,GAAG,CAAA,GAAA,wBAAK,CAAA,EAAE;IACvB,MAAM,EAAC,MAAM,EAAE,WAAW,CAAA,EAAC,GAAG,CAAA,GAAA,wBAAQ,CAAA,EAAE;IACxC;;;;;IAKE,CACF,qBACE,gCAAC,KAAG;QAAC,GAAG,EAAE,GAAG;kBACX,cAAA,gCAAC,mCAAa;YAAC,WAAW,EAAE,WAAW;sBACrC,cAAA,gCAAC,CAAA,GAAA,yCAAQ,CAAA;gBACP,eAAe,EAAE,OAAO,EAAE,OAAO,IAAI,4CAAsB;gBAC3D,KAAK,EAAE,WAAW;gBAClB,QAAQ,EAAE,cAAc;gBACxB,WAAW,EAAE,WAAW;gBACxB,WAAW,EAAE,cAAc;gBAC3B,QAAQ,EAAE,QAAQ;gBAClB,uBAAuB,EAAE,eAAe;gBACxC,UAAU,EAAE;oBACV,QAAQ,EAAE;wBACR,EAAE,EAAE,OAAO;gCACX,MAAM;iCACN,OAAO;qBACR;oBACD,WAAW,EAAE;wBACX,QAAQ,EAAE,EAAE;qBACb;iBACF;gBACD,KAAK,EAAE;+BAAC,SAAS;iBAAC;gBAClB,IAAI,EAAE;8BAAC,QAAQ;iBAAC;cAChB;UACY;MACZ,CACP;CACF,CAAC;;ADnKF;;AAGO,MAAM,yCAAc,GAAG,CAAA,GAAA,0BAAY,CAAA,CAAC;IACzC,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE;QACN,KAAK,EAAE;YACL,CAAA,GAAA,wBAAU,CAAA,CAAC;gBACT,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,UAAU;gBAChB,KAAK,EAAE,UAAU;gBACjB,UAAU,EAAE;oBACV,KAAK,EAAE,CAAA,GAAA,yCAAc,CAAA;iBACtB;aACF,CAAC;SACH;KACF;CACF,CAAC","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 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',\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 {value = '', onBlur, onChange, onFocus, readOnly} = props\n const [editedValue, setEditedValue] = useState<string | undefined>(value)\n const debouncedValue = useDebounce(editedValue, 100)\n // const sanityClient = useClient()\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 {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 = "" , onBlur: onBlur , onChange: onChange , 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 sanityClient = useClient()
116
36
  (0, $jPEKE$useEffect)(()=>{
117
37
  setEditedValue(value);
118
38
  }, [
@@ -130,63 +50,56 @@ 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
+ const client = sanityClient.withConfig({apiVersion: '2021-03-25'})
55
+
56
+ let success = true
57
+ const result = await client.assets
58
+ .upload('image', data)
59
+ .then((doc) => `${doc.url}?w=450`)
60
+ .catch(() => {
61
+ success = false
62
+ return `Error: Could not upload file. Only images are supported.`
63
+ })
64
+
65
+ yield result
66
+ return success
67
+ }*/ const { sanity: studioTheme } = (0, $jPEKE$useTheme)();
68
+ return /*#__PURE__*/ (0, $jPEKE$jsx)("div", {
156
69
  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
- }
70
+ "data-color-mode": studioTheme.color.dark ? "dark" : "light",
71
+ children: readOnly ? /*#__PURE__*/ (0, $jPEKE$jsx)((0, $jPEKE$Card), {
72
+ border: true,
73
+ padding: 3,
74
+ children: /*#__PURE__*/ (0, $jPEKE$jsx)((0, $jPEKE$uiwreactmdeditor).Markdown, {
75
+ source: value,
76
+ rehypePlugins: [
77
+ [
78
+ (0, $jPEKE$rehypesanitize)
79
+ ]
80
+ ]
183
81
  })
82
+ }) : /*#__PURE__*/ (0, $jPEKE$jsx)((0, $jPEKE$uiwreactmdeditor), {
83
+ value: editedValue,
84
+ onChange: setEditedValue,
85
+ onBlur: onBlur,
86
+ onFocus: onFocus,
87
+ previewOptions: {
88
+ rehypePlugins: [
89
+ [
90
+ (0, $jPEKE$rehypesanitize)
91
+ ]
92
+ ]
93
+ },
94
+ preview: "edit"
184
95
  })
185
96
  });
186
97
  });
187
98
 
188
99
 
189
100
 
101
+ // re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:
102
+ const $df9eabe9bda49ea8$export$18a9461578883ec4 = (0, $483dd42bf797352b$export$18a9461578883ec4);
190
103
  const $df9eabe9bda49ea8$export$f225414958dd8925 = (0, $jPEKE$createPlugin)({
191
104
  name: "markdown-editor",
192
105
  schema: {
@@ -196,7 +109,7 @@ const $df9eabe9bda49ea8$export$f225414958dd8925 = (0, $jPEKE$createPlugin)({
196
109
  name: "markdown",
197
110
  title: "Markdown",
198
111
  components: {
199
- input: (0, $483dd42bf797352b$export$18a9461578883ec4)
112
+ input: $df9eabe9bda49ea8$export$18a9461578883ec4
200
113
  }
201
114
  }),
202
115
  ]
@@ -204,5 +117,5 @@ const $df9eabe9bda49ea8$export$f225414958dd8925 = (0, $jPEKE$createPlugin)({
204
117
  });
205
118
 
206
119
 
207
- export {$df9eabe9bda49ea8$export$f225414958dd8925 as markdownSchema};
120
+ export {$df9eabe9bda49ea8$export$18a9461578883ec4 as MarkdownEditor, $df9eabe9bda49ea8$export$f225414958dd8925 as markdownSchema};
208
121
  //# 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 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',\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 {value = '', onBlur, onChange, onFocus, readOnly} = props\n const [editedValue, setEditedValue] = useState<string | undefined>(value)\n const debouncedValue = useDebounce(editedValue, 100)\n // const sanityClient = useClient()\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 {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-studio-v3.0",
3
+ "version": "3.0.0-v3-studio.1",
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",
42
+ "@sanity/incompatible-plugin": "^1.0.0",
43
43
  "@sanity/ui": "^0.37.9",
44
- "react-markdown": "^5.0.3",
45
- "react-mde": "^11.5.0",
46
- "remark-gfm": "^1.0.0"
44
+ "@uiw/react-md-editor": "^3.18.1",
45
+ "rehype-sanitize": "^5.0.1"
47
46
  },
48
47
  "devDependencies": {
49
48
  "@commitlint/cli": "^16.1.0",
50
49
  "@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",
50
+ "@parcel/packager-ts": "^2.7.0",
51
+ "@parcel/transformer-typescript-types": "^2.7.0",
52
+ "@sanity/plugin-kit": "^1.0.1",
53
+ "@sanity/semantic-release-preset": "^2.0.0",
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",
@@ -62,17 +62,17 @@
62
62
  "eslint-plugin-react-hooks": "^4.5.0",
63
63
  "husky": "^7.0.0",
64
64
  "lint-staged": "^12.3.3",
65
- "parcel": "^2.6.0",
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": "^2.30.1-purple-unicorn.964",
69
+ "sanity": "3.0.0-dev-preview.15",
70
70
  "styled-components": "^5.2.0",
71
- "typescript": "^4.7.3"
71
+ "typescript": "^4.8.2"
72
72
  },
73
73
  "peerDependencies": {
74
74
  "react": "^17.0.0 || ^18.0.0",
75
- "sanity": "purple-unicorn",
75
+ "sanity": "dev-preview",
76
76
  "styled-components": "^5.2.0"
77
77
  },
78
78
  "repository": {
@@ -1,96 +1,19 @@
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 {value = '', onBlur, onChange, onFocus, readOnly} = props
14
+ const [editedValue, setEditedValue] = useState<string | undefined>(value)
82
15
  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])
16
+ // const sanityClient = useClient()
94
17
 
95
18
  useEffect(() => {
96
19
  setEditedValue(value)
@@ -105,7 +28,7 @@ export const MarkdownEditor = forwardRef(function MarkdownEditor(
105
28
  // eslint-disable-next-line react-hooks/exhaustive-deps
106
29
  }, [debouncedValue, onChange])
107
30
 
108
- const saveImage = async function* (data: any) {
31
+ /* const saveImage = async function* (data: any) {
109
32
  const client = sanityClient.withConfig({apiVersion: '2021-03-25'})
110
33
 
111
34
  let success = true
@@ -119,46 +42,27 @@ export const MarkdownEditor = forwardRef(function MarkdownEditor(
119
42
 
120
43
  yield result
121
44
  return success
122
- }
123
-
124
- const generatePreview = useCallback(
125
- (markdown: string) => Promise.resolve(<Preview markdown={markdown} />),
126
- []
127
- )
45
+ }*/
128
46
 
129
- const inputId = useId()
130
47
  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
48
  return (
138
- <div ref={ref}>
139
- <MarkdownTheme studioTheme={studioTheme}>
140
- <ReactMde
141
- toolbarCommands={options?.toolbar || defaultToolbarCommands}
49
+ <div ref={ref} data-color-mode={studioTheme.color.dark ? 'dark' : 'light'}>
50
+ {readOnly ? (
51
+ <Card border padding={3}>
52
+ <MDEditor.Markdown source={value} rehypePlugins={[[rehypeSanitize]]} />
53
+ </Card>
54
+ ) : (
55
+ <MDEditor
142
56
  value={editedValue}
143
57
  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
- },
58
+ onBlur={onBlur}
59
+ onFocus={onFocus}
60
+ previewOptions={{
61
+ rehypePlugins: [[rehypeSanitize]],
157
62
  }}
158
- paste={{saveImage}}
159
- refs={{textarea}}
63
+ preview="edit"
160
64
  />
161
- </MarkdownTheme>
65
+ )}
162
66
  </div>
163
67
  )
164
68
  })
package/src/index.ts CHANGED
@@ -1,6 +1,11 @@
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
+
7
+ export {MarkdownEditor}
8
+
4
9
  export const markdownSchema = createPlugin({
5
10
  name: 'markdown-editor',
6
11
  schema: {