1 | const vm = require("vm");
|
2 | const asyncro = require("asyncro");
|
3 | const mime = require("mime");
|
4 | const CleanCSS = require("clean-css");
|
5 |
|
6 | const resource = require("./resource");
|
7 |
|
8 | const transformers = new Map;
|
9 | const cleanCss = new CleanCSS;
|
10 |
|
11 | const DEFAULT_TRANSFORMS = [{
|
12 | name: "string",
|
13 | transform(source, content, encoding = "utf8") {
|
14 | if (Buffer.isBuffer(content)) {
|
15 | content = content.toString(encoding);
|
16 | }
|
17 | return content;
|
18 | }
|
19 | }, {
|
20 | name: "cssmin",
|
21 | transform(source, content) {
|
22 | return cleanCss.minify(content).styles;
|
23 | }
|
24 | }, {
|
25 | name: "docstring",
|
26 | transform(source, content) {
|
27 | return content.match(/`((\\`|[^`])+)`/)[1];
|
28 | }
|
29 | }, {
|
30 | name: "stringify",
|
31 | transform(source, content) {
|
32 | return JSON.stringify(content);
|
33 | }
|
34 | }, {
|
35 | name: "dataurl",
|
36 | transform(source, content, type = getMimeType(source), charset = "") {
|
37 | if (!Buffer.isBuffer(content) || type.startsWith("text")) {
|
38 | if (!charset) charset = "utf8";
|
39 | if (!Buffer.isBuffer(content)) {
|
40 | content = Buffer.from(content, charset);
|
41 | }
|
42 | }
|
43 | if (charset) {
|
44 | charset = `;charset=${charset}`;
|
45 | }
|
46 | return `data:${type}${charset};base64,${content.toString("base64")}`;
|
47 | }
|
48 | }, {
|
49 | name: "eval",
|
50 | transform(source, content, code) {
|
51 | return vm.runInNewContext(code, {$0: content});
|
52 | }
|
53 | }, {
|
54 | name: "markdown",
|
55 | transform(source, content, type) {
|
56 | if (type == "codeblock") {
|
57 | return "```\n" + content + "\n```";
|
58 | }
|
59 | if (type == "code") {
|
60 | return "`" + content + "`";
|
61 | }
|
62 | if (type == "quote") {
|
63 | return content.split("\n").map(l => "> " + l).join("\n");
|
64 | }
|
65 | }
|
66 | }, {
|
67 | name: "parse",
|
68 | transform(source, content, ...props) {
|
69 | var json = JSON.parse(content);
|
70 | while (props.length) {
|
71 | json = json[props.shift()];
|
72 | }
|
73 | return json;
|
74 | }
|
75 | }, {
|
76 | name: "trim",
|
77 | transform(source, content) {
|
78 | return content.trim();
|
79 | }
|
80 | }];
|
81 |
|
82 | DEFAULT_TRANSFORMS.forEach(add);
|
83 |
|
84 | function getMimeType(source) {
|
85 | return source && resource.PATH_LIKE.has(source.name) &&
|
86 | mime.getType(source.args[0]) ||
|
87 | "text/plain";
|
88 | }
|
89 |
|
90 | function add(transformer) {
|
91 | transformers.set(transformer.name, transformer);
|
92 | }
|
93 |
|
94 |
|
95 | function transform(source, content, transforms) {
|
96 | return asyncro.reduce(
|
97 | transforms,
|
98 | (content, transform) => {
|
99 | const transformer = transformers.get(transform.name);
|
100 | return transformer.transform(source, content, ...transform.args);
|
101 | },
|
102 | content
|
103 | );
|
104 | }
|
105 |
|
106 | function has(name) {
|
107 | return transformers.has(name);
|
108 | }
|
109 |
|
110 | module.exports = {add, transform, has};
|