Node Webkit入門創建一個簡單Markdown編輯器

桌面應用程序已經消亡?如果從Node-Webkit項目在Github上的Star數量來看的話,結果並不是那麼悲觀。雖然現在越來越多的程序是在雲上部署,還是有很多的工作需要在我們本地的電腦上完成,類似文本編輯工具,Markdown編輯器,遊戲等等,都還需要離線狀態下運行。

之前我就說過,我個人非常的喜歡Markdown標記語言,如果能在本地實現一個簡單的Markdown編輯器的話,應該也是一件不錯的事情。本文將簡單的介紹一些Node Webkit的基礎知識,我們將基於Windows進行演示,但是可以非常簡單的部署到別的系統中。

Node Webkit入門創建一個簡單Markdown編輯器

什麼是Node WebKit

Node Webkit是Chromium的一個分離版本,Chromium是著名的Google Chrome瀏覽器的開源基礎(The open source base of Google Chome)。使用NW,我們可以使用最常見的HTML,CSS和JavaScript來創建可以運行中Windows,Max OSX,Linux桌面上的應用程序。也許,你可以使用HTML,CSS,JavaScript來創建強大的Web應用程序,但是,如果我們想對系統層面進行操作,比喻說修改系統上的某一個文件,目前你無法實現。使用NW,可以很方便實現上面的任務,這也是NW強大的部分,因為NW使用了Node.js,依賴NodeJS的模塊,比喻說,fs(對系統中的文件進行操作的模塊)和request(實現對各種Web Service的請求,而不需要考慮跨域的問題),基於對模塊的實用,你可以實現很多之前無法完成對任務。還有振奮人心的是,你甚至可以實用很多的本地數據庫的操作(NodeJS已經包含了很多對數據庫進行操作的模塊,比喻說MySQL),而且,因為它是分離的Chromium,所以也是支持localStorage和sessionStorage的,可以非常簡單的實現持久化。

開始做點正事吧

移步到Node Webkit Github主頁,根據你自己的系統下載NW。本文中,我將使用Windows(X64)版本,NodeJS已經中NW中包含了,但是如果你本地已經安裝了NodeJS了的話,也是沒有問題到,你也可以繼續實用npm命令來安裝依賴包。

zip文件下載後,解壓,然後創建一個

package.json 文件,這個文件中需要包含你對應用程序的相關的配置,例如:版本,名字,需要安裝的模塊,Webkit的工作欄是否該顯示等信息,下面是我的文件的內容。

{ "name": "markdown_editor", "main": "./html/index.html", "window": { "toolbar": true, "show": true, "icon": "./img/icon.png"

}, "dependencies": { "marked": "^0.3.3"

}

}

  • name: 應用程序的名字,這個名字不能帶空格。

  • main:應用程序啟動後,需要加載的HTML文件。

  • window:Webkit窗口的對象信息

    • toolbar:定義Webkit的工具欄是否該顯示,工具欄包含一個刷新按鈕,一個地址欄,一個可以打開Chromium 開發者工具的按鈕。

    • show:打開應用程序後,窗口是否該打開。某些場景下,不需要打開窗口程序,比喻說,你只想讓程序運行為一個系統托盤圖標。

    • icon:窗口圖標。

  • dependencies:依賴的NodeJS模塊

package.json可以包含更多的選項,你可以參考下面的鏈接。

在項目的根目錄下,我創建了4個文件夾:css,html,js和img,當然,你已經明白這4個文件夾代表的含義,

Node Webkit入門創建一個簡單Markdown編輯器

在img文件中,我增加了一個名字為'icon.png'的圖片(如上面的package.json描述對應)。下面,你可以看到其他2個文件的代碼塊

html/index.html

<title>Markdown Editor/<title>

<link>

<textarea>

css/screen.css

html, body{ height:98%;

}body{ font-family:Arial;

}a{ text-decoration:none !important;

}.md_editor{ float:left; width:50%; height:100%; resize:none; padding:0; margin:0;

}.md_result{ float:left; width:49%; box-sizing:border-box; padding:10px 10px 13px 10px; margin:0; height:100%; overflow-y:scroll;

}

你可以創建js/main.js(內容會在下面逐漸完善)。

