An editor for Microsoft Adaptive Cards that supports the new templating language and DOESN'T use JavaScript, because JavaScript isn't a real programming language.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

241 lines
8.9 KiB

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<style>
html, body {
height: 100%;
margin: 0;
}
/* Just have Monaco Fill All Available Space within control */
#container {
height: 100%;
width: 100%;
}
</style>
<style id="dynamic">
</style>
</head>
<body>
<div id="container" onkeydown="keyDown(event)"></div>
<script src="ms-appx-web:///Monaco/monaco-editor/min/vs/loader.js"></script>
<script>
var editor;
var model;
var contexts = {};
var decorations = [];
var modifingSelection = false; // Supress updates to selection when making edits.
Debug.log("Starting Monaco Load");
require.config({ paths: { 'vs': 'ms-appx-web:///Monaco/monaco-editor/min/vs' }});
require(['vs/editor/editor.main'], function () {
Debug.log("Grabbing Monaco Options");
let opt = getOptions();
opt["value"] = Parent.getValue("Text");
editor = monaco.editor.create(document.getElementById('container'), opt);
model = editor.getModel();
// Listen for Content Changes
model.onDidChangeContent((event) => {
Parent.setValue("Text", model.getValue());
//console.log("buffers: " + JSON.stringify(model._buffer._pieceTree._buffers));
//console.log("commandMgr: " + JSON.stringify(model._commandManager));
//console.log("viewState:" + JSON.stringify(editor.saveViewState()));
});
// Listen for Selection Changes
editor.onDidChangeCursorSelection((event) => {
if (!modifingSelection) {
console.log(event.source);
Parent.setValue("SelectedText", model.getValueInRange(event.selection));
Parent.setValue("SelectedRange", JSON.stringify(event.selection), "Selection");
}
})
// Set theme
let theme = Parent.getJsonValue("RequestedTheme");
theme = {
"0": "Default",
"1": "Light",
"2": "Dark"
}[theme];
if (theme == "Default") {
theme = Theme.currentThemeName.toString();
}
changeTheme(theme, Theme.isHighContrast.toString());
// Update Monaco Size when we receive a window resize event
window.addEventListener("resize", () => {
editor.layout();
});
// Disable WebView Scrollbar so Monaco Scrollbar can do heavy lifting
document.body.style.overflow = 'hidden';
// Callback to Parent that we're loaded
Debug.log("Loaded Monaco");
Parent.callAction("Loaded");
});
// TODO: Split these helper functions out into separate .js/.ts files.
var registerCompletionItemProvider = function (languageId, characters) {
return monaco.languages.registerCompletionItemProvider(languageId, {
triggerCharacters: characters,
provideCompletionItems: function (model, position, token, context) {
return Parent.callEvent("CompletionItemProvider" + languageId, [JSON.stringify(position), JSON.stringify(context)]).then(result => {
if (result) {
return JSON.parse(result);
}
});
}
//// TODO: support resolve method as well.
});
}
var registerHoverProvider = function (languageId) {
return monaco.languages.registerHoverProvider(languageId, {
provideHover: function (model, position) {
return Parent.callEvent("HoverProvider" + languageId, [JSON.stringify(position)]).then(result => {
if (result) {
return JSON.parse(result);
}
});
}
});
}
var addAction = function (action) {
action.run = function (ed) {
Parent.callAction("Action" + action.id)
};
editor.addAction(action);
};
var addCommand = function (keybindingStr, handlerName, context) {
return editor.addCommand(parseInt(keybindingStr), () => {
Parent.callAction(handlerName);
}, context);
};
var createContext = function (context) {
if (context) {
contexts[context.key] = editor.createContextKey(context.key, context.defaultValue);
}
};
var updateContext = function (key, value) {
contexts[key].set(value);
}
var updateContent = function (content) {
// Need to ignore updates from us notifying of a change
if (content != model.getValue()) {
model.setValue(content);
}
};
var updateSelectedContent = function (content) {
let selection = editor.getSelection();
// Need to ignore updates from us notifying of a change
if (content != model.getValueInRange(selection)) {
modifingSelection = true;
let range = new monaco.Range(selection.startLineNumber, selection.startColumn, selection.endLineNumber, selection.endColumn);
let op = { identifier: { major: 1, minor: 1 }, range, text: content, forceMoveMarkers: true };
// Make change to selection
model.pushEditOperations([], [op]);
// Update selection to new text.
selection.endLineNumber = selection.startLineNumber + content.split('\r').length - 1; // TODO: Not sure if line end is situational/platform specific... investigate more.
if (selection.startLineNumber === selection.endLineNumber) {
selection.endColumn = selection.startColumn + content.length;
} else {
selection.endColumn = content.length - content.lastIndexOf('\r');
}
// Update other selection bound for direction.
if (selection.getDirection() == monaco.SelectionDirection.LTR) {
selection.positionColumn = selection.endColumn;
selection.positionLineNumber = selection.endLineNumber;
} else {
selection.selectionStartColumn = selection.endColumn;
selection.selectionStartLineNumber = selection.endLineNumber;
}
modifingSelection = false;
editor.setSelection(selection);
}
};
var updateDecorations = function (newHighlights) {
if (newHighlights) {
decorations = editor.deltaDecorations(decorations, newHighlights);
} else {
decorations = editor.deltaDecorations(decorations, []);
}
};
var updateStyle = function (innerStyle) {
var style = document.getElementById("dynamic");
style.innerHTML = innerStyle;
};
var getOptions = function () {
let opt = null;
try {
opt = JSON.parse(Parent.getJsonValue("Options"));
} finally {
}
if (opt != null && typeof opt === "object") {
return opt;
}
return {};
};
var updateOptions = function (opt) {
if (opt != null && typeof opt === "object") {
editor.updateOptions(opt);
}
};
var updateLanguage = function (language) {
monaco.editor.setModelLanguage(model, language);
};
var changeTheme = function (theme, highcontrast) {
var newTheme = 'vs';
if (highcontrast == "True" || highcontrast == "true") {
newTheme = 'hc-black';
} else if (theme == "Dark") {
newTheme = 'vs-dark';
}
monaco.editor.setTheme(newTheme);
};
var keyDown = function (event) {
//Debug.log("Key Down:" + event.keyCode + " " + event.ctrlKey);
var result = Keyboard.keyDown(event.keyCode, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
if (result) {
// TODO: Figure out which of these things actually works...
event.keyCode = 0;
event.cancelBubble = true;
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
return false;
}
};
</script>
</body>
</html>