UNPKG

pxt-core

Version:

Microsoft MakeCode provides Blocks / JavaScript / Python tools and editors

996 lines • 69.5 kB
var pxt; (function (pxt) { var editor; (function (editor) { let SimState; (function (SimState) { SimState[SimState["Stopped"] = 0] = "Stopped"; // waiting to be started SimState[SimState["Pending"] = 1] = "Pending"; SimState[SimState["Starting"] = 2] = "Starting"; SimState[SimState["Running"] = 3] = "Running"; })(SimState = editor.SimState || (editor.SimState = {})); function isBlocks(f) { return pxt.U.endsWith(f.name, ".blocks"); } editor.isBlocks = isBlocks; let ErrorListState; (function (ErrorListState) { ErrorListState["HeaderOnly"] = "errorListHeader"; ErrorListState["Expanded"] = "errorListExpanded"; })(ErrorListState = editor.ErrorListState || (editor.ErrorListState = {})); let FilterState; (function (FilterState) { FilterState[FilterState["Hidden"] = 0] = "Hidden"; FilterState[FilterState["Visible"] = 1] = "Visible"; FilterState[FilterState["Disabled"] = 2] = "Disabled"; })(FilterState = editor.FilterState || (editor.FilterState = {})); editor.initExtensionsAsync = opts => Promise.resolve({}); editor.initFieldExtensionsAsync = opts => Promise.resolve({}); editor.HELP_IMAGE_URI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjYiIGhlaWdodD0iMjYiIHZpZXdCb3g9IjAgMCAyNiAyNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iMTMiIGN5PSIxMyIgcj0iMTMiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik0xNy45NTIgOS4xODQwMkMxNy45NTIgMTAuMjU2IDE3LjgxNiAxMS4wNzIgMTcuNTQ0IDExLjYzMkMxNy4yODggMTIuMTkyIDE2Ljc1MiAxMi43OTIgMTUuOTM2IDEzLjQzMkMxNS4xMiAxNC4wNzIgMTQuNTc2IDE0LjU4NCAxNC4zMDQgMTQuOTY4QzE0LjA0OCAxNS4zMzYgMTMuOTIgMTUuNzM2IDEzLjkyIDE2LjE2OFYxNi45NkgxMS44MDhDMTEuNDI0IDE2LjQ2NCAxMS4yMzIgMTUuODQgMTEuMjMyIDE1LjA4OEMxMS4yMzIgMTQuNjg4IDExLjM4NCAxNC4yODggMTEuNjg4IDEzLjg4OEMxMS45OTIgMTMuNDg4IDEyLjUzNiAxMi45NjggMTMuMzIgMTIuMzI4QzE0LjEwNCAxMS42NzIgMTQuNjI0IDExLjE2OCAxNC44OCAxMC44MTZDMTUuMTM2IDEwLjQ0OCAxNS4yNjQgOS45NjgwMiAxNS4yNjQgOS4zNzYwMkMxNS4yNjQgOC4yMDgwMiAxNC40MTYgNy42MjQwMiAxMi43MiA3LjYyNDAyQzExLjc2IDcuNjI0MDIgMTAuNzUyIDcuNzM2MDIgOS42OTYgNy45NjAwMkw5LjE0NCA4LjA4MDAyTDkgNi4wODgwMkMxMC40ODggNS41NjAwMiAxMS44NCA1LjI5NjAyIDEzLjA1NiA1LjI5NjAyQzE0LjczNiA1LjI5NjAyIDE1Ljk2OCA1LjYwODAyIDE2Ljc1MiA2LjIzMjAyQzE3LjU1MiA2Ljg0MDAyIDE3Ljk1MiA3LjgyNDAyIDE3Ljk1MiA5LjE4NDAyWk0xMS40IDIyVjE4LjY0SDE0LjE4NFYyMkgxMS40WiIgZmlsbD0iIzU5NUU3NCIvPgo8L3N2Zz4K'; let _initEditorExtensionsPromise; function initEditorExtensionsAsync() { if (!_initEditorExtensionsPromise) { _initEditorExtensionsPromise = Promise.resolve(); if (pxt.appTarget && pxt.appTarget.appTheme && pxt.appTarget.appTheme.extendFieldEditors) { const opts = {}; _initEditorExtensionsPromise = _initEditorExtensionsPromise .then(() => pxt.BrowserUtils.loadBlocklyAsync()) .then(() => pxt.BrowserUtils.loadScriptAsync("fieldeditors.js")) .then(() => pxt.editor.initFieldExtensionsAsync(opts)) .then(res => { if (res.fieldEditors) res.fieldEditors.forEach(fi => { pxt.blocks.registerFieldEditor(fi.selector, fi.editor, fi.validator); }); }); } } return _initEditorExtensionsPromise; } editor.initEditorExtensionsAsync = initEditorExtensionsAsync; })(editor = pxt.editor || (pxt.editor = {})); })(pxt || (pxt = {})); var pxt; (function (pxt) { var editor; (function (editor_1) { const pendingRequests = {}; /** * Binds incoming window messages to the project view. * Requires the "allowParentController" flag in the pxtarget.json/appTheme object. * * When the project view receives a request (EditorMessageRequest), * it starts the command and returns the result upon completion. * The response (EditorMessageResponse) contains the request id and result. * Some commands may be async, use the ``id`` field to correlate to the original request. */ function bindEditorMessages(getEditorAsync) { const allowEditorMessages = (pxt.appTarget.appTheme.allowParentController || pxt.shell.isControllerMode()) && pxt.BrowserUtils.isIFrame(); const allowExtensionMessages = pxt.appTarget.appTheme.allowPackageExtensions; const allowSimTelemetry = pxt.appTarget.appTheme.allowSimulatorTelemetry; if (!allowEditorMessages && !allowExtensionMessages && !allowSimTelemetry) return; window.addEventListener("message", (msg) => { const data = msg.data; if (!data || !/^pxt(host|editor|pkgext|sim)$/.test(data.type)) return false; if (data.type === "pxtpkgext" && allowExtensionMessages) { // Messages sent to the editor iframe from a child iframe containing an extension getEditorAsync().then(projectView => { projectView.handleExtensionRequest(data); }); } else if (data.type === "pxtsim" && allowSimTelemetry) { const event = data; if (event.action === "event") { if (event.category || event.message) { pxt.reportError(event.category, event.message, event.data); } else { pxt.tickEvent(event.tick, event.data); } } } else if (allowEditorMessages) { // Messages sent to the editor from the parent frame let p = Promise.resolve(); let resp = undefined; if (data.type == "pxthost") { // response from the host const req = pendingRequests[data.id]; if (!req) { pxt.debug(`pxthost: unknown request ${data.id}`); } else { p = p.then(() => req.resolve(data)); } } else if (data.type == "pxteditor") { // request from the editor p = p.then(() => { return getEditorAsync().then(projectView => { const req = data; pxt.debug(`pxteditor: ${req.action}`); switch (req.action.toLowerCase()) { case "switchjavascript": return Promise.resolve().then(() => projectView.openJavaScript()); case "switchpython": return Promise.resolve().then(() => projectView.openPython()); case "switchblocks": return Promise.resolve().then(() => projectView.openBlocks()); case "startsimulator": return Promise.resolve().then(() => projectView.startSimulator()); case "restartsimulator": return Promise.resolve().then(() => projectView.restartSimulator()); case "hidesimulator": return Promise.resolve().then(() => projectView.collapseSimulator()); case "showsimulator": return Promise.resolve().then(() => projectView.expandSimulator()); case "closeflyout": return Promise.resolve().then(() => projectView.closeFlyout()); case "unloadproject": return Promise.resolve().then(() => projectView.unloadProjectAsync()); case "saveproject": return projectView.saveProjectAsync(); case "redo": return Promise.resolve() .then(() => { const editor = projectView.editor; if (editor && editor.hasRedo()) editor.redo(); }); case "undo": return Promise.resolve() .then(() => { const editor = projectView.editor; if (editor && editor.hasUndo()) editor.undo(); }); case "setscale": { const zoommsg = data; return Promise.resolve() .then(() => projectView.editor.setScale(zoommsg.scale)); } case "stopsimulator": { const stop = data; return Promise.resolve() .then(() => projectView.stopSimulator(stop.unload)); } case "newproject": { const create = data; return Promise.resolve() .then(() => projectView.newProject(create.options)); } case "importproject": { const load = data; return Promise.resolve() .then(() => projectView.importProjectAsync(load.project, { filters: load.filters, searchBar: load.searchBar })); } case "openheader": { const open = data; return projectView.openProjectByHeaderIdAsync(open.headerId); } case "startactivity": { const msg = data; let tutorialPath = msg.path; let editorProjectName = undefined; if (/^([jt]s|py|blocks?):/i.test(tutorialPath)) { if (/^py:/i.test(tutorialPath)) editorProjectName = pxt.PYTHON_PROJECT_NAME; else if (/^[jt]s:/i.test(tutorialPath)) editorProjectName = pxt.JAVASCRIPT_PROJECT_NAME; else editorProjectName = pxt.BLOCKS_PROJECT_NAME; tutorialPath = tutorialPath.substr(tutorialPath.indexOf(':') + 1); } return Promise.resolve() .then(() => projectView.startActivity({ activity: msg.activityType, path: tutorialPath, title: msg.title, editor: editorProjectName, previousProjectHeaderId: msg.previousProjectHeaderId, carryoverPreviousCode: msg.carryoverPreviousCode })); } case "importtutorial": { const load = data; return Promise.resolve() .then(() => projectView.importTutorialAsync(load.markdown)); } case "proxytosim": { const simmsg = data; return Promise.resolve() .then(() => projectView.proxySimulatorMessage(simmsg.content)); } case "renderblocks": { const rendermsg = data; return Promise.resolve() .then(() => projectView.renderBlocksAsync(rendermsg)) .then(r => { return r.xml.then((svg) => { resp = svg.xml; }); }); } case "renderpython": { const rendermsg = data; return Promise.resolve() .then(() => projectView.renderPythonAsync(rendermsg)) .then(r => { resp = r.python; }); } case "toggletrace": { const togglemsg = data; return Promise.resolve() .then(() => projectView.toggleTrace(togglemsg.intervalSpeed)); } case "settracestate": { const trcmsg = data; return Promise.resolve() .then(() => projectView.setTrace(trcmsg.enabled, trcmsg.intervalSpeed)); } case "setsimulatorfullscreen": { const fsmsg = data; return Promise.resolve() .then(() => projectView.setSimulatorFullScreen(fsmsg.enabled)); } case "togglehighcontrast": { return Promise.resolve() .then(() => projectView.toggleHighContrast()); } case "sethighcontrast": { const hcmsg = data; return Promise.resolve() .then(() => projectView.setHighContrast(hcmsg.on)); } case "togglegreenscreen": { return Promise.resolve() .then(() => projectView.toggleGreenScreen()); } case "print": { return Promise.resolve() .then(() => projectView.printCode()); } case "pair": { return projectView.pairAsync(); } case "info": { return Promise.resolve() .then(() => { resp = { versions: pxt.appTarget.versions, locale: ts.pxtc.Util.userLanguage(), availableLocales: pxt.appTarget.appTheme.availableLocales }; }); } case "shareproject": { const msg = data; return projectView.anonymousPublishHeaderByIdAsync(msg.headerId, msg.projectName) .then(scriptInfo => { resp = scriptInfo; }); } case "savelocalprojectstocloud": { const msg = data; return projectView.saveLocalProjectsToCloudAsync(msg.headerIds) .then(guidMap => { resp = { headerIdMap: guidMap }; }); } case "requestprojectcloudstatus": { // Responses are sent as separate "projectcloudstatus" messages. const msg = data; return projectView.requestProjectCloudStatus(msg.headerIds); } case "convertcloudprojectstolocal": { const msg = data; return projectView.convertCloudProjectsToLocal(msg.userId); } case "setlanguagerestriction": { const msg = data; if (msg.restriction === "no-blocks") { console.warn("no-blocks language restriction is not supported"); throw new Error("no-blocks language restriction is not supported"); } return projectView.setLanguageRestrictionAsync(msg.restriction); } } return Promise.resolve(); }); }); } p.then(() => sendResponse(data, resp, true, undefined), (err) => sendResponse(data, resp, false, err)); } return true; }, false); } editor_1.bindEditorMessages = bindEditorMessages; /** * Sends analytics messages upstream to container if any */ function enableControllerAnalytics() { if (!pxt.appTarget.appTheme.allowParentController || !pxt.BrowserUtils.isIFrame()) return; const te = pxt.tickEvent; pxt.tickEvent = function (id, data) { if (te) te(id, data); postHostMessageAsync({ type: 'pxthost', action: 'event', tick: id, response: false, data }); }; const rexp = pxt.reportException; pxt.reportException = function (err, data) { if (rexp) rexp(err, data); try { postHostMessageAsync({ type: 'pxthost', action: 'event', tick: 'error', message: err.message, response: false, data }); } catch (e) { } }; const re = pxt.reportError; pxt.reportError = function (cat, msg, data) { if (re) re(cat, msg, data); postHostMessageAsync({ type: 'pxthost', action: 'event', tick: 'error', category: cat, message: msg, data }); }; } editor_1.enableControllerAnalytics = enableControllerAnalytics; function sendResponse(request, resp, success, error) { if (request.response) { window.parent.postMessage({ type: request.type, id: request.id, resp, success, error }, "*"); } } /** * Determines if host messages should be posted */ function shouldPostHostMessages() { return pxt.appTarget.appTheme.allowParentController && pxt.BrowserUtils.isIFrame(); } editor_1.shouldPostHostMessages = shouldPostHostMessages; /** * Posts a message from the editor to the host */ function postHostMessageAsync(msg) { return new Promise((resolve, reject) => { const env = pxt.Util.clone(msg); env.id = ts.pxtc.Util.guidGen(); if (msg.response) pendingRequests[env.id] = { resolve, reject }; window.parent.postMessage(env, "*"); if (!msg.response) resolve(undefined); }); } editor_1.postHostMessageAsync = postHostMessageAsync; })(editor = pxt.editor || (pxt.editor = {})); })(pxt || (pxt = {})); var pxt; (function (pxt) { var editor; (function (editor) { var experiments; (function (experiments_1) { function key(experiment) { const id = (typeof experiment === "object") ? experiment.id : experiment; return `experiments-${id}`; } function syncTheme() { const theme = pxt.savedAppTheme(); const r = {}; const experiments = all(); experiments.forEach(experiment => { const enabled = isEnabled(experiment); theme[experiment.id] = !!enabled; if (enabled) r[experiment.id] = enabled ? 1 : 0; }); if (experiments.length && Object.keys(r).length) { pxt.tickEvent("experiments.loaded", r); pxt.reloadAppTargetVariant(); } return pxt.appTarget.appTheme; } experiments_1.syncTheme = syncTheme; function all() { const ids = pxt.appTarget.appTheme.experiments; if (!ids) return []; return [ { id: "print", name: lf("Print Code"), description: lf("Print the code from the current project"), feedbackUrl: "https://github.com/microsoft/pxt/issues/4740" }, { id: "greenScreen", name: lf("Green screen"), description: lf("Display a webcam video stream or a green background behind the code."), feedbackUrl: "https://github.com/microsoft/pxt/issues/4738" }, { id: "allowPackageExtensions", name: lf("Editor Extensions"), description: lf("Allow Extensions to add buttons in the editor."), feedbackUrl: "https://github.com/microsoft/pxt/issues/4741" }, { id: "instructions", name: lf("Wiring Instructions"), description: lf("Generate step-by-step assembly instructions for breadboard wiring."), feedbackUrl: "https://github.com/microsoft/pxt/issues/4739" }, { id: "debugger", name: lf("Debugger"), description: lf("Step through code and inspect variables in the debugger"), feedbackUrl: "https://github.com/microsoft/pxt/issues/4729" }, { id: "bluetoothUartConsole", name: "Bluetooth Console", description: lf("Receives UART message through Web Bluetooth"), feedbackUrl: "https://github.com/microsoft/pxt/issues/4796" }, { id: "bluetoothPartialFlashing", name: "Bluetooth Download", description: lf("Download code via Web Bluetooth"), feedbackUrl: "https://github.com/microsoft/pxt/issues/4807" }, { id: "simScreenshot", name: lf("Simulator Screenshots"), description: lf("Download screenshots of the simulator"), feedbackUrl: "https://github.com/microsoft/pxt/issues/5232" }, { id: "python", name: lf("Static Python"), description: lf("Use Static Python to code your device"), feedbackUrl: "https://github.com/microsoft/pxt/issues/5390" }, { id: "simGif", name: lf("Simulator Gifs"), description: lf("Download gifs of the simulator"), feedbackUrl: "https://github.com/microsoft/pxt/issues/5297" }, { id: "qrCode", name: lf("Shared QR Code"), description: lf("Generate a QR Code form the shared project url"), feedbackUrl: "https://github.com/microsoft/pxt/issues/5456" }, { id: "importExtensionFiles", name: lf("Import Extension Files"), description: lf("Import Extensions from compiled project files") }, { id: "debugExtensionCode", name: lf("Debug Extension Code"), description: lf("Use the JavaScript debugger to debug extension code") }, { id: "snippetBuilder", name: lf("Snippet Builder"), description: lf("Try out the new snippet dialogs.") }, { id: "experimentalHw", name: lf("Experimental Hardware"), description: lf("Enable support for hardware marked 'experimental' in the hardware seletion dialog") }, { id: "checkForHwVariantWebUSB", name: lf("Detect Hardware with WebUSB"), description: lf("When compiling, use WebUSB to detect hardware configuration.") }, { id: "githubEditor", name: lf("GitHub editor"), description: lf("Review, commit and push to GitHub."), feedbackUrl: "https://github.com/microsoft/pxt/issues/6419", enableOnline: true, }, { id: "githubCompiledJs", name: lf("GitHub Pages JavaScript"), description: lf("Commit compiled javascript when creating a release"), enableOnline: true, }, { id: "blocksCollapsing", name: lf("Collapse blocks"), description: lf("Collapse and expand functions or event blocks") }, { id: "tutorialBlocksDiff", name: lf("Tutorial Block Diffs"), description: lf("Automatially render blocks diff in tutorials") }, { id: "openProjectNewTab", name: lf("Open in New Tab"), description: lf("Open an editor in a new tab.") }, { id: "openProjectNewDependentTab", name: lf("Open in New Connected Tab"), description: lf("Open connected editors in different browser tabs.") }, { id: "accessibleBlocks", name: lf("Accessible Blocks"), description: lf("Use the WASD keys to move and modify blocks."), feedbackUrl: "https://github.com/microsoft/pxt/issues/6850" }, { id: "errorList", name: lf("Error List"), description: lf("Show an error list panel for JavaScript and Python.") }, { id: "blocksErrorList", name: lf("Blocks Error List"), description: lf("Show an error list panel for Blocks") }, ].filter(experiment => ids.indexOf(experiment.id) > -1 && !(pxt.BrowserUtils.isPxtElectron() && experiment.enableOnline)); } experiments_1.all = all; function clear() { all().forEach(experiment => pxt.storage.removeLocal(key(experiment))); syncTheme(); } experiments_1.clear = clear; function someEnabled() { return all().some(experiment => isEnabled(experiment)); } experiments_1.someEnabled = someEnabled; function isEnabled(experiment) { return !!pxt.storage.getLocal(key(experiment)); } experiments_1.isEnabled = isEnabled; function toggle(experiment) { setState(experiment, !isEnabled(experiment)); } experiments_1.toggle = toggle; function state() { const r = {}; all().forEach(experiment => r[experiment.id] = isEnabled(experiment)); return JSON.stringify(r); } experiments_1.state = state; function setState(experiment, enabled) { if (enabled == isEnabled(experiment)) return; // no changes if (enabled) pxt.storage.setLocal(key(experiment), "1"); else pxt.storage.removeLocal(key(experiment)); // sync theme syncTheme(); } experiments_1.setState = setState; })(experiments = editor.experiments || (editor.experiments = {})); })(editor = pxt.editor || (pxt.editor = {})); })(pxt || (pxt = {})); /// <reference path="../localtypings/monaco.d.ts" /> /// <reference path="../built/pxtlib.d.ts"/> /// <reference path="../built/pxtblocks.d.ts"/> var pxt; (function (pxt) { var vs; (function (vs) { function syncModels(mainPkg, libs, currFile, readOnly) { if (readOnly) return; let extraLibs = monaco.languages.typescript.typescriptDefaults.getExtraLibs(); let modelMap = {}; mainPkg.sortedDeps().forEach(pkg => { pkg.getFiles().forEach(f => { let fp = pkg.id + "/" + f; let proto = "pkg:" + fp; if (/\.(ts)$/.test(f) && fp != currFile) { if (!monaco.languages.typescript.typescriptDefaults.getExtraLibs()[fp]) { // inserting a space creates syntax errors in Python let content = pkg.readFile(f) || "\n"; libs[fp] = monaco.languages.typescript.typescriptDefaults.addExtraLib(content, fp); } modelMap[fp] = "1"; } }); }); // dispose of any extra libraries, the typescript worker will be killed as a result of this Object.keys(extraLibs) .filter(lib => /\.(ts)$/.test(lib) && !modelMap[lib]) .forEach(lib => { libs[lib].dispose(); }); } vs.syncModels = syncModels; function initMonacoAsync(element) { return new Promise((resolve, reject) => { if (typeof (window.monaco) === 'object') { // monaco is already loaded resolve(createEditor(element)); return; } let monacoPaths = window.MonacoPaths; let onGotAmdLoader = () => { let req = window.require; req.config({ paths: monacoPaths }); // Load monaco req(['vs/editor/editor.main'], () => { setupMonaco(); resolve(createEditor(element)); }); }; // Load AMD loader if necessary if (!window.require) { let loaderScript = document.createElement('script'); loaderScript.type = 'text/javascript'; loaderScript.src = monacoPaths['vs/loader']; loaderScript.addEventListener('load', onGotAmdLoader); document.body.appendChild(loaderScript); } else { onGotAmdLoader(); } }); } vs.initMonacoAsync = initMonacoAsync; function setupMonaco() { initAsmMonarchLanguage(); initTypeScriptLanguageDefinition(); } function createEditor(element) { const inverted = pxt.appTarget.appTheme.invertedMonaco; const hasFieldEditors = !!(pxt.appTarget.appTheme.monacoFieldEditors && pxt.appTarget.appTheme.monacoFieldEditors.length); const isAndroid = pxt.BrowserUtils.isAndroid(); let editor = monaco.editor.create(element, { model: null, ariaLabel: pxt.Util.lf("JavaScript editor"), fontFamily: "'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'monospace'", scrollBeyondLastLine: true, language: "typescript", mouseWheelZoom: false, wordBasedSuggestions: true, lineNumbersMinChars: 3, formatOnPaste: true, folding: hasFieldEditors, glyphMargin: hasFieldEditors || pxt.appTarget.appTheme.debugger, minimap: { enabled: false }, fixedOverflowWidgets: true, autoIndent: "full", useTabStops: true, dragAndDrop: true, matchBrackets: "always", occurrencesHighlight: false, quickSuggestionsDelay: 200, theme: inverted ? 'vs-dark' : 'vs', renderIndentGuides: true, accessibilityHelpUrl: "", // disable completions on android quickSuggestions: { "other": !isAndroid, "comments": !isAndroid, "strings": !isAndroid }, acceptSuggestionOnCommitCharacter: !isAndroid, acceptSuggestionOnEnter: !isAndroid ? "on" : "off", accessibilitySupport: !isAndroid ? "on" : "off" }); editor.layout(); return editor; } vs.createEditor = createEditor; function initAsmMonarchLanguage() { monaco.languages.register({ id: 'asm', extensions: ['.asm'] }); monaco.languages.setMonarchTokensProvider('asm', { // Set defaultToken to invalid to see what you do not tokenize yet // defaultToken: 'invalid', tokenPostfix: '', //Extracted from http://infocenter.arm.com/help/topic/com.arm.doc.qrc0006e/QRC0006_UAL16.pdf //Should be a superset of the instructions emitted keywords: [ 'movs', 'mov', 'adds', 'add', 'adcs', 'adr', 'subs', 'sbcs', 'sub', 'rsbs', 'muls', 'cmp', 'cmn', 'ands', 'eors', 'orrs', 'bics', 'mvns', 'tst', 'lsls', 'lsrs', 'asrs', 'rors', 'ldr', 'ldrh', 'ldrb', 'ldrsh', 'ldrsb', 'ldm', 'str', 'strh', 'strb', 'stm', 'push', 'pop', 'cbz', 'cbnz', 'b', 'bl', 'bx', 'blx', 'sxth', 'sxtb', 'uxth', 'uxtb', 'rev', 'rev16', 'revsh', 'svc', 'cpsid', 'cpsie', 'setend', 'bkpt', 'nop', 'sev', 'wfe', 'wfi', 'yield', 'beq', 'bne', 'bcs', 'bhs', 'bcc', 'blo', 'bmi', 'bpl', 'bvs', 'bvc', 'bhi', 'bls', 'bge', 'blt', 'bgt', 'ble', 'bal', //Registers 'r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15', 'pc', 'sp', 'lr' ], typeKeywords: [ '.startaddr', '.hex', '.short', '.space', '.section', '.string', '.byte' ], operators: [], // Not all of these are valid in ARM Assembly symbols: /[:\*]+/, // C# style strings escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/, // The main tokenizer for our languages tokenizer: { root: [ // identifiers and keywords [/(\.)?[a-z_$\.][\w$]*/, { cases: { '@typeKeywords': 'keyword', '@keywords': 'keyword', '@default': 'identifier' } }], // whitespace { include: '@whitespace' }, // delimiters and operators [/[{}()\[\]]/, '@brackets'], [/[<>](?!@symbols)/, '@brackets'], [/@symbols/, { cases: { '@operators': 'operator', '@default': '' } }], // @ annotations. [/@\s*[a-zA-Z_\$][\w\$]*/, { token: 'annotation' }], // numbers //[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'], [/(#|(0[xX]))?[0-9a-fA-F]+/, 'number'], // delimiter: after number because of .\d floats [/[;,.]/, 'delimiter'], // strings [/"([^"\\]|\\.)*$/, 'string.invalid'], [/"/, { token: 'string.quote', bracket: '@open', next: '@string' }], // characters [/'[^\\']'/, 'string'], [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], [/'/, 'string.invalid'] ], comment: [], string: [ [/[^\\"]+/, 'string'], [/@escapes/, 'string.escape'], [/\\./, 'string.escape.invalid'], [/"/, { token: 'string.quote', bracket: '@close', next: '@pop' }] ], whitespace: [ [/[ \t\r\n]+/, 'white'], [/\/\*/, 'comment', '@comment'], [/;.*$/, 'comment'], ], } }); } function initTypeScriptLanguageDefinition() { if (!monaco.languages.typescript) { return; } // validation settings monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({ noSyntaxValidation: true, noSemanticValidation: true }); // Register our worker monaco.languages.typescript.typescriptDefaults.setWorkerOptions({ customWorkerPath: pxt.webConfig.typeScriptWorkerJs }); // compiler options monaco.languages.typescript.typescriptDefaults.setCompilerOptions({ allowUnreachableCode: true, noImplicitAny: true, allowJs: false, allowUnusedLabels: true, target: monaco.languages.typescript.ScriptTarget.ES5, outDir: "built", rootDir: ".", noLib: true, mouseWheelZoom: false }); } })(vs = pxt.vs || (pxt.vs = {})); })(pxt || (pxt = {})); /// <reference path="../built/pxtlib.d.ts"/> var pxt; (function (pxt) { var workspace; (function (workspace) { function freshHeader(name, modTime) { let header = { target: pxt.appTarget.id, targetVersion: pxt.appTarget.versions.target, name: name, meta: {}, editor: pxt.JAVASCRIPT_PROJECT_NAME, pubId: "", pubCurrent: false, _rev: null, id: pxt.U.guidGen(), recentUse: modTime, modificationTime: modTime, cloudUserId: null, cloudCurrent: false, cloudVersion: null, cloudLastSyncTime: 0, isDeleted: false, }; return header; } workspace.freshHeader = freshHeader; })(workspace = pxt.workspace || (pxt.workspace = {})); })(pxt || (pxt = {})); /// <reference path="../../localtypings/monaco.d.ts" /> var pxt; (function (pxt) { var editor; (function (editor) { const definitions = {}; function registerMonacoFieldEditor(name, definition) { definitions[name] = definition; } editor.registerMonacoFieldEditor = registerMonacoFieldEditor; function getMonacoFieldEditor(name) { return definitions[name]; } editor.getMonacoFieldEditor = getMonacoFieldEditor; })(editor = pxt.editor || (pxt.editor = {})); })(pxt || (pxt = {})); /// <reference path="./monacoFieldEditor.ts" /> var pxt; (function (pxt) { var editor; (function (editor) { const fieldEditorId = "image-editor"; class MonacoReactFieldEditor { getId() { return fieldEditorId; } showEditorAsync(fileType, editrange, host) { this.fileType = fileType; this.editrange = editrange; this.host = host; return this.initAsync().then(() => { const value = this.textToValue(host.getText(editrange)); if (!value) { return Promise.resolve(null); } this.fv = pxt.react.getFieldEditorView(this.getFieldEditorId(), value, this.getOptions()); this.fv.onHide(() => { this.onClosed(); }); this.fv.show(); return new Promise((resolve, reject) => { this.resolver = resolve; this.rejecter = reject; }); }); } onClosed() { if (this.resolver) { this.resolver({ range: this.editrange, replacement: this.resultToText(this.fv.getResult()) }); this.editrange = undefined; this.resolver = undefined; this.rejecter = undefined; } } dispose() { this.onClosed(); } initAsync() { return Promise.resolve(); } textToValue(text) { return null; } resultToText(result) { return result + ""; } getFieldEditorId() { return ""; } getOptions() { return null; } } editor.MonacoReactFieldEditor = MonacoReactFieldEditor; })(editor = pxt.editor || (pxt.editor = {})); })(pxt || (pxt = {})); /// <reference path="./monacoFieldEditor.ts" /> /// <reference path="./field_react.ts" /> var pxt; (function (pxt) { var editor; (function (editor) { const fieldEditorId = "music-editor"; class MonacoSongEditor extends editor.MonacoReactFieldEditor { textToValue(text) { this.isPython = text.indexOf("`") === -1; this.text = text; const match = pxt.parseAssetTSReference(text); if (match) { const { type, name: matchedName } = match; const name = matchedName.trim(); const project = pxt.react.getTilemapProject(); this.isAsset = true; const asset = project.lookupAssetByName("song" /* pxt.AssetType.Song */, name); if (asset) { return asset; } else { const newAsset = project.createNewSong(pxt.assets.music.getEmptySong(2)); if (name && !project.isNameTaken("song" /* pxt.AssetType.Song */, name) && pxt.validateAssetName(name)) { newAsset.meta.displayName = name; } return newAsset; } } const hexLiteralMatch = /hex\s*(?:`|\(""")\s*([a-fA-F0-9]*)\s*(?:`|"""\))\s*(?:;?)/m.exec(text); if (hexLiteralMatch) { const contents = hexLiteralMatch[1].trim(); if (contents) { return createFakeAsset(pxt.assets.music.decodeSongFromHex(contents)); } return createFakeAsset(pxt.assets.music.getEmptySong(2)); } return undefined; // never } resultToText(result) { var _a; if ((_a = result.meta) === null || _a === void 0 ? void 0 : _a.displayName) { const project = pxt.react.getTilemapProject(); if (this.isAsset || project.lookupAsset(result.type, result.id)) { result = project.updateAsset(result); } else { result = project.createNewSong(result.song, result.meta.displayName); } this.isAsset = true; return pxt.getTSReferenceForAsset(result, this.isPython); } let hexString = pxt.assets.music.encodeSongToHex(result.song); if (this.isPython) { hexString = `hex("""${hexString}""")`; } else { hexString = "hex`" + hexString + "`"; } return this.text.replace(/hex\s*(?:`|\(""")\s*([a-fA-F0-9]*)\s*(?:`|"""\))\s*(?:;?)/m, hexString); } getFieldEditorId() { return fieldEditorId; } getOptions() { return { bloc