上面的操作是一個最簡單的配置,目前這個程序還看到任何的有用的功能,如果你點擊"nw.exe",package.json會被讀取,程序會解析到應該首先加載"index.html",截止目前,頁面中只會包含一個文本編輯器(text editor)和位於右邊的一個空的div,接下來,我們會完善左邊的編輯器,讓它包含一個Markdown 標記語言編輯器,然後對應的HTML展現中右邊的div中。

增加Markdown解析器

在這一節中,我們首先要增加的是一個Markdown解析器,利用這個解析器,當你在左邊輸入內容的時候,內容都會得到解析,並在右邊的div中以HTML的形式進行展現。回頭,再來看package.json,我們中dependencies這個部分增加了marked依賴,現在需要做的是,打開項目的根目錄(包含package.json的目錄),在這個目錄中,執行 ** npm install ** (請確保npm能正常運行)。NPM會堅持項目的依賴項,然後從NPM倉庫中獲取,並下載到本地。執行結束後,觀察項目目錄,會看到一個名字為node_modules的目錄,這個目錄裡已經包含了marked這個依賴項。

現在,marked依賴已經安裝,我們可以在程序中調用了,首先,我們需要在 index.html中的部分包含此腳本。

圖示:目前為止文本編輯的運行狀態,HTML已經得到正確的展現。

為程序增加菜單

在這一部分,我們將為頂層的Webkit窗口增加一個菜單,這個菜單包含 "New","Open","Save" 和"Exit",我們首先要創建一個

menu.js 文件。文件內容如下:

exports.initMenu = function(){ var win = global.gui.Window.get(); var menubar = new global.gui.Menu({ type: 'menubar' }); var fileMenu = new global.gui.Menu();

fileMenu.append(new global.gui.MenuItem({

label: 'New',

click: function() {

}

}));

fileMenu.append(new global.gui.MenuItem({

label: 'Open',

click: function() {

}

}));

fileMenu.append(new global.gui.MenuItem({

label: 'Save',

click: function() {

}

}));

fileMenu.append(new global.gui.MenuItem({

label: 'Exit',

click: function() { global.gui.App.quit();

}

}));

menubar.append(new global.gui.MenuItem({ label: 'File', submenu: fileMenu}));

win.menu = menubar;

};

上面的代碼中,win 對象得到請求調用。如果需要改變Webkit窗口對象的話,這個對象就需要獲取到,比喻說現在,增加一個菜單。一個菜單對象被創建出來,而且增加了不同選項到子菜單,現在只有Exit菜單做一些真實的事情,關閉事件被調用時,會有動作需要執行。你需要增加這部分代碼到 main.jsinit()方法中。

Node Webkit入門創建一個簡單Markdown編輯器

接下來,我們需要做 editor.js 中增加2個方法。

exports.loadText = function(text){ var textEditor = global.$('#editor');

textEditor.val(text);

exports.reload();

};

exports.loadFile = function(file){ var fs = require('fs');

fs.readFile(file, 'utf8', function (err,data) { if (err) { return console.log(err);

}

exports.loadText(data);

});

};

loadText() 會替換當前左側編輯區域的內容,當文本替換後, reload() 會被調用,所以Markdown可以直接被解析為展現的HTML文檔,做右側的div中顯示。而loadFile()方法是加載一個給定的地址的文件,讀取內容,並顯示在文本區域中。

現在我們可以實現 文件打開 的業務了,我們首先在 index.html中增加下面的代碼。

這是一個隱藏的文件選擇對話框,當"Open"按鈕按下的時候,我們讓這個對話框打開並顯示。在editor.js中增加如下代碼:

exports.chooseFile = function(name, callback) { var chooser = global.$(name);

chooser.change(function(evt) {

callback(global.$(this).val());

});

chooser.trigger('click');

};

該方法會得到文件對話框的名字,name對應的就是上面定義的#openFileDialog,第二個參數是我們選擇要打開的文件後,要執行的方法,要執行成功,你需要在 menu.js 文件中 "require" editor.js ,然後在initMenu()方法中要做相應的調整。

var editor = require("./../js/editor.js");

接下來,我們可以在menu.js中完成打開文件的方法。

fileMenu.append(new global.gui.MenuItem({ label: 'Open',

click: function() {

editor.chooseFile("#openFileDialog", function(filename){

editor.loadFile(filename);

});

}

}));

