Skip to content

Commit

Permalink
Merge pull request #2141 from tf/master
Browse files Browse the repository at this point in the history
Add sub and sup marks to editable text
  • Loading branch information
tf authored Aug 6, 2024
2 parents 4c22bce + 6102f0e commit d059f1e
Show file tree
Hide file tree
Showing 13 changed files with 233 additions and 25 deletions.
4 changes: 0 additions & 4 deletions entry_types/scrolled/config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1010,14 +1010,10 @@ de:
open_in_new_tab_message: Öffnen im selben Tab ist im Editor deaktiviert.
formats:
block_quote: Blockzitat
bold: Fett
bulleted_list: Auflistung
heading: Überschrift
italic: Kursiv
ordered_list: Aufzählung
paragraph: Absatz
strikethrough: Durchgestrichen
underline: Unterstrichen
insert_content_element:
after: Neues Element unterhalb einfügen
before: Neues Element oberhalb einfügen
Expand Down
4 changes: 0 additions & 4 deletions entry_types/scrolled/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -848,14 +848,10 @@ en:
open_in_new_tab_message: Opening in same tab is disabled inside the editor
formats:
block_quote: Block quote
bold: Bold
bulleted_list: Bulleted list
heading: Heading
italic: Italic
ordered_list: Ordered list
paragraph: Paragraph
strikethrough: Strikethrough
underline: Underline
insert_content_element:
after: Insert new element below
before: Insert new element above
Expand Down
10 changes: 10 additions & 0 deletions entry_types/scrolled/config/locales/new/sub_sup.de.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
de:
pageflow_scrolled:
inline_editing:
formats:
bold: Fett (Strg+B)
italic: Kursiv (Strg+I)
strikethrough: Durchgestrichen (Strg+Umschalten+S)
underline: Unterstrichen (Strg+U)
sub: Tiefgestellt (Strg+;)
sup: Hochgestellt (Strg+,)
10 changes: 10 additions & 0 deletions entry_types/scrolled/config/locales/new/sub_sup.en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
en:
pageflow_scrolled:
inline_editing:
formats:
bold: Bold (Ctrl+B)
italic: Italic (Ctrl+I)
strikethrough: Strikethrough (Ctrl+Shift+S)
underline: Underline (Ctrl+U)
sub: Subscript (Ctrl+;)
sup: Superscript (Ctrl+,)
18 changes: 18 additions & 0 deletions entry_types/scrolled/package/spec/frontend/EditableText-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,24 @@ describe('EditableText', () => {
expect(container.querySelector('p')).toHaveTextContent('\uFEFF', {normalizeWhitespace: false})
});

it('renders sub and sup text', () => {
const value = [{
type: 'paragraph',
children: [
{text: 'x'},
{text: '3', sup: true},
{text: ' and '},
{text: 'CO'},
{text: '2', sub: true}
]
}];

const {container} = render(<EditableText value={value} />);

expect(container.querySelector('sup')).toHaveTextContent('3')
expect(container.querySelector('sub')).toHaveTextContent('2')
});

