Method for using Electron simply a MarkDown editor

MarkDown is a must-have skill of each of our developers. In writing MarkDown, always look for a variety of editors, but each editor can only meet the needs of a certain aspect, but It is not possible to meet the needs of everyday writing.

So I will try my own hands and try to take a MarkDown editor using Electron.

The following Russen, the painful needs of the MARKDOWN editor I have:

    There must be a graphics function, but also directly uploaded to its own picture background, such as seven Bull;
  • The style must be customized;
  • Exported HTML content can be pasted directly into the public account editor, directly publish without formatting;
  • You can customize the fixed module, such as the head of the article, or the tail.
  • You can customize the function, such as: Automatically load random pictures, enrich our article content.
  • must be cross-platform.
  • Other.
  • Environmental construction

Using Electron as a cross-platform development framework, it is the ideal choice, and then, if: vs code, Atom is large The application of 级 is also based on Electron development.


Use JavaScript, HTML, and CSS to build cross-platform desktop applications

I first use electron, we downloaded back to run:

# 示 项目 项目 项目 项目 $ git clone StarT # Enter this warehouse $ cd electron-quick-start # installation dependencies and runs $ npm install && npm start

  VUE is the leader of the current front-end frame, and it is still developed by our people. I am also a loyal fan of Vue. I started using Vue at the 1.0 version of the fire.  

The two is recommended in this article 利用Electron简单撸一个Markdown编辑器的方法 SimulatedGREG / Electron-Vue


mounting the plug-in and runs:

NPM InstallNPM Run DEV

  Selecting a plug-in  
1. Ace Editor

Select a good editor is critical: 利用Electron简单撸一个Markdown编辑器的方法

chairuosen / Vue2-ace-editor: https: / /

npm install buefy vue2-ace-editor vue-massial-design-icons --save 

2. MarkDown-IT 利用Electron简单撸一个Markdown编辑器的方法

Can quickly parse the markdown content, I choose to use the plugin: markdown-it


3. Electron-store

Since it is an editor application, all many personalized settings and content, it is necessary to save local, such as the style file required by the editor, custom head tail content, etc. Here I chose:
  NPM Install Electron-Store - Save  


Everything is ready, let us start to achieve simple MarkDown’s editing and preview feature. SRC

folder structure:
  . ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ rs - AppveYor.yml ├─- build│ └ - iCons│ ├─- 256x256.png│ ├─- icon.icns│ └─- icon.ico ├ - DIST│ ├─ Electron│ │ └── Main .js│ └─- Web ├ - package.json├ - SRC│ ├─ INDEX.EJS│ ├─MAIN│ │ ├─ INDEX.DEV.JS│ │ ├─ INDEX.JS│ │ ├── Mainmenu.js│ │ ├─ Preview-Server.js│ │ └─Renderer.js│ ├─ Renrer│ │ ├──APP .VUE│ │ ├── Assets│ │ │ ├──Cs│ │ │ │ └─ Coding01.css│ │ │ └─Logo.png│ │ ├─ Components│ │ │ ─── EditorPage.Vue│ │ │ └─ Preview.Vue│ │ └ - Main.js│ └─- Store│ ├── Content.js│ └── Store.js ├ - static ── Yarn.lock 

The entire app is mainly divided into two columns of structure, editing the markdown content on the left side, see the effect on the right, and the page view is mainly rendered by renderer, so we first in renderer Create a Vue page under / components /


EditorPage.Vue :


Editing Zone

On the left side of the plug-in:

Require Vue2-ace-editor ‘) , processing real-time listening Editor

Enter the MarkDown content to pass the content.
 WATCH: {INPUT: Function (Newcontent, OldContent) {Messagebus.NewContentTorender (Newcontent);}},   

Messagebus is to put the VUE and IPCRENDERER related logic events main.js :

 Import Vue from 'vue'; import app from './app'; import' buefy / dist / buefy.css'; import util from 'util'; import {ipcrenderer} from 'electron'; if (! Process.env.is_web ) Vue.use (require ( 'vue-electron')) Vue.config.productionTip = falseexport const messageBus = new Vue ({methods: {newContentToRender (newContent) {ipcRenderer.send ( 'newContentToRender', newContent);}, saveCurrentFile () {}}}); // Listen to NewContentTopReView, passed URL2PREVIEW to the NEWCONTENTTOPREVIEW Event // of the Vue, which is transmitted to the Preview component to get IPcRenderer.on ( 'newContentToPreview', (event, url2preview) => {console.log ( `ipcRenderer.on newContentToPreview $ {util.inspect (event)} $ {url2preview}`);. messageBus $ emit ( 'newContentToPreview', URL2PREVIEW);}); / * eslint-disable no-new * / new vue ({Components: {app}, template: ''}). $ mount ('# app') 
The editor's content will be removed from ipcrenderer.send ('newcontenttorender', newcontent); , is
ipcmain.on, by the main process. 'NewContentTorender', Function (Event, Content)
Event is acquired.
A electron application has only one main master process, a lot of localization (such as: local storage, file reading, etc.) more Treatment.
In this case, the first function you want to implement is, “You can customize the fixed module, such as the head of the article, or the tail”

We use a plug-in: Electron-store

, used to store head and tail content, create Class:

