Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
This repository was archived by the owner on Mar 29, 2024. It is now read-only.

📝 A medium like Rich Text Editor built on draft-js with a focus on keyboard shortcuts.

License

NotificationsYou must be signed in to change notification settings

brijeshb42/medium-draft

Repository files navigation

Latest development is going on in thisbranch.

medium-draft -demo

npm versionBuild Status

A medium like rich text editor built upondraft-js with an emphasis on eliminating mouse usage by adding relevant keyboard shortcuts.

Documentation in progress.

Install the beta version using

npm install medium-draft@beta

Features

  • Focus on keyboard shortcuts and auto transform of text blocks.
  • Image addition with support for rich text captioning.
  • Minimize mouse usage.
  • Autolists.
  • Proper handling ofRETURN presses.
  • It also has implementations of some custom blocks like:
    • caption - Can be used as a caption for media blocks like image or video instead of nesteddraft-js instances for simplicity.
    • block-quote-caption - Caption forblockquotes.
    • todo - Todo text with a checkbox.
  • Easily customizable toolbar viatoolbarConfig for the following block and inline styles. Defaults to all. Case sensitive.
    • block: ['ordered-list-item', 'unordered-list-item', 'blockquote', 'header-three', 'todo']
    • inline: ['BOLD', 'ITALIC', 'UNDERLINE', 'hyperlink', 'HIGHLIGHT']
Following are the keyboard shortcuts to toggle block types (Alt and CTRL for Windows/Linux andOption and Command for OSX)
  • Alt/Option +

    • 1 - Toggle Ordered list item
    • * - Toggle Unordered list item
    • # - Toggle Header-three.
    • < - Toggle Caption block.
    • > - Toggle unstyled or paragraph block.
    • H - Highlight selection.
Other Shortcuts
  • CMD/CTRL +K -> Add Link
  • CMD/CTRL +SHIFT +K -> Remove link if cursor is inside a word with link.
Editor level commands

These commands are not a part of the core editor but have been implemented in the example code that uses themedium-draft editor.

  • Command/CTRL +S - Save current data tolocalstorage.
  • Alt + Shift +L - Load previously saved data fromlocalstorage.
Special characters while typing: While typing in an empty block, if the content matches one of the following, that particular block's type and look will be changed to the corresponding block specified below
  • -- - If current block isblockquote, it will be changed toblock-quote-caption, elsecaption.
  • *.(An asterisk and a period) -unordered-list-item.
  • *<SPACE>(An asterisk and a space) -unordered-list-item.
  • -<SPACE>(A hyphen and a space) -unordered-list-item.
  • 1.(The number 1 and a period) -unordered-list-item.
  • ## -header-two.
  • [] -todo.
  • == -unstyled.

Installation

  • npm.
    • npm install medium-draft.
    • import Editor from 'medium-draft'
  • Browser
    • Include<link rel="stylesheet" type="text/css" href="https://unpkg.com/medium-draft/dist/medium-draft.css"> in<head>
    • Include<script src="https://unpkg.com/medium-draft/dist/medium-draft.js"></script>.medium-draft is available in the global object asMediumDraft.

Usage

medium-draft sits on top ofdraft-js with some built in functionalities and blocks. Its API is almost the same as that ofdraft-js. You can take a look atthe demo editor's code to see the implementation.

CSS

Include the css that comes with the library in your HTML -

<linkrel="stylesheet"type="text/css"href="https://unpkg.com/medium-draft/dist/medium-draft.css">

If you are usingwebpack for bundling, you can import the CSS like this in your JS code

import'medium-draft/lib/index.css';

If you are usingsideButtons, you will also need to include the css forfont-awesome -

<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">

or something equivalent.

JS (ES6)

At the minimum, you need to provideeditorState andonChange props, the same asdraft-js.

importReactfrom'react';importReactDOMfrom'react-dom';// if using webpack// import 'medium-draft/lib/index.css';import{Editor,createEditorState,}from'medium-draft';classAppextendsReact.Component{constructor(props){super(props);this.state={editorState:createEditorState(),// for empty content};/*    this.state = {      editorState: createEditorState(data), // with content    };    */this.onChange=(editorState)=>{this.setState({ editorState});};this.refsEditor=React.createRef();}componentDidMount(){this.refsEditor.current.focus();}render(){const{ editorState}=this.state;return(<Editorref={this.refsEditor}editorState={editorState}onChange={this.onChange}/>);}};ReactDOM.render(<App/>,document.getElementById('app'));

