diff --git a/mkdocs/docs/playground/backend.json b/mkdocs/docs/playground/backend.json
index 55afaacea..76e0a669c 100644
--- a/mkdocs/docs/playground/backend.json
+++ b/mkdocs/docs/playground/backend.json
@@ -3,6 +3,8 @@
{"name": "RunEpsilonFunction", "url": "https://uk-ac-york-cs-epsilon-playground.h5rwqzvxy5sr4.eu-west-1.cs.amazonlightsail.com/epsilon"},
{"name": "FlexmiToPlantUMLFunction", "url": "https://uk-ac-york-cs-epsilon-playground.h5rwqzvxy5sr4.eu-west-1.cs.amazonlightsail.com/flexmi2plantuml"},
{"name": "EmfaticToPlantUMLFunction", "url": "https://uk-ac-york-cs-epsilon-playground.h5rwqzvxy5sr4.eu-west-1.cs.amazonlightsail.com/emfatic2plantuml"},
- {"name": "ShortURLFunction", "url": "https://l4p4ni4wo4lqtxk4qfedsapbtm0olxqn.lambda-url.eu-west-1.on.aws/"}
+ {"name": "ShortURLFunction", "url": "https://l4p4ni4wo4lqtxk4qfedsapbtm0olxqn.lambda-url.eu-west-1.on.aws/"},
+ {"name": "Yjs", "url":"wss://uk-ac-york-cs-epsilon-yjs.h5rwqzvxy5sr4.eu-west-1.cs.amazonlightsail.com/ws/", "public": "wss://demos.yjs.dev/ws"},
+ {"name": "Kroki", "url": "https://uk-ac-york-cs-epsilon-kroki.h5rwqzvxy5sr4.eu-west-1.cs.amazonlightsail.com"}
]
}
\ No newline at end of file
diff --git a/mkdocs/docs/playground/backend.local.json b/mkdocs/docs/playground/backend.local.json
index afe0556d5..7b5de6776 100644
--- a/mkdocs/docs/playground/backend.local.json
+++ b/mkdocs/docs/playground/backend.local.json
@@ -3,6 +3,8 @@
{"name": "RunEpsilonFunction", "url": "http://localhost:8080/epsilon"},
{"name": "FlexmiToPlantUMLFunction", "url": "http://localhost:8080/flexmi2plantuml"},
{"name": "EmfaticToPlantUMLFunction", "url": "http://localhost:8080/emfatic2plantuml"},
- {"name": "ShortURLFunction", "url": "http://localhost:8080/shorturl"}
+ {"name": "ShortURLFunction", "url": "http://localhost:8080/shorturl"},
+ {"name": "Yjs", "url": "ws://localhost:1234", "alternative": "wss://demos.yjs.dev/ws"},
+ {"name": "Kroki", "url": "https://uk-ac-york-cs-epsilon-kroki.h5rwqzvxy5sr4.eu-west-1.cs.amazonlightsail.com"}
]
}
diff --git a/mkdocs/docs/playground/css/custom.css b/mkdocs/docs/playground/css/custom.css
index 3b0995aa5..b5aa36762 100644
--- a/mkdocs/docs/playground/css/custom.css
+++ b/mkdocs/docs/playground/css/custom.css
@@ -180,6 +180,10 @@
content: url("../images/maximise.png");
}
+.mif-liveshare::before {
+ content: url("../images/liveshare.png");
+}
+
.active-toggle .icon .mif-folder::before {
content: url("../images/open-folder.png");
}
@@ -226,16 +230,6 @@ body {
display:none;
}
-.ace_gutter {
- background-color: white !important;
- border-right: 1px solid rgb(215,215,215) !important;
- z-index: 0;
-}
-
-.ace_gutter-active-line {
- background-color: white !important;
-}
-
#preloader {
position: fixed;
height: 100%;
@@ -308,3 +302,14 @@ body {
text-align:center;
color: rgb(205, 53, 44);
}
+
+#liveShareStatus {
+ background-color1: #63BCE9;
+ background-color: #62A92F;
+ color: white;
+ display: none;
+}
+
+#preloader-message {
+ padding: 10px;
+}
\ No newline at end of file
diff --git a/mkdocs/docs/playground/images/liveshare.png b/mkdocs/docs/playground/images/liveshare.png
new file mode 100644
index 000000000..ab70bff5f
Binary files /dev/null and b/mkdocs/docs/playground/images/liveshare.png differ
diff --git a/mkdocs/docs/playground/index.html b/mkdocs/docs/playground/index.html
index 2ae95df86..9a570fce4 100644
--- a/mkdocs/docs/playground/index.html
+++ b/mkdocs/docs/playground/index.html
@@ -12,20 +12,31 @@
- 
+ 
diff --git a/mkdocs/docs/playground/js/Backend.js b/mkdocs/docs/playground/js/Backend.js
index ebc31ad55..a4fa9eb21 100644
--- a/mkdocs/docs/playground/js/Backend.js
+++ b/mkdocs/docs/playground/js/Backend.js
@@ -35,6 +35,14 @@ class Backend {
getShortURLService() {
return this.services["ShortURLFunction"];
}
+
+ getYjsService() {
+ return this.services["Yjs"];
+ }
+
+ getKrokiService() {
+ return this.services["Kroki"];
+ }
}
export { Backend };
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/ConsolePanel.js b/mkdocs/docs/playground/js/ConsolePanel.js
index 2b285bbe5..823b2cf66 100644
--- a/mkdocs/docs/playground/js/ConsolePanel.js
+++ b/mkdocs/docs/playground/js/ConsolePanel.js
@@ -1,19 +1,13 @@
-import { define } from "ace-builds";
import { Panel } from "./Panel.js";
-import { language, programPanel, secondProgramPanel } from "./Playground.js";
class ConsolePanel extends Panel {
constructor() {
super("console");
- this.editor.setReadOnly(true);
+ this.editor.updateOptions({ readOnly: true });
this.setValue("");
this.createButtons();
-
- this.defineHoverlink();
- this.detectSemanticErrorLinks(this.editor);
- this.detectSyntacticErrorLinks(this.editor);
- this.setTitleAndIcon("Console", "console");
+ this.setTitleAndIcon("Console", "console");
}
getButtons() {
@@ -25,15 +19,14 @@ class ConsolePanel extends Panel {
}
setOutput(str) {
- document.getElementById("consoleEditor").style.color = "black";
- this.editor.getSession().setUseWrapMode(false);
+ this.setLanguage("out");
+ this.editor.updateOptions({wordWrap: "off"});
this.setValue(str);
-
}
setError(str) {
- document.getElementById("consoleEditor").style.color = "#CD352C";
- this.editor.getSession().setUseWrapMode(true);
+ this.setLanguage("err");
+ this.editor.updateOptions({wordWrap: "on"});
this.setValue(str);
}
@@ -42,7 +35,6 @@ class ConsolePanel extends Panel {
if (editorElement != null) {
editorElement.parentNode.style = "flex-basis: calc(100% - 4px);";
}
- this.editor.resize();
}
createElement() {
@@ -58,231 +50,6 @@ class ConsolePanel extends Panel {
return root;
}
-
- defineHoverlink() {
- define("hoverlink", [], function (require, exports, module) {
- "use strict";
-
- var oop = require("ace/lib/oop");
- var event = require("ace/lib/event");
- var Range = require("ace/range").Range;
- var EventEmitter = require("ace/lib/event_emitter").EventEmitter;
-
- var HoverLink = function (editor, regex, fieldName, disableOn) {
- this.fieldName = fieldName;
- if (editor[this.fieldName])
- return;
-
- editor[this.fieldName] = this;
- this.editor = editor;
- this.regex = regex;
-
- this.update = this.update.bind(this);
- this.onMouseMove = this.onMouseMove.bind(this);
- this.onMouseOut = this.onMouseOut.bind(this);
- this.onClick = this.onClick.bind(this);
- this.disableOn = disableOn;
-
- event.addListener(editor.renderer.scroller, "mousemove", this.onMouseMove);
- event.addListener(editor.renderer.content, "mouseout", this.onMouseOut);
- event.addListener(editor.renderer.content, "click", this.onClick);
- };
-
- (function () {
- oop.implement(this, EventEmitter);
-
- this.token = {};
- this.range = new Range();
-
- this.update = function () {
- if (this.disableOn()) {
- return;
- }
-
- this.$timer = null;
- var editor = this.editor;
- var renderer = editor.renderer;
-
- var canvasPos = renderer.scroller.getBoundingClientRect();
- var offset = (this.x + renderer.scrollLeft - canvasPos.left - renderer.$padding) / renderer.characterWidth;
- var row = Math.floor((this.y + renderer.scrollTop - canvasPos.top) / renderer.lineHeight);
- var col = Math.round(offset);
-
- var screenPos = { row: row, column: col, side: offset - col > 0 ? 1 : -1 };
- var session = editor.session;
- var docPos = session.screenToDocumentPosition(screenPos.row, screenPos.column);
-
- var selectionRange = editor.selection.getRange();
- if (!selectionRange.isEmpty()) {
- if (selectionRange.start.row <= row && selectionRange.end.row >= row)
- return this.clear();
- }
-
- var line = editor.session.getLine(docPos.row);
- if (docPos.column === line.length) {
- var clippedPos = editor.session.documentToScreenPosition(docPos.row, docPos.column);
- if (clippedPos.column != screenPos.column) {
- return this.clear();
- }
- }
-
- var token = this.findLink(docPos.row, docPos.column);
- this.link = token;
- if (!token) {
- return this.clear();
- }
- this.isOpen = true;
- editor.renderer.setCursorStyle("pointer");
-
- session.removeMarker(this.marker);
-
- this.range = new Range(token.row, token.start, token.row, token.start + token.value.length);
- this.marker = session.addMarker(this.range, "ace_link_marker", "text", true);
- };
-
- this.clear = function () {
- if (this.isOpen) {
- this.editor.session.removeMarker(this.marker);
- this.editor.renderer.setCursorStyle("");
- this.isOpen = false;
- }
- };
-
- this.getMatchAround = function (regExp, string, col) {
- var match;
- regExp.lastIndex = 0;
- string.replace(regExp, function (str) {
- var offset = arguments[arguments.length - 2];
- var length = str.length;
- if (offset <= col && offset + length >= col)
- match = {
- start: offset,
- value: str
- };
- });
-
- return match;
- };
-
- this.onClick = function () {
- if (this.link) {
- this.link.editor = this.editor;
- this._signal("open", this.link);
- this.clear();
- }
- };
-
- this.findLink = function (row, column) {
- var editor = this.editor;
- var session = editor.session;
- var line = session.getLine(row);
-
- var match = this.getMatchAround(this.regex, line, column);
- if (!match)
- return;
-
- match.row = row;
- return match;
- };
-
- this.onMouseMove = function (e) {
- if (this.editor.$mouseHandler.isMousePressed) {
- if (!this.editor.selection.isEmpty())
- this.clear();
- return;
- }
- this.x = e.clientX;
- this.y = e.clientY;
- this.update();
- };
-
- this.onMouseOut = function (e) {
- this.clear();
- };
-
- this.destroy = function () {
- this.onMouseOut();
- event.removeListener(this.editor.renderer.scroller, "mousemove", this.onMouseMove);
- event.removeListener(this.editor.renderer.content, "mouseout", this.onMouseOut);
- delete this.editor[this.fieldName];
- };
-
- }).call(HoverLink.prototype);
-
- exports.HoverLink = HoverLink;
-
- });
- }
-
- selectRange(editor, e, getSelectionOptions) {
- var location = e.value;
- if (editor.getValue().indexOf(location) > -1) {
- var Range = ace.require("ace/range").Range;
- var selectionOptions = getSelectionOptions(location);
-
- selectionOptions.panel.getEditor().selection.setRange(new Range(
- selectionOptions.startLine,
- selectionOptions.startColumn,
- selectionOptions.endLine,
- selectionOptions.endColumn
- ));
- }
- }
-
- detectSemanticErrorLinks(editor) {
- var that = this;
- var semErrorRegex = /\(((.+?)@(\d+):(\d+)-(\d+):(\d+))\)/i;
- var HoverLink = ace.require("hoverlink").HoverLink;
- editor.semanticErrorLinks = new HoverLink(
- editor,
- semErrorRegex,
- "semanticErrorLinks",
- () => false
- );
- editor.semanticErrorLinks.on("open", function (e) {
- var getSelectionOptions = function (val) {
- var matches = val.match(semErrorRegex);
- var programExtension = matches[2].split(".").pop();
- return {
- panel: language === "egx" && programExtension === "egl"
- || language === "eml" && programExtension === "ecl"
- ? secondProgramPanel
- : programPanel,
- startLine: parseInt(matches[3]) - 1,
- startColumn: parseInt(matches[4]),
- endLine: parseInt(matches[5]) - 1,
- endColumn: parseInt(matches[6]),
- };
- }
- that.selectRange(editor, e, getSelectionOptions);
- });
- }
-
- detectSyntacticErrorLinks(editor) {
- var that = this;
- var synErrorRegex = /^Line: (\d+),( Column: \d+,)?/i;
- var HoverLink = ace.require("hoverlink").HoverLink;
- editor.syntacticErrorLinks = new HoverLink(
- editor,
- synErrorRegex,
- "syntacticErrorLinks",
- () => language === "egx" || language === "eml"
- );
- editor.syntacticErrorLinks.on("open", function (e) {
- var getSelectionOptions = function (val) {
- var matches = val.match(synErrorRegex);
- var lineNumber = parseInt(matches[1]) - 1;
- return {
- panel: programPanel,
- startLine: lineNumber,
- startColumn: 0,
- endLine: lineNumber + 1,
- endColumn: 0,
- };
- }
- that.selectRange(editor, e, getSelectionOptions);
- });
- }
}
export { ConsolePanel };
diff --git a/mkdocs/docs/playground/js/DownloadDialog.js b/mkdocs/docs/playground/js/DownloadDialog.js
index 5260d4f24..5ad3853af 100644
--- a/mkdocs/docs/playground/js/DownloadDialog.js
+++ b/mkdocs/docs/playground/js/DownloadDialog.js
@@ -111,7 +111,8 @@ class DownloadDialog {
caption: "Cancel",
cls: "js-dialog-close"
}
- ]
+ ],
+ closeButton: true
});
}
diff --git a/mkdocs/docs/playground/js/LiveShareDialog.js b/mkdocs/docs/playground/js/LiveShareDialog.js
new file mode 100644
index 000000000..fc253dc68
--- /dev/null
+++ b/mkdocs/docs/playground/js/LiveShareDialog.js
@@ -0,0 +1,50 @@
+import {programPanel, consolePanel, firstModelPanel, firstMetamodelPanel, secondModelPanel, secondMetamodelPanel, secondProgramPanel, thirdModelPanel, thirdMetamodelPanel, outputPanel, liveShareManager} from './Playground.js'
+
+class LiveShareDialog {
+
+ showEditorLineNumbers = false;
+
+ //TODO: Show a message to inform the user that we are trying to connect to the live sharing server as this can take a while sometimes
+ show(event) {
+ event.preventDefault();
+
+ liveShareManager.attempt( function () {
+ if (!liveShareManager.inSession()) {
+ liveShareManager.startSession();
+ }
+
+ Metro.dialog.create({
+ title: "Live Sharing",
+ content: "You can invite others to join this session by sharing " +
+ //"",
+ "this link with them." ,
+
+ actions: [
+ {
+ caption: "Copy Link to Clipboard",
+ cls: "js-dialog-close success",
+ onclick: function(){
+ copyToClipboard(liveShareManager.getShareURL());
+ }
+ },
+ {
+ caption: "Stop Live Sharing",
+ cls: "js-dialog-close alert",
+ onclick: function () {
+ liveShareManager.leaveSession();
+ }
+ },
+ {
+ caption: "Close",
+ cls: "js-dialog-close"
+ }
+
+ ],
+ closeButton: true
+ });
+ });
+ }
+
+}
+
+export { LiveShareDialog };
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/LiveShareManager.js b/mkdocs/docs/playground/js/LiveShareManager.js
new file mode 100644
index 000000000..b510d25de
--- /dev/null
+++ b/mkdocs/docs/playground/js/LiveShareManager.js
@@ -0,0 +1,133 @@
+import * as Y from 'yjs'
+import { WebsocketProvider } from 'y-websocket'
+import { MonacoBinding } from 'y-monaco'
+import * as monaco from 'monaco-editor'
+import { backend, consolePanel, outputPanel, preloader } from './Playground';
+import 'metro4';
+
+// TODO: Join session via URL, disconnect, start new session -> the window url is different to the new share URL and this can cause confusion
+class LiveShareManager {
+
+ sessionId;
+ providers = [];
+
+ init() {
+ var parameters = new URLSearchParams(window.location.search);
+ this.sessionId = parameters.get("session");
+
+ if (this.willJoinSession()) {
+ var self = this;
+ // Try to join the session and if it fails, initialise
+ // panels from the fields of the example instead
+ preloader.progress("Joining live sharing session");
+ this.attempt(function () {
+ self.sessionId = self.getOrCreateSessionId();
+ self.joinSession(true);
+ preloader.hide();
+ }, function() {
+ initialisePanelValues()
+ preloader.hide();
+ });
+ }
+ else {
+ preloader.hide();
+ }
+ }
+
+ attempt(onServiceAvailable, onServiceUnavailable = () => {}, notify = true) {
+ const ws = new WebSocket(backend.getYjsService());
+ ws.onopen = () => {
+ onServiceAvailable();
+ ws.close();
+ };
+ ws.onerror = () => {
+ onServiceUnavailable();
+ if (notify) {
+ Metro.notify.create("Connection Error
Live sharing is not available at the moment.", null, {keepOpen: false, cls: "warning", width: 300});
+ ws.close();
+ }
+ };
+ }
+
+ showLiveShareStatus(status) {
+ var liveShareBadges = document.getElementById("liveShareBadges");
+ var liveShareTitleBadges = document.getElementById("liveShareTitleBadges");
+
+ if (status) {
+ liveShareBadges.style.display = "block";
+ liveShareTitleBadges.style.display = "inline";
+ }
+ else {
+ liveShareBadges.style.display = "none";
+ liveShareTitleBadges.style.display = "none";
+ }
+ }
+
+ startSession() {
+ this.joinSession(false);
+ }
+
+ leaveSession() {
+ this.providers.forEach(provider => provider.destroy());
+ this.providers = [];
+ this.sessionId = undefined;
+ this.showLiveShareStatus(false);
+ }
+
+ joinSession(existing) {
+
+ var self = this;
+ self.sessionId = self.getOrCreateSessionId();
+ self.showLiveShareStatus(true);
+
+ for (const panel of window.getActivePanels()) {
+ if (panel != consolePanel && panel != outputPanel) {
+ const ydoc = new Y.Doc();
+ const provider = new WebsocketProvider(backend.getYjsService(), 'epsilon-playground-' + self.sessionId + "-" + panel.getId(), ydoc);
+ self.providers.push(provider);
+ const ytext = ydoc.getText('monaco');
+ var editor = panel.getEditor();
+ var value = panel.getEditor().getValue();
+ const monacoBinding = new MonacoBinding(ytext, (editor.getModel()), new Set([editor]), provider.awareness);
+ if (!existing) panel.getEditor().setValue(value);
+ }
+ }
+
+ }
+
+ inSession() {
+ return this.sessionId != undefined;
+ }
+
+ getOrCreateSessionId() {
+ if (this.sessionId != undefined) return this.sessionId;
+ else return this.createSessionId();
+ }
+
+ willJoinSession() {
+ var parameters = new URLSearchParams(window.location.search);
+ return parameters.has("session");
+ }
+
+ getShareURL() {
+ const url = new URL(window.location.href);
+ url.searchParams.set("session", this.sessionId);
+ url.searchParams.delete("start");
+ return url.toString();
+ }
+
+ createSessionId() {
+ let result = '';
+ const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
+ const charactersLength = characters.length;
+ let counter = 0;
+ while (counter < 6) {
+ result += characters.charAt(Math.floor(Math.random() * charactersLength));
+ counter += 1;
+ }
+ return result;
+ }
+
+}
+
+export {LiveShareManager};
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/MetamodelPanel.js b/mkdocs/docs/playground/js/MetamodelPanel.js
index 0c46a973c..e9cef19a9 100644
--- a/mkdocs/docs/playground/js/MetamodelPanel.js
+++ b/mkdocs/docs/playground/js/MetamodelPanel.js
@@ -8,7 +8,7 @@ class MetamodelPanel extends ModelPanel {
}
setupSyntaxHighlighting() {
- this.editor.getSession().setMode("ace/mode/emfatic");
+ this.setLanguage("emf");
}
getButtons() {
diff --git a/mkdocs/docs/playground/js/ModelPanel.js b/mkdocs/docs/playground/js/ModelPanel.js
index 44989acd7..ba1149f71 100644
--- a/mkdocs/docs/playground/js/ModelPanel.js
+++ b/mkdocs/docs/playground/js/ModelPanel.js
@@ -13,7 +13,7 @@ class ModelPanel extends Panel {
super(id);
this.editable = editable;
this.metamodelPanel = metamodelPanel;
- this.setupSyntaxHighlighting();
+
this.createButtons();
this.setTitleAndIcon("Model", "flexmi");
}
@@ -22,6 +22,7 @@ class ModelPanel extends Panel {
super.init();
this.setDiagramRefreshButtonVisible(false);
this.setFitDiagramButtonVisible(!this.editable);
+ this.setupSyntaxHighlighting();
}
showDiagram() {
@@ -45,10 +46,9 @@ class ModelPanel extends Panel {
}
setupSyntaxHighlighting() {
- this.editor.getSession().setMode("ace/mode/xml");
this.updateSyntaxHighlighting();
var self = this;
- this.editor.getSession().on('change', function () {
+ this.editor.getModel().onDidChangeContent((event) => {
self.updateSyntaxHighlighting();
});
}
@@ -60,12 +60,12 @@ class ModelPanel extends Panel {
* flavour is assumed
*/
updateSyntaxHighlighting() {
- var val = this.editor.getSession().getValue();
+ var val = this.editor.getValue();
if ((val.trim() + "").startsWith("<")) {
- this.editor.getSession().setMode("ace/mode/xml");
+ this.setLanguage("xml");
}
else {
- this.editor.getSession().setMode("ace/mode/yaml");
+ this.setLanguage("yaml");
}
}
@@ -292,7 +292,7 @@ class ModelPanel extends Panel {
editorElement.style.height = parentElement.offsetHeight - 42 + "px";
}
- this.editor.resize();
+ // this.editor.resize();
// Fit the diagram
var diagramElement = document.getElementById(this.id + "Diagram");
diff --git a/mkdocs/docs/playground/js/MonacoSetup.js b/mkdocs/docs/playground/js/MonacoSetup.js
new file mode 100644
index 000000000..38dbec7fc
--- /dev/null
+++ b/mkdocs/docs/playground/js/MonacoSetup.js
@@ -0,0 +1,439 @@
+import * as monaco from 'monaco-editor'
+
+class MonacoSetup {
+
+ do() {
+ this.registerEmfatic();
+ this.registerEolBasedLanguage("eol");
+ this.registerEolBasedLanguage("evl", ['context', 'constraint', 'guard', 'pre', 'post', 'assumes', 'critique', 'message', 'title', 'do', 'check', 'fix', 'typeOf', 'kindOf', 'high', 'medium', 'low'], ['constraintTrace', 'extras']);
+
+ var etlKeywords = ['transform', 'auto', 'guard', 'pre', 'post', 'to', 'extends', 'rule', 'abstract'];
+ var etlConstants = ['transTrace'];
+ this.registerEolBasedLanguage("etl", etlKeywords, etlConstants);
+
+ this.registerEolBasedLanguage("egx", ['transform', 'rule', 'guard', 'pre', 'post', 'target', 'extends', 'parameters', 'template', 'overwrite', 'protectRegions', 'merge', 'append', 'patch'], ['generated']);
+ this.registerEolBasedLanguage("flock", ['delete', 'retype', 'to', 'migrate', 'when', 'ignoring', 'package', 'pre', 'post'], ['original', 'migrated']);
+ this.registerEolBasedLanguage("ecl", ['match', 'auto', 'do', 'compare', 'guard', 'pre', 'post', 'with', 'extends', 'rule', 'abstract'], ['matchTrace', 'autoCompare', 'matchInfo']);
+ this.registerEolBasedLanguage("eml", etlKeywords.concat(['merge', 'mid', 'with', 'into']), etlConstants.concat(['matchTrace', 'mergeTrace']));
+
+ ["epl", "emg"].forEach(l => { this.registerEolBasedLanguage(l, ['pre', 'post', 'pattern', 'match', 'guard', 'do', 'onmatch', 'nomatch', 'from', 'no', 'optional', 'active']); });
+
+ this.registerEolBasedLanguage("pinset", etlKeywords.concat(['pre', 'post', 'dataset', 'over', 'from', 'guard', 'properties', 'reference', 'column', 'grid', 'keys', 'header', 'body', 'as']));
+ this.registerEgl();
+ this.registerConsoleOutputLanguage();
+ this.registerConsoleErrorLanguage();
+ this.registerPlaygroundTheme();
+ }
+
+ registerPlaygroundTheme() {
+ monaco.editor.defineTheme('playground', {
+ base: 'vs',
+ inherit: true,
+ rules: [],
+ colors: { "editor.background": "#ffffff" }
+ });
+ }
+
+ registerConsoleOutputLanguage() {
+ monaco.languages.register({ id: 'out' });
+ monaco.languages.setMonarchTokensProvider('out', {
+ defaultToken: '',
+ tokenizer: {
+ root: []
+ }
+ });
+ }
+
+ registerConsoleErrorLanguage() {
+ monaco.languages.register({ id: 'err' });
+ monaco.languages.setMonarchTokensProvider('err', {
+ defaultToken: 'constant',
+ tokenizer: {
+ root: []
+ }
+ });
+ monaco.languages.registerLinkProvider({ language: 'err', exclusive: true }, {
+ provideLinks: function(model, token) {
+ const regex = /\b([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)@(\d+):(\d+)-(\d+):(\d+)\b/g;
+ const text = model.getValue();
+ let match;
+ let links = [];
+
+ while ((match = regex.exec(text)) !== null) {
+ const range = new monaco.Range(
+ model.getPositionAt(match.index).lineNumber,
+ model.getPositionAt(match.index).column,
+ model.getPositionAt(match.index + match[0].length).lineNumber,
+ model.getPositionAt(match.index + match[0].length).column
+ );
+
+ links.push({
+ range: range,
+ file: match[1],
+ extension: match[2],
+ startLine: parseInt(match[3], 10),
+ startColumn: parseInt(match[4], 10) + 1,
+ endLine: parseInt(match[5], 10),
+ endColumn: parseInt(match[6], 10) + 1,
+ tooltip: `Navigate to ${match[1]}.${match[2]} from ${match[3]}:${match[4]} to ${match[5]}:${match[6]}`
+ });
+ }
+
+ return { links: links };
+ },
+ resolveLink: function(link) {
+
+ var panel = language === "egx" && link.extension === "egl"
+ || language === "eml" && link.extension === "ecl"
+ ? secondProgramPanel
+ : programPanel;
+
+ const editor = panel.getEditor();
+
+ if (editor) {
+ const selectionRange = new monaco.Range(
+ link.startLine, link.startColumn,
+ link.endLine, link.endColumn
+ );
+
+ editor.setSelection(selectionRange);
+ editor.revealRange(selectionRange, monaco.editor.ScrollType.Smooth);
+ }
+ }
+ });
+ }
+
+ registerEolBasedLanguage(language, extraKeywords = [], extraConstants = []) {
+ monaco.languages.register({ id: language });
+ monaco.languages.setMonarchTokensProvider(language, {
+ defaultToken: '',
+ tokenPostfix: '.' + language,
+
+ keywords: [
+ 'import', 'driver', 'alias', 'if', 'switch', 'case', 'default', 'operation', 'function', 'new',
+ 'else', 'for', 'var', 'return', 'async', 'break', 'breakAll', 'and', 'or', 'not', 'xor', 'implies',
+ 'ext', 'in', 'continue', 'while', 'throw', 'delete', 'transaction', 'abort', 'model', 'group', 'as'
+ ].concat(extraKeywords),
+
+ constants: [
+ 'true', 'false', 'self', 'loopCount', 'hasMore'
+ ].concat(extraConstants),
+
+ types: [
+ 'String', 'Boolean', 'Integer', 'Real', 'Any', 'Map', 'Collection', 'Bag', 'Sequence', 'Set', 'OrderedSet', 'Native', 'List', 'Tuple', 'ConcurrentSet', 'ConcurrentBag', 'ConcurrentMap'
+ ],
+
+ operators: [
+ '=', '>', '<', '!', '~', '?', ':',
+ '==', '<=', '>=', '!=', '&&', '||', '++', '--',
+ '+', '-', '*', '/', '&', '|', '^', '%', '<<',
+ '>>', '>>>', '+=', '-=', '*=', '/=', '&=', '|=',
+ '^=', '%='
+ ],
+
+ // we include these common regular expressions
+ symbols: /[=>](?!@symbols)/, '@brackets'],
+ [/@symbols/, {
+ cases: {
+ '@operators': 'delimiter',
+ '@default': ''
+ }
+ }],
+
+ // numbers
+ [/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/, 'number.float'],
+ [/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/, 'number.float'],
+ [/0[xX](@hexdigits)[Ll]?/, 'number.hex'],
+ [/0(@octaldigits)[Ll]?/, 'number.octal'],
+ [/0[bB](@binarydigits)[Ll]?/, 'number.binary'],
+ [/(@digits)[fFdD]/, 'number.float'],
+ [/(@digits)[lL]?/, 'number'],
+
+ // delimiter: after number because of .\d floats
+ [/[;,.]/, 'delimiter'],
+
+ // strings
+ [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
+ [/"/, 'string', '@string'],
+
+ // characters
+ [/'[^\\']'/, 'string'],
+ [/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
+ [/'/, 'string.invalid']
+ ],
+
+ whitespace: [
+ [/[ \t\r\n]+/, ''],
+ [/\/\*/, 'comment', '@comment'],
+ [/\/\/.*$/, 'comment'],
+ ],
+
+ comment: [
+ [/[^\/*]+/, 'comment'],
+ [/\*\//, 'comment', '@pop'],
+ [/[\/*]/, 'comment']
+ ],
+
+ string: [
+ [/[^\\"]+/, 'string'],
+ [/@escapes/, 'string.escape'],
+ [/\\./, 'string.escape.invalid'],
+ [/"/, 'string', '@pop']
+ ],
+ },
+ });
+ }
+
+ registerEgl() {
+ monaco.languages.register({ id: 'egl' });
+ monaco.languages.setMonarchTokensProvider('egl', {
+ defaultToken: 'string',
+ tokenPostfix: '',
+
+ tokenizer: {
+ root: [
+ [/\[%(=)?/, { token: '@rematch', switchTo: '@egl.root' }],
+ [/\[\*/, 'comment', '@comment'],
+ ],
+
+ comment: [
+ [/\*\]/, 'comment', '@pop'],
+ [/./, 'comment']
+ ],
+
+ egl: [
+ [/%\]/, { token: 'delimiter', switchTo: '@$S2.$S3' }],
+ { include: 'eglRoot' }
+ ],
+
+ eglRoot: [
+ [
+ /[a-zA-Z_]\w*/,
+ {
+ cases: {
+ '@keywords': { token: 'keyword' },
+ '@constants': { token: 'constant' },
+ '@types': { token: 'type' },
+ '@default': 'identifier'
+ }
+ }
+ ],
+
+ // brackets
+ [/[{}]/, 'delimiter.bracket'],
+ [/[\[\]]/, 'delimiter.array'],
+ [/[()]/, 'delimiter.parenthesis'],
+
+ // whitespace
+ [/[ \t\r\n]+/],
+
+ // comments
+ [/(#|\/\/)$/, 'comment'],
+ [/(#|\/\/)/, 'comment', '@eolLineComment'],
+
+ // block comments
+ [/\/\*/, 'comment', '@eolComment'],
+
+ // strings
+ [/"/, 'string', '@doubleQuoteString'],
+ [/'/, 'string', '@singleQuoteString'],
+
+ // delimiters
+ [/[\+\-\*\%\&\|\^\~\!\=\<\>\/\?\;\:\.\,\@]/, 'delimiter'],
+
+ // numbers
+ [/\d*\d+[eE]([\-+]?\d+)?/, 'number.float'],
+ [/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
+ [/0[xX][0-9a-fA-F']*[0-9a-fA-F]/, 'number.hex'],
+ [/0[0-7']*[0-7]/, 'number.octal'],
+ [/0[bB][0-1']*[0-1]/, 'number.binary'],
+ [/\d[\d']*/, 'number'],
+ [/\d/, 'number']
+ ],
+
+ eolComment: [
+ [/\*\//, 'comment', '@pop'],
+ [/[^*]+/, 'comment'],
+ [/./, 'comment']
+ ],
+
+ eolLineComment: [
+ [/\?>/, { token: '@rematch', next: '@pop' }],
+ [/.$/, 'comment', '@pop'],
+ [/[^?]+$/, 'comment', '@pop'],
+ [/[^?]+/, 'comment'],
+ [/./, 'comment']
+ ],
+
+ doubleQuoteString: [
+ [/[^\\"]+/, 'string'],
+ [/@escapes/, 'string.escape'],
+ [/\\./, 'string.escape.invalid'],
+ [/"/, 'string', '@pop']
+ ],
+
+ singleQuoteString: [
+ [/[^\\']+/, 'string'],
+ [/@escapes/, 'string.escape'],
+ [/\\./, 'string.escape.invalid'],
+ [/'/, 'string', '@pop']
+ ]
+ },
+
+ keywords: [
+ 'import', 'driver', 'alias', 'if', 'switch', 'case', 'default', 'operation', 'function', 'new',
+ 'else', 'for', 'var', 'return', 'async', 'break', 'breakAll', 'and', 'or', 'not', 'xor', 'implies',
+ 'ext', 'in', 'continue', 'while', 'throw', 'delete', 'transaction', 'abort', 'model', 'group', 'as'
+ ],
+
+ constants: [
+ 'true', 'false', 'self', 'loopCount', 'hasMore'
+ ],
+
+ types: [
+ 'String', 'Boolean', 'Integer', 'Real', 'Any', 'Map', 'Collection', 'Bag', 'Sequence', 'Set', 'OrderedSet', 'Native', 'List', 'Tuple', 'ConcurrentSet', 'ConcurrentBag', 'ConcurrentMap'
+ ],
+
+ escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/
+ });
+ }
+
+ registerEmfatic() {
+ monaco.languages.register({ id: "emf" });
+ monaco.languages.setMonarchTokensProvider("emf", {
+ defaultToken: '',
+ tokenPostfix: '.emf',
+
+ keywords: [
+ 'abstract', 'attr', 'class', 'enum', 'mapentry', 'extends', 'import', 'package', 'ref', 'val', 'op', 'readonly', 'volatile', 'transient', 'unsettable', 'derived', 'unique', 'ordered', 'resolve', 'id'
+ ],
+
+ constants: [
+ 'true', 'false', 'self', 'loopCount', 'hasMore'
+ ],
+
+ types: [
+ 'boolean', 'Boolean', 'byte', 'Byte', 'char', 'Character', 'double', 'Double', 'float', 'Float', 'int', 'Integer', 'long', 'Long', 'short', 'Short', 'Date', 'String', 'Object', 'Class', 'EObject', 'EClass'
+ ],
+
+ operators: [
+ '=', '~'
+ ],
+
+ // we include these common regular expressions
+ symbols: /[=>](?!@symbols)/, '@brackets'],
+ [/@symbols/, {
+ cases: {
+ '@operators': 'delimiter',
+ '@default': ''
+ }
+ }],
+
+ // @ annotations.
+ [/@[^(]*/, 'annotation'],
+
+ //TODO: Not sure why $ annotations don't work
+
+ // numbers
+ [/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/, 'number.float'],
+ [/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/, 'number.float'],
+ [/0[xX](@hexdigits)[Ll]?/, 'number.hex'],
+ [/0(@octaldigits)[Ll]?/, 'number.octal'],
+ [/0[bB](@binarydigits)[Ll]?/, 'number.binary'],
+ [/(@digits)[fFdD]/, 'number.float'],
+ [/(@digits)[lL]?/, 'number'],
+
+ // delimiter: after number because of .\d floats
+ [/[;,.]/, 'delimiter'],
+
+ // strings
+ [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
+ [/"/, 'string', '@string'],
+
+ // characters
+ [/'[^\\']'/, 'string'],
+ [/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
+ [/'/, 'string.invalid']
+ ],
+
+ whitespace: [
+ [/[ \t\r\n]+/, ''],
+ [/\/\*\*(?!\/)/, 'comment.doc'],
+ [/\/\*/, 'comment', '@comment'],
+ [/\/\/.*$/, 'comment'],
+ ],
+
+ comment: [
+ [/[^\/*]+/, 'comment'],
+ // [/\/\*/, 'comment', '@push' ], // nested comment not allowed :-(
+ // [/\/\*/, 'comment.invalid' ], // this breaks block comments in the shape of /* //*/
+ [/\*\//, 'comment', '@pop'],
+ [/[\/*]/, 'comment']
+ ],
+
+ string: [
+ [/[^\\"]+/, 'string'],
+ [/@escapes/, 'string.escape'],
+ [/\\./, 'string.escape.invalid'],
+ [/"/, 'string', '@pop']
+ ],
+ },
+ });
+ }
+
+}
+
+export {MonacoSetup};
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/OutputPanel.js b/mkdocs/docs/playground/js/OutputPanel.js
index 910f2062e..bac8a76f0 100644
--- a/mkdocs/docs/playground/js/OutputPanel.js
+++ b/mkdocs/docs/playground/js/OutputPanel.js
@@ -1,5 +1,6 @@
import { ModelPanel } from "./ModelPanel.js";
import { language } from "./Playground.js";
+import * as monaco from 'monaco-editor';
class OutputPanel extends ModelPanel {
@@ -14,8 +15,7 @@ class OutputPanel extends ModelPanel {
this.outputLanguage = outputLanguage;
this.language = language;
this.createButtons();
- this.getEditor().getSession().setMode("ace/mode/" + outputLanguage.toLowerCase());
- //this.getEditor().getSession().setUseWrapMode(false);
+ this.setLanguage(outputLanguage.toLowerCase());
}
setupSyntaxHighlighting() {}
@@ -45,7 +45,7 @@ class OutputPanel extends ModelPanel {
}
var select = this.getSelect();
- var previousSelection = select.getSelected();
+ var previousSelection = select.getSelected()[0];
select.data(Object.fromEntries(options));
@@ -58,38 +58,50 @@ class OutputPanel extends ModelPanel {
var self = this;
Metro.dialog.create({
title: "Set Generated Text Language",
- content: "
You can set the language of the generated text to any language supported by the ACE editor.
",
+ content: "You can set the language of the generated text to any language supported by the Monaco editor.
",
actions: [
{
caption: "OK",
cls: "js-dialog-close success",
onclick: function () {
var outputLanguage = document.getElementById("language").value;
- self.getEditor().getSession().setMode("ace/mode/" + outputLanguage.toLowerCase());
+ self.setLanguage(outputLanguage.toLowerCase());
}
},
{
caption: "Cancel",
cls: "js-dialog-close"
}
- ]
+ ],
+ closeButton: true
});
}
+ getLanguageForPath(path) {
+ const ext = path.split('.').pop(); // Extract file extension
+ return monaco.languages.getLanguages().find(lang =>
+ lang.extensions?.includes(`.${ext}`)
+ )?.id || 'plaintext'; // Default to plaintext if unknown
+ }
+
+ setLanguage(language) {
+ super.setLanguage(language);
+ this.outputLanguage = language;
+ }
+
displayGeneratedFile(path) {
for (const generatedFile of this.generatedFiles) {
if (generatedFile.path == path) {
+ // Set the detected language to the editor model
+ this.setLanguage(this.getLanguageForPath(path));
this.setValue(generatedFile.content);
- // Set the right syntax highlighting for the file extension
- var modelist = ace.require("ace/ext/modelist");
- this.getEditor().getSession().setMode(modelist.getModeForPath(path + "").mode);
return;
}
}
-
+
// If the generated path is invalid, reset the editor
this.setValue("");
- this.getEditor().getSession().setMode("ace/mode/text");
+ this.setLanguage("plaintext");
}
generatedFileSelected() {
diff --git a/mkdocs/docs/playground/js/Panel.js b/mkdocs/docs/playground/js/Panel.js
index 2f597749f..58e910174 100644
--- a/mkdocs/docs/playground/js/Panel.js
+++ b/mkdocs/docs/playground/js/Panel.js
@@ -1,3 +1,5 @@
+import * as monaco from 'monaco-editor';
+
class Panel {
id;
@@ -11,18 +13,29 @@ class Panel {
constructor(id) {
this.id = id;
this.getElement();
-
- // Set up the panel's editor
- this.editor = ace.edit(this.element.querySelector('.editor'));
- this.editor.setShowPrintMargin(false);
- this.editor.setTheme("ace/theme/eclipse");
- this.editor.renderer.setShowGutter(false);
- this.editor.setFontSize("1rem");
- this.editor.setOptions({
- fontSize: "11pt",
- useSoftTabs: true
+
+ this.editor = monaco.editor.create(this.element.querySelector('.editor'), {
+ theme: "playground",
+ autoDetectHighContrast: "false",
+ fontSize: 14,
+ automaticLayout: true,
+ minimap: {
+ enabled: false
+ },
+ lineNumbers: "off",
+ renderLineHighlight: "none",
+ occurrencesHighlight: "off",
+ selectionHighlight: false,
+ insertSpaces: false,
+ acceptSuggestionOnEnter: "off",
+ stickyScroll: {
+ enabled: false,
+ maxLineCount: 0
+ },
+ overviewRulerLanes: 0,
+ // folding: false
});
-
+
this.visible = true;
}
@@ -110,6 +123,10 @@ class Panel {
this.maximised = !this.maximised;
}
+ setLanguage(language) {
+ monaco.editor.setModelLanguage(this.editor.getModel(), language);
+ }
+
getEditor() {
return this.editor;
}
@@ -120,9 +137,7 @@ class Panel {
setValue(value) {
if (value === undefined) value = "";
- this.editor.setValue((value + ""), 1);
- // Reset undo manager
- this.editor.session.getUndoManager().reset();
+ this.editor.setValue(value);
}
buttonHtml(icon, hint, id = null) {
diff --git a/mkdocs/docs/playground/js/Playground.js b/mkdocs/docs/playground/js/Playground.js
index 03c59bd6f..9c22cd801 100644
--- a/mkdocs/docs/playground/js/Playground.js
+++ b/mkdocs/docs/playground/js/Playground.js
@@ -1,11 +1,3 @@
-import 'ace-builds/src-min-noconflict/ace';
-import 'ace-builds/src-min-noconflict/theme-eclipse';
-import 'ace-builds/src-min-noconflict/mode-xml';
-import 'ace-builds/src-min-noconflict/mode-yaml';
-import 'ace-builds/src-min-noconflict/mode-java';
-import 'ace-builds/src-min-noconflict/mode-html';
-import 'ace-builds/src-min-noconflict/ext-modelist';
-
import { ModelPanel } from './ModelPanel.js';
import { ConsolePanel } from "./ConsolePanel.js";
import { ProgramPanel } from "./ProgramPanel.js";
@@ -14,11 +6,13 @@ import { ExampleManager } from './ExampleManager.js';
import { DownloadDialog } from './DownloadDialog.js';
import { MetamodelPanel } from './MetamodelPanel.js';
import { SettingsDialog } from './SettingsDialog.js';
+import { LiveShareDialog } from './LiveShareDialog.js';
import { Preloader } from './Preloader.js';
import { Backend } from './Backend.js';
import { Layout } from './Layout.js';
import 'metro4';
-import './highlighting/highlighting.js';
+import { MonacoSetup } from './MonacoSetup.js';
+import { LiveShareManager } from './LiveShareManager.js';
export var language = "eol";
var outputType = "text";
@@ -27,6 +21,8 @@ var example;
var url = window.location + "";
var questionMark = url.indexOf("?");
+new MonacoSetup().do();
+
export var programPanel = new ProgramPanel();
export var secondProgramPanel = new ProgramPanel("secondProgram");
export var firstMetamodelPanel = new MetamodelPanel("firstMetamodel");
@@ -40,13 +36,17 @@ export var outputPanel;
export var consolePanel = new ConsolePanel();
var downloadDialog = new DownloadDialog();
var settingsDialog = new SettingsDialog();
-var preloader = new Preloader();
+var liveShareDialog = new LiveShareDialog();
+export var preloader = new Preloader();
export var backend = new Backend();
export var examplesManager = new ExampleManager();
+export var liveShareManager = new LiveShareManager();
+
var panels = [];
backend.configure();
+preloader.progress("Fetching programs, models and metamodels");
example = examplesManager.getSelectedExample();
setup();
@@ -74,14 +74,9 @@ function setup() {
if (language == "egx") secondProgramPanel.setLanguage("egl");
if (language == "eml") secondProgramPanel.setLanguage("ecl");
- programPanel.setValue(example.program);
- secondProgramPanel.setValue(example.secondProgram);
- firstModelPanel.setValue(example.flexmi);
- firstMetamodelPanel.setValue(example.emfatic);
- secondModelPanel.setValue(example.secondFlexmi);
- secondMetamodelPanel.setValue(example.secondEmfatic);
- thirdModelPanel.setValue(example.thirdFlexmi);
- thirdMetamodelPanel.setValue(example.thirdEmfatic);
+ if (!liveShareManager.willJoinSession()) {
+ initialisePanelValues();
+ }
document.getElementById("navview").style.display = "block";
@@ -104,6 +99,16 @@ function setup() {
fit();
}
+function initialisePanelValues() {
+ programPanel.setValue(example.program);
+ secondProgramPanel.setValue(example.secondProgram);
+ firstModelPanel.setValue(example.flexmi);
+ firstMetamodelPanel.setValue(example.emfatic);
+ secondModelPanel.setValue(example.secondFlexmi);
+ secondMetamodelPanel.setValue(example.secondEmfatic);
+ thirdModelPanel.setValue(example.thirdFlexmi);
+ thirdMetamodelPanel.setValue(example.thirdEmfatic);
+}
function copyShortenedLink(event) {
event.preventDefault();
@@ -135,7 +140,8 @@ function copyShortenedLink(event) {
onclick: function(){
copyToClipboard(baseUrl + "?" + json.shortened);
}
- }]
+ }],
+ closeButton: true
});
}
Metro.notify.killAll();
@@ -250,7 +256,7 @@ function editorsToJsonObject() {
"secondEmfatic": secondMetamodelPanel.getValue(),
"secondFlexmi": secondModelPanel.getValue(),
"thirdEmfatic": thirdMetamodelPanel.getValue(),
- "thirdFlexmi": thirdModelPanel.getValue(),
+ "thirdFlexmi": thirdModelPanel.getValue()
};
}
@@ -265,7 +271,6 @@ function fit() {
splitter.style.maxHeight = window.innerHeight + "px";
panels.forEach(panel => panel.fit());
- preloader.hide();
}
function runProgram() {
@@ -325,7 +330,7 @@ function runProgram() {
else krokiEndpoint = "graphviz/svg"
var krokiXhr = new XMLHttpRequest();
- krokiXhr.open("POST", "https://uk-ac-york-cs-epsilon-kroki.h5rwqzvxy5sr4.eu-west-1.cs.amazonlightsail.com/" + krokiEndpoint, true);
+ krokiXhr.open("POST", backend.getKrokiService() + "/" + krokiEndpoint, true);
krokiXhr.setRequestHeader("Accept", "image/svg+xml");
krokiXhr.setRequestHeader("Content-Type", "text/plain");
krokiXhr.onreadystatechange = function () {
@@ -380,7 +385,7 @@ function getActivePanels() {
}
function longNotification(title, cls="light") {
- Metro.notify.create("" + title + "...
This may take a few seconds to complete if the back end is not warmed up.", null, {keepOpen: true, cls: cls, width: 300});
+ Metro.notify.create("" + title + "...
This may take a few seconds to complete.", null, {keepOpen: true, cls: cls, width: 300});
}
function updateGutterVisibility() {
@@ -429,6 +434,10 @@ function showSettings(event) {
settingsDialog.show(event);
}
+function showLiveShare(event) {
+ liveShareDialog.show(event);
+}
+
// Some functions and variables are accessed
// by onclick - or similer - events
// We need to use window.x = x for this to work
@@ -447,12 +456,17 @@ window.secondMetamodelPanel = secondMetamodelPanel;
window.thirdModelPanel = thirdModelPanel;
window.thirdMetamodelPanel = thirdMetamodelPanel;
window.panels = panels;
+window.preloader = preloader;
window.backend = backend;
window.longNotification = longNotification;
window.showDownloadOptions = showDownloadOptions;
window.showSettings = showSettings;
+window.showLiveShare = showLiveShare;
+window.initialisePanelValues = initialisePanelValues;
window.copyShortenedLink = copyShortenedLink;
+window.copyToClipboard = copyToClipboard;
window.downloadDialog = downloadDialog;
window.language = language;
window.getActivePanels = getActivePanels;
+liveShareManager.init();
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/Preloader.js b/mkdocs/docs/playground/js/Preloader.js
index ec25d032e..aa5eeddd6 100644
--- a/mkdocs/docs/playground/js/Preloader.js
+++ b/mkdocs/docs/playground/js/Preloader.js
@@ -2,6 +2,10 @@ class Preloader {
visible = true;
+ progress(message) {
+ document.getElementById("preloader-message").innerHTML = message + "...";
+ }
+
hide() {
if (this.visible) {
var self = this;
diff --git a/mkdocs/docs/playground/js/ProgramPanel.js b/mkdocs/docs/playground/js/ProgramPanel.js
index a1205daad..2255db7ab 100644
--- a/mkdocs/docs/playground/js/ProgramPanel.js
+++ b/mkdocs/docs/playground/js/ProgramPanel.js
@@ -10,7 +10,8 @@ class ProgramPanel extends Panel {
setLanguage(language) {
this.language = language;
- this.editor.getSession().setMode("ace/mode/" + language);
+ super.setLanguage(language);
+
this.createButtons();
var title = "";
@@ -41,7 +42,7 @@ class ProgramPanel extends Panel {
if (editorElement != null) {
editorElement.parentNode.style = "flex-basis: calc(100% - 4px);";
}
- this.editor.resize();
+ // this.editor.resize();
}
getButtons() {
@@ -59,16 +60,6 @@ class ProgramPanel extends Panel {
});
}
return buttons;
- /*
- return [{
- html: this.buttonHtml("help", languageName + " language reference"),
- cls: "sys-button",
- onclick: "window.open('https://www.eclipse.org/epsilon/doc/'+language);"
- }, {
- html: this.buttonHtml("run", "Run the program (Ctrl/Cmd+S)"),
- cls: "sys-button",
- onclick: "runProgram()"
- }];*/
}
// TODO: Identical to ConsolePanel.createElement()
diff --git a/mkdocs/docs/playground/js/SettingsDialog.js b/mkdocs/docs/playground/js/SettingsDialog.js
index bb8fcf627..59798609a 100644
--- a/mkdocs/docs/playground/js/SettingsDialog.js
+++ b/mkdocs/docs/playground/js/SettingsDialog.js
@@ -46,13 +46,18 @@ class SettingsDialog {
caption: "Cancel",
cls: "js-dialog-close"
}
- ]
+ ],
+ closeButton: true
});
}
updateEditorLineNumbers() {
this.showEditorLineNumbers = document.getElementById("editorLineNumbers").checked;
- panels.forEach(p => p.getEditor().renderer.setShowGutter(this.showEditorLineNumbers));
+ panels.forEach(p => {
+ p.getEditor().updateOptions({
+ lineNumbers: this.showEditorLineNumbers ? 'on' : 'off'
+ });
+ });
}
createEditorLineNumbersCheckbox() {
diff --git a/mkdocs/docs/playground/js/highlighting/ecl.js b/mkdocs/docs/playground/js/highlighting/ecl.js
deleted file mode 100644
index 3f15ad185..000000000
--- a/mkdocs/docs/playground/js/highlighting/ecl.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/ecl_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
-var eclHighlightRules = function() {
-
- var keywords = (
- "match|with|auto|do|compare|rule|pre|post|not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- } ]
- };
- this.normalizeRules();
-};
-
-oop.inherits(eclHighlightRules, TextHighlightRules);
-
-exports.eclHighlightRules = eclHighlightRules;
-});
-
-define("ace/mode/ecl",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/ecl_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextMode = require("./text").Mode;
-var eclHighlightRules = require("./ecl_highlight_rules").eclHighlightRules;
-
-var Mode = function() {
- this.HighlightRules = eclHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
-};
-oop.inherits(Mode, TextMode);
-
-(function() {
- this.$id = "ace/mode/ecl";
- this.snippetFileId = "ace/snippets/ecl";
-}).call(Mode.prototype);
-
-exports.Mode = Mode;
-
-});
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/egl.js b/mkdocs/docs/playground/js/highlighting/egl.js
deleted file mode 100644
index 3504c46e4..000000000
--- a/mkdocs/docs/playground/js/highlighting/egl.js
+++ /dev/null
@@ -1,135 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/egl_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
-var EglHighlightRules = function() {
-
- var keywords = (
- "not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [
- {
- token: "text",
- regex: "\\[%",
- next: "dynamic"
- },
- {
- token: "comment",
- regex: "\\[\\*",
- next: "comment"
- },
- {
- token: "string",
- regex: "."
- }
- ],
- "comment" : [
- {
- token: "comment",
- regex: "\\*\\]",
- next: "start"
- },
- {
- token: "comment",
- regex: "."
- }
- ],
- "dynamic_comment" : [
- {
- token: "comment",
- regex: "\\*/",
- next: "dynamic"
- },
- {
- token: "comment",
- regex: "."
- }
- ],
- "dynamic" : [
- {
- token : "comment",
- regex : "//.*$"
- },
- {
- token : "comment",
- regex : "/\\*",
- next : "dynamic_comment"
- },
- {
- token : "string", // " string
- regex : '".*?"'
- },
- {
- token : "string", // ' string
- regex : "'.*?'"
- },
- {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- },
- {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- },
- {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- },
- {
- token : "text",
- regex : "\\s+"
- },
- {
- token: "text",
- regex: "%\\]",
- next: "start"
- }]
- };
-};
-
-oop.inherits(EglHighlightRules, TextHighlightRules);
-
-exports.EglHighlightRules = EglHighlightRules;
-
-});
-
-define("ace/mode/egl",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/egl_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextMode = require("./text").Mode;
-var EglHighlightRules = require("./egl_highlight_rules").EglHighlightRules;
-
-var Mode = function() {
- this.HighlightRules = EglHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
-};
-oop.inherits(Mode, TextMode);
-
-exports.Mode = Mode;
-});
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/egx.js b/mkdocs/docs/playground/js/highlighting/egx.js
deleted file mode 100644
index bbb77c1ab..000000000
--- a/mkdocs/docs/playground/js/highlighting/egx.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/egx_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
- "use strict";
-
- var oop = require("../lib/oop");
- var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
- var egxHighlightRules = function() {
-
- var keywords = (
- "rule|transform|template|merge|append|patch|template|parameters|formatter|target||guard|pre|post|not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies|extends"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- } ]
- };
- this.normalizeRules();
- };
-
- oop.inherits(egxHighlightRules, TextHighlightRules);
-
- exports.egxHighlightRules = egxHighlightRules;
- });
-
- define("ace/mode/egx",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/egx_highlight_rules"], function(require, exports, module) {
- "use strict";
-
- var oop = require("../lib/oop");
- var TextMode = require("./text").Mode;
- var egxHighlightRules = require("./egx_highlight_rules").egxHighlightRules;
-
- var Mode = function() {
- this.HighlightRules = egxHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
- };
- oop.inherits(Mode, TextMode);
-
- (function() {
- this.$id = "ace/mode/egx";
- this.snippetFileId = "ace/snippets/egx";
- }).call(Mode.prototype);
-
- exports.Mode = Mode;
-
- });
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/emfatic.js b/mkdocs/docs/playground/js/highlighting/emfatic.js
deleted file mode 100644
index 0ea24a69f..000000000
--- a/mkdocs/docs/playground/js/highlighting/emfatic.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/emfatic_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
-var emfaticHighlightRules = function() {
-
- var keywords = (
- "abstract|attr|class|enum|extends|import|package|ref|val|op|readonly|volatile|transient|unsettable|derived|unique|ordered|resolve|id|datatype"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "boolean|Boolean|byte|Byte|char|Character|double|Double|float|Float|int|Integer|long|Long|short|Short|Date|String|Object|Class|EObject|EClass"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- regex : "@.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token : "text",
- regex : "~[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- } ]
- };
- this.normalizeRules();
-};
-
-oop.inherits(emfaticHighlightRules, TextHighlightRules);
-
-exports.emfaticHighlightRules = emfaticHighlightRules;
-});
-
-define("ace/mode/emfatic",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/emfatic_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextMode = require("./text").Mode;
-var emfaticHighlightRules = require("./emfatic_highlight_rules").emfaticHighlightRules;
-
-var Mode = function() {
- this.HighlightRules = emfaticHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
-};
-oop.inherits(Mode, TextMode);
-
-(function() {
- this.$id = "ace/mode/emfatic";
- this.snippetFileId = "ace/snippets/emfatic";
-}).call(Mode.prototype);
-
-exports.Mode = Mode;
-});
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/emg.js b/mkdocs/docs/playground/js/highlighting/emg.js
deleted file mode 100644
index 86d2d16c6..000000000
--- a/mkdocs/docs/playground/js/highlighting/emg.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/emg_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
-var emgHighlightRules = function() {
-
- var keywords = (
- "match|onmatch|nomatch|pattern|do|from|pre|post|not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies|$instances"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token: "keyword",
- regex: "(@list|@probability)"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- }]
- };
- this.normalizeRules();
-};
-
-oop.inherits(emgHighlightRules, TextHighlightRules);
-
-exports.emgHighlightRules = emgHighlightRules;
-});
-
-define("ace/mode/emg",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/emg_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextMode = require("./text").Mode;
-var emgHighlightRules = require("./emg_highlight_rules").emgHighlightRules;
-
-var Mode = function() {
- this.HighlightRules = emgHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
-};
-oop.inherits(Mode, TextMode);
-
-(function() {
- this.$id = "ace/mode/emg";
- this.snippetFileId = "ace/snippets/emg";
-}).call(Mode.prototype);
-
-exports.Mode = Mode;
-
-});
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/eml.js b/mkdocs/docs/playground/js/highlighting/eml.js
deleted file mode 100644
index e39435ccb..000000000
--- a/mkdocs/docs/playground/js/highlighting/eml.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/eml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
-var emlHighlightRules = function() {
-
- var keywords = (
- "merge|with|into|rule|transform|to|guard|pre|post|not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies|extends"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- } ]
- };
- this.normalizeRules();
-};
-
-oop.inherits(emlHighlightRules, TextHighlightRules);
-
-exports.emlHighlightRules = emlHighlightRules;
-});
-
-define("ace/mode/eml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/eml_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextMode = require("./text").Mode;
-var emlHighlightRules = require("./eml_highlight_rules").emlHighlightRules;
-
-var Mode = function() {
- this.HighlightRules = emlHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
-};
-oop.inherits(Mode, TextMode);
-
-(function() {
- this.$id = "ace/mode/eml";
- this.snippetFileId = "ace/snippets/eml";
-}).call(Mode.prototype);
-
-exports.Mode = Mode;
-
-});
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/eol.js b/mkdocs/docs/playground/js/highlighting/eol.js
deleted file mode 100644
index 90c455501..000000000
--- a/mkdocs/docs/playground/js/highlighting/eol.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/eol_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
-var eolHighlightRules = function() {
-
- var keywords = (
- "not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- } ]
- };
- this.normalizeRules();
-};
-
-oop.inherits(eolHighlightRules, TextHighlightRules);
-
-exports.eolHighlightRules = eolHighlightRules;
-});
-
-define("ace/mode/eol",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/eol_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextMode = require("./text").Mode;
-var eolHighlightRules = require("./eol_highlight_rules").eolHighlightRules;
-
-var Mode = function() {
- this.HighlightRules = eolHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
-};
-oop.inherits(Mode, TextMode);
-
-(function() {
- this.$id = "ace/mode/eol";
- this.snippetFileId = "ace/snippets/eol";
-}).call(Mode.prototype);
-
-exports.Mode = Mode;
-
-});
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/epl.js b/mkdocs/docs/playground/js/highlighting/epl.js
deleted file mode 100644
index 69fa39310..000000000
--- a/mkdocs/docs/playground/js/highlighting/epl.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/epl_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
-var eplHighlightRules = function() {
-
- var keywords = (
- "match|onmatch|nomatch|pattern|do|from|pre|post|not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- } ]
- };
- this.normalizeRules();
-};
-
-oop.inherits(eplHighlightRules, TextHighlightRules);
-
-exports.eplHighlightRules = eplHighlightRules;
-});
-
-define("ace/mode/epl",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/epl_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextMode = require("./text").Mode;
-var eplHighlightRules = require("./epl_highlight_rules").eplHighlightRules;
-
-var Mode = function() {
- this.HighlightRules = eplHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
-};
-oop.inherits(Mode, TextMode);
-
-(function() {
- this.$id = "ace/mode/epl";
- this.snippetFileId = "ace/snippets/epl";
-}).call(Mode.prototype);
-
-exports.Mode = Mode;
-
-});
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/etl.js b/mkdocs/docs/playground/js/highlighting/etl.js
deleted file mode 100644
index adcbe2075..000000000
--- a/mkdocs/docs/playground/js/highlighting/etl.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/etl_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
-var etlHighlightRules = function() {
-
- var keywords = (
- "rule|transform|to|guard|pre|post|not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies|extends"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- } ]
- };
- this.normalizeRules();
-};
-
-oop.inherits(etlHighlightRules, TextHighlightRules);
-
-exports.etlHighlightRules = etlHighlightRules;
-});
-
-define("ace/mode/etl",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/etl_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextMode = require("./text").Mode;
-var etlHighlightRules = require("./etl_highlight_rules").etlHighlightRules;
-
-var Mode = function() {
- this.HighlightRules = etlHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
-};
-oop.inherits(Mode, TextMode);
-
-(function() {
- this.$id = "ace/mode/etl";
- this.snippetFileId = "ace/snippets/etl";
-}).call(Mode.prototype);
-
-exports.Mode = Mode;
-
-});
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/evl.js b/mkdocs/docs/playground/js/highlighting/evl.js
deleted file mode 100644
index 2929cc1dd..000000000
--- a/mkdocs/docs/playground/js/highlighting/evl.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/evl_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
-var evlHighlightRules = function() {
-
- var keywords = (
- "context|constraint|critique|message|guard|check|fix|do|title|pre|post|not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- } ]
- };
- this.normalizeRules();
-};
-
-oop.inherits(evlHighlightRules, TextHighlightRules);
-
-exports.evlHighlightRules = evlHighlightRules;
-});
-
-define("ace/mode/evl",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/evl_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextMode = require("./text").Mode;
-var evlHighlightRules = require("./evl_highlight_rules").evlHighlightRules;
-
-var Mode = function() {
- this.HighlightRules = evlHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
-};
-oop.inherits(Mode, TextMode);
-
-(function() {
- this.$id = "ace/mode/evl";
- this.snippetFileId = "ace/snippets/evl";
-}).call(Mode.prototype);
-
-exports.Mode = Mode;
-
-});
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/flock.js b/mkdocs/docs/playground/js/highlighting/flock.js
deleted file mode 100644
index 8aaa9f185..000000000
--- a/mkdocs/docs/playground/js/highlighting/flock.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/flock_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
-var flockHighlightRules = function() {
-
- var keywords = (
- "delete|retype|to|migrate|when|ignoring|package|pre|post|not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies|extends"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- } ]
- };
- this.normalizeRules();
-};
-
-oop.inherits(flockHighlightRules, TextHighlightRules);
-
-exports.flockHighlightRules = flockHighlightRules;
-});
-
-define("ace/mode/flock",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/flock_highlight_rules"], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var TextMode = require("./text").Mode;
-var flockHighlightRules = require("./flock_highlight_rules").flockHighlightRules;
-
-var Mode = function() {
- this.HighlightRules = flockHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
-};
-oop.inherits(Mode, TextMode);
-
-(function() {
- this.$id = "ace/mode/flock";
- this.snippetFileId = "ace/snippets/flock";
-}).call(Mode.prototype);
-
-exports.Mode = Mode;
-
-});
\ No newline at end of file
diff --git a/mkdocs/docs/playground/js/highlighting/highlighting.js b/mkdocs/docs/playground/js/highlighting/highlighting.js
deleted file mode 100644
index afe8bbaeb..000000000
--- a/mkdocs/docs/playground/js/highlighting/highlighting.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import './eol.js';
-import './etl.js';
-import './emg.js';
-import './flock.js';
-import './evl.js';
-import './epl.js';
-import './eml.js';
-import './ecl.js';
-import './egl.js';
-import './egx.js';
-import './pinset.js';
-import './emfatic.js';
-
-const CDN = 'https://cdn.jsdelivr.net/npm/ace-builds@1.14.0/src-min-noconflict';
-
-// Now we tell ace to use the CDN locations to look for language-related
-// files so that we don't have to include them in the bundle
-ace.config.set('basePath', CDN);
-ace.config.set('modePath', CDN);
-ace.config.set('themePath', CDN);
-ace.config.set('workerPath', CDN);
diff --git a/mkdocs/docs/playground/js/highlighting/pinset.js b/mkdocs/docs/playground/js/highlighting/pinset.js
deleted file mode 100644
index 5122e6bda..000000000
--- a/mkdocs/docs/playground/js/highlighting/pinset.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import {define} from "ace-builds";
-
-define("ace/mode/pinset_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
- "use strict";
-
- var oop = require("../lib/oop");
- var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
-
- var pinsetHighlightRules = function() {
-
- var keywords = (
- "|dataset|over|from|column|properties|reference|grid|keys|header|body|guard|pre|post|not|delete|import|for|while|in|and|or|operation|return|var|throw|if|new|else|transaction|abort|break|continue|assert|assertError|not|function|default|switch|case|as|ext|driver|alias|model|breakAll|async|group|nor|xor|implies|extends"
- );
-
- var builtinConstants = (
- "true|false|self"
- );
-
- var builtinFunctions = (
- ""
- );
-
- var dataTypes = (
- "Any|String|Integer|Real|Boolean|Native|Bag|Set|List|Sequence|Map|OrderedSet|Collection|Tuple|ConcurrentBag|ConcurrentMap|ConcurrentSet"
- );
-
- var keywordMapper = this.createKeywordMapper({
- "support.function": builtinFunctions,
- "keyword": keywords,
- "constant.language": builtinConstants,
- "storage.type": dataTypes
- }, "identifier", false);
-
- this.$rules = {
- "start" : [ {
- token : "comment",
- regex : "//.*$"
- }, {
- token : "comment",
- start : "/\\*",
- end : "\\*/"
- }, {
- token : "string", // " string
- regex : '".*?"'
- }, {
- token : "string", // ' string
- regex : "'.*?'"
- }, {
- token : "string", // ` string (apache drill)
- regex : "`.*?`"
- }, {
- token : "constant.numeric", // float
- regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
- }, {
- token : keywordMapper,
- regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
- }, {
- token : "text",
- regex : "\\s+"
- } ]
- };
- this.normalizeRules();
- };
-
- oop.inherits(pinsetHighlightRules, TextHighlightRules);
-
- exports.pinsetHighlightRules = pinsetHighlightRules;
- });
-
- define("ace/mode/pinset",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/pinset_highlight_rules"], function(require, exports, module) {
- "use strict";
-
- var oop = require("../lib/oop");
- var TextMode = require("./text").Mode;
- var pinsetHighlightRules = require("./pinset_highlight_rules").pinsetHighlightRules;
-
- var Mode = function() {
- this.HighlightRules = pinsetHighlightRules;
- this.$behaviour = this.$defaultBehaviour;
- };
- oop.inherits(Mode, TextMode);
-
- (function() {
- this.$id = "ace/mode/pinset";
- this.snippetFileId = "ace/snippets/pinset";
- }).call(Mode.prototype);
-
- exports.Mode = Mode;
-
- });
diff --git a/mkdocs/docs/playground/package.json b/mkdocs/docs/playground/package.json
index 1e6d8c8f9..bc84243ff 100644
--- a/mkdocs/docs/playground/package.json
+++ b/mkdocs/docs/playground/package.json
@@ -12,16 +12,24 @@
"author": "",
"license": "ISC",
"dependencies": {
- "ace-builds": "1.14.0",
+ "css-loader": "^7.1.2",
"handlebars": "4.7.7",
"jszip": "3.10.1",
- "metro4": "4.5.1",
- "svg-pan-zoom": "3.6.1"
+ "metro4": "^4.6.0",
+ "monaco-editor": "0.52.2",
+ "monaco-editor-webpack-plugin": "^7.1.0",
+ "style-loader": "^4.0.0",
+ "svg-pan-zoom": "3.6.1",
+ "y-monaco": "0.1.2",
+ "yjs": "^13.3.1"
},
"devDependencies": {
"cypress": "13.16.0",
"file-loader": "6.2.0",
"webpack": "5.75.0",
- "webpack-cli": "5.1.4"
+ "webpack-cli": "5.1.4",
+ "y-protocols": "^1.0.5",
+ "y-websocket": "^1.5.4",
+ "yjs": "^13.5.23"
}
}
diff --git a/mkdocs/docs/playground/readme.md b/mkdocs/docs/playground/readme.md
index 07fac828b..21c3038f1 100644
--- a/mkdocs/docs/playground/readme.md
+++ b/mkdocs/docs/playground/readme.md
@@ -36,3 +36,10 @@ To speed up test execution, please disable live reloading by serving the website
```
./serve-no-livereload.sh
```
+
+## Running YJS locally
+
+YJS enables live collaboration in the Playground. To run YJS locally, run:
+
+- `npm i y-websocket`
+- `HOST=localhost PORT=1234 npx y-websocket`
\ No newline at end of file
diff --git a/mkdocs/docs/playground/run-cypress-local.sh b/mkdocs/docs/playground/run-cypress-local.sh
index cccb3fe0f..d5987ff83 100755
--- a/mkdocs/docs/playground/run-cypress-local.sh
+++ b/mkdocs/docs/playground/run-cypress-local.sh
@@ -18,7 +18,7 @@ wait_for_service() {
}
cleanup() {
- git restore .
+ git restore backend.json
if test -n "$PID_MKDOCS"; then
echo "Stopping mkdocs at PID $PID_MKDOCS"
pkill -P "$PID_MKDOCS"
@@ -39,7 +39,7 @@ npx webpack --mode=development
PID_MKDOCS=$!
# Start backend in the background
-docker run --rm -p 8080:8080 ghcr.io/epsilonlabs/playground-backend:standalone-server &
+docker run --rm -p 8080:8080 ghcr.io/epsilonlabs/playground-backend/standalone-server &
PID_DOCKER=$!
# Wait for both to finish starting
diff --git a/mkdocs/docs/playground/webpack.config.js b/mkdocs/docs/playground/webpack.config.js
index f5024be45..727e140f9 100644
--- a/mkdocs/docs/playground/webpack.config.js
+++ b/mkdocs/docs/playground/webpack.config.js
@@ -1,3 +1,4 @@
+const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const path = require('path');
module.exports = {
@@ -6,5 +7,19 @@ module.exports = {
publicPath: 'dist/',
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
- }
+ },
+ devtool: 'source-map', // Add this line to enable source maps
+ module: {
+ rules: [
+ {
+ test: /\.css$/,
+ use: ['style-loader', 'css-loader']
+ },
+ {
+ test: /\.ttf$/,
+ type: 'asset/resource'
+ }
+ ]
+ },
+ plugins: [new MonacoWebpackPlugin()]
};
\ No newline at end of file