Skip to content

Commit

Permalink
Command refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
andrerpena committed May 4, 2022
1 parent 2447e37 commit 68ec338
Show file tree
Hide file tree
Showing 18 changed files with 355 additions and 335 deletions.
10 changes: 5 additions & 5 deletions demo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import * as React from "react";
import ReactDOM from "react-dom";
import { Box, ChakraProvider, HStack, Textarea } from "@chakra-ui/react";
import { useTextAreaMarkdownEditor } from "../src/hooks/use-markdown-editor";
import { useTextAreaMarkdownEditor } from "../src";
import { faBold, faItalic, faCode } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { bold, code, italic } from "../src";
import { boldCommand, codeCommand, italicCommand } from "../src";
import { ToolbarButton } from "./toolbar-button";

export type DemoProps = {};

export const Demo: React.FunctionComponent<DemoProps> = () => {
const { ref, commandController } = useTextAreaMarkdownEditor({
commandMap: {
bold: bold,
italic: italic,
code: code
bold: boldCommand,
italic: italicCommand,
code: codeCommand
}
});

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-mde",
"version": "12.0.6",
"version": "12.0.7",
"description": "React Markdown Editor",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
import * as React from "react";
import { Command } from "../command";
import { textHelpers } from "../../helpers/textHelpers";
export const bold: Command = {
import {
getCharactersAfterSelection,
getCharactersBeforeSelection,
getSelectedText,
selectWord
} from "../../helpers/textHelpers";

export const boldCommand: Command = {
shouldUndo: options => {
return (
textHelpers.getCharactersBeforeSelection(options.initialState, 2) ===
"**" &&
textHelpers.getCharactersAfterSelection(options.initialState, 2) === "**"
getCharactersBeforeSelection(options.initialState, 2) === "**" &&
getCharactersAfterSelection(options.initialState, 2) === "**"
);
},
execute: ({ initialState, textApi }) => {
// Adjust the selection to encompass the whole word if the caret is inside one
const newSelectionRange = textHelpers.selectWord({
const newSelectionRange = selectWord({
text: initialState.text,
selection: initialState.selection
});
const state1 = textApi.setSelectionRange(newSelectionRange);
// Replaces the current selection with the bold mark up
const state2 = textApi.replaceSelection(
`**${textHelpers.getSelectedText(state1)}**`
);
const state2 = textApi.replaceSelection(`**${getSelectedText(state1)}**`);
// Adjust the selection to not contain the **
textApi.setSelectionRange({
start:
state2.selection.end - 2 - textHelpers.getSelectedText(state1).length,
start: state2.selection.end - 2 - getSelectedText(state1).length,
end: state2.selection.end - 2
});
},
undo: ({ initialState, textApi }) => {
const text = textHelpers.getSelectedText(initialState);
const text = getSelectedText(initialState);
textApi.setSelectionRange({
start: initialState.selection.start - 2,
end: initialState.selection.end + 2
Expand Down
8 changes: 8 additions & 0 deletions src/commands/markdown-commands/checkedListCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Command } from "../command";
import { makeList } from "../../helpers/listHelpers";

export const checkedListCommand: Command = {
execute: ({ initialState, textApi }) => {
makeList(initialState, textApi, () => `- [ ] `);
}
};
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import * as React from "react";
import { Command } from "../command";
import { textHelpers } from "../../helpers/textHelpers";

export const codeBlock: Command = {
import {
getBreaksNeededForEmptyLineAfter,
getBreaksNeededForEmptyLineBefore,
getSelectedText,
selectWord
} from "../../helpers/textHelpers";

export const codeBlockCommand: Command = {
execute: async ({ textApi, initialState }) => {
// Adjust the selection to encompass the whole word if the caret is inside one
const newSelectionRange = textHelpers.selectWord({
const newSelectionRange = selectWord({
text: initialState.text,
selection: initialState.selection
});
const state1 = textApi.setSelectionRange(newSelectionRange);

// when there's no breaking line
if (textHelpers.getSelectedText(state1).indexOf("\n") === -1) {
textApi.replaceSelection(`\`${textHelpers.getSelectedText(state1)}\``);
if (getSelectedText(state1).indexOf("\n") === -1) {
textApi.replaceSelection(`\`${getSelectedText(state1)}\``);
// Adjust the selection to not contain the **

const selectionStart = state1.selection.start + 1;
const selectionEnd =
selectionStart + textHelpers.getSelectedText(state1).length;
const selectionEnd = selectionStart + getSelectedText(state1).length;

textApi.setSelectionRange({
start: selectionStart,
Expand All @@ -27,27 +31,24 @@ export const codeBlock: Command = {
return;
}

const breaksBeforeCount = textHelpers.getBreaksNeededForEmptyLineBefore(
const breaksBeforeCount = getBreaksNeededForEmptyLineBefore(
state1.text,
state1.selection.start
);
const breaksBefore = Array(breaksBeforeCount + 1).join("\n");

const breaksAfterCount = textHelpers.getBreaksNeededForEmptyLineAfter(
const breaksAfterCount = getBreaksNeededForEmptyLineAfter(
state1.text,
state1.selection.end
);
const breaksAfter = Array(breaksAfterCount + 1).join("\n");

textApi.replaceSelection(
`${breaksBefore}\`\`\`\n${textHelpers.getSelectedText(
state1
)}\n\`\`\`${breaksAfter}`
`${breaksBefore}\`\`\`\n${getSelectedText(state1)}\n\`\`\`${breaksAfter}`
);

const selectionStart = state1.selection.start + breaksBeforeCount + 4;
const selectionEnd =
selectionStart + textHelpers.getSelectedText(state1).length;
const selectionEnd = selectionStart + getSelectedText(state1).length;

textApi.setSelectionRange({
start: selectionStart,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
import * as React from "react";
import { Command } from "../command";
import { textHelpers } from "../../helpers/textHelpers";
import {
getCharactersAfterSelection,
getCharactersBeforeSelection,
getSelectedText,
selectWord
} from "../../helpers/textHelpers";

export const code: Command = {
export const codeCommand: Command = {
shouldUndo: options => {
return (
textHelpers.getCharactersBeforeSelection(options.initialState, 1) ===
"`" &&
textHelpers.getCharactersAfterSelection(options.initialState, 1) === "`"
getCharactersBeforeSelection(options.initialState, 1) === "`" &&
getCharactersAfterSelection(options.initialState, 1) === "`"
);
},
execute: ({ initialState, textApi }) => {
// Adjust the selection to encompass the whole word if the caret is inside one
const newSelectionRange = textHelpers.selectWord({
const newSelectionRange = selectWord({
text: initialState.text,
selection: initialState.selection
});
const state1 = textApi.setSelectionRange(newSelectionRange);
// Replaces the current selection with the italic mark up
const state2 = textApi.replaceSelection(
`\`${textHelpers.getSelectedText(state1)}\``
);
const state2 = textApi.replaceSelection(`\`${getSelectedText(state1)}\``);
// Adjust the selection to not contain the *
textApi.setSelectionRange({
start:
state2.selection.end - 1 - textHelpers.getSelectedText(state1).length,
start: state2.selection.end - 1 - getSelectedText(state1).length,
end: state2.selection.end - 1
});
},
undo: ({ initialState, textApi }) => {
const text = textHelpers.getSelectedText(initialState);
const text = getSelectedText(initialState);
textApi.setSelectionRange({
start: initialState.selection.start - 1,
end: initialState.selection.end + 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
import * as React from "react";
import { Command } from "../command";
import { textHelpers } from "../../helpers/textHelpers";
import { TextController, TextState } from "../../types/CommandOptions";
import { getSelectedText, selectWord } from "../../helpers/textHelpers";

function setHeader(
initialState: TextState,
api: TextController,
prefix: string
) {
// Adjust the selection to encompass the whole word if the caret is inside one
const newSelectionRange = textHelpers.selectWord({
const newSelectionRange = selectWord({
text: initialState.text,
selection: initialState.selection
});
const state1 = api.setSelectionRange(newSelectionRange);
// Add the prefix to the selection
const state2 = api.replaceSelection(
`${prefix}${textHelpers.getSelectedText(state1)}`
);
const state2 = api.replaceSelection(`${prefix}${getSelectedText(state1)}`);
// Adjust the selection to not contain the prefix
api.setSelectionRange({
start: state2.selection.end - textHelpers.getSelectedText(state1).length,
start: state2.selection.end - getSelectedText(state1).length,
end: state2.selection.end
});
}

export const header: Command = {
export const headerCommand: Command = {
execute: ({ initialState, textApi }) => {
setHeader(initialState, textApi, "### ");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import * as React from "react";
import { Command } from "../command";
import { textHelpers } from "../../helpers/textHelpers";
import { getSelectedText, selectWord } from "../../helpers/textHelpers";

export const image: Command = {
export const imageCommand: Command = {
execute: ({ initialState, textApi }) => {
// Replaces the current selection with the whole word selected
const state1 = textApi.setSelectionRange(
textHelpers.selectWord({
selectWord({
text: initialState.text,
selection: initialState.selection
})
);
// Replaces the current selection with the image
const imageTemplate =
textHelpers.getSelectedText(state1) ||
"https://example.com/your-image.png";
getSelectedText(state1) || "https://example.com/your-image.png";
textApi.replaceSelection(`![](${imageTemplate})`);
// Adjust the selection to not contain the **
textApi.setSelectionRange({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
import * as React from "react";
import { Command } from "../command";
import { textHelpers } from "../../helpers/textHelpers";
import {
getCharactersAfterSelection,
getCharactersBeforeSelection,
getSelectedText,
selectWord
} from "../../helpers/textHelpers";

export const italic: Command = {
export const italicCommand: Command = {
shouldUndo: options => {
return (
textHelpers.getCharactersBeforeSelection(options.initialState, 1) ===
"*" &&
textHelpers.getCharactersAfterSelection(options.initialState, 1) === "*"
getCharactersBeforeSelection(options.initialState, 1) === "*" &&
getCharactersAfterSelection(options.initialState, 1) === "*"
);
},
execute: ({ initialState, textApi }) => {
// Adjust the selection to encompass the whole word if the caret is inside one
const newSelectionRange = textHelpers.selectWord({
const newSelectionRange = selectWord({
text: initialState.text,
selection: initialState.selection
});
const state1 = textApi.setSelectionRange(newSelectionRange);
// Replaces the current selection with the italic mark up
const state2 = textApi.replaceSelection(
`*${textHelpers.getSelectedText(state1)}*`
);
const state2 = textApi.replaceSelection(`*${getSelectedText(state1)}*`);
// Adjust the selection to not contain the *
textApi.setSelectionRange({
start:
state2.selection.end - 1 - textHelpers.getSelectedText(state1).length,
start: state2.selection.end - 1 - getSelectedText(state1).length,
end: state2.selection.end - 1
});
},
undo: ({ initialState, textApi }) => {
const text = textHelpers.getSelectedText(initialState);
const text = getSelectedText(initialState);
textApi.setSelectionRange({
start: initialState.selection.start - 1,
end: initialState.selection.end + 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import * as React from "react";
import { Command } from "../command";
import { textHelpers } from "../../helpers/textHelpers";
import { getSelectedText, selectWord } from "../../helpers/textHelpers";

export const link: Command = {
export const linkCommand: Command = {
execute: ({ initialState, textApi }) => {
// Adjust the selection to encompass the whole word if the caret is inside one
const newSelectionRange = textHelpers.selectWord({
const newSelectionRange = selectWord({
text: initialState.text,
selection: initialState.selection
});
const state1 = textApi.setSelectionRange(newSelectionRange);
// Replaces the current selection with the bold mark up
const state2 = textApi.replaceSelection(
`[${textHelpers.getSelectedText(state1)}](url)`
`[${getSelectedText(state1)}](url)`
);
// Adjust the selection to not contain the **
textApi.setSelectionRange({
start:
state2.selection.end - 6 - textHelpers.getSelectedText(state1).length,
start: state2.selection.end - 6 - getSelectedText(state1).length,
end: state2.selection.end - 6
});
}
Expand Down
Loading

0 comments on commit 68ec338

Please sign in to comment.