UNPKG

4.35 kBPlain TextView Raw
1<template>
2 <div class="monitor">
3 <div id="monitor-iframe">
4 <div class="monitor-iframe-holder" ref="iframe"></div>
5 </div>
6 <console class="monitor-console"></console>
7 </div>
8</template>
9
10<script>
11import { mapActions, mapState } from 'vuex';
12import progress from 'nprogress';
13import bus from '@/js/eventbus.js';
14import createIframe from '@/js/iframe.js';
15import * as transform from '@/js/transform.js';
16import proxyConsole from '!raw-loader!babel-loader!@/js/proxy-console';
17import Console from './console.vue';
18
19const sandboxAttributes = [
20 // 'allow-modals',
21 'allow-forms',
22 'allow-pointer-lock',
23 'allow-popups',
24 'allow-same-origin',
25 'allow-scripts'
26];
27
28const replaceQuote = str => str.replace(/__QUOTE_LEFT__/g, '<');
29const createElement = tag => (content = '', attrs = {}) => {
30 attrs = Object.keys(attrs)
31 .map(key => {
32 return `${key}="${attrs[key]}"`;
33 })
34 .join(' ');
35 return replaceQuote(
36 `__QUOTE_LEFT__${tag} ${attrs}>${content}__QUOTE_LEFT__/${tag}>`
37 );
38};
39
40export default {
41 data() {
42 return {
43 iframe: null,
44 runTimer: null
45 };
46 },
47 components: { Console },
48 computed: {
49 ...mapState(['boxes', 'autoRun', 'dependencies'])
50 },
51 mounted() {
52 this.iframe = createIframe({
53 el: this.$refs.iframe,
54 sandboxAttrs: sandboxAttributes
55 });
56 window.addEventListener('message', this.listenIframe);
57 bus.$on('run', this.run);
58 window.monitor = this;
59 },
60 beforeDestroy() {
61 window.removeEventListener('message', this.listenIframe);
62 },
63 methods: {
64 ...mapActions(['setIframeStatus', 'transform', 'clearLogs', 'addLog']),
65 run() {
66 progress.start();
67 clearTimeout(this.runTimer);
68 this.runTimer = setTimeout(async () => {
69 this.clearLogs();
70 this.setIframeStatus('loading');
71 await this.transform(true);
72 const headStyle = await this.transformCSS();
73 const html = await this.transformHTML();
74 const rawData = await this.transformRawData();
75 const jsScript = await this.transformJS();
76 const runtimeScript = await this.runtimeScript();
77 const runtimeStyle = await this.runtimeStyle();
78 this.iframe.setContent({
79 head: headStyle + runtimeStyle,
80 body: html + runtimeScript + rawData + jsScript
81 });
82 progress.done();
83 }, 1000);
84 },
85 async runtimeScript() {
86 const console = createElement('script')(proxyConsole);
87 const dependencies = this.dependencies.js
88 .map(dependence => `<script src="${dependence}"><\/script>`) //eslint-disable-line no-useless-escape
89 .join('\n');
90 return console + '\n' + dependencies;
91 },
92 async runtimeStyle() {
93 const dependencies = this.dependencies.css
94 .map(dependence => `<link rel="stylesheet" href="${dependence}">`) //eslint-disable-line no-useless-escape
95 .join('\n');
96 return dependencies;
97 },
98 async transformCSS() {
99 let code = '';
100 if (this.boxes.css) {
101 code = await transform.css(this.boxes.css).then(code => {
102 return code;
103 });
104 }
105 return createElement('style')(code);
106 },
107 async transformHTML() {
108 let code = '';
109 if (this.boxes.html) {
110 code = await transform.html(this.boxes.html);
111 }
112 return code;
113 },
114 async transformJS() {
115 let code = '';
116 if (this.boxes.javascript) {
117 code = await transform.javascript(this.boxes.javascript);
118 }
119 return createElement('script')(code);
120 },
121 async transformRawData() {
122 let code = '';
123 if (this.boxes.rawdata) {
124 code = await transform.rawdata(this.boxes.rawdata);
125 }
126 return createElement('script')(code, { type: 'text/x-rawdata' });
127 },
128 listenIframe({ data = {} }) {
129 if (data.type === 'demoground-console') {
130 if (data.method === 'clear') {
131 this.clearLogs();
132 } else {
133 this.addLog({ type: data.method, message: data.args.join('\\n') });
134 }
135 }
136 }
137 }
138};
139</script>
140
141<style lang="scss">
142@import '@/css/index.scss';
143.monitor {
144 max-height: 100%;
145 box-sizing: border-box;
146 padding: 20px 20px 0 20px;
147 display: flex;
148 flex-direction: column;
149 & #monitor-iframe {
150 width: 100%;
151 height: 100px;
152 flex-grow: 1;
153 background: $c-bg;
154 }
155}
156</style>