這一段代碼調用editor.js中的 chooseFile() 方法,如果你選擇了文件的話,文件的路徑會傳遞給loadFile()方法,然後文本區域會替換。

Node Webkit入門創建一個簡單Markdown編輯器

接下來,我們可以實現"New"命令,新建按鈕按下的時候,左邊的文本區域會被置空,右邊的區域也會移除,在上面我們開發的代碼的基礎上,我們可以通過幾行簡單的代碼來實現該功能:

fileMenu.append(new global.gui.MenuItem({ label: 'New',

click: function() {

editor.loadText("");

}

}));

最後一個要實現的功能,我們可以實現菜單中的"Save"按鈕,當這個按鈕被按下時,一個新文件對話框會打開,你可以指定保存的文件的位置。首先要做的是在index.html中增加一個hidden域,你可以把它放在打開文件的下面。

nwsaveas用來設置保存的文字的默認名字,然後我們在editor.js中,編寫如下的代碼:

fileMenu.append(new global.gui.MenuItem({ label: 'Save', click: function() {

editor.chooseFile("#saveFileDialog", function(filename){ var fs = require('fs'); var textEditor = global.$('#editor');

fs.writeFile(filename, textEditor.val(), function(err) { if(err) { console.log(err);

} else { console.log("The file was saved!");

}

});

});

}

}));

Save按鈕按下時,我可以使用chooseFile()方法,文件路徑和文件名字輸入後,fs模塊會加載,文本區域的內容會通過writeFile()方法保存到文件中。

截止目前我們編寫了一個簡陋但是可以運行的Markdown編寫工具,我們可以看一下解析來,可以做一些什麼。

其他的功能

文件後綴

我們的程序需要處理的時.md文件,所以我們需要做的是,讀取傳輸給程序的arguments,可以在main.jsinit()方法中進行操作:

if(global.gui.App.argv.length > 0){

editor.loadFile(global.gui.App.argv[0]);

}

多選行,進行Tab

Notepad++ 這一類的程序有一個非常好用的功能是,你可以同時選擇多行,然後按下Tab鍵時,多行同時移動,按下 Shift+Tab的時候,進行相反的移動,這裡我們可以使用一個非常好用的JavaScript庫,Taboverride,你需要做的是,在index.html中包含它,然後在main.js中的init()方法中進行編寫。

tabOverride.set(global.window.document.getElementsByTagName('textarea'));

完結

我們已經實現了一個很好的簡單的編輯奇,當然,還需要一些其他的功能,比喻說:

區分Save和Save As

現在當你點擊Save按鈕的時候,總會有一個保存文件的對話框出現,但是當你點擊Save As按鈕後,程序應該記住,你之前保存的位置,然後進行一個直接的保存。

關閉時候保存

目前,如果你正在編輯一個文件,某種情況下,關閉應用程序,不會有任何的提示,你需要保存一個變量changed,用來標記系統是不是有改動,如果有改動的話,要彈出提示,提示用戶是否保存。

快捷鍵

現在系統還缺少快捷鍵的操作,比喻說常用的Ctrl+S保存,Ctrl+O打開。

打印到PDF

如果程序支持打印功能的話,就更好了,我們可以將Markdown變成PDF,然後將PDF通過打印程序打印,如果感興趣的話也可以使用PhontomJS來進行HTML到PDF的打印。

創建一個工具條

MS Word形式的工具條也是一個非常好的功能,比喻說,我們可以 標題號,斜體,粗體,等等,放置在工具條上,方便操作

移除調試條

如果你是在進行開發,那麼Debug工具條是一個非常好的幫手,但是如果你需要進行發佈,你可以通過編輯package.json

中的toolbar屬性為false來移除.

重定向外部URL

如果你想要點擊一個鏈接時,在Webkit窗口中打開一個外部網站的話,你可以通過捕獲URL的點擊,然後在默認瀏覽器中打開選擇的URL.

打包Editor程序

如果要打包程序的話,打包成一個獨立的.exe或者.app程序,你可以閱讀官方的文檔.

https://github.com/nwjs/nw.js/wiki/How-to-package-and-distribute-your-apps

文檔中,詳細描述了所有的過程.

更多文章,查看 www.wahwoo.org.


分享到:


相關文章: