5个JavaScript代码片段:解锁SiYuan笔记的隐藏自定义能力

5个JavaScript代码片段:解锁SiYuan笔记的隐藏自定义能力

【免费下载链接】siyuan A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. 【免费下载链接】siyuan 项目地址: https://gitcode.com/GitHub_Trending/si/siyuan

你是否还在为笔记软件不够灵活而烦恼?SiYuan作为一款注重隐私的开源知识管理工具,提供了强大的JavaScript代码片段功能,让普通用户也能通过简单代码实现高级自定义。本文将通过5个实用案例,带你掌握从基础配置到高级交互的完整自定义流程,无需专业开发经验也能打造专属笔记体验。

代码片段功能基础

SiYuan的代码片段系统允许用户通过JavaScript扩展界面功能和交互逻辑。所有相关配置都集中在app/src/config/util/snippets.ts模块中,该模块负责代码片段的加载、渲染和管理。

代码片段的工作原理很简单:用户编写的JavaScript代码会被注入到应用的HTML头部,从而可以访问和修改SiYuan的内部API。系统会自动处理代码的加载顺序和执行环境,确保自定义功能与核心功能无缝集成。

代码片段管理界面

片段1:自动为标题添加序号

这个代码片段可以为文档中的所有标题自动添加层级序号,帮助你在长文档中保持清晰的结构。实现原理是通过监听文档加载完成事件,然后遍历所有标题元素并添加序号前缀。

// 自动为标题添加序号
document.addEventListener('DOMContentLoaded', function() {
  // 获取所有标题元素
  const headings = document.querySelectorAll('.protyle-wysiwyg [data-node-id]');
  
  // 定义层级计数器
  const levelCounts = [0, 0, 0, 0, 0, 0];
  
  headings.forEach(heading => {
    // 获取标题层级
    const level = parseInt(heading.tagName.replace('H', ''));
    if (isNaN(level) || level < 1 || level > 6) return;
    
    // 更新计数器
    for (let i = level; i <= 6; i++) {
      levelCounts[i] = 0;
    }
    levelCounts[level]++;
    
    // 生成序号
    let numbering = '';
    for (let i = 1; i <= level; i++) {
      if (levelCounts[i] > 0) {
        numbering += (i > 1 ? '.' : '') + levelCounts[i];
      }
    }
    
    // 添加序号前缀
    const contentElement = heading.querySelector('.protyle-action + div');
    if (contentElement && !contentElement.innerHTML.startsWith(numbering + '.')) {
      contentElement.innerHTML = numbering + '. ' + contentElement.innerHTML;
    }
  });
});

使用方法非常简单:在代码片段管理界面点击"添加"按钮,选择JavaScript类型,粘贴上述代码并启用即可。系统会在每次加载文档时自动执行这段代码,为所有标题添加序号。

片段2:实现自定义快捷键

SiYuan虽然内置了丰富的快捷键,但有时我们需要根据个人习惯自定义。下面的代码展示了如何添加一个"复制当前块ID"的自定义快捷键(Alt+Shift+C)。

// 自定义快捷键:复制当前块ID (Alt+Shift+C)
document.addEventListener('keydown', function(e) {
  // 检查快捷键组合 (Alt+Shift+C)
  if (e.altKey && e.shiftKey && e.code === 'KeyC') {
    // 获取当前选中的块
    const selectedBlock = document.querySelector('.protyle-wysiwyg [data-node-id].protyle-selected');
    if (selectedBlock) {
      // 获取块ID
      const blockId = selectedBlock.getAttribute('data-node-id');
      // 复制到剪贴板
      navigator.clipboard.writeText(blockId).then(() => {
        // 显示提示
        siyuan.notification.showMessage('块ID已复制: ' + blockId);
      });
      e.preventDefault();
      e.stopPropagation();
    }
  }
});

这段代码通过监听全局键盘事件实现快捷键功能。当检测到Alt+Shift+C组合键时,会查找当前选中的块元素,提取其data-node-id属性值并复制到剪贴板,最后通过SiYuan的notification API显示成功提示。

片段3:自动备份每日笔记

