注意,以下所以功能必须先安装 [js] 连续点击 openAny,小代码,大作用,让一切触手可达 这个代码片段才行。
ctrl+shif+p 全局搜索仅搜文档(不影响原有搜索状态)
功能简介:
ctrl+shif+p 打开全局搜索对话框,然后自动临时设置搜索参数为仅搜索文档,当关闭搜索窗口后,一切复原,不影响原本的搜索设置。
代码:
// ctrl+shif+p 全局搜索仅搜文档(不影响原有搜索状态)
(async ()=>{
// 等待openAny加载完毕
await waitFor(() => typeof openAny !== 'undefined');
// 注册快捷键
const ctrl = navigator.platform.indexOf("Mac") > -1 ? 'meta' : 'ctrl';
openAny.setKeymap(`shift+${ctrl}+p`, async (event, {getSelectedText}) => {
openAny
.press(`${ctrl}+p`) // 打开搜索框
.click("#searchFilter") // 点击类型过滤按钮
.input(getSelectedText(), "#searchInput") // 搜索框置空
.invoke(async ({sleep,whenElementRemoved}) => {
// 【注意】invoke内部建议用新的OpenAny对象,防止用await时与上层链相互等待造成死锁
const openAny = new OpenAny();
// 获取当前的文档类型
const oldTypes = siyuan?.storage['local-searchdata']?.types;
// 查询所有文档类型,仅保留文档类型打开,其他全关闭
openAny
.queryElAll('[data-key="dialog-searchtype"] [type="checkbox"]')
.forEach(async (checkbox) =>
checkbox.matches('[data-type="document"]')
? !checkbox.checked && checkbox.click()
: checkbox.checked && checkbox.click()
);
// 点击确定按钮
openAny.click('[data-key="dialog-searchtype"] .b3-dialog__action .b3-button--text')
await sleep(100); // 等待100ms
openAny.focus("#searchInput"); // 聚焦搜索框
// placehoder
openAny.queryEl('#searchInput').placeholder = '请输入文档标题';
// 等待搜索对话框被关闭
whenElementRemoved('[data-key="dialog-globalsearch"]', ()=>{
// 恢复原本的文档类型
if(oldTypes) siyuan.storage['local-searchdata'].types = oldTypes;
});
});
});
function waitFor(conditionFn, timeoutMs=5000) {
return new Promise((resolve, reject) => {
const start = Date.now();
const check = () => {
if(typeof conditionFn === 'string')
conditionFn = () => document.querySelector(conditionFn);
const result = conditionFn();
if (result) resolve(result);
else if (Date.now() - start > timeoutMs) reject();
else requestAnimationFrame(check); // 利用浏览器刷新周期
};
check();
});
}
})();
代码放到思源 js 代码片段中即可。
快速输入,灵感输入
功能简介:
当你在思源中阅读或写文章时,突然有灵感迸发,如果你找到录入灵感的文档再录入,可能由于思维改变或者如果有人突然打扰,你的灵感有可能消失,即使后来再想起来也得花费些功夫。
这个代码可以让你按快捷键 alt+i 快速录入你的灵感,回车后自动保存到你指定的文档,方便日后查看。
代码:
// 快速输入,灵感记录等
(async ()=>{
// 请填写灵感即将保存的文档ID
const captureDocId = '20250307013535-lreu6jb';
// 是否按回车键提交
// 当为 true 时,回车键提交,shift+回车 换行
// 当为 false 时,回车换行,ctrl+回车 提交
const enterSubmit = true;
// 输入框显示行数,默认3行,当行数是1时,无法换行,同时始终回车提交
const inputLines = 3;
// 等待openAny加载完毕
await waitFor(() => typeof openAny !== 'undefined');
// 注册快捷键
openAny.setKeymap("alt+i", async (event, {fetchSyncPost, showInputBox}) => {
const input = await showInputBox("", "", "", inputLines, enterSubmit);
if(!input) return;
const result = await fetchSyncPost('/api/block/insertBlock', {
"dataType": "markdown",
"data": getFormattedDateTime() + "\n{: style=\"color:#989898;\"}\n" + input + "\n---",
"nextID": "",
"previousID": "",
"parentID": captureDocId
});
console.log(result);
});
function getFormattedDateTime() {
const now = new Date();
// 获取年、月、日、时、分、秒
const year = now.getFullYear(); // 年
const month = String(now.getMonth() + 1).padStart(2, '0'); // 月(注意月份从 0 开始,需要加 1)
const day = String(now.getDate()).padStart(2, '0'); // 日
const hours = String(now.getHours()).padStart(2, '0'); // 时
const minutes = String(now.getMinutes()).padStart(2, '0'); // 分
const seconds = String(now.getSeconds()).padStart(2, '0'); // 秒
// 拼接成字符串
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
function waitFor(conditionFn, timeoutMs=5000) {
return new Promise((resolve, reject) => {
const start = Date.now();
const check = () => {
if(typeof conditionFn === 'string')
conditionFn = () => document.querySelector(conditionFn);
const result = conditionFn();
if (result) resolve(result);
else if (Date.now() - start > timeoutMs) reject();
else requestAnimationFrame(check); // 利用浏览器刷新周期
};
check();
});
}
})();
代码放到思源 js 代码片段中即可。
快速隐藏/显示上次打开的侧边栏
功能简介:
如图所示,在面包屑右边增加一个按钮,用于快速隐藏当前展开的侧栏/重新打开上次隐藏的侧栏(或者按 Alt+Z 快捷键)
这个功能已经内置在 QYL 主题,也欢迎大家使用 @queguaiya 大佬的这个主题。
代码:
请前往帖子 [js] 快速隐藏 / 呼出侧栏代码片段分享 查看
感谢 @queguaiya 大佬分享的代码!
快速查询不重复列表
功能简介:
通过关键词查询有序、无序列表及任务列表,然后打开全局搜索框并显示查询结果,在查询结果中不会显示重复的列表(注意仅定位到最外层的列表,不会直接定位到子级)
搜索关键词,空格表示并且,OR 表示或
代码:
// // 快速查询不重复列表(自动生成SQL并打开全局搜索对话框)
{
let results = await openAny.fn.showInputBox('', '', '请输入要查询的关键词,空格代表并且,OR代表或');
if (results) {
// 检查是否包含 OR 逻辑
if (results.includes(' OR ')) {
// 按 OR 分割,并去重、过滤空字符串
const orKeywords = [...new Set(results.split(' OR '))]
.filter(keyword => keyword.trim())
.map(keyword => `b.markdown LIKE '%${keyword}%'`)
.join(' OR ');
results = `AND (${orKeywords})`;
} else {
// 如果没有 OR,则按空格分割,并去重、过滤空字符串
results = [...new Set(results.split(' '))]
.filter(keyword => keyword.trim())
.map(keyword => `AND b.markdown LIKE '%${keyword}%'`)
.join(' ');
}
// 构造最终 SQL 查询
const sql = `select * from (SELECT b.* FROM blocks b LEFT JOIN blocks p ON b.parent_id = p.id WHERE b.type = 'l' ${results} AND (b.parent_id = b.root_id OR (p.type IS NULL OR p.type NOT IN ('l', 'i')))) as blocks`;
openAny.press((navigator.platform.indexOf("Mac") > -1) ? 'meta+p' : 'ctrl+p')
.clicks('#searchSyntaxCheck', '[data-name="searchMethod"] .b3-menu__item:nth-child(3)')
.input(sql, '#searchInput');
}
}
关联帖子:
思源怎么实现 Obsidian 这样的搜索效果?困扰了好久,用 SQL 能实现吗? - wilsons 的回帖
快速查询制卡数据
功能简介:
通过关键词查询制卡数据,然后打开全局搜索框并显示查询结果。
搜索关键词,空格表示并且,OR 表示或
代码:
// 快速查询制卡数据(自动生成SQL并打开全局搜索对话框)
setTimeout(() => {
// 这里设置快捷键即可👇
openAny.addKeymap('alt+z', async (event) => {
event.preventDefault();
let sql = `select * from blocks where 1 {{query_keywords}} and ial like '%custom-riff-decks=%' order by updated desc`;
let results = await openAny.fn.showInputBox('', '', '请输入要查询的关键词,空格代表并且,OR代表或');
if (results) {
// 检查是否包含 OR 逻辑
if (results.includes(' OR ')) {
// 按 OR 分割,并去重、过滤空字符串
const orKeywords = [...new Set(results.split(' OR '))]
.filter(keyword => keyword.trim())
.map(keyword => `markdown LIKE '%${keyword}%'`)
.join(' OR ');
results = `AND (${orKeywords})`;
} else {
// 如果没有 OR,则按空格分割,并去重、过滤空字符串
results = [...new Set(results.split(' '))]
.filter(keyword => keyword.trim())
.map(keyword => `AND markdown LIKE '%${keyword}%'`)
.join(' ');
}
// 构造最终 SQL 查询
sql = sql.replace(/\{\{query_keywords\}\}/ig, results);
openAny.press((navigator.platform.indexOf("Mac") > -1) ? 'meta+p' : 'ctrl+p')
.clicks('#searchSyntaxCheck', '[data-name="searchMethod"] .b3-menu__item:nth-child(3)')
.input(sql, '#searchInput');
}
});
}, 1500);
关联帖子:
其他
ctrl+alt+x 只显示文字外观窗口一部分
之前一个同学提的这个需求,虽然 css 可以实现,我认为 js 实现是最完美的,因为按快捷键后临时修改,关闭窗口后恢复原状,不具有侵入性。
openAny.setKeymap('ctrl+alt+x', async (event, {newSetStyle})=>{
const setStyle = newSetStyle();
// 设置样式
setStyle(`.protyle-font > *:not(:nth-child(7),:nth-child(8)):not(:last-child) {
display:none;
}`);
// 等待外观窗口出现
await openAny.getEl('.protyle-util:not(.fn__none)');
// 等待外观窗口关闭
await openAny.getEl('.protyle-util.fn__none', null, -1);
// 删除样式,不影响后续操作
setStyle('');
});
alt+z 给文字添加指定颜色和背景色
openAny.setKeymap('alt+z', (event)=>{event.preventDefault();openAny.press('ctrl+alt+x', document.activeElement).clicks('.protyle-util [style="color:var(--b3-font-color9)"]', '.protyle-util [style="background-color:var(--b3-font-background6)"]').invoke(()=>openAny.queryEl('.protyle-util:not(.fn__none)')?.classList?.add('fn__none'))});
打开指定笔记的今日日记
// 在这里输入你想在哪个笔记本中打开今日日记
const noteBookName = '我的笔记';
// 这里用wwhenExist先等待指定元素出现,否则需要在do内调用 await new OpenAny().whenExist()等待目标出现
openAny.click('#barWorkspace').whenExist('[data-name="barWorkspace"]').do(()=>{
const subMenuItems = [...openAny.queryElAll('[data-id="dailyNote"] .b3-menu__label')];
const notebutton = subMenuItems.find(item => item.textContent === noteBookName)?.closest('button.b3-menu__item');
// 返回链元素,供下一个链click调用,也可以直接在这里click,不用再次调用下一个链click
return notebutton;
}).click();
模式切换(预览和所见即所得切换)
按 ctrl+alt+7 即可
setTimeout(()=>{
openAny.addKeymap('alt+meta+7', ()=>{
const isPreview = document.querySelector('.protyle-preview:not(.fn__none) .protyle-preview__action');
setTimeout(()=>{if(!isPreview) openAny.press('alt+meta+9');}, 50);
});
}, 1500);
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于