mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-02-24 09:13:24 +01:00
* remove some key usage from core, refactor Operations.apply * undeprecate some methods * convert more key usage to paths * update deprecations * convert selection commands to use all paths * refactor word boundary selection logic * convert many at-range commands to use paths * convert wrapBlock and wrapInline to not use keys * cleanup * remove chainability from editor * simplify commands, queries and middleware * convert deleteAtRange * remove key usage from schema, deprecate *ByKey methods * migrate *ByKey tests, remove index from *ByPath signatures * rename at-current-range tests * deprecate mode key usage, migrate more tests away from keys * deprecate range and point methods which rely on keys to work * refactor insertBlock, without fixing warnings * add pathRef/pointRef, fix insertBlock/Inline deprecations, work on insertFragment * refactor insertFragment * get rich-text example rendering * fix lint * refactor query files, fix more tests * remove unused queries, refactor others * deprecate splitDescendantsByPath * merge master * add typescript, convert slate, slate-hyperscript, slate-plain-serializer * add Point, Path, Range, Annotation tests * add Annotation, Change, Element, Fragment, Mark, Range, Selection, Value interfaces tests * add Operation and Text tests * add Node tests * get operations and normalization tests working for slate * get *AtPath command tests passing * rename *AtPath command tests * rename * get *AtPoint tests working * rename * rename * add value queries tests * add element, mark and path queries tests * convert most on-selection tests * convert on-selection commands * rename * get addMarks and delete commands working * rename * rename * rename * refactor value.positions(), work on delete tests * progress on delete tests * more delete work * finish delete tests * start converting to at-based commands * restructure query tests * restructure operations tests * more work converting to multi-purpose commands * lots of progress on converting to at-based commands * add unwrapNodes * remove setValue * more progress * refactor node commands to use consistent matching logic * cleanup, get non-fragment commands passing * remove annotations and isAtomic * rename surround/pluck to cover/uncover * add location concept, change at-path to from-path for iterables * refactor batches * add location-based queries * refactor hanging logic * more location query work * renaming * use getMatch more * add split to wrap/unwrap * flip levels/ancestors ordering * switch splitNodes to use levels * change split to always:false by default * fix tests * add more queries tests * fixing more delete logic * add more splitNodes tests * get rest of delete tests passing * fix location-based logic in some commands * cleanup * get previous packages tests passing again * add slate-history package * start slate-schema work * start of react working * rendering fixes * get rich and plain text examples working * get image example working with hooks and dropping * refactor onDrop to be internal * inline more event handlers * refactor lots of event-related logic * change rendering to use render props * delete unused stuff * cleanup dom utils * remove unused deps * remove unnecessary packages, add placeholder * remove slate-react-placeholder package * remove unused dep * remove unnecessary tests, fix readonly example * convert checklists example * switch to next from webpack * get link example working * convert more examples * preserve keys, memoized leafs/texts, fix node lookup * fix to always useLayoutEffect for ordering * fix annotations to be maps, memoize elements * remove Change interface * remove String interface * rename Node.entries to Node.nodes * remove unnecessary value queries * default to selection when iterating, cleanup * remove unused files * update scroll into view logic * fix undoing, remove constructor types * dont sync selection while composing * add workflows * remove unused deps * convert mentions example * tweaks * convert remaining examples * rename h to jsx, update schema * fix schema tests * fix slate-schema logic and tests * really fix slate-schema and forced-layout example * get start of insertFragment tests working * remove Fragment interface * remove debugger * get all non-skipped tests passing * cleanup deps * run prettier * configure eslint for typescript * more eslint fixes... * more passing * update some docs * fix examples * port windows undo hotkey change * fix deps, add basic firefox support * add event overriding, update walkthroughs * add commands, remove classes, cleanup examples * cleanup rollup config * update tests * rename queries tests * update other tests * update walkthroughs * cleanup interface exports * cleanup, change mark transforms to require location * undo mark transform change * more * fix tests * fix example * update walkthroughs * update docs * update docs * remove annotations * remove value, move selection and children to editor * add migrating doc * fix lint * fix tests * fix DOM types aliasing * add next export * update deps, fix prod build * fix prod build * update scripts * update docs and changelogs * update workflow and pull request template
176 lines
5.6 KiB
JavaScript
176 lines
5.6 KiB
JavaScript
import Prism from 'prismjs'
|
|
import React, { useCallback, useMemo } from 'react'
|
|
import { Slate, Editable, withReact } from 'slate-react'
|
|
import { Text, createEditor } from 'slate'
|
|
import { withHistory } from 'slate-history'
|
|
|
|
// eslint-disable-next-line
|
|
;Prism.languages.markdown=Prism.languages.extend("markup",{}),Prism.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},code:[{pattern:/^(?: {4}|\t).+/m,alias:"keyword"},{pattern:/``.+?``|`[^`\n]+`/,alias:"keyword"}],title:[{pattern:/\w+.*(?:\r?\n|\r)(?:==+|--+)/,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])([\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:/(^|[^\\])(\*\*|__)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^\*\*|^__|\*\*$|__$/}},italic:{pattern:/(^|[^\\])([*_])(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^[*_]|[*_]$/}},url:{pattern:/!?\[[^\]]+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[[^\]\n]*\])/,inside:{variable:{pattern:/(!?\[)[^\]]+(?=\]$)/,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),Prism.languages.markdown.bold.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.italic.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.bold.inside.italic=Prism.util.clone(Prism.languages.markdown.italic),Prism.languages.markdown.italic.inside.bold=Prism.util.clone(Prism.languages.markdown.bold); // prettier-ignore
|
|
|
|
const MarkdownPreviewExample = () => {
|
|
const renderDecoration = useCallback(props => <Decoration {...props} />, [])
|
|
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
|
|
const decorate = useCallback(([node, path]) => {
|
|
const ranges = []
|
|
|
|
if (!Text.isText(node)) {
|
|
return ranges
|
|
}
|
|
|
|
const getLength = token => {
|
|
if (typeof token === 'string') {
|
|
return token.length
|
|
} else if (typeof token.content === 'string') {
|
|
return token.content.length
|
|
} else {
|
|
return token.content.reduce((l, t) => l + getLength(t), 0)
|
|
}
|
|
}
|
|
|
|
const tokens = Prism.tokenize(node.text, Prism.languages.markdown)
|
|
let start = 0
|
|
|
|
for (const token of tokens) {
|
|
const length = getLength(token)
|
|
const end = start + length
|
|
|
|
if (typeof token !== 'string') {
|
|
ranges.push({
|
|
type: token.type,
|
|
anchor: { path, offset: start },
|
|
focus: { path, offset: end },
|
|
})
|
|
}
|
|
|
|
start = end
|
|
}
|
|
|
|
return ranges
|
|
}, [])
|
|
|
|
return (
|
|
<Slate editor={editor} defaultValue={initialValue}>
|
|
<Editable
|
|
decorate={decorate}
|
|
renderDecoration={renderDecoration}
|
|
placeholder="Write some markdown..."
|
|
/>
|
|
</Slate>
|
|
)
|
|
}
|
|
|
|
const Decoration = props => {
|
|
const { children, decoration, attributes } = props
|
|
|
|
switch (decoration.type) {
|
|
case 'bold':
|
|
return <strong {...attributes}>{children}</strong>
|
|
case 'code':
|
|
return <code {...attributes}>{children}</code>
|
|
case 'italic':
|
|
return <em {...attributes}>{children}</em>
|
|
case 'underlined':
|
|
return <u {...attributes}>{children}</u>
|
|
case 'title': {
|
|
return (
|
|
<span
|
|
{...attributes}
|
|
style={{
|
|
fontWeight: 'bold',
|
|
fontSize: '20px',
|
|
margin: '20px 0 10px 0',
|
|
display: 'inline-block',
|
|
}}
|
|
>
|
|
{children}
|
|
</span>
|
|
)
|
|
}
|
|
case 'punctuation': {
|
|
return (
|
|
<span {...attributes} style={{ opacity: 0.2 }}>
|
|
{children}
|
|
</span>
|
|
)
|
|
}
|
|
case 'list': {
|
|
return (
|
|
<span
|
|
{...attributes}
|
|
style={{
|
|
paddingLeft: '10px',
|
|
lineHeight: '10px',
|
|
fontSize: '20px',
|
|
}}
|
|
>
|
|
{children}
|
|
</span>
|
|
)
|
|
}
|
|
case 'hr': {
|
|
return (
|
|
<span
|
|
{...attributes}
|
|
style={{
|
|
borderBottom: '2px solid #000',
|
|
display: 'block',
|
|
opacity: 0.2,
|
|
}}
|
|
>
|
|
{children}
|
|
</span>
|
|
)
|
|
}
|
|
case 'blockquote': {
|
|
return (
|
|
<span
|
|
{...attributes}
|
|
style={{
|
|
borderLeft: '2px solid #ddd',
|
|
display: 'inline-block',
|
|
paddingLeft: '10px',
|
|
color: '#aaa',
|
|
fontStyle: 'italic',
|
|
}}
|
|
>
|
|
{children}
|
|
</span>
|
|
)
|
|
}
|
|
|
|
default: {
|
|
throw new Error(`Unknown markdown decoration type: "${decoration.type}"`)
|
|
}
|
|
}
|
|
}
|
|
|
|
const initialValue = [
|
|
{
|
|
children: [
|
|
{
|
|
text:
|
|
'Slate is flexible enough to add **decorations** that can format text based on its content. For example, this editor has **Markdown** preview decorations on it, to make it _dead_ simple to make an editor with built-in Markdown previewing.',
|
|
marks: [],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: '## Try it out!',
|
|
marks: [],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'Try it out for yourself!',
|
|
marks: [],
|
|
},
|
|
],
|
|
},
|
|
]
|
|
|
|
export default MarkdownPreviewExample
|