diff --git a/.eslintrc.json b/.eslintrc.json index 496db96f..20b56e74 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -8,7 +8,8 @@ "no-underscore-dangle": [0], "react/jsx-filename-extension": [0, { "extensions": [".js", ".jsx"] }], "new-cap": [0], - "react/require-extension": "off" + "react/require-extension": "off", + "max-len": [0] }, "globals": { "describe": true, diff --git a/index.html b/index.html index 050f5eb2..e4f9c83f 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ Editor - + + + +
Waiting for content
+ + + + + + diff --git a/src/basic.scss b/src/basic.scss new file mode 100644 index 00000000..99ebc6e3 --- /dev/null +++ b/src/basic.scss @@ -0,0 +1,119 @@ +.md-block-header-one { + font-size: 2em; +} +.md-block-header-two { + font-size: 1.7em; +} +.md-block-header-three { + font-size: 1.3em; +} +.md-block-header-four { + font-size: 1em; +} +.md-block-header-five { + font-size: 0.8em; +} +.md-block-header-six { + font-size: 0.7em; +} + +.md-block-header-one, +.md-block-header-two, +.md-block-header-three, +.md-block-header-four, +.md-block-header-five, +.md-block-header-six { + margin-bottom: 5px; +} + +.md-block-blockquote { + margin: 0; + padding-left: 15px; + border-left: 5px solid #4CA8DE; + padding: 10px 0 10px 20px; + background-color: #E2F2FF; + font-size: 1.1em; +} + +.md-block-image { + margin: 0 0 10px 0; + + img { + width: 100%; + } + + figcaption { + text-align: center; + font-size: 0.9em; + } +} + +.md-block-todo { + margin: 10px 0 10px 0; + + input[type=checkbox] { + float: left; + position: relative; + top: 4px; + left: -4px; + } + p { + margin-left: 18px; + } +} + +.md-block-unordered-list-item, .md-block-ordered-list-item { + padding-left: 20px; + + li { + margin-bottom: 5px; + } +} + +.md-inline-code { + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 4px 0px; + font-size: 0.9em; + padding: 1px 3px; + color: rgb(85, 85, 85); + background-color: rgb(252, 252, 252); + border-width: 1px; + border-style: solid; + border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(187, 187, 187); + border-image: initial; + border-radius: 3px; + box-shadow: rgb(187, 187, 187) 0px -1px 0px inset; +} + + +.md-inline-link { + color: #08c; + + &:visited { + color: #08c; + } +} + +.md-inline-highlight { + background: yellow; +} + +p { + &.md-block-block-quote-caption { + + &::before { + content: '\2013'; + color: #999; + float: left; + font-weight: bold; + display: inline; + margin-right: 10px; + } + margin-top: 0; + font-size: 0.8em; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + background: #fafafa; + } +} diff --git a/src/example.js b/src/example.js index 473c77b2..8ecab06a 100644 --- a/src/example.js +++ b/src/example.js @@ -40,6 +40,13 @@ import { NOT_HANDLED } from './index'; +import { + setRenderOptions, + blockToHTML, + entityToHTML, + styleToHTML, +} from './exporter'; + const newTypeMap = StringToTypeMap; newTypeMap['2.'] = Block.OL; @@ -55,6 +62,38 @@ const DQUOTE_END = '”'; const SQUOTE_START = '‘'; const SQUOTE_END = '’'; +const newBlockToHTML = (block) => { + const blockType = block.type; + if (block.type === Block.ATOMIC) { + if (block.text === 'E') { + return { + start: '
', + end: '
', + }; + } else if (block.text === '-') { + return
; + } + } + return blockToHTML(block); +}; + +const newEntityToHTML = (entity, originalText) => { + if (entity.type === 'embed') { + return ( +
+ Embedded ― {entity.data.url} + +
+ ); + } + return entityToHTML(entity, originalText); +}; + const handleBeforeInput = (editorState, str, onChange) => { if (str === '"' || str === '\'') { const currentBlock = getCurrentBlock(editorState); @@ -275,6 +314,12 @@ class App extends React.Component { component: SeparatorSideButton, }]; + this.exporter = setRenderOptions({ + styleToHTML, + blockToHTML: newBlockToHTML, + entityToHTML: newEntityToHTML, + }); + this.getEditorState = () => this.state.editorState; this.logData = this.logData.bind(this); @@ -376,10 +421,15 @@ class App extends React.Component { } logData(e) { - const es = convertToRaw(this.state.editorState.getCurrentContent()); + const currentContent = this.state.editorState.getCurrentContent(); + const es = convertToRaw(currentContent); console.log(es); console.log(this.state.editorState.getSelection().toJS()); window.ga('send', 'event', 'draftjs', 'log-data'); + let eHTML = this.exporter(currentContent); + var newWin = open('/rendered.html','windowName','height=600,width=600'); + setTimeout(() => newWin.postMessage(eHTML, window.location.origin), 2000); + window.newWin = newWin; } loadSavedData() { diff --git a/src/exporter.js b/src/exporter.js new file mode 100644 index 00000000..3ad6392d --- /dev/null +++ b/src/exporter.js @@ -0,0 +1,128 @@ +import React from 'react'; +import { convertToHTML } from 'draft-convert'; + +import { Inline, Block, Entity } from './util/constants'; + +export const styleToHTML = (style) => { + switch (style) { + case Inline.ITALIC: + return ; + case Inline.BOLD: + return ; + case Inline.STRIKETHROUGH: + return ; + case Inline.UNDERLINE: + return ; + case Inline.HIGHLIGHT: + return ; + case Inline.CODE: + return ; + default: + return null; + } +}; + +export const blockToHTML = (block) => { + const blockType = block.type; + switch (blockType) { + case Block.H1: + // eslint-disable-next-line jsx-a11y/heading-has-content + return

; + case Block.H2: + // eslint-disable-next-line jsx-a11y/heading-has-content + return

; + case Block.H3: + // eslint-disable-next-line jsx-a11y/heading-has-content + return

; + case Block.H4: + // eslint-disable-next-line jsx-a11y/heading-has-content + return

; + case Block.H5: + // eslint-disable-next-line jsx-a11y/heading-has-content + return

; + case Block.H6: + // eslint-disable-next-line jsx-a11y/heading-has-content + return
; + case Block.BLOCKQUOTE_CAPTION: + case Block.CAPTION: + return { + start: `

`, + end: '

', + }; + case Block.IMAGE: { + const imgData = block.data; + const text = block.text; + const extraClass = (text.length > 0 ? ' md-block-image-has-caption' : ''); + return { + start: `
${block.text}
`, + end: '
', + }; + } + case Block.ATOMIC: + return { + start: `
`, + end: '
', + }; + case Block.TODO: { + const checked = block.data.checked || false; + let inp = ''; + let containerClass = ''; + if (checked) { + inp = ''; + containerClass = 'md-block-todo-checked'; + } else { + inp = ''; + containerClass = 'md-block-todo-unchecked'; + } + return { + start: `
${inp}

`, + end: '

', + }; + } + case Block.BREAK: + return
; + case Block.BLOCKQUOTE: + return
; + case Block.OL: + return { + element:
  • , + nest:
      , + }; + case Block.UL: + return { + element:
    1. , + nest:
        , + }; + case Block.UNSTYLED: + return

        ; + default: return null; + } +}; + + +export const entityToHTML = (entity, originalText) => { + if (entity.type === Entity.LINK) { + return ( + + {originalText} + + ); + } + return originalText; +}; + +export const options = { + styleToHTML, + blockToHTML, + entityToHTML, +}; + +export const setRenderOptions = (htmlOptions = options) => convertToHTML(htmlOptions); + + +export default (contentState, htmlOptions = options) => convertToHTML(htmlOptions)(contentState); diff --git a/webpack.config.js b/webpack.config.js index 89b02c18..ba9dd790 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -66,13 +66,11 @@ function getPlugins(env) { plugins.push(new ExtractTextPlugin('[name].css')); // plugins.push(new ExtractTextPlugin(isDev ? '[name].css' : '[name].[hash].css')); plugins.push(hashJsonPlugin); - plugins.push(new webpack.optimize.DedupePlugin()); plugins.push(new webpack.optimize.UglifyJsPlugin({ - output: {comments: false}, - compress: { - warnings: false, - dead_code: true, - }, + sourceMap: false, + output: { comments: false }, + debug: false, + compress: { warnings: false, dead_code: true } })); plugins.push(bannerPlugin); } @@ -91,16 +89,13 @@ function getEntry(env) { 'immutable', 'draft-js', ] - // entries.push('webpack-dev-server/client?http://localhost:8080/'); - // entries.push('webpack/hot/only-dev-server'); entries.push('./index'); } else { entries = ['./index']; } - // entries.push('babel-polyfill'); - entry['medium-draft'] = entries; entry.example = './example'; + entry['basic'] = './basic.scss'; return entry; } @@ -113,12 +108,12 @@ function getLoaders(env) { exclude: /node_modules/ }); - loaders.push({ - test: /\.jsx?$/, - loaders: 'eslint-loader', - enforce: "pre", - include: APP_DIR, - }); + // loaders.push({ + // test: /\.jsx?$/, + // loaders: 'eslint-loader', + // enforce: "pre", + // include: APP_DIR, + // }); loaders.push({ test: /\.(jpe?g|png|gif|svg)$/i, @@ -168,7 +163,11 @@ var options = { 'node_modules' ], extensions: ['.js', '.jsx'], - } + }, + devServer: { + historyApiFallback: false, + noInfo: false, + }, }; if (isProd) {