Add code blocks to rich text editor (#9921)
* Applies small changes to code block display in timeline * Makes the composer code block look like the timeline display, but without line numbers * Adds a button to allow code blocks to be implemented * Adds tests for the new button
This commit is contained in:
parent
422802ea6d
commit
a63da74f06
5 changed files with 32 additions and 3 deletions
|
@ -548,7 +548,7 @@ $left-gutter: 64px;
|
||||||
pre,
|
pre,
|
||||||
code {
|
code {
|
||||||
font-family: $monospace-font-family !important;
|
font-family: $monospace-font-family !important;
|
||||||
background-color: $codeblock-background-color;
|
background-color: $system;
|
||||||
}
|
}
|
||||||
|
|
||||||
code:not(pre *) {
|
code:not(pre *) {
|
||||||
|
@ -578,6 +578,8 @@ $left-gutter: 64px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
border: 1px solid $quinary-content;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
white-space: pre; /* we want code blocks to be scrollable and not wrap */
|
white-space: pre; /* we want code blocks to be scrollable and not wrap */
|
||||||
|
|
||||||
|
@ -756,6 +758,8 @@ $left-gutter: 64px;
|
||||||
|
|
||||||
.mx_EventTile_collapsedCodeBlock {
|
.mx_EventTile_collapsedCodeBlock {
|
||||||
max-height: 30vh;
|
max-height: 30vh;
|
||||||
|
padding-top: $spacing-12;
|
||||||
|
padding-bottom: $spacing-12;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inserted adjacent to <pre> blocks, (See TextualBody) */
|
/* Inserted adjacent to <pre> blocks, (See TextualBody) */
|
||||||
|
|
|
@ -46,10 +46,23 @@ limitations under the License.
|
||||||
|
|
||||||
// model output always includes a linebreak but we do not want the user
|
// model output always includes a linebreak but we do not want the user
|
||||||
// to see it when writing input in lists
|
// to see it when writing input in lists
|
||||||
:is(ol, ul) + br:last-of-type {
|
:is(ol, ul, pre) + br:last-of-type {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> pre {
|
||||||
|
font-size: $font-15px;
|
||||||
|
line-height: $font-24px;
|
||||||
|
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding: $spacing-8 $spacing-12;
|
||||||
|
|
||||||
|
background-color: $inlinecode-background-color;
|
||||||
|
border: 1px solid $inlinecode-border-color;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-family: $monospace-font-family !important;
|
font-family: $monospace-font-family !important;
|
||||||
background-color: $inlinecode-background-color;
|
background-color: $inlinecode-background-color;
|
||||||
|
|
3
res/img/element-icons/room/composer/code_block.svg
Normal file
3
res/img/element-icons/room/composer/code_block.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4.14288 6.99997L5.47622 5.66663C5.5905 5.55235 5.64765 5.41266 5.64765 5.24758C5.64765 5.0825 5.5905 4.94282 5.47622 4.82854C5.36193 4.71425 5.22225 4.65711 5.05717 4.65711C4.89209 4.65711 4.75241 4.71425 4.63812 4.82854L2.86669 6.59997C2.8032 6.66346 2.75876 6.72695 2.73336 6.79044C2.70796 6.85393 2.69526 6.92377 2.69526 6.99997C2.69526 7.07616 2.70796 7.146 2.73336 7.20949C2.75876 7.27298 2.8032 7.33647 2.86669 7.39996L4.65717 9.19044C4.77145 9.30473 4.91114 9.36187 5.07622 9.36187C5.2413 9.36187 5.38098 9.30473 5.49526 9.19044C5.60955 9.07616 5.66669 8.93647 5.66669 8.77139C5.66669 8.60631 5.60955 8.46663 5.49526 8.35235L4.14288 6.99997ZM9.85717 6.99997L8.50479 8.35235C8.3905 8.46663 8.33336 8.60631 8.33336 8.77139C8.33336 8.93647 8.3905 9.07616 8.50479 9.19044C8.61907 9.30473 8.75876 9.36187 8.92384 9.36187C9.08891 9.36187 9.2286 9.30473 9.34288 9.19044L11.1334 7.39996C11.1969 7.33647 11.2413 7.27298 11.2667 7.20949C11.2921 7.146 11.3048 7.07616 11.3048 6.99997C11.3048 6.92377 11.2921 6.85393 11.2667 6.79044C11.2413 6.72695 11.1969 6.66346 11.1334 6.59997L9.34288 4.80949C9.29209 4.746 9.2286 4.70155 9.15241 4.67616C9.07622 4.65076 9.00003 4.63806 8.92384 4.63806C8.84765 4.63806 8.77463 4.65076 8.70479 4.67616C8.63495 4.70155 8.56828 4.746 8.50479 4.80949C8.3905 4.92377 8.33336 5.06346 8.33336 5.22854C8.33336 5.39362 8.3905 5.5333 8.50479 5.64758L9.85717 6.99997ZM1.28574 13.8571C0.980979 13.8571 0.714312 13.7428 0.48574 13.5143C0.257169 13.2857 0.142883 13.019 0.142883 12.7143V1.28568C0.142883 0.980918 0.257169 0.714251 0.48574 0.485679C0.714312 0.257108 0.980979 0.142822 1.28574 0.142822H12.7143C13.0191 0.142822 13.2857 0.257108 13.5143 0.485679C13.7429 0.714251 13.8572 0.980918 13.8572 1.28568V12.7143C13.8572 13.019 13.7429 13.2857 13.5143 13.5143C13.2857 13.7428 13.0191 13.8571 12.7143 13.8571H1.28574ZM1.28574 12.7143H12.7143V1.28568H1.28574V12.7143Z" fill="currentColor"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2 KiB |
|
@ -26,6 +26,7 @@ import { Icon as InlineCodeIcon } from "../../../../../../res/img/element-icons/
|
||||||
import { Icon as LinkIcon } from "../../../../../../res/img/element-icons/room/composer/link.svg";
|
import { Icon as LinkIcon } from "../../../../../../res/img/element-icons/room/composer/link.svg";
|
||||||
import { Icon as BulletedListIcon } from "../../../../../../res/img/element-icons/room/composer/bulleted_list.svg";
|
import { Icon as BulletedListIcon } from "../../../../../../res/img/element-icons/room/composer/bulleted_list.svg";
|
||||||
import { Icon as NumberedListIcon } from "../../../../../../res/img/element-icons/room/composer/numbered_list.svg";
|
import { Icon as NumberedListIcon } from "../../../../../../res/img/element-icons/room/composer/numbered_list.svg";
|
||||||
|
import { Icon as CodeBlockIcon } from "../../../../../../res/img/element-icons/room/composer/code_block.svg";
|
||||||
import AccessibleTooltipButton from "../../../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../../../elements/AccessibleTooltipButton";
|
||||||
import { Alignment } from "../../../elements/Tooltip";
|
import { Alignment } from "../../../elements/Tooltip";
|
||||||
import { KeyboardShortcut } from "../../../settings/KeyboardShortcut";
|
import { KeyboardShortcut } from "../../../settings/KeyboardShortcut";
|
||||||
|
@ -132,6 +133,12 @@ export function FormattingButtons({ composer, actionStates }: FormattingButtonsP
|
||||||
onClick={() => composer.inlineCode()}
|
onClick={() => composer.inlineCode()}
|
||||||
icon={<InlineCodeIcon className="mx_FormattingButtons_Icon" />}
|
icon={<InlineCodeIcon className="mx_FormattingButtons_Icon" />}
|
||||||
/>
|
/>
|
||||||
|
<Button
|
||||||
|
actionState={actionStates.codeBlock}
|
||||||
|
label={_td("Code block")}
|
||||||
|
onClick={() => composer.codeBlock()}
|
||||||
|
icon={<CodeBlockIcon className="mx_FormattingButtons_Icon" />}
|
||||||
|
/>
|
||||||
<Button
|
<Button
|
||||||
actionState={actionStates.link}
|
actionState={actionStates.link}
|
||||||
label={_td("Link")}
|
label={_td("Link")}
|
||||||
|
|
|
@ -28,6 +28,7 @@ const mockWysiwyg = {
|
||||||
underline: jest.fn(),
|
underline: jest.fn(),
|
||||||
strikeThrough: jest.fn(),
|
strikeThrough: jest.fn(),
|
||||||
inlineCode: jest.fn(),
|
inlineCode: jest.fn(),
|
||||||
|
codeBlock: jest.fn(),
|
||||||
link: jest.fn(),
|
link: jest.fn(),
|
||||||
orderedList: jest.fn(),
|
orderedList: jest.fn(),
|
||||||
unorderedList: jest.fn(),
|
unorderedList: jest.fn(),
|
||||||
|
@ -36,7 +37,7 @@ const mockWysiwyg = {
|
||||||
const openLinkModalSpy = jest.spyOn(LinkModal, "openLinkModal");
|
const openLinkModalSpy = jest.spyOn(LinkModal, "openLinkModal");
|
||||||
|
|
||||||
const testCases: Record<
|
const testCases: Record<
|
||||||
Exclude<ActionTypes, "undo" | "redo" | "clear" | "codeBlock">,
|
Exclude<ActionTypes, "undo" | "redo" | "clear">,
|
||||||
{ label: string; mockFormatFn: jest.Func | jest.SpyInstance }
|
{ label: string; mockFormatFn: jest.Func | jest.SpyInstance }
|
||||||
> = {
|
> = {
|
||||||
bold: { label: "Bold", mockFormatFn: mockWysiwyg.bold },
|
bold: { label: "Bold", mockFormatFn: mockWysiwyg.bold },
|
||||||
|
@ -44,6 +45,7 @@ const testCases: Record<
|
||||||
underline: { label: "Underline", mockFormatFn: mockWysiwyg.underline },
|
underline: { label: "Underline", mockFormatFn: mockWysiwyg.underline },
|
||||||
strikeThrough: { label: "Strikethrough", mockFormatFn: mockWysiwyg.strikeThrough },
|
strikeThrough: { label: "Strikethrough", mockFormatFn: mockWysiwyg.strikeThrough },
|
||||||
inlineCode: { label: "Code", mockFormatFn: mockWysiwyg.inlineCode },
|
inlineCode: { label: "Code", mockFormatFn: mockWysiwyg.inlineCode },
|
||||||
|
codeBlock: { label: "Code block", mockFormatFn: mockWysiwyg.inlineCode },
|
||||||
link: { label: "Link", mockFormatFn: openLinkModalSpy },
|
link: { label: "Link", mockFormatFn: openLinkModalSpy },
|
||||||
orderedList: { label: "Numbered list", mockFormatFn: mockWysiwyg.orderedList },
|
orderedList: { label: "Numbered list", mockFormatFn: mockWysiwyg.orderedList },
|
||||||
unorderedList: { label: "Bulleted list", mockFormatFn: mockWysiwyg.unorderedList },
|
unorderedList: { label: "Bulleted list", mockFormatFn: mockWysiwyg.unorderedList },
|
||||||
|
|
Loading…
Reference in a new issue