mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-02-28 18:14:08 +08:00
feat(markdown): Add Markdown composer
This commit is contained in:
parent
d1ba5a3e2b
commit
a8b8359e0c
11 changed files with 191 additions and 0 deletions
26
internal_packages/composer-markdown/README.md
Normal file
26
internal_packages/composer-markdown/README.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
|
||||
# N1 Markdown Composer
|
||||
|
||||
A plugin for N1 that allows you to compose emails using markdown.
|
||||
|
||||

|
||||

|
||||
|
||||
## 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 |
BIN
internal_packages/composer-markdown/icon.png
Normal file
BIN
internal_packages/composer-markdown/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
21
internal_packages/composer-markdown/lib/main.cjsx
Normal file
21
internal_packages/composer-markdown/lib/main.cjsx
Normal 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)
|
|
@ -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
|
72
internal_packages/composer-markdown/lib/markdown-editor.cjsx
Normal file
72
internal_packages/composer-markdown/lib/markdown-editor.cjsx
Normal 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
|
9
internal_packages/composer-markdown/lib/utils.coffee
Normal file
9
internal_packages/composer-markdown/lib/utils.coffee
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
class Utils
|
||||
|
||||
@getTextFromHtml: (html) ->
|
||||
div = document.createElement('div')
|
||||
div.innerHTML = html
|
||||
div.textContent ? div.innerText
|
||||
|
||||
module.exports = Utils
|
25
internal_packages/composer-markdown/package.json
Normal file
25
internal_packages/composer-markdown/package.json
Normal 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"
|
||||
}
|
||||
}
|
16
internal_packages/composer-markdown/stylesheets/index.css
Normal file
16
internal_packages/composer-markdown/stylesheets/index.css
Normal 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;
|
||||
}
|
|
@ -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 = [];
|
||||
|
|
Loading…
Reference in a new issue