繼上一篇 node webkit 用javascript打造web native之後,終於算是可以做出一個atom編輯器,只是這裡是為了記念一下Nokia的Lumia手機,最後代碼見https://github.com/gmszone/lumia
開始之前需要配置好開發環境,也就是這個,下面是
Mac OS下的
https://github.com/rogerwang/node-webkit
找到對應的版本
將app複製到Application,接著把下面的alias添加到
~/.bash_profile
# alias to nw alias nw="/Applications/node-webkit.app/Contents/MacOS/node-webkit"
應用一下
source ~/.bash_profile
啟動應用的方式是
nw app.nw
啟動之前需要
zip -r app.nw *
這樣我們就有了一個基本的架構了
lumia 0.1最初的版本是來自
https://github.com/zcbenz/nw-sample-apps
也就是node-webkit官網給的樣本
只是這樣本看上去一點都不友好,在寫這篇文章時Lumia編輯器的
看上去和atom editor像極了,因為css就是參考atom編輯器的。
架構組成目前主要是由下面兩個構成基本的功能(轉載保留:自己動手寫編輯器——Lumia Inspired by Atom)
- Node.js
- Node-webkit
- CodeMirror
顯然Node-Webkit發揮了主要的功能,但是CodeMirror也功不可沒,作為一個線上編輯器的工具,其他目前的工作者。
- Underscore JS擴充庫
- StringJS 讓對String的處理更加簡單
不過Package.json裡面有更多的庫,但是還沒有發揮作用。
Lumia Editor 準系統暫時沒有對Node-Webkit的樣本做了太多的修改,修改主要基於下面幾個部分
- 去除了Save、Open、New三個button,直接改為了快速鍵
- 美化UI
- 擴充了匹配,支援更多的語言
- Sublime快速鍵綁定
所以,他的準系統就是
- 開啟、儲存、建立檔案
- 和Sublime一樣的快速鍵
- Atom一樣的外觀
- 搜尋
Javascript+HTML+Node-WebkitHTML+CSS主要是對介面的美化
<body style="background:#fff"> <div class="workspace" background="#fff"> <div class="horizontal"> <div class="vertical"> <div class="panes"> <div class="pane" style="min-width:100%;"> <ul tabindex="-1" class="list-inline tab-bar inset-panel"> <li class="tab active"> <div class="title" id="title">untitled</div> <div class="close-icon"></div> </li> </ul> <div class="editor"> <div id="editor"></div> </div> </div> </div> <div class="status-bar tool-panel panel-bottom"> <div class="flexbox-repaint-hack"> <div class="status-bar-left"> <div class="cursor-position inline-block" id="mode"> </a> <div class="status-image inline-block"> <span class="image-size" style="display: none;"></span> </div> </div> </div> </div> </div> </div> <input style="display:none;" id="newFile" type="file" /> <input style="display:none;" id="openFile" type="file" /> <input style="display:none;" id="saveFile" type="file" nwsaveas /> </div> <div style="display:none"> <button style="display:none;" id="new">New</button> <button style="display:none;" id="open">Open</button> <button style="display:none;" id="save">Save</button> </div> </body>
如把title移到了最上面,變成了和title一樣的位置,看上去像極了chrome瀏覽器的標籤,這裡主要是用了CSS的虛擬元素
.tab-bar .tab:before { content:''; position: absolute; top: -1px; left: -16px; height: 26px; width: 30px; border-top-left-radius: 3px; border-left: 1px solid #b9b9b9; box-shadow: inset 1px -1px 1px rgba(0, 0, 0, 0.05); -webkit-transform: skewX(133deg); } .tab-bar:after { content:""; position: absolute; bottom: 0; height: 5px; left: 0px; width: 100%; background-color: #f0f0f0; border-bottom: 1px solid #dddddd; border-top: 1px solid #b9b9b9; }
這些主要就是表現在外見上的,大致上就是上面的作法。
editor.js裡面做的主要就是判斷和處理事件了
onload = function() { newButton = document.getElementById("new"); openButton = document.getElementById("open"); saveButton = document.getElementById("save"); newButton.addEventListener("click", handleNewButton); openButton.addEventListener("click", handleOpenButton); saveButton.addEventListener("click", handleSaveButton); $("#saveFile").change(function(evt) { onChosenFileToSave($(this).val()); }); $("#openFile").change(function(evt) { onChosenFileToOpen($(this).val()); }); editor = CodeMirror( document.getElementById("editor"), { lineNumbers: true, keyMap: "sublime", autoCloseBrackets: true, matchBrackets: true, showCursorWhenSelecting: true, extraKeys: { "Cmd-N": function(instance) { handleNewButton() }, "Ctrl-N": function(instance) { handleNewButton() }, "Cmd-O": function(instance) { handleOpenButton() }, "Ctrl-O": function(instance) { handleOpenButton() }, "Cmd-S": function(instance) { handleSaveButton() }, "Ctrl-S": function(instance) { handleSaveButton() }, "Cmd-Shift-P": function(instance) { console.log("hello".green) } } }); newFile(); onresize(); gui.Window.get().show(); };
可以看到的是editor主要是由CodeMirror驅動的,還有就是對於語言的判斷,這個是用於判斷是哪種語言並給予高亮。
function handleDocumentChange(title) { var mode = "javascript"; var modeName = "JavaScript"; if (title) { title = title.match(/[^/]+$/)[0]; document.getElementById("title").innerHTML = title; document.title ="Lumia"+title; _.each(m.allmodes, function(modes) { if (S(title).contains(modes["filename"])) { mode = modes["mode"]; modeName = modes["modeName"]; console.log(mode); } }); } else { document.getElementById("title").innerHTML = "[no document loaded]"; } editor.setOption("mode", mode); document.getElementById("mode").innerHTML = modeName; }
主要的工作是
underscore和
stringjs做的,這裡的m用的是外部檔案。
var m = require('./allmodes')