feat(markdown): Add Markdown composer

This commit is contained in:
Jackie Luo 2016-08-30 19:23:01 -07:00
parent d1ba5a3e2b
commit a8b8359e0c
11 changed files with 191 additions and 0 deletions

View file

@ -0,0 +1,26 @@
# N1 Markdown Composer
A plugin for N1 that allows you to compose emails using markdown.
![Markdown Screenshot Editor](/assets/markdown_screenshot_edit.png?raw=true "Markdown Composer Editor")
![Markdown Screenshot Preview](/assets/markdown_screenshot_preview.png?raw=true "Markdown Composer Preview")
## Install this plugin:
1. Download and run N1
2. Clone this repository (Make sure you have `git` installed and available in
your system path)
3. From the menu, select `Developer > Install a Package Manually...`
From the dialog, choose the directory of this plugin to install it!
> When you install packages, they're moved to `~/.nylas/packages`,
> and N1 runs `apm install` on the command line to fetch dependencies
> listed in the package's `package.json`
## Usage
Just write emails using markdown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,21 @@
# Markdown Editor
# Last Revised: April 23, 2015 by Ben Gotow
#
# Markdown editor is a simple React component that allows you to type your
# emails in markdown and see the live preview of your email in html
#
{ExtensionRegistry, ComponentRegistry} = require 'nylas-exports'
MarkdownEditor = require './markdown-editor'
MarkdownComposerExtension = require './markdown-composer-extension'
module.exports =
activate: ->
ComponentRegistry.register MarkdownEditor,
role: 'Composer:Editor'
ExtensionRegistry.Composer.register(MarkdownComposerExtension)
serialize: ->
deactivate: ->
ComponentRegistry.unregister(MarkdownEditor)
ExtensionRegistry.Composer.unregister(MarkdownComposerExtension)

View file

@ -0,0 +1,21 @@
marked = require 'marked'
Utils = require './utils'
{ComposerExtension} = require 'nylas-exports'
rawBodies = {}
class MarkdownComposerExtension extends ComposerExtension
@applyTransformsToDraft: ({draft}) ->
nextDraft = draft.clone()
rawBodies[draft.clientId] = nextDraft.body
nextDraft.body = marked(Utils.getTextFromHtml(draft.body))
return nextDraft
@unapplyTransformsToDraft: ({draft}) ->
nextDraft = draft.clone()
nextDraft.body = rawBodies[nextDraft.clientId] ? nextDraft.body
return nextDraft
module.exports = MarkdownComposerExtension

View file

@ -0,0 +1,72 @@
Utils = require './utils'
SimpleMDE = require 'simplemde'
nylas = require 'nylas-exports'
React = nylas.React
ReactDOM = nylas.ReactDOM
# Keep a file-scope variable containing the contents of the markdown stylesheet.
# This will be embedded in the markdown preview iFrame, as well as the email body.
# The stylesheet is loaded when a preview component is first mounted.
markdownStylesheet = null
class MarkdownEditor extends React.Component
@displayName: 'MarkdownEditor'
@propTypes:
body: React.PropTypes.string.isRequired,
onBodyChanged: React.PropTypes.func.isRequired,
componentDidMount: =>
textarea = ReactDOM.findDOMNode(@refs.textarea)
@mde = new SimpleMDE(
element: textarea,
hideIcons: ['fullscreen', 'side-by-side']
showIcons: ['code', 'table']
)
@mde.codemirror.on "change", @_onBodyChanged
@mde.value(Utils.getTextFromHtml(@props.body))
componentWillReceiveProps: (newProps) =>
currentText = Utils.getTextFromHtml(@props.body)
if @props.body isnt newProps.body and currentText.length is 0
@mde.value(Utils.getTextFromHtml(newProps.body))
@mde.codemirror.execCommand('goDocEnd')
focus: =>
@mde.codemirror.focus()
@mde.codemirror.execCommand('goDocEnd')
focusAbsoluteEnd: =>
@focus()
getCurrentSelection: ->
getPreviousSelection: ->
setSelection: ->
_onDOMMutated: ->
_onBodyChanged: =>
setImmediate =>
@props.onBodyChanged(target: {value: @mde.value()})
render: ->
# TODO sorry
# Add style tag to disable incompatible plugins
<div className="markdown-editor">
<style>
{".btn-mail-merge { display:none; }"}
{".btn-emoji { display:none; }"}
{".btn-templates { display:none; }"}
{".btn-scheduler { display:none; }"}
{".btn-translate { display:none; }"}
{".signature-button-dropdown { display:none; }"}
</style>
<textarea
ref="textarea"
className="editing-region"
/>
</div>
module.exports = MarkdownEditor

View file

@ -0,0 +1,9 @@
class Utils
@getTextFromHtml: (html) ->
div = document.createElement('div')
div.innerHTML = html
div.textContent ? div.innerText
module.exports = Utils

View file

@ -0,0 +1,25 @@
{
"name": "composer-markdown",
"version": "0.1.0",
"main": "./lib/main",
"title": "Markdown (Experimental)",
"description": "Write emails using Markdown!",
"license": "GPL-3.0",
"icon": "./icon.png",
"engines": {
"nylas": "*"
},
"isOptional": true,
"repository": {
"type": "git",
"url": ""
},
"windowTypes": {
"default": true,
"composer": true
},
"dependencies": {
"marked": "^0.3",
"simplemde": "^1.11.2"
}
}

View file

@ -0,0 +1,16 @@
@import "../internal_packages/composer-markdown/node_modules/simplemde/dist/simplemde.min.css";
.markdown-editor {
padding-top: 10px;
}
.CodeMirror {
height: 300px;
}
.CodeMirror-sided {
display: inline-block;
}
.editor-preview-side.editor-preview-active-side {
position: static;
display: inline-block;
height: 300px;
}

View file

@ -89,6 +89,7 @@ export default class Application extends EventEmitter {
'N1-Phishing-Detection': 'phishing-detection',
'N1-Github-Contact-Card-Section': 'github-contact-card',
'N1-Keybase': 'keybase',
'N1-Markdown': 'composer-markdown',
}
const exampleOldNames = Object.keys(exampleNewNames);
let examplesEnabled = [];