1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-04-21 22:02:05 +02:00

add plaintext example

This commit is contained in:
Ian Storm Taylor 2016-06-17 19:57:37 -07:00
parent 0caee5b687
commit 1413d57a04
11 changed files with 214 additions and 54 deletions

View File

@ -1,6 +1,7 @@
# Binaries.
bin = ./node_modules/.bin
babel = $(bin)/babel
browserify = $(bin)/browserify
standard = $(bin)/standard
mocha = $(bin)/mocha
@ -19,12 +20,21 @@ endif
# Remove the generated files.
clean:
@ rm -rf ./node_modules
@ rm -rf ./dist ./node_modules
# Build the examples.
examples: ./node_modules
# Build the source.
dist: ./node_modules $(shell find ./lib)
@ $(babel) --out-dir ./dist ./lib
@ touch ./dist
# Build the basic example.
example-basic: ./node_modules
@ $(browserify) --debug --transform babelify --outfile ./examples/basic/build.js ./examples/basic/index.js
# Build the plaintext example.
example-plaintext: ./node_modules
@ $(browserify) --debug --transform babelify --outfile ./examples/plaintext/build.js ./examples/plaintext/index.js
# Lint the sources files with Standard JS.
lint: ./node_modules
@ $(standard) ./lib
@ -36,7 +46,7 @@ node_modules: ./package.json
# Build the test source.
test/support/build.js: ./node_modules $(shell find ./lib) ./test/browser.js
@ $(browserify) --transform babelify --outfile ./test/support/build.js ./test/browser.js
@ $(browserify) --debug --transform babelify --outfile ./test/support/build.js ./test/browser.js
# Run the tests.
test: test-browser test-server
@ -49,9 +59,13 @@ test-browser: ./node_modules ./test/support/build.js
test-server: ./node_modules
@ $(mocha) --reporter spec --timeout 5000 ./test/server.js
# Watch the examples.
watch-examples: ./node_modules
@ $(MAKE) examples browserify=$(watchify)
# Watch the basic example.
watch-example-basic: ./node_modules
@ $(MAKE) example-basic browserify=$(watchify)
# Watch the plaintext example.
watch-example-plaintext: ./node_modules
@ $(MAKE) example-plaintext browserify=$(watchify)
# Phony targets.
.PHONY: examples

View File

