Skip to content

Commit f4a28a7

Browse files
committedJun 1, 2023
feat: 新增自定义处理函数配置
1 parent ef435aa commit f4a28a7

File tree

6 files changed

+206
-7
lines changed

6 files changed

+206
-7
lines changed
 

‎src/i18n/en_US.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"importer": "Importer",
33
"selectFile": "Select file",
4-
"cancel": "Cancel",
54
"startImport": "Single import",
65
"importerLoaded": "Importer loaded",
76
"importerUnloaded": "Importer unloaded",
@@ -35,5 +34,16 @@
3534
"tempCountExists": "Please clean up the temporary files before batch import",
3635
"reportBug1": "Encounter problems? , to the developer terwer ",
3736
"reportBug2": "feedback",
38-
"reportBug3": " bar~"
37+
"reportBug3": " bar~",
38+
"setting": "setting",
39+
"cancel": "Cancel",
40+
"save": "Save",
41+
"customFnHandler": "Custom handler",
42+
"customFnSwitch": "Custom handler switch",
43+
"customFnSwitchTips": "Enable or disable custom handlers",
44+
"customFnHandlerTips": "You can customize the processing function here, and it will be called automatically during the import process. Please note: modifying this may cause the import to not work. If there is a problem, you can disable the custom processing function",
45+
"customFnHandlerPlaceholder": "Custom handler",
46+
"enableCustomFn": "Enable custom functions",
47+
"enableCustomFnTips": "Are you sure you want to enable custom functions? This action may cause imports to be unavailable. Please confirm that you have understood how custom functions work?",
48+
"importConfigSaveSuccess": "Configuration saved successfully"
3949
}

‎src/i18n/zh_CN.json

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"importer": "导入插件",
33
"selectFile": "选择文件",
4-
"cancel": "取消",
54
"startImport": "单个导入",
65
"importerLoaded": "导入工具已加载",
76
"importerUnloaded": "导入工具已卸载",
@@ -28,7 +27,7 @@
2827
"importFolder": "批量导入",
2928
"importFolderTip": "支持混合.epub,.docx,.opml",
3029
"importNotRecursive1": "1、不递归",
31-
"importNotRecursive2": "2、不支持MD,批量导入MD请使用笔记本自带功能",
30+
"importNotRecursive2": "2、不支持MD,批量导入MD请使用笔记本自带功能",
3231
"importNotRecursive3": "3、不支持html,因为安全限制,浏览器现在无法获取绝对路径,可通过单个导入(支持资源文件)",
3332
"importTipNotAllowed": "不允许的文件类型:",
3433
"importError": "导入出错:",
@@ -39,5 +38,16 @@
3938
"tempCountExists": "请先清理临时文件在进行批量导入",
4039
"reportBug1": "遇到问题? 发邮件到 youweics@163.com 或者 给开发者 terwer ",
4140
"reportBug2": "反馈一下",
42-
"reportBug3": " 吧~"
41+
"reportBug3": " 吧~",
42+
"setting": "设置",
43+
"cancel": "取消",
44+
"save": "保存",
45+
"customFnHandler": "自定义处理函数",
46+
"customFnSwitch": "自定义处理函数开关",
47+
"customFnSwitchTips": "启用或者禁用自定义处理函数",
48+
"customFnHandlerTips": "可以在这里自定义处理函数,导入过程中会自动调用,请注意:修改此处可能会导致导入不工作,若出现问题可禁用自定义处理函数。正则表达式在线测试可参考:",
49+
"customFnHandlerPlaceholder": "自定义处理函数",
50+
"enableCustomFn": "启用自定义函数",
51+
"enableCustomFnTips": "确认要启用自定义函数吗,此操作可能导致导入不可用,请确认您已经了解自定义函数的工作原理?",
52+
"importConfigSaveSuccess": "配置保存成功"
4353
}

‎src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
* questions.
2424
*/
2525

