Merge pull request #273 from jorilallo/markdown-checkboxes
Markdown shortcuts for checkbox lists
This commit is contained in:
@@ -22,28 +22,27 @@ export default class TodoItem extends Component {
|
|||||||
const { children, checked, readOnly } = this.props;
|
const { children, checked, readOnly } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledLi contentEditable={false}>
|
<ListItem>
|
||||||
<input
|
<Input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checked}
|
checked={checked}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
disabled={readOnly}
|
disabled={readOnly}
|
||||||
|
contentEditable={false}
|
||||||
/>
|
/>
|
||||||
{' '}
|
{children}
|
||||||
<span contentEditable={!readOnly} suppressContentEditableWarning>
|
</ListItem>
|
||||||
{children}
|
|
||||||
</span>
|
|
||||||
</StyledLi>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledLi = styled.li`
|
const ListItem = styled.li`
|
||||||
input {
|
padding-left: 1.4em;
|
||||||
margin-right: 0.25em;
|
position: relative;
|
||||||
}
|
`;
|
||||||
|
|
||||||
&:last-child:focus {
|
const Input = styled.input`
|
||||||
outline: none;
|
position: absolute;
|
||||||
}
|
left: 0;
|
||||||
|
top: 0.4em;
|
||||||
`;
|
`;
|
||||||
|
|||||||
13
frontend/components/Editor/components/TodoList.js
Normal file
13
frontend/components/Editor/components/TodoList.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// @flow
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const TodoList = styled.ul`
|
||||||
|
list-style: none;
|
||||||
|
padding: 0 !important;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default TodoList;
|
||||||
@@ -40,17 +40,24 @@ export default function MarkdownShortcuts() {
|
|||||||
onSpace(ev: SyntheticEvent, state: Object) {
|
onSpace(ev: SyntheticEvent, state: Object) {
|
||||||
if (state.isExpanded) return;
|
if (state.isExpanded) return;
|
||||||
const { startBlock, startOffset } = state;
|
const { startBlock, startOffset } = state;
|
||||||
const chars = startBlock.text.slice(0, startOffset).replace(/\s*/g, '');
|
const chars = startBlock.text.slice(0, startOffset).trim();
|
||||||
const type = this.getType(chars);
|
const type = this.getType(chars);
|
||||||
|
|
||||||
if (type) {
|
if (type) {
|
||||||
if (type === 'list-item' && startBlock.type === 'list-item') return;
|
if (type === 'list-item' && startBlock.type === 'list-item') return;
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
const transform = state.transform().setBlock(type);
|
let checked;
|
||||||
|
if (chars === '[x]') checked = true;
|
||||||
|
if (chars === '[ ]') checked = false;
|
||||||
|
const transform = state
|
||||||
|
.transform()
|
||||||
|
.setBlock({ type, data: { checked } });
|
||||||
|
|
||||||
if (type === 'list-item') {
|
if (type === 'list-item') {
|
||||||
if (chars === '1.') {
|
if (checked !== undefined) {
|
||||||
|
transform.wrapBlock('todo-list');
|
||||||
|
} else if (chars === '1.') {
|
||||||
transform.wrapBlock('ordered-list');
|
transform.wrapBlock('ordered-list');
|
||||||
} else {
|
} else {
|
||||||
transform.wrapBlock('bulleted-list');
|
transform.wrapBlock('bulleted-list');
|
||||||
@@ -234,6 +241,8 @@ export default function MarkdownShortcuts() {
|
|||||||
case '-':
|
case '-':
|
||||||
case '+':
|
case '+':
|
||||||
case '1.':
|
case '1.':
|
||||||
|
case '[ ]':
|
||||||
|
case '[x]':
|
||||||
return 'list-item';
|
return 'list-item';
|
||||||
case '>':
|
case '>':
|
||||||
return 'block-quote';
|
return 'block-quote';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
|
||||||
import Code from './components/Code';
|
import Code from './components/Code';
|
||||||
import InlineCode from './components/InlineCode';
|
import InlineCode from './components/InlineCode';
|
||||||
import Image from './components/Image';
|
import Image from './components/Image';
|
||||||
import Link from './components/Link';
|
import Link from './components/Link';
|
||||||
import ListItem from './components/ListItem';
|
import ListItem from './components/ListItem';
|
||||||
|
import TodoList from './components/TodoList';
|
||||||
import {
|
import {
|
||||||
Heading1,
|
Heading1,
|
||||||
Heading2,
|
Heading2,
|
||||||
@@ -17,15 +17,6 @@ import {
|
|||||||
import Paragraph from './components/Paragraph';
|
import Paragraph from './components/Paragraph';
|
||||||
import type { Props, Node, Transform } from './types';
|
import type { Props, Node, Transform } from './types';
|
||||||
|
|
||||||
const TodoList = styled.ul`
|
|
||||||
list-style: none;
|
|
||||||
padding-left: 0;
|
|
||||||
|
|
||||||
ul {
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const createSchema = () => {
|
const createSchema = () => {
|
||||||
return {
|
return {
|
||||||
marks: {
|
marks: {
|
||||||
@@ -63,7 +54,7 @@ const createSchema = () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
rules: [
|
rules: [
|
||||||
// ensure first node is a heading
|
// ensure first node is always a heading
|
||||||
{
|
{
|
||||||
match: (node: Node) => {
|
match: (node: Node) => {
|
||||||
return node.kind === 'document';
|
return node.kind === 'document';
|
||||||
@@ -77,7 +68,7 @@ const createSchema = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// remove any marks in first heading
|
// automatically removes any marks in first heading
|
||||||
{
|
{
|
||||||
match: (node: Node) => {
|
match: (node: Node) => {
|
||||||
return node.kind === 'heading1';
|
return node.kind === 'heading1';
|
||||||
|
|||||||
Reference in New Issue
Block a user