Hiroki

大部分笔记已经转移到 https://github.com/hschen0712/machine_learning_notes ,QQ:357033150, 欢迎交流

一段markdown编辑器代码研究

一段markdown编辑器代码研究

说明

代码在 https://github.com/dukeofharen/markdown-editor
之所以选择这个来分析是一方面是因为它的代码结构比较简单,易于扩展,可塑性强;另一方面,自己可以跟着教程边做边学,掌握js的相关知识。
以下内容整理自作者写的tutorial

源码文件结构

源代码有4个目录

  • css用于存放样式
  • html目录下的文件是index.html,是app的主页
  • img是一些图片
  • js里面放的是js的脚本
    此外,还有一个package.json文件,这个文件里面放的是配置信息,在程序运行前nwjs会加载package.json

先来看js目录

jquery目录保存压缩过的jquery源码。
taboverride.min.js这个不知道是什么,先空着。
editor.jsmain.jsmenu.js是我们要重点分析的文件。editor.js是编辑器的脚本,main.js是主程序,menu.js是菜单的脚本。
先来看index.html,我截取了最重要的几行代码

...
	<script src="../js/jquery/jquery.min.js" type="text/javascript"></script>
	<script type="text/javascript" src="../js/main.js"></script>
	<script type="text/javascript" src="../js/taboverride/taboverride.min.js"></script>
	<script type="text/javascript">
		global.window = window;
		global.$ = $;
		global.gui = require('nw.gui');
		init();
	</script>
...

前几行加载了需要的js文件,接着在页面里嵌入了几行js代码。

		global.window = window;
		global.$ = $;
		global.gui = require('nw.gui');

第一行代码的意义是将DOM中的窗口对象window存放于global中。
第二行代码是把jquery对象存放在global变量中。
第三行是把nw.js中的gui对象存放在global中。
之所以这样做,是因为node.js的上下文中访问不到这三个对象,所以要把这三个对象存放在一个全局变量中。
最后,调用了main.js中的init()方法。

接下来让我们先来看main.js中的init()方法。

function init(){
	var menu = require("./../js/menu.js");
	menu.initMenu();

	global.$(global.window.document).ready(function(){
		var editor = require("./../js/editor.js");
		if(global.gui.App.argv.length > 0){
			editor.loadFile(global.gui.App.argv[0]);
		}
		var textEditor = global.$('#editor');
		textEditor.bind('input propertychange', function() {
			editor.reload();
		});
		tabOverride.set(global.window.document.getElementsByTagName('textarea'));
	});
}

首先init函数加载了menu.js模块。require相当于import,不同的是因为js是动态脚本语言,所以可以用到时再加载。获取menu对象后,调用了menu对象的initMenu方法,初始化菜单栏。

接着,调用jquery选择了window.document用于获取页面,并给ready()函数传入一个回调函数,意义是当页面加载完毕时,执行回调函数里面的内容。所谓回调函数,js的api文档是这么解释的:

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.

意思就是回调函数是 被作为参数传递给另一个父函数,且在父函数执行完毕后才开始执行的子函数。

那么回到正题来,回调函数里面干了什么事情呢?
1.

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

获取一个编辑器对象。

var textEditor = global.$('#editor');

用jquery的选择器选择index.htmlid=editor的元素:

<textarea name="markdown" id="editor" class="md_editor"></textarea>

其实就是文本编辑区。
3.

		textEditor.bind('input propertychange', function() {
			editor.reload();
		});

这段代码含义是给文本编辑区绑定一个事件,当检测到文本框内的内容改变时,就调用函数reload()重新渲染右边的预览区。

让我们看看reload函数

exports.reload = function(){
	var marked = require("marked");
	marked.setOptions({
	renderer: new marked.Renderer(),
		gfm: true,
		tables: true,
		breaks: false,
		pedantic: false,
		sanitize: false,
		smartLists: true,
		smartypants: false
	});
	var resultDiv = global.$('.md_result');
	var textEditor = global.$('#editor');
	var text = textEditor.val();
	resultDiv.html(marked(text));
};

1.首先加载marked
2.接着配置markdown解析器。

  • gfm:应该是github flavored markdown的缩写
  • tables:应该是允许使用表格
    剩下的都不知道什么意思。。。

var resultDiv = global.$('.md_result');
从css中选择类.md_result,这个类代表右边渲染出来的html网页。
4.获得文本编辑区的内容
.html是jquery的函数,是对innerHTML的封装,功能是设置或者获取DOM元素内的html内容。
这里我们用marked渲染文本,然后赋值给.md_result类里面的内容。
exports相当于导出功能,使得其他文件可以用到这里面定义的方法。

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

loadText完成的功能是,用text替换掉文本编辑区的内容,目前还不支持多文件。

posted on 2015-11-22 15:25  Hiroki  阅读(443)  评论(0编辑  收藏  举报

导航