Skip to content
This repository has been archived by the owner on Jul 14, 2021. It is now read-only.

Commit

Permalink
🚧 Add WIP AutoURL functionality
Browse files Browse the repository at this point in the history
Currently still contains a bug, see enzoferey/slate-instant-replace#1.

Add is-url as dependency
Add slate-instant-replace as dependency
  • Loading branch information
flowirtz committed Aug 3, 2018
1 parent acf3dc8 commit c80cb6e
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 2 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
"dependencies": {
"immutable": "^3.8.2",
"is-hotkey": "^0.1.2",
"is-url": "^1.2.4",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-scripts": "1.1.4",
"slate": "^0.36.1",
"slate-instant-replace": "^0.1.7",
"slate-react": "^0.14.2"
},
"scripts": {
Expand Down
6 changes: 4 additions & 2 deletions src/Editor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { Editor as SlateEditor } from 'slate-react'
import { Value } from 'slate'

import DocumentViewer from './dev-document-viewer/DocumentViewer'

import CodeBlockPlugin from './plugins/code-block'
import AutoURL from './plugins/auto-url'

const initialValue = Value.fromJSON({
document: {
Expand Down Expand Up @@ -33,9 +35,9 @@ const initialValue = Value.fromJSON({
value: initialValue,
}

const code = CodeBlockPlugin()
this.plugins = [
...code.plugins
...CodeBlockPlugin().plugins,
...AutoURL().plugins,
]
}

Expand Down
59 changes: 59 additions & 0 deletions src/plugins/auto-url/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react'

import InstantReplace from 'slate-instant-replace'
import isUrl from 'is-url'

export default function AutoURL(options) {
return {
changes: {},
helpers: {},
components: {},
plugins: [
InstantReplace(AddURL),
RenderLinkNode
],
}
}

const wrapLink = (change, href) => {
change.wrapInline({
type: 'link',
data: { href }
})
change.collapseToEnd()
}

const unwrapLink = (change) => {
change.unwrapInline('link')
}

const AddURL = (change, lastWord) => {
if(isUrl(lastWord)) {
change.extend(-lastWord.length)
change.focus()

change.call(unwrapLink)

const href = lastWord.startsWith('http') ? lastWord : `https://${lastWord}`;

change.call(wrapLink, href)
}
}

function LinkNode(props) {
const { attributes, children, node } = props
const { data } = node
const href = data.get('href')

return (
<a { ...attributes } href={href}>
{ children }
</a>
)
}

const RenderLinkNode = {
renderNode(props) {
return props.node.type === 'link' ? <LinkNode {...props} /> : null
}
}
85 changes: 85 additions & 0 deletions src/removeMe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Inline } from "slate";

export const isPrintableChar = event => event.key.length === 1;

export const isCtrlOrCmd = event => event.ctrlKey || event.metaKey;

const isSpace = event => event.key === " ";

const getSelection = change => change.value.fragment.text;

const getLastWordRec = (change, maxIndex, counter = 0) => {
// If first char of the input is found just select everything (single word)
// console.log(`counter ${counter} and maxi ${maxIndex}`)
console.log(`start: ${change.value.selection.startKey} and end ${change.value.selection.endKey}`)
console.log(`counter is ${counter} and maxi ${maxIndex}`)
// alert()
if (counter === maxIndex) {
console.log('I AM IN')
const selectedWord = getSelection(change);
change.extend(counter);
console.log(`extended by ${counter}`)
return selectedWord;
}

// Move selection
const selectedWord = getSelection(change.extend(-1));

// Exit condition
if (selectedWord[0] === " ") {
change.extend(counter + 1); // one more needed because space
return selectedWord.substring(1);
}

return getLastWordRec(change, maxIndex, counter + 1);
};

export const getLastWord = change => {
const offsetCurrentWord = change.value.focusOffset;
return getLastWordRec(change, offsetCurrentWord);
};

const getPreviousNode = change => {
const block = change.value.focusBlock;
const activeKey = change.value.selection.focusKey;
return block.getPreviousSibling(activeKey);
};

export const focusPreviousNode = change => {
const offsetCurrentWord = change.value.focusOffset;
// check if we just started a the node
if (offsetCurrentWord === 0) {
const previousNode = getPreviousNode(change);
if (previousNode && Inline.isInline(previousNode)) {
change.extendToEndOf(previousNode).focus();
}
}
};

const InstantReplace = transforms => ({
onKeyDown(event, change) {
if (!isPrintableChar(event)) return;

// needed to handle space & control + key actions by default
if (!isCtrlOrCmd(event)) {
if (!isSpace(event)) focusPreviousNode(change);
change.insertText(event.key);

// Apply transforms
if (Array.isArray(transforms)) {
transforms.forEach(transform => {
const lastWord = getLastWord(change);
transform(change, lastWord);
});
} else if (transforms) {
const lastWord = getLastWord(change);
transforms(change, lastWord);
}

// Prevent insertion of the char
event.preventDefault();
}
}
});

export default InstantReplace;
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3663,6 +3663,10 @@ is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"

is-url@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52"

is-utf8@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
Expand Down Expand Up @@ -6188,6 +6192,10 @@ slate-hotkeys@^0.1.3:
is-hotkey "^0.1.1"
slate-dev-environment "^0.1.3"

slate-instant-replace@^0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/slate-instant-replace/-/slate-instant-replace-0.1.7.tgz#f5361aeda7a0a134d60e2ee245ea1f8922f846be"

slate-plain-serializer@^0.5.25:
version "0.5.25"
resolved "https://registry.yarnpkg.com/slate-plain-serializer/-/slate-plain-serializer-0.5.25.tgz#e5b29e5fbb2c461bc0990b8dc7164a997f3ec5b8"
Expand Down

0 comments on commit c80cb6e

Please sign in to comment.