对于重要的每日笔记,自动备份功能可以提供额外保障。这个片段会在每天指定时间自动导出当天的日记笔记,并保存到指定目录。

// 自动备份每日笔记
(function() {
  // 配置备份时间 (小时:分钟)
  const backupTime = "23:59";
  // 目标笔记本路径
  const targetNotebook = "/日记";
  
  // 计算当前时间与目标时间的差值
  function getDelay() {
    const now = new Date();
    const [hours, minutes] = backupTime.split(':').map(Number);
    const target = new Date(now);
    target.setHours(hours, minutes, 0, 0);
    
    if (target <= now) {
      target.setDate(target.getDate() + 1);
    }
    
    return target - now;
  }
  
  // 执行备份
  function performBackup() {
    // 获取今天的日期字符串 (YYYY-MM-DD)
    const today = new Date().toISOString().split('T')[0];
    
    // 调用SiYuan导出API
    siyuan.api.exportMd({
      path: `${targetNotebook}/${today}`,
      mode: "single",
      withID: false,
      withEmbed: true,
      withBacklink: false,
      withAttr: false,
      fileType: "md"
    }).then(() => {
      siyuan.notification.showMessage(`每日笔记备份成功: ${today}`);
    }).catch(err => {
      siyuan.notification.showMessage(`备份失败: ${err.message}`, 5000, "error");
    });
    
    // 安排下一次备份
    setTimeout(performBackup, getDelay());
  }
  
  // 立即安排第一次备份
  setTimeout(performBackup, getDelay());
})();

该实现使用了自执行函数模式,避免污染全局命名空间。代码会根据设定的备份时间自动计算下次执行时间,然后通过setTimeout递归调用,实现每日自动备份。备份功能通过调用SiYuan的exportMd API实现,支持自定义笔记本路径和导出选项。

片段4:自定义块引用样式

SiYuan默认的块引用样式比较简单,通过代码片段可以实现更丰富的视觉效果,如不同类型的引用使用不同颜色标识。

// 自定义块引用样式
(function() {
  // 创建样式元素
  const style = document.createElement('style');
  style.textContent = `
    /* 重要引用样式 */
    .protyle-wysiwyg [data-type="quote"] .p[contenteditable="true"]::before {
      content: "";
      position: absolute;
      left: 0;
      top: 0;
      bottom: 0;
      width: 4px;
      background-color: #ff4d4f;
      border-radius: 2px;
    }
    
    /* 提示引用样式 */
    .protyle-wysiwyg [data-type="quote"] .p[contenteditable="true"]:has(> span:contains("提示:"))::before {
      background-color: #faad14;
    }
    
    /* 链接引用样式 */
    .protyle-wysiwyg [data-type="quote"] .p[contenteditable="true"]:has(> span:contains("链接:"))::before {
      background-color: #1890ff;
    }
  `;
  document.head.appendChild(style);
})();

这个代码片段通过动态创建style元素,为不同类型的块引用添加左侧彩色边框。使用了CSS的:has()伪类选择器,可以根据引用内容中的特定文本(如"提示:"、"链接:")自动应用不同颜色,使文档结构更加清晰。

自定义块引用样式效果

片段5:实现笔记内容搜索高亮

SiYuan内置搜索功能虽然强大,但有时我们需要在阅读长文档时持续高亮显示某些关键词。这个代码片段实现了一个简单的关键词高亮功能,可以在当前文档中标记指定关键词。