it('does not render zero width no break space between two formatted words', () => {
const value = [{
type: 'paragraph',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/** @jsx jsx */
import {
toggleMark,
isMarkActive
} from 'frontend/inlineEditing/EditableText/marks';

import {createHyperscript} from 'slate-hyperscript';

const h = createHyperscript({
elements: {
paragraph: {type: 'paragraph'},
},
});

// Strip meta tags to make deep equality checks work
const jsx = (tagName, attributes, ...children) => {
delete attributes.__self;
delete attributes.__source;
return h(tagName, attributes, ...children);
}

describe('isMarkActive', () => {
it('returns true if current node has mark', () => {
const editor = (
<editor>
<paragraph>
<text bold>Line 1<cursor /></text>
</paragraph>
</editor>
);

expect(isMarkActive(editor, 'bold')).toEqual(true);
expect(isMarkActive(editor, 'italic')).toEqual(false);
});
});

describe('toggleMark', () => {
it('adds mark', () => {
const editor = (
<editor>
<paragraph>
Some <anchor />text<focus />
</paragraph>
</editor>
);

toggleMark(editor, 'bold');

const output = (
<editor>
<paragraph>
Some <text bold>text</text>
</paragraph>
</editor>
);
expect(editor.children).toEqual(output.children);
});

it('removes mark', () => {
const editor = (
<editor>
<paragraph>
Some <text bold><anchor />text<focus /></text>
</paragraph>
</editor>
);

toggleMark(editor, 'bold');

const output = (
<editor>
<paragraph>
Some text
</paragraph>
</editor>
);
expect(editor.children).toEqual(output.children);
});

it('treats sub and sup as mutually exclusive', () => {
const editor = (
<editor>
<paragraph>
Some <text sup><anchor />text<focus /></text>
</paragraph>
</editor>
);

toggleMark(editor, 'sub');

const output = (
<editor>
<paragraph>
Some <text sub>text</text>
</paragraph>
</editor>
);
expect(editor.children).toEqual(output.children);
});
});
8 changes: 8 additions & 0 deletions entry_types/scrolled/package/src/frontend/EditableText.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,13 @@ export function renderLeaf({attributes, children, leaf}) {
children = <s>{children}</s>
}

if (leaf.sub) {
children = <sub>{children}</sub>
}

if (leaf.sup) {
children = <sup>{children}</sup>
}

return <span {...attributes}>{children}</span>
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import {ReactEditor, useSlate} from 'slate-react';
import {Toolbar} from '../Toolbar';
import {useI18n} from '../../i18n';
import {useSelectLinkDestination} from '../useSelectLinkDestination';
import {isMarkActive, toggleMark} from './marks';

import styles from './index.module.css';

import BoldIcon from '../images/bold.svg';
import UnderlineIcon from '../images/underline.svg';
import ItalicIcon from '../images/italic.svg';
import StrikethroughIcon from '../images/strikethrough.svg';
import SubIcon from '../images/sub.svg';
import SupIcon from '../images/sup.svg';
import LinkIcon from '../images/link.svg';

export function HoveringToolbar({position}) {
Expand Down Expand Up @@ -88,6 +91,16 @@ function renderToolbar(editor, t, selectLinkDestination) {
text: t('pageflow_scrolled.inline_editing.formats.strikethrough'),
icon: StrikethroughIcon
},
{
name: 'sub',
text: t('pageflow_scrolled.inline_editing.formats.sub'),
icon: SubIcon
},
{
name: 'sup',
text: t('pageflow_scrolled.inline_editing.formats.sup'),
icon: SupIcon
},
{
name: 'link',
text: isButtonActive(editor, 'link') ?
Expand Down Expand Up @@ -148,18 +161,3 @@ function isLinkActive(editor) {
const [link] = Editor.nodes(editor, {match: n => n.type === 'link'});
return !!link;
}

function toggleMark(editor, format) {
const isActive = isMarkActive(editor, format)

if (isActive) {
Editor.removeMark(editor, format)
} else {
Editor.addMark(editor, format, true)
}
}

function isMarkActive(editor, format) {
const marks = Editor.marks(editor)
return marks ? marks[format] === true : false
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useMemo, useEffect} from 'react';
import React, {useCallback, useMemo, useEffect} from 'react';
import classNames from 'classnames';
import {createEditor, Transforms, Node, Text as SlateText, Range} from 'slate';
import {Slate, Editable, withReact, ReactEditor} from 'slate-react';
Expand Down Expand Up @@ -32,6 +32,8 @@ import {
renderLeafWithLineBreakDecoration
} from './lineBreaks';

import {useShortcutHandler} from './shortcuts';

import styles from './index.module.css';

export const EditableText = React.memo(function EditableText({
Expand All @@ -54,7 +56,14 @@ export const EditableText = React.memo(function EditableText({
),
[selectionRect]
);

const handleLineBreaks = useLineBreakHandler(editor);
const handleShortcuts = useShortcutHandler(editor);

const handleKeyDown = useCallback(event => {
handleLineBreaks(event);
handleShortcuts(event);
}, [handleLineBreaks, handleShortcuts]);

useEffect(() => {
if (autoFocus) {
Expand Down Expand Up @@ -102,7 +111,7 @@ export const EditableText = React.memo(function EditableText({
<Editable
className={className}
decorate={decorateLineBreaks}
onKeyDown={handleLineBreaks}
onKeyDown={handleKeyDown}
renderElement={renderElementWithLinkPreview}
renderLeaf={renderLeafWithLineBreakDecoration} />
</LinkTooltipProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {Editor} from 'slate';

const mutuallyExclusive = {
sup: 'sub',
sub: 'sup'
}

export function toggleMark(editor, format) {
const isActive = isMarkActive(editor, format)

if (isActive) {
Editor.removeMark(editor, format)
} else {
if (mutuallyExclusive[format] &&
isMarkActive(editor, mutuallyExclusive[format])) {
Editor.removeMark(editor, mutuallyExclusive[format]);
}

Editor.addMark(editor, format, true)
}
}

export function isMarkActive(editor, format) {
const marks = Editor.marks(editor)
return marks ? marks[format] === true : false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {useCallback} from 'react';
import {toggleMark} from './marks';

export function useShortcutHandler(editor) {
return useCallback(event => {
if (!event.ctrlKey) {
return;
}

if (event.key === 'b') {
event.preventDefault()
toggleMark(editor, 'bold');
}
else if (event.key === 'i') {
event.preventDefault()
toggleMark(editor, 'italic');
}
else if (event.key === 'u') {
event.preventDefault()
toggleMark(editor, 'underline');
}
else if (event.key === 'S') {
event.preventDefault()
toggleMark(editor, 'strikethrough');
}
else if (event.key === ',') {
event.preventDefault()
toggleMark(editor, 'sup');
}
else if (event.key === ';') {
event.preventDefault()
toggleMark(editor, 'sub');
}
}, [editor]);
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit d059f1e

Please sign in to comment.