-
Notifications
You must be signed in to change notification settings - Fork 1
/
iframe-loader.js
88 lines (84 loc) · 2.92 KB
/
iframe-loader.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
/**
* This loader allows loading iframes specifically for this project. The iframes are
* loaded in such a way that they can use typescript content and such content is then
* compiled and attached as a data-uri
*
* This way, each iframe is self contained and isolated so it can be used in the final
* application as a single entity and allow applications to sign transactions inside these
* sandboxed and isolated iframes.
*/
const cheerio = require("cheerio");
const webpackConfig = require("./webpack.nested.config");
const webpack = require("webpack");
const fs = require("fs");
const logStats = require("./utils");
const path = require("path");
const compileTypescriptFile = async (filePath) => {
return new Promise((resolve, reject) => {
const name = path.basename(filePath.replace(/\.ts$/, ""));
const resultPath = path.resolve(__dirname, "lib");
webpack(webpackConfig(name, filePath, resultPath), (error, stats) => {
if (error) {
reject(error.details);
} else {
const information = stats.toJson();
if (stats.hasErrors()) {
const { errors } = information;
reject(errors.join("\n"));
} else {
if (stats.hasWarnings()) {
const { warnings } = information;
// Show them but still emit the file
console.warn(warnings.join("\n"));
} else {
// Display stats as default webpack does
logStats(information);
}
// FIXME: show stats
const temporaryPath = path.join(resultPath, `${name}.js`);
const contentBuffer = fs.readFileSync(temporaryPath);
// Delete the temporary file
fs.unlinkSync(temporaryPath);
// Return ths script content
resolve(contentBuffer);
}
}
});
});
};
const handleScripts = async (content) => {
const document = cheerio.load(content);
const script = document('script[type="text/prs.typescript"]');
// Wait to parse all the frames
const absolutePath = path.resolve(__dirname, script.attr("src"));
// Compile typescript
const compiled = await compileTypescriptFile(absolutePath);
// Replace the src with a data uri
// script.removeAttr("src");
// Write the script into the iframe, note that we don't
// want the library to escape anything so we use the text
// method
script.replaceWith(
`<script type="text/javascript">${compiled.toString()}</script>`,
);
return document;
};
const loader = function (content, map, meta) {
const callback = this.async();
const loader = async () => {
// Get all iframes (there will be just 1)
const document = await handleScripts(content);
// Now convert it to string
return document.html();
};
loader()
.then((result) => {
callback(null, result, map, meta);
})
.catch((message) => {
this.emitError(message);
// Also print it?
console.error(message);
});
};
module.exports = loader;