Import {app} from ‘electron’ Import Path from ‘Path’Import FS from’FS’Import Estore from ‘electron-store’class content {constructor () {this.estore = new eStore () this.estore.set (‘ headercontent “,`

This article
1 minute
`) this.estore.Set (‘footercontent’,`

Coding01 looks to you continue to pay attention `)} // this will Just Return The Property on The` Data` Object Get (Key, VAL) {Return this.estore.get ('WindowBounds', VAL)} // ... and this will set it set Key, Val) {this.estore.set (key, val)} getContent (Content) {returnTh.HeaderContent + Content + this.footerContent} getHeaderContent () {Return THISTORE.GET ('HeaderContent', '') GetfooterContent () {returnTEN, '')}}} // Expose The ClassexportDEFAULT Content

Note: Here is just a write dead head and tail content.
 With the tail content, and the editor's MarkDown content, we can integrate these content, then output to our right side  Preview  components.  
ipcmain.on (‘NewContentTorender’, Function (Event, Content) {const rendred = renderContent, Content, Csscontent, ‘Layout1.html’) Download Admiral; HETML ‘ const previewURL = newContent (rendered); mainWindow.webContents.send ( ‘newContentToPreview’, previewURL);});

wherein, renderContent (headerContent, footerContent, Content, CSSContent, ‘Layout1.html’)

method is to load our head, tail, markdown content, CSS style and our template


. This is relatively simple, directly watching code:

Import mdit from ‘markdown-it’; import ejs from ‘ejs’; const mditconfig = {HTML: true, / / Enable html tags in SourceXHTMLOUT: TRUE, // Use ‘/’ To Close Single Tags (

) BREAKS: FALSE, // Convert ‘\ n’ in Paragraphs Into // Langprefix: 'Language-', // CSS Language Prefix for fenced blocks linkify: true, // Autoconvert url-like texts to links typographer: false, // Enable smartypants and other sweet transforms // Highlighter function Should return escaped html, // or '' if input not changed highlight:. function (/ * Str, Lang * /) {RETURN '';}}; const md = mdit (mditconfig); const layouts = []; Export Function RenderContent (HeaderContent, FooterContent, Content, Csscontent, Layoutfile) {const text = Md.render (Content); const layout = layouts [layoutfile]; const rendred = EJS.Render (layout, {title: 'page title ", content: text, csscontent: CSSContent,HeaderContent: headerContent: footercontent,}; return rendered;} layouts ['Layout1.html'] = `

  Method for using Electron simply a MarkDown editor插图3 

qrcode `;
Here, the MARKDOWN content is parsed using the plug-in , and then ejs.Render () is used to populate the various positions of the template. Here, it is also for our goals:
style must be customized
and packaged various situations, using different heads, tails, templates, and patterns

When we have content, we also need to put it on “Server”, const previewurl = newcontent (rendered);

  Import http From 'http'; import url from 'url'; var server; var content; export function cretertain () {if (server) throw new error ("Server ALR)Eady Started "); Server = http.createserver (RequestHandler); Server.Listen (0," ");} export function newcontent (text) {content = text; return genurl ('content";} export function currentContent () {return content;} function genurl (pathname) {const url2preview = url.format ({protocol: 'http', hostname: server.address () address, port: server.address () port, pathname:.. Pathname}; Return Url2preview;} Function RequestHandler (Req, Res) {Try {RES.WRITEHEAD (200, {'Content-Type': 'Text / HTML', 'Content-length': content.length}); res .end (content);} catch (err) {RES.WRITEHEAD (500, {'content-type': 'text / plain'}; res. erd (err.stack);}}  

Finally get URL objects, transfer to our right side preview Components, that is, mainwindow.webcontents.send ('newcontettopreview', previewurl);

Note: Communication between main and renderer processes, ipcmain
 And  ipcrenderer 
IPCMAIN Unable to send messages to ipcrenderer . Because ipcmain is only .on () method is not . SEND () . So only WebContents can be used.
The time used on the right is a IFRAME
control, which is specifically made into one component
preview :
Import {Messagebus} from '../main.js'; EXPORT Default {Methods: {Reload (PreviewSrcurl ) {. this $ el.src = previewSrcURL;}}, created: function (.) {messageBus $ on ( 'newContentToPreview', (url2preview) => {console.log ( `newContentToPreview $ {url2preview}`); this. Reload (Url2Preview);});}}
In Preview Components We use Vue Monitor

event, load URL objects in real time.

Messagebus. $ ON (‘NewContentTopReview’, (Url2Preview) => {this.Reload (Url2Preview);});
   We basically realize the most basic version of the MarkDown editor function, 
YARN RUN DEV Running to see the effect:


For the first time, use electron, very superficial, but at least learned: There is only one main process for each electron application, mainly The application window is derived from the system. In the main process, IPCMain listens to events from IPCRenderer, but there is no Send method, only BrowserWindow can only take advantage of BrowserWindow. WebContents.send (). Each page has a corresponding RENDERER process for rendering the page. Of course, there are corresponding IPCRenderer for receiving and sending events. In the Vue page assembly, we still pass and receive messages with Vue’s $ ON and `$ EMIT. Next, improve the application step by step, the goal is to satisfy your own needs, then it is: Maybe it is open. Solving Chinese coding issues
Since we use

iframe , it is necessary to embed

iframe .

Copy code
 code is as follows:   The above is all the content of this article, I hope to everyone I have helpful, I hope everyone will support Tumi Clouds.    The above is all the content of this article, I hope to help everyone, I hope everyone will support Tumi Clouds.                      
© Copyright Notice
Just support it if you like
comment Grab the couch

Please log in to comment