/
export.js
102 lines (88 loc) · 2.55 KB
/
export.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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import JSZip from "jszip";
import { selectors } from "../../lib/store";
import { convertToBrowserTheme } from "../../lib/themes";
import { makeLog } from "../../lib/utils";
const log = makeLog("export");
export default function performThemeExport({
name = "Default Name",
// TODO: Need other manifest attributes?
store,
bgImages
}) {
log("performThemeExport");
reset();
const zip = new JSZip();
const state = store.getState();
const themeData = selectors.theme(state);
const customBackgrounds = selectors.themeCustomImages(state);
const theme = convertToBrowserTheme(themeData, bgImages, customBackgrounds);
if (theme.images) {
const { images } = theme;
const { additional_backgrounds } = images;
if (images.theme_frame) {
images.theme_frame = addImage(zip, images.theme_frame);
}
if (additional_backgrounds) {
for (let idx = 0; idx < additional_backgrounds.length; idx++) {
additional_backgrounds[idx] = addImage(
zip,
additional_backgrounds[idx]
);
}
}
}
const manifest = {
manifest_version: 2,
version: "1.0",
name,
theme
};
log("manifest", manifest);
zip.file("manifest.json", JSON.stringify(manifest, null, " "));
return Promise.all(pendingImages)
.then(() => zip.generateAsync({ type: "base64" }))
.then(data => "data:application/x-xpinstall;base64," + data);
}
let pendingImages = [];
let currId = 0;
const genId = () => currId++;
function reset() {
pendingImages = [];
currId = 0;
}
const extensions = {
"image/png": ".png",
"image/jpeg": ".jpg",
"image/bmp": ".bmp"
};
function addImage(zip, data) {
if (data.startsWith("data:")) {
// Convert data: URL into binary file entry in zip
const [meta, b64data] = data.split(",", 2);
const [type] = meta.substr(5).split(/;/, 1);
const filename = `images/${genId()}${extensions[type]}`;
zip.file(filename, base64ToUint8array(b64data));
return filename;
}
if (data.startsWith("images/")) {
// Convert file path into pending image fetch.
const filename = data;
pendingImages.push(
fetch(filename)
.then(response => response.blob())
.then(data => zip.file(filename, data))
);
return filename;
}
// TODO: Throw error? The previous conditions should be all known images
return data;
}
function base64ToUint8array(s) {
var byteChars = atob(s);
var l = byteChars.length;
var byteNumbers = new Array(l);
for (var i = 0; i < l; i++) {
byteNumbers[i] = byteChars.charCodeAt(i);
}
return new Uint8Array(byteNumbers);
}