diff --git a/site/examples/code-highlighting.js b/site/examples/code-highlighting.js new file mode 100644 index 000000000..e02c983bf --- /dev/null +++ b/site/examples/code-highlighting.js @@ -0,0 +1,237 @@ +import Prism from 'prismjs' +import 'prismjs/components/prism-python' +import 'prismjs/components/prism-php' +import 'prismjs/components/prism-sql' +import 'prismjs/components/prism-java' +import React, { useState, useCallback, useMemo } from 'react' +import { Slate, Editable, withReact } from 'slate-react' +import { Text, createEditor } from 'slate' +import { withHistory } from 'slate-history' +import { css } from 'emotion' + +const CodeHighlightingExample = () => { + const [value, setValue] = useState(initialValue) + const [language, setLanguage] = useState('html') + const renderLeaf = useCallback(props => , []) + const editor = useMemo(() => withHistory(withReact(createEditor())), []) + + // decorate function depends on the language selected + const decorate = useCallback( + ([node, path]) => { + const ranges = [] + if (!Text.isText(node)) { + return ranges + } + const tokens = Prism.tokenize(node.text, Prism.languages[language]) + let start = 0 + + for (const token of tokens) { + const length = getLength(token) + const end = start + length + + if (typeof token !== 'string') { + ranges.push({ + [token.type]: true, + anchor: { path, offset: start }, + focus: { path, offset: end }, + }) + } + + start = end + } + + return ranges + }, + [language] + ) + + return ( + setValue(value)}> +
+

+ Select a language + +

+
+ +
+ ) +} + +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) + } +} + +// different token types, styles found on Prismjs website +const Leaf = ({ attributes, children, leaf }) => { + return ( + + {children} + + ) +} + +const initialValue = [ + { + children: [ + { + text: '

Hi!

', + }, + ], + }, +] + +// modifications and additions to prism library + +Prism.languages.python = Prism.languages.extend('python', {}) +Prism.languages.insertBefore('python', 'prolog', { + comment: { pattern: /##[^\n]*/, alias: 'comment' }, +}) +Prism.languages.javascript = Prism.languages.extend('javascript', {}) +Prism.languages.insertBefore('javascript', 'prolog', { + comment: { pattern: /\/\/[^\n]*/, alias: 'comment' }, +}) +Prism.languages.html = Prism.languages.extend('html', {}) +Prism.languages.insertBefore('html', 'prolog', { + comment: { pattern: //, alias: 'comment' }, +}) +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 + +export default CodeHighlightingExample diff --git a/site/pages/examples/[example].js b/site/pages/examples/[example].js index 46bf13acb..b6558cad8 100644 --- a/site/pages/examples/[example].js +++ b/site/pages/examples/[example].js @@ -24,6 +24,7 @@ import PlainText from '../../examples/plaintext' import ReadOnly from '../../examples/read-only' import RichText from '../../examples/richtext' import SearchHighlighting from '../../examples/search-highlighting' +import CodeHighlighting from '../../examples/code-highlighting' import Tables from '../../examples/tables' const EXAMPLES = [ @@ -43,6 +44,7 @@ const EXAMPLES = [ ['Read-only', ReadOnly, 'read-only'], ['Rich Text', RichText, 'richtext'], ['Search Highlighting', SearchHighlighting, 'search-highlighting'], + ['Code Highlighting', CodeHighlighting, 'code-highlighting'], ['Tables', Tables, 'tables'], ]