diff --git a/package.json b/package.json index 8d6e086..8f3e7b9 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,8 @@ "download-git-repo": "^3.0.2", "electron-store": "^8.0.0", "marked": "^2.0.7", + "node-fetch": "^2.6.1", + "puppeteer-core": "^10.0.0", "query-string": "^7.0.0", "uuid": "^8.3.2", "vue": "^2.5.16", diff --git a/src/main/api.js b/src/main/api.js index 6234c93..8aff460 100644 --- a/src/main/api.js +++ b/src/main/api.js @@ -1,12 +1,20 @@ import {app, BrowserWindow} from 'electron'; import {getlocalDataFile, saveData, getData} from './common/utils'; import path from "path"; -import marked from 'marked'; -const rendererMD = new marked.Renderer(); + +const puppeteer = require("puppeteer-core"); +const pie = require("puppeteer-in-electron") const appPath = path.join(getlocalDataFile()); const dbPath = path.join(appPath, './db.json'); +let browser +pie.initialize(app).then(res => { + pie.connect(app, puppeteer).then(b => { + browser = b; + }) +}) + export default { getPath(arg) { return app.getPath(arg.name); @@ -104,34 +112,28 @@ export default { }, ubrowser: { - goto: ({md, title}) => { - marked.setOptions({ - renderer: rendererMD, - gfm: true, - tables: true, - breaks: false, - pedantic: false, - sanitize: false, - smartLists: true, - smartypants: false - }); - const htmlContent = marked(md); - const win = new BrowserWindow({ - height: 600, - useContentSize: true, - width: 788, - title, - webPreferences: { - webSecurity: false, - enableRemoteModule: true, - backgroundThrottling: false, - webviewTag: true, - nodeIntegration: true // 在网页中集成Node - } - }); - win.loadURL('data:text/html;charset=UTF-8,' + encodeURIComponent(htmlContent)) + goto: async ({winId}) => { + const win = BrowserWindow.fromId(winId); + await win.loadURL(url); + }, + async value({selector, value, winId}) { + const win = BrowserWindow.fromId(winId); + const page = await pie.getPage(browser, win); + const nd = await page.$(selector); + nd.type(value); + }, + + async click({selector, winId}) { + const win = BrowserWindow.fromId(winId); + const page = await pie.getPage(browser, win); + const nd = await page.$(selector); + nd.click(); + }, + + async run(options) { + const win = BrowserWindow.fromId(options.winId); + win.setSize(options.width || 800, options.height || 600) win.once('ready-to-show', () => win.show()); - return win.id - } + }, } } diff --git a/src/main/common.js b/src/main/common.js index 2783b5d..96ea579 100644 --- a/src/main/common.js +++ b/src/main/common.js @@ -16,6 +16,17 @@ export default function init(mainWindow) { mainWindow.show(); }); + ipcMain.on('init-shortcut', (event) => { + globalShortcut.register('Esc', () => { + mainWindow.show(); + event.sender.send('init-rubick'); + }); + globalShortcut.register('ctrl+d', () => { + event.sender.send('new-window'); + }); + }) + + ipcMain.on('msg-trigger', async (event, arg) => { const window = arg.winId ? BrowserWindow.fromId(arg.winId) : mainWindow const operators = arg.type.split('.'); @@ -23,7 +34,7 @@ export default function init(mainWindow) { operators.forEach((op) => { fn = fn[op]; }); - const data = fn(arg, window); + const data = await fn(arg, window); event.sender.send(`msg-back-${arg.type}`, data); }); @@ -41,6 +52,7 @@ export default function init(mainWindow) { width: 788, titleBarStyle: 'hiddenInset', title: '拉比克', + show: false, webPreferences: { webSecurity: false, enableRemoteModule: true, diff --git a/src/renderer/App.vue b/src/renderer/App.vue index f6a7d19..8113bc0 100644 --- a/src/renderer/App.vue +++ b/src/renderer/App.vue @@ -77,6 +77,10 @@ export default { } }, mounted() { + // 注册快捷键 + ipcRenderer.send('init-shortcut'); + ipcRenderer.on('init-rubick', this.closeTag); + ipcRenderer.on('new-window', this.newWindow); const searchNd = document.getElementById('search'); searchNd && searchNd.addEventListener('keydown', this.checkNeedInit) }, @@ -108,18 +112,19 @@ export default { path: '/home', }); }, + newWindow() { + ipcRenderer.send('new-window', { + ...this.selected, + ...this.$route.query, + }); + this.closeTag(); + }, goMenu() { if (this.selected && this.selected.key === 'plugin-container') { const pluginMenu = [ { label: '分离窗口', - click: () => { - ipcRenderer.send('new-window', { - ...this.$route.query, - ...this.selected - }); - this.closeTag(); - } + click: this.newWindow }, { label: '开发者工具', diff --git a/static/preload.js b/static/preload.js index 6a4fb83..f5cb615 100644 --- a/static/preload.js +++ b/static/preload.js @@ -1,3 +1,5 @@ +const marked = require("marked"); +const rendererMD = new marked.Renderer(); const path = require('path'); let filePath = ''; @@ -20,6 +22,7 @@ const {ipcRenderer, nativeImage, clipboard, remote} = require('electron'); const currentWindow = remote.getCurrentWindow(); const winId = currentWindow.id; +const BrowserWindow = remote.BrowserWindow; function convertImgToBase64(url, callback, outputFormat){ var canvas = document.createElement('CANVAS'), @@ -174,16 +177,75 @@ window.utools = window.rubick = { ipcRenderer.sendToHost('setFeature', {feature}); }, ubrowser: { - goto(md, title) { - ipcRenderer.send('msg-trigger', { - type: 'ubrowser.goto', - md, title, + winId: '', + async goto(md, opts) { + const objExp = new RegExp(/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/); + let winId; + let win; + win = new BrowserWindow({ + show: false, + title: typeof opts === 'object' ? '' : opts, + webPreferences: { + webSecurity: false, + enableRemoteModule: true, + backgroundThrottling: false, + webviewTag: true, + nodeIntegration: true // 在网页中集成Node + } }); - return utools.ubrowser; + if(objExp.test(md) && md.indexOf('http') === 0) { + await win.loadURL(md); + winId = win.id; + } else { + marked.setOptions({ + renderer: rendererMD, + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + smartLists: true, + smartypants: false + }); + const htmlContent = marked(md); + win.loadURL('data:text/html;charset=UTF-8,' + encodeURIComponent(htmlContent)) + win.once('ready-to-show', () => win.show()); + winId = win.id; + } + return { + value(selector, value) { + ipcRenderer.send('msg-trigger', { + type: 'ubrowser.value', + winId, + selector, value + }); + return new Promise(resolve => { + ipcRenderer.once(`msg-back-ubrowser.value`, (e, result) => { + resolve(this) + }); + }) + }, + click(selector) { + ipcRenderer.send('msg-trigger', { + type: 'ubrowser.click', + winId, + selector, + }); + return new Promise(resolve => { + ipcRenderer.once(`msg-back-ubrowser.click`, (e, result) => { + resolve(this) + }); + }) + }, + run(options) { + ipcRenderer.send('msg-trigger', { + type: 'ubrowser.run', + winId, + ...options + }); + } + } }, - run() { - - } } } require(path.join(filePath, '../preload.js'));