diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fdf51cc..daaaaf48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,11 @@ -### 0.6.10 +### 0.6.11 **Features** - Add **dark** theme and **light** theme in both realtime preview mode and source code mode. +- Insert `doutu` into the document, use CMD + / to open the panel. + **Optimization** - Customize the scroll bar background color and thumb color. diff --git a/package-lock.json b/package-lock.json index e8d51cf1..70efd6c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "marktext", - "version": "0.3.1", + "version": "0.6.10", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -550,11 +550,11 @@ "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, "axios": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.16.2.tgz", - "integrity": "sha1-uk+S8XFn37q0CYN4VFS5rBScPG0=", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", "requires": { - "follow-redirects": "1.2.6", + "follow-redirects": "1.4.1", "is-buffer": "1.1.6" } }, @@ -5387,9 +5387,9 @@ "dev": true }, "follow-redirects": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.2.6.tgz", - "integrity": "sha512-FrMqZ/FONtHnbqO651UPpfRUVukIEwJhXMfdr/JWAmrDbeYBu773b1J6gdWDyRIj4hvvzQEHoEOTrdR8o6KLYA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", + "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", "requires": { "debug": "3.1.0" } diff --git a/package.json b/package.json index 122429f1..9d082c26 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "marktext", - "version": "0.6.10", + "version": "0.6.11", "author": "Jocs ", "description": "A markdown editor", "license": "MIT", @@ -68,7 +68,7 @@ } }, "dependencies": { - "axios": "^0.16.1", + "axios": "^0.18.0", "cheerio": "^1.0.0-rc.2", "codemirror": "^5.31.0", "css-tree": "^1.0.0-alpha.27", diff --git a/src/editor/contentState/formatCtrl.js b/src/editor/contentState/formatCtrl.js index 8149a049..bd5341c0 100644 --- a/src/editor/contentState/formatCtrl.js +++ b/src/editor/contentState/formatCtrl.js @@ -175,6 +175,35 @@ const formatCtrl = ContentState => { block.text = generator(tokens) } + ContentState.prototype.insertAidou = function (url) { + const { start, end } = this.cursor + const { key, offset: startOffset } = start + const { offset: endOffset } = end + const block = this.getBlock(key) + const { text } = block + if (key !== end.key) { + block.text = text.substring(0, startOffset) + `![](${url})` + text.substring(startOffset) + const offset = startOffset + 2 + this.cursor = { + start: { key, offset }, + end: { key, offset } + } + } else { + block.text = text.substring(0, start.offset) + `![${text.substring(startOffset, endOffset)}](${url})` + text.substring(end.offset) + this.cursor = { + start: { + key, + offset: startOffset + 2 + }, + end: { + key, + offset: startOffset + 2 + text.substring(startOffset, endOffset).length + } + } + } + this.render() + } + ContentState.prototype.format = function (type) { const { start, end } = selection.getCursorRange() const startBlock = this.getBlock(start.key) diff --git a/src/editor/index.js b/src/editor/index.js index 65f6ab35..a8b87bea 100644 --- a/src/editor/index.js +++ b/src/editor/index.js @@ -454,6 +454,10 @@ class Aganippe { this.contentState.format(type) } + insertAidou (url) { + this.contentState.insertAidou(url) + } + search (value, opt) { const { selectHighlight } = opt this.contentState.search(value, opt) diff --git a/src/main/createWindow.js b/src/main/createWindow.js index 80e68abd..6147d1d2 100644 --- a/src/main/createWindow.js +++ b/src/main/createWindow.js @@ -16,6 +16,9 @@ const createWindow = (pathname, options = {}) => { const { x, y, width, height } = mainWindowState const winOpt = Object.assign({ x, y, width, height }, { + webPreferences: { + webSecurity: false + }, useContentSize: true, show: false, frame: false, diff --git a/src/main/menus/edit.js b/src/main/menus/edit.js index 868b0b7c..835af502 100755 --- a/src/main/menus/edit.js +++ b/src/main/menus/edit.js @@ -58,5 +58,13 @@ export default { click: (menuItem, browserWindow) => { actions.edit(browserWindow, 'replace') } + }, { + type: 'separator' + }, { + label: 'Aidou', + accelerator: 'CmdOrCtrl+/', + click: (menuItem, browserWindow) => { + actions.edit(browserWindow, 'aidou') + } }] } diff --git a/src/main/menus/theme.js b/src/main/menus/theme.js index d0484ad7..6181bc3d 100644 --- a/src/main/menus/theme.js +++ b/src/main/menus/theme.js @@ -5,14 +5,14 @@ export default { submenu: [{ label: 'Dark', type: 'radio', - checked: true, + checked: false, click (menuItem, browserWindow) { actions.selectTheme(browserWindow, 'dark') } }, { label: 'Light', type: 'radio', - checked: false, + checked: true, click (menuItem, browserWindow) { actions.selectTheme(browserWindow, 'light') } diff --git a/src/renderer/assets/symbolIcon/index.js b/src/renderer/assets/symbolIcon/index.js index 0821f0fd..6928d609 100644 --- a/src/renderer/assets/symbolIcon/index.js +++ b/src/renderer/assets/symbolIcon/index.js @@ -1 +1 @@ -(function(window){var svgSprite='';var script=function(){var scripts=document.getElementsByTagName("script");return scripts[scripts.length-1]}();var shouldInjectCss=script.getAttribute("data-injectcss");var ready=function(fn){if(document.addEventListener){if(~["complete","loaded","interactive"].indexOf(document.readyState)){setTimeout(fn,0)}else{var loadFn=function(){document.removeEventListener("DOMContentLoaded",loadFn,false);fn()};document.addEventListener("DOMContentLoaded",loadFn,false)}}else if(document.attachEvent){IEContentLoaded(window,fn)}function IEContentLoaded(w,fn){var d=w.document,done=false,init=function(){if(!done){done=true;fn()}};var polling=function(){try{d.documentElement.doScroll("left")}catch(e){setTimeout(polling,50);return}init()};polling();d.onreadystatechange=function(){if(d.readyState=="complete"){d.onreadystatechange=null;init()}}}};var before=function(el,target){target.parentNode.insertBefore(el,target)};var prepend=function(el,target){if(target.firstChild){before(el,target.firstChild)}else{target.appendChild(el)}};function appendSvg(){var div,svg;div=document.createElement("div");div.innerHTML=svgSprite;svgSprite=null;svg=div.getElementsByTagName("svg")[0];if(svg){svg.setAttribute("aria-hidden","true");svg.style.position="absolute";svg.style.width=0;svg.style.height=0;svg.style.overflow="hidden";prepend(svg,document.body)}}if(shouldInjectCss&&!window.__iconfont__svg__cssinject__){window.__iconfont__svg__cssinject__=true;try{document.write("")}catch(e){console&&console.log(e)}}ready(appendSvg)})(window) +(function(window){var svgSprite='';var script=function(){var scripts=document.getElementsByTagName("script");return scripts[scripts.length-1]}();var shouldInjectCss=script.getAttribute("data-injectcss");var ready=function(fn){if(document.addEventListener){if(~["complete","loaded","interactive"].indexOf(document.readyState)){setTimeout(fn,0)}else{var loadFn=function(){document.removeEventListener("DOMContentLoaded",loadFn,false);fn()};document.addEventListener("DOMContentLoaded",loadFn,false)}}else if(document.attachEvent){IEContentLoaded(window,fn)}function IEContentLoaded(w,fn){var d=w.document,done=false,init=function(){if(!done){done=true;fn()}};var polling=function(){try{d.documentElement.doScroll("left")}catch(e){setTimeout(polling,50);return}init()};polling();d.onreadystatechange=function(){if(d.readyState=="complete"){d.onreadystatechange=null;init()}}}};var before=function(el,target){target.parentNode.insertBefore(el,target)};var prepend=function(el,target){if(target.firstChild){before(el,target.firstChild)}else{target.appendChild(el)}};function appendSvg(){var div,svg;div=document.createElement("div");div.innerHTML=svgSprite;svgSprite=null;svg=div.getElementsByTagName("svg")[0];if(svg){svg.setAttribute("aria-hidden","true");svg.style.position="absolute";svg.style.width=0;svg.style.height=0;svg.style.overflow="hidden";prepend(svg,document.body)}}if(shouldInjectCss&&!window.__iconfont__svg__cssinject__){window.__iconfont__svg__cssinject__=true;try{document.write("")}catch(e){console&&console.log(e)}}ready(appendSvg)})(window) diff --git a/src/renderer/components/Editor.vue b/src/renderer/components/Editor.vue index 24949172..daeed838 100644 --- a/src/renderer/components/Editor.vue +++ b/src/renderer/components/Editor.vue @@ -54,11 +54,15 @@ + + + \ No newline at end of file diff --git a/src/renderer/components/aidou/hotWords.js b/src/renderer/components/aidou/hotWords.js new file mode 100644 index 00000000..08e48a6f --- /dev/null +++ b/src/renderer/components/aidou/hotWords.js @@ -0,0 +1,117 @@ +export default [ + 'bug', + '代码有毒', + '大佬', + 'hentai', + '变态', + '40米', + '哈哈', + '嘿嘿', + '滑稽', + '原谅', + '喜欢', + '秋裤', + '盒子精', + '吃鸡', + '阿卡林', + '元旦快乐', + '新年快乐', + '康娜', + '赞', + '2b', + '正面上我', + 'bilibili', + '胖次', + '飞机', + '哲学', + '鸡鸡', + '2233', + '233', + '蕾姆', + '拉姆', + 'niconiconi', + '图样图森破', + '非战斗人员', + '天依', + '绅士', + '今天的风儿', + '战5渣', + '楼上', + '楼下', + '女装', + '吸猫', + '二次元', + '新吧唧', + 'poi', + '提督', + '咸鱼', + '滴滴', + '老司机', + '香菜', + '金馆长', + '笑', + '机智', + '撩', + '套路', + '洪荒之力', + '傲娇', + '一言不合', + '百合', + '白学家', + '电学', + '白色相册', + '诚哥', + '本子', + '香蕉君', + '金坷垃', + '舰娘', + '圣杯', + '呆毛', + '咖喱棒', + '金闪闪', + '吃土', + '小目标', + 'FFF团', + '友谊的小船', + '狗带', + '没想到你是这样的', + '懵逼', + '我好方', + '辣眼睛', + '猴赛雷', + '吓死宝宝了', + '宝宝', + '咋不上天', + '重要的事', + '城会玩', + 'A4腰', + '城会玩', + '厉害了我的哥', + '感觉身体被掏空', + '互相伤害', + '北京瘫', + '葛优躺', + '一颗赛艇', + '因吹斯汀', + '醒醒', + '社会我', + '萝莉', + '御姐', + '正太', + 'Loli', + '单身狗', + '逗比', + '坟头草', + '你开心', + '裤子都脱了', + '算我输', + '修仙', + '老哥稳', + '奶子', + '小姐姐', + '石乐志', + '皮皮虾我们走', + '我们走', + '小拳拳', + '把我的意大利' +] diff --git a/src/renderer/components/aidou/loading.vue b/src/renderer/components/aidou/loading.vue new file mode 100644 index 00000000..e10b2254 --- /dev/null +++ b/src/renderer/components/aidou/loading.vue @@ -0,0 +1,94 @@ + + + + + + \ No newline at end of file diff --git a/src/renderer/store/aidou.js b/src/renderer/store/aidou.js new file mode 100644 index 00000000..6eef5391 --- /dev/null +++ b/src/renderer/store/aidou.js @@ -0,0 +1,38 @@ +import resource from './resource' + +const state = { + aiLoading: false, + aiList: [] +} + +const mutations = { + SET_AI_LIST (state, { data, type }) { + console.log(type) + if (type === 'search') { + state.aiList = data + } else { + state.aiList = [...state.aiList, ...data] + } + }, + SET_AI_STATUS (state, bool) { + state.aiLoading = bool + } +} + +const actions = { + AI_SEARCH ({ commit }, { params, type }) { + commit('SET_AI_STATUS', true) + return resource.sogou(params) + .then(({ data, total }) => { + commit('SET_AI_LIST', { data, type }) + commit('SET_AI_STATUS', false) + return { data, total } + }) + .catch(err => { + console.log(err) + commit('SET_AI_STATUS', false) + }) + } +} + +export default { state, mutations, actions } diff --git a/src/renderer/store/index.js b/src/renderer/store/index.js index 8ceb1680..c4821a10 100644 --- a/src/renderer/store/index.js +++ b/src/renderer/store/index.js @@ -2,11 +2,13 @@ import Vue from 'vue' import Vuex from 'vuex' import editorStore from './editor' +import aidouStore from './aidou' Vue.use(Vuex) const storeArray = [ - editorStore + editorStore, + aidouStore ] const { actions, mutations, state } = storeArray.reduce((acc, s) => { diff --git a/src/renderer/store/resource.js b/src/renderer/store/resource.js new file mode 100644 index 00000000..48720c93 --- /dev/null +++ b/src/renderer/store/resource.js @@ -0,0 +1,63 @@ +import axios from 'axios' +import { serialize, merge, dataURItoBlob } from '../util' + +const CONFIG = { + SOGOU: { + API: 'https://pic.sogou.com/pics/json.jsp', + PARAMS: { + query: '', + st: 5, + start: 0, + xml_len: 100, + reqFrom: 'wap_result' + }, + HOT_SEARCH: 'https://pic.sogou.com/pic/emo/' + } +} + +const resource = { + sogou ({ query, page, size }) { + const api = CONFIG.SOGOU.API + const defParams = CONFIG.SOGOU.PARAMS + const params = merge(defParams, { + query: `${query} 表情`, + start: (page - 1) * size, + xml_len: size + }) + const queryURL = `${api}?${serialize(params)}` + return axios.get(queryURL, { withCredentials: true }).then(({ data = {} }) => { + console.log(data) + return { + data: (data.items || []).map(it => ({ + link: it.locImageLink, + suffix: it.type + })), + total: data.totalNum || 0 + } + }) + }, + fetchImgToBase64 (url) { + return axios.get(url, { responseType: 'blob' }) + .then(({ data }) => new Promise((resolve, reject) => { + const reader = new window.FileReader() + reader.onloadend = () => resolve(reader.result) + reader.onerror = reject + reader.readAsDataURL(data) + })) + }, + sm (base64) { + const api = 'https://sm.ms/api/upload' + const data = new window.FormData() + data.append('smfile', dataURItoBlob(base64, 'temp.png')) + return axios.post(api, data).then(({ data }) => { + const { data: res } = data + return { + url: res.url, + err: '', + server: 'sm' + } + }) + } +} + +export default resource diff --git a/src/renderer/util/index.js b/src/renderer/util/index.js new file mode 100644 index 00000000..b04ea4ed --- /dev/null +++ b/src/renderer/util/index.js @@ -0,0 +1,17 @@ +export function serialize (params) { + return Object.keys(params).map(key => `${key}=${params[key]}`).join('&') +} +export function merge (...args) { + return Object.assign({}, ...args) +} +export function dataURItoBlob (dataURI) { + const data = dataURI.split(';base64,') + const byte = window.atob(data[1]) + const mime = data[0].split(':')[1] + const ab = new ArrayBuffer(byte.length) + const ia = new Uint8Array(ab) + for (let i = 0; i < byte.length; i++) { + ia[i] = byte.charCodeAt(i) + } + return new window.Blob([ab], { type: mime }) +}