@pipelab/plugin-netlify 1.0.0-beta.1 → 1.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -3
- package/CHANGELOG.md +0 -18
- package/src/assets/netlify-icon.webp +0 -0
- package/src/build.ts +0 -158
- package/src/index.ts +0 -26
- package/src/publish.ts +0 -236
- package/tsconfig.json +0 -8
- package/tsdown.config.ts +0 -15
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipelab/plugin-netlify",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.4",
|
|
4
4
|
"license": "FSL-1.1-MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/CynToolkit/pipelab.git",
|
|
8
8
|
"directory": "plugins/plugin-netlify"
|
|
9
9
|
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
10
13
|
"type": "module",
|
|
11
14
|
"main": "./dist/index.cjs",
|
|
12
15
|
"module": "./dist/index.mjs",
|
|
@@ -18,12 +21,12 @@
|
|
|
18
21
|
"@types/node": "^24.12.2",
|
|
19
22
|
"electron": "32.1.2",
|
|
20
23
|
"untun": "0.1.3",
|
|
21
|
-
"@pipelab/plugin-core": "1.0.0-beta.
|
|
24
|
+
"@pipelab/plugin-core": "1.0.0-beta.4"
|
|
22
25
|
},
|
|
23
26
|
"devDependencies": {
|
|
24
27
|
"tsdown": "0.21.2",
|
|
25
28
|
"typescript": "5.9.3",
|
|
26
|
-
"@pipelab/tsconfig": "1.0.0-beta.
|
|
29
|
+
"@pipelab/tsconfig": "1.0.0-beta.2"
|
|
27
30
|
},
|
|
28
31
|
"scripts": {
|
|
29
32
|
"format": "oxfmt .",
|
package/CHANGELOG.md
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# @pipelab/plugin-netlify
|
|
2
|
-
|
|
3
|
-
## 1.0.0-beta.1
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- @pipelab/plugin-core@1.0.0-beta.1
|
|
8
|
-
|
|
9
|
-
## 1.0.0-beta.0
|
|
10
|
-
|
|
11
|
-
### Major Changes
|
|
12
|
-
|
|
13
|
-
- e1befbf: initial release
|
|
14
|
-
|
|
15
|
-
### Patch Changes
|
|
16
|
-
|
|
17
|
-
- Updated dependencies [e1befbf]
|
|
18
|
-
- @pipelab/plugin-core@1.0.0-beta.0
|
|
Binary file
|
package/src/build.ts
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { ensure, extractZip, zipFolder } from "@pipelab/plugin-core";
|
|
2
|
-
import {
|
|
3
|
-
createAction,
|
|
4
|
-
createActionRunner,
|
|
5
|
-
createNetlifySiteParam,
|
|
6
|
-
createPathParam,
|
|
7
|
-
createStringParam,
|
|
8
|
-
downloadFile,
|
|
9
|
-
fileExists,
|
|
10
|
-
runWithLiveLogs,
|
|
11
|
-
runPnpm,
|
|
12
|
-
} from "@pipelab/plugin-core";
|
|
13
|
-
import { createReadStream } from "node:fs";
|
|
14
|
-
import { cp, mkdir, rm, writeFile } from "node:fs/promises";
|
|
15
|
-
import { delimiter, dirname, join } from "node:path";
|
|
16
|
-
|
|
17
|
-
export const ID = "netlify-build";
|
|
18
|
-
|
|
19
|
-
export const buildNetlifySite = createAction({
|
|
20
|
-
id: ID,
|
|
21
|
-
name: "Build Netlify site",
|
|
22
|
-
description: "",
|
|
23
|
-
icon: "",
|
|
24
|
-
displayString: "`Build ${fmt.param(params['input-folder'], 'primary', 'No path selected')}`",
|
|
25
|
-
meta: {},
|
|
26
|
-
params: {
|
|
27
|
-
"input-folder": createPathParam("", {
|
|
28
|
-
required: true,
|
|
29
|
-
label: "Path to the folder to upload to netlify",
|
|
30
|
-
control: {
|
|
31
|
-
type: "path",
|
|
32
|
-
options: {
|
|
33
|
-
properties: ["openDirectory"],
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
}),
|
|
37
|
-
token: createStringParam("", {
|
|
38
|
-
required: true,
|
|
39
|
-
label: "Token",
|
|
40
|
-
}),
|
|
41
|
-
},
|
|
42
|
-
outputs: {},
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
export const buildNetlifySiteRunner = createActionRunner<typeof buildNetlifySite>(
|
|
46
|
-
async ({ log, inputs, cwd, abortSignal, paths }) => {
|
|
47
|
-
log("Building netlify site");
|
|
48
|
-
|
|
49
|
-
const { node } = paths;
|
|
50
|
-
|
|
51
|
-
const buildDir = join(cwd, "build");
|
|
52
|
-
|
|
53
|
-
const inputFolder = inputs["input-folder"];
|
|
54
|
-
// ensure input folder have apackage.json
|
|
55
|
-
const packageJsonPath = join(inputFolder, "package.json");
|
|
56
|
-
const packageJson = await fileExists(packageJsonPath);
|
|
57
|
-
if (!packageJson) {
|
|
58
|
-
throw new Error("No package.json found in input folder");
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
await cp(inputs["input-folder"], buildDir, { recursive: true });
|
|
62
|
-
|
|
63
|
-
const netlifyDir = join(buildDir, ".netlify");
|
|
64
|
-
const netlifyState = join(netlifyDir, "state.json");
|
|
65
|
-
|
|
66
|
-
await mkdir(netlifyDir, { recursive: true });
|
|
67
|
-
|
|
68
|
-
await writeFile(netlifyState, `{ "siteId": "${inputs.site}" }`, "utf-8");
|
|
69
|
-
|
|
70
|
-
// log('Installing packages')
|
|
71
|
-
// await runWithLiveLogs(
|
|
72
|
-
// node,
|
|
73
|
-
// [pnpm, 'install', '--prefer-offline'],
|
|
74
|
-
// {
|
|
75
|
-
// cwd: buildDir,
|
|
76
|
-
// env: {
|
|
77
|
-
// // DEBUG: '*',
|
|
78
|
-
// PATH: `${dirname(node)}${delimiter}${process.env.PATH}`,
|
|
79
|
-
// PNPM_HOME: pnpmHome
|
|
80
|
-
// },
|
|
81
|
-
// cancelSignal: abortSignal
|
|
82
|
-
// },
|
|
83
|
-
// log,
|
|
84
|
-
// {
|
|
85
|
-
// onStderr(data) {
|
|
86
|
-
// log(data)
|
|
87
|
-
// },
|
|
88
|
-
// onStdout(data) {
|
|
89
|
-
// log(data)
|
|
90
|
-
// }
|
|
91
|
-
// }
|
|
92
|
-
// )
|
|
93
|
-
|
|
94
|
-
// await runWithLiveLogs(
|
|
95
|
-
// node,
|
|
96
|
-
// [pnpm, 'build', '--preset', 'netlify'],
|
|
97
|
-
// {
|
|
98
|
-
// cwd: buildDir,
|
|
99
|
-
// env: {
|
|
100
|
-
// // DEBUG: '*',
|
|
101
|
-
// PATH: `${dirname(node)}${delimiter}${process.env.PATH}`,
|
|
102
|
-
// PNPM_HOME: pnpmHome
|
|
103
|
-
// },
|
|
104
|
-
// cancelSignal: abortSignal
|
|
105
|
-
// },
|
|
106
|
-
// log,
|
|
107
|
-
// {
|
|
108
|
-
// onStderr(data) {
|
|
109
|
-
// log(data)
|
|
110
|
-
// },
|
|
111
|
-
// onStdout(data) {
|
|
112
|
-
// log(data)
|
|
113
|
-
// }
|
|
114
|
-
// }
|
|
115
|
-
// )
|
|
116
|
-
const { all: buildOut } = await runPnpm(buildDir, {
|
|
117
|
-
args: ["--package", "netlify-cli", "dlx", "netlify", "build"],
|
|
118
|
-
extraEnv: {
|
|
119
|
-
NETLIFY_AUTH_TOKEN: inputs.token,
|
|
120
|
-
},
|
|
121
|
-
signal: abortSignal,
|
|
122
|
-
});
|
|
123
|
-
if (buildOut) log(buildOut);
|
|
124
|
-
|
|
125
|
-
// const distDir = join(buildDir, 'dist')
|
|
126
|
-
|
|
127
|
-
// const distZipPath = join(cwd, 'dist.zip')
|
|
128
|
-
// const zip = await zipFolder(distDir, distZipPath, log)
|
|
129
|
-
|
|
130
|
-
// console.log('zip', zip)
|
|
131
|
-
// console.log('distZipPath', distZipPath)
|
|
132
|
-
|
|
133
|
-
// const result = await fetch(`https://api.netlify.com/api/v1/sites/${inputs.site}/deploys`, {
|
|
134
|
-
// method: 'POST',
|
|
135
|
-
// body: createReadStream(distZipPath),
|
|
136
|
-
// headers: {
|
|
137
|
-
// 'Content-Type': 'application/zip',
|
|
138
|
-
// Authorization: `Bearer ${inputs.token}`
|
|
139
|
-
// },
|
|
140
|
-
// duplex: 'half'
|
|
141
|
-
// })
|
|
142
|
-
//
|
|
143
|
-
// const deploy = await result.json()
|
|
144
|
-
|
|
145
|
-
const { all: deployOut } = await runPnpm(buildDir, {
|
|
146
|
-
args: ["--package", "netlify-cli", "dlx", "netlify", "deploy", "--prod"],
|
|
147
|
-
extraEnv: {
|
|
148
|
-
NETLIFY_AUTH_TOKEN: inputs.token,
|
|
149
|
-
},
|
|
150
|
-
signal: abortSignal,
|
|
151
|
-
});
|
|
152
|
-
if (deployOut) log(deployOut);
|
|
153
|
-
|
|
154
|
-
// log('Deployed to netlify', deploy)
|
|
155
|
-
|
|
156
|
-
log("Uploaded to netlify");
|
|
157
|
-
},
|
|
158
|
-
);
|
package/src/index.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { uploadToNetlify, uploadToNetlifyRunner } from "./publish";
|
|
2
|
-
import { buildNetlifySite, buildNetlifySiteRunner } from "./build";
|
|
3
|
-
|
|
4
|
-
import { createNodeDefinition } from "@pipelab/plugin-core";
|
|
5
|
-
const icon = new URL("./assets/netlify-icon.webp", import.meta.url).href;
|
|
6
|
-
|
|
7
|
-
export default createNodeDefinition({
|
|
8
|
-
description: "Netlify",
|
|
9
|
-
name: "Netlify",
|
|
10
|
-
id: "netlify",
|
|
11
|
-
icon: {
|
|
12
|
-
type: "image",
|
|
13
|
-
image: icon,
|
|
14
|
-
},
|
|
15
|
-
nodes: [
|
|
16
|
-
// make and package
|
|
17
|
-
{
|
|
18
|
-
node: buildNetlifySite,
|
|
19
|
-
runner: buildNetlifySiteRunner,
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
node: uploadToNetlify,
|
|
23
|
-
runner: uploadToNetlifyRunner,
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
});
|
package/src/publish.ts
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import { ensure, extractZip, zipFolder } from "@pipelab/plugin-core";
|
|
2
|
-
import {
|
|
3
|
-
createAction,
|
|
4
|
-
createActionRunner,
|
|
5
|
-
createNetlifySiteParam,
|
|
6
|
-
createPathParam,
|
|
7
|
-
createStringParam,
|
|
8
|
-
downloadFile,
|
|
9
|
-
fileExists,
|
|
10
|
-
runWithLiveLogs,
|
|
11
|
-
runPnpm,
|
|
12
|
-
fetchPipelabAsset,
|
|
13
|
-
} from "@pipelab/plugin-core";
|
|
14
|
-
import { createReadStream } from "node:fs";
|
|
15
|
-
import { cp, mkdir, rm, writeFile } from "node:fs/promises";
|
|
16
|
-
import { delimiter, dirname, join, basename } from "node:path";
|
|
17
|
-
|
|
18
|
-
export const ID = "netlify-upload";
|
|
19
|
-
|
|
20
|
-
export interface ButlerJSONOutputLog {
|
|
21
|
-
level: "info";
|
|
22
|
-
message: string;
|
|
23
|
-
time: number;
|
|
24
|
-
type: "log";
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface ButlerJSONOutputProgress {
|
|
28
|
-
bps: number;
|
|
29
|
-
eta: number;
|
|
30
|
-
progress: number;
|
|
31
|
-
time: 1736873335;
|
|
32
|
-
type: "progress";
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export type ButlerJSONOutput = ButlerJSONOutputLog | ButlerJSONOutputProgress;
|
|
36
|
-
|
|
37
|
-
export const uploadToNetlify = createAction({
|
|
38
|
-
id: ID,
|
|
39
|
-
name: "Upload to Netlify",
|
|
40
|
-
description: "",
|
|
41
|
-
icon: "",
|
|
42
|
-
displayString:
|
|
43
|
-
"`Upload ${fmt.param(params['input-folder'], 'primary', 'No path selected')} to ${fmt.param(params['site'], 'primary', 'No site')}`",
|
|
44
|
-
meta: {},
|
|
45
|
-
params: {
|
|
46
|
-
"input-folder": createPathParam("", {
|
|
47
|
-
required: true,
|
|
48
|
-
label: "Path to the folder to upload to netlify",
|
|
49
|
-
control: {
|
|
50
|
-
type: "path",
|
|
51
|
-
options: {
|
|
52
|
-
properties: ["openDirectory"],
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
}),
|
|
56
|
-
token: createStringParam("", {
|
|
57
|
-
required: true,
|
|
58
|
-
label: "Token",
|
|
59
|
-
}),
|
|
60
|
-
site: createNetlifySiteParam("", "token", {
|
|
61
|
-
required: true,
|
|
62
|
-
label: "Site",
|
|
63
|
-
}),
|
|
64
|
-
},
|
|
65
|
-
outputs: {},
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
export const uploadToNetlifyRunner = createActionRunner<typeof uploadToNetlify>(
|
|
69
|
-
async ({ log, inputs, cwd, abortSignal, paths, context }) => {
|
|
70
|
-
log("Uploading to netlify");
|
|
71
|
-
|
|
72
|
-
const { node } = paths;
|
|
73
|
-
|
|
74
|
-
const sitesResult = await fetch(`https://api.netlify.com/api/v1/sites/${inputs.site}`, {
|
|
75
|
-
method: "GET",
|
|
76
|
-
headers: {
|
|
77
|
-
"Content-Type": "application/zip",
|
|
78
|
-
Authorization: `Bearer ${inputs.token}`,
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
|
-
const site = await sitesResult.json();
|
|
82
|
-
|
|
83
|
-
log("site", site);
|
|
84
|
-
if (!site) {
|
|
85
|
-
throw new Error("Site does not exist");
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const appFolder = inputs["input-folder"];
|
|
89
|
-
|
|
90
|
-
// 1. Prepare input folder with temmplate
|
|
91
|
-
// Assume input folder is always a static site
|
|
92
|
-
const destinationFolder = join(cwd);
|
|
93
|
-
const rawAssetFolder = await fetchPipelabAsset("@pipelab/asset-netlify", "^1.0.0", { context });
|
|
94
|
-
const templateFolder = join(rawAssetFolder, "template");
|
|
95
|
-
|
|
96
|
-
// copy template to destination
|
|
97
|
-
await cp(templateFolder, destinationFolder, {
|
|
98
|
-
recursive: true,
|
|
99
|
-
filter: (src) => {
|
|
100
|
-
return basename(src) !== "node_modules";
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
const placeAppFolder = join(destinationFolder, "dist");
|
|
104
|
-
if (appFolder) {
|
|
105
|
-
// copy app to template
|
|
106
|
-
await cp(appFolder, placeAppFolder, { recursive: true });
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// 2. Ensure correct configuration
|
|
110
|
-
const packageJsonPath = join(appFolder, "package.json");
|
|
111
|
-
const packageJson = await fileExists(packageJsonPath);
|
|
112
|
-
if (!packageJson) {
|
|
113
|
-
throw new Error("No package.json found in input folder");
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const netlifyDir = join(destinationFolder, ".netlify");
|
|
117
|
-
const netlifyState = join(netlifyDir, "state.json");
|
|
118
|
-
|
|
119
|
-
await mkdir(netlifyDir, { recursive: true });
|
|
120
|
-
|
|
121
|
-
await writeFile(netlifyState, `{ "siteId": "${inputs.site}" }`, "utf-8");
|
|
122
|
-
|
|
123
|
-
// 3. Package installation
|
|
124
|
-
log("Installing packages");
|
|
125
|
-
const { all } = await runPnpm(destinationFolder, {
|
|
126
|
-
signal: abortSignal,
|
|
127
|
-
context,
|
|
128
|
-
});
|
|
129
|
-
// 4. netlify deploy
|
|
130
|
-
const { all: deployOut } = await runPnpm(destinationFolder, {
|
|
131
|
-
args: ["--package", "netlify-cli", "dlx", "netlify", "deploy", "--prod"],
|
|
132
|
-
extraEnv: {
|
|
133
|
-
NETLIFY_AUTH_TOKEN: inputs.token,
|
|
134
|
-
},
|
|
135
|
-
signal: abortSignal,
|
|
136
|
-
context,
|
|
137
|
-
});
|
|
138
|
-
if (deployOut) log(deployOut);
|
|
139
|
-
|
|
140
|
-
// ensure input folder have a package.json
|
|
141
|
-
|
|
142
|
-
// await runWithLiveLogs(
|
|
143
|
-
// node,
|
|
144
|
-
// [pnpm, 'build', '--preset', 'netlify'],
|
|
145
|
-
// {
|
|
146
|
-
// cwd: buildDir,
|
|
147
|
-
// env: {
|
|
148
|
-
// // DEBUG: '*',
|
|
149
|
-
// PATH: `${dirname(node)}${delimiter}${process.env.PATH}`,
|
|
150
|
-
// PNPM_HOME: pnpmHome
|
|
151
|
-
// },
|
|
152
|
-
// cancelSignal: abortSignal
|
|
153
|
-
// },
|
|
154
|
-
// log,
|
|
155
|
-
// {
|
|
156
|
-
// onStderr(data) {
|
|
157
|
-
// log(data)
|
|
158
|
-
// },
|
|
159
|
-
// onStdout(data) {
|
|
160
|
-
// log(data)
|
|
161
|
-
// }
|
|
162
|
-
// }
|
|
163
|
-
// )
|
|
164
|
-
// await runWithLiveLogs(
|
|
165
|
-
// node,
|
|
166
|
-
// [pnpm, '--package', 'netlify-cli', 'dlx', 'netlify', 'build'],
|
|
167
|
-
// {
|
|
168
|
-
// cwd: buildDir,
|
|
169
|
-
// env: {
|
|
170
|
-
// // DEBUG: '*',
|
|
171
|
-
// PATH: `${dirname(node)}${delimiter}${process.env.PATH}`,
|
|
172
|
-
// PNPM_HOME: pnpmHome,
|
|
173
|
-
// NETLIFY_AUTH_TOKEN: inputs.token
|
|
174
|
-
// },
|
|
175
|
-
// cancelSignal: abortSignal
|
|
176
|
-
// },
|
|
177
|
-
// log,
|
|
178
|
-
// {
|
|
179
|
-
// onStderr(data) {
|
|
180
|
-
// log(data)
|
|
181
|
-
// },
|
|
182
|
-
// onStdout(data) {
|
|
183
|
-
// log(data)
|
|
184
|
-
// }
|
|
185
|
-
// }
|
|
186
|
-
// )
|
|
187
|
-
|
|
188
|
-
// const distDir = join(buildDir, 'dist')
|
|
189
|
-
|
|
190
|
-
// const distZipPath = join(cwd, 'dist.zip')
|
|
191
|
-
// const zip = await zipFolder(distDir, distZipPath, log)
|
|
192
|
-
|
|
193
|
-
// console.log('zip', zip)
|
|
194
|
-
// console.log('distZipPath', distZipPath)
|
|
195
|
-
|
|
196
|
-
// const result = await fetch(`https://api.netlify.com/api/v1/sites/${inputs.site}/deploys`, {
|
|
197
|
-
// method: 'POST',
|
|
198
|
-
// body: createReadStream(distZipPath),
|
|
199
|
-
// headers: {
|
|
200
|
-
// 'Content-Type': 'application/zip',
|
|
201
|
-
// Authorization: `Bearer ${inputs.token}`
|
|
202
|
-
// },
|
|
203
|
-
// duplex: 'half'
|
|
204
|
-
// })
|
|
205
|
-
//
|
|
206
|
-
// const deploy = await result.json()
|
|
207
|
-
|
|
208
|
-
// await runWithLiveLogs(
|
|
209
|
-
// node,
|
|
210
|
-
// [pnpm, '--package', 'netlify-cli', 'dlx', 'netlify', 'deploy', '--prod'],
|
|
211
|
-
// {
|
|
212
|
-
// cwd: buildDir,
|
|
213
|
-
// env: {
|
|
214
|
-
// // DEBUG: '*',
|
|
215
|
-
// PATH: `${dirname(node)}${delimiter}${process.env.PATH}`,
|
|
216
|
-
// PNPM_HOME: pnpmHome,
|
|
217
|
-
// NETLIFY_AUTH_TOKEN: inputs.token
|
|
218
|
-
// },
|
|
219
|
-
// cancelSignal: abortSignal
|
|
220
|
-
// },
|
|
221
|
-
// log,
|
|
222
|
-
// {
|
|
223
|
-
// onStderr(data) {
|
|
224
|
-
// log(data)
|
|
225
|
-
// },
|
|
226
|
-
// onStdout(data) {
|
|
227
|
-
// log(data)
|
|
228
|
-
// }
|
|
229
|
-
// }
|
|
230
|
-
// )
|
|
231
|
-
|
|
232
|
-
// log('Deployed to netlify', deploy)
|
|
233
|
-
|
|
234
|
-
log("Uploaded to netlify");
|
|
235
|
-
},
|
|
236
|
-
);
|
package/tsconfig.json
DELETED
package/tsdown.config.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "tsdown";
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
entry: ["src/index.ts"],
|
|
5
|
-
format: ["esm", "cjs"],
|
|
6
|
-
dts: true,
|
|
7
|
-
clean: true,
|
|
8
|
-
loader: {
|
|
9
|
-
".webp": "dataurl",
|
|
10
|
-
".png": "dataurl",
|
|
11
|
-
".jpg": "dataurl",
|
|
12
|
-
".jpeg": "dataurl",
|
|
13
|
-
".svg": "dataurl",
|
|
14
|
-
},
|
|
15
|
-
});
|