/**
* amWiki Web端 - 文档加载与渲染模块
* @author Tevin
*/
;
(function (win, doc, $) {
'use strict';
var hljs = win.hljs;
var marked = win.marked;
var URL_ENCODE_NAME = 'AMWikiUrlEncode'; //记录url编码的键名
/**
* 文档管理
* @constructor
*/
var Docs = function () {
this.$e = {
win: $(win),
//markdown 文档内容容器
view: $('#view'),
//网页 title 标签
title: $('title'),
//目录悬浮窗标题
contentsTitle: $('#contentsTitle')
};
this.data = {
//记录页面宽度
pageWidth: 0
};
this._initUrlEncode();
this._initHashEvent();
};
/**
* 初始化url编码类型标记
* @private
*/
Docs.prototype._initUrlEncode = function () {
/*
* 由于win与linux采用不同编码保存中文文件名
* 记录浏览器打开当前域名的wiki时服务器中文文件名的编码类型
*/
if (!localStorage[URL_ENCODE_NAME]) {
localStorage[URL_ENCODE_NAME] = 'utf8';
} else if (localStorage[URL_ENCODE_NAME] != 'utf8' && localStorage[URL_ENCODE_NAME] != 'gbk') {
localStorage[URL_ENCODE_NAME] = 'utf8';
}
//旧版本记录移除
delete localStorage.urlEcode
};
/**
* 修正移动端hash变化时滚动位置
* @private
*/
Docs.prototype._initHashEvent = function () {
var that = this;
this.data.pageWidth = this.$e.win.width();
this.$e.win.on('resize', function () {
that.data.pageWidth = that.$e.win.width();
});
this.$e.win.on('hashchange', function (e) {
var hash = location.hash.split('#')[1];
if (that.data.pageWidth <= 720) {
that.$e.view.find('h1,h2,h3').each(function (index, element) {
var $title = $(element);
var text = $title.text().replace(/\s+/g, '');
if (hash == text) {
that.$e.win.scrollTop($title.offset().top - 55);
}
});
}
});
};
/**
* 转换链接文本
* @param {String} str
* @returns {String}
* @private
*/
Docs.prototype._tramsformLinkText = function (str) {
return str
.replace(/^\s+|\s+$/g, '') //去除首尾空格
.replace(/'/g, ''') //转义单引号
.replace(/"/g, '"') //转义双引号,由于双引号无法正确传递给html属性,当作为hash时将删除处理
.replace(/\(/g, '(') //转义左圆括号
.replace(/\)/g, ')') //转义右圆括号
.replace(/\[/g, '[') //转义左中括号
.replace(/\]/g, ']'); //转义右中括号
};
/**
* 设置文档h1、h2、h3描记
* @returns {string}
* @private
*/
Docs.prototype._setTitlesAnchor = function () {
var that = this;
var $titles = null;
var hash = '';
var contentsMd = ''; //提取目录为markdown字符串
if (location.hash && location.hash.length > 1) {
hash = location.hash.split('#')[1];
}
var anchorHtml = '' +
'';
$titles = that.$e.view.find('h1,h2,h3');
$titles.each(function (index, element) {
var $this = $(element);
var text1 = that._tramsformLinkText($this.text());
var text2 = text1.replace(/"/g, ''); //删除双引号
//提取目录
if ($this.is('h2')) {
contentsMd += '1. [' + text1 + '](#' + text2 + ' "' + text2 + '")\n';
} else if ($this.is('h3')) {
contentsMd += '\t1. [' + text1 + '](#' + text2 + ' "' + text2 + '")\n';
}
//设置描记
$this.prepend(anchorHtml.replace(/{title}/g, text2));
//首次打开页面滚动位置修正
if (hash == $this.text().replace(/"/g, '')) {
if (that.data.pageWidth <= 720) {
that.$e.win.scrollTop($this.offset().top - 55);
} else {
that.$e.win.scrollTop($this.offset().top);
}
}
});
if (contentsMd.indexOf('\t') == 0) {
contentsMd = '1. \n' + contentsMd;
}
return contentsMd;
};
/**
* 创建脚注
* @param {String} text
* @returns {String}
* @private
*/
Docs.prototype._setFootnote = function (text) {
var footnotes = [];
var noteReg = /\[\^([ a-zA-Z\d]+)]/g;
var footReg = /\[\^([ a-zA-Z\d]+)]: ?([\S\s]+?)(?=\[\^(?:[ a-zA-Z\d]+)]|\n\n|$)/g;
var templates = $.trim($('#template\\:footnote').text()).split(/[\r\n]+\s*/g);
templates[4] += templates[5] + templates[6] + templates[7] + templates[8];
var html = '';
//提取脚注内容
text = text.replace(footReg, function (match, s1, s2, index) {
var title = '';
s2 = s2.replace(/"(.*?)"\s*$/, function (m, ss1) {
title = ss1;
return '';
});
footnotes.push({
index: index,
note: s1,
content: s2,
title: title,
used: false
});
//从页面上删除底部脚注内容
return '';
});
//将脚注的标记转为序号
text = text.replace(noteReg, function (match, s1) {
for (var i = 0, foot; foot = footnotes[i]; i++) {
if (foot.note == s1) {
foot.used = true;
return templates[0].replace(/{{index}}/g, i + 1 + '').replace('{{title}}', foot.title);
}
}
//当脚注的正文不存在,视标记文本为正文
var length = footnotes.push({
index: 0,
note: s1,
content: s1,
used: true
});
return templates[0].replace(/{{index}}/g, length + '');
});
//生成底部脚注html
if (footnotes.length >= 1) {
for (var i = 0, foot; foot = footnotes[i]; i++) {
if (foot.used) {
html += templates[2]
.replace('{{index}}', i + 1)
.replace('{{content}}', foot.content)
.replace('{{back}}', templates[4].replace('{{index}}', i + 1));
} else {
html += templates[3].replace('{{content}}', foot.content);
}
}
html = templates[1].replace('{{list}}', html);
}
return text + '\n
' + html;
};
/**
* 设置js代码块注释显示隐藏
* @param {Object} $elm
* @private
*/
Docs.prototype._setJSCommentDisable = function ($elm) {
var $disBtn = $('