Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(common-ui): Add Markdown component. #2741

Merged
merged 29 commits into from
Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
92cdcbd
feat(common-ui): Add markdown renderer
victorgcramos Mar 14, 2022
2b0c4ce
chore(common-ui): Setup tests and dev mode
victorgcramos Mar 14, 2022
83e6742
feat(common-ui): Add Markdown Diff
victorgcramos Mar 14, 2022
7eb42e0
test(common-ui): improve markdown diff tests
victorgcramos Mar 15, 2022
a59af6f
test(common-ui): improve diff tests
victorgcramos Mar 15, 2022
86b1386
chore(common-ui): add remark gfm plugin
victorgcramos Mar 17, 2022
dd4bdcf
refactor(common-ui): move diff to markdown dir
victorgcramos Mar 17, 2022
5e1d4a6
test(common-ui): gfm plugin test adjustments
victorgcramos Mar 17, 2022
7f5c153
feat(common-ui): markdown improvements
victorgcramos Mar 17, 2022
854833e
chore(common-ui): add SVG loader
victorgcramos Mar 17, 2022
0eb3397
feat(common-ui): add Markdown Editor
victorgcramos Mar 17, 2022
98cfc40
test(common-ui): markdown editor commands utils
victorgcramos Mar 17, 2022
4e9f39f
test(common-ui): markdown editor commands tests
victorgcramos Mar 17, 2022
f4efabc
feat(common-ui): add MarkdownEditor PropTypes
victorgcramos Mar 17, 2022
f2bb76a
wip(common-ui): fix markdown diff
victorgcramos Mar 23, 2022
0219e44
feat(common-ui): improve diff tests.
victorgcramos Mar 24, 2022
584a40d
feat(common-ui): improve diff tests.
victorgcramos Mar 24, 2022
29db7f0
feat(common-ui): multiline commands on md editor
victorgcramos Mar 24, 2022
63a1c39
feat(common-ui): add commands shortcuts
victorgcramos Mar 24, 2022
1f37424
feat(common-ui): review fixes
victorgcramos Mar 25, 2022
fc7194a
refactor(common-ui): MD editor commands utils
victorgcramos Mar 28, 2022
7ef2633
refactor(common-ui): state changes on MDE commands
victorgcramos Mar 28, 2022
df31962
fix(common-ui): cleanup
victorgcramos Mar 28, 2022
8446d53
chore(multi): upgrade pi-ui
victorgcramos Mar 29, 2022
eb49c3c
refactor(common-ui): improve MD commands structure
victorgcramos Mar 29, 2022
476063e
feat(common-ui): use createCommand for MD commands
victorgcramos Mar 29, 2022
75c24a7
docs(common-ui): add Markdown Editor docs
victorgcramos Mar 30, 2022
2a9fe6a
test(common-ui): MDE commands tests
victorgcramos Mar 30, 2022
82ff4d1
test(common-ui): add Markdown Editor tests
victorgcramos Mar 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -433,12 +433,19 @@ describe("Given DiffHTML", () => {
addedNode: "CODE",
},
{
name: "list by paragraph",
name: "ordered list by paragraph",
oldText: `1. ${content}`,
newText: content,
removedNode: "LI",
addedNode: "P",
},
{
name: "unordered list by paragraph",
oldText: `- ${content}`,
newText: content,
removedNode: "LI",
addedNode: "P",
},
{
name: "code block by paragraph",
oldText: `\`\`\`\n${content}\n\`\`\``,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useRef, useState } from "react";
import React, { useMemo, useRef, useState } from "react";
import PropTypes from "prop-types";
import { classNames } from "pi-ui";
import styles from "./MarkdownEditor.module.css";
import { MarkdownRenderer } from "../MarkdownRenderer";
import { commands, getMultiLineContent, getSelectedContent } from "./commands";
import { commands, executeCommand } from "./commands";

export function MarkdownEditor({
onChange,
Expand All @@ -15,6 +15,11 @@ export function MarkdownEditor({
const editorRef = useRef();
const [showPreview, setShowPreview] = useState(false);
const [value, setValue] = useState(initialValue);
const availableCommands = useMemo(
() => [...customCommands, ...commands],
[customCommands]
);

function handleChange(e) {
setValue(e.target.value);
onChange(e.target.value);
Expand All @@ -25,16 +30,33 @@ export function MarkdownEditor({
function handleShowWrite() {
setShowPreview(false);
}
const handleCommand = (command) => () => {
const content = editorRef.current.value;
const startPos = editorRef.current.selectionStart;
const endPos = editorRef.current.selectionEnd;
const selected = getSelectedContent(content, startPos, endPos);
const lines = getMultiLineContent(content, startPos, endPos);
const newString = command({ selected, lines });
setValue(newString);
onChange(newString);
};

const handleCommand =
(command, { offset = 0 } = {}) =>
() => {
const content = editorRef.current.value;
const startPos = editorRef.current.selectionStart;
const endPos = editorRef.current.selectionEnd;
const newString = executeCommand(command, content, startPos, endPos);
// prevent sync issues between textarea updates.
victorgcramos marked this conversation as resolved.
Show resolved Hide resolved
setTimeout(() => {
setValue(newString);
onChange(newString);
editorRef.current.focus();
editorRef.current.selectionStart = startPos + offset;
editorRef.current.selectionEnd = endPos + offset;
}, 1);
};

function handleKeyPress(event) {
if (event.metaKey || event.ctrlKey) {
const cmd = availableCommands.find((c) => c.commandKey === event.key);
if (cmd) {
const { command, offset } = cmd;
handleCommand(command, { offset })();
}
}
}

return (
<div className={classNames(styles.editorWrapper, wrapperClassName)}>
Expand All @@ -44,8 +66,8 @@ export function MarkdownEditor({
<div onClick={handleShowPreview}>Preview</div>
</div>
<div className={styles.actionButtons}>
{[...commands, ...customCommands].map(({ command, Icon }, i) => (
<span key={i} onClick={handleCommand(command)}>
{availableCommands.map(({ command, Icon, offset }, i) => (
<span key={i} onClick={handleCommand(command, { offset })}>
<Icon />
</span>
))}
Expand All @@ -66,7 +88,9 @@ export function MarkdownEditor({
ref={editorRef}
className={styles.editor}
value={value}
onKeyPress={handleKeyPress}
onChange={handleChange}
// onSelect={(e) => console.log("EVENT", e)}
/>
<MarkdownRenderer body={value} className={styles.preview} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import ItalicSVG from "./assets/italic.svg";
import QuoteSVG from "./assets/quote.svg";
import CodeSVG from "./assets/code.svg";
import BulletListSVG from "./assets/bulletList.svg";
// import { ReactComponent as ImageSVG } from "./assets/image.svg";
import NumberedListSVG from "./assets/numberedList.svg";
// TODO: Add image command

function formatEachLine(lines, formatFn, { ignoreBlankLines } = {}) {
let index = 0;
return lines.reduce((acc, curr) => {
return lines.reduce((acc, curr, i) => {
if (ignoreBlankLines && curr.length === 0) {
return `${acc}\n`;
}
index++;
return `${acc}\n${formatFn(curr, index)}`;
return `${acc}${!!i ? "\n" : ""}${formatFn(curr, index)}`;
}, "");
}

Expand All @@ -33,39 +33,47 @@ const multiLineCommand =
export const commands = [
{
label: "Bold Text",
commandKey: "b",
offset: 2,
Icon: BoldSVG,
command: ({ selected: { previous, current, next } }) =>
`${previous}**${current}**${next}`,
},
{
label: "Italic",
commandKey: "i",
offset: 1,
Icon: ItalicSVG,
command: ({ selected: { previous, current, next } }) =>
`${previous}*${current}*${next}`,
`${previous}_${current}_${next}`,
},
{
label: "Quote",
Icon: QuoteSVG,
offset: 2,
command: multiLineCommand((curr) => `> ${curr}`, {
ignoreBlankLines: true,
}),
},
{
label: "Code",
Icon: CodeSVG,
offset: 1,
command: ({ selected: { previous, current, next } }) =>
`${previous}\`${current}\`${next}`,
},
{
label: "List",
Icon: BulletListSVG,
offset: 2,
command: multiLineCommand((curr) => `- ${curr}`, {
ignoreBlankLines: true,
}),
},
{
label: "Numbered List",
Icon: NumberedListSVG,
offset: 3,
command: multiLineCommand((curr, i) => `${i}. ${curr}`, {
ignoreBlankLines: true,
}),
Expand Down