连续点击 openAny,小代码,大作用,让一切触手可达。
缘起
由于思源命令功能较弱,很多系统功能不方便被代码打开,obsidian 这方面较有优势,ob 的命令丰富,可任意调用。
再加上 ob 的插件有 quickadd 及 commander 的宏定义,使其几乎无所不能,任意发挥。
然临渊羡鱼,不如退而结网,突发奇想就开发了这个 openAny 代码片段,意思是打开一切,这意味着思源大部分的功能都可以通过它来打开。
它通过模拟点击,模拟输入和模拟快捷键实现对任意功能的调用,并支持通过 invoke 回调函数来实现那些模拟操作无法实现或较难实现的功能。
功能
支持多个元素的链式点击或文本输入或模拟按键等。
使用场景介绍
这个功能的核心是通过代码模拟用户操作,类似于自动化脚本或宏录制。以往需要手动完成的操作,例如点击按钮、输入文字、调用菜单功能等,现在都可以通过编写代码来实现自动化处理。这种技术可以极大地解放双手,帮助用户高效完成重复性任务。
主要实现方式包括模拟点击、按键输入、触发回调函数等。通过这些方法,您可以轻松实现许多实用功能,例如:
- 快速打开设置:无需手动导航到复杂的菜单路径。
- 批量添加样式:为选中的文字快速应用特定样式。
- 快捷键注册:将隐藏在深层菜单中的功能绑定到快捷键上,大幅提升操作效率。
- 自定义工具栏:将常用功能直接添加到工具栏或编辑器导航中,方便随时调用。
- 快速打开外网搜索,翻译,咨询 AI 等: 通过 showOptionsMenu 可以弹出选择项。
- 快捷输入,文字补全等: 通过
getCharsBeforeCursor
可以获取前导文字用来补全,showInputBox
则可弹出输入框,可以用来快速输入,问 AI 等。
您可以通过编写代码片段(如在 runjs
代码块中)或直接嵌入自己的项目代码中,来注册快捷键或定义自动化操作逻辑。这些代码可以直接在控制台运行,验证其效果。
示例说明
为了更好地理解这些功能的实际应用,您可以参考以下示例代码。将其粘贴到开发者工具控制台中执行,即可观察其效果。
通过这种方式,您可以快速利用代码实现自动化操作,并根据实际需求进行扩展和定制。无论是优化工作流还是提升操作效率,都能带来显著的价值!
基本使用
调用方式:
注意:选择符尽量全局唯一,但只要能达到目的且不会产生歧义及副作用即可。
openAny.click('').clicks('','').clicks(['']).press('alt+p').pressByKeymap('config').sleep(100).invoke(({})=>{}).el('').input('').sendText('');
openAny.addKeymap('alt+z', (event)=>{}) // 注册快捷键
openAny.invoke(({sleep, ...args})=>{}) // 通过函数执行某些操作,返回值放在openAny.prev中,通过await openAny.getInvokeReturn()获取;【注意】invoke中使用openAny.xx()前面不能用await,需要await的需用new OpenAny().xx()代替,因为await会与上层链相互等待造成死锁
openAny.el('').selectText('some text', element).press('', element); // 触发选中文本,并等待后续操作,可参考举例说明部分的示例
openAny.press('mouseright'); // 模拟鼠标按右键
openAny.press('mousemiddle'); // 模拟鼠标按中键
openAny.press('mouseover'); // 模拟鼠标悬停
openAny.press('ctrl+mouseleft') // 模拟鼠标ctrl+单击
openAny.on('', (args)=>{}) // 绑定思源事件总线
openAny.off('', handler) // 解绑思源事件总线
openAny.emit('', data) // 触发自定义事件
new OpenAny().click(''); // new 新实例方式调用,推荐
openAny.showMessage().click(''); // 开启出错是发送通知消息,参数true显示消息,false不显示消息,默认true (但未调用此方法时,openAny默认是false)
openAny.resetChain().click(''); // 如果某些未知异常导致openAny假死状态时,可以通过resetChain复活,如果是new OpenAny().xxx();方式没有这个问题
注意,默认已经暴露了一个 openAny 的实例,如果 new 新的实例,已经通过 openAny 注册的按键,关联属性等在实例外部不能共享,因为每个实例是独立的。
click 的第二个参数可以传递父元素对象或选中符,这样的话,这个元素的获取就在父元素下获取。
clicks 要想传递父元素,第一个参数必须传数组,然后第二个元素传父元素对象或选择符即可。
press 的第二个参数也可以传一个元素或选择符,作为在哪个元素上按键,默认是 body,编辑器里的有些操作需要作用域编辑器上的,这时只需要传.protyle-wysiwyg 元素即可。
也可以多个分别分开调用,比如:
await openAny.click('');
await openAny.click('');
await openAny.press('');
注意,分开调用时,如果没用 await 中间混入了其他代码可能导致执行顺序混乱,但 openAny 的执行顺序还是调用的顺序,建议混用时使用 await 以保证代码清晰度。
注意,模拟按键的默认是在 document.body 上触发,某些操作如果想作用到编辑器中,可能需要在第二个参数中传递 .protyle-wysiwyg
dom 元素。
另外,一些特殊按键可能无法生效,比如 ctrl+v 等。
或用 try...catch 捕获错误,比如:
try {
openAny.click('').clicks('','');
} catch(e) {
console.log(e);
}
注意,这里必须加 await,否则捕获不到异常,只能在控制台打印。
这里有点问题,由于无法区分是否使用 try 情况,所以一般出现错误时都会在控制台打印错误信息,方便调试查看,无论是否 catch 错误,但不影响正常使用;另外,如果开启 showMessage,则也会发送错误通知,无论是否 catch 错误,如果介意通知,可以不使用 showMessage,而在逻辑中自行通知。
或者
openAny.click('').click('').catch((e)=>{console.error("捕获错误:", e);});
说明:这里是单实例实现链式调用是有弊端的,比如,意外未知异常可能导致 openAny 假死,需要显示掉 openAny.resetChain()才能恢复,谨慎起见,也可以每次执行前调用一次 resetChain,但还是建议尽量使用 new OpenAny()。
添加到顶栏
如果你想把代码放到顶栏,可以先安装 runjs 插件,然后在任意文档插入 js 代码块,然后输入类似下面的代码
async function main() {
// your code here
}
main();
plugin.saveAction(thisBlock.id, "your code name");
然后,在代码块的右侧选择插件->runjs-> 运行代码即可。
使用下面这个 css 可以让 runjs 顶栏按钮变红,更容易从众多按钮中分辨。
#plugin_sy-run-js_0 svg {
color: deeppink;
}
也可以先用 openAny.addKeymap 设置为快捷键映射,然后使用工具栏自定义插件实现。
添加到编辑器顶部导航栏
可以通过类似的示例添加按钮到编辑器导航栏
// 比如添加移动按钮到编辑器顶部导航栏
setTimeout(() => {
openAny.invoke(({ onProtyleLoad, showMessage }) => {
onProtyleLoad(protyle => {
// 发布服务下不显示
if (window.siyuan.config.readonly) return;
// 创建按钮
if (protyle?.querySelector('.protyle-breadcrumb [data-type="move"]')) return;
const exitFocusBtn = protyle.querySelector('.protyle-breadcrumb [data-type="exit-focus"]');
if (!exitFocusBtn) return;
const moveHtml = `<button class="block__icon fn__flex-center ariaLabel" aria-label="移动" data-type="move"><svg><use xlink:href="#iconMove"></use></svg></button>`;
exitFocusBtn.insertAdjacentHTML('afterend', moveHtml);
const moveBtn = protyle.querySelector('.protyle-breadcrumb [data-type="move"]');
if (!moveBtn) return;
// 点击事件
moveBtn.addEventListener('click', async () => {
// 锁定状态下不可修改
const icon = protyle?.querySelector('button[data-type="readonly"] use')?.getAttributeNS('http://www.w3.org/1999/xlink', 'href');
if (icon === '#iconLock') {
showMessage('锁定状态不可用');
return
}
// 模拟点击移动菜单
openAny.click('.protyle-breadcrumb [data-type="doc"]', protyle).click('#commonMenu[data-name="titleMenu"] button[data-id="move"]');
});
});
});
}, 1000);
说明:
1 这里使用 setTimeout 等待 openAny 加载完毕
2 使用 openAny.invoke 注册回调函数,当然也可以直接写代码,只不过 invoke 回调中会有一些通用函数方便使用
3 使用 invoke 自带的 onProtyleLoad 函数监听编辑器加载事件,在这个事件中把按钮写入到编辑器导航栏
4 最后在按钮事件中,调用 openAny.click 模拟菜单点击事件打开移动操作对话框
5 这里看似很复杂,其实核心代码只有这一句 openAny.click('.protyle-breadcrumb [data-type="doc"]', protyle).click('#commonMenu[data-name="titleMenu"] button[data-id="move"]');
,前面的都是创建按钮相关操作。
注意, invoke 的返回值放在 openAny.prev 中,通过 await openAny.getInvokeReturn();
获取
【注意】 invoke 中使用 openAny.xx()前面不能用 await,需要 await 的需用 new OpenAny().xx()代替,因为 await 会与上层链相互等待造成死锁
invoke 的回调函数 callback 的参数有:
prev, // 上一个调用的元素或返回值
sleep,
whenElementExist,
showMessage,
showErrorMessage,
querySql,
fetchSyncPost,
fetchSyncGet,
requestApi,
getProtyle,
getCurrentDocId,
getCurrentNotebookId,
newSetStyle,
onProtyleLoad,
onToolbarShow,
getCharsBeforeCursor,
showInputBox,
showOptionsMenu,
selectText,
这些函数也可以通过 openAny.fn.xxx() 或 openAny.functions.xxx()直接调用。
添加到编辑器工具栏
onToolbarShow(callback)
功能简介:
当编辑器工具栏出现时,进行添加按钮等操作。
使用示例:
onToolbarShow((selection, toolbar, protyle) => {
console.log(selection, toolbar, protyle);
});
注册快捷键
openAny.addKeymap('', ()=>{})
比如
openAny.addKeymap('alt+z', (event)=>{
event.preventDefault();
openAny.press('alt+p')
})
然后可以把这些代码放到 js 代码片段中即可。
addKeymap 第三个参数可以传一个 node,代表在哪个元素上监听,默认是在 window 上。
第四个参数是监听事件的选项,默认是 true,即在捕获阶段触发。
注册快捷键还支持按键和鼠标的组合, 鼠标字符有:mouseleft
,mousemiddle
,mouseright
,mouseover
,大小写没影响,分别代表鼠标左键,中键和右键。
比如:
openAny.addKeymap('alt+meta+mouseleft', (event)=>{
event.preventDefault();
const target = event.target;
if(target.matches('.some-selector')) {
// your code here
}
})
删除注册的快捷键可用用 openAny.removeKeymap('', callback, options);
比如:
openAny.removeKeymap('alt+meta+mouseleft', (event)=>{
event.preventDefault();
const target = event.target;
if(target.matches('.some-selector')) {
// your code here
}
})
注意,callback 也必须完全一样才行,与 js 自带的事件删除不一样,这里只要求,callback.toString()完全一致就行,如果有 node 和 options 的,也要加上。
注意,如果删除时不填写 callback,node,options 参数则会把所有同名的快捷键都删除,但只会删除通过 openAny 添加的快捷键。尽量提供完整参数,防止误删除。
另外,如果使用了不同的实例注册的快捷键,也仅删除相同实例下注册的快捷键。
按键字符有哪些? 参见下面的详情 👇
字母键
包含从 A 到 Z 的所有英文字母键:
- A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
数字键(主键盘区)
包含主键盘上的数字键:
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
功能键
包含键盘顶部的功能键:
- F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12
方向键
用于控制方向的按键:
- 上箭头 (ArrowUp), 下箭头 (ArrowDown), 左箭头 (ArrowLeft), 右箭头 (ArrowRight)
特殊键
包括常用的特殊功能键:
- Backspace(退格键), Tab(制表键), Enter(回车键), Shift(左 Shift 键), Control(左 Ctrl 键), Alt(左 Alt 键)
- CapsLock(大写锁定键), Escape(Esc 键), Space(空格键)
- PageUp(向上翻页键), PageDown(向下翻页键), End(结束键), Home(首页键)
- Insert(插入键), Delete(删除键)
数字小键盘
位于键盘右侧的小键盘区域:
- 数字键:Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7, Numpad8, Numpad9
- 运算符键:NumpadAdd(加号), NumpadSubtract(减号), NumpadMultiply(乘号), NumpadDivide(除号)
- 小数点键:NumpadDecimal
- 回车键:NumpadEnter
标点符号键
主键盘上的标点符号键:
- 分号 (;) - Semicolon
- 等号 (=) - Equal
- 逗号 (,) - Comma
- 减号 (-) - Minus
- 句号 (.) - Period
- 斜杠 (/) - Slash
- 反引号 (`) - Backquote
- 左方括号 ([) - BracketLeft
- 反斜杠 () - Backslash
- 右方括号 (]) - BracketRight
- 单引号 (') - Quote
鼠标键
mouseleft
mousemiddle
mouseright
mouseover
其他键
一些额外的特殊功能键:
- ContextMenu(右键菜单键), NumLock(数字锁定键), ScrollLock(滚动锁定键)
- Pause(暂停键), PrintScreen(打印屏幕键)
扩展函数
除了 openAny 自带的函数外,你也可以向 openAny 扩展自己的函数,这些函数同样会出现在 invoke 和事件回调参数中。
扩展函数通过 addFunction 方法增加,比如:
openAny.addFunction('fnName', ()=>{});
// 或
const myFunction = ()=>{};
openAny.addFunction('myFunction', myFunction);
举例说明
打开设置
openAny.click('#barWorkspace').click('[data-id="config"]');
从命令窗口打开设置
openAny.click('#barCommand').el('[data-key="dialog-commandpanel"] .search__header input').input('设置').click('#commands [data-command="config"]');
调用思源 keymap 打开设置窗口(这里的 config 是 siyuan.config.keymap 中的值)
openAny.pressByKeymap('config');
或 openAny.pressByFnName('config');
这里的 pressByFnName 是 pressByKeymap 的别名
或 openAny.press('keymap.config');
或 openAny.press('fn.config');
这里有 keymap 和 fn 前缀时会自动调用上面的 pressByKeymap 或 pressByFnName 方法
或 openAny.press('keymap.general.config');
全名方式调用,这里的 general 是 siyuan.config.keymap 后面的键,如果是 general 也可以省略,其他则不能省略
打开代码片段窗口
openAny.clicks('#barWorkspace', '[data-id="config"]', '[data-name="appearance"]', '#codeSnippet', '[data-key="dialog-setting"] svg.b3-dialog__close');
alt+z 实现文本标记和加粗
openAny.addKeymap('alt+z', (event)=>{event.preventDefault();openAny.clicks('[data-type="strong"]', '[data-type="mark"]')});
alt+z 实现文本设置颜色和背景色
openAny.addKeymap('alt+z', (event)=>{event.preventDefault();openAny.press('meta+alt+x', document.activeElement).clicks('.protyle-util [style="color:var(--b3-font-color9)"]', '.protyle-util [style="background-color:var(--b3-font-background6)"]').invoke(()=>document.querySelector('.protyle-util:not(.fn__none)').classList.add('fn__none'))});
触发选中文本,并给文本加粗
openAny.selectText('some text', document.activeElement).press('meta+b', document.activeElement);
快速切换预览模式和编辑模式
openAny.addKeymap('alt+meta+0', (event)=>{
event.preventDefault();
const isPreview = document.querySelector('.protyle-preview:not(.fn__none) .protyle-preview__action');
if(!isPreview) openAny.press('alt+meta+9'); else openAny.press('alt+meta+7');
});
转移快捷键(注册快捷键),该功能按 alt+z 触发 alt+p
openAny.addKeymap('alt+z', (event)=>{event.preventDefault();openAny.press('alt+p')})
更多例子请参考
[js] 这个功能可以封神!openAny 教程之快速打开(可自定义的命令面板)
[js] 第二弹,openAny 教程之全局搜索仅搜文档 / 快速灵感输入 / 快速显示隐藏侧边栏等
使用手册
注意,以下 👇 文档由 AI 生成仅供参考!
OpenAny
是一个用于模拟用户操作(如点击、输入、快捷键等)的工具类。它支持链式调用,能够实现复杂的自动化操作,同时提供了错误处理和快捷键注册功能。以下是详细的使用说明。
1. 初始化与基本调用
初始化实例
推荐通过 new OpenAny()
创建新实例:
const openAny = new OpenAny();
也可以直接使用全局实例:
openAny.click('#selector');
链式调用
所有方法均支持链式调用,例如:
openAny.click('#selector1')
.click('#selector2')
.input('Hello World', '#inputSelector')
.press('Enter');
2. 核心方法
2.1 模拟点击
方法:click(selector, parentElement)
- 参数:
selector
:CSS 选择器或 DOM 元素。parentElement
(可选):父级元素范围。
- 示例:
openAny.click('#button'); // 点击指定按钮
方法:clicks(...selectors)
- 支持批量点击多个元素。
- 参数:
selectors
:选择器数组或多个字符串参数。
- 示例:
openAny.clicks('#button1', '#button2', '#button3');
2.2 输入与文本操作
方法:input(text, selector)
- 在指定输入框中输入文本。
- 参数:
text
:要输入的文本。selector
:目标输入框的选择器。
- 示例:
openAny.input('Hello World', '#inputField');
方法:sendText(text, selector)
- 向可编辑区域发送文本。
- 示例:
openAny.sendText('Hello World', '.editableArea');
方法:clear(selector)
- 清空指定输入框的内容。
- 示例:
openAny.clear('#inputField');
2.3 快捷键模拟
方法:press(keys, element)
- 模拟按键操作。
- 参数:
keys
:按键组合,如'Ctrl+A'
或'Meta+Z'
。element
(可选):目标元素。
- 示例:
openAny.press('Ctrl+S'); // 保存操作
具体键盘名可参考 [js] 连续点击 openAny,小代码,大作用,让一切触手可达
另外,鼠标键有 mouseleft, mouseclick,mousemiddle,mouseright,mouseover。
方法:pressByKeymap(fnName)
- 根据思源笔记的快捷键配置触发操作。
- 参数:
fnName
:快捷键名称。
- 示例:
openAny.pressByKeymap('general.config'); // 打开设置窗口
2.4 延迟与等待
方法:sleep(delay)
- 添加延迟。
- 参数:
delay
:延迟时间(毫秒)。
- 示例:
openAny.sleep(1000); // 延迟1秒
方法:el(selector)
- 等待指定元素加载完成。
- 参数:
selector
:目标元素的选择器。
- 示例:
openAny.el('#dynamicElement').sendText('someText');
2.5 自定义逻辑
方法:invoke(callback)
- 执行自定义逻辑。
- 参数:
callback
:回调函数,接收上下文参数。- callback 的参数有:
- prev, // 上一个调用的元素或返回值
sleep,
whenElementExist,
showMessage,
showErrorMessage,
querySql,
fetchSyncPost,
fetchSyncGet,
requestApi,
getProtyle,
getCurrentDocId,
getCurrentNotebookId,
newSetStyle,
onProtyleLoad,
onToolbarShow,
getCharsBeforeCursor,
showInputBox,
showOptionsMenu,
selectText,
- 示例:
openAny.invoke({}) => {
console.log('Custom logic executed.');
});
这些函数也可以通过 openAny.fn.xxx() 或 openAny.functions.xxx()直接调用。
【注意】 invoke 中使用 openAny.xx()前面不能用 await,需要 await 的需用 new OpenAny().xx()代替,因为 await 会与上层链相互等待造成死锁
2.6 快捷键注册
方法:addKeymap(keys, callback, node, options)
- 注册全局快捷键。这些代码放到代码片段中即可。
- 参数:
keys
:快捷键组合,如'Alt+Z'
。callback
:触发时执行的回调函数。- node 在哪个元素上绑定
- options addEventListener 的选项
- 示例:
openAny.addKeymap('Alt+Z', (event) => {
event.preventDefault();
openAny.click('#button');
});
2.7 快捷键删除
方法:removeKeymap(keys, callback)
-
注册全局快捷键。这些代码放到代码片段中即可。
-
参数:
keys
:快捷键组合,如'Alt+Z'
。callback
:触发时执行的回调函数。- node 在哪个元素上绑定
- options addEventListener 的选项
-
示例:
openAny.addKeymap('Alt+Z', (event) => {
event.preventDefault();
openAny.click('#button');
});
注意,callback 也必须完全一样才行,与 js 自带的事件删除不一样,这里只要求,callback.toString()完全一致就行,如果有 node 和 options 的,也要加上。
注意,如果删除时不填写 callback,node,options 参数则会把所有同名的快捷键都删除,但只会删除通过 openAny 添加的快捷键。尽量提供完整参数,防止误删除。
另外,如果使用了不同的实例注册的快捷键,也仅删除相同实例下注册的快捷键。
3. 错误处理
错误捕获
建议使用 try...catch
捕获异常:
try {
await openAny.click('#valid1').click('#invalid');
} catch (e) {
console.error("捕获错误:", e);
}
显示错误消息
启用错误消息通知:
openAny.showMessage().click('#invalid');
参数 true 显示消息,false 不显示消息,默认 true (但未调用此方法时,openAny 默认是 false)
4. 高级用法
4.1 多步骤操作
将多个操作组合在一起:
await openAny
.el('#inputField')
.input('Hello World')
.press('Enter')
.click('#submitButton');
4.2 invoke 函数
通过函数处理那些模拟点击无法实现的操作:
openAny.invoke({}) => {
console.log('Custom logic executed.');
});
4.3 快捷键转移
将一个快捷键映射到另一个操作:
openAny.addKeymap('Alt+X', (event) => {
event.preventDefault();
openAny.press('Ctrl+S');
});
5. 注意事项
- 选择器唯一性:选择符不一定要全局唯一,但需确保不会产生歧义或副作用。
- 异步操作:链式调用时无需手动处理异步,
OpenAny
内部已封装 Promise。 - 分开调用:如果需要分开调用方法,切勿混合其他代码,除非你能清晰知道执行顺序。
- 异常恢复:若出现未知异常导致假死状态,可通过
resetChain()
恢复。
6. 实例说明
1: 如何打开设置窗口?
openAny.click('#barWorkspace').click('[data-id="config"]');
2: 如何快速切换预览模式和编辑模式?
openAny.addKeymap('Alt+Meta+0', (event) => {
event.preventDefault();
const isPreview = document.querySelector('.protyle-preview:not(.fn__none) .protyle-preview__action');
if (!isPreview) openAny.press('Alt+Meta+9');
else openAny.press('Alt+Meta+7');
});
3: 如何给文字添加颜色和背景色?
openAny.addKeymap('Alt+Z', (event) => {
event.preventDefault();
openAny.press('Meta+Alt+X', document.activeElement)
.clicks('.protyle-util [style="color:var(--b3-font-color9)"]',
'.protyle-util [style="background-color:var(--b3-font-background6)"]')
.invoke(() => document.querySelector('.protyle-util:not(.fn__none)').classList.add('fn__none'));
});
新增函数
这些函数都可以用在 openAny.invoke 函数回调中。
以下是对您提供的几个函数的使用教程,包含每个函数的功能描述、使用场景以及代码示例。
1. showOptionsMenu
弹出选项菜单
功能描述:
showOptionsMenu
是一个异步函数,用于弹出一个选项菜单供用户选择。它接收一个选项数组,并返回用户选择的值。如果用户取消选择,则返回 null
。
参数
showOptionsMenu(options, title = '')
使用场景:
- 用户需要从多个选项中选择一个(例如:跳转到不同的搜索引擎或 AI 工具)。
- 需要动态生成选项列表并获取用户的选择结果。
使用示例:
async function demo() {
// 定义选项列表
const options = [
{ label: 'Google 搜索', value: 'https://www.google.com' },
{ label: 'Bing 搜索', value: 'https://www.bing.com' },
{ label: '百度搜索', value: 'https://www.baidu.com' }
];
// 调用 showOptionsMenu 显示选项菜单
const selectedValue = await showOptionsMenu(options);
if (selectedValue === null) {
console.log('用户取消了选择');
} else {
console.log(`用户选择了:${selectedValue}`);
window.location.href = selectedValue; // 跳转到用户选择的搜索引擎
}
}
2. showInputBox
弹出输入框
功能描述:
showInputBox
是一个异步函数,用于弹出一个输入框,允许用户输入内容。如果用户点击确认按钮,则返回输入的内容;如果用户取消输入,则返回 null
。
参数
showInputBox(defaultText = '', title = '', placeholder = '');
使用场景:
- 获取用户的自定义输入(例如:提交表单、设置标题等)。
- 需要动态处理用户输入内容。
使用示例:
async function inputDemo() {
// 弹出输入框,默认内容为 "默认内容"
const result = await showInputBox('请输入您的名字');
if (result !== null) {
console.log('用户输入:', result);
alert(`你好, ${result}! 欢迎使用本系统。`);
} else {
console.log('用户取消了输入');
}
}
3. onToolbarShow
监听工具栏显示事件
功能描述:
onToolbarShow
是一个回调函数,当工具栏显示时触发。它接收三个参数:
selection
:当前选中的内容。toolbar
:工具栏对象。protyle
:与编辑器相关的上下文信息。
使用场景:
- 动态调整工具栏的行为或样式。
- 根据用户选中的内容,动态更新工具栏的选项。
使用示例:
// 监听工具栏显示事件
onToolbarShow((selection, toolbar, protyle) => {
console.log('当前选中内容:', selection);
console.log('工具栏对象:', toolbar);
console.log('编辑器上下文:', protyle);
// 示例:打印选中文本
if (selection && selection.length > 0) {
console.log('选中文本是:'+selection);
}
});
4. getCharsBeforeCursor
获取光标前的字符
功能描述:
getCharsBeforeCursor
是一个同步函数,用于获取光标前指定数量的字符。它接收一个参数 count
,表示需要获取的字符数。
使用场景:
- 文字补全功能(例如:根据光标前的字符预测下一个单词)。
- 分析用户当前输入上下文。
使用示例:
function autoCompleteExample() {
// 获取光标前 5 个字符
const charsBeforeCursor = getCharsBeforeCursor(5);
console.log('光标前的字符:', charsBeforeCursor);
// 示例:简单文字补全逻辑
if (charsBeforeCursor.endsWith('hel')) {
console.log('建议补全为: hello');
} else if (charsBeforeCursor.endsWith('wor')) {
console.log('建议补全为: world');
}
}
5. newSetStyle
动态设置样式
功能描述:
newSetStyle
是一个函数,用于创建一个动态样式设置器。调用该函数后,会返回一个新的函数(例如:setStyle
),该函数可以接收 CSS 样式字符串作为参数,并将其应用到目标元素或全局样式中。
使用场景:
- 动态调整页面样式(例如:根据用户偏好更改主题颜色)。
- 实现运行时的样式定制(例如:在特定条件下修改菜单、按钮或其他组件的样式)。
- 开发可复用的样式管理工具。
使用教程
1. 初始化 newSetStyle
首先,调用 newSetStyle
创建一个样式设置器实例(如 setStyle
)。这个实例可以用来动态注入 CSS 样式。
// 初始化样式设置器
const setStyle = newSetStyle();
2. 应用样式
通过 setStyle
函数,您可以传入一段 CSS 样式字符串,这些样式会被动态注入到页面中。
示例 1:设置全局样式
// 定义新的全局样式
setStyle(`
body {
background-color: #f8f9fa;
font-family: Arial, sans-serif;
color: #333;
}
button {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
`);
console.log('全局样式已更新');
示例 2:设置特定组件样式
// 定义菜单的样式
setStyle(`
.custom-menu {
background-color: #ffffff;
border: 1px solid #ddd;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
border-radius: 8px;
padding: 10px;
}
.custom-menu-item {
padding: 8px 16px;
cursor: pointer;
}
.custom-menu-item:hover {
background-color: #f0f0f0;
}
`);
console.log('菜单样式已更新');
3. 动态切换样式
您可以多次调用 setStyle
来动态切换样式,从而实现主题切换或条件样式调整。
示例:根据用户选择切换主题
function switchTheme(theme) {
if (theme === 'dark') {
setStyle(`
body {
background-color: #121212;
color: #e0e0e0;
}
button {
background-color: #bb86fc;
color: #121212;
}
`);
console.log('切换到深色主题');
} else {
setStyle(`
body {
background-color: #ffffff;
color: #333;
}
button {
background-color: #007bff;
color: white;
}
`);
console.log('切换到浅色主题');
}
}
// 调用示例
switchTheme('dark'); // 切换到深色主题
setTimeout(() => switchTheme('light'), 3000); // 3秒后切换到浅色主题
4. 清除样式
如果需要清除之前注入的样式,可以在实现 newSetStyle
的底层逻辑时添加清除功能(假设有 clearStyles
方法)。
示例:清除所有动态样式
// 假设 newSetStyle 返回的对象包含 clearStyles 方法
setStyle.clearStyles();
console.log('所有动态样式已清除');
总结
newSetStyle
是一个强大的工具,允许开发者动态地注入和管理 CSS 样式。通过它,您可以轻松实现以下功能:
- 动态样式调整:根据用户交互或系统状态实时更新样式。
- 主题切换:支持深色模式、浅色模式等多主题切换。
- 组件样式隔离:为特定组件或模块定义独立的样式规则。
6. selectText
触发选中文本
功能描述:
selectText
可以触发选中编辑器文本,配合按钮操作,可以对编辑器进行一定的编辑操作。
使用场景:
- 选中文本添加样式等。
- 选中文本搜索等。
使用示例:
openAny.selectText('some text', document.activeElement).press('meta+b', document.activeElement);
7. openFile
打开本地文件
功能描述:
openFile
可以打开本地文件,支持各种类型,用默认程序打开。
使用场景:
- 打开本地文件
使用示例:
openAny.openFile('/yourpath/yourfile.txt');
8. showFileInFolder
定位文件或文件夹的
功能描述:
showFileInFolder
在系统资源管理器中定位文件或文件夹的位置。
使用场景:
- 定位文件或文件夹的位置
使用示例:
openAny.showFileInFolder('/yourpath/yourfile.txt');
9. runCmd
运行本地命令
功能描述:
runCmd
可以执行本地命令,并等待返回结果。
使用场景:
- 与本地脚本交互
使用示例:
// mac
openAny.runCmd('open -a /path/some.app'); //运行指定app
//windows
openAny.runCmd('start calc'); // 打开计算器
也可以把这些函数与其他函数相结合实现与本地文件或应用的交互。
代码
代码放到哪里
这个是针对小白用户的说明,老用户可忽略。
- 设置 -> 外观 -> 代码片段 -> JS 中添加新的 js 代码片段即可。
- 输入帖子中的代码到你新建的代码片段中
- 开启代码片段即可(如果有问题重启思源试试)
分享你的代码
可把你的自定义代码分享到评论区。
openAny,不只是打开,一切皆有可能!
打赏作者
打赏用户超过 20 考虑开发类似 obsidian quickAdd 那样的宏操作界面
鸣谢
❤️ 感谢最近以来各位大佬们的打赏!
虽然不能一一感谢!但都铭记在心!再次感谢!🙏
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于