Merge branch 'release/2.0.0-beta4.2'

This commit is contained in:
purocean
2019-08-09 18:00:13 +08:00
8 changed files with 79 additions and 42 deletions
+4
View File
@@ -0,0 +1,4 @@
# These are supported funding model platforms
# github: purocean
custom: https://github.com/purocean/yn#%E6%8D%90%E8%B5%A0
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 210 KiB

+11 -5
View File
@@ -6,15 +6,16 @@
![截图](./0.png)
## 特色
+ 使用方便:使用 Monaco 编辑器(vscode 编辑器内核)编辑,添加了针对 Markdown 文件加入快捷键和补全规则
+ 归档方便:图片文件保存在本地,无元数据文件或其他数据库,Markdown 文件可简单处理离线工作
+ 拓展性强:可在文档中嵌入小工具、可运行的代码块、ECharts 图形、Plantuml 图形等
+ 支持加密:用来保存账号等隐私文件,文件可单独设置密码
+ **使用方便**:使用 Monaco 编辑器(vscode 编辑器内核)编辑,添加了针对 Markdown 文件加入快捷键和补全规则
+ **兼容性强**:资源保存本地,Markdown 文件可简单处理离线工作;拓展功能尽量用 Markdown 原有的语法实现
+ **高拓展性**:可在文档中嵌入小工具、可运行的代码块、ECharts 图形、Plantuml 图形、Drawio 图形等
+ **支持加密**:用来保存账号等隐私文件,文件可单独设置密码
## 注意事项
+ Yank Note 是一款**针对程序员**的 Markdown 编辑器,目标应用场景为在本机写文章,日志,笔记,小工具。
+ Yank Note 为了更高的拓展性和方便性,牺牲了安全防护(命令执行,文件读写)。如果要用 Yank Note 打开外来 Markdown 文件,**请务必仔细甄别文件内容是值得信任的**。
+ 为了更高的拓展性和方便性,Yank Note 牺牲了安全防护(命令执行,任意文件读写)。如果要用它打开外来 Markdown 文件,**请务必仔细甄别文件内容是值得信任的**。
+ 如果要改造为对外的 Web 服务,本工具可能不太适合。或者请运行在可隔离控制的环境下。
+ 加密文件的加密解密操作均在前端完成,请**务必保管好自己的密码**。一旦密码丢失,就只能暴力破解了。
## Yank-Note 2.0 开发计划
[V2 项目看板](https://github.com/purocean/yn/projects/2)
@@ -158,6 +159,11 @@ yarn run start
## 更新日志
[最新发布](https://github.com/purocean/yn/releases)
### [v2.0.0-beta4.2](https://github.com/purocean/yn/releases/tag/v2.0.0-beta4.2) 2019-08-09
1. 修复文件方式引入 drawio 图形问题
1. 支持直接在新窗口打开 drawio 图形
1. 调整 drawio 图形样式
### [v2.0.0-beta4.1](https://github.com/purocean/yn/releases/tag/v2.0.0-beta4.1) 2019-08-09
1. 修复 js 文件打包拷贝
1. 修复在 Electron 中用新窗口打开 drawio 图形
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "yank.note.yang",
"version": "2.0.0-beta4.1",
"version": "2.0.0-beta4.2",
"description": "Yank-Note",
"main": "dist/app.js",
"author": {
+3 -1
View File
@@ -26,7 +26,9 @@ const createWindow = () => {
webPreferences: {
webSecurity: false,
nodeIntegration: true
}
},
minWidth: 700,
minHeight: 500,
})
win.maximize()
+8 -3
View File
@@ -6,7 +6,9 @@
<div :style="{
backgroundColor: `rgb(${220 - 220 * todoDoneCount / todoCount}, ${200 * todoDoneCount / todoCount}, 0)`,
width: `${todoDoneCount * 100 / todoCount}%`
}"> {{(todoDoneCount * 100 / todoCount).toFixed(2)}}% {{todoDoneCount}}/{{todoCount}} </div>
}">
<span style="padding-right: 3px;">{{(todoDoneCount * 100 / todoCount).toFixed(2)}}% {{todoDoneCount}}/{{todoCount}}</span>
</div>
</div>
<div v-else></div>
<div class="convert">
@@ -206,9 +208,10 @@ export default {
const nodes = this.$refs.view.querySelectorAll('.drawio[data-file]')
for (const el of nodes) {
const originPath = el.dataset.file
let originPath = el.dataset.file
if (originPath) {
const filepath = originPath.startsWith('/') ? originPath : (file.dirname(this.filePath) + originPath.replace(/^.\//, ''))
originPath = decodeURI(originPath)
const filepath = originPath.startsWith('/') ? originPath : (file.dirname(this.filePath) + '/' + originPath.replace(/^.\//, ''))
DrawioPlugin.load(el, this.fileRepo, filepath)
} else {
DrawioPlugin.load(el)
@@ -388,6 +391,7 @@ export default {
background: #303133;
}
.markdown-body /deep/ div.drawio-wrapper,
.markdown-body /deep/ input,
.markdown-body /deep/ img
{
@@ -395,6 +399,7 @@ export default {
filter: brightness(70%);
}
.markdown-body /deep/ div.drawio-wrapper:hover,
.markdown-body /deep/ img:hover
{
filter: none;
+6 -1
View File
@@ -26,6 +26,7 @@
<script>
import { mapState } from 'vuex'
import File from '@/lib/file'
import DrawioPlugin from '@/plugins/DrawioPlugin'
export default {
name: 'tree-node',
@@ -55,7 +56,11 @@ export default {
if (item.name.endsWith('.md')) {
this.$store.commit('app/setCurrentFile', item)
} else {
window.open(`api/attachment/${encodeURIComponent(item.name)}?repo=${item.repo}&path=${encodeURIComponent(item.path)}`)
if (item.path.toLowerCase().endsWith('.drawio')) {
DrawioPlugin.open(item)
} else {
window.open(`api/attachment/${encodeURIComponent(item.name)}?repo=${item.repo}&path=${encodeURIComponent(item.path)}`)
}
}
}
},
+46 -31
View File
@@ -11,7 +11,7 @@ const Plugin = md => {
iframe.dataset['content'] = content || ''
return `
<div style="position: relative">
<div class="drawio-wrapper" style="position: relative">
${iframe.outerHTML}
</div>
`
@@ -48,8 +48,7 @@ const Plugin = md => {
}
}
Plugin.load = async (el, repo, path) => {
let content = el.dataset['content']
const buildSrcdoc = async ({ repo, path, content }) => {
if (!content) {
content = (await file.read({ repo, path })).content
}
@@ -67,7 +66,7 @@ Plugin.load = async (el, repo, path) => {
xml: content
})
const srcdoc = `
return `
<style>
::selection {
background: #d3d3d3;
@@ -102,53 +101,64 @@ Plugin.load = async (el, repo, path) => {
max-width: 100%;
max-height: 100%;
}
body {
background: #fff;
}
</style>
${div.outerHTML}
<script src="${location.origin}/viewer.min.js"></script>
`
}
const openInNewWindow = srcdoc => {
const opener = window.open('about:blank')
const frame = document.createElement('iframe')
frame.width = '100%'
frame.height = '100%'
frame.frameBorder = '0'
frame.srcdoc = srcdoc
const isElectron = !!(window && window.process && window.process.versions && window.process.versions['electron'])
if (isElectron) {
const json = JSON.stringify(frame.outerHTML)
opener.eval(`
document.body.style.height = '100vh'
document.body.style.margin = '0'
document.body.innerHTML = ${json}
`)
} else {
opener.document.body.style.height = '100vh'
opener.document.body.style.margin = '0'
opener.document.body.appendChild(frame)
}
}
Plugin.load = async (el, repo, path) => {
const content = el.dataset['content']
const srcdoc = await buildSrcdoc({ repo, path, content })
const resize = () => {
el.contentDocument.body.style.height = 'auto'
el.contentDocument.documentElement.style.height = 'auto'
el.height = el.contentDocument.documentElement.scrollHeight + 'px'
el.height = el.contentDocument.documentElement.offsetHeight + 'px'
el.contentDocument.body.style.height = el.contentDocument.body.clientHeight + 'px'
el.contentDocument.documentElement.style.height = '100%'
appVm.$bus.emit('resize')
window.appVm.$bus.emit('resize')
}
const appVm = window.appVm
el.onload = () => setTimeout(resize, 300)
el.srcdoc = srcdoc
const button1 = document.createElement('button')
button1.style.cssText = 'margin-left: 5px;font-size: 14px;background: #444444; border: 0; padding: 0 6px; color: #ccc; cursor: pointer; border-radius: 2px; transition: all .3s ease-in-out; line-height: 24px;'
button1.style.cssText = 'margin-left: 5px;font-size: 14px;background: #cacaca; border: 0; padding: 0 6px; color: #2c2b2b; cursor: pointer; border-radius: 2px; transition: all .3s ease-in-out; line-height: 24px;'
button1.innerText = '适应高度'
button1.onclick = resize
const button2 = document.createElement('button')
button2.style.cssText = 'margin-left: 5px;font-size: 14px;background: #444444; border: 0; padding: 0 6px; color: #ccc; cursor: pointer; border-radius: 2px; transition: all .3s ease-in-out; line-height: 24px;'
button2.style.cssText = 'margin-left: 5px;font-size: 14px;background: #cacaca; border: 0; padding: 0 6px; color: #2c2b2b; cursor: pointer; border-radius: 2px; transition: all .3s ease-in-out; line-height: 24px;'
button2.innerText = '新窗口打开'
button2.onclick = () => {
const opener = window.open('about:blank')
const frame = document.createElement('iframe')
frame.width = '100%'
frame.height = '100%'
frame.frameBorder = '0'
frame.srcdoc = srcdoc
const isElectron = !!(window && window.process && window.process.versions && window.process.versions['electron'])
if (isElectron) {
const json = JSON.stringify(frame.outerHTML)
opener.eval(`
document.body.style.height = '100vh'
document.body.style.margin = '0'
document.body.innerHTML = ${json}
`)
} else {
opener.document.body.style.height = '100vh'
opener.document.body.style.margin = '0'
opener.document.body.appendChild(frame)
}
}
button2.onclick = () => openInNewWindow(srcdoc)
const action = document.createElement('div')
action.className = 'no-print'
@@ -158,4 +168,9 @@ Plugin.load = async (el, repo, path) => {
el.parentElement.appendChild(action)
}
Plugin.open = async file => {
const srcdoc = await buildSrcdoc(file)
openInNewWindow(srcdoc)
}
export default Plugin