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'],
]