added two apps, and better implementation
This commit is contained in:
Vendored
+2
-2
@@ -11,8 +11,8 @@
|
|||||||
"type": "node-terminal"
|
"type": "node-terminal"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "npm run server",
|
"command": "node run-servers.js",
|
||||||
"name": "2. Start server (w. hot)",
|
"name": "2. Start servers (w. hot)",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "node-terminal"
|
"type": "node-terminal"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
console.log("hello");
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { BaseElement } from "../_base";
|
|
||||||
import { NotificationBubble } from "./notification-bubble";
|
|
||||||
import './notification-bubbles.less';
|
|
||||||
|
|
||||||
export class NotificationBubbles extends BaseElement {
|
|
||||||
add(text: string, type: 'log' | 'info' | 'warn' | 'error' | 'syntax-error') {
|
|
||||||
var bubble = <NotificationBubble>document.createElement("notification-bubble");
|
|
||||||
bubble.innerText = text;
|
|
||||||
bubble.classList.add(type);
|
|
||||||
this.appendChild(bubble);
|
|
||||||
}
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
this.innerHTML = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export function hello() {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
window.onerror = function (error) {
|
|
||||||
parent.document.body.getElementsByTagName("notification-bubbles")[0].add(error, 'syntax-error');
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
try {
|
|
||||||
setTimeout(() => {
|
|
||||||
[replace]
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (ex) {
|
|
||||||
parent.document.body.getElementsByTagName("notification-bubbles")[0].add(ex, 'syntax-error');
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// define a new console
|
|
||||||
var console=(function(oldCons){
|
|
||||||
return {
|
|
||||||
log: function(text){
|
|
||||||
oldCons.log(text);
|
|
||||||
parent.document.body.getElementsByTagName("notification-bubbles")[0].add(text, 'log');
|
|
||||||
},
|
|
||||||
info: function (text) {
|
|
||||||
oldCons.info(text);
|
|
||||||
parent.document.body.getElementsByTagName("notification-bubbles")[0].add(text, 'info');
|
|
||||||
},
|
|
||||||
warn: function (text) {
|
|
||||||
oldCons.warn(text);
|
|
||||||
parent.document.body.getElementsByTagName("notification-bubbles")[0].add(text, 'warn');
|
|
||||||
},
|
|
||||||
error: function (text) {
|
|
||||||
oldCons.error(text);
|
|
||||||
parent.document.body.getElementsByTagName("notification-bubbles")[0].add(text, 'error');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}(window.console));
|
|
||||||
|
|
||||||
//Then redefine the old console
|
|
||||||
window.console = console;
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import { BaseElement } from "../_base";
|
|
||||||
import './output-frame.less';
|
|
||||||
import watchConsole from './injects/watch-console.txt';
|
|
||||||
import tryCatch from './injects/try-catch.txt';
|
|
||||||
import onError from './injects/on-error.txt';
|
|
||||||
import windowStopScript from './injects/window-stop.txt';
|
|
||||||
import { NotificationBubbles } from "../notification-bubbles/notification-bubbles";
|
|
||||||
|
|
||||||
export class OutputFrame extends BaseElement {
|
|
||||||
public Iframe: HTMLIFrameElement | null = null;
|
|
||||||
private watchConsoleScript: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.watchConsoleScript = watchConsole;
|
|
||||||
}
|
|
||||||
|
|
||||||
onInit(): void {
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
onUpdate(): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
if (this.Iframe && this.hasChild(this.Iframe)) {
|
|
||||||
this.removeChild(this.Iframe);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Iframe = document.createElement("iframe");
|
|
||||||
this.Iframe.setAttribute("sandbox", "allow-pointer-lock allow-same-origin allow-scripts");
|
|
||||||
|
|
||||||
this.appendChild(this.Iframe);
|
|
||||||
|
|
||||||
var bubbles = <NotificationBubbles>this.find("notification-bubbles");
|
|
||||||
bubbles.reset();
|
|
||||||
|
|
||||||
this.setInitScript(windowStopScript);
|
|
||||||
this.setInitScript(onError);
|
|
||||||
this.setInitScript(watchConsole);
|
|
||||||
}
|
|
||||||
|
|
||||||
preventInfiniteLoop(value: string) {
|
|
||||||
return value.replace("while (true)", "while (false)");
|
|
||||||
}
|
|
||||||
|
|
||||||
private setInitScript(value: string) {
|
|
||||||
var script: HTMLScriptElement = document.createElement("script");
|
|
||||||
script.setAttribute("async", "");
|
|
||||||
script.innerHTML = this.preventInfiniteLoop(value);
|
|
||||||
|
|
||||||
this.Iframe?.contentWindow?.document.body.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
setScript(value: string) {
|
|
||||||
this.reset();
|
|
||||||
|
|
||||||
var script: HTMLScriptElement = document.createElement("script");
|
|
||||||
script.setAttribute("async", "");
|
|
||||||
script.innerHTML = this.preventInfiniteLoop(value);
|
|
||||||
|
|
||||||
this.Iframe?.contentWindow?.document.body.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
surroundTryCatch(value: string) {
|
|
||||||
return tryCatch.replace("[replace]", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
code editor
|
code editor
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-horiz">
|
<div class="flex-horiz">
|
||||||
<code-editor></code-editor>
|
<code-editor style="min-width: 50%; max-width: 50%;"></code-editor>
|
||||||
<output-frame></output-frame>
|
<output-frame></output-frame>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-shrink section bottom">methods: rect, box, center, width, height</div>
|
<div class="flex-shrink section bottom">methods: rect, box, center, width, height</div>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
html, body, body > * {
|
html, body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -22,6 +22,7 @@ html, body, body > * {
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
flex-basis: 1px;
|
flex-basis: 1px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex-horiz .flex-shrink, .flex-vert .flex-shrink {
|
.flex-horiz .flex-shrink, .flex-vert .flex-shrink {
|
||||||
@@ -34,6 +35,15 @@ html, body, body > * {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-reset {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;
|
font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;
|
||||||
@@ -13,7 +13,4 @@ window.customElements.define('notification-bubbles', NotificationBubbles);
|
|||||||
window.customElements.define('notification-bubble', NotificationBubble);
|
window.customElements.define('notification-bubble', NotificationBubble);
|
||||||
|
|
||||||
|
|
||||||
var appEle = document.createElement("div");
|
document.body.innerHTML += bootHtml;
|
||||||
appEle.innerHTML = bootHtml;
|
|
||||||
|
|
||||||
document.body.appendChild(appEle);
|
|
||||||
+28
-1
@@ -13,6 +13,7 @@ export class CodeEditor extends BaseElement {
|
|||||||
|
|
||||||
this.initWorkers();
|
this.initWorkers();
|
||||||
|
|
||||||
|
|
||||||
var editor = monaco.editor.create(this, {
|
var editor = monaco.editor.create(this, {
|
||||||
value: this.input,
|
value: this.input,
|
||||||
language: 'javascript',
|
language: 'javascript',
|
||||||
@@ -20,9 +21,35 @@ export class CodeEditor extends BaseElement {
|
|||||||
contextmenu: false,
|
contextmenu: false,
|
||||||
minimap: {
|
minimap: {
|
||||||
enabled: false
|
enabled: false
|
||||||
}
|
},
|
||||||
|
autoIndent: "full"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
monaco.languages.registerCompletionItemProvider("javascript", {
|
||||||
|
triggerCharacters: ["."],
|
||||||
|
provideCompletionItems: (model, position, context, token) => (
|
||||||
|
{
|
||||||
|
suggestions: [
|
||||||
|
{
|
||||||
|
label: 'for',
|
||||||
|
kind: monaco.languages.CompletionItemKind.Function,
|
||||||
|
insertText: 'for (let i = 0; i < array.length; i++) {\n\n}',
|
||||||
|
range: <any>null,
|
||||||
|
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'forr',
|
||||||
|
kind: monaco.languages.CompletionItemKind.Function,
|
||||||
|
insertText: 'for (var i = array.length - 1; i >= 0; i--) {\n\n}',
|
||||||
|
range: <any>null,
|
||||||
|
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
editor.onDidChangeModelContent((e) => {
|
editor.onDidChangeModelContent((e) => {
|
||||||
this.input = editor.getValue();
|
this.input = editor.getValue();
|
||||||
this.outputFrame.setScript(this.input);
|
this.outputFrame.setScript(this.input);
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
var myDiv = document.createElement("div");
|
||||||
|
myDiv.innerText = "hello moto";
|
||||||
|
|
||||||
|
document.body.appendChild(myDiv);
|
||||||
|
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
while (i < 10) {
|
||||||
|
console.log("hello " + i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = { hello: true, moto: "enabled" };
|
||||||
|
|
||||||
|
console.log(obj);
|
||||||
+6
@@ -3,6 +3,7 @@ notification-bubble {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
color: black;
|
color: black;
|
||||||
background-color: #a0ffa7;
|
background-color: #a0ffa7;
|
||||||
|
border: 1px solid #8ddf92;
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
box-shadow: 1px 1px 1px 1px rgba(0,0,0,0.19);
|
box-shadow: 1px 1px 1px 1px rgba(0,0,0,0.19);
|
||||||
@@ -11,22 +12,27 @@ notification-bubble {
|
|||||||
|
|
||||||
notification-bubble.log {
|
notification-bubble.log {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
border-color: #dfdfdf;
|
||||||
}
|
}
|
||||||
|
|
||||||
notification-bubble.info {
|
notification-bubble.info {
|
||||||
background-color: #e7e7b3;
|
background-color: #e7e7b3;
|
||||||
|
border-color: #d4d4a9;
|
||||||
}
|
}
|
||||||
|
|
||||||
notification-bubble.warn {
|
notification-bubble.warn {
|
||||||
background-color: #fff9a0;
|
background-color: #fff9a0;
|
||||||
|
border-color: #e6e094;
|
||||||
}
|
}
|
||||||
|
|
||||||
notification-bubble.error {
|
notification-bubble.error {
|
||||||
background-color: #ffa0a0;
|
background-color: #ffa0a0;
|
||||||
|
border-color: #df8e8e;
|
||||||
}
|
}
|
||||||
|
|
||||||
notification-bubble.syntax-error {
|
notification-bubble.syntax-error {
|
||||||
background-color: #ff6262;
|
background-color: #ff6262;
|
||||||
|
background-color: #d15353;
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { messageListener } from "../../../shared/message-listener";
|
||||||
|
import { BaseElement } from "../_base";
|
||||||
|
import { NotificationBubble } from "./notification-bubble";
|
||||||
|
import './notification-bubbles.less';
|
||||||
|
|
||||||
|
export class NotificationBubbles extends BaseElement {
|
||||||
|
add(text: string, type: 'log' | 'info' | 'warn' | 'error' | 'syntax-error' | 'script' | 'time' | 'response') {
|
||||||
|
|
||||||
|
if (text && type) {
|
||||||
|
var bubble = <NotificationBubble>document.createElement("notification-bubble");
|
||||||
|
bubble.innerText = text;
|
||||||
|
bubble.classList.add(type);
|
||||||
|
this.appendChild(bubble);
|
||||||
|
|
||||||
|
if (this.children.length > 50) {
|
||||||
|
this.removeChild(this.children[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
onInit(): void {
|
||||||
|
messageListener((type, value) => {
|
||||||
|
if (type != 'script' && type != 'response')
|
||||||
|
this.add(value, type);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { BaseElement } from "../_base";
|
||||||
|
import './output-frame.less';
|
||||||
|
import { NotificationBubbles } from "../notification-bubbles/notification-bubbles";
|
||||||
|
import { GetOutputFrameUrl } from "../../../shared/url-helpers";
|
||||||
|
import { GetNotificationBubbles } from "../../../shared/getdom";
|
||||||
|
import { postMessage } from "../../../shared/post-message";
|
||||||
|
|
||||||
|
export class OutputFrame extends BaseElement {
|
||||||
|
public Iframe: HTMLIFrameElement | null = null;
|
||||||
|
public CurrentIframeScriptRemoveResponseListener: Function | null = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
onInit(): void {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
onUpdate(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(resetNotificationBubbles: boolean = true) {
|
||||||
|
if (this.CurrentIframeScriptRemoveResponseListener != null) {
|
||||||
|
this.CurrentIframeScriptRemoveResponseListener();
|
||||||
|
this.CurrentIframeScriptRemoveResponseListener = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.Iframe && this.hasChild(this.Iframe)) {
|
||||||
|
this.removeChild(this.Iframe);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Iframe = document.createElement("iframe");
|
||||||
|
this.Iframe.setAttribute("sandbox", "allow-pointer-lock allow-same-origin allow-scripts");
|
||||||
|
this.Iframe.src = GetOutputFrameUrl();
|
||||||
|
this.appendChild(this.Iframe);
|
||||||
|
|
||||||
|
if (resetNotificationBubbles) {
|
||||||
|
var bubbles = GetNotificationBubbles();
|
||||||
|
if (bubbles && bubbles.reset) {
|
||||||
|
bubbles.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setError() {
|
||||||
|
this.reset();
|
||||||
|
if (this.Iframe) {
|
||||||
|
this.Iframe.src = GetOutputFrameUrl() + "execution-time-error.html";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
preventInfiniteLoop(value: string) {
|
||||||
|
return value.replace("while (true)", "while (false)");
|
||||||
|
}
|
||||||
|
|
||||||
|
setScript(value: string) {
|
||||||
|
this.reset();
|
||||||
|
this.onIframeLoaded(() => {
|
||||||
|
this.CurrentIframeScriptRemoveResponseListener = postMessage(this.Iframe?.contentWindow, "script", value, (executeTimeInMs, exceedTimeInMs) => {
|
||||||
|
if (executeTimeInMs === -1) {
|
||||||
|
this.setError();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var bubbles = GetNotificationBubbles();
|
||||||
|
bubbles.add("code executed in: " + executeTimeInMs + "ms", "info");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onIframeLoaded(fn: Function) {
|
||||||
|
if (this.Iframe) {
|
||||||
|
this.Iframe.onload = () => {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.waitFor(this.Iframe, () => {
|
||||||
|
this.onIframeLoaded(fn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 166 KiB |
@@ -0,0 +1,11 @@
|
|||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import './app.less';
|
||||||
|
import bootHtml from './app.html';
|
||||||
|
import { watchConsole } from './injects/watch-console';
|
||||||
|
import { setOnErrorListener } from './injects/on-error';
|
||||||
|
import { createScript } from '../shared/create-script';
|
||||||
|
import { messageListener } from '../shared/message-listener';
|
||||||
|
import { postMessage, postResponseMessage } from '../shared/post-message';
|
||||||
|
|
||||||
|
|
||||||
|
document.body.innerHTML += bootHtml;
|
||||||
|
watchConsole((type, value) => {
|
||||||
|
postMessage(parent, type, value);
|
||||||
|
});
|
||||||
|
messageListener((type, value, id) => {
|
||||||
|
if (type == "script") {
|
||||||
|
createScript(value);
|
||||||
|
postResponseMessage(parent, id, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setOnErrorListener((type, value) => {
|
||||||
|
postMessage(parent, type, value);
|
||||||
|
});
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { NotificationBubbles } from "../../codeeditor-app/elements/notification-bubbles/notification-bubbles";
|
||||||
|
|
||||||
|
export function setOnErrorListener(fn: (type: 'syntax-error', value: any) => void) {
|
||||||
|
window.onerror = function (error) {
|
||||||
|
fn('syntax-error', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { NotificationBubbles } from "../../codeeditor-app/elements/notification-bubbles/notification-bubbles";
|
||||||
|
|
||||||
|
export function tryCatch(fn: Function) {
|
||||||
|
try {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
var bubbles = <NotificationBubbles>parent.document.body.getElementsByTagName("notification-bubbles")[0];
|
||||||
|
//@ts-ignore
|
||||||
|
bubbles.add(err, 'syntax-error');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { NotificationBubbles } from "../../codeeditor-app/elements/notification-bubbles/notification-bubbles";
|
||||||
|
|
||||||
|
export function watchConsole(fn: (type: 'log' | 'info' | 'warn' | 'error', value: any) => void) {
|
||||||
|
// define a new console
|
||||||
|
var console: any = (function (oldCons) {
|
||||||
|
return {
|
||||||
|
log: function (text: any) {
|
||||||
|
oldCons.log(text);
|
||||||
|
fn('log', text);
|
||||||
|
},
|
||||||
|
info: function (text: any) {
|
||||||
|
oldCons.info(text);
|
||||||
|
fn('info', text);
|
||||||
|
},
|
||||||
|
warn: function (text: any) {
|
||||||
|
oldCons.warn(text);
|
||||||
|
fn('warn', text);
|
||||||
|
},
|
||||||
|
error: function (text: any) {
|
||||||
|
oldCons.error(text);
|
||||||
|
fn('error', text);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}(window.console));
|
||||||
|
|
||||||
|
//Then redefine the old console
|
||||||
|
window.console = console;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" id="master-viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
|
<title>output error</title>
|
||||||
|
<base href="/" />
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 22px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 0.6em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="center">
|
||||||
|
took too long to run?<br />
|
||||||
|
<small>why you infinite loopin?</small>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" id="master-viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
|
<title>output</title>
|
||||||
|
<base href="/" />
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript" src="/output.frame.bundle.js?v=1"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,22 @@
|
|||||||
|
const WebpackDevServer = require("webpack-dev-server");
|
||||||
|
const webpack = require("webpack");
|
||||||
|
|
||||||
|
const codeeditorConfig = require("./webpack.dev.js");
|
||||||
|
const outputframeConfig = require("./webpack.dev-outputframe.js");
|
||||||
|
|
||||||
|
const codeeditorCompiler = webpack(codeeditorConfig);
|
||||||
|
const outputframeCompiler = webpack(outputframeConfig);
|
||||||
|
|
||||||
|
|
||||||
|
const server1 = new WebpackDevServer(codeeditorCompiler, {
|
||||||
|
hot: true,
|
||||||
|
historyApiFallback: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const server2 = new WebpackDevServer(outputframeCompiler, {
|
||||||
|
hot: true,
|
||||||
|
historyApiFallback: true
|
||||||
|
})
|
||||||
|
|
||||||
|
server1.listen(8020, "localhost", function() { console.log("server 1 rdy"); })
|
||||||
|
server2.listen(8021, "localhost", function() { console.log("server 2 rdy"); })
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export function createScript(value: string) {
|
||||||
|
var script: HTMLScriptElement = document.createElement("script");
|
||||||
|
script.setAttribute("async", "");
|
||||||
|
script.innerHTML = value;
|
||||||
|
|
||||||
|
document.body.appendChild(script);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { NotificationBubbles } from "../codeeditor-app/elements/notification-bubbles/notification-bubbles";
|
||||||
|
import { OutputFrame } from "../codeeditor-app/elements/output-frame/output-frame";
|
||||||
|
|
||||||
|
export function GetNotificationBubbles(): NotificationBubbles {
|
||||||
|
return <NotificationBubbles>document.getElementsByTagName("notification-bubbles")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GetOutputFrame(): OutputFrame {
|
||||||
|
return <OutputFrame>document.getElementsByTagName("output-frame")[0];
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
export function messageListener(fn: (type: 'script' | 'log' | 'info' | 'warn' | 'error' | 'syntax-error' | 'time' | 'response', value: string, id: number) => void): Function {
|
||||||
|
|
||||||
|
var evt = function(e: any) {
|
||||||
|
if (!e.data || e.data === '' || e.data.type === 'webpackOk') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn(e.data.type, e.data.value, e.data.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('message', evt);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('message', evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { messageListener } from "./message-listener";
|
||||||
|
|
||||||
|
export function postMessage(window: Window | null | undefined, type: string, value: any, onResponse?: (executeTimeInMs: number, exceedTimeInMs: number) => void): Function {
|
||||||
|
var postId = +new Date();
|
||||||
|
var responseTimeout = 5000;
|
||||||
|
var execResponse = true;
|
||||||
|
|
||||||
|
if (window && type && value) {
|
||||||
|
if (onResponse) {
|
||||||
|
var timeoutHandle: number | null = null;
|
||||||
|
|
||||||
|
var remListener = messageListener((type, value, id) => {
|
||||||
|
if (type == "response" && id == postId) {
|
||||||
|
if (timeoutHandle != null)
|
||||||
|
clearTimeout(timeoutHandle);
|
||||||
|
|
||||||
|
remListener();
|
||||||
|
if (execResponse)
|
||||||
|
onResponse(+new Date() - id, responseTimeout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
timeoutHandle = setTimeout(() => {
|
||||||
|
remListener();
|
||||||
|
if (timeoutHandle != null) {
|
||||||
|
clearTimeout(timeoutHandle);
|
||||||
|
if (execResponse)
|
||||||
|
onResponse(-1, responseTimeout);
|
||||||
|
}
|
||||||
|
}, responseTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.postMessage({ type: type, value: (typeof value === 'string' || value instanceof String) ? value : JSON.stringify(value), id: postId }, "*");
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (onResponse) {
|
||||||
|
execResponse = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export function postResponseMessage(window: Window | null | undefined, id: number, value: any) {
|
||||||
|
if (window && value) {
|
||||||
|
window.postMessage({ type: "response", value: JSON.stringify(value), id: id }, "*");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
export function GetUrl(): string {
|
||||||
|
return location.protocol + "//" + location.host + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IsLocalhost(): boolean {
|
||||||
|
return location.href.indexOf("://localhost") != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GetOutputFrameUrl(): string {
|
||||||
|
if (IsLocalhost()) {
|
||||||
|
return "http://127.0.0.1:8021/";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "https://outputframe.davidmeincke.dk/";
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-2
@@ -1,12 +1,13 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: {
|
entry: {
|
||||||
'main': path.resolve(__dirname, 'App', 'boot.ts'),
|
'main': path.resolve(__dirname, 'codeeditor-app', 'boot.ts'),
|
||||||
'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
|
'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
|
||||||
'json.worker': 'monaco-editor/esm/vs/language/json/json.worker',
|
'json.worker': 'monaco-editor/esm/vs/language/json/json.worker',
|
||||||
'css.worker': 'monaco-editor/esm/vs/language/css/css.worker',
|
'css.worker': 'monaco-editor/esm/vs/language/css/css.worker',
|
||||||
'html.worker': 'monaco-editor/esm/vs/language/html/html.worker',
|
'html.worker': 'monaco-editor/esm/vs/language/html/html.worker',
|
||||||
'ts.worker': 'monaco-editor/esm/vs/language/typescript/ts.worker'
|
'ts.worker': 'monaco-editor/esm/vs/language/typescript/ts.worker',
|
||||||
|
'../outputframe/output.frame': path.resolve(__dirname, 'outputframe-app', 'boot.ts')
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: [".ts", ".js", ".json"]
|
extensions: [".ts", ".js", ".json"]
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const { merge } = require('webpack-merge');
|
||||||
|
const copyPlugin = require('copy-webpack-plugin');
|
||||||
|
const common = require('./webpack.common.js');
|
||||||
|
|
||||||
|
const devFolderName = "dev-dist";
|
||||||
|
|
||||||
|
module.exports = merge(common, {
|
||||||
|
mode: 'development',
|
||||||
|
output: {
|
||||||
|
globalObject: 'self',
|
||||||
|
filename: '[name].bundle.js',
|
||||||
|
path: path.resolve(__dirname, devFolderName, 'outputframe'),
|
||||||
|
publicPath: "/"
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
historyApiFallback: true
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new copyPlugin(
|
||||||
|
{
|
||||||
|
patterns: [
|
||||||
|
{
|
||||||
|
from: path.resolve(__dirname, 'codeeditor-app/static'),
|
||||||
|
to: path.resolve(__dirname, devFolderName, 'codeeditor', '[name][ext]')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: path.resolve(__dirname, 'outputframe-app/static'),
|
||||||
|
to: path.resolve(__dirname, devFolderName, 'outputframe', '[name][ext]')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
]
|
||||||
|
});
|
||||||
+7
-7
@@ -2,7 +2,6 @@ const path = require('path');
|
|||||||
const { merge } = require('webpack-merge');
|
const { merge } = require('webpack-merge');
|
||||||
const copyPlugin = require('copy-webpack-plugin');
|
const copyPlugin = require('copy-webpack-plugin');
|
||||||
const common = require('./webpack.common.js');
|
const common = require('./webpack.common.js');
|
||||||
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
|
|
||||||
|
|
||||||
const devFolderName = "dev-dist";
|
const devFolderName = "dev-dist";
|
||||||
|
|
||||||
@@ -11,13 +10,10 @@ module.exports = merge(common, {
|
|||||||
output: {
|
output: {
|
||||||
globalObject: 'self',
|
globalObject: 'self',
|
||||||
filename: '[name].bundle.js',
|
filename: '[name].bundle.js',
|
||||||
path: path.resolve(__dirname, devFolderName),
|
path: path.resolve(__dirname, devFolderName, 'codeeditor'),
|
||||||
publicPath: "/"
|
publicPath: "/"
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
static: {
|
|
||||||
directory: path.join(__dirname, devFolderName),
|
|
||||||
},
|
|
||||||
historyApiFallback: true
|
historyApiFallback: true
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
@@ -25,8 +21,12 @@ module.exports = merge(common, {
|
|||||||
{
|
{
|
||||||
patterns: [
|
patterns: [
|
||||||
{
|
{
|
||||||
from: path.resolve(__dirname, 'static'),
|
from: path.resolve(__dirname, 'codeeditor-app/static'),
|
||||||
to: path.resolve(__dirname, devFolderName, '[name][ext]')
|
to: path.resolve(__dirname, devFolderName, 'codeeditor', '[name][ext]')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: path.resolve(__dirname, 'outputframe-app/static'),
|
||||||
|
to: path.resolve(__dirname, devFolderName, 'outputframe', '[name][ext]')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -3,7 +3,6 @@ const common = require('./webpack.common.js');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const ReplaceInFileWebpackPlugin = require('replace-in-file-webpack-plugin');
|
const ReplaceInFileWebpackPlugin = require('replace-in-file-webpack-plugin');
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
|
|
||||||
|
|
||||||
const prodFolderName = "prod-dist";
|
const prodFolderName = "prod-dist";
|
||||||
|
|
||||||
@@ -18,28 +17,29 @@ const replaceVersionInHtmlOption = {
|
|||||||
return match.toString().substr(0, 3) +
|
return match.toString().substr(0, 3) +
|
||||||
+new Date();
|
+new Date();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = merge(common, {
|
module.exports = merge(common, {
|
||||||
mode: "production",
|
mode: "production",
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, prodFolderName),
|
globalObject: 'self',
|
||||||
publicPath: "/",
|
filename: '[name].bundle.js',
|
||||||
filename: 'main.js'
|
path: path.resolve(__dirname, prodFolderName, "codeeditor"),
|
||||||
|
publicPath: "/"
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new CopyWebpackPlugin(
|
new CopyWebpackPlugin(
|
||||||
{
|
{
|
||||||
patterns: [
|
patterns: [
|
||||||
{
|
{
|
||||||
from: path.resolve(__dirname, 'index.html'),
|
from: path.resolve(__dirname, 'codeeditor-app/static'),
|
||||||
to: path.resolve(__dirname, prodFolderName, '[name][ext]')
|
to: path.resolve(__dirname, prodFolderName, 'codeeditor', '[name][ext]')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: path.resolve(__dirname, 'manifest.json'),
|
from: path.resolve(__dirname, 'outputframe-app/static'),
|
||||||
to: path.resolve(__dirname, devFolderName, '[name][ext]')
|
to: path.resolve(__dirname, prodFolderName, 'outputframe', '[name][ext]')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user