@ -75,9 +75,6 @@ function renderNode(node) {
)
}
}
default: {
throw new Error(`Unknown node type "${node.type}".`)
}
}
}
@ -88,9 +85,6 @@ function renderMark(mark) {
fontWeight: 'bold'
}
}
default: {
throw new Error(`Unknown mark type "${mark.type}".`)
}
}
}
@ -112,6 +106,7 @@ class App extends React.Component {
state={this.state.state}
onChange={(state) => {
console.log('State:', state.toJS())
console.log('Content:', Raw.serialize(state))
this.setState({ state })
}}
/>

View File

@ -0,0 +1,10 @@
<html>
<head>
<meta charset="utf-8" />
<title>Editor | Basic Example</title>
</head>
<body>
<main></main>
<script src="build.js"></script>
</body>
</html>

View File

@ -0,0 +1,44 @@
import Editor from '../..'
import React from 'react'
import ReactDOM from 'react-dom'
import { Plaintext } from '../..'
/**
* State.
*/
const state = 'A string of plain text.'
/**
* App.
*/
class App extends React.Component {
state = {
state: Plaintext.deserialize(state)
};
render() {
return (
<Editor
state={this.state.state}
onChange={(state) => {
console.log('State:', state.toJS())
console.log('Content:', Plaintext.serialize(state))
this.setState({ state })
}}
/>
)
}
}
/**
* Attach.
*/
const app = <App />
const root = document.body.querySelector('main')
ReactDOM.render(app, root)

View File

@ -46,6 +46,16 @@ class Editor extends React.Component {
this.setState({ plugins })
}
/**
* Get the editor's current `state`.
*
* @return {State} state
*/
getState() {
return this.props.state
}
/**
* When the `state` changes, pass through plugins, then bubble up.
*
@ -65,16 +75,6 @@ class Editor extends React.Component {
this.props.onChange(state)
}
/**
* Get the editor's current `state`.
*
* @return {State} state
*/
getState() {
return this.props.state
}
/**
* When an event by `name` fires, pass it through the plugins, and update the
* state if one of them chooses to.
@ -102,15 +102,47 @@ class Editor extends React.Component {
render() {
return (
<Content
renderMark={this.props.renderMark}
renderNode={this.props.renderNode}
state={this.props.state}
onChange={state => this.onChange(state)}
onKeyDown={e => this.onEvent('onKeyDown', e)}
renderMark={mark => this.renderMark(mark)}
renderNode={node => this.renderNode(node)}
/>
)
}
/**
* Render a `node`, cascading through the plugins.
*
* @param {Node} node
* @return {Component} component
*/
renderNode(node) {
for (const plugin of this.state.plugins) {
if (!plugin.renderNode) continue
const component = plugin.renderNode(node, this.props.state, this)
if (component) return component
throw new Error('No renderer found for node.')
}
}
/**
* Render a `mark`, cascading through the plugins.
*
* @param {Mark} mark
* @return {Object} style
*/
renderMark(mark) {
for (const plugin of this.state.plugins) {
if (!plugin.renderMark) continue
const style = plugin.renderMark(mark, this.props.state, this)
if (style) return style
throw new Error('No renderer found for mark.')
}
}
/**
* Resolve the editor's current plugins from `props` when they change.
*

View File

@ -1,36 +1,24 @@
/**
* Components.
* Editor.
*/
import Editor from './components/editor'
export default Editor
/**
* Models.
*/
import Character from './models/character'
import Node from './models/node'
import Selection from './models/selection'
import State from './models/state'
import Text from './models/text'
export { default as Character } from './models/character'
export { default as Node } from './models/node'
export { default as Selection } from './models/selection'
export { default as State } from './models/state'
export { default as Text } from './models/text'
/**
* Serializers.
*/
import Raw from './serializers/raw'
/**
* Export.
*/
export default Editor
export {
Character,
Node,
Raw,
Selection,
State,
Text
}
export { default as Raw } from './serializers/raw'
export { default as Plaintext } from './serializers/plaintext'

View File

@ -66,9 +66,7 @@ class Node extends NodeRecord {
get text() {
return this
.filterNodes(node => node.type == 'text')
.map(node => node.characters)
.flatten()
.map(character => character.text)
.map(node => node.text)
.join('')
}

View File

@ -459,12 +459,14 @@ class State extends StateRecord {
let { characters } = startNode
// Create a list of the new characters, with the right marks.
const { marks } = characters.get(startOffset)
const marks = characters.has(startOffset)
? characters.get(startOffset).marks
: null
const newCharacters = data.split('').reduce((list, char) => {
return list.push(Character.create({
text: char,
marks
}))
const obj = { text: char }
if (marks) obj.marks = marks
return list.push(Character.create(obj))
}, Character.createList())
// Splice in the new characters.

View File

@ -1,4 +1,5 @@
import React from 'react'
import keycode from 'keycode'
import { IS_WINDOWS, IS_MAC } from '../utils/environment'
@ -62,6 +63,28 @@ export default {
console.log('Unhandled key down.')
}
}
},
/**
* Default `node` renderer.
*
* @param {Node} node
* @return {Component} component
*/
renderNode(node) {
return (props) => <div>{props.children}</div>
},
/**
* Default `mark` renderer.
*
* @param {Mark} mark
* @return {Object} style
*/
renderMark(mark) {
return {}
}
}

View File

@ -0,0 +1,53 @@
import Character from '../models/character'
import Node from '../models/node'
import Text from '../models/text'
import State from '../models/state'
/**
* Serialize a `state` into a plaintext `string`.
*
* @param {State} state
* @return {String} string
*/
function serialize(state) {
return state.nodes
.map(node => node.text)
.join('\n')
}
/**
* Deserialize a plaintext `string` into a `state`.
*
* @param {String} string
* @return {State} state
*/
function deserialize(string) {
const characters = string
.split('')
.reduce((list, char) => {
return list.push(Character.create({ text: char }))
}, Character.createList())
const text = Text.create({ characters })
const texts = Node.createMap([text])
const node = Node.create({
type: 'paragraph',
nodes: texts,
})
const nodes = Node.createMap([node])
const state = State.create({ nodes })
return state
}
/**
* Export.
*/
export default {
serialize,
deserialize
}

View File

@ -13,6 +13,7 @@
"uid": "0.0.2"
},
"devDependencies": {
"babel-cli": "^6.10.1",
"babel-core": "^6.9.1",
"babel-polyfill": "^6.9.1",
"babel-preset-es2015": "^6.9.0",