写个 Chrome 扩展程序来 JSON 格式化

1,253 阅读5分钟

背景

平时工作中经常会遇到需要格式化 JSON 查看数据的情况,以前收藏了一个网址用来格式化 JSON 很方便,最近广告越来越多,每次打开都有弹窗广告,烦不胜烦。虽然复制粘贴到编辑器再 Format 可以解决问题,但是比较麻烦,干脆自己写个 Chrome 扩展程序来解决问题。

创建第一个 Chrome 扩展程序

创建

创建 Chrome 扩展程序(或者说 Chrome 插件)其实很简单,我们先创建一个最基础的扩展程序来演示,当用户点击扩展工具栏图标时,该扩展将显示 "Hello Extensions"。

Hello Extension popup

首先,我们新建一个文件夹,我给他命名为 hello-world,并在根目录创建 manifest.json 配置文件:

{
  "manifest_version": 3,
  "name": "Hello Extensions",
  "description": "Base Level Extension",
  "version": "1.0",
  "action": {
    "default_popup": "hello.html",
    "default_icon": "hello_extensions.png"
  }
}

其中 "default_icon": "hello_extensions.png" 指定了图标文件,需要在文件夹添加名为 hello_extensions.png 图片,作为扩展程序的图标。

最后创建 hello.html 文件。

<html>
  <body>
    <h1>Hello Extensions</h1>
  </body>
</html>

此时我们的文件夹有如下三个文件:

image.png

这样一个简单的扩展程序就完成了,现在需要在 Chrome 加载它。

加载

打开 chrome://extensions ,按下图先打开“开发者模式”,然后点击“加载已解压的扩展程序”来加载我们刚才创建的扩展程序文件夹(我的为 hello-world) 。

Pasted Graphic.png

现在可以在打开新页面后,在扩展程序中找到我们新创建的 "Hello Extensions" 了,可以点击 “图钉” 图标将扩展固定在 Tab 上。

image.png

点击扩展程序的图标,可以看到弹出了 "Hello Extensions"。

image.png

刷新

现在尝试修改 manifest.json 中的 name,然后在扩展程序管理中刷新,可以看到扩展程序的名字发生了变化。

{
  "manifest_version": 3,
  "name": "Hello World",
  // ...
}
image.png

manifest.json

在 Chrome 扩展开发中,manifest.json 是必须包含的文件。它是一个 JSON 格式的文件,包含了 Chrome 扩展的元数据和配置信息。Chrome 浏览器通过解析这个文件来了解如何加载和管理插件。以下是 manifest.json 文件中可能包含的一些重要字段及其作用:

  • manifest_version:指定 manifest 文件的版本,目前的版本为 3。
  • name:插件的名称。
  • version:插件的版本号。
  • description:对插件功能的简短描述。
  • icons:插件的图标,可以在不同的上下文中使用,比如扩展栏、扩展管理页面等。
  • permissions:插件请求的权限列表,如访问标签页、使用cookies、访问特定网站的数据等。
  • host_permissions:列出扩展可以访问的网站。
  • action:用于定义扩展在浏览器工具栏中的按钮及其行为。
  • background
    • service_worker:指定扩展的后台服务工作线程。Manifest V3不再支持长时间运行的后台页面,而是使用服务工作线程。
  • content_scripts:指定插件将注入到网页中的脚本,以及这些脚本应当在哪些网页上运行。
  • options_ui
    • page:定义扩展的选项页面。
    • open_in_tab:布尔值,指定选项页面是否在新标签页中打开。
  • content_security_policy
    • extension_pages:定义了扩展页面的内容安全策略。
  • web_accessible_resources
    • resources:列出了哪些资源可以被网页内容访问。
    • extension_ids:指定哪些扩展可以访问这些资源。
  • declarativeNetRequest
    • rule_resources:定义了扩展声明性网络请求规则的资源。
  • commands:定义插件的快捷键命令。

JSON 编辑器

学会了创建扩展程序,接下来开始正题。格式化 JSON 前需要先找一个 JSON 编辑器。我选择了 jsoneditor

