Skip to content

Commit

Permalink
Merge branch 'master' of github.com:obgnail/typora_plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
obgnail committed Aug 17, 2023
2 parents 061e384 + d382d78 commit 911893a
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 63 deletions.
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@
| 13 | auto_number | 章节、表格、图片、代码块等自动编号 ||
| 14 | outline | 以表格、图片、代码块形式的大纲 ||
| 15 | mindmap | 根据文档大纲一键生成思维导图 ||
| 16 | go_top | 一键到文章顶部 ||
| 17 | truncate_text | 暂时隐藏内容,提高大文件渲染性能 ||
| 18 | right_click_menu | 右键菜单统一管理、调用插件 ||
| 19 | mermaid_replace | 替换 mermaid 组件 | × |
| 20 | old_window_tab | 标签页管理(已废弃) | × |
| 16 | export_enhance | 导出 html 时避免图片丢失 ||
| 17 | go_top | 一键到文章顶部 ||
| 18 | truncate_text | 暂时隐藏内容,提高大文件渲染性能 ||
| 19 | right_click_menu | 右键菜单统一管理、调用插件 ||
| 20 | mermaid_replace | 替换 mermaid 组件 | × |
| 21 | old_window_tab | 标签页管理(已废弃) | × |

> 如果各位有其他的需求,或发现 BUG,欢迎提 issue。如果能给我颗 star ⭐ 就更好了 : )
Expand Down Expand Up @@ -180,7 +181,9 @@ JSBridge.invoke('executeJavaScript', 1, "_myValue=123; JSBridge.invoke('executeJ

中英文混排时,中文与英文之间、中文与数字之间添加空格。

快捷键:Ctrl+shift+K(如果快捷键冲突了,请在右键菜单中使用)
快捷键:ctrl+shift+K、ctrl+shift+B

> 新版本 Typora 的 ctrl+shift+K 快捷键被占用了。故提供两个快捷键,也可以在右键菜单中使用。
![md_padding](assets/md_padding.gif)

Expand Down Expand Up @@ -277,7 +280,7 @@ const BUILTIN = [
![datatables](assets/datatables.png)

> NOTE:**此脚本是有安全隐患的。不要在不信任文件中使用此插件,否则极端情况下会让你的电脑中毒**使用此脚本需要做到:将普通表格转为增强表格前需要审视表格内容,确认没有问题才可以转化。
> NOTE:**此脚本是有安全隐患的。不要在不信任文件中使用此插件,否则极端情况下会让你的电脑中毒**使用此脚本需要做到:将普通表格转为增强表格前需要审视表格内容,确认没有问题才可以转化。
其实此插件可以是提供开放能力的,实现类似于 obsidian 的 `dataview` 插件的功能。不过暂时不做,原因:

Expand Down Expand Up @@ -331,6 +334,14 @@ const BUILTIN = [


### export_enhance:导出增强

导出 html 时,将图片转为 base64,避免图片丢失。

> 此插件有一个配置为 `DOWNLOAD_NETWORK_IMAGE`,功能是下载网络图片,将也网络图片转为 base64,默认为 false。若置为 true,有可能因为网络问题导致导出超时。


### truncate_text:暂时隐藏内容,提高大文件渲染性能

大文件在 Typora 的渲染性能很糟糕,用此脚本暂时隐藏内容(只是隐藏显示,不修改文件),提高渲染性能。也可以用于防偷窥。
Expand Down
6 changes: 2 additions & 4 deletions plugin/auto_number.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,11 @@
];

const dynamicCallArgsGenerator = () => {
let arg_name, arg_value;
let arg_name = "启用";
let arg_value = "enable";
if (!!document.getElementById(config.ID)) {
arg_name = "禁用";
arg_value = "disable";
} else {
arg_name = "启用";
arg_value = "enable";
}
return [{arg_name, arg_value}]
}
Expand Down
93 changes: 93 additions & 0 deletions plugin/export_enhance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
(() => {
const config = global._pluginUtils.getPluginSetting("export_enhance");
const Path = global._pluginUtils.Package.Path;
const tempFolder = global._pluginUtils.tempFolder; // i‘d like to shit here

const isNetworkImage = src => /^https?|(ftp):\/\//.test(src);

const getCurDir = () => {
const filepath = global._pluginUtils.getFilePath();
return Path.dirname(filepath)
}

const toBase64 = imagePath => {
const bitmap = global._pluginUtils.Package.Fs.readFileSync(imagePath);
const data = Buffer.from(bitmap).toString('base64');
return `data:image;base64,${data}`;
}

const simplePromise = result => new Promise(resolve => resolve(result));

const decoMixin = {
regexp: new RegExp(`<img.*?src="(.*?)".*?>`, "gs"),
writeIdx: -1,
imageMap: {}, // map src to localFileName, use for network image only

init: () => {
decoMixin.writeIdx = -1
decoMixin.imageMap = {}
},

downloadAllImage: async (html) => {
for (let result of html.matchAll(decoMixin.regexp)) {
if (result.length !== 2 || result.index < decoMixin.writeIdx || !isNetworkImage(result[1])) continue
const src = result[1];
if (!decoMixin.imageMap.hasOwnProperty(src)) { // single flight
const filename = Math.random() + "_" + Path.basename(src);
const {state} = await JSBridge.invoke("app.download", src, tempFolder, filename);
if (state === "completed") {
decoMixin.imageMap[src] = filename;
}
}
}
},

afterExportToHtml: async (exportResult, ...args) => {
decoMixin.init();

const exportConfig = args[0];
if (!exportConfig || exportConfig["type"] !== "html" && exportConfig["type"] !== "html-plain") return exportResult;

const html = await exportResult;
decoMixin.writeIdx = html.indexOf(`id='write'`);
if (decoMixin.writeIdx === -1) return simplePromise(html);

if (config.DOWNLOAD_NETWORK_IMAGE) {
await decoMixin.downloadAllImage(html)
}

const dirname = getCurDir();
const newHtml = html.replace(decoMixin.regexp, (origin, src, srcIdx) => {
if (srcIdx < decoMixin.writeIdx) return origin;

let result = origin;
let imagePath;
try {
if (isNetworkImage(src)) {
if (!config.DOWNLOAD_NETWORK_IMAGE || !decoMixin.imageMap.hasOwnProperty(src)) return origin
const path = decoMixin.imageMap[src];
imagePath = Path.join(tempFolder, path);
} else {
imagePath = Path.join(dirname, src);
}
const base64Data = toBase64(imagePath);
result = origin.replace(src, base64Data);
} catch (e) {
console.log("export error:", e);
}
return result;
})
return simplePromise(newHtml);
}
}

global._pluginUtils.decorate(
() => (File && File.editor && File.editor.export && File.editor.export.exportToHTML),
File.editor.export,
"exportToHTML",
null,
decoMixin.afterExportToHtml,
true,
);
console.log("export_enhance.js had been injected");
})()
34 changes: 1 addition & 33 deletions plugin/global/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,7 @@
const filepath = global._pluginUtils.joinPath("./plugin/global/settings/settings.toml");
const {parse} = global._pluginUtils.requireFile("./plugin/global/toml/index.js");
const settingFile = global._pluginUtils.Package.Fs.readFileSync(filepath, 'utf8');
const settings = parse(settingFile);
registerHotKey(settings);
return settings
}

const registerHotKey = settings => {
Object.keys(settings).forEach(plugin => {
Object.keys(settings[plugin]).forEach(setting => {
if (setting.indexOf("HOTKEY") !== -1) {
const hotkey = settings[plugin][setting];
if (Array.isArray(hotkey)) {
settings[plugin][setting] = hotkey.map(ele => toHotkeyFunc(ele));
} else {
settings[plugin][setting] = toHotkeyFunc(hotkey);
}
}
})
})
}

const toHotkeyFunc = hotkeyString => {
const keyList = hotkeyString.toLowerCase().split("+").map(k => k.trim());
const ctrl = keyList.indexOf("ctrl") !== -1;
const shift = keyList.indexOf("shift") !== -1;
const alt = keyList.indexOf("alt") !== -1;
const key = keyList.filter(key => key !== "ctrl" && key !== "shift" && key !== "alt")[0];

return ev => {
return global._pluginUtils.metaKeyPressed(ev) === ctrl
&& global._pluginUtils.shiftKeyPressed(ev) === shift
&& global._pluginUtils.altKeyPressed(ev) === alt
&& ev.key.toLowerCase() === key
}
return parse(settingFile)
}

module.exports = {
Expand Down
10 changes: 9 additions & 1 deletion plugin/global/settings/settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ cmd = "cd $m && git add . && git commit -m \"message\""
# 启用插件
ENABLE = true
# 快捷键
HOTKEY = "ctrl+shift+k"
HOTKEY = ["ctrl+shift+k", "ctrl+shift+b"]


############### read_only ###############
Expand Down Expand Up @@ -388,6 +388,14 @@ CLASS_NAME = "plugin-file-counter"
LOOP_DETECT_INTERVAL = 300


############### export_enhance ###############
[export_enhance]
# 启用插件
ENABLE = true
# 是否下载网络图片(若为true,有可能因为网络问题导致超时)
DOWNLOAD_NETWORK_IMAGE = false


############### mermaid_replace ###############
[mermaid_replace]
# 启用插件
Expand Down
30 changes: 28 additions & 2 deletions plugin/global/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
(() => {
const isBetaVersion = parseInt(window._options.appVersion.split(".")[0]) === 0;

const tempFolder = File.option.tempPath;

const insertStyle = (id, css) => {
const style = document.createElement('style');
style.id = id;
Expand Down Expand Up @@ -28,7 +30,7 @@
const shiftKeyPressed = ev => !!ev.shiftKey;
const altKeyPressed = ev => !!ev.altKey;

const getPluginSetting = fixed_name => global._plugin_settings[fixed_name];
const getPluginSetting = fixed_name => global._pluginSettings[fixed_name];
const getDirname = () => global.dirname || global.__dirname;
const getFilePath = () => File.filePath || File.bundle && File.bundle.filePath;
const joinPath = (...paths) => Package.Path.join(getDirname(), ...paths);
Expand Down Expand Up @@ -103,8 +105,30 @@
}, detectInterval);
}

const toHotkeyFunc = hotkeyString => {
const keyList = hotkeyString.toLowerCase().split("+").map(k => k.trim());
const ctrl = keyList.indexOf("ctrl") !== -1;
const shift = keyList.indexOf("shift") !== -1;
const alt = keyList.indexOf("alt") !== -1;
const key = keyList.filter(key => key !== "ctrl" && key !== "shift" && key !== "alt")[0];

return ev => global._pluginUtils.metaKeyPressed(ev) === ctrl
&& global._pluginUtils.shiftKeyPressed(ev) === shift
&& global._pluginUtils.altKeyPressed(ev) === alt
&& ev.key.toLowerCase() === key
}

const hotkeyList = []
const registerWindowHotkey = (hotkey, call) => hotkey instanceof Function && hotkeyList.push({hotkey, call});
const registerWindowHotkey = (hotkey, call) => {
if (typeof hotkey === "string") {
hotkey = toHotkeyFunc(hotkey);
hotkeyList.push({hotkey, call});
} else if (hotkey instanceof Array) {
for (const h of hotkey) {
registerWindowHotkey(h, call);
}
}
};
window.addEventListener("keydown", ev => {
for (let hotkey of hotkeyList) {
if (hotkey.hotkey(ev)) {
Expand Down Expand Up @@ -150,6 +174,7 @@

module.exports = {
isBetaVersion,
tempFolder,
insertStyle,
insertStyleFile,
getPlugin,
Expand All @@ -167,6 +192,7 @@
decorateOpenFile,
decorateAddCodeBlock,
loopDetector,
toHotkeyFunc,
registerWindowHotkey,
dragFixedModal,
};
Expand Down
20 changes: 13 additions & 7 deletions plugin/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* 1. 整个插件系统向外暴露的变量:
1. global._plugins_had_injected: 是否所有的插件都已加载完毕
1. global._pluginsHadInjected: 是否所有的插件都已加载完毕
2. global._plugins: 全部的插件
3. global._pluginUtils: 通用的工具
4. global._plugin_settings: 全部的插件配置
4. global._pluginSettings: 全部的插件配置
2. global._plugins使用声明式(声明替代代码开发)
1. name: 展示的插件名
2. fixed_name: 固定的插件名(可以看作是插件的UUID)
Expand All @@ -16,7 +16,7 @@
4. 使用例子可以看collapse_paragraph.js。此插件实现了用户在不同区域(标题处点击、非标题处点击)右键菜单会有不同的第三级菜单。
*/
window.onload = () => {
global._plugins_had_injected = false;
global._pluginsHadInjected = false;
global._plugins = [
{
name: "标签页管理",
Expand Down Expand Up @@ -120,6 +120,12 @@ window.onload = () => {
src: "./plugin/truncate_text.js",
clickable: true,
},
{
name: "导出增强",
fixed_name: "export_enhance",
src: "./plugin/export_enhance.js",
clickable: false,
},
{
name: "mermaid替换",
fixed_name: "mermaid_replace",
Expand All @@ -143,6 +149,7 @@ window.onload = () => {
const loadPlugins = (join, access, dirname) => {
const promises = [];
global._plugins.forEach(plugin => {
plugin.enable = global._pluginSettings[plugin.fixed_name].ENABLE;
if (!plugin.enable) return;
const filepath = join(dirname, plugin.src);
const promise = new Promise((resolve, reject) => {
Expand Down Expand Up @@ -170,8 +177,8 @@ window.onload = () => {
})

Promise.all(promises)
.then(() => global._plugins_had_injected = true)
.catch(() => global._plugins_had_injected = true)
.then(() => global._pluginsHadInjected = true)
.catch(() => global._pluginsHadInjected = true)
}

const loadUtils = (join, dirname) => {
Expand All @@ -182,8 +189,7 @@ window.onload = () => {
const loadSettings = (join, dirname) => {
const configPath = join(dirname, "./plugin/global/settings.js");
const {pluginSettings} = reqnode(configPath);
global._plugins.forEach(plugin => plugin.enable = pluginSettings[plugin.fixed_name].ENABLE)
global._plugin_settings = pluginSettings;
global._pluginSettings = pluginSettings;
}

const load = () => {
Expand Down
4 changes: 3 additions & 1 deletion plugin/read_only.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
global._pluginUtils.insertStyle("plugin-read-only-style", css);
})()

const excludeList = config.EXCLUDE_HOTKEY.map(h => global._pluginUtils.toHotkeyFunc(h));

const isExclude = ev => {
for (const func of config.EXCLUDE_HOTKEY) {
for (const func of excludeList) {
if (func(ev)) {
return true
}
Expand Down
2 changes: 1 addition & 1 deletion plugin/right_click_menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@
}, 500)
}

global._pluginUtils.loopDetector(() => global._plugins_had_injected, appendMenu, config.LOOP_DETECT_INTERVAL);
global._pluginUtils.loopDetector(() => global._pluginsHadInjected, appendMenu, config.LOOP_DETECT_INTERVAL);

//////////////////////// 以下是声明式插件系统代码 ////////////////////////
const call = type => {
Expand Down
10 changes: 3 additions & 7 deletions plugin/window_tab/window_tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,13 +333,9 @@
filePath && openTab(filePath);
});

const hotkeyList = [config.SWITCH_NEXT_TAB_HOTKEY, config.SWITCH_PREVIOUS_TAB_HOTKEY, config.CLOSE_HOTKEY];
const opList = [nextTab, previousTab, closeActiveTab]
for (let idx = 0; idx < hotkeyList.length; idx++) {
for (let hotkey of hotkeyList[idx]) {
global._pluginUtils.registerWindowHotkey(hotkey, opList[idx]);
}
}
global._pluginUtils.registerWindowHotkey(config.SWITCH_NEXT_TAB_HOTKEY, nextTab);
global._pluginUtils.registerWindowHotkey(config.SWITCH_PREVIOUS_TAB_HOTKEY, previousTab);
global._pluginUtils.registerWindowHotkey(config.CLOSE_HOTKEY, closeActiveTab);

entities.tabBar.addEventListener("click", ev => {
const closeButton = ev.target.closest(".close-button");
Expand Down

0 comments on commit 911893a

Please sign in to comment.