emotion是什么?
在4.2K星级,Emotion是一个高性能且灵活的CSS-in-JS库,允许您使用字符串或对象样式设置应用程序样式。它具有可预测的组合,以避免CSS的特殊性问题。基于glam 库及其理念,我们的想法是通过使用babel和PostCSS解析样式来编写CSS时保持运行时性能。核心运行时为2.3kb,React支持为4kb。
copy from 掘金
slate文档源码
import { Editor, getEventTransfer } from 'slate-react'
import { Block, Value } from 'slate'
import React from 'react'
import initialValueAsJson from './value.json'
import imageExtensions from 'image-extensions'
import isUrl from 'is-url'
import { css } from 'emotion'
import { Button, Icon, Toolbar } from '../components'
/**
* Deserialize the initial editor value.
*
* @type {Object}
*/
const initialValue = Value.fromJSON(initialValueAsJson)
/**
* A function to determine whether a URL has an image extension.
*
* @param {String} url
* @return {Boolean}
*/
function isImage(url) {
return imageExtensions.includes(getExtension(url))
}
/**
* Get the extension of the URL, using the URL API.
*
* @param {String} url
* @return {String}
*/
function getExtension(url) {
return new URL(url).pathname.split('.').pop()
}
/**
* A change function to standardize inserting images.
*
* @param {Editor} editor
* @param {String} src
* @param {Range} target
*/
function insertImage(editor, src, target) {
if (target) {
editor.select(target)
}
editor.insertBlock({
type: 'image',
data: { src },
})
}
/**
* The editor's schema.
*
* @type {Object}
*/
const schema = {
document: {
last: { type: 'paragraph' },
normalize: (editor, { code, node, child }) => {
switch (code) {
case 'last_child_type_invalid': {
const paragraph = Block.create('paragraph')
return editor.insertNodeByKey(node.key, node.nodes.size, paragraph)
}
}
},
},
blocks: {
image: {
isVoid: true,
},
},
}
/**
* The images example.
*
* @type {Component}
*/
class Images extends React.Component {
/**
* Store a reference to the `editor`.
*
* @param {Editor} editor
*/
ref = editor => {
this.editor = editor
}
/**
* Render the app.
*
* @return {Element} element
*/
render() {
return (
<div>
<Toolbar>
<Button onMouseDown={this.onClickImage}>
<Icon>image</Icon>
</Button>
</Toolbar>
<Editor
placeholder="Enter some text..."
ref={this.ref}
defaultValue={initialValue}
schema={schema}
onDrop={this.onDropOrPaste}
onPaste={this.onDropOrPaste}
renderBlock={this.renderBlock}
/>
</div>
)
}
/**
* Render a Slate block.
*
* @param {Object} props
* @return {Element}
*/
renderBlock = (props, editor, next) => {
const { attributes, node, isFocused } = props
switch (node.type) {
case 'image': {
const src = node.data.get('src')
return (
<img
{...attributes}
src={src}
className={css`
display: block;
max-width: 100%;
max-height: 20em;
box-shadow: ${isFocused ? '0 0 0 2px blue;' : 'none'};
`}
/>
)
}
default: {
return next()
}
}
}
/**
* On clicking the image button, prompt for an image and insert it.
*
* @param {Event} event
*/
onClickImage = event => {
event.preventDefault()
const src = window.prompt('Enter the URL of the image:')
if (!src) return
this.editor.command(insertImage, src)
}
/**
* On drop, insert the image wherever it is dropped.
*
* @param {Event} event
* @param {Editor} editor
* @param {Function} next
*/
onDropOrPaste = (event, editor, next) => {
const target = editor.findEventRange(event)
if (!target && event.type === 'drop') return next()
const transfer = getEventTransfer(event)
const { type, text, files } = transfer
if (type === 'files') {
for (const file of files) {
const reader = new FileReader()
const [mime] = file.type.split('/')
if (mime !== 'image') continue
reader.addEventListener('load', () => {
editor.command(insertImage, reader.result, target)
})
reader.readAsDataURL(file)
}
return
}
if (type === 'text') {
if (!isUrl(text)) return next()
if (!isImage(text)) return next()
editor.command(insertImage, text, target)
return
}
next()
}
}
/**
* Export.
*/
export default Images
网友评论