Customizing side buttons

medium-draft'sEditor accepts a prop calledsideButtons. By default, there is only one (image) button, but you can add more. ThesideButtons prop must be an array of objects with each object having the following signature:

{"title":"unique-button-name","component":ButtonComponent}

For ex:

{"title":"Image","component":ImageSideButton}

Example code:

Right now, the image button simply adds an image inside the editor usingURL.createObjectURL. But if you would like to first upload the image to your server and then add that image to the editor, you can follow one of the 2 methods:

  1. Either extend the defaultImageSideButton component that comes withmedium-draft.

  2. Or create your own component with the complete functionality yourself.

For simplicity, we will follow the first method. If you study theimplementation ofImageSideButton, you will see anonChange method that receives the file chooser event where the seleced files are available asevent.target.files. We will simply override this method as we don't want to customize anything else. Also note that each side button component receivesgetEditorState function (returns the drafteditorState),setEditorState(newEditorState) function (sets the new editorState) andclose function which you need to call manually to close the side buttons list:

importReactfrom'react';import{ImageSideButton,Block,addNewBlock,createEditorState,Editor,}from'medium-draft';import'isomorphic-fetch';classCustomImageSideButtonextendsImageSideButton{/*  We will only check for first file and also whether  it is an image or not.  */onChange(e){constfile=e.target.files[0];if(file.type.indexOf('image/')===0){// This is a post request to server endpoint with image as `image`constformData=newFormData();formData.append('image',file);fetch('/your-server-endpoint',{method:'POST',body:formData,}).then((response)=>{if(response.status===200){// Assuming server responds with// `{ "url": "http://example-cdn.com/image.jpg"}`returnresponse.json().then(data=>{if(data.url){this.props.setEditorState(addNewBlock(this.props.getEditorState(),Block.IMAGE,{src:data.url,}));}});}});}this.props.close();}}// Now pass this component instead of default prop to Editor example above.classAppextendsReact.Component{constructor(props){super(props);this.sideButtons=[{title:'Image',component:CustomImageSideButton,}];this.state={editorState:createEditorState(),// for empty content};/*    this.state = {      editorState: createEditorState(data), // with content    };    */this.onChange=(editorState)=>{this.setState({ editorState});};this.refsEditor=React.createRef()}componentDidMount(){this.refsEditor.current.focus();}render(){const{ editorState}=this.state;return(<Editorref={this.refsEditor}editorState={editorState}onChange={this.onChange}sideButtons={this.sideButtons}/>);}};

Removing side buttons

To remove the side buttons entirely, so that the circular add button never appears, just pass an empty array:

sideButtons={[]}

Customizing toolbar

There are three props you can use to customize the buttons in the toolbar that appears whenever you select text within the editor:

  • blockButtons
  • inlineButtons
  • toolbarConfig

The default block-level editor buttons are['header-three', 'unordered-list-item', 'ordered-list-item', 'blockquote', 'todo'], and the default inline editor buttons['BOLD', 'ITALIC', 'UNDERLINE', 'HIGHLIGHT', 'hyperlink'].

For example, if you want to keep the default block buttons and add a few more, you can do something like the following:

import{BLOCK_BUTTONS}from'medium-draft';constblockButtons=[{label:'H1',style:'header-one',icon:'header',description:'Heading 1',},{label:'H2',style:'header-two',icon:'header',description:'Heading 2',}].concat(BLOCK_BUTTONS);// in your component<EditorblockButtons={blockButtons}.../>

If you want toremove some buttons orreorder them, you could use functions likearray.slice on the defaultBLOCK_BUTTONS andINLINE_BUTTONS, but this is probably more trouble than it's worth.

For this purpose it's better to use thetoolbarConfig prop:

// custom ordering for block and inline buttons, and removes some buttonsconsttoolbarConfig={block:['unordered-list-item','header-one','header-three'],inline:['BOLD','UNDERLINE','hyperlink'],}<EditortoolbarConfig={toolbarConfig}.../>

The strings inside theblock andinline arrays must match thestyle attribute insideblockButtons andinlineButtons arrays.

To summarize: if you need add, remove, and reorder buttons, it's probably easiest to useblockButtons,inlineButtons, andtoolbarConfig together.

Supply Your Own Toolbar

If the toolbar customization props aren't sufficient to get the behavior you want, you can inject your own toolbar with theToolbarComponent prop.

This pattern is calledcomponent injection. YourToolbarComponent receives the same props as the default toolbar.

If you want to write your own toolbar component, a good place to start iswith the default component.

Render data to HTML

The feature to export HTML is available from version0.4.1 onwards.

medium-draft usesdraft-convert (which in turn uses react-dom-server) to renderdraft-js'seditorState to HTML.

The exporter is not a part of the core library. If you want to usemedium-draft-exporter, follow these steps -

Browserify/webpack

  • npm install draft-convert.

draft-convert is part ofpeerDependencies ofmedium-draft.

Code
importmediumDraftExporterfrom'medium-draft/lib/exporter';consteditorState=/* your draft editorState */;constrenderedHTML=mediumDraftExporter(editorState.getCurrentContent());/* Use renderedHTML */

Browser

  • Add the following scripts before your js code.
<scriptsrc="https://unpkg.com/react-dom@15.2.1/dist/react-dom-server.min.js"></script><scriptsrc="https://unpkg.com/draft-convert@1.3.3/dist/draft-convert.min.js"></script><scriptsrc="https://unpkg.com/medium-draft/dist/medium-draft-exporter.js"></script>

The exporter is available asMediumDraftExporter global;

  • JS
varmediumDraftExporter=MediumDraftExporter.default;consteditorState=/* your draft editorState */;constrenderedHTML=mediumDraftExporter(editorState.getCurrentContent());/* Use renderedHTML */

Themedium-draft-exporter also comes with a preset CSS if you want to apply some basic styles to the rendered HTML.

  • In webpack, as part of your rendered HTML's page, use this-

    import'medium-draft/lib/basic.css'
  • In browser, in your rendered html's page, you can include this stylesheet link

    <linkrel="stylesheet"type="text/css"href="https://unpkg.com/medium-draft/dist/basic.css">

Load HTML exported usingmedium-draft-exporter toeditorState

The feature to export HTML is available from version0.5.3 onwards.

medium-draft usesdraft-convert (which in turn uses react-dom-server) to renderdraft-js'seditorState to HTML.

The importer is not a part of the core library. If you want to usemedium-draft-importer, follow these steps -

Browserify/webpack

  • npm install draft-convert.

draft-convert is part ofpeerDependencies ofmedium-draft.

Code
import{convertToRaw}from'draft-js';import{createEditorState}from'medium-draft';importmediumDraftImporterfrom'medium-draft/lib/importer';consthtml=/* your previously exported html */;consteditorState=createEditorState(convertToRaw(mediumDraftImporter(html)));// Use this editorState

Browser

  • Add the following scripts before your js code.
<scriptsrc="https://unpkg.com/react-dom@15.2.1/dist/react-dom-server.min.js"></script><scriptsrc="https://unpkg.com/draft-convert@1.3.3/dist/draft-convert.min.js"></script><scriptsrc="https://unpkg.com/medium-draft/dist/medium-draft-importer.js"></script>

The importer is available asMediumDraftImporter global;

  • JS
const{ convertToRaw}=Draft;const{ createEditorState}=MediumDraft;constmediumDraftImporter=MediumDraftImporter.default;consthtml=/* your previously exported html */;consteditorState=createEditorState(convertToRaw(mediumDraftImporter(html)));// Use this editorState

Issues

  • Write an exporter to export draft data to HTML specifically formedium-draft.
  • Figure out a way to show placeholder text for empty image captions.
  • Currently, the toolbar that appears when text is selected needs to be fixed regarding its position in the viewport.

Developer

  • Clone this repogit clone https://github.com/brijeshb42/medium-draft.git.
  • Install node packagesnpm install react react-dom draft-convert && npm install.
  • Start local demonpm run dev. This will start a local server on port8080.
  • Build usingnpm run build.

LICENSE

MIT

About

📝 A medium like Rich Text Editor built on draft-js with a focus on keyboard shortcuts.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp