【工具】轻松转换JSON与Markdown表格——自制Obsidian插件

news2024/11/13 10:12:49

文章目录

  • 一、插件简介
  • 二、功能详解
  • 三、使用教程
  • 四、插件代码
  • 五、总结

一、插件简介

 JsonMdTableConverter是一款用于Obsidian的插件,它可以帮助用户在JSON格式和Markdown表格之间进行快速转换。这款插件具有以下特点:

  1. 轻松识别并转换JSON与Markdown表格;
  2. 支持通过右键菜单、命令面板和插件图标三种方式调用;
  3. 界面简洁,操作简单。

二、功能详解

  1. JSON转换为Markdown表格
     当我们有一段JSON数据,希望将其转换为Markdown表格以便在Obsidian中查看时,JsonMdTableConverter可以轻松实现。插件会自动识别JSON数据中的字段,并生成对应的Markdown表格。
  2. Markdown表格转换为JSON
     同样地,当我们需要在Markdown表格和JSON之间进行转换时,JsonMdTableConverterPlugin也能轻松应对。只需选中Markdown表格,插件便会将其转换为JSON格式。
  3. 方便的调用方式
     为了满足不同用户的使用习惯,JsonMdTableConverter提供了以下三种调用方式:
    (1)插件图标:在Obsidian的编辑器上方,点击插件图标即可调用;
    在这里插入图片描述
    (2)命令面板:按下快捷键(如Ctrl+P),输入“JSON/MD Table Converter”即可;
    请添加图片描述
    (3)右键菜单:在编辑器中右键点击,选择“JSON/MD Table Converter”菜单项。
    请添加图片描述

三、使用教程

  1. 安装插件

    1. 在Obsidian仓库文件夹的.obsidian下创建plugins文件夹
      在这里插入图片描述
      在这里插入图片描述
    2. 在此文件夹下创建插件的文件夹,随意命名,比如json-md-table-converter
      在这里插入图片描述
    3. 在插件的路径下创建两个文件main.jsmainfest.json
      在这里插入图片描述
    4. 将JsonMdTableConverter插件插件代码复制相应的文件中,然后重启Obsidian。
    5. 将插件启动(需要关闭安全模式)
      在这里插入图片描述
  2. 转换操作

    1. 选中需要转换的JSON或Markdown表格内容;
    2. 选中以下三种方式之一进行转换:
      • 点击插件图标;
      • 按下快捷键(如Ctrl+P),输入“JSON/MD Table Converter”;
      • 在编辑器中右键点击,选择“JSON/MD Table Converter”。

四、插件代码

manifest.json

{
  "id": "json-md-table-converter",
  "name": "JSON to Markdown Table Converter",
  "version": "0.9.0",
  "description": "Convert JSON strings to Markdown tables and vice versa."
}

main.js

const { Plugin } = require('obsidian');

class JsonMdTableConverterPlugin extends Plugin {
  async onload() {
    // 注册左边栏图标(一般不需要,可以去掉)
    this.addRibbonIcon('dice', 'JSON/MD Table Converter', (evt) => {
      this.convertToJsonOrMd();
    }); 

    // 注册指令
    this.addCommand({
      id: 'convert-json-md-table',
      name: 'JSON/MD Table Converter',
      callback: () => {
        this.convertToJsonOrMd();
      },
    }); 

    // 注册右键菜单
    this.registerEvent(
      this.app.workspace.on('editor-menu', (menu, editor, event) => {
        menu.addItem((item) => {
          item
            .setTitle('JSON/MD Table Converter')
            .setIcon('dice')
            .onClick(() => {
              this.convertToJsonOrMd();
            });
        });
      })
    );
  }

  convertToJsonOrMd() {
    const activeLeaf = this.app.workspace.activeLeaf;
    if (!activeLeaf) return;
    const editor = activeLeaf.view.sourceMode.cmEditor;
    const text = editor.getSelection() || editor.getValue();
    let result = '';
    try {
      // 尝试将文本解析为JSON
      const json = JSON.parse(text);
      if (
        Array.isArray(json) &&
        json.length > 0 &&
        typeof json[0] === 'object'
      ) {
        // 转换为Markdown表格
        result = this.jsonToMdTable(json);
      } else {
        // 如果不是数组或者数组元素不是对象,则提示用户
        return new Notice('Invalid JSON: JSON must be an array of objects.');
      }
    } catch (e) {
      const msg = this.isMarkdownTable(text);
      if (msg !== 'success') {
        return new Notice(msg);
      }
      // 解析失败,可能是Markdown表格
      result = JSON.stringify(this.mdTableToJson(text), null, 2);
    }
    editor.replaceSelection(result);
  }

  jsonToMdTable(json) {
    const fieldSet = new Set(); // 使用Set来存储不重复的字段
    for (let i = 0; i < json.length; i++) {
      const elementKeys = Object.keys(json[i]);
      for (let j = 0; j < elementKeys.length; j++) {
        fieldSet.add(elementKeys[j]); // 将字段添加到Set中
      }
    }
    const headers = Array.from(fieldSet);
    const headerRow = '| ' + headers.join(' | ') + ' |';
    const separatorRow = '| ' + headers.map(() => ':--:').join(' | ') + ' |';
    const bodyRows = json.map(
      (obj) =>
        '| ' + headers.map((header) => obj[header] || '').join(' | ') + ' |'
    );
    return [headerRow, separatorRow, ...bodyRows].join('\n');
  }

  mdTableToJson(mdTable) {
    const rows = mdTable.split('\n').filter((row) => row.trim() !== '');
    for (let i = 0; i < rows.length; i++) {
      rows[i] = rows[i].replace(/^\|+|\|+$/g, '');
    }
    const headers = rows[0].split('|').map((header) => header.trim());
    const jsonArray = rows.slice(2).map((row) => {
      const values = row.split('|').map((value) => value.trim());
      return headers.reduce((obj, header, index) => {
        obj[header] = values[index];
        return obj;
      }, {});
    });
    return jsonArray;
  }

  isMarkdownTable(str) {
    // 去除字符串首尾的空白字符,并按行分割
    const lines = str.trim().split('\n');
    const msg =
      'Conversion failed: The selected text is neither valid JSON nor a Markdown table.';
    // 检查至少有两行
    if (lines.length < 2) {
      return msg;
    }
    // 检查每行是否至少包含一个'|'
    for (let line of lines) {
      if (line.indexOf('|') === -1) {
        return msg;
      }
    }
    let separatorLine = lines[1].replaceAll(' ', '');
    // 分隔符行应该由'-'或':'组成,并且由'|'分隔
    if (separatorLine.startsWith('|')) { // 只去掉首尾的各一个'|'
      separatorLine = separatorLine.slice(1);
    }
    if (separatorLine.endsWith('|')) {
      separatorLine = separatorLine.slice(0, -1);
    }
    const separators = separatorLine.split('|');
    for (let separator of separators) {
      separator = separator.replaceAll(' ', '');
      if (separator.startsWith(':')) {
        separator = separator.slice(1);
      }
      if (separator.endsWith(':')) {
        separator = separator.slice(0, -1);
      }
      if (!/^-+$/.test(separator)) {
        return msg;
      }
    }
    // 检查分隔符行与标题行和内容行的列数是否匹配
    for (let line of lines) {
      if (line.startsWith('|')) {
        line = line.slice(1);
      }
      if (line.endsWith('|')) {
        line = line.slice(0, -1);
      }
      const pipeCount = line.split('|').length;
      if (pipeCount !== separators.length) {
        return msg;
      }
    }
    if (lines.length == 2) {
      return 'Conversion failed: Markdown table should contain at least one row of data.';
    }
    return 'success';
  }
}

module.exports = JsonMdTableConverterPlugin;

五、总结

 JsonMdTableConverter插件极大地简化了JSON与Markdown表格之间的转换操作,提高了我们的工作效率。希望这款插件能为大家带来便利,如有任何建议或疑问,欢迎在评论区留言交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1945548.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解锁PCIe8516高速数据采集卡应用——超声波无损检测

超声波无损检测是无损检测技术的重要手段之一&#xff0c;由于其信号的高频特性&#xff0c;需要采用高速数据采集设备来采集、记录、分析和处理。 某客户需要使用超声波对钢材进行无损检测&#xff0c;由于声波在钢材中的传播速度很高&#xff0c;(纵波CL的传播速度为5900米/秒…

分布式训练并行策略

1.分布式训练的概念 分布式训练&#xff08;Distributed Training&#xff09;是指将机器学习或深度学习模型训练任务分解成多个子任 务&#xff0c;并在多个计算设备上并行地进行训练。 一个模型训练任务往往会有大量的训练样本作为输入&#xff0c;可以利用一个计算设备完成…

【C语言】链式队列的实现

队列基本概念 首先我们要了解什么是队列&#xff0c;队列里面包含什么。 队列是线性表的一种是一种先进先出&#xff08;First In Fi Out&#xff09;的数据结构。在需要排队的场景下有很强的应用性。有数组队列也有链式队列&#xff0c;数组实现的队列时间复杂度太大&#x…

PySide(PyQt),自定义图标按钮

1、在Qt Designer中新建画面&#xff0c;并放置3个按钮&#xff08;QPushButton&#xff09;和一个分组框&#xff08;QGroupBox&#xff09;小部件&#xff0c;分别命名为btn_1&#xff0c; btn_2&#xff0c;btn_3和btnStation。 2、将所有小部件的显示文字内容删除。 3、将…

前端面试宝典【Javascript篇】【1】

欢迎来到《前端面试宝典》&#xff0c;这里是你通往互联网大厂的专属通道&#xff0c;专为渴望在前端领域大放异彩的你量身定制。通过本专栏的学习&#xff0c;无论是一线大厂还是初创企业的面试&#xff0c;都能自信满满地展现你的实力。 核心特色&#xff1a; 独家实战案例…

畅销款超声波眼镜清洗器该怎么选?2024年最强超声波清洗机推荐指南

眼镜是现代生活中不可或缺的物品&#xff0c;但许多人可能不清楚如何正确清洁眼镜。传统的清洁方法可能会对眼镜造成损害&#xff0c;例如使用普通肥皂或清水清洗时容易划伤镜片。为了解决这个问题&#xff0c;家用超声眼镜波清洗机应运而生。超声波清洗机通过超声波振动原理进…

昇思MindSpore 应用学习-CycleGAN图像风格迁移互换

日期 心得 昇思MindSpore 应用学习-CycleGAN图像风格迁移互换&#xff08;AI代码学习&#xff09; CycleGAN图像风格迁移互换 模型介绍 模型简介 CycleGAN(Cycle Generative Adversarial Network) 即循环对抗生成网络&#xff0c;来自论文 Unpaired Image-to-Image Trans…

小白0基础怎么快速写一篇激光SLAM论文

大家好呀&#xff0c;我是一个SLAM方向的在读博士&#xff0c;深知SLAM学习过程一路走来的坎坷&#xff0c;也十分感谢各位大佬的优质文章和源码。如有不对的地方欢迎指出&#xff0c;欢迎各位大佬交流讨论&#xff0c;一起进步。博主创建了一个科研互助群Q&#xff1a;9510262…

视频翻译保留原音色pyvideotrans+clone-voice

剪映的视频翻译时长限制5分钟以内&#xff0c;需要积分2700首次有减免大概21.6元&#xff08;1秒9积分/1元100积分&#xff09; • 视频翻译配音工具pyvideotrans 将视频从一种语言翻译为另一种语言&#xff0c;并添加配音 打包链接&#xff1a;夸克网盘分享 升级补丁&#…

三、基础语法1(30小时精通C++和外挂实战)

三、基础语法1&#xff08;30小时精通C和外挂实战&#xff09; 1&#xff0c;开发环境的搭建2&#xff0c;cin和cout3、4&#xff0c;函数重载5&#xff0c;使用IDA分析exe6.1&#xff0c;默认参数6.2&#xff0c;默认参数的本质汇编7&#xff0c;externC1作用8&#xff0c;ext…

防御和进攻编程

防御性编程是许多程序员都听说过的一个术语&#xff0c;对于某些程序&#xff0c;防御性编程是必不可少的。对于其他程序&#xff0c;它可能偶尔使用一下。除此之外&#xff0c;还有攻击性编程。 在本文中&#xff0c;我们将首先研究“正常编程”。我们首先研究它&#xff0c;…

android(安卓)最简单明了解释版本控制之MinSdkVersion、CompileSdkVersion、TargetSdkVersion

1、先明白几个概念 &#xff08;1&#xff09;平台版本&#xff08;Android SDK版本号&#xff09; 平台版本也就是我们平时说的安卓8、安卓9、安卓10 &#xff08;2&#xff09;API级别&#xff08;API Level&#xff09; Android 平台提供的框架 API 被称作“API 级别” …

Mongodb的通配符索引

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第95篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

Blender 4.2 安装GIS插件步骤

Blender 4 更新以后插件安装变得复杂&#xff0c;插件界面的安装按钮不显示&#xff0c;界面布局改变&#xff0c;怎么安装插件&#xff1a; 1. 在线安装&#xff1a; “编辑”&#xff08;Edit&#xff09;>进入偏好设置&#xff08;Preferences setting&#xff09;>…

文件粉碎销毁 硬盘粉碎销毁 废弃的文件如何销毁

废弃的文件可以采用多种方法进行销毁&#xff0c;具体取决于文件的敏感性和数量。以下是一些常见的废弃文件销毁方法&#xff1a; 1. 机械粉碎&#xff1a;这是一种常见的方法&#xff0c;尤其适用于含有敏感信息的文件。可以使用碎纸机将文件切碎&#xff0c;对于小批量的资料…

Python新手如何制作植物大战僵尸?这篇文章教会你!

引言 《植物大战僵尸》是一款非常受欢迎的塔防游戏&#xff0c;玩家需要种植各种植物来抵御僵尸的进攻。在这篇文章中&#xff0c;我们将使用Python编写一个简化版的植物大战僵尸游戏&#xff0c;以展示如何使用Python创建游戏。 游戏规则 玩家将种植不同类型的植物来防御僵尸…

微软“蓝屏”事件:对全球IT基础设施韧性与安全性的深刻反思

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

【ai】windows ollama安装qwen

可以直接github下载,或者官方网站下载:参考大神的介绍当前最新0.28安装windows的预览版本,出现一个服务? 直接跑会TLS超时? 配置代理 export https_proxy=http://192.168.50.65:7890 export http_proxy

JavaWeb笔记_Session

Session概述 Session是一种在服务端记录用户会话信息的技术 Session的创建和获取 /*** HttpServletRequest对象中的方法:* public HttpSession getSession()* 如果当前服务端没有session,那就在服务端新建一个session对象* 如果在服务端有这个session,那么就直…

【C++】类和对象之继承

目录 继承的概念和定义 继承的概念 继承的定义 继承的定义格式 继承关系和访问限定符 继承基类成员访问方式的变化 访问权限实例 基类和派生类对象赋值转换 继承中的作用域 派生类的默认成员函数 继承与友元 继承与静态成员 复杂的菱形继承及菱形虚拟继承 继承的…