Chrome扩展

前言:这个网站可以生成比较好看的logo,但是logo加了水印还收费(太穷了qaq),所以记了个todo,开发了个chrome扩展让他能自动提取svg保存到本地。

贴一下Chrome官方文档https://developer.chrome.com/docs/extensions/mv3/getstarted/,这里为了简单用的v2,但是v2在23年会下掉,建议用v3。

了解主要文件

manifest.json

这里指定扩展的基本信息,包括名称,描述,图标,允许访问的域名,扩展的UI界面,以及动态注入的脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"manifest_version": 2,
"name": "TanTan",
"version": "1.0.0",
"description": "Hello, Help you Download svg.",
"icons": {
"16": "img/icon16.png",
"48": "img/icon48.png",
"128": "img/icon128.png"
},
"browser_action": {
"default_icon": "img/icon128.png",
"default_popup": "popup.html"
},
"permissions": [
"<all_urls>"
],
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"content.js"
],
"run_at": "document_start"
}
]
}

manifest.json中引入 popup.html ,这里确定了下图这块区域,但由于浏览器的内容安全策略 ( CSP ),不允许使用内联脚本,因此js的操作要放在单独的文件中。也就是下面的popup.js。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<!DOCTYPE html>
<html>

<head>
<title>Covid-19 Stats- UK</title>
<meta charset="utf-8">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.container {
width: 450px;
height: 500px;
display: flex;
flex-flow: column;
align-items: center;
overflow: hidden;
}

.imgs {
width: 400px;
height: 400px;
overflow: auto;
margin-top: 40px;
}
li{
margin-top: 10px;
padding: 10px;
border: 1px solid rgb(179, 179, 179);
}
.button {
position: fixed;
left: 50%;
transform: translate(-50%);
}

ul {
list-style: none;
}
</style>
</head>

<body>
<div class="container mt-3">
<button type="button" class="btn btn-outline-primary button">TanTan</button>
<ul class="imgs"></ul>
</div>
</body>
<script src="popup.js" type="module"></script>

</html>

这里会选中当前的页面,然后给你注入的脚本(content.js)发送数据并接受数据执行callback。

1
2
3
4
5
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, index, function (response) {
if (callback) callback(response);
});
});

整体代码:接受content.js返回给的svg使用canvas做中转,将svg+xml在canvas上绘制,调用canvas方法转成base64的png格式,添加click函数用于保存svg / png。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function drawInlineSVG(svgStr) {
const svg = document.createElement('div')
svg.innerHTML = svgStr
var svgData = new XMLSerializer().serializeToString(svg.children[0]);
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var img = document.createElement("img");
img.setAttribute("src", "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svgData))));
img.onload = function () {
canvas.width = img.width
canvas.height = img.height
ctx.drawImage(img, 0, 0);
const dataURL = canvas.toDataURL("image/png");
console.log(dataURL);
};
return img;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);

element.style.display = 'none';
document.body.appendChild(element);

element.click();

document.body.removeChild(element);
}
// 前端demo代码
function drawInlineSVG(svgStr) {
const svg = document.createElement('div')
svg.innerHTML = svgStr
var svgData = new XMLSerializer().serializeToString(svg.children[0]);
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var img = document.createElement("img");
img.setAttribute("src", "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svgData))));
img.onload = function () {
canvas.width = img.width
canvas.height = img.height
ctx.drawImage(img, 0, 0);
const dataURL = canvas.toDataURL("image/png");
console.log(dataURL);
};
return img;
}
let sum = 10;
function sendMessageToContentScript() {
const callback = (response) => {
const img = drawInlineSVG(response)
const li = document.createElement('li')
li.appendChild(img)
li.addEventListener('click', (e) => {
download('download.svg', response)
})
document.getElementsByClassName('imgs')[0].appendChild(li)
}
for (let index = 0; index <= sum; index += 2) {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, index, function (response) {
if (callback) callback(response);
});
});
}
sum += 10;
}
window.onload = () => {
const btn = document.getElementsByClassName('button')[0]
const ul = document.getElementsByClassName('imgs')[0]
btn.addEventListener('click', sendMessageToContentScript)
}

content.js

因为他可以被注入到页面中,所以content.js可以获取到当前页面的dom,因此通过选择器选中svg传给popup.js。

1
2
3
4
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
const svgs = document.querySelectorAll('.svg-card > svg')
sendResponse(svgs[request].outerHTML);
});

Chrome扩展
https://jing-jiu.github.io/jing-jiu/2022/09/05/其他/Chrome扩展/
作者
Jing-Jiu
发布于
2022年9月5日
许可协议