// 笔记内容搜索高亮
(function() {
  // 配置需要高亮的关键词列表
  const keywords = ["重要", "待办", "注意", "思考"];
  
  // 创建样式
  const style = document.createElement('style');
  style.textContent = `
    .keyword-highlight {
      background-color: rgba(255, 251, 0, 0.4);
      padding: 0 2px;
      border-radius: 2px;
    }
  `;
  document.head.appendChild(style);
  
  // 高亮处理函数
  function highlightKeywords() {
    // 获取所有可编辑内容区域
    const contentAreas = document.querySelectorAll('.protyle-wysiwyg .p[contenteditable="true"]');
    
    contentAreas.forEach(area => {
      // 保存当前光标位置
      const selection = window.getSelection();
      let range = null;
      if (selection.rangeCount > 0 && area.contains(selection.focusNode)) {
        range = selection.getRangeAt(0);
      }
      
      // 处理文本节点
      const walker = document.createTreeWalker(area, NodeFilter.SHOW_TEXT, {
        acceptNode: node => {
          // 排除已经高亮的文本和代码块
          if (node.parentElement && (node.parentElement.classList.contains('keyword-highlight') || 
              node.parentElement.closest('.code-block') || 
              node.parentElement.closest('.language-'))) {
            return NodeFilter.FILTER_REJECT;
          }
          return NodeFilter.FILTER_ACCEPT;
        }
      });
      
      const textNodes = [];
      let currentNode;
      while (currentNode = walker.nextNode()) {
        textNodes.push(currentNode);
      }
      
      // 处理每个文本节点
      textNodes.forEach(node => {
        let content = node.textContent;
        let modified = false;
        
        // 检查每个关键词
        keywords.forEach(keyword => {
          if (content.includes(keyword)) {
            modified = true;
            // 使用正则表达式全局匹配关键词
            const regex = new RegExp(`(${keyword})`, 'g');
            content = content.replace(regex, '<span class="keyword-highlight">$1</span>');
          }
        });
        
        // 如果内容被修改,替换文本节点为span元素
        if (modified) {
          const span = document.createElement('span');
          span.innerHTML = content;
          node.parentNode.replaceChild(span, node);
        }
      });
      
      // 恢复光标位置
      if (range) {
        selection.removeAllRanges();
        selection.addRange(range);
      }
    });
  }
  
  // 监听文档变化
  const observer = new MutationObserver(highlightKeywords);
  observer.observe(document.body, {
    childList: true,
    subtree: true,
    characterData: true
  });
  
  // 初始加载时执行一次
  highlightKeywords();
})();

这个代码片段通过创建一个MutationObserver来监听文档变化,当检测到内容更新时自动扫描文本并高亮预设关键词。使用TreeWalker遍历文本节点,避免处理代码块和已高亮内容,确保高亮功能不会干扰正常编辑。

高级应用:片段管理与共享

随着自定义片段增多,管理变得尤为重要。SiYuan的代码片段系统支持批量导入导出功能,你可以将自己编写的实用片段导出为JSON文件,与其他用户共享。

所有代码片段的管理功能都在app/src/config/util/snippets.ts中实现,包括:

  • 片段的增删改查
  • 启用/禁用状态管理
  • 搜索和过滤功能
  • 导入/导出功能

代码片段导入导出

要导出你的代码片段集合,只需在代码片段管理界面点击"导出"按钮,系统会生成一个包含所有片段的JSON文件。导入时选择该文件即可恢复所有自定义片段。

注意事项与最佳实践

在使用JavaScript代码片段时,需要注意以下几点:

  1. 代码片段会直接影响SiYuan的运行环境,错误的代码可能导致应用不稳定
  2. 升级SiYuan后,部分内部API可能变化,需要检查自定义片段是否兼容
  3. 复杂功能建议先在测试环境验证,再应用到生产笔记中
  4. 定期备份你的代码片段,防止意外丢失

建议将常用的代码片段整理成文档,记录其功能、使用场景和依赖的API版本,以便日后维护和分享。对于特别复杂的功能,可以考虑将其开发为正式插件,获得更好的兼容性和支持。

通过本文介绍的5个实用代码片段,相信你已经掌握了SiYuan自定义功能的基本方法。这些示例仅仅展示了冰山一角,结合SiYuan丰富的内部API,你可以实现更多个性化功能,让笔记系统真正为你所用。

现在就打开SiYuan的代码片段管理界面,开始你的定制之旅吧!如果创建了实用的代码片段,欢迎在社区分享,帮助更多用户解锁SiYuan的隐藏潜力。

【免费下载链接】siyuan A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. 【免费下载链接】siyuan 项目地址: https://gitcode.com/GitHub_Trending/si/siyuan

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值