接下来简单写个 JSON 格式化的页面:

  • HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JSON格式化</title>
    <link rel="stylesheet" href="./index.css" />
    <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/9.10.4/jsoneditor.min.js"></script> -->
    <!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/9.10.4/jsoneditor.min.css" />  -->

    <script src="../lib/jsoneditor.min.js"></script>
    <link rel="stylesheet" href="../lib/jsoneditor.min.css" />
  </head>
  <body>
    <div class="container">
      <textarea type="textarea" id="input" class="source"> </textarea>
      <div id="jsoneditor" class="target"></div>
    </div>

    <script src="./index.js"></script>
  </body>
</html>
  • JavaScript
const container = document.getElementById("jsoneditor");
const errorMsg = document.getElementById("errorMsg");
const input = document.getElementById("input");

const options = {
  modes: ["code", "form", "tree"],
  onChangeText(text) {
    try {
      const json = JSON.parse(text);
      input.value = JSON.stringify(json, null, 4);
    } catch (e) {}
  },
  showErrorTable: true,
};

const editor = new JSONEditor(container, options, "");

input.addEventListener("input", (event) => {
  const text = event.target.value;
  if (!text) {
    editor.set();
    editor.container.className = "target";
    return;
  }
  try {
    const json = JSON.parse(text);
    editor.set(json);
    editor.container.className = "target";
  } catch (e) {
    editor.set(e.message);
    editor.container.className = "target error-status";
  }
});
  • CSS
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html,
body {
  height: 100%;
}
.container {
  display: flex;
  flex-direction: row;
  font-family: menlo, "monospace", Tahoma, 微软雅黑, 幼圆 !important;
  height: 100%;
  padding: 20px;
  position: relative;
}
.source {
  flex: 45% 0 0;
  margin-right: 10px;
  padding: 10px 10px 10px 30px;
  border: 0;
  border-radius: 0;
  resize: none;
  outline: none;
  border: 1px solid #d8d8d8;
  border-radius: 5px;
  font-size: 16px;
}
.target {
  flex: 1;
}

/* JSON编辑器菜单 */
div.jsoneditor,
div.jsoneditor-menu {
  border-color: #35cca2;
}
div.jsoneditor-menu {
  background-color: #35cca2;
}
/* JSON编辑器代码颜色 */
.ace-jsoneditor .ace_variable {
  color: #92278f;
  font-weight: bold;
}
.ace-jsoneditor .ace_string {
  color: #3ab54a;
  font-weight: bold;
}
.ace-jsoneditor .ace_constant.ace_numeric {
  color: #25aae2;
  font-weight: bold;
}
/* 输入不合法JSON的情况下 */
.error-status .ace_constant, .error-status .ace_string {
  color: #f1592a;
  font-weight: bold;
}

页面效果(我承认我借(chao)鉴(xi)了某个 JSON 网站:

image.png

左边是我们贴进去的字符串,右边是格式化后的 JSON。左边或右边编辑的时候,另一边也会同步修改,当 JSON 格式错误时,也会展示对应的错误信息。

其中用到了 jsoneditor 的资源,因为直接在扩展程序打开遇到了跨域的错误,所以我复制了一份到本地。

扩展程序中打开页面

页面已经写好了,可以开始写扩展程序了。

新建一个 json-formatter 文件夹,然后创建 manifest.json 文件:

{
  "manifest_version": 3,
  "name": "JSON Formatter",
  "description": "JSON Formatter",
  "version": "1.0",
  "background": {
    "service_worker": "background.js"
  },
  "permissions": ["scripting"],
  "action": {
    "default_icon": "json.jpg"
  }
}

其中 background.service_worker 指定了扩展程序的脚本文件,我们只需要在这里实现一件事,就是在点击扩展程序的时候,打开 JSON 编辑页面:

chrome.action.onClicked.addListener(function (activeTab) {
  chrome.tabs.create({
    url: "./json-editor/index.html",
    selected: true,
    active: true,
  });
});

最后看一下项目结构:

image.png

效果展示

Apr-24-2024 23-36-29.gif