Files
mixly3-server/mixly/common/modules/mixly-modules/electron/wiki-manager.js
2026-01-24 16:12:04 +08:00

284 lines
9.5 KiB
JavaScript

goog.loadJs('electron', () => {
goog.require('path');
goog.require('Mixly.Config');
goog.require('Mixly.Env');
goog.require('Mixly.Msg');
goog.require('Mixly.Electron');
goog.provide('Mixly.Electron.WikiManager');
const {
Config,
Env,
Msg,
Electron
} = Mixly;
const { WikiManager } = Electron;
const { BOARD } = Config;
const fs = Mixly.require('fs');
const fs_plus = Mixly.require('fs-plus');
const fs_extra = Mixly.require('fs-extra');
const path = Mixly.require('path');
const json2md = Mixly.require('json2md');
const electron_localshortcut = Mixly.require('electron-localshortcut');
const electron_remote = Mixly.require('@electron/remote');
const { ipcMain } = electron_remote;
class WikiPage {
constructor(indexPath, gotoInfo = null) {
this.gotoInfo = gotoInfo;
this.updateContentFile();
this.win = Electron.newBrowserWindow(indexPath);
this.isDestroyed = false;
this.addReceiveCommandEvent();
this.addLocalShortcutEvent();
this.win.on('close', () => {
this.isDestroyed = true;
});
$(window).unload(() => {
if (!this.isDestroyed)
this.win.close();
});
}
addLocalShortcutEvent() {
//打开或关闭开发者工具
electron_localshortcut.register(this.win, 'CmdOrCtrl+Shift+I', () => {
if (!this.isDestroyed)
this.win.webContents.toggleDevTools();
});
//重载页面
electron_localshortcut.register(this.win, 'CmdOrCtrl+R', () => {
this.reload();
});
}
addReceiveCommandEvent() {
ipcMain.on('command', (event, command) => {
if (typeof command !== 'object') return;
switch (command.func) {
case 'getPath':
this.updateWiki();
break;
}
});
}
sendCommand(command) {
if (this.isDestroyed || typeof command !== 'object') return;
this.win.webContents.send('command', command);
}
reload() {
if (!this.isDestroyed) {
this.updateContentFile();
this.win.reload();
}
}
getPagePath(contentPath, contentList) {
if (typeof contentList !== 'object' || !contentPath.length) return null;
if (contentPath.length === 1) {
for (let key in contentList) {
const child = contentList[key];
if (child?.link?.title !== contentPath[0]) {
continue;
}
const { title, source } = child.link;
if (title !== contentPath[0] || typeof source !== 'string') {
return null;
}
try {
const filePath = source.match(/(?<=(\?file=))[^\s]*/g);
if (filePath?.length) {
return filePath[0];
}
} catch (error) {
console.log(error);
}
return null;
}
return null;
} else {
for (let key in contentList) {
const child = contentList[key];
if (child
&& child.length === 2
&& child[0].h5 === contentPath[0]) {
let childPath = [ ...contentPath ];
childPath.shift();
return this.getPagePath(childPath, child[1].ul);
}
}
}
}
goto(pageList, scrollPos) {
const args = [];
const pagePath = this.getPagePath(pageList, this.contentList);
if (!pageList) return;
args.push(pagePath);
scrollPos && args.push(scrollPos);
this.sendCommand({
func: 'goto',
args
});
this.win.focus();
}
updateContentFile() {
const wikiContentPath = path.join(Env.boardDirPath, 'wiki/content.md');
const defaultWikiPath = path.join(Env.boardDirPath, 'wiki/wiki-libs/' + Msg.nowLang);
const wikiHomePagePath = path.join(defaultWikiPath, 'home');
const thirdPartyLibsPath = path.join(Env.boardDirPath, 'libraries/ThirdParty/');
const changelogPath = path.join(Env.clientPath, 'CHANGELOG');
const wikiList = [];
if (fs_plus.isFileSync(wikiHomePagePath + '.md'))
wikiList.push({
h4: {
link: {
title: Msg.Lang['wiki.home'],
source: '?file=' + encodeURIComponent(wikiHomePagePath)
}
}
});
if (fs_plus.isDirectorySync(defaultWikiPath)) {
const childContentList = this.getContentJson(defaultWikiPath, BOARD.boardType);
if (childContentList)
wikiList.push(childContentList);
}
if (fs_plus.isDirectorySync(thirdPartyLibsPath)) {
const libsName = fs.readdirSync(thirdPartyLibsPath);
for (let name of libsName) {
const libWikiPath = path.join(thirdPartyLibsPath, name , 'wiki', Msg.nowLang);
if (fs_plus.isDirectorySync(libWikiPath)) {
const childContentList = this.getContentJson(libWikiPath, name);
if (childContentList) {
wikiList.push(childContentList);
}
}
}
}
this.contentList = wikiList;
try {
const md = json2md(wikiList);
const lineList = md.split('\n');
for (let i = 0; i < lineList.length; i++) {
if (!lineList[i].replaceAll(' ', '')) {
lineList.splice(i, 1);
i--;
} else {
if (!lineList[i].indexOf('#####'))
lineList[i] = '\n' + lineList[i];
}
}
fs_extra.outputFile(wikiContentPath, lineList.join('\n'));
} catch (error) {
console.log(error);
}
}
updateWiki() {
const args = [
{
default: path.join(Env.boardDirPath, 'wiki/wiki-libs/'),
thirdParty: path.join(Env.boardDirPath, 'libraries/ThirdParty/'),
content: path.join(Env.boardDirPath, 'wiki/content.md')
}
];
if (this.gotoInfo) {
const { page, scrollPos } = this.gotoInfo;
const pagePath = this.getPagePath(this.gotoInfo.page, this.contentList);
if (pagePath) {
const goto = [];
goto.push(pagePath);
scrollPos && goto.push(scrollPos);
args[0].goto = goto;
}
this.gotoInfo = null;
}
this.sendCommand({
func: 'setPath',
args
});
}
getContentJson(dirPath, title = null) {
const dirNameList = path.basename(dirPath).split('-');
if (dirNameList.length !== 2 && !title) return null;
const contentList = [];
contentList.push({ h5: title ?? dirNameList[1] });
contentList.push({ ul: [] });
const { ul } = contentList[1];
const keyList = fs.readdirSync(dirPath);
for (let key of keyList) {
const nowPath = path.join(dirPath, key);
if (fs_plus.isDirectorySync(nowPath)) {
const childContentList = this.getContentJson(nowPath);
if (childContentList && childContentList[1].ul.length)
ul.push(childContentList);
} else {
const extname = path.extname(key);
if (extname !== '.md') continue;
const fileNameList = path.basename(key, '.md').split('-');
if (fileNameList.length !== 2) continue;
const newPath = path.join(path.dirname(nowPath), path.basename(key, '.md'));
ul.push({ link: { title: fileNameList[1], source: '?file=' + encodeURIComponent(newPath) + ' \"' + fileNameList[1] + '\"' } });
}
}
return contentList;
}
}
WikiManager.WikiPage = WikiPage;
WikiManager.openWiki = (gotoInfo) => {
const goto = (gotoInfo && typeof gotoInfo === 'object') ? gotoInfo[Msg.nowLang] : null;
if (!WikiManager.wiki || WikiManager.wiki.isDestroyed) {
const wikiPath = path.join(Env.indexDirPath, '../common/wiki/index.html');
if (fs_plus.isFileSync(wikiPath)) {
WikiManager.wiki = new WikiPage(wikiPath, goto);
} else {
layer.msg(Msg.Lang['wiki.pageNotFound'], { time: 1000 });
}
} else {
const { win } = WikiManager.wiki;
win && win.focus();
if (goto) {
const { page, scrollPos } = goto;
WikiManager.wiki.goto(page, scrollPos);
}
}
}
WikiManager.registerContextMenu = () => {
const openWikiPage = {
displayText: Msg.Lang['wiki.open'],
preconditionFn: function(scope) {
const { wiki } = scope.block;
if (typeof wiki === 'object') {
if (typeof wiki[Msg.nowLang] === 'object'
&& typeof wiki[Msg.nowLang].page === 'object') {
return 'enabled';
}
}
return 'hidden';
},
callback: function(scope) {
const { wiki } = scope.block;
WikiManager.openWiki(wiki);
},
scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK,
id: 'wiki_open',
weight: 200
};
Blockly.ContextMenuRegistry.registry.register(openWikiPage);
}
});