mirror of
https://github.com/leanote/desktop-app.git
synced 2025-10-17 16:45:21 +00:00
move src/* to /
This commit is contained in:
224
public/plugins/export_html/plugin.js
Normal file
224
public/plugins/export_html/plugin.js
Normal file
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* 导出HTML插件
|
||||
* @author life life@leanote.com
|
||||
* 选择目录, 将图片保存到文件夹中, 有个html文件(以笔记名命名)
|
||||
* 注意, fs.existsSync总返回false, readFileSync可用
|
||||
*/
|
||||
define(function() {
|
||||
var async = require('async');
|
||||
|
||||
var exportHTML = {
|
||||
langs: {
|
||||
'en-us': {
|
||||
'export': 'Export HTML',
|
||||
'exportSuccess': 'HTML saved successful!',
|
||||
'exportFailure': 'HTML saved failure!',
|
||||
'notExists': 'Please sync your note to ther server firslty.'
|
||||
},
|
||||
'zh-cn': {
|
||||
'export': '导出HTML',
|
||||
'exportSuccess': 'HTML导出成功!',
|
||||
'exportFailure': 'HTML导出失败!'
|
||||
},
|
||||
'zh-hk': {
|
||||
'export': '導出HTML',
|
||||
'exportSuccess': 'HTML導出成功!',
|
||||
'exportFailure': 'HTML導出失敗!'
|
||||
}
|
||||
},
|
||||
|
||||
_inited: false,
|
||||
init: function() {
|
||||
var me = this;
|
||||
me._inited = true;
|
||||
},
|
||||
|
||||
getPluginPath: function() {
|
||||
return Api.evtService.getProjectBasePath() + '/public/plugins/export_html' ;
|
||||
},
|
||||
|
||||
htmlTpl: '',
|
||||
markdownTpl: '',
|
||||
getTpl: function(isMarkdown) {
|
||||
var tpl = isMarkdown ? this.markdownTpl : this.htmlTpl;
|
||||
if(tpl) {
|
||||
return tpl;
|
||||
}
|
||||
var basePluginPath = this.getPluginPath();
|
||||
|
||||
var tplName = isMarkdown ? 'markdown' : 'html';
|
||||
var tplPath = basePluginPath + '/tpl/' + tplName + '.tpl';
|
||||
tpl = Api.nodeFs.readFileSync(tplPath, 'utf-8');
|
||||
isMarkdown ? (this.markdownTpl = tpl) : (this.htmlTpl = tpl);
|
||||
return tpl;
|
||||
},
|
||||
// 生成html或markdown
|
||||
render: function(note) {
|
||||
var tpl = this.getTpl(note.IsMarkdown);
|
||||
var title = note.Title || getMsg('Untitled');
|
||||
tpl = tpl.replace(/\{title\}/g, title);
|
||||
tpl = tpl.replace(/\{content\}/g, note.Content);
|
||||
return tpl;
|
||||
},
|
||||
|
||||
replaceAll: function(src, pattern, to) {
|
||||
if(!src) {
|
||||
return src;
|
||||
}
|
||||
while(true) {
|
||||
var oldSrc = src;
|
||||
src = src.replace(pattern, to);
|
||||
if(oldSrc === src) {
|
||||
return src;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
fixFilename: function(filename) {
|
||||
var reg = new RegExp("/|#|\\$|!|\\^|\\*|'| |\"|%|&|\\(|\\)|\\+|\\,|/|:|;|<|>|=|\\?|@|\\||\\\\", 'g');
|
||||
filename = filename.replace(reg, "-");
|
||||
// 防止出现两个连续的-
|
||||
while(filename.indexOf('--') != -1) {
|
||||
filename = this.replaceAll(filename, '--', '-');
|
||||
}
|
||||
return filename;
|
||||
},
|
||||
|
||||
// 写图片,并替换图片路径
|
||||
writeFiles: function(filesPath, content, callback) {
|
||||
var me = this;
|
||||
// http://127.0.0.1:8912/api/file/getImage?fileId=5581029f6289dc3301000000
|
||||
// 找到图片
|
||||
var reg = new RegExp(Api.evtService.localUrl + '/api/file/getImage\\?fileId=([0-9a-zA-Z]{24})', 'g');
|
||||
// console.log(Api.evtService.localUrl + '/api/file/getImage\\?fileId=([0-9a-zA-Z]{24})');
|
||||
var matches = content.match(reg);
|
||||
// content = content.replace(reg, Evt.leanoteUrl + '/api/file/getImage');
|
||||
|
||||
if(matches && matches.length) {
|
||||
Api.nodeFs.mkdirSync(filesPath);
|
||||
// 取最后一个名字
|
||||
var pathInfo = Api.commonService.splitFile(filesPath);
|
||||
var dirName = pathInfo.name;
|
||||
|
||||
async.eachSeries(matches, function(url, cb) {
|
||||
var fileId = url.substr(url.length - 24);
|
||||
Api.fileService.getImageLocalPath(fileId, function(err, imagePath) {
|
||||
// 将图片copy到filesPath下
|
||||
if(imagePath) {
|
||||
var distFileName = fileId + '.png';
|
||||
Api.commonService.copyFile(imagePath, filesPath + '/' + distFileName, function(ok) {
|
||||
content = me.replaceAll(content, url, dirName + '/' + distFileName);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
else {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
}, function() {
|
||||
callback(content);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
callback(content);
|
||||
},
|
||||
|
||||
// 得到存放images, js, css的路径
|
||||
getFilesPath: function(basePath, nameNotExt, n, cb) {
|
||||
var me = this;
|
||||
var absPath = basePath + '/' + nameNotExt + '_files';
|
||||
if (n > 1) {
|
||||
absPath += '-' + n;
|
||||
}
|
||||
Api.nodeFs.exists(absPath, function(exists) {
|
||||
if(!exists) {
|
||||
cb(absPath);
|
||||
}
|
||||
else {
|
||||
me.getFilesPath(basePath, nameNotExt, n+1, cb);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 得到可用的文件名, 避免冲突
|
||||
getHtmlFilePath: function(pathInfo, n, cb) {
|
||||
var me = this;
|
||||
if(n > 1) {
|
||||
pathInfo.nameNotExt = pathInfo.nameNotExtRaw + '-' + n;
|
||||
}
|
||||
var absPath = pathInfo.getFullPath();
|
||||
// 总是覆盖
|
||||
return cb(absPath);
|
||||
|
||||
// Api.nodeFs.existsSync(absPath) 总是返回false, 不知道什么原因
|
||||
// 在控制台上是可以的
|
||||
Api.nodeFs.exists(absPath, function(exists) {
|
||||
if(!exists) {
|
||||
cb(absPath);
|
||||
}
|
||||
else {
|
||||
me.getHtmlFilePath(pathInfo, n+1, cb);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
exportHTML: function(note) {
|
||||
var me = this;
|
||||
if(!note) {
|
||||
return;
|
||||
}
|
||||
|
||||
var name = note.Title ? note.Title + '.html' : getMsg('Untitled') + '.html';
|
||||
name = me.fixFilename(name);
|
||||
|
||||
Api.gui.dialog.showSaveDialog(Api.gui.getCurrentWindow(), {title: name, defaultPath: name}, function(targetPath) {
|
||||
if(targetPath) {
|
||||
// 将路径和名字区分开
|
||||
var pathInfo = Api.commonService.splitFile(targetPath);
|
||||
pathInfo.nameNotExt = me.fixFilename(pathInfo.nameNotExt); // 重新修正一次
|
||||
var nameNotExt = pathInfo.nameNotExt;
|
||||
pathInfo.nameNotExtRaw = pathInfo.nameNotExt;
|
||||
// 得到可用文件的绝对路径
|
||||
me.getHtmlFilePath(pathInfo, 1, function(absHtmlFilePath) {
|
||||
me.getFilesPath(pathInfo.path, pathInfo.nameNotExt, 1, function(absFilesPath) {
|
||||
// alert(absHtmlFilePath + ' --- ' + absFilesPath);
|
||||
var html = me.render(note);
|
||||
// 写图片
|
||||
me.writeFiles(absFilesPath, html, function(html) {
|
||||
// 把文件写到
|
||||
Api.commonService.writeFile(absHtmlFilePath, html);
|
||||
Notify.show({title: 'Info', body: getMsg('plugin.export_html.exportSuccess')});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 打开前要执行的
|
||||
onOpen: function() {
|
||||
var me = this;
|
||||
var gui = Api.gui;
|
||||
|
||||
var menu = {
|
||||
label: Api.getMsg('plugin.export_html.export'),
|
||||
click: (function() {
|
||||
return function(note) {
|
||||
me.exportHTML(note);
|
||||
}
|
||||
})()
|
||||
};
|
||||
Api.addExportMenu(menu);
|
||||
},
|
||||
// 打开后
|
||||
onOpenAfter: function() {
|
||||
},
|
||||
// 关闭时需要运行的
|
||||
onClose: function() {
|
||||
}
|
||||
};
|
||||
|
||||
return exportHTML;
|
||||
|
||||
});
|
165
public/plugins/export_html/tpl/html.tpl
Normal file
165
public/plugins/export_html/tpl/html.tpl
Normal file
@@ -0,0 +1,165 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="tool" content="leanote-desktop-app">
|
||||
<title>{title}</title>
|
||||
<style>
|
||||
|
||||
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*公用文字样式*/
|
||||
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
|
||||
.note-container{
|
||||
width:850px;
|
||||
margin:auto;
|
||||
padding: 10px 20px;
|
||||
box-shadow: 1px 1px 10px #eee;
|
||||
}
|
||||
#title {
|
||||
margin: 0;
|
||||
}
|
||||
table {
|
||||
margin-bottom: 16px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table th, table td {
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
table th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table tr {
|
||||
background-color: none;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
table tr:nth-child(2n) {
|
||||
background-color: rgb(247, 247, 249);
|
||||
}
|
||||
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
|
||||
border: 1px solid #ddd;
|
||||
border-collapse: collapse;
|
||||
padding: 6px 13px;
|
||||
}
|
||||
blockquote {
|
||||
border-left-width:10px;
|
||||
background-color:rgba(128,128,128,0.05);
|
||||
border-top-right-radius:5px;
|
||||
border-bottom-right-radius:5px;
|
||||
padding:15px 20px;
|
||||
border-left:5px solid rgba(128,128,128,0.075);
|
||||
}
|
||||
blockquote p {
|
||||
margin-bottom:1.1em;
|
||||
font-size:1em;
|
||||
line-height:1.45
|
||||
}
|
||||
blockquote ul:last-child,blockquote ol:last-child {
|
||||
margin-bottom:0
|
||||
}
|
||||
pre {
|
||||
padding: 18px;
|
||||
background-color: #f7f7f9;
|
||||
border: 1px solid #e1e1e8;
|
||||
border-radius: 3px;
|
||||
display: block;
|
||||
}
|
||||
code {
|
||||
padding: 2px 4px;
|
||||
font-size: 90%;
|
||||
color: #c7254e;
|
||||
white-space: nowrap;
|
||||
background-color: #f9f2f4;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.footnote {
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
top: -0.5em;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin:2em 0
|
||||
}
|
||||
img {
|
||||
max-width:100%
|
||||
}
|
||||
pre {
|
||||
word-break:break-word
|
||||
}
|
||||
p,pre,pre.prettyprint,blockquote {
|
||||
margin:0 0 1.1em
|
||||
}
|
||||
hr {
|
||||
margin:2em 0
|
||||
}
|
||||
img {
|
||||
max-width:100%
|
||||
}
|
||||
.sequence-diagram,.flow-chart {
|
||||
text-align:center;
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
.sequence-diagram text,.flow-chart text {
|
||||
font-size:15px !important;
|
||||
font-family:"Source Sans Pro",sans-serif !important
|
||||
}
|
||||
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
|
||||
fill:#f6f6f6
|
||||
}
|
||||
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
|
||||
stroke:#3f3f3f
|
||||
}
|
||||
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
|
||||
stroke:none
|
||||
}
|
||||
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
|
||||
fill:#3f3f3f
|
||||
}
|
||||
ul,ol {
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
ul ul,ol ul,ul ol,ol ol {
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
kbd {
|
||||
padding:.1em .6em;
|
||||
border:1px solid rgba(63,63,63,0.25);
|
||||
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||||
box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||||
font-size:.7em;
|
||||
font-family:sans-serif;
|
||||
background-color:#fff;
|
||||
color:#333;
|
||||
border-radius:3px;
|
||||
display:inline-block;
|
||||
margin:0 .1em;
|
||||
white-space:nowrap
|
||||
}
|
||||
.toc ul {
|
||||
list-style-type:none;
|
||||
margin-bottom:15px
|
||||
}
|
||||
</style>
|
||||
<!-- 该css供自定义样式 -->
|
||||
<link href="../leanote-html.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="note-container">
|
||||
<h1 class="title" id="leanote-title">{title}</h1>
|
||||
<div class="content-html" id="leanote-content">{content}</div>
|
||||
</div>
|
||||
|
||||
<!-- 该js供其它处理 -->
|
||||
<script src="../leanote-html.js"></script>
|
||||
</body>
|
||||
</html>
|
213
public/plugins/export_html/tpl/markdown.tpl
Normal file
213
public/plugins/export_html/tpl/markdown.tpl
Normal file
@@ -0,0 +1,213 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="tool" content="leanote-desktop-app">
|
||||
<title>{title}</title>
|
||||
<style>
|
||||
.tab{font-size:12px; margin-bottom: 10px;}
|
||||
.tab a{cursor:pointer;cursor:pointer;display:inline-block;margin-right:10px;color:#000}#tab-html{color:#ccc}
|
||||
|
||||
.content-container .content-html{visibility: hidden;}
|
||||
.content-container.html .content-markdown{display:none}
|
||||
.content-container.html .content-html{display:block; visibility: visible;}
|
||||
.content-container.html #tab-markdown{color:#ccc}
|
||||
.content-container.html #tab-html{color:#000}
|
||||
.content-markdown {overflow: auto;}
|
||||
textarea {display: none;}
|
||||
|
||||
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*公用文字样式*/
|
||||
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
|
||||
.note-container{
|
||||
width:850px;
|
||||
margin:auto;
|
||||
padding: 10px 20px;
|
||||
box-shadow: 1px 1px 10px #eee;
|
||||
}
|
||||
#title {
|
||||
margin: 0;
|
||||
}
|
||||
table {
|
||||
margin-bottom: 16px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table th, table td {
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
table th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table tr {
|
||||
background-color: none;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
table tr:nth-child(2n) {
|
||||
background-color: rgb(247, 247, 249);
|
||||
}
|
||||
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
|
||||
border: 1px solid #ddd;
|
||||
border-collapse: collapse;
|
||||
padding: 6px 13px;
|
||||
}
|
||||
blockquote {
|
||||
border-left-width:10px;
|
||||
background-color:rgba(128,128,128,0.05);
|
||||
border-top-right-radius:5px;
|
||||
border-bottom-right-radius:5px;
|
||||
padding:15px 20px;
|
||||
border-left:5px solid rgba(128,128,128,0.075);
|
||||
}
|
||||
blockquote p {
|
||||
margin-bottom:1.1em;
|
||||
font-size:1em;
|
||||
line-height:1.45
|
||||
}
|
||||
blockquote ul:last-child,blockquote ol:last-child {
|
||||
margin-bottom:0
|
||||
}
|
||||
pre {
|
||||
padding: 18px;
|
||||
background-color: #f7f7f9;
|
||||
border: 1px solid #e1e1e8;
|
||||
border-radius: 3px;
|
||||
display: block;
|
||||
}
|
||||
code {
|
||||
padding: 2px 4px;
|
||||
font-size: 90%;
|
||||
color: #c7254e;
|
||||
white-space: nowrap;
|
||||
background-color: #f9f2f4;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.footnote {
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
top: -0.5em;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin:2em 0
|
||||
}
|
||||
img {
|
||||
max-width:100%;
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
pre {
|
||||
word-break:break-word
|
||||
}
|
||||
p,pre,pre.prettyprint,blockquote {
|
||||
margin:0 0 1.1em
|
||||
}
|
||||
hr {
|
||||
margin:2em 0
|
||||
}
|
||||
img {
|
||||
max-width:100%
|
||||
}
|
||||
.sequence-diagram,.flow-chart {
|
||||
text-align:center;
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
.sequence-diagram text,.flow-chart text {
|
||||
font-size:15px !important;
|
||||
font-family:"Source Sans Pro",sans-serif !important
|
||||
}
|
||||
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
|
||||
fill:#f6f6f6
|
||||
}
|
||||
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
|
||||
stroke:#3f3f3f
|
||||
}
|
||||
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
|
||||
stroke:none
|
||||
}
|
||||
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
|
||||
fill:#3f3f3f
|
||||
}
|
||||
ul,ol {
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
ul ul,ol ul,ul ol,ol ol {
|
||||
margin-bottom:1.1em
|
||||
}
|
||||
kbd {
|
||||
padding:.1em .6em;
|
||||
border:1px solid rgba(63,63,63,0.25);
|
||||
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||||
box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||||
font-size:.7em;
|
||||
font-family:sans-serif;
|
||||
background-color:#fff;
|
||||
color:#333;
|
||||
border-radius:3px;
|
||||
display:inline-block;
|
||||
margin:0 .1em;
|
||||
white-space:nowrap
|
||||
}
|
||||
.toc ul {
|
||||
list-style-type:none;
|
||||
margin-bottom:15px
|
||||
}
|
||||
</style>
|
||||
<!-- 该css供自定义样式 -->
|
||||
<link href="../leanote-markdown.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="note-container">
|
||||
<h1 class="title" id="leanote-title">{title}</h1>
|
||||
<div class="content-container" id="content-container">
|
||||
<!-- 切换 -->
|
||||
<div class="tab"><a id="tab-markdown">Markdown</a><a id="tab-html">HTML</a></div>
|
||||
<textarea id="leanote-content-markdown">{content}</textarea>
|
||||
<!-- markdown -->
|
||||
<pre class="content-markdown">{content}</pre>
|
||||
<!-- html -->
|
||||
<div class="content-html" id="leanote-content-html"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 该js供其它处理 -->
|
||||
<script src="../leanote-markdown.js"></script>
|
||||
<script src="http://leanote.github.io/markdown-to-html/markdown-to-html.min.js"></script>
|
||||
<script>
|
||||
function init() {
|
||||
markdownToHtml(document.getElementById('leanote-content-markdown').value, document.getElementById('leanote-content-html'), function(html) {
|
||||
// 解析后执行
|
||||
if(window.markdownParsed) {
|
||||
window.markdownParsed(html);
|
||||
}
|
||||
});
|
||||
var $m = document.getElementById('tab-markdown');
|
||||
var $h = document.getElementById('tab-html');
|
||||
var $cc = document.getElementById('content-container');
|
||||
function toggleToHtml(isToHtml) {
|
||||
$cc.className = isToHtml ? 'content-container html' : 'content-container';
|
||||
}
|
||||
$m.addEventListener('click', function() {
|
||||
toggleToHtml(false);
|
||||
});
|
||||
$h.addEventListener('click', function() {
|
||||
toggleToHtml(true);
|
||||
});
|
||||
}
|
||||
|
||||
// 如果不要自动解析html, notParseMarkdown在leanote-markdown.js中定义
|
||||
if(!window.notParseMarkdown) {
|
||||
init();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user