26-
import { App, IObject, Plugin } from "siyuan"
26+
import { App, getFrontend, IObject, Plugin } from "siyuan"
2727
import { createLogger } from "./utils/simple-logger"
2828
import KernelApi from "./api/kernel-api"
2929
import { isDev, mediaDir } from "./Constants"
@@ -41,10 +41,13 @@ import { simpleLogger } from "zhi-lib-base"
4141
export default class ImporterPlugin extends Plugin {
4242
public logger
4343
public kernelApi: KernelApi
44+
public isMobile: boolean
4445

4546
constructor(options: { app: App; id: string; name: string; i18n: IObject }) {
4647
super(options)
4748

49+
const frontEnd = getFrontend()
50+
this.isMobile = frontEnd === "mobile" || frontEnd === "browser-mobile"
4851
this.logger = simpleLogger("index", "importer", isDev)
4952
this.kernelApi = new KernelApi()
5053
}

‎src/lib/ImportSetting.svelte

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<!--
2+
- Copyright (c) 2023, Terwer . All rights reserved.
3+
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
-
5+
- This code is free software; you can redistribute it and/or modify it
6+
- under the terms of the GNU General Public License version 2 only, as
7+
- published by the Free Software Foundation. Terwer designates this
8+
- particular file as subject to the "Classpath" exception as provided
9+
- by Terwer in the LICENSE file that accompanied this code.
10+
-
11+
- This code is distributed in the hope that it will be useful, but WITHOUT
12+
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
- version 2 for more details (a copy is included in the LICENSE file that
15+
- accompanied this code).
16+
-
17+
- You should have received a copy of the GNU General Public License version
18+
- 2 along with this work; if not, write to the Free Software Foundation,
19+
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
-
21+
- Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com
22+
- or visit www.terwer.space if you need additional information or have any
23+
- questions.
24+
-->
25+
26+
<script lang="ts">
27+
import ImporterPlugin from "../index"
28+
import { onMount } from "svelte"
29+
import { confirm, showMessage } from "siyuan"
30+
import { loadImporterConfig, saveImporterConfig } from "../store/config"
31+
32+
export let pluginInstance: ImporterPlugin
33+
export let dialog
34+
35+
let customFnSwitch = false
36+
let customFn
37+
let importerConfig = {}
38+
39+
const onSaveSetting = async () => {
40+
dialog.destroy()
41+
42+
importerConfig.customFnSwitch = customFnSwitch
43+
importerConfig.customFn = customFn
44+
await saveImporterConfig(pluginInstance, importerConfig)
45+
pluginInstance.logger.info("saved important config =>", importerConfig)
46+
showMessage(`${pluginInstance.i18n.importConfigSaveSuccess}`, 2000, "info")
47+
}
48+
49+
const onCancel = async () => {
50+
dialog.destroy()
51+
}
52+
53+
const updateSwitch = (event) => {
54+
event.stopPropagation()
55+
56+
if (!customFnSwitch) {
57+
confirm(
58+
`⚠️${pluginInstance.i18n.enableCustomFn}`,
59+
`${pluginInstance.i18n.enableCustomFnTips}`,
60+
() => {
61+
const inputEl = document.querySelector("#customFnSwitch")
62+
inputEl.checked = customFnSwitch
63+
},
64+
() => {
65+
customFnSwitch = !customFnSwitch
66+
}
67+
)
68+
}
69+
}
70+
71+
onMount(async () => {
72+
// 加载配置
73+
importerConfig = await loadImporterConfig(pluginInstance)
74+
75+
customFnSwitch = importerConfig.customFnSwitch ?? false
76+
customFn =
77+
importerConfig.customFn ??
78+
`
79+
// 您可以参考这个案例进行修改,注意:请勿修改方法名,只需修改实现即可
80+
// 将字符串中形如"xxx^yyy"的部分替换成"xxx"
81+
export function customFn(mdText) {
82+
const regex = /\\^\\(\\[.*[0-9].*]\\(#.*#.*\\)\\)/g // 匹配格式为 ^[[数字]](#链接) 的脚注
83+
return mdText.replace(regex, "") // 使用空字符串替换匹配到的脚注
84+
}
85+
`
86+
})
87+
</script>
88+
89+
<div class="config__tab-container">
90+
<label class="fn__flex b3-label">
91+
<div class="fn__flex-1">
92+
{pluginInstance.i18n.customFnSwitch}
93+
<div class="b3-label__text">{pluginInstance.i18n.customFnSwitchTips}</div>
94+
</div>
95+
<span class="fn__space" />
96+
<input
97+
id="customFnSwitch"
98+
class="b3-switch fn__flex-center"
99+
type="checkbox"
100+
on:click={(event) => updateSwitch(event)}
101+
bind:checked={customFnSwitch}
102+
/>
103+
</label>
104+
105+
<label class="fn__flex b3-label">
106+
<div class="fn__flex-1">
107+
{pluginInstance.i18n.customFnHandler}
108+
<div class="b3-label__text">
109+
{pluginInstance.i18n.customFnHandlerTips}
110+
<a href="https://www.regextester.com" target="_blank">https://www.regextester.com</a>
111+
</div>
112+
<div class="fn__hr" />
113+
<textarea
114+
class="b3-text-field fn__block"
115+
placeholder={pluginInstance.i18n.customFnHandlerPlaceholder}
116+
rows="10"
117+
spellcheck="false"
118+
bind:value={customFn}
119+
/>
120+
</div>
121+
</label>
122+
123+
<div class="b3-dialog__action">
124+
<button class="b3-button b3-button--cancel" on:click={onCancel}>{pluginInstance.i18n.cancel}</button>
125+
<div class="fn__space" />
126+
<button class="b3-button b3-button--text" on:click={onSaveSetting}>{pluginInstance.i18n.save}</button>
127+
</div>
128+
</div>

‎src/topbar.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424
*/
2525

2626
import ImporterPlugin from "./index"
27-
import { Dialog, getFrontend } from "siyuan"
27+
import { Dialog, getFrontend, Menu } from "siyuan"
2828
import ImportForm from "./lib/ImportForm.svelte"
2929
import { iconImporter } from "./utils/svg"
30+
import ImportSetting from "./lib/ImportSetting.svelte"
3031

3132
/**
3233
* 顶栏按钮
@@ -45,6 +46,7 @@ export async function initTopbar(pluginInstance: ImporterPlugin) {
4546
pluginInstance.logger.info(`this.i18n.importer added toolbar`)
4647
},
4748
})
49+
4850
topBarElement.addEventListener("click", async () => {
4951
const frontEnd = getFrontend()
5052
const isMobile = frontEnd === "mobile" || frontEnd === "browser-mobile"
@@ -62,4 +64,49 @@ export async function initTopbar(pluginInstance: ImporterPlugin) {
6264
},
6365
})
6466
})
67+
68+
// 添加右键菜单
69+
topBarElement.addEventListener("contextmenu", () => {
70+
let rect = topBarElement.getBoundingClientRect()
71+
// 如果获取不到宽度,则使用更多按钮的宽度
72+
if (rect.width === 0) {
73+
rect = document.querySelector("#barMore").getBoundingClientRect()
74+
}
75+
initContextMenu(pluginInstance, rect)
76+
})
77+
78+
const initContextMenu = async (pluginInstance: ImporterPlugin, rect: DOMRect) => {
79+
const menu = new Menu("importerContextMenu")
80+
81+
// 设置
82+
menu.addItem({
83+
iconHTML: iconImporter.iconSetting,
84+
label: pluginInstance.i18n.setting,
85+
click: () => {
86+
const settingId = "siyuan-importing-setting"
87+
const d = new Dialog({
88+
title: `${pluginInstance.i18n.setting} - ${pluginInstance.i18n.importer}`,
89+
content: `<div id="${settingId}"></div>`,
90+
width: pluginInstance.isMobile ? "92vw" : "720px",
91+
})
92+
new ImportSetting({
93+
target: document.getElementById(settingId) as HTMLElement,
94+
props: {
95+
pluginInstance: pluginInstance,
96+
dialog: d,
97+
},
98+
})
99+
},
100+
})
101+
102+
if (pluginInstance.isMobile) {
103+
menu.fullscreen()
104+
} else {
105+
menu.open({
106+
x: rect.right,
107+
y: rect.bottom,
108+
isLeft: true,
109+
})
110+
}
111+
}
65112
}

‎src/utils/svg.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@
2525

2626
export const iconImporter = {
2727
iconImporter: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M352 96l64 0c17.7 0 32 14.3 32 32l0 256c0 17.7-14.3 32-32 32l-64 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l64 0c53 0 96-43 96-96l0-256c0-53-43-96-96-96l-64 0c-17.7 0-32 14.3-32 32s14.3 32 32 32zm-9.4 182.6c12.5-12.5 12.5-32.8 0-45.3l-128-128c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L242.7 224 32 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l210.7 0-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l128-128z"/></svg>`,
28+
iconSetting: `<span class="importer-menu-icon"><svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512"><path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/></svg></span>`,
2829
}

0 commit comments

Comments
 (0)