Skip to content

Commit 3eb0538

Browse files
authored
Merge branch 'master' into suggestions-autoplace
2 parents c91c049 + 6dbd9b9 commit 3eb0538

9 files changed

Lines changed: 45 additions & 37 deletions

File tree

docs/bundle-prod.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-mde",
3-
"version": "11.0.1",
3+
"version": "11.0.5",
44
"description": "React Markdown Editor",
55
"main": "./lib/js/index.js",
66
"types": "./lib/definitions/index.d.ts",

readme.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ A simple yet powerful and extensible **React Markdown Editor** that aims to have
1919
## Installing
2020

2121
npm i react-mde
22-
22+
2323
## Using
2424

2525
React-mde is a completely controlled component.
@@ -87,21 +87,22 @@ The types are described below
8787
- **onChange: (value: string)**: Event handler for the `onChange` event.
8888
- **selectedTab: "write" | "preview"**: The currently selected tab.
8989
- **onTabChange: (tab) => void**: Function called when the selected tab changes.
90-
- **classes?: [Object](https://github.com/andrerpena/react-mde/blob/master/src/classes.ts)**: An object containing the following optional properties: *reactMde*, *toolbar*, *preview*, *textArea* and *suggestionsDropdown*.
90+
- **classes?: [Object](https://github.com/andrerpena/react-mde/blob/master/src/classes.ts)**: An object containing the following optional properties: *reactMde*, *toolbar*, *preview*, *textArea* and *suggestionsDropdown*.
9191
This allows for passing class names to each of the inner components of React-mde. Classes defined in the *classes* prop
9292
follow the specification of [Jed Watson's classNames project](https://github.com/JedWatson/classnames).
9393
- **commands?: Record<string, Command>**: An object with string properties representing keys, and a Command object as value for each key. These are custom commands. Commands are explained in more details below.
94-
- **toolbarCommands?: string[][]**: Array of array of strings, indicating which commands should be displayed. Each outer array is a group. Example: `[["code", "bold"], ["italic"]]`
94+
- **toolbarCommands?: string[][]**: Array of array of strings, indicating which commands should be displayed. Each outer array is a group. Example: `[["code", "bold"], ["italic"]]`. The default list can be obtained with `import { getDefaultToolbarCommands } from 'react-mde', getDefaultToolbarCommands()`
9595
- **generateMarkdownPreview: (markdown: string) => Promise<string | ReactElement>;**: Function that should return a Promise to the generated HTML or a React element for the preview. If this `prop` is falsy, then no preview is going to be generated.
9696
- **getIcon?: (commandName: string) => React.ReactNode }** An optional set of button content options, including an `iconProvider` to allow custom icon rendering.
9797
options. It is recommended to [inspect the layouts source code](https://github.com/andrerpena/react-mde/tree/master/src/components-layout) to see what options can be passed to each
9898
while the documentation is not complete.
9999
- **loadingPreview**: What to display in the preview while it is loading. Value can be string, React Element or anything React can render.
100100
- **readOnly?: boolean**: Flag to render the editor in read-only mode.
101-
- **l18n?**: A localization option. It contains the strings `write`, `preview` and `uploadingImage`.
101+
- [**l18n?**](src/types/L18n.ts): A localization option. It contains the strings `write`, `preview`, `uploadingImage` and `pasteDropSelect`.
102102
- **minEditorHeight?: number**: The minimum height of the editor.
103103
- **maxEditorHeight?: number**: The max height of the editor (after that, it will scroll).
104104
- **minPreviewHeight?: number**: The minimum height of the preview.
105+
- **heightUnits?: string**: The height units, defaults to `px`.
105106
- **loadSuggestions?: (text: string, triggeredBy: string) => Promise<Suggestion[]>**: Function to load mention suggestions based on the
106107
given `text` and `triggeredBy` (character that triggered the suggestions). The result should be an array of `{preview: React.ReactNode, value: string}`.
107108
The `preview` is what is going to be displayed in the suggestions box. The `value` is what is going to be inserted in the `textarea` on click or enter.
@@ -117,22 +118,22 @@ The following styles from React-mde should be added: (Both .scss and .css files
117118
Easiest way: import `react-mde-all.css`:
118119

119120
import 'react-mde/lib/styles/css/react-mde-all.css';
120-
121+
121122
If you want to have a more granular control over the styles, you can [import each individual file](https://github.com/andrerpena/react-mde/tree/master/src/styles).
122-
123+
123124
If you're using SASS, you can override these variables: https://github.com/andrerpena/react-mde/blob/master/src/styles/variables.scss
124125

125126
## XSS concerns
126127

127128
React-mde does not automatically sanitize the HTML preview. If your using Showdown,
128129
this has been taken from [their documentation](https://github.com/showdownjs/showdown/wiki/Markdown's-XSS-Vulnerability-(and-how-to-mitigate-it)):
129-
130+
130131
> Cross-side scripting is a well known technique to gain access to private information of the users
131-
of a website. The attacker injects spurious HTML content (a script) on the web page which will read
132+
of a website. The attacker injects spurious HTML content (a script) on the web page which will read
132133
the user’s cookies and do something bad with it (like steal credentials). As a countermeasure,
133-
you should filter any suspicious content coming from user input. Showdown doesn’t include an
134+
you should filter any suspicious content coming from user input. Showdown doesn’t include an
134135
XSS filter, so you must provide your own. But be careful in how you do it…
135-
136+
136137
You might want to take a look at [showdown-xss-filter](https://github.com/VisionistInc/showdown-xss-filter).
137138

138139
It is also possible to return a Promise to a React Element from `generateMarkdownPreview`, which makes

src/commands/default-commands/save-image-command.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,13 @@ export const saveImageCommand: Command = {
4848
);
4949

5050
for (const index in items) {
51+
const initialState = textApi.getState();
5152
const breaksBeforeCount = getBreaksNeededForEmptyLineBefore(
5253
initialState.text,
5354
initialState.selection.start
5455
);
55-
const breaksBefore = Array(breaksBeforeCount + 1).join("\n");
5656

57+
const breaksBefore = Array(breaksBeforeCount + 1).join("\n");
5758
const placeHolder = `${breaksBefore}![${l18n.uploadingImage}]()`;
5859

5960
textApi.replaceSelection(placeHolder);
@@ -78,8 +79,9 @@ export const saveImageCommand: Command = {
7879
end: initialState.selection.start + placeHolder.length
7980
});
8081

81-
const realImageMarkdown = `${breaksBefore}![image](${imageUrl})`;
82-
82+
const realImageMarkdown = imageUrl
83+
? `${breaksBefore}![image](${imageUrl})`
84+
: "";
8385
const selectionDelta = realImageMarkdown.length - placeHolder.length;
8486

8587
textApi.replaceSelection(realImageMarkdown);

src/components/Preview.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export interface PreviewProps {
77
refObject?: React.RefObject<HTMLDivElement>;
88
loadingPreview?: React.ReactNode;
99
minHeight: number;
10+
heightUnits: string;
1011
generateMarkdownPreview: GenerateMarkdownPreview;
1112
markdown: string;
1213
}
@@ -48,7 +49,7 @@ export class Preview extends React.Component<
4849
}
4950

5051
render() {
51-
const { classes, minHeight, loadingPreview, refObject } = this.props;
52+
const { classes, minHeight, loadingPreview, refObject, heightUnits } = this.props;
5253
const { preview, loading } = this.state;
5354
const finalHtml = loading ? loadingPreview : preview;
5455

@@ -66,10 +67,12 @@ export class Preview extends React.Component<
6667
content = <div className="mde-preview-content">{finalHtml}</div>;
6768
}
6869

70+
const minHeightVal = (minHeight && heightUnits) ? (minHeight + 10) + heightUnits : minHeight + 10;
71+
6972
return (
7073
<div
7174
className={classNames("mde-preview", classes, { loading })}
72-
style={{ minHeight: minHeight + 10 }}
75+
style={{ minHeight: minHeightVal }}
7376
data-testid="mde-preview"
7477
>
7578
{content}

src/components/ReactMde.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export interface ReactMdeProps {
3333
maxEditorHeight?: number;
3434
initialEditorHeight?: number;
3535
minPreviewHeight?: number;
36+
heightUnits?: string;
3637
classes?: Classes;
3738
refs?: Refs;
3839
toolbarCommands?: ToolbarCommands;
@@ -88,6 +89,7 @@ export class ReactMde extends React.Component<ReactMdeProps, ReactMdeState> {
8889
minEditorHeight: 200,
8990
maxEditorHeight: 500,
9091
minPreviewHeight: 200,
92+
heightUnits: "px",
9193
selectedTab: "write",
9294
disablePreview: false,
9395
suggestionTriggerCharacters: ["@"],
@@ -169,6 +171,7 @@ export class ReactMde extends React.Component<ReactMdeProps, ReactMdeState> {
169171
value,
170172
l18n,
171173
minPreviewHeight,
174+
heightUnits,
172175
childProps,
173176
selectedTab,
174177
generateMarkdownPreview,
@@ -227,6 +230,7 @@ export class ReactMde extends React.Component<ReactMdeProps, ReactMdeState> {
227230
textAreaComponent={textAreaComponent}
228231
textAreaProps={childProps && childProps.textArea}
229232
height={this.state.editorHeight}
233+
heightUnits={this.props.heightUnits}
230234
value={value}
231235
suggestionTriggerCharacters={suggestionTriggerCharacters}
232236
loadSuggestions={loadSuggestions}
@@ -253,6 +257,7 @@ export class ReactMde extends React.Component<ReactMdeProps, ReactMdeState> {
253257
refObject={this.finalRefs.preview}
254258
loadingPreview={loadingPreview}
255259
minHeight={minPreviewHeight}
260+
heightUnits={heightUnits}
256261
generateMarkdownPreview={generateMarkdownPreview}
257262
markdown={value}
258263
/>

src/components/SuggestionsDropdown.tsx

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,12 @@ export const SuggestionsDropdown: React.FunctionComponent<SuggestionsDropdownPro
2626
focusIndex,
2727
textAreaRef
2828
}) => {
29-
const handleSuggestionClick = useCallback(
30-
(event: React.MouseEvent) => {
31-
event.preventDefault();
32-
const index = parseInt(
33-
event.currentTarget.attributes["data-index"].value
34-
);
35-
onSuggestionSelected(index);
36-
},
37-
[suggestions]
38-
);
29+
const handleSuggestionClick = (event: React.MouseEvent) => {
30+
event.preventDefault();
31+
const index = parseInt(event.currentTarget.attributes["data-index"].value);
32+
onSuggestionSelected(index);
33+
};
3934

40-
// onMouseDown should be cancelled because onClick will handle it propertly. This way, the textarea does not lose
41-
// focus
4235
const handleMouseDown =
4336
(event: React.MouseEvent) => event.preventDefault();
4437

src/components/TextArea.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export interface TextAreaProps {
4242
refObject?: React.RefObject<HTMLTextAreaElement>;
4343
readOnly?: boolean;
4444
height?: number;
45+
heightUnits?: string;
4546
suggestionTriggerCharacters?: string[];
4647
suggestionsAutoplace?: boolean;
4748
loadSuggestions?: (
@@ -364,6 +365,7 @@ export class TextArea extends React.Component<TextAreaProps, TextAreaState> {
364365
readOnly,
365366
textAreaProps,
366367
height,
368+
heightUnits,
367369
value,
368370
suggestionTriggerCharacters,
369371
loadSuggestions,
@@ -384,13 +386,15 @@ export class TextArea extends React.Component<TextAreaProps, TextAreaState> {
384386
"textarea") as DetailedHTMLFactory<
385387
TextareaHTMLAttributes<HTMLTextAreaElement>,
386388
HTMLTextAreaElement
387-
>;
389+
>;
390+
391+
const heightVal = (height && heightUnits) ? height + heightUnits : height;
388392

389393
return (
390394
<div className="mde-textarea-wrapper">
391395
<TextAreaComponent
392396
className={classNames("mde-text", classes)}
393-
style={{ height }}
397+
style={{ height: heightVal }}
394398
ref={this.props.refObject}
395399
readOnly={readOnly}
396400
value={value}
@@ -401,8 +405,8 @@ export class TextArea extends React.Component<TextAreaProps, TextAreaState> {
401405
this.handleOnChange(event);
402406
}}
403407
onBlur={event => {
408+
textAreaProps?.onBlur?.(event);
404409
if (suggestionsEnabled) {
405-
textAreaProps?.onBlur?.(event);
406410
this.handleBlur();
407411
}
408412
}}
@@ -411,14 +415,14 @@ export class TextArea extends React.Component<TextAreaProps, TextAreaState> {
411415
this.handleKeyDown(event);
412416
}}
413417
onKeyUp={event => {
418+
textAreaProps?.onKeyUp?.(event);
414419
if (suggestionsEnabled) {
415-
textAreaProps?.onKeyUp?.(event);
416420
this.handleKeyUp(event);
417421
}
418422
}}
419423
onKeyPress={event => {
424+
textAreaProps?.onKeyPress?.(event);
420425
if (suggestionsEnabled) {
421-
textAreaProps?.onKeyPress?.(event);
422426
this.handleKeyPress(event);
423427
}
424428
}}

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4418,9 +4418,9 @@ inherits@2.0.3:
44184418
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
44194419

44204420
ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
4421-
version "1.3.5"
4422-
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
4423-
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
4421+
version "1.3.8"
4422+
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
4423+
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
44244424

44254425
interpret@^1.1.0:
44264426
version "1.2.0"

0 commit comments

Comments
 (0)