From 024d0c450625970ed506207205e78327cacf6b1e Mon Sep 17 00:00:00 2001 From: ocogeclub Date: Tue, 20 Dec 2022 23:16:28 +0900 Subject: [PATCH] =?UTF-8?q?[update]=20Blockly=20=E3=82=92=20npm=20?= =?UTF-8?q?=E3=81=A7=E3=82=A4=E3=83=B3=E3=82=B9=E3=83=88=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- {google-blockly => blocks}/custom-dialog.js | 0 blocks/sensors/amg8833/index.js | 27 +- google-blockly/blockly_compressed.js | 1540 -------- google-blockly/blockly_compressed.js.map | 1 - google-blockly/blocks_compressed.js | 230 -- google-blockly/blocks_compressed.js.map | 1 - google-blockly/gulpfile.js | 53 - google-blockly/javascript_compressed.js | 331 -- google-blockly/javascript_compressed.js.map | 1 - google-blockly/jsconfig.json | 12 - google-blockly/media/1x1.gif | Bin 43 -> 0 bytes google-blockly/media/click.mp3 | Bin 2304 -> 0 bytes google-blockly/media/click.ogg | Bin 4865 -> 0 bytes google-blockly/media/click.wav | Bin 3782 -> 0 bytes google-blockly/media/delete.mp3 | Bin 3123 -> 0 bytes google-blockly/media/delete.ogg | Bin 5731 -> 0 bytes google-blockly/media/delete.wav | Bin 9164 -> 0 bytes google-blockly/media/disconnect.mp3 | Bin 1586 -> 0 bytes google-blockly/media/disconnect.ogg | Bin 4404 -> 0 bytes google-blockly/media/disconnect.wav | Bin 1492 -> 0 bytes google-blockly/media/dropdown-arrow.svg | 1 - google-blockly/media/handclosed.cur | Bin 326 -> 0 bytes google-blockly/media/handdelete.cur | Bin 766 -> 0 bytes google-blockly/media/handopen.cur | Bin 198 -> 0 bytes google-blockly/media/pilcrow.png | Bin 1010 -> 0 bytes google-blockly/media/quote0.png | Bin 771 -> 0 bytes google-blockly/media/quote1.png | Bin 738 -> 0 bytes google-blockly/media/sprites.png | Bin 2595 -> 0 bytes google-blockly/media/sprites.svg | 74 - google-blockly/msg/js/en.js | 425 -- google-blockly/msg/js/ja.js | 425 -- google-blockly/msg/json/en.json | 397 -- google-blockly/msg/json/ja.json | 358 -- google-blockly/msg/messages.js | 1599 -------- google-blockly/python_compressed.js | 254 -- google-blockly/python_compressed.js.map | 1 - index.html | 24 +- index.js | 20 +- package-lock.json | 3889 ++++++++++++------- package.json | 15 +- ugj_blocks.js | 86 +- 41 files changed, 2558 insertions(+), 7206 deletions(-) rename {google-blockly => blocks}/custom-dialog.js (100%) delete mode 100644 google-blockly/blockly_compressed.js delete mode 100644 google-blockly/blockly_compressed.js.map delete mode 100644 google-blockly/blocks_compressed.js delete mode 100644 google-blockly/blocks_compressed.js.map delete mode 100644 google-blockly/gulpfile.js delete mode 100644 google-blockly/javascript_compressed.js delete mode 100644 google-blockly/javascript_compressed.js.map delete mode 100644 google-blockly/jsconfig.json delete mode 100644 google-blockly/media/1x1.gif delete mode 100644 google-blockly/media/click.mp3 delete mode 100644 google-blockly/media/click.ogg delete mode 100644 google-blockly/media/click.wav delete mode 100644 google-blockly/media/delete.mp3 delete mode 100644 google-blockly/media/delete.ogg delete mode 100644 google-blockly/media/delete.wav delete mode 100644 google-blockly/media/disconnect.mp3 delete mode 100644 google-blockly/media/disconnect.ogg delete mode 100644 google-blockly/media/disconnect.wav delete mode 100644 google-blockly/media/dropdown-arrow.svg delete mode 100644 google-blockly/media/handclosed.cur delete mode 100644 google-blockly/media/handdelete.cur delete mode 100644 google-blockly/media/handopen.cur delete mode 100644 google-blockly/media/pilcrow.png delete mode 100644 google-blockly/media/quote0.png delete mode 100644 google-blockly/media/quote1.png delete mode 100644 google-blockly/media/sprites.png delete mode 100644 google-blockly/media/sprites.svg delete mode 100644 google-blockly/msg/js/en.js delete mode 100644 google-blockly/msg/js/ja.js delete mode 100644 google-blockly/msg/json/en.json delete mode 100644 google-blockly/msg/json/ja.json delete mode 100644 google-blockly/msg/messages.js delete mode 100644 google-blockly/python_compressed.js delete mode 100644 google-blockly/python_compressed.js.map diff --git a/google-blockly/custom-dialog.js b/blocks/custom-dialog.js similarity index 100% rename from google-blockly/custom-dialog.js rename to blocks/custom-dialog.js diff --git a/blocks/sensors/amg8833/index.js b/blocks/sensors/amg8833/index.js index d4dcbaf..7e180e1 100644 --- a/blocks/sensors/amg8833/index.js +++ b/blocks/sensors/amg8833/index.js @@ -161,7 +161,7 @@ Blockly.JavaScript['ugj_grideye_canvas_create'] = function (block) { _grideye_canvas.style.height = '160px'; _grideye_canvas.id = 'subcanvas'; document.getElementById('display_area').appendChild(_grideye_canvas); - _grideye_ctx = _grideye_canvas.getContext('2d'); + _grideye_ctx = _grideye_canvas.getContext('2d', {willReadFrequently: true}); _grideye_imgData = _grideye_ctx.createImageData(8, 8); `; return code; @@ -275,11 +275,7 @@ Blockly.Blocks['ugj_teachable_machine'] = { }; Blockly.JavaScript['ugj_teachable_machine'] = function (block) { Blockly.JavaScript.provideFunction_( - 'require_ts', [`const _tf = require('@tensorflow/tfjs');`] - // 'require_ts', [`const _tf = require('@tensorflow/tfjs-node');`] - ); - Blockly.JavaScript.provideFunction_( - 'require_wasm', [`const _wasm = require('@tensorflow/tfjs-backend-wasm');`] + 'require_ts', [`const _tf = require('@tensorflow/tfjs-node');`] ); Blockly.JavaScript.provideFunction_( 'require_mobilenet', [`const _mobilenet = require('@tensorflow-models/mobilenet');`] @@ -288,8 +284,7 @@ Blockly.JavaScript['ugj_teachable_machine'] = function (block) { 'require_knn', [`const _knnClassifier = require('@tensorflow-models/knn-classifier');`] ); - var code = `await _tf.setBackend('wasm'); - const _net = await _mobilenet.load({ version: 1, alpha: 0.25 }); // 高速・低精度 + var code = ` const _net = await _mobilenet.load({ version: 1, alpha: 0.25 }); // 高速・低精度 const _classifier = _knnClassifier.create(); `; return code; @@ -376,10 +371,7 @@ Blockly.Blocks['ugj_tensorset_stringify'] = { } }; Blockly.JavaScript['ugj_tensorset_stringify'] = function (block) { - Blockly.JavaScript.provideFunction_( - 'require_tensorset', [`const _Tensorset = require('tensorset');`] - ); - var code = `await _Tensorset.stringify(_classifier.getClassifierDataset())`; + var code = `JSON.stringify( Object.entries(_classifier.getClassifierDataset()).map(([label, data])=>[label, Array.from(data.dataSync()), data.shape]) )`; return [code, Blockly.JavaScript.ORDER_NONE]; }; /***************************************** */ @@ -407,17 +399,8 @@ Blockly.Blocks['ugj_tensorset_parse'] = { } }; Blockly.JavaScript['ugj_tensorset_parse'] = function (block) { - Blockly.JavaScript.provideFunction_( - 'require_tensorset', [`const _Tensorset = require('tensorset');`] - ); var value_class_data_json = Blockly.JavaScript.valueToCode(block, 'class_data_json', Blockly.JavaScript.ORDER_ATOMIC); - var code = `try { - let _class_dataset = _Tensorset.parse(${value_class_data_json}); - _classifier.setClassifierDataset(_class_dataset); - } catch (error) { - alert('Could not load class dataset.'); - } - `; + var code = `_classifier.setClassifierDataset( Object.fromEntries( JSON.parse(${value_class_data_json}).map(([label, data, shape])=>[label, _tf.tensor(data, shape)]) ) );`; return code; }; diff --git a/google-blockly/blockly_compressed.js b/google-blockly/blockly_compressed.js deleted file mode 100644 index df8abc6..0000000 --- a/google-blockly/blockly_compressed.js +++ /dev/null @@ -1,1540 +0,0 @@ -// Do not edit this file; automatically generated. - -/* eslint-disable */ -;(function(root, factory) { - if (typeof define === 'function' && define.amd) { // AMD - define([], factory); - } else if (typeof exports === 'object') { // Node.js - module.exports = factory(); - } else { // Browser - var factoryExports = factory(); - root.Blockly = factoryExports; - } -}(this, function() { -var $={}; -var longStart$$module$build$src$core$touch=function(a,b){longStop$$module$build$src$core$touch();a.changedTouches&&1!==a.changedTouches.length||(longPid_$$module$build$src$core$touch=setTimeout(function(){a.changedTouches&&(a.button=2,a.clientX=a.changedTouches[0].clientX,a.clientY=a.changedTouches[0].clientY);b&&b.handleRightClick(a)},LONGPRESS$$module$build$src$core$touch))},longStop$$module$build$src$core$touch=function(){longPid_$$module$build$src$core$touch&&(clearTimeout(longPid_$$module$build$src$core$touch), -longPid_$$module$build$src$core$touch=0)},clearTouchIdentifier$$module$build$src$core$touch=function(){touchIdentifier_$$module$build$src$core$touch=null},shouldHandleEvent$$module$build$src$core$touch=function(a){return!isMouseOrTouchEvent$$module$build$src$core$touch(a)||checkTouchIdentifier$$module$build$src$core$touch(a)},getTouchIdentifierFromEvent$$module$build$src$core$touch=function(a){return a instanceof PointerEvent?String(a.pointerId):a instanceof MouseEvent?"mouse":a.changedTouches&&a.changedTouches[0]&& -void 0!==a.changedTouches[0].identifier&&null!==a.changedTouches[0].identifier?String(a.changedTouches[0].identifier):"mouse"},checkTouchIdentifier$$module$build$src$core$touch=function(a){const b=getTouchIdentifierFromEvent$$module$build$src$core$touch(a);return void 0!==touchIdentifier_$$module$build$src$core$touch&&null!==touchIdentifier_$$module$build$src$core$touch?touchIdentifier_$$module$build$src$core$touch===b:"mousedown"===a.type||"touchstart"===a.type||"pointerdown"===a.type?(touchIdentifier_$$module$build$src$core$touch= -b,!0):!1},setClientFromTouch$$module$build$src$core$touch=function(a){if(a.type.startsWith("touch")&&a.changedTouches){const b=a.changedTouches[0];a.clientX=b.clientX;a.clientY=b.clientY}},isMouseOrTouchEvent$$module$build$src$core$touch=function(a){return a.type.startsWith("touch")||a.type.startsWith("mouse")||a.type.startsWith("pointer")},isTouchEvent$$module$build$src$core$touch=function(a){return a.type.startsWith("touch")||a.type.startsWith("pointer")},splitEventByTouches$$module$build$src$core$touch= -function(a){const b=[];if(a.changedTouches)for(let c=0;c{g(n);const p=!f;h&&p&&n.preventDefault()},m=0;m{if(k instanceof -TouchEvent&&k.changedTouches&&1===k.changedTouches.length){const l=k.changedTouches[0];k.clientX=l.clientX;k.clientY=l.clientY}e(k);k.preventDefault()},h=0;ha.classList.contains(c)))return!1;a.classList.add(...b);return!0},removeClasses$$module$build$src$core$utils$dom=function(a,b){a.classList.remove(...b.split(" "))},removeClass$$module$build$src$core$utils$dom=function(a,b){b=b.split(" ");if(b.every(c=>!a.classList.contains(c)))return!1;a.classList.remove(...b);return!0},hasClass$$module$build$src$core$utils$dom= -function(a,b){return a.classList.contains(b)},removeNode$$module$build$src$core$utils$dom=function(a){return a&&a.parentNode?a.parentNode.removeChild(a):null},insertAfter$$module$build$src$core$utils$dom=function(a,b){const c=b.nextSibling;b=b.parentNode;if(!b)throw Error("Reference node has no parent.");c?b.insertBefore(a,c):b.appendChild(a)},containsNode$$module$build$src$core$utils$dom=function(a,b){return!!(a.compareDocumentPosition(b)&NodeType$$module$build$src$core$utils$dom.DOCUMENT_POSITION_CONTAINED_BY)}, -setCssTransform$$module$build$src$core$utils$dom=function(a,b){a.style.transform=b;a.style["-webkit-transform"]=b},startTextWidthCache$$module$build$src$core$utils$dom=function(){cacheReference$$module$build$src$core$utils$dom++;cacheWidths$$module$build$src$core$utils$dom||(cacheWidths$$module$build$src$core$utils$dom=Object.create(null))},stopTextWidthCache$$module$build$src$core$utils$dom=function(){cacheReference$$module$build$src$core$utils$dom--;cacheReference$$module$build$src$core$utils$dom|| -(cacheWidths$$module$build$src$core$utils$dom=null)},getTextWidth$$module$build$src$core$utils$dom=function(a){const b=a.textContent+"\n"+a.className.baseVal;let c;if(cacheWidths$$module$build$src$core$utils$dom&&(c=cacheWidths$$module$build$src$core$utils$dom[b]))return c;try{c=a.getComputedTextLength()}catch(d){return 8*a.textContent.length}cacheWidths$$module$build$src$core$utils$dom&&(cacheWidths$$module$build$src$core$utils$dom[b]=c);return c},getFastTextWidth$$module$build$src$core$utils$dom= -function(a,b,c,d){return getFastTextWidthWithSizeString$$module$build$src$core$utils$dom(a,b+"pt",c,d)},getFastTextWidthWithSizeString$$module$build$src$core$utils$dom=function(a,b,c,d){const e=a.textContent;a=e+"\n"+a.className.baseVal;var f;if(cacheWidths$$module$build$src$core$utils$dom&&(f=cacheWidths$$module$build$src$core$utils$dom[a]))return f;canvasContext$$module$build$src$core$utils$dom||(f=document.createElement("canvas"),f.className="blocklyComputeCanvas",document.body.appendChild(f), -canvasContext$$module$build$src$core$utils$dom=f.getContext("2d"));canvasContext$$module$build$src$core$utils$dom.font=c+" "+b+" "+d;f=e?canvasContext$$module$build$src$core$utils$dom.measureText(e).width:0;cacheWidths$$module$build$src$core$utils$dom&&(cacheWidths$$module$build$src$core$utils$dom[a]=f);return f},measureFontMetrics$$module$build$src$core$utils$dom=function(a,b,c,d){const e=document.createElement("span");e.style.font=c+" "+b+" "+d;e.textContent=a;a=document.createElement("div");a.style.width= -"1px";a.style.height="0";b=document.createElement("div");b.setAttribute("style","position: fixed; top: 0; left: 0; display: flex;");b.appendChild(e);b.appendChild(a);document.body.appendChild(b);c={height:0,baseline:0};try{b.style.alignItems="baseline",c.baseline=a.offsetTop-e.offsetTop,b.style.alignItems="flex-end",c.height=a.offsetTop-e.offsetTop}finally{document.body.removeChild(b)}return c},toRadians$$module$build$src$core$utils$math=function(a){return a*Math.PI/180},toDegrees$$module$build$src$core$utils$math= -function(a){return 180*a/Math.PI},clamp$$module$build$src$core$utils$math=function(a,b,c){if(c1'),d.appendChild(c),b.push(d));if(Blocks$$module$build$src$core$blocks.variables_get){a.sort(VariableModel$$module$build$src$core$variable_model.compareByName);for(let e=0,f;f=a[e];e++)c=createElement$$module$build$src$core$utils$xml("block"), -c.setAttribute("type","variables_get"),c.setAttribute("gap","8"),c.appendChild(generateVariableFieldDom$$module$build$src$core$variables(f)),b.push(c)}}return b},generateUniqueName$$module$build$src$core$variables=function(a){return TEST_ONLY$$module$build$src$core$variables.generateUniqueNameInternal(a)},generateUniqueNameInternal$$module$build$src$core$variables=function(a){return generateUniqueNameFromOptions$$module$build$src$core$variables(VAR_LETTER_OPTIONS$$module$build$src$core$variables.charAt(0), -a.getAllVariableNames())},generateUniqueNameFromOptions$$module$build$src$core$variables=function(a,b){if(!b.length)return a;const c=VAR_LETTER_OPTIONS$$module$build$src$core$variables;let d="",e=c.indexOf(a);for(;;){let f=!1;for(let g=0;g>>/g,a),content$$module$build$src$core$css="",a=document.createElement("style"),a.id="blockly-common-style",b=document.createTextNode(b),a.appendChild(b),document.head.insertBefore(a,document.head.firstChild)))},getRelativeXY$$module$build$src$core$utils$svg_math= -function(a){const b=new Coordinate$$module$build$src$core$utils$coordinate(0,0);var c=a.x&&a.getAttribute("x");const d=a.y&&a.getAttribute("y");c&&(b.x=parseInt(c));d&&(b.y=parseInt(d));if(c=(c=a.getAttribute("transform"))&&c.match(XY_REGEX$$module$build$src$core$utils$svg_math))b.x+=Number(c[1]),c[3]&&(b.y+=Number(c[3]));(a=a.getAttribute("style"))&&-1/g,"<$1$2>")},domToPrettyText$$module$build$src$core$xml=function(a){a=domToText$$module$build$src$core$xml(a).split("<");let b="";for(let c= -1;c"!==d.slice(-2)&&(b+=" ")}a=a.join("\n");a=a.replace(/(<(\w+)\b[^>]*>[^\n]*)\n *<\/\2>/g,"$1");return a.replace(/^\n/,"")},textToDom$$module$build$src$core$xml=function(a){const b=textToDomDocument$$module$build$src$core$utils$xml(a);if(!b||!b.documentElement||b.getElementsByTagName("parsererror").length)throw Error("textToDom was unable to parse: "+a);return b.documentElement},clearWorkspaceAndLoadFromXml$$module$build$src$core$xml= -function(a,b){b.setResizesEnabled(!1);b.clear();a=domToWorkspace$$module$build$src$core$xml(a,b);b.setResizesEnabled(!0);return a},domToWorkspace$$module$build$src$core$xml=function(a,b){let c=0;b.RTL&&(c=b.getWidth());const d=[];startTextWidthCache$$module$build$src$core$utils$dom();const e=getGroup$$module$build$src$core$events$utils();e||setGroup$$module$build$src$core$events$utils(!0);b.setResizesEnabled&&b.setResizesEnabled(!1);let f=!0;try{for(let g=0,h;h=a.childNodes[g];g++){const k=h.nodeName.toLowerCase(), -l=h;if("block"===k||"shadow"===k&&!getRecordUndo$$module$build$src$core$events$utils()){const m=domToBlock$$module$build$src$core$xml(l,b);d.push(m.id);const n=l.hasAttribute("x")?parseInt(l.getAttribute("x")):10,p=l.hasAttribute("y")?parseInt(l.getAttribute("y")):10;isNaN(n)||isNaN(p)||m.moveBy(b.RTL?c-n:n,p);f=!1}else{if("shadow"===k)throw TypeError("Shadow block cannot be a top-level block.");if("comment"===k)b.rendered?WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg.fromXmlRendered(l, -b,c):WorkspaceComment$$module$build$src$core$workspace_comment.fromXml(l,b);else if("variables"===k){if(f)domToVariables$$module$build$src$core$xml(l,b);else throw Error("'variables' tag must exist once before block and shadow tag elements in the workspace XML, but it was found in another location.");f=!1}}}}finally{e||setGroup$$module$build$src$core$events$utils(!1),stopTextWidthCache$$module$build$src$core$utils$dom()}b.setResizesEnabled&&b.setResizesEnabled(!0);fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(FINISHED_LOADING$$module$build$src$core$events$utils))(b)); -return d},appendDomToWorkspace$$module$build$src$core$xml=function(a,b){if(!b.getBlocksBoundingBox)return domToWorkspace$$module$build$src$core$xml(a,b);var c=b.getBlocksBoundingBox();a=domToWorkspace$$module$build$src$core$xml(a,b);if(c&&c.top!==c.bottom){var d=c.bottom;c=b.RTL?c.right:c.left;var e=Infinity;let f=-Infinity,g=Infinity;for(let h=0;hf&&(f=k.x)}d=d-g+10;c=b.RTL?c-f:c-e;for(e=0;eb&&(b=c[d].length);var e=-Infinity;let f,g=1;do{d=e;f=a;a=[];e=c.length/g;let h=1;for(let k= -0;kd);return f},wrapScore$$module$build$src$core$utils$string=function(a,b,c){const d=[0],e=[];for(var f=0;fd&&(d=h,e=g)}return e?wrapMutate$$module$build$src$core$utils$string(a, -e,c):b},wrapToText$$module$build$src$core$utils$string=function(a,b){const c=[];for(let d=0;dRADIUS_OK$$module$build$src$core$tooltip&&hide$$module$build$src$core$tooltip()}else poisonedElement$$module$build$src$core$tooltip!==element$$module$build$src$core$tooltip&&(clearTimeout(showPid$$module$build$src$core$tooltip),lastX$$module$build$src$core$tooltip=a.pageX,lastY$$module$build$src$core$tooltip=a.pageY,showPid$$module$build$src$core$tooltip=setTimeout(show$$module$build$src$core$tooltip, -HOVER_MS$$module$build$src$core$tooltip))},dispose$$module$build$src$core$tooltip=function(){poisonedElement$$module$build$src$core$tooltip=element$$module$build$src$core$tooltip=null;hide$$module$build$src$core$tooltip()},hide$$module$build$src$core$tooltip=function(){visible$$module$build$src$core$tooltip&&(visible$$module$build$src$core$tooltip=!1,containerDiv$$module$build$src$core$tooltip&&(containerDiv$$module$build$src$core$tooltip.style.display="none"));showPid$$module$build$src$core$tooltip&& -clearTimeout(showPid$$module$build$src$core$tooltip)},block$$module$build$src$core$tooltip=function(){hide$$module$build$src$core$tooltip();blocked$$module$build$src$core$tooltip=!0},unblock$$module$build$src$core$tooltip=function(){blocked$$module$build$src$core$tooltip=!1},renderContent$$module$build$src$core$tooltip=function(){containerDiv$$module$build$src$core$tooltip&&element$$module$build$src$core$tooltip&&("function"===typeof customTooltip$$module$build$src$core$tooltip?customTooltip$$module$build$src$core$tooltip(containerDiv$$module$build$src$core$tooltip, -element$$module$build$src$core$tooltip):renderDefaultContent$$module$build$src$core$tooltip())},renderDefaultContent$$module$build$src$core$tooltip=function(){var a=getTooltipOfObject$$module$build$src$core$tooltip(element$$module$build$src$core$tooltip);a=wrap$$module$build$src$core$utils$string(a,LIMIT$$module$build$src$core$tooltip);a=a.split("\n");for(let b=0;bc+window.scrollY&&(e-=containerDiv$$module$build$src$core$tooltip.offsetHeight+ -2*OFFSET_Y$$module$build$src$core$tooltip);a?d=Math.max(MARGINS$$module$build$src$core$tooltip-window.scrollX,d):d+containerDiv$$module$build$src$core$tooltip.offsetWidth>b+window.scrollX-2*MARGINS$$module$build$src$core$tooltip&&(d=b-containerDiv$$module$build$src$core$tooltip.offsetWidth-2*MARGINS$$module$build$src$core$tooltip);return{x:d,y:e}},show$$module$build$src$core$tooltip=function(){if(!blocked$$module$build$src$core$tooltip&&(poisonedElement$$module$build$src$core$tooltip=element$$module$build$src$core$tooltip, -containerDiv$$module$build$src$core$tooltip)){containerDiv$$module$build$src$core$tooltip.textContent="";renderContent$$module$build$src$core$tooltip();var a=element$$module$build$src$core$tooltip.RTL;containerDiv$$module$build$src$core$tooltip.style.direction=a?"rtl":"ltr";containerDiv$$module$build$src$core$tooltip.style.display="block";visible$$module$build$src$core$tooltip=!0;var {x:b,y:c}=getPosition$$module$build$src$core$tooltip(a);containerDiv$$module$build$src$core$tooltip.style.left=b+"px"; -containerDiv$$module$build$src$core$tooltip.style.top=c+"px"}},getHsvSaturation$$module$build$src$core$utils$colour=function(){return hsvSaturation$$module$build$src$core$utils$colour},setHsvSaturation$$module$build$src$core$utils$colour=function(a){hsvSaturation$$module$build$src$core$utils$colour=a},getHsvValue$$module$build$src$core$utils$colour=function(){return hsvValue$$module$build$src$core$utils$colour},setHsvValue$$module$build$src$core$utils$colour=function(a){hsvValue$$module$build$src$core$utils$colour= -a},parse$$module$build$src$core$utils$colour=function(a){a=String(a).toLowerCase().trim();var b=names$$module$build$src$core$utils$colour[a];if(b)return b;b="0x"===a.substring(0,2)?"#"+a.substring(2):a;b="#"===b[0]?b:"#"+b;if(/^#[0-9a-f]{6}$/.test(b))return b;if(/^#[0-9a-f]{3}$/.test(b))return["#",b[1],b[1],b[2],b[2],b[3],b[3]].join("");var c=a.match(/^(?:rgb)?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);return c&&(a=Number(c[1]),b=Number(c[2]),c=Number(c[3]),0<=a&&256>a&&0<=b&&256>b&&0<=c&&256> -c)?rgbToHex$$module$build$src$core$utils$colour(a,b,c):null},rgbToHex$$module$build$src$core$utils$colour=function(a,b,c){b=a<<16|b<<8|c;return 16>a?"#"+(16777216|b).toString(16).substr(1):"#"+b.toString(16)},hexToRgb$$module$build$src$core$utils$colour=function(a){a=parse$$module$build$src$core$utils$colour(a);if(!a)return[0,0,0];a=parseInt(a.substr(1),16);return[a>>16,a>>8&255,a&255]},hsvToHex$$module$build$src$core$utils$colour=function(a,b,c){let d=0,e=0,f=0;if(0===b)f=e=d=c;else{const g=Math.floor(a/ -60),h=a/60-g;a=c*(1-b);const k=c*(1-b*h);b=c*(1-b*(1-h));switch(g){case 1:d=k;e=c;f=a;break;case 2:d=a;e=c;f=b;break;case 3:d=a;e=k;f=c;break;case 4:d=b;e=a;f=c;break;case 5:d=c;e=a;f=k;break;case 6:case 0:d=c,e=b,f=a}}return rgbToHex$$module$build$src$core$utils$colour(Math.floor(d),Math.floor(e),Math.floor(f))},blend$$module$build$src$core$utils$colour=function(a,b,c){a=parse$$module$build$src$core$utils$colour(a);if(!a)return null;b=parse$$module$build$src$core$utils$colour(b);if(!b)return null; -a=hexToRgb$$module$build$src$core$utils$colour(a);b=hexToRgb$$module$build$src$core$utils$colour(b);return rgbToHex$$module$build$src$core$utils$colour(Math.round(b[0]+c*(a[0]-b[0])),Math.round(b[1]+c*(a[1]-b[1])),Math.round(b[2]+c*(a[2]-b[2])))},hueToHex$$module$build$src$core$utils$colour=function(a){return hsvToHex$$module$build$src$core$utils$colour(a,hsvSaturation$$module$build$src$core$utils$colour,255*hsvValue$$module$build$src$core$utils$colour)},tokenizeInterpolationInternal$$module$build$src$core$utils$parsing= -function(a,b){const c=[];var d=a.split("");d.push("");var e=0;a=[];let f=null;for(let k=0;k=g?(e=2,f=g,(g=a.join(""))&&c.push(g),a.length=0):"{"===g?e=3:(a.push("%",g),e=0);else if(2===e)if("0"<=g&&"9">=g)f+=g;else{var h=void 0;c.push(parseInt(null!=(h=f)?h:"",10));k--;e=0}else 3===e&&(""===g?(a.splice(0,0,"%{"),k--,e=0):"}"!==g?a.push(g):(e=a.join(""), -/[A-Z]\w*/i.test(e)?(g=e.toUpperCase(),(g=g.startsWith("BKY_")?g.substring(4):null)&&g in Msg$$module$build$src$core$msg?(e=Msg$$module$build$src$core$msg[g],"string"===typeof e?Array.prototype.push.apply(c,tokenizeInterpolationInternal$$module$build$src$core$utils$parsing(e,b)):b?c.push(String(e)):c.push(e)):c.push("%{"+e+"}")):c.push("%{"+e+"}"),e=a.length=0))}(b=a.join(""))&&c.push(b);h=[];a.length=0;for(d=0;d=c)return{hue:c,hex:hsvToHex$$module$build$src$core$utils$colour(c,getHsvSaturation$$module$build$src$core$utils$colour(), -255*getHsvValue$$module$build$src$core$utils$colour())};if(c=parse$$module$build$src$core$utils$colour(b))return{hue:null,hex:c};c='Invalid colour: "'+b+'"';a!==b&&(c+=' (from "'+a+'")');throw Error(c);},getDiv$$module$build$src$core$widgetdiv=function(){return containerDiv$$module$build$src$core$widgetdiv},testOnly_setDiv$$module$build$src$core$widgetdiv=function(a){containerDiv$$module$build$src$core$widgetdiv=a},createDom$$module$build$src$core$widgetdiv=function(){containerDiv$$module$build$src$core$widgetdiv|| -(containerDiv$$module$build$src$core$widgetdiv=document.createElement("div"),containerDiv$$module$build$src$core$widgetdiv.className="blocklyWidgetDiv",(getParentContainer$$module$build$src$core$common()||document.body).appendChild(containerDiv$$module$build$src$core$widgetdiv))},show$$module$build$src$core$widgetdiv=function(a,b,c){hide$$module$build$src$core$widgetdiv();owner$$module$build$src$core$widgetdiv=a;dispose$$module$build$src$core$widgetdiv=c;if(a=containerDiv$$module$build$src$core$widgetdiv)a.style.direction= -b?"rtl":"ltr",a.style.display="block",b=getMainWorkspace$$module$build$src$core$common(),rendererClassName$$module$build$src$core$widgetdiv=b.getRenderer().getClassName(),themeClassName$$module$build$src$core$widgetdiv=b.getTheme().getClassName(),rendererClassName$$module$build$src$core$widgetdiv&&addClass$$module$build$src$core$utils$dom(a,rendererClassName$$module$build$src$core$widgetdiv),themeClassName$$module$build$src$core$widgetdiv&&addClass$$module$build$src$core$utils$dom(a,themeClassName$$module$build$src$core$widgetdiv)}, -hide$$module$build$src$core$widgetdiv=function(){if(isVisible$$module$build$src$core$widgetdiv()){owner$$module$build$src$core$widgetdiv=null;var a=containerDiv$$module$build$src$core$widgetdiv;a&&(a.style.display="none",a.style.left="",a.style.top="",dispose$$module$build$src$core$widgetdiv&&dispose$$module$build$src$core$widgetdiv(),dispose$$module$build$src$core$widgetdiv=null,a.textContent="",rendererClassName$$module$build$src$core$widgetdiv&&(removeClass$$module$build$src$core$utils$dom(a,rendererClassName$$module$build$src$core$widgetdiv), -rendererClassName$$module$build$src$core$widgetdiv=""),themeClassName$$module$build$src$core$widgetdiv&&(removeClass$$module$build$src$core$utils$dom(a,themeClassName$$module$build$src$core$widgetdiv),themeClassName$$module$build$src$core$widgetdiv=""),getMainWorkspace$$module$build$src$core$common().markFocused())}},isVisible$$module$build$src$core$widgetdiv=function(){return!!owner$$module$build$src$core$widgetdiv},hideIfOwner$$module$build$src$core$widgetdiv=function(a){owner$$module$build$src$core$widgetdiv=== -a&&hide$$module$build$src$core$widgetdiv()},positionInternal$$module$build$src$core$widgetdiv=function(a,b,c){containerDiv$$module$build$src$core$widgetdiv.style.left=a+"px";containerDiv$$module$build$src$core$widgetdiv.style.top=b+"px";containerDiv$$module$build$src$core$widgetdiv.style.height=c+"px"},positionWithAnchor$$module$build$src$core$widgetdiv=function(a,b,c,d){const e=calculateY$$module$build$src$core$widgetdiv(a,b,c);a=calculateX$$module$build$src$core$widgetdiv(a,b,c,d);0>e?positionInternal$$module$build$src$core$widgetdiv(a, -0,c.height+e):positionInternal$$module$build$src$core$widgetdiv(a,e,c.height)},calculateX$$module$build$src$core$widgetdiv=function(a,b,c,d){return d?Math.min(Math.max(b.right-c.width,a.left),a.right-c.width):Math.max(Math.min(b.left,a.right-c.width),a.left)},calculateY$$module$build$src$core$widgetdiv=function(a,b,c){return b.bottom+c.height>=a.bottom?b.top-c.height:b.bottom},register$$module$build$src$core$field_registry=function(a,b){register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FIELD, -a,b)},unregister$$module$build$src$core$field_registry=function(a){unregister$$module$build$src$core$registry(Type$$module$build$src$core$registry.FIELD,a)},fromJson$$module$build$src$core$field_registry=function(a){return TEST_ONLY$$module$build$src$core$field_registry.fromJsonInternal(a)},fromJsonInternal$$module$build$src$core$field_registry=function(a){const b=getObject$$module$build$src$core$registry(Type$$module$build$src$core$registry.FIELD,a.type);if(b){if("function"!==typeof b.fromJson)throw new TypeError("returned Field was not a IRegistrableField"); -return b.fromJson(a)}console.warn("Blockly could not create a field of type "+a.type+". The field is probably not being registered. This could be because the file is not loaded, the field does not register itself (Issue #1584), or the registration is not being reached.");return null},setRole$$module$build$src$core$utils$aria=function(a,b){a.setAttribute(ROLE_ATTRIBUTE$$module$build$src$core$utils$aria,b)},setState$$module$build$src$core$utils$aria=function(a,b,c){Array.isArray(c)&&(c=c.join(" ")); -a.setAttribute(ARIA_PREFIX$$module$build$src$core$utils$aria+b,`${c}`)},validateOptions$$module$build$src$core$field_dropdown=function(a){if(!Array.isArray(a))throw TypeError("FieldDropdown options must be an array.");if(!a.length)throw TypeError("FieldDropdown options must not be an empty array.");let b=!1;for(let c=0;c document.");}else a instanceof Element&&(b=a);return b},register$$module$build$src$core$extensions=function(a,b){if("string"!==typeof a||""===a.trim())throw Error('Error: Invalid extension name "'+ -a+'"');if(allExtensions$$module$build$src$core$extensions[a])throw Error('Error: Extension "'+a+'" is already registered.');if("function"!==typeof b)throw Error('Error: Extension "'+a+'" must be a function');allExtensions$$module$build$src$core$extensions[a]=b},registerMixin$$module$build$src$core$extensions=function(a,b){if(!b||"object"!==typeof b)throw Error('Error: Mixin "'+a+'" must be a object');register$$module$build$src$core$extensions(a,function(){this.mixin(b)})},registerMutator$$module$build$src$core$extensions= -function(a,b,c,d){const e='Error when registering mutator "'+a+'": ';checkHasMutatorProperties$$module$build$src$core$extensions(e,b);const f=checkMutatorDialog$$module$build$src$core$extensions(b,e);if(c&&"function"!==typeof c)throw Error(e+'Extension "'+a+'" is not a function');register$$module$build$src$core$extensions(a,function(){f&&this.setMutator(new $.Mutator$$module$build$src$core$mutator(d||[],this));this.mixin(b);c&&c.apply(this)})},unregister$$module$build$src$core$extensions=function(a){isRegistered$$module$build$src$core$extensions(a)? -delete allExtensions$$module$build$src$core$extensions[a]:console.warn('No extension mapping for name "'+a+'" found to unregister')},isRegistered$$module$build$src$core$extensions=function(a){return!!allExtensions$$module$build$src$core$extensions[a]},apply$$module$build$src$core$extensions=function(a,b,c){const d=allExtensions$$module$build$src$core$extensions[a];if("function"!==typeof d)throw Error('Error: Extension "'+a+'" not found.');let e;c?checkNoMutatorProperties$$module$build$src$core$extensions(a, -b):e=getMutatorProperties$$module$build$src$core$extensions(b);d.apply(b);if(c)checkHasMutatorProperties$$module$build$src$core$extensions('Error after applying mutator "'+a+'": ',b);else if(!mutatorPropertiesMatch$$module$build$src$core$extensions(e,b))throw Error('Error when applying extension "'+a+'": mutation properties changed when applying a non-mutator extension.');},checkNoMutatorProperties$$module$build$src$core$extensions=function(a,b){if(getMutatorProperties$$module$build$src$core$extensions(b).length)throw Error('Error: tried to apply mutation "'+ -a+'" to a block that already has mutator functions. Block id: '+b.id);},checkXmlHooks$$module$build$src$core$extensions=function(a,b){return checkHasFunctionPair$$module$build$src$core$extensions(a.mutationToDom,a.domToMutation,b+" mutationToDom/domToMutation")},checkJsonHooks$$module$build$src$core$extensions=function(a,b){return checkHasFunctionPair$$module$build$src$core$extensions(a.saveExtraState,a.loadExtraState,b+" saveExtraState/loadExtraState")},checkMutatorDialog$$module$build$src$core$extensions= -function(a,b){return checkHasFunctionPair$$module$build$src$core$extensions(a.compose,a.decompose,b+" compose/decompose")},checkHasFunctionPair$$module$build$src$core$extensions=function(a,b,c){if(a&&b){if("function"!==typeof a||"function"!==typeof b)throw Error(c+" must be a function");return!0}if(!a&&!b)return!1;throw Error(c+"Must have both or neither functions");},checkHasMutatorProperties$$module$build$src$core$extensions=function(a,b){const c=checkXmlHooks$$module$build$src$core$extensions(b, -a),d=checkJsonHooks$$module$build$src$core$extensions(b,a);if(!c&&!d)throw Error(a+"Mutations must contain either XML hooks, or JSON hooks, or both");checkMutatorDialog$$module$build$src$core$extensions(b,a)},getMutatorProperties$$module$build$src$core$extensions=function(a){const b=[];void 0!==a.domToMutation&&b.push(a.domToMutation);void 0!==a.mutationToDom&&b.push(a.mutationToDom);void 0!==a.saveExtraState&&b.push(a.saveExtraState);void 0!==a.loadExtraState&&b.push(a.loadExtraState);void 0!==a.compose&& -b.push(a.compose);void 0!==a.decompose&&b.push(a.decompose);return b},mutatorPropertiesMatch$$module$build$src$core$extensions=function(a,b){b=getMutatorProperties$$module$build$src$core$extensions(b);if(b.length!==a.length)return!1;for(let c=0;c{g.disposed||g.setConnectionTracking(!0)},1);return g},appendPrivate$$module$build$src$core$serialization$blocks=function(a,b,{parentConnection:c,isShadow:d=!1}={}){if(!a.type)throw new MissingBlockType$$module$build$src$core$serialization$exceptions(a); -const e=b.newBlock(a.type,a.id);e.setShadow(d);loadCoords$$module$build$src$core$serialization$blocks(e,a);loadAttributes$$module$build$src$core$serialization$blocks(e,a);loadExtraState$$module$build$src$core$serialization$blocks(e,a);tryToConnectParent$$module$build$src$core$serialization$blocks(c,e,a);loadIcons$$module$build$src$core$serialization$blocks(e,a);loadFields$$module$build$src$core$serialization$blocks(e,a);loadInputBlocks$$module$build$src$core$serialization$blocks(e,a);loadNextBlocks$$module$build$src$core$serialization$blocks(e, -a);initBlock$$module$build$src$core$serialization$blocks(e,b.rendered);return e},loadCoords$$module$build$src$core$serialization$blocks=function(a,b){let c=void 0===b.x?0:b.x;b=void 0===b.y?0:b.y;const d=a.workspace;c=d.RTL?d.getWidth()-c:c;a.moveBy(c,b)},loadAttributes$$module$build$src$core$serialization$blocks=function(a,b){b.collapsed&&a.setCollapsed(!0);!1===b.enabled&&a.setEnabled(!1);void 0!==b.inline&&a.setInputsInline(b.inline);void 0!==b.data&&(a.data=b.data)},loadExtraState$$module$build$src$core$serialization$blocks= -function(a,b){b.extraState&&(a.loadExtraState?a.loadExtraState(b.extraState):a.domToMutation&&a.domToMutation(textToDom$$module$build$src$core$xml(b.extraState)))},tryToConnectParent$$module$build$src$core$serialization$blocks=function(a,b,c){if(a){if(a.getSourceBlock().isShadow()&&!b.isShadow())throw new RealChildOfShadow$$module$build$src$core$serialization$exceptions(c);if(a.type===inputTypes$$module$build$src$core$input_types.VALUE){var d=b.outputConnection;if(!d)throw new MissingConnection$$module$build$src$core$serialization$exceptions("output", -b,c);}else if(d=b.previousConnection,!d)throw new MissingConnection$$module$build$src$core$serialization$exceptions("previous",b,c);if(!a.connect(d)){const e=b.workspace.connectionChecker;throw new BadConnectionCheck$$module$build$src$core$serialization$exceptions(e.getErrorMessage(e.canConnectWithReason(d,a,!1),d,a),a.type===inputTypes$$module$build$src$core$input_types.VALUE?"output connection":"previous connection",b,c);}}},loadIcons$$module$build$src$core$serialization$blocks=function(a,b){b.icons&& -(b=b.icons.comment)&&(a.setCommentText(b.text),"pinned"in b&&(a.commentModel.pinned=b.pinned),"width"in b&&"height"in b&&(a.commentModel.size=new Size$$module$build$src$core$utils$size(b.width,b.height)),b.pinned&&a.rendered&&!a.isInFlyout&&setTimeout(()=>a.getCommentIcon().setVisible(!0),1))},loadFields$$module$build$src$core$serialization$blocks=function(a,b){if(b.fields){var c=Object.keys(b.fields);for(let d=0;dc)){var d=b.getSvgXY(a.getSvgRoot());a.outputConnection?(d.x+=(a.RTL?3:-3)*c,d.y+=13*c):a.previousConnection&&(d.x+=(a.RTL?-23:23)*c,d.y+=3*c);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CIRCLE,{cx:d.x,cy:d.y,r:0,fill:"none", -stroke:"#888","stroke-width":10},b.getParentSvg());connectionUiStep$$module$build$src$core$block_animations(a,new Date,c)}},connectionUiStep$$module$build$src$core$block_animations=function(a,b,c){const d=((new Date).getTime()-b.getTime())/150;1a.workspace.scale)){var b=a.getHeightWidth().height;b=Math.atan(10/b)/Math.PI*180;a.RTL||(b*=-1);disconnectGroup$$module$build$src$core$block_animations=a.getSvgRoot();disconnectUiStep$$module$build$src$core$block_animations(disconnectGroup$$module$build$src$core$block_animations,b,new Date)}},disconnectUiStep$$module$build$src$core$block_animations= -function(a,b,c){const d=((new Date).getTime()-c.getTime())/200;let e="";1>=d&&(e=`skewX(${Math.round(Math.sin(d*Math.PI*3)*(1-d)*b)})`,disconnectPid$$module$build$src$core$block_animations=setTimeout(disconnectUiStep$$module$build$src$core$block_animations,10,a,b,c));a.skew_=e;a.setAttribute("transform",a.translate_+a.skew_)},disconnectUiStop$$module$build$src$core$block_animations=function(){if(disconnectGroup$$module$build$src$core$block_animations){disconnectPid$$module$build$src$core$block_animations&& -clearTimeout(disconnectPid$$module$build$src$core$block_animations);const a=disconnectGroup$$module$build$src$core$block_animations;a.skew_="";a.setAttribute("transform",a.translate_);disconnectGroup$$module$build$src$core$block_animations=null}},copy$$module$build$src$core$clipboard=function(a){TEST_ONLY$$module$build$src$core$clipboard.copyInternal(a)},copyInternal$$module$build$src$core$clipboard=function(a){copyData$$module$build$src$core$clipboard=a.toCopyData()},paste$$module$build$src$core$clipboard= -function(){if(!copyData$$module$build$src$core$clipboard)return null;let a=copyData$$module$build$src$core$clipboard.source;a.isFlyout&&(a=a.targetWorkspace);return copyData$$module$build$src$core$clipboard.typeCounts&&a.isCapacityAvailable(copyData$$module$build$src$core$clipboard.typeCounts)?a.paste(copyData$$module$build$src$core$clipboard.saveInfo):null},duplicate$$module$build$src$core$clipboard=function(a){return TEST_ONLY$$module$build$src$core$clipboard.duplicateInternal(a)},duplicateInternal$$module$build$src$core$clipboard= -function(a){const b=copyData$$module$build$src$core$clipboard;copy$$module$build$src$core$clipboard(a);let c,d,e;a=null!=(e=null==(c=a.toCopyData())?void 0:null==(d=c.source)?void 0:d.paste(copyData$$module$build$src$core$clipboard.saveInfo))?e:null;copyData$$module$build$src$core$clipboard=b;return a},getCurrentBlock$$module$build$src$core$contextmenu=function(){return currentBlock$$module$build$src$core$contextmenu},setCurrentBlock$$module$build$src$core$contextmenu=function(a){currentBlock$$module$build$src$core$contextmenu= -a},show$$module$build$src$core$contextmenu=function(a,b,c){show$$module$build$src$core$widgetdiv(dummyOwner$$module$build$src$core$contextmenu,c,dispose$$module$build$src$core$contextmenu);if(b.length){var d=populate_$$module$build$src$core$contextmenu(b,c);menu_$$module$build$src$core$contextmenu=d;position_$$module$build$src$core$contextmenu(d,a,c);setTimeout(function(){d.focus()},1);currentBlock$$module$build$src$core$contextmenu=null}else hide$$module$build$src$core$contextmenu()},populate_$$module$build$src$core$contextmenu= -function(a,b){const c=new Menu$$module$build$src$core$menu;c.setRole(Role$$module$build$src$core$utils$aria.MENU);for(let d=0;d{disable$$module$build$src$core$events$utils();let c;try{c=domToBlock$$module$build$src$core$xml(b,a.workspace);const d=a.getRelativeToSurfaceXY();d.x=a.RTL?d.x-$.config$$module$build$src$core$config.snapRadius:d.x+$.config$$module$build$src$core$config.snapRadius; -d.y+=2*$.config$$module$build$src$core$config.snapRadius;c.moveBy(d.x,d.y)}finally{enable$$module$build$src$core$events$utils()}isEnabled$$module$build$src$core$events$utils()&&!c.isShadow()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(CREATE$$module$build$src$core$events$utils))(c));c.select()}},commentDeleteOption$$module$build$src$core$contextmenu=function(a){return{text:Msg$$module$build$src$core$msg.REMOVE_COMMENT,enabled:!0,callback:function(){setGroup$$module$build$src$core$events$utils(!0); -a.dispose();setGroup$$module$build$src$core$events$utils(!1)}}},commentDuplicateOption$$module$build$src$core$contextmenu=function(a){return{text:Msg$$module$build$src$core$msg.DUPLICATE_COMMENT,enabled:!0,callback:function(){duplicate$$module$build$src$core$clipboard(a)}}},workspaceCommentOption$$module$build$src$core$contextmenu=function(a,b){const c={enabled:!0};c.text=Msg$$module$build$src$core$msg.ADD_COMMENT;c.callback=function(){const d=new WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg(a, -Msg$$module$build$src$core$msg.WORKSPACE_COMMENT_DEFAULT_TEXT,WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg.DEFAULT_SIZE,WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg.DEFAULT_SIZE);var e=a.getInjectionDiv().getBoundingClientRect();e=new Coordinate$$module$build$src$core$utils$coordinate(b.clientX-e.left,b.clientY-e.top);const f=a.getOriginOffsetInPixels();e=Coordinate$$module$build$src$core$utils$coordinate.difference(e,f);e.scale(1/a.scale);d.moveBy(e.x,e.y); -a.rendered&&(d.initSvg(),d.render(),d.select())};return c},getStartPositionRect$$module$build$src$core$positionable_helpers=function(a,b,c,d,e,f){const g=f.scrollbar&&f.scrollbar.canScrollVertically();a.horizontal===horizontalPosition$$module$build$src$core$positionable_helpers.LEFT?(c=e.absoluteMetrics.left+c,g&&f.RTL&&(c+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness)):(c=e.absoluteMetrics.left+e.viewMetrics.width-b.width-c,g&&!f.RTL&&(c-=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness)); -a.vertical===verticalPosition$$module$build$src$core$positionable_helpers.TOP?a=e.absoluteMetrics.top+d:(a=e.absoluteMetrics.top+e.viewMetrics.height-b.height-d,f.scrollbar&&f.scrollbar.canScrollHorizontally()&&(a-=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness));return new Rect$$module$build$src$core$utils$rect(a,a+b.height,c,c+b.width)},getCornerOppositeToolbox$$module$build$src$core$positionable_helpers=function(a,b){return{horizontal:b.toolboxMetrics.position===Position$$module$build$src$core$utils$toolbox.LEFT|| -a.horizontalLayout&&!a.RTL?horizontalPosition$$module$build$src$core$positionable_helpers.RIGHT:horizontalPosition$$module$build$src$core$positionable_helpers.LEFT,vertical:b.toolboxMetrics.position===Position$$module$build$src$core$utils$toolbox.BOTTOM?verticalPosition$$module$build$src$core$positionable_helpers.TOP:verticalPosition$$module$build$src$core$positionable_helpers.BOTTOM}},bumpPositionRect$$module$build$src$core$positionable_helpers=function(a,b,c,d){const e=a.left,f=a.right-a.left,g= -a.bottom-a.top;for(let h=0;hg[1].priority-f[1].priority);var e=getRecordUndo$$module$build$src$core$events$utils();setRecordUndo$$module$build$src$core$events$utils(c);(c=getGroup$$module$build$src$core$events$utils())|| -setGroup$$module$build$src$core$events$utils(!0);startTextWidthCache$$module$build$src$core$utils$dom();b instanceof WorkspaceSvg$$module$build$src$core$workspace_svg&&b.setResizesEnabled(!1);for(const [,f]of d.reverse()){let g;null==(g=f)||g.clear(b)}for(let [f,g]of d.reverse())if(a[f]){let h;null==(h=g)||h.load(a[f],b)}b instanceof WorkspaceSvg$$module$build$src$core$workspace_svg&&b.setResizesEnabled(!0);stopTextWidthCache$$module$build$src$core$utils$dom();fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(FINISHED_LOADING$$module$build$src$core$events$utils))(b)); -setGroup$$module$build$src$core$events$utils(c);setRecordUndo$$module$build$src$core$events$utils(e)}},bumpObjectIntoBounds$$module$build$src$core$bump_objects=function(a,b,c){const d=c.getBoundingRectangle(),e=d.right-d.left,f=clamp$$module$build$src$core$utils$math(b.top,d.top,b.top+b.height-(d.bottom-d.top))-d.top;let g=b.left;b=b.left+b.width-e;a.RTL?g=Math.min(b,g):b=Math.max(g,b);return(a=clamp$$module$build$src$core$utils$math(g,d.left,b)-d.left)||f?(c.moveBy(a,f),!0):!1},bumpIntoBoundsHandler$$module$build$src$core$bump_objects= -function(a){return b=>{var c=a.getMetricsManager();if(c.hasFixedEdges()&&!a.isDragging()){var d;if(-1!==BUMP_EVENTS$$module$build$src$core$events$utils.indexOf(null!=(d=b.type)?d:"")){d=c.getScrollMetrics(!0);const e=extractObjectFromEvent$$module$build$src$core$bump_objects(a,b);e&&(c=getGroup$$module$build$src$core$events$utils(),setGroup$$module$build$src$core$events$utils(b.group),bumpObjectIntoBounds$$module$build$src$core$bump_objects(a,d,e)&&!b.group&&console.warn("Moved object in bounds but there was no event group. This may break undo."), -null!==c&&setGroup$$module$build$src$core$events$utils(c))}else b.type===VIEWPORT_CHANGE$$module$build$src$core$events$utils&&b.scale&&b.oldScale&&b.scale>b.oldScale&&bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects(a)}}},extractObjectFromEvent$$module$build$src$core$bump_objects=function(a,b){let c=null;switch(b.type){case CREATE$$module$build$src$core$events$utils:case MOVE$$module$build$src$core$events$utils:(c=a.getBlockById(b.blockId))&&(c=c.getRootBlock());break;case COMMENT_CREATE$$module$build$src$core$events$utils:case COMMENT_MOVE$$module$build$src$core$events$utils:c= -a.getCommentById(b.commentId)}return c},bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects=function(a){var b=a.getMetricsManager();if(b.hasFixedEdges()&&!a.isDragging()){b=b.getScrollMetrics(!0);var c=a.getTopBoundedElements();for(let d=0,e;e=c[d];d++)bumpObjectIntoBounds$$module$build$src$core$bump_objects(a,b,e)}},inject$$module$build$src$core$inject=function(a,b){"string"===typeof a&&(a=document.getElementById(a)||document.querySelector(a));if(!a||!containsNode$$module$build$src$core$utils$dom(document, -a))throw Error("Error: container is not in current document.");b=new Options$$module$build$src$core$options(b||{});const c=document.createElement("div");c.className="injectionDiv";c.tabIndex=0;setState$$module$build$src$core$utils$aria(c,State$$module$build$src$core$utils$aria.LABEL,Msg$$module$build$src$core$msg.WORKSPACE_ARIA_LABEL);a.appendChild(c);a=createDom$$module$build$src$core$inject(c,b);const d=new BlockDragSurfaceSvg$$module$build$src$core$block_drag_surface(c),e=new WorkspaceDragSurfaceSvg$$module$build$src$core$workspace_drag_surface_svg(c), -f=createMainWorkspace$$module$build$src$core$inject(a,b,d,e);init$$module$build$src$core$inject(f);setMainWorkspace$$module$build$src$core$common(f);svgResize$$module$build$src$core$common(f);c.addEventListener("focusin",function(){setMainWorkspace$$module$build$src$core$common(f)});return f},createDom$$module$build$src$core$inject=function(a,b){a.setAttribute("dir","LTR");inject$$module$build$src$core$css(b.hasCss,b.pathToMedia);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG, -{xmlns:SVG_NS$$module$build$src$core$utils$dom,"xmlns:html":HTML_NS$$module$build$src$core$utils$dom,"xmlns:xlink":XLINK_NS$$module$build$src$core$utils$dom,version:"1.1","class":"blocklySvg",tabindex:"0"},a);const c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.DEFS,{},a),d=String(Math.random()).substring(2);b.gridPattern=Grid$$module$build$src$core$grid.createDom(d,b.gridOptions,c);return a},createMainWorkspace$$module$build$src$core$inject=function(a,b, -c,d){b.parentWorkspace=null;b=new WorkspaceSvg$$module$build$src$core$workspace_svg(b,c,d);c=b.options;b.scale=c.zoomOptions.startScale;a.appendChild(b.createDom("blocklyMainBackground"));d=b.getInjectionDiv();var e=b.getRenderer().getClassName();e&&addClass$$module$build$src$core$utils$dom(d,e);(e=b.getTheme().getClassName())&&addClass$$module$build$src$core$utils$dom(d,e);!c.hasCategories&&c.languageTree&&(d=b.addFlyout(Svg$$module$build$src$core$utils$svg.SVG),insertAfter$$module$build$src$core$utils$dom(d, -a));c.hasTrashcan&&b.addTrashcan();c.zoomOptions&&c.zoomOptions.controls&&b.addZoomControls();b.getThemeManager().subscribe(a,"workspaceBackgroundColour","background-color");b.translate(0,0);b.addChangeListener(bumpIntoBoundsHandler$$module$build$src$core$bump_objects(b));svgResize$$module$build$src$core$common(b);createDom$$module$build$src$core$widgetdiv();createDom$$module$build$src$core$dropdowndiv();createDom$$module$build$src$core$tooltip();return b},init$$module$build$src$core$inject=function(a){const b= -a.options;var c=a.getParentSvg();conditionalBind$$module$build$src$core$browser_events(c.parentNode,"contextmenu",null,function(d){isTargetInput$$module$build$src$core$browser_events(d)||d.preventDefault()});c=conditionalBind$$module$build$src$core$browser_events(window,"resize",null,function(){a.hideChaff(!0);svgResize$$module$build$src$core$common(a);bumpTopObjectsIntoBounds$$module$build$src$core$bump_objects(a)});a.setResizeHandlerWrapper(c);bindDocumentEvents$$module$build$src$core$inject(); -if(b.languageTree){c=a.getToolbox();const d=a.getFlyout(!0);c?c.init():d&&(d.init(a),d.show(b.languageTree),"function"===typeof d.scrollToStart&&d.scrollToStart())}b.hasTrashcan&&a.trashcan.init();b.zoomOptions&&b.zoomOptions.controls&&a.zoomControls_.init();b.moveOptions&&b.moveOptions.scrollbars?(a.scrollbar=new ScrollbarPair$$module$build$src$core$scrollbar_pair(a,!0===b.moveOptions.scrollbars||!!b.moveOptions.scrollbars.horizontal,!0===b.moveOptions.scrollbars||!!b.moveOptions.scrollbars.vertical, -"blocklyMainWorkspaceScrollbar"),a.scrollbar.resize()):a.setMetrics({x:.5,y:.5});b.hasSounds&&loadSounds$$module$build$src$core$inject(b.pathToMedia,a)},onKeyDown$$module$build$src$core$inject=function(a){const b=getMainWorkspace$$module$build$src$core$common();if(b&&!(isTargetInput$$module$build$src$core$browser_events(a)||b.rendered&&!b.isVisible()))ShortcutRegistry$$module$build$src$core$shortcut_registry.registry.onKeyDown(b,a)},bindDocumentEvents$$module$build$src$core$inject=function(){documentEventsBound$$module$build$src$core$inject|| -(conditionalBind$$module$build$src$core$browser_events(document,"scroll",null,function(){const a=getAllWorkspaces$$module$build$src$core$common();for(let b=0,c;c=a[b];b++)c instanceof WorkspaceSvg$$module$build$src$core$workspace_svg&&c.updateInverseScreenCTM()}),conditionalBind$$module$build$src$core$browser_events(document,"keydown",null,onKeyDown$$module$build$src$core$inject),bind$$module$build$src$core$browser_events(document,"touchend",null,longStop$$module$build$src$core$touch),bind$$module$build$src$core$browser_events(document, -"touchcancel",null,longStop$$module$build$src$core$touch),IPAD$$module$build$src$core$utils$useragent&&conditionalBind$$module$build$src$core$browser_events(window,"orientationchange",document,function(){svgResize$$module$build$src$core$common(getMainWorkspace$$module$build$src$core$common())}));documentEventsBound$$module$build$src$core$inject=!0},loadSounds$$module$build$src$core$inject=function(a,b){function c(){for(;e.length;)unbind$$module$build$src$core$browser_events(e.pop());d.preload()}const d= -b.getAudioManager();d.load([a+"click.mp3",a+"click.wav",a+"click.ogg"],"click");d.load([a+"disconnect.wav",a+"disconnect.mp3",a+"disconnect.ogg"],"disconnect");d.load([a+"delete.mp3",a+"delete.ogg",a+"delete.wav"],"delete");const e=[];e.push(conditionalBind$$module$build$src$core$browser_events(document,"mousemove",null,c,!0));e.push(conditionalBind$$module$build$src$core$browser_events(document,"touchstart",null,c,!0))},registerUndo$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(){return Msg$$module$build$src$core$msg.UNDO}, -preconditionFn(a){return 0b.length?deleteNext_$$module$build$src$core$contextmenu_items(b,c):confirm$$module$build$src$core$dialog(Msg$$module$build$src$core$msg.DELETE_ALL_BLOCKS.replace("%1",String(b.length)),function(d){d&&deleteNext_$$module$build$src$core$contextmenu_items(b,c)})}},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.WORKSPACE,id:"workspaceDelete", -weight:6})},registerWorkspaceOptions_$$module$build$src$core$contextmenu_items=function(){registerUndo$$module$build$src$core$contextmenu_items();registerRedo$$module$build$src$core$contextmenu_items();registerCleanup$$module$build$src$core$contextmenu_items();registerCollapse$$module$build$src$core$contextmenu_items();registerExpand$$module$build$src$core$contextmenu_items();registerDeleteAll$$module$build$src$core$contextmenu_items()},registerDuplicate$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(){return Msg$$module$build$src$core$msg.DUPLICATE_BLOCK}, -preconditionFn(a){a=a.block;return!a.isInFlyout&&a.isDeletable()&&a.isMovable()?a.isDuplicatable()?"enabled":"disabled":"hidden"},callback(a){a.block&&duplicate$$module$build$src$core$clipboard(a.block)},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.BLOCK,id:"blockDuplicate",weight:1})},registerComment$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(a){return a.block.getCommentIcon()? -Msg$$module$build$src$core$msg.REMOVE_COMMENT:Msg$$module$build$src$core$msg.ADD_COMMENT},preconditionFn(a){a=a.block;return!a.isInFlyout&&a.workspace.options.comments&&!a.isCollapsed()&&a.isEditable()?"enabled":"hidden"},callback(a){a=a.block;a.getCommentIcon()?a.setCommentText(null):a.setCommentText("")},scopeType:ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.BLOCK,id:"blockComment",weight:2})},registerInline$$module$build$src$core$contextmenu_items=function(){ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.register({displayText(a){return a.block.getInputsInline()? -Msg$$module$build$src$core$msg.EXTERNAL_INPUTS:Msg$$module$build$src$core$msg.INLINE_INPUTS},preconditionFn(a){a=a.block;if(!a.isInFlyout&&a.isMovable()&&!a.isCollapsed())for(let b=1;b>>0,$jscomp.propertyToPolyfillSymbol[e]=$jscomp.IS_SYMBOL_NATIVE? -$jscomp.global.Symbol(e):$jscomp.POLYFILL_PREFIX+c+"$"+e),$jscomp.defineProperty(d,$jscomp.propertyToPolyfillSymbol[e],{configurable:!0,writable:!0,value:b})))};$jscomp.polyfill("globalThis",function(a){return a||$jscomp.global},"es_2020","es3");$jscomp.arrayIteratorImpl=function(a){var b=0;return function(){return b=this.left&&a<=this.right&&b>=this.top&&b<=this.bottom}intersects(a){return!(this.left>a.right||this.righta.bottom||this.bottome.top?getPositionAboveMetrics$$module$build$src$core$dropdowndiv(c,d,e,f):b+f.heightdocument.documentElement.clientTop?getPositionAboveMetrics$$module$build$src$core$dropdowndiv(c,d,e,f):getPositionTopOfPageMetrics$$module$build$src$core$dropdowndiv(a,e,f)}},TEST_ONLY$$module$build$src$core$dropdowndiv=internal$$module$build$src$core$dropdowndiv,module$build$src$core$dropdowndiv={};module$build$src$core$dropdowndiv.ANIMATION_TIME=ANIMATION_TIME$$module$build$src$core$dropdowndiv; -module$build$src$core$dropdowndiv.ARROW_HORIZONTAL_PADDING=ARROW_HORIZONTAL_PADDING$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.ARROW_SIZE=ARROW_SIZE$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.BORDER_SIZE=BORDER_SIZE$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.PADDING_Y=PADDING_Y$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.TEST_ONLY=internal$$module$build$src$core$dropdowndiv; -module$build$src$core$dropdowndiv.clearContent=clearContent$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.createDom=createDom$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.getContentDiv=getContentDiv$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.getPositionX=getPositionX$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.hide=hide$$module$build$src$core$dropdowndiv; -module$build$src$core$dropdowndiv.hideIfOwner=hideIfOwner$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.hideWithoutAnimation=hideWithoutAnimation$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.isVisible=isVisible$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.repositionForWindowResize=repositionForWindowResize$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.setBoundsElement=setBoundsElement$$module$build$src$core$dropdowndiv; -module$build$src$core$dropdowndiv.setColour=setColour$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.show=show$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.showPositionedByBlock=showPositionedByBlock$$module$build$src$core$dropdowndiv;module$build$src$core$dropdowndiv.showPositionedByField=showPositionedByField$$module$build$src$core$dropdowndiv;var typeMap$$module$build$src$core$registry=Object.create(null),TEST_ONLY$$module$build$src$core$registry={typeMap:typeMap$$module$build$src$core$registry},nameMap$$module$build$src$core$registry=Object.create(null),DEFAULT$$module$build$src$core$registry="default",Type$$module$build$src$core$registry=class{constructor(a){this.name=a}toString(){return this.name}};Type$$module$build$src$core$registry.CONNECTION_CHECKER=new Type$$module$build$src$core$registry("connectionChecker"); -Type$$module$build$src$core$registry.CURSOR=new Type$$module$build$src$core$registry("cursor");Type$$module$build$src$core$registry.EVENT=new Type$$module$build$src$core$registry("event");Type$$module$build$src$core$registry.FIELD=new Type$$module$build$src$core$registry("field");Type$$module$build$src$core$registry.RENDERER=new Type$$module$build$src$core$registry("renderer");Type$$module$build$src$core$registry.TOOLBOX=new Type$$module$build$src$core$registry("toolbox"); -Type$$module$build$src$core$registry.THEME=new Type$$module$build$src$core$registry("theme");Type$$module$build$src$core$registry.TOOLBOX_ITEM=new Type$$module$build$src$core$registry("toolboxItem");Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX=new Type$$module$build$src$core$registry("flyoutsVerticalToolbox");Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX=new Type$$module$build$src$core$registry("flyoutsHorizontalToolbox"); -Type$$module$build$src$core$registry.METRICS_MANAGER=new Type$$module$build$src$core$registry("metricsManager");Type$$module$build$src$core$registry.BLOCK_DRAGGER=new Type$$module$build$src$core$registry("blockDragger");Type$$module$build$src$core$registry.SERIALIZER=new Type$$module$build$src$core$registry("serializer");var module$build$src$core$registry={};module$build$src$core$registry.DEFAULT=DEFAULT$$module$build$src$core$registry;module$build$src$core$registry.TEST_ONLY=TEST_ONLY$$module$build$src$core$registry; -module$build$src$core$registry.Type=Type$$module$build$src$core$registry;module$build$src$core$registry.getAllItems=getAllItems$$module$build$src$core$registry;module$build$src$core$registry.getClass=getClass$$module$build$src$core$registry;module$build$src$core$registry.getClassFromOptions=getClassFromOptions$$module$build$src$core$registry;module$build$src$core$registry.getObject=getObject$$module$build$src$core$registry;module$build$src$core$registry.hasItem=hasItem$$module$build$src$core$registry; -module$build$src$core$registry.register=register$$module$build$src$core$registry;module$build$src$core$registry.unregister=unregister$$module$build$src$core$registry;var soup$$module$build$src$core$utils$idgenerator="!#$%()*+,-./:;=?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",internal$$module$build$src$core$utils$idgenerator={genUid:()=>{const a=soup$$module$build$src$core$utils$idgenerator.length,b=[];for(let c=0;20>c;c++)b[c]=soup$$module$build$src$core$utils$idgenerator.charAt(Math.random()*a);return b.join("")}},TEST_ONLY$$module$build$src$core$utils$idgenerator=internal$$module$build$src$core$utils$idgenerator,nextId$$module$build$src$core$utils$idgenerator= -0,module$build$src$core$utils$idgenerator={};module$build$src$core$utils$idgenerator.TEST_ONLY=internal$$module$build$src$core$utils$idgenerator;module$build$src$core$utils$idgenerator.genUid=genUid$$module$build$src$core$utils$idgenerator;module$build$src$core$utils$idgenerator.getNextUniqueId=getNextUniqueId$$module$build$src$core$utils$idgenerator;var group$$module$build$src$core$events$utils="",recordUndo$$module$build$src$core$events$utils=!0,disabled$$module$build$src$core$events$utils=0,CREATE$$module$build$src$core$events$utils="create",BLOCK_CREATE$$module$build$src$core$events$utils=CREATE$$module$build$src$core$events$utils,DELETE$$module$build$src$core$events$utils="delete",BLOCK_DELETE$$module$build$src$core$events$utils=DELETE$$module$build$src$core$events$utils,CHANGE$$module$build$src$core$events$utils="change",BLOCK_CHANGE$$module$build$src$core$events$utils= -CHANGE$$module$build$src$core$events$utils,MOVE$$module$build$src$core$events$utils="move",BLOCK_MOVE$$module$build$src$core$events$utils=MOVE$$module$build$src$core$events$utils,VAR_CREATE$$module$build$src$core$events$utils="var_create",VAR_DELETE$$module$build$src$core$events$utils="var_delete",VAR_RENAME$$module$build$src$core$events$utils="var_rename",UI$$module$build$src$core$events$utils="ui",BLOCK_DRAG$$module$build$src$core$events$utils="drag",SELECTED$$module$build$src$core$events$utils= -"selected",CLICK$$module$build$src$core$events$utils="click",MARKER_MOVE$$module$build$src$core$events$utils="marker_move",BUBBLE_OPEN$$module$build$src$core$events$utils="bubble_open",TRASHCAN_OPEN$$module$build$src$core$events$utils="trashcan_open",TOOLBOX_ITEM_SELECT$$module$build$src$core$events$utils="toolbox_item_select",THEME_CHANGE$$module$build$src$core$events$utils="theme_change",VIEWPORT_CHANGE$$module$build$src$core$events$utils="viewport_change",COMMENT_CREATE$$module$build$src$core$events$utils= -"comment_create",COMMENT_DELETE$$module$build$src$core$events$utils="comment_delete",COMMENT_CHANGE$$module$build$src$core$events$utils="comment_change",COMMENT_MOVE$$module$build$src$core$events$utils="comment_move",FINISHED_LOADING$$module$build$src$core$events$utils="finished_loading",BUMP_EVENTS$$module$build$src$core$events$utils=[CREATE$$module$build$src$core$events$utils,MOVE$$module$build$src$core$events$utils,COMMENT_CREATE$$module$build$src$core$events$utils,COMMENT_MOVE$$module$build$src$core$events$utils], -FIRE_QUEUE$$module$build$src$core$events$utils=[],TEST_ONLY$$module$build$src$core$events$utils={FIRE_QUEUE:FIRE_QUEUE$$module$build$src$core$events$utils,fireNow:fireNow$$module$build$src$core$events$utils,fireInternal:fireInternal$$module$build$src$core$events$utils,setGroupInternal:setGroupInternal$$module$build$src$core$events$utils},module$build$src$core$events$utils={};module$build$src$core$events$utils.BLOCK_CHANGE=CHANGE$$module$build$src$core$events$utils; -module$build$src$core$events$utils.BLOCK_CREATE=CREATE$$module$build$src$core$events$utils;module$build$src$core$events$utils.BLOCK_DELETE=DELETE$$module$build$src$core$events$utils;module$build$src$core$events$utils.BLOCK_DRAG=BLOCK_DRAG$$module$build$src$core$events$utils;module$build$src$core$events$utils.BLOCK_MOVE=MOVE$$module$build$src$core$events$utils;module$build$src$core$events$utils.BUBBLE_OPEN=BUBBLE_OPEN$$module$build$src$core$events$utils; -module$build$src$core$events$utils.BUMP_EVENTS=BUMP_EVENTS$$module$build$src$core$events$utils;module$build$src$core$events$utils.CHANGE=CHANGE$$module$build$src$core$events$utils;module$build$src$core$events$utils.CLICK=CLICK$$module$build$src$core$events$utils;module$build$src$core$events$utils.COMMENT_CHANGE=COMMENT_CHANGE$$module$build$src$core$events$utils;module$build$src$core$events$utils.COMMENT_CREATE=COMMENT_CREATE$$module$build$src$core$events$utils; -module$build$src$core$events$utils.COMMENT_DELETE=COMMENT_DELETE$$module$build$src$core$events$utils;module$build$src$core$events$utils.COMMENT_MOVE=COMMENT_MOVE$$module$build$src$core$events$utils;module$build$src$core$events$utils.CREATE=CREATE$$module$build$src$core$events$utils;module$build$src$core$events$utils.DELETE=DELETE$$module$build$src$core$events$utils;module$build$src$core$events$utils.FINISHED_LOADING=FINISHED_LOADING$$module$build$src$core$events$utils; -module$build$src$core$events$utils.MARKER_MOVE=MARKER_MOVE$$module$build$src$core$events$utils;module$build$src$core$events$utils.MOVE=MOVE$$module$build$src$core$events$utils;module$build$src$core$events$utils.SELECTED=SELECTED$$module$build$src$core$events$utils;module$build$src$core$events$utils.TEST_ONLY=TEST_ONLY$$module$build$src$core$events$utils;module$build$src$core$events$utils.THEME_CHANGE=THEME_CHANGE$$module$build$src$core$events$utils; -module$build$src$core$events$utils.TOOLBOX_ITEM_SELECT=TOOLBOX_ITEM_SELECT$$module$build$src$core$events$utils;module$build$src$core$events$utils.TRASHCAN_OPEN=TRASHCAN_OPEN$$module$build$src$core$events$utils;module$build$src$core$events$utils.UI=UI$$module$build$src$core$events$utils;module$build$src$core$events$utils.VAR_CREATE=VAR_CREATE$$module$build$src$core$events$utils;module$build$src$core$events$utils.VAR_DELETE=VAR_DELETE$$module$build$src$core$events$utils; -module$build$src$core$events$utils.VAR_RENAME=VAR_RENAME$$module$build$src$core$events$utils;module$build$src$core$events$utils.VIEWPORT_CHANGE=VIEWPORT_CHANGE$$module$build$src$core$events$utils;module$build$src$core$events$utils.clearPendingUndo=clearPendingUndo$$module$build$src$core$events$utils;module$build$src$core$events$utils.disable=disable$$module$build$src$core$events$utils;module$build$src$core$events$utils.disableOrphans=disableOrphans$$module$build$src$core$events$utils; -module$build$src$core$events$utils.enable=enable$$module$build$src$core$events$utils;module$build$src$core$events$utils.filter=filter$$module$build$src$core$events$utils;module$build$src$core$events$utils.fire=fire$$module$build$src$core$events$utils;module$build$src$core$events$utils.fromJson=fromJson$$module$build$src$core$events$utils;module$build$src$core$events$utils.get=get$$module$build$src$core$events$utils;module$build$src$core$events$utils.getDescendantIds=getDescendantIds$$module$build$src$core$events$utils; -module$build$src$core$events$utils.getGroup=getGroup$$module$build$src$core$events$utils;module$build$src$core$events$utils.getRecordUndo=getRecordUndo$$module$build$src$core$events$utils;module$build$src$core$events$utils.isEnabled=isEnabled$$module$build$src$core$events$utils;module$build$src$core$events$utils.setGroup=setGroup$$module$build$src$core$events$utils;module$build$src$core$events$utils.setRecordUndo=setRecordUndo$$module$build$src$core$events$utils;var inputTypes$$module$build$src$core$input_types;(function(a){a[a.VALUE=1]="VALUE";a[a.STATEMENT=3]="STATEMENT";a[a.DUMMY=5]="DUMMY"})(inputTypes$$module$build$src$core$input_types||(inputTypes$$module$build$src$core$input_types={}));$.module$build$src$core$input_types={};$.module$build$src$core$input_types.inputTypes=inputTypes$$module$build$src$core$input_types;var NAME_SPACE$$module$build$src$core$utils$xml,xmlDocument$$module$build$src$core$utils$xml;NAME_SPACE$$module$build$src$core$utils$xml="https://developers.google.com/blockly/xml";xmlDocument$$module$build$src$core$utils$xml=globalThis.document;$.module$build$src$core$utils$xml={};$.module$build$src$core$utils$xml.NAME_SPACE=NAME_SPACE$$module$build$src$core$utils$xml;$.module$build$src$core$utils$xml.createElement=createElement$$module$build$src$core$utils$xml; -$.module$build$src$core$utils$xml.createTextNode=createTextNode$$module$build$src$core$utils$xml;$.module$build$src$core$utils$xml.domToText=domToText$$module$build$src$core$utils$xml;$.module$build$src$core$utils$xml.getDocument=getDocument$$module$build$src$core$utils$xml;$.module$build$src$core$utils$xml.setDocument=setDocument$$module$build$src$core$utils$xml;$.module$build$src$core$utils$xml.textToDomDocument=textToDomDocument$$module$build$src$core$utils$xml;var alertImplementation$$module$build$src$core$dialog=function(a,b){window.alert(a);b&&b()},confirmImplementation$$module$build$src$core$dialog=function(a,b){b(window.confirm(a))},promptImplementation$$module$build$src$core$dialog=function(a,b,c){c(window.prompt(a,b))},TEST_ONLY$$module$build$src$core$dialog={confirmInternal:confirmInternal$$module$build$src$core$dialog},module$build$src$core$dialog={};module$build$src$core$dialog.TEST_ONLY=TEST_ONLY$$module$build$src$core$dialog; -module$build$src$core$dialog.alert=alert$$module$build$src$core$dialog;module$build$src$core$dialog.confirm=confirm$$module$build$src$core$dialog;module$build$src$core$dialog.prompt=prompt$$module$build$src$core$dialog;module$build$src$core$dialog.setAlert=setAlert$$module$build$src$core$dialog;module$build$src$core$dialog.setConfirm=setConfirm$$module$build$src$core$dialog;module$build$src$core$dialog.setPrompt=setPrompt$$module$build$src$core$dialog;var Msg$$module$build$src$core$msg,setLocale$$module$build$src$core$msg;Msg$$module$build$src$core$msg=Object.create(null);setLocale$$module$build$src$core$msg=function(a){Object.keys(a).forEach(function(b){Msg$$module$build$src$core$msg[b]=a[b]})};$.module$build$src$core$msg={};$.module$build$src$core$msg.Msg=Msg$$module$build$src$core$msg;$.module$build$src$core$msg.setLocale=setLocale$$module$build$src$core$msg;var Abstract$$module$build$src$core$events$events_abstract=class{constructor(){this.workspaceId=void 0;this.isUiEvent=!1;this.type="";this.group=getGroup$$module$build$src$core$events$utils();this.recordUndo=getRecordUndo$$module$build$src$core$events$utils()}toJson(){return{type:this.type,group:this.group}}fromJson(a){this.isBlank=!1;this.group=a.group||""}isNull(){return!1}run(a){}getEventWorkspace_(){let a;this.workspaceId&&(a=getWorkspaceById$$module$build$src$core$common(this.workspaceId));if(!a)throw Error("Workspace is null. Event must have been generated from real Blockly events."); -return a}},module$build$src$core$events$events_abstract={};module$build$src$core$events$events_abstract.Abstract=Abstract$$module$build$src$core$events$events_abstract;var VarBase$$module$build$src$core$events$events_var_base=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.isBlank="undefined"===typeof a;a&&(this.varId=a.getId(),this.workspaceId=a.workspace.id)}toJson(){const a=super.toJson();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");a.varId=this.varId;return a}fromJson(a){super.fromJson(a);this.varId=a.varId}},module$build$src$core$events$events_var_base= -{};module$build$src$core$events$events_var_base.VarBase=VarBase$$module$build$src$core$events$events_var_base;var VarCreate$$module$build$src$core$events$events_var_create=class extends VarBase$$module$build$src$core$events$events_var_base{constructor(a){super(a);this.type=VAR_CREATE$$module$build$src$core$events$utils;a&&(this.varType=a.type,this.varName=a.name)}toJson(){const a=super.toJson();if(!this.varType)throw Error("The var type is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson"); -a.varType=this.varType;a.varName=this.varName;return a}fromJson(a){super.fromJson(a);this.varType=a.varType;this.varName=a.varName}run(a){const b=this.getEventWorkspace_();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson");a?b.createVariable(this.varName,this.varType,this.varId):b.deleteVariableById(this.varId)}}; -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,VAR_CREATE$$module$build$src$core$events$utils,VarCreate$$module$build$src$core$events$events_var_create);var module$build$src$core$events$events_var_create={};module$build$src$core$events$events_var_create.VarCreate=VarCreate$$module$build$src$core$events$events_var_create;var VariableModel$$module$build$src$core$variable_model=class{constructor(a,b,c,d){this.workspace=a;this.name=b;this.type=c||"";this.id_=d||genUid$$module$build$src$core$utils$idgenerator();fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(VAR_CREATE$$module$build$src$core$events$utils))(this))}getId(){return this.id_}static compareByName(a,b){return a.name.localeCompare(b.name,void 0,{sensitivity:"base"})}},module$build$src$core$variable_model={}; -module$build$src$core$variable_model.VariableModel=VariableModel$$module$build$src$core$variable_model;var CATEGORY_NAME$$module$build$src$core$variables,VAR_LETTER_OPTIONS$$module$build$src$core$variables,TEST_ONLY$$module$build$src$core$variables;CATEGORY_NAME$$module$build$src$core$variables="VARIABLE";VAR_LETTER_OPTIONS$$module$build$src$core$variables="ijkmnopqrstuvwxyzabcdefgh";TEST_ONLY$$module$build$src$core$variables={generateUniqueNameInternal:generateUniqueNameInternal$$module$build$src$core$variables};$.module$build$src$core$variables={}; -$.module$build$src$core$variables.CATEGORY_NAME=CATEGORY_NAME$$module$build$src$core$variables;$.module$build$src$core$variables.TEST_ONLY=TEST_ONLY$$module$build$src$core$variables;$.module$build$src$core$variables.VAR_LETTER_OPTIONS=VAR_LETTER_OPTIONS$$module$build$src$core$variables;$.module$build$src$core$variables.allDeveloperVariables=allDeveloperVariables$$module$build$src$core$variables;$.module$build$src$core$variables.allUsedVarModels=allUsedVarModels$$module$build$src$core$variables; -$.module$build$src$core$variables.createVariableButtonHandler=createVariableButtonHandler$$module$build$src$core$variables;$.module$build$src$core$variables.flyoutCategory=flyoutCategory$$module$build$src$core$variables;$.module$build$src$core$variables.flyoutCategoryBlocks=flyoutCategoryBlocks$$module$build$src$core$variables;$.module$build$src$core$variables.generateUniqueName=generateUniqueName$$module$build$src$core$variables;$.module$build$src$core$variables.generateUniqueNameFromOptions=generateUniqueNameFromOptions$$module$build$src$core$variables; -$.module$build$src$core$variables.generateVariableFieldDom=generateVariableFieldDom$$module$build$src$core$variables;$.module$build$src$core$variables.getAddedVariables=getAddedVariables$$module$build$src$core$variables;$.module$build$src$core$variables.getOrCreateVariablePackage=getOrCreateVariablePackage$$module$build$src$core$variables;$.module$build$src$core$variables.getVariable=getVariable$$module$build$src$core$variables;$.module$build$src$core$variables.nameUsedWithAnyType=nameUsedWithAnyType$$module$build$src$core$variables; -$.module$build$src$core$variables.promptName=promptName$$module$build$src$core$variables;$.module$build$src$core$variables.renameVariable=renameVariable$$module$build$src$core$variables;var WorkspaceComment$$module$build$src$core$workspace_comment=class{constructor(a,b,c,d,e){this.workspace=a;this.editable_=this.movable_=this.deletable_=!0;this.disposed_=!1;this.isComment=!0;this.id=e&&!a.getCommentById(e)?e:genUid$$module$build$src$core$utils$idgenerator();a.addTopComment(this);this.xy_=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.height_=c;this.width_=d;this.RTL=a.RTL;this.content_=b;WorkspaceComment$$module$build$src$core$workspace_comment.fireCreateEvent(this)}dispose(){this.disposed_|| -(isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(COMMENT_DELETE$$module$build$src$core$events$utils))(this)),this.workspace.removeTopComment(this),this.disposed_=!0)}getHeight(){return this.height_}setHeight(a){this.height_=a}getWidth(){return this.width_}setWidth(a){this.width_=a}getXY(){return new Coordinate$$module$build$src$core$utils$coordinate(this.xy_.x,this.xy_.y)}moveBy(a,b){const c=new (get$$module$build$src$core$events$utils(COMMENT_MOVE$$module$build$src$core$events$utils))(this); -this.xy_.translate(a,b);c.recordNew();fire$$module$build$src$core$events$utils(c)}isDeletable(){return this.deletable_&&!(this.workspace&&this.workspace.options.readOnly)}setDeletable(a){this.deletable_=a}isMovable(){return this.movable_&&!(this.workspace&&this.workspace.options.readOnly)}setMovable(a){this.movable_=a}isEditable(){return this.editable_&&!(this.workspace&&this.workspace.options.readOnly)}setEditable(a){this.editable_=a}getContent(){return this.content_}setContent(a){this.content_!== -a&&(fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(COMMENT_CHANGE$$module$build$src$core$events$utils))(this,this.content_,a)),this.content_=a)}toXmlWithXY(a){a=this.toXml(a);a.setAttribute("x",`${Math.round(this.xy_.x)}`);a.setAttribute("y",`${Math.round(this.xy_.y)}`);a.setAttribute("h",`${this.height_}`);a.setAttribute("w",`${this.width_}`);return a}toXml(a){const b=createElement$$module$build$src$core$utils$xml("comment");a||(b.id=this.id);b.textContent= -this.getContent();return b}static fireCreateEvent(a){if(isEnabled$$module$build$src$core$events$utils()){const b=getGroup$$module$build$src$core$events$utils();b||setGroup$$module$build$src$core$events$utils(!0);try{fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(COMMENT_CREATE$$module$build$src$core$events$utils))(a))}finally{b||setGroup$$module$build$src$core$events$utils(!1)}}}static fromXml(a,b){var c=WorkspaceComment$$module$build$src$core$workspace_comment.parseAttributes(a); -b=new WorkspaceComment$$module$build$src$core$workspace_comment(b,c.content,c.h,c.w,c.id);c=a.getAttribute("x");a=a.getAttribute("y");c=c?parseInt(c,10):NaN;a=a?parseInt(a,10):NaN;isNaN(c)||isNaN(a)||b.moveBy(c,a);WorkspaceComment$$module$build$src$core$workspace_comment.fireCreateEvent(b);return b}static parseAttributes(a){const b=a.getAttribute("h"),c=a.getAttribute("w"),d=a.getAttribute("x"),e=a.getAttribute("y"),f=a.getAttribute("id");if(!f)throw Error("No ID present in XML comment definition."); -let g;return{id:f,h:b?parseInt(b):100,w:c?parseInt(c):100,x:d?parseInt(d):NaN,y:e?parseInt(e):NaN,content:null!=(g=a.textContent)?g:""}}},module$build$src$core$workspace_comment={};module$build$src$core$workspace_comment.WorkspaceComment=WorkspaceComment$$module$build$src$core$workspace_comment;var UiBase$$module$build$src$core$events$events_ui_base=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.isBlank=!0;this.recordUndo=!1;this.isUiEvent=!0;this.isBlank="undefined"===typeof a;this.workspaceId=a?a:""}},module$build$src$core$events$events_ui_base={};module$build$src$core$events$events_ui_base.UiBase=UiBase$$module$build$src$core$events$events_ui_base;var Selected$$module$build$src$core$events$events_selected=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c){super(c);this.type=SELECTED$$module$build$src$core$events$utils;this.oldElementId=null!=a?a:void 0;this.newElementId=null!=b?b:void 0}toJson(){const a=super.toJson();a.oldElementId=this.oldElementId;a.newElementId=this.newElementId;return a}fromJson(a){super.fromJson(a);this.oldElementId=a.oldElementId;this.newElementId=a.newElementId}}; -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,SELECTED$$module$build$src$core$events$utils,Selected$$module$build$src$core$events$events_selected);var module$build$src$core$events$events_selected={};module$build$src$core$events$events_selected.Selected=Selected$$module$build$src$core$events$events_selected;var injected$$module$build$src$core$css=!1,content$$module$build$src$core$css='\n.blocklySvg {\n background-color: #fff;\n outline: none;\n overflow: hidden; /* IE overflows by default. */\n position: absolute;\n display: block;\n}\n\n.blocklyWidgetDiv {\n display: none;\n position: absolute;\n z-index: 99999; /* big value for bootstrap3 compatibility */\n}\n\n.injectionDiv {\n height: 100%;\n position: relative;\n overflow: hidden; /* So blocks in drag surface disappear at edges */\n touch-action: none;\n}\n\n.blocklyNonSelectable {\n user-select: none;\n -ms-user-select: none;\n -webkit-user-select: none;\n}\n\n.blocklyWsDragSurface {\n display: none;\n position: absolute;\n top: 0;\n left: 0;\n}\n\n/* Added as a separate rule with multiple classes to make it more specific\n than a bootstrap rule that selects svg:root. See issue #1275 for context.\n*/\n.blocklyWsDragSurface.blocklyOverflowVisible {\n overflow: visible;\n}\n\n.blocklyBlockDragSurface {\n display: none;\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n overflow: visible !important;\n z-index: 50; /* Display below toolbox, but above everything else. */\n}\n\n.blocklyBlockCanvas.blocklyCanvasTransitioning,\n.blocklyBubbleCanvas.blocklyCanvasTransitioning {\n transition: transform .5s;\n}\n\n.blocklyTooltipDiv {\n background-color: #ffffc7;\n border: 1px solid #ddc;\n box-shadow: 4px 4px 20px 1px rgba(0,0,0,.15);\n color: #000;\n display: none;\n font: 9pt sans-serif;\n opacity: .9;\n padding: 2px;\n position: absolute;\n z-index: 100000; /* big value for bootstrap3 compatibility */\n}\n\n.blocklyDropDownDiv {\n position: absolute;\n left: 0;\n top: 0;\n z-index: 1000;\n display: none;\n border: 1px solid;\n border-color: #dadce0;\n background-color: #fff;\n border-radius: 2px;\n padding: 4px;\n box-shadow: 0 0 3px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownDiv.blocklyFocused {\n box-shadow: 0 0 6px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownContent {\n max-height: 300px; // @todo: spec for maximum height.\n overflow: auto;\n overflow-x: hidden;\n position: relative;\n}\n\n.blocklyDropDownArrow {\n position: absolute;\n left: 0;\n top: 0;\n width: 16px;\n height: 16px;\n z-index: -1;\n background-color: inherit;\n border-color: inherit;\n}\n\n.blocklyDropDownButton {\n display: inline-block;\n float: left;\n padding: 0;\n margin: 4px;\n border-radius: 4px;\n outline: none;\n border: 1px solid;\n transition: box-shadow .1s;\n cursor: pointer;\n}\n\n.blocklyArrowTop {\n border-top: 1px solid;\n border-left: 1px solid;\n border-top-left-radius: 4px;\n border-color: inherit;\n}\n\n.blocklyArrowBottom {\n border-bottom: 1px solid;\n border-right: 1px solid;\n border-bottom-right-radius: 4px;\n border-color: inherit;\n}\n\n.blocklyResizeSE {\n cursor: se-resize;\n fill: #aaa;\n}\n\n.blocklyResizeSW {\n cursor: sw-resize;\n fill: #aaa;\n}\n\n.blocklyResizeLine {\n stroke: #515A5A;\n stroke-width: 1;\n}\n\n.blocklyHighlightedConnectionPath {\n fill: none;\n stroke: #fc3;\n stroke-width: 4px;\n}\n\n.blocklyPathLight {\n fill: none;\n stroke-linecap: round;\n stroke-width: 1;\n}\n\n.blocklySelected>.blocklyPathLight {\n display: none;\n}\n\n.blocklyDraggable {\n /* backup for browsers (e.g. IE11) that don\'t support grab */\n cursor: url("<<>>/handopen.cur"), auto;\n cursor: grab;\n cursor: -webkit-grab;\n}\n\n /* backup for browsers (e.g. IE11) that don\'t support grabbing */\n.blocklyDragging {\n /* backup for browsers (e.g. IE11) that don\'t support grabbing */\n cursor: url("<<>>/handclosed.cur"), auto;\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n /* Changes cursor on mouse down. Not effective in Firefox because of\n https://bugzilla.mozilla.org/show_bug.cgi?id=771241 */\n.blocklyDraggable:active {\n /* backup for browsers (e.g. IE11) that don\'t support grabbing */\n cursor: url("<<>>/handclosed.cur"), auto;\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n/* Change the cursor on the whole drag surface in case the mouse gets\n ahead of block during a drag. This way the cursor is still a closed hand.\n */\n.blocklyBlockDragSurface .blocklyDraggable {\n /* backup for browsers (e.g. IE11) that don\'t support grabbing */\n cursor: url("<<>>/handclosed.cur"), auto;\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n.blocklyDragging.blocklyDraggingDelete {\n cursor: url("<<>>/handdelete.cur"), auto;\n}\n\n.blocklyDragging>.blocklyPath,\n.blocklyDragging>.blocklyPathLight {\n fill-opacity: .8;\n stroke-opacity: .8;\n}\n\n.blocklyDragging>.blocklyPathDark {\n display: none;\n}\n\n.blocklyDisabled>.blocklyPath {\n fill-opacity: .5;\n stroke-opacity: .5;\n}\n\n.blocklyDisabled>.blocklyPathLight,\n.blocklyDisabled>.blocklyPathDark {\n display: none;\n}\n\n.blocklyInsertionMarker>.blocklyPath,\n.blocklyInsertionMarker>.blocklyPathLight,\n.blocklyInsertionMarker>.blocklyPathDark {\n fill-opacity: .2;\n stroke: none;\n}\n\n.blocklyMultilineText {\n font-family: monospace;\n}\n\n.blocklyNonEditableText>text {\n pointer-events: none;\n}\n\n.blocklyFlyout {\n position: absolute;\n z-index: 20;\n}\n\n.blocklyText text {\n cursor: default;\n}\n\n/*\n Don\'t allow users to select text. It gets annoying when trying to\n drag a block and selected text moves instead.\n*/\n.blocklySvg text,\n.blocklyBlockDragSurface text {\n user-select: none;\n -ms-user-select: none;\n -webkit-user-select: none;\n cursor: inherit;\n}\n\n.blocklyHidden {\n display: none;\n}\n\n.blocklyFieldDropdown:not(.blocklyHidden) {\n display: block;\n}\n\n.blocklyIconGroup {\n cursor: default;\n}\n\n.blocklyIconGroup:not(:hover),\n.blocklyIconGroupReadonly {\n opacity: .6;\n}\n\n.blocklyIconShape {\n fill: #00f;\n stroke: #fff;\n stroke-width: 1px;\n}\n\n.blocklyIconSymbol {\n fill: #fff;\n}\n\n.blocklyMinimalBody {\n margin: 0;\n padding: 0;\n}\n\n.blocklyHtmlInput {\n border: none;\n border-radius: 4px;\n height: 100%;\n margin: 0;\n outline: none;\n padding: 0;\n width: 100%;\n text-align: center;\n display: block;\n box-sizing: border-box;\n}\n\n/* Edge and IE introduce a close icon when the input value is longer than a\n certain length. This affects our sizing calculations of the text input.\n Hiding the close icon to avoid that. */\n.blocklyHtmlInput::-ms-clear {\n display: none;\n}\n\n.blocklyMainBackground {\n stroke-width: 1;\n stroke: #c6c6c6; /* Equates to #ddd due to border being off-pixel. */\n}\n\n.blocklyMutatorBackground {\n fill: #fff;\n stroke: #ddd;\n stroke-width: 1;\n}\n\n.blocklyFlyoutBackground {\n fill: #ddd;\n fill-opacity: .8;\n}\n\n.blocklyMainWorkspaceScrollbar {\n z-index: 20;\n}\n\n.blocklyFlyoutScrollbar {\n z-index: 30;\n}\n\n.blocklyScrollbarHorizontal,\n.blocklyScrollbarVertical {\n position: absolute;\n outline: none;\n}\n\n.blocklyScrollbarBackground {\n opacity: 0;\n}\n\n.blocklyScrollbarHandle {\n fill: #ccc;\n}\n\n.blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,\n.blocklyScrollbarHandle:hover {\n fill: #bbb;\n}\n\n/* Darken flyout scrollbars due to being on a grey background. */\n/* By contrast, workspace scrollbars are on a white background. */\n.blocklyFlyout .blocklyScrollbarHandle {\n fill: #bbb;\n}\n\n.blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,\n.blocklyFlyout .blocklyScrollbarHandle:hover {\n fill: #aaa;\n}\n\n.blocklyInvalidInput {\n background: #faa;\n}\n\n.blocklyVerticalMarker {\n stroke-width: 3px;\n fill: rgba(255,255,255,.5);\n pointer-events: none;\n}\n\n.blocklyComputeCanvas {\n position: absolute;\n width: 0;\n height: 0;\n}\n\n.blocklyNoPointerEvents {\n pointer-events: none;\n}\n\n.blocklyContextMenu {\n border-radius: 4px;\n max-height: 100%;\n}\n\n.blocklyDropdownMenu {\n border-radius: 2px;\n padding: 0 !important;\n}\n\n.blocklyDropdownMenu .blocklyMenuItem {\n /* 28px on the left for icon or checkbox. */\n padding-left: 28px;\n}\n\n/* BiDi override for the resting state. */\n.blocklyDropdownMenu .blocklyMenuItemRtl {\n /* Flip left/right padding for BiDi. */\n padding-left: 5px;\n padding-right: 28px;\n}\n\n.blocklyWidgetDiv .blocklyMenu {\n background: #fff;\n border: 1px solid transparent;\n box-shadow: 0 0 3px 1px rgba(0,0,0,.3);\n font: normal 13px Arial, sans-serif;\n margin: 0;\n outline: none;\n padding: 4px 0;\n position: absolute;\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 100%;\n z-index: 20000; /* Arbitrary, but some apps depend on it... */\n}\n\n.blocklyWidgetDiv .blocklyMenu.blocklyFocused {\n box-shadow: 0 0 6px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownDiv .blocklyMenu {\n background: inherit; /* Compatibility with gapi, reset from goog-menu */\n border: inherit; /* Compatibility with gapi, reset from goog-menu */\n font: normal 13px "Helvetica Neue", Helvetica, sans-serif;\n outline: none;\n position: relative; /* Compatibility with gapi, reset from goog-menu */\n z-index: 20000; /* Arbitrary, but some apps depend on it... */\n}\n\n/* State: resting. */\n.blocklyMenuItem {\n border: none;\n color: #000;\n cursor: pointer;\n list-style: none;\n margin: 0;\n /* 7em on the right for shortcut. */\n min-width: 7em;\n padding: 6px 15px;\n white-space: nowrap;\n}\n\n/* State: disabled. */\n.blocklyMenuItemDisabled {\n color: #ccc;\n cursor: inherit;\n}\n\n/* State: hover. */\n.blocklyMenuItemHighlight {\n background-color: rgba(0,0,0,.1);\n}\n\n/* State: selected/checked. */\n.blocklyMenuItemCheckbox {\n height: 16px;\n position: absolute;\n width: 16px;\n}\n\n.blocklyMenuItemSelected .blocklyMenuItemCheckbox {\n background: url(<<>>/sprites.png) no-repeat -48px -16px;\n float: left;\n margin-left: -24px;\n position: static; /* Scroll with the menu. */\n}\n\n.blocklyMenuItemRtl .blocklyMenuItemCheckbox {\n float: right;\n margin-right: -24px;\n}\n', -module$build$src$core$css={};module$build$src$core$css.inject=inject$$module$build$src$core$css;module$build$src$core$css.register=register$$module$build$src$core$css;var Svg$$module$build$src$core$utils$svg=class{constructor(a){this.tagName=a}toString(){return this.tagName}};Svg$$module$build$src$core$utils$svg.ANIMATE=new Svg$$module$build$src$core$utils$svg("animate");Svg$$module$build$src$core$utils$svg.CIRCLE=new Svg$$module$build$src$core$utils$svg("circle");Svg$$module$build$src$core$utils$svg.CLIPPATH=new Svg$$module$build$src$core$utils$svg("clipPath");Svg$$module$build$src$core$utils$svg.DEFS=new Svg$$module$build$src$core$utils$svg("defs"); -Svg$$module$build$src$core$utils$svg.FECOMPOSITE=new Svg$$module$build$src$core$utils$svg("feComposite");Svg$$module$build$src$core$utils$svg.FECOMPONENTTRANSFER=new Svg$$module$build$src$core$utils$svg("feComponentTransfer");Svg$$module$build$src$core$utils$svg.FEFLOOD=new Svg$$module$build$src$core$utils$svg("feFlood");Svg$$module$build$src$core$utils$svg.FEFUNCA=new Svg$$module$build$src$core$utils$svg("feFuncA");Svg$$module$build$src$core$utils$svg.FEGAUSSIANBLUR=new Svg$$module$build$src$core$utils$svg("feGaussianBlur"); -Svg$$module$build$src$core$utils$svg.FEPOINTLIGHT=new Svg$$module$build$src$core$utils$svg("fePointLight");Svg$$module$build$src$core$utils$svg.FESPECULARLIGHTING=new Svg$$module$build$src$core$utils$svg("feSpecularLighting");Svg$$module$build$src$core$utils$svg.FILTER=new Svg$$module$build$src$core$utils$svg("filter");Svg$$module$build$src$core$utils$svg.FOREIGNOBJECT=new Svg$$module$build$src$core$utils$svg("foreignObject");Svg$$module$build$src$core$utils$svg.G=new Svg$$module$build$src$core$utils$svg("g"); -Svg$$module$build$src$core$utils$svg.IMAGE=new Svg$$module$build$src$core$utils$svg("image");Svg$$module$build$src$core$utils$svg.LINE=new Svg$$module$build$src$core$utils$svg("line");Svg$$module$build$src$core$utils$svg.PATH=new Svg$$module$build$src$core$utils$svg("path");Svg$$module$build$src$core$utils$svg.PATTERN=new Svg$$module$build$src$core$utils$svg("pattern");Svg$$module$build$src$core$utils$svg.POLYGON=new Svg$$module$build$src$core$utils$svg("polygon"); -Svg$$module$build$src$core$utils$svg.RECT=new Svg$$module$build$src$core$utils$svg("rect");Svg$$module$build$src$core$utils$svg.SVG=new Svg$$module$build$src$core$utils$svg("svg");Svg$$module$build$src$core$utils$svg.TEXT=new Svg$$module$build$src$core$utils$svg("text");Svg$$module$build$src$core$utils$svg.TSPAN=new Svg$$module$build$src$core$utils$svg("tspan");var module$build$src$core$utils$svg={};module$build$src$core$utils$svg.Svg=Svg$$module$build$src$core$utils$svg;var XY_REGEX$$module$build$src$core$utils$svg_math=/translate\(\s*([-+\d.e]+)([ ,]\s*([-+\d.e]+)\s*)?/,XY_STYLE_REGEX$$module$build$src$core$utils$svg_math=/transform:\s*translate(?:3d)?\(\s*([-+\d.e]+)\s*px([ ,]\s*([-+\d.e]+)\s*px)?/,TEST_ONLY$$module$build$src$core$utils$svg_math={XY_REGEX:XY_REGEX$$module$build$src$core$utils$svg_math,XY_STYLE_REGEX:XY_STYLE_REGEX$$module$build$src$core$utils$svg_math},module$build$src$core$utils$svg_math={};module$build$src$core$utils$svg_math.TEST_ONLY=TEST_ONLY$$module$build$src$core$utils$svg_math; -module$build$src$core$utils$svg_math.getDocumentScroll=getDocumentScroll$$module$build$src$core$utils$svg_math;module$build$src$core$utils$svg_math.getInjectionDivXY=getInjectionDivXY$$module$build$src$core$utils$svg_math;module$build$src$core$utils$svg_math.getRelativeXY=getRelativeXY$$module$build$src$core$utils$svg_math;module$build$src$core$utils$svg_math.getViewportBBox=getViewportBBox$$module$build$src$core$utils$svg_math;module$build$src$core$utils$svg_math.is3dSupported=is3dSupported$$module$build$src$core$utils$svg_math; -module$build$src$core$utils$svg_math.screenToWsCoordinates=screenToWsCoordinates$$module$build$src$core$utils$svg_math;var RESIZE_SIZE$$module$build$src$core$workspace_comment_svg=8,BORDER_RADIUS$$module$build$src$core$workspace_comment_svg=3,TEXTAREA_OFFSET$$module$build$src$core$workspace_comment_svg=2,WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg=class extends WorkspaceComment$$module$build$src$core$workspace_comment{constructor(a,b,c,d,e){super(a,b,c,d,e);this.onMouseMoveWrapper_=this.onMouseUpWrapper_=null;this.eventsInit_=!1;this.deleteIconBorder_=this.deleteGroup_=this.resizeGroup_=this.foreignObject_= -this.svgHandleTarget_=this.svgRectTarget_=this.textarea_=null;this.rendered_=this.autoLayout_=this.focused_=!1;this.svgGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyComment"});this.svgGroup_.translate_="";this.workspace=a;this.svgRect_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyCommentRect",x:0,y:0,rx:BORDER_RADIUS$$module$build$src$core$workspace_comment_svg,ry:BORDER_RADIUS$$module$build$src$core$workspace_comment_svg}); -this.svgGroup_.appendChild(this.svgRect_);this.useDragSurface_=!!a.getBlockDragSurface();this.render()}dispose(){this.disposed_||(getSelected$$module$build$src$core$common()===this&&(this.unselect(),this.workspace.cancelCurrentGesture()),isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(COMMENT_DELETE$$module$build$src$core$events$utils))(this)),removeNode$$module$build$src$core$utils$dom(this.svgGroup_),this.disposeInternal_(), -disable$$module$build$src$core$events$utils(),super.dispose(),enable$$module$build$src$core$events$utils())}initSvg(a){if(!this.workspace.rendered)throw TypeError("Workspace is headless.");this.workspace.options.readOnly||this.eventsInit_||(conditionalBind$$module$build$src$core$browser_events(this.svgRectTarget_,"mousedown",this,this.pathMouseDown_),conditionalBind$$module$build$src$core$browser_events(this.svgHandleTarget_,"mousedown",this,this.pathMouseDown_));this.eventsInit_=!0;this.updateMovable(); -this.getSvgRoot().parentNode||this.workspace.getBubbleCanvas().appendChild(this.getSvgRoot());!a&&this.textarea_&&this.textarea_.select()}pathMouseDown_(a){const b=this.workspace.getGesture(a);b&&b.handleBubbleStart(a,this)}showContextMenu(a){throw Error("The implementation of showContextMenu should be monkey-patched in by blockly.ts");}select(){if(getSelected$$module$build$src$core$common()!==this){var a=null;if(getSelected$$module$build$src$core$common()){a=getSelected$$module$build$src$core$common().id; -disable$$module$build$src$core$events$utils();try{getSelected$$module$build$src$core$common().unselect()}finally{enable$$module$build$src$core$events$utils()}}a=new (get$$module$build$src$core$events$utils(SELECTED$$module$build$src$core$events$utils))(a,this.id,this.workspace.id);fire$$module$build$src$core$events$utils(a);setSelected$$module$build$src$core$common(this);this.addSelect()}}unselect(){if(getSelected$$module$build$src$core$common()===this){var a=new (get$$module$build$src$core$events$utils(SELECTED$$module$build$src$core$events$utils))(this.id, -null,this.workspace.id);fire$$module$build$src$core$events$utils(a);setSelected$$module$build$src$core$common(null);this.removeSelect();this.blurFocus()}}addSelect(){addClass$$module$build$src$core$utils$dom(this.svgGroup_,"blocklySelected");this.setFocus()}removeSelect(){addClass$$module$build$src$core$utils$dom(this.svgGroup_,"blocklySelected");this.blurFocus()}addFocus(){addClass$$module$build$src$core$utils$dom(this.svgGroup_,"blocklyFocused")}removeFocus(){removeClass$$module$build$src$core$utils$dom(this.svgGroup_, -"blocklyFocused")}getRelativeToSurfaceXY(){let a=0,b=0;const c=this.useDragSurface_?this.workspace.getBlockDragSurface().getGroup():null;let d=this.getSvgRoot();if(d){do{var e=getRelativeXY$$module$build$src$core$utils$svg_math(d);a+=e.x;b+=e.y;this.useDragSurface_&&this.workspace.getBlockDragSurface().getCurrentBlock()===d&&(e=this.workspace.getBlockDragSurface().getSurfaceTranslation(),a+=e.x,b+=e.y);d=d.parentNode}while(d&&d!==this.workspace.getBubbleCanvas()&&d!==c)}return this.xy_=new Coordinate$$module$build$src$core$utils$coordinate(a, -b)}moveBy(a,b){const c=new (get$$module$build$src$core$events$utils(COMMENT_MOVE$$module$build$src$core$events$utils))(this),d=this.getRelativeToSurfaceXY();this.translate(d.x+a,d.y+b);this.xy_=new Coordinate$$module$build$src$core$utils$coordinate(d.x+a,d.y+b);c.recordNew();fire$$module$build$src$core$events$utils(c);this.workspace.resizeContents()}translate(a,b){this.xy_=new Coordinate$$module$build$src$core$utils$coordinate(a,b);this.getSvgRoot().setAttribute("transform","translate("+a+","+b+")")}moveToDragSurface(){if(this.useDragSurface_){var a= -this.getRelativeToSurfaceXY();this.clearTransformAttributes_();this.workspace.getBlockDragSurface().translateSurface(a.x,a.y);this.workspace.getBlockDragSurface().setBlocksAndShow(this.getSvgRoot())}}moveDuringDrag(a,b){a?a.translateSurface(b.x,b.y):(this.svgGroup_.translate_="translate("+b.x+","+b.y+")",this.svgGroup_.setAttribute("transform",this.svgGroup_.translate_+this.svgGroup_.skew_))}moveTo(a,b){this.translate(a,b)}clearTransformAttributes_(){this.getSvgRoot().removeAttribute("transform")}getBoundingRectangle(){var a= -this.getRelativeToSurfaceXY();const b=this.getHeightWidth(),c=a.y,d=a.y+b.height;let e;this.RTL?(e=a.x-b.width,a=a.x):(e=a.x,a=a.x+b.width);return new Rect$$module$build$src$core$utils$rect(c,d,e,a)}updateMovable(){this.isMovable()?addClass$$module$build$src$core$utils$dom(this.svgGroup_,"blocklyDraggable"):removeClass$$module$build$src$core$utils$dom(this.svgGroup_,"blocklyDraggable")}setMovable(a){super.setMovable(a);this.updateMovable()}setEditable(a){super.setEditable(a);this.textarea_&&(this.textarea_.readOnly= -!a)}setDragging(a){a?(a=this.getSvgRoot(),a.translate_="",a.skew_="",addClass$$module$build$src$core$utils$dom(this.svgGroup_,"blocklyDragging")):removeClass$$module$build$src$core$utils$dom(this.svgGroup_,"blocklyDragging")}getSvgRoot(){return this.svgGroup_}getContent(){return this.textarea_?this.textarea_.value:this.content_}setContent(a){super.setContent(a);this.textarea_&&(this.textarea_.value=a)}setDeleteStyle(a){a?addClass$$module$build$src$core$utils$dom(this.svgGroup_,"blocklyDraggingDelete"): -removeClass$$module$build$src$core$utils$dom(this.svgGroup_,"blocklyDraggingDelete")}setAutoLayout(a){}toXmlWithXY(a){let b=0;this.workspace.RTL&&(b=this.workspace.getWidth());a=this.toXml(a);const c=this.getRelativeToSurfaceXY();a.setAttribute("x",Math.round(this.workspace.RTL?b-c.x:c.x));a.setAttribute("y",Math.round(c.y));a.setAttribute("h",this.getHeight());a.setAttribute("w",this.getWidth());return a}toCopyData(){return{saveInfo:this.toXmlWithXY(),source:this.workspace,typeCounts:null}}getHeightWidth(){return{width:this.getWidth(), -height:this.getHeight()}}render(){if(!this.rendered_){var a=this.getHeightWidth();this.createEditor_();this.svgGroup_.appendChild(this.foreignObject_);this.svgHandleTarget_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyCommentHandleTarget",x:0,y:0});this.svgGroup_.appendChild(this.svgHandleTarget_);this.svgRectTarget_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyCommentTarget", -x:0,y:0,rx:BORDER_RADIUS$$module$build$src$core$workspace_comment_svg,ry:BORDER_RADIUS$$module$build$src$core$workspace_comment_svg});this.svgGroup_.appendChild(this.svgRectTarget_);this.addResizeDom_();this.isDeletable()&&this.addDeleteDom_();this.setSize_(a.width,a.height);this.textarea_.value=this.content_;this.rendered_=!0;this.resizeGroup_&&conditionalBind$$module$build$src$core$browser_events(this.resizeGroup_,"mousedown",this,this.resizeMouseDown_);this.isDeletable()&&(conditionalBind$$module$build$src$core$browser_events(this.deleteGroup_, -"mousedown",this,this.deleteMouseDown_),conditionalBind$$module$build$src$core$browser_events(this.deleteGroup_,"mouseout",this,this.deleteMouseOut_),conditionalBind$$module$build$src$core$browser_events(this.deleteGroup_,"mouseup",this,this.deleteMouseUp_))}}createEditor_(){this.foreignObject_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FOREIGNOBJECT,{x:0,y:WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg.TOP_OFFSET,"class":"blocklyCommentForeignObject"}); -const a=document.createElementNS(HTML_NS$$module$build$src$core$utils$dom,"body");a.setAttribute("xmlns",HTML_NS$$module$build$src$core$utils$dom);a.className="blocklyMinimalBody";const b=document.createElementNS(HTML_NS$$module$build$src$core$utils$dom,"textarea");b.className="blocklyCommentTextarea";b.setAttribute("dir",this.RTL?"RTL":"LTR");b.readOnly=!this.isEditable();a.appendChild(b);this.textarea_=b;this.foreignObject_.appendChild(a);conditionalBind$$module$build$src$core$browser_events(b, -"wheel",this,function(c){c.stopPropagation()});conditionalBind$$module$build$src$core$browser_events(b,"change",this,function(c){this.setContent(b.value)});return this.foreignObject_}addResizeDom_(){this.resizeGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":this.RTL?"blocklyResizeSW":"blocklyResizeSE"},this.svgGroup_);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.POLYGON,{points:"0,x x,x x,0".replace(/x/g, -RESIZE_SIZE$$module$build$src$core$workspace_comment_svg.toString())},this.resizeGroup_);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{"class":"blocklyResizeLine",x1:RESIZE_SIZE$$module$build$src$core$workspace_comment_svg/3,y1:RESIZE_SIZE$$module$build$src$core$workspace_comment_svg-1,x2:RESIZE_SIZE$$module$build$src$core$workspace_comment_svg-1,y2:RESIZE_SIZE$$module$build$src$core$workspace_comment_svg/3},this.resizeGroup_);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE, -{"class":"blocklyResizeLine",x1:2*RESIZE_SIZE$$module$build$src$core$workspace_comment_svg/3,y1:RESIZE_SIZE$$module$build$src$core$workspace_comment_svg-1,x2:RESIZE_SIZE$$module$build$src$core$workspace_comment_svg-1,y2:2*RESIZE_SIZE$$module$build$src$core$workspace_comment_svg/3},this.resizeGroup_)}addDeleteDom_(){this.deleteGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyCommentDeleteIcon"},this.svgGroup_);this.deleteIconBorder_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CIRCLE, -{"class":"blocklyDeleteIconShape",r:"7",cx:"7.5",cy:"7.5"},this.deleteGroup_);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{x1:"5",y1:"10",x2:"10",y2:"5",stroke:"#fff","stroke-width":"2"},this.deleteGroup_);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{x1:"5",y1:"5",x2:"10",y2:"10",stroke:"#fff","stroke-width":"2"},this.deleteGroup_)}resizeMouseDown_(a){this.unbindDragEvents_();isRightButton$$module$build$src$core$browser_events(a)|| -(this.workspace.startDrag(a,new Coordinate$$module$build$src$core$utils$coordinate(this.workspace.RTL?-this.width_:this.width_,this.height_)),this.onMouseUpWrapper_=conditionalBind$$module$build$src$core$browser_events(document,"mouseup",this,this.resizeMouseUp_),this.onMouseMoveWrapper_=conditionalBind$$module$build$src$core$browser_events(document,"mousemove",this,this.resizeMouseMove_),this.workspace.hideChaff());a.stopPropagation()}deleteMouseDown_(a){this.deleteIconBorder_&&addClass$$module$build$src$core$utils$dom(this.deleteIconBorder_, -"blocklyDeleteIconHighlighted");a.stopPropagation()}deleteMouseOut_(a){this.deleteIconBorder_&&removeClass$$module$build$src$core$utils$dom(this.deleteIconBorder_,"blocklyDeleteIconHighlighted")}deleteMouseUp_(a){this.dispose();a.stopPropagation()}unbindDragEvents_(){this.onMouseUpWrapper_&&(unbind$$module$build$src$core$browser_events(this.onMouseUpWrapper_),this.onMouseUpWrapper_=null);this.onMouseMoveWrapper_&&(unbind$$module$build$src$core$browser_events(this.onMouseMoveWrapper_),this.onMouseMoveWrapper_= -null)}resizeMouseUp_(a){clearTouchIdentifier$$module$build$src$core$touch();this.unbindDragEvents_()}resizeMouseMove_(a){this.autoLayout_=!1;a=this.workspace.moveDrag(a);this.setSize_(this.RTL?-a.x:a.x,a.y)}resizeComment_(){const a=this.getHeightWidth(),b=WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg.TOP_OFFSET,c=2*TEXTAREA_OFFSET$$module$build$src$core$workspace_comment_svg;this.foreignObject_.setAttribute("width",a.width);this.foreignObject_.setAttribute("height",(a.height-b).toString()); -this.RTL&&this.foreignObject_.setAttribute("x",(-a.width).toString());this.textarea_.style.width=a.width-c+"px";this.textarea_.style.height=a.height-c-b+"px"}setSize_(a,b){a=Math.max(a,45);b=Math.max(b,20+WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg.TOP_OFFSET);this.width_=a;this.height_=b;this.svgRect_.setAttribute("width",a);this.svgRect_.setAttribute("height",b);this.svgRectTarget_.setAttribute("width",a);this.svgRectTarget_.setAttribute("height",b);this.svgHandleTarget_.setAttribute("width", -a);this.svgHandleTarget_.setAttribute("height",WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg.TOP_OFFSET);this.RTL&&(this.svgRect_.setAttribute("transform","scale(-1 1)"),this.svgRectTarget_.setAttribute("transform","scale(-1 1)"));this.resizeGroup_&&(this.RTL?(this.resizeGroup_.setAttribute("transform","translate("+(-a+RESIZE_SIZE$$module$build$src$core$workspace_comment_svg)+","+(b-RESIZE_SIZE$$module$build$src$core$workspace_comment_svg)+") scale(-1 1)"),this.deleteGroup_.setAttribute("transform", -"translate("+(-a+RESIZE_SIZE$$module$build$src$core$workspace_comment_svg)+","+-RESIZE_SIZE$$module$build$src$core$workspace_comment_svg+") scale(-1 1)")):(this.resizeGroup_.setAttribute("transform","translate("+(a-RESIZE_SIZE$$module$build$src$core$workspace_comment_svg)+","+(b-RESIZE_SIZE$$module$build$src$core$workspace_comment_svg)+")"),this.deleteGroup_.setAttribute("transform","translate("+(a-RESIZE_SIZE$$module$build$src$core$workspace_comment_svg)+","+-RESIZE_SIZE$$module$build$src$core$workspace_comment_svg+ -")")));this.resizeComment_()}disposeInternal_(){this.svgHandleTarget_=this.svgRectTarget_=this.foreignObject_=this.textarea_=null;this.disposed_=!0}setFocus(){this.focused_=!0;setTimeout(()=>{this.disposed_||(this.textarea_.focus(),this.addFocus(),this.svgRectTarget_&&addClass$$module$build$src$core$utils$dom(this.svgRectTarget_,"blocklyCommentTargetFocused"),this.svgHandleTarget_&&addClass$$module$build$src$core$utils$dom(this.svgHandleTarget_,"blocklyCommentHandleTargetFocused"))},0)}blurFocus(){this.focused_= -!1;setTimeout(()=>{this.disposed_||(this.textarea_.blur(),this.removeFocus(),this.svgRectTarget_&&removeClass$$module$build$src$core$utils$dom(this.svgRectTarget_,"blocklyCommentTargetFocused"),this.svgHandleTarget_&&removeClass$$module$build$src$core$utils$dom(this.svgHandleTarget_,"blocklyCommentHandleTargetFocused"))},0)}static fromXmlRendered(a,b,c){disable$$module$build$src$core$events$utils();let d;try{const e=WorkspaceComment$$module$build$src$core$workspace_comment.parseAttributes(a);d=new WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg(b, -e.content,e.h,e.w,e.id);b.rendered&&(d.initSvg(!0),d.render());if(!isNaN(e.x)&&!isNaN(e.y))if(b.RTL){const f=c||b.getWidth();d.moveBy(f-e.x,e.y)}else d.moveBy(e.x,e.y)}finally{enable$$module$build$src$core$events$utils()}WorkspaceComment$$module$build$src$core$workspace_comment.fireCreateEvent(d);return d}};WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg.DEFAULT_SIZE=100;WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg.TOP_OFFSET=10;register$$module$build$src$core$css("\n.blocklyCommentForeignObject {\n position: relative;\n z-index: 0;\n}\n\n.blocklyCommentRect {\n fill: #E7DE8E;\n stroke: #bcA903;\n stroke-width: 1px;\n}\n\n.blocklyCommentTarget {\n fill: transparent;\n stroke: #bcA903;\n}\n\n.blocklyCommentTargetFocused {\n fill: none;\n}\n\n.blocklyCommentHandleTarget {\n fill: none;\n}\n\n.blocklyCommentHandleTargetFocused {\n fill: transparent;\n}\n\n.blocklyFocused>.blocklyCommentRect {\n fill: #B9B272;\n stroke: #B9B272;\n}\n\n.blocklySelected>.blocklyCommentTarget {\n stroke: #fc3;\n stroke-width: 3px;\n}\n\n.blocklyCommentDeleteIcon {\n cursor: pointer;\n fill: #000;\n display: none;\n}\n\n.blocklySelected > .blocklyCommentDeleteIcon {\n display: block;\n}\n\n.blocklyDeleteIconShape {\n fill: #000;\n stroke: #000;\n stroke-width: 1px;\n}\n\n.blocklyDeleteIconShape.blocklyDeleteIconHighlighted {\n stroke: #fc3;\n}\n"); -var module$build$src$core$workspace_comment_svg={};module$build$src$core$workspace_comment_svg.WorkspaceCommentSvg=WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg;$.module$build$src$core$xml={};$.module$build$src$core$xml.appendDomToWorkspace=appendDomToWorkspace$$module$build$src$core$xml;$.module$build$src$core$xml.blockToDom=blockToDom$$module$build$src$core$xml;$.module$build$src$core$xml.blockToDomWithXY=blockToDomWithXY$$module$build$src$core$xml;$.module$build$src$core$xml.clearWorkspaceAndLoadFromXml=clearWorkspaceAndLoadFromXml$$module$build$src$core$xml;$.module$build$src$core$xml.deleteNext=deleteNext$$module$build$src$core$xml; -$.module$build$src$core$xml.domToBlock=domToBlock$$module$build$src$core$xml;$.module$build$src$core$xml.domToPrettyText=domToPrettyText$$module$build$src$core$xml;$.module$build$src$core$xml.domToText=domToText$$module$build$src$core$xml;$.module$build$src$core$xml.domToVariables=domToVariables$$module$build$src$core$xml;$.module$build$src$core$xml.domToWorkspace=domToWorkspace$$module$build$src$core$xml;$.module$build$src$core$xml.textToDom=textToDom$$module$build$src$core$xml; -$.module$build$src$core$xml.variablesToDom=variablesToDom$$module$build$src$core$xml;$.module$build$src$core$xml.workspaceToDom=workspaceToDom$$module$build$src$core$xml;var BlockBase$$module$build$src$core$events$events_block_base=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.isBlank=!!a;a&&(this.blockId=a.id,this.workspaceId=a.workspace.id)}toJson(){const a=super.toJson();if(!this.blockId)throw Error("The block ID is undefined. Either pass a block to the constructor, or call fromJson");a.blockId=this.blockId;return a}fromJson(a){super.fromJson(a);this.blockId=a.blockId}},module$build$src$core$events$events_block_base= -{};module$build$src$core$events$events_block_base.BlockBase=BlockBase$$module$build$src$core$events$events_block_base;var BlockChange$$module$build$src$core$events$events_block_change=class extends BlockBase$$module$build$src$core$events$events_block_base{constructor(a,b,c,d,e){super(a);this.type=CHANGE$$module$build$src$core$events$utils;a&&(this.element=b,this.name=c||void 0,this.oldValue=d,this.newValue=e)}toJson(){const a=super.toJson();if(!this.element)throw Error("The changed element is undefined. Either pass an element to the constructor, or call fromJson");a.element=this.element;a.name=this.name;a.oldValue= -this.oldValue;a.newValue=this.newValue;return a}fromJson(a){super.fromJson(a);this.element=a.element;this.name=a.name;this.oldValue=a.oldValue;this.newValue=a.newValue}isNull(){return this.oldValue===this.newValue}run(a){var b=this.getEventWorkspace_();if(!this.blockId)throw Error("The block ID is undefined. Either pass a block to the constructor, or call fromJson");b=b.getBlockById(this.blockId);if(!b)throw Error("The associated block is undefined. Either pass a block to the constructor, or call fromJson"); -b.mutator&&b.mutator.setVisible(!1);a=a?this.newValue:this.oldValue;switch(this.element){case "field":(b=b.getField(this.name))?b.setValue(a):console.warn("Can't set non-existent field: "+this.name);break;case "comment":b.setCommentText(a||null);break;case "collapsed":b.setCollapsed(!!a);break;case "disabled":b.setEnabled(!a);break;case "inline":b.setInputsInline(!!a);break;case "mutation":const c=BlockChange$$module$build$src$core$events$events_block_change.getExtraBlockState_(b);b.loadExtraState? -b.loadExtraState(JSON.parse(a||"{}")):b.domToMutation&&b.domToMutation(textToDom$$module$build$src$core$xml(a||""));fire$$module$build$src$core$events$utils(new BlockChange$$module$build$src$core$events$events_block_change(b,"mutation",null,c,a));break;default:console.warn("Unknown change type: "+this.element)}}static getExtraBlockState_(a){return a.saveExtraState?(a=a.saveExtraState())?JSON.stringify(a):"":a.mutationToDom?(a=a.mutationToDom())?domToText$$module$build$src$core$xml(a):"": -""}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,CHANGE$$module$build$src$core$events$utils,BlockChange$$module$build$src$core$events$events_block_change);var module$build$src$core$events$events_block_change={};module$build$src$core$events$events_block_change.BlockChange=BlockChange$$module$build$src$core$events$events_block_change;var MarkerManager$$module$build$src$core$marker_manager=class{constructor(a){this.workspace=a;this.cursorSvg_=this.cursor_=null;this.markers=new Map;this.markerSvg_=null}registerMarker(a,b){this.markers.has(a)&&this.unregisterMarker(a);b.setDrawer(this.workspace.getRenderer().makeMarkerDrawer(this.workspace,b));this.setMarkerSvg(b.getDrawer().createDom());this.markers.set(a,b)}unregisterMarker(a){const b=this.markers.get(a);if(b)b.dispose(),this.markers.delete(a);else throw Error("Marker with ID "+ -a+" does not exist. Can only unregister markers that exist.");}getCursor(){return this.cursor_}getMarker(a){return this.markers.get(a)||null}setCursor(a){this.cursor_&&this.cursor_.getDrawer()&&this.cursor_.getDrawer().dispose();if(this.cursor_=a)a=this.workspace.getRenderer().makeMarkerDrawer(this.workspace,this.cursor_),this.cursor_.setDrawer(a),this.setCursorSvg(this.cursor_.getDrawer().createDom())}setCursorSvg(a){a?(this.workspace.getBlockCanvas().appendChild(a),this.cursorSvg_=a):this.cursorSvg_= -null}setMarkerSvg(a){a?this.workspace.getBlockCanvas()&&(this.cursorSvg_?this.workspace.getBlockCanvas().insertBefore(a,this.cursorSvg_):this.workspace.getBlockCanvas().appendChild(a)):this.markerSvg_=null}updateMarkers(){this.workspace.keyboardAccessibilityMode&&this.cursorSvg_&&this.workspace.getCursor().draw()}dispose(){const a=Object.keys(this.markers);for(let b=0,c;c=a[b];b++)this.unregisterMarker(c);this.markers.clear();this.cursor_&&(this.cursor_.dispose(),this.cursor_=null)}}; -MarkerManager$$module$build$src$core$marker_manager.LOCAL_MARKER="local_marker_1";var module$build$src$core$marker_manager={};module$build$src$core$marker_manager.MarkerManager=MarkerManager$$module$build$src$core$marker_manager;$.module$build$src$core$utils$string={};$.module$build$src$core$utils$string.commonWordPrefix=commonWordPrefix$$module$build$src$core$utils$string;$.module$build$src$core$utils$string.commonWordSuffix=commonWordSuffix$$module$build$src$core$utils$string;$.module$build$src$core$utils$string.isNumber=isNumber$$module$build$src$core$utils$string;$.module$build$src$core$utils$string.shortestStringLength=shortestStringLength$$module$build$src$core$utils$string; -$.module$build$src$core$utils$string.startsWith=startsWith$$module$build$src$core$utils$string;$.module$build$src$core$utils$string.wrap=wrap$$module$build$src$core$utils$string;var customTooltip$$module$build$src$core$tooltip=void 0,visible$$module$build$src$core$tooltip=!1,blocked$$module$build$src$core$tooltip=!1,LIMIT$$module$build$src$core$tooltip=50,mouseOutPid$$module$build$src$core$tooltip=0,showPid$$module$build$src$core$tooltip=0,lastX$$module$build$src$core$tooltip=0,lastY$$module$build$src$core$tooltip=0,element$$module$build$src$core$tooltip=null,poisonedElement$$module$build$src$core$tooltip=null,OFFSET_X$$module$build$src$core$tooltip=0,OFFSET_Y$$module$build$src$core$tooltip= -10,RADIUS_OK$$module$build$src$core$tooltip=10,HOVER_MS$$module$build$src$core$tooltip=750,MARGINS$$module$build$src$core$tooltip=5,containerDiv$$module$build$src$core$tooltip=null,module$build$src$core$tooltip={};module$build$src$core$tooltip.HOVER_MS=HOVER_MS$$module$build$src$core$tooltip;module$build$src$core$tooltip.LIMIT=LIMIT$$module$build$src$core$tooltip;module$build$src$core$tooltip.MARGINS=MARGINS$$module$build$src$core$tooltip;module$build$src$core$tooltip.OFFSET_X=OFFSET_X$$module$build$src$core$tooltip; -module$build$src$core$tooltip.OFFSET_Y=OFFSET_Y$$module$build$src$core$tooltip;module$build$src$core$tooltip.RADIUS_OK=RADIUS_OK$$module$build$src$core$tooltip;module$build$src$core$tooltip.bindMouseEvents=bindMouseEvents$$module$build$src$core$tooltip;module$build$src$core$tooltip.block=block$$module$build$src$core$tooltip;module$build$src$core$tooltip.createDom=createDom$$module$build$src$core$tooltip;module$build$src$core$tooltip.dispose=dispose$$module$build$src$core$tooltip; -module$build$src$core$tooltip.getCustomTooltip=getCustomTooltip$$module$build$src$core$tooltip;module$build$src$core$tooltip.getDiv=getDiv$$module$build$src$core$tooltip;module$build$src$core$tooltip.getTooltipOfObject=getTooltipOfObject$$module$build$src$core$tooltip;module$build$src$core$tooltip.hide=hide$$module$build$src$core$tooltip;module$build$src$core$tooltip.isVisible=isVisible$$module$build$src$core$tooltip;module$build$src$core$tooltip.setCustomTooltip=setCustomTooltip$$module$build$src$core$tooltip; -module$build$src$core$tooltip.unbindMouseEvents=unbindMouseEvents$$module$build$src$core$tooltip;module$build$src$core$tooltip.unblock=unblock$$module$build$src$core$tooltip;var hsvSaturation$$module$build$src$core$utils$colour=.45,hsvValue$$module$build$src$core$utils$colour=.65,names$$module$build$src$core$utils$colour={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00"},module$build$src$core$utils$colour={};module$build$src$core$utils$colour.blend=blend$$module$build$src$core$utils$colour; -module$build$src$core$utils$colour.getHsvSaturation=getHsvSaturation$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.getHsvValue=getHsvValue$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.hexToRgb=hexToRgb$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.hsvToHex=hsvToHex$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.hueToHex=hueToHex$$module$build$src$core$utils$colour; -module$build$src$core$utils$colour.names=names$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.parse=parse$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.rgbToHex=rgbToHex$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.setHsvSaturation=setHsvSaturation$$module$build$src$core$utils$colour;module$build$src$core$utils$colour.setHsvValue=setHsvValue$$module$build$src$core$utils$colour;var module$build$src$core$utils$parsing={};module$build$src$core$utils$parsing.checkMessageReferences=checkMessageReferences$$module$build$src$core$utils$parsing;module$build$src$core$utils$parsing.parseBlockColour=parseBlockColour$$module$build$src$core$utils$parsing;module$build$src$core$utils$parsing.replaceMessageReferences=replaceMessageReferences$$module$build$src$core$utils$parsing;module$build$src$core$utils$parsing.tokenizeInterpolation=tokenizeInterpolation$$module$build$src$core$utils$parsing;var Sentinel$$module$build$src$core$utils$sentinel=class{},module$build$src$core$utils$sentinel={};module$build$src$core$utils$sentinel.Sentinel=Sentinel$$module$build$src$core$utils$sentinel;var owner$$module$build$src$core$widgetdiv=null,dispose$$module$build$src$core$widgetdiv=null,rendererClassName$$module$build$src$core$widgetdiv="",themeClassName$$module$build$src$core$widgetdiv="",containerDiv$$module$build$src$core$widgetdiv,module$build$src$core$widgetdiv={};module$build$src$core$widgetdiv.createDom=createDom$$module$build$src$core$widgetdiv;module$build$src$core$widgetdiv.getDiv=getDiv$$module$build$src$core$widgetdiv;module$build$src$core$widgetdiv.hide=hide$$module$build$src$core$widgetdiv; -module$build$src$core$widgetdiv.hideIfOwner=hideIfOwner$$module$build$src$core$widgetdiv;module$build$src$core$widgetdiv.isVisible=isVisible$$module$build$src$core$widgetdiv;module$build$src$core$widgetdiv.positionWithAnchor=positionWithAnchor$$module$build$src$core$widgetdiv;module$build$src$core$widgetdiv.show=show$$module$build$src$core$widgetdiv;module$build$src$core$widgetdiv.testOnly_setDiv=testOnly_setDiv$$module$build$src$core$widgetdiv;var Field$$module$build$src$core$field=class{constructor(a,b,c){this.name=void 0;this.constants_=this.mouseDownWrapper_=this.textContent_=this.textElement_=this.borderRect_=this.fieldGroup_=this.markerSvg_=this.cursorSvg_=this.tooltip_=this.validator_=null;this.disposed=!1;this.maxDisplayLength=50;this.sourceBlock_=null;this.enabled_=this.visible_=this.isDirty_=!0;this.suffixField=this.prefixField=this.clickTarget_=null;this.EDITABLE=!0;this.SERIALIZABLE=!1;this.CURSOR="";this.value_="DEFAULT_VALUE"in -new.target.prototype?new.target.prototype.DEFAULT_VALUE:null;this.size_=new Size$$module$build$src$core$utils$size(0,0);a!==Field$$module$build$src$core$field.SKIP_SETUP&&(c&&this.configure_(c),this.setValue(a),b&&this.setValidator(b))}configure_(a){a.tooltip&&this.setTooltip(replaceMessageReferences$$module$build$src$core$utils$parsing(a.tooltip))}setSourceBlock(a){if(this.sourceBlock_)throw Error("Field already bound to a block");this.sourceBlock_=a}getConstants(){!this.constants_&&this.sourceBlock_&& -!this.sourceBlock_.isDeadOrDying()&&this.sourceBlock_.workspace.rendered&&(this.constants_=this.sourceBlock_.workspace.getRenderer().getConstants());return this.constants_}getSourceBlock(){return this.sourceBlock_}init(){this.fieldGroup_||(this.fieldGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{}),this.isVisible()||(this.fieldGroup_.style.display="none"),this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_),this.initView(),this.updateEditable(), -this.setTooltip(this.tooltip_),this.bindEvents_(),this.initModel())}initView(){this.createBorderRect_();this.createTextElement_()}initModel(){}createBorderRect_(){this.borderRect_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{rx:this.getConstants().FIELD_BORDER_RECT_RADIUS,ry:this.getConstants().FIELD_BORDER_RECT_RADIUS,x:0,y:0,height:this.size_.height,width:this.size_.width,"class":"blocklyFieldRect"},this.fieldGroup_)}createTextElement_(){this.textElement_= -createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.TEXT,{"class":"blocklyText"},this.fieldGroup_);this.getConstants().FIELD_TEXT_BASELINE_CENTER&&this.textElement_.setAttribute("dominant-baseline","central");this.textContent_=document.createTextNode("");this.textElement_.appendChild(this.textContent_)}bindEvents_(){const a=this.getClickTarget_();if(!a)throw Error("A click target has not been set.");bindMouseEvents$$module$build$src$core$tooltip(a);this.mouseDownWrapper_= -conditionalBind$$module$build$src$core$browser_events(a,"mousedown",this,this.onMouseDown_)}fromXml(a){this.setValue(a.textContent)}toXml(a){a.textContent=this.getValue();return a}saveState(a){a=this.saveLegacyState(Field$$module$build$src$core$field);return null!==a?a:this.getValue()}loadState(a){this.loadLegacyState(Field$$module$build$src$core$field,a)||this.setValue(a)}saveLegacyState(a){return a.prototype.saveState===this.saveState&&a.prototype.toXml!==this.toXml?(a=createElement$$module$build$src$core$utils$xml("field"), -a.setAttribute("name",this.name||""),domToText$$module$build$src$core$xml(this.toXml(a)).replace(' xmlns="https://developers.google.com/blockly/xml"',"")):null}loadLegacyState(a,b){return a.prototype.loadState===this.loadState&&a.prototype.fromXml!==this.fromXml?(this.fromXml(textToDom$$module$build$src$core$xml(b)),!0):!1}dispose(){hideIfOwner$$module$build$src$core$dropdowndiv(this);hideIfOwner$$module$build$src$core$widgetdiv(this);unbindMouseEvents$$module$build$src$core$tooltip(this.getClickTarget_()); -this.mouseDownWrapper_&&unbind$$module$build$src$core$browser_events(this.mouseDownWrapper_);removeNode$$module$build$src$core$utils$dom(this.fieldGroup_);this.disposed=!0}updateEditable(){const a=this.fieldGroup_,b=this.getSourceBlock();this.EDITABLE&&a&&b&&(this.enabled_&&b.isEditable()?(addClass$$module$build$src$core$utils$dom(a,"blocklyEditableText"),removeClass$$module$build$src$core$utils$dom(a,"blocklyNonEditableText"),a.style.cursor=this.CURSOR):(addClass$$module$build$src$core$utils$dom(a, -"blocklyNonEditableText"),removeClass$$module$build$src$core$utils$dom(a,"blocklyEditableText"),a.style.cursor=""))}setEnabled(a){this.enabled_=a;this.updateEditable()}isEnabled(){return this.enabled_}isClickable(){return this.enabled_&&!!this.sourceBlock_&&this.sourceBlock_.isEditable()&&this.showEditor_!==Field$$module$build$src$core$field.prototype.showEditor_}isCurrentlyEditable(){return this.enabled_&&this.EDITABLE&&!!this.sourceBlock_&&this.sourceBlock_.isEditable()}isSerializable(){let a=!1; -this.name&&(this.SERIALIZABLE?a=!0:this.EDITABLE&&(console.warn("Detected an editable field that was not serializable. Please define SERIALIZABLE property as true on all editable custom fields. Proceeding with serialization."),a=!0));return a}isVisible(){return this.visible_}setVisible(a){if(this.visible_!==a){this.visible_=a;var b=this.fieldGroup_;b&&(b.style.display=a?"block":"none")}}setValidator(a){this.validator_=a}getValidator(){return this.validator_}getSvgRoot(){return this.fieldGroup_}getBorderRect(){if(!this.borderRect_)throw Error(`The border rectangle is ${this.borderRect_}.`); -return this.borderRect_}getTextElement(){if(!this.textElement_)throw Error(`The text element is ${this.textElement_}.`);return this.textElement_}getTextContent(){if(!this.textContent_)throw Error(`The text content is ${this.textContent_}.`);return this.textContent_}applyColour(){}render_(){this.textContent_&&(this.textContent_.nodeValue=this.getDisplayText_());this.updateSize_()}showEditor(a){this.isClickable()&&this.showEditor_(a)}showEditor_(a){}updateSize_(a){const b=this.getConstants();a=void 0!== -a?a:this.borderRect_?this.getConstants().FIELD_BORDER_RECT_X_PADDING:0;let c=2*a,d=b.FIELD_TEXT_HEIGHT,e=0;this.textElement_&&(e=getFastTextWidth$$module$build$src$core$utils$dom(this.textElement_,b.FIELD_TEXT_FONTSIZE,b.FIELD_TEXT_FONTWEIGHT,b.FIELD_TEXT_FONTFAMILY),c+=e);this.borderRect_&&(d=Math.max(d,b.FIELD_BORDER_RECT_HEIGHT));this.size_.height=d;this.size_.width=c;this.positionTextElement_(a,e);this.positionBorderRect_()}positionTextElement_(a,b){if(this.textElement_){var c=this.getConstants(), -d=this.size_.height/2,e;this.textElement_.setAttribute("x",`${(null==(e=this.getSourceBlock())?0:e.RTL)?this.size_.width-b-a:a}`);this.textElement_.setAttribute("y",`${c.FIELD_TEXT_BASELINE_CENTER?d:d-c.FIELD_TEXT_HEIGHT/2+c.FIELD_TEXT_BASELINE}`)}}positionBorderRect_(){this.borderRect_&&(this.borderRect_.setAttribute("width",`${this.size_.width}`),this.borderRect_.setAttribute("height",`${this.size_.height}`),this.borderRect_.setAttribute("rx",`${this.getConstants().FIELD_BORDER_RECT_RADIUS}`),this.borderRect_.setAttribute("ry", -`${this.getConstants().FIELD_BORDER_RECT_RADIUS}`))}getSize(){if(!this.isVisible())return new Size$$module$build$src$core$utils$size(0,0);this.isDirty_?(this.render_(),this.isDirty_=!1):this.visible_&&0===this.size_.width&&(console.warn("Deprecated use of setting size_.width to 0 to rerender a field. Set field.isDirty_ to true instead."),this.render_());return this.size_}getScaledBBox(){let a;var b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;if(this.borderRect_){var c= -this.borderRect_.getBoundingClientRect();a=getPageOffset$$module$build$src$core$utils$style(this.borderRect_);b=c.width;c=c.height}else{c=this.sourceBlock_.getHeightWidth();const d=b.workspace.scale;a=this.getAbsoluteXY_();b=(c.width+1)*d;c=(c.height+1)*d;GECKO$$module$build$src$core$utils$useragent?(a.x+=1.5*d,a.y+=1.5*d):(a.x-=.5*d,a.y-=.5*d)}return new Rect$$module$build$src$core$utils$rect(a.y,a.y+c,a.x,a.x+b)}getDisplayText_(){let a=this.getText();if(!a)return Field$$module$build$src$core$field.NBSP; -a.length>this.maxDisplayLength&&(a=a.substring(0,this.maxDisplayLength-2)+"\u2026");a=a.replace(/\s/g,Field$$module$build$src$core$field.NBSP);this.sourceBlock_&&this.sourceBlock_.RTL&&(a+="\u200f");return a}getText(){const a=this.getText_();return null!==a?String(a):String(this.getValue())}getText_(){return null}markDirty(){this.isDirty_=!0;this.constants_=null}forceRerender(){this.isDirty_=!0;this.sourceBlock_&&this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours(), -this.updateMarkers_())}setValue(a){if(null!==a){var b=this.doClassValidation_(a);a=this.processValidation_(a,b);if(!(a instanceof Error)){if(b=this.getValidator())if(b=b.call(this,a),a=this.processValidation_(a,b),a instanceof Error)return;b=this.sourceBlock_;if(!b||!b.disposed){var c=this.getValue();c===a?this.doValueUpdate_(a):(this.doValueUpdate_(a),b&&isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(CHANGE$$module$build$src$core$events$utils))(b, -"field",this.name||null,c,a)),this.isDirty_&&this.forceRerender())}}}}processValidation_(a,b){if(null===b)return this.doValueInvalid_(a),this.isDirty_&&this.forceRerender(),Error();void 0!==b&&(a=b);return a}getValue(){return this.value_}doClassValidation_(a){return null===a||void 0===a?null:a}doValueUpdate_(a){this.value_=a;this.isDirty_=!0}doValueInvalid_(a){}onMouseDown_(a){this.sourceBlock_&&!this.sourceBlock_.isDeadOrDying()&&(a=this.sourceBlock_.workspace.getGesture(a))&&a.setStartField(this)}setTooltip(a){a|| -""===a||(a=this.sourceBlock_);const b=this.getClickTarget_();b?b.tooltip=a:this.tooltip_=a}getTooltip(){const a=this.getClickTarget_();return a?getTooltipOfObject$$module$build$src$core$tooltip(a):getTooltipOfObject$$module$build$src$core$tooltip({tooltip:this.tooltip_})}getClickTarget_(){return this.clickTarget_||this.getSvgRoot()}getAbsoluteXY_(){return getPageOffset$$module$build$src$core$utils$style(this.getClickTarget_())}referencesVariables(){return!1}refreshVariableName(){}getParentInput(){let a= -null;const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;const c=b.inputList;for(let d=0;da?this.menuItems_.length:a,-1)}highlightFirst_(){this.highlightHelper_(-1,1)}highlightLast_(){this.highlightHelper_(this.menuItems_.length, --1)}highlightHelper_(a,b){a+=b;let c;for(;c=this.menuItems_[a];){if(c.isEnabled()){this.setHighlighted(c);break}a+=b}}handleMouseOver_(a){(a=this.getMenuItem_(a.target))&&(a.isEnabled()?this.highlightedItem_!==a&&this.setHighlighted(a):this.setHighlighted(null))}handleClick_(a){const b=this.openingCoords;this.openingCoords=null;if(b&&"number"===typeof a.clientX){const c=new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY);if(1>Coordinate$$module$build$src$core$utils$coordinate.distance(b, -c))return}(a=this.getMenuItem_(a.target))&&a.performAction()}handleMouseEnter_(a){this.focus()}handleMouseLeave_(a){this.getElement()&&(this.blur_(),this.setHighlighted(null))}handleKeyEvent_(a){if(this.menuItems_.length&&!(a.shiftKey||a.ctrlKey||a.metaKey||a.altKey)){var b=this.highlightedItem_;switch(a.keyCode){case KeyCodes$$module$build$src$core$utils$keycodes.ENTER:case KeyCodes$$module$build$src$core$utils$keycodes.SPACE:b&&b.performAction();break;case KeyCodes$$module$build$src$core$utils$keycodes.UP:this.highlightPrevious(); -break;case KeyCodes$$module$build$src$core$utils$keycodes.DOWN:this.highlightNext();break;case KeyCodes$$module$build$src$core$utils$keycodes.PAGE_UP:case KeyCodes$$module$build$src$core$utils$keycodes.HOME:this.highlightFirst_();break;case KeyCodes$$module$build$src$core$utils$keycodes.PAGE_DOWN:case KeyCodes$$module$build$src$core$utils$keycodes.END:this.highlightLast_();break;default:return}a.preventDefault();a.stopPropagation()}}getSize(){const a=this.getElement(),b=getSize$$module$build$src$core$utils$style(a); -b.height=a.scrollHeight;return b}},module$build$src$core$menu={};module$build$src$core$menu.Menu=Menu$$module$build$src$core$menu;var MenuItem$$module$build$src$core$menuitem=class{constructor(a,b){this.content=a;this.opt_value=b;this.enabled_=!0;this.element_=null;this.rightToLeft_=!1;this.roleName_=null;this.highlight_=this.checked_=this.checkable_=!1;this.actionHandler_=null}createDom(){const a=document.createElement("div");a.id=getNextUniqueId$$module$build$src$core$utils$idgenerator();this.element_=a;a.className="blocklyMenuItem goog-menuitem "+(this.enabled_?"":"blocklyMenuItemDisabled goog-menuitem-disabled ")+(this.checked_? -"blocklyMenuItemSelected goog-option-selected ":"")+(this.highlight_?"blocklyMenuItemHighlight goog-menuitem-highlight ":"")+(this.rightToLeft_?"blocklyMenuItemRtl goog-menuitem-rtl ":"");const b=document.createElement("div");b.className="blocklyMenuItemContent goog-menuitem-content";if(this.checkable_){var c=document.createElement("div");c.className="blocklyMenuItemCheckbox goog-menuitem-checkbox";b.appendChild(c)}c=this.content;"string"===typeof this.content&&(c=document.createTextNode(this.content)); -b.appendChild(c);a.appendChild(b);this.roleName_&&setRole$$module$build$src$core$utils$aria(a,this.roleName_);setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.SELECTED,this.checkable_&&this.checked_||!1);setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.DISABLED,!this.enabled_);return a}dispose(){this.element_=null}getElement(){return this.element_}getId(){return this.element_.id}getValue(){let a;return null!=(a=this.opt_value)? -a:null}setRightToLeft(a){this.rightToLeft_=a}setRole(a){this.roleName_=a}setCheckable(a){this.checkable_=a}setChecked(a){this.checked_=a}setHighlighted(a){this.highlight_=a;const b=this.getElement();b&&this.isEnabled()&&(a?(addClass$$module$build$src$core$utils$dom(b,"blocklyMenuItemHighlight"),addClass$$module$build$src$core$utils$dom(b,"goog-menuitem-highlight")):(removeClass$$module$build$src$core$utils$dom(b,"blocklyMenuItemHighlight"),removeClass$$module$build$src$core$utils$dom(b,"goog-menuitem-highlight")))}isEnabled(){return this.enabled_}setEnabled(a){this.enabled_= -a}performAction(){this.isEnabled()&&this.actionHandler_&&this.actionHandler_(this)}onAction(a,b){this.actionHandler_=a.bind(b)}},module$build$src$core$menuitem={};module$build$src$core$menuitem.MenuItem=MenuItem$$module$build$src$core$menuitem;var FieldDropdown$$module$build$src$core$field_dropdown=class extends Field$$module$build$src$core$field{constructor(a,b,c){super(Field$$module$build$src$core$field.SKIP_SETUP);this.svgArrow_=this.arrow_=this.imageElement_=this.menu_=this.selectedMenuItem_=null;this.SERIALIZABLE=!0;this.CURSOR="default";this.suffixField=this.prefixField=this.generatedOptions_=null;a!==Field$$module$build$src$core$field.SKIP_SETUP&&(Array.isArray(a)&&(validateOptions$$module$build$src$core$field_dropdown(a),a=JSON.parse(JSON.stringify(a))), -this.menuGenerator_=a,this.trimOptions_(),this.selectedOption_=this.getOptions(!1)[0],c&&this.configure_(c),this.setValue(this.selectedOption_[1]),b&&this.setValidator(b))}fromXml(a){this.isOptionListDynamic()&&this.getOptions(!1);this.setValue(a.textContent)}loadState(a){this.loadLegacyState(FieldDropdown$$module$build$src$core$field_dropdown,a)||(this.isOptionListDynamic()&&this.getOptions(!1),this.setValue(a))}initView(){this.shouldAddBorderRect_()?this.createBorderRect_():this.clickTarget_=this.sourceBlock_.getSvgRoot(); -this.createTextElement_();this.imageElement_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{},this.fieldGroup_);this.getConstants().FIELD_DROPDOWN_SVG_ARROW?this.createSVGArrow_():this.createTextArrow_();this.borderRect_&&addClass$$module$build$src$core$utils$dom(this.borderRect_,"blocklyDropdownRect")}shouldAddBorderRect_(){let a;return!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW&& -!(null==(a=this.getSourceBlock())?0:a.isShadow())}createTextArrow_(){this.arrow_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.TSPAN,{},this.textElement_);let a;this.arrow_.appendChild(document.createTextNode((null==(a=this.getSourceBlock())?0:a.RTL)?FieldDropdown$$module$build$src$core$field_dropdown.ARROW_CHAR+" ":" "+FieldDropdown$$module$build$src$core$field_dropdown.ARROW_CHAR));let b;(null==(b=this.getSourceBlock())?0:b.RTL)?this.getTextElement().insertBefore(this.arrow_, -this.textContent_):this.getTextElement().appendChild(this.arrow_)}createSVGArrow_(){this.svgArrow_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{height:this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE+"px",width:this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE+"px"},this.fieldGroup_);this.svgArrow_.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.getConstants().FIELD_DROPDOWN_SVG_ARROW_DATAURI)}showEditor_(a){var b=this.getSourceBlock(); -if(!b)throw new UnattachedFieldError$$module$build$src$core$field;this.dropdownCreate_();this.menu_.openingCoords=a&&"number"===typeof a.clientX?new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY):null;clearContent$$module$build$src$core$dropdowndiv();a=this.menu_.render(getContentDiv$$module$build$src$core$dropdowndiv());addClass$$module$build$src$core$utils$dom(a,"blocklyDropdownMenu");if(this.getConstants().FIELD_DROPDOWN_COLOURED_DIV){a=b.isShadow()?b.getParent().getColour(): -b.getColour();b=b.isShadow()?b.getParent().style.colourTertiary:this.sourceBlock_.style.colourTertiary;if(!b)throw Error("The renderer did not properly initialize the block style");setColour$$module$build$src$core$dropdowndiv(a,b)}showPositionedByField$$module$build$src$core$dropdowndiv(this,this.dropdownDispose_.bind(this));this.menu_.focus();this.selectedMenuItem_&&this.menu_.setHighlighted(this.selectedMenuItem_);this.applyColour()}dropdownCreate_(){const a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field; -const b=new Menu$$module$build$src$core$menu;b.setRole(Role$$module$build$src$core$utils$aria.LISTBOX);this.menu_=b;const c=this.getOptions(!1);this.selectedMenuItem_=null;for(let e=0;ea.length)){b=[];for(c=0;c=a||isNaN(a)?0:Math.min(a,this.scrollbarLength_)}setHandleLength_(a){this.handleLength_=a;this.svgHandle_.setAttribute(this.lengthAttribute_,String(this.handleLength_))}constrainHandlePosition_(a){return a=0>=a||isNaN(a)?0:Math.min(a,this.scrollbarLength_-this.handleLength_)}setHandlePosition(a){this.handlePosition_=a;this.svgHandle_.setAttribute(this.positionAttribute_,String(this.handlePosition_))}setScrollbarLength_(a){this.scrollbarLength_= -a;this.outerSvg_.setAttribute(this.lengthAttribute_,String(this.scrollbarLength_));this.svgBackground_.setAttribute(this.lengthAttribute_,String(this.scrollbarLength_))}setPosition(a,b){this.position.x=a;this.position.y=b;a=this.position.x+this.origin_.x;b=this.position.y+this.origin_.y;this.outerSvg_&&setCssTransform$$module$build$src$core$utils$dom(this.outerSvg_,"translate("+a+"px,"+b+"px)")}resize(a){if(!a&&(a=this.workspace.getMetrics(),!a))return;this.oldHostMetrics_&&Scrollbar$$module$build$src$core$scrollbar.metricsAreEquivalent_(a, -this.oldHostMetrics_)||(this.horizontal?this.resizeHorizontal_(a):this.resizeVertical_(a),this.oldHostMetrics_=a,this.updateMetrics_())}requiresViewResize_(a){return this.oldHostMetrics_?this.oldHostMetrics_.viewWidth!==a.viewWidth||this.oldHostMetrics_.viewHeight!==a.viewHeight||this.oldHostMetrics_.absoluteLeft!==a.absoluteLeft||this.oldHostMetrics_.absoluteTop!==a.absoluteTop:!0}resizeHorizontal_(a){this.requiresViewResize_(a)?this.resizeViewHorizontal(a):this.resizeContentHorizontal(a)}resizeViewHorizontal(a){var b= -a.viewWidth-2*this.margin_;this.pair_&&(b-=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness);this.setScrollbarLength_(Math.max(0,b));b=a.absoluteLeft+this.margin_;this.pair_&&this.workspace.RTL&&(b+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness);this.setPosition(b,a.absoluteTop+a.viewHeight-Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness-this.margin_);this.resizeContentHorizontal(a)}resizeContentHorizontal(a){if(a.viewWidth>=a.scrollWidth)this.setHandleLength_(this.scrollbarLength_), -this.setHandlePosition(0),this.pair_||this.setVisible(!1);else{this.pair_||this.setVisible(!0);var b=this.scrollbarLength_*a.viewWidth/a.scrollWidth;b=this.constrainHandleLength_(b);this.setHandleLength_(b);b=a.scrollWidth-a.viewWidth;var c=this.scrollbarLength_-this.handleLength_;a=(a.viewLeft-a.scrollLeft)/b*c;a=this.constrainHandlePosition_(a);this.setHandlePosition(a);this.ratio=c/b}}resizeVertical_(a){this.requiresViewResize_(a)?this.resizeViewVertical(a):this.resizeContentVertical(a)}resizeViewVertical(a){let b= -a.viewHeight-2*this.margin_;this.pair_&&(b-=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness);this.setScrollbarLength_(Math.max(0,b));this.setPosition(this.workspace.RTL?a.absoluteLeft+this.margin_:a.absoluteLeft+a.viewWidth-Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness-this.margin_,a.absoluteTop+this.margin_);this.resizeContentVertical(a)}resizeContentVertical(a){if(a.viewHeight>=a.scrollHeight)this.setHandleLength_(this.scrollbarLength_),this.setHandlePosition(0),this.pair_|| -this.setVisible(!1);else{this.pair_||this.setVisible(!0);var b=this.scrollbarLength_*a.viewHeight/a.scrollHeight;b=this.constrainHandleLength_(b);this.setHandleLength_(b);b=a.scrollHeight-a.viewHeight;var c=this.scrollbarLength_-this.handleLength_;a=(a.viewTop-a.scrollTop)/b*c;a=this.constrainHandlePosition_(a);this.setHandlePosition(a);this.ratio=c/b}}createDom_(a){let b="blocklyScrollbar"+(this.horizontal?"Horizontal":"Vertical");a&&(b+=" "+a);this.outerSvg_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG, -{"class":b});this.svgGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{},this.outerSvg_);this.svgBackground_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyScrollbarBackground"},this.svgGroup_);a=Math.floor((Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness-5)/2);this.svgHandle_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyScrollbarHandle", -rx:a,ry:a},this.svgGroup_);this.workspace.getThemeManager().subscribe(this.svgHandle_,"scrollbarColour","fill");this.workspace.getThemeManager().subscribe(this.svgHandle_,"scrollbarOpacity","fill-opacity");insertAfter$$module$build$src$core$utils$dom(this.outerSvg_,this.workspace.getParentSvg())}isVisible(){return this.isVisible_}setContainerVisible(a){const b=a!==this.containerVisible_;this.containerVisible_=a;b&&this.updateDisplay_()}setVisible(a){const b=a!==this.isVisible();if(this.pair_)throw Error("Unable to toggle visibility of paired scrollbars."); -this.isVisible_=a;b&&this.updateDisplay_()}updateDisplay_(){this.containerVisible_&&this.isVisible()?this.outerSvg_.setAttribute("display","block"):this.outerSvg_.setAttribute("display","none")}onMouseDownBar_(a){this.workspace.markFocused();clearTouchIdentifier$$module$build$src$core$touch();this.cleanUp_();if(isRightButton$$module$build$src$core$browser_events(a))a.stopPropagation();else{var b=mouseToSvg$$module$build$src$core$browser_events(a,this.workspace.getParentSvg(),this.workspace.getInverseScreenCTM()); -b=this.horizontal?b.x:b.y;var c=getInjectionDivXY$$module$build$src$core$utils$svg_math(this.svgHandle_);c=this.horizontal?c.x:c.y;var d=this.handlePosition_,e=.95*this.handleLength_;b<=c?d-=e:b>=c+this.handleLength_&&(d+=e);this.setHandlePosition(this.constrainHandlePosition_(d));this.updateMetrics_();a.stopPropagation();a.preventDefault()}}onMouseDownHandle_(a){this.workspace.markFocused();this.cleanUp_();isRightButton$$module$build$src$core$browser_events(a)?a.stopPropagation():(this.startDragHandle= -this.handlePosition_,this.workspace.setupDragSurface(),this.startDragMouse_=this.horizontal?a.clientX:a.clientY,this.onMouseUpWrapper_=conditionalBind$$module$build$src$core$browser_events(document,"mouseup",this,this.onMouseUpHandle_),this.onMouseMoveWrapper_=conditionalBind$$module$build$src$core$browser_events(document,"mousemove",this,this.onMouseMoveHandle_),a.stopPropagation(),a.preventDefault())}onMouseMoveHandle_(a){this.setHandlePosition(this.constrainHandlePosition_(this.startDragHandle+ -((this.horizontal?a.clientX:a.clientY)-this.startDragMouse_)));this.updateMetrics_()}onMouseUpHandle_(){this.workspace.resetDragSurface();clearTouchIdentifier$$module$build$src$core$touch();this.cleanUp_()}cleanUp_(){this.workspace.hideChaff(!0);this.onMouseUpWrapper_&&(unbind$$module$build$src$core$browser_events(this.onMouseUpWrapper_),this.onMouseUpWrapper_=null);this.onMouseMoveWrapper_&&(unbind$$module$build$src$core$browser_events(this.onMouseMoveWrapper_),this.onMouseMoveWrapper_=null)}getRatio_(){let a= -this.handlePosition_/(this.scrollbarLength_-this.handleLength_);isNaN(a)&&(a=0);return a}updateMetrics_(){const a=this.getRatio_();this.horizontal?this.workspace.setMetrics({x:a}):this.workspace.setMetrics({y:a})}set(a,b){this.setHandlePosition(this.constrainHandlePosition_(a*this.ratio));(b||void 0===b)&&this.updateMetrics_()}setOrigin(a,b){this.origin_=new Coordinate$$module$build$src$core$utils$coordinate(a,b)}static metricsAreEquivalent_(a,b){return a.viewWidth===b.viewWidth&&a.viewHeight===b.viewHeight&& -a.viewLeft===b.viewLeft&&a.viewTop===b.viewTop&&a.absoluteTop===b.absoluteTop&&a.absoluteLeft===b.absoluteLeft&&a.scrollWidth===b.scrollWidth&&a.scrollHeight===b.scrollHeight&&a.scrollLeft===b.scrollLeft&&a.scrollTop===b.scrollTop}};Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness=TOUCH_ENABLED$$module$build$src$core$touch?25:15;Scrollbar$$module$build$src$core$scrollbar.DEFAULT_SCROLLBAR_MARGIN=.5;var module$build$src$core$scrollbar={};module$build$src$core$scrollbar.Scrollbar=Scrollbar$$module$build$src$core$scrollbar;var Bubble$$module$build$src$core$bubble=class{constructor(a,b,c,d,e,f){this.resizeGroup_=this.bubbleBack_=this.bubbleArrow_=this.bubbleGroup_=null;this.height_=this.width_=this.relativeTop_=this.relativeLeft_=0;this.autoLayout_=!0;this.onMouseDownResizeWrapper_=this.onMouseDownBubbleWrapper_=this.moveCallback_=this.resizeCallback_=null;this.rendered_=this.disposed=!1;this.workspace_=a;this.content_=b;this.shape_=c;c=Bubble$$module$build$src$core$bubble.ARROW_ANGLE;this.workspace_.RTL&&(c=-c);this.arrow_radians_= -toRadians$$module$build$src$core$utils$math(c);a.getBubbleCanvas().appendChild(this.createDom_(b,!(!e||!f)));this.setAnchorLocation(d);e&&f||(a=this.content_.getBBox(),e=a.width+2*Bubble$$module$build$src$core$bubble.BORDER_WIDTH,f=a.height+2*Bubble$$module$build$src$core$bubble.BORDER_WIDTH);this.setBubbleSize(e,f);this.positionBubble_();this.renderArrow_();this.rendered_=!0}createDom_(a,b){this.bubbleGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G, -{});var c={filter:"url(#"+this.workspace_.getRenderer().getConstants().embossFilterId+")"};JavaFx$$module$build$src$core$utils$useragent&&(c={});c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,c,this.bubbleGroup_);this.bubbleArrow_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATH,{},c);this.bubbleBack_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"blocklyDraggable", -x:0,y:0,rx:Bubble$$module$build$src$core$bubble.BORDER_WIDTH,ry:Bubble$$module$build$src$core$bubble.BORDER_WIDTH},c);b?(this.resizeGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":this.workspace_.RTL?"blocklyResizeSW":"blocklyResizeSE"},this.bubbleGroup_),b=2*Bubble$$module$build$src$core$bubble.BORDER_WIDTH,createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.POLYGON,{points:"0,x x,x x,0".replace(/x/g,b.toString())}, -this.resizeGroup_),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{"class":"blocklyResizeLine",x1:b/3,y1:b-1,x2:b-1,y2:b/3},this.resizeGroup_),createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{"class":"blocklyResizeLine",x1:2*b/3,y1:b-1,x2:b-1,y2:2*b/3},this.resizeGroup_)):this.resizeGroup_=null;this.workspace_.options.readOnly||(this.onMouseDownBubbleWrapper_=conditionalBind$$module$build$src$core$browser_events(this.bubbleBack_, -"mousedown",this,this.bubbleMouseDown_),this.resizeGroup_&&(this.onMouseDownResizeWrapper_=conditionalBind$$module$build$src$core$browser_events(this.resizeGroup_,"mousedown",this,this.resizeMouseDown_)));this.bubbleGroup_.appendChild(a);return this.bubbleGroup_}getSvgRoot(){return this.bubbleGroup_}setSvgId(a){let b;null==(b=this.bubbleGroup_)||b.setAttribute("data-block-id",a)}bubbleMouseDown_(a){const b=this.workspace_.getGesture(a);b&&b.handleBubbleStart(a,this)}showContextMenu(a){}isDeletable(){return!1}setDeleteStyle(a){}resizeMouseDown_(a){this.promote(); -Bubble$$module$build$src$core$bubble.unbindDragEvents_();isRightButton$$module$build$src$core$browser_events(a)||(this.workspace_.startDrag(a,new Coordinate$$module$build$src$core$utils$coordinate(this.workspace_.RTL?-this.width_:this.width_,this.height_)),Bubble$$module$build$src$core$bubble.onMouseUpWrapper_=conditionalBind$$module$build$src$core$browser_events(document,"mouseup",this,Bubble$$module$build$src$core$bubble.bubbleMouseUp_),Bubble$$module$build$src$core$bubble.onMouseMoveWrapper_=conditionalBind$$module$build$src$core$browser_events(document, -"mousemove",this,this.resizeMouseMove_),this.workspace_.hideChaff());a.stopPropagation()}resizeMouseMove_(a){this.autoLayout_=!1;a=this.workspace_.moveDrag(a);this.setBubbleSize(this.workspace_.RTL?-a.x:a.x,a.y);this.workspace_.RTL&&this.positionBubble_()}registerResizeEvent(a){this.resizeCallback_=a}registerMoveEvent(a){this.moveCallback_=a}promote(){let a;const b=null==(a=this.bubbleGroup_)?void 0:a.parentNode;return(null==b?void 0:b.lastChild)!==this.bubbleGroup_&&this.bubbleGroup_?(null==b||b.appendChild(this.bubbleGroup_), -!0):!1}setAnchorLocation(a){this.anchorXY_=a;this.rendered_&&this.positionBubble_()}layoutBubble_(){var a=this.workspace_.getMetricsManager().getViewMetrics(!0),b=this.getOptimalRelativeLeft_(a),c=this.getOptimalRelativeTop_(a),d=this.shape_.getBBox();const e={x:b,y:-this.height_-this.workspace_.getRenderer().getConstants().MIN_BLOCK_HEIGHT},f={x:-this.width_-30,y:c};c={x:d.width,y:c};var g={x:b,y:d.height};b=d.widtha.width)return b;if(this.workspace_.RTL){var c=this.anchorXY_.x-b,d=a.left+a.width;a=a.left+Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness/this.workspace_.scale;c-this.width_d&&(b=-(d-this.anchorXY_.x))}else{c=b+this.anchorXY_.x;d=c+this.width_;const e=a.left;a=a.left+a.width-Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness/ -this.workspace_.scale;ca&&(b=a-this.anchorXY_.x-this.width_)}return b}getOptimalRelativeTop_(a){let b=-this.height_/4;if(this.height_>a.height)return b;const c=this.anchorXY_.y+b,d=c+this.height_,e=a.top;a=a.top+a.height-Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness/this.workspace_.scale;const f=this.anchorXY_.y;ca&&(b=a-f-this.height_);return b}positionBubble_(){let a=this.anchorXY_.x;a=this.workspace_.RTL?a-(this.relativeLeft_+this.width_):a+ -this.relativeLeft_;this.moveTo(a,this.relativeTop_+this.anchorXY_.y)}moveTo(a,b){let c;null==(c=this.bubbleGroup_)||c.setAttribute("transform","translate("+a+","+b+")")}setDragging(a){!a&&this.moveCallback_&&this.moveCallback_()}getBubbleSize(){return new Size$$module$build$src$core$utils$size(this.width_,this.height_)}setBubbleSize(a,b){const c=2*Bubble$$module$build$src$core$bubble.BORDER_WIDTH;a=Math.max(a,c+45);b=Math.max(b,c+20);this.width_=a;this.height_=b;let d;null==(d=this.bubbleBack_)|| -d.setAttribute("width",a.toString());let e;null==(e=this.bubbleBack_)||e.setAttribute("height",b.toString());this.resizeGroup_&&(this.workspace_.RTL?this.resizeGroup_.setAttribute("transform","translate("+2*Bubble$$module$build$src$core$bubble.BORDER_WIDTH+","+(b-c)+") scale(-1 1)"):this.resizeGroup_.setAttribute("transform","translate("+(a-c)+","+(b-c)+")"));this.autoLayout_&&this.layoutBubble_();this.positionBubble_();this.renderArrow_();this.resizeCallback_&&this.resizeCallback_()}renderArrow_(){const a= -[];var b=this.width_/2,c=this.height_/2,d=-this.relativeLeft_,e=-this.relativeTop_;if(b===d&&c===e)a.push("M "+b+","+c);else{e-=c;d-=b;this.workspace_.RTL&&(d*=-1);var f=Math.sqrt(e*e+d*d),g=Math.acos(d/f);0>e&&(g=2*Math.PI-g);var h=g+Math.PI/2;h>2*Math.PI&&(h-=2*Math.PI);var k=Math.sin(h);const n=Math.cos(h);var l=this.getBubbleSize();h=(l.width+l.height)/Bubble$$module$build$src$core$bubble.ARROW_THICKNESS;h=Math.min(h,l.width,l.height)/4;l=1-Bubble$$module$build$src$core$bubble.ANCHOR_RADIUS/f; -d=b+l*d;e=c+l*e;l=b+h*n;const p=c+h*k;b-=h*n;c-=h*k;k=g+this.arrow_radians_;k>2*Math.PI&&(k-=2*Math.PI);g=Math.sin(k)*f/Bubble$$module$build$src$core$bubble.ARROW_BEND;f=Math.cos(k)*f/Bubble$$module$build$src$core$bubble.ARROW_BEND;a.push("M"+l+","+p);a.push("C"+(l+f)+","+(p+g)+" "+d+","+e+" "+d+","+e);a.push("C"+d+","+e+" "+(b+f)+","+(c+g)+" "+b+","+c)}a.push("z");let m;null==(m=this.bubbleArrow_)||m.setAttribute("d",a.join(" "))}setColour(a){let b;null==(b=this.bubbleBack_)||b.setAttribute("fill", -a);let c;null==(c=this.bubbleArrow_)||c.setAttribute("fill",a)}dispose(){this.onMouseDownBubbleWrapper_&&unbind$$module$build$src$core$browser_events(this.onMouseDownBubbleWrapper_);this.onMouseDownResizeWrapper_&&unbind$$module$build$src$core$browser_events(this.onMouseDownResizeWrapper_);Bubble$$module$build$src$core$bubble.unbindDragEvents_();removeNode$$module$build$src$core$utils$dom(this.bubbleGroup_);this.disposed=!0}moveDuringDrag(a,b){a?a.translateSurface(b.x,b.y):this.moveTo(b.x,b.y);this.relativeLeft_= -this.workspace_.RTL?this.anchorXY_.x-b.x-this.width_:b.x-this.anchorXY_.x;this.relativeTop_=b.y-this.anchorXY_.y;this.renderArrow_()}getRelativeToSurfaceXY(){return new Coordinate$$module$build$src$core$utils$coordinate(this.workspace_.RTL?-this.relativeLeft_+this.anchorXY_.x-this.width_:this.anchorXY_.x+this.relativeLeft_,this.anchorXY_.y+this.relativeTop_)}setAutoLayout(a){this.autoLayout_=a}static unbindDragEvents_(){Bubble$$module$build$src$core$bubble.onMouseUpWrapper_&&(unbind$$module$build$src$core$browser_events(Bubble$$module$build$src$core$bubble.onMouseUpWrapper_), -Bubble$$module$build$src$core$bubble.onMouseUpWrapper_=null);Bubble$$module$build$src$core$bubble.onMouseMoveWrapper_&&(unbind$$module$build$src$core$browser_events(Bubble$$module$build$src$core$bubble.onMouseMoveWrapper_),Bubble$$module$build$src$core$bubble.onMouseMoveWrapper_=null)}static bubbleMouseUp_(a){clearTouchIdentifier$$module$build$src$core$touch();Bubble$$module$build$src$core$bubble.unbindDragEvents_()}static textToDom(a){const b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.TEXT, -{"class":"blocklyText blocklyBubbleText blocklyNoPointerEvents",y:Bubble$$module$build$src$core$bubble.BORDER_WIDTH});a=a.split("\n");for(let c=0;ca||Math.abs(this.workspaceHeight_-d)>a)this.workspaceWidth_=c,this.workspaceHeight_=d,this.bubble_.setBubbleSize(c+a,d+a),this.svgDialog_.setAttribute("width",`${this.workspaceWidth_}`),this.svgDialog_.setAttribute("height", -`${this.workspaceHeight_}`),this.workspace_.setCachedParentSvgSize(this.workspaceWidth_,this.workspaceHeight_);this.getBlock().RTL&&(a="translate("+this.workspaceWidth_+",0)",this.workspace_.getCanvas().setAttribute("transform",a));this.workspace_.resize()}onBubbleMove_(){this.workspace_&&this.workspace_.recordDragTargets()}setVisible(a){if(a!==this.isVisible()){var b=this.getBlock();fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(BUBBLE_OPEN$$module$build$src$core$events$utils))(b, -a,"mutator"));if(a){this.bubble_=new Bubble$$module$build$src$core$bubble(b.workspace,this.createEditor_(),b.pathObject.svgPath,this.iconXY_,null,null);this.bubble_.setSvgId(b.id);this.bubble_.registerMoveEvent(this.onBubbleMove_.bind(this));var c=this.workspace_.options.languageTree;a=this.workspace_.getFlyout();c&&(a.init(this.workspace_),a.show(c));this.rootBlock_=b.decompose(this.workspace_);c=this.rootBlock_.getDescendants(!1);for(let d=0,e;e=c[d];d++)e.render();this.rootBlock_.setMovable(!1); -this.rootBlock_.setDeletable(!1);a?(c=2*a.CORNER_RADIUS,a=this.rootBlock_.RTL?a.getWidth()+c:c):a=c=16;b.RTL&&(a=-a);this.rootBlock_.moveBy(a,c);if(b.saveConnections){const d=this.rootBlock_;b.saveConnections(d);this.sourceListener_=()=>{const e=this.getBlock();e.saveConnections&&e.saveConnections(d)};b.workspace.addChangeListener(this.sourceListener_)}this.resizeBubble_();this.workspace_.addChangeListener(this.workspaceChanged_.bind(this));this.updateWorkspace_();this.applyColour()}else this.svgDialog_= -null,this.workspace_.dispose(),this.rootBlock_=this.workspace_=null,null==(c=this.bubble_)||c.dispose(),this.bubble_=null,this.workspaceHeight_=this.workspaceWidth_=0,this.sourceListener_&&(b.workspace.removeChangeListener(this.sourceListener_),this.sourceListener_=null)}}workspaceChanged_(a){this.shouldIgnoreMutatorEvent_(a)||this.updateWorkspacePid_||(this.updateWorkspacePid_=setTimeout(()=>{this.updateWorkspacePid_=null;this.updateWorkspace_()},0))}shouldIgnoreMutatorEvent_(a){return a.isUiEvent|| -a.type===CREATE$$module$build$src$core$events$utils||a.type===CHANGE$$module$build$src$core$events$utils&&"disabled"===a.element}updateWorkspace_(){if(!this.workspace_.isDragging()){var a=this.workspace_.getTopBlocks(!1);for(let d=0,e;e=a[d];d++){var b=e.getRelativeToSurfaceXY();20>b.y&&e.moveBy(0,20-b.y);if(e.RTL){var c=-20;const f=this.workspace_.getFlyout();f&&(c-=f.getWidth());b.x>c&&e.moveBy(c-b.x,0)}else 20>b.x&&e.moveBy(20-b.x,0)}}if(this.rootBlock_&&this.rootBlock_.workspace===this.workspace_){(a= -getGroup$$module$build$src$core$events$utils())||setGroup$$module$build$src$core$events$utils(!0);const d=this.getBlock();b=BlockChange$$module$build$src$core$events$events_block_change.getExtraBlockState_(d);c=d.rendered;d.rendered=!1;d.compose(this.rootBlock_);d.rendered=c;d.initSvg();d.rendered&&d.render();c=BlockChange$$module$build$src$core$events$events_block_change.getExtraBlockState_(d);if(b!==c){fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(CHANGE$$module$build$src$core$events$utils))(d, -"mutation",null,b,c));const e=getGroup$$module$build$src$core$events$utils();setTimeout(function(){const f=getGroup$$module$build$src$core$events$utils();setGroup$$module$build$src$core$events$utils(e);d.bumpNeighbours();setGroup$$module$build$src$core$events$utils(f)},$.config$$module$build$src$core$config.bumpDelay)}this.workspace_.isDragging()||setTimeout(()=>this.resizeBubble_(),0);setGroup$$module$build$src$core$events$utils(a)}}dispose(){this.getBlock().mutator=null;super.dispose()}updateBlockStyle(){var a= -this.workspace_;if(a&&a.getAllBlocks(!1)){const b=a.getAllBlocks(!1);for(let c=0,d;d=b[c];c++)d.setStyle(d.getStyleName());if(a=a.getFlyout()){a=a.getWorkspace().getAllBlocks(!1);for(let c=0,d;d=a[c];c++)d.setStyle(d.getStyleName())}}}static reconnect(a,b,c){if(!a||!a.getSourceBlock().workspace)return!1;c=b.getInput(c).connection;const d=a.targetBlock();return d&&d!==b||!c||c.targetConnection===a?!1:(c.isConnected()&&c.disconnect(),c.connect(a),!0)}static findParentWs(a){let b=null;if(a&&a.options){const c= -a.options.parentWorkspace;a.isFlyout?c&&c.options&&(b=c.options.parentWorkspace):c&&(b=c)}return b}};module$build$src$core$mutator={};module$build$src$core$mutator.Mutator=$.Mutator$$module$build$src$core$mutator;var allExtensions$$module$build$src$core$extensions=Object.create(null),TEST_ONLY$$module$build$src$core$extensions={allExtensions:allExtensions$$module$build$src$core$extensions};register$$module$build$src$core$extensions("parent_tooltip_when_inline",extensionParentTooltip$$module$build$src$core$extensions);$.module$build$src$core$extensions={};$.module$build$src$core$extensions.TEST_ONLY=TEST_ONLY$$module$build$src$core$extensions;$.module$build$src$core$extensions.apply=apply$$module$build$src$core$extensions; -$.module$build$src$core$extensions.buildTooltipForDropdown=buildTooltipForDropdown$$module$build$src$core$extensions;$.module$build$src$core$extensions.buildTooltipWithFieldText=buildTooltipWithFieldText$$module$build$src$core$extensions;$.module$build$src$core$extensions.isRegistered=isRegistered$$module$build$src$core$extensions;$.module$build$src$core$extensions.register=register$$module$build$src$core$extensions;$.module$build$src$core$extensions.registerMixin=registerMixin$$module$build$src$core$extensions; -$.module$build$src$core$extensions.registerMutator=registerMutator$$module$build$src$core$extensions;$.module$build$src$core$extensions.runAfterPageLoad=runAfterPageLoad$$module$build$src$core$extensions;$.module$build$src$core$extensions.unregister=unregister$$module$build$src$core$extensions;var module$build$src$core$utils$array={};module$build$src$core$utils$array.removeElem=removeElem$$module$build$src$core$utils$array;var module$build$src$core$utils$svg_paths={};module$build$src$core$utils$svg_paths.arc=arc$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.curve=curve$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.line=line$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.lineOnAxis=lineOnAxis$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.lineTo=lineTo$$module$build$src$core$utils$svg_paths; -module$build$src$core$utils$svg_paths.moveBy=moveBy$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.moveTo=moveTo$$module$build$src$core$utils$svg_paths;module$build$src$core$utils$svg_paths.point=point$$module$build$src$core$utils$svg_paths;var getInjectionDivXY_$$module$build$src$core$utils=getInjectionDivXY$$module$build$src$core$utils,module$build$src$core$utils={};module$build$src$core$utils.Coordinate=Coordinate$$module$build$src$core$utils$coordinate;module$build$src$core$utils.KeyCodes=KeyCodes$$module$build$src$core$utils$keycodes;module$build$src$core$utils.Rect=Rect$$module$build$src$core$utils$rect;module$build$src$core$utils.Size=Size$$module$build$src$core$utils$size;module$build$src$core$utils.Svg=Svg$$module$build$src$core$utils$svg; -module$build$src$core$utils.aria=module$build$src$core$utils$aria;module$build$src$core$utils.array=module$build$src$core$utils$array;module$build$src$core$utils.arrayRemove=arrayRemove$$module$build$src$core$utils;module$build$src$core$utils.browserEvents=module$build$src$core$browser_events;module$build$src$core$utils.checkMessageReferences=checkMessageReferences$$module$build$src$core$utils;module$build$src$core$utils.colour=module$build$src$core$utils$colour; -module$build$src$core$utils.deprecation=module$build$src$core$utils$deprecation;module$build$src$core$utils.dom=module$build$src$core$utils$dom;module$build$src$core$utils.extensions=$.module$build$src$core$extensions;module$build$src$core$utils.getBlockTypeCounts=getBlockTypeCounts$$module$build$src$core$utils;module$build$src$core$utils.getDocumentScroll=getDocumentScroll$$module$build$src$core$utils;module$build$src$core$utils.getInjectionDivXY_=getInjectionDivXY$$module$build$src$core$utils; -module$build$src$core$utils.getRelativeXY=getRelativeXY$$module$build$src$core$utils;module$build$src$core$utils.getViewportBBox=getViewportBBox$$module$build$src$core$utils;module$build$src$core$utils.idGenerator=module$build$src$core$utils$idgenerator;module$build$src$core$utils.is3dSupported=is3dSupported$$module$build$src$core$utils;module$build$src$core$utils.math=module$build$src$core$utils$math;module$build$src$core$utils.object=$.module$build$src$core$utils$object; -module$build$src$core$utils.parseBlockColour=parseBlockColour$$module$build$src$core$utils;module$build$src$core$utils.parsing=module$build$src$core$utils$parsing;module$build$src$core$utils.replaceMessageReferences=replaceMessageReferences$$module$build$src$core$utils;module$build$src$core$utils.runAfterPageLoad=runAfterPageLoad$$module$build$src$core$utils;module$build$src$core$utils.screenToWsCoordinates=screenToWsCoordinates$$module$build$src$core$utils;module$build$src$core$utils.string=$.module$build$src$core$utils$string; -module$build$src$core$utils.style=module$build$src$core$utils$style;module$build$src$core$utils.svgMath=module$build$src$core$utils$svg_math;module$build$src$core$utils.svgPaths=module$build$src$core$utils$svg_paths;module$build$src$core$utils.tokenizeInterpolation=tokenizeInterpolation$$module$build$src$core$utils;module$build$src$core$utils.toolbox=module$build$src$core$utils$toolbox;module$build$src$core$utils.userAgent=module$build$src$core$utils$useragent;module$build$src$core$utils.xml=$.module$build$src$core$utils$xml;var TrashcanOpen$$module$build$src$core$events$events_trashcan_open=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b){super(b);this.type=TRASHCAN_OPEN$$module$build$src$core$events$utils;this.isOpen=a}toJson(){const a=super.toJson();if(void 0===this.isOpen)throw Error("Whether this is already open or not is undefined. Either pass a value to the constructor, or call fromJson");a.isOpen=this.isOpen;return a}fromJson(a){super.fromJson(a);this.isOpen=a.isOpen}}; -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,TRASHCAN_OPEN$$module$build$src$core$events$utils,TrashcanOpen$$module$build$src$core$events$events_trashcan_open);var module$build$src$core$events$events_trashcan_open={};module$build$src$core$events$events_trashcan_open.TrashcanOpen=TrashcanOpen$$module$build$src$core$events$events_trashcan_open;var Capability$$module$build$src$core$component_manager=class{constructor(a){this.name_=a}toString(){return this.name_}};Capability$$module$build$src$core$component_manager.POSITIONABLE=new Capability$$module$build$src$core$component_manager("positionable");Capability$$module$build$src$core$component_manager.DRAG_TARGET=new Capability$$module$build$src$core$component_manager("drag_target");Capability$$module$build$src$core$component_manager.DELETE_AREA=new Capability$$module$build$src$core$component_manager("delete_area"); -Capability$$module$build$src$core$component_manager.AUTOHIDEABLE=new Capability$$module$build$src$core$component_manager("autohideable"); -var ComponentManager$$module$build$src$core$component_manager=class{constructor(){this.componentData=new Map;this.capabilityToComponentIds=new Map}addComponent(a,b){const c=a.component.id;if(!b&&this.componentData.has(c)){var d;throw Error('Plugin "'+c+'" with capabilities "'+(null==(d=this.componentData.get(c))?void 0:d.capabilities)+'" already added.');}this.componentData.set(c,a);b=[];for(d=0;d{d.push(this.componentData.get(e))});d.sort(function(e,f){return e.weight-f.weight});d.forEach(function(e){c.push(e.component)})}else a.forEach(d=>{c.push(this.componentData.get(d).component)});return c}};ComponentManager$$module$build$src$core$component_manager.Capability=Capability$$module$build$src$core$component_manager;var module$build$src$core$component_manager={}; -module$build$src$core$component_manager.ComponentManager=ComponentManager$$module$build$src$core$component_manager;var DeserializationError$$module$build$src$core$serialization$exceptions=class extends Error{},MissingBlockType$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a){super("Expected to find a 'type' property, defining the block type");this.state=a}},MissingConnection$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a, -b,c){super(`The block ${b.toDevString()} is missing a(n) ${a} -connection`);this.block=b;this.state=c}},BadConnectionCheck$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a,b,c,d){super(`The block ${c.toDevString()} could not connect its -${b} to its parent, because: ${a}`);this.childBlock=c;this.childState=d}},RealChildOfShadow$$module$build$src$core$serialization$exceptions=class extends DeserializationError$$module$build$src$core$serialization$exceptions{constructor(a){super("Encountered a real block which is defined as a child of a shadow\nblock. It is an invariant of Blockly that shadow blocks only have shadow\nchildren");this.state=a}},module$build$src$core$serialization$exceptions={}; -module$build$src$core$serialization$exceptions.BadConnectionCheck=BadConnectionCheck$$module$build$src$core$serialization$exceptions;module$build$src$core$serialization$exceptions.DeserializationError=DeserializationError$$module$build$src$core$serialization$exceptions;module$build$src$core$serialization$exceptions.MissingBlockType=MissingBlockType$$module$build$src$core$serialization$exceptions;module$build$src$core$serialization$exceptions.MissingConnection=MissingConnection$$module$build$src$core$serialization$exceptions; -module$build$src$core$serialization$exceptions.RealChildOfShadow=RealChildOfShadow$$module$build$src$core$serialization$exceptions;var VARIABLES$$module$build$src$core$serialization$priorities=100,BLOCKS$$module$build$src$core$serialization$priorities=50,module$build$src$core$serialization$priorities={};module$build$src$core$serialization$priorities.BLOCKS=BLOCKS$$module$build$src$core$serialization$priorities;module$build$src$core$serialization$priorities.VARIABLES=VARIABLES$$module$build$src$core$serialization$priorities;var module$build$src$core$serialization$registry={};module$build$src$core$serialization$registry.register=register$$module$build$src$core$serialization$registry;module$build$src$core$serialization$registry.unregister=unregister$$module$build$src$core$serialization$registry;var saveBlock$$module$build$src$core$serialization$blocks=save$$module$build$src$core$serialization$blocks,BlockSerializer$$module$build$src$core$serialization$blocks=class{constructor(){this.priority=BLOCKS$$module$build$src$core$serialization$priorities}save(a){const b=[];for(const c of a.getTopBlocks(!1))(a=save$$module$build$src$core$serialization$blocks(c,{addCoordinates:!0,doFullSerialization:!1}))&&b.push(a);return b.length?{languageVersion:0,blocks:b}:null}load(a,b){a=a.blocks;for(const c of a)append$$module$build$src$core$serialization$blocks(c, -b,{recordUndo:getRecordUndo$$module$build$src$core$events$utils()})}clear(a){for(const b of a.getTopBlocks(!1))b.dispose(!1)}};register$$module$build$src$core$serialization$registry("blocks",new BlockSerializer$$module$build$src$core$serialization$blocks);var module$build$src$core$serialization$blocks={};module$build$src$core$serialization$blocks.append=append$$module$build$src$core$serialization$blocks;module$build$src$core$serialization$blocks.appendInternal=appendInternal$$module$build$src$core$serialization$blocks; -module$build$src$core$serialization$blocks.save=save$$module$build$src$core$serialization$blocks;var BlockCreate$$module$build$src$core$events$events_block_create=class extends BlockBase$$module$build$src$core$events$events_block_base{constructor(a){super(a);this.type=CREATE$$module$build$src$core$events$utils;a&&(a.isShadow()&&(this.recordUndo=!1),this.xml=blockToDomWithXY$$module$build$src$core$xml(a),this.ids=getDescendantIds$$module$build$src$core$events$utils(a),this.json=save$$module$build$src$core$serialization$blocks(a,{addCoordinates:!0}))}toJson(){const a=super.toJson();if(!this.xml)throw Error("The block XML is undefined. Either pass a block to the constructor, or call fromJson"); -if(!this.ids)throw Error("The block IDs are undefined. Either pass a block to the constructor, or call fromJson");if(!this.json)throw Error("The block JSON is undefined. Either pass a block to the constructor, or call fromJson");a.xml=domToText$$module$build$src$core$xml(this.xml);a.ids=this.ids;a.json=this.json;this.recordUndo||(a.recordUndo=this.recordUndo);return a}fromJson(a){super.fromJson(a);this.xml=textToDom$$module$build$src$core$xml(a.xml);this.ids=a.ids;this.json=a.json;void 0!==a.recordUndo&& -(this.recordUndo=a.recordUndo)}run(a){const b=this.getEventWorkspace_();if(!this.json)throw Error("The block JSON is undefined. Either pass a block to the constructor, or call fromJson");if(!this.ids)throw Error("The block IDs are undefined. Either pass a block to the constructor, or call fromJson");if(a)append$$module$build$src$core$serialization$blocks(this.json,b);else for(a=0;aa||a>this.fieldRow.length)throw Error("index "+ -a+" out of bounds.");if(!(b||""===b&&c))return a;"string"===typeof b&&(b=fromJson$$module$build$src$core$field_registry({type:"field_label",text:b}));b.setSourceBlock(this.sourceBlock_);this.sourceBlock_.rendered&&(b.init(),b.applyColour());b.name=c;b.setVisible(this.isVisible());b.prefixField&&(a=this.insertFieldAt(a,b.prefixField));this.fieldRow.splice(a,0,b);a++;b.suffixField&&(a=this.insertFieldAt(a,b.suffixField));this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours()); -return a}removeField(a,b){for(let c=0,d;d=this.fieldRow[c];c++)if(d.name===a)return d.dispose(),this.fieldRow.splice(c,1),this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours()),!0;if(b)return!1;throw Error('Field "'+a+'" not found.');}isVisible(){return this.visible_}setVisible(a){let b=[];if(this.visible_===a)return b;this.visible_=a;for(let d=0,e;e=this.fieldRow[d];d++)e.setVisible(a);if(this.connection){var c=this.connection;a?b=c.startTrackingAll():c.stopTrackingAll(); -if(c=c.targetBlock())c.getSvgRoot().style.display=a?"block":"none"}return b}markDirty(){for(let a=0,b;b=this.fieldRow[a];a++)b.markDirty()}setCheck(a){if(!this.connection)throw Error("This input does not have a connection.");this.connection.setCheck(a);return this}setAlign(a){this.align=a;this.sourceBlock_.rendered&&this.sourceBlock_.render();return this}setShadowDom(a){if(!this.connection)throw Error("This input does not have a connection.");this.connection.setShadowDom(a);return this}getShadowDom(){if(!this.connection)throw Error("This input does not have a connection."); -return this.connection.getShadowDom()}init(){if(this.sourceBlock_.workspace.rendered)for(let a=0;aa&&(e=e.substring(0,a-3)+"...");return e}appendValueInput(a){return this.appendInput_(inputTypes$$module$build$src$core$input_types.VALUE,a)}appendStatementInput(a){return this.appendInput_(inputTypes$$module$build$src$core$input_types.STATEMENT,a)}appendDummyInput(a){return this.appendInput_(inputTypes$$module$build$src$core$input_types.DUMMY, -a||"")}jsonInit(a){var b=a.type?'Block "'+a.type+'": ':"";if(a.output&&a.previousStatement)throw Error(b+"Must not have both an output and a previousStatement.");a.style&&a.style.hat&&(this.hat=a.style.hat,a.style=null);if(a.style&&a.colour)throw Error(b+"Must not have both a colour and a style.");a.style?this.jsonInitStyle_(a,b):this.jsonInitColour_(a,b);for(var c=0;void 0!==a["message"+c];)this.interpolate_(a["message"+c],a["args"+c]||[],a["lastDummyAlign"+c],b),c++;void 0!==a.inputsInline&&this.setInputsInline(a.inputsInline); -void 0!==a.output&&this.setOutput(!0,a.output);void 0!==a.outputShape&&this.setOutputShape(a.outputShape);void 0!==a.previousStatement&&this.setPreviousStatement(!0,a.previousStatement);void 0!==a.nextStatement&&this.setNextStatement(!0,a.nextStatement);void 0!==a.tooltip&&(c=replaceMessageReferences$$module$build$src$core$utils$parsing(a.tooltip),this.setTooltip(c));void 0!==a.enableContextMenu&&(this.contextMenu=!!a.enableContextMenu);void 0!==a.suppressPrefixSuffix&&(this.suppressPrefixSuffix= -!!a.suppressPrefixSuffix);void 0!==a.helpUrl&&(c=replaceMessageReferences$$module$build$src$core$utils$parsing(a.helpUrl),this.setHelpUrl(c));"string"===typeof a.extensions&&(console.warn(b+"JSON attribute 'extensions' should be an array of strings. Found raw string in JSON for '"+a.type+"' block."),a.extensions=[a.extensions]);void 0!==a.mutator&&apply$$module$build$src$core$extensions(a.mutator,this,!0);a=a.extensions;if(Array.isArray(a))for(b=0;b -f||f>b)throw Error('Block "'+this.type+'": Message index %'+f+" out of range.");if(c[f])throw Error('Block "'+this.type+'": Message index %'+f+" duplicated.");c[f]=!0;d++}}if(d!==b)throw Error('Block "'+this.type+'": Message does not reference all '+b+" arg(s).");}interpolateArguments_(a,b,c){const d=[];for(let e=0;e=this.inputList.length)throw RangeError("Input index "+a+" out of bounds.");if(b>this.inputList.length)throw RangeError("Reference input "+b+" out of bounds.");const c=this.inputList[a];this.inputList.splice(a,1);a{this.isDeadOrDying()||(this.warningTextDb.delete(c),this.setWarningText(a,c))},100));else{this.isInFlyout&&(a=null);b=!1;if("string"===typeof a){d=this.getSurroundParent();let e=null;for(;d;)d.isCollapsed()&&(e=d),d=d.getSurroundParent();e&&e.setWarningText(Msg$$module$build$src$core$msg.COLLAPSED_WARNINGS_WARNING,BlockSvg$$module$build$src$core$block_svg.COLLAPSED_WARNING_ID);this.warning||(this.warning=new Warning$$module$build$src$core$warning(this),b=!0);this.warning.setText(a, -c)}else this.warning&&!c?(this.warning.dispose(),b=!0):this.warning&&(b=this.warning.getText(),this.warning.setText("",c),(d=this.warning.getText())||this.warning.dispose(),b=b!==d);b&&this.rendered&&(this.render(),this.bumpNeighbours())}}setMutator(a){this.mutator&&this.mutator!==a&&this.mutator.dispose();a&&(a.setBlock(this),this.mutator=a,a.createIcon());this.rendered&&(this.render(),this.bumpNeighbours())}setEnabled(a){this.isEnabled()!==a&&(super.setEnabled(a),this.rendered&&!this.getInheritedDisabled()&& -this.updateDisabled())}setHighlighted(a){this.rendered&&this.pathObject.updateHighlighted(a)}addSelect(){this.pathObject.updateSelected(!0)}removeSelect(){this.pathObject.updateSelected(!1)}setDeleteStyle(a){this.pathObject.updateDraggingDelete(a)}getColour(){return this.style.colourPrimary}setColour(a){super.setColour(a);a=this.workspace.getRenderer().getConstants().getBlockStyleForColour(this.colour_);this.pathObject.setStyle(a.style);this.style=a.style;this.styleName_=a.name;this.applyColour()}setStyle(a){const b= -this.workspace.getRenderer().getConstants().getBlockStyle(a);this.styleName_=a;if(b)this.hat=b.hat,this.pathObject.setStyle(b),this.colour_=b.colourPrimary,this.style=b,this.applyColour();else throw Error("Invalid style name: "+a);}bringToFront(){let a=this;do{const b=a.getSvgRoot(),c=b.parentNode,d=c.childNodes;d[d.length-1]!==b&&c.appendChild(b);a=a.getParent()}while(a)}setPreviousStatement(a,b){super.setPreviousStatement(a,b);this.rendered&&(this.render(),this.bumpNeighbours())}setNextStatement(a, -b){super.setNextStatement(a,b);this.rendered&&(this.render(),this.bumpNeighbours())}setOutput(a,b){super.setOutput(a,b);this.rendered&&(this.render(),this.bumpNeighbours())}setInputsInline(a){super.setInputsInline(a);this.rendered&&(this.render(),this.bumpNeighbours())}removeInput(a,b){a=super.removeInput(a,b);this.rendered&&(this.render(),this.bumpNeighbours());return a}moveNumberedInputBefore(a,b){super.moveNumberedInputBefore(a,b);this.rendered&&(this.render(),this.bumpNeighbours())}appendInput_(a, -b){a=super.appendInput_(a,b);this.rendered&&(this.render(),this.bumpNeighbours());return a}setConnectionTracking(a){this.previousConnection&&this.previousConnection.setTracking(a);this.outputConnection&&this.outputConnection.setTracking(a);if(this.nextConnection){this.nextConnection.setTracking(a);var b=this.nextConnection.targetBlock();b&&b.setConnectionTracking(a)}if(!this.collapsed_)for(b=0;b{setGroup$$module$build$src$core$events$utils(a);this.snapToGrid();setGroup$$module$build$src$core$events$utils(!1)},$.config$$module$build$src$core$config.bumpDelay/2);setTimeout(()=>{setGroup$$module$build$src$core$events$utils(a);this.bumpNeighbours();setGroup$$module$build$src$core$events$utils(!1)},$.config$$module$build$src$core$config.bumpDelay)}positionNearConnection(a, -b){a.type!==ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT&&a.type!==ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE||this.moveBy(b.x-a.x,b.y-a.y)}getFirstStatementConnection(){return super.getFirstStatementConnection()}getChildren(a){return super.getChildren(a)}render(a){if(!this.renderIsInProgress_){this.renderIsInProgress_=!0;try{this.rendered=!0;startTextWidthCache$$module$build$src$core$utils$dom();this.isCollapsed()&&this.updateCollapsed_();this.workspace.getRenderer().render(this); -this.updateConnectionLocations_();if(!1!==a){const b=this.getParent();b?b.render(!0):this.workspace.resizeContents()}stopTextWidthCache$$module$build$src$core$utils$dom();this.updateMarkers_()}finally{this.renderIsInProgress_=!1}}}updateMarkers_(){this.workspace.keyboardAccessibilityMode&&this.pathObject.cursorSvg&&this.workspace.getCursor().draw();this.workspace.keyboardAccessibilityMode&&this.pathObject.markerSvg&&this.workspace.getMarker(MarkerManager$$module$build$src$core$marker_manager.LOCAL_MARKER).draw()}updateConnectionLocations_(){const a= -this.getRelativeToSurfaceXY();this.previousConnection&&this.previousConnection.moveToOffset(a);this.outputConnection&&this.outputConnection.moveToOffset(a);for(let b=0;b=this.workspace.options.maxTrashcanContents||(a=new Options$$module$build$src$core$options({scrollbars:!0,parentWorkspace:this.workspace,rtl:this.workspace.RTL, -oneBasedIndex:this.workspace.options.oneBasedIndex,renderer:this.workspace.options.renderer,rendererOverrides:this.workspace.options.rendererOverrides,move:{scrollbars:!0}}),this.workspace.horizontalLayout?(a.toolboxPosition=this.workspace.toolboxPosition===Position$$module$build$src$core$utils$toolbox.TOP?Position$$module$build$src$core$utils$toolbox.BOTTOM:Position$$module$build$src$core$utils$toolbox.TOP,this.flyout=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX, -this.workspace.options,!0))(a)):(a.toolboxPosition=this.workspace.toolboxPosition===Position$$module$build$src$core$utils$toolbox.RIGHT?Position$$module$build$src$core$utils$toolbox.LEFT:Position$$module$build$src$core$utils$toolbox.RIGHT,this.flyout=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX,this.workspace.options,!0))(a)),this.workspace.addChangeListener(this.onDelete_.bind(this)))}createDom(){this.svgGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G, -{"class":"blocklyTrash"});let a;const b=String(Math.random()).substring(2);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CLIPPATH,{id:"blocklyTrashBodyClipPath"+b},this.svgGroup_);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{width:WIDTH$$module$build$src$core$trashcan,height:BODY_HEIGHT$$module$build$src$core$trashcan,y:LID_HEIGHT$$module$build$src$core$trashcan},a);const c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE, -{width:SPRITE$$module$build$src$core$sprites.width,x:-SPRITE_LEFT$$module$build$src$core$trashcan,height:SPRITE$$module$build$src$core$sprites.height,y:-SPRITE_TOP$$module$build$src$core$trashcan,"clip-path":"url(#blocklyTrashBodyClipPath"+b+")"},this.svgGroup_);c.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.workspace.options.pathToMedia+SPRITE$$module$build$src$core$sprites.url);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CLIPPATH, -{id:"blocklyTrashLidClipPath"+b},this.svgGroup_);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{width:WIDTH$$module$build$src$core$trashcan,height:LID_HEIGHT$$module$build$src$core$trashcan},a);this.svgLid_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{width:SPRITE$$module$build$src$core$sprites.width,x:-SPRITE_LEFT$$module$build$src$core$trashcan,height:SPRITE$$module$build$src$core$sprites.height,y:-SPRITE_TOP$$module$build$src$core$trashcan, -"clip-path":"url(#blocklyTrashLidClipPath"+b+")"},this.svgGroup_);this.svgLid_.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.workspace.options.pathToMedia+SPRITE$$module$build$src$core$sprites.url);bind$$module$build$src$core$browser_events(this.svgGroup_,"mousedown",this,this.blockMouseDownWhenOpenable_);bind$$module$build$src$core$browser_events(this.svgGroup_,"mouseup",this,this.click);bind$$module$build$src$core$browser_events(c,"mouseover",this,this.mouseOver_);bind$$module$build$src$core$browser_events(c, -"mouseout",this,this.mouseOut_);this.animateLid_();return this.svgGroup_}init(){0this.minOpenness_&&1>this.lidOpen_&&(this.lidTask_=setTimeout(this.animateLid_.bind(this),ANIMATION_LENGTH$$module$build$src$core$trashcan/ -a))}setLidAngle_(a){const b=this.workspace.toolboxPosition===Position$$module$build$src$core$utils$toolbox.RIGHT||this.workspace.horizontalLayout&&this.workspace.RTL;let c;null==(c=this.svgLid_)||c.setAttribute("transform","rotate("+(b?-a:a)+","+(b?4:WIDTH$$module$build$src$core$trashcan-4)+","+(LID_HEIGHT$$module$build$src$core$trashcan-2)+")")}setMinOpenness_(a){this.minOpenness_=a;this.isLidOpen||this.setLidAngle_(a*MAX_LID_ANGLE$$module$build$src$core$trashcan)}closeLid(){this.setLidOpen(!1)}click(){this.hasContents_()&& -this.openFlyout()}fireUiEvent_(a){a=new (get$$module$build$src$core$events$utils(TRASHCAN_OPEN$$module$build$src$core$events$utils))(a,this.workspace.id);fire$$module$build$src$core$events$utils(a)}blockMouseDownWhenOpenable_(a){!this.contentsIsOpen()&&this.hasContents_()&&a.stopPropagation()}mouseOver_(){this.hasContents_()&&this.setLidOpen(!0)}mouseOut_(){this.setLidOpen(!1)}onDelete_(a){if(!(0>=this.workspace.options.maxTrashcanContents||a.type!==DELETE$$module$build$src$core$events$utils||a.type!== -DELETE$$module$build$src$core$events$utils||a.wasShadow)){if(!a.oldJson)throw Error("Encountered a delete event without proper oldJson");a=JSON.stringify(this.cleanBlockJson_(a.oldJson));if(-1===this.contents_.indexOf(a)){for(this.contents_.unshift(a);this.contents_.length>this.workspace.options.maxTrashcanContents;)this.contents_.pop();this.setMinOpenness_(HAS_BLOCKS_LID_ANGLE$$module$build$src$core$trashcan)}}}cleanBlockJson_(a){function b(c){if(c){delete c.id;delete c.x;delete c.y;delete c.enabled; -if(c.icons&&c.icons.comment){var d=c.icons.comment;delete d.height;delete d.width;delete d.pinned}d=c.inputs;for(var e in d){var f=d[e];const g=f.block;f=f.shadow;g&&b(g);f&&b(f)}c.next&&(e=c.next,c=e.block,e=e.shadow,c&&b(c),e&&b(e))}}a=JSON.parse(JSON.stringify(a));b(a);return Object.assign({},{kind:"BLOCK"},a)}},WIDTH$$module$build$src$core$trashcan=47,BODY_HEIGHT$$module$build$src$core$trashcan=44,LID_HEIGHT$$module$build$src$core$trashcan=16,MARGIN_VERTICAL$$module$build$src$core$trashcan=20, -MARGIN_HORIZONTAL$$module$build$src$core$trashcan=20,MARGIN_HOTSPOT$$module$build$src$core$trashcan=10,SPRITE_LEFT$$module$build$src$core$trashcan=0,SPRITE_TOP$$module$build$src$core$trashcan=32,HAS_BLOCKS_LID_ANGLE$$module$build$src$core$trashcan=.1,ANIMATION_LENGTH$$module$build$src$core$trashcan=80,ANIMATION_FRAMES$$module$build$src$core$trashcan=4,OPACITY_MIN$$module$build$src$core$trashcan=.4,OPACITY_MAX$$module$build$src$core$trashcan=.8,MAX_LID_ANGLE$$module$build$src$core$trashcan=45,module$build$src$core$trashcan= -{};module$build$src$core$trashcan.Trashcan=Trashcan$$module$build$src$core$trashcan;var ToolboxItemSelect$$module$build$src$core$events$events_toolbox_item_select=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c){super(c);this.type=TOOLBOX_ITEM_SELECT$$module$build$src$core$events$utils;this.oldItem=null!=a?a:void 0;this.newItem=null!=b?b:void 0}toJson(){const a=super.toJson();a.oldItem=this.oldItem;a.newItem=this.newItem;return a}fromJson(a){super.fromJson(a);this.oldItem=a.oldItem;this.newItem=a.newItem}}; -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,TOOLBOX_ITEM_SELECT$$module$build$src$core$events$utils,ToolboxItemSelect$$module$build$src$core$events$events_toolbox_item_select);var module$build$src$core$events$events_toolbox_item_select={};module$build$src$core$events$events_toolbox_item_select.ToolboxItemSelect=ToolboxItemSelect$$module$build$src$core$events$events_toolbox_item_select;var ToolboxItem$$module$build$src$core$toolbox$toolbox_item=class{constructor(a,b,c){this.id_=a.toolboxitemid||getNextUniqueId$$module$build$src$core$utils$idgenerator();this.level_=(this.parent_=c||null)?this.parent_.getLevel()+1:0;this.toolboxItemDef_=a;this.parentToolbox_=b;this.workspace_=this.parentToolbox_.getWorkspace()}init(){}getDiv(){return null}getClickTarget(){return null}getId(){return this.id_}getParent(){return null}getLevel(){return this.level_}isSelectable(){return!1}isCollapsible(){return!1}dispose(){}setVisible_(a){}}, -module$build$src$core$toolbox$toolbox_item={};module$build$src$core$toolbox$toolbox_item.ToolboxItem=ToolboxItem$$module$build$src$core$toolbox$toolbox_item;var ToolboxCategory$$module$build$src$core$toolbox$category=class extends ToolboxItem$$module$build$src$core$toolbox$toolbox_item{constructor(a,b,c){super(a,b,c);this.colour_=this.name_="";this.labelDom_=this.iconDom_=this.rowContents_=this.rowDiv_=this.htmlDiv_=null;this.isDisabled_=this.isHidden_=!1;this.flyoutItems_=[];this.cssConfig_=this.makeDefaultCssConfig_()}init(){this.parseCategoryDef_(this.toolboxItemDef_);this.parseContents_(this.toolboxItemDef_);this.createDom_();"true"===this.toolboxItemDef_.hidden&& -this.hide()}makeDefaultCssConfig_(){return{container:"blocklyToolboxCategory",row:"blocklyTreeRow",rowcontentcontainer:"blocklyTreeRowContentContainer",icon:"blocklyTreeIcon",label:"blocklyTreeLabel",contents:"blocklyToolboxContents",selected:"blocklyTreeSelected",openicon:"blocklyTreeIconOpen",closedicon:"blocklyTreeIconClosed"}}parseContents_(a){if("custom"in a)this.flyoutItems_=a.custom;else if(a=a.contents)for(let b=0;b>>/sprites.png);\n height: 16px;\n vertical-align: middle;\n visibility: hidden;\n width: 16px;\n}\n\n.blocklyTreeIconClosed {\n background-position: -32px -1px;\n}\n\n.blocklyToolboxDiv[dir="RTL"] .blocklyTreeIconClosed {\n background-position: 0 -1px;\n}\n\n.blocklyTreeSelected>.blocklyTreeIconClosed {\n background-position: -32px -17px;\n}\n\n.blocklyToolboxDiv[dir="RTL"] .blocklyTreeSelected>.blocklyTreeIconClosed {\n background-position: 0 -17px;\n}\n\n.blocklyTreeIconOpen {\n background-position: -16px -1px;\n}\n\n.blocklyTreeSelected>.blocklyTreeIconOpen {\n background-position: -16px -17px;\n}\n\n.blocklyTreeLabel {\n cursor: default;\n font: 16px sans-serif;\n padding: 0 3px;\n vertical-align: middle;\n}\n\n.blocklyToolboxDelete .blocklyTreeLabel {\n cursor: url("<<>>/handdelete.cur"), auto;\n}\n\n.blocklyTreeSelected .blocklyTreeLabel {\n color: #fff;\n}\n'); -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX_ITEM,ToolboxCategory$$module$build$src$core$toolbox$category.registrationName,ToolboxCategory$$module$build$src$core$toolbox$category);var module$build$src$core$toolbox$category={};module$build$src$core$toolbox$category.ToolboxCategory=ToolboxCategory$$module$build$src$core$toolbox$category;var ToolboxSeparator$$module$build$src$core$toolbox$separator=class extends ToolboxItem$$module$build$src$core$toolbox$toolbox_item{constructor(a,b){super(a,b);this.cssConfig_={container:"blocklyTreeSeparator"};this.htmlDiv_=null;Object.assign(this.cssConfig_,a.cssconfig||a.cssConfig)}init(){this.createDom_()}createDom_(){const a=document.createElement("div"),b=this.cssConfig_.container;b&&addClass$$module$build$src$core$utils$dom(a,b);return this.htmlDiv_=a}getDiv(){return this.htmlDiv_}dispose(){removeNode$$module$build$src$core$utils$dom(this.htmlDiv_)}}; -ToolboxSeparator$$module$build$src$core$toolbox$separator.registrationName="sep";register$$module$build$src$core$css('\n.blocklyTreeSeparator {\n border-bottom: solid #e5e5e5 1px;\n height: 0;\n margin: 5px 0;\n}\n\n.blocklyToolboxDiv[layout="h"] .blocklyTreeSeparator {\n border-right: solid #e5e5e5 1px;\n border-bottom: none;\n height: auto;\n margin: 0 5px 0 5px;\n padding: 5px 0;\n width: 0;\n}\n'); -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX_ITEM,ToolboxSeparator$$module$build$src$core$toolbox$separator.registrationName,ToolboxSeparator$$module$build$src$core$toolbox$separator);var module$build$src$core$toolbox$separator={};module$build$src$core$toolbox$separator.ToolboxSeparator=ToolboxSeparator$$module$build$src$core$toolbox$separator;var CollapsibleToolboxCategory$$module$build$src$core$toolbox$collapsible_category=class extends ToolboxCategory$$module$build$src$core$toolbox$category{constructor(a,b,c){super(a,b,c);this.subcategoriesDiv_=null;this.expanded_=!1;this.toolboxItems_=[]}makeDefaultCssConfig_(){const a=super.makeDefaultCssConfig_();a.contents="blocklyToolboxContents";return a}parseContents_(a){const b=a.contents;let c=!0;if(a.custom)this.flyoutItems_=a.custom;else if(b)for(a=0;a>>/handdelete.cur"), auto;\n}\n\n.blocklyToolboxGrab {\n cursor: url("<<>>/handclosed.cur"), auto;\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n/* Category tree in Toolbox. */\n.blocklyToolboxDiv {\n background-color: #ddd;\n overflow-x: visible;\n overflow-y: auto;\n padding: 4px 0 4px 0;\n position: absolute;\n z-index: 70; /* so blocks go under toolbox when dragging */\n -webkit-tap-highlight-color: transparent; /* issue #1345 */\n}\n\n.blocklyToolboxContents {\n display: flex;\n flex-wrap: wrap;\n flex-direction: column;\n}\n\n.blocklyToolboxContents:focus {\n outline: none;\n}\n'); -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX,DEFAULT$$module$build$src$core$registry,Toolbox$$module$build$src$core$toolbox$toolbox);var module$build$src$core$toolbox$toolbox={};module$build$src$core$toolbox$toolbox.Toolbox=Toolbox$$module$build$src$core$toolbox$toolbox;var defaultBlockStyles$$module$build$src$core$theme$zelos={colour_blocks:{colourPrimary:"#CF63CF",colourSecondary:"#C94FC9",colourTertiary:"#BD42BD"},list_blocks:{colourPrimary:"#9966FF",colourSecondary:"#855CD6",colourTertiary:"#774DCB"},logic_blocks:{colourPrimary:"#4C97FF",colourSecondary:"#4280D7",colourTertiary:"#3373CC"},loop_blocks:{colourPrimary:"#0fBD8C",colourSecondary:"#0DA57A",colourTertiary:"#0B8E69"},math_blocks:{colourPrimary:"#59C059",colourSecondary:"#46B946",colourTertiary:"#389438"}, -procedure_blocks:{colourPrimary:"#FF6680",colourSecondary:"#FF4D6A",colourTertiary:"#FF3355"},text_blocks:{colourPrimary:"#FFBF00",colourSecondary:"#E6AC00",colourTertiary:"#CC9900"},variable_blocks:{colourPrimary:"#FF8C1A",colourSecondary:"#FF8000",colourTertiary:"#DB6E00"},variable_dynamic_blocks:{colourPrimary:"#FF8C1A",colourSecondary:"#FF8000",colourTertiary:"#DB6E00"},hat_blocks:{colourPrimary:"#4C97FF",colourSecondary:"#4280D7",colourTertiary:"#3373CC",hat:"cap"}},categoryStyles$$module$build$src$core$theme$zelos= -{colour_category:{colour:"#CF63CF"},list_category:{colour:"#9966FF"},logic_category:{colour:"#4C97FF"},loop_category:{colour:"#0fBD8C"},math_category:{colour:"#59C059"},procedure_category:{colour:"#FF6680"},text_category:{colour:"#FFBF00"},variable_category:{colour:"#FF8C1A"},variable_dynamic_category:{colour:"#FF8C1A"}},Zelos$$module$build$src$core$theme$zelos=new Theme$$module$build$src$core$theme("zelos",defaultBlockStyles$$module$build$src$core$theme$zelos,categoryStyles$$module$build$src$core$theme$zelos), -module$build$src$core$theme$zelos={};module$build$src$core$theme$zelos.Zelos=Zelos$$module$build$src$core$theme$zelos;var module$build$src$core$theme$themes={};module$build$src$core$theme$themes.Classic=Classic$$module$build$src$core$theme$classic;module$build$src$core$theme$themes.Zelos=Zelos$$module$build$src$core$theme$zelos;var Click$$module$build$src$core$events$events_click=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c){b=a?a.workspace.id:b;null===b&&(b=void 0);super(b);this.type=CLICK$$module$build$src$core$events$utils;this.blockId=a?a.id:void 0;this.targetType=c}toJson(){const a=super.toJson();if(!this.targetType)throw Error("The click target type is undefined. Either pass a block to the constructor, or call fromJson");a.targetType=this.targetType;a.blockId=this.blockId;return a}fromJson(a){super.fromJson(a); -this.targetType=a.targetType;this.blockId=a.blockId}},ClickTarget$$module$build$src$core$events$events_click;(function(a){a.BLOCK="block";a.WORKSPACE="workspace";a.ZOOM_CONTROLS="zoom_controls"})(ClickTarget$$module$build$src$core$events$events_click||(ClickTarget$$module$build$src$core$events$events_click={}));register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,CLICK$$module$build$src$core$events$utils,Click$$module$build$src$core$events$events_click); -var module$build$src$core$events$events_click={};module$build$src$core$events$events_click.Click=Click$$module$build$src$core$events$events_click;module$build$src$core$events$events_click.ClickTarget=ClickTarget$$module$build$src$core$events$events_click;var BubbleDragger$$module$build$src$core$bubble_dragger=class{constructor(a,b){this.bubble=a;this.workspace=b;this.dragTarget_=null;this.wouldDeleteBubble_=!1;this.startXY_=this.bubble.getRelativeToSurfaceXY();this.dragSurface_=b.getBlockDragSurface()}startBubbleDrag(){getGroup$$module$build$src$core$events$utils()||setGroup$$module$build$src$core$events$utils(!0);this.workspace.setResizesEnabled(!1);this.bubble.setAutoLayout(!1);this.dragSurface_&&(this.bubble.moveTo(0,0),this.dragSurface_.translateSurface(this.startXY_.x, -this.startXY_.y),this.dragSurface_.setBlocksAndShow(this.bubble.getSvgRoot()));this.bubble.setDragging&&this.bubble.setDragging(!0)}dragBubble(a,b){b=this.pixelsToWorkspaceUnits_(b);b=Coordinate$$module$build$src$core$utils$coordinate.sum(this.startXY_,b);this.bubble.moveDuringDrag(this.dragSurface_,b);b=this.dragTarget_;this.dragTarget_=this.workspace.getDragTarget(a);a=this.wouldDeleteBubble_;this.wouldDeleteBubble_=this.shouldDelete_(this.dragTarget_);a!==this.wouldDeleteBubble_&&this.updateCursorDuringBubbleDrag_(); -this.dragTarget_!==b&&(b&&b.onDragExit(this.bubble),this.dragTarget_&&this.dragTarget_.onDragEnter(this.bubble));this.dragTarget_&&this.dragTarget_.onDragOver(this.bubble)}shouldDelete_(a){return a&&this.workspace.getComponentManager().hasCapability(a.id,ComponentManager$$module$build$src$core$component_manager.Capability.DELETE_AREA)?a.wouldDelete(this.bubble,!1):!1}updateCursorDuringBubbleDrag_(){this.bubble.setDeleteStyle(this.wouldDeleteBubble_)}endBubbleDrag(a,b){this.dragBubble(a,b);this.dragTarget_&& -this.dragTarget_.shouldPreventMove(this.bubble)?a=this.startXY_:(a=this.pixelsToWorkspaceUnits_(b),a=Coordinate$$module$build$src$core$utils$coordinate.sum(this.startXY_,a));this.bubble.moveTo(a.x,a.y);if(this.dragTarget_)this.dragTarget_.onDrop(this.bubble);this.wouldDeleteBubble_?(this.fireMoveEvent_(),this.bubble.dispose()):(this.dragSurface_&&this.dragSurface_.clearAndHide(this.workspace.getBubbleCanvas()),this.bubble.setDragging&&this.bubble.setDragging(!1),this.fireMoveEvent_());this.workspace.setResizesEnabled(!0); -setGroup$$module$build$src$core$events$utils(!1)}fireMoveEvent_(){if(this.bubble instanceof WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg){const a=new (get$$module$build$src$core$events$utils(COMMENT_MOVE$$module$build$src$core$events$utils))(this.bubble);a.setOldCoordinate(this.startXY_);a.recordNew();fire$$module$build$src$core$events$utils(a)}}pixelsToWorkspaceUnits_(a){a=new Coordinate$$module$build$src$core$utils$coordinate(a.x/this.workspace.scale,a.y/this.workspace.scale); -this.workspace.isMutator&&a.scale(1/this.workspace.options.parentWorkspace.scale);return a}},module$build$src$core$bubble_dragger={};module$build$src$core$bubble_dragger.BubbleDragger=BubbleDragger$$module$build$src$core$bubble_dragger;var WorkspaceDragger$$module$build$src$core$workspace_dragger=class{constructor(a){this.workspace=a;this.horizontalScrollEnabled_=this.workspace.isMovableHorizontally();this.verticalScrollEnabled_=this.workspace.isMovableVertically();this.startScrollXY_=new Coordinate$$module$build$src$core$utils$coordinate(a.scrollX,a.scrollY)}dispose(){this.workspace=null}startDrag(){getSelected$$module$build$src$core$common()&&getSelected$$module$build$src$core$common().unselect();this.workspace.setupDragSurface()}endDrag(a){this.drag(a); -this.workspace.resetDragSurface()}drag(a){a=Coordinate$$module$build$src$core$utils$coordinate.sum(this.startScrollXY_,a);if(this.horizontalScrollEnabled_&&this.verticalScrollEnabled_)this.workspace.scroll(a.x,a.y);else if(this.horizontalScrollEnabled_)this.workspace.scroll(a.x,this.workspace.scrollY);else if(this.verticalScrollEnabled_)this.workspace.scroll(this.workspace.scrollX,a.y);else throw new TypeError("Invalid state.");}},module$build$src$core$workspace_dragger={}; -module$build$src$core$workspace_dragger.WorkspaceDragger=WorkspaceDragger$$module$build$src$core$workspace_dragger;var Gesture$$module$build$src$core$gesture=class{constructor(a,b){this.creatorWorkspace=b;this.mouseDownXY_=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.startWorkspace_=this.targetBlock_=this.startBlock_=this.startField_=this.startBubble_=null;this.hasExceededDragRadius_=!1;this.flyout_=this.workspaceDragger_=this.blockDragger_=this.bubbleDragger_=this.onUpWrapper_=this.onMoveWrapper_=null;this.isEnding_=this.hasStarted_=this.calledUpdateIsDragging_=!1;this.mostRecentEvent_=a; -this.currentDragDeltaXY_=new Coordinate$$module$build$src$core$utils$coordinate(0,0);this.healStack_=!DRAG_STACK$$module$build$src$core$internal_constants}dispose(){clearTouchIdentifier$$module$build$src$core$touch();unblock$$module$build$src$core$tooltip();this.creatorWorkspace.clearGesture();this.onMoveWrapper_&&unbind$$module$build$src$core$browser_events(this.onMoveWrapper_);this.onUpWrapper_&&unbind$$module$build$src$core$browser_events(this.onUpWrapper_);this.blockDragger_&&this.blockDragger_.dispose(); -this.workspaceDragger_&&this.workspaceDragger_.dispose()}updateFromEvent_(a){const b=new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY);this.updateDragDelta_(b)&&(this.updateIsDragging_(),longStop$$module$build$src$core$touch());this.mostRecentEvent_=a}updateDragDelta_(a){this.currentDragDeltaXY_=Coordinate$$module$build$src$core$utils$coordinate.difference(a,this.mouseDownXY_);return this.hasExceededDragRadius_?!1:this.hasExceededDragRadius_=Coordinate$$module$build$src$core$utils$coordinate.magnitude(this.currentDragDeltaXY_)> -(this.flyout_?$.config$$module$build$src$core$config.flyoutDragRadius:$.config$$module$build$src$core$config.dragRadius)}updateIsDraggingFromFlyout_(){let a;if(!this.targetBlock_||null==(a=this.flyout_)||!a.isBlockCreatable(this.targetBlock_))return!1;if(!this.flyout_.targetWorkspace)throw Error("Cannot update dragging from the flyout because the ' +\n 'flyout's target workspace is undefined");return!this.flyout_.isScrollable()||this.flyout_.isDragTowardWorkspace(this.currentDragDeltaXY_)? -(this.startWorkspace_=this.flyout_.targetWorkspace,this.startWorkspace_.updateScreenCalculationsIfScrolled(),getGroup$$module$build$src$core$events$utils()||setGroup$$module$build$src$core$events$utils(!0),this.startBlock_=null,this.targetBlock_=this.flyout_.createBlock(this.targetBlock_),this.targetBlock_.select(),!0):!1}updateIsDraggingBubble_(){if(!this.startBubble_)return!1;this.startDraggingBubble_();return!0}updateIsDraggingBlock_(){if(!this.targetBlock_)return!1;if(this.flyout_){if(this.updateIsDraggingFromFlyout_())return this.startDraggingBlock_(), -!0}else if(this.targetBlock_.isMovable())return this.startDraggingBlock_(),!0;return!1}updateIsDraggingWorkspace_(){if(!this.startWorkspace_)throw Error("Cannot update dragging the workspace because the start workspace is undefined");if(this.flyout_?this.flyout_.isScrollable():this.startWorkspace_&&this.startWorkspace_.isDraggable())this.workspaceDragger_=new WorkspaceDragger$$module$build$src$core$workspace_dragger(this.startWorkspace_),this.workspaceDragger_.startDrag()}updateIsDragging_(){if(this.calledUpdateIsDragging_)throw Error("updateIsDragging_ should only be called once per gesture."); -this.calledUpdateIsDragging_=!0;this.updateIsDraggingBubble_()||this.updateIsDraggingBlock_()||this.updateIsDraggingWorkspace_()}startDraggingBlock_(){this.blockDragger_=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.BLOCK_DRAGGER,this.creatorWorkspace.options,!0))(this.targetBlock_,this.startWorkspace_);this.blockDragger_.startDrag(this.currentDragDeltaXY_,this.healStack_);this.blockDragger_.drag(this.mostRecentEvent_,this.currentDragDeltaXY_)}startDraggingBubble_(){if(!this.startBubble_)throw Error("Cannot update dragging the bubble because the start bubble is undefined"); -if(!this.startWorkspace_)throw Error("Cannot update dragging the bubble because the start workspace is undefined");this.bubbleDragger_=new BubbleDragger$$module$build$src$core$bubble_dragger(this.startBubble_,this.startWorkspace_);this.bubbleDragger_.startBubbleDrag();this.bubbleDragger_.dragBubble(this.mostRecentEvent_,this.currentDragDeltaXY_)}doStart(a){if(isTargetInput$$module$build$src$core$browser_events(a))this.cancel();else{if(!this.startWorkspace_)throw Error("Cannot start the gesture because the start workspace is undefined"); -this.hasStarted_=!0;disconnectUiStop$$module$build$src$core$block_animations();this.startWorkspace_.updateScreenCalculationsIfScrolled();this.startWorkspace_.isMutator&&this.startWorkspace_.resize();this.startWorkspace_.hideChaff(!!this.flyout_);this.startWorkspace_.markFocused();this.mostRecentEvent_=a;block$$module$build$src$core$tooltip();this.targetBlock_&&this.targetBlock_.select();isRightButton$$module$build$src$core$browser_events(a)?this.handleRightClick(a):("touchstart"!==a.type.toLowerCase()&& -"pointerdown"!==a.type.toLowerCase()||"mouse"===a.pointerType||longStart$$module$build$src$core$touch(a,this),this.mouseDownXY_=new Coordinate$$module$build$src$core$utils$coordinate(a.clientX,a.clientY),this.healStack_=a.altKey||a.ctrlKey||a.metaKey,this.bindMouseEvents(a))}}bindMouseEvents(a){this.onMoveWrapper_=conditionalBind$$module$build$src$core$browser_events(document,"mousemove",null,this.handleMove.bind(this));this.onUpWrapper_=conditionalBind$$module$build$src$core$browser_events(document, -"mouseup",null,this.handleUp.bind(this));a.preventDefault();a.stopPropagation()}handleMove(a){this.updateFromEvent_(a);this.workspaceDragger_?this.workspaceDragger_.drag(this.currentDragDeltaXY_):this.blockDragger_?this.blockDragger_.drag(this.mostRecentEvent_,this.currentDragDeltaXY_):this.bubbleDragger_&&this.bubbleDragger_.dragBubble(this.mostRecentEvent_,this.currentDragDeltaXY_);a.preventDefault();a.stopPropagation()}handleUp(a){this.updateFromEvent_(a);longStop$$module$build$src$core$touch(); -this.isEnding_?console.log("Trying to end a gesture recursively."):(this.isEnding_=!0,this.bubbleDragger_?this.bubbleDragger_.endBubbleDrag(a,this.currentDragDeltaXY_):this.blockDragger_?this.blockDragger_.endDrag(a,this.currentDragDeltaXY_):this.workspaceDragger_?this.workspaceDragger_.endDrag(this.currentDragDeltaXY_):this.isBubbleClick_()?this.doBubbleClick_():this.isFieldClick_()?this.doFieldClick_():this.isBlockClick_()?this.doBlockClick_():this.isWorkspaceClick_()&&this.doWorkspaceClick_(a), -a.preventDefault(),a.stopPropagation(),this.dispose())}cancel(){this.isEnding_||(longStop$$module$build$src$core$touch(),this.bubbleDragger_?this.bubbleDragger_.endBubbleDrag(this.mostRecentEvent_,this.currentDragDeltaXY_):this.blockDragger_?this.blockDragger_.endDrag(this.mostRecentEvent_,this.currentDragDeltaXY_):this.workspaceDragger_&&this.workspaceDragger_.endDrag(this.currentDragDeltaXY_),this.dispose())}handleRightClick(a){this.targetBlock_?(this.bringBlockToFront_(),this.targetBlock_.workspace.hideChaff(!!this.flyout_), -this.targetBlock_.showContextMenu(a)):this.startBubble_?this.startBubble_.showContextMenu(a):this.startWorkspace_&&!this.flyout_&&(this.startWorkspace_.hideChaff(),this.startWorkspace_.showContextMenu(a));a.preventDefault();a.stopPropagation();this.dispose()}handleWsStart(a,b){if(this.hasStarted_)throw Error("Tried to call gesture.handleWsStart, but the gesture had already been started.");this.setStartWorkspace_(b);this.mostRecentEvent_=a;this.doStart(a)}fireWorkspaceClick_(a){fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(CLICK$$module$build$src$core$events$utils))(null, -a.id,"workspace"))}handleFlyoutStart(a,b){if(this.hasStarted_)throw Error("Tried to call gesture.handleFlyoutStart, but the gesture had already been started.");this.setStartFlyout_(b);this.handleWsStart(a,b.getWorkspace())}handleBlockStart(a,b){if(this.hasStarted_)throw Error("Tried to call gesture.handleBlockStart, but the gesture had already been started.");this.setStartBlock(b);this.mostRecentEvent_=a}handleBubbleStart(a,b){if(this.hasStarted_)throw Error("Tried to call gesture.handleBubbleStart, but the gesture had already been started."); -this.setStartBubble(b);this.mostRecentEvent_=a}doBubbleClick_(){this.startBubble_ instanceof WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg&&(this.startBubble_.setFocus(),this.startBubble_.select())}doFieldClick_(){if(!this.startField_)throw Error("Cannot do a field click because the start field is undefined");this.startField_.showEditor(this.mostRecentEvent_);this.bringBlockToFront_()}doBlockClick_(){if(this.flyout_&&this.flyout_.autoClose){if(!this.targetBlock_)throw Error("Cannot do a block click because the target block is undefined"); -this.targetBlock_.isEnabled()&&(getGroup$$module$build$src$core$events$utils()||setGroup$$module$build$src$core$events$utils(!0),this.flyout_.createBlock(this.targetBlock_).scheduleSnapAndBump())}else{if(!this.startWorkspace_)throw Error("Cannot do a block click because the start workspace is undefined");const a=new (get$$module$build$src$core$events$utils(CLICK$$module$build$src$core$events$utils))(this.startBlock_,this.startWorkspace_.id,"block");fire$$module$build$src$core$events$utils(a)}this.bringBlockToFront_(); -setGroup$$module$build$src$core$events$utils(!1)}doWorkspaceClick_(a){a=this.creatorWorkspace;getSelected$$module$build$src$core$common()&&getSelected$$module$build$src$core$common().unselect();this.fireWorkspaceClick_(this.startWorkspace_||a)}bringBlockToFront_(){this.targetBlock_&&!this.flyout_&&this.targetBlock_.bringToFront()}setStartField(a){if(this.hasStarted_)throw Error("Tried to call gesture.setStartField, but the gesture had already been started.");this.startField_||(this.startField_=a)}setStartBubble(a){this.startBubble_|| -(this.startBubble_=a)}setStartBlock(a){this.startBlock_||this.startBubble_||(this.startBlock_=a,a.isInFlyout&&a!==a.getRootBlock()?this.setTargetBlock_(a.getRootBlock()):this.setTargetBlock_(a))}setTargetBlock_(a){a.isShadow()?this.setTargetBlock_(a.getParent()):this.targetBlock_=a}setStartWorkspace_(a){this.startWorkspace_||(this.startWorkspace_=a)}setStartFlyout_(a){this.flyout_||(this.flyout_=a)}isBubbleClick_(){return!!this.startBubble_&&!this.hasExceededDragRadius_}isBlockClick_(){return!!this.startBlock_&& -!this.hasExceededDragRadius_&&!this.isFieldClick_()}isFieldClick_(){return(this.startField_?this.startField_.isClickable():!1)&&!this.hasExceededDragRadius_&&(!this.flyout_||!this.flyout_.autoClose)}isWorkspaceClick_(){return!this.startBlock_&&!this.startBubble_&&!this.startField_&&!this.hasExceededDragRadius_}isDragging(){return!!this.workspaceDragger_||!!this.blockDragger_||!!this.bubbleDragger_}hasStarted(){return this.hasStarted_}getInsertionMarkers(){return this.blockDragger_?this.blockDragger_.getInsertionMarkers(): -[]}getCurrentDragger(){let a,b;return null!=(b=null!=(a=this.blockDragger_)?a:this.workspaceDragger_)?b:this.bubbleDragger_}static inProgress(){const a=getAllWorkspaces$$module$build$src$core$common();for(let b=0,c;c=a[b];b++)if(c.currentGesture_)return!0;return!1}},module$build$src$core$gesture={};module$build$src$core$gesture.Gesture=Gesture$$module$build$src$core$gesture;var ShortcutRegistry$$module$build$src$core$shortcut_registry=class{constructor(){this.shortcuts=new Map;this.keyMap=new Map;this.reset()}reset(){this.shortcuts.clear();this.keyMap.clear()}register(a,b){if(this.shortcuts.get(a.name)&&!b)throw Error('Shortcut with name "'+a.name+'" already exists.');this.shortcuts.set(a.name,a);if((b=a.keyCodes)&&0=this.connections_.length)return-1;b=a.y;let d=c;for(;0<=d&&this.connections_[d].y===b;){if(this.connections_[d]===a)return d;d--}for(d=c;da)c=d;else{b=d;break}}return b}removeConnection(a,b){a=this.findIndexOfConnection_(a,b);if(-1===a)throw Error("Unable to find connection in connectionDB.");this.connections_.splice(a,1)}getNeighbours(a,b){function c(l){const m=e-d[l].x,n=f-d[l].y; -Math.sqrt(m*m+n*n)<=b&&k.push(d[l]);return nrect,`,`${a} .blocklyEditableText>rect {`,`fill: ${this.FIELD_BORDER_RECT_COLOUR};`,"fill-opacity: .6;","stroke: none;","}",`${a} .blocklyNonEditableText>text,`,`${a} .blocklyEditableText>text {`,"fill: #000;","}",`${a} .blocklyFlyoutLabelText {`,"fill: #000;","}",`${a} .blocklyText.blocklyBubbleText {`,"fill: #000;","}",`${a} .blocklyEditableText:not(.editing):hover>rect {`,"stroke: #fff;","stroke-width: 2;","}",`${a} .blocklyHtmlInput {`, -`font-family: ${this.FIELD_TEXT_FONTFAMILY};`,`font-weight: ${this.FIELD_TEXT_FONTWEIGHT};`,"}",`${a} .blocklySelected>.blocklyPath {`,"stroke: #fc3;","stroke-width: 3px;","}",`${a} .blocklyHighlightedConnectionPath {`,"stroke: #fc3;","}",`${a} .blocklyReplaceable .blocklyPath {`,"fill-opacity: .5;","}",`${a} .blocklyReplaceable .blocklyPathLight,`,`${a} .blocklyReplaceable .blocklyPathDark {`,"display: none;","}",`${a} .blocklyInsertionMarker>.blocklyPath {`,`fill-opacity: ${this.INSERTION_MARKER_OPACITY};`, -"stroke: none;","}"]}},module$build$src$core$renderers$common$constants={};module$build$src$core$renderers$common$constants.ConstantProvider=ConstantProvider$$module$build$src$core$renderers$common$constants;module$build$src$core$renderers$common$constants.isDynamicShape=isDynamicShape$$module$build$src$core$renderers$common$constants;var useDebugger$$module$build$src$core$renderers$common$debug=!1,module$build$src$core$renderers$common$debug={};module$build$src$core$renderers$common$debug.isDebuggerEnabled=isDebuggerEnabled$$module$build$src$core$renderers$common$debug;module$build$src$core$renderers$common$debug.startDebugger=startDebugger$$module$build$src$core$renderers$common$debug;module$build$src$core$renderers$common$debug.stopDebugger=stopDebugger$$module$build$src$core$renderers$common$debug;var Debug$$module$build$src$core$renderers$common$debugger=class{constructor(a){this.constants=a;this.debugElements_=[];this.svgRoot_=null;this.randomColour_=""}clearElems(){for(let a=0;aa.height;e&&(b-=d);this.debugElements_.push(createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT, -{"class":"rowSpacerRect blockRenderDebug",x:c?-(a.xPos+a.width):a.xPos,y:b,width:a.width,height:d,stroke:e?"black":"blue",fill:"blue","fill-opacity":"0.5","stroke-width":"1px"},this.svgRoot_))}}drawSpacerElem(a,b,c){if(Debug$$module$build$src$core$renderers$common$debugger.config.elemSpacers){b=Math.abs(a.width);var d=0>a.width,e=d?a.xPos-b:a.xPos;c&&(e=-(e+b));this.debugElements_.push(createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"elemSpacerRect blockRenderDebug", -x:e,y:a.centerline-a.height/2,width:b,height:a.height,stroke:"pink",fill:d?"black":"pink","fill-opacity":"0.5","stroke-width":"1px"},this.svgRoot_))}}drawRenderedElem(a,b){if(Debug$$module$build$src$core$renderers$common$debugger.config.elems){let c=a.xPos;b&&(c=-(c+a.width));b=a.centerline-a.height/2;this.debugElements_.push(createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"rowRenderingRect blockRenderDebug",x:c,y:b,width:a.width,height:a.height, -stroke:"black",fill:"none","stroke-width":"1px"},this.svgRoot_));Types$$module$build$src$core$renderers$measurables$types.isField(a)&&a instanceof Field$$module$build$src$core$renderers$measurables$field&&a.field instanceof $.FieldLabel$$module$build$src$core$field_label&&this.debugElements_.push(createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"rowRenderingRect blockRenderDebug",x:c,y:b+this.constants.FIELD_TEXT_BASELINE,width:a.width,height:"0.1px", -stroke:"red",fill:"none","stroke-width":"0.5px"},this.svgRoot_))}Types$$module$build$src$core$renderers$measurables$types.isInput(a)&&a instanceof InputConnection$$module$build$src$core$renderers$measurables$input_connection&&Debug$$module$build$src$core$renderers$common$debugger.config.connections&&this.drawConnection(a.connectionModel)}drawConnection(a){if(Debug$$module$build$src$core$renderers$common$debugger.config.connections){var b="",c=0,d="";a.type===ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE? -(c=4,b="magenta",d="none"):a.type===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE?(c=2,d=b="magenta"):a.type===ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT?(c=4,b="goldenrod",d="none"):a.type===ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT&&(c=2,d=b="goldenrod");this.debugElements_.push(createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CIRCLE,{"class":"blockRenderDebug",cx:a.getOffsetInBlock().x, -cy:a.getOffsetInBlock().y,r:c,fill:d,stroke:b},this.svgRoot_))}}drawRenderedRow(a,b,c){Debug$$module$build$src$core$renderers$common$debugger.config.rows&&(this.debugElements_.push(createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"elemRenderingRect blockRenderDebug",x:c?-(a.xPos+a.width):a.xPos,y:a.yPos,width:a.width,height:a.height,stroke:"red",fill:"none","stroke-width":"1px"},this.svgRoot_)),Types$$module$build$src$core$renderers$measurables$types.isTopOrBottomRow(a)|| -Debug$$module$build$src$core$renderers$common$debugger.config.connectedBlockBounds&&this.debugElements_.push(createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{"class":"connectedBlockWidth blockRenderDebug",x:c?-(a.xPos+a.widthWithConnectedBlocks):a.xPos,y:a.yPos,width:a.widthWithConnectedBlocks,height:a.height,stroke:this.randomColour_,fill:"none","stroke-width":"1px","stroke-dasharray":"3,3"},this.svgRoot_)))}drawRowWithElements(a,b,c){for(let d=0;db-$.config$$module$build$src$core$config.currentConnectionPreference)}if(this.localConnection_||this.closestConnection_)console.error("Only one of localConnection_ and closestConnection_ was set.");else return!0}else return!(!this.localConnection_||!this.closestConnection_);console.error("Returning true from shouldUpdatePreviews, but it's not clear why.");return!0}getCandidate_(a){let b= -this.getStartRadius_(),c=null,d=null;this.markerConnection_&&this.markerConnection_.isConnected()||this.updateAvailableConnections();for(let e=0;ethis.previousScale_){b=c-this.previousScale_;b=0this.cachedPoints.size&&(this.cachedPoints.clear(),this.previousScale_=0)}getTouchPoint(a){return this.startWorkspace_?new Coordinate$$module$build$src$core$utils$coordinate(a.changedTouches? -a.changedTouches[0].pageX:a.pageX,a.changedTouches?a.changedTouches[0].pageY:a.pageY):null}},module$build$src$core$touch_gesture={};module$build$src$core$touch_gesture.TouchGesture=TouchGesture$$module$build$src$core$touch_gesture;var CATEGORY_NAME$$module$build$src$core$variables_dynamic="VARIABLE_DYNAMIC",onCreateVariableButtonClick_String$$module$build$src$core$variables_dynamic=stringButtonClickHandler$$module$build$src$core$variables_dynamic,onCreateVariableButtonClick_Number$$module$build$src$core$variables_dynamic=numberButtonClickHandler$$module$build$src$core$variables_dynamic,onCreateVariableButtonClick_Colour$$module$build$src$core$variables_dynamic=colourButtonClickHandler$$module$build$src$core$variables_dynamic, -module$build$src$core$variables_dynamic={};module$build$src$core$variables_dynamic.CATEGORY_NAME=CATEGORY_NAME$$module$build$src$core$variables_dynamic;module$build$src$core$variables_dynamic.flyoutCategory=flyoutCategory$$module$build$src$core$variables_dynamic;module$build$src$core$variables_dynamic.flyoutCategoryBlocks=flyoutCategoryBlocks$$module$build$src$core$variables_dynamic;module$build$src$core$variables_dynamic.onCreateVariableButtonClick_Colour=colourButtonClickHandler$$module$build$src$core$variables_dynamic; -module$build$src$core$variables_dynamic.onCreateVariableButtonClick_Number=numberButtonClickHandler$$module$build$src$core$variables_dynamic;module$build$src$core$variables_dynamic.onCreateVariableButtonClick_String=stringButtonClickHandler$$module$build$src$core$variables_dynamic;var ConnectionChecker$$module$build$src$core$connection_checker=class{canConnect(a,b,c,d){return this.canConnectWithReason(a,b,c,d)===Connection$$module$build$src$core$connection.CAN_CONNECT}canConnectWithReason(a,b,c,d){const e=this.doSafetyChecks(a,b);return e!==Connection$$module$build$src$core$connection.CAN_CONNECT?e:this.doTypeChecks(a,b)?c&&!this.doDragChecks(a,b,d||0)?Connection$$module$build$src$core$connection.REASON_DRAG_CHECKS_FAILED:Connection$$module$build$src$core$connection.CAN_CONNECT: -Connection$$module$build$src$core$connection.REASON_CHECKS_FAILED}getErrorMessage(a,b,c){switch(a){case Connection$$module$build$src$core$connection.REASON_SELF_CONNECTION:return"Attempted to connect a block to itself.";case Connection$$module$build$src$core$connection.REASON_DIFFERENT_WORKSPACES:return"Blocks not on same workspace.";case Connection$$module$build$src$core$connection.REASON_WRONG_TYPE:return"Attempt to connect incompatible types.";case Connection$$module$build$src$core$connection.REASON_TARGET_NULL:return"Target connection is null."; -case Connection$$module$build$src$core$connection.REASON_CHECKS_FAILED:return"Connection checks failed. "+(b+" expected "+b.getCheck()+", found "+c.getCheck());case Connection$$module$build$src$core$connection.REASON_SHADOW_PARENT:return"Connecting non-shadow to shadow block.";case Connection$$module$build$src$core$connection.REASON_DRAG_CHECKS_FAILED:return"Drag checks failed.";case Connection$$module$build$src$core$connection.REASON_PREVIOUS_AND_OUTPUT:return"Block would have an output and a previous connection."; -default:return"Unknown connection failure: this should never happen!"}}doSafetyChecks(a,b){if(!a||!b)return Connection$$module$build$src$core$connection.REASON_TARGET_NULL;let c,d,e;a.isSuperior()?(c=a.getSourceBlock(),d=b.getSourceBlock(),e=b):(d=a.getSourceBlock(),c=b.getSourceBlock(),e=a,a=b);return c===d?Connection$$module$build$src$core$connection.REASON_SELF_CONNECTION:e.type!==OPPOSITE_TYPE$$module$build$src$core$internal_constants[a.type]?Connection$$module$build$src$core$connection.REASON_WRONG_TYPE: -c.workspace!==d.workspace?Connection$$module$build$src$core$connection.REASON_DIFFERENT_WORKSPACES:c.isShadow()&&!d.isShadow()?Connection$$module$build$src$core$connection.REASON_SHADOW_PARENT:e.type===ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE&&d.previousConnection&&d.previousConnection.isConnected()||e.type===ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT&&d.outputConnection&&d.outputConnection.isConnected()?Connection$$module$build$src$core$connection.REASON_PREVIOUS_AND_OUTPUT: -Connection$$module$build$src$core$connection.CAN_CONNECT}doTypeChecks(a,b){a=a.getCheck();b=b.getCheck();if(!a||!b)return!0;for(let c=0;cc||b.getSourceBlock().isInsertionMarker())return!1;switch(b.type){case ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT:return this.canConnectToPrevious_(a,b);case ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE:if(b.isConnected()&& -!b.targetBlock().isInsertionMarker()||a.isConnected())return!1;break;case ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE:if(b.isConnected()&&!b.targetBlock().isMovable()&&!b.targetBlock().isShadow())return!1;break;case ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT:if(b.isConnected()&&!a.getSourceBlock().nextConnection&&!b.targetBlock().isShadow()&&b.targetBlock().nextConnection)return!1;break;default:return!1}return-1!==draggingConnections$$module$build$src$core$common.indexOf(b)? -!1:!0}canConnectToPrevious_(a,b){if(a.targetConnection||-1!==draggingConnections$$module$build$src$core$common.indexOf(b))return!1;if(!b.targetConnection)return!0;a=b.targetBlock();return a.isInsertionMarker()?!a.getPreviousBlock():!1}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.CONNECTION_CHECKER,DEFAULT$$module$build$src$core$registry,ConnectionChecker$$module$build$src$core$connection_checker);var module$build$src$core$connection_checker={}; -module$build$src$core$connection_checker.ConnectionChecker=ConnectionChecker$$module$build$src$core$connection_checker;var VarDelete$$module$build$src$core$events$events_var_delete=class extends VarBase$$module$build$src$core$events$events_var_base{constructor(a){super(a);this.type=VAR_DELETE$$module$build$src$core$events$utils;a&&(this.varType=a.type,this.varName=a.name)}toJson(){const a=super.toJson();if(!this.varType)throw Error("The var type is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson"); -a.varType=this.varType;a.varName=this.varName;return a}fromJson(a){super.fromJson(a);this.varType=a.varType;this.varName=a.varName}run(a){const b=this.getEventWorkspace_();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.varName)throw Error("The var name is undefined. Either pass a variable to the constructor, or call fromJson");a?b.deleteVariableById(this.varId):b.createVariable(this.varName,this.varType,this.varId)}}; -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,VAR_DELETE$$module$build$src$core$events$utils,VarDelete$$module$build$src$core$events$events_var_delete);var module$build$src$core$events$events_var_delete={};module$build$src$core$events$events_var_delete.VarDelete=VarDelete$$module$build$src$core$events$events_var_delete;var VarRename$$module$build$src$core$events$events_var_rename=class extends VarBase$$module$build$src$core$events$events_var_base{constructor(a,b){super(a);this.type=VAR_RENAME$$module$build$src$core$events$utils;a&&(this.oldName=a.name,this.newName="undefined"===typeof b?"":b)}toJson(){const a=super.toJson();if(!this.oldName)throw Error("The old var name is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.newName)throw Error("The new var name is undefined. Either pass a value to the constructor, or call fromJson"); -a.oldName=this.oldName;a.newName=this.newName;return a}fromJson(a){super.fromJson(a);this.oldName=a.oldName;this.newName=a.newName}run(a){const b=this.getEventWorkspace_();if(!this.varId)throw Error("The var ID is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.oldName)throw Error("The old var name is undefined. Either pass a variable to the constructor, or call fromJson");if(!this.newName)throw Error("The new var name is undefined. Either pass a value to the constructor, or call fromJson"); -a?b.renameVariableById(this.varId,this.newName):b.renameVariableById(this.varId,this.oldName)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,VAR_RENAME$$module$build$src$core$events$utils,VarRename$$module$build$src$core$events$events_var_rename);var module$build$src$core$events$events_var_rename={};module$build$src$core$events$events_var_rename.VarRename=VarRename$$module$build$src$core$events$events_var_rename;var VariableMap$$module$build$src$core$variable_map=class{constructor(a){this.workspace=a;this.variableMap=new Map}clear(){this.variableMap.clear()}renameVariable(a,b){const c=this.getVariable(b,a.type),d=this.workspace.getAllBlocks(!1);setGroup$$module$build$src$core$events$utils(!0);try{c&&c.getId()!==a.getId()?this.renameVariableWithConflict_(a,b,c,d):this.renameVariableAndUses_(a,b,d)}finally{setGroup$$module$build$src$core$events$utils(!1)}}renameVariableById(a,b){const c=this.getVariableById(a); -if(!c)throw Error("Tried to rename a variable that didn't exist. ID: "+a);this.renameVariable(c,b)}renameVariableAndUses_(a,b,c){fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(VAR_RENAME$$module$build$src$core$events$utils))(a,b));a.name=b;for(b=0;b{e&&b&&this.deleteVariableInternal(b,d)})):this.deleteVariableInternal(b, -d)}else console.warn("Can't delete non-existent variable: "+a)}deleteVariableInternal(a,b){const c=getGroup$$module$build$src$core$events$utils();c||setGroup$$module$build$src$core$events$utils(!0);try{for(let d=0;d -a.name)}getVariableUsesById(a){const b=[],c=this.workspace.getAllBlocks(!1);for(let d=0;dthis.remainingCapacityOfType(c))return!1;b+=a[c]}return b>this.remainingCapacity()?!1:!0}hasBlockLimits(){return Infinity!==this.options.maxBlocks||!!this.options.maxInstances}getUndoStack(){return this.undoStack_}getRedoStack(){return this.redoStack_}undo(a){var b= -a?this.redoStack_:this.undoStack_,c=a?this.undoStack_:this.redoStack_;const d=b.pop();if(d){for(var e=[d];b.length&&d.group&&d.group===b[b.length-1].group;)e.push(b.pop());for(b=0;bthis.MAX_UNDO&&0<=this.MAX_UNDO;)this.undoStack_.shift();for(let b=0;bimage, .blocklyZoom>svg>image {\n opacity: .4;\n}\n\n.blocklyZoom>image:hover, .blocklyZoom>svg>image:hover {\n opacity: .6;\n}\n\n.blocklyZoom>image:active, .blocklyZoom>svg>image:active {\n opacity: .8;\n}\n");var module$build$src$core$zoom_controls={};module$build$src$core$zoom_controls.ZoomControls=ZoomControls$$module$build$src$core$zoom_controls;var ZOOM_TO_FIT_MARGIN$$module$build$src$core$workspace_svg=20,WorkspaceSvg$$module$build$src$core$workspace_svg=class extends Workspace$$module$build$src$core$workspace{constructor(a,b,c){super(a);this.resizeHandlerWrapper_=null;this.resizesEnabled_=this.isVisible_=this.rendered=!0;this.startScrollY=this.startScrollX=this.scrollY=this.scrollX=0;this.dragDeltaXY_=null;this.oldScale_=this.scale=1;this.oldLeft_=this.oldTop_=0;this.workspaceDragSurface_=this.blockDragSurface_=this.currentGesture_=this.toolbox_= -this.flyout_=this.scrollbar=this.trashcan=null;this.isDragSurfaceActive_=!1;this.inverseScreenCTM_=this.targetWorkspace=this.configureContextMenu=this.lastRecordedPageScroll_=this.injectionDiv_=null;this.inverseScreenCTMDirty_=!0;this.highlightedBlocks_=[];this.toolboxCategoryCallbacks=new Map;this.flyoutButtonCallbacks=new Map;this.cachedParentSvg_=null;this.keyboardAccessibilityMode=!1;this.topBoundedElements_=[];this.dragTargetAreas_=[];this.zoomControls_=null;this.metricsManager_=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.METRICS_MANAGER, -a,!0))(this);this.getMetrics=a.getMetrics||this.metricsManager_.getMetrics.bind(this.metricsManager_);this.setMetrics=a.setMetrics||WorkspaceSvg$$module$build$src$core$workspace_svg.setTopLevelWorkspaceMetrics_;this.componentManager_=new ComponentManager$$module$build$src$core$component_manager;this.connectionDBList=ConnectionDB$$module$build$src$core$connection_db.init(this.connectionChecker);b&&(this.blockDragSurface_=b);c&&(this.workspaceDragSurface_=c);this.useWorkspaceDragSurface_=!!this.workspaceDragSurface_; -this.audioManager_=new WorkspaceAudio$$module$build$src$core$workspace_audio(a.parentWorkspace);this.grid_=this.options.gridPattern?new Grid$$module$build$src$core$grid(this.options.gridPattern,a.gridOptions):null;this.markerManager_=new MarkerManager$$module$build$src$core$marker_manager(this);$.module$build$src$core$variables&&flyoutCategory$$module$build$src$core$variables&&this.registerToolboxCategoryCallback(CATEGORY_NAME$$module$build$src$core$variables,flyoutCategory$$module$build$src$core$variables); -module$build$src$core$variables_dynamic&&flyoutCategory$$module$build$src$core$variables_dynamic&&this.registerToolboxCategoryCallback(CATEGORY_NAME$$module$build$src$core$variables_dynamic,flyoutCategory$$module$build$src$core$variables_dynamic);$.module$build$src$core$procedures&&flyoutCategory$$module$build$src$core$procedures&&(this.registerToolboxCategoryCallback(CATEGORY_NAME$$module$build$src$core$procedures,flyoutCategory$$module$build$src$core$procedures),this.addChangeListener(mutatorOpenListener$$module$build$src$core$procedures)); -this.themeManager_=this.options.parentWorkspace?this.options.parentWorkspace.getThemeManager():new ThemeManager$$module$build$src$core$theme_manager(this,this.options.theme||Classic$$module$build$src$core$theme$classic);this.themeManager_.subscribeWorkspace(this);let d;this.renderer_=init$$module$build$src$core$renderers$common$block_rendering(this.options.renderer||"geras",this.getTheme(),null!=(d=this.options.rendererOverrides)?d:void 0);this.cachedParentSvgSize_=new Size$$module$build$src$core$utils$size(0, -0)}getMarkerManager(){return this.markerManager_}getMetricsManager(){return this.metricsManager_}setMetricsManager(a){this.metricsManager_=a;this.getMetrics=this.metricsManager_.getMetrics.bind(this.metricsManager_)}getComponentManager(){return this.componentManager_}setCursorSvg(a){this.markerManager_.setCursorSvg(a)}setMarkerSvg(a){this.markerManager_.setMarkerSvg(a)}getMarker(a){return this.markerManager_?this.markerManager_.getMarker(a):null}getCursor(){return this.markerManager_?this.markerManager_.getCursor(): -null}getRenderer(){return this.renderer_}getThemeManager(){return this.themeManager_}getTheme(){return this.themeManager_.getTheme()}setTheme(a){a||(a=Classic$$module$build$src$core$theme$classic);this.themeManager_.setTheme(a)}refreshTheme(){this.svgGroup_&&this.renderer_.refreshDom(this.svgGroup_,this.getTheme());this.updateBlockStyles_(this.getAllBlocks(!1).filter(function(b){return!!b.getStyleName()}));this.refreshToolboxSelection();this.toolbox_&&this.toolbox_.refreshTheme();this.isVisible()&& -this.setVisible(!0);const a=new (get$$module$build$src$core$events$utils(THEME_CHANGE$$module$build$src$core$events$utils))(this.getTheme().name,this.id);fire$$module$build$src$core$events$utils(a)}updateBlockStyles_(a){for(let b=0,c;c=a[b];b++){const d=c.getStyleName();if(d){const e=c;e.setStyle(d);e.mutator&&e.mutator.updateBlockStyle()}}}getInverseScreenCTM(){if(this.inverseScreenCTMDirty_){const a=this.getParentSvg().getScreenCTM();a&&(this.inverseScreenCTM_=a.inverse(),this.inverseScreenCTMDirty_= -!1)}return this.inverseScreenCTM_}updateInverseScreenCTM(){this.inverseScreenCTMDirty_=!0}isVisible(){return this.isVisible_}getSvgXY(a){let b=0,c=0,d=1;if(containsNode$$module$build$src$core$utils$dom(this.getCanvas(),a)||containsNode$$module$build$src$core$utils$dom(this.getBubbleCanvas(),a))d=this.scale;do{const e=getRelativeXY$$module$build$src$core$utils$svg_math(a);if(a===this.getCanvas()||a===this.getBubbleCanvas())d=1;b+=e.x*d;c+=e.y*d;a=a.parentNode}while(a&&a!==this.getParentSvg());return new Coordinate$$module$build$src$core$utils$coordinate(b, -c)}getCachedParentSvgSize(){const a=this.cachedParentSvgSize_;return new Size$$module$build$src$core$utils$size(a.width,a.height)}getOriginOffsetInPixels(){return getInjectionDivXY$$module$build$src$core$utils$svg_math(this.getCanvas())}getInjectionDiv(){if(!this.injectionDiv_){let a=this.svgGroup_;for(;a;){if(-1!==(" "+(a.getAttribute("class")||"")+" ").indexOf(" injectionDiv ")){this.injectionDiv_=a;break}a=a.parentNode}}return this.injectionDiv_}getBlockCanvas(){return this.svgBlockCanvas_}setResizeHandlerWrapper(a){this.resizeHandlerWrapper_= -a}createDom(a){this.svgGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyWorkspace"});a&&(this.svgBackground_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.RECT,{height:"100%",width:"100%","class":a},this.svgGroup_),"blocklyMainBackground"===a&&this.grid_?this.svgBackground_.style.fill="url(#"+this.grid_.getPatternId()+")":this.themeManager_.subscribe(this.svgBackground_,"workspaceBackgroundColour", -"fill"));this.svgBlockCanvas_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyBlockCanvas"},this.svgGroup_);this.svgBubbleCanvas_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyBubbleCanvas"},this.svgGroup_);this.isFlyout||(conditionalBind$$module$build$src$core$browser_events(this.svgGroup_,"mousedown",this,this.onMouseDown_,!1,!0),document.body.addEventListener("wheel",function(){}), -conditionalBind$$module$build$src$core$browser_events(this.svgGroup_,"wheel",this,this.onMouseWheel_));this.options.hasCategories&&(this.toolbox_=new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.TOOLBOX,this.options,!0))(this));this.grid_&&this.grid_.update(this.scale);this.recordDragTargets();(a=getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.CURSOR,this.options))&&this.markerManager_.setCursor(new a);this.renderer_.createDom(this.svgGroup_, -this.getTheme());return this.svgGroup_}dispose(){this.rendered=!1;this.currentGesture_&&this.currentGesture_.cancel();this.svgGroup_&&removeNode$$module$build$src$core$utils$dom(this.svgGroup_);this.toolbox_&&(this.toolbox_.dispose(),this.toolbox_=null);this.flyout_&&(this.flyout_.dispose(),this.flyout_=null);this.trashcan&&(this.trashcan.dispose(),this.trashcan=null);this.scrollbar&&(this.scrollbar.dispose(),this.scrollbar=null);this.zoomControls_&&this.zoomControls_.dispose();this.audioManager_&& -this.audioManager_.dispose();this.grid_&&(this.grid_=null);this.renderer_.dispose();this.markerManager_&&this.markerManager_.dispose();super.dispose();this.themeManager_&&(this.themeManager_.unsubscribeWorkspace(this),this.themeManager_.unsubscribe(this.svgBackground_),this.options.parentWorkspace||this.themeManager_.dispose());this.connectionDBList.length=0;this.toolboxCategoryCallbacks.clear();this.flyoutButtonCallbacks.clear();if(!this.options.parentWorkspace){const a=this.getParentSvg();a&&a.parentNode&& -removeNode$$module$build$src$core$utils$dom(a.parentNode)}this.resizeHandlerWrapper_&&(unbind$$module$build$src$core$browser_events(this.resizeHandlerWrapper_),this.resizeHandlerWrapper_=null)}addTrashcan(){this.trashcan=WorkspaceSvg$$module$build$src$core$workspace_svg.newTrashcan(this);const a=this.trashcan.createDom();this.svgGroup_.insertBefore(a,this.svgBlockCanvas_)}static newTrashcan(a){throw Error("The implementation of newTrashcan should be monkey-patched in by blockly.ts");}addZoomControls(){this.zoomControls_= -new ZoomControls$$module$build$src$core$zoom_controls(this);const a=this.zoomControls_.createDom();this.svgGroup_.appendChild(a)}addFlyout(a){const b=new Options$$module$build$src$core$options({parentWorkspace:this,rtl:this.RTL,oneBasedIndex:this.options.oneBasedIndex,horizontalLayout:this.horizontalLayout,renderer:this.options.renderer,rendererOverrides:this.options.rendererOverrides,move:{scrollbars:!0}});b.toolboxPosition=this.options.toolboxPosition;this.flyout_=this.horizontalLayout?new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX, -this.options,!0))(b):new (getClassFromOptions$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX,this.options,!0))(b);this.flyout_.autoClose=!1;this.flyout_.getWorkspace().setVisible(!0);return this.flyout_.createDom(a)}getFlyout(a){return this.flyout_||a?this.flyout_:this.toolbox_?this.toolbox_.getFlyout():null}getToolbox(){return this.toolbox_}updateScreenCalculations_(){this.updateInverseScreenCTM();this.recordDragTargets()}resizeContents(){this.resizesEnabled_&& -this.rendered&&(this.scrollbar&&this.scrollbar.resize(),this.updateInverseScreenCTM())}resize(){this.toolbox_&&this.toolbox_.position();this.flyout_&&this.flyout_.position();const a=this.componentManager_.getComponents(ComponentManager$$module$build$src$core$component_manager.Capability.POSITIONABLE,!0),b=this.getMetricsManager().getUiMetrics(),c=[];for(let d=0,e;e=a[d];d++){e.position(b,c);const f=e.getBoundingRectangle();f&&c.push(f)}this.scrollbar&&this.scrollbar.resize();this.updateScreenCalculations_()}updateScreenCalculationsIfScrolled(){const a= -getDocumentScroll$$module$build$src$core$utils$svg_math();Coordinate$$module$build$src$core$utils$coordinate.equals(this.lastRecordedPageScroll_,a)||(this.lastRecordedPageScroll_=a,this.updateScreenCalculations_())}getCanvas(){return this.svgBlockCanvas_}setCachedParentSvgSize(a,b){const c=this.getParentSvg();null!=a&&(this.cachedParentSvgSize_.width=a,c.setAttribute("data-cached-width",a.toString()));null!=b&&(this.cachedParentSvgSize_.height=b,c.setAttribute("data-cached-height",b.toString()))}getBubbleCanvas(){return this.svgBubbleCanvas_}getParentSvg(){if(!this.cachedParentSvg_){let a= -this.svgGroup_;for(;a;){if("svg"===a.tagName){this.cachedParentSvg_=a;break}a=a.parentNode}}return this.cachedParentSvg_}maybeFireViewportChangeEvent(){if(isEnabled$$module$build$src$core$events$utils()){var a=this.scale,b=-this.scrollY,c=-this.scrollX;if(!(a===this.oldScale_&&1>Math.abs(b-this.oldTop_)&&1>Math.abs(c-this.oldLeft_))){var d=new (get$$module$build$src$core$events$utils(VIEWPORT_CHANGE$$module$build$src$core$events$utils))(b,c,a,this.id,this.oldScale_);this.oldScale_=a;this.oldTop_= -b;this.oldLeft_=c;fire$$module$build$src$core$events$utils(d)}}}translate(a,b){if(this.useWorkspaceDragSurface_&&this.isDragSurfaceActive_){var c;null==(c=this.workspaceDragSurface_)||c.translateSurface(a,b)}else c="translate("+a+","+b+") scale("+this.scale+")",this.svgBlockCanvas_.setAttribute("transform",c),this.svgBubbleCanvas_.setAttribute("transform",c);this.blockDragSurface_&&this.blockDragSurface_.translateAndScaleGroup(a,b,this.scale);this.grid_&&this.grid_.moveTo(a,b);this.maybeFireViewportChangeEvent()}resetDragSurface(){if(this.useWorkspaceDragSurface_){this.isDragSurfaceActive_= -!1;var a=this.workspaceDragSurface_.getSurfaceTranslation();this.workspaceDragSurface_.clearAndHide(this.svgGroup_);a="translate("+a.x+","+a.y+") scale("+this.scale+")";this.svgBlockCanvas_.setAttribute("transform",a);this.svgBubbleCanvas_.setAttribute("transform",a)}}setupDragSurface(){if(this.useWorkspaceDragSurface_&&!this.isDragSurfaceActive_){this.isDragSurfaceActive_=!0;var a=this.svgBlockCanvas_.previousSibling,b,c=parseInt(null!=(b=this.getParentSvg().getAttribute("width"))?b:"0"),d;b=parseInt(null!= -(d=this.getParentSvg().getAttribute("height"))?d:"0");d=getRelativeXY$$module$build$src$core$utils$svg_math(this.getCanvas());this.workspaceDragSurface_.setContentsAndShow(this.getCanvas(),this.getBubbleCanvas(),a,c,b,this.scale);this.workspaceDragSurface_.translateSurface(d.x,d.y)}}getBlockDragSurface(){return this.blockDragSurface_}getWidth(){const a=this.getMetrics();return a?a.viewWidth/this.scale:0}setVisible(a){this.isVisible_=a;if(this.svgGroup_)if(this.scrollbar&&this.scrollbar.setContainerVisible(a), -this.getFlyout()&&this.getFlyout().setContainerVisible(a),this.getParentSvg().style.display=a?"block":"none",this.toolbox_&&this.toolbox_.setVisible(a),a){a=this.getAllBlocks(!1);for(let b=a.length-1;0<=b;b--)a[b].markDirty();this.render();this.toolbox_&&this.toolbox_.position()}else this.hideChaff(!0)}render(){var a=this.getAllBlocks(!1);for(var b=a.length-1;0<=b;b--)a[b].render(!1);if(this.currentGesture_)for(a=this.currentGesture_.getInsertionMarkers(),b=0;b=Math.abs(d-l.x)&&1>=Math.abs(e-l.y)){f=!0;break}}if(!f){const h=c.getConnections_(!1);for(let k=0,l;l=h[k];k++)if(l.closest($.config$$module$build$src$core$config.snapRadius,new Coordinate$$module$build$src$core$utils$coordinate(d,e)).connection){f=!0; -break}}f&&(d=this.RTL?d-$.config$$module$build$src$core$config.snapRadius:d+$.config$$module$build$src$core$config.snapRadius,e+=2*$.config$$module$build$src$core$config.snapRadius)}while(f);c.moveTo(new Coordinate$$module$build$src$core$utils$coordinate(d,e))}}finally{enable$$module$build$src$core$events$utils()}isEnabled$$module$build$src$core$events$utils()&&!c.isShadow()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(CREATE$$module$build$src$core$events$utils))(c)); -c.select();return c}pasteWorkspaceComment_(a){disable$$module$build$src$core$events$utils();let b;try{b=WorkspaceCommentSvg$$module$build$src$core$workspace_comment_svg.fromXmlRendered(a,this);let c,d=parseInt(null!=(c=a.getAttribute("x"))?c:"0"),e,f=parseInt(null!=(e=a.getAttribute("y"))?e:"0");isNaN(d)||isNaN(f)||(this.RTL&&(d=-d),b.moveBy(d+50,f+50))}finally{enable$$module$build$src$core$events$utils()}isEnabled$$module$build$src$core$events$utils()&&WorkspaceComment$$module$build$src$core$workspace_comment.fireCreateEvent(b); -b.select();return b}refreshToolboxSelection(){const a=this.isFlyout?this.targetWorkspace:this;a&&!a.currentGesture_&&a.toolbox_&&a.toolbox_.getFlyout()&&a.toolbox_.refreshSelection()}renameVariableById(a,b){super.renameVariableById(a,b);this.refreshToolboxSelection()}deleteVariableById(a){super.deleteVariableById(a);this.refreshToolboxSelection()}createVariable(a,b,c){a=super.createVariable(a,b,c);this.refreshToolboxSelection();return a}recordDragTargets(){const a=this.componentManager_.getComponents(ComponentManager$$module$build$src$core$component_manager.Capability.DRAG_TARGET, -!0);this.dragTargetAreas_=[];for(let b=0,c;c=a[b];b++){const d=c.getClientRect();d&&this.dragTargetAreas_.push({component:c,clientRect:d})}}newBlock(a,b){throw Error("The implementation of newBlock should be monkey-patched in by blockly.ts");}getDragTarget(a){for(let b=0,c;c=this.dragTargetAreas_[b];b++)if(c.clientRect.contains(a.clientX,a.clientY))return c.component;return null}onMouseDown_(a){const b=this.getGesture(a);b&&b.handleWsStart(a,this)}startDrag(a,b){a=mouseToSvg$$module$build$src$core$browser_events(a, -this.getParentSvg(),this.getInverseScreenCTM());a.x/=this.scale;a.y/=this.scale;this.dragDeltaXY_=Coordinate$$module$build$src$core$utils$coordinate.difference(b,a)}moveDrag(a){a=mouseToSvg$$module$build$src$core$browser_events(a,this.getParentSvg(),this.getInverseScreenCTM());a.x/=this.scale;a.y/=this.scale;return Coordinate$$module$build$src$core$utils$coordinate.sum(this.dragDeltaXY_,a)}isDragging(){return null!==this.currentGesture_&&this.currentGesture_.isDragging()}isDraggable(){return this.options.moveOptions&& -this.options.moveOptions.drag}isMovable(){return this.options.moveOptions&&!!this.options.moveOptions.scrollbars||this.options.moveOptions&&this.options.moveOptions.wheel||this.options.moveOptions&&this.options.moveOptions.drag||this.options.zoomOptions&&this.options.zoomOptions.wheel||this.options.zoomOptions&&this.options.zoomOptions.pinch}isMovableHorizontally(){const a=!!this.scrollbar;return this.isMovable()&&(!a||a&&this.scrollbar.canScrollHorizontally())}isMovableVertically(){const a=!!this.scrollbar; -return this.isMovable()&&(!a||a&&this.scrollbar.canScrollVertically())}onMouseWheel_(a){if(Gesture$$module$build$src$core$gesture.inProgress())a.preventDefault(),a.stopPropagation();else{var b=this.options.zoomOptions&&this.options.zoomOptions.wheel,c=this.options.moveOptions&&this.options.moveOptions.wheel;if(b||c){var d=getScrollDeltaPixels$$module$build$src$core$browser_events(a);if(MAC$$module$build$src$core$utils$useragent)var e=a.metaKey;b&&(a.ctrlKey||e||!c)?(d=-d.y/50,b=mouseToSvg$$module$build$src$core$browser_events(a, -this.getParentSvg(),this.getInverseScreenCTM()),this.zoom(b.x,b.y,d)):(b=this.scrollX-d.x,c=this.scrollY-d.y,a.shiftKey&&!d.x&&(b=this.scrollX-d.y,c=this.scrollY),this.scroll(b,c));a.preventDefault()}}}getBlocksBoundingBox(){const a=this.getTopBoundedElements();if(!a.length)return new Rect$$module$build$src$core$utils$rect(0,0,0,0);const b=a[0].getBoundingRectangle();for(let d=1;db.bottom&&(b.bottom=c.bottom),c.leftb.right&&(b.right=c.right))}return b}cleanUp(){this.setResizesEnabled(!1);setGroup$$module$build$src$core$events$utils(!0);const a=this.getTopBlocks(!0);let b=0;for(let c=0,d;d=a[c];c++){if(!d.isMovable())continue;const e=d.getRelativeToSurfaceXY();d.moveBy(-e.x,b-e.y);d.snapToGrid();b=d.getRelativeToSurfaceXY().y+d.getHeightWidth().height+this.renderer_.getConstants().MIN_BLOCK_HEIGHT}setGroup$$module$build$src$core$events$utils(!1); -this.setResizesEnabled(!0)}showContextMenu(a){if(!this.options.readOnly&&!this.isFlyout){var b=ContextMenuRegistry$$module$build$src$core$contextmenu_registry.registry.getContextMenuOptions(ContextMenuRegistry$$module$build$src$core$contextmenu_registry.ScopeType.WORKSPACE,{workspace:this});this.configureContextMenu&&this.configureContextMenu(b,a);show$$module$build$src$core$contextmenu(a,b,this.RTL)}}updateToolbox(a){if(a=convertToolboxDefToJson$$module$build$src$core$utils$toolbox(a)){if(!this.options.languageTree)throw Error("Existing toolbox is null. Can't create new toolbox."); -if(hasCategories$$module$build$src$core$utils$toolbox(a)){if(!this.toolbox_)throw Error("Existing toolbox has no categories. Can't change mode.");this.options.languageTree=a;this.toolbox_.render(a)}else{if(!this.flyout_)throw Error("Existing toolbox has categories. Can't change mode.");this.options.languageTree=a;this.flyout_.show(a)}}else if(this.options.languageTree)throw Error("Can't nullify an existing toolbox.");}markFocused(){this.options.parentWorkspace?this.options.parentWorkspace.markFocused(): -(setMainWorkspace$$module$build$src$core$common(this),this.setBrowserFocus())}setBrowserFocus(){document.activeElement&&document.activeElement instanceof HTMLElement&&document.activeElement.blur();try{this.getParentSvg().focus({preventScroll:!0})}catch(a){try{this.getParentSvg().parentElement.setActive()}catch(b){this.getParentSvg().parentElement.focus({preventScroll:!0})}}}zoom(a,b,c){c=Math.pow(this.options.zoomOptions.scaleSpeed,c);const d=this.scale*c;if(this.scale!==d){d>this.options.zoomOptions.maxScale? -c=this.options.zoomOptions.maxScale/this.scale:dthis.options.zoomOptions.maxScale?a=this.options.zoomOptions.maxScale:this.options.zoomOptions.minScale&&ac.autoHide(b))}static setTopLevelWorkspaceMetrics_(a){const b= -this.getMetrics();"number"===typeof a.x&&(this.scrollX=-(b.scrollLeft+(b.scrollWidth-b.viewWidth)*a.x));"number"===typeof a.y&&(this.scrollY=-(b.scrollTop+(b.scrollHeight-b.viewHeight)*a.y));this.translate(this.scrollX+b.absoluteLeft,this.scrollY+b.absoluteTop)}},module$build$src$core$workspace_svg={};module$build$src$core$workspace_svg.WorkspaceSvg=WorkspaceSvg$$module$build$src$core$workspace_svg;module$build$src$core$workspace_svg.resizeSvgContents=resizeSvgContents$$module$build$src$core$workspace_svg;var module$build$src$core$serialization$workspaces={};module$build$src$core$serialization$workspaces.load=load$$module$build$src$core$serialization$workspaces;module$build$src$core$serialization$workspaces.save=save$$module$build$src$core$serialization$workspaces;var VariableSerializer$$module$build$src$core$serialization$variables=class{constructor(){this.priority=VARIABLES$$module$build$src$core$serialization$priorities}save(a){const b=[];for(const c of a.getAllVariables())a={name:c.name,id:c.getId()},c.type&&(a.type=c.type),b.push(a);return b.length?b:null}load(a,b){for(const c of a)b.createVariable(c.name,c.type,c.id)}clear(a){a.getVariableMap().clear()}};register$$module$build$src$core$serialization$registry("variables",new VariableSerializer$$module$build$src$core$serialization$variables); -var module$build$src$core$serialization$variables={};var ConstantProvider$$module$build$src$core$renderers$zelos$constants=class extends ConstantProvider$$module$build$src$core$renderers$common$constants{constructor(){super();this.GRID_UNIT=4;this.CURSOR_COLOUR="#ffa200";this.CURSOR_RADIUS=5;this.JAGGED_TEETH_WIDTH=this.JAGGED_TEETH_HEIGHT=0;this.START_HAT_HEIGHT=22;this.START_HAT_WIDTH=96;this.SHAPES={HEXAGONAL:1,ROUND:2,SQUARE:3,PUZZLE:4,NOTCH:5};this.SHAPE_IN_SHAPE_PADDING={1:{0:5*this.GRID_UNIT,1:2*this.GRID_UNIT,2:5*this.GRID_UNIT,3:5*this.GRID_UNIT}, -2:{0:3*this.GRID_UNIT,1:3*this.GRID_UNIT,2:1*this.GRID_UNIT,3:2*this.GRID_UNIT},3:{0:2*this.GRID_UNIT,1:2*this.GRID_UNIT,2:2*this.GRID_UNIT,3:2*this.GRID_UNIT}};this.FULL_BLOCK_FIELDS=!0;this.FIELD_TEXT_FONTWEIGHT="bold";this.FIELD_TEXT_FONTFAMILY='"Helvetica Neue", "Segoe UI", Helvetica, sans-serif';this.FIELD_COLOUR_FULL_BLOCK=this.FIELD_TEXTINPUT_BOX_SHADOW=this.FIELD_DROPDOWN_SVG_ARROW=this.FIELD_DROPDOWN_COLOURED_DIV=this.FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW=!0;this.SELECTED_GLOW_COLOUR="#fff200"; -this.SELECTED_GLOW_SIZE=.5;this.REPLACEMENT_GLOW_COLOUR="#fff200";this.REPLACEMENT_GLOW_SIZE=2;this.selectedGlowFilterId="";this.selectedGlowFilter_=null;this.replacementGlowFilterId="";this.SQUARED=this.ROUNDED=this.HEXAGONAL=this.replacementGlowFilter_=null;this.SMALL_PADDING=this.GRID_UNIT;this.MEDIUM_PADDING=2*this.GRID_UNIT;this.MEDIUM_LARGE_PADDING=3*this.GRID_UNIT;this.LARGE_PADDING=4*this.GRID_UNIT;this.CORNER_RADIUS=1*this.GRID_UNIT;this.NOTCH_WIDTH=9*this.GRID_UNIT;this.NOTCH_HEIGHT=2*this.GRID_UNIT; -this.STATEMENT_INPUT_NOTCH_OFFSET=this.NOTCH_OFFSET_LEFT=3*this.GRID_UNIT;this.MIN_BLOCK_WIDTH=2*this.GRID_UNIT;this.MIN_BLOCK_HEIGHT=12*this.GRID_UNIT;this.EMPTY_STATEMENT_INPUT_HEIGHT=6*this.GRID_UNIT;this.TOP_ROW_MIN_HEIGHT=this.CORNER_RADIUS;this.TOP_ROW_PRECEDES_STATEMENT_MIN_HEIGHT=this.LARGE_PADDING;this.BOTTOM_ROW_MIN_HEIGHT=this.CORNER_RADIUS;this.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT=6*this.GRID_UNIT;this.STATEMENT_BOTTOM_SPACER=-this.NOTCH_HEIGHT;this.STATEMENT_INPUT_SPACER_MIN_WIDTH=40* -this.GRID_UNIT;this.STATEMENT_INPUT_PADDING_LEFT=4*this.GRID_UNIT;this.EMPTY_INLINE_INPUT_PADDING=4*this.GRID_UNIT;this.EMPTY_INLINE_INPUT_HEIGHT=8*this.GRID_UNIT;this.DUMMY_INPUT_MIN_HEIGHT=8*this.GRID_UNIT;this.DUMMY_INPUT_SHADOW_MIN_HEIGHT=6*this.GRID_UNIT;this.CURSOR_WS_WIDTH=20*this.GRID_UNIT;this.FIELD_TEXT_FONTSIZE=3*this.GRID_UNIT;this.FIELD_BORDER_RECT_RADIUS=this.CORNER_RADIUS;this.FIELD_BORDER_RECT_X_PADDING=2*this.GRID_UNIT;this.FIELD_BORDER_RECT_Y_PADDING=1.625*this.GRID_UNIT;this.FIELD_BORDER_RECT_HEIGHT= -8*this.GRID_UNIT;this.FIELD_DROPDOWN_BORDER_RECT_HEIGHT=8*this.GRID_UNIT;this.FIELD_DROPDOWN_SVG_ARROW_PADDING=this.FIELD_BORDER_RECT_X_PADDING;this.FIELD_COLOUR_DEFAULT_WIDTH=2*this.GRID_UNIT;this.FIELD_COLOUR_DEFAULT_HEIGHT=4*this.GRID_UNIT;this.FIELD_CHECKBOX_X_OFFSET=1*this.GRID_UNIT;this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH=12*this.GRID_UNIT}setFontConstants_(a){super.setFontConstants_(a);this.FIELD_DROPDOWN_BORDER_RECT_HEIGHT=this.FIELD_BORDER_RECT_HEIGHT=this.FIELD_TEXT_HEIGHT+2*this.FIELD_BORDER_RECT_Y_PADDING}init(){super.init(); -this.HEXAGONAL=this.makeHexagonal();this.ROUNDED=this.makeRounded();this.SQUARED=this.makeSquared();this.STATEMENT_INPUT_NOTCH_OFFSET=this.NOTCH_OFFSET_LEFT+this.INSIDE_CORNERS.rightWidth}setDynamicProperties_(a){super.setDynamicProperties_(a);this.SELECTED_GLOW_COLOUR=a.getComponentStyle("selectedGlowColour")||this.SELECTED_GLOW_COLOUR;const b=Number(a.getComponentStyle("selectedGlowSize"));this.SELECTED_GLOW_SIZE=b&&!isNaN(b)?b:this.SELECTED_GLOW_SIZE;this.REPLACEMENT_GLOW_COLOUR=a.getComponentStyle("replacementGlowColour")|| -this.REPLACEMENT_GLOW_COLOUR;this.REPLACEMENT_GLOW_SIZE=(a=Number(a.getComponentStyle("replacementGlowSize")))&&!isNaN(a)?a:this.REPLACEMENT_GLOW_SIZE}dispose(){super.dispose();this.selectedGlowFilter_&&removeNode$$module$build$src$core$utils$dom(this.selectedGlowFilter_);this.replacementGlowFilter_&&removeNode$$module$build$src$core$utils$dom(this.replacementGlowFilter_)}makeStartHat(){const a=this.START_HAT_HEIGHT,b=this.START_HAT_WIDTH,c=curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(25, --a),point$$module$build$src$core$utils$svg_paths(71,-a),point$$module$build$src$core$utils$svg_paths(b,0)]);return{height:a,width:b,path:c}}makeHexagonal(){function a(c,d,e){var f=c/2;f=f>b?b:f;e=e?-1:1;c=(d?-1:1)*c/2;return lineTo$$module$build$src$core$utils$svg_paths(-e*f,c)+lineTo$$module$build$src$core$utils$svg_paths(e*f,c)}const b=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH;return{type:this.SHAPES.HEXAGONAL,isDynamic:!0,width(c){c/=2;return c>b?b:c},height(c){return c},connectionOffsetY(c){return c/ -2},connectionOffsetX(c){return-c},pathDown(c){return a(c,!1,!1)},pathUp(c){return a(c,!0,!1)},pathRightDown(c){return a(c,!1,!0)},pathRightUp(c){return a(c,!1,!0)}}}makeRounded(){function a(d,e,f){const g=d>c?d-c:0;d=(d>c?c:d)/2;return arc$$module$build$src$core$utils$svg_paths("a","0 0,1",d,point$$module$build$src$core$utils$svg_paths((e?-1:1)*d,(e?-1:1)*d))+lineOnAxis$$module$build$src$core$utils$svg_paths("v",(f?1:-1)*g)+arc$$module$build$src$core$utils$svg_paths("a","0 0,1",d,point$$module$build$src$core$utils$svg_paths((e? -1:-1)*d,(e?-1:1)*d))}const b=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH,c=2*b;return{type:this.SHAPES.ROUND,isDynamic:!0,width(d){d/=2;return d>b?b:d},height(d){return d},connectionOffsetY(d){return d/2},connectionOffsetX(d){return-d},pathDown(d){return a(d,!1,!1)},pathUp(d){return a(d,!0,!1)},pathRightDown(d){return a(d,!1,!0)},pathRightUp(d){return a(d,!1,!0)}}}makeSquared(){function a(c,d,e){c-=2*b;return arc$$module$build$src$core$utils$svg_paths("a","0 0,1",b,point$$module$build$src$core$utils$svg_paths((d? --1:1)*b,(d?-1:1)*b))+lineOnAxis$$module$build$src$core$utils$svg_paths("v",(e?1:-1)*c)+arc$$module$build$src$core$utils$svg_paths("a","0 0,1",b,point$$module$build$src$core$utils$svg_paths((d?1:-1)*b,(d?-1:1)*b))}const b=this.CORNER_RADIUS;return{type:this.SHAPES.SQUARE,isDynamic:!0,width(c){return b},height(c){return c},connectionOffsetY(c){return c/2},connectionOffsetX(c){return-c},pathDown(c){return a(c,!1,!1)},pathUp(c){return a(c,!0,!1)},pathRightDown(c){return a(c,!1,!0)},pathRightUp(c){return a(c, -!1,!0)}}}shapeFor(a){let b=a.getCheck();!b&&a.targetConnection&&(b=a.targetConnection.getCheck());switch(a.type){case ConnectionType$$module$build$src$core$connection_type.INPUT_VALUE:case ConnectionType$$module$build$src$core$connection_type.OUTPUT_VALUE:a=a.getSourceBlock().getOutputShape();if(null!==a)switch(a){case this.SHAPES.HEXAGONAL:return this.HEXAGONAL;case this.SHAPES.ROUND:return this.ROUNDED;case this.SHAPES.SQUARE:return this.SQUARED}if(b&&-1!==b.indexOf("Boolean"))return this.HEXAGONAL; -if(b&&-1!==b.indexOf("Number"))return this.ROUNDED;b&&b.indexOf("String");return this.ROUNDED;case ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT:case ConnectionType$$module$build$src$core$connection_type.NEXT_STATEMENT:return this.NOTCH;default:throw Error("Unknown type");}}makeNotch(){function a(l){return curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l*e/2,0),point$$module$build$src$core$utils$svg_paths(l*e*3/4,g/2),point$$module$build$src$core$utils$svg_paths(l* -e,g)])+line$$module$build$src$core$utils$svg_paths([point$$module$build$src$core$utils$svg_paths(l*e,f)])+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l*e/4,g/2),point$$module$build$src$core$utils$svg_paths(l*e/2,g),point$$module$build$src$core$utils$svg_paths(l*e,g)])+lineOnAxis$$module$build$src$core$utils$svg_paths("h",l*d)+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l*e/2,0),point$$module$build$src$core$utils$svg_paths(l* -e*3/4,-(g/2)),point$$module$build$src$core$utils$svg_paths(l*e,-g)])+line$$module$build$src$core$utils$svg_paths([point$$module$build$src$core$utils$svg_paths(l*e,-f)])+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(l*e/4,-(g/2)),point$$module$build$src$core$utils$svg_paths(l*e/2,-g),point$$module$build$src$core$utils$svg_paths(l*e,-g)])}const b=this.NOTCH_WIDTH,c=this.NOTCH_HEIGHT,d=b/3,e=d/3,f=c/2,g=f/2,h=a(1),k=a(-1);return{type:this.SHAPES.NOTCH, -width:b,height:c,pathLeft:h,pathRight:k}}makeInsideCorners(){const a=this.CORNER_RADIUS,b=arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a,point$$module$build$src$core$utils$svg_paths(-a,a)),c=arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a,point$$module$build$src$core$utils$svg_paths(-a,a)),d=arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a,point$$module$build$src$core$utils$svg_paths(a,a)),e=arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a,point$$module$build$src$core$utils$svg_paths(a, -a));return{width:a,height:a,pathTop:b,pathBottom:d,rightWidth:a,rightHeight:a,pathTopRight:c,pathBottomRight:e}}generateSecondaryColour_(a){return blend$$module$build$src$core$utils$colour("#000",a,.15)||a}generateTertiaryColour_(a){return blend$$module$build$src$core$utils$colour("#000",a,.25)||a}createDom(a,b,c){super.createDom(a,b,c);a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.DEFS,{},a);b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FILTER, -{id:"blocklySelectedGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEGAUSSIANBLUR,{"in":"SourceGraphic",stdDeviation:this.SELECTED_GLOW_SIZE},b);c=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPONENTTRANSFER,{result:"outBlur"},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFUNCA,{type:"table", -tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},c);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFLOOD,{"flood-color":this.SELECTED_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPOSITE,{"in":"outColor",in2:"outBlur",operator:"in",result:"outGlow"},b);this.selectedGlowFilterId=b.id;this.selectedGlowFilter_=b;a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FILTER, -{id:"blocklyReplacementGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEGAUSSIANBLUR,{"in":"SourceGraphic",stdDeviation:this.REPLACEMENT_GLOW_SIZE},a);b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPONENTTRANSFER,{result:"outBlur"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFUNCA,{type:"table", -tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},b);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FEFLOOD,{"flood-color":this.REPLACEMENT_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPOSITE,{"in":"outColor",in2:"outBlur",operator:"in",result:"outGlow"},a);createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.FECOMPOSITE,{"in":"SourceGraphic", -in2:"outGlow",operator:"over"},a);this.replacementGlowFilterId=a.id;this.replacementGlowFilter_=a}getCSS_(a){return[`${a} .blocklyText,`,`${a} .blocklyFlyoutLabelText {`,`font: ${this.FIELD_TEXT_FONTWEIGHT} ${this.FIELD_TEXT_FONTSIZE}`+`pt ${this.FIELD_TEXT_FONTFAMILY};`,"}",`${a} .blocklyText {`,"fill: #fff;","}",`${a} .blocklyNonEditableText>rect:not(.blocklyDropdownRect),`,`${a} .blocklyEditableText>rect:not(.blocklyDropdownRect) {`,`fill: ${this.FIELD_BORDER_RECT_COLOUR};`,"}",`${a} .blocklyNonEditableText>text,`, -`${a} .blocklyEditableText>text,`,`${a} .blocklyNonEditableText>g>text,`,`${a} .blocklyEditableText>g>text {`,"fill: #575E75;","}",`${a} .blocklyFlyoutLabelText {`,"fill: #575E75;","}",`${a} .blocklyText.blocklyBubbleText {`,"fill: #575E75;","}",`${a} .blocklyDraggable:not(.blocklyDisabled)`," .blocklyEditableText:not(.editing):hover>rect,",`${a} .blocklyDraggable:not(.blocklyDisabled)`," .blocklyEditableText:not(.editing):hover>.blocklyPath {","stroke: #fff;","stroke-width: 2;","}",`${a} .blocklyHtmlInput {`, -`font-family: ${this.FIELD_TEXT_FONTFAMILY};`,`font-weight: ${this.FIELD_TEXT_FONTWEIGHT};`,"color: #575E75;","}",`${a} .blocklyDropdownText {`,"fill: #fff !important;","}",`${a}.blocklyWidgetDiv .goog-menuitem,`,`${a}.blocklyDropDownDiv .goog-menuitem {`,`font-family: ${this.FIELD_TEXT_FONTFAMILY};`,"}",`${a}.blocklyDropDownDiv .goog-menuitem-content {`,"color: #fff;","}",`${a} .blocklyHighlightedConnectionPath {`,`stroke: ${this.SELECTED_GLOW_COLOUR};`,"}",`${a} .blocklyDisabled > .blocklyOutlinePath {`, -`fill: url(#blocklyDisabledPattern${this.randomIdentifier})`,"}",`${a} .blocklyInsertionMarker>.blocklyPath {`,`fill-opacity: ${this.INSERTION_MARKER_OPACITY};`,"stroke: none;","}"]}},module$build$src$core$renderers$zelos$constants={};module$build$src$core$renderers$zelos$constants.ConstantProvider=ConstantProvider$$module$build$src$core$renderers$zelos$constants;var Drawer$$module$build$src$core$renderers$zelos$drawer=class extends Drawer$$module$build$src$core$renderers$common$drawer{constructor(a,b){super(a,b)}draw(){const a=this.block_.pathObject;a.beginDrawing();this.hideHiddenIcons_();this.drawOutline_();this.drawInternals_();a.setPath(this.outlinePath_+"\n"+this.inlinePath_);this.info_.RTL&&a.flipRTL();if(isDebuggerEnabled$$module$build$src$core$renderers$common$debug()){let b,c;null==(b=this.block_)||null==(c=b.renderingDebugger)||c.drawDebug(this.block_, -this.info_)}this.recordSizeOnBlock_();this.info_.outputConnection&&(a.outputShapeType=this.info_.outputConnection.shape.type);a.endDrawing()}drawOutline_(){this.info_.outputConnection&&this.info_.outputConnection.isDynamicShape&&!this.info_.hasStatementInput&&!this.info_.bottomRow.hasNextConnection?(this.drawFlatTop_(),this.drawRightDynamicConnection_(),this.drawFlatBottom_(),this.drawLeftDynamicConnection_()):super.drawOutline_()}drawLeft_(){this.info_.outputConnection&&this.info_.outputConnection.isDynamicShape? -this.drawLeftDynamicConnection_():super.drawLeft_()}drawRightSideRow_(a){if(!(0>=a.height))if(Types$$module$build$src$core$renderers$measurables$types.isSpacer(a)&&(a.precedesStatement||a.followsStatement)){var b=this.constants_.INSIDE_CORNERS.rightHeight;b=a.height-(a.precedesStatement?b:0);this.outlinePath_+=(a.followsStatement?this.constants_.INSIDE_CORNERS.pathBottomRight:"")+(0=c||0>=b)throw Error("Height and width values of an image field must be greater than 0.");this.size_=new Size$$module$build$src$core$utils$size(b,c+$.FieldImage$$module$build$src$core$field_image.Y_PADDING);this.imageHeight_=c;"function"===typeof e&&(this.clickHandler_=e);a!==Field$$module$build$src$core$field.SKIP_SETUP&&(g?this.configure_(g):(this.flipRtl_=!!f,this.altText_=replaceMessageReferences$$module$build$src$core$utils$parsing(d)||""),this.setValue(replaceMessageReferences$$module$build$src$core$utils$parsing(a)))}configure_(a){super.configure_(a); -a.flipRtl&&(this.flipRtl_=a.flipRtl);a.alt&&(this.altText_=replaceMessageReferences$$module$build$src$core$utils$parsing(a.alt))}initView(){this.imageElement_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.IMAGE,{height:this.imageHeight_+"px",width:this.size_.width+"px",alt:this.altText_},this.fieldGroup_);this.imageElement_.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",this.value_);this.clickHandler_&&(this.imageElement_.style.cursor= -"pointer")}updateSize_(){}doClassValidation_(a){return"string"!==typeof a?null:a}doValueUpdate_(a){this.value_=a;this.imageElement_&&this.imageElement_.setAttributeNS(XLINK_NS$$module$build$src$core$utils$dom,"xlink:href",String(this.value_))}getFlipRtl(){return this.flipRtl_}setAlt(a){a!==this.altText_&&(this.altText_=a||"",this.imageElement_&&this.imageElement_.setAttribute("alt",this.altText_))}showEditor_(){this.clickHandler_&&this.clickHandler_(this)}setOnClickHandler(a){this.clickHandler_=a}getText_(){return this.altText_}static fromJson(a){if(!a.src|| -!a.width||!a.height)throw Error("src, width, and height values for an image field arerequired. The width and height must be non-zero.");return new this(a.src,a.width,a.height,void 0,void 0,void 0,a)}};$.FieldImage$$module$build$src$core$field_image.Y_PADDING=1;register$$module$build$src$core$field_registry("field_image",$.FieldImage$$module$build$src$core$field_image);$.FieldImage$$module$build$src$core$field_image.prototype.DEFAULT_VALUE="";var module$build$src$core$field_image={}; -module$build$src$core$field_image.FieldImage=$.FieldImage$$module$build$src$core$field_image;$.FieldTextInput$$module$build$src$core$field_textinput=class extends Field$$module$build$src$core$field{constructor(a,b,c){super(Field$$module$build$src$core$field.SKIP_SETUP);this.spellcheck_=!0;this.htmlInput_=null;this.isTextValid_=this.isBeingEdited_=!1;this.onKeyInputWrapper_=this.onKeyDownWrapper_=null;this.fullBlockClickTarget_=!1;this.workspace_=null;this.SERIALIZABLE=!0;this.CURSOR="text";a!==Field$$module$build$src$core$field.SKIP_SETUP&&(c&&this.configure_(c),this.setValue(a),b&&this.setValidator(b))}configure_(a){super.configure_(a); -void 0!==a.spellcheck&&(this.spellcheck_=a.spellcheck)}initView(){const a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;if(this.getConstants().FULL_BLOCK_FIELDS){let b=0,c=0;for(let d=0,e;e=a.inputList[d];d++){for(let f=0;e.fieldRow[f];f++)b++;e.connection&&c++}this.fullBlockClickTarget_=1>=b&&a.outputConnection&&!c}else this.fullBlockClickTarget_=!1;this.fullBlockClickTarget_?this.clickTarget_=this.sourceBlock_.getSvgRoot():this.createBorderRect_();this.createTextElement_()}doClassValidation_(a){return null=== -a||void 0===a?null:String(a)}doValueInvalid_(a){this.isBeingEdited_&&(this.isTextValid_=!1,a=this.value_,this.value_=this.htmlInput_.getAttribute("data-untyped-default-value"),this.sourceBlock_&&isEnabled$$module$build$src$core$events$utils()&&fire$$module$build$src$core$events$utils(new (get$$module$build$src$core$events$utils(CHANGE$$module$build$src$core$events$utils))(this.sourceBlock_,"field",this.name||null,a,this.value_)))}doValueUpdate_(a){this.isTextValid_=!0;this.value_=a;this.isBeingEdited_|| -(this.isDirty_=!0)}applyColour(){if(this.sourceBlock_&&this.getConstants().FULL_BLOCK_FIELDS){var a=this.sourceBlock_;if(this.borderRect_){if(!a.style.colourTertiary)throw Error("The renderer did not properly initialize the block style");this.borderRect_.setAttribute("stroke",a.style.colourTertiary)}else a.pathObject.svgPath.setAttribute("fill",this.getConstants().FIELD_BORDER_RECT_COLOUR)}}render_(){super.render_();if(this.isBeingEdited_){this.resizeEditor_();const a=this.htmlInput_;this.isTextValid_? -(removeClass$$module$build$src$core$utils$dom(a,"blocklyInvalidInput"),setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.INVALID,!1)):(addClass$$module$build$src$core$utils$dom(a,"blocklyInvalidInput"),setState$$module$build$src$core$utils$aria(a,State$$module$build$src$core$utils$aria.INVALID,!0))}}setSpellcheck(a){a!==this.spellcheck_&&(this.spellcheck_=a,this.htmlInput_&&this.htmlInput_.setAttribute("spellcheck",this.spellcheck_))}showEditor_(a,b){this.workspace_= -this.sourceBlock_.workspace;a=b||!1;!a&&(MOBILE$$module$build$src$core$utils$useragent||ANDROID$$module$build$src$core$utils$useragent||IPAD$$module$build$src$core$utils$useragent)?this.showPromptEditor_():this.showInlineEditor_(a)}showPromptEditor_(){prompt$$module$build$src$core$dialog(Msg$$module$build$src$core$msg.CHANGE_VALUE_TITLE,this.getText(),a=>{null!==a&&this.setValue(this.getValueFromEditorText_(a))})}showInlineEditor_(a){const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field; -show$$module$build$src$core$widgetdiv(this,b.RTL,this.widgetDispose_.bind(this));this.htmlInput_=this.widgetCreate_();this.isBeingEdited_=!0;a||(this.htmlInput_.focus({preventScroll:!0}),this.htmlInput_.select())}widgetCreate_(){var a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;setGroup$$module$build$src$core$events$utils(!0);const b=getDiv$$module$build$src$core$widgetdiv();var c=this.getClickTarget_();if(!c)throw Error("A click target has not been set."); -addClass$$module$build$src$core$utils$dom(c,"editing");c=document.createElement("input");c.className="blocklyHtmlInput";c.setAttribute("spellcheck",this.spellcheck_);const d=this.workspace_.getScale();var e=this.getConstants().FIELD_TEXT_FONTSIZE*d+"pt";b.style.fontSize=e;c.style.fontSize=e;e=$.FieldTextInput$$module$build$src$core$field_textinput.BORDERRADIUS*d+"px";this.fullBlockClickTarget_&&(e=this.getScaledBBox(),e=(e.bottom-e.top)/2+"px",a=a.getParent()?a.getParent().style.colourTertiary:this.sourceBlock_.style.colourTertiary, -c.style.border=1*d+"px solid "+a,b.style.borderRadius=e,b.style.transition="box-shadow 0.25s ease 0s",this.getConstants().FIELD_TEXTINPUT_BOX_SHADOW&&(b.style.boxShadow="rgba(255, 255, 255, 0.3) 0 0 0 "+4*d+"px"));c.style.borderRadius=e;b.appendChild(c);c.value=c.defaultValue=this.getEditorText_(this.value_);c.setAttribute("data-untyped-default-value",this.value_);c.setAttribute("data-old-value","");this.resizeEditor_();this.bindInputEvents_(c);return c}widgetDispose_(){this.isBeingEdited_=!1;this.isTextValid_= -!0;this.forceRerender();this.onFinishEditing_(this.value_);setGroup$$module$build$src$core$events$utils(!1);this.unbindInputEvents_();var a=getDiv$$module$build$src$core$widgetdiv().style;a.width="auto";a.height="auto";a.fontSize="";a.transition="";a.boxShadow="";this.htmlInput_=null;a=this.getClickTarget_();if(!a)throw Error("A click target has not been set.");removeClass$$module$build$src$core$utils$dom(a,"editing")}onFinishEditing_(a){}bindInputEvents_(a){this.onKeyDownWrapper_=conditionalBind$$module$build$src$core$browser_events(a, -"keydown",this,this.onHtmlInputKeyDown_);this.onKeyInputWrapper_=conditionalBind$$module$build$src$core$browser_events(a,"input",this,this.onHtmlInputChange_)}unbindInputEvents_(){this.onKeyDownWrapper_&&(unbind$$module$build$src$core$browser_events(this.onKeyDownWrapper_),this.onKeyDownWrapper_=null);this.onKeyInputWrapper_&&(unbind$$module$build$src$core$browser_events(this.onKeyInputWrapper_),this.onKeyInputWrapper_=null)}onHtmlInputKeyDown_(a){a.keyCode===KeyCodes$$module$build$src$core$utils$keycodes.ENTER? -(hide$$module$build$src$core$widgetdiv(),hideWithoutAnimation$$module$build$src$core$dropdowndiv()):a.keyCode===KeyCodes$$module$build$src$core$utils$keycodes.ESC?(this.setValue(this.htmlInput_.getAttribute("data-untyped-default-value")),hide$$module$build$src$core$widgetdiv(),hideWithoutAnimation$$module$build$src$core$dropdowndiv()):a.keyCode===KeyCodes$$module$build$src$core$utils$keycodes.TAB&&(hide$$module$build$src$core$widgetdiv(),hideWithoutAnimation$$module$build$src$core$dropdowndiv(),this.sourceBlock_.tab(this, -!a.shiftKey),a.preventDefault())}onHtmlInputChange_(a){a=this.htmlInput_.value;a!==this.htmlInput_.getAttribute("data-old-value")&&(this.htmlInput_.setAttribute("data-old-value",a),a=this.getValueFromEditorText_(a),this.setValue(a),this.forceRerender(),this.resizeEditor_())}setEditorValue_(a){this.isDirty_=!0;this.isBeingEdited_&&(this.htmlInput_.value=this.getEditorText_(a));this.setValue(a)}resizeEditor_(){var a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field; -const b=getDiv$$module$build$src$core$widgetdiv(),c=this.getScaledBBox();b.style.width=c.right-c.left+"px";b.style.height=c.bottom-c.top+"px";a=new Coordinate$$module$build$src$core$utils$coordinate(a.RTL?c.right-b.offsetWidth:c.left,c.top);b.style.left=a.x+"px";b.style.top=a.y+"px"}isTabNavigable(){return!0}getText_(){return this.isBeingEdited_&&this.htmlInput_?this.htmlInput_.value:null}getEditorText_(a){return String(a)}getValueFromEditorText_(a){return a}static fromJson(a){return new this(replaceMessageReferences$$module$build$src$core$utils$parsing(a.text), -void 0,a)}};$.FieldTextInput$$module$build$src$core$field_textinput.BORDERRADIUS=4;register$$module$build$src$core$field_registry("field_input",$.FieldTextInput$$module$build$src$core$field_textinput);$.FieldTextInput$$module$build$src$core$field_textinput.prototype.DEFAULT_VALUE="";var module$build$src$core$field_textinput={};module$build$src$core$field_textinput.FieldTextInput=$.FieldTextInput$$module$build$src$core$field_textinput;var BottomRow$$module$build$src$core$renderers$zelos$measurables$bottom_row=class extends BottomRow$$module$build$src$core$renderers$measurables$bottom_row{constructor(a){super(a)}endsWithElemSpacer(){return!1}hasLeftSquareCorner(a){return!!a.outputConnection}hasRightSquareCorner(a){return!!a.outputConnection&&!a.statementInputCount&&!a.nextConnection}},module$build$src$core$renderers$zelos$measurables$bottom_row={};module$build$src$core$renderers$zelos$measurables$bottom_row.BottomRow=BottomRow$$module$build$src$core$renderers$zelos$measurables$bottom_row;var StatementInput$$module$build$src$core$renderers$zelos$measurables$inputs=class extends StatementInput$$module$build$src$core$renderers$measurables$statement_input{constructor(a,b){super(a,b);this.connectedBottomNextConnection=!1;if(this.connectedBlock){for(a=this.connectedBlock;b=a.getNextBlock();)a=b;a.nextConnection||(this.height=this.connectedBlockHeight,this.connectedBottomNextConnection=!0)}}},module$build$src$core$renderers$zelos$measurables$inputs={}; -module$build$src$core$renderers$zelos$measurables$inputs.StatementInput=StatementInput$$module$build$src$core$renderers$zelos$measurables$inputs;var RightConnectionShape$$module$build$src$core$renderers$zelos$measurables$row_elements=class extends Measurable$$module$build$src$core$renderers$measurables$base{constructor(a){super(a);this.width=this.height=0;this.type|=Types$$module$build$src$core$renderers$measurables$types.getType("RIGHT_CONNECTION")}},module$build$src$core$renderers$zelos$measurables$row_elements={};module$build$src$core$renderers$zelos$measurables$row_elements.RightConnectionShape=RightConnectionShape$$module$build$src$core$renderers$zelos$measurables$row_elements;var TopRow$$module$build$src$core$renderers$zelos$measurables$top_row=class extends TopRow$$module$build$src$core$renderers$measurables$top_row{constructor(a){super(a)}endsWithElemSpacer(){return!1}hasLeftSquareCorner(a){const b=(a.hat?"cap"===a.hat:this.constants_.ADD_START_HATS)&&!a.outputConnection&&!a.previousConnection;return!!a.outputConnection||b}hasRightSquareCorner(a){return!!a.outputConnection&&!a.statementInputCount&&!a.nextConnection}},module$build$src$core$renderers$zelos$measurables$top_row= -{};module$build$src$core$renderers$zelos$measurables$top_row.TopRow=TopRow$$module$build$src$core$renderers$zelos$measurables$top_row;var RenderInfo$$module$build$src$core$renderers$zelos$info=class extends RenderInfo$$module$build$src$core$renderers$common$info{constructor(a,b){super(a,b);this.isInline=!0;this.renderer_=a;this.constants_=this.renderer_.getConstants();this.topRow=new TopRow$$module$build$src$core$renderers$zelos$measurables$top_row(this.constants_);this.bottomRow=new BottomRow$$module$build$src$core$renderers$zelos$measurables$bottom_row(this.constants_);this.isMultiRow=!b.getInputsInline()||b.isCollapsed();this.hasStatementInput= -0=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!d.precedesStatement;if(Types$$module$build$src$core$renderers$measurables$types.isInputRow(f)&&f.hasStatement){f.measure(); -let g,h;b=f.width-(null!=(h=null==(g=f.getLastInput())?void 0:g.width)?h:0)+a}else if(c&&(2===e||d)&&Types$$module$build$src$core$renderers$measurables$types.isInputRow(f)&&!f.hasStatement){d=f.xPos;c=null;for(let g=0;gc?c:this.height/2,b-c*(1-Math.sin(Math.acos((c-this.constants_.SMALL_PADDING)/c)));default:return 0}if(Types$$module$build$src$core$renderers$measurables$types.isInlineInput(a)&&a instanceof -InputConnection$$module$build$src$core$renderers$measurables$input_connection){const e=a.connectedBlock;a=e?e.pathObject.outputShapeType:a.shape.type;return null==a||e&&e.outputConnection&&(e.statementInputCount||e.nextConnection)||c===d.SHAPES.HEXAGONAL&&c!==a?0:b-this.constants_.SHAPE_IN_SHAPE_PADDING[c][a]}return Types$$module$build$src$core$renderers$measurables$types.isField(a)&&a instanceof Field$$module$build$src$core$renderers$measurables$field?c===d.SHAPES.ROUND&&a.field instanceof $.FieldTextInput$$module$build$src$core$field_textinput? -b-2.75*d.GRID_UNIT:b-this.constants_.SHAPE_IN_SHAPE_PADDING[c][0]:Types$$module$build$src$core$renderers$measurables$types.isIcon(a)?this.constants_.SMALL_PADDING:0}finalizeVerticalAlignment_(){if(!this.outputConnection)for(let d=2;d=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!g.precedesStatement;if(a?this.topRow.hasPreviousConnection:e.followsStatement){var c=f.elements[1];c=3===f.elements.length&& -c instanceof Field$$module$build$src$core$renderers$measurables$field&&(c.field instanceof $.FieldLabel$$module$build$src$core$field_label||c.field instanceof $.FieldImage$$module$build$src$core$field_image);if(!a&&c)e.height-=this.constants_.SMALL_PADDING,g.height-=this.constants_.SMALL_PADDING,f.height-=this.constants_.MEDIUM_PADDING;else if(!a&&!b)e.height+=this.constants_.SMALL_PADDING;else if(b){a=!1;for(b=0;b.blocklyPathLight,`,`${a} .blocklyInsertionMarker>.blocklyPathDark {`,`fill-opacity: ${this.INSERTION_MARKER_OPACITY};`,"stroke: none;", -"}"])}},module$build$src$core$renderers$geras$constants={};module$build$src$core$renderers$geras$constants.ConstantProvider=ConstantProvider$$module$build$src$core$renderers$geras$constants;var Highlighter$$module$build$src$core$renderers$geras$highlighter=class{constructor(a){this.inlineSteps_=this.steps_="";this.info_=a;this.RTL_=this.info_.RTL;a=a.getRenderer();this.constants_=a.getConstants();this.highlightConstants_=a.getHighlightConstants();this.highlightOffset_=this.highlightConstants_.OFFSET;this.outsideCornerPaths_=this.highlightConstants_.OUTSIDE_CORNER;this.insideCornerPaths_=this.highlightConstants_.INSIDE_CORNER;this.puzzleTabPaths_=this.highlightConstants_.PUZZLE_TAB;this.notchPaths_= -this.highlightConstants_.NOTCH;this.startPaths_=this.highlightConstants_.START_HAT;this.jaggedTeethPaths_=this.highlightConstants_.JAGGED_TEETH}getPath(){return this.steps_+"\n"+this.inlineSteps_}drawTopCorner(a){this.steps_+=moveBy$$module$build$src$core$utils$svg_paths(a.xPos,this.info_.startY);for(let b=0,c;c=a.elements[b];b++)Types$$module$build$src$core$renderers$measurables$types.isLeftSquareCorner(c)?this.steps_+=this.highlightConstants_.START_POINT:Types$$module$build$src$core$renderers$measurables$types.isLeftRoundedCorner(c)? -this.steps_+=this.outsideCornerPaths_.topLeft(this.RTL_):Types$$module$build$src$core$renderers$measurables$types.isPreviousConnection(c)?this.steps_+=this.notchPaths_.pathLeft:Types$$module$build$src$core$renderers$measurables$types.isHat(c)?this.steps_+=this.startPaths_.path(this.RTL_):Types$$module$build$src$core$renderers$measurables$types.isSpacer(c)&&0!==c.width&&(this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",c.xPos+c.width-this.highlightOffset_));this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H", -a.xPos+a.width-this.highlightOffset_)}drawJaggedEdge_(a){this.info_.RTL&&(this.steps_+=this.jaggedTeethPaths_.pathLeft+lineOnAxis$$module$build$src$core$utils$svg_paths("v",a.height-this.jaggedTeethPaths_.height-this.highlightOffset_))}drawValueInput(a){const b=a.getLastInput();if(this.RTL_){const c=a.height-b.connectionHeight;this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(b.xPos+b.width-this.highlightOffset_,a.yPos)+this.puzzleTabPaths_.pathDown(this.RTL_)+lineOnAxis$$module$build$src$core$utils$svg_paths("v", -c)}else this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(b.xPos+b.width,a.yPos)+this.puzzleTabPaths_.pathDown(this.RTL_)}drawStatementInput(a){const b=a.getLastInput();if(b)if(this.RTL_){const c=a.height-2*this.insideCornerPaths_.height;this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(b.xPos,a.yPos)+this.insideCornerPaths_.pathTop(this.RTL_)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",c)+this.insideCornerPaths_.pathBottom(this.RTL_)+lineTo$$module$build$src$core$utils$svg_paths(a.width- -b.xPos-this.insideCornerPaths_.width,0)}else this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(b.xPos,a.yPos+a.height)+this.insideCornerPaths_.pathBottom(this.RTL_)+lineTo$$module$build$src$core$utils$svg_paths(a.width-b.xPos-this.insideCornerPaths_.width,0)}drawRightSideRow(a){const b=a.xPos+a.width-this.highlightOffset_;a instanceof SpacerRow$$module$build$src$core$renderers$measurables$spacer_row&&a.followsStatement&&(this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H", -b));this.RTL_&&(this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",b),a.height>this.highlightOffset_&&(this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("V",a.yPos+a.height-this.highlightOffset_)))}drawBottomRow(a){if(this.RTL_)this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("V",a.baseline-this.highlightOffset_);else{const b=this.info_.bottomRow.elements[0];Types$$module$build$src$core$renderers$measurables$types.isLeftSquareCorner(b)?this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(a.xPos+ -this.highlightOffset_,a.baseline-this.highlightOffset_):Types$$module$build$src$core$renderers$measurables$types.isLeftRoundedCorner(b)&&(this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(a.xPos,a.baseline),this.steps_+=this.outsideCornerPaths_.bottomLeft())}}drawLeft(){var a=this.info_.outputConnection;a&&(a=a.connectionOffsetY+a.height,this.RTL_?this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(this.info_.startX,a):(this.steps_+=moveTo$$module$build$src$core$utils$svg_paths(this.info_.startX+ -this.highlightOffset_,this.info_.bottomRow.baseline-this.highlightOffset_),this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("V",a)),this.steps_+=this.puzzleTabPaths_.pathUp(this.RTL_));this.RTL_||(a=this.info_.topRow,Types$$module$build$src$core$renderers$measurables$types.isLeftRoundedCorner(a.elements[0])?this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("V",this.outsideCornerPaths_.height):this.steps_+=lineOnAxis$$module$build$src$core$utils$svg_paths("V",a.capline+this.highlightOffset_))}drawInlineInput(a){const b= -this.highlightOffset_,c=a.xPos+a.connectionWidth;var d=a.centerline-a.height/2;const e=a.width-a.connectionWidth,f=d+b;this.RTL_?(d=a.connectionOffsetY-b,a=a.height-(a.connectionOffsetY+a.connectionHeight)+b,this.inlineSteps_+=moveTo$$module$build$src$core$utils$svg_paths(c-b,f)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",d)+this.puzzleTabPaths_.pathDown(this.RTL_)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",a)+lineOnAxis$$module$build$src$core$utils$svg_paths("h",e)):this.inlineSteps_+= -moveTo$$module$build$src$core$utils$svg_paths(a.xPos+a.width+b,f)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",a.height)+lineOnAxis$$module$build$src$core$utils$svg_paths("h",-e)+moveTo$$module$build$src$core$utils$svg_paths(c,d+a.connectionOffsetY)+this.puzzleTabPaths_.pathDown(this.RTL_)}},module$build$src$core$renderers$geras$highlighter={};module$build$src$core$renderers$geras$highlighter.Highlighter=Highlighter$$module$build$src$core$renderers$geras$highlighter;var Drawer$$module$build$src$core$renderers$geras$drawer=class extends Drawer$$module$build$src$core$renderers$common$drawer{constructor(a,b){super(a,b);this.highlighter_=new Highlighter$$module$build$src$core$renderers$geras$highlighter(b)}draw(){this.hideHiddenIcons_();this.drawOutline_();this.drawInternals_();const a=this.block_.pathObject;a.setPath(this.outlinePath_+"\n"+this.inlinePath_);a.setHighlightPath(this.highlighter_.getPath());this.info_.RTL&&a.flipRTL();if(isDebuggerEnabled$$module$build$src$core$renderers$common$debug()){let b, -c;null==(b=this.block_)||null==(c=b.renderingDebugger)||c.drawDebug(this.block_,this.info_)}this.recordSizeOnBlock_()}drawTop_(){this.highlighter_.drawTopCorner(this.info_.topRow);this.highlighter_.drawRightSideRow(this.info_.topRow);super.drawTop_()}drawJaggedEdge_(a){this.highlighter_.drawJaggedEdge_(a);super.drawJaggedEdge_(a)}drawValueInput_(a){this.highlighter_.drawValueInput(a);super.drawValueInput_(a)}drawStatementInput_(a){this.highlighter_.drawStatementInput(a);super.drawStatementInput_(a)}drawRightSideRow_(a){this.highlighter_.drawRightSideRow(a); -this.outlinePath_+=lineOnAxis$$module$build$src$core$utils$svg_paths("H",a.xPos+a.width)+lineOnAxis$$module$build$src$core$utils$svg_paths("V",a.yPos+a.height)}drawBottom_(){this.highlighter_.drawBottomRow(this.info_.bottomRow);super.drawBottom_()}drawLeft_(){this.highlighter_.drawLeft();super.drawLeft_()}drawInlineInput_(a){this.highlighter_.drawInlineInput(a);super.drawInlineInput_(a)}positionInlineInputConnection_(a){const b=a.centerline-a.height/2;if(a.connectionModel){let c=a.xPos+a.connectionWidth+ -this.constants_.DARK_PATH_OFFSET;this.info_.RTL&&(c*=-1);a.connectionModel.setOffsetInBlock(c,b+a.connectionOffsetY+this.constants_.DARK_PATH_OFFSET)}}positionStatementInputConnection_(a){const b=a.getLastInput();if(null==b?0:b.connectionModel){let c=a.xPos+a.statementEdge+b.notchOffset;c=this.info_.RTL?-1*c:c+this.constants_.DARK_PATH_OFFSET;b.connectionModel.setOffsetInBlock(c,a.yPos+this.constants_.DARK_PATH_OFFSET)}}positionExternalValueConnection_(a){const b=a.getLastInput();if(b&&b.connectionModel){let c= -a.xPos+a.width+this.constants_.DARK_PATH_OFFSET;this.info_.RTL&&(c*=-1);b.connectionModel.setOffsetInBlock(c,a.yPos)}}positionNextConnection_(){const a=this.info_.bottomRow;if(a.connection){const b=a.connection,c=b.xPos;b.connectionModel.setOffsetInBlock((this.info_.RTL?-c:c)+this.constants_.DARK_PATH_OFFSET/2,a.baseline+this.constants_.DARK_PATH_OFFSET)}}},module$build$src$core$renderers$geras$drawer={};module$build$src$core$renderers$geras$drawer.Drawer=Drawer$$module$build$src$core$renderers$geras$drawer;var HighlightConstantProvider$$module$build$src$core$renderers$geras$highlight_constants=class{constructor(a){this.OFFSET=.5;this.constantProvider=a;this.START_POINT=moveBy$$module$build$src$core$utils$svg_paths(this.OFFSET,this.OFFSET)}init(){this.INSIDE_CORNER=this.makeInsideCorner();this.OUTSIDE_CORNER=this.makeOutsideCorner();this.PUZZLE_TAB=this.makePuzzleTab();this.NOTCH=this.makeNotch();this.JAGGED_TEETH=this.makeJaggedTeeth();this.START_HAT=this.makeStartHat()}makeInsideCorner(){const a=this.constantProvider.CORNER_RADIUS, -b=this.OFFSET,c=(1-Math.SQRT1_2)*(a+b)-b,d=moveBy$$module$build$src$core$utils$svg_paths(c,c)+arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a,point$$module$build$src$core$utils$svg_paths(-c-b,a-c)),e=arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a+b,point$$module$build$src$core$utils$svg_paths(a+b,a+b)),f=moveBy$$module$build$src$core$utils$svg_paths(c,-c)+arc$$module$build$src$core$utils$svg_paths("a","0 0,0",a+b,point$$module$build$src$core$utils$svg_paths(a-c,c+b));return{width:a+ -b,height:a,pathTop(g){return g?d:""},pathBottom(g){return g?e:f}}}makeOutsideCorner(){const a=this.constantProvider.CORNER_RADIUS,b=this.OFFSET,c=(1-Math.SQRT1_2)*(a-b)+b,d=moveBy$$module$build$src$core$utils$svg_paths(c,c)+arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a-b,point$$module$build$src$core$utils$svg_paths(a-c,-c+b)),e=moveBy$$module$build$src$core$utils$svg_paths(b,a)+arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a-b,point$$module$build$src$core$utils$svg_paths(a,-a+ -b)),f=-c,g=moveBy$$module$build$src$core$utils$svg_paths(c,f)+arc$$module$build$src$core$utils$svg_paths("a","0 0,1",a-b,point$$module$build$src$core$utils$svg_paths(-c+b,-f-a));return{height:a,topLeft(h){return h?d:e},bottomLeft(){return g}}}makePuzzleTab(){const a=this.constantProvider.TAB_WIDTH,b=this.constantProvider.TAB_HEIGHT,c=moveBy$$module$build$src$core$utils$svg_paths(-2,-b+3.4)+lineTo$$module$build$src$core$utils$svg_paths(-.45*a,-2.1),d=lineOnAxis$$module$build$src$core$utils$svg_paths("v", -2.5)+moveBy$$module$build$src$core$utils$svg_paths(.97*-a,2.5)+curve$$module$build$src$core$utils$svg_paths("q",[point$$module$build$src$core$utils$svg_paths(.05*-a,10),point$$module$build$src$core$utils$svg_paths(.3*a,9.5)])+moveBy$$module$build$src$core$utils$svg_paths(.67*a,-1.9)+lineOnAxis$$module$build$src$core$utils$svg_paths("v",2.5),e=lineOnAxis$$module$build$src$core$utils$svg_paths("v",-1.5)+moveBy$$module$build$src$core$utils$svg_paths(-.92*a,-.5)+curve$$module$build$src$core$utils$svg_paths("q", -[point$$module$build$src$core$utils$svg_paths(-.19*a,-5.5),point$$module$build$src$core$utils$svg_paths(0,-11)])+moveBy$$module$build$src$core$utils$svg_paths(.92*a,1),f=moveBy$$module$build$src$core$utils$svg_paths(-5,b-.7)+lineTo$$module$build$src$core$utils$svg_paths(.46*a,-2.1);return{width:a,height:b,pathUp(g){return g?c:e},pathDown(g){return g?d:f}}}makeNotch(){return{pathLeft:lineOnAxis$$module$build$src$core$utils$svg_paths("h",this.OFFSET)+this.constantProvider.NOTCH.pathLeft}}makeJaggedTeeth(){return{pathLeft:lineTo$$module$build$src$core$utils$svg_paths(5.1, -2.6)+moveBy$$module$build$src$core$utils$svg_paths(-10.2,6.8)+lineTo$$module$build$src$core$utils$svg_paths(5.1,2.6),height:12,width:10.2}}makeStartHat(){const a=this.constantProvider.START_HAT.height,b=moveBy$$module$build$src$core$utils$svg_paths(25,-8.7)+curve$$module$build$src$core$utils$svg_paths("c",[point$$module$build$src$core$utils$svg_paths(29.7,-6.2),point$$module$build$src$core$utils$svg_paths(57.2,-.5),point$$module$build$src$core$utils$svg_paths(75,8.7)]),c=curve$$module$build$src$core$utils$svg_paths("c", -[point$$module$build$src$core$utils$svg_paths(17.8,-9.2),point$$module$build$src$core$utils$svg_paths(45.3,-14.9),point$$module$build$src$core$utils$svg_paths(75,-8.7)])+moveTo$$module$build$src$core$utils$svg_paths(100.5,a+.5);return{path(d){return d?b:c}}}},module$build$src$core$renderers$geras$highlight_constants={};module$build$src$core$renderers$geras$highlight_constants.HighlightConstantProvider=HighlightConstantProvider$$module$build$src$core$renderers$geras$highlight_constants;var InlineInput$$module$build$src$core$renderers$geras$measurables$inline_input=class extends InlineInput$$module$build$src$core$renderers$measurables$inline_input{constructor(a,b){super(a,b);this.constants_=a;this.connectedBlock&&(this.width+=this.constants_.DARK_PATH_OFFSET,this.height+=this.constants_.DARK_PATH_OFFSET)}},module$build$src$core$renderers$geras$measurables$inline_input={};module$build$src$core$renderers$geras$measurables$inline_input.InlineInput=InlineInput$$module$build$src$core$renderers$geras$measurables$inline_input;var StatementInput$$module$build$src$core$renderers$geras$measurables$statement_input=class extends StatementInput$$module$build$src$core$renderers$measurables$statement_input{constructor(a,b){super(a,b);this.constants_=a;this.connectedBlock&&(this.height+=this.constants_.DARK_PATH_OFFSET)}},module$build$src$core$renderers$geras$measurables$statement_input={};module$build$src$core$renderers$geras$measurables$statement_input.StatementInput=StatementInput$$module$build$src$core$renderers$geras$measurables$statement_input;var RenderInfo$$module$build$src$core$renderers$geras$info=class extends RenderInfo$$module$build$src$core$renderers$common$info{constructor(a,b){super(a,b);this.renderer_=a}getRenderer(){return this.renderer_}populateBottomRow_(){super.populateBottomRow_();this.block_.inputList.length&&this.block_.inputList[this.block_.inputList.length-1].type===inputTypes$$module$build$src$core$input_types.STATEMENT||(this.bottomRow.minHeight=this.constants_.MEDIUM_PADDING-this.constants_.DARK_PATH_OFFSET)}addInput_(a, -b){this.isInline&&a.type===inputTypes$$module$build$src$core$input_types.VALUE?(b.elements.push(new InlineInput$$module$build$src$core$renderers$geras$measurables$inline_input(this.constants_,a)),b.hasInlineInput=!0):a.type===inputTypes$$module$build$src$core$input_types.STATEMENT?(b.elements.push(new StatementInput$$module$build$src$core$renderers$geras$measurables$statement_input(this.constants_,a)),b.hasStatement=!0):a.type===inputTypes$$module$build$src$core$input_types.VALUE?(b.elements.push(new ExternalValueInput$$module$build$src$core$renderers$measurables$external_value_input(this.constants_, -a)),b.hasExternalInput=!0):a.type===inputTypes$$module$build$src$core$input_types.DUMMY&&(b.minHeight=Math.max(b.minHeight,this.constants_.DUMMY_INPUT_MIN_HEIGHT),b.hasDummyInput=!0);this.isInline||null!==b.align||(b.align=a.align)}addElemSpacing_(){let a=!1;for(let c=0,d;d=this.rows[c];c++)d.hasExternalInput&&(a=!0);for(let c=0,d;d=this.rows[c];c++){var b=d.elements;d.elements=[];d.startsWithElemSpacer()&&d.elements.push(new InRowSpacer$$module$build$src$core$renderers$measurables$in_row_spacer(this.constants_, -this.getInRowSpacing_(null,b[0])));if(b.length){for(let e=0;e{const c=this.targetWorkspace.getGesture(b); -c&&(c.setStartBlock(a),c.handleFlyoutStart(b,this))}}onMouseDown_(a){const b=this.targetWorkspace.getGesture(a);b&&b.handleFlyoutStart(a,this)}isBlockCreatable(a){return a.isEnabled()}createBlock(a){let b=null;disable$$module$build$src$core$events$utils();var c=this.targetWorkspace.getAllVariables();this.targetWorkspace.setResizesEnabled(!1);try{b=this.placeNewBlock_(a)}finally{enable$$module$build$src$core$events$utils()}this.targetWorkspace.hideChaff();a=getAddedVariables$$module$build$src$core$variables(this.targetWorkspace, -c);if(isEnabled$$module$build$src$core$events$utils()){setGroup$$module$build$src$core$events$utils(!0);for(c=0;c-b||a<-180+b||a>180-b?!0:!1}getClientRect(){if(!this.svgGroup_||this.autoClose||!this.isVisible())return null;const a=this.svgGroup_.getBoundingClientRect(), -b=a.left;return this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.LEFT?new Rect$$module$build$src$core$utils$rect(-1E9,1E9,-1E9,b+a.width):new Rect$$module$build$src$core$utils$rect(-1E9,1E9,b,1E9)}reflowInternal_(){this.workspace_.scale=this.getFlyoutScale();let a=0;var b=this.workspace_.getTopBlocks(!1);for(let d=0,e;e=b[d];d++){var c=e.getHeightWidth().width;e.outputConnection&&(c-=this.tabWidth_);a=Math.max(a,c)}for(let d=0,e;e=this.buttons_[d];d++)a=Math.max(a,e.width);a+= -1.5*this.MARGIN+this.tabWidth_;a*=this.workspace_.scale;a+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness;if(this.width_!==a){for(let d=0,e;e=b[d];d++){if(this.RTL){c=e.getRelativeToSurfaceXY().x;let f=a/this.workspace_.scale-this.MARGIN;e.outputConnection||(f-=this.tabWidth_);e.moveBy(f-c,0)}this.rectMap_.has(e)&&this.moveRectToBlock_(this.rectMap_.get(e),e)}if(this.RTL)for(let d=0,e;e=this.buttons_[d];d++)b=e.getPosition().y,e.moveTo(a/this.workspace_.scale-e.width-this.MARGIN-this.tabWidth_, -b);this.targetWorkspace.toolboxPosition!==this.toolboxPosition_||this.toolboxPosition_!==Position$$module$build$src$core$utils$toolbox.LEFT||this.targetWorkspace.getToolbox()||this.targetWorkspace.translate(this.targetWorkspace.scrollX+a,this.targetWorkspace.scrollY);this.width_=a;this.position();this.targetWorkspace.recordDragTargets()}}};VerticalFlyout$$module$build$src$core$flyout_vertical.registryName="verticalFlyout"; -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_VERTICAL_TOOLBOX,DEFAULT$$module$build$src$core$registry,VerticalFlyout$$module$build$src$core$flyout_vertical);var module$build$src$core$flyout_vertical={};module$build$src$core$flyout_vertical.VerticalFlyout=VerticalFlyout$$module$build$src$core$flyout_vertical;var HorizontalFlyout$$module$build$src$core$flyout_horizontal=class extends Flyout$$module$build$src$core$flyout_base{constructor(a){super(a);this.horizontalLayout=!0}setMetrics_(a){if(this.isVisible()){var b=this.workspace_.getMetricsManager(),c=b.getScrollMetrics(),d=b.getViewMetrics();b=b.getAbsoluteMetrics();"number"===typeof a.x&&(this.workspace_.scrollX=-(c.left+(c.width-d.width)*a.x));this.workspace_.translate(this.workspace_.scrollX+b.left,this.workspace_.scrollY+b.top)}}getX(){return 0}getY(){if(!this.isVisible())return 0; -var a=this.targetWorkspace.getMetricsManager();const b=a.getAbsoluteMetrics(),c=a.getViewMetrics();a=a.getToolboxMetrics();const d=this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.TOP;return this.targetWorkspace.toolboxPosition===this.toolboxPosition_?this.targetWorkspace.getToolbox()?d?a.height:c.height-this.height_:d?0:c.height:d?0:c.height+b.top-this.height_}position(){if(this.isVisible()&&this.targetWorkspace.isVisible()){var a=this.targetWorkspace.getMetricsManager().getViewMetrics(); -this.width_=a.width;this.setBackgroundPath_(a.width-2*this.CORNER_RADIUS,this.height_-this.CORNER_RADIUS);a=this.getX();var b=this.getY();this.positionAt_(this.width_,this.height_,a,b)}}setBackgroundPath_(a,b){const c=this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.TOP,d=["M 0,"+(c?0:this.CORNER_RADIUS)];c?(d.push("h",a+2*this.CORNER_RADIUS),d.push("v",b),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,-this.CORNER_RADIUS,this.CORNER_RADIUS),d.push("h",-a),d.push("a", -this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,-this.CORNER_RADIUS,-this.CORNER_RADIUS)):(d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,this.CORNER_RADIUS,-this.CORNER_RADIUS),d.push("h",a),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,this.CORNER_RADIUS,this.CORNER_RADIUS),d.push("v",b),d.push("h",-a-2*this.CORNER_RADIUS));d.push("z");this.svgBackground_.setAttribute("d",d.join(" "))}scrollToStart(){let a;null==(a=this.workspace_.scrollbar)||a.setX(this.RTL?Infinity:0)}wheel_(a){var b= -getScrollDeltaPixels$$module$build$src$core$browser_events(a);if(b=b.x||b.y){const c=this.workspace_.getMetricsManager(),d=c.getScrollMetrics();b=c.getViewMetrics().left-d.left+b;let e;null==(e=this.workspace_.scrollbar)||e.setX(b);hide$$module$build$src$core$widgetdiv();hideWithoutAnimation$$module$build$src$core$dropdowndiv()}a.preventDefault();a.stopPropagation()}layout_(a,b){this.workspace_.scale=this.targetWorkspace.scale;const c=this.MARGIN;let d=c+this.tabWidth_;this.RTL&&(a=a.reverse());for(let h= -0,k;k=a[h];h++)if("block"===k.type){var e=k.block,f=e.getDescendants(!1);for(let m=0,n;n=f[m];m++)n.isInFlyout=!0;e.render();f=e.getSvgRoot();const l=e.getHeightWidth();var g=e.outputConnection?this.tabWidth_:0;g=this.RTL?d+l.width:d-g;e.moveBy(g,c);g=this.createRect_(e,g,c,l,h);d+=l.width+b[h];this.addBlockListeners_(f,e,g)}else"button"===k.type&&(e=k.button,this.initFlyoutButton_(e,d,c),d+=e.width+b[h])}isDragTowardWorkspace(a){a=Math.atan2(a.y,a.x)/Math.PI*180;const b=this.dragAngleRange_;return a< -90+b&&a>90-b||a>-90-b&&a<-90+b?!0:!1}getClientRect(){if(!this.svgGroup_||this.autoClose||!this.isVisible())return null;const a=this.svgGroup_.getBoundingClientRect(),b=a.top;return this.toolboxPosition_===Position$$module$build$src$core$utils$toolbox.TOP?new Rect$$module$build$src$core$utils$rect(-1E9,b+a.height,-1E9,1E9):new Rect$$module$build$src$core$utils$rect(b,1E9,-1E9,1E9)}reflowInternal_(){this.workspace_.scale=this.getFlyoutScale();let a=0;const b=this.workspace_.getTopBlocks(!1);for(let d= -0,e;e=b[d];d++)a=Math.max(a,e.getHeightWidth().height);const c=this.buttons_;for(let d=0,e;e=c[d];d++)a=Math.max(a,e.height);a+=1.5*this.MARGIN;a*=this.workspace_.scale;a+=Scrollbar$$module$build$src$core$scrollbar.scrollbarThickness;if(this.height_!==a){for(let d=0,e;e=b[d];d++)this.rectMap_.has(e)&&this.moveRectToBlock_(this.rectMap_.get(e),e);this.targetWorkspace.toolboxPosition!==this.toolboxPosition_||this.toolboxPosition_!==Position$$module$build$src$core$utils$toolbox.TOP||this.targetWorkspace.getToolbox()|| -this.targetWorkspace.translate(this.targetWorkspace.scrollX,this.targetWorkspace.scrollY+a);this.height_=a;this.position();this.targetWorkspace.recordDragTargets()}}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.FLYOUTS_HORIZONTAL_TOOLBOX,DEFAULT$$module$build$src$core$registry,HorizontalFlyout$$module$build$src$core$flyout_horizontal);var module$build$src$core$flyout_horizontal={};module$build$src$core$flyout_horizontal.HorizontalFlyout=HorizontalFlyout$$module$build$src$core$flyout_horizontal;var FieldVariable$$module$build$src$core$field_variable=class extends FieldDropdown$$module$build$src$core$field_dropdown{constructor(a,b,c,d,e){super(Field$$module$build$src$core$field.SKIP_SETUP);this.defaultType_="";this.variableTypes=[];this.variable_=null;this.SERIALIZABLE=!0;this.menuGenerator_=FieldVariable$$module$build$src$core$field_variable.dropdownCreate;this.defaultVariableName="string"===typeof a?a:"";this.size_=new Size$$module$build$src$core$utils$size(0,0);a!==Field$$module$build$src$core$field.SKIP_SETUP&& -(e?this.configure_(e):this.setTypes_(c,d),b&&this.setValidator(b))}configure_(a){super.configure_(a);this.setTypes_(a.variableTypes,a.defaultType)}initModel(){var a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;this.variable_||(a=getOrCreateVariablePackage$$module$build$src$core$variables(a.workspace,null,this.defaultVariableName,this.defaultType_),this.doValueUpdate_(a.getId()))}shouldAddBorderRect_(){const a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field; -return super.shouldAddBorderRect_()&&(!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||"variables_get"!==a.type)}fromXml(a){var b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;const c=a.getAttribute("id"),d=a.textContent,e=a.getAttribute("variabletype")||a.getAttribute("variableType")||"";b=getOrCreateVariablePackage$$module$build$src$core$variables(b.workspace,c,d,e);if(null!==e&&e!==b.type)throw Error("Serialized variable type with id '"+b.getId()+ -"' had type "+b.type+", and does not match variable field that references it: "+domToText$$module$build$src$core$xml(a)+".");this.setValue(b.getId())}toXml(a){this.initModel();a.id=this.variable_.getId();a.textContent=this.variable_.name;this.variable_.type&&a.setAttribute("variabletype",this.variable_.type);return a}saveState(a){var b=this.saveLegacyState(FieldVariable$$module$build$src$core$field_variable);if(null!==b)return b;this.initModel();b={id:this.variable_.getId()};a&&(b.name=this.variable_.name, -b.type=this.variable_.type);return b}loadState(a){const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;this.loadLegacyState(FieldVariable$$module$build$src$core$field_variable,a)||(a=getOrCreateVariablePackage$$module$build$src$core$variables(b.workspace,a.id||null,a.name,a.type||""),this.setValue(a.getId()))}setSourceBlock(a){if(a.isShadow())throw Error("Variable fields are not allowed to exist on shadow blocks.");super.setSourceBlock(a)}getValue(){return this.variable_? -this.variable_.getId():null}getText(){return this.variable_?this.variable_.name:""}getVariable(){return this.variable_}getValidator(){return this.variable_?this.validator_:null}doClassValidation_(a){if(null===a)return null;var b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;b=getVariable$$module$build$src$core$variables(b.workspace,a);if(!b)return console.warn("Variable id doesn't point to a real variable! ID was "+a),null;b=b.type;return this.typeIsAllowed_(b)? -a:(console.warn("Variable type doesn't match this field! Type was "+b),null)}doValueUpdate_(a){const b=this.getSourceBlock();if(!b)throw new UnattachedFieldError$$module$build$src$core$field;this.variable_=getVariable$$module$build$src$core$variables(b.workspace,a);super.doValueUpdate_(a)}typeIsAllowed_(a){const b=this.getVariableTypes_();if(!b)return!0;for(let c=0;cthis.max_&&setState$$module$build$src$core$utils$aria(a, -State$$module$build$src$core$utils$aria.VALUEMAX,this.max_);return a}static fromJson(a){return new this(a.value,void 0,void 0,void 0,void 0,a)}};register$$module$build$src$core$field_registry("field_number",FieldNumber$$module$build$src$core$field_number);FieldNumber$$module$build$src$core$field_number.prototype.DEFAULT_VALUE=0;var module$build$src$core$field_number={};module$build$src$core$field_number.FieldNumber=FieldNumber$$module$build$src$core$field_number;var FieldMultilineInput$$module$build$src$core$field_multilineinput=class extends $.FieldTextInput$$module$build$src$core$field_textinput{constructor(a,b,c){super(Field$$module$build$src$core$field.SKIP_SETUP);this.textGroup_=null;this.maxLines_=Infinity;this.isOverflowedY_=!1;a!==Field$$module$build$src$core$field.SKIP_SETUP&&(c&&this.configure_(c),this.setValue(a),b&&this.setValidator(b))}configure_(a){super.configure_(a);a.maxLines&&this.setMaxLines(a.maxLines)}toXml(a){a.textContent=this.getValue().replace(/\n/g, -" ");return a}fromXml(a){this.setValue(a.textContent.replace(/ /g,"\n"))}saveState(){const a=this.saveLegacyState(FieldMultilineInput$$module$build$src$core$field_multilineinput);return null!==a?a:this.getValue()}loadState(a){this.loadLegacyState(Field$$module$build$src$core$field,a)||this.setValue(a)}initView(){this.createBorderRect_();this.textGroup_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.G,{"class":"blocklyEditableText"},this.fieldGroup_)}getDisplayText_(){const a= -this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;let b=this.getText();if(!b)return Field$$module$build$src$core$field.NBSP;const c=b.split("\n");b="";const d=this.isOverflowedY_?this.maxLines_:c.length;for(let e=0;ethis.maxDisplayLength?f=f.substring(0,this.maxDisplayLength-4)+"...":this.isOverflowedY_&&e===d-1&&(f=f.substring(0,f.length-3)+"...");f=f.replace(/\s/g,Field$$module$build$src$core$field.NBSP);b+=f;e!==d-1&&(b+="\n")}a.RTL&& -(b+="\u200f");return b}doValueUpdate_(a){super.doValueUpdate_(a);this.isOverflowedY_=this.value_.split("\n").length>this.maxLines_}render_(){var a=this.getSourceBlock();if(!a)throw new UnattachedFieldError$$module$build$src$core$field;for(var b;b=this.textGroup_.firstChild;)this.textGroup_.removeChild(b);b=this.getDisplayText_().split("\n");let c=0;for(let d=0;de&&(e=h);f+=this.getConstants().FIELD_TEXT_HEIGHT+(0this.maxDisplayLength&&(a[h]=a[h].substring(0,this.maxDisplayLength));g.textContent=a[h];const k=getFastTextWidth$$module$build$src$core$utils$dom(g,b,c,d);k>e&&(e=k)}e+=this.htmlInput_.offsetWidth-this.htmlInput_.clientWidth}this.borderRect_&&(f+=2*this.getConstants().FIELD_BORDER_RECT_Y_PADDING,e+=2*this.getConstants().FIELD_BORDER_RECT_X_PADDING,this.borderRect_.setAttribute("width",e),this.borderRect_.setAttribute("height",f));this.size_.width=e;this.size_.height= -f;this.positionBorderRect_()}showEditor_(a,b){super.showEditor_(a,b);this.forceRerender()}widgetCreate_(){const a=getDiv$$module$build$src$core$widgetdiv(),b=this.workspace_.getScale(),c=document.createElement("textarea");c.className="blocklyHtmlInput blocklyHtmlTextAreaInput";c.setAttribute("spellcheck",this.spellcheck_);var d=this.getConstants().FIELD_TEXT_FONTSIZE*b+"pt";a.style.fontSize=d;c.style.fontSize=d;c.style.borderRadius=$.FieldTextInput$$module$build$src$core$field_textinput.BORDERRADIUS* -b+"px";d=this.getConstants().FIELD_BORDER_RECT_X_PADDING*b;const e=this.getConstants().FIELD_BORDER_RECT_Y_PADDING*b/2;c.style.padding=e+"px "+d+"px "+e+"px "+d+"px";d=this.getConstants().FIELD_TEXT_HEIGHT+this.getConstants().FIELD_BORDER_RECT_Y_PADDING;c.style.lineHeight=d*b+"px";a.appendChild(c);c.value=c.defaultValue=this.getEditorText_(this.value_);c.setAttribute("data-untyped-default-value",this.value_);c.setAttribute("data-old-value","");GECKO$$module$build$src$core$utils$useragent?setTimeout(this.resizeEditor_.bind(this), -0):this.resizeEditor_();this.bindInputEvents_(c);return c}setMaxLines(a){"number"===typeof a&&0a?0>e&&0e&&(e=0):0d-1&&fd-1&&e--:0>b?0>f&&(f=0):0Math.floor(c.length/d)-1&&(f=Math.floor(c.length/d)-1);this.setHighlightedCell_(this.picker_.childNodes[f].childNodes[e],f*d+e)}}onMouseMove_(a){const b=(a=a.target)&& -Number(a.getAttribute("data-index"));null!==b&&b!==this.highlightedIndex_&&this.setHighlightedCell_(a,b)}onMouseEnter_(){this.picker_.focus({preventScroll:!0})}onMouseLeave_(){this.picker_.blur();const a=this.getHighlighted_();a&&removeClass$$module$build$src$core$utils$dom(a,"blocklyColourHighlighted")}getHighlighted_(){if(!this.highlightedIndex_)return null;const a=this.columns_||FieldColour$$module$build$src$core$field_colour.COLUMNS,b=this.picker_.childNodes[Math.floor(this.highlightedIndex_/ -a)];return b?b.childNodes[this.highlightedIndex_%a]:null}setHighlightedCell_(a,b){const c=this.getHighlighted_();c&&removeClass$$module$build$src$core$utils$dom(c,"blocklyColourHighlighted");addClass$$module$build$src$core$utils$dom(a,"blocklyColourHighlighted");this.highlightedIndex_=b;setState$$module$build$src$core$utils$aria(this.picker_,State$$module$build$src$core$utils$aria.ACTIVEDESCENDANT,a.getAttribute("id"))}dropdownCreate_(){const a=this.columns_||FieldColour$$module$build$src$core$field_colour.COLUMNS, -b=this.colours_||FieldColour$$module$build$src$core$field_colour.COLOURS,c=this.titles_||FieldColour$$module$build$src$core$field_colour.TITLES,d=this.getValue(),e=document.createElement("table");e.className="blocklyColourTable";e.tabIndex=0;e.dir="ltr";setRole$$module$build$src$core$utils$aria(e,Role$$module$build$src$core$utils$aria.GRID);setState$$module$build$src$core$utils$aria(e,State$$module$build$src$core$utils$aria.EXPANDED,!0);setState$$module$build$src$core$utils$aria(e,State$$module$build$src$core$utils$aria.ROWCOUNT, -Math.floor(b.length/a));setState$$module$build$src$core$utils$aria(e,State$$module$build$src$core$utils$aria.COLCOUNT,a);let f;for(let g=0;gtr>td {\n border: .5px solid #888;\n box-sizing: border-box;\n cursor: pointer;\n display: inline-block;\n height: 20px;\n padding: 0;\n width: 20px;\n}\n\n.blocklyColourTable>tr>td.blocklyColourHighlighted {\n border-color: #eee;\n box-shadow: 2px 2px 7px 2px rgba(0,0,0,.3);\n position: relative;\n}\n\n.blocklyColourSelected, .blocklyColourSelected:hover {\n border-color: #eee !important;\n outline: 1px solid #333;\n position: relative;\n}\n"); -register$$module$build$src$core$field_registry("field_colour",FieldColour$$module$build$src$core$field_colour);var module$build$src$core$field_colour={};module$build$src$core$field_colour.FieldColour=FieldColour$$module$build$src$core$field_colour;$.FieldCheckbox$$module$build$src$core$field_checkbox=class extends Field$$module$build$src$core$field{constructor(a,b,c){super(Field$$module$build$src$core$field.SKIP_SETUP);this.SERIALIZABLE=!0;this.CURSOR="default";this.checkChar_=$.FieldCheckbox$$module$build$src$core$field_checkbox.CHECK_CHAR;a!==Field$$module$build$src$core$field.SKIP_SETUP&&(c&&this.configure_(c),this.setValue(a),b&&this.setValidator(b))}configure_(a){super.configure_(a);a.checkCharacter&&(this.checkChar_=a.checkCharacter)}saveState(){const a= -this.saveLegacyState($.FieldCheckbox$$module$build$src$core$field_checkbox);return null!==a?a:this.getValueBoolean()}initView(){super.initView();const a=this.getTextElement();addClass$$module$build$src$core$utils$dom(a,"blocklyCheckbox");a.style.display=this.value_?"block":"none"}render_(){this.textContent_&&(this.textContent_.nodeValue=this.getDisplayText_());this.updateSize_(this.getConstants().FIELD_CHECKBOX_X_OFFSET)}getDisplayText_(){return this.checkChar_}setCheckCharacter(a){this.checkChar_= -a||$.FieldCheckbox$$module$build$src$core$field_checkbox.CHECK_CHAR;this.forceRerender()}showEditor_(){this.setValue(!this.value_)}doClassValidation_(a){return!0===a||"TRUE"===a?"TRUE":!1===a||"FALSE"===a?"FALSE":null}doValueUpdate_(a){this.value_=this.convertValueToBool_(a);this.textElement_&&(this.textElement_.style.display=this.value_?"block":"none")}getValue(){return this.value_?"TRUE":"FALSE"}getValueBoolean(){return this.value_}getText(){return String(this.convertValueToBool_(this.value_))}convertValueToBool_(a){return"string"=== -typeof a?"TRUE"===a:!!a}static fromJson(a){return new this(a.checked,void 0,a)}};$.FieldCheckbox$$module$build$src$core$field_checkbox.CHECK_CHAR="\u2713";register$$module$build$src$core$field_registry("field_checkbox",$.FieldCheckbox$$module$build$src$core$field_checkbox);$.FieldCheckbox$$module$build$src$core$field_checkbox.prototype.DEFAULT_VALUE=!1;var module$build$src$core$field_checkbox={};module$build$src$core$field_checkbox.FieldCheckbox=$.FieldCheckbox$$module$build$src$core$field_checkbox;var FieldAngle$$module$build$src$core$field_angle=class extends $.FieldTextInput$$module$build$src$core$field_textinput{constructor(a,b,c){super(Field$$module$build$src$core$field.SKIP_SETUP);this.moveSurfaceWrapper_=this.clickSurfaceWrapper_=this.clickWrapper_=this.symbol_=this.line_=this.gauge_=this.editor_=null;this.SERIALIZABLE=!0;this.clockwise_=FieldAngle$$module$build$src$core$field_angle.CLOCKWISE;this.offset_=FieldAngle$$module$build$src$core$field_angle.OFFSET;this.wrap_=FieldAngle$$module$build$src$core$field_angle.WRAP; -this.round_=FieldAngle$$module$build$src$core$field_angle.ROUND;a!==Field$$module$build$src$core$field.SKIP_SETUP&&(c&&this.configure_(c),this.setValue(a),b&&this.setValidator(b))}configure_(a){super.configure_(a);switch(a.mode){case Mode$$module$build$src$core$field_angle.COMPASS:this.clockwise_=!0;this.offset_=90;break;case Mode$$module$build$src$core$field_angle.PROTRACTOR:this.clockwise_=!1,this.offset_=0}a.clockwise&&(this.clockwise_=a.clockwise);a.offset&&(this.offset_=a.offset);a.wrap&&(this.wrap_= -a.wrap);a.round&&(this.round_=a.round)}initView(){super.initView();this.symbol_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.TSPAN,{});this.symbol_.appendChild(document.createTextNode("\u00b0"));this.getTextElement().appendChild(this.symbol_)}render_(){super.render_();this.updateGraph_()}showEditor_(a){super.showEditor_(a,MOBILE$$module$build$src$core$utils$useragent||ANDROID$$module$build$src$core$utils$useragent||IPAD$$module$build$src$core$utils$useragent); -this.dropdownCreate_();getContentDiv$$module$build$src$core$dropdowndiv().appendChild(this.editor_);if(this.sourceBlock_ instanceof BlockSvg$$module$build$src$core$block_svg){if(!this.sourceBlock_.style.colourTertiary)throw Error("The renderer did not properly initialize the block style");setColour$$module$build$src$core$dropdowndiv(this.sourceBlock_.style.colourPrimary,this.sourceBlock_.style.colourTertiary)}showPositionedByField$$module$build$src$core$dropdowndiv(this,this.dropdownDispose_.bind(this)); -this.updateGraph_()}dropdownCreate_(){const a=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.SVG,{xmlns:SVG_NS$$module$build$src$core$utils$dom,"xmlns:html":HTML_NS$$module$build$src$core$utils$dom,"xmlns:xlink":XLINK_NS$$module$build$src$core$utils$dom,version:"1.1",height:2*FieldAngle$$module$build$src$core$field_angle.HALF+"px",width:2*FieldAngle$$module$build$src$core$field_angle.HALF+"px",style:"touch-action: none"}),b=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.CIRCLE, -{cx:FieldAngle$$module$build$src$core$field_angle.HALF,cy:FieldAngle$$module$build$src$core$field_angle.HALF,r:FieldAngle$$module$build$src$core$field_angle.RADIUS,"class":"blocklyAngleCircle"},a);this.gauge_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.PATH,{"class":"blocklyAngleGauge"},a);this.line_=createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{x1:FieldAngle$$module$build$src$core$field_angle.HALF,y1:FieldAngle$$module$build$src$core$field_angle.HALF, -"class":"blocklyAngleLine"},a);for(let c=0;360>c;c+=15)createSvgElement$$module$build$src$core$utils$dom(Svg$$module$build$src$core$utils$svg.LINE,{x1:FieldAngle$$module$build$src$core$field_angle.HALF+FieldAngle$$module$build$src$core$field_angle.RADIUS,y1:FieldAngle$$module$build$src$core$field_angle.HALF,x2:FieldAngle$$module$build$src$core$field_angle.HALF+FieldAngle$$module$build$src$core$field_angle.RADIUS-(0===c%45?10:5),y2:FieldAngle$$module$build$src$core$field_angle.HALF,"class":"blocklyAngleMarks", -transform:"rotate("+c+","+FieldAngle$$module$build$src$core$field_angle.HALF+","+FieldAngle$$module$build$src$core$field_angle.HALF+")"},a);this.clickWrapper_=conditionalBind$$module$build$src$core$browser_events(a,"click",this,this.hide_);this.clickSurfaceWrapper_=conditionalBind$$module$build$src$core$browser_events(b,"click",this,this.onMouseMove_,!0,!0);this.moveSurfaceWrapper_=conditionalBind$$module$build$src$core$browser_events(b,"mousemove",this,this.onMouseMove_,!0,!0);this.editor_=a}dropdownDispose_(){this.clickWrapper_&& -(unbind$$module$build$src$core$browser_events(this.clickWrapper_),this.clickWrapper_=null);this.clickSurfaceWrapper_&&(unbind$$module$build$src$core$browser_events(this.clickSurfaceWrapper_),this.clickSurfaceWrapper_=null);this.moveSurfaceWrapper_&&(unbind$$module$build$src$core$browser_events(this.moveSurfaceWrapper_),this.moveSurfaceWrapper_=null);this.line_=this.gauge_=null}hide_(){hideIfOwner$$module$build$src$core$dropdowndiv(this);hide$$module$build$src$core$widgetdiv()}onMouseMove_(a){var b= -this.gauge_.ownerSVGElement.getBoundingClientRect();const c=a.clientX-b.left-FieldAngle$$module$build$src$core$field_angle.HALF;a=a.clientY-b.top-FieldAngle$$module$build$src$core$field_angle.HALF;b=Math.atan(-a/c);isNaN(b)||(b=toDegrees$$module$build$src$core$utils$math(b),0>c?b+=180:0a&&(a+=360);a>this.wrap_&&(a-=360);return a}static fromJson(a){return new this(a.angle,void 0,a)}};FieldAngle$$module$build$src$core$field_angle.ROUND=15;FieldAngle$$module$build$src$core$field_angle.HALF=50;FieldAngle$$module$build$src$core$field_angle.CLOCKWISE=!1; -FieldAngle$$module$build$src$core$field_angle.OFFSET=0;FieldAngle$$module$build$src$core$field_angle.WRAP=360;FieldAngle$$module$build$src$core$field_angle.RADIUS=FieldAngle$$module$build$src$core$field_angle.HALF-1;register$$module$build$src$core$css("\n.blocklyAngleCircle {\n stroke: #444;\n stroke-width: 1;\n fill: #ddd;\n fill-opacity: .8;\n}\n\n.blocklyAngleMarks {\n stroke: #444;\n stroke-width: 1;\n}\n\n.blocklyAngleGauge {\n fill: #f88;\n fill-opacity: .8;\n pointer-events: none;\n}\n\n.blocklyAngleLine {\n stroke: #f00;\n stroke-width: 2;\n stroke-linecap: round;\n pointer-events: none;\n}\n"); -register$$module$build$src$core$field_registry("field_angle",FieldAngle$$module$build$src$core$field_angle);FieldAngle$$module$build$src$core$field_angle.prototype.DEFAULT_VALUE=0;var Mode$$module$build$src$core$field_angle;(function(a){a.COMPASS="compass";a.PROTRACTOR="protractor"})(Mode$$module$build$src$core$field_angle||(Mode$$module$build$src$core$field_angle={}));var module$build$src$core$field_angle={};module$build$src$core$field_angle.FieldAngle=FieldAngle$$module$build$src$core$field_angle; -module$build$src$core$field_angle.Mode=Mode$$module$build$src$core$field_angle;var BlockMove$$module$build$src$core$events$events_block_move=class extends BlockBase$$module$build$src$core$events$events_block_base{constructor(a){super(a);this.type=MOVE$$module$build$src$core$events$utils;a&&(a.isShadow()&&(this.recordUndo=!1),a=this.currentLocation_(),this.oldParentId=a.parentId,this.oldInputName=a.inputName,this.oldCoordinate=a.coordinate)}toJson(){const a=super.toJson();a.newParentId=this.newParentId;a.newInputName=this.newInputName;this.newCoordinate&&(a.newCoordinate=`${Math.round(this.newCoordinate.x)}, `+ -`${Math.round(this.newCoordinate.y)}`);this.recordUndo||(a.recordUndo=this.recordUndo);return a}fromJson(a){super.fromJson(a);this.newParentId=a.newParentId;this.newInputName=a.newInputName;if(a.newCoordinate){const b=a.newCoordinate.split(",");this.newCoordinate=new Coordinate$$module$build$src$core$utils$coordinate(Number(b[0]),Number(b[1]))}void 0!==a.recordUndo&&(this.recordUndo=a.recordUndo)}recordNew(){const a=this.currentLocation_();this.newParentId=a.parentId;this.newInputName=a.inputName; -this.newCoordinate=a.coordinate}currentLocation_(){var a=this.getEventWorkspace_();if(!this.blockId)throw Error("The block ID is undefined. Either pass a block to the constructor, or call fromJson");var b=a.getBlockById(this.blockId);if(!b)throw Error("The block associated with the block move event could not be found");a={};const c=b.getParent();if(c){if(a.parentId=c.id,b=c.getInputWithBlock(b))a.inputName=b.name}else a.coordinate=b.getRelativeToSurfaceXY();return a}isNull(){return this.oldParentId=== -this.newParentId&&this.oldInputName===this.newInputName&&Coordinate$$module$build$src$core$utils$coordinate.equals(this.oldCoordinate,this.newCoordinate)}run(a){var b=this.getEventWorkspace_();if(!this.blockId)throw Error("The block ID is undefined. Either pass a block to the constructor, or call fromJson");var c=b.getBlockById(this.blockId);if(c){var d=a?this.newParentId:this.oldParentId,e=a?this.newInputName:this.oldInputName;a=a?this.newCoordinate:this.oldCoordinate;if(d){var f=b.getBlockById(d); -if(!f){console.warn("Can't connect to non-existent block: "+d);return}}c.getParent()&&c.unplug();if(a)e=c.getRelativeToSurfaceXY(),c.moveBy(a.x-e.x,a.y-e.y);else{b=c.outputConnection;if(!b||c.previousConnection&&c.previousConnection.isConnected())b=c.previousConnection;let g;c=b.type;if(e){if(c=f.getInput(e))g=c.connection}else c===ConnectionType$$module$build$src$core$connection_type.PREVIOUS_STATEMENT&&(g=f.nextConnection);g?b.connect(g):console.warn("Can't connect to non-existent input: "+e)}}else console.warn("Can't move non-existent block: "+ -this.blockId)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,MOVE$$module$build$src$core$events$utils,BlockMove$$module$build$src$core$events$events_block_move);var module$build$src$core$events$events_block_move={};module$build$src$core$events$events_block_move.BlockMove=BlockMove$$module$build$src$core$events$events_block_move;var CommentBase$$module$build$src$core$events$events_comment_base=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.isBlank=!a;a&&(this.commentId=a.id,this.workspaceId=a.workspace.id,this.group=getGroup$$module$build$src$core$events$utils(),this.recordUndo=getRecordUndo$$module$build$src$core$events$utils())}toJson(){const a=super.toJson();if(!this.commentId)throw Error("The comment ID is undefined. Either pass a comment to the constructor, or call fromJson"); -a.commentId=this.commentId;return a}fromJson(a){super.fromJson(a);this.commentId=a.commentId}static CommentCreateDeleteHelper(a,b){var c=a.getEventWorkspace_();if(b){b=createElement$$module$build$src$core$utils$xml("xml");if(!a.xml)throw Error("Ecountered a comment event without proper xml");b.appendChild(a.xml);domToWorkspace$$module$build$src$core$xml(b,c)}else{if(!a.commentId)throw Error("The comment ID is undefined. Either pass a comment to the constructor, or call fromJson");(c=c.getCommentById(a.commentId))? -c.dispose():console.warn("Can't uncreate non-existent comment: "+a.commentId)}}},module$build$src$core$events$events_comment_base={};module$build$src$core$events$events_comment_base.CommentBase=CommentBase$$module$build$src$core$events$events_comment_base;var CommentChange$$module$build$src$core$events$events_comment_change=class extends CommentBase$$module$build$src$core$events$events_comment_base{constructor(a,b,c){super(a);this.type=COMMENT_CHANGE$$module$build$src$core$events$utils;a&&(this.oldContents_="undefined"===typeof b?"":b,this.newContents_="undefined"===typeof c?"":c)}toJson(){const a=super.toJson();if(!this.oldContents_)throw Error("The old contents is undefined. Either pass a value to the constructor, or call fromJson");if(!this.newContents_)throw Error("The new contents is undefined. Either pass a value to the constructor, or call fromJson"); -a.oldContents=this.oldContents_;a.newContents=this.newContents_;return a}fromJson(a){super.fromJson(a);this.oldContents_=a.oldContents;this.newContents_=a.newContents}isNull(){return this.oldContents_===this.newContents_}run(a){var b=this.getEventWorkspace_();if(!this.commentId)throw Error("The comment ID is undefined. Either pass a comment to the constructor, or call fromJson");if(b=b.getCommentById(this.commentId)){var c=a?this.newContents_:this.oldContents_;if(!c){if(a)throw Error("The new contents is undefined. Either pass a value to the constructor, or call fromJson"); -throw Error("The old contents is undefined. Either pass a value to the constructor, or call fromJson");}b.setContent(c)}else console.warn("Can't change non-existent comment: "+this.commentId)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,COMMENT_CHANGE$$module$build$src$core$events$utils,CommentChange$$module$build$src$core$events$events_comment_change);var module$build$src$core$events$events_comment_change={}; -module$build$src$core$events$events_comment_change.CommentChange=CommentChange$$module$build$src$core$events$events_comment_change;var CommentCreate$$module$build$src$core$events$events_comment_create=class extends CommentBase$$module$build$src$core$events$events_comment_base{constructor(a){super(a);this.type=COMMENT_CREATE$$module$build$src$core$events$utils;a&&(this.xml=a.toXmlWithXY())}toJson(){const a=super.toJson();if(!this.xml)throw Error("The comment XML is undefined. Either pass a comment to the constructor, or call fromJson");a.xml=domToText$$module$build$src$core$xml(this.xml);return a}fromJson(a){super.fromJson(a); -this.xml=textToDom$$module$build$src$core$xml(a.xml)}run(a){CommentBase$$module$build$src$core$events$events_comment_base.CommentCreateDeleteHelper(this,a)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,COMMENT_CREATE$$module$build$src$core$events$utils,CommentCreate$$module$build$src$core$events$events_comment_create);var module$build$src$core$events$events_comment_create={};module$build$src$core$events$events_comment_create.CommentCreate=CommentCreate$$module$build$src$core$events$events_comment_create;var CommentDelete$$module$build$src$core$events$events_comment_delete=class extends CommentBase$$module$build$src$core$events$events_comment_base{constructor(a){super(a);this.type=COMMENT_DELETE$$module$build$src$core$events$utils;a&&(this.xml=a.toXmlWithXY())}run(a){CommentBase$$module$build$src$core$events$events_comment_base.CommentCreateDeleteHelper(this,!a)}}; -register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,COMMENT_DELETE$$module$build$src$core$events$utils,CommentDelete$$module$build$src$core$events$events_comment_delete);var module$build$src$core$events$events_comment_delete={};module$build$src$core$events$events_comment_delete.CommentDelete=CommentDelete$$module$build$src$core$events$events_comment_delete;var CommentMove$$module$build$src$core$events$events_comment_move=class extends CommentBase$$module$build$src$core$events$events_comment_base{constructor(a){super(a);this.type=COMMENT_MOVE$$module$build$src$core$events$utils;a&&(this.comment_=a,this.oldCoordinate_=a.getXY())}recordNew(){if(this.newCoordinate_)throw Error("Tried to record the new position of a comment on the same event twice.");if(!this.comment_)throw Error("The comment is undefined. Pass a comment to the constructor if you want to use the record functionality"); -this.newCoordinate_=this.comment_.getXY()}setOldCoordinate(a){this.oldCoordinate_=a}toJson(){const a=super.toJson();if(!this.oldCoordinate_)throw Error("The old comment position is undefined. Either pass a comment to the constructor, or call fromJson");if(!this.newCoordinate_)throw Error("The new comment position is undefined. Either call recordNew, or call fromJson");a.oldCoordinate=`${Math.round(this.oldCoordinate_.x)}, `+`${Math.round(this.oldCoordinate_.y)}`;a.newCoordinate=Math.round(this.newCoordinate_.x)+ -","+Math.round(this.newCoordinate_.y);return a}fromJson(a){super.fromJson(a);let b=a.oldCoordinate.split(",");this.oldCoordinate_=new Coordinate$$module$build$src$core$utils$coordinate(Number(b[0]),Number(b[1]));b=a.newCoordinate.split(",");this.newCoordinate_=new Coordinate$$module$build$src$core$utils$coordinate(Number(b[0]),Number(b[1]))}isNull(){return Coordinate$$module$build$src$core$utils$coordinate.equals(this.oldCoordinate_,this.newCoordinate_)}run(a){var b=this.getEventWorkspace_();if(!this.commentId)throw Error("The comment ID is undefined. Either pass a comment to the constructor, or call fromJson"); -if(b=b.getCommentById(this.commentId)){a=a?this.newCoordinate_:this.oldCoordinate_;if(!a)throw Error("Either oldCoordinate_ or newCoordinate_ is undefined. Either pass a comment to the constructor and call recordNew, or call fromJson");var c=b.getXY();b.moveBy(a.x-c.x,a.y-c.y)}else console.warn("Can't move non-existent comment: "+this.commentId)}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,COMMENT_MOVE$$module$build$src$core$events$utils,CommentMove$$module$build$src$core$events$events_comment_move); -var module$build$src$core$events$events_comment_move={};module$build$src$core$events$events_comment_move.CommentMove=CommentMove$$module$build$src$core$events$events_comment_move;var BlockDrag$$module$build$src$core$events$events_block_drag=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c){super(a?a.workspace.id:void 0);this.type=BLOCK_DRAG$$module$build$src$core$events$utils;a&&(this.blockId=a.id,this.isStart=b,this.blocks=c)}toJson(){const a=super.toJson();if(void 0===this.isStart)throw Error("Whether this event is the start of a drag is undefined. Either pass the value to the constructor, or call fromJson");if(void 0===this.blockId)throw Error("The block ID is undefined. Either pass a block to the constructor, or call fromJson"); -a.isStart=this.isStart;a.blockId=this.blockId;a.blocks=this.blocks;return a}fromJson(a){super.fromJson(a);this.isStart=a.isStart;this.blockId=a.blockId;this.blocks=a.blocks}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,BLOCK_DRAG$$module$build$src$core$events$utils,BlockDrag$$module$build$src$core$events$events_block_drag);var module$build$src$core$events$events_block_drag={};module$build$src$core$events$events_block_drag.BlockDrag=BlockDrag$$module$build$src$core$events$events_block_drag;var Ui$$module$build$src$core$events$events_ui=class extends UiBase$$module$build$src$core$events$events_ui_base{constructor(a,b,c,d){super(a?a.workspace.id:void 0);this.type=UI$$module$build$src$core$events$utils;this.blockId=a?a.id:null;this.element="undefined"===typeof b?"":b;this.oldValue="undefined"===typeof c?"":c;this.newValue="undefined"===typeof d?"":d}toJson(){const a=super.toJson();a.element=this.element;void 0!==this.newValue&&(a.newValue=this.newValue);this.blockId&&(a.blockId=this.blockId); -return a}fromJson(a){super.fromJson(a);this.element=a.element;this.newValue=a.newValue;this.blockId=a.blockId}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,UI$$module$build$src$core$events$utils,Ui$$module$build$src$core$events$events_ui);var module$build$src$core$events$events_ui={};module$build$src$core$events$events_ui.Ui=Ui$$module$build$src$core$events$events_ui;var FinishedLoading$$module$build$src$core$events$workspace_events=class extends Abstract$$module$build$src$core$events$events_abstract{constructor(a){super();this.isBlank=!0;this.recordUndo=!1;this.type=FINISHED_LOADING$$module$build$src$core$events$utils;this.isBlank=!!a;a&&(this.workspaceId=a.id)}toJson(){const a=super.toJson();if(!this.workspaceId)throw Error("The workspace ID is undefined. Either pass a workspace to the constructor, or call fromJson");a.workspaceId=this.workspaceId;return a}fromJson(a){super.fromJson(a); -this.workspaceId=a.workspaceId}};register$$module$build$src$core$registry(Type$$module$build$src$core$registry.EVENT,FINISHED_LOADING$$module$build$src$core$events$utils,FinishedLoading$$module$build$src$core$events$workspace_events);var module$build$src$core$events$workspace_events={};module$build$src$core$events$workspace_events.FinishedLoading=FinishedLoading$$module$build$src$core$events$workspace_events;var Abstract$$module$build$src$core$events$events,BLOCK_CHANGE$$module$build$src$core$events$events,BLOCK_CREATE$$module$build$src$core$events$events,BLOCK_DELETE$$module$build$src$core$events$events,BLOCK_DRAG$$module$build$src$core$events$events,BLOCK_MOVE$$module$build$src$core$events$events,BUBBLE_OPEN$$module$build$src$core$events$events,BUMP_EVENTS$$module$build$src$core$events$events,CHANGE$$module$build$src$core$events$events,CLICK$$module$build$src$core$events$events,COMMENT_CHANGE$$module$build$src$core$events$events, -COMMENT_CREATE$$module$build$src$core$events$events,COMMENT_DELETE$$module$build$src$core$events$events,COMMENT_MOVE$$module$build$src$core$events$events,CREATE$$module$build$src$core$events$events,DELETE$$module$build$src$core$events$events,FINISHED_LOADING$$module$build$src$core$events$events,MARKER_MOVE$$module$build$src$core$events$events,MOVE$$module$build$src$core$events$events,SELECTED$$module$build$src$core$events$events,THEME_CHANGE$$module$build$src$core$events$events,TOOLBOX_ITEM_SELECT$$module$build$src$core$events$events, -TRASHCAN_OPEN$$module$build$src$core$events$events,UI$$module$build$src$core$events$events,VAR_CREATE$$module$build$src$core$events$events,VAR_DELETE$$module$build$src$core$events$events,VAR_RENAME$$module$build$src$core$events$events,VIEWPORT_CHANGE$$module$build$src$core$events$events,clearPendingUndo$$module$build$src$core$events$events,disable$$module$build$src$core$events$events,enable$$module$build$src$core$events$events,filter$$module$build$src$core$events$events,fire$$module$build$src$core$events$events, -fromJson$$module$build$src$core$events$events,getDescendantIds$$module$build$src$core$events$events,get$$module$build$src$core$events$events,getGroup$$module$build$src$core$events$events,getRecordUndo$$module$build$src$core$events$events,isEnabled$$module$build$src$core$events$events,setGroup$$module$build$src$core$events$events,setRecordUndo$$module$build$src$core$events$events,disableOrphans$$module$build$src$core$events$events;Abstract$$module$build$src$core$events$events=Abstract$$module$build$src$core$events$events_abstract; -BLOCK_CHANGE$$module$build$src$core$events$events=CHANGE$$module$build$src$core$events$utils;BLOCK_CREATE$$module$build$src$core$events$events=CREATE$$module$build$src$core$events$utils;BLOCK_DELETE$$module$build$src$core$events$events=DELETE$$module$build$src$core$events$utils;BLOCK_DRAG$$module$build$src$core$events$events=BLOCK_DRAG$$module$build$src$core$events$utils;BLOCK_MOVE$$module$build$src$core$events$events=MOVE$$module$build$src$core$events$utils; -BUBBLE_OPEN$$module$build$src$core$events$events=BUBBLE_OPEN$$module$build$src$core$events$utils;BUMP_EVENTS$$module$build$src$core$events$events=BUMP_EVENTS$$module$build$src$core$events$utils;CHANGE$$module$build$src$core$events$events=CHANGE$$module$build$src$core$events$utils;CLICK$$module$build$src$core$events$events=CLICK$$module$build$src$core$events$utils;COMMENT_CHANGE$$module$build$src$core$events$events=COMMENT_CHANGE$$module$build$src$core$events$utils; -COMMENT_CREATE$$module$build$src$core$events$events=COMMENT_CREATE$$module$build$src$core$events$utils;COMMENT_DELETE$$module$build$src$core$events$events=COMMENT_DELETE$$module$build$src$core$events$utils;COMMENT_MOVE$$module$build$src$core$events$events=COMMENT_MOVE$$module$build$src$core$events$utils;CREATE$$module$build$src$core$events$events=CREATE$$module$build$src$core$events$utils;DELETE$$module$build$src$core$events$events=DELETE$$module$build$src$core$events$utils; -FINISHED_LOADING$$module$build$src$core$events$events=FINISHED_LOADING$$module$build$src$core$events$utils;MARKER_MOVE$$module$build$src$core$events$events=MARKER_MOVE$$module$build$src$core$events$utils;MOVE$$module$build$src$core$events$events=MOVE$$module$build$src$core$events$utils;SELECTED$$module$build$src$core$events$events=SELECTED$$module$build$src$core$events$utils;THEME_CHANGE$$module$build$src$core$events$events=THEME_CHANGE$$module$build$src$core$events$utils; -TOOLBOX_ITEM_SELECT$$module$build$src$core$events$events=TOOLBOX_ITEM_SELECT$$module$build$src$core$events$utils;TRASHCAN_OPEN$$module$build$src$core$events$events=TRASHCAN_OPEN$$module$build$src$core$events$utils;UI$$module$build$src$core$events$events=UI$$module$build$src$core$events$utils;VAR_CREATE$$module$build$src$core$events$events=VAR_CREATE$$module$build$src$core$events$utils;VAR_DELETE$$module$build$src$core$events$events=VAR_DELETE$$module$build$src$core$events$utils; -VAR_RENAME$$module$build$src$core$events$events=VAR_RENAME$$module$build$src$core$events$utils;VIEWPORT_CHANGE$$module$build$src$core$events$events=VIEWPORT_CHANGE$$module$build$src$core$events$utils;clearPendingUndo$$module$build$src$core$events$events=clearPendingUndo$$module$build$src$core$events$utils;disable$$module$build$src$core$events$events=disable$$module$build$src$core$events$utils;enable$$module$build$src$core$events$events=enable$$module$build$src$core$events$utils; -filter$$module$build$src$core$events$events=filter$$module$build$src$core$events$utils;fire$$module$build$src$core$events$events=fire$$module$build$src$core$events$utils;fromJson$$module$build$src$core$events$events=fromJson$$module$build$src$core$events$utils;getDescendantIds$$module$build$src$core$events$events=getDescendantIds$$module$build$src$core$events$utils;get$$module$build$src$core$events$events=get$$module$build$src$core$events$utils;getGroup$$module$build$src$core$events$events=getGroup$$module$build$src$core$events$utils; -getRecordUndo$$module$build$src$core$events$events=getRecordUndo$$module$build$src$core$events$utils;isEnabled$$module$build$src$core$events$events=isEnabled$$module$build$src$core$events$utils;setGroup$$module$build$src$core$events$events=setGroup$$module$build$src$core$events$utils;setRecordUndo$$module$build$src$core$events$events=setRecordUndo$$module$build$src$core$events$utils;disableOrphans$$module$build$src$core$events$events=disableOrphans$$module$build$src$core$events$utils; -$.module$build$src$core$events$events={};$.module$build$src$core$events$events.Abstract=Abstract$$module$build$src$core$events$events_abstract;$.module$build$src$core$events$events.BLOCK_CHANGE=CHANGE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.BLOCK_CREATE=CREATE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.BLOCK_DELETE=DELETE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.BLOCK_DRAG=BLOCK_DRAG$$module$build$src$core$events$utils; -$.module$build$src$core$events$events.BLOCK_MOVE=MOVE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.BUBBLE_OPEN=BUBBLE_OPEN$$module$build$src$core$events$utils;$.module$build$src$core$events$events.BUMP_EVENTS=BUMP_EVENTS$$module$build$src$core$events$utils;$.module$build$src$core$events$events.BlockBase=BlockBase$$module$build$src$core$events$events_block_base;$.module$build$src$core$events$events.BlockChange=BlockChange$$module$build$src$core$events$events_block_change; -$.module$build$src$core$events$events.BlockCreate=BlockCreate$$module$build$src$core$events$events_block_create;$.module$build$src$core$events$events.BlockDelete=BlockDelete$$module$build$src$core$events$events_block_delete;$.module$build$src$core$events$events.BlockDrag=BlockDrag$$module$build$src$core$events$events_block_drag;$.module$build$src$core$events$events.BlockMove=BlockMove$$module$build$src$core$events$events_block_move;$.module$build$src$core$events$events.BubbleOpen=BubbleOpen$$module$build$src$core$events$events_bubble_open; -$.module$build$src$core$events$events.BubbleType=BubbleType$$module$build$src$core$events$events_bubble_open;$.module$build$src$core$events$events.CHANGE=CHANGE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.CLICK=CLICK$$module$build$src$core$events$utils;$.module$build$src$core$events$events.COMMENT_CHANGE=COMMENT_CHANGE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.COMMENT_CREATE=COMMENT_CREATE$$module$build$src$core$events$utils; -$.module$build$src$core$events$events.COMMENT_DELETE=COMMENT_DELETE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.COMMENT_MOVE=COMMENT_MOVE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.CREATE=CREATE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.Click=Click$$module$build$src$core$events$events_click;$.module$build$src$core$events$events.ClickTarget=ClickTarget$$module$build$src$core$events$events_click; -$.module$build$src$core$events$events.CommentBase=CommentBase$$module$build$src$core$events$events_comment_base;$.module$build$src$core$events$events.CommentChange=CommentChange$$module$build$src$core$events$events_comment_change;$.module$build$src$core$events$events.CommentCreate=CommentCreate$$module$build$src$core$events$events_comment_create;$.module$build$src$core$events$events.CommentDelete=CommentDelete$$module$build$src$core$events$events_comment_delete; -$.module$build$src$core$events$events.CommentMove=CommentMove$$module$build$src$core$events$events_comment_move;$.module$build$src$core$events$events.DELETE=DELETE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.FINISHED_LOADING=FINISHED_LOADING$$module$build$src$core$events$utils;$.module$build$src$core$events$events.FinishedLoading=FinishedLoading$$module$build$src$core$events$workspace_events;$.module$build$src$core$events$events.MARKER_MOVE=MARKER_MOVE$$module$build$src$core$events$utils; -$.module$build$src$core$events$events.MOVE=MOVE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.MarkerMove=MarkerMove$$module$build$src$core$events$events_marker_move;$.module$build$src$core$events$events.SELECTED=SELECTED$$module$build$src$core$events$utils;$.module$build$src$core$events$events.Selected=Selected$$module$build$src$core$events$events_selected;$.module$build$src$core$events$events.THEME_CHANGE=THEME_CHANGE$$module$build$src$core$events$utils; -$.module$build$src$core$events$events.TOOLBOX_ITEM_SELECT=TOOLBOX_ITEM_SELECT$$module$build$src$core$events$utils;$.module$build$src$core$events$events.TRASHCAN_OPEN=TRASHCAN_OPEN$$module$build$src$core$events$utils;$.module$build$src$core$events$events.ThemeChange=ThemeChange$$module$build$src$core$events$events_theme_change;$.module$build$src$core$events$events.ToolboxItemSelect=ToolboxItemSelect$$module$build$src$core$events$events_toolbox_item_select; -$.module$build$src$core$events$events.TrashcanOpen=TrashcanOpen$$module$build$src$core$events$events_trashcan_open;$.module$build$src$core$events$events.UI=UI$$module$build$src$core$events$utils;$.module$build$src$core$events$events.Ui=Ui$$module$build$src$core$events$events_ui;$.module$build$src$core$events$events.UiBase=UiBase$$module$build$src$core$events$events_ui_base;$.module$build$src$core$events$events.VAR_CREATE=VAR_CREATE$$module$build$src$core$events$utils; -$.module$build$src$core$events$events.VAR_DELETE=VAR_DELETE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.VAR_RENAME=VAR_RENAME$$module$build$src$core$events$utils;$.module$build$src$core$events$events.VIEWPORT_CHANGE=VIEWPORT_CHANGE$$module$build$src$core$events$utils;$.module$build$src$core$events$events.VarBase=VarBase$$module$build$src$core$events$events_var_base;$.module$build$src$core$events$events.VarCreate=VarCreate$$module$build$src$core$events$events_var_create; -$.module$build$src$core$events$events.VarDelete=VarDelete$$module$build$src$core$events$events_var_delete;$.module$build$src$core$events$events.VarRename=VarRename$$module$build$src$core$events$events_var_rename;$.module$build$src$core$events$events.ViewportChange=ViewportChange$$module$build$src$core$events$events_viewport;$.module$build$src$core$events$events.clearPendingUndo=clearPendingUndo$$module$build$src$core$events$utils;$.module$build$src$core$events$events.disable=disable$$module$build$src$core$events$utils; -$.module$build$src$core$events$events.disableOrphans=disableOrphans$$module$build$src$core$events$utils;$.module$build$src$core$events$events.enable=enable$$module$build$src$core$events$utils;$.module$build$src$core$events$events.filter=filter$$module$build$src$core$events$utils;$.module$build$src$core$events$events.fire=fire$$module$build$src$core$events$utils;$.module$build$src$core$events$events.fromJson=fromJson$$module$build$src$core$events$utils;$.module$build$src$core$events$events.get=get$$module$build$src$core$events$utils; -$.module$build$src$core$events$events.getDescendantIds=getDescendantIds$$module$build$src$core$events$utils;$.module$build$src$core$events$events.getGroup=getGroup$$module$build$src$core$events$utils;$.module$build$src$core$events$events.getRecordUndo=getRecordUndo$$module$build$src$core$events$utils;$.module$build$src$core$events$events.isEnabled=isEnabled$$module$build$src$core$events$utils;$.module$build$src$core$events$events.setGroup=setGroup$$module$build$src$core$events$utils; -$.module$build$src$core$events$events.setRecordUndo=setRecordUndo$$module$build$src$core$events$utils;registerDefaultOptions$$module$build$src$core$contextmenu_items();var module$build$src$core$contextmenu_items={};module$build$src$core$contextmenu_items.registerCleanup=registerCleanup$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerCollapse=registerCollapse$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerCollapseExpandBlock=registerCollapseExpandBlock$$module$build$src$core$contextmenu_items; -module$build$src$core$contextmenu_items.registerComment=registerComment$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerDefaultOptions=registerDefaultOptions$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerDelete=registerDelete$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerDeleteAll=registerDeleteAll$$module$build$src$core$contextmenu_items; -module$build$src$core$contextmenu_items.registerDisable=registerDisable$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerDuplicate=registerDuplicate$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerExpand=registerExpand$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerHelp=registerHelp$$module$build$src$core$contextmenu_items; -module$build$src$core$contextmenu_items.registerInline=registerInline$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerRedo=registerRedo$$module$build$src$core$contextmenu_items;module$build$src$core$contextmenu_items.registerUndo=registerUndo$$module$build$src$core$contextmenu_items;var BlockDragger$$module$build$src$core$block_dragger=class{constructor(a,b){this.dragTarget_=null;this.wouldDeleteBlock_=!1;this.draggingBlock_=a;this.draggedConnectionManager_=new InsertionMarkerManager$$module$build$src$core$insertion_marker_manager(this.draggingBlock_);this.workspace_=b;this.startXY_=this.draggingBlock_.getRelativeToSurfaceXY();this.dragIconData_=initIconData$$module$build$src$core$block_dragger(a)}dispose(){this.dragIconData_.length=0;this.draggedConnectionManager_&&this.draggedConnectionManager_.dispose()}startDrag(a, -b){getGroup$$module$build$src$core$events$utils()||setGroup$$module$build$src$core$events$utils(!0);this.fireDragStartEvent_();this.workspace_.isMutator&&this.draggingBlock_.bringToFront();startTextWidthCache$$module$build$src$core$utils$dom();this.workspace_.setResizesEnabled(!1);disconnectUiStop$$module$build$src$core$block_animations();this.shouldDisconnect_(b)&&this.disconnectBlock_(b,a);this.draggingBlock_.setDragging(!0);this.draggingBlock_.moveToDragSurface()}shouldDisconnect_(a){return!!(this.draggingBlock_.getParent()|| -a&&this.draggingBlock_.nextConnection&&this.draggingBlock_.nextConnection.targetBlock())}disconnectBlock_(a,b){this.draggingBlock_.unplug(a);a=this.pixelsToWorkspaceUnits_(b);a=Coordinate$$module$build$src$core$utils$coordinate.sum(this.startXY_,a);this.draggingBlock_.translate(a.x,a.y);disconnectUiEffect$$module$build$src$core$block_animations(this.draggingBlock_);this.draggedConnectionManager_.updateAvailableConnections()}fireDragStartEvent_(){const a=new (get$$module$build$src$core$events$utils(BLOCK_DRAG$$module$build$src$core$events$utils))(this.draggingBlock_, -!0,this.draggingBlock_.getDescendants(!1));fire$$module$build$src$core$events$utils(a)}drag(a,b){b=this.pixelsToWorkspaceUnits_(b);var c=Coordinate$$module$build$src$core$utils$coordinate.sum(this.startXY_,b);this.draggingBlock_.moveDuringDrag(c);this.dragIcons_(b);c=this.dragTarget_;this.dragTarget_=this.workspace_.getDragTarget(a);this.draggedConnectionManager_.update(b,this.dragTarget_);a=this.wouldDeleteBlock_;this.wouldDeleteBlock_=this.draggedConnectionManager_.wouldDeleteBlock();a!==this.wouldDeleteBlock_&& -this.updateCursorDuringBlockDrag_();this.dragTarget_!==c&&(c&&c.onDragExit(this.draggingBlock_),this.dragTarget_&&this.dragTarget_.onDragEnter(this.draggingBlock_));this.dragTarget_&&this.dragTarget_.onDragOver(this.draggingBlock_)}endDrag(a,b){this.drag(a,b);this.dragIconData_=[];this.fireDragEndEvent_();stopTextWidthCache$$module$build$src$core$utils$dom();disconnectUiStop$$module$build$src$core$block_animations();a=null;this.dragTarget_&&this.dragTarget_.shouldPreventMove(this.draggingBlock_)? -b=this.startXY_:(b=this.getNewLocationAfterDrag_(b),a=b.delta,b=b.newLocation);this.draggingBlock_.moveOffDragSurface(b);if(this.dragTarget_)this.dragTarget_.onDrop(this.draggingBlock_);this.maybeDeleteBlock_()||(this.draggingBlock_.setDragging(!1),a?this.updateBlockAfterMove_(a):bumpObjectIntoBounds$$module$build$src$core$bump_objects(this.draggingBlock_.workspace,this.workspace_.getMetricsManager().getScrollMetrics(!0),this.draggingBlock_));this.workspace_.setResizesEnabled(!0);setGroup$$module$build$src$core$events$utils(!1)}getNewLocationAfterDrag_(a){a= -this.pixelsToWorkspaceUnits_(a);const b=Coordinate$$module$build$src$core$utils$coordinate.sum(this.startXY_,a);return{delta:a,newLocation:b}}maybeDeleteBlock_(){return this.wouldDeleteBlock_?(this.fireMoveEvent_(),this.draggingBlock_.dispose(!1,!0),draggingConnections$$module$build$src$core$common.length=0,!0):!1}updateBlockAfterMove_(a){this.draggingBlock_.moveConnections(a.x,a.y);this.fireMoveEvent_();this.draggedConnectionManager_.wouldConnectBlock()?this.draggedConnectionManager_.applyConnections(): -this.draggingBlock_.render();this.draggingBlock_.scheduleSnapAndBump()}fireDragEndEvent_(){const a=new (get$$module$build$src$core$events$utils(BLOCK_DRAG$$module$build$src$core$events$utils))(this.draggingBlock_,!1,this.draggingBlock_.getDescendants(!1));fire$$module$build$src$core$events$utils(a)}updateToolboxStyle_(a){const b=this.workspace_.getToolbox();if(b){const c=this.draggingBlock_.isDeletable()?"blocklyToolboxDelete":"blocklyToolboxGrab";a&&"function"===typeof b.removeStyle?b.removeStyle(c): -a||"function"!==typeof b.addStyle||b.addStyle(c)}}fireMoveEvent_(){const a=new (get$$module$build$src$core$events$utils(MOVE$$module$build$src$core$events$utils))(this.draggingBlock_);a.oldCoordinate=this.startXY_;a.recordNew();fire$$module$build$src$core$events$utils(a)}updateCursorDuringBlockDrag_(){this.draggingBlock_.setDeleteStyle(this.wouldDeleteBlock_)}pixelsToWorkspaceUnits_(a){a=new Coordinate$$module$build$src$core$utils$coordinate(a.x/this.workspace_.scale,a.y/this.workspace_.scale);this.workspace_.isMutator&& -a.scale(1/this.workspace_.options.parentWorkspace.scale);return a}dragIcons_(a){for(let b=0;b void;\n preventDefault: () => void;\n}\n\n/** Length in ms for a touch to become a long press. */\nconst LONGPRESS = 750;\n\n/**\n * Whether touch is enabled in the browser.\n * Copied from Closure's goog.events.BrowserFeature.TOUCH_ENABLED\n */\nexport const TOUCH_ENABLED = 'ontouchstart' in globalThis ||\n !!(globalThis['document'] && document.documentElement &&\n 'ontouchstart' in\n document.documentElement) || // IE10 uses non-standard touch events,\n // so it has a different check.\n !!(globalThis['navigator'] &&\n (globalThis['navigator']['maxTouchPoints'] ||\n (globalThis['navigator'] as any)['msMaxTouchPoints']));\n\n/** Which touch events are we currently paying attention to? */\nlet touchIdentifier_: string|null = null;\n\n/**\n * The TOUCH_MAP lookup dictionary specifies additional touch events to fire,\n * in conjunction with mouse events.\n *\n * @alias Blockly.Touch.TOUCH_MAP\n */\nexport const TOUCH_MAP: {[key: string]: string[]} = globalThis['PointerEvent'] ?\n {\n 'mousedown': ['pointerdown'],\n 'mouseenter': ['pointerenter'],\n 'mouseleave': ['pointerleave'],\n 'mousemove': ['pointermove'],\n 'mouseout': ['pointerout'],\n 'mouseover': ['pointerover'],\n 'mouseup': ['pointerup', 'pointercancel'],\n 'touchend': ['pointerup'],\n 'touchcancel': ['pointercancel'],\n } :\n {\n 'mousedown': ['touchstart'],\n 'mousemove': ['touchmove'],\n 'mouseup': ['touchend', 'touchcancel'],\n };\n\n/** PID of queued long-press task. */\nlet longPid_: AnyDuringMigration = 0;\n\n/**\n * Context menus on touch devices are activated using a long-press.\n * Unfortunately the contextmenu touch event is currently (2015) only supported\n * by Chrome. This function is fired on any touchstart event, queues a task,\n * which after about a second opens the context menu. The tasks is killed\n * if the touch event terminates early.\n *\n * @param e Touch start event.\n * @param gesture The gesture that triggered this longStart.\n * @alias Blockly.Touch.longStart\n * @internal\n */\nexport function longStart(e: Event, gesture: Gesture) {\n longStop();\n // Punt on multitouch events.\n // AnyDuringMigration because: Property 'changedTouches' does not exist on\n // type 'Event'.\n if ((e as AnyDuringMigration).changedTouches &&\n (e as AnyDuringMigration).changedTouches.length !== 1) {\n return;\n }\n longPid_ = setTimeout(function() {\n // TODO(#6097): Make types accurate, possibly by refactoring touch handling.\n // AnyDuringMigration because: Property 'changedTouches' does not exist on\n // type 'Event'.\n const typelessEvent = e as AnyDuringMigration;\n // Additional check to distinguish between touch events and pointer events\n if (typelessEvent.changedTouches) {\n // TouchEvent\n typelessEvent.button = 2; // Simulate a right button click.\n // e was a touch event. It needs to pretend to be a mouse event.\n typelessEvent.clientX = typelessEvent.changedTouches[0].clientX;\n typelessEvent.clientY = typelessEvent.changedTouches[0].clientY;\n }\n\n // Let the gesture route the right-click correctly.\n if (gesture) {\n gesture.handleRightClick(e);\n }\n }, LONGPRESS);\n}\n\n/**\n * Nope, that's not a long-press. Either touchend or touchcancel was fired,\n * or a drag hath begun. Kill the queued long-press task.\n *\n * @alias Blockly.Touch.longStop\n * @internal\n */\nexport function longStop() {\n if (longPid_) {\n clearTimeout(longPid_);\n longPid_ = 0;\n }\n}\n\n/**\n * Clear the touch identifier that tracks which touch stream to pay attention\n * to. This ends the current drag/gesture and allows other pointers to be\n * captured.\n *\n * @alias Blockly.Touch.clearTouchIdentifier\n */\nexport function clearTouchIdentifier() {\n touchIdentifier_ = null;\n}\n\n/**\n * Decide whether Blockly should handle or ignore this event.\n * Mouse and touch events require special checks because we only want to deal\n * with one touch stream at a time. All other events should always be handled.\n *\n * @param e The event to check.\n * @returns True if this event should be passed through to the registered\n * handler; false if it should be blocked.\n * @alias Blockly.Touch.shouldHandleEvent\n */\nexport function shouldHandleEvent(e: Event|PseudoEvent): boolean {\n return !isMouseOrTouchEvent(e) || checkTouchIdentifier(e);\n}\n\n/**\n * Get the touch identifier from the given event. If it was a mouse event, the\n * identifier is the string 'mouse'.\n *\n * @param e Pointer event, mouse event, or touch event.\n * @returns The pointerId, or touch identifier from the first changed touch, if\n * defined. Otherwise 'mouse'.\n * @alias Blockly.Touch.getTouchIdentifierFromEvent\n */\nexport function getTouchIdentifierFromEvent(e: Event|PseudoEvent): string {\n if (e instanceof PointerEvent) {\n return String(e.pointerId);\n }\n\n if (e instanceof MouseEvent) {\n return 'mouse';\n }\n\n /**\n * TODO(#6097): Fix types. This is a catch-all for everything but mouse\n * and pointer events.\n */\n const pseudoEvent = /** {!PseudoEvent} */ e;\n\n // AnyDuringMigration because: Property 'changedTouches' does not exist on\n // type 'PseudoEvent | Event'. AnyDuringMigration because: Property\n // 'changedTouches' does not exist on type 'PseudoEvent | Event'.\n // AnyDuringMigration because: Property 'changedTouches' does not exist on\n // type 'PseudoEvent | Event'. AnyDuringMigration because: Property\n // 'changedTouches' does not exist on type 'PseudoEvent | Event'.\n // AnyDuringMigration because: Property 'changedTouches' does not exist on\n // type 'PseudoEvent | Event'.\n return (pseudoEvent as AnyDuringMigration).changedTouches &&\n (pseudoEvent as AnyDuringMigration).changedTouches[0] &&\n (pseudoEvent as AnyDuringMigration).changedTouches[0].identifier !==\n undefined &&\n (pseudoEvent as AnyDuringMigration).changedTouches[0].identifier !==\n null ?\n String((pseudoEvent as AnyDuringMigration).changedTouches[0].identifier) :\n 'mouse';\n}\n\n/**\n * Check whether the touch identifier on the event matches the current saved\n * identifier. If there is no identifier, that means it's a mouse event and\n * we'll use the identifier \"mouse\". This means we won't deal well with\n * multiple mice being used at the same time. That seems okay.\n * If the current identifier was unset, save the identifier from the\n * event. This starts a drag/gesture, during which touch events with other\n * identifiers will be silently ignored.\n *\n * @param e Mouse event or touch event.\n * @returns Whether the identifier on the event matches the current saved\n * identifier.\n * @alias Blockly.Touch.checkTouchIdentifier\n */\nexport function checkTouchIdentifier(e: Event|PseudoEvent): boolean {\n const identifier = getTouchIdentifierFromEvent(e);\n\n // if (touchIdentifier_) is insufficient because Android touch\n // identifiers may be zero.\n if (touchIdentifier_ !== undefined && touchIdentifier_ !== null) {\n // We're already tracking some touch/mouse event. Is this from the same\n // source?\n return touchIdentifier_ === identifier;\n }\n if (e.type === 'mousedown' || e.type === 'touchstart' ||\n e.type === 'pointerdown') {\n // No identifier set yet, and this is the start of a drag. Set it and\n // return.\n touchIdentifier_ = identifier;\n return true;\n }\n // There was no identifier yet, but this wasn't a start event so we're going\n // to ignore it. This probably means that another drag finished while this\n // pointer was down.\n return false;\n}\n\n/**\n * Set an event's clientX and clientY from its first changed touch. Use this to\n * make a touch event work in a mouse event handler.\n *\n * @param e A touch event.\n * @alias Blockly.Touch.setClientFromTouch\n */\nexport function setClientFromTouch(e: Event|PseudoEvent) {\n // AnyDuringMigration because: Property 'changedTouches' does not exist on\n // type 'PseudoEvent | Event'.\n if (e.type.startsWith('touch') && (e as AnyDuringMigration).changedTouches) {\n // Map the touch event's properties to the event.\n // AnyDuringMigration because: Property 'changedTouches' does not exist on\n // type 'PseudoEvent | Event'.\n const touchPoint = (e as AnyDuringMigration).changedTouches[0];\n // AnyDuringMigration because: Property 'clientX' does not exist on type\n // 'PseudoEvent | Event'.\n (e as AnyDuringMigration).clientX = touchPoint.clientX;\n // AnyDuringMigration because: Property 'clientY' does not exist on type\n // 'PseudoEvent | Event'.\n (e as AnyDuringMigration).clientY = touchPoint.clientY;\n }\n}\n\n/**\n * Check whether a given event is a mouse, touch, or pointer event.\n *\n * @param e An event.\n * @returns True if it is a mouse, touch, or pointer event; false otherwise.\n * @alias Blockly.Touch.isMouseOrTouchEvent\n */\nexport function isMouseOrTouchEvent(e: Event|PseudoEvent): boolean {\n return e.type.startsWith('touch') || e.type.startsWith('mouse') ||\n e.type.startsWith('pointer');\n}\n\n/**\n * Check whether a given event is a touch event or a pointer event.\n *\n * @param e An event.\n * @returns True if it is a touch or pointer event; false otherwise.\n * @alias Blockly.Touch.isTouchEvent\n */\nexport function isTouchEvent(e: Event|PseudoEvent): boolean {\n return e.type.startsWith('touch') || e.type.startsWith('pointer');\n}\n\n/**\n * Split an event into an array of events, one per changed touch or mouse\n * point.\n *\n * @param e A mouse event or a touch event with one or more changed touches.\n * @returns An array of events or pseudo events.\n * Each pseudo-touch event will have exactly one changed touch and there\n * will be no real touch events.\n * @alias Blockly.Touch.splitEventByTouches\n */\nexport function splitEventByTouches(e: Event): Array {\n const events = [];\n // AnyDuringMigration because: Property 'changedTouches' does not exist on\n // type 'PseudoEvent | Event'.\n if ((e as AnyDuringMigration).changedTouches) {\n // AnyDuringMigration because: Property 'changedTouches' does not exist on\n // type 'PseudoEvent | Event'.\n for (let i = 0; i < (e as AnyDuringMigration).changedTouches.length; i++) {\n const newEvent = {\n type: e.type,\n // AnyDuringMigration because: Property 'changedTouches' does not exist\n // on type 'PseudoEvent | Event'.\n changedTouches: [(e as AnyDuringMigration).changedTouches[i]],\n target: e.target,\n stopPropagation() {\n e.stopPropagation();\n },\n preventDefault() {\n e.preventDefault();\n },\n };\n events[i] = newEvent;\n }\n } else {\n events.push(e);\n }\n // AnyDuringMigration because: Type '(Event | { type: string; changedTouches:\n // Touch[]; target: EventTarget | null; stopPropagation(): void;\n // preventDefault(): void; })[]' is not assignable to type '(PseudoEvent |\n // Event)[]'.\n return events as AnyDuringMigration;\n}\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Browser event handling.\n *\n * @namespace Blockly.browserEvents\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.browserEvents');\n\nimport * as Touch from './touch.js';\nimport * as userAgent from './utils/useragent.js';\n\n\n/**\n * Blockly opaque event data used to unbind events when using\n * `bind` and `conditionalBind`.\n *\n * @alias Blockly.browserEvents.Data\n */\nexport type Data = [EventTarget, string, (e: Event) => void][];\n\n/**\n * The multiplier for scroll wheel deltas using the line delta mode.\n * See https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaMode\n * for more information on deltaMode.\n */\nconst LINE_MODE_MULTIPLIER = 40;\n\n/**\n * The multiplier for scroll wheel deltas using the page delta mode.\n * See https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaMode\n * for more information on deltaMode.\n */\nconst PAGE_MODE_MULTIPLIER = 125;\n\n/**\n * Bind an event handler that can be ignored if it is not part of the active\n * touch stream.\n * Use this for events that either start or continue a multi-part gesture (e.g.\n * mousedown or mousemove, which may be part of a drag or click).\n *\n * @param node Node upon which to listen.\n * @param name Event name to listen to (e.g. 'mousedown').\n * @param thisObject The value of 'this' in the function.\n * @param func Function to call when event is triggered.\n * @param opt_noCaptureIdentifier True if triggering on this event should not\n * block execution of other event handlers on this touch or other\n * simultaneous touches. False by default.\n * @param opt_noPreventDefault True if triggering on this event should prevent\n * the default handler. False by default. If opt_noPreventDefault is\n * provided, opt_noCaptureIdentifier must also be provided.\n * @returns Opaque data that can be passed to unbindEvent_.\n * @alias Blockly.browserEvents.conditionalBind\n */\nexport function conditionalBind(\n node: EventTarget, name: string, thisObject: Object|null, func: Function,\n opt_noCaptureIdentifier?: boolean, opt_noPreventDefault?: boolean): Data {\n let handled = false;\n /**\n *\n * @param e\n */\n function wrapFunc(e: Event) {\n const captureIdentifier = !opt_noCaptureIdentifier;\n // Handle each touch point separately. If the event was a mouse event, this\n // will hand back an array with one element, which we're fine handling.\n const events = Touch.splitEventByTouches(e);\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n if (captureIdentifier && !Touch.shouldHandleEvent(event)) {\n continue;\n }\n Touch.setClientFromTouch(event);\n if (thisObject) {\n func.call(thisObject, event);\n } else {\n func(event);\n }\n handled = true;\n }\n }\n\n const bindData: Data = [];\n if (globalThis['PointerEvent'] && name in Touch.TOUCH_MAP) {\n for (let i = 0; i < Touch.TOUCH_MAP[name].length; i++) {\n const type = Touch.TOUCH_MAP[name][i];\n node.addEventListener(type, wrapFunc, false);\n bindData.push([node, type, wrapFunc]);\n }\n } else {\n node.addEventListener(name, wrapFunc, false);\n bindData.push([node, name, wrapFunc]);\n\n // Add equivalent touch event.\n if (name in Touch.TOUCH_MAP) {\n const touchWrapFunc = (e: Event) => {\n wrapFunc(e);\n // Calling preventDefault stops the browser from scrolling/zooming the\n // page.\n const preventDef = !opt_noPreventDefault;\n if (handled && preventDef) {\n e.preventDefault();\n }\n };\n for (let i = 0; i < Touch.TOUCH_MAP[name].length; i++) {\n const type = Touch.TOUCH_MAP[name][i];\n node.addEventListener(type, touchWrapFunc, false);\n bindData.push([node, type, touchWrapFunc]);\n }\n }\n }\n return bindData;\n}\n\n/**\n * Bind an event handler that should be called regardless of whether it is part\n * of the active touch stream.\n * Use this for events that are not part of a multi-part gesture (e.g.\n * mouseover for tooltips).\n *\n * @param node Node upon which to listen.\n * @param name Event name to listen to (e.g. 'mousedown').\n * @param thisObject The value of 'this' in the function.\n * @param func Function to call when event is triggered.\n * @returns Opaque data that can be passed to unbindEvent_.\n * @alias Blockly.browserEvents.bind\n */\nexport function bind(\n node: EventTarget, name: string, thisObject: Object|null,\n func: Function): Data {\n /**\n *\n * @param e\n */\n function wrapFunc(e: Event) {\n if (thisObject) {\n func.call(thisObject, e);\n } else {\n func(e);\n }\n }\n\n const bindData: Data = [];\n if (globalThis['PointerEvent'] && name in Touch.TOUCH_MAP) {\n for (let i = 0; i < Touch.TOUCH_MAP[name].length; i++) {\n const type = Touch.TOUCH_MAP[name][i];\n node.addEventListener(type, wrapFunc, false);\n bindData.push([node, type, wrapFunc]);\n }\n } else {\n node.addEventListener(name, wrapFunc, false);\n bindData.push([node, name, wrapFunc]);\n\n // Add equivalent touch event.\n if (name in Touch.TOUCH_MAP) {\n const touchWrapFunc = (e: Event) => {\n // Punt on multitouch events.\n if (e instanceof TouchEvent && e.changedTouches &&\n e.changedTouches.length === 1) {\n // Map the touch event's properties to the event.\n const touchPoint = e.changedTouches[0];\n // TODO (6311): We are trying to make a touch event look like a mouse\n // event, which is not allowed, because it requires adding more\n // properties to the event. How do we want to deal with this?\n (e as AnyDuringMigration).clientX = touchPoint.clientX;\n (e as AnyDuringMigration).clientY = touchPoint.clientY;\n }\n wrapFunc(e);\n\n // Stop the browser from scrolling/zooming the page.\n e.preventDefault();\n };\n for (let i = 0; i < Touch.TOUCH_MAP[name].length; i++) {\n const type = Touch.TOUCH_MAP[name][i];\n node.addEventListener(type, touchWrapFunc, false);\n bindData.push([node, type, touchWrapFunc]);\n }\n }\n }\n return bindData;\n}\n\n/**\n * Unbind one or more events event from a function call.\n *\n * @param bindData Opaque data from bindEvent_.\n * This list is emptied during the course of calling this function.\n * @returns The function call.\n * @alias Blockly.browserEvents.unbind\n */\nexport function unbind(bindData: Data): (e: Event) => void {\n // Accessing an element of the last property of the array is unsafe if the\n // bindData is an empty array. But that should never happen because developers\n // should only pass Data from bind or conditionalBind.\n const callback = bindData[bindData.length - 1][2];\n while (bindData.length) {\n const bindDatum = bindData.pop();\n const node = bindDatum![0];\n const name = bindDatum![1];\n const func = bindDatum![2];\n node.removeEventListener(name, func, false);\n }\n return callback;\n}\n\n/**\n * Returns true if this event is targeting a text input widget?\n *\n * @param e An event.\n * @returns True if text input.\n * @alias Blockly.browserEvents.isTargetInput\n */\nexport function isTargetInput(e: Event): boolean {\n if (e.target instanceof HTMLElement) {\n if (e.target.isContentEditable ||\n e.target.getAttribute('data-is-text-input') === 'true') {\n return true;\n }\n\n if (e.target instanceof HTMLInputElement) {\n const target = e.target;\n return target.type === 'text' || target.type === 'number' ||\n target.type === 'email' || target.type === 'password' ||\n target.type === 'search' || target.type === 'tel' ||\n target.type === 'url';\n }\n\n if (e.target instanceof HTMLTextAreaElement) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Returns true this event is a right-click.\n *\n * @param e Mouse event.\n * @returns True if right-click.\n * @alias Blockly.browserEvents.isRightButton\n */\nexport function isRightButton(e: MouseEvent): boolean {\n if (e.ctrlKey && userAgent.MAC) {\n // Control-clicking on Mac OS X is treated as a right-click.\n // WebKit on Mac OS X fails to change button to 2 (but Gecko does).\n return true;\n }\n return e.button === 2;\n}\n\n/**\n * Returns the converted coordinates of the given mouse event.\n * The origin (0,0) is the top-left corner of the Blockly SVG.\n *\n * @param e Mouse event.\n * @param svg SVG element.\n * @param matrix Inverted screen CTM to use.\n * @returns Object with .x and .y properties.\n * @alias Blockly.browserEvents.mouseToSvg\n */\nexport function mouseToSvg(\n e: MouseEvent, svg: SVGSVGElement, matrix: SVGMatrix|null): SVGPoint {\n const svgPoint = svg.createSVGPoint();\n svgPoint.x = e.clientX;\n svgPoint.y = e.clientY;\n\n if (!matrix) {\n matrix = svg.getScreenCTM()!.inverse();\n }\n return svgPoint.matrixTransform(matrix);\n}\n\n/**\n * Returns the scroll delta of a mouse event in pixel units.\n *\n * @param e Mouse event.\n * @returns Scroll delta object with .x and .y properties.\n * @alias Blockly.browserEvents.getScrollDeltaPixels\n */\nexport function getScrollDeltaPixels(e: WheelEvent): {x: number, y: number} {\n switch (e.deltaMode) {\n case 0x00: // Pixel mode.\n default:\n return {x: e.deltaX, y: e.deltaY};\n case 0x01: // Line mode.\n return {\n x: e.deltaX * LINE_MODE_MULTIPLIER,\n y: e.deltaY * LINE_MODE_MULTIPLIER,\n };\n case 0x02: // Page mode.\n return {\n x: e.deltaX * PAGE_MODE_MULTIPLIER,\n y: e.deltaY * PAGE_MODE_MULTIPLIER,\n };\n }\n}\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Common functions used both internally and externally, but which\n * must not be at the top level to avoid circular dependencies.\n *\n * @namespace Blockly.common\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.common');\n\n/* eslint-disable-next-line no-unused-vars */\nimport type {Block} from './block.js';\nimport {BlockDefinition, Blocks} from './blocks.js';\nimport type {Connection} from './connection.js';\nimport type {ICopyable} from './interfaces/i_copyable.js';\nimport type {Workspace} from './workspace.js';\nimport type {WorkspaceSvg} from './workspace_svg.js';\n\n\n/** Database of all workspaces. */\nconst WorkspaceDB_ = Object.create(null);\n\n\n/**\n * Find the workspace with the specified ID.\n *\n * @param id ID of workspace to find.\n * @returns The sought after workspace or null if not found.\n */\nexport function getWorkspaceById(id: string): Workspace|null {\n return WorkspaceDB_[id] || null;\n}\n\n/**\n * Find all workspaces.\n *\n * @returns Array of workspaces.\n */\nexport function getAllWorkspaces(): Workspace[] {\n const workspaces = [];\n for (const workspaceId in WorkspaceDB_) {\n workspaces.push(WorkspaceDB_[workspaceId]);\n }\n return workspaces;\n}\n\n/**\n * Register a workspace in the workspace db.\n *\n * @param workspace\n */\nexport function registerWorkspace(workspace: Workspace) {\n WorkspaceDB_[workspace.id] = workspace;\n}\n\n/**\n * Unregister a workspace from the workspace db.\n *\n * @param workspace\n */\nexport function unregisterWorkpace(workspace: Workspace) {\n delete WorkspaceDB_[workspace.id];\n}\n\n/**\n * The main workspace most recently used.\n * Set by Blockly.WorkspaceSvg.prototype.markFocused\n */\nlet mainWorkspace: Workspace;\n\n/**\n * Returns the last used top level workspace (based on focus). Try not to use\n * this function, particularly if there are multiple Blockly instances on a\n * page.\n *\n * @returns The main workspace.\n * @alias Blockly.common.getMainWorkspace\n */\nexport function getMainWorkspace(): Workspace {\n return mainWorkspace;\n}\n\n/**\n * Sets last used main workspace.\n *\n * @param workspace The most recently used top level workspace.\n * @alias Blockly.common.setMainWorkspace\n */\nexport function setMainWorkspace(workspace: Workspace) {\n mainWorkspace = workspace;\n}\n\n/**\n * Currently selected copyable object.\n */\nlet selected: ICopyable|null = null;\n\n/**\n * Returns the currently selected copyable object.\n *\n * @alias Blockly.common.getSelected\n */\nexport function getSelected(): ICopyable|null {\n return selected;\n}\n\n/**\n * Sets the currently selected block. This function does not visually mark the\n * block as selected or fire the required events. If you wish to\n * programmatically select a block, use `BlockSvg#select`.\n *\n * @param newSelection The newly selected block.\n * @alias Blockly.common.setSelected\n * @internal\n */\nexport function setSelected(newSelection: ICopyable|null) {\n selected = newSelection;\n}\n\n/**\n * Container element in which to render the WidgetDiv, DropDownDiv and Tooltip.\n */\nlet parentContainer: Element|null;\n\n/**\n * Get the container element in which to render the WidgetDiv, DropDownDiv and\n * Tooltip.\n *\n * @returns The parent container.\n * @alias Blockly.common.getParentContainer\n */\nexport function getParentContainer(): Element|null {\n return parentContainer;\n}\n\n/**\n * Set the parent container. This is the container element that the WidgetDiv,\n * DropDownDiv, and Tooltip are rendered into the first time `Blockly.inject`\n * is called.\n * This method is a NOP if called after the first `Blockly.inject`.\n *\n * @param newParent The container element.\n * @alias Blockly.common.setParentContainer\n */\nexport function setParentContainer(newParent: Element) {\n parentContainer = newParent;\n}\n\n/**\n * Size the SVG image to completely fill its container. Call this when the view\n * actually changes sizes (e.g. on a window resize/device orientation change).\n * See workspace.resizeContents to resize the workspace when the contents\n * change (e.g. when a block is added or removed).\n * Record the height/width of the SVG image.\n *\n * @param workspace Any workspace in the SVG.\n * @alias Blockly.common.svgResize\n */\nexport function svgResize(workspace: WorkspaceSvg) {\n let mainWorkspace = workspace;\n while (mainWorkspace.options.parentWorkspace) {\n mainWorkspace = mainWorkspace.options.parentWorkspace;\n }\n const svg = mainWorkspace.getParentSvg();\n const cachedSize = mainWorkspace.getCachedParentSvgSize();\n const div = svg.parentElement;\n if (!(div instanceof HTMLElement)) {\n // Workspace deleted, or something.\n return;\n }\n\n const width = div.offsetWidth;\n const height = div.offsetHeight;\n if (cachedSize.width !== width) {\n svg.setAttribute('width', width + 'px');\n mainWorkspace.setCachedParentSvgSize(width, null);\n }\n if (cachedSize.height !== height) {\n svg.setAttribute('height', height + 'px');\n mainWorkspace.setCachedParentSvgSize(null, height);\n }\n mainWorkspace.resize();\n}\n\n/**\n * All of the connections on blocks that are currently being dragged.\n */\nexport const draggingConnections: Connection[] = [];\n\n/**\n * Get a map of all the block's descendants mapping their type to the number of\n * children with that type.\n *\n * @param block The block to map.\n * @param opt_stripFollowing Optionally ignore all following\n * statements (blocks that are not inside a value or statement input\n * of the block).\n * @returns Map of types to type counts for descendants of the bock.\n * @alias Blockly.common.getBlockTypeCounts\n */\nexport function getBlockTypeCounts(\n block: Block, opt_stripFollowing?: boolean): {[key: string]: number} {\n const typeCountsMap = Object.create(null);\n const descendants = block.getDescendants(true);\n if (opt_stripFollowing) {\n const nextBlock = block.getNextBlock();\n if (nextBlock) {\n const index = descendants.indexOf(nextBlock);\n descendants.splice(index, descendants.length - index);\n }\n }\n for (let i = 0, checkBlock; checkBlock = descendants[i]; i++) {\n if (typeCountsMap[checkBlock.type]) {\n typeCountsMap[checkBlock.type]++;\n } else {\n typeCountsMap[checkBlock.type] = 1;\n }\n }\n return typeCountsMap;\n}\n\n/**\n * Helper function for defining a block from JSON. The resulting function has\n * the correct value of jsonDef at the point in code where jsonInit is called.\n *\n * @param jsonDef The JSON definition of a block.\n * @returns A function that calls jsonInit with the correct value\n * of jsonDef.\n */\nfunction jsonInitFactory(jsonDef: AnyDuringMigration): () => void {\n return function(this: Block) {\n this.jsonInit(jsonDef);\n };\n}\n\n/**\n * Define blocks from an array of JSON block definitions, as might be generated\n * by the Blockly Developer Tools.\n *\n * @param jsonArray An array of JSON block definitions.\n * @alias Blockly.common.defineBlocksWithJsonArray\n */\nexport function defineBlocksWithJsonArray(jsonArray: AnyDuringMigration[]) {\n TEST_ONLY.defineBlocksWithJsonArrayInternal(jsonArray);\n}\n\n/**\n * Private version of defineBlocksWithJsonArray for stubbing in tests.\n */\nfunction defineBlocksWithJsonArrayInternal(jsonArray: AnyDuringMigration[]) {\n defineBlocks(createBlockDefinitionsFromJsonArray(jsonArray));\n}\n\n/**\n * Define blocks from an array of JSON block definitions, as might be generated\n * by the Blockly Developer Tools.\n *\n * @param jsonArray An array of JSON block definitions.\n * @returns A map of the block\n * definitions created.\n * @alias Blockly.common.defineBlocksWithJsonArray\n */\nexport function createBlockDefinitionsFromJsonArray(\n jsonArray: AnyDuringMigration[]): {[key: string]: BlockDefinition} {\n const blocks: {[key: string]: BlockDefinition} = {};\n for (let i = 0; i < jsonArray.length; i++) {\n const elem = jsonArray[i];\n if (!elem) {\n console.warn(`Block definition #${i} in JSON array is ${elem}. Skipping`);\n continue;\n }\n const type = elem['type'];\n if (!type) {\n console.warn(\n `Block definition #${i} in JSON array is missing a type attribute. ` +\n 'Skipping.');\n continue;\n }\n blocks[type] = {init: jsonInitFactory(elem)};\n }\n return blocks;\n}\n\n/**\n * Add the specified block definitions to the block definitions\n * dictionary (Blockly.Blocks).\n *\n * @param blocks A map of block\n * type names to block definitions.\n * @alias Blockly.common.defineBlocks\n */\nexport function defineBlocks(blocks: {[key: string]: BlockDefinition}) {\n // Iterate over own enumerable properties.\n for (const type of Object.keys(blocks)) {\n const definition = blocks[type];\n if (type in Blocks) {\n console.warn(`Block definiton \"${type}\" overwrites previous definition.`);\n }\n Blocks[type] = definition;\n }\n}\n\nexport const TEST_ONLY = {defineBlocksWithJsonArrayInternal};\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility methods for DOM manipulation.\n * These methods are not specific to Blockly, and could be factored out into\n * a JavaScript framework such as Closure.\n *\n * @namespace Blockly.utils.dom\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.dom');\n\nimport type {Svg} from './svg.js';\n\n\n/**\n * Required name space for SVG elements.\n *\n * @alias Blockly.utils.dom.SVG_NS\n */\nexport const SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Required name space for HTML elements.\n *\n * @alias Blockly.utils.dom.HTML_NS\n */\nexport const HTML_NS = 'http://www.w3.org/1999/xhtml';\n\n/**\n * Required name space for XLINK elements.\n *\n * @alias Blockly.utils.dom.XLINK_NS\n */\nexport const XLINK_NS = 'http://www.w3.org/1999/xlink';\n\n/**\n * Node type constants.\n * https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\n *\n * @alias Blockly.utils.dom.NodeType\n */\nexport enum NodeType {\n ELEMENT_NODE = 1,\n TEXT_NODE = 3,\n COMMENT_NODE = 8,\n DOCUMENT_POSITION_CONTAINED_BY = 16\n}\n\n/** Temporary cache of text widths. */\nlet cacheWidths: {[key: string]: number}|null = null;\n\n/** Number of current references to cache. */\nlet cacheReference = 0;\n\n/** A HTML canvas context used for computing text width. */\nlet canvasContext: CanvasRenderingContext2D|null = null;\n\n/**\n * Helper method for creating SVG elements.\n *\n * @param name Element's tag name.\n * @param attrs Dictionary of attribute names and values.\n * @param opt_parent Optional parent on which to append the element.\n * @returns if name is a string or a more specific type if it a member of Svg.\n * @alias Blockly.utils.dom.createSvgElement\n */\nexport function createSvgElement(\n name: string|Svg, attrs: {[key: string]: string|number},\n opt_parent?: Element|null): T {\n const e = document.createElementNS(SVG_NS, String(name)) as T;\n for (const key in attrs) {\n e.setAttribute(key, `${attrs[key]}`);\n }\n if (opt_parent) {\n opt_parent.appendChild(e);\n }\n return e;\n}\n\n/**\n * Add a CSS class to a element.\n *\n * Handles multiple space-separated classes for legacy reasons.\n *\n * @param element DOM element to add class to.\n * @param className Name of class to add.\n * @returns True if class was added, false if already present.\n * @alias Blockly.utils.dom.addClass\n */\nexport function addClass(element: Element, className: string): boolean {\n const classNames = className.split(' ');\n if (classNames.every((name) => element.classList.contains(name))) {\n return false;\n }\n element.classList.add(...classNames);\n return true;\n}\n\n/**\n * Removes multiple classes from an element.\n *\n * @param element DOM element to remove classes from.\n * @param classNames A string of one or multiple class names for an element.\n * @alias Blockly.utils.dom.removeClasses\n */\nexport function removeClasses(element: Element, classNames: string) {\n element.classList.remove(...classNames.split(' '));\n}\n\n/**\n * Remove a CSS class from a element.\n *\n * Handles multiple space-separated classes for legacy reasons.\n *\n * @param element DOM element to remove class from.\n * @param className Name of class to remove.\n * @returns True if class was removed, false if never present.\n * @alias Blockly.utils.dom.removeClass\n */\nexport function removeClass(element: Element, className: string): boolean {\n const classNames = className.split(' ');\n if (classNames.every((name) => !element.classList.contains(name))) {\n return false;\n }\n element.classList.remove(...classNames);\n return true;\n}\n\n/**\n * Checks if an element has the specified CSS class.\n *\n * @param element DOM element to check.\n * @param className Name of class to check.\n * @returns True if class exists, false otherwise.\n * @alias Blockly.utils.dom.hasClass\n */\nexport function hasClass(element: Element, className: string): boolean {\n return element.classList.contains(className);\n}\n\n/**\n * Removes a node from its parent. No-op if not attached to a parent.\n *\n * @param node The node to remove.\n * @returns The node removed if removed; else, null.\n * @alias Blockly.utils.dom.removeNode\n */\n// Copied from Closure goog.dom.removeNode\nexport function removeNode(node: Node|null): Node|null {\n return node && node.parentNode ? node.parentNode.removeChild(node) : null;\n}\n\n/**\n * Insert a node after a reference node.\n * Contrast with node.insertBefore function.\n *\n * @param newNode New element to insert.\n * @param refNode Existing element to precede new node.\n * @alias Blockly.utils.dom.insertAfter\n */\nexport function insertAfter(newNode: Element, refNode: Element) {\n const siblingNode = refNode.nextSibling;\n const parentNode = refNode.parentNode;\n if (!parentNode) {\n throw Error('Reference node has no parent.');\n }\n if (siblingNode) {\n parentNode.insertBefore(newNode, siblingNode);\n } else {\n parentNode.appendChild(newNode);\n }\n}\n\n/**\n * Whether a node contains another node.\n *\n * @param parent The node that should contain the other node.\n * @param descendant The node to test presence of.\n * @returns Whether the parent node contains the descendant node.\n * @alias Blockly.utils.dom.containsNode\n */\nexport function containsNode(parent: Node, descendant: Node): boolean {\n return !!(\n parent.compareDocumentPosition(descendant) &\n NodeType.DOCUMENT_POSITION_CONTAINED_BY);\n}\n\n/**\n * Sets the CSS transform property on an element. This function sets the\n * non-vendor-prefixed and vendor-prefixed versions for backwards compatibility\n * with older browsers. See https://caniuse.com/#feat=transforms2d\n *\n * @param element Element to which the CSS transform will be applied.\n * @param transform The value of the CSS `transform` property.\n * @alias Blockly.utils.dom.setCssTransform\n */\nexport function setCssTransform(\n element: HTMLElement|SVGElement, transform: string) {\n element.style['transform'] = transform;\n element.style['-webkit-transform' as any] = transform;\n}\n\n/**\n * Start caching text widths. Every call to this function MUST also call\n * stopTextWidthCache. Caches must not survive between execution threads.\n *\n * @alias Blockly.utils.dom.startTextWidthCache\n */\nexport function startTextWidthCache() {\n cacheReference++;\n if (!cacheWidths) {\n cacheWidths = Object.create(null);\n }\n}\n\n/**\n * Stop caching field widths. Unless caching was already on when the\n * corresponding call to startTextWidthCache was made.\n *\n * @alias Blockly.utils.dom.stopTextWidthCache\n */\nexport function stopTextWidthCache() {\n cacheReference--;\n if (!cacheReference) {\n cacheWidths = null;\n }\n}\n\n/**\n * Gets the width of a text element, caching it in the process.\n *\n * @param textElement An SVG 'text' element.\n * @returns Width of element.\n * @alias Blockly.utils.dom.getTextWidth\n */\nexport function getTextWidth(textElement: SVGTextElement): number {\n const key = textElement.textContent + '\\n' + textElement.className.baseVal;\n let width;\n // Return the cached width if it exists.\n if (cacheWidths) {\n width = cacheWidths[key];\n if (width) {\n return width;\n }\n }\n\n // Attempt to compute fetch the width of the SVG text element.\n try {\n width = textElement.getComputedTextLength();\n } catch (e) {\n // In other cases where we fail to get the computed text. Instead, use an\n // approximation and do not cache the result. At some later point in time\n // when the block is inserted into the visible DOM, this method will be\n // called again and, at that point in time, will not throw an exception.\n return textElement.textContent!.length * 8;\n }\n\n // Cache the computed width and return.\n if (cacheWidths) {\n cacheWidths[key] = width;\n }\n return width;\n}\n\n/**\n * Gets the width of a text element using a faster method than `getTextWidth`.\n * This method requires that we know the text element's font family and size in\n * advance. Similar to `getTextWidth`, we cache the width we compute.\n *\n * @param textElement An SVG 'text' element.\n * @param fontSize The font size to use.\n * @param fontWeight The font weight to use.\n * @param fontFamily The font family to use.\n * @returns Width of element.\n * @alias Blockly.utils.dom.getFastTextWidth\n */\nexport function getFastTextWidth(\n textElement: SVGTextElement, fontSize: number, fontWeight: string,\n fontFamily: string): number {\n return getFastTextWidthWithSizeString(\n textElement, fontSize + 'pt', fontWeight, fontFamily);\n}\n\n/**\n * Gets the width of a text element using a faster method than `getTextWidth`.\n * This method requires that we know the text element's font family and size in\n * advance. Similar to `getTextWidth`, we cache the width we compute.\n * This method is similar to `getFastTextWidth` but expects the font size\n * parameter to be a string.\n *\n * @param textElement An SVG 'text' element.\n * @param fontSize The font size to use.\n * @param fontWeight The font weight to use.\n * @param fontFamily The font family to use.\n * @returns Width of element.\n * @alias Blockly.utils.dom.getFastTextWidthWithSizeString\n */\nexport function getFastTextWidthWithSizeString(\n textElement: SVGTextElement, fontSize: string, fontWeight: string,\n fontFamily: string): number {\n const text = textElement.textContent;\n const key = text + '\\n' + textElement.className.baseVal;\n let width;\n\n // Return the cached width if it exists.\n if (cacheWidths) {\n width = cacheWidths[key];\n if (width) {\n return width;\n }\n }\n\n if (!canvasContext) {\n // Inject the canvas element used for computing text widths.\n const computeCanvas = (document.createElement('canvas'));\n computeCanvas.className = 'blocklyComputeCanvas';\n document.body.appendChild(computeCanvas);\n\n // Initialize the HTML canvas context and set the font.\n // The context font must match blocklyText's fontsize and font-family\n // set in CSS.\n canvasContext = computeCanvas.getContext('2d') as CanvasRenderingContext2D;\n }\n // Set the desired font size and family.\n canvasContext.font = fontWeight + ' ' + fontSize + ' ' + fontFamily;\n\n // Measure the text width using the helper canvas context.\n if (text) {\n width = canvasContext.measureText(text).width;\n } else {\n width = 0;\n }\n\n // Cache the computed width and return.\n if (cacheWidths) {\n cacheWidths[key] = width;\n }\n return width;\n}\n\n/**\n * Measure a font's metrics. The height and baseline values.\n *\n * @param text Text to measure the font dimensions of.\n * @param fontSize The font size to use.\n * @param fontWeight The font weight to use.\n * @param fontFamily The font family to use.\n * @returns Font measurements.\n * @alias Blockly.utils.dom.measureFontMetrics\n */\nexport function measureFontMetrics(\n text: string, fontSize: string, fontWeight: string,\n fontFamily: string): {height: number, baseline: number} {\n const span = (document.createElement('span'));\n span.style.font = fontWeight + ' ' + fontSize + ' ' + fontFamily;\n span.textContent = text;\n\n const block = (document.createElement('div'));\n block.style.width = '1px';\n block.style.height = '0';\n\n const div = (document.createElement('div'));\n div.setAttribute('style', 'position: fixed; top: 0; left: 0; display: flex;');\n div.appendChild(span);\n div.appendChild(block);\n\n document.body.appendChild(div);\n const result = {\n height: 0,\n baseline: 0,\n };\n try {\n div.style.alignItems = 'baseline';\n result.baseline = block.offsetTop - span.offsetTop;\n div.style.alignItems = 'flex-end';\n result.height = block.offsetTop - span.offsetTop;\n } finally {\n document.body.removeChild(div);\n }\n return result;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility methods for math.\n * These methods are not specific to Blockly, and could be factored out into\n * a JavaScript framework such as Closure.\n *\n * @namespace Blockly.utils.math\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.math');\n\n\n/**\n * Converts degrees to radians.\n * Copied from Closure's goog.math.toRadians.\n *\n * @param angleDegrees Angle in degrees.\n * @returns Angle in radians.\n * @alias Blockly.utils.math.toRadians\n */\nexport function toRadians(angleDegrees: number): number {\n return angleDegrees * Math.PI / 180;\n}\n\n/**\n * Converts radians to degrees.\n * Copied from Closure's goog.math.toDegrees.\n *\n * @param angleRadians Angle in radians.\n * @returns Angle in degrees.\n * @alias Blockly.utils.math.toDegrees\n */\nexport function toDegrees(angleRadians: number): number {\n return angleRadians * 180 / Math.PI;\n}\n\n/**\n * Clamp the provided number between the lower bound and the upper bound.\n *\n * @param lowerBound The desired lower bound.\n * @param number The number to clamp.\n * @param upperBound The desired upper bound.\n * @returns The clamped number.\n * @alias Blockly.utils.math.clamp\n */\nexport function clamp(\n lowerBound: number, number: number, upperBound: number): number {\n if (upperBound < lowerBound) {\n const temp = upperBound;\n upperBound = lowerBound;\n lowerBound = temp;\n }\n return Math.max(lowerBound, Math.min(number, upperBound));\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Helper function for warning developers about deprecations.\n * This method is not specific to Blockly.\n *\n * @namespace Blockly.utils.deprecation\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.deprecation');\n\n\n/**\n * Warn developers that a function or property is deprecated.\n *\n * @param name The name of the function or property.\n * @param deprecationDate The date of deprecation. Prefer 'version n.0.0'\n * format, and fall back to 'month yyyy' or 'quarter yyyy' format.\n * @param deletionDate The date of deletion. Prefer 'version n.0.0'\n * format, and fall back to 'month yyyy' or 'quarter yyyy' format.\n * @param opt_use The name of a function or property to use instead, if any.\n * @alias Blockly.utils.deprecation.warn\n * @internal\n */\nexport function warn(\n name: string, deprecationDate: string, deletionDate: string,\n opt_use?: string) {\n let msg = name + ' was deprecated in ' + deprecationDate +\n ' and will be deleted in ' + deletionDate + '.';\n if (opt_use) {\n msg += '\\nUse ' + opt_use + ' instead.';\n }\n console.warn(msg);\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utilities for element styles.\n * These methods are not specific to Blockly, and could be factored out into\n * a JavaScript framework such as Closure.\n *\n * @namespace Blockly.utils.style\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.style');\n\nimport * as deprecation from './deprecation.js';\nimport {Coordinate} from './coordinate.js';\nimport {Rect} from './rect.js';\nimport {Size} from './size.js';\n\n\n/**\n * Gets the height and width of an element.\n * Similar to Closure's goog.style.getSize\n *\n * @param element Element to get size of.\n * @returns Object with width/height properties.\n * @alias Blockly.utils.style.getSize\n */\nexport function getSize(element: Element): Size {\n return TEST_ONLY.getSizeInternal(element);\n}\n\n/**\n * Private version of getSize for stubbing in tests.\n */\nfunction getSizeInternal(element: Element): Size {\n if (getComputedStyle(element, 'display') !== 'none') {\n return getSizeWithDisplay(element);\n }\n\n // Evaluate size with a temporary element.\n // AnyDuringMigration because: Property 'style' does not exist on type\n // 'Element'.\n const style = (element as AnyDuringMigration).style;\n const originalDisplay = style.display;\n const originalVisibility = style.visibility;\n const originalPosition = style.position;\n\n style.visibility = 'hidden';\n style.position = 'absolute';\n style.display = 'inline';\n\n const offsetWidth = (element as HTMLElement).offsetWidth;\n const offsetHeight = (element as HTMLElement).offsetHeight;\n\n style.display = originalDisplay;\n style.position = originalPosition;\n style.visibility = originalVisibility;\n\n return new Size(offsetWidth, offsetHeight);\n}\n\n/**\n * Gets the height and width of an element when the display is not none.\n *\n * @param element Element to get size of.\n * @returns Object with width/height properties.\n */\nfunction getSizeWithDisplay(element: Element): Size {\n const offsetWidth = (element as HTMLElement).offsetWidth;\n const offsetHeight = (element as HTMLElement).offsetHeight;\n return new Size(offsetWidth, offsetHeight);\n}\n\n/**\n * Retrieves a computed style value of a node. It returns empty string\n * if the property requested is an SVG one and it has not been\n * explicitly set (firefox and webkit).\n *\n * Copied from Closure's goog.style.getComputedStyle\n *\n * @param element Element to get style of.\n * @param property Property to get (camel-case).\n * @returns Style value.\n * @alias Blockly.utils.style.getComputedStyle\n */\nexport function getComputedStyle(element: Element, property: string): string {\n const styles = window.getComputedStyle(element);\n // element.style[..] is undefined for browser specific styles\n // as 'filter'.\n return (styles as AnyDuringMigration)[property] ||\n styles.getPropertyValue(property);\n}\n\n/**\n * Gets the cascaded style value of a node, or null if the value cannot be\n * computed (only Internet Explorer can do this).\n *\n * Copied from Closure's goog.style.getCascadedStyle\n *\n * @param element Element to get style of.\n * @param style Property to get (camel-case).\n * @returns Style value.\n * @deprecated No longer provided by Blockly.\n * @alias Blockly.utils.style.getCascadedStyle\n */\nexport function getCascadedStyle(element: Element, style: string): string {\n deprecation.warn(\n 'Blockly.utils.style.getCascadedStyle', 'version 9', 'version 10');\n // AnyDuringMigration because: Property 'currentStyle' does not exist on type\n // 'Element'. AnyDuringMigration because: Property 'currentStyle' does not\n // exist on type 'Element'.\n return (element as AnyDuringMigration).currentStyle ?\n (element as AnyDuringMigration).currentStyle[style] :\n '' as string;\n}\n\n/**\n * Returns a Coordinate object relative to the top-left of the HTML document.\n * Similar to Closure's goog.style.getPageOffset\n *\n * @param el Element to get the page offset for.\n * @returns The page offset.\n * @alias Blockly.utils.style.getPageOffset\n */\nexport function getPageOffset(el: Element): Coordinate {\n const pos = new Coordinate(0, 0);\n const box = el.getBoundingClientRect();\n const documentElement = document.documentElement;\n // Must add the scroll coordinates in to get the absolute page offset\n // of element since getBoundingClientRect returns relative coordinates to\n // the viewport.\n const scrollCoord = new Coordinate(\n window.pageXOffset || documentElement.scrollLeft,\n window.pageYOffset || documentElement.scrollTop);\n pos.x = box.left + scrollCoord.x;\n pos.y = box.top + scrollCoord.y;\n\n return pos;\n}\n\n/**\n * Calculates the viewport coordinates relative to the document.\n * Similar to Closure's goog.style.getViewportPageOffset\n *\n * @returns The page offset of the viewport.\n * @alias Blockly.utils.style.getViewportPageOffset\n */\nexport function getViewportPageOffset(): Coordinate {\n const body = document.body;\n const documentElement = document.documentElement;\n const scrollLeft = body.scrollLeft || documentElement.scrollLeft;\n const scrollTop = body.scrollTop || documentElement.scrollTop;\n return new Coordinate(scrollLeft, scrollTop);\n}\n\n/**\n * Gets the computed border widths (on all sides) in pixels\n * Copied from Closure's goog.style.getBorderBox\n *\n * @param element The element to get the border widths for.\n * @returns The computed border widths.\n * @alias Blockly.utils.style.getBorderBox\n */\nexport function getBorderBox(element: Element): Rect {\n const left = parseFloat(getComputedStyle(element, 'borderLeftWidth'));\n const right = parseFloat(getComputedStyle(element, 'borderRightWidth'));\n const top = parseFloat(getComputedStyle(element, 'borderTopWidth'));\n const bottom = parseFloat(getComputedStyle(element, 'borderBottomWidth'));\n\n return new Rect(top, bottom, left, right);\n}\n\n/**\n * Changes the scroll position of `container` with the minimum amount so\n * that the content and the borders of the given `element` become visible.\n * If the element is bigger than the container, its top left corner will be\n * aligned as close to the container's top left corner as possible.\n * Copied from Closure's goog.style.scrollIntoContainerView\n *\n * @param element The element to make visible.\n * @param container The container to scroll. If not set, then the document\n * scroll element will be used.\n * @param opt_center Whether to center the element in the container.\n * Defaults to false.\n * @alias Blockly.utils.style.scrollIntoContainerView\n */\nexport function scrollIntoContainerView(\n element: Element, container: Element, opt_center?: boolean) {\n const offset = getContainerOffsetToScrollInto(element, container, opt_center);\n container.scrollLeft = offset.x;\n container.scrollTop = offset.y;\n}\n\n/**\n * Calculate the scroll position of `container` with the minimum amount so\n * that the content and the borders of the given `element` become visible.\n * If the element is bigger than the container, its top left corner will be\n * aligned as close to the container's top left corner as possible.\n * Copied from Closure's goog.style.getContainerOffsetToScrollInto\n *\n * @param element The element to make visible.\n * @param container The container to scroll. If not set, then the document\n * scroll element will be used.\n * @param opt_center Whether to center the element in the container.\n * Defaults to false.\n * @returns The new scroll position of the container.\n * @alias Blockly.utils.style.getContainerOffsetToScrollInto\n */\nexport function getContainerOffsetToScrollInto(\n element: Element, container: Element, opt_center?: boolean): Coordinate {\n // Absolute position of the element's border's top left corner.\n const elementPos = getPageOffset(element);\n // Absolute position of the container's border's top left corner.\n const containerPos = getPageOffset(container);\n const containerBorder = getBorderBox(container);\n // Relative pos. of the element's border box to the container's content box.\n const relX = elementPos.x - containerPos.x - containerBorder.left;\n const relY = elementPos.y - containerPos.y - containerBorder.top;\n // How much the element can move in the container, i.e. the difference between\n // the element's bottom-right-most and top-left-most position where it's\n // fully visible.\n const elementSize = getSizeWithDisplay(element);\n const spaceX = container.clientWidth - elementSize.width;\n const spaceY = container.clientHeight - elementSize.height;\n let scrollLeft = container.scrollLeft;\n let scrollTop = container.scrollTop;\n if (opt_center) {\n // All browsers round non-integer scroll positions down.\n scrollLeft += relX - spaceX / 2;\n scrollTop += relY - spaceY / 2;\n } else {\n // This formula was designed to give the correct scroll values in the\n // following cases:\n // - element is higher than container (spaceY < 0) => scroll down by relY\n // - element is not higher that container (spaceY >= 0):\n // - it is above container (relY < 0) => scroll up by abs(relY)\n // - it is below container (relY > spaceY) => scroll down by relY - spaceY\n // - it is in the container => don't scroll\n scrollLeft += Math.min(relX, Math.max(relX - spaceX, 0));\n scrollTop += Math.min(relY, Math.max(relY - spaceY, 0));\n }\n return new Coordinate(scrollLeft, scrollTop);\n}\n\nexport const TEST_ONLY = {\n getSizeInternal,\n};\n","/**\n * @license\n * Copyright 2016 Massachusetts Institute of Technology\n * All rights reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * A div that floats on top of the workspace, for drop-down menus.\n *\n * @class\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.dropDownDiv');\n\nimport type {BlockSvg} from './block_svg.js';\nimport * as common from './common.js';\nimport * as dom from './utils/dom.js';\nimport type {Field} from './field.js';\nimport * as math from './utils/math.js';\nimport {Rect} from './utils/rect.js';\nimport type {Size} from './utils/size.js';\nimport * as style from './utils/style.js';\nimport type {WorkspaceSvg} from './workspace_svg.js';\n\n\n/**\n * Arrow size in px. Should match the value in CSS\n * (need to position pre-render).\n */\nexport const ARROW_SIZE = 16;\n\n/**\n * Drop-down border size in px. Should match the value in CSS (need to position\n * the arrow).\n */\nexport const BORDER_SIZE = 1;\n\n/**\n * Amount the arrow must be kept away from the edges of the main drop-down div,\n * in px.\n */\nexport const ARROW_HORIZONTAL_PADDING = 12;\n\n/** Amount drop-downs should be padded away from the source, in px. */\nexport const PADDING_Y = 16;\n\n/** Length of animations in seconds. */\nexport const ANIMATION_TIME = 0.25;\n\n/**\n * Timer for animation out, to be cleared if we need to immediately hide\n * without disrupting new shows.\n */\nlet animateOutTimer: ReturnType|null = null;\n\n/** Callback for when the drop-down is hidden. */\nlet onHide: Function|null = null;\n\n/** A class name representing the current owner's workspace renderer. */\nlet renderedClassName = '';\n\n/** A class name representing the current owner's workspace theme. */\nlet themeClassName = '';\n\n/** The content element. */\nlet div: HTMLDivElement;\n\n/** The content element. */\nlet content: HTMLDivElement;\n\n/** The arrow element. */\nlet arrow: HTMLDivElement;\n\n/**\n * Drop-downs will appear within the bounds of this element if possible.\n * Set in setBoundsElement.\n */\nlet boundsElement: Element|null = null;\n\n/** The object currently using the drop-down. */\nlet owner: Field|null = null;\n\n/** Whether the dropdown was positioned to a field or the source block. */\nlet positionToField: boolean|null = null;\n\n/**\n * Dropdown bounds info object used to encapsulate sizing information about a\n * bounding element (bounding box and width/height).\n */\nexport interface BoundsInfo {\n top: number;\n left: number;\n bottom: number;\n right: number;\n width: number;\n height: number;\n}\n\n/** Dropdown position metrics. */\nexport interface PositionMetrics {\n initialX: number;\n initialY: number;\n finalX: number;\n finalY: number;\n arrowX: number|null;\n arrowY: number|null;\n arrowAtTop: boolean|null;\n arrowVisible: boolean;\n}\n\n/**\n * Create and insert the DOM element for this div.\n *\n * @internal\n */\nexport function createDom() {\n if (div) {\n return; // Already created.\n }\n div = document.createElement('div');\n div.className = 'blocklyDropDownDiv';\n const parentDiv = common.getParentContainer() || document.body;\n parentDiv.appendChild(div);\n\n content = document.createElement('div');\n content.className = 'blocklyDropDownContent';\n div.appendChild(content);\n\n arrow = document.createElement('div');\n arrow.className = 'blocklyDropDownArrow';\n div.appendChild(arrow);\n\n div.style.opacity = '0';\n // Transition animation for transform: translate() and opacity.\n div.style.transition = 'transform ' + ANIMATION_TIME + 's, ' +\n 'opacity ' + ANIMATION_TIME + 's';\n\n // Handle focusin/out events to add a visual indicator when\n // a child is focused or blurred.\n div.addEventListener('focusin', function() {\n dom.addClass(div, 'blocklyFocused');\n });\n div.addEventListener('focusout', function() {\n dom.removeClass(div, 'blocklyFocused');\n });\n}\n\n/**\n * Set an element to maintain bounds within. Drop-downs will appear\n * within the box of this element if possible.\n *\n * @param boundsElem Element to bind drop-down to.\n */\nexport function setBoundsElement(boundsElem: Element|null) {\n boundsElement = boundsElem;\n}\n\n/**\n * Provide the div for inserting content into the drop-down.\n *\n * @returns Div to populate with content.\n */\nexport function getContentDiv(): Element {\n return content;\n}\n\n/** Clear the content of the drop-down. */\nexport function clearContent() {\n content.textContent = '';\n content.style.width = '';\n}\n\n/**\n * Set the colour for the drop-down.\n *\n * @param backgroundColour Any CSS colour for the background.\n * @param borderColour Any CSS colour for the border.\n */\nexport function setColour(backgroundColour: string, borderColour: string) {\n div.style.backgroundColor = backgroundColour;\n div.style.borderColor = borderColour;\n}\n\n/**\n * Shortcut to show and place the drop-down with positioning determined\n * by a particular block. The primary position will be below the block,\n * and the secondary position above the block. Drop-down will be\n * constrained to the block's workspace.\n *\n * @param field The field showing the drop-down.\n * @param block Block to position the drop-down around.\n * @param opt_onHide Optional callback for when the drop-down is hidden.\n * @param opt_secondaryYOffset Optional Y offset for above-block positioning.\n * @returns True if the menu rendered below block; false if above.\n */\nexport function showPositionedByBlock(\n field: Field, block: BlockSvg, opt_onHide?: Function,\n opt_secondaryYOffset?: number): boolean {\n return showPositionedByRect(\n getScaledBboxOfBlock(block), field, opt_onHide, opt_secondaryYOffset);\n}\n\n/**\n * Shortcut to show and place the drop-down with positioning determined\n * by a particular field. The primary position will be below the field,\n * and the secondary position above the field. Drop-down will be\n * constrained to the block's workspace.\n *\n * @param field The field to position the dropdown against.\n * @param opt_onHide Optional callback for when the drop-down is hidden.\n * @param opt_secondaryYOffset Optional Y offset for above-block positioning.\n * @returns True if the menu rendered below block; false if above.\n */\nexport function showPositionedByField(\n field: Field, opt_onHide?: Function,\n opt_secondaryYOffset?: number): boolean {\n positionToField = true;\n return showPositionedByRect(\n getScaledBboxOfField(field), field, opt_onHide, opt_secondaryYOffset);\n}\n/**\n * Get the scaled bounding box of a block.\n *\n * @param block The block.\n * @returns The scaled bounding box of the block.\n */\nfunction getScaledBboxOfBlock(block: BlockSvg): Rect {\n const blockSvg = block.getSvgRoot();\n const scale = block.workspace.scale;\n const scaledHeight = block.height * scale;\n const scaledWidth = block.width * scale;\n const xy = style.getPageOffset(blockSvg);\n return new Rect(xy.y, xy.y + scaledHeight, xy.x, xy.x + scaledWidth);\n}\n\n/**\n * Get the scaled bounding box of a field.\n *\n * @param field The field.\n * @returns The scaled bounding box of the field.\n */\nfunction getScaledBboxOfField(field: Field): Rect {\n const bBox = field.getScaledBBox();\n return new Rect(bBox.top, bBox.bottom, bBox.left, bBox.right);\n}\n\n/**\n * Helper method to show and place the drop-down with positioning determined\n * by a scaled bounding box. The primary position will be below the rect,\n * and the secondary position above the rect. Drop-down will be constrained to\n * the block's workspace.\n *\n * @param bBox The scaled bounding box.\n * @param field The field to position the dropdown against.\n * @param opt_onHide Optional callback for when the drop-down is hidden.\n * @param opt_secondaryYOffset Optional Y offset for above-block positioning.\n * @returns True if the menu rendered below block; false if above.\n */\nfunction showPositionedByRect(\n bBox: Rect, field: Field, opt_onHide?: Function,\n opt_secondaryYOffset?: number): boolean {\n // If we can fit it, render below the block.\n const primaryX = bBox.left + (bBox.right - bBox.left) / 2;\n const primaryY = bBox.bottom;\n // If we can't fit it, render above the entire parent block.\n const secondaryX = primaryX;\n let secondaryY = bBox.top;\n if (opt_secondaryYOffset) {\n secondaryY += opt_secondaryYOffset;\n }\n const sourceBlock = field.getSourceBlock() as BlockSvg;\n // Set bounds to main workspace; show the drop-down.\n let workspace = sourceBlock.workspace;\n while (workspace.options.parentWorkspace) {\n workspace = workspace.options.parentWorkspace;\n }\n setBoundsElement(workspace.getParentSvg().parentNode as Element | null);\n return show(\n field, sourceBlock.RTL, primaryX, primaryY, secondaryX, secondaryY,\n opt_onHide);\n}\n\n/**\n * Show and place the drop-down.\n * The drop-down is placed with an absolute \"origin point\" (x, y) - i.e.,\n * the arrow will point at this origin and box will positioned below or above\n * it. If we can maintain the container bounds at the primary point, the arrow\n * will point there, and the container will be positioned below it.\n * If we can't maintain the container bounds at the primary point, fall-back to\n * the secondary point and position above.\n *\n * @param newOwner The object showing the drop-down\n * @param rtl Right-to-left (true) or left-to-right (false).\n * @param primaryX Desired origin point x, in absolute px.\n * @param primaryY Desired origin point y, in absolute px.\n * @param secondaryX Secondary/alternative origin point x, in absolute px.\n * @param secondaryY Secondary/alternative origin point y, in absolute px.\n * @param opt_onHide Optional callback for when the drop-down is hidden.\n * @returns True if the menu rendered at the primary origin point.\n * @internal\n */\nexport function show(\n newOwner: Field, rtl: boolean, primaryX: number, primaryY: number,\n secondaryX: number, secondaryY: number, opt_onHide?: Function): boolean {\n owner = newOwner;\n onHide = opt_onHide || null;\n // Set direction.\n div.style.direction = rtl ? 'rtl' : 'ltr';\n\n const mainWorkspace = common.getMainWorkspace() as WorkspaceSvg;\n renderedClassName = mainWorkspace.getRenderer().getClassName();\n themeClassName = mainWorkspace.getTheme().getClassName();\n if (renderedClassName) {\n dom.addClass(div, renderedClassName);\n }\n if (themeClassName) {\n dom.addClass(div, themeClassName);\n }\n\n // When we change `translate` multiple times in close succession,\n // Chrome may choose to wait and apply them all at once.\n // Since we want the translation to initial X, Y to be immediate,\n // and the translation to final X, Y to be animated,\n // we saw problems where both would be applied after animation was turned on,\n // making the dropdown appear to fly in from (0, 0).\n // Using both `left`, `top` for the initial translation and then `translate`\n // for the animated transition to final X, Y is a workaround.\n return positionInternal(primaryX, primaryY, secondaryX, secondaryY);\n}\n\nconst internal = {\n /**\n * Get sizing info about the bounding element.\n *\n * @returns An object containing size information about the bounding element\n * (bounding box and width/height).\n */\n getBoundsInfo: function(): BoundsInfo {\n const boundPosition = style.getPageOffset(boundsElement as Element);\n const boundSize = style.getSize(boundsElement as Element);\n\n return {\n left: boundPosition.x,\n right: boundPosition.x + boundSize.width,\n top: boundPosition.y,\n bottom: boundPosition.y + boundSize.height,\n width: boundSize.width,\n height: boundSize.height,\n };\n },\n\n /**\n * Helper to position the drop-down and the arrow, maintaining bounds.\n * See explanation of origin points in show.\n *\n * @param primaryX Desired origin point x, in absolute px.\n * @param primaryY Desired origin point y, in absolute px.\n * @param secondaryX Secondary/alternative origin point x, in absolute px.\n * @param secondaryY Secondary/alternative origin point y, in absolute px.\n * @returns Various final metrics, including rendered positions for drop-down\n * and arrow.\n */\n getPositionMetrics: function(\n primaryX: number, primaryY: number, secondaryX: number,\n secondaryY: number): PositionMetrics {\n const boundsInfo = internal.getBoundsInfo();\n const divSize = style.getSize(div as Element);\n\n // Can we fit in-bounds below the target?\n if (primaryY + divSize.height < boundsInfo.bottom) {\n return getPositionBelowMetrics(primaryX, primaryY, boundsInfo, divSize);\n }\n // Can we fit in-bounds above the target?\n if (secondaryY - divSize.height > boundsInfo.top) {\n return getPositionAboveMetrics(\n secondaryX, secondaryY, boundsInfo, divSize);\n }\n // Can we fit outside the workspace bounds (but inside the window)\n // below?\n if (primaryY + divSize.height < document.documentElement.clientHeight) {\n return getPositionBelowMetrics(primaryX, primaryY, boundsInfo, divSize);\n }\n // Can we fit outside the workspace bounds (but inside the window)\n // above?\n if (secondaryY - divSize.height > document.documentElement.clientTop) {\n return getPositionAboveMetrics(\n secondaryX, secondaryY, boundsInfo, divSize);\n }\n\n // Last resort, render at top of page.\n return getPositionTopOfPageMetrics(primaryX, boundsInfo, divSize);\n },\n};\n\n/**\n * Get the metrics for positioning the div below the source.\n *\n * @param primaryX Desired origin point x, in absolute px.\n * @param primaryY Desired origin point y, in absolute px.\n * @param boundsInfo An object containing size information about the bounding\n * element (bounding box and width/height).\n * @param divSize An object containing information about the size of the\n * DropDownDiv (width & height).\n * @returns Various final metrics, including rendered positions for drop-down\n * and arrow.\n */\nfunction getPositionBelowMetrics(\n primaryX: number, primaryY: number, boundsInfo: BoundsInfo,\n divSize: Size): PositionMetrics {\n const xCoords =\n getPositionX(primaryX, boundsInfo.left, boundsInfo.right, divSize.width);\n\n const arrowY = -(ARROW_SIZE / 2 + BORDER_SIZE);\n const finalY = primaryY + PADDING_Y;\n\n return {\n initialX: xCoords.divX,\n initialY: primaryY,\n finalX: xCoords.divX, // X position remains constant during animation.\n finalY,\n arrowX: xCoords.arrowX,\n arrowY,\n arrowAtTop: true,\n arrowVisible: true,\n };\n}\n\n/**\n * Get the metrics for positioning the div above the source.\n *\n * @param secondaryX Secondary/alternative origin point x, in absolute px.\n * @param secondaryY Secondary/alternative origin point y, in absolute px.\n * @param boundsInfo An object containing size information about the bounding\n * element (bounding box and width/height).\n * @param divSize An object containing information about the size of the\n * DropDownDiv (width & height).\n * @returns Various final metrics, including rendered positions for drop-down\n * and arrow.\n */\nfunction getPositionAboveMetrics(\n secondaryX: number, secondaryY: number, boundsInfo: BoundsInfo,\n divSize: Size): PositionMetrics {\n const xCoords = getPositionX(\n secondaryX, boundsInfo.left, boundsInfo.right, divSize.width);\n\n const arrowY = divSize.height - BORDER_SIZE * 2 - ARROW_SIZE / 2;\n const finalY = secondaryY - divSize.height - PADDING_Y;\n const initialY = secondaryY - divSize.height; // No padding on Y.\n\n return {\n initialX: xCoords.divX,\n initialY,\n finalX: xCoords.divX, // X position remains constant during animation.\n finalY,\n arrowX: xCoords.arrowX,\n arrowY,\n arrowAtTop: false,\n arrowVisible: true,\n };\n}\n\n/**\n * Get the metrics for positioning the div at the top of the page.\n *\n * @param sourceX Desired origin point x, in absolute px.\n * @param boundsInfo An object containing size information about the bounding\n * element (bounding box and width/height).\n * @param divSize An object containing information about the size of the\n * DropDownDiv (width & height).\n * @returns Various final metrics, including rendered positions for drop-down\n * and arrow.\n */\nfunction getPositionTopOfPageMetrics(\n sourceX: number, boundsInfo: BoundsInfo, divSize: Size): PositionMetrics {\n const xCoords =\n getPositionX(sourceX, boundsInfo.left, boundsInfo.right, divSize.width);\n\n // No need to provide arrow-specific information because it won't be visible.\n return {\n initialX: xCoords.divX,\n initialY: 0,\n finalX: xCoords.divX, // X position remains constant during animation.\n finalY: 0, // Y position remains constant during animation.\n arrowAtTop: null,\n arrowX: null,\n arrowY: null,\n arrowVisible: false,\n };\n}\n\n/**\n * Get the x positions for the left side of the DropDownDiv and the arrow,\n * accounting for the bounds of the workspace.\n *\n * @param sourceX Desired origin point x, in absolute px.\n * @param boundsLeft The left edge of the bounding element, in absolute px.\n * @param boundsRight The right edge of the bounding element, in absolute px.\n * @param divWidth The width of the div in px.\n * @returns An object containing metrics for the x positions of the left side of\n * the DropDownDiv and the arrow.\n * @internal\n */\nexport function getPositionX(\n sourceX: number, boundsLeft: number, boundsRight: number,\n divWidth: number): {divX: number, arrowX: number} {\n let divX = sourceX;\n // Offset the topLeft coord so that the dropdowndiv is centered.\n divX -= divWidth / 2;\n // Fit the dropdowndiv within the bounds of the workspace.\n divX = math.clamp(boundsLeft, divX, boundsRight - divWidth);\n\n let arrowX = sourceX;\n // Offset the arrow coord so that the arrow is centered.\n arrowX -= ARROW_SIZE / 2;\n // Convert the arrow position to be relative to the top left of the div.\n let relativeArrowX = arrowX - divX;\n const horizPadding = ARROW_HORIZONTAL_PADDING;\n // Clamp the arrow position so that it stays attached to the dropdowndiv.\n relativeArrowX = math.clamp(\n horizPadding, relativeArrowX, divWidth - horizPadding - ARROW_SIZE);\n\n return {arrowX: relativeArrowX, divX};\n}\n\n/**\n * Is the container visible?\n *\n * @returns True if visible.\n */\nexport function isVisible(): boolean {\n return !!owner;\n}\n\n/**\n * Hide the menu only if it is owned by the provided object.\n *\n * @param divOwner Object which must be owning the drop-down to hide.\n * @param opt_withoutAnimation True if we should hide the dropdown without\n * animating.\n * @returns True if hidden.\n */\nexport function hideIfOwner(\n divOwner: Field, opt_withoutAnimation?: boolean): boolean {\n if (owner === divOwner) {\n if (opt_withoutAnimation) {\n hideWithoutAnimation();\n } else {\n hide();\n }\n return true;\n }\n return false;\n}\n\n/** Hide the menu, triggering animation. */\nexport function hide() {\n // Start the animation by setting the translation and fading out.\n // Reset to (initialX, initialY) - i.e., no translation.\n div.style.transform = 'translate(0, 0)';\n div.style.opacity = '0';\n // Finish animation - reset all values to default.\n animateOutTimer = setTimeout(function() {\n hideWithoutAnimation();\n }, ANIMATION_TIME * 1000);\n if (onHide) {\n onHide();\n onHide = null;\n }\n}\n\n/** Hide the menu, without animation. */\nexport function hideWithoutAnimation() {\n if (!isVisible()) {\n return;\n }\n if (animateOutTimer) {\n clearTimeout(animateOutTimer);\n }\n\n // Reset style properties in case this gets called directly\n // instead of hide() - see discussion on #2551.\n div.style.transform = '';\n div.style.left = '';\n div.style.top = '';\n div.style.opacity = '0';\n div.style.display = 'none';\n div.style.backgroundColor = '';\n div.style.borderColor = '';\n\n if (onHide) {\n onHide();\n onHide = null;\n }\n clearContent();\n owner = null;\n\n if (renderedClassName) {\n dom.removeClass(div, renderedClassName);\n renderedClassName = '';\n }\n if (themeClassName) {\n dom.removeClass(div, themeClassName);\n themeClassName = '';\n }\n (common.getMainWorkspace() as WorkspaceSvg).markFocused();\n}\n\n/**\n * Set the dropdown div's position.\n *\n * @param primaryX Desired origin point x, in absolute px.\n * @param primaryY Desired origin point y, in absolute px.\n * @param secondaryX Secondary/alternative origin point x, in absolute px.\n * @param secondaryY Secondary/alternative origin point y, in absolute px.\n * @returns True if the menu rendered at the primary origin point.\n */\nfunction positionInternal(\n primaryX: number, primaryY: number, secondaryX: number,\n secondaryY: number): boolean {\n const metrics =\n internal.getPositionMetrics(primaryX, primaryY, secondaryX, secondaryY);\n\n // Update arrow CSS.\n if (metrics.arrowVisible) {\n arrow.style.display = '';\n arrow.style.transform = 'translate(' + metrics.arrowX + 'px,' +\n metrics.arrowY + 'px) rotate(45deg)';\n arrow.setAttribute(\n 'class',\n metrics.arrowAtTop ? 'blocklyDropDownArrow blocklyArrowTop' :\n 'blocklyDropDownArrow blocklyArrowBottom');\n } else {\n arrow.style.display = 'none';\n }\n\n const initialX = Math.floor(metrics.initialX);\n const initialY = Math.floor(metrics.initialY);\n const finalX = Math.floor(metrics.finalX);\n const finalY = Math.floor(metrics.finalY);\n\n // First apply initial translation.\n div.style.left = initialX + 'px';\n div.style.top = initialY + 'px';\n\n // Show the div.\n div.style.display = 'block';\n div.style.opacity = '1';\n // Add final translate, animated through `transition`.\n // Coordinates are relative to (initialX, initialY),\n // where the drop-down is absolutely positioned.\n const dx = finalX - initialX;\n const dy = finalY - initialY;\n div.style.transform = 'translate(' + dx + 'px,' + dy + 'px)';\n\n return !!metrics.arrowAtTop;\n}\n\n/**\n * Repositions the dropdownDiv on window resize. If it doesn't know how to\n * calculate the new position, it will just hide it instead.\n *\n * @internal\n */\nexport function repositionForWindowResize() {\n // This condition mainly catches the dropdown div when it is being used as a\n // dropdown. It is important not to close it in this case because on Android,\n // when a field is focused, the soft keyboard opens triggering a window resize\n // event and we want the dropdown div to stick around so users can type into\n // it.\n if (owner) {\n const block = owner.getSourceBlock() as BlockSvg;\n const bBox = positionToField ? getScaledBboxOfField(owner) :\n getScaledBboxOfBlock(block);\n // If we can fit it, render below the block.\n const primaryX = bBox.left + (bBox.right - bBox.left) / 2;\n const primaryY = bBox.bottom;\n // If we can't fit it, render above the entire parent block.\n const secondaryX = primaryX;\n const secondaryY = bBox.top;\n positionInternal(primaryX, primaryY, secondaryX, secondaryY);\n } else {\n hide();\n }\n}\n\nexport const TEST_ONLY = internal;\n","/**\n * @license\n * Copyright 2020 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * This file is a universal registry that provides generic methods\n * for registering and unregistering different types of classes.\n *\n * @namespace Blockly.registry\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.registry');\n\nimport type {Abstract} from './events/events_abstract.js';\nimport type {Field} from './field.js';\nimport type {IBlockDragger} from './interfaces/i_block_dragger.js';\nimport type {IConnectionChecker} from './interfaces/i_connection_checker.js';\nimport type {IFlyout} from './interfaces/i_flyout.js';\nimport type {IMetricsManager} from './interfaces/i_metrics_manager.js';\nimport type {ISerializer} from './interfaces/i_serializer.js';\nimport type {IToolbox} from './interfaces/i_toolbox.js';\nimport type {Cursor} from './keyboard_nav/cursor.js';\nimport type {Options} from './options.js';\nimport type {Renderer} from './renderers/common/renderer.js';\nimport type {Theme} from './theme.js';\nimport type {ToolboxItem} from './toolbox/toolbox_item.js';\n\n\n/**\n * A map of maps. With the keys being the type and name of the class we are\n * registering and the value being the constructor function.\n * e.g. {'field': {'field_angle': Blockly.FieldAngle}}\n */\nconst typeMap: {\n [key: string]:\n {[key: string]: (new () => AnyDuringMigration)|AnyDuringMigration}\n} = Object.create(null);\nexport const TEST_ONLY = {typeMap};\n\n/**\n * A map of maps. With the keys being the type and caseless name of the class we\n * are registring, and the value being the most recent cased name for that\n * registration.\n */\nconst nameMap: {[key: string]: {[key: string]: string}} = Object.create(null);\n\n/**\n * The string used to register the default class for a type of plugin.\n *\n * @alias Blockly.registry.DEFAULT\n */\nexport const DEFAULT = 'default';\n\n/**\n * A name with the type of the element stored in the generic.\n *\n * @alias Blockly.registry.Type\n */\nexport class Type<_T> {\n /** @param name The name of the registry type. */\n constructor(private readonly name: string) {}\n\n /**\n * Returns the name of the type.\n *\n * @returns The name.\n */\n toString(): string {\n return this.name;\n }\n\n static CONNECTION_CHECKER = new Type('connectionChecker');\n\n static CURSOR = new Type('cursor');\n\n static EVENT = new Type('event');\n\n static FIELD = new Type('field');\n\n static RENDERER = new Type('renderer');\n\n static TOOLBOX = new Type('toolbox');\n\n static THEME = new Type('theme');\n\n static TOOLBOX_ITEM = new Type('toolboxItem');\n\n static FLYOUTS_VERTICAL_TOOLBOX = new Type('flyoutsVerticalToolbox');\n\n static FLYOUTS_HORIZONTAL_TOOLBOX =\n new Type('flyoutsHorizontalToolbox');\n\n static METRICS_MANAGER = new Type('metricsManager');\n\n static BLOCK_DRAGGER = new Type('blockDragger');\n\n /** @internal */\n static SERIALIZER = new Type('serializer');\n}\n\n/**\n * Registers a class based on a type and name.\n *\n * @param type The type of the plugin.\n * (e.g. Field, Renderer)\n * @param name The plugin's name. (Ex. field_angle, geras)\n * @param registryItem The class or object to register.\n * @param opt_allowOverrides True to prevent an error when overriding an already\n * registered item.\n * @throws {Error} if the type or name is empty, a name with the given type has\n * already been registered, or if the given class or object is not valid for\n * its type.\n * @alias Blockly.registry.register\n */\nexport function register(\n type: string|Type, name: string,\n registryItem: (new (...p1: AnyDuringMigration[]) => T)|null|\n AnyDuringMigration,\n opt_allowOverrides?: boolean): void {\n if (!(type instanceof Type) && typeof type !== 'string' ||\n String(type).trim() === '') {\n throw Error(\n 'Invalid type \"' + type + '\". The type must be a' +\n ' non-empty string or a Blockly.registry.Type.');\n }\n type = String(type).toLowerCase();\n\n if (typeof name !== 'string' || name.trim() === '') {\n throw Error(\n 'Invalid name \"' + name + '\". The name must be a' +\n ' non-empty string.');\n }\n const caselessName = name.toLowerCase();\n if (!registryItem) {\n throw Error('Can not register a null value');\n }\n let typeRegistry = typeMap[type];\n let nameRegistry = nameMap[type];\n // If the type registry has not been created, create it.\n if (!typeRegistry) {\n typeRegistry = typeMap[type] = Object.create(null);\n nameRegistry = nameMap[type] = Object.create(null);\n }\n\n // Validate that the given class has all the required properties.\n validate(type, registryItem);\n\n // Don't throw an error if opt_allowOverrides is true.\n if (!opt_allowOverrides && typeRegistry[caselessName]) {\n throw Error(\n 'Name \"' + caselessName + '\" with type \"' + type +\n '\" already registered.');\n }\n typeRegistry[caselessName] = registryItem;\n nameRegistry[caselessName] = name;\n}\n\n/**\n * Checks the given registry item for properties that are required based on the\n * type.\n *\n * @param type The type of the plugin. (e.g. Field, Renderer)\n * @param registryItem A class or object that we are checking for the required\n * properties.\n */\nfunction validate(type: string, registryItem: Function|AnyDuringMigration) {\n switch (type) {\n case String(Type.FIELD):\n if (typeof registryItem.fromJson !== 'function') {\n throw Error('Type \"' + type + '\" must have a fromJson function');\n }\n break;\n }\n}\n\n/**\n * Unregisters the registry item with the given type and name.\n *\n * @param type The type of the plugin.\n * (e.g. Field, Renderer)\n * @param name The plugin's name. (Ex. field_angle, geras)\n * @alias Blockly.registry.unregister\n */\nexport function unregister(type: string|Type, name: string) {\n type = String(type).toLowerCase();\n name = name.toLowerCase();\n const typeRegistry = typeMap[type];\n if (!typeRegistry || !typeRegistry[name]) {\n console.warn(\n 'Unable to unregister [' + name + '][' + type + '] from the ' +\n 'registry.');\n return;\n }\n delete typeMap[type][name];\n delete nameMap[type][name];\n}\n\n/**\n * Gets the registry item for the given name and type. This can be either a\n * class or an object.\n *\n * @param type The type of the plugin.\n * (e.g. Field, Renderer)\n * @param name The plugin's name. (Ex. field_angle, geras)\n * @param opt_throwIfMissing Whether or not to throw an error if we are unable\n * to find the plugin.\n * @returns The class or object with the given name and type or null if none\n * exists.\n */\nfunction getItem(\n type: string|Type, name: string, opt_throwIfMissing?: boolean):\n (new (...p1: AnyDuringMigration[]) => T)|null|AnyDuringMigration {\n type = String(type).toLowerCase();\n name = name.toLowerCase();\n const typeRegistry = typeMap[type];\n if (!typeRegistry || !typeRegistry[name]) {\n const msg = 'Unable to find [' + name + '][' + type + '] in the registry.';\n if (opt_throwIfMissing) {\n throw new Error(\n msg + ' You must require or register a ' + type + ' plugin.');\n } else {\n console.warn(msg);\n }\n return null;\n }\n return typeRegistry[name];\n}\n\n/**\n * Returns whether or not the registry contains an item with the given type and\n * name.\n *\n * @param type The type of the plugin.\n * (e.g. Field, Renderer)\n * @param name The plugin's name. (Ex. field_angle, geras)\n * @returns True if the registry has an item with the given type and name, false\n * otherwise.\n * @alias Blockly.registry.hasItem\n */\nexport function hasItem(type: string|Type, name: string): boolean {\n type = String(type).toLowerCase();\n name = name.toLowerCase();\n const typeRegistry = typeMap[type];\n if (!typeRegistry) {\n return false;\n }\n return !!typeRegistry[name];\n}\n\n/**\n * Gets the class for the given name and type.\n *\n * @param type The type of the plugin.\n * (e.g. Field, Renderer)\n * @param name The plugin's name. (Ex. field_angle, geras)\n * @param opt_throwIfMissing Whether or not to throw an error if we are unable\n * to find the plugin.\n * @returns The class with the given name and type or null if none exists.\n * @alias Blockly.registry.getClass\n */\nexport function getClass(\n type: string|Type, name: string, opt_throwIfMissing?: boolean):\n (new (...p1: AnyDuringMigration[]) => T)|null {\n return getItem(type, name, opt_throwIfMissing) as (\n new (...p1: AnyDuringMigration[]) => T) |\n null;\n}\n\n/**\n * Gets the object for the given name and type.\n *\n * @param type The type of the plugin.\n * (e.g. Category)\n * @param name The plugin's name. (Ex. logic_category)\n * @param opt_throwIfMissing Whether or not to throw an error if we are unable\n * to find the object.\n * @returns The object with the given name and type or null if none exists.\n * @alias Blockly.registry.getObject\n */\nexport function getObject(\n type: string|Type, name: string, opt_throwIfMissing?: boolean): T|null {\n return getItem(type, name, opt_throwIfMissing) as T;\n}\n\n/**\n * Returns a map of items registered with the given type.\n *\n * @param type The type of the plugin. (e.g. Category)\n * @param opt_cased Whether or not to return a map with cased keys (rather than\n * caseless keys). False by default.\n * @param opt_throwIfMissing Whether or not to throw an error if we are unable\n * to find the object. False by default.\n * @returns A map of objects with the given type, or null if none exists.\n * @alias Blockly.registry.getAllItems\n */\nexport function getAllItems(\n type: string|Type, opt_cased?: boolean, opt_throwIfMissing?: boolean):\n {[key: string]: T|null|(new (...p1: AnyDuringMigration[]) => T)}|null {\n type = String(type).toLowerCase();\n const typeRegistry = typeMap[type];\n if (!typeRegistry) {\n const msg = `Unable to find [${type}] in the registry.`;\n if (opt_throwIfMissing) {\n throw new Error(`${msg} You must require or register a ${type} plugin.`);\n } else {\n console.warn(msg);\n }\n return null;\n }\n if (!opt_cased) {\n return typeRegistry;\n }\n const nameRegistry = nameMap[type];\n const casedRegistry = Object.create(null);\n const keys = Object.keys(typeRegistry);\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n casedRegistry[nameRegistry[key]] = typeRegistry[key];\n }\n return casedRegistry;\n}\n\n/**\n * Gets the class from Blockly options for the given type.\n * This is used for plugins that override a built in feature. (e.g. Toolbox)\n *\n * @param type The type of the plugin.\n * @param options The option object to check for the given plugin.\n * @param opt_throwIfMissing Whether or not to throw an error if we are unable\n * to find the plugin.\n * @returns The class for the plugin.\n * @alias Blockly.registry.getClassFromOptions\n */\nexport function getClassFromOptions(\n type: Type, options: Options, opt_throwIfMissing?: boolean):\n (new (...p1: AnyDuringMigration[]) => T)|null {\n const typeName = type.toString();\n const plugin = options.plugins[typeName] || DEFAULT;\n\n // If the user passed in a plugin class instead of a registered plugin name.\n if (typeof plugin === 'function') {\n return plugin;\n }\n return getClass(type, plugin, opt_throwIfMissing);\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Generators for unique IDs.\n *\n * @namespace Blockly.utils.idGenerator\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.idGenerator');\n\n/**\n * Legal characters for the universally unique IDs. Should be all on\n * a US keyboard. No characters that conflict with XML or JSON.\n * Requests to remove additional 'problematic' characters from this\n * soup will be denied. That's your failure to properly escape in\n * your own environment. Issues #251, #625, #682, #1304.\n */\nconst soup = '!#$%()*+,-./:;=?@[]^_`{|}~' +\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\n/**\n * Namespace object for internal implementations we want to be able to\n * stub in tests. Do not use externally.\n *\n * @internal\n */\nconst internal = {\n /**\n * Generate a random unique ID. This should be globally unique.\n * 87 characters ^ 20 length is greater than 128 bits (better than a UUID).\n *\n * @returns A globally unique ID string.\n */\n genUid: () => {\n const length = 20;\n const soupLength = soup.length;\n const id = [];\n for (let i = 0; i < length; i++) {\n id[i] = soup.charAt(Math.random() * soupLength);\n }\n return id.join('');\n },\n};\nexport const TEST_ONLY = internal;\n\n/** Next unique ID to use. */\nlet nextId = 0;\n\n/**\n * Generate the next unique element IDs.\n * IDs are compatible with the HTML4 'id' attribute restrictions:\n * Use only ASCII letters, digits, '_', '-' and '.'\n *\n * For UUIDs use genUid (below) instead; this ID generator should\n * primarily be used for IDs that end up in the DOM.\n *\n * @returns The next unique identifier.\n * @alias Blockly.utils.idGenerator.getNextUniqueId\n */\nexport function getNextUniqueId(): string {\n return 'blockly-' + (nextId++).toString(36);\n}\n\n/**\n * Generate a random unique ID.\n *\n * @see internal.genUid\n * @returns A globally unique ID string.\n * @alias Blockly.utils.idGenerator.genUid\n */\nexport function genUid(): string {\n return internal.genUid();\n}\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Helper methods for events that are fired as a result of\n * actions in Blockly's editor.\n *\n * @namespace Blockly.Events.utils\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.Events.utils');\n\nimport type {Block} from '../block.js';\nimport * as common from '../common.js';\nimport * as registry from '../registry.js';\nimport * as idGenerator from '../utils/idgenerator.js';\nimport type {Workspace} from '../workspace.js';\nimport type {WorkspaceSvg} from '../workspace_svg.js';\n\nimport type {Abstract} from './events_abstract.js';\nimport type {BlockChange} from './events_block_change.js';\nimport type {BlockCreate} from './events_block_create.js';\nimport type {BlockMove} from './events_block_move.js';\nimport type {CommentCreate} from './events_comment_create.js';\nimport type {CommentMove} from './events_comment_move.js';\nimport type {ViewportChange} from './events_viewport.js';\n\n\n/** Group ID for new events. Grouped events are indivisible. */\nlet group = '';\n\n/** Sets whether the next event should be added to the undo stack. */\nlet recordUndo = true;\n\n/**\n * Sets whether events should be added to the undo stack.\n *\n * @param newValue True if events should be added to the undo stack.\n * @alias Blockly.Events.utils.setRecordUndo\n */\nexport function setRecordUndo(newValue: boolean) {\n recordUndo = newValue;\n}\n\n/**\n * Returns whether or not events will be added to the undo stack.\n *\n * @returns True if events will be added to the undo stack.\n * @alias Blockly.Events.utils.getRecordUndo\n */\nexport function getRecordUndo(): boolean {\n return recordUndo;\n}\n\n/** Allow change events to be created and fired. */\nlet disabled = 0;\n\n/**\n * Name of event that creates a block. Will be deprecated for BLOCK_CREATE.\n *\n * @alias Blockly.Events.utils.CREATE\n */\nexport const CREATE = 'create';\n\n/**\n * Name of event that creates a block.\n *\n * @alias Blockly.Events.utils.BLOCK_CREATE\n */\nexport const BLOCK_CREATE = CREATE;\n\n/**\n * Name of event that deletes a block. Will be deprecated for BLOCK_DELETE.\n *\n * @alias Blockly.Events.utils.DELETE\n */\nexport const DELETE = 'delete';\n\n/**\n * Name of event that deletes a block.\n *\n * @alias Blockly.Events.utils.BLOCK_DELETE\n */\nexport const BLOCK_DELETE = DELETE;\n\n/**\n * Name of event that changes a block. Will be deprecated for BLOCK_CHANGE.\n *\n * @alias Blockly.Events.utils.CHANGE\n */\nexport const CHANGE = 'change';\n\n/**\n * Name of event that changes a block.\n *\n * @alias Blockly.Events.utils.BLOCK_CHANGE\n */\nexport const BLOCK_CHANGE = CHANGE;\n\n/**\n * Name of event that moves a block. Will be deprecated for BLOCK_MOVE.\n *\n * @alias Blockly.Events.utils.MOVE\n */\nexport const MOVE = 'move';\n\n/**\n * Name of event that moves a block.\n *\n * @alias Blockly.Events.utils.BLOCK_MOVE\n */\nexport const BLOCK_MOVE = MOVE;\n\n/**\n * Name of event that creates a variable.\n *\n * @alias Blockly.Events.utils.VAR_CREATE\n */\nexport const VAR_CREATE = 'var_create';\n\n/**\n * Name of event that deletes a variable.\n *\n * @alias Blockly.Events.utils.VAR_DELETE\n */\nexport const VAR_DELETE = 'var_delete';\n\n/**\n * Name of event that renames a variable.\n *\n * @alias Blockly.Events.utils.VAR_RENAME\n */\nexport const VAR_RENAME = 'var_rename';\n\n/**\n * Name of generic event that records a UI change.\n *\n * @alias Blockly.Events.utils.UI\n */\nexport const UI = 'ui';\n\n/**\n * Name of event that record a block drags a block.\n *\n * @alias Blockly.Events.utils.BLOCK_DRAG\n */\nexport const BLOCK_DRAG = 'drag';\n\n/**\n * Name of event that records a change in selected element.\n *\n * @alias Blockly.Events.utils.SELECTED\n */\nexport const SELECTED = 'selected';\n\n/**\n * Name of event that records a click.\n *\n * @alias Blockly.Events.utils.CLICK\n */\nexport const CLICK = 'click';\n\n/**\n * Name of event that records a marker move.\n *\n * @alias Blockly.Events.utils.MARKER_MOVE\n */\nexport const MARKER_MOVE = 'marker_move';\n\n/**\n * Name of event that records a bubble open.\n *\n * @alias Blockly.Events.utils.BUBBLE_OPEN\n */\nexport const BUBBLE_OPEN = 'bubble_open';\n\n/**\n * Name of event that records a trashcan open.\n *\n * @alias Blockly.Events.utils.TRASHCAN_OPEN\n */\nexport const TRASHCAN_OPEN = 'trashcan_open';\n\n/**\n * Name of event that records a toolbox item select.\n *\n * @alias Blockly.Events.utils.TOOLBOX_ITEM_SELECT\n */\nexport const TOOLBOX_ITEM_SELECT = 'toolbox_item_select';\n\n/**\n * Name of event that records a theme change.\n *\n * @alias Blockly.Events.utils.THEME_CHANGE\n */\nexport const THEME_CHANGE = 'theme_change';\n\n/**\n * Name of event that records a viewport change.\n *\n * @alias Blockly.Events.utils.VIEWPORT_CHANGE\n */\nexport const VIEWPORT_CHANGE = 'viewport_change';\n\n/**\n * Name of event that creates a comment.\n *\n * @alias Blockly.Events.utils.COMMENT_CREATE\n */\nexport const COMMENT_CREATE = 'comment_create';\n\n/**\n * Name of event that deletes a comment.\n *\n * @alias Blockly.Events.utils.COMMENT_DELETE\n */\nexport const COMMENT_DELETE = 'comment_delete';\n\n/**\n * Name of event that changes a comment.\n *\n * @alias Blockly.Events.utils.COMMENT_CHANGE\n */\nexport const COMMENT_CHANGE = 'comment_change';\n\n/**\n * Name of event that moves a comment.\n *\n * @alias Blockly.Events.utils.COMMENT_MOVE\n */\nexport const COMMENT_MOVE = 'comment_move';\n\n/**\n * Name of event that records a workspace load.\n *\n * @alias Blockly.Events.utils.FINISHED_LOADING\n */\nexport const FINISHED_LOADING = 'finished_loading';\n\n/**\n * Type of events that cause objects to be bumped back into the visible\n * portion of the workspace.\n *\n * Not to be confused with bumping so that disconnected connections do not\n * appear connected.\n *\n * @alias Blockly.Events.utils.BumpEvent\n */\nexport type BumpEvent = BlockCreate|BlockMove|CommentCreate|CommentMove;\n\n/**\n * List of events that cause objects to be bumped back into the visible\n * portion of the workspace.\n *\n * Not to be confused with bumping so that disconnected connections do not\n * appear connected.\n *\n * @alias Blockly.Events.utils.BUMP_EVENTS\n */\nexport const BUMP_EVENTS: string[] =\n [BLOCK_CREATE, BLOCK_MOVE, COMMENT_CREATE, COMMENT_MOVE];\n\n/** List of events queued for firing. */\nconst FIRE_QUEUE: Abstract[] = [];\n\n/**\n * Create a custom event and fire it.\n *\n * @param event Custom data for event.\n * @alias Blockly.Events.utils.fire\n */\nexport function fire(event: Abstract) {\n TEST_ONLY.fireInternal(event);\n}\n\n/**\n * Private version of fireInternal for stubbing in tests.\n */\nfunction fireInternal(event: Abstract) {\n if (!isEnabled()) {\n return;\n }\n if (!FIRE_QUEUE.length) {\n // First event added; schedule a firing of the event queue.\n setTimeout(fireNow, 0);\n }\n FIRE_QUEUE.push(event);\n}\n\n\n/** Fire all queued events. */\nfunction fireNow() {\n const queue = filter(FIRE_QUEUE, true);\n FIRE_QUEUE.length = 0;\n for (let i = 0, event; event = queue[i]; i++) {\n if (!event.workspaceId) {\n continue;\n }\n const eventWorkspace = common.getWorkspaceById(event.workspaceId);\n if (eventWorkspace) {\n eventWorkspace.fireChangeListener(event);\n }\n }\n}\n\n/**\n * Filter the queued events and merge duplicates.\n *\n * @param queueIn Array of events.\n * @param forward True if forward (redo), false if backward (undo).\n * @returns Array of filtered events.\n * @alias Blockly.Events.utils.filter\n */\nexport function filter(queueIn: Abstract[], forward: boolean): Abstract[] {\n let queue = queueIn.slice();\n // Shallow copy of queue.\n if (!forward) {\n // Undo is merged in reverse order.\n queue.reverse();\n }\n const mergedQueue = [];\n const hash = Object.create(null);\n // Merge duplicates.\n for (let i = 0, event; event = queue[i]; i++) {\n if (!event.isNull()) {\n // Treat all UI events as the same type in hash table.\n const eventType = event.isUiEvent ? UI : event.type;\n // TODO(#5927): Check whether `blockId` exists before accessing it.\n const blockId = (event as AnyDuringMigration).blockId;\n const key = [eventType, blockId, event.workspaceId].join(' ');\n\n const lastEntry = hash[key];\n const lastEvent = lastEntry ? lastEntry.event : null;\n if (!lastEntry) {\n // Each item in the hash table has the event and the index of that event\n // in the input array. This lets us make sure we only merge adjacent\n // move events.\n hash[key] = {event, index: i};\n mergedQueue.push(event);\n } else if (event.type === MOVE && lastEntry.index === i - 1) {\n const moveEvent = event as BlockMove;\n // Merge move events.\n lastEvent.newParentId = moveEvent.newParentId;\n lastEvent.newInputName = moveEvent.newInputName;\n lastEvent.newCoordinate = moveEvent.newCoordinate;\n lastEntry.index = i;\n } else if (\n event.type === CHANGE &&\n (event as BlockChange).element === lastEvent.element &&\n (event as BlockChange).name === lastEvent.name) {\n const changeEvent = event as BlockChange;\n // Merge change events.\n lastEvent.newValue = changeEvent.newValue;\n } else if (event.type === VIEWPORT_CHANGE) {\n const viewportEvent = event as ViewportChange;\n // Merge viewport change events.\n lastEvent.viewTop = viewportEvent.viewTop;\n lastEvent.viewLeft = viewportEvent.viewLeft;\n lastEvent.scale = viewportEvent.scale;\n lastEvent.oldScale = viewportEvent.oldScale;\n } else if (event.type === CLICK && lastEvent.type === BUBBLE_OPEN) {\n // Drop click events caused by opening/closing bubbles.\n } else {\n // Collision: newer events should merge into this event to maintain\n // order.\n hash[key] = {event, index: i};\n mergedQueue.push(event);\n }\n }\n }\n // Filter out any events that have become null due to merging.\n queue = mergedQueue.filter(function(e) {\n return !e.isNull();\n });\n if (!forward) {\n // Restore undo order.\n queue.reverse();\n }\n // Move mutation events to the top of the queue.\n // Intentionally skip first event.\n for (let i = 1, event; event = queue[i]; i++) {\n // AnyDuringMigration because: Property 'element' does not exist on type\n // 'Abstract'.\n if (event.type === CHANGE &&\n (event as AnyDuringMigration).element === 'mutation') {\n queue.unshift(queue.splice(i, 1)[0]);\n }\n }\n return queue;\n}\n\n/**\n * Modify pending undo events so that when they are fired they don't land\n * in the undo stack. Called by Workspace.clearUndo.\n *\n * @alias Blockly.Events.utils.clearPendingUndo\n */\nexport function clearPendingUndo() {\n for (let i = 0, event; event = FIRE_QUEUE[i]; i++) {\n event.recordUndo = false;\n }\n}\n\n/**\n * Stop sending events. Every call to this function MUST also call enable.\n *\n * @alias Blockly.Events.utils.disable\n */\nexport function disable() {\n disabled++;\n}\n\n/**\n * Start sending events. Unless events were already disabled when the\n * corresponding call to disable was made.\n *\n * @alias Blockly.Events.utils.enable\n */\nexport function enable() {\n disabled--;\n}\n\n/**\n * Returns whether events may be fired or not.\n *\n * @returns True if enabled.\n * @alias Blockly.Events.utils.isEnabled\n */\nexport function isEnabled(): boolean {\n return disabled === 0;\n}\n\n/**\n * Current group.\n *\n * @returns ID string.\n * @alias Blockly.Events.utils.getGroup\n */\nexport function getGroup(): string {\n return group;\n}\n\n/**\n * Start or stop a group.\n *\n * @param state True to start new group, false to end group.\n * String to set group explicitly.\n * @alias Blockly.Events.utils.setGroup\n */\nexport function setGroup(state: boolean|string) {\n TEST_ONLY.setGroupInternal(state);\n}\n\n/**\n * Private version of setGroup for stubbing in tests.\n */\nfunction setGroupInternal(state: boolean|string) {\n if (typeof state === 'boolean') {\n group = state ? idGenerator.genUid() : '';\n } else {\n group = state;\n }\n}\n\n/**\n * Compute a list of the IDs of the specified block and all its descendants.\n *\n * @param block The root block.\n * @returns List of block IDs.\n * @alias Blockly.Events.utils.getDescendantIds\n * @internal\n */\nexport function getDescendantIds(block: Block): string[] {\n const ids = [];\n const descendants = block.getDescendants(false);\n for (let i = 0, descendant; descendant = descendants[i]; i++) {\n ids[i] = descendant.id;\n }\n return ids;\n}\n\n/**\n * Decode the JSON into an event.\n *\n * @param json JSON representation.\n * @param workspace Target workspace for event.\n * @returns The event represented by the JSON.\n * @throws {Error} if an event type is not found in the registry.\n * @alias Blockly.Events.utils.fromJson\n */\nexport function fromJson(\n json: AnyDuringMigration, workspace: Workspace): Abstract {\n const eventClass = get(json['type']);\n if (!eventClass) {\n throw Error('Unknown event type.');\n }\n const event = new eventClass();\n event.fromJson(json);\n event.workspaceId = workspace.id;\n return event;\n}\n\n/**\n * Gets the class for a specific event type from the registry.\n *\n * @param eventType The type of the event to get.\n * @returns The event class with the given type.\n * @alias Blockly.Events.utils.get\n */\nexport function get(eventType: string):\n (new (...p1: AnyDuringMigration[]) => Abstract) {\n const event = registry.getClass(registry.Type.EVENT, eventType);\n if (!event) {\n throw new Error(`Event type ${eventType} not found in registry.`);\n }\n return event;\n}\n\n/**\n * Enable/disable a block depending on whether it is properly connected.\n * Use this on applications where all blocks should be connected to a top block.\n * Recommend setting the 'disable' option to 'false' in the config so that\n * users don't try to re-enable disabled orphan blocks.\n *\n * @param event Custom data for event.\n * @alias Blockly.Events.utils.disableOrphans\n */\nexport function disableOrphans(event: Abstract) {\n if (event.type === MOVE || event.type === CREATE) {\n const blockEvent = event as BlockMove | BlockCreate;\n if (!blockEvent.workspaceId) {\n return;\n }\n const eventWorkspace =\n common.getWorkspaceById(blockEvent.workspaceId) as WorkspaceSvg;\n if (!blockEvent.blockId) {\n throw new Error('Encountered a blockEvent without a proper blockId');\n }\n let block = eventWorkspace.getBlockById(blockEvent.blockId);\n if (block) {\n // Changing blocks as part of this event shouldn't be undoable.\n const initialUndoFlag = recordUndo;\n try {\n recordUndo = false;\n const parent = block.getParent();\n if (parent && parent.isEnabled()) {\n const children = block.getDescendants(false);\n for (let i = 0, child; child = children[i]; i++) {\n child.setEnabled(true);\n }\n } else if (\n (block.outputConnection || block.previousConnection) &&\n !eventWorkspace.isDragging()) {\n do {\n block.setEnabled(false);\n block = block.getNextBlock();\n } while (block);\n }\n } finally {\n recordUndo = initialUndoFlag;\n }\n }\n }\n}\n\nexport const TEST_ONLY = {\n FIRE_QUEUE,\n fireNow,\n fireInternal,\n setGroupInternal,\n};\n","/**\n * @license\n * Copyright 2018 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * XML element manipulation.\n * These methods are not specific to Blockly, and could be factored out into\n * a JavaScript framework such as Closure.\n *\n * @namespace Blockly.utils.xml\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.xml');\n\n\n/**\n * Namespace for Blockly's XML.\n *\n * @alias Blockly.utils.xml.NAME_SPACE\n */\nexport const NAME_SPACE = 'https://developers.google.com/blockly/xml';\n\n/**\n * The Document object to use. By default this is just document, but\n * the Node.js build of Blockly (see scripts/package/node/core.js)\n * calls setDocument to supply a Document implementation from the\n * jsdom package instead.\n */\nlet xmlDocument: Document = globalThis['document'];\n\n/**\n * Get the document object to use for XML serialization.\n *\n * @returns The document object.\n * @alias Blockly.utils.xml.getDocument\n */\nexport function getDocument(): Document {\n return xmlDocument;\n}\n\n/**\n * Get the document object to use for XML serialization.\n *\n * @param document The document object to use.\n * @alias Blockly.utils.xml.setDocument\n */\nexport function setDocument(document: Document) {\n xmlDocument = document;\n}\n\n/**\n * Create DOM element for XML.\n *\n * @param tagName Name of DOM element.\n * @returns New DOM element.\n * @alias Blockly.utils.xml.createElement\n */\nexport function createElement(tagName: string): Element {\n return xmlDocument.createElementNS(NAME_SPACE, tagName);\n}\n\n/**\n * Create text element for XML.\n *\n * @param text Text content.\n * @returns New DOM text node.\n * @alias Blockly.utils.xml.createTextNode\n */\nexport function createTextNode(text: string): Text {\n return xmlDocument.createTextNode(text);\n}\n\n/**\n * Converts an XML string into a DOM tree.\n *\n * @param text XML string.\n * @returns The DOM document.\n * @throws if XML doesn't parse.\n * @alias Blockly.utils.xml.textToDomDocument\n */\nexport function textToDomDocument(text: string): Document {\n const oParser = new DOMParser();\n return oParser.parseFromString(text, 'text/xml');\n}\n\n/**\n * Converts a DOM structure into plain text.\n * Currently the text format is fairly ugly: all one line with no whitespace.\n *\n * @param dom A tree of XML nodes.\n * @returns Text representation.\n * @alias Blockly.utils.xml.domToText\n */\nexport function domToText(dom: Node): string {\n const oSerializer = new XMLSerializer();\n return oSerializer.serializeToString(dom);\n}\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Wrapper functions around JS functions for showing alert/confirmation dialogs.\n *\n * @namespace Blockly.dialog\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.dialog');\n\n\nlet alertImplementation = function(message: string, opt_callback?: () => void) {\n window.alert(message);\n if (opt_callback) {\n opt_callback();\n }\n};\n\nlet confirmImplementation = function(\n message: string, callback: (result: boolean) => void) {\n callback(window.confirm(message));\n};\n\nlet promptImplementation = function(\n message: string, defaultValue: string,\n callback: (result: string|null) => void) {\n callback(window.prompt(message, defaultValue));\n};\n\n/**\n * Wrapper to window.alert() that app developers may override via setAlert to\n * provide alternatives to the modal browser window.\n *\n * @param message The message to display to the user.\n * @param opt_callback The callback when the alert is dismissed.\n * @alias Blockly.dialog.alert\n */\nexport function alert(message: string, opt_callback?: () => void) {\n alertImplementation(message, opt_callback);\n}\n\n/**\n * Sets the function to be run when Blockly.dialog.alert() is called.\n *\n * @param alertFunction The function to be run.\n * @see Blockly.dialog.alert\n * @alias Blockly.dialog.setAlert\n */\nexport function setAlert(alertFunction: (p1: string, p2?: () => void) => void) {\n alertImplementation = alertFunction;\n}\n\n/**\n * Wrapper to window.confirm() that app developers may override via setConfirm\n * to provide alternatives to the modal browser window.\n *\n * @param message The message to display to the user.\n * @param callback The callback for handling user response.\n * @alias Blockly.dialog.confirm\n */\nexport function confirm(message: string, callback: (p1: boolean) => void) {\n TEST_ONLY.confirmInternal(message, callback);\n}\n\n/**\n * Private version of confirm for stubbing in tests.\n */\nfunction confirmInternal(message: string, callback: (p1: boolean) => void) {\n confirmImplementation(message, callback);\n}\n\n\n/**\n * Sets the function to be run when Blockly.dialog.confirm() is called.\n *\n * @param confirmFunction The function to be run.\n * @see Blockly.dialog.confirm\n * @alias Blockly.dialog.setConfirm\n */\nexport function setConfirm(\n confirmFunction: (p1: string, p2: (p1: boolean) => void) => void) {\n confirmImplementation = confirmFunction;\n}\n\n/**\n * Wrapper to window.prompt() that app developers may override via setPrompt to\n * provide alternatives to the modal browser window. Built-in browser prompts\n * are often used for better text input experience on mobile device. We strongly\n * recommend testing mobile when overriding this.\n *\n * @param message The message to display to the user.\n * @param defaultValue The value to initialize the prompt with.\n * @param callback The callback for handling user response.\n * @alias Blockly.dialog.prompt\n */\nexport function prompt(\n message: string, defaultValue: string,\n callback: (p1: string|null) => void) {\n promptImplementation(message, defaultValue, callback);\n}\n\n/**\n * Sets the function to be run when Blockly.dialog.prompt() is called.\n *\n * @param promptFunction The function to be run.\n * @see Blockly.dialog.prompt\n * @alias Blockly.dialog.setPrompt\n */\nexport function setPrompt(\n promptFunction: (p1: string, p2: string, p3: (p1: string|null) => void) =>\n void) {\n promptImplementation = promptFunction;\n}\n\nexport const TEST_ONLY = {\n confirmInternal,\n};\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility functions for handling variables.\n *\n * @namespace Blockly.Variables\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.Variables');\n\nimport {Blocks} from './blocks.js';\nimport * as dialog from './dialog.js';\nimport {Msg} from './msg.js';\nimport * as utilsXml from './utils/xml.js';\nimport {VariableModel} from './variable_model.js';\nimport type {Workspace} from './workspace.js';\nimport type {WorkspaceSvg} from './workspace_svg.js';\nimport * as Xml from './xml.js';\n\n\n/**\n * String for use in the \"custom\" attribute of a category in toolbox XML.\n * This string indicates that the category should be dynamically populated with\n * variable blocks.\n * See also Blockly.Procedures.CATEGORY_NAME and\n * Blockly.VariablesDynamic.CATEGORY_NAME.\n *\n * @alias Blockly.Variables.CATEGORY_NAME\n */\nexport const CATEGORY_NAME = 'VARIABLE';\n\n/**\n * Find all user-created variables that are in use in the workspace.\n * For use by generators.\n * To get a list of all variables on a workspace, including unused variables,\n * call Workspace.getAllVariables.\n *\n * @param ws The workspace to search for variables.\n * @returns Array of variable models.\n * @alias Blockly.Variables.allUsedVarModels\n */\nexport function allUsedVarModels(ws: Workspace): VariableModel[] {\n const blocks = ws.getAllBlocks(false);\n const variables = new Set();\n // Iterate through every block and add each variable to the set.\n for (let i = 0; i < blocks.length; i++) {\n const blockVariables = blocks[i].getVarModels();\n if (blockVariables) {\n for (let j = 0; j < blockVariables.length; j++) {\n const variable = blockVariables[j];\n const id = variable.getId();\n if (id) {\n variables.add(variable);\n }\n }\n }\n }\n // Convert the set into a list.\n return Array.from(variables.values());\n}\n\n/**\n * Find all developer variables used by blocks in the workspace.\n * Developer variables are never shown to the user, but are declared as global\n * variables in the generated code.\n * To declare developer variables, define the getDeveloperVariables function on\n * your block and return a list of variable names.\n * For use by generators.\n *\n * @param workspace The workspace to search.\n * @returns A list of non-duplicated variable names.\n * @alias Blockly.Variables.allDeveloperVariables\n */\nexport function allDeveloperVariables(workspace: Workspace): string[] {\n const blocks = workspace.getAllBlocks(false);\n const variables = new Set();\n for (let i = 0, block; block = blocks[i]; i++) {\n const getDeveloperVariables = block.getDeveloperVariables;\n if (getDeveloperVariables) {\n const devVars = getDeveloperVariables();\n for (let j = 0; j < devVars.length; j++) {\n variables.add(devVars[j]);\n }\n }\n }\n // Convert the set into a list.\n return Array.from(variables.values());\n}\n\n/**\n * Construct the elements (blocks and button) required by the flyout for the\n * variable category.\n *\n * @param workspace The workspace containing variables.\n * @returns Array of XML elements.\n * @alias Blockly.Variables.flyoutCategory\n */\nexport function flyoutCategory(workspace: WorkspaceSvg): Element[] {\n let xmlList = new Array();\n const button = document.createElement('button');\n button.setAttribute('text', '%{BKY_NEW_VARIABLE}');\n button.setAttribute('callbackKey', 'CREATE_VARIABLE');\n\n workspace.registerButtonCallback('CREATE_VARIABLE', function(button) {\n createVariableButtonHandler(button.getTargetWorkspace());\n });\n\n xmlList.push(button);\n\n const blockList = flyoutCategoryBlocks(workspace);\n xmlList = xmlList.concat(blockList);\n return xmlList;\n}\n\n/**\n * Construct the blocks required by the flyout for the variable category.\n *\n * @param workspace The workspace containing variables.\n * @returns Array of XML block elements.\n * @alias Blockly.Variables.flyoutCategoryBlocks\n */\nexport function flyoutCategoryBlocks(workspace: Workspace): Element[] {\n const variableModelList = workspace.getVariablesOfType('');\n\n const xmlList = [];\n if (variableModelList.length > 0) {\n // New variables are added to the end of the variableModelList.\n const mostRecentVariable = variableModelList[variableModelList.length - 1];\n if (Blocks['variables_set']) {\n const block = utilsXml.createElement('block');\n block.setAttribute('type', 'variables_set');\n block.setAttribute('gap', Blocks['math_change'] ? '8' : '24');\n block.appendChild(generateVariableFieldDom(mostRecentVariable));\n xmlList.push(block);\n }\n if (Blocks['math_change']) {\n const block = utilsXml.createElement('block');\n block.setAttribute('type', 'math_change');\n block.setAttribute('gap', Blocks['variables_get'] ? '20' : '8');\n block.appendChild(generateVariableFieldDom(mostRecentVariable));\n const value = Xml.textToDom(\n '' +\n '' +\n '1' +\n '' +\n '');\n block.appendChild(value);\n xmlList.push(block);\n }\n\n if (Blocks['variables_get']) {\n variableModelList.sort(VariableModel.compareByName);\n for (let i = 0, variable; variable = variableModelList[i]; i++) {\n const block = utilsXml.createElement('block');\n block.setAttribute('type', 'variables_get');\n block.setAttribute('gap', '8');\n block.appendChild(generateVariableFieldDom(variable));\n xmlList.push(block);\n }\n }\n }\n return xmlList;\n}\n\n/** @alias Blockly.Variables.VAR_LETTER_OPTIONS */\nexport const VAR_LETTER_OPTIONS = 'ijkmnopqrstuvwxyzabcdefgh';\n\n/**\n * Return a new variable name that is not yet being used. This will try to\n * generate single letter variable names in the range 'i' to 'z' to start with.\n * If no unique name is located it will try 'i' to 'z', 'a' to 'h',\n * then 'i2' to 'z2' etc. Skip 'l'.\n *\n * @param workspace The workspace to be unique in.\n * @returns New variable name.\n * @alias Blockly.Variables.generateUniqueName\n */\nexport function generateUniqueName(workspace: Workspace): string {\n return TEST_ONLY.generateUniqueNameInternal(workspace);\n}\n\n/**\n * Private version of generateUniqueName for stubbing in tests.\n */\nfunction generateUniqueNameInternal(workspace: Workspace): string {\n return generateUniqueNameFromOptions(\n VAR_LETTER_OPTIONS.charAt(0), workspace.getAllVariableNames());\n}\n\n/**\n * Returns a unique name that is not present in the usedNames array. This\n * will try to generate single letter names in the range a - z (skip l). It\n * will start with the character passed to startChar.\n *\n * @param startChar The character to start the search at.\n * @param usedNames A list of all of the used names.\n * @returns A unique name that is not present in the usedNames array.\n * @alias Blockly.Variables.generateUniqueNameFromOptions\n */\nexport function generateUniqueNameFromOptions(\n startChar: string, usedNames: string[]): string {\n if (!usedNames.length) {\n return startChar;\n }\n\n const letters = VAR_LETTER_OPTIONS;\n let suffix = '';\n let letterIndex = letters.indexOf(startChar);\n let potName = startChar;\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n let inUse = false;\n for (let i = 0; i < usedNames.length; i++) {\n if (usedNames[i].toLowerCase() === potName) {\n inUse = true;\n break;\n }\n }\n if (!inUse) {\n return potName;\n }\n\n letterIndex++;\n if (letterIndex === letters.length) {\n // Reached the end of the character sequence so back to 'i'.\n letterIndex = 0;\n suffix = `${Number(suffix) + 1}`;\n }\n potName = letters.charAt(letterIndex) + suffix;\n }\n}\n\n/**\n * Handles \"Create Variable\" button in the default variables toolbox category.\n * It will prompt the user for a variable name, including re-prompts if a name\n * is already in use among the workspace's variables.\n *\n * Custom button handlers can delegate to this function, allowing variables\n * types and after-creation processing. More complex customization (e.g.,\n * prompting for variable type) is beyond the scope of this function.\n *\n * @param workspace The workspace on which to create the variable.\n * @param opt_callback A callback. It will be passed an acceptable new variable\n * name, or null if change is to be aborted (cancel button), or undefined if\n * an existing variable was chosen.\n * @param opt_type The type of the variable like 'int', 'string', or ''. This\n * will default to '', which is a specific type.\n * @alias Blockly.Variables.createVariableButtonHandler\n */\nexport function createVariableButtonHandler(\n workspace: Workspace, opt_callback?: (p1?: string|null) => void,\n opt_type?: string) {\n const type = opt_type || '';\n // This function needs to be named so it can be called recursively.\n function promptAndCheckWithAlert(defaultName: string) {\n promptName(Msg['NEW_VARIABLE_TITLE'], defaultName, function(text) {\n if (text) {\n const existing = nameUsedWithAnyType(text, workspace);\n if (existing) {\n let msg;\n if (existing.type === type) {\n msg = Msg['VARIABLE_ALREADY_EXISTS'].replace('%1', existing.name);\n } else {\n msg = Msg['VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE'];\n msg = msg.replace('%1', existing.name).replace('%2', existing.type);\n }\n dialog.alert(msg, function() {\n promptAndCheckWithAlert(text);\n });\n } else {\n // No conflict\n workspace.createVariable(text, type);\n if (opt_callback) {\n opt_callback(text);\n }\n }\n } else {\n // User canceled prompt.\n if (opt_callback) {\n opt_callback(null);\n }\n }\n });\n }\n promptAndCheckWithAlert('');\n}\n\n/**\n * Opens a prompt that allows the user to enter a new name for a variable.\n * Triggers a rename if the new name is valid. Or re-prompts if there is a\n * collision.\n *\n * @param workspace The workspace on which to rename the variable.\n * @param variable Variable to rename.\n * @param opt_callback A callback. It will be passed an acceptable new variable\n * name, or null if change is to be aborted (cancel button), or undefined if\n * an existing variable was chosen.\n * @alias Blockly.Variables.renameVariable\n */\nexport function renameVariable(\n workspace: Workspace, variable: VariableModel,\n opt_callback?: (p1?: string|null) => void) {\n // This function needs to be named so it can be called recursively.\n function promptAndCheckWithAlert(defaultName: string) {\n const promptText =\n Msg['RENAME_VARIABLE_TITLE'].replace('%1', variable.name);\n promptName(promptText, defaultName, function(newName) {\n if (newName) {\n const existing =\n nameUsedWithOtherType(newName, variable.type, workspace);\n if (existing) {\n const msg = Msg['VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE']\n .replace('%1', existing.name)\n .replace('%2', existing.type);\n dialog.alert(msg, function() {\n promptAndCheckWithAlert(newName);\n });\n } else {\n workspace.renameVariableById(variable.getId(), newName);\n if (opt_callback) {\n opt_callback(newName);\n }\n }\n } else {\n // User canceled prompt.\n if (opt_callback) {\n opt_callback(null);\n }\n }\n });\n }\n promptAndCheckWithAlert('');\n}\n\n/**\n * Prompt the user for a new variable name.\n *\n * @param promptText The string of the prompt.\n * @param defaultText The default value to show in the prompt's field.\n * @param callback A callback. It will be passed the new variable name, or null\n * if the user picked something illegal.\n * @alias Blockly.Variables.promptName\n */\nexport function promptName(\n promptText: string, defaultText: string,\n callback: (p1: string|null) => void) {\n dialog.prompt(promptText, defaultText, function(newVar) {\n // Merge runs of whitespace. Strip leading and trailing whitespace.\n // Beyond this, all names are legal.\n if (newVar) {\n newVar = newVar.replace(/[\\s\\xa0]+/g, ' ').trim();\n if (newVar === Msg['RENAME_VARIABLE'] || newVar === Msg['NEW_VARIABLE']) {\n // Ok, not ALL names are legal...\n newVar = null;\n }\n }\n callback(newVar);\n });\n}\n/**\n * Check whether there exists a variable with the given name but a different\n * type.\n *\n * @param name The name to search for.\n * @param type The type to exclude from the search.\n * @param workspace The workspace to search for the variable.\n * @returns The variable with the given name and a different type, or null if\n * none was found.\n */\nfunction nameUsedWithOtherType(\n name: string, type: string, workspace: Workspace): VariableModel|null {\n const allVariables = workspace.getVariableMap().getAllVariables();\n\n name = name.toLowerCase();\n for (let i = 0, variable; variable = allVariables[i]; i++) {\n if (variable.name.toLowerCase() === name && variable.type !== type) {\n return variable;\n }\n }\n return null;\n}\n\n/**\n * Check whether there exists a variable with the given name of any type.\n *\n * @param name The name to search for.\n * @param workspace The workspace to search for the variable.\n * @returns The variable with the given name, or null if none was found.\n * @alias Blockly.Variables.nameUsedWithAnyType\n */\nexport function nameUsedWithAnyType(\n name: string, workspace: Workspace): VariableModel|null {\n const allVariables = workspace.getVariableMap().getAllVariables();\n\n name = name.toLowerCase();\n for (let i = 0, variable; variable = allVariables[i]; i++) {\n if (variable.name.toLowerCase() === name) {\n return variable;\n }\n }\n return null;\n}\n\n/**\n * Generate DOM objects representing a variable field.\n *\n * @param variableModel The variable model to represent.\n * @returns The generated DOM.\n * @alias Blockly.Variables.generateVariableFieldDom\n */\nexport function generateVariableFieldDom(variableModel: VariableModel):\n Element {\n /* Generates the following XML:\n * foo\n */\n const field = utilsXml.createElement('field');\n field.setAttribute('name', 'VAR');\n field.setAttribute('id', variableModel.getId());\n field.setAttribute('variabletype', variableModel.type);\n const name = utilsXml.createTextNode(variableModel.name);\n field.appendChild(name);\n return field;\n}\n\n/**\n * Helper function to look up or create a variable on the given workspace.\n * If no variable exists, creates and returns it.\n *\n * @param workspace The workspace to search for the variable. It may be a\n * flyout workspace or main workspace.\n * @param id The ID to use to look up or create the variable, or null.\n * @param opt_name The string to use to look up or create the variable.\n * @param opt_type The type to use to look up or create the variable.\n * @returns The variable corresponding to the given ID or name + type\n * combination.\n * @alias Blockly.Variables.getOrCreateVariablePackage\n */\nexport function getOrCreateVariablePackage(\n workspace: Workspace, id: string|null, opt_name?: string,\n opt_type?: string): VariableModel {\n let variable = getVariable(workspace, id, opt_name, opt_type);\n if (!variable) {\n variable = createVariable(workspace, id, opt_name, opt_type);\n }\n return variable;\n}\n\n/**\n * Look up a variable on the given workspace.\n * Always looks in the main workspace before looking in the flyout workspace.\n * Always prefers lookup by ID to lookup by name + type.\n *\n * @param workspace The workspace to search for the variable. It may be a\n * flyout workspace or main workspace.\n * @param id The ID to use to look up the variable, or null.\n * @param opt_name The string to use to look up the variable.\n * Only used if lookup by ID fails.\n * @param opt_type The type to use to look up the variable.\n * Only used if lookup by ID fails.\n * @returns The variable corresponding to the given ID or name + type\n * combination, or null if not found.\n * @alias Blockly.Variables.getVariable\n */\nexport function getVariable(\n workspace: Workspace, id: string|null, opt_name?: string,\n opt_type?: string): VariableModel|null {\n const potentialVariableMap = workspace.getPotentialVariableMap();\n let variable = null;\n // Try to just get the variable, by ID if possible.\n if (id) {\n // Look in the real variable map before checking the potential variable map.\n variable = workspace.getVariableById(id);\n if (!variable && potentialVariableMap) {\n variable = potentialVariableMap.getVariableById(id);\n }\n if (variable) {\n return variable;\n }\n }\n // If there was no ID, or there was an ID but it didn't match any variables,\n // look up by name and type.\n if (opt_name) {\n if (opt_type === undefined) {\n throw Error('Tried to look up a variable by name without a type');\n }\n // Otherwise look up by name and type.\n variable = workspace.getVariable(opt_name, opt_type);\n if (!variable && potentialVariableMap) {\n variable = potentialVariableMap.getVariable(opt_name, opt_type);\n }\n }\n return variable;\n}\n\n/**\n * Helper function to create a variable on the given workspace.\n *\n * @param workspace The workspace in which to create the variable. It may be a\n * flyout workspace or main workspace.\n * @param id The ID to use to create the variable, or null.\n * @param opt_name The string to use to create the variable.\n * @param opt_type The type to use to create the variable.\n * @returns The variable corresponding to the given ID or name + type\n * combination.\n */\nfunction createVariable(\n workspace: Workspace, id: string|null, opt_name?: string,\n opt_type?: string): VariableModel {\n const potentialVariableMap = workspace.getPotentialVariableMap();\n // Variables without names get uniquely named for this workspace.\n if (!opt_name) {\n const ws =\n (workspace.isFlyout ? (workspace as WorkspaceSvg).targetWorkspace :\n workspace);\n opt_name = generateUniqueName(ws!);\n }\n\n // Create a potential variable if in the flyout.\n let variable = null;\n if (potentialVariableMap) {\n variable = potentialVariableMap.createVariable(opt_name, opt_type, id);\n } else {\n // In the main workspace, create a real variable.\n variable = workspace.createVariable(opt_name, opt_type, id);\n }\n return variable;\n}\n\n/**\n * Helper function to get the list of variables that have been added to the\n * workspace after adding a new block, using the given list of variables that\n * were in the workspace before the new block was added.\n *\n * @param workspace The workspace to inspect.\n * @param originalVariables The array of variables that existed in the workspace\n * before adding the new block.\n * @returns The new array of variables that were freshly added to the workspace\n * after creating the new block, or [] if no new variables were added to the\n * workspace.\n * @alias Blockly.Variables.getAddedVariables\n * @internal\n */\nexport function getAddedVariables(\n workspace: Workspace, originalVariables: VariableModel[]): VariableModel[] {\n const allCurrentVariables = workspace.getAllVariables();\n const addedVariables = [];\n if (originalVariables.length !== allCurrentVariables.length) {\n for (let i = 0; i < allCurrentVariables.length; i++) {\n const variable = allCurrentVariables[i];\n // For any variable that is present in allCurrentVariables but not\n // present in originalVariables, add the variable to addedVariables.\n if (originalVariables.indexOf(variable) === -1) {\n addedVariables.push(variable);\n }\n }\n }\n return addedVariables;\n}\n\nexport const TEST_ONLY = {\n generateUniqueNameInternal,\n};\n","/**\n * @license\n * Copyright 2013 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Inject Blockly's CSS synchronously.\n *\n * @namespace Blockly.Css\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.Css');\n\n\n/** Has CSS already been injected? */\nlet injected = false;\n\n/**\n * Add some CSS to the blob that will be injected later. Allows optional\n * components such as fields and the toolbox to store separate CSS.\n *\n * @param cssContent Multiline CSS string or an array of single lines of CSS.\n * @alias Blockly.Css.register\n */\nexport function register(cssContent: string) {\n if (injected) {\n throw Error('CSS already injected');\n }\n content += '\\n' + cssContent;\n}\n\n/**\n * Inject the CSS into the DOM. This is preferable over using a regular CSS\n * file since:\n * a) It loads synchronously and doesn't force a redraw later.\n * b) It speeds up loading by not blocking on a separate HTTP transfer.\n * c) The CSS content may be made dynamic depending on init options.\n *\n * @param hasCss If false, don't inject CSS (providing CSS becomes the\n * document's responsibility).\n * @param pathToMedia Path from page to the Blockly media directory.\n * @alias Blockly.Css.inject\n */\nexport function inject(hasCss: boolean, pathToMedia: string) {\n // Only inject the CSS once.\n if (injected) {\n return;\n }\n injected = true;\n if (!hasCss) {\n return;\n }\n // Strip off any trailing slash (either Unix or Windows).\n const mediaPath = pathToMedia.replace(/[\\\\/]$/, '');\n const cssContent = content.replace(/<<>>/g, mediaPath);\n // Cleanup the collected css content after injecting it to the DOM.\n content = '';\n\n // Inject CSS tag at start of head.\n const cssNode = document.createElement('style');\n cssNode.id = 'blockly-common-style';\n const cssTextNode = document.createTextNode(cssContent);\n cssNode.appendChild(cssTextNode);\n document.head.insertBefore(cssNode, document.head.firstChild);\n}\n\n/**\n * The CSS content for Blockly.\n *\n * @alias Blockly.Css.content\n */\nlet content = `\n.blocklySvg {\n background-color: #fff;\n outline: none;\n overflow: hidden; /* IE overflows by default. */\n position: absolute;\n display: block;\n}\n\n.blocklyWidgetDiv {\n display: none;\n position: absolute;\n z-index: 99999; /* big value for bootstrap3 compatibility */\n}\n\n.injectionDiv {\n height: 100%;\n position: relative;\n overflow: hidden; /* So blocks in drag surface disappear at edges */\n touch-action: none;\n}\n\n.blocklyNonSelectable {\n user-select: none;\n -ms-user-select: none;\n -webkit-user-select: none;\n}\n\n.blocklyWsDragSurface {\n display: none;\n position: absolute;\n top: 0;\n left: 0;\n}\n\n/* Added as a separate rule with multiple classes to make it more specific\n than a bootstrap rule that selects svg:root. See issue #1275 for context.\n*/\n.blocklyWsDragSurface.blocklyOverflowVisible {\n overflow: visible;\n}\n\n.blocklyBlockDragSurface {\n display: none;\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n overflow: visible !important;\n z-index: 50; /* Display below toolbox, but above everything else. */\n}\n\n.blocklyBlockCanvas.blocklyCanvasTransitioning,\n.blocklyBubbleCanvas.blocklyCanvasTransitioning {\n transition: transform .5s;\n}\n\n.blocklyTooltipDiv {\n background-color: #ffffc7;\n border: 1px solid #ddc;\n box-shadow: 4px 4px 20px 1px rgba(0,0,0,.15);\n color: #000;\n display: none;\n font: 9pt sans-serif;\n opacity: .9;\n padding: 2px;\n position: absolute;\n z-index: 100000; /* big value for bootstrap3 compatibility */\n}\n\n.blocklyDropDownDiv {\n position: absolute;\n left: 0;\n top: 0;\n z-index: 1000;\n display: none;\n border: 1px solid;\n border-color: #dadce0;\n background-color: #fff;\n border-radius: 2px;\n padding: 4px;\n box-shadow: 0 0 3px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownDiv.blocklyFocused {\n box-shadow: 0 0 6px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownContent {\n max-height: 300px; // @todo: spec for maximum height.\n overflow: auto;\n overflow-x: hidden;\n position: relative;\n}\n\n.blocklyDropDownArrow {\n position: absolute;\n left: 0;\n top: 0;\n width: 16px;\n height: 16px;\n z-index: -1;\n background-color: inherit;\n border-color: inherit;\n}\n\n.blocklyDropDownButton {\n display: inline-block;\n float: left;\n padding: 0;\n margin: 4px;\n border-radius: 4px;\n outline: none;\n border: 1px solid;\n transition: box-shadow .1s;\n cursor: pointer;\n}\n\n.blocklyArrowTop {\n border-top: 1px solid;\n border-left: 1px solid;\n border-top-left-radius: 4px;\n border-color: inherit;\n}\n\n.blocklyArrowBottom {\n border-bottom: 1px solid;\n border-right: 1px solid;\n border-bottom-right-radius: 4px;\n border-color: inherit;\n}\n\n.blocklyResizeSE {\n cursor: se-resize;\n fill: #aaa;\n}\n\n.blocklyResizeSW {\n cursor: sw-resize;\n fill: #aaa;\n}\n\n.blocklyResizeLine {\n stroke: #515A5A;\n stroke-width: 1;\n}\n\n.blocklyHighlightedConnectionPath {\n fill: none;\n stroke: #fc3;\n stroke-width: 4px;\n}\n\n.blocklyPathLight {\n fill: none;\n stroke-linecap: round;\n stroke-width: 1;\n}\n\n.blocklySelected>.blocklyPathLight {\n display: none;\n}\n\n.blocklyDraggable {\n /* backup for browsers (e.g. IE11) that don't support grab */\n cursor: url(\"<<>>/handopen.cur\"), auto;\n cursor: grab;\n cursor: -webkit-grab;\n}\n\n /* backup for browsers (e.g. IE11) that don't support grabbing */\n.blocklyDragging {\n /* backup for browsers (e.g. IE11) that don't support grabbing */\n cursor: url(\"<<>>/handclosed.cur\"), auto;\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n /* Changes cursor on mouse down. Not effective in Firefox because of\n https://bugzilla.mozilla.org/show_bug.cgi?id=771241 */\n.blocklyDraggable:active {\n /* backup for browsers (e.g. IE11) that don't support grabbing */\n cursor: url(\"<<>>/handclosed.cur\"), auto;\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n/* Change the cursor on the whole drag surface in case the mouse gets\n ahead of block during a drag. This way the cursor is still a closed hand.\n */\n.blocklyBlockDragSurface .blocklyDraggable {\n /* backup for browsers (e.g. IE11) that don't support grabbing */\n cursor: url(\"<<>>/handclosed.cur\"), auto;\n cursor: grabbing;\n cursor: -webkit-grabbing;\n}\n\n.blocklyDragging.blocklyDraggingDelete {\n cursor: url(\"<<>>/handdelete.cur\"), auto;\n}\n\n.blocklyDragging>.blocklyPath,\n.blocklyDragging>.blocklyPathLight {\n fill-opacity: .8;\n stroke-opacity: .8;\n}\n\n.blocklyDragging>.blocklyPathDark {\n display: none;\n}\n\n.blocklyDisabled>.blocklyPath {\n fill-opacity: .5;\n stroke-opacity: .5;\n}\n\n.blocklyDisabled>.blocklyPathLight,\n.blocklyDisabled>.blocklyPathDark {\n display: none;\n}\n\n.blocklyInsertionMarker>.blocklyPath,\n.blocklyInsertionMarker>.blocklyPathLight,\n.blocklyInsertionMarker>.blocklyPathDark {\n fill-opacity: .2;\n stroke: none;\n}\n\n.blocklyMultilineText {\n font-family: monospace;\n}\n\n.blocklyNonEditableText>text {\n pointer-events: none;\n}\n\n.blocklyFlyout {\n position: absolute;\n z-index: 20;\n}\n\n.blocklyText text {\n cursor: default;\n}\n\n/*\n Don't allow users to select text. It gets annoying when trying to\n drag a block and selected text moves instead.\n*/\n.blocklySvg text,\n.blocklyBlockDragSurface text {\n user-select: none;\n -ms-user-select: none;\n -webkit-user-select: none;\n cursor: inherit;\n}\n\n.blocklyHidden {\n display: none;\n}\n\n.blocklyFieldDropdown:not(.blocklyHidden) {\n display: block;\n}\n\n.blocklyIconGroup {\n cursor: default;\n}\n\n.blocklyIconGroup:not(:hover),\n.blocklyIconGroupReadonly {\n opacity: .6;\n}\n\n.blocklyIconShape {\n fill: #00f;\n stroke: #fff;\n stroke-width: 1px;\n}\n\n.blocklyIconSymbol {\n fill: #fff;\n}\n\n.blocklyMinimalBody {\n margin: 0;\n padding: 0;\n}\n\n.blocklyHtmlInput {\n border: none;\n border-radius: 4px;\n height: 100%;\n margin: 0;\n outline: none;\n padding: 0;\n width: 100%;\n text-align: center;\n display: block;\n box-sizing: border-box;\n}\n\n/* Edge and IE introduce a close icon when the input value is longer than a\n certain length. This affects our sizing calculations of the text input.\n Hiding the close icon to avoid that. */\n.blocklyHtmlInput::-ms-clear {\n display: none;\n}\n\n.blocklyMainBackground {\n stroke-width: 1;\n stroke: #c6c6c6; /* Equates to #ddd due to border being off-pixel. */\n}\n\n.blocklyMutatorBackground {\n fill: #fff;\n stroke: #ddd;\n stroke-width: 1;\n}\n\n.blocklyFlyoutBackground {\n fill: #ddd;\n fill-opacity: .8;\n}\n\n.blocklyMainWorkspaceScrollbar {\n z-index: 20;\n}\n\n.blocklyFlyoutScrollbar {\n z-index: 30;\n}\n\n.blocklyScrollbarHorizontal,\n.blocklyScrollbarVertical {\n position: absolute;\n outline: none;\n}\n\n.blocklyScrollbarBackground {\n opacity: 0;\n}\n\n.blocklyScrollbarHandle {\n fill: #ccc;\n}\n\n.blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,\n.blocklyScrollbarHandle:hover {\n fill: #bbb;\n}\n\n/* Darken flyout scrollbars due to being on a grey background. */\n/* By contrast, workspace scrollbars are on a white background. */\n.blocklyFlyout .blocklyScrollbarHandle {\n fill: #bbb;\n}\n\n.blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,\n.blocklyFlyout .blocklyScrollbarHandle:hover {\n fill: #aaa;\n}\n\n.blocklyInvalidInput {\n background: #faa;\n}\n\n.blocklyVerticalMarker {\n stroke-width: 3px;\n fill: rgba(255,255,255,.5);\n pointer-events: none;\n}\n\n.blocklyComputeCanvas {\n position: absolute;\n width: 0;\n height: 0;\n}\n\n.blocklyNoPointerEvents {\n pointer-events: none;\n}\n\n.blocklyContextMenu {\n border-radius: 4px;\n max-height: 100%;\n}\n\n.blocklyDropdownMenu {\n border-radius: 2px;\n padding: 0 !important;\n}\n\n.blocklyDropdownMenu .blocklyMenuItem {\n /* 28px on the left for icon or checkbox. */\n padding-left: 28px;\n}\n\n/* BiDi override for the resting state. */\n.blocklyDropdownMenu .blocklyMenuItemRtl {\n /* Flip left/right padding for BiDi. */\n padding-left: 5px;\n padding-right: 28px;\n}\n\n.blocklyWidgetDiv .blocklyMenu {\n background: #fff;\n border: 1px solid transparent;\n box-shadow: 0 0 3px 1px rgba(0,0,0,.3);\n font: normal 13px Arial, sans-serif;\n margin: 0;\n outline: none;\n padding: 4px 0;\n position: absolute;\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 100%;\n z-index: 20000; /* Arbitrary, but some apps depend on it... */\n}\n\n.blocklyWidgetDiv .blocklyMenu.blocklyFocused {\n box-shadow: 0 0 6px 1px rgba(0,0,0,.3);\n}\n\n.blocklyDropDownDiv .blocklyMenu {\n background: inherit; /* Compatibility with gapi, reset from goog-menu */\n border: inherit; /* Compatibility with gapi, reset from goog-menu */\n font: normal 13px \"Helvetica Neue\", Helvetica, sans-serif;\n outline: none;\n position: relative; /* Compatibility with gapi, reset from goog-menu */\n z-index: 20000; /* Arbitrary, but some apps depend on it... */\n}\n\n/* State: resting. */\n.blocklyMenuItem {\n border: none;\n color: #000;\n cursor: pointer;\n list-style: none;\n margin: 0;\n /* 7em on the right for shortcut. */\n min-width: 7em;\n padding: 6px 15px;\n white-space: nowrap;\n}\n\n/* State: disabled. */\n.blocklyMenuItemDisabled {\n color: #ccc;\n cursor: inherit;\n}\n\n/* State: hover. */\n.blocklyMenuItemHighlight {\n background-color: rgba(0,0,0,.1);\n}\n\n/* State: selected/checked. */\n.blocklyMenuItemCheckbox {\n height: 16px;\n position: absolute;\n width: 16px;\n}\n\n.blocklyMenuItemSelected .blocklyMenuItemCheckbox {\n background: url(<<>>/sprites.png) no-repeat -48px -16px;\n float: left;\n margin-left: -24px;\n position: static; /* Scroll with the menu. */\n}\n\n.blocklyMenuItemRtl .blocklyMenuItemCheckbox {\n float: right;\n margin-right: -24px;\n}\n`;\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility methods realted to figuring out positions of SVG elements.\n *\n * @namespace Blockly.utils.svgMath\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.svgMath');\n\nimport type {WorkspaceSvg} from '../workspace_svg.js';\n\nimport {Coordinate} from './coordinate.js';\nimport * as deprecation from './deprecation.js';\nimport {Rect} from './rect.js';\nimport * as style from './style.js';\n\n\n/**\n * Static regex to pull the x,y values out of an SVG translate() directive.\n * Note that Firefox and IE (9,10) return 'translate(12)' instead of\n * 'translate(12, 0)'.\n * Note that IE (9,10) returns 'translate(16 8)' instead of 'translate(16, 8)'.\n * Note that IE has been reported to return scientific notation (0.123456e-42).\n */\nconst XY_REGEX = /translate\\(\\s*([-+\\d.e]+)([ ,]\\s*([-+\\d.e]+)\\s*)?/;\n\n/**\n * Static regex to pull the x,y values out of a translate() or translate3d()\n * style property.\n * Accounts for same exceptions as XY_REGEX.\n */\nconst XY_STYLE_REGEX =\n /transform:\\s*translate(?:3d)?\\(\\s*([-+\\d.e]+)\\s*px([ ,]\\s*([-+\\d.e]+)\\s*px)?/;\n\n/**\n * Return the coordinates of the top-left corner of this element relative to\n * its parent. Only for SVG elements and children (e.g. rect, g, path).\n *\n * @param element SVG element to find the coordinates of.\n * @returns Object with .x and .y properties.\n * @alias Blockly.utils.svgMath.getRelativeXY\n */\nexport function getRelativeXY(element: Element): Coordinate {\n const xy = new Coordinate(0, 0);\n // First, check for x and y attributes.\n // Checking for the existence of x/y properties is faster than getAttribute.\n // However, x/y contains an SVGAnimatedLength object, so rely on getAttribute\n // to get the number.\n const x = (element as any).x && element.getAttribute('x');\n const y = (element as any).y && element.getAttribute('y');\n if (x) {\n xy.x = parseInt(x);\n }\n if (y) {\n xy.y = parseInt(y);\n }\n // Second, check for transform=\"translate(...)\" attribute.\n const transform = element.getAttribute('transform');\n const r = transform && transform.match(XY_REGEX);\n if (r) {\n xy.x += Number(r[1]);\n if (r[3]) {\n xy.y += Number(r[3]);\n }\n }\n\n // Then check for style = transform: translate(...) or translate3d(...)\n const style = element.getAttribute('style');\n if (style && style.indexOf('translate') > -1) {\n const styleComponents = style.match(XY_STYLE_REGEX);\n if (styleComponents) {\n xy.x += Number(styleComponents[1]);\n if (styleComponents[3]) {\n xy.y += Number(styleComponents[3]);\n }\n }\n }\n return xy;\n}\n\n/**\n * Return the coordinates of the top-left corner of this element relative to\n * the div Blockly was injected into.\n *\n * @param element SVG element to find the coordinates of. If this is not a child\n * of the div Blockly was injected into, the behaviour is undefined.\n * @returns Object with .x and .y properties.\n * @alias Blockly.utils.svgMath.getInjectionDivXY\n */\nexport function getInjectionDivXY(element: Element): Coordinate {\n let x = 0;\n let y = 0;\n while (element) {\n const xy = getRelativeXY(element);\n x = x + xy.x;\n y = y + xy.y;\n const classes = element.getAttribute('class') || '';\n if ((' ' + classes + ' ').indexOf(' injectionDiv ') !== -1) {\n break;\n }\n element = element.parentNode as Element;\n }\n return new Coordinate(x, y);\n}\n\n/**\n * Check if 3D transforms are supported by adding an element\n * and attempting to set the property.\n *\n * @returns True if 3D transforms are supported.\n * @deprecated No longer provided by Blockly.\n * @alias Blockly.utils.svgMath.is3dSupported\n */\nexport function is3dSupported(): boolean {\n // All browsers support translate3d in 2022.\n deprecation.warn(\n 'Blockly.utils.svgMath.is3dSupported', 'version 9', 'version 10');\n return true;\n}\n\n/**\n * Get the position of the current viewport in window coordinates. This takes\n * scroll into account.\n *\n * @returns An object containing window width, height, and scroll position in\n * window coordinates.\n * @alias Blockly.utils.svgMath.getViewportBBox\n * @internal\n */\nexport function getViewportBBox(): Rect {\n // Pixels, in window coordinates.\n const scrollOffset = style.getViewportPageOffset();\n return new Rect(\n scrollOffset.y, document.documentElement.clientHeight + scrollOffset.y,\n scrollOffset.x, document.documentElement.clientWidth + scrollOffset.x);\n}\n\n/**\n * Gets the document scroll distance as a coordinate object.\n * Copied from Closure's goog.dom.getDocumentScroll.\n *\n * @returns Object with values 'x' and 'y'.\n * @alias Blockly.utils.svgMath.getDocumentScroll\n */\nexport function getDocumentScroll(): Coordinate {\n const el = document.documentElement;\n const win = window;\n return new Coordinate(\n win.pageXOffset || el.scrollLeft, win.pageYOffset || el.scrollTop);\n}\n\n/**\n * Converts screen coordinates to workspace coordinates.\n *\n * @param ws The workspace to find the coordinates on.\n * @param screenCoordinates The screen coordinates to be converted to workspace\n * coordinates\n * @returns The workspace coordinates.\n * @alias Blockly.utils.svgMath.screenToWsCoordinates\n */\nexport function screenToWsCoordinates(\n ws: WorkspaceSvg, screenCoordinates: Coordinate): Coordinate {\n const screenX = screenCoordinates.x;\n const screenY = screenCoordinates.y;\n\n const injectionDiv = ws.getInjectionDiv();\n // Bounding rect coordinates are in client coordinates, meaning that they\n // are in pixels relative to the upper left corner of the visible browser\n // window. These coordinates change when you scroll the browser window.\n const boundingRect = injectionDiv.getBoundingClientRect();\n\n // The client coordinates offset by the injection div's upper left corner.\n const clientOffsetPixels =\n new Coordinate(screenX - boundingRect.left, screenY - boundingRect.top);\n\n // The offset in pixels between the main workspace's origin and the upper\n // left corner of the injection div.\n const mainOffsetPixels = ws.getOriginOffsetInPixels();\n\n // The position of the new comment in pixels relative to the origin of the\n // main workspace.\n const finalOffsetPixels =\n Coordinate.difference(clientOffsetPixels, mainOffsetPixels);\n // The position in main workspace coordinates.\n const finalOffsetMainWs = finalOffsetPixels.scale(1 / ws.scale);\n return finalOffsetMainWs;\n}\n\nexport const TEST_ONLY = {\n XY_REGEX,\n XY_STYLE_REGEX,\n};\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * XML reader and writer.\n *\n * @namespace Blockly.Xml\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.Xml');\n\nimport type {Block} from './block.js';\nimport type {BlockSvg} from './block_svg.js';\nimport type {Connection} from './connection.js';\nimport * as eventUtils from './events/utils.js';\nimport type {Field} from './field.js';\nimport {inputTypes} from './input_types.js';\nimport * as dom from './utils/dom.js';\nimport {Size} from './utils/size.js';\nimport * as utilsXml from './utils/xml.js';\nimport type {VariableModel} from './variable_model.js';\nimport * as Variables from './variables.js';\nimport type {Workspace} from './workspace.js';\nimport {WorkspaceComment} from './workspace_comment.js';\nimport {WorkspaceCommentSvg} from './workspace_comment_svg.js';\nimport type {WorkspaceSvg} from './workspace_svg.js';\n\n\n/**\n * Encode a block tree as XML.\n *\n * @param workspace The workspace containing blocks.\n * @param opt_noId True if the encoder should skip the block IDs.\n * @returns XML DOM element.\n * @alias Blockly.Xml.workspaceToDom\n */\nexport function workspaceToDom(\n workspace: Workspace, opt_noId?: boolean): Element {\n const treeXml = utilsXml.createElement('xml');\n const variablesElement =\n variablesToDom(Variables.allUsedVarModels(workspace));\n if (variablesElement.hasChildNodes()) {\n treeXml.appendChild(variablesElement);\n }\n const comments = workspace.getTopComments(true);\n for (let i = 0; i < comments.length; i++) {\n const comment = comments[i];\n treeXml.appendChild(comment.toXmlWithXY(opt_noId));\n }\n const blocks = workspace.getTopBlocks(true);\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n treeXml.appendChild(blockToDomWithXY(block, opt_noId));\n }\n return treeXml;\n}\n\n/**\n * Encode a list of variables as XML.\n *\n * @param variableList List of all variable models.\n * @returns Tree of XML elements.\n * @alias Blockly.Xml.variablesToDom\n */\nexport function variablesToDom(variableList: VariableModel[]): Element {\n const variables = utilsXml.createElement('variables');\n for (let i = 0; i < variableList.length; i++) {\n const variable = variableList[i];\n const element = utilsXml.createElement('variable');\n element.appendChild(utilsXml.createTextNode(variable.name));\n if (variable.type) {\n element.setAttribute('type', variable.type);\n }\n element.id = variable.getId();\n variables.appendChild(element);\n }\n return variables;\n}\n\n/**\n * Encode a block subtree as XML with XY coordinates.\n *\n * @param block The root block to encode.\n * @param opt_noId True if the encoder should skip the block ID.\n * @returns Tree of XML elements or an empty document fragment if the block was\n * an insertion marker.\n * @alias Blockly.Xml.blockToDomWithXY\n */\nexport function blockToDomWithXY(block: Block, opt_noId?: boolean): Element|\n DocumentFragment {\n if (block.isInsertionMarker()) { // Skip over insertion markers.\n block = block.getChildren(false)[0];\n if (!block) {\n // Disappears when appended.\n return new DocumentFragment();\n }\n }\n\n let width = 0; // Not used in LTR.\n if (block.workspace.RTL) {\n width = block.workspace.getWidth();\n }\n\n const element = blockToDom(block, opt_noId);\n const xy = block.getRelativeToSurfaceXY();\n // AnyDuringMigration because: Property 'setAttribute' does not exist on type\n // 'Element | DocumentFragment'.\n (element as AnyDuringMigration)\n .setAttribute('x', Math.round(block.workspace.RTL ? width - xy.x : xy.x));\n // AnyDuringMigration because: Property 'setAttribute' does not exist on type\n // 'Element | DocumentFragment'.\n (element as AnyDuringMigration).setAttribute('y', Math.round(xy.y));\n return element;\n}\n\n/**\n * Encode a field as XML.\n *\n * @param field The field to encode.\n * @returns XML element, or null if the field did not need to be serialized.\n */\nfunction fieldToDom(field: Field): Element|null {\n if (field.isSerializable()) {\n const container = utilsXml.createElement('field');\n container.setAttribute('name', field.name || '');\n return field.toXml(container);\n }\n return null;\n}\n\n/**\n * Encode all of a block's fields as XML and attach them to the given tree of\n * XML elements.\n *\n * @param block A block with fields to be encoded.\n * @param element The XML element to which the field DOM should be attached.\n */\nfunction allFieldsToDom(block: Block, element: Element) {\n for (let i = 0; i < block.inputList.length; i++) {\n const input = block.inputList[i];\n for (let j = 0; j < input.fieldRow.length; j++) {\n const field = input.fieldRow[j];\n const fieldDom = fieldToDom(field);\n if (fieldDom) {\n element.appendChild(fieldDom);\n }\n }\n }\n}\n\n/**\n * Encode a block subtree as XML.\n *\n * @param block The root block to encode.\n * @param opt_noId True if the encoder should skip the block ID.\n * @returns Tree of XML elements or an empty document fragment if the block was\n * an insertion marker.\n * @alias Blockly.Xml.blockToDom\n */\nexport function blockToDom(block: Block, opt_noId?: boolean): Element|\n DocumentFragment {\n // Skip over insertion markers.\n if (block.isInsertionMarker()) {\n const child = block.getChildren(false)[0];\n if (child) {\n return blockToDom(child);\n } else {\n // Disappears when appended.\n return new DocumentFragment();\n }\n }\n\n const element = utilsXml.createElement(block.isShadow() ? 'shadow' : 'block');\n element.setAttribute('type', block.type);\n if (!opt_noId) {\n // It's important to use setAttribute here otherwise IE11 won't serialize\n // the block's ID when domToText is called.\n element.setAttribute('id', block.id);\n }\n if (block.mutationToDom) {\n // Custom data for an advanced block.\n const mutation = block.mutationToDom();\n if (mutation && (mutation.hasChildNodes() || mutation.hasAttributes())) {\n element.appendChild(mutation);\n }\n }\n\n allFieldsToDom(block, element);\n\n const commentText = block.getCommentText();\n if (commentText) {\n const size = block.commentModel.size;\n const pinned = block.commentModel.pinned;\n\n const commentElement = utilsXml.createElement('comment');\n commentElement.appendChild(utilsXml.createTextNode(commentText));\n // AnyDuringMigration because: Argument of type 'boolean' is not assignable\n // to parameter of type 'string'.\n commentElement.setAttribute('pinned', pinned as AnyDuringMigration);\n // AnyDuringMigration because: Argument of type 'number' is not assignable\n // to parameter of type 'string'.\n commentElement.setAttribute('h', size.height as AnyDuringMigration);\n // AnyDuringMigration because: Argument of type 'number' is not assignable\n // to parameter of type 'string'.\n commentElement.setAttribute('w', size.width as AnyDuringMigration);\n\n element.appendChild(commentElement);\n }\n\n if (block.data) {\n const dataElement = utilsXml.createElement('data');\n dataElement.appendChild(utilsXml.createTextNode(block.data));\n element.appendChild(dataElement);\n }\n\n for (let i = 0; i < block.inputList.length; i++) {\n const input = block.inputList[i];\n let container: Element;\n let empty = true;\n if (input.type === inputTypes.DUMMY) {\n continue;\n } else {\n const childBlock = input.connection!.targetBlock();\n if (input.type === inputTypes.VALUE) {\n container = utilsXml.createElement('value');\n } else if (input.type === inputTypes.STATEMENT) {\n container = utilsXml.createElement('statement');\n }\n const childShadow = input.connection!.getShadowDom();\n if (childShadow && (!childBlock || !childBlock.isShadow())) {\n container!.appendChild(cloneShadow(childShadow, opt_noId));\n }\n if (childBlock) {\n const childElem = blockToDom(childBlock, opt_noId);\n if (childElem.nodeType === dom.NodeType.ELEMENT_NODE) {\n container!.appendChild(childElem);\n empty = false;\n }\n }\n }\n container!.setAttribute('name', input.name);\n if (!empty) {\n element.appendChild(container!);\n }\n }\n if (block.inputsInline !== undefined &&\n block.inputsInline !== block.inputsInlineDefault) {\n element.setAttribute('inline', block.inputsInline.toString());\n }\n if (block.isCollapsed()) {\n element.setAttribute('collapsed', 'true');\n }\n if (!block.isEnabled()) {\n element.setAttribute('disabled', 'true');\n }\n if (!block.isDeletable() && !block.isShadow()) {\n element.setAttribute('deletable', 'false');\n }\n if (!block.isMovable() && !block.isShadow()) {\n element.setAttribute('movable', 'false');\n }\n if (!block.isEditable()) {\n element.setAttribute('editable', 'false');\n }\n\n const nextBlock = block.getNextBlock();\n let container: Element;\n if (nextBlock) {\n const nextElem = blockToDom(nextBlock, opt_noId);\n if (nextElem.nodeType === dom.NodeType.ELEMENT_NODE) {\n container = utilsXml.createElement('next');\n container.appendChild(nextElem);\n element.appendChild(container);\n }\n }\n const nextShadow =\n block.nextConnection && block.nextConnection.getShadowDom();\n if (nextShadow && (!nextBlock || !nextBlock.isShadow())) {\n container!.appendChild(cloneShadow(nextShadow, opt_noId));\n }\n\n return element;\n}\n\n/**\n * Deeply clone the shadow's DOM so that changes don't back-wash to the block.\n *\n * @param shadow A tree of XML elements.\n * @param opt_noId True if the encoder should skip the block ID.\n * @returns A tree of XML elements.\n */\nfunction cloneShadow(shadow: Element, opt_noId?: boolean): Element {\n shadow = shadow.cloneNode(true) as Element;\n // Walk the tree looking for whitespace. Don't prune whitespace in a tag.\n let node: Node|null = shadow;\n let textNode;\n while (node) {\n if (opt_noId && node.nodeName === 'shadow') {\n // Strip off IDs from shadow blocks. There should never be a 'block' as\n // a child of a 'shadow', so no need to check that.\n (node as Element).removeAttribute('id');\n }\n if (node.firstChild) {\n node = node.firstChild;\n } else {\n while (node && !node.nextSibling) {\n textNode = node;\n node = node.parentNode;\n if (textNode.nodeType === dom.NodeType.TEXT_NODE &&\n (textNode as Text).data.trim() === '' &&\n node?.firstChild !== textNode) {\n // Prune whitespace after a tag.\n dom.removeNode(textNode);\n }\n }\n if (node) {\n textNode = node;\n node = node.nextSibling;\n if (textNode.nodeType === dom.NodeType.TEXT_NODE &&\n (textNode as Text).data.trim() === '') {\n // Prune whitespace before a tag.\n dom.removeNode(textNode);\n }\n }\n }\n }\n return shadow;\n}\n\n/**\n * Converts a DOM structure into plain text.\n * Currently the text format is fairly ugly: all one line with no whitespace,\n * unless the DOM itself has whitespace built-in.\n *\n * @param dom A tree of XML nodes.\n * @returns Text representation.\n * @alias Blockly.Xml.domToText\n */\nexport function domToText(dom: Node): string {\n const text = utilsXml.domToText(dom);\n // Unpack self-closing tags. These tags fail when embedded in HTML.\n // -> \n return text.replace(/<(\\w+)([^<]*)\\/>/g, '<$1$2>');\n}\n\n/**\n * Converts a DOM structure into properly indented text.\n *\n * @param dom A tree of XML elements.\n * @returns Text representation.\n * @alias Blockly.Xml.domToPrettyText\n */\nexport function domToPrettyText(dom: Node): string {\n // This function is not guaranteed to be correct for all XML.\n // But it handles the XML that Blockly generates.\n const blob = domToText(dom);\n // Place every open and close tag on its own line.\n const lines = blob.split('<');\n // Indent every line.\n let indent = '';\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n if (line[0] === '/') {\n indent = indent.substring(2);\n }\n lines[i] = indent + '<' + line;\n if (line[0] !== '/' && line.slice(-2) !== '/>') {\n indent += ' ';\n }\n }\n // Pull simple tags back together.\n // E.g. \n let text = lines.join('\\n');\n text = text.replace(/(<(\\w+)\\b[^>]*>[^\\n]*)\\n *<\\/\\2>/g, '$1');\n // Trim leading blank line.\n return text.replace(/^\\n/, '');\n}\n\n/**\n * Converts an XML string into a DOM structure.\n *\n * @param text An XML string.\n * @returns A DOM object representing the singular child of the document\n * element.\n * @throws if the text doesn't parse.\n * @alias Blockly.Xml.textToDom\n */\nexport function textToDom(text: string): Element {\n const doc = utilsXml.textToDomDocument(text);\n if (!doc || !doc.documentElement ||\n doc.getElementsByTagName('parsererror').length) {\n throw Error('textToDom was unable to parse: ' + text);\n }\n return doc.documentElement;\n}\n\n/**\n * Clear the given workspace then decode an XML DOM and\n * create blocks on the workspace.\n *\n * @param xml XML DOM.\n * @param workspace The workspace.\n * @returns An array containing new block IDs.\n * @alias Blockly.Xml.clearWorkspaceAndLoadFromXml\n */\nexport function clearWorkspaceAndLoadFromXml(\n xml: Element, workspace: WorkspaceSvg): string[] {\n workspace.setResizesEnabled(false);\n workspace.clear();\n // AnyDuringMigration because: Argument of type 'WorkspaceSvg' is not\n // assignable to parameter of type 'Workspace'.\n const blockIds = domToWorkspace(xml, workspace as AnyDuringMigration);\n workspace.setResizesEnabled(true);\n return blockIds;\n}\n\n/**\n * Decode an XML DOM and create blocks on the workspace.\n *\n * @param xml XML DOM.\n * @param workspace The workspace.\n * @returns An array containing new block IDs.\n * @suppress {strictModuleDepCheck} Suppress module check while workspace\n * comments are not bundled in.\n * @alias Blockly.Xml.domToWorkspace\n */\nexport function domToWorkspace(xml: Element, workspace: Workspace): string[] {\n let width = 0; // Not used in LTR.\n if (workspace.RTL) {\n width = workspace.getWidth();\n }\n const newBlockIds = []; // A list of block IDs added by this call.\n dom.startTextWidthCache();\n const existingGroup = eventUtils.getGroup();\n if (!existingGroup) {\n eventUtils.setGroup(true);\n }\n\n // Disable workspace resizes as an optimization.\n // Assume it is rendered so we can check.\n if ((workspace as WorkspaceSvg).setResizesEnabled) {\n (workspace as WorkspaceSvg).setResizesEnabled(false);\n }\n let variablesFirst = true;\n try {\n for (let i = 0, xmlChild; xmlChild = xml.childNodes[i]; i++) {\n const name = xmlChild.nodeName.toLowerCase();\n const xmlChildElement = xmlChild as Element;\n if (name === 'block' ||\n name === 'shadow' && !eventUtils.getRecordUndo()) {\n // Allow top-level shadow blocks if recordUndo is disabled since\n // that means an undo is in progress. Such a block is expected\n // to be moved to a nested destination in the next operation.\n const block = domToBlock(xmlChildElement, workspace);\n newBlockIds.push(block.id);\n // AnyDuringMigration because: Argument of type 'string | null' is not\n // assignable to parameter of type 'string'.\n const blockX = xmlChildElement.hasAttribute('x') ?\n parseInt(xmlChildElement.getAttribute('x') as AnyDuringMigration) :\n 10;\n // AnyDuringMigration because: Argument of type 'string | null' is not\n // assignable to parameter of type 'string'.\n const blockY = xmlChildElement.hasAttribute('y') ?\n parseInt(xmlChildElement.getAttribute('y') as AnyDuringMigration) :\n 10;\n if (!isNaN(blockX) && !isNaN(blockY)) {\n block.moveBy(workspace.RTL ? width - blockX : blockX, blockY);\n }\n variablesFirst = false;\n } else if (name === 'shadow') {\n throw TypeError('Shadow block cannot be a top-level block.');\n } else if (name === 'comment') {\n if (workspace.rendered) {\n WorkspaceCommentSvg.fromXmlRendered(\n xmlChildElement, workspace as WorkspaceSvg, width);\n } else {\n WorkspaceComment.fromXml(xmlChildElement, workspace);\n }\n } else if (name === 'variables') {\n if (variablesFirst) {\n domToVariables(xmlChildElement, workspace);\n } else {\n throw Error(\n '\\'variables\\' tag must exist once before block and ' +\n 'shadow tag elements in the workspace XML, but it was found in ' +\n 'another location.');\n }\n variablesFirst = false;\n }\n }\n } finally {\n if (!existingGroup) {\n eventUtils.setGroup(false);\n }\n dom.stopTextWidthCache();\n }\n // Re-enable workspace resizing.\n if ((workspace as WorkspaceSvg).setResizesEnabled) {\n (workspace as WorkspaceSvg).setResizesEnabled(true);\n }\n eventUtils.fire(new (eventUtils.get(eventUtils.FINISHED_LOADING))(workspace));\n return newBlockIds;\n}\n\n/**\n * Decode an XML DOM and create blocks on the workspace. Position the new\n * blocks immediately below prior blocks, aligned by their starting edge.\n *\n * @param xml The XML DOM.\n * @param workspace The workspace to add to.\n * @returns An array containing new block IDs.\n * @alias Blockly.Xml.appendDomToWorkspace\n */\nexport function appendDomToWorkspace(\n xml: Element, workspace: WorkspaceSvg): string[] {\n // First check if we have a WorkspaceSvg, otherwise the blocks have no shape\n // and the position does not matter.\n // Assume it is rendered so we can check.\n if (!(workspace as WorkspaceSvg).getBlocksBoundingBox) {\n return domToWorkspace(xml, workspace);\n }\n\n const bbox = (workspace as WorkspaceSvg).getBlocksBoundingBox();\n // Load the new blocks into the workspace and get the IDs of the new blocks.\n const newBlockIds = domToWorkspace(xml, workspace);\n if (bbox && bbox.top !== bbox.bottom) { // Check if any previous block.\n let offsetY = 0; // Offset to add to y of the new block.\n let offsetX = 0;\n const farY = bbox.bottom; // Bottom position.\n const topX = workspace.RTL ? bbox.right : bbox.left; // X of bounding box.\n // Check position of the new blocks.\n let newLeftX = Infinity; // X of top left corner.\n let newRightX = -Infinity; // X of top right corner.\n let newY = Infinity; // Y of top corner.\n const ySeparation = 10;\n for (let i = 0; i < newBlockIds.length; i++) {\n const blockXY =\n workspace.getBlockById(newBlockIds[i])!.getRelativeToSurfaceXY();\n if (blockXY.y < newY) {\n newY = blockXY.y;\n }\n if (blockXY.x < newLeftX) { // if we left align also on x\n newLeftX = blockXY.x;\n }\n if (blockXY.x > newRightX) { // if we right align also on x\n newRightX = blockXY.x;\n }\n }\n offsetY = farY - newY + ySeparation;\n offsetX = workspace.RTL ? topX - newRightX : topX - newLeftX;\n for (let i = 0; i < newBlockIds.length; i++) {\n const block = workspace.getBlockById(newBlockIds[i]);\n block!.moveBy(offsetX, offsetY);\n }\n }\n return newBlockIds;\n}\n\n/**\n * Decode an XML block tag and create a block (and possibly sub blocks) on the\n * workspace.\n *\n * @param xmlBlock XML block element.\n * @param workspace The workspace.\n * @returns The root block created.\n * @alias Blockly.Xml.domToBlock\n */\nexport function domToBlock(xmlBlock: Element, workspace: Workspace): Block {\n // Create top-level block.\n eventUtils.disable();\n const variablesBeforeCreation = workspace.getAllVariables();\n let topBlock;\n try {\n topBlock = domToBlockHeadless(xmlBlock, workspace);\n // Generate list of all blocks.\n if (workspace.rendered) {\n const topBlockSvg = topBlock as BlockSvg;\n const blocks = topBlock.getDescendants(false);\n topBlockSvg.setConnectionTracking(false);\n // Render each block.\n for (let i = blocks.length - 1; i >= 0; i--) {\n (blocks[i] as BlockSvg).initSvg();\n }\n for (let i = blocks.length - 1; i >= 0; i--) {\n (blocks[i] as BlockSvg).render(false);\n }\n // Populating the connection database may be deferred until after the\n // blocks have rendered.\n setTimeout(function() {\n if (!topBlockSvg.disposed) {\n topBlockSvg.setConnectionTracking(true);\n }\n }, 1);\n topBlockSvg.updateDisabled();\n // Allow the scrollbars to resize and move based on the new contents.\n // TODO(@picklesrus): #387. Remove when domToBlock avoids resizing.\n (workspace as WorkspaceSvg).resizeContents();\n } else {\n const blocks = topBlock.getDescendants(false);\n for (let i = blocks.length - 1; i >= 0; i--) {\n blocks[i].initModel();\n }\n }\n } finally {\n eventUtils.enable();\n }\n if (eventUtils.isEnabled()) {\n // AnyDuringMigration because: Property 'get' does not exist on type\n // '(name: string) => void'.\n const newVariables =\n Variables.getAddedVariables(workspace, variablesBeforeCreation);\n // Fire a VarCreate event for each (if any) new variable created.\n for (let i = 0; i < newVariables.length; i++) {\n const thisVariable = newVariables[i];\n eventUtils.fire(\n new (eventUtils.get(eventUtils.VAR_CREATE))(thisVariable));\n }\n // Block events come after var events, in case they refer to newly created\n // variables.\n eventUtils.fire(new (eventUtils.get(eventUtils.CREATE))(topBlock));\n }\n return topBlock;\n}\n\n/**\n * Decode an XML list of variables and add the variables to the workspace.\n *\n * @param xmlVariables List of XML variable elements.\n * @param workspace The workspace to which the variable should be added.\n * @alias Blockly.Xml.domToVariables\n */\nexport function domToVariables(xmlVariables: Element, workspace: Workspace) {\n for (let i = 0; i < xmlVariables.children.length; i++) {\n const xmlChild = xmlVariables.children[i];\n const type = xmlChild.getAttribute('type');\n const id = xmlChild.getAttribute('id');\n const name = xmlChild.textContent;\n\n // AnyDuringMigration because: Argument of type 'string | null' is not\n // assignable to parameter of type 'string'.\n workspace.createVariable(name as AnyDuringMigration, type, id);\n }\n}\n\n/** A mapping of nodeName to node for child nodes of xmlBlock. */\ninterface childNodeTagMap {\n mutation: Element[];\n comment: Element[];\n data: Element[];\n field: Element[];\n input: Element[];\n next: Element[];\n}\n\n/**\n * Creates a mapping of childNodes for each supported XML tag for the provided\n * xmlBlock. Logs a warning for any encountered unsupported tags.\n *\n * @param xmlBlock XML block element.\n * @returns The childNode map from nodeName to node.\n */\nfunction mapSupportedXmlTags(xmlBlock: Element): childNodeTagMap {\n const childNodeMap = {\n mutation: new Array(),\n comment: new Array(),\n data: new Array(),\n field: new Array(),\n input: new Array(),\n next: new Array(),\n };\n for (let i = 0; i < xmlBlock.children.length; i++) {\n const xmlChild = xmlBlock.children[i];\n if (xmlChild.nodeType === dom.NodeType.TEXT_NODE) {\n // Ignore any text at the level. It's all whitespace anyway.\n continue;\n }\n switch (xmlChild.nodeName.toLowerCase()) {\n case 'mutation':\n childNodeMap.mutation.push(xmlChild);\n break;\n case 'comment':\n childNodeMap.comment.push(xmlChild);\n break;\n case 'data':\n childNodeMap.data.push(xmlChild);\n break;\n case 'title':\n // Titles were renamed to field in December 2013.\n // Fall through.\n case 'field':\n childNodeMap.field.push(xmlChild);\n break;\n case 'value':\n case 'statement':\n childNodeMap.input.push(xmlChild);\n break;\n case 'next':\n childNodeMap.next.push(xmlChild);\n break;\n default:\n // Unknown tag; ignore. Same principle as HTML parsers.\n console.warn('Ignoring unknown tag: ' + xmlChild.nodeName);\n }\n }\n return childNodeMap;\n}\n\n/**\n * Applies mutation tag child nodes to the given block.\n *\n * @param xmlChildren Child nodes.\n * @param block The block to apply the child nodes on.\n * @returns True if mutation may have added some elements that need\n * initialization (requiring initSvg call).\n */\nfunction applyMutationTagNodes(xmlChildren: Element[], block: Block): boolean {\n let shouldCallInitSvg = false;\n for (let i = 0; i < xmlChildren.length; i++) {\n const xmlChild = xmlChildren[i];\n // Custom data for an advanced block.\n if (block.domToMutation) {\n block.domToMutation(xmlChild);\n if ((block as BlockSvg).initSvg) {\n // Mutation may have added some elements that need initializing.\n shouldCallInitSvg = true;\n }\n }\n }\n return shouldCallInitSvg;\n}\n\n/**\n * Applies comment tag child nodes to the given block.\n *\n * @param xmlChildren Child nodes.\n * @param block The block to apply the child nodes on.\n */\nfunction applyCommentTagNodes(xmlChildren: Element[], block: Block) {\n for (let i = 0; i < xmlChildren.length; i++) {\n const xmlChild = xmlChildren[i];\n const text = xmlChild.textContent;\n const pinned = xmlChild.getAttribute('pinned') === 'true';\n // AnyDuringMigration because: Argument of type 'string | null' is not\n // assignable to parameter of type 'string'.\n const width = parseInt(xmlChild.getAttribute('w') as AnyDuringMigration);\n // AnyDuringMigration because: Argument of type 'string | null' is not\n // assignable to parameter of type 'string'.\n const height = parseInt(xmlChild.getAttribute('h') as AnyDuringMigration);\n\n block.setCommentText(text);\n block.commentModel.pinned = pinned;\n if (!isNaN(width) && !isNaN(height)) {\n block.commentModel.size = new Size(width, height);\n }\n\n if (pinned && (block as BlockSvg).getCommentIcon && !block.isInFlyout) {\n const blockSvg = block as BlockSvg;\n setTimeout(function() {\n blockSvg.getCommentIcon()!.setVisible(true);\n }, 1);\n }\n }\n}\n\n/**\n * Applies data tag child nodes to the given block.\n *\n * @param xmlChildren Child nodes.\n * @param block The block to apply the child nodes on.\n */\nfunction applyDataTagNodes(xmlChildren: Element[], block: Block) {\n for (let i = 0; i < xmlChildren.length; i++) {\n const xmlChild = xmlChildren[i];\n block.data = xmlChild.textContent;\n }\n}\n\n/**\n * Applies field tag child nodes to the given block.\n *\n * @param xmlChildren Child nodes.\n * @param block The block to apply the child nodes on.\n */\nfunction applyFieldTagNodes(xmlChildren: Element[], block: Block) {\n for (let i = 0; i < xmlChildren.length; i++) {\n const xmlChild = xmlChildren[i];\n const nodeName = xmlChild.getAttribute('name');\n // AnyDuringMigration because: Argument of type 'string | null' is not\n // assignable to parameter of type 'string'.\n domToField(block, nodeName as AnyDuringMigration, xmlChild);\n }\n}\n\n/**\n * Finds any enclosed blocks or shadows within this XML node.\n *\n * @param xmlNode The XML node to extract child block info from.\n * @returns Any found child block.\n */\nfunction findChildBlocks(xmlNode: Element):\n {childBlockElement: Element|null, childShadowElement: Element|null} {\n const childBlockInfo = {childBlockElement: null, childShadowElement: null};\n for (let i = 0; i < xmlNode.childNodes.length; i++) {\n const xmlChild = xmlNode.childNodes[i];\n if (xmlChild.nodeType === dom.NodeType.ELEMENT_NODE) {\n if (xmlChild.nodeName.toLowerCase() === 'block') {\n // AnyDuringMigration because: Type 'Element' is not assignable to type\n // 'null'.\n childBlockInfo.childBlockElement =\n xmlChild as Element as AnyDuringMigration;\n } else if (xmlChild.nodeName.toLowerCase() === 'shadow') {\n // AnyDuringMigration because: Type 'Element' is not assignable to type\n // 'null'.\n childBlockInfo.childShadowElement =\n xmlChild as Element as AnyDuringMigration;\n }\n }\n }\n return childBlockInfo;\n}\n/**\n * Applies input child nodes (value or statement) to the given block.\n *\n * @param xmlChildren Child nodes.\n * @param workspace The workspace containing the given block.\n * @param block The block to apply the child nodes on.\n * @param prototypeName The prototype name of the block.\n */\nfunction applyInputTagNodes(\n xmlChildren: Element[], workspace: Workspace, block: Block,\n prototypeName: string) {\n for (let i = 0; i < xmlChildren.length; i++) {\n const xmlChild = xmlChildren[i];\n const nodeName = xmlChild.getAttribute('name');\n // AnyDuringMigration because: Argument of type 'string | null' is not\n // assignable to parameter of type 'string'.\n const input = block.getInput(nodeName as AnyDuringMigration);\n if (!input) {\n console.warn(\n 'Ignoring non-existent input ' + nodeName + ' in block ' +\n prototypeName);\n break;\n }\n const childBlockInfo = findChildBlocks(xmlChild);\n if (childBlockInfo.childBlockElement) {\n if (!input.connection) {\n throw TypeError('Input connection does not exist.');\n }\n domToBlockHeadless(\n childBlockInfo.childBlockElement, workspace, input.connection, false);\n }\n // Set shadow after so we don't create a shadow we delete immediately.\n if (childBlockInfo.childShadowElement) {\n input.connection?.setShadowDom(childBlockInfo.childShadowElement);\n }\n }\n}\n\n/**\n * Applies next child nodes to the given block.\n *\n * @param xmlChildren Child nodes.\n * @param workspace The workspace containing the given block.\n * @param block The block to apply the child nodes on.\n */\nfunction applyNextTagNodes(\n xmlChildren: Element[], workspace: Workspace, block: Block) {\n for (let i = 0; i < xmlChildren.length; i++) {\n const xmlChild = xmlChildren[i];\n const childBlockInfo = findChildBlocks(xmlChild);\n if (childBlockInfo.childBlockElement) {\n if (!block.nextConnection) {\n throw TypeError('Next statement does not exist.');\n }\n // If there is more than one XML 'next' tag.\n if (block.nextConnection.isConnected()) {\n throw TypeError('Next statement is already connected.');\n }\n // Create child block.\n domToBlockHeadless(\n childBlockInfo.childBlockElement, workspace, block.nextConnection,\n true);\n }\n // Set shadow after so we don't create a shadow we delete immediately.\n if (childBlockInfo.childShadowElement && block.nextConnection) {\n block.nextConnection.setShadowDom(childBlockInfo.childShadowElement);\n }\n }\n}\n\n/**\n * Decode an XML block tag and create a block (and possibly sub blocks) on the\n * workspace.\n *\n * @param xmlBlock XML block element.\n * @param workspace The workspace.\n * @param parentConnection The parent connection to to connect this block to\n * after instantiating.\n * @param connectedToParentNext Whether the provided parent connection is a next\n * connection, rather than output or statement.\n * @returns The root block created.\n */\nfunction domToBlockHeadless(\n xmlBlock: Element, workspace: Workspace, parentConnection?: Connection,\n connectedToParentNext?: boolean): Block {\n let block = null;\n const prototypeName = xmlBlock.getAttribute('type');\n if (!prototypeName) {\n throw TypeError('Block type unspecified: ' + xmlBlock.outerHTML);\n }\n const id = xmlBlock.getAttribute('id');\n // AnyDuringMigration because: Argument of type 'string | null' is not\n // assignable to parameter of type 'string | undefined'.\n block = workspace.newBlock(prototypeName, id as AnyDuringMigration);\n\n // Preprocess childNodes so tags can be processed in a consistent order.\n const xmlChildNameMap = mapSupportedXmlTags(xmlBlock);\n\n const shouldCallInitSvg =\n applyMutationTagNodes(xmlChildNameMap.mutation, block);\n applyCommentTagNodes(xmlChildNameMap.comment, block);\n applyDataTagNodes(xmlChildNameMap.data, block);\n\n // Connect parent after processing mutation and before setting fields.\n if (parentConnection) {\n if (connectedToParentNext) {\n if (block.previousConnection) {\n parentConnection.connect(block.previousConnection);\n } else {\n throw TypeError('Next block does not have previous statement.');\n }\n } else {\n if (block.outputConnection) {\n parentConnection.connect(block.outputConnection);\n } else if (block.previousConnection) {\n parentConnection.connect(block.previousConnection);\n } else {\n throw TypeError(\n 'Child block does not have output or previous statement.');\n }\n }\n }\n\n applyFieldTagNodes(xmlChildNameMap.field, block);\n applyInputTagNodes(xmlChildNameMap.input, workspace, block, prototypeName);\n applyNextTagNodes(xmlChildNameMap.next, workspace, block);\n\n if (shouldCallInitSvg) {\n // This shouldn't even be called here\n // (ref: https://github.com/google/blockly/pull/4296#issuecomment-884226021\n // But the XML serializer/deserializer is iceboxed so I'm not going to fix\n // it.\n (block as BlockSvg).initSvg();\n }\n\n const inline = xmlBlock.getAttribute('inline');\n if (inline) {\n block.setInputsInline(inline === 'true');\n }\n const disabled = xmlBlock.getAttribute('disabled');\n if (disabled) {\n block.setEnabled(disabled !== 'true' && disabled !== 'disabled');\n }\n const deletable = xmlBlock.getAttribute('deletable');\n if (deletable) {\n block.setDeletable(deletable === 'true');\n }\n const movable = xmlBlock.getAttribute('movable');\n if (movable) {\n block.setMovable(movable === 'true');\n }\n const editable = xmlBlock.getAttribute('editable');\n if (editable) {\n block.setEditable(editable === 'true');\n }\n const collapsed = xmlBlock.getAttribute('collapsed');\n if (collapsed) {\n block.setCollapsed(collapsed === 'true');\n }\n if (xmlBlock.nodeName.toLowerCase() === 'shadow') {\n // Ensure all children are also shadows.\n const children = block.getChildren(false);\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (!child.isShadow()) {\n throw TypeError('Shadow block not allowed non-shadow child.');\n }\n }\n // Ensure this block doesn't have any variable inputs.\n if (block.getVarModels().length) {\n throw TypeError('Shadow blocks cannot have variable references.');\n }\n block.setShadow(true);\n }\n return block;\n}\n\n/**\n * Decode an XML field tag and set the value of that field on the given block.\n *\n * @param block The block that is currently being deserialized.\n * @param fieldName The name of the field on the block.\n * @param xml The field tag to decode.\n */\nfunction domToField(block: Block, fieldName: string, xml: Element) {\n const field = block.getField(fieldName);\n if (!field) {\n console.warn(\n 'Ignoring non-existent field ' + fieldName + ' in block ' + block.type);\n return;\n }\n field.fromXml(xml);\n}\n\n/**\n * Remove any 'next' block (statements in a stack).\n *\n * @param xmlBlock XML block element or an empty DocumentFragment if the block\n * was an insertion marker.\n * @alias Blockly.Xml.deleteNext\n */\nexport function deleteNext(xmlBlock: Element|DocumentFragment) {\n for (let i = 0; i < xmlBlock.childNodes.length; i++) {\n const child = xmlBlock.childNodes[i];\n if (child.nodeName.toLowerCase() === 'next') {\n xmlBlock.removeChild(child);\n break;\n }\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility methods for string manipulation.\n * These methods are not specific to Blockly, and could be factored out into\n * a JavaScript framework such as Closure.\n *\n * @namespace Blockly.utils.string\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.string');\n\nimport * as deprecation from './deprecation.js';\n\n\n/**\n * Fast prefix-checker.\n * Copied from Closure's goog.string.startsWith.\n *\n * @param str The string to check.\n * @param prefix A string to look for at the start of `str`.\n * @returns True if `str` begins with `prefix`.\n * @alias Blockly.utils.string.startsWith\n * @deprecated Use built-in **string.startsWith** instead.\n */\nexport function startsWith(str: string, prefix: string): boolean {\n deprecation.warn(\n 'Blockly.utils.string.startsWith()', 'April 2022', 'April 2023',\n 'Use built-in string.startsWith');\n return str.startsWith(prefix);\n}\n\n/**\n * Given an array of strings, return the length of the shortest one.\n *\n * @param array Array of strings.\n * @returns Length of shortest string.\n * @alias Blockly.utils.string.shortestStringLength\n */\nexport function shortestStringLength(array: string[]): number {\n if (!array.length) {\n return 0;\n }\n return array\n .reduce(function(a, b) {\n return a.length < b.length ? a : b;\n })\n .length;\n}\n\n/**\n * Given an array of strings, return the length of the common prefix.\n * Words may not be split. Any space after a word is included in the length.\n *\n * @param array Array of strings.\n * @param opt_shortest Length of shortest string.\n * @returns Length of common prefix.\n * @alias Blockly.utils.string.commonWordPrefix\n */\nexport function commonWordPrefix(\n array: string[], opt_shortest?: number): number {\n if (!array.length) {\n return 0;\n } else if (array.length === 1) {\n return array[0].length;\n }\n let wordPrefix = 0;\n const max = opt_shortest || shortestStringLength(array);\n let len;\n for (len = 0; len < max; len++) {\n const letter = array[0][len];\n for (let i = 1; i < array.length; i++) {\n if (letter !== array[i][len]) {\n return wordPrefix;\n }\n }\n if (letter === ' ') {\n wordPrefix = len + 1;\n }\n }\n for (let i = 1; i < array.length; i++) {\n const letter = array[i][len];\n if (letter && letter !== ' ') {\n return wordPrefix;\n }\n }\n return max;\n}\n\n/**\n * Given an array of strings, return the length of the common suffix.\n * Words may not be split. Any space after a word is included in the length.\n *\n * @param array Array of strings.\n * @param opt_shortest Length of shortest string.\n * @returns Length of common suffix.\n * @alias Blockly.utils.string.commonWordSuffix\n */\nexport function commonWordSuffix(\n array: string[], opt_shortest?: number): number {\n if (!array.length) {\n return 0;\n } else if (array.length === 1) {\n return array[0].length;\n }\n let wordPrefix = 0;\n const max = opt_shortest || shortestStringLength(array);\n let len;\n for (len = 0; len < max; len++) {\n const letter = array[0].substr(-len - 1, 1);\n for (let i = 1; i < array.length; i++) {\n if (letter !== array[i].substr(-len - 1, 1)) {\n return wordPrefix;\n }\n }\n if (letter === ' ') {\n wordPrefix = len + 1;\n }\n }\n for (let i = 1; i < array.length; i++) {\n const letter = array[i].charAt(array[i].length - len - 1);\n if (letter && letter !== ' ') {\n return wordPrefix;\n }\n }\n return max;\n}\n\n/**\n * Wrap text to the specified width.\n *\n * @param text Text to wrap.\n * @param limit Width to wrap each line.\n * @returns Wrapped text.\n * @alias Blockly.utils.string.wrap\n */\nexport function wrap(text: string, limit: number): string {\n const lines = text.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n lines[i] = wrapLine(lines[i], limit);\n }\n return lines.join('\\n');\n}\n\n/**\n * Wrap single line of text to the specified width.\n *\n * @param text Text to wrap.\n * @param limit Width to wrap each line.\n * @returns Wrapped text.\n */\nfunction wrapLine(text: string, limit: number): string {\n if (text.length <= limit) {\n // Short text, no need to wrap.\n return text;\n }\n // Split the text into words.\n const words = text.trim().split(/\\s+/);\n // Set limit to be the length of the largest word.\n for (let i = 0; i < words.length; i++) {\n if (words[i].length > limit) {\n limit = words[i].length;\n }\n }\n\n let lastScore;\n let score = -Infinity;\n let lastText;\n let lineCount = 1;\n do {\n lastScore = score;\n lastText = text;\n // Create a list of booleans representing if a space (false) or\n // a break (true) appears after each word.\n let wordBreaks = [];\n // Seed the list with evenly spaced linebreaks.\n const steps = words.length / lineCount;\n let insertedBreaks = 1;\n for (let i = 0; i < words.length - 1; i++) {\n if (insertedBreaks < (i + 1.5) / steps) {\n insertedBreaks++;\n wordBreaks[i] = true;\n } else {\n wordBreaks[i] = false;\n }\n }\n wordBreaks = wrapMutate(words, wordBreaks, limit);\n score = wrapScore(words, wordBreaks, limit);\n text = wrapToText(words, wordBreaks);\n lineCount++;\n } while (score > lastScore);\n return lastText;\n}\n\n/**\n * Compute a score for how good the wrapping is.\n *\n * @param words Array of each word.\n * @param wordBreaks Array of line breaks.\n * @param limit Width to wrap each line.\n * @returns Larger the better.\n */\nfunction wrapScore(\n words: string[], wordBreaks: boolean[], limit: number): number {\n // If this function becomes a performance liability, add caching.\n // Compute the length of each line.\n const lineLengths = [0];\n const linePunctuation = [];\n for (let i = 0; i < words.length; i++) {\n lineLengths[lineLengths.length - 1] += words[i].length;\n if (wordBreaks[i] === true) {\n lineLengths.push(0);\n linePunctuation.push(words[i].charAt(words[i].length - 1));\n } else if (wordBreaks[i] === false) {\n lineLengths[lineLengths.length - 1]++;\n }\n }\n const maxLength = Math.max(...lineLengths);\n\n let score = 0;\n for (let i = 0; i < lineLengths.length; i++) {\n // Optimize for width.\n // -2 points per char over limit (scaled to the power of 1.5).\n score -= Math.pow(Math.abs(limit - lineLengths[i]), 1.5) * 2;\n // Optimize for even lines.\n // -1 point per char smaller than max (scaled to the power of 1.5).\n score -= Math.pow(maxLength - lineLengths[i], 1.5);\n // Optimize for structure.\n // Add score to line endings after punctuation.\n if ('.?!'.indexOf(linePunctuation[i]) !== -1) {\n score += limit / 3;\n } else if (',;)]}'.indexOf(linePunctuation[i]) !== -1) {\n score += limit / 4;\n }\n }\n // All else being equal, the last line should not be longer than the\n // previous line. For example, this looks wrong:\n // aaa bbb\n // ccc ddd eee\n if (lineLengths.length > 1 &&\n lineLengths[lineLengths.length - 1] <=\n lineLengths[lineLengths.length - 2]) {\n score += 0.5;\n }\n return score;\n}\n/**\n * Mutate the array of line break locations until an optimal solution is found.\n * No line breaks are added or deleted, they are simply moved around.\n *\n * @param words Array of each word.\n * @param wordBreaks Array of line breaks.\n * @param limit Width to wrap each line.\n * @returns New array of optimal line breaks.\n */\nfunction wrapMutate(\n words: string[], wordBreaks: boolean[], limit: number): boolean[] {\n let bestScore = wrapScore(words, wordBreaks, limit);\n let bestBreaks;\n // Try shifting every line break forward or backward.\n for (let i = 0; i < wordBreaks.length - 1; i++) {\n if (wordBreaks[i] === wordBreaks[i + 1]) {\n continue;\n }\n const mutatedWordBreaks = (new Array()).concat(wordBreaks);\n mutatedWordBreaks[i] = !mutatedWordBreaks[i];\n mutatedWordBreaks[i + 1] = !mutatedWordBreaks[i + 1];\n const mutatedScore = wrapScore(words, mutatedWordBreaks, limit);\n if (mutatedScore > bestScore) {\n bestScore = mutatedScore;\n bestBreaks = mutatedWordBreaks;\n }\n }\n if (bestBreaks) {\n // Found an improvement. See if it may be improved further.\n return wrapMutate(words, bestBreaks, limit);\n }\n // No improvements found. Done.\n return wordBreaks;\n}\n\n/**\n * Reassemble the array of words into text, with the specified line breaks.\n *\n * @param words Array of each word.\n * @param wordBreaks Array of line breaks.\n * @returns Plain text.\n */\nfunction wrapToText(words: string[], wordBreaks: boolean[]): string {\n const text = [];\n for (let i = 0; i < words.length; i++) {\n text.push(words[i]);\n if (wordBreaks[i] !== undefined) {\n text.push(wordBreaks[i] ? '\\n' : ' ');\n }\n }\n return text.join('');\n}\n\n/**\n * Is the given string a number (includes negative and decimals).\n *\n * @param str Input string.\n * @returns True if number, false otherwise.\n * @alias Blockly.utils.string.isNumber\n */\nexport function isNumber(str: string): boolean {\n return /^\\s*-?\\d+(\\.\\d+)?\\s*$/.test(str);\n}\n","/**\n * @license\n * Copyright 2011 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Library to create tooltips for Blockly.\n * First, call createDom() after onload.\n * Second, set the 'tooltip' property on any SVG element that needs a tooltip.\n * If the tooltip is a string, or a function that returns a string, that message\n * will be displayed. If the tooltip is an SVG element, then that object's\n * tooltip will be used. Third, call bindMouseEvents(e) passing the SVG element.\n *\n * @namespace Blockly.Tooltip\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.Tooltip');\n\nimport * as browserEvents from './browser_events.js';\nimport * as common from './common.js';\nimport * as blocklyString from './utils/string.js';\n\n\n/**\n * A type which can define a tooltip.\n * Either a string, an object containing a tooltip property, or a function which\n * returns either a string, or another arbitrarily nested function which\n * eventually unwinds to a string.\n *\n * @alias Blockly.Tooltip.TipInfo\n */\nexport type TipInfo =\n string|{tooltip: AnyDuringMigration}|(() => TipInfo|string|Function);\n\n/**\n * A function that renders custom tooltip UI.\n * 1st parameter: the div element to render content into.\n * 2nd parameter: the element being moused over (i.e., the element for which the\n * tooltip should be shown).\n *\n * @alias Blockly.Tooltip.CustomTooltip\n */\nexport type CustomTooltip = (p1: Element, p2: Element) => AnyDuringMigration;\n\n/**\n * An optional function that renders custom tooltips into the provided DIV. If\n * this is defined, the function will be called instead of rendering the default\n * tooltip UI.\n */\nlet customTooltip: CustomTooltip|undefined = undefined;\n\n/**\n * Sets a custom function that will be called if present instead of the default\n * tooltip UI.\n *\n * @param customFn A custom tooltip used to render an alternate tooltip UI.\n * @alias Blockly.Tooltip.setCustomTooltip\n */\nexport function setCustomTooltip(customFn: CustomTooltip) {\n customTooltip = customFn;\n}\n\n/**\n * Gets the custom tooltip function.\n *\n * @returns The custom tooltip function, if defined.\n */\nexport function getCustomTooltip(): CustomTooltip|undefined {\n return customTooltip;\n}\n\n/** Is a tooltip currently showing? */\nlet visible = false;\n\n/**\n * Returns whether or not a tooltip is showing\n *\n * @returns True if a tooltip is showing\n * @alias Blockly.Tooltip.isVisible\n */\nexport function isVisible(): boolean {\n return visible;\n}\n\n/** Is someone else blocking the tooltip from being shown? */\nlet blocked = false;\n\n/**\n * Maximum width (in characters) of a tooltip.\n *\n * @alias Blockly.Tooltip.LIMIT\n */\nexport const LIMIT = 50;\n\n/** PID of suspended thread to clear tooltip on mouse out. */\nlet mouseOutPid: AnyDuringMigration = 0;\n\n/** PID of suspended thread to show the tooltip. */\nlet showPid: AnyDuringMigration = 0;\n\n/**\n * Last observed X location of the mouse pointer (freezes when tooltip appears).\n */\nlet lastX = 0;\n\n/**\n * Last observed Y location of the mouse pointer (freezes when tooltip appears).\n */\nlet lastY = 0;\n\n/** Current element being pointed at. */\nlet element: AnyDuringMigration = null;\n\n/**\n * Once a tooltip has opened for an element, that element is 'poisoned' and\n * cannot respawn a tooltip until the pointer moves over a different element.\n */\nlet poisonedElement: AnyDuringMigration = null;\n\n/**\n * Horizontal offset between mouse cursor and tooltip.\n *\n * @alias Blockly.Tooltip.OFFSET_X\n */\nexport const OFFSET_X = 0;\n\n/**\n * Vertical offset between mouse cursor and tooltip.\n *\n * @alias Blockly.Tooltip.OFFSET_Y\n */\nexport const OFFSET_Y = 10;\n\n/**\n * Radius mouse can move before killing tooltip.\n *\n * @alias Blockly.Tooltip.RADIUS_OK\n */\nexport const RADIUS_OK = 10;\n\n/**\n * Delay before tooltip appears.\n *\n * @alias Blockly.Tooltip.HOVER_MS\n */\nexport const HOVER_MS = 750;\n\n/**\n * Horizontal padding between tooltip and screen edge.\n *\n * @alias Blockly.Tooltip.MARGINS\n */\nexport const MARGINS = 5;\n\n/** The HTML container. Set once by createDom. */\nlet containerDiv: HTMLDivElement|null = null;\n\n/**\n * Returns the HTML tooltip container.\n *\n * @returns The HTML tooltip container.\n * @alias Blockly.Tooltip.getDiv\n */\nexport function getDiv(): HTMLDivElement|null {\n return containerDiv;\n}\n\n/**\n * Returns the tooltip text for the given element.\n *\n * @param object The object to get the tooltip text of.\n * @returns The tooltip text of the element.\n * @alias Blockly.Tooltip.getTooltipOfObject\n */\nexport function getTooltipOfObject(object: AnyDuringMigration|null): string {\n const obj = getTargetObject(object);\n if (obj) {\n let tooltip = obj.tooltip;\n while (typeof tooltip === 'function') {\n tooltip = tooltip();\n }\n if (typeof tooltip !== 'string') {\n throw Error('Tooltip function must return a string.');\n }\n return tooltip;\n }\n return '';\n}\n\n/**\n * Returns the target object that the given object is targeting for its\n * tooltip. Could be the object itself.\n *\n * @param obj The object are trying to find the target tooltip object of.\n * @returns The target tooltip object.\n */\nfunction getTargetObject(obj: object|null): {tooltip: AnyDuringMigration}|null {\n while (obj && (obj as any).tooltip) {\n if (typeof (obj as any).tooltip === 'string' ||\n typeof (obj as any).tooltip === 'function') {\n return obj as {tooltip: string | (() => string)};\n }\n obj = (obj as any).tooltip;\n }\n return null;\n}\n\n/**\n * Create the tooltip div and inject it onto the page.\n *\n * @alias Blockly.Tooltip.createDom\n */\nexport function createDom() {\n if (containerDiv) {\n return; // Already created.\n }\n // Create an HTML container for popup overlays (e.g. editor widgets).\n containerDiv = document.createElement('div');\n containerDiv.className = 'blocklyTooltipDiv';\n const container = common.getParentContainer() || document.body;\n container.appendChild(containerDiv);\n}\n\n/**\n * Binds the required mouse events onto an SVG element.\n *\n * @param element SVG element onto which tooltip is to be bound.\n * @alias Blockly.Tooltip.bindMouseEvents\n */\nexport function bindMouseEvents(element: Element) {\n // TODO (#6097): Don't stash wrapper info on the DOM.\n (element as AnyDuringMigration).mouseOverWrapper_ =\n browserEvents.bind(element, 'mouseover', null, onMouseOver);\n (element as AnyDuringMigration).mouseOutWrapper_ =\n browserEvents.bind(element, 'mouseout', null, onMouseOut);\n\n // Don't use bindEvent_ for mousemove since that would create a\n // corresponding touch handler, even though this only makes sense in the\n // context of a mouseover/mouseout.\n element.addEventListener('mousemove', onMouseMove, false);\n}\n\n/**\n * Unbinds tooltip mouse events from the SVG element.\n *\n * @param element SVG element onto which tooltip is bound.\n * @alias Blockly.Tooltip.unbindMouseEvents\n */\nexport function unbindMouseEvents(element: Element|null) {\n if (!element) {\n return;\n }\n // TODO (#6097): Don't stash wrapper info on the DOM.\n browserEvents.unbind((element as AnyDuringMigration).mouseOverWrapper_);\n browserEvents.unbind((element as AnyDuringMigration).mouseOutWrapper_);\n element.removeEventListener('mousemove', onMouseMove);\n}\n\n/**\n * Hide the tooltip if the mouse is over a different object.\n * Initialize the tooltip to potentially appear for this object.\n *\n * @param e Mouse event.\n */\nfunction onMouseOver(e: Event) {\n if (blocked) {\n // Someone doesn't want us to show tooltips.\n return;\n }\n // If the tooltip is an object, treat it as a pointer to the next object in\n // the chain to look at. Terminate when a string or function is found.\n const newElement = getTargetObject(e.currentTarget);\n if (element !== newElement) {\n hide();\n poisonedElement = null;\n element = newElement;\n }\n // Forget about any immediately preceding mouseOut event.\n clearTimeout(mouseOutPid);\n}\n\n/**\n * Hide the tooltip if the mouse leaves the object and enters the workspace.\n *\n * @param _e Mouse event.\n */\nfunction onMouseOut(_e: Event) {\n if (blocked) {\n // Someone doesn't want us to show tooltips.\n return;\n }\n // Moving from one element to another (overlapping or with no gap) generates\n // a mouseOut followed instantly by a mouseOver. Fork off the mouseOut\n // event and kill it if a mouseOver is received immediately.\n // This way the task only fully executes if mousing into the void.\n mouseOutPid = setTimeout(function() {\n element = null;\n poisonedElement = null;\n hide();\n }, 1);\n clearTimeout(showPid);\n}\n\n/**\n * When hovering over an element, schedule a tooltip to be shown. If a tooltip\n * is already visible, hide it if the mouse strays out of a certain radius.\n *\n * @param e Mouse event.\n */\nfunction onMouseMove(e: Event) {\n if (!element || !(element as AnyDuringMigration).tooltip) {\n // No tooltip here to show.\n return;\n } else if (blocked) {\n // Someone doesn't want us to show tooltips. We are probably handling a\n // user gesture, such as a click or drag.\n return;\n }\n if (visible) {\n // Compute the distance between the mouse position when the tooltip was\n // shown and the current mouse position. Pythagorean theorem.\n // AnyDuringMigration because: Property 'pageX' does not exist on type\n // 'Event'.\n const dx = lastX - (e as AnyDuringMigration).pageX;\n // AnyDuringMigration because: Property 'pageY' does not exist on type\n // 'Event'.\n const dy = lastY - (e as AnyDuringMigration).pageY;\n if (Math.sqrt(dx * dx + dy * dy) > RADIUS_OK) {\n hide();\n }\n } else if (poisonedElement !== element) {\n // The mouse moved, clear any previously scheduled tooltip.\n clearTimeout(showPid);\n // Maybe this time the mouse will stay put. Schedule showing of tooltip.\n // AnyDuringMigration because: Property 'pageX' does not exist on type\n // 'Event'.\n lastX = (e as AnyDuringMigration).pageX;\n // AnyDuringMigration because: Property 'pageY' does not exist on type\n // 'Event'.\n lastY = (e as AnyDuringMigration).pageY;\n showPid = setTimeout(show, HOVER_MS);\n }\n}\n\n/**\n * Dispose of the tooltip.\n *\n * @alias Blockly.Tooltip.dispose\n * @internal\n */\nexport function dispose() {\n element = null;\n poisonedElement = null;\n hide();\n}\n\n/**\n * Hide the tooltip.\n *\n * @alias Blockly.Tooltip.hide\n */\nexport function hide() {\n if (visible) {\n visible = false;\n if (containerDiv) {\n containerDiv.style.display = 'none';\n }\n }\n if (showPid) {\n clearTimeout(showPid);\n }\n}\n\n/**\n * Hide any in-progress tooltips and block showing new tooltips until the next\n * call to unblock().\n *\n * @alias Blockly.Tooltip.block\n * @internal\n */\nexport function block() {\n hide();\n blocked = true;\n}\n\n/**\n * Unblock tooltips: allow them to be scheduled and shown according to their own\n * logic.\n *\n * @alias Blockly.Tooltip.unblock\n * @internal\n */\nexport function unblock() {\n blocked = false;\n}\n\n/** Renders the tooltip content into the tooltip div. */\nfunction renderContent() {\n if (!containerDiv || !element) {\n // This shouldn't happen, but if it does, we can't render.\n return;\n }\n if (typeof customTooltip === 'function') {\n customTooltip(containerDiv, element);\n } else {\n renderDefaultContent();\n }\n}\n\n/** Renders the default tooltip UI. */\nfunction renderDefaultContent() {\n let tip = getTooltipOfObject(element);\n tip = blocklyString.wrap(tip, LIMIT);\n // Create new text, line by line.\n const lines = tip.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const div = (document.createElement('div'));\n div.appendChild(document.createTextNode(lines[i]));\n containerDiv!.appendChild(div);\n }\n}\n\n/**\n * Gets the coordinates for the tooltip div, taking into account the edges of\n * the screen to prevent showing the tooltip offscreen.\n *\n * @param rtl True if the tooltip should be in right-to-left layout.\n * @returns Coordinates at which the tooltip div should be placed.\n */\nfunction getPosition(rtl: boolean): {x: number, y: number} {\n // Position the tooltip just below the cursor.\n const windowWidth = document.documentElement.clientWidth;\n const windowHeight = document.documentElement.clientHeight;\n\n let anchorX = lastX;\n if (rtl) {\n anchorX -= OFFSET_X + containerDiv!.offsetWidth;\n } else {\n anchorX += OFFSET_X;\n }\n\n let anchorY = lastY + OFFSET_Y;\n if (anchorY + containerDiv!.offsetHeight > windowHeight + window.scrollY) {\n // Falling off the bottom of the screen; shift the tooltip up.\n anchorY -= containerDiv!.offsetHeight + 2 * OFFSET_Y;\n }\n\n if (rtl) {\n // Prevent falling off left edge in RTL mode.\n anchorX = Math.max(MARGINS - window.scrollX, anchorX);\n } else {\n if (anchorX + containerDiv!.offsetWidth >\n windowWidth + window.scrollX - 2 * MARGINS) {\n // Falling off the right edge of the screen;\n // clamp the tooltip on the edge.\n anchorX = windowWidth - containerDiv!.offsetWidth - 2 * MARGINS;\n }\n }\n\n return {x: anchorX, y: anchorY};\n}\n\n/** Create the tooltip and show it. */\nfunction show() {\n if (blocked) {\n // Someone doesn't want us to show tooltips.\n return;\n }\n poisonedElement = element;\n if (!containerDiv) {\n return;\n }\n // Erase all existing text.\n containerDiv.textContent = '';\n\n // Add new content.\n renderContent();\n\n // Display the tooltip.\n const rtl = (element as any).RTL;\n containerDiv.style.direction = rtl ? 'rtl' : 'ltr';\n containerDiv.style.display = 'block';\n visible = true;\n\n const {x, y} = getPosition(rtl);\n containerDiv.style.left = x + 'px';\n containerDiv.style.top = y + 'px';\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility methods for colour manipulation.\n *\n * @namespace Blockly.utils.colour\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.colour');\n\n\n/**\n * The richness of block colours, regardless of the hue.\n * Must be in the range of 0 (inclusive) to 1 (exclusive).\n *\n * @alias Blockly.utils.colour.hsvSaturation\n */\nlet hsvSaturation = 0.45;\n\n/**\n * Get the richness of block colours, regardless of the hue.\n *\n * @alias Blockly.utils.colour.getHsvSaturation\n * @returns The current richness.\n * @internal\n */\nexport function getHsvSaturation(): number {\n return hsvSaturation;\n}\n\n/**\n * Set the richness of block colours, regardless of the hue.\n *\n * @param newSaturation The new richness, in the range of 0 (inclusive) to 1\n * (exclusive)\n * @alias Blockly.utils.colour.setHsvSaturation\n * @internal\n */\nexport function setHsvSaturation(newSaturation: number) {\n hsvSaturation = newSaturation;\n}\n\n/**\n * The intensity of block colours, regardless of the hue.\n * Must be in the range of 0 (inclusive) to 1 (exclusive).\n *\n * @alias Blockly.utils.colour.hsvValue\n */\nlet hsvValue = 0.65;\n\n/**\n * Get the intensity of block colours, regardless of the hue.\n *\n * @alias Blockly.utils.colour.getHsvValue\n * @returns The current intensity.\n * @internal\n */\nexport function getHsvValue(): number {\n return hsvValue;\n}\n\n/**\n * Set the intensity of block colours, regardless of the hue.\n *\n * @param newValue The new intensity, in the range of 0 (inclusive) to 1\n * (exclusive)\n * @alias Blockly.utils.colour.setHsvValue\n * @internal\n */\nexport function setHsvValue(newValue: number) {\n hsvValue = newValue;\n}\n\n/**\n * Parses a colour from a string.\n * .parse('red') = '#ff0000'\n * .parse('#f00') = '#ff0000'\n * .parse('#ff0000') = '#ff0000'\n * .parse('0xff0000') = '#ff0000'\n * .parse('rgb(255, 0, 0)') = '#ff0000'\n *\n * @param str Colour in some CSS format.\n * @returns A string containing a hex representation of the colour, or null if\n * can't be parsed.\n * @alias Blockly.utils.colour.parse\n */\nexport function parse(str: string|number): string|null {\n str = String(str).toLowerCase().trim();\n let hex = names[str];\n if (hex) {\n // e.g. 'red'\n return hex;\n }\n hex = str.substring(0, 2) === '0x' ? '#' + str.substring(2) : str;\n hex = hex[0] === '#' ? hex : '#' + hex;\n if (/^#[0-9a-f]{6}$/.test(hex)) {\n // e.g. '#00ff88'\n return hex;\n }\n if (/^#[0-9a-f]{3}$/.test(hex)) {\n // e.g. '#0f8'\n return ['#', hex[1], hex[1], hex[2], hex[2], hex[3], hex[3]].join('');\n }\n const rgb = str.match(/^(?:rgb)?\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/);\n if (rgb) {\n // e.g. 'rgb(0, 128, 255)'\n const r = Number(rgb[1]);\n const g = Number(rgb[2]);\n const b = Number(rgb[3]);\n if (r >= 0 && r < 256 && g >= 0 && g < 256 && b >= 0 && b < 256) {\n return rgbToHex(r, g, b);\n }\n }\n return null;\n}\n\n/**\n * Converts a colour from RGB to hex representation.\n *\n * @param r Amount of red, int between 0 and 255.\n * @param g Amount of green, int between 0 and 255.\n * @param b Amount of blue, int between 0 and 255.\n * @returns Hex representation of the colour.\n * @alias Blockly.utils.colour.rgbToHex\n */\nexport function rgbToHex(r: number, g: number, b: number): string {\n const rgb = r << 16 | g << 8 | b;\n if (r < 0x10) {\n return '#' + (0x1000000 | rgb).toString(16).substr(1);\n }\n return '#' + rgb.toString(16);\n}\n\n/**\n * Converts a colour to RGB.\n *\n * @param colour String representing colour in any colour format ('#ff0000',\n * 'red', '0xff000', etc).\n * @returns RGB representation of the colour.\n * @alias Blockly.utils.colour.hexToRgb\n */\nexport function hexToRgb(colour: string): number[] {\n const hex = parse(colour);\n if (!hex) {\n return [0, 0, 0];\n }\n\n const rgb = parseInt(hex.substr(1), 16);\n const r = rgb >> 16;\n const g = rgb >> 8 & 255;\n const b = rgb & 255;\n\n return [r, g, b];\n}\n\n/**\n * Converts an HSV triplet to hex representation.\n *\n * @param h Hue value in [0, 360].\n * @param s Saturation value in [0, 1].\n * @param v Brightness in [0, 255].\n * @returns Hex representation of the colour.\n * @alias Blockly.utils.colour.hsvToHex\n */\nexport function hsvToHex(h: number, s: number, v: number): string {\n let red = 0;\n let green = 0;\n let blue = 0;\n if (s === 0) {\n red = v;\n green = v;\n blue = v;\n } else {\n const sextant = Math.floor(h / 60);\n const remainder = h / 60 - sextant;\n const val1 = v * (1 - s);\n const val2 = v * (1 - s * remainder);\n const val3 = v * (1 - s * (1 - remainder));\n switch (sextant) {\n case 1:\n red = val2;\n green = v;\n blue = val1;\n break;\n case 2:\n red = val1;\n green = v;\n blue = val3;\n break;\n case 3:\n red = val1;\n green = val2;\n blue = v;\n break;\n case 4:\n red = val3;\n green = val1;\n blue = v;\n break;\n case 5:\n red = v;\n green = val1;\n blue = val2;\n break;\n case 6:\n case 0:\n red = v;\n green = val3;\n blue = val1;\n break;\n }\n }\n return rgbToHex(Math.floor(red), Math.floor(green), Math.floor(blue));\n}\n\n/**\n * Blend two colours together, using the specified factor to indicate the\n * weight given to the first colour.\n *\n * @param colour1 First colour.\n * @param colour2 Second colour.\n * @param factor The weight to be given to colour1 over colour2.\n * Values should be in the range [0, 1].\n * @returns Combined colour represented in hex.\n * @alias Blockly.utils.colour.blend\n */\nexport function blend(colour1: string, colour2: string, factor: number): string|\n null {\n const hex1 = parse(colour1);\n if (!hex1) {\n return null;\n }\n const hex2 = parse(colour2);\n if (!hex2) {\n return null;\n }\n const rgb1 = hexToRgb(hex1);\n const rgb2 = hexToRgb(hex2);\n const r = Math.round(rgb2[0] + factor * (rgb1[0] - rgb2[0]));\n const g = Math.round(rgb2[1] + factor * (rgb1[1] - rgb2[1]));\n const b = Math.round(rgb2[2] + factor * (rgb1[2] - rgb2[2]));\n return rgbToHex(r, g, b);\n}\n\n/**\n * A map that contains the 16 basic colour keywords as defined by W3C:\n * https://www.w3.org/TR/2018/REC-css-color-3-20180619/#html4\n * The keys of this map are the lowercase \"readable\" names of the colours,\n * while the values are the \"hex\" values.\n *\n * @alias Blockly.utils.colour.names\n */\nexport const names: {[key: string]: string} = {\n 'aqua': '#00ffff',\n 'black': '#000000',\n 'blue': '#0000ff',\n 'fuchsia': '#ff00ff',\n 'gray': '#808080',\n 'green': '#008000',\n 'lime': '#00ff00',\n 'maroon': '#800000',\n 'navy': '#000080',\n 'olive': '#808000',\n 'purple': '#800080',\n 'red': '#ff0000',\n 'silver': '#c0c0c0',\n 'teal': '#008080',\n 'white': '#ffffff',\n 'yellow': '#ffff00',\n};\n\n/**\n * Convert a hue (HSV model) into an RGB hex triplet.\n *\n * @param hue Hue on a colour wheel (0-360).\n * @returns RGB code, e.g. '#5ba65b'.\n * @alias Blockly.utils.colour.hueToHex\n */\nexport function hueToHex(hue: number): string {\n return hsvToHex(hue, hsvSaturation, hsvValue * 255);\n}\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @namespace Blockly.utils.parsing\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.parsing');\n\nimport {Msg} from '../msg.js';\n\nimport * as colourUtils from './colour.js';\n\n\n/**\n * Internal implementation of the message reference and interpolation token\n * parsing used by tokenizeInterpolation() and replaceMessageReferences().\n *\n * @param message Text which might contain string table references and\n * interpolation tokens.\n * @param parseInterpolationTokens Option to parse numeric\n * interpolation tokens (%1, %2, ...) when true.\n * @returns Array of strings and numbers.\n */\nfunction tokenizeInterpolationInternal(\n message: string, parseInterpolationTokens: boolean): (string|number)[] {\n const tokens = [];\n const chars = message.split('');\n chars.push( // End marker.\n '');\n // Parse the message with a finite state machine.\n // 0 - Base case.\n // 1 - % found.\n // 2 - Digit found.\n // 3 - Message ref found.\n let state = 0;\n const buffer = new Array();\n let number = null;\n for (let i = 0; i < chars.length; i++) {\n const c = chars[i];\n if (state === 0) { // Start escape.\n if (c === '%') {\n const text = buffer.join('');\n if (text) {\n tokens.push(text);\n }\n buffer.length = 0;\n state = 1;\n } else {\n buffer.push(c); // Regular char.\n }\n } else if (state === 1) {\n if (c === '%') {\n buffer.push(c); // Escaped %: %%\n state = 0;\n } else if (parseInterpolationTokens && '0' <= c && c <= '9') {\n state = 2;\n number = c;\n const text = buffer.join('');\n if (text) {\n tokens.push(text);\n }\n buffer.length = 0;\n } else if (c === '{') {\n state = 3;\n } else {\n buffer.push('%', c); // Not recognized. Return as literal.\n state = 0;\n }\n } else if (state === 2) {\n if ('0' <= c && c <= '9') {\n number += c; // Multi-digit number.\n } else {\n tokens.push(parseInt(number ?? '', 10));\n i--; // Parse this char again.\n state = 0;\n }\n } else if (state === 3) { // String table reference\n if (c === '') {\n // Premature end before closing '}'\n buffer.splice(0, 0, '%{'); // Re-insert leading delimiter\n i--; // Parse this char again.\n state = 0; // and parse as string literal.\n } else if (c !== '}') {\n buffer.push(c);\n } else {\n const rawKey = buffer.join('');\n if (/[A-Z]\\w*/i.test(rawKey)) { // Strict matching\n // Found a valid string key. Attempt case insensitive match.\n const keyUpper = rawKey.toUpperCase();\n\n // BKY_ is the prefix used to namespace the strings used in\n // Blockly core files and the predefined blocks in ../blocks/.\n // These strings are defined in ../msgs/ files.\n const bklyKey =\n keyUpper.startsWith('BKY_') ? keyUpper.substring(4) : null;\n if (bklyKey && bklyKey in Msg) {\n const rawValue = Msg[bklyKey];\n if (typeof rawValue === 'string') {\n // Attempt to dereference substrings, too, appending to the\n // end.\n Array.prototype.push.apply(\n tokens,\n tokenizeInterpolationInternal(\n rawValue, parseInterpolationTokens));\n } else if (parseInterpolationTokens) {\n // When parsing interpolation tokens, numbers are special\n // placeholders (%1, %2, etc). Make sure all other values are\n // strings.\n tokens.push(String(rawValue));\n } else {\n tokens.push(rawValue);\n }\n } else {\n // No entry found in the string table. Pass reference as string.\n tokens.push('%{' + rawKey + '}');\n }\n buffer.length = 0; // Clear the array\n state = 0;\n } else {\n tokens.push('%{' + rawKey + '}');\n buffer.length = 0;\n state = 0; // and parse as string literal.\n }\n }\n }\n }\n let text = buffer.join('');\n if (text) {\n tokens.push(text);\n }\n\n // Merge adjacent text tokens into a single string.\n const mergedTokens = [];\n buffer.length = 0;\n for (let i = 0; i < tokens.length; i++) {\n if (typeof tokens[i] === 'string') {\n buffer.push(tokens[i] as string);\n } else {\n text = buffer.join('');\n if (text) {\n mergedTokens.push(text);\n }\n buffer.length = 0;\n mergedTokens.push(tokens[i]);\n }\n }\n text = buffer.join('');\n if (text) {\n mergedTokens.push(text);\n }\n buffer.length = 0;\n\n return mergedTokens;\n}\n\n/**\n * Parse a string with any number of interpolation tokens (%1, %2, ...).\n * It will also replace string table references (e.g., %{bky_my_msg} and\n * %{BKY_MY_MSG} will both be replaced with the value in\n * Msg['MY_MSG']). Percentage sign characters '%' may be self-escaped\n * (e.g., '%%').\n *\n * @param message Text which might contain string table references and\n * interpolation tokens.\n * @returns Array of strings and numbers.\n * @alias Blockly.utils.parsing.tokenizeInterpolation\n */\nexport function tokenizeInterpolation(message: string): (string|number)[] {\n return tokenizeInterpolationInternal(message, true);\n}\n\n/**\n * Replaces string table references in a message, if the message is a string.\n * For example, \"%{bky_my_msg}\" and \"%{BKY_MY_MSG}\" will both be replaced with\n * the value in Msg['MY_MSG'].\n *\n * @param message Message, which may be a string that contains\n * string table references.\n * @returns String with message references replaced.\n * @alias Blockly.utils.parsing.replaceMessageReferences\n */\nexport function replaceMessageReferences(message: string|any): string {\n if (typeof message !== 'string') {\n return message;\n }\n const interpolatedResult = tokenizeInterpolationInternal(message, false);\n // When parseInterpolationTokens === false, interpolatedResult should be at\n // most length 1.\n return interpolatedResult.length ? String(interpolatedResult[0]) : '';\n}\n\n/**\n * Validates that any %{MSG_KEY} references in the message refer to keys of\n * the Msg string table.\n *\n * @param message Text which might contain string table references.\n * @returns True if all message references have matching values.\n * Otherwise, false.\n * @alias Blockly.utils.parsing.checkMessageReferences\n */\nexport function checkMessageReferences(message: string): boolean {\n let validSoFar = true;\n\n const msgTable = Msg;\n // TODO (#1169): Implement support for other string tables,\n // prefixes other than BKY_.\n const m = message.match(/%{BKY_[A-Z]\\w*}/ig);\n if (m) {\n for (let i = 0; i < m.length; i++) {\n const msgKey = m[i].toUpperCase();\n if (msgTable[msgKey.slice(6, -1)] === undefined) {\n console.warn('No message string for ' + m[i] + ' in ' + message);\n validSoFar = false; // Continue to report other errors.\n }\n }\n }\n\n return validSoFar;\n}\n\n/**\n * Parse a block colour from a number or string, as provided in a block\n * definition.\n *\n * @param colour HSV hue value (0 to 360), #RRGGBB string,\n * or a message reference string pointing to one of those two values.\n * @returns An object containing the colour as\n * a #RRGGBB string, and the hue if the input was an HSV hue value.\n * @throws {Error} If the colour cannot be parsed.\n * @alias Blockly.utils.parsing.parseBlockColour\n */\nexport function parseBlockColour(colour: number|\n string): {hue: number|null, hex: string} {\n const dereferenced =\n typeof colour === 'string' ? replaceMessageReferences(colour) : colour;\n\n const hue = Number(dereferenced);\n if (!isNaN(hue) && 0 <= hue && hue <= 360) {\n return {\n hue: hue,\n hex: colourUtils.hsvToHex(\n hue, colourUtils.getHsvSaturation(), colourUtils.getHsvValue() * 255),\n };\n } else {\n const hex = colourUtils.parse(dereferenced);\n if (hex) {\n // Only store hue if colour is set as a hue.\n return {hue: null, hex: hex};\n } else {\n let errorMsg = 'Invalid colour: \"' + dereferenced + '\"';\n if (colour !== dereferenced) {\n errorMsg += ' (from \"' + colour + '\")';\n }\n throw Error(errorMsg);\n }\n }\n}\n","/**\n * @license\n * Copyright 2013 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * A div that floats on top of Blockly. This singleton contains\n * temporary HTML UI widgets that the user is currently interacting with.\n * E.g. text input areas, colour pickers, context menus.\n *\n * @namespace Blockly.WidgetDiv\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.WidgetDiv');\n\nimport * as common from './common.js';\nimport * as dom from './utils/dom.js';\nimport type {Rect} from './utils/rect.js';\nimport type {Size} from './utils/size.js';\nimport type {WorkspaceSvg} from './workspace_svg.js';\n\n\n/** The object currently using this container. */\nlet owner: unknown = null;\n\n/** Optional cleanup function set by whichever object uses the widget. */\nlet dispose: (() => void)|null = null;\n\n/** A class name representing the current owner's workspace renderer. */\nlet rendererClassName = '';\n\n/** A class name representing the current owner's workspace theme. */\nlet themeClassName = '';\n\n/** The HTML container for popup overlays (e.g. editor widgets). */\nlet containerDiv: HTMLDivElement|null;\n\n/**\n * Returns the HTML container for editor widgets.\n *\n * @returns The editor widget container.\n * @alias Blockly.WidgetDiv.getDiv\n */\nexport function getDiv(): HTMLDivElement|null {\n return containerDiv;\n}\n\n/**\n * Allows unit tests to reset the div. Do not use outside of tests.\n *\n * @param newDiv The new value for the DIV field.\n * @alias Blockly.WidgetDiv.testOnly_setDiv\n * @internal\n */\nexport function testOnly_setDiv(newDiv: HTMLDivElement|null) {\n containerDiv = newDiv;\n}\n\n/**\n * Create the widget div and inject it onto the page.\n *\n * @alias Blockly.WidgetDiv.createDom\n */\nexport function createDom() {\n if (containerDiv) {\n return; // Already created.\n }\n\n containerDiv = document.createElement('div') as HTMLDivElement;\n containerDiv.className = 'blocklyWidgetDiv';\n const container = common.getParentContainer() || document.body;\n container.appendChild(containerDiv);\n}\n\n/**\n * Initialize and display the widget div. Close the old one if needed.\n *\n * @param newOwner The object that will be using this container.\n * @param rtl Right-to-left (true) or left-to-right (false).\n * @param newDispose Optional cleanup function to be run when the widget is\n * closed.\n * @alias Blockly.WidgetDiv.show\n */\nexport function show(newOwner: unknown, rtl: boolean, newDispose: () => void) {\n hide();\n owner = newOwner;\n dispose = newDispose;\n const div = containerDiv;\n if (!div) return;\n div.style.direction = rtl ? 'rtl' : 'ltr';\n div.style.display = 'block';\n const mainWorkspace = common.getMainWorkspace() as WorkspaceSvg;\n rendererClassName = mainWorkspace.getRenderer().getClassName();\n themeClassName = mainWorkspace.getTheme().getClassName();\n if (rendererClassName) {\n dom.addClass(div, rendererClassName);\n }\n if (themeClassName) {\n dom.addClass(div, themeClassName);\n }\n}\n\n/**\n * Destroy the widget and hide the div.\n *\n * @alias Blockly.WidgetDiv.hide\n */\nexport function hide() {\n if (!isVisible()) {\n return;\n }\n owner = null;\n\n const div = containerDiv;\n if (!div) return;\n div.style.display = 'none';\n div.style.left = '';\n div.style.top = '';\n dispose && dispose();\n dispose = null;\n div.textContent = '';\n\n if (rendererClassName) {\n dom.removeClass(div, rendererClassName);\n rendererClassName = '';\n }\n if (themeClassName) {\n dom.removeClass(div, themeClassName);\n themeClassName = '';\n }\n (common.getMainWorkspace() as WorkspaceSvg).markFocused();\n}\n\n/**\n * Is the container visible?\n *\n * @returns True if visible.\n * @alias Blockly.WidgetDiv.isVisible\n */\nexport function isVisible(): boolean {\n return !!owner;\n}\n\n/**\n * Destroy the widget and hide the div if it is being used by the specified\n * object.\n *\n * @param oldOwner The object that was using this container.\n * @alias Blockly.WidgetDiv.hideIfOwner\n */\nexport function hideIfOwner(oldOwner: unknown) {\n if (owner === oldOwner) {\n hide();\n }\n}\n/**\n * Set the widget div's position and height. This function does nothing clever:\n * it will not ensure that your widget div ends up in the visible window.\n *\n * @param x Horizontal location (window coordinates, not body).\n * @param y Vertical location (window coordinates, not body).\n * @param height The height of the widget div (pixels).\n */\nfunction positionInternal(x: number, y: number, height: number) {\n containerDiv!.style.left = x + 'px';\n containerDiv!.style.top = y + 'px';\n containerDiv!.style.height = height + 'px';\n}\n\n/**\n * Position the widget div based on an anchor rectangle.\n * The widget should be placed adjacent to but not overlapping the anchor\n * rectangle. The preferred position is directly below and aligned to the left\n * (LTR) or right (RTL) side of the anchor.\n *\n * @param viewportBBox The bounding rectangle of the current viewport, in window\n * coordinates.\n * @param anchorBBox The bounding rectangle of the anchor, in window\n * coordinates.\n * @param widgetSize The size of the widget that is inside the widget div, in\n * window coordinates.\n * @param rtl Whether the workspace is in RTL mode. This determines horizontal\n * alignment.\n * @alias Blockly.WidgetDiv.positionWithAnchor\n * @internal\n */\nexport function positionWithAnchor(\n viewportBBox: Rect, anchorBBox: Rect, widgetSize: Size, rtl: boolean) {\n const y = calculateY(viewportBBox, anchorBBox, widgetSize);\n const x = calculateX(viewportBBox, anchorBBox, widgetSize, rtl);\n\n if (y < 0) {\n positionInternal(x, 0, widgetSize.height + y);\n } else {\n positionInternal(x, y, widgetSize.height);\n }\n}\n\n/**\n * Calculate an x position (in window coordinates) such that the widget will not\n * be offscreen on the right or left.\n *\n * @param viewportBBox The bounding rectangle of the current viewport, in window\n * coordinates.\n * @param anchorBBox The bounding rectangle of the anchor, in window\n * coordinates.\n * @param widgetSize The dimensions of the widget inside the widget div.\n * @param rtl Whether the Blockly workspace is in RTL mode.\n * @returns A valid x-coordinate for the top left corner of the widget div, in\n * window coordinates.\n */\nfunction calculateX(\n viewportBBox: Rect, anchorBBox: Rect, widgetSize: Size,\n rtl: boolean): number {\n if (rtl) {\n // Try to align the right side of the field and the right side of widget.\n const widgetLeft = anchorBBox.right - widgetSize.width;\n // Don't go offscreen left.\n const x = Math.max(widgetLeft, viewportBBox.left);\n // But really don't go offscreen right:\n return Math.min(x, viewportBBox.right - widgetSize.width);\n } else {\n // Try to align the left side of the field and the left side of widget.\n // Don't go offscreen right.\n const x = Math.min(anchorBBox.left, viewportBBox.right - widgetSize.width);\n // But left is more important, because that's where the text is.\n return Math.max(x, viewportBBox.left);\n }\n}\n\n/**\n * Calculate a y position (in window coordinates) such that the widget will not\n * be offscreen on the top or bottom.\n *\n * @param viewportBBox The bounding rectangle of the current viewport, in window\n * coordinates.\n * @param anchorBBox The bounding rectangle of the anchor, in window\n * coordinates.\n * @param widgetSize The dimensions of the widget inside the widget div.\n * @returns A valid y-coordinate for the top left corner of the widget div, in\n * window coordinates.\n */\nfunction calculateY(\n viewportBBox: Rect, anchorBBox: Rect, widgetSize: Size): number {\n // Flip the widget vertically if off the bottom.\n // The widget could go off the top of the window, but it would also go off\n // the bottom. The window is just too small.\n if (anchorBBox.bottom + widgetSize.height >= viewportBBox.bottom) {\n // The bottom of the widget is at the top of the field.\n return anchorBBox.top - widgetSize.height;\n } else {\n // The top of the widget is at the bottom of the field.\n return anchorBBox.bottom;\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Fields can be created based on a JSON definition. This file\n * contains methods for registering those JSON definitions, and building the\n * fields based on JSON.\n *\n * @namespace Blockly.fieldRegistry\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.fieldRegistry');\n\nimport type {Field} from './field.js';\nimport type {IRegistrableField} from './interfaces/i_registrable_field.js';\nimport * as registry from './registry.js';\n\n\n/**\n * Registers a field type.\n * fieldRegistry.fromJson uses this registry to\n * find the appropriate field type.\n *\n * @param type The field type name as used in the JSON definition.\n * @param fieldClass The field class containing a fromJson function that can\n * construct an instance of the field.\n * @throws {Error} if the type name is empty, the field is already registered,\n * or the fieldClass is not an object containing a fromJson function.\n * @alias Blockly.fieldRegistry.register\n */\nexport function register(type: string, fieldClass: IRegistrableField) {\n registry.register(registry.Type.FIELD, type, fieldClass);\n}\n\n/**\n * Unregisters the field registered with the given type.\n *\n * @param type The field type name as used in the JSON definition.\n * @alias Blockly.fieldRegistry.unregister\n */\nexport function unregister(type: string) {\n registry.unregister(registry.Type.FIELD, type);\n}\n\n/**\n * Construct a Field from a JSON arg object.\n * Finds the appropriate registered field by the type name as registered using\n * fieldRegistry.register.\n *\n * @param options A JSON object with a type and options specific to the field\n * type.\n * @returns The new field instance or null if a field wasn't found with the\n * given type name\n * @alias Blockly.fieldRegistry.fromJson\n * @internal\n */\nexport function fromJson(options: AnyDuringMigration): Field|null {\n return TEST_ONLY.fromJsonInternal(options);\n}\n\n/**\n * Private version of fromJson for stubbing in tests.\n *\n * @param options\n */\nfunction fromJsonInternal(options: AnyDuringMigration): Field|null {\n const fieldObject = registry.getObject(registry.Type.FIELD, options['type']);\n if (!fieldObject) {\n console.warn(\n 'Blockly could not create a field of type ' + options['type'] +\n '. The field is probably not being registered. This could be because' +\n ' the file is not loaded, the field does not register itself (Issue' +\n ' #1584), or the registration is not being reached.');\n return null;\n } else if (typeof (fieldObject as any)['fromJson'] !== 'function') {\n throw new TypeError('returned Field was not a IRegistrableField');\n } else {\n return (fieldObject as unknown as IRegistrableField).fromJson(options);\n }\n}\n\nexport const TEST_ONLY = {\n fromJsonInternal,\n};\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * ARIA-related constants and utilities.\n * These methods are not specific to Blockly, and could be factored out into\n * a JavaScript framework such as Closure.\n *\n * @namespace Blockly.utils.aria\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.aria');\n\n\n/** ARIA states/properties prefix. */\nconst ARIA_PREFIX = 'aria-';\n\n/** ARIA role attribute. */\nconst ROLE_ATTRIBUTE = 'role';\n\n/**\n * ARIA role values.\n * Copied from Closure's goog.a11y.aria.Role\n *\n * @alias Blockly.utils.aria.Role\n */\nexport enum Role {\n // ARIA role for an interactive control of tabular data.\n GRID = 'grid',\n\n // ARIA role for a cell in a grid.\n GRIDCELL = 'gridcell',\n // ARIA role for a group of related elements like tree item siblings.\n GROUP = 'group',\n\n // ARIA role for a listbox.\n LISTBOX = 'listbox',\n\n // ARIA role for a popup menu.\n MENU = 'menu',\n\n // ARIA role for menu item elements.\n MENUITEM = 'menuitem',\n // ARIA role for a checkbox box element inside a menu.\n MENUITEMCHECKBOX = 'menuitemcheckbox',\n // ARIA role for option items that are children of combobox, listbox, menu,\n // radiogroup, or tree elements.\n OPTION = 'option',\n // ARIA role for ignorable cosmetic elements with no semantic significance.\n PRESENTATION = 'presentation',\n\n // ARIA role for a row of cells in a grid.\n ROW = 'row',\n // ARIA role for a tree.\n TREE = 'tree',\n\n // ARIA role for a tree item that sometimes may be expanded or collapsed.\n TREEITEM = 'treeitem'\n}\n\n/**\n * ARIA states and properties.\n * Copied from Closure's goog.a11y.aria.State\n *\n * @alias Blockly.utils.aria.State\n */\nexport enum State {\n // ARIA property for setting the currently active descendant of an element,\n // for example the selected item in a list box. Value: ID of an element.\n ACTIVEDESCENDANT = 'activedescendant',\n // ARIA property defines the total number of columns in a table, grid, or\n // treegrid.\n // Value: integer.\n COLCOUNT = 'colcount',\n // ARIA state for a disabled item. Value: one of {true, false}.\n DISABLED = 'disabled',\n\n // ARIA state for setting whether the element like a tree node is expanded.\n // Value: one of {true, false, undefined}.\n EXPANDED = 'expanded',\n\n // ARIA state indicating that the entered value does not conform. Value:\n // one of {false, true, 'grammar', 'spelling'}\n INVALID = 'invalid',\n\n // ARIA property that provides a label to override any other text, value, or\n // contents used to describe this element. Value: string.\n LABEL = 'label',\n // ARIA property for setting the element which labels another element.\n // Value: space-separated IDs of elements.\n LABELLEDBY = 'labelledby',\n\n // ARIA property for setting the level of an element in the hierarchy.\n // Value: integer.\n LEVEL = 'level',\n // ARIA property indicating if the element is horizontal or vertical.\n // Value: one of {'vertical', 'horizontal'}.\n ORIENTATION = 'orientation',\n\n // ARIA property that defines an element's number of position in a list.\n // Value: integer.\n POSINSET = 'posinset',\n\n // ARIA property defines the total number of rows in a table, grid, or\n // treegrid.\n // Value: integer.\n ROWCOUNT = 'rowcount',\n\n // ARIA state for setting the currently selected item in the list.\n // Value: one of {true, false, undefined}.\n SELECTED = 'selected',\n // ARIA property defining the number of items in a list. Value: integer.\n SETSIZE = 'setsize',\n\n // ARIA property for slider maximum value. Value: number.\n VALUEMAX = 'valuemax',\n\n // ARIA property for slider minimum value. Value: number.\n VALUEMIN = 'valuemin'\n}\n\n/**\n * Sets the role of an element.\n *\n * Similar to Closure's goog.a11y.aria\n *\n * @param element DOM node to set role of.\n * @param roleName Role name.\n * @alias Blockly.utils.aria.setRole\n */\nexport function setRole(element: Element, roleName: Role) {\n element.setAttribute(ROLE_ATTRIBUTE, roleName);\n}\n\n/**\n * Sets the state or property of an element.\n * Copied from Closure's goog.a11y.aria\n *\n * @param element DOM node where we set state.\n * @param stateName State attribute being set.\n * Automatically adds prefix 'aria-' to the state name if the attribute is\n * not an extra attribute.\n * @param value Value for the state attribute.\n * @alias Blockly.utils.aria.setState\n */\nexport function setState(\n element: Element, stateName: State, value: string|boolean|number|string[]) {\n if (Array.isArray(value)) {\n value = value.join(' ');\n }\n const attrStateName = ARIA_PREFIX + stateName;\n element.setAttribute(attrStateName, `${value}`);\n}\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Dropdown input field. Used for editable titles and variables.\n * In the interests of a consistent UI, the toolbox shares some functions and\n * properties with the context menu.\n *\n * @class\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.FieldDropdown');\n\nimport type {BlockSvg} from './block_svg.js';\nimport * as dropDownDiv from './dropdowndiv.js';\nimport {FieldConfig, Field, UnattachedFieldError} from './field.js';\nimport * as fieldRegistry from './field_registry.js';\nimport {Menu} from './menu.js';\nimport {MenuItem} from './menuitem.js';\nimport * as aria from './utils/aria.js';\nimport {Coordinate} from './utils/coordinate.js';\nimport * as dom from './utils/dom.js';\nimport * as parsing from './utils/parsing.js';\nimport type {Sentinel} from './utils/sentinel.js';\nimport * as utilsString from './utils/string.js';\nimport {Svg} from './utils/svg.js';\nimport * as userAgent from './utils/useragent.js';\n\n\n/**\n * Class for an editable dropdown field.\n *\n * @alias Blockly.FieldDropdown\n */\nexport class FieldDropdown extends Field {\n /** Horizontal distance that a checkmark overhangs the dropdown. */\n static CHECKMARK_OVERHANG = 25;\n\n /**\n * Maximum height of the dropdown menu, as a percentage of the viewport\n * height.\n */\n static MAX_MENU_HEIGHT_VH = 0.45;\n static ARROW_CHAR: AnyDuringMigration;\n\n /** A reference to the currently selected menu item. */\n private selectedMenuItem_: MenuItem|null = null;\n\n /** The dropdown menu. */\n protected menu_: Menu|null = null;\n\n /**\n * SVG image element if currently selected option is an image, or null.\n */\n private imageElement_: SVGImageElement|null = null;\n\n /** Tspan based arrow element. */\n private arrow_: SVGTSpanElement|null = null;\n\n /** SVG based arrow element. */\n private svgArrow_: SVGElement|null = null;\n\n /**\n * Serializable fields are saved by the serializer, non-serializable fields\n * are not. Editable fields should also be serializable.\n */\n override SERIALIZABLE = true;\n\n /** Mouse cursor style when over the hotspot that initiates the editor. */\n override CURSOR = 'default';\n // TODO(b/109816955): remove '!', see go/strict-prop-init-fix.\n protected menuGenerator_!: AnyDuringMigration[][]|\n ((this: FieldDropdown) => AnyDuringMigration[][]);\n\n /** A cache of the most recently generated options. */\n // AnyDuringMigration because: Type 'null' is not assignable to type\n // 'string[][]'.\n private generatedOptions_: string[][] = null as AnyDuringMigration;\n\n /**\n * The prefix field label, of common words set after options are trimmed.\n *\n * @internal\n */\n override prefixField: string|null = null;\n\n /**\n * The suffix field label, of common words set after options are trimmed.\n *\n * @internal\n */\n override suffixField: string|null = null;\n // TODO(b/109816955): remove '!', see go/strict-prop-init-fix.\n private selectedOption_!: Array;\n override clickTarget_: AnyDuringMigration;\n\n /**\n * @param menuGenerator A non-empty array of options for a dropdown list, or a\n * function which generates these options. Also accepts Field.SKIP_SETUP\n * if you wish to skip setup (only used by subclasses that want to handle\n * configuration and setting the field value after their own constructors\n * have run).\n * @param opt_validator A function that is called to validate changes to the\n * field's value. Takes in a language-neutral dropdown option & returns a\n * validated language-neutral dropdown option, or null to abort the\n * change.\n * @param opt_config A map of options used to configure the field.\n * See the [field creation documentation]{@link\n * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/dropdown#creation}\n * for a list of properties this parameter supports.\n * @throws {TypeError} If `menuGenerator` options are incorrectly structured.\n */\n constructor(\n menuGenerator: AnyDuringMigration[][]|Function|Sentinel,\n opt_validator?: Function, opt_config?: FieldConfig) {\n super(Field.SKIP_SETUP);\n\n // If we pass SKIP_SETUP, don't do *anything* with the menu generator.\n if (menuGenerator === Field.SKIP_SETUP) {\n return;\n }\n\n if (Array.isArray(menuGenerator)) {\n validateOptions(menuGenerator);\n // Deep copy the option structure so it doesn't change.\n menuGenerator = JSON.parse(JSON.stringify(menuGenerator));\n }\n\n /**\n * An array of options for a dropdown list,\n * or a function which generates these options.\n */\n this.menuGenerator_ = menuGenerator as AnyDuringMigration[][] |\n ((this: FieldDropdown) => AnyDuringMigration[][]);\n\n this.trimOptions_();\n\n /**\n * The currently selected option. The field is initialized with the\n * first option selected.\n */\n this.selectedOption_ = this.getOptions(false)[0];\n\n if (opt_config) {\n this.configure_(opt_config);\n }\n this.setValue(this.selectedOption_[1]);\n if (opt_validator) {\n this.setValidator(opt_validator);\n }\n }\n\n /**\n * Sets the field's value based on the given XML element. Should only be\n * called by Blockly.Xml.\n *\n * @param fieldElement The element containing info about the field's state.\n * @internal\n */\n override fromXml(fieldElement: Element) {\n if (this.isOptionListDynamic()) {\n this.getOptions(false);\n }\n this.setValue(fieldElement.textContent);\n }\n\n /**\n * Sets the field's value based on the given state.\n *\n * @param state The state to apply to the dropdown field.\n * @internal\n */\n override loadState(state: AnyDuringMigration) {\n if (this.loadLegacyState(FieldDropdown, state)) {\n return;\n }\n if (this.isOptionListDynamic()) {\n this.getOptions(false);\n }\n this.setValue(state);\n }\n\n /**\n * Create the block UI for this dropdown.\n *\n * @internal\n */\n override initView() {\n if (this.shouldAddBorderRect_()) {\n this.createBorderRect_();\n } else {\n this.clickTarget_ = (this.sourceBlock_ as BlockSvg).getSvgRoot();\n }\n this.createTextElement_();\n\n this.imageElement_ = dom.createSvgElement(Svg.IMAGE, {}, this.fieldGroup_);\n\n if (this.getConstants()!.FIELD_DROPDOWN_SVG_ARROW) {\n this.createSVGArrow_();\n } else {\n this.createTextArrow_();\n }\n\n if (this.borderRect_) {\n dom.addClass(this.borderRect_, 'blocklyDropdownRect');\n }\n }\n\n /**\n * Whether or not the dropdown should add a border rect.\n *\n * @returns True if the dropdown field should add a border rect.\n */\n protected shouldAddBorderRect_(): boolean {\n return !this.getConstants()!.FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW ||\n this.getConstants()!.FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW &&\n !this.getSourceBlock()?.isShadow();\n }\n\n /** Create a tspan based arrow. */\n protected createTextArrow_() {\n this.arrow_ = dom.createSvgElement(Svg.TSPAN, {}, this.textElement_);\n this.arrow_!.appendChild(document.createTextNode(\n this.getSourceBlock()?.RTL ? FieldDropdown.ARROW_CHAR + ' ' :\n ' ' + FieldDropdown.ARROW_CHAR));\n if (this.getSourceBlock()?.RTL) {\n // AnyDuringMigration because: Argument of type 'SVGTSpanElement | null'\n // is not assignable to parameter of type 'Node'.\n this.getTextElement().insertBefore(\n this.arrow_ as AnyDuringMigration, this.textContent_);\n } else {\n // AnyDuringMigration because: Argument of type 'SVGTSpanElement | null'\n // is not assignable to parameter of type 'Node'.\n this.getTextElement().appendChild(this.arrow_ as AnyDuringMigration);\n }\n }\n\n /** Create an SVG based arrow. */\n protected createSVGArrow_() {\n this.svgArrow_ = dom.createSvgElement(\n Svg.IMAGE, {\n 'height': this.getConstants()!.FIELD_DROPDOWN_SVG_ARROW_SIZE + 'px',\n 'width': this.getConstants()!.FIELD_DROPDOWN_SVG_ARROW_SIZE + 'px',\n },\n this.fieldGroup_);\n this.svgArrow_!.setAttributeNS(\n dom.XLINK_NS, 'xlink:href',\n this.getConstants()!.FIELD_DROPDOWN_SVG_ARROW_DATAURI);\n }\n\n /**\n * Create a dropdown menu under the text.\n *\n * @param opt_e Optional mouse event that triggered the field to open, or\n * undefined if triggered programmatically.\n */\n protected override showEditor_(opt_e?: Event) {\n const block = this.getSourceBlock();\n if (!block) {\n throw new UnattachedFieldError();\n }\n this.dropdownCreate_();\n // AnyDuringMigration because: Property 'clientX' does not exist on type\n // 'Event'.\n if (opt_e && typeof (opt_e as AnyDuringMigration).clientX === 'number') {\n // AnyDuringMigration because: Property 'clientY' does not exist on type\n // 'Event'. AnyDuringMigration because: Property 'clientX' does not exist\n // on type 'Event'.\n this.menu_!.openingCoords = new Coordinate(\n (opt_e as AnyDuringMigration).clientX,\n (opt_e as AnyDuringMigration).clientY);\n } else {\n this.menu_!.openingCoords = null;\n }\n\n // Remove any pre-existing elements in the dropdown.\n dropDownDiv.clearContent();\n // Element gets created in render.\n const menuElement = this.menu_!.render(dropDownDiv.getContentDiv());\n dom.addClass(menuElement, 'blocklyDropdownMenu');\n\n if (this.getConstants()!.FIELD_DROPDOWN_COLOURED_DIV) {\n const primaryColour =\n block.isShadow() ? block.getParent()!.getColour() : block.getColour();\n const borderColour = block.isShadow() ?\n (block.getParent() as BlockSvg).style.colourTertiary :\n (this.sourceBlock_ as BlockSvg).style.colourTertiary;\n if (!borderColour) {\n throw new Error(\n 'The renderer did not properly initialize the block style');\n }\n dropDownDiv.setColour(primaryColour, borderColour);\n }\n\n dropDownDiv.showPositionedByField(this, this.dropdownDispose_.bind(this));\n\n // Focusing needs to be handled after the menu is rendered and positioned.\n // Otherwise it will cause a page scroll to get the misplaced menu in\n // view. See issue #1329.\n this.menu_!.focus();\n\n if (this.selectedMenuItem_) {\n this.menu_!.setHighlighted(this.selectedMenuItem_);\n }\n\n this.applyColour();\n }\n\n /** Create the dropdown editor. */\n private dropdownCreate_() {\n const block = this.getSourceBlock();\n if (!block) {\n throw new UnattachedFieldError();\n }\n const menu = new Menu();\n menu.setRole(aria.Role.LISTBOX);\n this.menu_ = menu;\n\n const options = this.getOptions(false);\n this.selectedMenuItem_ = null;\n for (let i = 0; i < options.length; i++) {\n let content = options[i][0]; // Human-readable text or image.\n const value = options[i][1]; // Language-neutral value.\n if (typeof content === 'object') {\n // An image, not text.\n const image = new Image(content['width'], content['height']);\n image.src = content['src'];\n image.alt = content['alt'] || '';\n content = image;\n }\n const menuItem = new MenuItem(content, value);\n menuItem.setRole(aria.Role.OPTION);\n menuItem.setRightToLeft(block.RTL);\n menuItem.setCheckable(true);\n menu.addChild(menuItem);\n menuItem.setChecked(value === this.value_);\n if (value === this.value_) {\n this.selectedMenuItem_ = menuItem;\n }\n menuItem.onAction(this.handleMenuActionEvent_, this);\n }\n }\n\n /**\n * Disposes of events and DOM-references belonging to the dropdown editor.\n */\n private dropdownDispose_() {\n if (this.menu_) {\n this.menu_.dispose();\n }\n this.menu_ = null;\n this.selectedMenuItem_ = null;\n this.applyColour();\n }\n\n /**\n * Handle an action in the dropdown menu.\n *\n * @param menuItem The MenuItem selected within menu.\n */\n private handleMenuActionEvent_(menuItem: MenuItem) {\n dropDownDiv.hideIfOwner(this, true);\n this.onItemSelected_(this.menu_ as Menu, menuItem);\n }\n\n /**\n * Handle the selection of an item in the dropdown menu.\n *\n * @param menu The Menu component clicked.\n * @param menuItem The MenuItem selected within menu.\n */\n protected onItemSelected_(menu: Menu, menuItem: MenuItem) {\n this.setValue(menuItem.getValue());\n }\n\n /**\n * Factor out common words in statically defined options.\n * Create prefix and/or suffix labels.\n */\n private trimOptions_() {\n const options = this.menuGenerator_;\n if (!Array.isArray(options)) {\n return;\n }\n let hasImages = false;\n\n // Localize label text and image alt text.\n for (let i = 0; i < options.length; i++) {\n const label = options[i][0];\n if (typeof label === 'string') {\n options[i][0] = parsing.replaceMessageReferences(label);\n } else {\n if (label.alt !== null) {\n options[i][0].alt = parsing.replaceMessageReferences(label.alt);\n }\n hasImages = true;\n }\n }\n if (hasImages || options.length < 2) {\n return; // Do nothing if too few items or at least one label is an image.\n }\n const strings = [];\n for (let i = 0; i < options.length; i++) {\n strings.push(options[i][0]);\n }\n const shortest = utilsString.shortestStringLength(strings);\n const prefixLength = utilsString.commonWordPrefix(strings, shortest);\n const suffixLength = utilsString.commonWordSuffix(strings, shortest);\n if (!prefixLength && !suffixLength) {\n return;\n }\n if (shortest <= prefixLength + suffixLength) {\n // One or more strings will entirely vanish if we proceed. Abort.\n return;\n }\n if (prefixLength) {\n this.prefixField = strings[0].substring(0, prefixLength - 1);\n }\n if (suffixLength) {\n this.suffixField = strings[0].substr(1 - suffixLength);\n }\n\n this.menuGenerator_ =\n FieldDropdown.applyTrim_(options, prefixLength, suffixLength);\n }\n\n /**\n * @returns True if the option list is generated by a function.\n * Otherwise false.\n */\n isOptionListDynamic(): boolean {\n return typeof this.menuGenerator_ === 'function';\n }\n\n /**\n * Return a list of the options for this dropdown.\n *\n * @param opt_useCache For dynamic options, whether or not to use the cached\n * options or to re-generate them.\n * @returns A non-empty array of option tuples:\n * (human-readable text or image, language-neutral name).\n * @throws {TypeError} If generated options are incorrectly structured.\n */\n getOptions(opt_useCache?: boolean): AnyDuringMigration[][] {\n if (this.isOptionListDynamic()) {\n if (!this.generatedOptions_ || !opt_useCache) {\n // AnyDuringMigration because: Property 'call' does not exist on type\n // 'any[][] | ((this: FieldDropdown) => any[][])'.\n this.generatedOptions_ =\n (this.menuGenerator_ as AnyDuringMigration).call(this);\n validateOptions(this.generatedOptions_);\n }\n return this.generatedOptions_;\n }\n return this.menuGenerator_ as string[][];\n }\n\n /**\n * Ensure that the input value is a valid language-neutral option.\n *\n * @param opt_newValue The input value.\n * @returns A valid language-neutral option, or null if invalid.\n */\n protected override doClassValidation_(opt_newValue?: AnyDuringMigration):\n string|null {\n let isValueValid = false;\n const options = this.getOptions(true);\n for (let i = 0, option; option = options[i]; i++) {\n // Options are tuples of human-readable text and language-neutral values.\n if (option[1] === opt_newValue) {\n isValueValid = true;\n break;\n }\n }\n if (!isValueValid) {\n if (this.sourceBlock_) {\n console.warn(\n 'Cannot set the dropdown\\'s value to an unavailable option.' +\n ' Block type: ' + this.sourceBlock_.type +\n ', Field name: ' + this.name + ', Value: ' + opt_newValue);\n }\n return null;\n }\n return opt_newValue as string;\n }\n\n /**\n * Update the value of this dropdown field.\n *\n * @param newValue The value to be saved. The default validator guarantees\n * that this is one of the valid dropdown options.\n */\n protected override doValueUpdate_(newValue: AnyDuringMigration) {\n super.doValueUpdate_(newValue);\n const options = this.getOptions(true);\n for (let i = 0, option; option = options[i]; i++) {\n if (option[1] === this.value_) {\n this.selectedOption_ = option;\n }\n }\n }\n\n /**\n * Updates the dropdown arrow to match the colour/style of the block.\n *\n * @internal\n */\n override applyColour() {\n const style = (this.sourceBlock_ as BlockSvg).style;\n if (!style.colourSecondary) {\n throw new Error(\n 'The renderer did not properly initialize the block style');\n }\n if (!style.colourTertiary) {\n throw new Error(\n 'The renderer did not properly initialize the block style');\n }\n if (this.borderRect_) {\n this.borderRect_.setAttribute('stroke', style.colourTertiary);\n if (this.menu_) {\n this.borderRect_.setAttribute('fill', style.colourTertiary);\n } else {\n this.borderRect_.setAttribute('fill', 'transparent');\n }\n }\n // Update arrow's colour.\n if (this.sourceBlock_ && this.arrow_) {\n if (this.sourceBlock_.isShadow()) {\n this.arrow_.style.fill = style.colourSecondary;\n } else {\n this.arrow_.style.fill = style.colourPrimary;\n }\n }\n }\n\n /** Draws the border with the correct width. */\n protected override render_() {\n // Hide both elements.\n this.getTextContent().nodeValue = '';\n this.imageElement_!.style.display = 'none';\n\n // Show correct element.\n const option = this.selectedOption_ && this.selectedOption_[0];\n if (option && typeof option === 'object') {\n this.renderSelectedImage_((option));\n } else {\n this.renderSelectedText_();\n }\n\n this.positionBorderRect_();\n }\n\n /**\n * Renders the selected option, which must be an image.\n *\n * @param imageJson Selected option that must be an image.\n */\n private renderSelectedImage_(imageJson: ImageProperties) {\n const block = this.getSourceBlock();\n if (!block) {\n throw new UnattachedFieldError();\n }\n this.imageElement_!.style.display = '';\n this.imageElement_!.setAttributeNS(\n dom.XLINK_NS, 'xlink:href', imageJson.src);\n // AnyDuringMigration because: Argument of type 'number' is not assignable\n // to parameter of type 'string'.\n this.imageElement_!.setAttribute(\n 'height', imageJson.height as AnyDuringMigration);\n // AnyDuringMigration because: Argument of type 'number' is not assignable\n // to parameter of type 'string'.\n this.imageElement_!.setAttribute(\n 'width', imageJson.width as AnyDuringMigration);\n\n const imageHeight = Number(imageJson.height);\n const imageWidth = Number(imageJson.width);\n\n // Height and width include the border rect.\n const hasBorder = !!this.borderRect_;\n const height = Math.max(\n hasBorder ? this.getConstants()!.FIELD_DROPDOWN_BORDER_RECT_HEIGHT : 0,\n imageHeight + IMAGE_Y_PADDING);\n const xPadding =\n hasBorder ? this.getConstants()!.FIELD_BORDER_RECT_X_PADDING : 0;\n let arrowWidth = 0;\n if (this.svgArrow_) {\n arrowWidth = this.positionSVGArrow_(\n imageWidth + xPadding,\n height / 2 - this.getConstants()!.FIELD_DROPDOWN_SVG_ARROW_SIZE / 2);\n } else {\n arrowWidth = dom.getFastTextWidth(\n this.arrow_ as SVGTSpanElement,\n this.getConstants()!.FIELD_TEXT_FONTSIZE,\n this.getConstants()!.FIELD_TEXT_FONTWEIGHT,\n this.getConstants()!.FIELD_TEXT_FONTFAMILY);\n }\n this.size_.width = imageWidth + arrowWidth + xPadding * 2;\n this.size_.height = height;\n\n let arrowX = 0;\n if (block.RTL) {\n const imageX = xPadding + arrowWidth;\n this.imageElement_!.setAttribute('x', imageX.toString());\n } else {\n arrowX = imageWidth + arrowWidth;\n this.getTextElement().setAttribute('text-anchor', 'end');\n this.imageElement_!.setAttribute('x', xPadding.toString());\n }\n this.imageElement_!.setAttribute(\n 'y', (height / 2 - imageHeight / 2).toString());\n\n this.positionTextElement_(arrowX + xPadding, imageWidth + arrowWidth);\n }\n\n /** Renders the selected option, which must be text. */\n private renderSelectedText_() {\n // Retrieves the selected option to display through getText_.\n this.getTextContent().nodeValue = this.getDisplayText_();\n const textElement = this.getTextElement();\n dom.addClass(textElement, 'blocklyDropdownText');\n textElement.setAttribute('text-anchor', 'start');\n\n // Height and width include the border rect.\n const hasBorder = !!this.borderRect_;\n const height = Math.max(\n hasBorder ? this.getConstants()!.FIELD_DROPDOWN_BORDER_RECT_HEIGHT : 0,\n this.getConstants()!.FIELD_TEXT_HEIGHT);\n const textWidth = dom.getFastTextWidth(\n this.getTextElement(), this.getConstants()!.FIELD_TEXT_FONTSIZE,\n this.getConstants()!.FIELD_TEXT_FONTWEIGHT,\n this.getConstants()!.FIELD_TEXT_FONTFAMILY);\n const xPadding =\n hasBorder ? this.getConstants()!.FIELD_BORDER_RECT_X_PADDING : 0;\n let arrowWidth = 0;\n if (this.svgArrow_) {\n arrowWidth = this.positionSVGArrow_(\n textWidth + xPadding,\n height / 2 - this.getConstants()!.FIELD_DROPDOWN_SVG_ARROW_SIZE / 2);\n }\n this.size_.width = textWidth + arrowWidth + xPadding * 2;\n this.size_.height = height;\n\n this.positionTextElement_(xPadding, textWidth);\n }\n\n /**\n * Position a drop-down arrow at the appropriate location at render-time.\n *\n * @param x X position the arrow is being rendered at, in px.\n * @param y Y position the arrow is being rendered at, in px.\n * @returns Amount of space the arrow is taking up, in px.\n */\n private positionSVGArrow_(x: number, y: number): number {\n if (!this.svgArrow_) {\n return 0;\n }\n const block = this.getSourceBlock();\n if (!block) {\n throw new UnattachedFieldError();\n }\n const hasBorder = !!this.borderRect_;\n const xPadding =\n hasBorder ? this.getConstants()!.FIELD_BORDER_RECT_X_PADDING : 0;\n const textPadding = this.getConstants()!.FIELD_DROPDOWN_SVG_ARROW_PADDING;\n const svgArrowSize = this.getConstants()!.FIELD_DROPDOWN_SVG_ARROW_SIZE;\n const arrowX = block.RTL ? xPadding : x + textPadding;\n this.svgArrow_.setAttribute(\n 'transform', 'translate(' + arrowX + ',' + y + ')');\n return svgArrowSize + textPadding;\n }\n\n /**\n * Use the `getText_` developer hook to override the field's text\n * representation. Get the selected option text. If the selected option is an\n * image we return the image alt text.\n *\n * @returns Selected option text.\n */\n protected override getText_(): string|null {\n if (!this.selectedOption_) {\n return null;\n }\n const option = this.selectedOption_[0];\n if (typeof option === 'object') {\n return option['alt'];\n }\n return option;\n }\n\n /**\n * Construct a FieldDropdown from a JSON arg object.\n *\n * @param options A JSON object with options (options).\n * @returns The new field instance.\n * @nocollapse\n * @internal\n */\n static fromJson(options: FieldDropdownFromJsonConfig): FieldDropdown {\n if (!options.options) {\n throw new Error(\n 'options are required for the dropdown field. The ' +\n 'options property must be assigned an array of ' +\n '[humanReadableValue, languageNeutralValue] tuples.');\n }\n // `this` might be a subclass of FieldDropdown if that class doesn't\n // override the static fromJson method.\n return new this(options.options, undefined, options);\n }\n\n /**\n * Use the calculated prefix and suffix lengths to trim all of the options in\n * the given array.\n *\n * @param options Array of option tuples:\n * (human-readable text or image, language-neutral name).\n * @param prefixLength The length of the common prefix.\n * @param suffixLength The length of the common suffix\n * @returns A new array with all of the option text trimmed.\n */\n static applyTrim_(\n options: AnyDuringMigration[][], prefixLength: number,\n suffixLength: number): AnyDuringMigration[][] {\n const newOptions = [];\n // Remove the prefix and suffix from the options.\n for (let i = 0; i < options.length; i++) {\n let text = options[i][0];\n const value = options[i][1];\n text = text.substring(prefixLength, text.length - suffixLength);\n newOptions[i] = [text, value];\n }\n return newOptions;\n }\n}\n\n/**\n * Definition of a human-readable image dropdown option.\n */\nexport interface ImageProperties {\n src: string;\n alt: string;\n width: number;\n height: number;\n}\n\n/**\n * An individual option in the dropdown menu. The first element is the human-\n * readable value (text or image), and the second element is the language-\n * neutral value.\n */\nexport type MenuOption = [string | ImageProperties, string];\n\n/**\n * fromJson config for the dropdown field.\n */\nexport interface FieldDropdownFromJsonConfig extends FieldConfig {\n options?: MenuOption[];\n}\n\n/**\n * The y offset from the top of the field to the top of the image, if an image\n * is selected.\n */\nconst IMAGE_Y_OFFSET = 5;\n\n/** The total vertical padding above and below an image. */\nconst IMAGE_Y_PADDING: number = IMAGE_Y_OFFSET * 2;\n\n/** Android can't (in 2014) display \"▾\", so use \"▼\" instead. */\nFieldDropdown.ARROW_CHAR = userAgent.ANDROID ? '▼' : '▾';\n\n/**\n * Validates the data structure to be processed as an options list.\n *\n * @param options The proposed dropdown options.\n * @throws {TypeError} If proposed options are incorrectly structured.\n */\nfunction validateOptions(options: AnyDuringMigration) {\n if (!Array.isArray(options)) {\n throw TypeError('FieldDropdown options must be an array.');\n }\n if (!options.length) {\n throw TypeError('FieldDropdown options must not be an empty array.');\n }\n let foundError = false;\n for (let i = 0; i < options.length; i++) {\n const tuple = options[i];\n if (!Array.isArray(tuple)) {\n foundError = true;\n console.error(\n 'Invalid option[' + i + ']: Each FieldDropdown option must be an ' +\n 'array. Found: ',\n tuple);\n } else if (typeof tuple[1] !== 'string') {\n foundError = true;\n console.error(\n 'Invalid option[' + i + ']: Each FieldDropdown option id must be ' +\n 'a string. Found ' + tuple[1] + ' in: ',\n tuple);\n } else if (\n tuple[0] && typeof tuple[0] !== 'string' &&\n typeof tuple[0].src !== 'string') {\n foundError = true;\n console.error(\n 'Invalid option[' + i + ']: Each FieldDropdown option must have a ' +\n 'string label or image description. Found' + tuple[0] + ' in: ',\n tuple);\n }\n }\n if (foundError) {\n throw TypeError('Found invalid FieldDropdown options.');\n }\n}\n\nfieldRegistry.register('field_dropdown', FieldDropdown);\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility methods for objects.\n *\n * @namespace Blockly.utils.object\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.object');\n\nimport * as deprecation from './deprecation.js';\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * @param childCtor Child class.\n * @param parentCtor Parent class.\n * @suppress {strictMissingProperties} superClass_ is not defined on Function.\n * @deprecated No longer provided by Blockly.\n * @alias Blockly.utils.object.inherits\n */\nexport function inherits(childCtor: Function, parentCtor: Function) {\n deprecation.warn('Blockly.utils.object.inherits', 'version 9', 'version 10');\n // Set a .superClass_ property so that methods can call parent methods\n // without hard-coding the parent class name.\n // Could be replaced by ES6's super().\n // AnyDuringMigration because: Property 'superClass_' does not exist on type\n // 'Function'.\n (childCtor as AnyDuringMigration).superClass_ = parentCtor.prototype;\n\n // Link the child class to the parent class so that static methods inherit.\n Object.setPrototypeOf(childCtor, parentCtor);\n\n // Replace the child constructor's prototype object with an instance\n // of the parent class.\n childCtor.prototype = Object.create(parentCtor.prototype);\n childCtor.prototype.constructor = childCtor;\n}\n// Alternatively, one could use this instead:\n// Object.setPrototypeOf(childCtor.prototype, parentCtor.prototype);\n\n/**\n * Copies all the members of a source object to a target object.\n *\n * @param target Target.\n * @param source Source.\n * @deprecated Use the built-in **Object.assign** instead.\n * @alias Blockly.utils.object.mixin\n */\nexport function mixin(target: AnyDuringMigration, source: AnyDuringMigration) {\n deprecation.warn(\n 'Blockly.utils.object.mixin', 'May 2022', 'May 2023', 'Object.assign');\n for (const x in source) {\n target[x] = source[x];\n }\n}\n\n/**\n * Complete a deep merge of all members of a source object with a target object.\n *\n * @param target Target.\n * @param source Source.\n * @returns The resulting object.\n * @alias Blockly.utils.object.deepMerge\n */\nexport function deepMerge(\n target: AnyDuringMigration,\n source: AnyDuringMigration): AnyDuringMigration {\n for (const x in source) {\n if (source[x] !== null && typeof source[x] === 'object') {\n target[x] = deepMerge(target[x] || Object.create(null), source[x]);\n } else {\n target[x] = source[x];\n }\n }\n return target;\n}\n\n/**\n * Returns an array of a given object's own enumerable property values.\n *\n * @param obj Object containing values.\n * @returns Array of values.\n * @deprecated Use the built-in **Object.values** instead.\n * @alias Blockly.utils.object.values\n */\nexport function values(obj: AnyDuringMigration): AnyDuringMigration[] {\n deprecation.warn(\n 'Blockly.utils.object.values', 'version 9', 'version 10',\n 'Object.values');\n return Object.values(obj);\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility functions for the toolbox and flyout.\n *\n * @namespace Blockly.utils.toolbox\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.toolbox');\n\nimport type {ConnectionState} from '../serialization/blocks.js';\nimport type {CssConfig as CategoryCssConfig} from '../toolbox/category.js';\nimport type {CssConfig as SeparatorCssConfig} from '../toolbox/separator.js';\nimport * as Xml from '../xml.js';\n\n\n/**\n * The information needed to create a block in the toolbox.\n * Note that disabled has a different type for backwards compatibility.\n *\n * @alias Blockly.utils.toolbox.BlockInfo\n */\nexport interface BlockInfo {\n kind: string;\n blockxml?: string|Node;\n type?: string;\n gap?: string|number;\n disabled?: string|boolean;\n enabled?: boolean;\n id?: string;\n x?: number;\n y?: number;\n collapsed?: boolean;\n inline?: boolean;\n data?: string;\n extraState?: AnyDuringMigration;\n icons?: {[key: string]: AnyDuringMigration};\n fields?: {[key: string]: AnyDuringMigration};\n inputs?: {[key: string]: ConnectionState};\n next?: ConnectionState;\n}\n\n/**\n * The information needed to create a separator in the toolbox.\n *\n * @alias Blockly.utils.toolbox.SeparatorInfo\n */\nexport interface SeparatorInfo {\n kind: string;\n id: string|undefined;\n gap: number|undefined;\n cssconfig: SeparatorCssConfig|undefined;\n}\n\n/**\n * The information needed to create a button in the toolbox.\n *\n * @alias Blockly.utils.toolbox.ButtonInfo\n */\nexport interface ButtonInfo {\n kind: string;\n text: string;\n callbackkey: string;\n}\n\n/**\n * The information needed to create a label in the toolbox.\n *\n * @alias Blockly.utils.toolbox.LabelInfo\n */\nexport interface LabelInfo {\n kind: string;\n text: string;\n id: string|undefined;\n}\n\n/**\n * The information needed to create either a button or a label in the flyout.\n *\n * @alias Blockly.utils.toolbox.ButtonOrLabelInfo\n */\nexport type ButtonOrLabelInfo = ButtonInfo|LabelInfo;\n\n/**\n * The information needed to create a category in the toolbox.\n *\n * @alias Blockly.utils.toolbox.StaticCategoryInfo\n */\nexport interface StaticCategoryInfo {\n kind: string;\n name: string;\n contents: ToolboxItemInfo[];\n id: string|undefined;\n categorystyle: string|undefined;\n colour: string|undefined;\n cssconfig: CategoryCssConfig|undefined;\n hidden: string|undefined;\n}\n\n/**\n * The information needed to create a custom category.\n *\n * @alias Blockly.utils.toolbox.DynamicCategoryInfo\n */\nexport interface DynamicCategoryInfo {\n kind: string;\n custom: string;\n id: string|undefined;\n categorystyle: string|undefined;\n colour: string|undefined;\n cssconfig: CategoryCssConfig|undefined;\n hidden: string|undefined;\n}\n\n/**\n * The information needed to create either a dynamic or static category.\n *\n * @alias Blockly.utils.toolbox.CategoryInfo\n */\nexport type CategoryInfo = StaticCategoryInfo|DynamicCategoryInfo;\n\n/**\n * Any information that can be used to create an item in the toolbox.\n *\n * @alias Blockly.utils.toolbox.ToolboxItemInfo\n */\nexport type ToolboxItemInfo = FlyoutItemInfo|StaticCategoryInfo;\n\n/**\n * All the different types that can be displayed in a flyout.\n *\n * @alias Blockly.utils.toolbox.FlyoutItemInfo\n */\nexport type FlyoutItemInfo =\n BlockInfo|SeparatorInfo|ButtonInfo|LabelInfo|DynamicCategoryInfo;\n\n/**\n * The JSON definition of a toolbox.\n *\n * @alias Blockly.utils.toolbox.ToolboxInfo\n */\nexport interface ToolboxInfo {\n kind?: string;\n contents: ToolboxItemInfo[];\n}\n\n/**\n * An array holding flyout items.\n *\n * @alias Blockly.utils.toolbox.FlyoutItemInfoArray\n */\nexport type FlyoutItemInfoArray = FlyoutItemInfo[];\n\n/**\n * All of the different types that can create a toolbox.\n *\n * @alias Blockly.utils.toolbox.ToolboxDefinition\n */\nexport type ToolboxDefinition = Node|ToolboxInfo|string;\n\n/**\n * All of the different types that can be used to show items in a flyout.\n *\n * @alias Blockly.utils.toolbox.FlyoutDefinition\n */\nexport type FlyoutDefinition = FlyoutItemInfoArray|NodeList|ToolboxInfo|Node[];\n\n/**\n * The name used to identify a toolbox that has category like items.\n * This only needs to be used if a toolbox wants to be treated like a category\n * toolbox but does not actually contain any toolbox items with the kind\n * 'category'.\n */\nconst CATEGORY_TOOLBOX_KIND = 'categoryToolbox';\n\n/**\n * The name used to identify a toolbox that has no categories and is displayed\n * as a simple flyout displaying blocks, buttons, or labels.\n */\nconst FLYOUT_TOOLBOX_KIND = 'flyoutToolbox';\n\n/**\n * Position of the toolbox and/or flyout relative to the workspace.\n *\n * @alias Blockly.utils.toolbox.Position\n */\nexport enum Position {\n TOP,\n BOTTOM,\n LEFT,\n RIGHT\n}\n\n/**\n * Converts the toolbox definition into toolbox JSON.\n *\n * @param toolboxDef The definition of the toolbox in one of its many forms.\n * @returns Object holding information for creating a toolbox.\n * @alias Blockly.utils.toolbox.convertToolboxDefToJson\n * @internal\n */\nexport function convertToolboxDefToJson(toolboxDef: ToolboxDefinition|\n null): ToolboxInfo|null {\n if (!toolboxDef) {\n return null;\n }\n\n if (toolboxDef instanceof Element || typeof toolboxDef === 'string') {\n toolboxDef = parseToolboxTree(toolboxDef);\n // AnyDuringMigration because: Argument of type 'Node | null' is not\n // assignable to parameter of type 'Node'.\n toolboxDef = convertToToolboxJson(toolboxDef as AnyDuringMigration);\n }\n\n const toolboxJson = toolboxDef as ToolboxInfo;\n validateToolbox(toolboxJson);\n return toolboxJson;\n}\n\n/**\n * Validates the toolbox JSON fields have been set correctly.\n *\n * @param toolboxJson Object holding information for creating a toolbox.\n * @throws {Error} if the toolbox is not the correct format.\n */\nfunction validateToolbox(toolboxJson: ToolboxInfo) {\n const toolboxKind = toolboxJson['kind'];\n const toolboxContents = toolboxJson['contents'];\n\n if (toolboxKind) {\n if (toolboxKind !== FLYOUT_TOOLBOX_KIND &&\n toolboxKind !== CATEGORY_TOOLBOX_KIND) {\n throw Error(\n 'Invalid toolbox kind ' + toolboxKind + '.' +\n ' Please supply either ' + FLYOUT_TOOLBOX_KIND + ' or ' +\n CATEGORY_TOOLBOX_KIND);\n }\n }\n if (!toolboxContents) {\n throw Error('Toolbox must have a contents attribute.');\n }\n}\n\n/**\n * Converts the flyout definition into a list of flyout items.\n *\n * @param flyoutDef The definition of the flyout in one of its many forms.\n * @returns A list of flyout items.\n * @alias Blockly.utils.toolbox.convertFlyoutDefToJsonArray\n * @internal\n */\nexport function convertFlyoutDefToJsonArray(flyoutDef: FlyoutDefinition|\n null): FlyoutItemInfoArray {\n if (!flyoutDef) {\n return [];\n }\n\n if ((flyoutDef as AnyDuringMigration)['contents']) {\n return (flyoutDef as AnyDuringMigration)['contents'];\n }\n // If it is already in the correct format return the flyoutDef.\n // AnyDuringMigration because: Property 'nodeType' does not exist on type\n // 'Node | FlyoutItemInfo'.\n if (Array.isArray(flyoutDef) && flyoutDef.length > 0 &&\n !((flyoutDef[0]) as AnyDuringMigration).nodeType) {\n // AnyDuringMigration because: Type 'FlyoutItemInfoArray | Node[]' is not\n // assignable to type 'FlyoutItemInfoArray'.\n return flyoutDef as AnyDuringMigration;\n }\n\n // AnyDuringMigration because: Type 'ToolboxItemInfo[] | FlyoutItemInfoArray'\n // is not assignable to type 'FlyoutItemInfoArray'.\n return xmlToJsonArray(flyoutDef as Node[] | NodeList) as AnyDuringMigration;\n}\n\n/**\n * Whether or not the toolbox definition has categories.\n *\n * @param toolboxJson Object holding information for creating a toolbox.\n * @returns True if the toolbox has categories.\n * @alias Blockly.utils.toolbox.hasCategories\n * @internal\n */\nexport function hasCategories(toolboxJson: ToolboxInfo|null): boolean {\n return TEST_ONLY.hasCategoriesInternal(toolboxJson);\n}\n\n/**\n * Private version of hasCategories for stubbing in tests.\n */\nfunction hasCategoriesInternal(toolboxJson: ToolboxInfo|null): boolean {\n if (!toolboxJson) {\n return false;\n }\n\n const toolboxKind = toolboxJson['kind'];\n if (toolboxKind) {\n return toolboxKind === CATEGORY_TOOLBOX_KIND;\n }\n\n const categories = toolboxJson['contents'].filter(function(item) {\n return item['kind'].toUpperCase() === 'CATEGORY';\n });\n return !!categories.length;\n}\n\n/**\n * Whether or not the category is collapsible.\n *\n * @param categoryInfo Object holing information for creating a category.\n * @returns True if the category has subcategories.\n * @alias Blockly.utils.toolbox.isCategoryCollapsible\n * @internal\n */\nexport function isCategoryCollapsible(categoryInfo: CategoryInfo): boolean {\n if (!categoryInfo || !(categoryInfo as AnyDuringMigration)['contents']) {\n return false;\n }\n\n const categories =\n (categoryInfo as AnyDuringMigration)['contents'].filter(function(\n item: AnyDuringMigration) {\n return item['kind'].toUpperCase() === 'CATEGORY';\n });\n return !!categories.length;\n}\n\n/**\n * Parses the provided toolbox definition into a consistent format.\n *\n * @param toolboxDef The definition of the toolbox in one of its many forms.\n * @returns Object holding information for creating a toolbox.\n */\nfunction convertToToolboxJson(toolboxDef: Node): ToolboxInfo {\n const contents = xmlToJsonArray(toolboxDef as Node | Node[]);\n const toolboxJson = {'contents': contents};\n if (toolboxDef instanceof Node) {\n addAttributes(toolboxDef, toolboxJson);\n }\n return toolboxJson;\n}\n\n/**\n * Converts the xml for a toolbox to JSON.\n *\n * @param toolboxDef The definition of the toolbox in one of its many forms.\n * @returns A list of objects in the toolbox.\n */\nfunction xmlToJsonArray(toolboxDef: Node|Node[]|NodeList): FlyoutItemInfoArray|\n ToolboxItemInfo[] {\n const arr = [];\n // If it is a node it will have children.\n // AnyDuringMigration because: Property 'childNodes' does not exist on type\n // 'Node | NodeList | Node[]'.\n let childNodes = (toolboxDef as AnyDuringMigration).childNodes;\n if (!childNodes) {\n // Otherwise the toolboxDef is an array or collection.\n childNodes = toolboxDef;\n }\n for (let i = 0, child; child = childNodes[i]; i++) {\n if (!child.tagName) {\n continue;\n }\n const obj = {};\n const tagName = child.tagName.toUpperCase();\n (obj as AnyDuringMigration)['kind'] = tagName;\n\n // Store the XML for a block.\n if (tagName === 'BLOCK') {\n (obj as AnyDuringMigration)['blockxml'] = child;\n } else if (child.childNodes && child.childNodes.length > 0) {\n // Get the contents of a category\n (obj as AnyDuringMigration)['contents'] = xmlToJsonArray(child);\n }\n\n // Add XML attributes to object\n addAttributes(child, obj);\n arr.push(obj);\n }\n // AnyDuringMigration because: Type '{}[]' is not assignable to type\n // 'ToolboxItemInfo[] | FlyoutItemInfoArray'.\n return arr as AnyDuringMigration;\n}\n\n/**\n * Adds the attributes on the node to the given object.\n *\n * @param node The node to copy the attributes from.\n * @param obj The object to copy the attributes to.\n */\nfunction addAttributes(node: Node, obj: AnyDuringMigration) {\n // AnyDuringMigration because: Property 'attributes' does not exist on type\n // 'Node'.\n for (let j = 0; j < (node as AnyDuringMigration).attributes.length; j++) {\n // AnyDuringMigration because: Property 'attributes' does not exist on type\n // 'Node'.\n const attr = (node as AnyDuringMigration).attributes[j];\n if (attr.nodeName.indexOf('css-') > -1) {\n obj['cssconfig'] = obj['cssconfig'] || {};\n obj['cssconfig'][attr.nodeName.replace('css-', '')] = attr.value;\n } else {\n obj[attr.nodeName] = attr.value;\n }\n }\n}\n\n/**\n * Parse the provided toolbox tree into a consistent DOM format.\n *\n * @param toolboxDef DOM tree of blocks, or text representation of same.\n * @returns DOM tree of blocks, or null.\n * @alias Blockly.utils.toolbox.parseToolboxTree\n */\nexport function parseToolboxTree(toolboxDef: Element|null|string): Element|\n null {\n let parsedToolboxDef: Element|null = null;\n if (toolboxDef) {\n if (typeof toolboxDef === 'string') {\n parsedToolboxDef = Xml.textToDom(toolboxDef);\n if (parsedToolboxDef.nodeName.toLowerCase() !== 'xml') {\n throw TypeError('Toolbox should be an document.');\n }\n } else if (toolboxDef instanceof Element) {\n parsedToolboxDef = toolboxDef;\n }\n }\n return parsedToolboxDef;\n}\n\nexport const TEST_ONLY = {\n hasCategoriesInternal,\n};\n","/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Extensions are functions that help initialize blocks, usually\n * adding dynamic behavior such as onchange handlers and mutators. These\n * are applied using Block.applyExtension(), or the JSON \"extensions\"\n * array attribute.\n *\n * @namespace Blockly.Extensions\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.Extensions');\n\nimport type {Block} from './block.js';\nimport type {BlockSvg} from './block_svg.js';\nimport {FieldDropdown} from './field_dropdown.js';\nimport {Mutator} from './mutator.js';\nimport * as parsing from './utils/parsing.js';\n\n\n/** The set of all registered extensions, keyed by extension name/id. */\nconst allExtensions = Object.create(null);\nexport const TEST_ONLY = {allExtensions};\n\n/**\n * Registers a new extension function. Extensions are functions that help\n * initialize blocks, usually adding dynamic behavior such as onchange\n * handlers and mutators. These are applied using Block.applyExtension(), or\n * the JSON \"extensions\" array attribute.\n *\n * @param name The name of this extension.\n * @param initFn The function to initialize an extended block.\n * @throws {Error} if the extension name is empty, the extension is already\n * registered, or extensionFn is not a function.\n * @alias Blockly.Extensions.register\n */\nexport function register(name: string, initFn: Function) {\n if (typeof name !== 'string' || name.trim() === '') {\n throw Error('Error: Invalid extension name \"' + name + '\"');\n }\n if (allExtensions[name]) {\n throw Error('Error: Extension \"' + name + '\" is already registered.');\n }\n if (typeof initFn !== 'function') {\n throw Error('Error: Extension \"' + name + '\" must be a function');\n }\n allExtensions[name] = initFn;\n}\n\n/**\n * Registers a new extension function that adds all key/value of mixinObj.\n *\n * @param name The name of this extension.\n * @param mixinObj The values to mix in.\n * @throws {Error} if the extension name is empty or the extension is already\n * registered.\n * @alias Blockly.Extensions.registerMixin\n */\nexport function registerMixin(name: string, mixinObj: AnyDuringMigration) {\n if (!mixinObj || typeof mixinObj !== 'object') {\n throw Error('Error: Mixin \"' + name + '\" must be a object');\n }\n register(name, function(this: Block) {\n this.mixin(mixinObj);\n });\n}\n\n/**\n * Registers a new extension function that adds a mutator to the block.\n * At register time this performs some basic sanity checks on the mutator.\n * The wrapper may also add a mutator dialog to the block, if both compose and\n * decompose are defined on the mixin.\n *\n * @param name The name of this mutator extension.\n * @param mixinObj The values to mix in.\n * @param opt_helperFn An optional function to apply after mixing in the object.\n * @param opt_blockList A list of blocks to appear in the flyout of the mutator\n * dialog.\n * @throws {Error} if the mutation is invalid or can't be applied to the block.\n * @alias Blockly.Extensions.registerMutator\n */\nexport function registerMutator(\n name: string, mixinObj: AnyDuringMigration,\n opt_helperFn?: () => AnyDuringMigration, opt_blockList?: string[]) {\n const errorPrefix = 'Error when registering mutator \"' + name + '\": ';\n\n checkHasMutatorProperties(errorPrefix, mixinObj);\n const hasMutatorDialog = checkMutatorDialog(mixinObj, errorPrefix);\n\n if (opt_helperFn && typeof opt_helperFn !== 'function') {\n throw Error(errorPrefix + 'Extension \"' + name + '\" is not a function');\n }\n\n // Sanity checks passed.\n register(name, function(this: Block) {\n if (hasMutatorDialog) {\n this.setMutator(new Mutator(opt_blockList || [], this as BlockSvg));\n }\n // Mixin the object.\n this.mixin(mixinObj);\n\n if (opt_helperFn) {\n opt_helperFn.apply(this);\n }\n });\n}\n\n/**\n * Unregisters the extension registered with the given name.\n *\n * @param name The name of the extension to unregister.\n * @alias Blockly.Extensions.unregister\n */\nexport function unregister(name: string) {\n if (isRegistered(name)) {\n delete allExtensions[name];\n } else {\n console.warn(\n 'No extension mapping for name \"' + name + '\" found to unregister');\n }\n}\n\n/**\n * Returns whether an extension is registered with the given name.\n *\n * @param name The name of the extension to check for.\n * @returns True if the extension is registered. False if it is not registered.\n * @alias Blockly.Extensions.isRegistered\n */\nexport function isRegistered(name: string): boolean {\n return !!allExtensions[name];\n}\n\n/**\n * Applies an extension method to a block. This should only be called during\n * block construction.\n *\n * @param name The name of the extension.\n * @param block The block to apply the named extension to.\n * @param isMutator True if this extension defines a mutator.\n * @throws {Error} if the extension is not found.\n * @alias Blockly.Extensions.apply\n */\nexport function apply(name: string, block: Block, isMutator: boolean) {\n const extensionFn = allExtensions[name];\n if (typeof extensionFn !== 'function') {\n throw Error('Error: Extension \"' + name + '\" not found.');\n }\n let mutatorProperties;\n if (isMutator) {\n // Fail early if the block already has mutation properties.\n checkNoMutatorProperties(name, block);\n } else {\n // Record the old properties so we can make sure they don't change after\n // applying the extension.\n mutatorProperties = getMutatorProperties(block);\n }\n extensionFn.apply(block);\n\n if (isMutator) {\n const errorPrefix = 'Error after applying mutator \"' + name + '\": ';\n checkHasMutatorProperties(errorPrefix, block);\n } else {\n if (!mutatorPropertiesMatch(\n mutatorProperties as AnyDuringMigration[], block)) {\n throw Error(\n 'Error when applying extension \"' + name + '\": ' +\n 'mutation properties changed when applying a non-mutator extension.');\n }\n }\n}\n\n/**\n * Check that the given block does not have any of the four mutator properties\n * defined on it. This function should be called before applying a mutator\n * extension to a block, to make sure we are not overwriting properties.\n *\n * @param mutationName The name of the mutation to reference in error messages.\n * @param block The block to check.\n * @throws {Error} if any of the properties already exist on the block.\n */\nfunction checkNoMutatorProperties(mutationName: string, block: Block) {\n const properties = getMutatorProperties(block);\n if (properties.length) {\n throw Error(\n 'Error: tried to apply mutation \"' + mutationName +\n '\" to a block that already has mutator functions.' +\n ' Block id: ' + block.id);\n }\n}\n\n/**\n * Checks if the given object has both the 'mutationToDom' and 'domToMutation'\n * functions.\n *\n * @param object The object to check.\n * @param errorPrefix The string to prepend to any error message.\n * @returns True if the object has both functions. False if it has neither\n * function.\n * @throws {Error} if the object has only one of the functions, or either is not\n * actually a function.\n */\nfunction checkXmlHooks(\n object: AnyDuringMigration, errorPrefix: string): boolean {\n return checkHasFunctionPair(\n object.mutationToDom, object.domToMutation,\n errorPrefix + ' mutationToDom/domToMutation');\n}\n/**\n * Checks if the given object has both the 'saveExtraState' and 'loadExtraState'\n * functions.\n *\n * @param object The object to check.\n * @param errorPrefix The string to prepend to any error message.\n * @returns True if the object has both functions. False if it has neither\n * function.\n * @throws {Error} if the object has only one of the functions, or either is not\n * actually a function.\n */\nfunction checkJsonHooks(\n object: AnyDuringMigration, errorPrefix: string): boolean {\n return checkHasFunctionPair(\n object.saveExtraState, object.loadExtraState,\n errorPrefix + ' saveExtraState/loadExtraState');\n}\n\n/**\n * Checks if the given object has both the 'compose' and 'decompose' functions.\n *\n * @param object The object to check.\n * @param errorPrefix The string to prepend to any error message.\n * @returns True if the object has both functions. False if it has neither\n * function.\n * @throws {Error} if the object has only one of the functions, or either is not\n * actually a function.\n */\nfunction checkMutatorDialog(\n object: AnyDuringMigration, errorPrefix: string): boolean {\n return checkHasFunctionPair(\n object.compose, object.decompose, errorPrefix + ' compose/decompose');\n}\n\n/**\n * Checks that both or neither of the given functions exist and that they are\n * indeed functions.\n *\n * @param func1 The first function in the pair.\n * @param func2 The second function in the pair.\n * @param errorPrefix The string to prepend to any error message.\n * @returns True if the object has both functions. False if it has neither\n * function.\n * @throws {Error} If the object has only one of the functions, or either is not\n * actually a function.\n */\nfunction checkHasFunctionPair(\n func1: AnyDuringMigration, func2: AnyDuringMigration,\n errorPrefix: string): boolean {\n if (func1 && func2) {\n if (typeof func1 !== 'function' || typeof func2 !== 'function') {\n throw Error(errorPrefix + ' must be a function');\n }\n return true;\n } else if (!func1 && !func2) {\n return false;\n }\n throw Error(errorPrefix + 'Must have both or neither functions');\n}\n\n/**\n * Checks that the given object required mutator properties.\n *\n * @param errorPrefix The string to prepend to any error message.\n * @param object The object to inspect.\n */\nfunction checkHasMutatorProperties(\n errorPrefix: string, object: AnyDuringMigration) {\n const hasXmlHooks = checkXmlHooks(object, errorPrefix);\n const hasJsonHooks = checkJsonHooks(object, errorPrefix);\n if (!hasXmlHooks && !hasJsonHooks) {\n throw Error(\n errorPrefix +\n 'Mutations must contain either XML hooks, or JSON hooks, or both');\n }\n // A block with a mutator isn't required to have a mutation dialog, but\n // it should still have both or neither of compose and decompose.\n checkMutatorDialog(object, errorPrefix);\n}\n\n/**\n * Get a list of values of mutator properties on the given block.\n *\n * @param block The block to inspect.\n * @returns A list with all of the defined properties, which should be\n * functions, but may be anything other than undefined.\n */\nfunction getMutatorProperties(block: Block): AnyDuringMigration[] {\n const result = [];\n // List each function explicitly by reference to allow for renaming\n // during compilation.\n if (block.domToMutation !== undefined) {\n result.push(block.domToMutation);\n }\n if (block.mutationToDom !== undefined) {\n result.push(block.mutationToDom);\n }\n if (block.saveExtraState !== undefined) {\n result.push(block.saveExtraState);\n }\n if (block.loadExtraState !== undefined) {\n result.push(block.loadExtraState);\n }\n if (block.compose !== undefined) {\n result.push(block.compose);\n }\n if (block.decompose !== undefined) {\n result.push(block.decompose);\n }\n return result;\n}\n\n/**\n * Check that the current mutator properties match a list of old mutator\n * properties. This should be called after applying a non-mutator extension,\n * to verify that the extension didn't change properties it shouldn't.\n *\n * @param oldProperties The old values to compare to.\n * @param block The block to inspect for new values.\n * @returns True if the property lists match.\n */\nfunction mutatorPropertiesMatch(\n oldProperties: AnyDuringMigration[], block: Block): boolean {\n const newProperties = getMutatorProperties(block);\n if (newProperties.length !== oldProperties.length) {\n return false;\n }\n for (let i = 0; i < newProperties.length; i++) {\n if (oldProperties[i] !== newProperties[i]) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Calls a function after the page has loaded, possibly immediately.\n *\n * @param fn Function to run.\n * @throws Error Will throw if no global document can be found (e.g., Node.js).\n * @internal\n */\nexport function runAfterPageLoad(fn: () => void) {\n if (typeof document !== 'object') {\n throw Error('runAfterPageLoad() requires browser document.');\n }\n if (document.readyState === 'complete') {\n fn(); // Page has already loaded. Call immediately.\n } else {\n // Poll readyState.\n const readyStateCheckInterval = setInterval(function() {\n if (document.readyState === 'complete') {\n clearInterval(readyStateCheckInterval);\n fn();\n }\n }, 10);\n }\n}\n\n/**\n * Builds an extension function that will map a dropdown value to a tooltip\n * string.\n *\n * This method includes multiple checks to ensure tooltips, dropdown options,\n * and message references are aligned. This aims to catch errors as early as\n * possible, without requiring developers to manually test tooltips under each\n * option. After the page is loaded, each tooltip text string will be checked\n * for matching message keys in the internationalized string table. Deferring\n * this until the page is loaded decouples loading dependencies. Later, upon\n * loading the first block of any given type, the extension will validate every\n * dropdown option has a matching tooltip in the lookupTable. Errors are\n * reported as warnings in the console, and are never fatal.\n *\n * @param dropdownName The name of the field whose value is the key to the\n * lookup table.\n * @param lookupTable The table of field values to tooltip text.\n * @returns The extension function.\n * @alias Blockly.Extensions.buildTooltipForDropdown\n */\nexport function buildTooltipForDropdown(\n dropdownName: string, lookupTable: {[key: string]: string}): Function {\n // List of block types already validated, to minimize duplicate warnings.\n const blockTypesChecked: AnyDuringMigration[] = [];\n\n // Check the tooltip string messages for invalid references.\n // Wait for load, in case Blockly.Msg is not yet populated.\n // runAfterPageLoad() does not run in a Node.js environment due to lack\n // of document object, in which case skip the validation.\n if (typeof document === 'object') { // Relies on document.readyState\n runAfterPageLoad(function() {\n for (const key in lookupTable) {\n // Will print warnings if reference is missing.\n parsing.checkMessageReferences(lookupTable[key]);\n }\n });\n }\n\n /** The actual extension. */\n function extensionFn(this: Block) {\n if (this.type && blockTypesChecked.indexOf(this.type) === -1) {\n checkDropdownOptionsInTable(this, dropdownName, lookupTable);\n blockTypesChecked.push(this.type);\n }\n\n this.setTooltip(function(this: Block) {\n const value = String(this.getFieldValue(dropdownName));\n let tooltip = lookupTable[value];\n if (tooltip === null) {\n if (blockTypesChecked.indexOf(this.type) === -1) {\n // Warn for missing values on generated tooltips.\n let warning = 'No tooltip mapping for value ' + value + ' of field ' +\n dropdownName;\n if (this.type !== null) {\n warning += ' of block type ' + this.type;\n }\n console.warn(warning + '.');\n }\n } else {\n tooltip = parsing.replaceMessageReferences(tooltip);\n }\n return tooltip;\n }.bind(this));\n }\n return extensionFn;\n}\n\n/**\n * Checks all options keys are present in the provided string lookup table.\n * Emits console warnings when they are not.\n *\n * @param block The block containing the dropdown\n * @param dropdownName The name of the dropdown\n * @param lookupTable The string lookup table\n */\nfunction checkDropdownOptionsInTable(\n block: Block, dropdownName: string, lookupTable: {[key: string]: string}) {\n // Validate all dropdown options have values.\n const dropdown = block.getField(dropdownName);\n if (dropdown instanceof FieldDropdown && !dropdown.isOptionListDynamic()) {\n const options = dropdown.getOptions();\n for (let i = 0; i < options.length; i++) {\n const optionKey = options[i][1]; // label, then value\n if (lookupTable[optionKey] === null) {\n console.warn(\n 'No tooltip mapping for value ' + optionKey + ' of field ' +\n dropdownName + ' of block type ' + block.type);\n }\n }\n }\n}\n\n/**\n * Builds an extension function that will install a dynamic tooltip. The\n * tooltip message should include the string '%1' and that string will be\n * replaced with the text of the named field.\n *\n * @param msgTemplate The template form to of the message text, with %1\n * placeholder.\n * @param fieldName The field with the replacement text.\n * @returns The extension function.\n * @alias Blockly.Extensions.buildTooltipWithFieldText\n */\nexport function buildTooltipWithFieldText(\n msgTemplate: string, fieldName: string): Function {\n // Check the tooltip string messages for invalid references.\n // Wait for load, in case Blockly.Msg is not yet populated.\n // runAfterPageLoad() does not run in a Node.js environment due to lack\n // of document object, in which case skip the validation.\n if (typeof document === 'object') { // Relies on document.readyState\n runAfterPageLoad(function() {\n // Will print warnings if reference is missing.\n parsing.checkMessageReferences(msgTemplate);\n });\n }\n\n /** The actual extension. */\n function extensionFn(this: Block) {\n this.setTooltip(function(this: Block) {\n const field = this.getField(fieldName);\n return parsing.replaceMessageReferences(msgTemplate)\n .replace('%1', field ? field.getText() : '');\n }.bind(this));\n }\n return extensionFn;\n}\n\n/**\n * Configures the tooltip to mimic the parent block when connected. Otherwise,\n * uses the tooltip text at the time this extension is initialized. This takes\n * advantage of the fact that all other values from JSON are initialized before\n * extensions.\n */\nfunction extensionParentTooltip(this: Block) {\n const tooltipWhenNotConnected = this.tooltip;\n this.setTooltip(function(this: Block) {\n const parent = this.getParent();\n return parent && parent.getInputsInline() && parent.tooltip ||\n tooltipWhenNotConnected;\n }.bind(this));\n}\nregister('parent_tooltip_when_inline', extensionParentTooltip);\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** @namespace Blockly.utils.array */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.array');\n\n\n/**\n * Removes the first occurrence of a particular value from an array.\n *\n * @param arr Array from which to remove value.\n * @param value Value to remove.\n * @returns True if an element was removed.\n * @alias Blockly.array.removeElem\n * @internal\n */\nexport function removeElem(arr: Array, value: T): boolean {\n const i = arr.indexOf(value);\n if (i === -1) {\n return false;\n }\n arr.splice(i, 1);\n return true;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Methods for creating parts of SVG path strings. See\n *\n * @namespace Blockly.utils.svgPaths\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils.svgPaths');\n\n\n/**\n * Create a string representing the given x, y pair. It does not matter whether\n * the coordinate is relative or absolute. The result has leading\n * and trailing spaces, and separates the x and y coordinates with a comma but\n * no space.\n *\n * @param x The x coordinate.\n * @param y The y coordinate.\n * @returns A string of the format ' x,y '\n * @alias Blockly.utils.svgPaths.point\n */\nexport function point(x: number, y: number): string {\n return ' ' + x + ',' + y + ' ';\n}\n\n/**\n * Draw a cubic or quadratic curve. See\n * developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#Cubic_B%C3%A9zier_Curve\n * These coordinates are unitless and hence in the user coordinate system.\n *\n * @param command The command to use.\n * Should be one of: c, C, s, S, q, Q.\n * @param points An array containing all of the points to pass to the curve\n * command, in order. The points are represented as strings of the format '\n * x, y '.\n * @returns A string defining one or more Bezier curves. See the MDN\n * documentation for exact format.\n * @alias Blockly.utils.svgPaths.curve\n */\nexport function curve(command: string, points: string[]): string {\n return ' ' + command + points.join('');\n}\n\n/**\n * Move the cursor to the given position without drawing a line.\n * The coordinates are absolute.\n * These coordinates are unitless and hence in the user coordinate system.\n * See developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#Line_commands\n *\n * @param x The absolute x coordinate.\n * @param y The absolute y coordinate.\n * @returns A string of the format ' M x,y '\n * @alias Blockly.utils.svgPaths.moveTo\n */\nexport function moveTo(x: number, y: number): string {\n return ' M ' + x + ',' + y + ' ';\n}\n\n/**\n * Move the cursor to the given position without drawing a line.\n * Coordinates are relative.\n * These coordinates are unitless and hence in the user coordinate system.\n * See developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#Line_commands\n *\n * @param dx The relative x coordinate.\n * @param dy The relative y coordinate.\n * @returns A string of the format ' m dx,dy '\n * @alias Blockly.utils.svgPaths.moveBy\n */\nexport function moveBy(dx: number, dy: number): string {\n return ' m ' + dx + ',' + dy + ' ';\n}\n\n/**\n * Draw a line from the current point to the end point, which is the current\n * point shifted by dx along the x-axis and dy along the y-axis.\n * These coordinates are unitless and hence in the user coordinate system.\n * See developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#Line_commands\n *\n * @param dx The relative x coordinate.\n * @param dy The relative y coordinate.\n * @returns A string of the format ' l dx,dy '\n * @alias Blockly.utils.svgPaths.lineTo\n */\nexport function lineTo(dx: number, dy: number): string {\n return ' l ' + dx + ',' + dy + ' ';\n}\n\n/**\n * Draw multiple lines connecting all of the given points in order. This is\n * equivalent to a series of 'l' commands.\n * These coordinates are unitless and hence in the user coordinate system.\n * See developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#Line_commands\n *\n * @param points An array containing all of the points to draw lines to, in\n * order. The points are represented as strings of the format ' dx,dy '.\n * @returns A string of the format ' l (dx,dy)+ '\n * @alias Blockly.utils.svgPaths.line\n */\nexport function line(points: string[]): string {\n return ' l' + points.join('');\n}\n\n/**\n * Draw a horizontal or vertical line.\n * The first argument specifies the direction and whether the given position is\n * relative or absolute.\n * These coordinates are unitless and hence in the user coordinate system.\n * See developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#LineTo_path_commands\n *\n * @param command The command to prepend to the coordinate. This should be one\n * of: V, v, H, h.\n * @param val The coordinate to pass to the command. It may be absolute or\n * relative.\n * @returns A string of the format ' command val '\n * @alias Blockly.utils.svgPaths.lineOnAxis\n */\nexport function lineOnAxis(command: string, val: number): string {\n return ' ' + command + ' ' + val + ' ';\n}\n\n/**\n * Draw an elliptical arc curve.\n * These coordinates are unitless and hence in the user coordinate system.\n * See developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#Elliptical_Arc_Curve\n *\n * @param command The command string. Either 'a' or 'A'.\n * @param flags The flag string. See the MDN documentation for a description\n * and examples.\n * @param radius The radius of the arc to draw.\n * @param point The point to move the cursor to after drawing the arc, specified\n * either in absolute or relative coordinates depending on the command.\n * @returns A string of the format 'command radius radius flags point'\n * @alias Blockly.utils.svgPaths.arc\n */\nexport function arc(\n command: string, flags: string, radius: number, point: string): string {\n return command + ' ' + radius + ' ' + radius + ' ' + flags + point;\n}\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility methods.\n *\n * @namespace Blockly.utils\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.utils');\n\nimport type {Block} from './block.js';\nimport * as browserEvents from './browser_events.js';\nimport * as common from './common.js';\nimport * as extensions from './extensions.js';\nimport * as aria from './utils/aria.js';\nimport * as arrayUtils from './utils/array.js';\nimport * as colour from './utils/colour.js';\nimport {Coordinate} from './utils/coordinate.js';\nimport * as deprecation from './utils/deprecation.js';\nimport * as dom from './utils/dom.js';\nimport * as idGenerator from './utils/idgenerator.js';\nimport {KeyCodes} from './utils/keycodes.js';\nimport * as math from './utils/math.js';\nimport type {Metrics} from './utils/metrics.js';\nimport * as object from './utils/object.js';\nimport * as parsing from './utils/parsing.js';\nimport {Rect} from './utils/rect.js';\nimport {Size} from './utils/size.js';\nimport * as stringUtils from './utils/string.js';\nimport * as style from './utils/style.js';\nimport {Svg} from './utils/svg.js';\nimport * as svgMath from './utils/svg_math.js';\nimport * as svgPaths from './utils/svg_paths.js';\nimport * as toolbox from './utils/toolbox.js';\nimport * as userAgent from './utils/useragent.js';\nimport * as xml from './utils/xml.js';\nimport type {WorkspaceSvg} from './workspace_svg.js';\n\n\nexport {\n aria,\n arrayUtils as array,\n browserEvents,\n colour,\n Coordinate,\n deprecation,\n dom,\n extensions,\n idGenerator,\n KeyCodes,\n math,\n Metrics,\n object,\n parsing,\n Rect,\n Size,\n stringUtils as string,\n style,\n Svg,\n svgMath,\n svgPaths,\n toolbox,\n userAgent,\n xml,\n};\n\n/**\n * Return the coordinates of the top-left corner of this element relative to\n * its parent. Only for SVG elements and children (e.g. rect, g, path).\n *\n * @param element SVG element to find the coordinates of.\n * @returns Object with .x and .y properties.\n * @deprecated Use **Blockly.utils.svgMath.getRelativeXY** instead.\n * @alias Blockly.utils.getRelativeXY\n */\nexport function getRelativeXY(element: Element): Coordinate {\n deprecation.warn(\n 'Blockly.utils.getRelativeXY', 'December 2021', 'December 2022',\n 'Blockly.utils.svgMath.getRelativeXY');\n return svgMath.getRelativeXY(element);\n}\n\n/**\n * Return the coordinates of the top-left corner of this element relative to\n * the div Blockly was injected into.\n *\n * @param element SVG element to find the coordinates of. If this is not a child\n * of the div Blockly was injected into, the behaviour is undefined.\n * @returns Object with .x and .y properties.\n * @deprecated Use **Blockly.utils.svgMath.getInjectionDivXY** instead.\n * @alias Blockly.utils.getInjectionDivXY_\n */\nfunction getInjectionDivXY(element: Element): Coordinate {\n deprecation.warn(\n 'Blockly.utils.getInjectionDivXY_', 'December 2021', 'December 2022',\n 'Blockly.utils.svgMath.getInjectionDivXY');\n return svgMath.getInjectionDivXY(element);\n}\nexport const getInjectionDivXY_ = getInjectionDivXY;\n\n/**\n * Parse a string with any number of interpolation tokens (%1, %2, ...).\n * It will also replace string table references (e.g., %{bky_my_msg} and\n * %{BKY_MY_MSG} will both be replaced with the value in\n * Msg['MY_MSG']). Percentage sign characters '%' may be self-escaped\n * (e.g., '%%').\n *\n * @param message Text which might contain string table references and\n * interpolation tokens.\n * @returns Array of strings and numbers.\n * @deprecated Use **Blockly.utils.parsing.tokenizeInterpolation** instead.\n * @alias Blockly.utils.tokenizeInterpolation\n */\nexport function tokenizeInterpolation(message: string): Array {\n deprecation.warn(\n 'Blockly.utils.tokenizeInterpolation', 'December 2021', 'December 2022',\n 'Blockly.utils.parsing.tokenizeInterpolation');\n return parsing.tokenizeInterpolation(message);\n}\n\n/**\n * Replaces string table references in a message, if the message is a string.\n * For example, \"%{bky_my_msg}\" and \"%{BKY_MY_MSG}\" will both be replaced with\n * the value in Msg['MY_MSG'].\n *\n * @param message Message, which may be a string that contains string table\n * references.\n * @returns String with message references replaced.\n * @deprecated Use **Blockly.utils.parsing.replaceMessageReferences** instead.\n * @alias Blockly.utils.replaceMessageReferences\n */\nexport function replaceMessageReferences(message: string|any): string {\n deprecation.warn(\n 'Blockly.utils.replaceMessageReferences', 'December 2021',\n 'December 2022', 'Blockly.utils.parsing.replaceMessageReferences');\n return parsing.replaceMessageReferences(message);\n}\n\n/**\n * Validates that any %{MSG_KEY} references in the message refer to keys of\n * the Msg string table.\n *\n * @param message Text which might contain string table references.\n * @returns True if all message references have matching values.\n * Otherwise, false.\n * @deprecated Use **Blockly.utils.parsing.checkMessageReferences** instead.\n * @alias Blockly.utils.checkMessageReferences\n */\nexport function checkMessageReferences(message: string): boolean {\n deprecation.warn(\n 'Blockly.utils.checkMessageReferences', 'December 2021', 'December 2022',\n 'Blockly.utils.parsing.checkMessageReferences');\n return parsing.checkMessageReferences(message);\n}\n\n/**\n * Check if 3D transforms are supported by adding an element\n * and attempting to set the property.\n *\n * @returns True if 3D transforms are supported.\n * @deprecated Use **Blockly.utils.svgMath.is3dSupported** instead.\n * @alias Blockly.utils.is3dSupported\n */\nexport function is3dSupported(): boolean {\n deprecation.warn(\n 'Blockly.utils.is3dSupported', 'December 2021', 'December 2022',\n 'Blockly.utils.svgMath.is3dSupported');\n return svgMath.is3dSupported();\n}\n\n/**\n * Get the position of the current viewport in window coordinates. This takes\n * scroll into account.\n *\n * @returns An object containing window width, height, and scroll position in\n * window coordinates.\n * @alias Blockly.utils.getViewportBBox\n * @deprecated Use **Blockly.utils.svgMath.getViewportBBox** instead.\n * @internal\n */\nexport function getViewportBBox(): Rect {\n deprecation.warn(\n 'Blockly.utils.getViewportBBox', 'December 2021', 'December 2022',\n 'Blockly.utils.svgMath.getViewportBBox');\n return svgMath.getViewportBBox();\n}\n\n/**\n * Removes the first occurrence of a particular value from an array.\n *\n * @param arr Array from which to remove value.\n * @param value Value to remove.\n * @returns True if an element was removed.\n * @alias Blockly.utils.arrayRemove\n * @deprecated Use **Blockly.array.removeElem** instead.\n * @internal\n */\nexport function arrayRemove(arr: Array, value: T): boolean {\n deprecation.warn(\n 'Blockly.utils.arrayRemove', 'December 2021', 'December 2022',\n 'Blockly.array.removeElem');\n return arrayUtils.removeElem(arr, value);\n}\n\n/**\n * Gets the document scroll distance as a coordinate object.\n * Copied from Closure's goog.dom.getDocumentScroll.\n *\n * @returns Object with values 'x' and 'y'.\n * @deprecated Use **Blockly.utils.svgMath.getDocumentScroll** instead.\n * @alias Blockly.utils.getDocumentScroll\n */\nexport function getDocumentScroll(): Coordinate {\n deprecation.warn(\n 'Blockly.utils.getDocumentScroll', 'December 2021', 'December 2022',\n 'Blockly.utils.svgMath.getDocumentScroll');\n return svgMath.getDocumentScroll();\n}\n\n/**\n * Get a map of all the block's descendants mapping their type to the number of\n * children with that type.\n *\n * @param block The block to map.\n * @param opt_stripFollowing Optionally ignore all following statements (blocks\n * that are not inside a value or statement input of the block).\n * @returns Map of types to type counts for descendants of the bock.\n * @deprecated Use **Blockly.common.getBlockTypeCounts** instead.\n * @alias Blockly.utils.getBlockTypeCounts\n */\nexport function getBlockTypeCounts(\n block: Block, opt_stripFollowing?: boolean): {[key: string]: number} {\n deprecation.warn(\n 'Blockly.utils.getBlockTypeCounts', 'December 2021', 'December 2022',\n 'Blockly.common.getBlockTypeCounts');\n return common.getBlockTypeCounts(block, opt_stripFollowing);\n}\n\n/**\n * Converts screen coordinates to workspace coordinates.\n *\n * @param ws The workspace to find the coordinates on.\n * @param screenCoordinates The screen coordinates to be converted to workspace\n * coordinates\n * @deprecated Use **Blockly.utils.svgMath.screenToWsCoordinates** instead.\n * @returns The workspace coordinates.\n */\nexport function screenToWsCoordinates(\n ws: WorkspaceSvg, screenCoordinates: Coordinate): Coordinate {\n deprecation.warn(\n 'Blockly.utils.screenToWsCoordinates', 'December 2021', 'December 2022',\n 'Blockly.utils.svgMath.screenToWsCoordinates');\n return svgMath.screenToWsCoordinates(ws, screenCoordinates);\n}\n\n/**\n * Parse a block colour from a number or string, as provided in a block\n * definition.\n *\n * @param colour HSV hue value (0 to 360), #RRGGBB string, or a message\n * reference string pointing to one of those two values.\n * @returns An object containing the colour as a #RRGGBB string, and the hue if\n * the input was an HSV hue value.\n * @throws {Error} If the colour cannot be parsed.\n * @deprecated Use **Blockly.utils.parsing.parseBlockColour** instead.\n * @alias Blockly.utils.parseBlockColour\n */\nexport function parseBlockColour(colour: number|\n string): {hue: number|null, hex: string} {\n deprecation.warn(\n 'Blockly.utils.parseBlockColour', 'December 2021', 'December 2022',\n 'Blockly.utils.parsing.parseBlockColour');\n return parsing.parseBlockColour(colour);\n}\n\n/**\n * Calls a function after the page has loaded, possibly immediately.\n *\n * @param fn Function to run.\n * @throws Error Will throw if no global document can be found (e.g., Node.js).\n * @deprecated No longer provided by Blockly.\n * @alias Blockly.utils.runAfterPageLoad\n */\nexport function runAfterPageLoad(fn: () => void) {\n deprecation.warn(\n 'Blockly.utils.runAfterPageLoad', 'December 2021', 'December 2022');\n extensions.runAfterPageLoad(fn);\n}\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Contains functions registering serializers (eg blocks, variables, plugins,\n * etc).\n *\n * @namespace Blockly.serialization.registry\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.serialization.registry');\n\n// eslint-disable-next-line no-unused-vars\nimport type {ISerializer} from '../interfaces/i_serializer.js';\nimport * as registry from '../registry.js';\n\n\n/**\n * Registers the given serializer so that it can be used for serialization and\n * deserialization.\n *\n * @param name The name of the serializer to register.\n * @param serializer The serializer to register.\n * @alias Blockly.serialization.registry.register\n */\nexport function register(name: string, serializer: ISerializer) {\n registry.register(registry.Type.SERIALIZER, name, serializer);\n}\n\n/**\n * Unregisters the serializer associated with the given name.\n *\n * @param name The name of the serializer to unregister.\n * @alias Blockly.serialization.registry.unregister\n */\nexport function unregister(name: string) {\n registry.unregister(registry.Type.SERIALIZER, name);\n}\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Handles serializing blocks to plain JavaScript objects only containing state.\n *\n * @namespace Blockly.serialization.blocks\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.serialization.blocks');\n\nimport type {Block} from '../block.js';\nimport type {BlockSvg} from '../block_svg.js';\nimport type {Connection} from '../connection.js';\nimport * as eventUtils from '../events/utils.js';\nimport {inputTypes} from '../input_types.js';\nimport type {ISerializer} from '../interfaces/i_serializer.js';\nimport {Size} from '../utils/size.js';\nimport type {Workspace} from '../workspace.js';\nimport * as Xml from '../xml.js';\n\nimport {BadConnectionCheck, MissingBlockType, MissingConnection, RealChildOfShadow} from './exceptions.js';\nimport * as priorities from './priorities.js';\nimport * as serializationRegistry from './registry.js';\n\n\n// TODO(#5160): Remove this once lint is fixed.\n/* eslint-disable no-use-before-define */\n\n/**\n * Represents the state of a connection.\n *\n * @alias Blockly.serialization.blocks.ConnectionState\n */\nexport interface ConnectionState {\n shadow: State|undefined;\n block: State|undefined;\n}\n\n/**\n * Represents the state of a given block.\n *\n * @alias Blockly.serialization.blocks.State\n */\nexport interface State {\n type: string;\n id?: string;\n x?: number;\n y?: number;\n collapsed?: boolean;\n enabled?: boolean;\n inline?: boolean;\n data?: string;\n extraState?: AnyDuringMigration;\n icons?: {[key: string]: AnyDuringMigration};\n fields?: {[key: string]: AnyDuringMigration};\n inputs?: {[key: string]: ConnectionState};\n next?: ConnectionState;\n}\n\n/**\n * Returns the state of the given block as a plain JavaScript object.\n *\n * @param block The block to serialize.\n * @param param1 addCoordinates: If true, the coordinates of the block are added\n * to the serialized state. False by default. addinputBlocks: If true,\n * children of the block which are connected to inputs will be serialized.\n * True by default. addNextBlocks: If true, children of the block which are\n * connected to the block's next connection (if it exists) will be\n * serialized. True by default. doFullSerialization: If true, fields that\n * normally just save a reference to some external state (eg variables) will\n * instead serialize all of the info about that state. This supports\n * deserializing the block into a workspace where that state doesn't yet\n * exist. True by default.\n * @returns The serialized state of the block, or null if the block could not be\n * serialied (eg it was an insertion marker).\n * @alias Blockly.serialization.blocks.save\n */\nexport function save(block: Block, {\n addCoordinates = false,\n addInputBlocks = true,\n addNextBlocks = true,\n doFullSerialization = true,\n}: {\n addCoordinates?: boolean,\n addInputBlocks?: boolean,\n addNextBlocks?: boolean,\n doFullSerialization?: boolean\n} = {}): State|null {\n if (block.isInsertionMarker()) {\n return null;\n }\n\n const state = {\n 'type': block.type,\n 'id': block.id,\n };\n\n if (addCoordinates) {\n // AnyDuringMigration because: Argument of type '{ type: string; id:\n // string; }' is not assignable to parameter of type 'State'.\n saveCoords(block, state as AnyDuringMigration);\n }\n // AnyDuringMigration because: Argument of type '{ type: string; id: string;\n // }' is not assignable to parameter of type 'State'.\n saveAttributes(block, state as AnyDuringMigration);\n // AnyDuringMigration because: Argument of type '{ type: string; id: string;\n // }' is not assignable to parameter of type 'State'.\n saveExtraState(block, state as AnyDuringMigration);\n // AnyDuringMigration because: Argument of type '{ type: string; id: string;\n // }' is not assignable to parameter of type 'State'.\n saveIcons(block, state as AnyDuringMigration);\n // AnyDuringMigration because: Argument of type '{ type: string; id: string;\n // }' is not assignable to parameter of type 'State'.\n saveFields(block, state as AnyDuringMigration, doFullSerialization);\n if (addInputBlocks) {\n // AnyDuringMigration because: Argument of type '{ type: string; id:\n // string; }' is not assignable to parameter of type 'State'.\n saveInputBlocks(block, state as AnyDuringMigration, doFullSerialization);\n }\n if (addNextBlocks) {\n // AnyDuringMigration because: Argument of type '{ type: string; id:\n // string; }' is not assignable to parameter of type 'State'.\n saveNextBlocks(block, state as AnyDuringMigration, doFullSerialization);\n }\n\n // AnyDuringMigration because: Type '{ type: string; id: string; }' is not\n // assignable to type 'State'.\n return state as AnyDuringMigration;\n}\n\n/**\n * Adds attributes to the given state object based on the state of the block.\n * Eg collapsed, disabled, inline, etc.\n *\n * @param block The block to base the attributes on.\n * @param state The state object to append to.\n */\nfunction saveAttributes(block: Block, state: State) {\n if (block.isCollapsed()) {\n state['collapsed'] = true;\n }\n if (!block.isEnabled()) {\n state['enabled'] = false;\n }\n if (block.inputsInline !== undefined &&\n block.inputsInline !== block.inputsInlineDefault) {\n state['inline'] = block.inputsInline;\n }\n // Data is a nullable string, so we don't need to worry about falsy values.\n if (block.data) {\n state['data'] = block.data;\n }\n}\n\n/**\n * Adds the coordinates of the given block to the given state object.\n *\n * @param block The block to base the coordinates on.\n * @param state The state object to append to.\n */\nfunction saveCoords(block: Block, state: State) {\n const workspace = block.workspace;\n const xy = block.getRelativeToSurfaceXY();\n state['x'] = Math.round(workspace.RTL ? workspace.getWidth() - xy.x : xy.x);\n state['y'] = Math.round(xy.y);\n}\n/**\n * Adds any extra state the block may provide to the given state object.\n *\n * @param block The block to serialize the extra state of.\n * @param state The state object to append to.\n */\nfunction saveExtraState(block: Block, state: State) {\n if (block.saveExtraState) {\n const extraState = block.saveExtraState();\n if (extraState !== null) {\n state['extraState'] = extraState;\n }\n } else if (block.mutationToDom) {\n const extraState = block.mutationToDom();\n if (extraState !== null) {\n state['extraState'] =\n Xml.domToText(extraState)\n .replace(\n ' xmlns=\"https://developers.google.com/blockly/xml\"', '');\n }\n }\n}\n\n/**\n * Adds the state of all of the icons on the block to the given state object.\n *\n * @param block The block to serialize the icon state of.\n * @param state The state object to append to.\n */\nfunction saveIcons(block: Block, state: State) {\n // TODO(#2105): Remove this logic and put it in the icon.\n if (block.getCommentText()) {\n state['icons'] = {\n 'comment': {\n 'text': block.getCommentText(),\n 'pinned': block.commentModel.pinned,\n 'height': Math.round(block.commentModel.size.height),\n 'width': Math.round(block.commentModel.size.width),\n },\n };\n }\n}\n\n/**\n * Adds the state of all of the fields on the block to the given state object.\n *\n * @param block The block to serialize the field state of.\n * @param state The state object to append to.\n * @param doFullSerialization Whether or not to serialize the full state of the\n * field (rather than possibly saving a reference to some state).\n */\nfunction saveFields(block: Block, state: State, doFullSerialization: boolean) {\n const fields = Object.create(null);\n for (let i = 0; i < block.inputList.length; i++) {\n const input = block.inputList[i];\n for (let j = 0; j < input.fieldRow.length; j++) {\n const field = input.fieldRow[j];\n if (field.isSerializable()) {\n fields[field.name!] = field.saveState(doFullSerialization);\n }\n }\n }\n if (Object.keys(fields).length) {\n state['fields'] = fields;\n }\n}\n\n/**\n * Adds the state of all of the child blocks of the given block (which are\n * connected to inputs) to the given state object.\n *\n * @param block The block to serialize the input blocks of.\n * @param state The state object to append to.\n * @param doFullSerialization Whether or not to do full serialization.\n */\nfunction saveInputBlocks(\n block: Block, state: State, doFullSerialization: boolean) {\n const inputs = Object.create(null);\n for (let i = 0; i < block.inputList.length; i++) {\n const input = block.inputList[i];\n if (input.type === inputTypes.DUMMY) {\n continue;\n }\n const connectionState =\n saveConnection(input.connection as Connection, doFullSerialization);\n if (connectionState) {\n inputs[input.name] = connectionState;\n }\n }\n\n if (Object.keys(inputs).length) {\n state['inputs'] = inputs;\n }\n}\n\n/**\n * Adds the state of all of the next blocks of the given block to the given\n * state object.\n *\n * @param block The block to serialize the next blocks of.\n * @param state The state object to append to.\n * @param doFullSerialization Whether or not to do full serialization.\n */\nfunction saveNextBlocks(\n block: Block, state: State, doFullSerialization: boolean) {\n if (!block.nextConnection) {\n return;\n }\n const connectionState =\n saveConnection(block.nextConnection, doFullSerialization);\n if (connectionState) {\n state['next'] = connectionState;\n }\n}\n\n/**\n * Returns the state of the given connection (ie the state of any connected\n * shadow or real blocks).\n *\n * @param connection The connection to serialize the connected blocks of.\n * @returns An object containing the state of any connected shadow block, or any\n * connected real block.\n * @param doFullSerialization Whether or not to do full serialization.\n */\nfunction saveConnection(connection: Connection, doFullSerialization: boolean):\n ConnectionState|null {\n const shadow = connection.getShadowState(true);\n const child = connection.targetBlock();\n if (!shadow && !child) {\n return null;\n }\n const state = Object.create(null);\n if (shadow) {\n state['shadow'] = shadow;\n }\n if (child && !child.isShadow()) {\n state['block'] = save(child, {doFullSerialization});\n }\n return state;\n}\n\n/**\n * Loads the block represented by the given state into the given workspace.\n *\n * @param state The state of a block to deserialize into the workspace.\n * @param workspace The workspace to add the block to.\n * @param param1 recordUndo: If true, events triggered by this function will be\n * undo-able by the user. False by default.\n * @returns The block that was just loaded.\n * @alias Blockly.serialization.blocks.append\n */\nexport function append(\n state: State, workspace: Workspace,\n {recordUndo = false}: {recordUndo?: boolean} = {}): Block {\n return appendInternal(state, workspace, {recordUndo});\n}\n\n/**\n * Loads the block represented by the given state into the given workspace.\n * This is defined internally so that the extra parameters don't clutter our\n * external API.\n * But it is exported so that other places within Blockly can call it directly\n * with the extra parameters.\n *\n * @param state The state of a block to deserialize into the workspace.\n * @param workspace The workspace to add the block to.\n * @param param1 parentConnection: If provided, the system will attempt to\n * connect the block to this connection after it is created. Undefined by\n * default. isShadow: If true, the block will be set to a shadow block after\n * it is created. False by default. recordUndo: If true, events triggered by\n * this function will be undo-able by the user. False by default.\n * @returns The block that was just appended.\n * @alias Blockly.serialization.blocks.appendInternal\n * @internal\n */\nexport function appendInternal(\n state: State, workspace: Workspace,\n {parentConnection = undefined, isShadow = false, recordUndo = false}: {\n parentConnection?: Connection,\n isShadow?: boolean,\n recordUndo?: boolean\n } = {}): Block {\n const prevRecordUndo = eventUtils.getRecordUndo();\n eventUtils.setRecordUndo(recordUndo);\n const existingGroup = eventUtils.getGroup();\n if (!existingGroup) {\n eventUtils.setGroup(true);\n }\n eventUtils.disable();\n\n const block = appendPrivate(state, workspace, {parentConnection, isShadow});\n\n eventUtils.enable();\n eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(block));\n eventUtils.setGroup(existingGroup);\n eventUtils.setRecordUndo(prevRecordUndo);\n\n // Adding connections to the connection db is expensive. This defers that\n // operation to decrease load time.\n if (workspace.rendered) {\n const blockSvg = block as BlockSvg;\n setTimeout(() => {\n if (!blockSvg.disposed) {\n blockSvg.setConnectionTracking(true);\n }\n }, 1);\n }\n\n return block;\n}\n\n/**\n * Loads the block represented by the given state into the given workspace.\n * This is defined privately so that it can be called recursively without firing\n * eroneous events. Events (and other things we only want to occur on the top\n * block) are handled by appendInternal.\n *\n * @param state The state of a block to deserialize into the workspace.\n * @param workspace The workspace to add the block to.\n * @param param1 parentConnection: If provided, the system will attempt to\n * connect the block to this connection after it is created. Undefined by\n * default. isShadow: The block will be set to a shadow block after it is\n * created. False by default.\n * @returns The block that was just appended.\n */\nfunction appendPrivate(\n state: State, workspace: Workspace,\n {parentConnection = undefined, isShadow = false}:\n {parentConnection?: Connection, isShadow?: boolean} = {}): Block {\n if (!state['type']) {\n throw new MissingBlockType(state);\n }\n\n const block = workspace.newBlock(state['type'], state['id']);\n block.setShadow(isShadow);\n loadCoords(block, state);\n loadAttributes(block, state);\n loadExtraState(block, state);\n tryToConnectParent(parentConnection, block, state);\n loadIcons(block, state);\n loadFields(block, state);\n loadInputBlocks(block, state);\n loadNextBlocks(block, state);\n initBlock(block, workspace.rendered);\n\n return block;\n}\n\n/**\n * Applies any coordinate information available on the state object to the\n * block.\n *\n * @param block The block to set the position of.\n * @param state The state object to reference.\n */\nfunction loadCoords(block: Block, state: State) {\n let x = state['x'] === undefined ? 0 : state['x'];\n const y = state['y'] === undefined ? 0 : state['y'];\n\n const workspace = block.workspace;\n x = workspace.RTL ? workspace.getWidth() - x : x;\n\n block.moveBy(x, y);\n}\n\n/**\n * Applies any attribute information available on the state object to the block.\n *\n * @param block The block to set the attributes of.\n * @param state The state object to reference.\n */\nfunction loadAttributes(block: Block, state: State) {\n if (state['collapsed']) {\n block.setCollapsed(true);\n }\n if (state['enabled'] === false) {\n block.setEnabled(false);\n }\n if (state['inline'] !== undefined) {\n block.setInputsInline(state['inline']);\n }\n if (state['data'] !== undefined) {\n block.data = state['data'];\n }\n}\n\n/**\n * Applies any extra state information available on the state object to the\n * block.\n *\n * @param block The block to set the extra state of.\n * @param state The state object to reference.\n */\nfunction loadExtraState(block: Block, state: State) {\n if (!state['extraState']) {\n return;\n }\n if (block.loadExtraState) {\n block.loadExtraState(state['extraState']);\n } else if (block.domToMutation) {\n block.domToMutation(Xml.textToDom(state['extraState']));\n }\n}\n\n/**\n * Attempts to connect the block to the parent connection, if it exists.\n *\n * @param parentConnection The parent connection to try to connect the block to.\n * @param child The block to try to connect to the parent.\n * @param state The state which defines the given block\n */\nfunction tryToConnectParent(\n parentConnection: Connection|undefined, child: Block, state: State) {\n if (!parentConnection) {\n return;\n }\n\n if (parentConnection.getSourceBlock().isShadow() && !child.isShadow()) {\n throw new RealChildOfShadow(state);\n }\n\n let connected = false;\n let childConnection;\n if (parentConnection.type === inputTypes.VALUE) {\n childConnection = child.outputConnection;\n if (!childConnection) {\n throw new MissingConnection('output', child, state);\n }\n connected = parentConnection.connect(childConnection);\n } else { // Statement type.\n childConnection = child.previousConnection;\n if (!childConnection) {\n throw new MissingConnection('previous', child, state);\n }\n connected = parentConnection.connect(childConnection);\n }\n\n if (!connected) {\n const checker = child.workspace.connectionChecker;\n throw new BadConnectionCheck(\n checker.getErrorMessage(\n checker.canConnectWithReason(\n childConnection, parentConnection, false),\n childConnection, parentConnection),\n parentConnection.type === inputTypes.VALUE ? 'output connection' :\n 'previous connection',\n child, state);\n }\n}\n\n/**\n * Applies icon state to the icons on the block, based on the given state\n * object.\n *\n * @param block The block to set the icon state of.\n * @param state The state object to reference.\n */\nfunction loadIcons(block: Block, state: State) {\n if (!state['icons']) {\n return;\n }\n // TODO(#2105): Remove this logic and put it in the icon.\n const comment = state['icons']['comment'];\n if (comment) {\n block.setCommentText(comment['text']);\n // Load if saved. (Cleaned unnecessary attributes when in the trashcan.)\n if ('pinned' in comment) {\n block.commentModel.pinned = comment['pinned'];\n }\n if ('width' in comment && 'height' in comment) {\n block.commentModel.size = new Size(comment['width'], comment['height']);\n }\n if (comment['pinned'] && block.rendered && !block.isInFlyout) {\n // Give the block a chance to be positioned and rendered before showing.\n const blockSvg = block as BlockSvg;\n setTimeout(() => blockSvg.getCommentIcon()!.setVisible(true), 1);\n }\n }\n}\n\n/**\n * Applies any field information available on the state object to the block.\n *\n * @param block The block to set the field state of.\n * @param state The state object to reference.\n */\nfunction loadFields(block: Block, state: State) {\n if (!state['fields']) {\n return;\n }\n const keys = Object.keys(state['fields']);\n for (let i = 0; i < keys.length; i++) {\n const fieldName = keys[i];\n const fieldState = state['fields'][fieldName];\n const field = block.getField(fieldName);\n if (!field) {\n console.warn(\n `Ignoring non-existant field ${fieldName} in block ${block.type}`);\n continue;\n }\n field.loadState(fieldState);\n }\n}\n\n/**\n * Creates any child blocks (attached to inputs) defined by the given state\n * and attaches them to the given block.\n *\n * @param block The block to attach input blocks to.\n * @param state The state object to reference.\n */\nfunction loadInputBlocks(block: Block, state: State) {\n if (!state['inputs']) {\n return;\n }\n const keys = Object.keys(state['inputs']);\n for (let i = 0; i < keys.length; i++) {\n const inputName = keys[i];\n const input = block.getInput(inputName);\n if (!input || !input.connection) {\n throw new MissingConnection(inputName, block, state);\n }\n loadConnection(input.connection, state['inputs'][inputName]);\n }\n}\n\n/**\n * Creates any next blocks defined by the given state and attaches them to the\n * given block.\n *\n * @param block The block to attach next blocks to.\n * @param state The state object to reference.\n */\nfunction loadNextBlocks(block: Block, state: State) {\n if (!state['next']) {\n return;\n }\n if (!block.nextConnection) {\n throw new MissingConnection('next', block, state);\n }\n loadConnection(block.nextConnection, state['next']);\n}\n/**\n * Applies the state defined by connectionState to the given connection, ie\n * assigns shadows and attaches child blocks.\n *\n * @param connection The connection to deserialize the connected blocks of.\n * @param connectionState The object containing the state of any connected\n * shadow block, or any connected real block.\n */\nfunction loadConnection(\n connection: Connection, connectionState: ConnectionState) {\n if (connectionState['shadow']) {\n connection.setShadowState(connectionState['shadow']);\n }\n if (connectionState['block']) {\n appendPrivate(\n connectionState['block'], connection.getSourceBlock().workspace,\n {parentConnection: connection});\n }\n}\n\n// TODO(#5146): Remove this from the serialization system.\n/**\n * Initializes the give block, eg init the model, inits the svg, renders, etc.\n *\n * @param block The block to initialize.\n * @param rendered Whether the block is a rendered or headless block.\n */\nfunction initBlock(block: Block, rendered: boolean) {\n if (rendered) {\n const blockSvg = block as BlockSvg;\n // Adding connections to the connection db is expensive. This defers that\n // operation to decrease load time.\n blockSvg.setConnectionTracking(false);\n\n blockSvg.initSvg();\n blockSvg.render(false);\n // fixes #6076 JSO deserialization doesn't\n // set .iconXY_ property so here it will be set\n const icons = blockSvg.getIcons();\n for (let i = 0; i < icons.length; i++) {\n icons[i].computeIconLocation();\n }\n } else {\n block.initModel();\n }\n}\n\n// Alias to disambiguate saving within the serializer.\nconst saveBlock = save;\n\n/**\n * Serializer for saving and loading block state.\n *\n * @alias Blockly.serialization.blocks.BlockSerializer\n */\nclass BlockSerializer implements ISerializer {\n priority: number;\n\n /* eslint-disable-next-line require-jsdoc */\n constructor() {\n /** The priority for deserializing blocks. */\n this.priority = priorities.BLOCKS;\n }\n\n /**\n * Serializes the blocks of the given workspace.\n *\n * @param workspace The workspace to save the blocks of.\n * @returns The state of the workspace's blocks, or null if there are no\n * blocks.\n */\n save(workspace: Workspace): {languageVersion: number, blocks: State[]}|null {\n const blockStates = [];\n for (const block of workspace.getTopBlocks(false)) {\n const state =\n saveBlock(block, {addCoordinates: true, doFullSerialization: false});\n if (state) {\n blockStates.push(state);\n }\n }\n if (blockStates.length) {\n return {\n 'languageVersion': 0, // Currently unused.\n 'blocks': blockStates,\n };\n }\n return null;\n }\n\n /**\n * Deserializes the blocks defined by the given state into the given\n * workspace.\n *\n * @param state The state of the blocks to deserialize.\n * @param workspace The workspace to deserialize into.\n */\n load(\n state: {languageVersion: number, blocks: State[]}, workspace: Workspace) {\n const blockStates = state['blocks'];\n for (const state of blockStates) {\n append(state, workspace, {recordUndo: eventUtils.getRecordUndo()});\n }\n }\n\n /**\n * Disposes of any blocks that exist on the workspace.\n *\n * @param workspace The workspace to clear the blocks of.\n */\n clear(workspace: Workspace) {\n // Cannot use workspace.clear() because that also removes variables.\n for (const block of workspace.getTopBlocks(false)) {\n block.dispose(false);\n }\n }\n}\n\nserializationRegistry.register('blocks', new BlockSerializer());\n","/**\n * @license\n * Copyright 2011 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Components for creating connections between blocks.\n *\n * @class\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.Connection');\n\nimport type {Block} from './block.js';\nimport {ConnectionType} from './connection_type.js';\nimport type {BlockMove} from './events/events_block_move.js';\nimport * as eventUtils from './events/utils.js';\nimport type {Input} from './input.js';\nimport type {IASTNodeLocationWithBlock} from './interfaces/i_ast_node_location_with_block.js';\nimport type {IConnectionChecker} from './interfaces/i_connection_checker.js';\nimport * as blocks from './serialization/blocks.js';\nimport * as Xml from './xml.js';\n\n\n/**\n * Class for a connection between blocks.\n *\n * @alias Blockly.Connection\n */\nexport class Connection implements IASTNodeLocationWithBlock {\n /** Constants for checking whether two connections are compatible. */\n static CAN_CONNECT = 0;\n static REASON_SELF_CONNECTION = 1;\n static REASON_WRONG_TYPE = 2;\n static REASON_TARGET_NULL = 3;\n static REASON_CHECKS_FAILED = 4;\n static REASON_DIFFERENT_WORKSPACES = 5;\n static REASON_SHADOW_PARENT = 6;\n static REASON_DRAG_CHECKS_FAILED = 7;\n static REASON_PREVIOUS_AND_OUTPUT = 8;\n\n protected sourceBlock_: Block;\n\n /** Connection this connection connects to. Null if not connected. */\n targetConnection: Connection|null = null;\n\n /**\n * Has this connection been disposed of?\n *\n * @internal\n */\n disposed = false;\n\n /** List of compatible value types. Null if all types are compatible. */\n private check_: string[]|null = null;\n\n /** DOM representation of a shadow block, or null if none. */\n private shadowDom_: Element|null = null;\n\n /**\n * Horizontal location of this connection.\n *\n * @internal\n */\n x = 0;\n\n /**\n * Vertical location of this connection.\n *\n * @internal\n */\n y = 0;\n\n private shadowState_: blocks.State|null = null;\n\n /**\n * @param source The block establishing this connection.\n * @param type The type of the connection.\n */\n constructor(source: Block, public type: number) {\n this.sourceBlock_ = source;\n }\n\n /**\n * Connect two connections together. This is the connection on the superior\n * block.\n *\n * @param childConnection Connection on inferior block.\n */\n protected connect_(childConnection: Connection) {\n const INPUT = ConnectionType.INPUT_VALUE;\n const parentBlock = this.getSourceBlock();\n const childBlock = childConnection.getSourceBlock();\n\n // Make sure the childConnection is available.\n if (childConnection.isConnected()) {\n childConnection.disconnect();\n }\n\n // Make sure the parentConnection is available.\n let orphan;\n if (this.isConnected()) {\n const shadowState = this.stashShadowState_();\n const target = this.targetBlock();\n if (target!.isShadow()) {\n target!.dispose(false);\n } else {\n this.disconnect();\n orphan = target;\n }\n this.applyShadowState_(shadowState);\n }\n\n // Connect the new connection to the parent.\n let event;\n if (eventUtils.isEnabled()) {\n event =\n new (eventUtils.get(eventUtils.BLOCK_MOVE))(childBlock) as BlockMove;\n }\n connectReciprocally(this, childConnection);\n childBlock.setParent(parentBlock);\n if (event) {\n event.recordNew();\n eventUtils.fire(event);\n }\n\n // Deal with the orphan if it exists.\n if (orphan) {\n const orphanConnection = this.type === INPUT ? orphan.outputConnection :\n orphan.previousConnection;\n const connection = Connection.getConnectionForOrphanedConnection(\n childBlock, (orphanConnection));\n if (connection) {\n orphanConnection.connect(connection);\n } else {\n orphanConnection.onFailedConnect(this);\n }\n }\n }\n\n /**\n * Dispose of this connection and deal with connected blocks.\n *\n * @internal\n */\n dispose() {\n // isConnected returns true for shadows and non-shadows.\n if (this.isConnected()) {\n // Destroy the attached shadow block & its children (if it exists).\n this.setShadowStateInternal_();\n\n const targetBlock = this.targetBlock();\n if (targetBlock) {\n // Disconnect the attached normal block.\n targetBlock.unplug();\n }\n }\n\n this.disposed = true;\n }\n\n /**\n * Get the source block for this connection.\n *\n * @returns The source block.\n */\n getSourceBlock(): Block {\n return this.sourceBlock_;\n }\n\n /**\n * Does the connection belong to a superior block (higher in the source\n * stack)?\n *\n * @returns True if connection faces down or right.\n */\n isSuperior(): boolean {\n return this.type === ConnectionType.INPUT_VALUE ||\n this.type === ConnectionType.NEXT_STATEMENT;\n }\n\n /**\n * Is the connection connected?\n *\n * @returns True if connection is connected to another connection.\n */\n isConnected(): boolean {\n return !!this.targetConnection;\n }\n\n /**\n * Get the workspace's connection type checker object.\n *\n * @returns The connection type checker for the source block's workspace.\n * @internal\n */\n getConnectionChecker(): IConnectionChecker {\n return this.sourceBlock_.workspace.connectionChecker;\n }\n\n /**\n * Called when an attempted connection fails. NOP by default (i.e. for\n * headless workspaces).\n *\n * @param _otherConnection Connection that this connection failed to connect\n * to.\n * @internal\n */\n onFailedConnect(_otherConnection: Connection) {}\n // NOP\n\n /**\n * Connect this connection to another connection.\n *\n * @param otherConnection Connection to connect to.\n * @returns Whether the the blocks are now connected or not.\n */\n connect(otherConnection: Connection): boolean {\n if (this.targetConnection === otherConnection) {\n // Already connected together. NOP.\n return true;\n }\n\n const checker = this.getConnectionChecker();\n if (checker.canConnect(this, otherConnection, false)) {\n const eventGroup = eventUtils.getGroup();\n if (!eventGroup) {\n eventUtils.setGroup(true);\n }\n // Determine which block is superior (higher in the source stack).\n if (this.isSuperior()) {\n // Superior block.\n this.connect_(otherConnection);\n } else {\n // Inferior block.\n otherConnection.connect_(this);\n }\n if (!eventGroup) {\n eventUtils.setGroup(false);\n }\n }\n\n return this.isConnected();\n }\n\n /** Disconnect this connection. */\n disconnect() {\n const otherConnection = this.targetConnection;\n if (!otherConnection) {\n throw Error('Source connection not connected.');\n }\n if (otherConnection.targetConnection !== this) {\n throw Error('Target connection not connected to source connection.');\n }\n let parentBlock;\n let childBlock;\n let parentConnection;\n if (this.isSuperior()) {\n // Superior block.\n parentBlock = this.sourceBlock_;\n childBlock = otherConnection.getSourceBlock();\n /* eslint-disable-next-line @typescript-eslint/no-this-alias */\n parentConnection = this;\n } else {\n // Inferior block.\n parentBlock = otherConnection.getSourceBlock();\n childBlock = this.sourceBlock_;\n parentConnection = otherConnection;\n }\n\n const eventGroup = eventUtils.getGroup();\n if (!eventGroup) {\n eventUtils.setGroup(true);\n }\n this.disconnectInternal_(parentBlock, childBlock);\n if (!childBlock.isShadow()) {\n // If we were disconnecting a shadow, no need to spawn a new one.\n parentConnection.respawnShadow_();\n }\n if (!eventGroup) {\n eventUtils.setGroup(false);\n }\n }\n\n /**\n * Disconnect two blocks that are connected by this connection.\n *\n * @param parentBlock The superior block.\n * @param childBlock The inferior block.\n */\n protected disconnectInternal_(parentBlock: Block, childBlock: Block) {\n let event;\n if (eventUtils.isEnabled()) {\n event =\n new (eventUtils.get(eventUtils.BLOCK_MOVE))(childBlock) as BlockMove;\n }\n const otherConnection = this.targetConnection;\n if (otherConnection) {\n otherConnection.targetConnection = null;\n }\n this.targetConnection = null;\n childBlock.setParent(null);\n if (event) {\n event.recordNew();\n eventUtils.fire(event);\n }\n }\n\n /**\n * Respawn the shadow block if there was one connected to the this connection.\n */\n protected respawnShadow_() {\n // Have to keep respawnShadow_ for backwards compatibility.\n this.createShadowBlock_(true);\n }\n\n /**\n * Returns the block that this connection connects to.\n *\n * @returns The connected block or null if none is connected.\n */\n targetBlock(): Block|null {\n if (this.isConnected()) {\n return this.targetConnection?.getSourceBlock() ?? null;\n }\n return null;\n }\n\n /**\n * Function to be called when this connection's compatible types have changed.\n */\n protected onCheckChanged_() {\n // The new value type may not be compatible with the existing connection.\n if (this.isConnected() &&\n (!this.targetConnection ||\n !this.getConnectionChecker().canConnect(\n this, this.targetConnection, false))) {\n const child = this.isSuperior() ? this.targetBlock() : this.sourceBlock_;\n child!.unplug();\n }\n }\n\n /**\n * Change a connection's compatibility.\n *\n * @param check Compatible value type or list of value types. Null if all\n * types are compatible.\n * @returns The connection being modified (to allow chaining).\n */\n setCheck(check: string|string[]|null): Connection {\n if (check) {\n if (!Array.isArray(check)) {\n check = [check];\n }\n this.check_ = check;\n this.onCheckChanged_();\n } else {\n this.check_ = null;\n }\n return this;\n }\n\n /**\n * Get a connection's compatibility.\n *\n * @returns List of compatible value types.\n * Null if all types are compatible.\n */\n getCheck(): string[]|null {\n return this.check_;\n }\n\n /**\n * Changes the connection's shadow block.\n *\n * @param shadowDom DOM representation of a block or null.\n */\n setShadowDom(shadowDom: Element|null) {\n this.setShadowStateInternal_({shadowDom});\n }\n\n /**\n * Returns the xml representation of the connection's shadow block.\n *\n * @param returnCurrent If true, and the shadow block is currently attached to\n * this connection, this serializes the state of that block and returns it\n * (so that field values are correct). Otherwise the saved shadowDom is\n * just returned.\n * @returns Shadow DOM representation of a block or null.\n */\n getShadowDom(returnCurrent?: boolean): Element|null {\n return returnCurrent && this.targetBlock()!.isShadow() ?\n Xml.blockToDom((this.targetBlock() as Block)) as Element :\n this.shadowDom_;\n }\n\n /**\n * Changes the connection's shadow block.\n *\n * @param shadowState An state represetation of the block or null.\n */\n setShadowState(shadowState: blocks.State|null) {\n this.setShadowStateInternal_({shadowState});\n }\n\n /**\n * Returns the serialized object representation of the connection's shadow\n * block.\n *\n * @param returnCurrent If true, and the shadow block is currently attached to\n * this connection, this serializes the state of that block and returns it\n * (so that field values are correct). Otherwise the saved state is just\n * returned.\n * @returns Serialized object representation of the block, or null.\n */\n getShadowState(returnCurrent?: boolean): blocks.State|null {\n if (returnCurrent && this.targetBlock() && this.targetBlock()!.isShadow()) {\n return blocks.save(this.targetBlock() as Block);\n }\n return this.shadowState_;\n }\n\n /**\n * Find all nearby compatible connections to this connection.\n * Type checking does not apply, since this function is used for bumping.\n *\n * Headless configurations (the default) do not have neighboring connection,\n * and always return an empty list (the default).\n * {@link RenderedConnection#neighbours} overrides this behavior with a list\n * computed from the rendered positioning.\n *\n * @param _maxLimit The maximum radius to another connection.\n * @returns List of connections.\n * @internal\n */\n neighbours(_maxLimit: number): Connection[] {\n return [];\n }\n\n /**\n * Get the parent input of a connection.\n *\n * @returns The input that the connection belongs to or null if no parent\n * exists.\n * @internal\n */\n getParentInput(): Input|null {\n let parentInput = null;\n const inputs = this.sourceBlock_.inputList;\n for (let i = 0; i < inputs.length; i++) {\n if (inputs[i].connection === this) {\n parentInput = inputs[i];\n break;\n }\n }\n return parentInput;\n }\n\n /**\n * This method returns a string describing this Connection in developer terms\n * (English only). Intended to on be used in console logs and errors.\n *\n * @returns The description.\n */\n toString(): string {\n const block = this.sourceBlock_;\n if (!block) {\n return 'Orphan Connection';\n }\n let msg;\n if (block.outputConnection === this) {\n msg = 'Output Connection of ';\n } else if (block.previousConnection === this) {\n msg = 'Previous Connection of ';\n } else if (block.nextConnection === this) {\n msg = 'Next Connection of ';\n } else {\n let parentInput = null;\n for (let i = 0, input; input = block.inputList[i]; i++) {\n if (input.connection === this) {\n parentInput = input;\n break;\n }\n }\n if (parentInput) {\n msg = 'Input \"' + parentInput.name + '\" connection on ';\n } else {\n console.warn('Connection not actually connected to sourceBlock_');\n return 'Orphan Connection';\n }\n }\n return msg + block.toDevString();\n }\n\n /**\n * Returns the state of the shadowDom_ and shadowState_ properties, then\n * temporarily sets those properties to null so no shadow respawns.\n *\n * @returns The state of both the shadowDom_ and shadowState_ properties.\n */\n private stashShadowState_():\n {shadowDom: Element|null, shadowState: blocks.State|null} {\n const shadowDom = this.getShadowDom(true);\n const shadowState = this.getShadowState(true);\n // Set to null so it doesn't respawn.\n this.shadowDom_ = null;\n this.shadowState_ = null;\n return {shadowDom, shadowState};\n }\n\n /**\n * Reapplies the stashed state of the shadowDom_ and shadowState_ properties.\n *\n * @param param0 The state to reapply to the shadowDom_ and shadowState_\n * properties.\n */\n private applyShadowState_({shadowDom, shadowState}: {\n shadowDom: Element|null,\n shadowState: blocks.State|null\n }) {\n this.shadowDom_ = shadowDom;\n this.shadowState_ = shadowState;\n }\n\n /**\n * Sets the state of the shadow of this connection.\n *\n * @param param0 The state to set the shadow of this connection to.\n */\n private setShadowStateInternal_({shadowDom = null, shadowState = null}: {\n shadowDom?: Element|null,\n shadowState?: blocks.State|null\n } = {}) {\n // One or both of these should always be null.\n // If neither is null, the shadowState will get priority.\n this.shadowDom_ = shadowDom;\n this.shadowState_ = shadowState;\n\n const target = this.targetBlock();\n if (!target) {\n this.respawnShadow_();\n if (this.targetBlock() && this.targetBlock()!.isShadow()) {\n this.serializeShadow_(this.targetBlock());\n }\n } else if (target.isShadow()) {\n target.dispose(false);\n this.respawnShadow_();\n if (this.targetBlock() && this.targetBlock()!.isShadow()) {\n this.serializeShadow_(this.targetBlock());\n }\n } else {\n const shadow = this.createShadowBlock_(false);\n this.serializeShadow_(shadow);\n if (shadow) {\n shadow.dispose(false);\n }\n }\n }\n\n /**\n * Creates a shadow block based on the current shadowState_ or shadowDom_.\n * shadowState_ gets priority.\n *\n * @param attemptToConnect Whether to try to connect the shadow block to this\n * connection or not.\n * @returns The shadow block that was created, or null if both the\n * shadowState_ and shadowDom_ are null.\n */\n private createShadowBlock_(attemptToConnect: boolean): Block|null {\n const parentBlock = this.getSourceBlock();\n const shadowState = this.getShadowState();\n const shadowDom = this.getShadowDom();\n if (parentBlock.isDeadOrDying() || !shadowState && !shadowDom) {\n return null;\n }\n\n let blockShadow;\n if (shadowState) {\n blockShadow = blocks.appendInternal(shadowState, parentBlock.workspace, {\n parentConnection: attemptToConnect ? this : undefined,\n isShadow: true,\n recordUndo: false,\n });\n return blockShadow;\n }\n\n if (shadowDom) {\n blockShadow = Xml.domToBlock(shadowDom, parentBlock.workspace);\n if (attemptToConnect) {\n if (this.type === ConnectionType.INPUT_VALUE) {\n if (!blockShadow.outputConnection) {\n throw new Error('Shadow block is missing an output connection');\n }\n if (!this.connect(blockShadow.outputConnection)) {\n throw new Error('Could not connect shadow block to connection');\n }\n } else if (this.type === ConnectionType.NEXT_STATEMENT) {\n if (!blockShadow.previousConnection) {\n throw new Error('Shadow block is missing previous connection');\n }\n if (!this.connect(blockShadow.previousConnection)) {\n throw new Error('Could not connect shadow block to connection');\n }\n } else {\n throw new Error(\n 'Cannot connect a shadow block to a previous/output connection');\n }\n }\n return blockShadow;\n }\n return null;\n }\n\n /**\n * Saves the given shadow block to both the shadowDom_ and shadowState_\n * properties, in their respective serialized forms.\n *\n * @param shadow The shadow to serialize, or null.\n */\n private serializeShadow_(shadow: Block|null) {\n if (!shadow) {\n return;\n }\n this.shadowDom_ = Xml.blockToDom(shadow) as Element;\n this.shadowState_ = blocks.save(shadow);\n }\n\n /**\n * Returns the connection (starting at the startBlock) which will accept\n * the given connection. This includes compatible connection types and\n * connection checks.\n *\n * @param startBlock The block on which to start the search.\n * @param orphanConnection The connection that is looking for a home.\n * @returns The suitable connection point on the chain of blocks, or null.\n */\n static getConnectionForOrphanedConnection(\n startBlock: Block, orphanConnection: Connection): Connection|null {\n if (orphanConnection.type === ConnectionType.OUTPUT_VALUE) {\n return getConnectionForOrphanedOutput(\n startBlock, orphanConnection.getSourceBlock());\n }\n // Otherwise we're dealing with a stack.\n const connection = startBlock.lastConnectionInStack(true);\n const checker = orphanConnection.getConnectionChecker();\n if (connection && checker.canConnect(orphanConnection, connection, false)) {\n return connection;\n }\n return null;\n }\n}\n\n/**\n * Update two connections to target each other.\n *\n * @param first The first connection to update.\n * @param second The second connection to update.\n */\nfunction connectReciprocally(first: Connection, second: Connection) {\n if (!first || !second) {\n throw Error('Cannot connect null connections.');\n }\n first.targetConnection = second;\n second.targetConnection = first;\n}\n/**\n * Returns the single connection on the block that will accept the orphaned\n * block, if one can be found. If the block has multiple compatible connections\n * (even if they are filled) this returns null. If the block has no compatible\n * connections, this returns null.\n *\n * @param block The superior block.\n * @param orphanBlock The inferior block.\n * @returns The suitable connection point on 'block', or null.\n */\nfunction getSingleConnection(block: Block, orphanBlock: Block): Connection|\n null {\n let foundConnection = null;\n const output = orphanBlock.outputConnection;\n const typeChecker = output.getConnectionChecker();\n\n for (let i = 0, input; input = block.inputList[i]; i++) {\n const connection = input.connection;\n if (connection && typeChecker.canConnect(output, connection, false)) {\n if (foundConnection) {\n return null; // More than one connection.\n }\n foundConnection = connection;\n }\n }\n return foundConnection;\n}\n\n/**\n * Walks down a row a blocks, at each stage checking if there are any\n * connections that will accept the orphaned block. If at any point there\n * are zero or multiple eligible connections, returns null. Otherwise\n * returns the only input on the last block in the chain.\n * Terminates early for shadow blocks.\n *\n * @param startBlock The block on which to start the search.\n * @param orphanBlock The block that is looking for a home.\n * @returns The suitable connection point on the chain of blocks, or null.\n */\nfunction getConnectionForOrphanedOutput(\n startBlock: Block, orphanBlock: Block): Connection|null {\n let newBlock: Block|null = startBlock;\n let connection;\n while (connection = getSingleConnection(newBlock, orphanBlock)) {\n newBlock = connection.targetBlock();\n if (!newBlock || newBlock.isShadow()) {\n return connection;\n }\n }\n return null;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * The class representing an AST node.\n * Used to traverse the Blockly AST.\n *\n * @class\n */\nimport * as goog from '../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.ASTNode');\n\nimport type {Block} from '../block.js';\nimport type {Connection} from '../connection.js';\nimport {ConnectionType} from '../connection_type.js';\nimport type {Field} from '../field.js';\nimport type {Input} from '../input.js';\nimport type {IASTNodeLocation} from '../interfaces/i_ast_node_location.js';\nimport type {IASTNodeLocationWithBlock} from '../interfaces/i_ast_node_location_with_block.js';\nimport {Coordinate} from '../utils/coordinate.js';\nimport type {Workspace} from '../workspace.js';\n\n\n/**\n * Class for an AST node.\n * It is recommended that you use one of the createNode methods instead of\n * creating a node directly.\n *\n * @alias Blockly.ASTNode\n */\nexport class ASTNode {\n /**\n * True to navigate to all fields. False to only navigate to clickable fields.\n */\n static NAVIGATE_ALL_FIELDS = false;\n\n /**\n * The default y offset to use when moving the cursor from a stack to the\n * workspace.\n */\n private static readonly DEFAULT_OFFSET_Y: number = -20;\n private readonly type_: string;\n private readonly isConnection_: boolean;\n private readonly location_: IASTNodeLocation;\n\n /** The coordinate on the workspace. */\n // AnyDuringMigration because: Type 'null' is not assignable to type\n // 'Coordinate'.\n private wsCoordinate_: Coordinate = null as AnyDuringMigration;\n\n /**\n * @param type The type of the location.\n * Must be in ASTNode.types.\n * @param location The position in the AST.\n * @param opt_params Optional dictionary of options.\n * @alias Blockly.ASTNode\n */\n constructor(type: string, location: IASTNodeLocation, opt_params?: Params) {\n if (!location) {\n throw Error('Cannot create a node without a location.');\n }\n\n /**\n * The type of the location.\n * One of ASTNode.types\n */\n this.type_ = type;\n\n /** Whether the location points to a connection. */\n this.isConnection_ = ASTNode.isConnectionType_(type);\n\n /** The location of the AST node. */\n this.location_ = location;\n\n this.processParams_(opt_params || null);\n }\n\n /**\n * Parse the optional parameters.\n *\n * @param params The user specified parameters.\n */\n private processParams_(params: Params|null) {\n if (!params) {\n return;\n }\n if (params.wsCoordinate) {\n this.wsCoordinate_ = params.wsCoordinate;\n }\n }\n\n /**\n * Gets the value pointed to by this node.\n * It is the callers responsibility to check the node type to figure out what\n * type of object they get back from this.\n *\n * @returns The current field, connection, workspace, or block the cursor is\n * on.\n */\n getLocation(): IASTNodeLocation {\n return this.location_;\n }\n\n /**\n * The type of the current location.\n * One of ASTNode.types\n *\n * @returns The type of the location.\n */\n getType(): string {\n return this.type_;\n }\n\n /**\n * The coordinate on the workspace.\n *\n * @returns The workspace coordinate or null if the location is not a\n * workspace.\n */\n getWsCoordinate(): Coordinate {\n return this.wsCoordinate_;\n }\n\n /**\n * Whether the node points to a connection.\n *\n * @returns [description]\n * @internal\n */\n isConnection(): boolean {\n return this.isConnection_;\n }\n\n /**\n * Given an input find the next editable field or an input with a non null\n * connection in the same block. The current location must be an input\n * connection.\n *\n * @returns The AST node holding the next field or connection or null if there\n * is no editable field or input connection after the given input.\n */\n private findNextForInput_(): ASTNode|null {\n const location = this.location_ as Connection;\n const parentInput = location.getParentInput();\n const block = parentInput!.getSourceBlock();\n // AnyDuringMigration because: Argument of type 'Input | null' is not\n // assignable to parameter of type 'Input'.\n const curIdx = block!.inputList.indexOf(parentInput as AnyDuringMigration);\n for (let i = curIdx + 1; i < block!.inputList.length; i++) {\n const input = block!.inputList[i];\n const fieldRow = input.fieldRow;\n for (let j = 0; j < fieldRow.length; j++) {\n const field = fieldRow[j];\n if (field.isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) {\n return ASTNode.createFieldNode(field);\n }\n }\n if (input.connection) {\n return ASTNode.createInputNode(input);\n }\n }\n return null;\n }\n\n /**\n * Given a field find the next editable field or an input with a non null\n * connection in the same block. The current location must be a field.\n *\n * @returns The AST node pointing to the next field or connection or null if\n * there is no editable field or input connection after the given input.\n */\n private findNextForField_(): ASTNode|null {\n const location = this.location_ as Field;\n const input = location.getParentInput();\n const block = location.getSourceBlock();\n if (!block) {\n throw new Error(\n 'The current AST location is not associated with a block');\n }\n const curIdx = block.inputList.indexOf((input));\n let fieldIdx = input.fieldRow.indexOf(location) + 1;\n for (let i = curIdx; i < block.inputList.length; i++) {\n const newInput = block.inputList[i];\n const fieldRow = newInput.fieldRow;\n while (fieldIdx < fieldRow.length) {\n if (fieldRow[fieldIdx].isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) {\n return ASTNode.createFieldNode(fieldRow[fieldIdx]);\n }\n fieldIdx++;\n }\n fieldIdx = 0;\n if (newInput.connection) {\n return ASTNode.createInputNode(newInput);\n }\n }\n return null;\n }\n\n /**\n * Given an input find the previous editable field or an input with a non null\n * connection in the same block. The current location must be an input\n * connection.\n *\n * @returns The AST node holding the previous field or connection.\n */\n private findPrevForInput_(): ASTNode|null {\n const location = this.location_ as Connection;\n const parentInput = location.getParentInput();\n const block = parentInput!.getSourceBlock();\n // AnyDuringMigration because: Argument of type 'Input | null' is not\n // assignable to parameter of type 'Input'.\n const curIdx = block!.inputList.indexOf(parentInput as AnyDuringMigration);\n for (let i = curIdx; i >= 0; i--) {\n const input = block!.inputList[i];\n if (input.connection && input !== parentInput) {\n return ASTNode.createInputNode(input);\n }\n const fieldRow = input.fieldRow;\n for (let j = fieldRow.length - 1; j >= 0; j--) {\n const field = fieldRow[j];\n if (field.isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) {\n return ASTNode.createFieldNode(field);\n }\n }\n }\n return null;\n }\n\n /**\n * Given a field find the previous editable field or an input with a non null\n * connection in the same block. The current location must be a field.\n *\n * @returns The AST node holding the previous input or field.\n */\n private findPrevForField_(): ASTNode|null {\n const location = this.location_ as Field;\n const parentInput = location.getParentInput();\n const block = location.getSourceBlock();\n if (!block) {\n throw new Error(\n 'The current AST location is not associated with a block');\n }\n const curIdx = block.inputList.indexOf((parentInput));\n let fieldIdx = parentInput.fieldRow.indexOf(location) - 1;\n for (let i = curIdx; i >= 0; i--) {\n const input = block.inputList[i];\n if (input.connection && input !== parentInput) {\n return ASTNode.createInputNode(input);\n }\n const fieldRow = input.fieldRow;\n while (fieldIdx > -1) {\n if (fieldRow[fieldIdx].isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) {\n return ASTNode.createFieldNode(fieldRow[fieldIdx]);\n }\n fieldIdx--;\n }\n // Reset the fieldIdx to the length of the field row of the previous\n // input.\n if (i - 1 >= 0) {\n fieldIdx = block.inputList[i - 1].fieldRow.length - 1;\n }\n }\n return null;\n }\n\n /**\n * Navigate between stacks of blocks on the workspace.\n *\n * @param forward True to go forward. False to go backwards.\n * @returns The first block of the next stack or null if there are no blocks\n * on the workspace.\n */\n private navigateBetweenStacks_(forward: boolean): ASTNode|null {\n let curLocation = this.getLocation();\n // TODO(#6097): Use instanceof checks to exit early for values of\n // curLocation that don't make sense.\n if ((curLocation as IASTNodeLocationWithBlock).getSourceBlock) {\n const block = (curLocation as IASTNodeLocationWithBlock).getSourceBlock();\n if (block) {\n curLocation = block;\n }\n }\n // TODO(#6097): Use instanceof checks to exit early for values of\n // curLocation that don't make sense.\n const curLocationAsBlock = curLocation as Block;\n if (!curLocationAsBlock || curLocationAsBlock.isDeadOrDying()) {\n return null;\n }\n const curRoot = curLocationAsBlock.getRootBlock();\n const topBlocks = curRoot.workspace.getTopBlocks(true);\n for (let i = 0; i < topBlocks.length; i++) {\n const topBlock = topBlocks[i];\n if (curRoot.id === topBlock.id) {\n const offset = forward ? 1 : -1;\n const resultIndex = i + offset;\n if (resultIndex === -1 || resultIndex === topBlocks.length) {\n return null;\n }\n return ASTNode.createStackNode(topBlocks[resultIndex]);\n }\n }\n throw Error(\n 'Couldn\\'t find ' + (forward ? 'next' : 'previous') + ' stack?!');\n }\n\n /**\n * Finds the top most AST node for a given block.\n * This is either the previous connection, output connection or block\n * depending on what kind of connections the block has.\n *\n * @param block The block that we want to find the top connection on.\n * @returns The AST node containing the top connection.\n */\n private findTopASTNodeForBlock_(block: Block): ASTNode|null {\n const topConnection = getParentConnection(block);\n if (topConnection) {\n return ASTNode.createConnectionNode(topConnection);\n } else {\n return ASTNode.createBlockNode(block);\n }\n }\n\n /**\n * Get the AST node pointing to the input that the block is nested under or if\n * the block is not nested then get the stack AST node.\n *\n * @param block The source block of the current location.\n * @returns The AST node pointing to the input connection or the top block of\n * the stack this block is in.\n */\n private getOutAstNodeForBlock_(block: Block): ASTNode|null {\n if (!block) {\n return null;\n }\n // If the block doesn't have a previous connection then it is the top of the\n // substack.\n const topBlock = block.getTopStackBlock();\n const topConnection = getParentConnection(topBlock);\n // If the top connection has a parentInput, create an AST node pointing to\n // that input.\n if (topConnection && topConnection.targetConnection &&\n topConnection.targetConnection.getParentInput()) {\n // AnyDuringMigration because: Argument of type 'Input | null' is not\n // assignable to parameter of type 'Input'.\n return ASTNode.createInputNode(\n topConnection.targetConnection.getParentInput() as\n AnyDuringMigration);\n } else {\n // Go to stack level if you are not underneath an input.\n return ASTNode.createStackNode(topBlock);\n }\n }\n\n /**\n * Find the first editable field or input with a connection on a given block.\n *\n * @param block The source block of the current location.\n * @returns An AST node pointing to the first field or input.\n * Null if there are no editable fields or inputs with connections on the\n * block.\n */\n private findFirstFieldOrInput_(block: Block): ASTNode|null {\n const inputs = block.inputList;\n for (let i = 0; i < inputs.length; i++) {\n const input = inputs[i];\n const fieldRow = input.fieldRow;\n for (let j = 0; j < fieldRow.length; j++) {\n const field = fieldRow[j];\n if (field.isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) {\n return ASTNode.createFieldNode(field);\n }\n }\n if (input.connection) {\n return ASTNode.createInputNode(input);\n }\n }\n return null;\n }\n\n /**\n * Finds the source block of the location of this node.\n *\n * @returns The source block of the location, or null if the node is of type\n * workspace.\n */\n getSourceBlock(): Block|null {\n if (this.getType() === ASTNode.types.BLOCK) {\n return this.getLocation() as Block;\n } else if (this.getType() === ASTNode.types.STACK) {\n return this.getLocation() as Block;\n } else if (this.getType() === ASTNode.types.WORKSPACE) {\n return null;\n } else {\n return (this.getLocation() as IASTNodeLocationWithBlock).getSourceBlock();\n }\n }\n\n /**\n * Find the element to the right of the current element in the AST.\n *\n * @returns An AST node that wraps the next field, connection, block, or\n * workspace. Or null if there is no node to the right.\n */\n next(): ASTNode|null {\n switch (this.type_) {\n case ASTNode.types.STACK:\n return this.navigateBetweenStacks_(true);\n\n case ASTNode.types.OUTPUT: {\n const connection = this.location_ as Connection;\n return ASTNode.createBlockNode(connection.getSourceBlock());\n }\n case ASTNode.types.FIELD:\n return this.findNextForField_();\n\n case ASTNode.types.INPUT:\n return this.findNextForInput_();\n\n case ASTNode.types.BLOCK: {\n const block = this.location_ as Block;\n const nextConnection = block.nextConnection;\n return ASTNode.createConnectionNode(nextConnection);\n }\n case ASTNode.types.PREVIOUS: {\n const connection = this.location_ as Connection;\n return ASTNode.createBlockNode(connection.getSourceBlock());\n }\n case ASTNode.types.NEXT: {\n const connection = this.location_ as Connection;\n const targetConnection = connection.targetConnection;\n return ASTNode.createConnectionNode(targetConnection!);\n }\n }\n\n return null;\n }\n\n /**\n * Find the element one level below and all the way to the left of the current\n * location.\n *\n * @returns An AST node that wraps the next field, connection, workspace, or\n * block. Or null if there is nothing below this node.\n */\n in(): ASTNode|null {\n switch (this.type_) {\n case ASTNode.types.WORKSPACE: {\n const workspace = this.location_ as Workspace;\n const topBlocks = workspace.getTopBlocks(true);\n if (topBlocks.length > 0) {\n return ASTNode.createStackNode(topBlocks[0]);\n }\n break;\n }\n case ASTNode.types.STACK: {\n const block = this.location_ as Block;\n return this.findTopASTNodeForBlock_(block);\n }\n case ASTNode.types.BLOCK: {\n const block = this.location_ as Block;\n return this.findFirstFieldOrInput_(block);\n }\n case ASTNode.types.INPUT: {\n const connection = this.location_ as Connection;\n const targetConnection = connection.targetConnection;\n return ASTNode.createConnectionNode(targetConnection!);\n }\n }\n\n return null;\n }\n\n /**\n * Find the element to the left of the current element in the AST.\n *\n * @returns An AST node that wraps the previous field, connection, workspace\n * or block. Or null if no node exists to the left. null.\n */\n prev(): ASTNode|null {\n switch (this.type_) {\n case ASTNode.types.STACK:\n return this.navigateBetweenStacks_(false);\n\n case ASTNode.types.OUTPUT:\n return null;\n\n case ASTNode.types.FIELD:\n return this.findPrevForField_();\n\n case ASTNode.types.INPUT:\n return this.findPrevForInput_();\n\n case ASTNode.types.BLOCK: {\n const block = this.location_ as Block;\n const topConnection = getParentConnection(block);\n return ASTNode.createConnectionNode(topConnection);\n }\n case ASTNode.types.PREVIOUS: {\n const connection = this.location_ as Connection;\n const targetConnection = connection.targetConnection;\n if (targetConnection && !targetConnection.getParentInput()) {\n return ASTNode.createConnectionNode(targetConnection);\n }\n break;\n }\n case ASTNode.types.NEXT: {\n const connection = this.location_ as Connection;\n return ASTNode.createBlockNode(connection.getSourceBlock());\n }\n }\n\n return null;\n }\n\n /**\n * Find the next element that is one position above and all the way to the\n * left of the current location.\n *\n * @returns An AST node that wraps the next field, connection, workspace or\n * block. Or null if we are at the workspace level.\n */\n out(): ASTNode|null {\n switch (this.type_) {\n case ASTNode.types.STACK: {\n const block = this.location_ as Block;\n const blockPos = block.getRelativeToSurfaceXY();\n // TODO: Make sure this is in the bounds of the workspace.\n const wsCoordinate =\n new Coordinate(blockPos.x, blockPos.y + ASTNode.DEFAULT_OFFSET_Y);\n return ASTNode.createWorkspaceNode(block.workspace, wsCoordinate);\n }\n case ASTNode.types.OUTPUT: {\n const connection = this.location_ as Connection;\n const target = connection.targetConnection;\n if (target) {\n return ASTNode.createConnectionNode(target);\n }\n return ASTNode.createStackNode(connection.getSourceBlock());\n }\n case ASTNode.types.FIELD: {\n const field = this.location_ as Field;\n const block = field.getSourceBlock();\n if (!block) {\n throw new Error(\n 'The current AST location is not associated with a block');\n }\n return ASTNode.createBlockNode(block);\n }\n case ASTNode.types.INPUT: {\n const connection = this.location_ as Connection;\n return ASTNode.createBlockNode(connection.getSourceBlock());\n }\n case ASTNode.types.BLOCK: {\n const block = this.location_ as Block;\n return this.getOutAstNodeForBlock_(block);\n }\n case ASTNode.types.PREVIOUS: {\n const connection = this.location_ as Connection;\n return this.getOutAstNodeForBlock_(connection.getSourceBlock());\n }\n case ASTNode.types.NEXT: {\n const connection = this.location_ as Connection;\n return this.getOutAstNodeForBlock_(connection.getSourceBlock());\n }\n }\n\n return null;\n }\n\n /**\n * Whether an AST node of the given type points to a connection.\n *\n * @param type The type to check. One of ASTNode.types.\n * @returns True if a node of the given type points to a connection.\n */\n private static isConnectionType_(type: string): boolean {\n switch (type) {\n case ASTNode.types.PREVIOUS:\n case ASTNode.types.NEXT:\n case ASTNode.types.INPUT:\n case ASTNode.types.OUTPUT:\n return true;\n }\n return false;\n }\n\n /**\n * Create an AST node pointing to a field.\n *\n * @param field The location of the AST node.\n * @returns An AST node pointing to a field.\n */\n static createFieldNode(field: Field): ASTNode|null {\n if (!field) {\n return null;\n }\n return new ASTNode(ASTNode.types.FIELD, field);\n }\n\n /**\n * Creates an AST node pointing to a connection. If the connection has a\n * parent input then create an AST node of type input that will hold the\n * connection.\n *\n * @param connection This is the connection the node will point to.\n * @returns An AST node pointing to a connection.\n */\n static createConnectionNode(connection: Connection): ASTNode|null {\n if (!connection) {\n return null;\n }\n const type = connection.type;\n if (type === ConnectionType.INPUT_VALUE) {\n // AnyDuringMigration because: Argument of type 'Input | null' is not\n // assignable to parameter of type 'Input'.\n return ASTNode.createInputNode(\n connection.getParentInput() as AnyDuringMigration);\n } else if (\n type === ConnectionType.NEXT_STATEMENT && connection.getParentInput()) {\n // AnyDuringMigration because: Argument of type 'Input | null' is not\n // assignable to parameter of type 'Input'.\n return ASTNode.createInputNode(\n connection.getParentInput() as AnyDuringMigration);\n } else if (type === ConnectionType.NEXT_STATEMENT) {\n return new ASTNode(ASTNode.types.NEXT, connection);\n } else if (type === ConnectionType.OUTPUT_VALUE) {\n return new ASTNode(ASTNode.types.OUTPUT, connection);\n } else if (type === ConnectionType.PREVIOUS_STATEMENT) {\n return new ASTNode(ASTNode.types.PREVIOUS, connection);\n }\n return null;\n }\n\n /**\n * Creates an AST node pointing to an input. Stores the input connection as\n * the location.\n *\n * @param input The input used to create an AST node.\n * @returns An AST node pointing to a input.\n */\n static createInputNode(input: Input): ASTNode|null {\n if (!input || !input.connection) {\n return null;\n }\n return new ASTNode(ASTNode.types.INPUT, input.connection);\n }\n\n /**\n * Creates an AST node pointing to a block.\n *\n * @param block The block used to create an AST node.\n * @returns An AST node pointing to a block.\n */\n static createBlockNode(block: Block): ASTNode|null {\n if (!block) {\n return null;\n }\n return new ASTNode(ASTNode.types.BLOCK, block);\n }\n\n /**\n * Create an AST node of type stack. A stack, represented by its top block, is\n * the set of all blocks connected to a top block, including the top\n * block.\n *\n * @param topBlock A top block has no parent and can be found in the list\n * returned by workspace.getTopBlocks().\n * @returns An AST node of type stack that points to the top block on the\n * stack.\n */\n static createStackNode(topBlock: Block): ASTNode|null {\n if (!topBlock) {\n return null;\n }\n return new ASTNode(ASTNode.types.STACK, topBlock);\n }\n\n /**\n * Creates an AST node pointing to a workspace.\n *\n * @param workspace The workspace that we are on.\n * @param wsCoordinate The position on the workspace for this node.\n * @returns An AST node pointing to a workspace and a position on the\n * workspace.\n */\n static createWorkspaceNode(\n workspace: Workspace|null, wsCoordinate: Coordinate|null): ASTNode|null {\n if (!wsCoordinate || !workspace) {\n return null;\n }\n const params = {wsCoordinate};\n return new ASTNode(ASTNode.types.WORKSPACE, workspace, params);\n }\n\n /**\n * Creates an AST node for the top position on a block.\n * This is either an output connection, previous connection, or block.\n *\n * @param block The block to find the top most AST node on.\n * @returns The AST node holding the top most position on the block.\n */\n static createTopNode(block: Block): ASTNode|null {\n let astNode;\n const topConnection = getParentConnection(block);\n if (topConnection) {\n astNode = ASTNode.createConnectionNode(topConnection);\n } else {\n astNode = ASTNode.createBlockNode(block);\n }\n return astNode;\n }\n}\n\nexport namespace ASTNode {\n export interface Params {\n wsCoordinate: Coordinate;\n }\n\n export enum types {\n FIELD = 'field',\n BLOCK = 'block',\n INPUT = 'input',\n OUTPUT = 'output',\n NEXT = 'next',\n PREVIOUS = 'previous',\n STACK = 'stack',\n WORKSPACE = 'workspace',\n }\n}\n\nexport type Params = ASTNode.Params;\n// No need to export ASTNode.types from the module at this time because (1) it\n// wasn't automatically converted by the automatic migration script, (2) the\n// name doesn't follow the styleguide.\n\n\n/**\n * Gets the parent connection on a block.\n * This is either an output connection, previous connection or undefined.\n * If both connections exist return the one that is actually connected\n * to another block.\n *\n * @param block The block to find the parent connection on.\n * @returns The connection connecting to the parent of the block.\n */\nfunction getParentConnection(block: Block): Connection {\n let topConnection = block.outputConnection;\n if (!topConnection ||\n block.previousConnection && block.previousConnection.isConnected()) {\n topConnection = block.previousConnection;\n }\n return topConnection;\n}\n","/**\n * @license\n * Copyright 2018 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Methods animating a block on connection and disconnection.\n *\n * @namespace Blockly.blockAnimations\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.blockAnimations');\n\nimport type {BlockSvg} from './block_svg.js';\nimport * as dom from './utils/dom.js';\nimport {Svg} from './utils/svg.js';\n\n\n/** A bounding box for a cloned block. */\ninterface CloneRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** PID of disconnect UI animation. There can only be one at a time. */\nlet disconnectPid: ReturnType|null = null;\n\n/** SVG group of wobbling block. There can only be one at a time. */\nlet disconnectGroup: SVGElement|null = null;\n\n\n/**\n * Play some UI effects (sound, animation) when disposing of a block.\n *\n * @param block The block being disposed of.\n * @alias Blockly.blockAnimations.disposeUiEffect\n * @internal\n */\nexport function disposeUiEffect(block: BlockSvg) {\n const workspace = block.workspace;\n const svgGroup = block.getSvgRoot();\n workspace.getAudioManager().play('delete');\n\n const xy = workspace.getSvgXY(svgGroup);\n // Deeply clone the current block.\n const clone: SVGGElement = svgGroup.cloneNode(true) as SVGGElement;\n clone.setAttribute('transform', 'translate(' + xy.x + ',' + xy.y + ')');\n workspace.getParentSvg().appendChild(clone);\n const cloneRect =\n {'x': xy.x, 'y': xy.y, 'width': block.width, 'height': block.height};\n disposeUiStep(clone, cloneRect, workspace.RTL, new Date(), workspace.scale);\n}\n/**\n * Animate a cloned block and eventually dispose of it.\n * This is a class method, not an instance method since the original block has\n * been destroyed and is no longer accessible.\n *\n * @param clone SVG element to animate and dispose of.\n * @param rect Starting rect of the clone.\n * @param rtl True if RTL, false if LTR.\n * @param start Date of animation's start.\n * @param workspaceScale Scale of workspace.\n */\nfunction disposeUiStep(\n clone: Element, rect: CloneRect, rtl: boolean, start: Date,\n workspaceScale: number) {\n const ms = new Date().getTime() - start.getTime();\n const percent = ms / 150;\n if (percent > 1) {\n dom.removeNode(clone);\n } else {\n const x =\n rect.x + (rtl ? -1 : 1) * rect.width * workspaceScale / 2 * percent;\n const y = rect.y + rect.height * workspaceScale * percent;\n const scale = (1 - percent) * workspaceScale;\n clone.setAttribute(\n 'transform',\n 'translate(' + x + ',' + y + ')' +\n ' scale(' + scale + ')');\n setTimeout(disposeUiStep, 10, clone, rect, rtl, start, workspaceScale);\n }\n}\n\n/**\n * Play some UI effects (sound, ripple) after a connection has been established.\n *\n * @param block The block being connected.\n * @alias Blockly.blockAnimations.connectionUiEffect\n * @internal\n */\nexport function connectionUiEffect(block: BlockSvg) {\n const workspace = block.workspace;\n const scale = workspace.scale;\n workspace.getAudioManager().play('click');\n if (scale < 1) {\n return; // Too small to care about visual effects.\n }\n // Determine the absolute coordinates of the inferior block.\n const xy = workspace.getSvgXY(block.getSvgRoot());\n // Offset the coordinates based on the two connection types, fix scale.\n if (block.outputConnection) {\n xy.x += (block.RTL ? 3 : -3) * scale;\n xy.y += 13 * scale;\n } else if (block.previousConnection) {\n xy.x += (block.RTL ? -23 : 23) * scale;\n xy.y += 3 * scale;\n }\n const ripple = dom.createSvgElement(\n Svg.CIRCLE, {\n 'cx': xy.x,\n 'cy': xy.y,\n 'r': 0,\n 'fill': 'none',\n 'stroke': '#888',\n 'stroke-width': 10,\n },\n workspace.getParentSvg());\n // Start the animation.\n connectionUiStep(ripple, new Date(), scale);\n}\n\n/**\n * Expand a ripple around a connection.\n *\n * @param ripple Element to animate.\n * @param start Date of animation's start.\n * @param scale Scale of workspace.\n */\nfunction connectionUiStep(ripple: SVGElement, start: Date, scale: number) {\n const ms = new Date().getTime() - start.getTime();\n const percent = ms / 150;\n if (percent > 1) {\n dom.removeNode(ripple);\n } else {\n ripple.setAttribute('r', (percent * 25 * scale).toString());\n ripple.style.opacity = (1 - percent).toString();\n disconnectPid = setTimeout(connectionUiStep, 10, ripple, start, scale);\n }\n}\n\n/**\n * Play some UI effects (sound, animation) when disconnecting a block.\n *\n * @param block The block being disconnected.\n * @alias Blockly.blockAnimations.disconnectUiEffect\n * @internal\n */\nexport function disconnectUiEffect(block: BlockSvg) {\n disconnectUiStop();\n block.workspace.getAudioManager().play('disconnect');\n if (block.workspace.scale < 1) {\n return; // Too small to care about visual effects.\n }\n // Horizontal distance for bottom of block to wiggle.\n const DISPLACEMENT = 10;\n // Scale magnitude of skew to height of block.\n const height = block.getHeightWidth().height;\n let magnitude = Math.atan(DISPLACEMENT / height) / Math.PI * 180;\n if (!block.RTL) {\n magnitude *= -1;\n }\n // Start the animation.\n disconnectGroup = block.getSvgRoot();\n disconnectUiStep(disconnectGroup, magnitude, new Date());\n}\n\n/**\n * Animate a brief wiggle of a disconnected block.\n *\n * @param group SVG element to animate.\n * @param magnitude Maximum degrees skew (reversed for RTL).\n * @param start Date of animation's start.\n */\nfunction disconnectUiStep(group: SVGElement, magnitude: number, start: Date) {\n const DURATION = 200; // Milliseconds.\n const WIGGLES = 3; // Half oscillations.\n\n const ms = new Date().getTime() - start.getTime();\n const percent = ms / DURATION;\n\n let skew = '';\n if (percent <= 1) {\n const val = Math.round(\n Math.sin(percent * Math.PI * WIGGLES) * (1 - percent) * magnitude);\n skew = `skewX(${val})`;\n disconnectPid = setTimeout(disconnectUiStep, 10, group, magnitude, start);\n }\n (group as AnyDuringMigration).skew_ = skew;\n group.setAttribute(\n 'transform',\n (group as AnyDuringMigration).translate_ +\n (group as AnyDuringMigration).skew_);\n}\n\n/**\n * Stop the disconnect UI animation immediately.\n *\n * @alias Blockly.blockAnimations.disconnectUiStop\n * @internal\n */\nexport function disconnectUiStop() {\n if (disconnectGroup) {\n if (disconnectPid) {\n clearTimeout(disconnectPid);\n }\n const group = disconnectGroup;\n (group as AnyDuringMigration).skew_ = '';\n group.setAttribute('transform', (group as AnyDuringMigration).translate_);\n disconnectGroup = null;\n }\n}\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Blockly's internal clipboard for managing copy-paste.\n *\n * @namespace Blockly.clipboard\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.clipboard');\n\nimport type {CopyData, ICopyable} from './interfaces/i_copyable.js';\n\n\n/** Metadata about the object that is currently on the clipboard. */\nlet copyData: CopyData|null = null;\n\n/**\n * Copy a block or workspace comment onto the local clipboard.\n *\n * @param toCopy Block or Workspace Comment to be copied.\n * @alias Blockly.clipboard.copy\n * @internal\n */\nexport function copy(toCopy: ICopyable) {\n TEST_ONLY.copyInternal(toCopy);\n}\n\n/**\n * Private version of copy for stubbing in tests.\n */\nfunction copyInternal(toCopy: ICopyable) {\n copyData = toCopy.toCopyData();\n}\n\n/**\n * Paste a block or workspace comment on to the main workspace.\n *\n * @returns The pasted thing if the paste was successful, null otherwise.\n * @alias Blockly.clipboard.paste\n * @internal\n */\nexport function paste(): ICopyable|null {\n if (!copyData) {\n return null;\n }\n // Pasting always pastes to the main workspace, even if the copy\n // started in a flyout workspace.\n let workspace = copyData.source;\n if (workspace.isFlyout) {\n workspace = workspace.targetWorkspace!;\n }\n if (copyData.typeCounts &&\n workspace.isCapacityAvailable(copyData.typeCounts)) {\n return workspace.paste(copyData.saveInfo);\n }\n return null;\n}\n\n/**\n * Duplicate this block and its children, or a workspace comment.\n *\n * @param toDuplicate Block or Workspace Comment to be duplicated.\n * @returns The block or workspace comment that was duplicated, or null if the\n * duplication failed.\n * @alias Blockly.clipboard.duplicate\n * @internal\n */\nexport function duplicate(toDuplicate: ICopyable): ICopyable|null {\n return TEST_ONLY.duplicateInternal(toDuplicate);\n}\n\n/**\n * Private version of duplicate for stubbing in tests.\n */\nfunction duplicateInternal(toDuplicate: ICopyable): ICopyable|null {\n const oldCopyData = copyData;\n copy(toDuplicate);\n const pastedThing =\n toDuplicate.toCopyData()?.source?.paste(copyData!.saveInfo) ?? null;\n copyData = oldCopyData;\n return pastedThing;\n}\n\nexport const TEST_ONLY = {\n duplicateInternal,\n copyInternal,\n};\n","/**\n * @license\n * Copyright 2011 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Functionality for the right-click context menus.\n *\n * @namespace Blockly.ContextMenu\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.ContextMenu');\n\nimport type {Block} from './block.js';\nimport type {BlockSvg} from './block_svg.js';\nimport * as browserEvents from './browser_events.js';\nimport * as clipboard from './clipboard.js';\nimport {config} from './config.js';\nimport * as dom from './utils/dom.js';\nimport type {ContextMenuOption, LegacyContextMenuOption} from './contextmenu_registry.js';\nimport * as eventUtils from './events/utils.js';\nimport {Menu} from './menu.js';\nimport {MenuItem} from './menuitem.js';\nimport {Msg} from './msg.js';\nimport * as aria from './utils/aria.js';\nimport {Coordinate} from './utils/coordinate.js';\nimport {Rect} from './utils/rect.js';\nimport * as svgMath from './utils/svg_math.js';\nimport * as WidgetDiv from './widgetdiv.js';\nimport {WorkspaceCommentSvg} from './workspace_comment_svg.js';\nimport type {WorkspaceSvg} from './workspace_svg.js';\nimport * as Xml from './xml.js';\n\n\n/**\n * Which block is the context menu attached to?\n */\nlet currentBlock: Block|null = null;\n\nconst dummyOwner = {};\n\n/**\n * Gets the block the context menu is currently attached to.\n *\n * @returns The block the context menu is attached to.\n * @alias Blockly.ContextMenu.getCurrentBlock\n */\nexport function getCurrentBlock(): Block|null {\n return currentBlock;\n}\n\n/**\n * Sets the block the context menu is currently attached to.\n *\n * @param block The block the context menu is attached to.\n * @alias Blockly.ContextMenu.setCurrentBlock\n */\nexport function setCurrentBlock(block: Block|null) {\n currentBlock = block;\n}\n\n/**\n * Menu object.\n */\nlet menu_: Menu|null = null;\n\n/**\n * Construct the menu based on the list of options and show the menu.\n *\n * @param e Mouse event.\n * @param options Array of menu options.\n * @param rtl True if RTL, false if LTR.\n * @alias Blockly.ContextMenu.show\n */\nexport function show(\n e: Event, options: (ContextMenuOption|LegacyContextMenuOption)[],\n rtl: boolean) {\n WidgetDiv.show(dummyOwner, rtl, dispose);\n if (!options.length) {\n hide();\n return;\n }\n const menu = populate_(options, rtl);\n menu_ = menu;\n\n position_(menu, e, rtl);\n // 1ms delay is required for focusing on context menus because some other\n // mouse event is still waiting in the queue and clears focus.\n setTimeout(function() {\n menu.focus();\n }, 1);\n currentBlock = null; // May be set by Blockly.Block.\n}\n\n/**\n * Create the context menu object and populate it with the given options.\n *\n * @param options Array of menu options.\n * @param rtl True if RTL, false if LTR.\n * @returns The menu that will be shown on right click.\n */\nfunction populate_(\n options: (ContextMenuOption|LegacyContextMenuOption)[],\n rtl: boolean): Menu {\n /* Here's what one option object looks like:\n {text: 'Make It So',\n enabled: true,\n callback: Blockly.MakeItSo}\n */\n const menu = new Menu();\n menu.setRole(aria.Role.MENU);\n for (let i = 0; i < options.length; i++) {\n const option = options[i];\n const menuItem = new MenuItem(option.text);\n menuItem.setRightToLeft(rtl);\n menuItem.setRole(aria.Role.MENUITEM);\n menu.addChild(menuItem);\n menuItem.setEnabled(option.enabled);\n if (option.enabled) {\n const actionHandler = function() {\n hide();\n // If .scope does not exist on the option, then the callback will not\n // be expecting a scope parameter, so there should be no problems. Just\n // assume it is a ContextMenuOption and we'll pass undefined if it's\n // not.\n option.callback((option as ContextMenuOption).scope);\n };\n menuItem.onAction(actionHandler, {});\n }\n }\n return menu;\n}\n\n/**\n * Add the menu to the page and position it correctly.\n *\n * @param menu The menu to add and position.\n * @param e Mouse event for the right click that is making the context\n * menu appear.\n * @param rtl True if RTL, false if LTR.\n */\nfunction position_(menu: Menu, e: Event, rtl: boolean) {\n // Record windowSize and scrollOffset before adding menu.\n const viewportBBox = svgMath.getViewportBBox();\n const mouseEvent = e as MouseEvent;\n // This one is just a point, but we'll pretend that it's a rect so we can use\n // some helper functions.\n const anchorBBox = new Rect(\n mouseEvent.clientY + viewportBBox.top,\n mouseEvent.clientY + viewportBBox.top,\n mouseEvent.clientX + viewportBBox.left,\n mouseEvent.clientX + viewportBBox.left);\n\n createWidget_(menu);\n const menuSize = menu.getSize();\n\n if (rtl) {\n anchorBBox.left += menuSize.width;\n anchorBBox.right += menuSize.width;\n viewportBBox.left += menuSize.width;\n viewportBBox.right += menuSize.width;\n }\n\n WidgetDiv.positionWithAnchor(viewportBBox, anchorBBox, menuSize, rtl);\n // Calling menuDom.focus() has to wait until after the menu has been placed\n // correctly. Otherwise it will cause a page scroll to get the misplaced menu\n // in view. See issue #1329.\n menu.focus();\n}\n\n/**\n * Create and render the menu widget inside Blockly's widget div.\n *\n * @param menu The menu to add to the widget div.\n */\nfunction createWidget_(menu: Menu) {\n const div = WidgetDiv.getDiv();\n if (!div) {\n throw Error('Attempting to create a context menu when widget div is null');\n }\n const menuDom = menu.render(div);\n dom.addClass(menuDom, 'blocklyContextMenu');\n // Prevent system context menu when right-clicking a Blockly context menu.\n browserEvents.conditionalBind(\n (menuDom as EventTarget), 'contextmenu', null, haltPropagation);\n // Focus only after the initial render to avoid issue #1329.\n menu.focus();\n}\n/**\n * Halts the propagation of the event without doing anything else.\n *\n * @param e An event.\n */\nfunction haltPropagation(e: Event) {\n // This event has been handled. No need to bubble up to the document.\n e.preventDefault();\n e.stopPropagation();\n}\n\n/**\n * Hide the context menu.\n *\n * @alias Blockly.ContextMenu.hide\n */\nexport function hide() {\n WidgetDiv.hideIfOwner(dummyOwner);\n currentBlock = null;\n}\n\n/**\n * Dispose of the menu.\n *\n * @alias Blockly.ContextMenu.dispose\n */\nexport function dispose() {\n if (menu_) {\n menu_.dispose();\n menu_ = null;\n }\n}\n\n/**\n * Create a callback function that creates and configures a block,\n * then places the new block next to the original.\n *\n * @param block Original block.\n * @param xml XML representation of new block.\n * @returns Function that creates a block.\n * @alias Blockly.ContextMenu.callbackFactory\n */\nexport function callbackFactory(block: Block, xml: Element): Function {\n return () => {\n eventUtils.disable();\n let newBlock;\n try {\n newBlock = Xml.domToBlock(xml, block.workspace!) as BlockSvg;\n // Move the new block next to the old block.\n const xy = block.getRelativeToSurfaceXY();\n if (block.RTL) {\n xy.x -= config.snapRadius;\n } else {\n xy.x += config.snapRadius;\n }\n xy.y += config.snapRadius * 2;\n newBlock.moveBy(xy.x, xy.y);\n } finally {\n eventUtils.enable();\n }\n if (eventUtils.isEnabled() && !newBlock.isShadow()) {\n eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(newBlock));\n }\n newBlock.select();\n };\n}\n\n// Helper functions for creating context menu options.\n\n/**\n * Make a context menu option for deleting the current workspace comment.\n *\n * @param comment The workspace comment where the\n * right-click originated.\n * @returns A menu option,\n * containing text, enabled, and a callback.\n * @alias Blockly.ContextMenu.commentDeleteOption\n * @internal\n */\nexport function commentDeleteOption(comment: WorkspaceCommentSvg):\n LegacyContextMenuOption {\n const deleteOption = {\n text: Msg['REMOVE_COMMENT'],\n enabled: true,\n callback: function() {\n eventUtils.setGroup(true);\n comment.dispose();\n eventUtils.setGroup(false);\n },\n };\n return deleteOption;\n}\n\n/**\n * Make a context menu option for duplicating the current workspace comment.\n *\n * @param comment The workspace comment where the\n * right-click originated.\n * @returns A menu option,\n * containing text, enabled, and a callback.\n * @alias Blockly.ContextMenu.commentDuplicateOption\n * @internal\n */\nexport function commentDuplicateOption(comment: WorkspaceCommentSvg):\n LegacyContextMenuOption {\n const duplicateOption = {\n text: Msg['DUPLICATE_COMMENT'],\n enabled: true,\n callback: function() {\n clipboard.duplicate(comment);\n },\n };\n return duplicateOption;\n}\n\n/**\n * Make a context menu option for adding a comment on the workspace.\n *\n * @param ws The workspace where the right-click\n * originated.\n * @param e The right-click mouse event.\n * @returns A menu option, containing text, enabled, and a callback.\n * @suppress {strictModuleDepCheck,checkTypes} Suppress checks while workspace\n * comments are not bundled in.\n * @alias Blockly.ContextMenu.workspaceCommentOption\n * @internal\n */\nexport function workspaceCommentOption(\n ws: WorkspaceSvg, e: Event): ContextMenuOption {\n /**\n * Helper function to create and position a comment correctly based on the\n * location of the mouse event.\n */\n function addWsComment() {\n const comment = new WorkspaceCommentSvg(\n ws, Msg['WORKSPACE_COMMENT_DEFAULT_TEXT'],\n WorkspaceCommentSvg.DEFAULT_SIZE, WorkspaceCommentSvg.DEFAULT_SIZE);\n\n const injectionDiv = ws.getInjectionDiv();\n // Bounding rect coordinates are in client coordinates, meaning that they\n // are in pixels relative to the upper left corner of the visible browser\n // window. These coordinates change when you scroll the browser window.\n const boundingRect = injectionDiv.getBoundingClientRect();\n\n // The client coordinates offset by the injection div's upper left corner.\n const mouseEvent = e as MouseEvent;\n const clientOffsetPixels = new Coordinate(\n mouseEvent.clientX - boundingRect.left,\n mouseEvent.clientY - boundingRect.top);\n\n // The offset in pixels between the main workspace's origin and the upper\n // left corner of the injection div.\n const mainOffsetPixels = ws.getOriginOffsetInPixels();\n\n // The position of the new comment in pixels relative to the origin of the\n // main workspace.\n const finalOffset =\n Coordinate.difference(clientOffsetPixels, mainOffsetPixels);\n // The position of the new comment in main workspace coordinates.\n finalOffset.scale(1 / ws.scale);\n\n const commentX = finalOffset.x;\n const commentY = finalOffset.y;\n comment.moveBy(commentX, commentY);\n if (ws.rendered) {\n comment.initSvg();\n comment.render();\n comment.select();\n }\n }\n\n const wsCommentOption = {\n enabled: true,\n } as ContextMenuOption;\n wsCommentOption.text = Msg['ADD_COMMENT'];\n wsCommentOption.callback = function() {\n addWsComment();\n };\n return wsCommentOption;\n}\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility functions for positioning UI elements.\n *\n * @namespace Blockly.uiPosition\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.uiPosition');\n\nimport type {UiMetrics} from './metrics_manager.js';\nimport {Scrollbar} from './scrollbar.js';\nimport {Rect} from './utils/rect.js';\nimport type {Size} from './utils/size.js';\nimport * as toolbox from './utils/toolbox.js';\nimport type {WorkspaceSvg} from './workspace_svg.js';\n\n\n/**\n * Enum for vertical positioning.\n *\n * @alias Blockly.uiPosition.verticalPosition\n * @internal\n */\nexport enum verticalPosition {\n TOP,\n BOTTOM\n}\n\n/**\n * Enum for horizontal positioning.\n *\n * @alias Blockly.uiPosition.horizontalPosition\n * @internal\n */\nexport enum horizontalPosition {\n LEFT,\n RIGHT\n}\n\n/**\n * An object defining a horizontal and vertical positioning.\n *\n * @alias Blockly.uiPosition.Position\n * @internal\n */\nexport interface Position {\n horizontal: horizontalPosition;\n vertical: verticalPosition;\n}\n\n/**\n * Enum for bump rules to use for dealing with collisions.\n *\n * @alias Blockly.uiPosition.bumpDirection\n * @internal\n */\nexport enum bumpDirection {\n UP,\n DOWN\n}\n\n/**\n * Returns a rectangle representing reasonable position for where to place a UI\n * element of the specified size given the restraints and locations of the\n * scrollbars. This method does not take into account any already placed UI\n * elements.\n *\n * @param position The starting horizontal and vertical position.\n * @param size the size of the UI element to get a start position for.\n * @param horizontalPadding The horizontal padding to use.\n * @param verticalPadding The vertical padding to use.\n * @param metrics The workspace UI metrics.\n * @param workspace The workspace.\n * @returns The suggested start position.\n * @alias Blockly.uiPosition.getStartPositionRect\n * @internal\n */\nexport function getStartPositionRect(\n position: Position, size: Size, horizontalPadding: number,\n verticalPadding: number, metrics: UiMetrics,\n workspace: WorkspaceSvg): Rect {\n // Horizontal positioning.\n let left = 0;\n const hasVerticalScrollbar =\n workspace.scrollbar && workspace.scrollbar.canScrollVertically();\n if (position.horizontal === horizontalPosition.LEFT) {\n left = metrics.absoluteMetrics.left + horizontalPadding;\n if (hasVerticalScrollbar && workspace.RTL) {\n left += Scrollbar.scrollbarThickness;\n }\n } else { // position.horizontal === horizontalPosition.RIGHT\n left = metrics.absoluteMetrics.left + metrics.viewMetrics.width -\n size.width - horizontalPadding;\n if (hasVerticalScrollbar && !workspace.RTL) {\n left -= Scrollbar.scrollbarThickness;\n }\n }\n // Vertical positioning.\n let top = 0;\n if (position.vertical === verticalPosition.TOP) {\n top = metrics.absoluteMetrics.top + verticalPadding;\n } else { // position.vertical === verticalPosition.BOTTOM\n top = metrics.absoluteMetrics.top + metrics.viewMetrics.height -\n size.height - verticalPadding;\n if (workspace.scrollbar && workspace.scrollbar.canScrollHorizontally()) {\n // The scrollbars are always positioned on the bottom if they exist.\n top -= Scrollbar.scrollbarThickness;\n }\n }\n return new Rect(top, top + size.height, left, left + size.width);\n}\n\n/**\n * Returns a corner position that is on the opposite side of the workspace from\n * the toolbox.\n * If in horizontal orientation, defaults to the bottom corner. If in vertical\n * orientation, defaults to the right corner.\n *\n * @param workspace The workspace.\n * @param metrics The workspace metrics.\n * @returns The suggested corner position.\n * @alias Blockly.uiPosition.getCornerOppositeToolbox\n * @internal\n */\nexport function getCornerOppositeToolbox(\n workspace: WorkspaceSvg, metrics: UiMetrics): Position {\n const leftCorner =\n metrics.toolboxMetrics.position !== toolbox.Position.LEFT &&\n (!workspace.horizontalLayout || workspace.RTL);\n const topCorner = metrics.toolboxMetrics.position === toolbox.Position.BOTTOM;\n const hPosition =\n leftCorner ? horizontalPosition.LEFT : horizontalPosition.RIGHT;\n const vPosition = topCorner ? verticalPosition.TOP : verticalPosition.BOTTOM;\n return {horizontal: hPosition, vertical: vPosition};\n}\n\n/**\n * Returns a position Rect based on a starting position that is bumped\n * so that it doesn't intersect with any of the provided savedPositions. This\n * method does not check that the bumped position is still within bounds.\n *\n * @param startRect The starting position to use.\n * @param margin The margin to use between elements when bumping.\n * @param bumpDir The direction to bump if there is a collision with an existing\n * UI element.\n * @param savedPositions List of rectangles that represent the positions of UI\n * elements already placed.\n * @returns The suggested position rectangle.\n * @alias Blockly.uiPosition.bumpPositionRect\n * @internal\n */\nexport function bumpPositionRect(\n startRect: Rect, margin: number, bumpDir: bumpDirection,\n savedPositions: Rect[]): Rect {\n let top = startRect.top;\n const left = startRect.left;\n const width = startRect.right - startRect.left;\n const height = startRect.bottom - startRect.top;\n\n // Check for collision and bump if needed.\n let boundingRect = startRect;\n for (let i = 0; i < savedPositions.length; i++) {\n const otherEl = savedPositions[i];\n if (boundingRect.intersects(otherEl)) {\n if (bumpDir === bumpDirection.UP) {\n top = otherEl.top - height - margin;\n } else { // bumpDir === bumpDirection.DOWN\n top = otherEl.bottom + margin;\n }\n // Recheck other savedPositions\n boundingRect = new Rect(top, top + height, left, left + width);\n i = -1;\n }\n }\n return boundingRect;\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Registers default keyboard shortcuts.\n *\n * @namespace Blockly.ShortcutItems\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.ShortcutItems');\n\nimport {BlockSvg} from './block_svg.js';\nimport * as clipboard from './clipboard.js';\nimport * as common from './common.js';\nimport {Gesture} from './gesture.js';\nimport type {ICopyable} from './interfaces/i_copyable.js';\nimport {KeyboardShortcut, ShortcutRegistry} from './shortcut_registry.js';\nimport {KeyCodes} from './utils/keycodes.js';\nimport type {WorkspaceSvg} from './workspace_svg.js';\n\n\n/**\n * Object holding the names of the default shortcut items.\n *\n * @alias Blockly.ShortcutItems.names\n */\nexport enum names {\n ESCAPE = 'escape',\n DELETE = 'delete',\n COPY = 'copy',\n CUT = 'cut',\n PASTE = 'paste',\n UNDO = 'undo',\n REDO = 'redo'\n}\n\n/**\n * Keyboard shortcut to hide chaff on escape.\n *\n * @alias Blockly.ShortcutItems.registerEscape\n */\nexport function registerEscape() {\n const escapeAction: KeyboardShortcut = {\n name: names.ESCAPE,\n preconditionFn(workspace) {\n return !workspace.options.readOnly;\n },\n callback(workspace) {\n // AnyDuringMigration because: Property 'hideChaff' does not exist on\n // type 'Workspace'.\n (workspace as AnyDuringMigration).hideChaff();\n return true;\n },\n keyCodes: [KeyCodes.ESC],\n };\n ShortcutRegistry.registry.register(escapeAction);\n}\n\n/**\n * Keyboard shortcut to delete a block on delete or backspace\n *\n * @alias Blockly.ShortcutItems.registerDelete\n */\nexport function registerDelete() {\n const deleteShortcut: KeyboardShortcut = {\n name: names.DELETE,\n preconditionFn(workspace) {\n const selected = common.getSelected();\n return !workspace.options.readOnly && selected != null &&\n selected.isDeletable();\n },\n callback(workspace, e) {\n // Delete or backspace.\n // Stop the browser from going back to the previous page.\n // Do this first to prevent an error in the delete code from resulting in\n // data loss.\n e.preventDefault();\n // Don't delete while dragging. Jeez.\n if (Gesture.inProgress()) {\n return false;\n }\n (common.getSelected() as BlockSvg).checkAndDelete();\n return true;\n },\n keyCodes: [KeyCodes.DELETE, KeyCodes.BACKSPACE],\n };\n ShortcutRegistry.registry.register(deleteShortcut);\n}\n\n/**\n * Keyboard shortcut to copy a block on ctrl+c, cmd+c, or alt+c.\n *\n * @alias Blockly.ShortcutItems.registerCopy\n */\nexport function registerCopy() {\n const ctrlC = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.C, [KeyCodes.CTRL]);\n const altC =\n ShortcutRegistry.registry.createSerializedKey(KeyCodes.C, [KeyCodes.ALT]);\n const metaC = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.C, [KeyCodes.META]);\n\n const copyShortcut: KeyboardShortcut = {\n name: names.COPY,\n preconditionFn(workspace) {\n const selected = common.getSelected();\n return !workspace.options.readOnly && !Gesture.inProgress() &&\n selected != null && selected.isDeletable() && selected.isMovable();\n },\n callback(workspace, e) {\n // Prevent the default copy behavior, which may beep or otherwise indicate\n // an error due to the lack of a selection.\n e.preventDefault();\n // AnyDuringMigration because: Property 'hideChaff' does not exist on\n // type 'Workspace'.\n (workspace as AnyDuringMigration).hideChaff();\n clipboard.copy(common.getSelected() as ICopyable);\n return true;\n },\n keyCodes: [ctrlC, altC, metaC],\n };\n ShortcutRegistry.registry.register(copyShortcut);\n}\n\n/**\n * Keyboard shortcut to copy and delete a block on ctrl+x, cmd+x, or alt+x.\n *\n * @alias Blockly.ShortcutItems.registerCut\n */\nexport function registerCut() {\n const ctrlX = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.X, [KeyCodes.CTRL]);\n const altX =\n ShortcutRegistry.registry.createSerializedKey(KeyCodes.X, [KeyCodes.ALT]);\n const metaX = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.X, [KeyCodes.META]);\n\n const cutShortcut: KeyboardShortcut = {\n name: names.CUT,\n preconditionFn(workspace) {\n const selected = common.getSelected();\n return !workspace.options.readOnly && !Gesture.inProgress() &&\n selected != null && selected instanceof BlockSvg &&\n selected.isDeletable() && selected.isMovable() &&\n !selected.workspace!.isFlyout;\n },\n callback() {\n const selected = common.getSelected();\n if (!selected) {\n // Shouldn't happen but appeases the type system\n return false;\n }\n clipboard.copy(selected);\n (selected as BlockSvg).checkAndDelete();\n return true;\n },\n keyCodes: [ctrlX, altX, metaX],\n };\n\n ShortcutRegistry.registry.register(cutShortcut);\n}\n\n/**\n * Keyboard shortcut to paste a block on ctrl+v, cmd+v, or alt+v.\n *\n * @alias Blockly.ShortcutItems.registerPaste\n */\nexport function registerPaste() {\n const ctrlV = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.V, [KeyCodes.CTRL]);\n const altV =\n ShortcutRegistry.registry.createSerializedKey(KeyCodes.V, [KeyCodes.ALT]);\n const metaV = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.V, [KeyCodes.META]);\n\n const pasteShortcut: KeyboardShortcut = {\n name: names.PASTE,\n preconditionFn(workspace) {\n return !workspace.options.readOnly && !Gesture.inProgress();\n },\n callback() {\n return !!(clipboard.paste());\n },\n keyCodes: [ctrlV, altV, metaV],\n };\n\n ShortcutRegistry.registry.register(pasteShortcut);\n}\n\n/**\n * Keyboard shortcut to undo the previous action on ctrl+z, cmd+z, or alt+z.\n *\n * @alias Blockly.ShortcutItems.registerUndo\n */\nexport function registerUndo() {\n const ctrlZ = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.Z, [KeyCodes.CTRL]);\n const altZ =\n ShortcutRegistry.registry.createSerializedKey(KeyCodes.Z, [KeyCodes.ALT]);\n const metaZ = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.Z, [KeyCodes.META]);\n\n const undoShortcut: KeyboardShortcut = {\n name: names.UNDO,\n preconditionFn(workspace) {\n return !workspace.options.readOnly && !Gesture.inProgress();\n },\n callback(workspace) {\n // 'z' for undo 'Z' is for redo.\n (workspace as WorkspaceSvg).hideChaff();\n workspace.undo(false);\n return true;\n },\n keyCodes: [ctrlZ, altZ, metaZ],\n };\n ShortcutRegistry.registry.register(undoShortcut);\n}\n\n/**\n * Keyboard shortcut to redo the previous action on ctrl+shift+z, cmd+shift+z,\n * or alt+shift+z.\n *\n * @alias Blockly.ShortcutItems.registerRedo\n */\nexport function registerRedo() {\n const ctrlShiftZ = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.Z, [KeyCodes.SHIFT, KeyCodes.CTRL]);\n const altShiftZ = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.Z, [KeyCodes.SHIFT, KeyCodes.ALT]);\n const metaShiftZ = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.Z, [KeyCodes.SHIFT, KeyCodes.META]);\n // Ctrl-y is redo in Windows. Command-y is never valid on Macs.\n const ctrlY = ShortcutRegistry.registry.createSerializedKey(\n KeyCodes.Y, [KeyCodes.CTRL]);\n\n const redoShortcut: KeyboardShortcut = {\n name: names.REDO,\n preconditionFn(workspace) {\n return !Gesture.inProgress() && !workspace.options.readOnly;\n },\n callback(workspace) {\n // 'z' for undo 'Z' is for redo.\n (workspace as WorkspaceSvg).hideChaff();\n workspace.undo(true);\n return true;\n },\n keyCodes: [ctrlShiftZ, altShiftZ, metaShiftZ, ctrlY],\n };\n ShortcutRegistry.registry.register(redoShortcut);\n}\n\n/**\n * Registers all default keyboard shortcut item. This should be called once per\n * instance of KeyboardShortcutRegistry.\n *\n * @alias Blockly.ShortcutItems.registerDefaultShortcuts\n * @internal\n */\nexport function registerDefaultShortcuts() {\n registerEscape();\n registerDelete();\n registerCopy();\n registerCut();\n registerPaste();\n registerUndo();\n registerRedo();\n}\n\nregisterDefaultShortcuts();\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Utility functions for handling procedures.\n *\n * @namespace Blockly.Procedures\n */\nimport * as goog from '../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.Procedures');\n\n// Unused import preserved for side-effects. Remove if unneeded.\nimport './events/events_block_change.js';\n\nimport type {Block} from './block.js';\nimport type {BlockSvg} from './block_svg.js';\nimport {Blocks} from './blocks.js';\nimport * as common from './common.js';\nimport type {Abstract} from './events/events_abstract.js';\nimport type {BubbleOpen} from './events/events_bubble_open.js';\nimport * as eventUtils from './events/utils.js';\nimport {Field, UnattachedFieldError} from './field.js';\nimport {Msg} from './msg.js';\nimport {Names} from './names.js';\nimport * as utilsXml from './utils/xml.js';\nimport * as Variables from './variables.js';\nimport type {Workspace} from './workspace.js';\nimport type {WorkspaceSvg} from './workspace_svg.js';\nimport * as Xml from './xml.js';\n\n\n/**\n * String for use in the \"custom\" attribute of a category in toolbox XML.\n * This string indicates that the category should be dynamically populated with\n * procedure blocks.\n * See also Blockly.Variables.CATEGORY_NAME and\n * Blockly.VariablesDynamic.CATEGORY_NAME.\n *\n * @alias Blockly.Procedures.CATEGORY_NAME\n */\nexport const CATEGORY_NAME = 'PROCEDURE';\n\n/**\n * The default argument for a procedures_mutatorarg block.\n *\n * @alias Blockly.Procedures.DEFAULT_ARG\n */\nexport const DEFAULT_ARG = 'x';\n\nexport type ProcedureTuple = [string, string[], boolean];\n\n/**\n * Procedure block type.\n *\n * @alias Blockly.Procedures.ProcedureBlock\n */\nexport interface ProcedureBlock {\n getProcedureCall: () => string;\n renameProcedure: (p1: string, p2: string) => void;\n getProcedureDef: () => ProcedureTuple;\n}\n\n/**\n * Find all user-created procedure definitions in a workspace.\n *\n * @param root Root workspace.\n * @returns Pair of arrays, the first contains procedures without return\n * variables, the second with. Each procedure is defined by a three-element\n * list of name, parameter list, and return value boolean.\n * @alias Blockly.Procedures.allProcedures\n */\nexport function allProcedures(root: Workspace):\n [ProcedureTuple[], ProcedureTuple[]] {\n const proceduresNoReturn =\n root.getBlocksByType('procedures_defnoreturn', false)\n .map(function(block) {\n return (block as unknown as ProcedureBlock).getProcedureDef();\n });\n const proceduresReturn =\n root.getBlocksByType('procedures_defreturn', false).map(function(block) {\n return (block as unknown as ProcedureBlock).getProcedureDef();\n });\n proceduresNoReturn.sort(procTupleComparator);\n proceduresReturn.sort(procTupleComparator);\n return [proceduresNoReturn, proceduresReturn];\n}\n\n/**\n * Comparison function for case-insensitive sorting of the first element of\n * a tuple.\n *\n * @param ta First tuple.\n * @param tb Second tuple.\n * @returns -1, 0, or 1 to signify greater than, equality, or less than.\n */\nfunction procTupleComparator(ta: ProcedureTuple, tb: ProcedureTuple): number {\n return ta[0].localeCompare(tb[0], undefined, {sensitivity: 'base'});\n}\n\n/**\n * Ensure two identically-named procedures don't exist.\n * Take the proposed procedure name, and return a legal name i.e. one that\n * is not empty and doesn't collide with other procedures.\n *\n * @param name Proposed procedure name.\n * @param block Block to disambiguate.\n * @returns Non-colliding name.\n * @alias Blockly.Procedures.findLegalName\n */\nexport function findLegalName(name: string, block: Block): string {\n if (block.isInFlyout) {\n // Flyouts can have multiple procedures called 'do something'.\n return name;\n }\n name = name || Msg['UNNAMED_KEY'] || 'unnamed';\n while (!isLegalName(name, block.workspace, block)) {\n // Collision with another procedure.\n const r = name.match(/^(.*?)(\\d+)$/);\n if (!r) {\n name += '2';\n } else {\n name = r[1] + (parseInt(r[2]) + 1);\n }\n }\n return name;\n}\n/**\n * Does this procedure have a legal name? Illegal names include names of\n * procedures already defined.\n *\n * @param name The questionable name.\n * @param workspace The workspace to scan for collisions.\n * @param opt_exclude Optional block to exclude from comparisons (one doesn't\n * want to collide with oneself).\n * @returns True if the name is legal.\n */\nfunction isLegalName(\n name: string, workspace: Workspace, opt_exclude?: Block): boolean {\n return !isNameUsed(name, workspace, opt_exclude);\n}\n\n/**\n * Return if the given name is already a procedure name.\n *\n * @param name The questionable name.\n * @param workspace The workspace to scan for collisions.\n * @param opt_exclude Optional block to exclude from comparisons (one doesn't\n * want to collide with oneself).\n * @returns True if the name is used, otherwise return false.\n * @alias Blockly.Procedures.isNameUsed\n */\nexport function isNameUsed(\n name: string, workspace: Workspace, opt_exclude?: Block): boolean {\n const blocks = workspace.getAllBlocks(false);\n // Iterate through every block and check the name.\n for (let i = 0; i < blocks.length; i++) {\n if (blocks[i] === opt_exclude) {\n continue;\n }\n // Assume it is a procedure block so we can check.\n const procedureBlock = blocks[i] as unknown as ProcedureBlock;\n if (procedureBlock.getProcedureDef) {\n const procName = procedureBlock.getProcedureDef();\n if (Names.equals(procName[0], name)) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Rename a procedure. Called by the editable field.\n *\n * @param name The proposed new name.\n * @returns The accepted name.\n * @alias Blockly.Procedures.rename\n */\nexport function rename(this: Field, name: string): string {\n const block = this.getSourceBlock();\n if (!block) {\n throw new UnattachedFieldError();\n }\n\n // Strip leading and trailing whitespace. Beyond this, all names are legal.\n name = name.trim();\n\n const legalName = findLegalName(name, block);\n const oldName = this.getValue();\n if (oldName !== name && oldName !== legalName) {\n // Rename any callers.\n const blocks = block.workspace.getAllBlocks(false);\n for (let i = 0; i < blocks.length; i++) {\n // Assume it is a procedure so we can check.\n const procedureBlock = blocks[i] as unknown as ProcedureBlock;\n if (procedureBlock.renameProcedure) {\n procedureBlock.renameProcedure(oldName as string, legalName);\n }\n }\n }\n return legalName;\n}\n\n/**\n * Construct the blocks required by the flyout for the procedure category.\n *\n * @param workspace The workspace containing procedures.\n * @returns Array of XML block elements.\n * @alias Blockly.Procedures.flyoutCategory\n */\nexport function flyoutCategory(workspace: WorkspaceSvg): Element[] {\n const xmlList = [];\n if (Blocks['procedures_defnoreturn']) {\n // \n // do something\n // \n const block = utilsXml.createElement('block');\n block.setAttribute('type', 'procedures_defnoreturn');\n block.setAttribute('gap', '16');\n const nameField = utilsXml.createElement('field');\n nameField.setAttribute('name', 'NAME');\n nameField.appendChild(\n utilsXml.createTextNode(Msg['PROCEDURES_DEFNORETURN_PROCEDURE']));\n block.appendChild(nameField);\n xmlList.push(block);\n }\n if (Blocks['procedures_defreturn']) {\n // \n // do something\n // \n const block = utilsXml.createElement('block');\n block.setAttribute('type', 'procedures_defreturn');\n block.setAttribute('gap', '16');\n const nameField = utilsXml.createElement('field');\n nameField.setAttribute('name', 'NAME');\n nameField.appendChild(\n utilsXml.createTextNode(Msg['PROCEDURES_DEFRETURN_PROCEDURE']));\n block.appendChild(nameField);\n xmlList.push(block);\n }\n if (Blocks['procedures_ifreturn']) {\n // \n const block = utilsXml.createElement('block');\n block.setAttribute('type', 'procedures_ifreturn');\n block.setAttribute('gap', '16');\n xmlList.push(block);\n }\n if (xmlList.length) {\n // Add slightly larger gap between system blocks and user calls.\n xmlList[xmlList.length - 1].setAttribute('gap', '24');\n }\n\n /**\n * Add items to xmlList for each listed procedure.\n *\n * @param procedureList A list of procedures, each of which is defined by a\n * three-element list of name, parameter list, and return value boolean.\n * @param templateName The type of the block to generate.\n */\n function populateProcedures(\n procedureList: ProcedureTuple[], templateName: string) {\n for (let i = 0; i < procedureList.length; i++) {\n const name = procedureList[i][0];\n const args = procedureList[i][1];\n // \n // \n // \n // \n // \n const block = utilsXml.createElement('block');\n block.setAttribute('type', templateName);\n block.setAttribute('gap', '16');\n const mutation = utilsXml.createElement('mutation');\n mutation.setAttribute('name', name);\n block.appendChild(mutation);\n for (let j = 0; j < args.length; j++) {\n const arg = utilsXml.createElement('arg');\n arg.setAttribute('name', args[j]);\n mutation.appendChild(arg);\n }\n xmlList.push(block);\n }\n }\n\n const tuple = allProcedures(workspace);\n populateProcedures(tuple[0], 'procedures_callnoreturn');\n populateProcedures(tuple[1], 'procedures_callreturn');\n return xmlList;\n}\n\n/**\n * Updates the procedure mutator's flyout so that the arg block is not a\n * duplicate of another arg.\n *\n * @param workspace The procedure mutator's workspace. This workspace's flyout\n * is what is being updated.\n */\nfunction updateMutatorFlyout(workspace: WorkspaceSvg) {\n const usedNames = [];\n const blocks = workspace.getBlocksByType('procedures_mutatorarg', false);\n for (let i = 0, block; block = blocks[i]; i++) {\n usedNames.push(block.getFieldValue('NAME'));\n }\n\n const xmlElement = utilsXml.createElement('xml');\n const argBlock = utilsXml.createElement('block');\n argBlock.setAttribute('type', 'procedures_mutatorarg');\n const nameField = utilsXml.createElement('field');\n nameField.setAttribute('name', 'NAME');\n const argValue =\n Variables.generateUniqueNameFromOptions(DEFAULT_ARG, usedNames);\n const fieldContent = utilsXml.createTextNode(argValue);\n\n nameField.appendChild(fieldContent);\n argBlock.appendChild(nameField);\n xmlElement.appendChild(argBlock);\n\n workspace.updateToolbox(xmlElement);\n}\n\n/**\n * Listens for when a procedure mutator is opened. Then it triggers a flyout\n * update and adds a mutator change listener to the mutator workspace.\n *\n * @param e The event that triggered this listener.\n * @alias Blockly.Procedures.mutatorOpenListener\n * @internal\n */\nexport function mutatorOpenListener(e: Abstract) {\n if (e.type !== eventUtils.BUBBLE_OPEN) {\n return;\n }\n const bubbleEvent = e as BubbleOpen;\n if (!(bubbleEvent.bubbleType === 'mutator' && bubbleEvent.isOpen) ||\n !bubbleEvent.blockId) {\n return;\n }\n const workspaceId = (bubbleEvent.workspaceId);\n const block = common.getWorkspaceById(workspaceId)!.getBlockById(\n bubbleEvent.blockId) as BlockSvg;\n const type = block.type;\n if (type !== 'procedures_defnoreturn' && type !== 'procedures_defreturn') {\n return;\n }\n const workspace = block.mutator!.getWorkspace() as WorkspaceSvg;\n updateMutatorFlyout(workspace);\n workspace.addChangeListener(mutatorChangeListener);\n}\n/**\n * Listens for changes in a procedure mutator and triggers flyout updates when\n * necessary.\n *\n * @param e The event that triggered this listener.\n */\nfunction mutatorChangeListener(e: Abstract) {\n if (e.type !== eventUtils.BLOCK_CREATE &&\n e.type !== eventUtils.BLOCK_DELETE &&\n e.type !== eventUtils.BLOCK_CHANGE) {\n return;\n }\n const workspaceId = e.workspaceId as string;\n const workspace = common.getWorkspaceById(workspaceId) as WorkspaceSvg;\n updateMutatorFlyout(workspace);\n}\n\n/**\n * Find all the callers of a named procedure.\n *\n * @param name Name of procedure.\n * @param workspace The workspace to find callers in.\n * @returns Array of caller blocks.\n * @alias Blockly.Procedures.getCallers\n */\nexport function getCallers(name: string, workspace: Workspace): Block[] {\n const callers = [];\n const blocks = workspace.getAllBlocks(false);\n // Iterate through every block and check the name.\n for (let i = 0; i < blocks.length; i++) {\n // Assume it is a procedure block so we can check.\n const procedureBlock = blocks[i] as unknown as ProcedureBlock;\n if (procedureBlock.getProcedureCall) {\n const procName = procedureBlock.getProcedureCall();\n // Procedure name may be null if the block is only half-built.\n if (procName && Names.equals(procName, name)) {\n callers.push(blocks[i]);\n }\n }\n }\n return callers;\n}\n\n/**\n * When a procedure definition changes its parameters, find and edit all its\n * callers.\n *\n * @param defBlock Procedure definition block.\n * @alias Blockly.Procedures.mutateCallers\n */\nexport function mutateCallers(defBlock: Block) {\n const oldRecordUndo = eventUtils.getRecordUndo();\n const procedureBlock = defBlock as unknown as ProcedureBlock;\n const name = procedureBlock.getProcedureDef()[0];\n const xmlElement = defBlock.mutationToDom!(true);\n const callers = getCallers(name, defBlock.workspace);\n for (let i = 0, caller; caller = callers[i]; i++) {\n const oldMutationDom = caller.mutationToDom!();\n const oldMutation = oldMutationDom && Xml.domToText(oldMutationDom);\n if (caller.domToMutation) {\n caller.domToMutation(xmlElement);\n }\n const newMutationDom = caller.mutationToDom!();\n const newMutation = newMutationDom && Xml.domToText(newMutationDom);\n if (oldMutation !== newMutation) {\n // Fire a mutation on every caller block. But don't record this as an\n // undo action since it is deterministically tied to the procedure's\n // definition mutation.\n eventUtils.setRecordUndo(false);\n eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CHANGE))(\n caller, 'mutation', null, oldMutation, newMutation));\n eventUtils.setRecordUndo(oldRecordUndo);\n }\n }\n}\n\n/**\n * Find the definition block for the named procedure.\n *\n * @param name Name of procedure.\n * @param workspace The workspace to search.\n * @returns The procedure definition block, or null not found.\n * @alias Blockly.Procedures.getDefinition\n */\nexport function getDefinition(name: string, workspace: Workspace): Block|null {\n // Do not assume procedure is a top block. Some languages allow nested\n // procedures. Also do not assume it is one of the built-in blocks. Only\n // rely on getProcedureDef.\n const blocks = workspace.getAllBlocks(false);\n for (let i = 0; i < blocks.length; i++) {\n // Assume it is a procedure block so we can check.\n const procedureBlock = blocks[i] as unknown as ProcedureBlock;\n if (procedureBlock.getProcedureDef) {\n const tuple = procedureBlock.getProcedureDef();\n if (tuple && Names.equals(tuple[0], name)) {\n return blocks[i]; // Can't use procedureBlock var due to type check.\n }\n }\n }\n return null;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * An object that provides constants for rendering blocks.\n *\n * @class\n */\nimport * as goog from '../../../closure/goog/goog.js';\ngoog.declareModuleId('Blockly.blockRendering.ConstantProvider');\n\nimport {ConnectionType} from '../../connection_type.js';\nimport type {RenderedConnection} from '../../rendered_connection.js';\nimport type {BlockStyle, Theme} from '../../theme.js';\nimport * as colour from '../../utils/colour.js';\nimport * as dom from '../../utils/dom.js';\nimport * as parsing from '../../utils/parsing.js';\nimport {Svg} from '../../utils/svg.js';\nimport * as svgPaths from '../../utils/svg_paths.js';\n\n\n/** An object containing sizing and path information about outside corners. */\nexport interface OutsideCorners {\n topLeft: string;\n topRight: string;\n bottomRight: string;\n bottomLeft: string;\n rightHeight: number;\n}\n\n/** An object containing sizing and path information about inside corners. */\nexport interface InsideCorners {\n width: number;\n height: number;\n pathTop: string;\n pathBottom: string;\n}\n\n/** An object containing sizing and path information about a start hat. */\nexport interface StartHat {\n height: number;\n width: number;\n path: string;\n}\n\n/** An object containing sizing and path information about a notch. */\nexport interface Notch {\n type: number;\n width: number;\n height: number;\n pathLeft: string;\n pathRight: string;\n}\n\n/** An object containing sizing and path information about a puzzle tab. */\nexport interface PuzzleTab {\n type: number;\n width: number;\n height: number;\n pathDown: string|((p1: number) => string);\n pathUp: string|((p1: number) => string);\n}\n\n/**\n * An object containing sizing and path information about collapsed block\n * indicators.\n */\nexport interface JaggedTeeth {\n height: number;\n width: number;\n path: string;\n}\n\nexport type BaseShape = {\n type: number; width: number; height: number;\n};\n\n/** An object containing sizing and type information about a dynamic shape. */\nexport type DynamicShape = {\n type: number; width: (p1: number) => number; height: (p1: number) => number;\n isDynamic: true;\n connectionOffsetY: (p1: number) => number;\n connectionOffsetX: (p1: number) => number;\n pathDown: (p1: number) => string;\n pathUp: (p1: number) => string;\n pathRightDown: (p1: number) => string;\n pathRightUp: (p1: number) => string;\n};\n\n/** An object containing sizing and type information about a shape. */\nexport type Shape = BaseShape|DynamicShape;\n\n/**\n * Returns whether the shape is dynamic or not.\n *\n * @param shape The shape to check for dynamic-ness.\n * @returns Whether the shape is a dynamic shape or not.\n */\nexport function isDynamicShape(shape: Shape): shape is DynamicShape {\n return (shape as DynamicShape).isDynamic;\n}\n\n/**\n * An object that provides constants for rendering blocks.\n *\n * @alias Blockly.blockRendering.ConstantProvider\n */\nexport class ConstantProvider {\n /** The size of an empty spacer. */\n NO_PADDING = 0;\n\n /** The size of small padding. */\n SMALL_PADDING = 3;\n\n /** The size of medium padding. */\n MEDIUM_PADDING = 5;\n\n /** The size of medium-large padding. */\n MEDIUM_LARGE_PADDING = 8;\n\n /** The size of large padding. */\n LARGE_PADDING = 10;\n TALL_INPUT_FIELD_OFFSET_Y: number;\n\n /** The height of the puzzle tab used for input and output connections. */\n TAB_HEIGHT = 15;\n\n /**\n * The offset from the top of the block at which a puzzle tab is positioned.\n */\n TAB_OFFSET_FROM_TOP = 5;\n\n /**\n * Vertical overlap of the puzzle tab, used to make it look more like a\n * puzzle piece.\n */\n TAB_VERTICAL_OVERLAP = 2.5;\n\n /** The width of the puzzle tab used for input and output connections. */\n TAB_WIDTH = 8;\n\n /** The width of the notch used for previous and next connections. */\n NOTCH_WIDTH = 15;\n\n /** The height of the notch used for previous and next connections. */\n NOTCH_HEIGHT = 4;\n\n /** The minimum width of the block. */\n MIN_BLOCK_WIDTH = 12;\n EMPTY_BLOCK_SPACER_HEIGHT = 16;\n DUMMY_INPUT_MIN_HEIGHT: number;\n DUMMY_INPUT_SHADOW_MIN_HEIGHT: number;\n\n /** Rounded corner radius. */\n CORNER_RADIUS = 8;\n\n /**\n * Offset from the left side of a block or the inside of a statement input\n * to the left side of the notch.\n */\n NOTCH_OFFSET_LEFT = 15;\n STATEMENT_INPUT_NOTCH_OFFSET: number;\n\n STATEMENT_BOTTOM_SPACER = 0;\n STATEMENT_INPUT_PADDING_LEFT = 20;\n\n /** Vertical padding between consecutive statement inputs. */\n BETWEEN_STATEMENT_PADDING_Y = 4;\n TOP_ROW_MIN_HEIGHT: number;\n TOP_ROW_PRECEDES_STATEMENT_MIN_HEIGHT: number;\n BOTTOM_ROW_MIN_HEIGHT: number;\n BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT: number;\n\n /**\n * Whether to add a 'hat' on top of all blocks with no previous or output\n * connections. Can be overridden by 'hat' property on Theme.BlockStyle.\n */\n ADD_START_HATS = false;\n\n /** Height of the top hat. */\n START_HAT_HEIGHT = 15;\n\n /** Width of the top hat. */\n START_HAT_WIDTH = 100;\n\n SPACER_DEFAULT_HEIGHT = 15;\n\n MIN_BLOCK_HEIGHT = 24;\n\n EMPTY_INLINE_INPUT_PADDING = 14.5;\n EMPTY_INLINE_INPUT_HEIGHT: number;\n\n EXTERNAL_VALUE_INPUT_PADDING = 2;\n EMPTY_STATEMENT_INPUT_HEIGHT: number;\n START_POINT: string;\n\n /** Height of SVG path for jagged teeth at the end of collapsed blocks. */\n JAGGED_TEETH_HEIGHT = 12;\n\n /** Width of SVG path for jagged teeth at the end of collapsed blocks. */\n JAGGED_TEETH_WIDTH = 6;\n\n /** Point size of text. */\n FIELD_TEXT_FONTSIZE = 11;\n\n /** Text font weight. */\n FIELD_TEXT_FONTWEIGHT = 'normal';\n\n /** Text font family. */\n FIELD_TEXT_FONTFAMILY = 'sans-serif';\n\n /**\n * Height of text. This constant is dynamically set in\n * `setFontConstants_` to be the height of the text based on the font\n * used.\n */\n FIELD_TEXT_HEIGHT = -1; // Dynamically set.\n\n /**\n * Text baseline. This constant is dynamically set in `setFontConstants_`\n * to be the baseline of the text based on the font used.\n */\n FIELD_TEXT_BASELINE = -1; // Dynamically set.\n\n /** A field's border rect corner radius. */\n FIELD_BORDER_RECT_RADIUS = 4;\n\n /** A field's border rect default height. */\n FIELD_BORDER_RECT_HEIGHT = 16;\n\n /** A field's border rect X padding. */\n FIELD_BORDER_RECT_X_PADDING = 5;\n\n /** A field's border rect Y padding. */\n FIELD_BORDER_RECT_Y_PADDING = 3;\n\n /**\n * The backing colour of a field's border rect.\n *\n * @internal\n */\n FIELD_BORDER_RECT_COLOUR = '#fff';\n FIELD_TEXT_BASELINE_CENTER: boolean;\n FIELD_DROPDOWN_BORDER_RECT_HEIGHT: number;\n\n /**\n * Whether or not a dropdown field should add a border rect when in a shadow\n * block.\n */\n FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW = false;\n\n /**\n * Whether or not a dropdown field's div should be coloured to match the\n * block colours.\n */\n FIELD_DROPDOWN_COLOURED_DIV = false;\n\n /** Whether or not a dropdown field uses a text or SVG arrow. */\n FIELD_DROPDOWN_SVG_ARROW = false;\n FIELD_DROPDOWN_SVG_ARROW_PADDING: number;\n\n /** A dropdown field's SVG arrow size. */\n FIELD_DROPDOWN_SVG_ARROW_SIZE = 12;\n FIELD_DROPDOWN_SVG_ARROW_DATAURI: string;\n\n /**\n * Whether or not to show a box shadow around the widget div. This is only a\n * feature of full block fields.\n */\n FIELD_TEXTINPUT_BOX_SHADOW = false;\n\n /**\n * Whether or not the colour field should display its colour value on the\n * entire block.\n */\n FIELD_COLOUR_FULL_BLOCK = false;\n\n /** A colour field's default width. */\n FIELD_COLOUR_DEFAULT_WIDTH = 26;\n FIELD_COLOUR_DEFAULT_HEIGHT: number;\n FIELD_CHECKBOX_X_OFFSET: number;\n /** @internal */\n randomIdentifier: string;\n\n /**\n * The defs tag that contains all filters and patterns for this Blockly\n * instance.\n */\n private defs_: SVGElement|null = null;\n\n /**\n * The ID of the emboss filter, or the empty string if no filter is set.\n *\n * @internal\n */\n embossFilterId = '';\n\n /** The element to use for highlighting, or null if not set. */\n private embossFilter_: SVGElement|null = null;\n\n /**\n * The ID of the disabled pattern, or the empty string if no pattern is set.\n *\n * @internal\n */\n disabledPatternId = '';\n\n /**\n * The element to use for disabled blocks, or null if not set.\n */\n private disabledPattern_: SVGElement|null = null;\n\n /**\n * The ID of the debug filter, or the empty string if no pattern is set.\n */\n debugFilterId = '';\n\n /**\n * The element to use for a debug highlight, or null if not set.\n */\n private debugFilter_: SVGElement|null = null;\n\n /** The - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/google-blockly/msg/js/en.js b/google-blockly/msg/js/en.js deleted file mode 100644 index f6a0304..0000000 --- a/google-blockly/msg/js/en.js +++ /dev/null @@ -1,425 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -var Blockly = Blockly || { Msg: Object.create(null) }; - -Blockly.Msg["ADD_COMMENT"] = "Add Comment"; -Blockly.Msg["CANNOT_DELETE_VARIABLE_PROCEDURE"] = "Can't delete the variable '%1' because it's part of the definition of the function '%2'"; -Blockly.Msg["CHANGE_VALUE_TITLE"] = "Change value:"; -Blockly.Msg["CLEAN_UP"] = "Clean up Blocks"; -Blockly.Msg["COLLAPSED_WARNINGS_WARNING"] = "Collapsed blocks contain warnings."; -Blockly.Msg["COLLAPSE_ALL"] = "Collapse Blocks"; -Blockly.Msg["COLLAPSE_BLOCK"] = "Collapse Block"; -Blockly.Msg["COLOUR_BLEND_COLOUR1"] = "colour 1"; -Blockly.Msg["COLOUR_BLEND_COLOUR2"] = "colour 2"; -Blockly.Msg["COLOUR_BLEND_HELPURL"] = "https://meyerweb.com/eric/tools/color-blend/#:::rgbp"; -Blockly.Msg["COLOUR_BLEND_RATIO"] = "ratio"; -Blockly.Msg["COLOUR_BLEND_TITLE"] = "blend"; -Blockly.Msg["COLOUR_BLEND_TOOLTIP"] = "Blends two colours together with a given ratio (0.0 - 1.0)."; -Blockly.Msg["COLOUR_PICKER_HELPURL"] = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg["COLOUR_PICKER_TOOLTIP"] = "Choose a colour from the palette."; -Blockly.Msg["COLOUR_RANDOM_HELPURL"] = "http://randomcolour.com"; -Blockly.Msg["COLOUR_RANDOM_TITLE"] = "random colour"; -Blockly.Msg["COLOUR_RANDOM_TOOLTIP"] = "Choose a colour at random."; -Blockly.Msg["COLOUR_RGB_BLUE"] = "blue"; -Blockly.Msg["COLOUR_RGB_GREEN"] = "green"; -Blockly.Msg["COLOUR_RGB_HELPURL"] = "https://www.december.com/html/spec/colorpercompact.html"; -Blockly.Msg["COLOUR_RGB_RED"] = "red"; -Blockly.Msg["COLOUR_RGB_TITLE"] = "colour with"; -Blockly.Msg["COLOUR_RGB_TOOLTIP"] = "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100."; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK"] = "break out of loop"; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE"] = "continue with next iteration of loop"; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK"] = "Break out of the containing loop."; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE"] = "Skip the rest of this loop, and continue with the next iteration."; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_WARNING"] = "Warning: This block may only be used within a loop."; -Blockly.Msg["CONTROLS_FOREACH_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#for-each"; -Blockly.Msg["CONTROLS_FOREACH_TITLE"] = "for each item %1 in list %2"; -Blockly.Msg["CONTROLS_FOREACH_TOOLTIP"] = "For each item in a list, set the variable '%1' to the item, and then do some statements."; -Blockly.Msg["CONTROLS_FOR_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#count-with"; -Blockly.Msg["CONTROLS_FOR_TITLE"] = "count with %1 from %2 to %3 by %4"; -Blockly.Msg["CONTROLS_FOR_TOOLTIP"] = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; -Blockly.Msg["CONTROLS_IF_ELSEIF_TOOLTIP"] = "Add a condition to the if block."; -Blockly.Msg["CONTROLS_IF_ELSE_TOOLTIP"] = "Add a final, catch-all condition to the if block."; -Blockly.Msg["CONTROLS_IF_HELPURL"] = "https://github.com/google/blockly/wiki/IfElse"; -Blockly.Msg["CONTROLS_IF_IF_TOOLTIP"] = "Add, remove, or reorder sections to reconfigure this if block."; -Blockly.Msg["CONTROLS_IF_MSG_ELSE"] = "else"; -Blockly.Msg["CONTROLS_IF_MSG_ELSEIF"] = "else if"; -Blockly.Msg["CONTROLS_IF_MSG_IF"] = "if"; -Blockly.Msg["CONTROLS_IF_TOOLTIP_1"] = "If a value is true, then do some statements."; -Blockly.Msg["CONTROLS_IF_TOOLTIP_2"] = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; -Blockly.Msg["CONTROLS_IF_TOOLTIP_3"] = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; -Blockly.Msg["CONTROLS_IF_TOOLTIP_4"] = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; -Blockly.Msg["CONTROLS_REPEAT_HELPURL"] = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"] = "do"; -Blockly.Msg["CONTROLS_REPEAT_TITLE"] = "repeat %1 times"; -Blockly.Msg["CONTROLS_REPEAT_TOOLTIP"] = "Do some statements several times."; -Blockly.Msg["CONTROLS_WHILEUNTIL_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#repeat"; -Blockly.Msg["CONTROLS_WHILEUNTIL_OPERATOR_UNTIL"] = "repeat until"; -Blockly.Msg["CONTROLS_WHILEUNTIL_OPERATOR_WHILE"] = "repeat while"; -Blockly.Msg["CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL"] = "While a value is false, then do some statements."; -Blockly.Msg["CONTROLS_WHILEUNTIL_TOOLTIP_WHILE"] = "While a value is true, then do some statements."; -Blockly.Msg["DELETE_ALL_BLOCKS"] = "Delete all %1 blocks?"; -Blockly.Msg["DELETE_BLOCK"] = "Delete Block"; -Blockly.Msg["DELETE_VARIABLE"] = "Delete the '%1' variable"; -Blockly.Msg["DELETE_VARIABLE_CONFIRMATION"] = "Delete %1 uses of the '%2' variable?"; -Blockly.Msg["DELETE_X_BLOCKS"] = "Delete %1 Blocks"; -Blockly.Msg["DIALOG_CANCEL"] = "Cancel"; -Blockly.Msg["DIALOG_OK"] = "OK"; -Blockly.Msg["DISABLE_BLOCK"] = "Disable Block"; -Blockly.Msg["DUPLICATE_BLOCK"] = "Duplicate"; -Blockly.Msg["DUPLICATE_COMMENT"] = "Duplicate Comment"; -Blockly.Msg["ENABLE_BLOCK"] = "Enable Block"; -Blockly.Msg["EXPAND_ALL"] = "Expand Blocks"; -Blockly.Msg["EXPAND_BLOCK"] = "Expand Block"; -Blockly.Msg["EXTERNAL_INPUTS"] = "External Inputs"; -Blockly.Msg["HELP"] = "Help"; -Blockly.Msg["INLINE_INPUTS"] = "Inline Inputs"; -Blockly.Msg["LISTS_CREATE_EMPTY_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg["LISTS_CREATE_EMPTY_TITLE"] = "create empty list"; -Blockly.Msg["LISTS_CREATE_EMPTY_TOOLTIP"] = "Returns a list, of length 0, containing no data records"; -Blockly.Msg["LISTS_CREATE_WITH_CONTAINER_TITLE_ADD"] = "list"; -Blockly.Msg["LISTS_CREATE_WITH_CONTAINER_TOOLTIP"] = "Add, remove, or reorder sections to reconfigure this list block."; -Blockly.Msg["LISTS_CREATE_WITH_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg["LISTS_CREATE_WITH_INPUT_WITH"] = "create list with"; -Blockly.Msg["LISTS_CREATE_WITH_ITEM_TOOLTIP"] = "Add an item to the list."; -Blockly.Msg["LISTS_CREATE_WITH_TOOLTIP"] = "Create a list with any number of items."; -Blockly.Msg["LISTS_GET_INDEX_FIRST"] = "first"; -Blockly.Msg["LISTS_GET_INDEX_FROM_END"] = "# from end"; -Blockly.Msg["LISTS_GET_INDEX_FROM_START"] = "#"; -Blockly.Msg["LISTS_GET_INDEX_GET"] = "get"; -Blockly.Msg["LISTS_GET_INDEX_GET_REMOVE"] = "get and remove"; -Blockly.Msg["LISTS_GET_INDEX_LAST"] = "last"; -Blockly.Msg["LISTS_GET_INDEX_RANDOM"] = "random"; -Blockly.Msg["LISTS_GET_INDEX_REMOVE"] = "remove"; -Blockly.Msg["LISTS_GET_INDEX_TAIL"] = ""; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_FIRST"] = "Returns the first item in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_FROM"] = "Returns the item at the specified position in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_LAST"] = "Returns the last item in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_RANDOM"] = "Returns a random item in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST"] = "Removes and returns the first item in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM"] = "Removes and returns the item at the specified position in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST"] = "Removes and returns the last item in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM"] = "Removes and returns a random item in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST"] = "Removes the first item in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM"] = "Removes the item at the specified position in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST"] = "Removes the last item in a list."; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM"] = "Removes a random item in a list."; -Blockly.Msg["LISTS_GET_SUBLIST_END_FROM_END"] = "to # from end"; -Blockly.Msg["LISTS_GET_SUBLIST_END_FROM_START"] = "to #"; -Blockly.Msg["LISTS_GET_SUBLIST_END_LAST"] = "to last"; -Blockly.Msg["LISTS_GET_SUBLIST_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; -Blockly.Msg["LISTS_GET_SUBLIST_START_FIRST"] = "get sub-list from first"; -Blockly.Msg["LISTS_GET_SUBLIST_START_FROM_END"] = "get sub-list from # from end"; -Blockly.Msg["LISTS_GET_SUBLIST_START_FROM_START"] = "get sub-list from #"; -Blockly.Msg["LISTS_GET_SUBLIST_TAIL"] = ""; -Blockly.Msg["LISTS_GET_SUBLIST_TOOLTIP"] = "Creates a copy of the specified portion of a list."; -Blockly.Msg["LISTS_INDEX_FROM_END_TOOLTIP"] = "%1 is the last item."; -Blockly.Msg["LISTS_INDEX_FROM_START_TOOLTIP"] = "%1 is the first item."; -Blockly.Msg["LISTS_INDEX_OF_FIRST"] = "find first occurrence of item"; -Blockly.Msg["LISTS_INDEX_OF_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; -Blockly.Msg["LISTS_INDEX_OF_LAST"] = "find last occurrence of item"; -Blockly.Msg["LISTS_INDEX_OF_TOOLTIP"] = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; -Blockly.Msg["LISTS_INLIST"] = "in list"; -Blockly.Msg["LISTS_ISEMPTY_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#is-empty"; -Blockly.Msg["LISTS_ISEMPTY_TITLE"] = "%1 is empty"; -Blockly.Msg["LISTS_ISEMPTY_TOOLTIP"] = "Returns true if the list is empty."; -Blockly.Msg["LISTS_LENGTH_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#length-of"; -Blockly.Msg["LISTS_LENGTH_TITLE"] = "length of %1"; -Blockly.Msg["LISTS_LENGTH_TOOLTIP"] = "Returns the length of a list."; -Blockly.Msg["LISTS_REPEAT_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg["LISTS_REPEAT_TITLE"] = "create list with item %1 repeated %2 times"; -Blockly.Msg["LISTS_REPEAT_TOOLTIP"] = "Creates a list consisting of the given value repeated the specified number of times."; -Blockly.Msg["LISTS_REVERSE_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#reversing-a-list"; -Blockly.Msg["LISTS_REVERSE_MESSAGE0"] = "reverse %1"; -Blockly.Msg["LISTS_REVERSE_TOOLTIP"] = "Reverse a copy of a list."; -Blockly.Msg["LISTS_SET_INDEX_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#in-list--set"; -Blockly.Msg["LISTS_SET_INDEX_INPUT_TO"] = "as"; -Blockly.Msg["LISTS_SET_INDEX_INSERT"] = "insert at"; -Blockly.Msg["LISTS_SET_INDEX_SET"] = "set"; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST"] = "Inserts the item at the start of a list."; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_FROM"] = "Inserts the item at the specified position in a list."; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_LAST"] = "Append the item to the end of a list."; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM"] = "Inserts the item randomly in a list."; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_FIRST"] = "Sets the first item in a list."; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_FROM"] = "Sets the item at the specified position in a list."; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_LAST"] = "Sets the last item in a list."; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_RANDOM"] = "Sets a random item in a list."; -Blockly.Msg["LISTS_SORT_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg["LISTS_SORT_ORDER_ASCENDING"] = "ascending"; -Blockly.Msg["LISTS_SORT_ORDER_DESCENDING"] = "descending"; -Blockly.Msg["LISTS_SORT_TITLE"] = "sort %1 %2 %3"; -Blockly.Msg["LISTS_SORT_TOOLTIP"] = "Sort a copy of a list."; -Blockly.Msg["LISTS_SORT_TYPE_IGNORECASE"] = "alphabetic, ignore case"; -Blockly.Msg["LISTS_SORT_TYPE_NUMERIC"] = "numeric"; -Blockly.Msg["LISTS_SORT_TYPE_TEXT"] = "alphabetic"; -Blockly.Msg["LISTS_SPLIT_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg["LISTS_SPLIT_LIST_FROM_TEXT"] = "make list from text"; -Blockly.Msg["LISTS_SPLIT_TEXT_FROM_LIST"] = "make text from list"; -Blockly.Msg["LISTS_SPLIT_TOOLTIP_JOIN"] = "Join a list of texts into one text, separated by a delimiter."; -Blockly.Msg["LISTS_SPLIT_TOOLTIP_SPLIT"] = "Split text into a list of texts, breaking at each delimiter."; -Blockly.Msg["LISTS_SPLIT_WITH_DELIMITER"] = "with delimiter"; -Blockly.Msg["LOGIC_BOOLEAN_FALSE"] = "false"; -Blockly.Msg["LOGIC_BOOLEAN_HELPURL"] = "https://github.com/google/blockly/wiki/Logic#values"; -Blockly.Msg["LOGIC_BOOLEAN_TOOLTIP"] = "Returns either true or false."; -Blockly.Msg["LOGIC_BOOLEAN_TRUE"] = "true"; -Blockly.Msg["LOGIC_COMPARE_HELPURL"] = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_EQ"] = "Return true if both inputs equal each other."; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_GT"] = "Return true if the first input is greater than the second input."; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_GTE"] = "Return true if the first input is greater than or equal to the second input."; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_LT"] = "Return true if the first input is smaller than the second input."; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_LTE"] = "Return true if the first input is smaller than or equal to the second input."; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_NEQ"] = "Return true if both inputs are not equal to each other."; -Blockly.Msg["LOGIC_NEGATE_HELPURL"] = "https://github.com/google/blockly/wiki/Logic#not"; -Blockly.Msg["LOGIC_NEGATE_TITLE"] = "not %1"; -Blockly.Msg["LOGIC_NEGATE_TOOLTIP"] = "Returns true if the input is false. Returns false if the input is true."; -Blockly.Msg["LOGIC_NULL"] = "null"; -Blockly.Msg["LOGIC_NULL_HELPURL"] = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg["LOGIC_NULL_TOOLTIP"] = "Returns null."; -Blockly.Msg["LOGIC_OPERATION_AND"] = "and"; -Blockly.Msg["LOGIC_OPERATION_HELPURL"] = "https://github.com/google/blockly/wiki/Logic#logical-operations"; -Blockly.Msg["LOGIC_OPERATION_OR"] = "or"; -Blockly.Msg["LOGIC_OPERATION_TOOLTIP_AND"] = "Return true if both inputs are true."; -Blockly.Msg["LOGIC_OPERATION_TOOLTIP_OR"] = "Return true if at least one of the inputs is true."; -Blockly.Msg["LOGIC_TERNARY_CONDITION"] = "test"; -Blockly.Msg["LOGIC_TERNARY_HELPURL"] = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg["LOGIC_TERNARY_IF_FALSE"] = "if false"; -Blockly.Msg["LOGIC_TERNARY_IF_TRUE"] = "if true"; -Blockly.Msg["LOGIC_TERNARY_TOOLTIP"] = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; -Blockly.Msg["MATH_ADDITION_SYMBOL"] = "+"; -Blockly.Msg["MATH_ARITHMETIC_HELPURL"] = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_ADD"] = "Return the sum of the two numbers."; -Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_DIVIDE"] = "Return the quotient of the two numbers."; -Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_MINUS"] = "Return the difference of the two numbers."; -Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_MULTIPLY"] = "Return the product of the two numbers."; -Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_POWER"] = "Return the first number raised to the power of the second number."; -Blockly.Msg["MATH_ATAN2_HELPURL"] = "https://en.wikipedia.org/wiki/Atan2"; -Blockly.Msg["MATH_ATAN2_TITLE"] = "atan2 of X:%1 Y:%2"; -Blockly.Msg["MATH_ATAN2_TOOLTIP"] = "Return the arctangent of point (X, Y) in degrees from -180 to 180."; -Blockly.Msg["MATH_CHANGE_HELPURL"] = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg["MATH_CHANGE_TITLE"] = "change %1 by %2"; -Blockly.Msg["MATH_CHANGE_TOOLTIP"] = "Add a number to variable '%1'."; -Blockly.Msg["MATH_CONSTANT_HELPURL"] = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg["MATH_CONSTANT_TOOLTIP"] = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; -Blockly.Msg["MATH_CONSTRAIN_HELPURL"] = "https://en.wikipedia.org/wiki/Clamping_(graphics)"; -Blockly.Msg["MATH_CONSTRAIN_TITLE"] = "constrain %1 low %2 high %3"; -Blockly.Msg["MATH_CONSTRAIN_TOOLTIP"] = "Constrain a number to be between the specified limits (inclusive)."; -Blockly.Msg["MATH_DIVISION_SYMBOL"] = "÷"; -Blockly.Msg["MATH_IS_DIVISIBLE_BY"] = "is divisible by"; -Blockly.Msg["MATH_IS_EVEN"] = "is even"; -Blockly.Msg["MATH_IS_NEGATIVE"] = "is negative"; -Blockly.Msg["MATH_IS_ODD"] = "is odd"; -Blockly.Msg["MATH_IS_POSITIVE"] = "is positive"; -Blockly.Msg["MATH_IS_PRIME"] = "is prime"; -Blockly.Msg["MATH_IS_TOOLTIP"] = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; -Blockly.Msg["MATH_IS_WHOLE"] = "is whole"; -Blockly.Msg["MATH_MODULO_HELPURL"] = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg["MATH_MODULO_TITLE"] = "remainder of %1 ÷ %2"; -Blockly.Msg["MATH_MODULO_TOOLTIP"] = "Return the remainder from dividing the two numbers."; -Blockly.Msg["MATH_MULTIPLICATION_SYMBOL"] = "×"; -Blockly.Msg["MATH_NUMBER_HELPURL"] = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg["MATH_NUMBER_TOOLTIP"] = "A number."; -Blockly.Msg["MATH_ONLIST_HELPURL"] = ""; -Blockly.Msg["MATH_ONLIST_OPERATOR_AVERAGE"] = "average of list"; -Blockly.Msg["MATH_ONLIST_OPERATOR_MAX"] = "max of list"; -Blockly.Msg["MATH_ONLIST_OPERATOR_MEDIAN"] = "median of list"; -Blockly.Msg["MATH_ONLIST_OPERATOR_MIN"] = "min of list"; -Blockly.Msg["MATH_ONLIST_OPERATOR_MODE"] = "modes of list"; -Blockly.Msg["MATH_ONLIST_OPERATOR_RANDOM"] = "random item of list"; -Blockly.Msg["MATH_ONLIST_OPERATOR_STD_DEV"] = "standard deviation of list"; -Blockly.Msg["MATH_ONLIST_OPERATOR_SUM"] = "sum of list"; -Blockly.Msg["MATH_ONLIST_TOOLTIP_AVERAGE"] = "Return the average (arithmetic mean) of the numeric values in the list."; -Blockly.Msg["MATH_ONLIST_TOOLTIP_MAX"] = "Return the largest number in the list."; -Blockly.Msg["MATH_ONLIST_TOOLTIP_MEDIAN"] = "Return the median number in the list."; -Blockly.Msg["MATH_ONLIST_TOOLTIP_MIN"] = "Return the smallest number in the list."; -Blockly.Msg["MATH_ONLIST_TOOLTIP_MODE"] = "Return a list of the most common item(s) in the list."; -Blockly.Msg["MATH_ONLIST_TOOLTIP_RANDOM"] = "Return a random element from the list."; -Blockly.Msg["MATH_ONLIST_TOOLTIP_STD_DEV"] = "Return the standard deviation of the list."; -Blockly.Msg["MATH_ONLIST_TOOLTIP_SUM"] = "Return the sum of all the numbers in the list."; -Blockly.Msg["MATH_POWER_SYMBOL"] = "^"; -Blockly.Msg["MATH_RANDOM_FLOAT_HELPURL"] = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg["MATH_RANDOM_FLOAT_TITLE_RANDOM"] = "random fraction"; -Blockly.Msg["MATH_RANDOM_FLOAT_TOOLTIP"] = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; -Blockly.Msg["MATH_RANDOM_INT_HELPURL"] = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg["MATH_RANDOM_INT_TITLE"] = "random integer from %1 to %2"; -Blockly.Msg["MATH_RANDOM_INT_TOOLTIP"] = "Return a random integer between the two specified limits, inclusive."; -Blockly.Msg["MATH_ROUND_HELPURL"] = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg["MATH_ROUND_OPERATOR_ROUND"] = "round"; -Blockly.Msg["MATH_ROUND_OPERATOR_ROUNDDOWN"] = "round down"; -Blockly.Msg["MATH_ROUND_OPERATOR_ROUNDUP"] = "round up"; -Blockly.Msg["MATH_ROUND_TOOLTIP"] = "Round a number up or down."; -Blockly.Msg["MATH_SINGLE_HELPURL"] = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg["MATH_SINGLE_OP_ABSOLUTE"] = "absolute"; -Blockly.Msg["MATH_SINGLE_OP_ROOT"] = "square root"; -Blockly.Msg["MATH_SINGLE_TOOLTIP_ABS"] = "Return the absolute value of a number."; -Blockly.Msg["MATH_SINGLE_TOOLTIP_EXP"] = "Return e to the power of a number."; -Blockly.Msg["MATH_SINGLE_TOOLTIP_LN"] = "Return the natural logarithm of a number."; -Blockly.Msg["MATH_SINGLE_TOOLTIP_LOG10"] = "Return the base 10 logarithm of a number."; -Blockly.Msg["MATH_SINGLE_TOOLTIP_NEG"] = "Return the negation of a number."; -Blockly.Msg["MATH_SINGLE_TOOLTIP_POW10"] = "Return 10 to the power of a number."; -Blockly.Msg["MATH_SINGLE_TOOLTIP_ROOT"] = "Return the square root of a number."; -Blockly.Msg["MATH_SUBTRACTION_SYMBOL"] = "-"; -Blockly.Msg["MATH_TRIG_ACOS"] = "acos"; -Blockly.Msg["MATH_TRIG_ASIN"] = "asin"; -Blockly.Msg["MATH_TRIG_ATAN"] = "atan"; -Blockly.Msg["MATH_TRIG_COS"] = "cos"; -Blockly.Msg["MATH_TRIG_HELPURL"] = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg["MATH_TRIG_SIN"] = "sin"; -Blockly.Msg["MATH_TRIG_TAN"] = "tan"; -Blockly.Msg["MATH_TRIG_TOOLTIP_ACOS"] = "Return the arccosine of a number."; -Blockly.Msg["MATH_TRIG_TOOLTIP_ASIN"] = "Return the arcsine of a number."; -Blockly.Msg["MATH_TRIG_TOOLTIP_ATAN"] = "Return the arctangent of a number."; -Blockly.Msg["MATH_TRIG_TOOLTIP_COS"] = "Return the cosine of a degree (not radian)."; -Blockly.Msg["MATH_TRIG_TOOLTIP_SIN"] = "Return the sine of a degree (not radian)."; -Blockly.Msg["MATH_TRIG_TOOLTIP_TAN"] = "Return the tangent of a degree (not radian)."; -Blockly.Msg["NEW_COLOUR_VARIABLE"] = "Create colour variable..."; -Blockly.Msg["NEW_NUMBER_VARIABLE"] = "Create number variable..."; -Blockly.Msg["NEW_STRING_VARIABLE"] = "Create string variable..."; -Blockly.Msg["NEW_VARIABLE"] = "Create variable..."; -Blockly.Msg["NEW_VARIABLE_TITLE"] = "New variable name:"; -Blockly.Msg["NEW_VARIABLE_TYPE_TITLE"] = "New variable type:"; -Blockly.Msg["ORDINAL_NUMBER_SUFFIX"] = ""; -Blockly.Msg["PROCEDURES_ALLOW_STATEMENTS"] = "allow statements"; -Blockly.Msg["PROCEDURES_BEFORE_PARAMS"] = "with:"; -Blockly.Msg["PROCEDURES_CALLNORETURN_HELPURL"] = "https://en.wikipedia.org/wiki/Subroutine"; -Blockly.Msg["PROCEDURES_CALLNORETURN_TOOLTIP"] = "Run the user-defined function '%1'."; -Blockly.Msg["PROCEDURES_CALLRETURN_HELPURL"] = "https://en.wikipedia.org/wiki/Subroutine"; -Blockly.Msg["PROCEDURES_CALLRETURN_TOOLTIP"] = "Run the user-defined function '%1' and use its output."; -Blockly.Msg["PROCEDURES_CALL_BEFORE_PARAMS"] = "with:"; -Blockly.Msg["PROCEDURES_CREATE_DO"] = "Create '%1'"; -Blockly.Msg["PROCEDURES_DEFNORETURN_COMMENT"] = "Describe this function..."; -Blockly.Msg["PROCEDURES_DEFNORETURN_DO"] = ""; -Blockly.Msg["PROCEDURES_DEFNORETURN_HELPURL"] = "https://en.wikipedia.org/wiki/Subroutine"; -Blockly.Msg["PROCEDURES_DEFNORETURN_PROCEDURE"] = "do something"; -Blockly.Msg["PROCEDURES_DEFNORETURN_TITLE"] = "to"; -Blockly.Msg["PROCEDURES_DEFNORETURN_TOOLTIP"] = "Creates a function with no output."; -Blockly.Msg["PROCEDURES_DEFRETURN_HELPURL"] = "https://en.wikipedia.org/wiki/Subroutine"; -Blockly.Msg["PROCEDURES_DEFRETURN_RETURN"] = "return"; -Blockly.Msg["PROCEDURES_DEFRETURN_TOOLTIP"] = "Creates a function with an output."; -Blockly.Msg["PROCEDURES_DEF_DUPLICATE_WARNING"] = "Warning: This function has duplicate parameters."; -Blockly.Msg["PROCEDURES_HIGHLIGHT_DEF"] = "Highlight function definition"; -Blockly.Msg["PROCEDURES_IFRETURN_HELPURL"] = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg["PROCEDURES_IFRETURN_TOOLTIP"] = "If a value is true, then return a second value."; -Blockly.Msg["PROCEDURES_IFRETURN_WARNING"] = "Warning: This block may be used only within a function definition."; -Blockly.Msg["PROCEDURES_MUTATORARG_TITLE"] = "input name:"; -Blockly.Msg["PROCEDURES_MUTATORARG_TOOLTIP"] = "Add an input to the function."; -Blockly.Msg["PROCEDURES_MUTATORCONTAINER_TITLE"] = "inputs"; -Blockly.Msg["PROCEDURES_MUTATORCONTAINER_TOOLTIP"] = "Add, remove, or reorder inputs to this function."; -Blockly.Msg["REDO"] = "Redo"; -Blockly.Msg["REMOVE_COMMENT"] = "Remove Comment"; -Blockly.Msg["RENAME_VARIABLE"] = "Rename variable..."; -Blockly.Msg["RENAME_VARIABLE_TITLE"] = "Rename all '%1' variables to:"; -Blockly.Msg["TEXT_APPEND_HELPURL"] = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg["TEXT_APPEND_TITLE"] = "to %1 append text %2"; -Blockly.Msg["TEXT_APPEND_TOOLTIP"] = "Append some text to variable '%1'."; -Blockly.Msg["TEXT_CHANGECASE_HELPURL"] = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; -Blockly.Msg["TEXT_CHANGECASE_OPERATOR_LOWERCASE"] = "to lower case"; -Blockly.Msg["TEXT_CHANGECASE_OPERATOR_TITLECASE"] = "to Title Case"; -Blockly.Msg["TEXT_CHANGECASE_OPERATOR_UPPERCASE"] = "to UPPER CASE"; -Blockly.Msg["TEXT_CHANGECASE_TOOLTIP"] = "Return a copy of the text in a different case."; -Blockly.Msg["TEXT_CHARAT_FIRST"] = "get first letter"; -Blockly.Msg["TEXT_CHARAT_FROM_END"] = "get letter # from end"; -Blockly.Msg["TEXT_CHARAT_FROM_START"] = "get letter #"; -Blockly.Msg["TEXT_CHARAT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#extracting-text"; -Blockly.Msg["TEXT_CHARAT_LAST"] = "get last letter"; -Blockly.Msg["TEXT_CHARAT_RANDOM"] = "get random letter"; -Blockly.Msg["TEXT_CHARAT_TAIL"] = ""; -Blockly.Msg["TEXT_CHARAT_TITLE"] = "in text %1 %2"; -Blockly.Msg["TEXT_CHARAT_TOOLTIP"] = "Returns the letter at the specified position."; -Blockly.Msg["TEXT_COUNT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#counting-substrings"; -Blockly.Msg["TEXT_COUNT_MESSAGE0"] = "count %1 in %2"; -Blockly.Msg["TEXT_COUNT_TOOLTIP"] = "Count how many times some text occurs within some other text."; -Blockly.Msg["TEXT_CREATE_JOIN_ITEM_TOOLTIP"] = "Add an item to the text."; -Blockly.Msg["TEXT_CREATE_JOIN_TITLE_JOIN"] = "join"; -Blockly.Msg["TEXT_CREATE_JOIN_TOOLTIP"] = "Add, remove, or reorder sections to reconfigure this text block."; -Blockly.Msg["TEXT_GET_SUBSTRING_END_FROM_END"] = "to letter # from end"; -Blockly.Msg["TEXT_GET_SUBSTRING_END_FROM_START"] = "to letter #"; -Blockly.Msg["TEXT_GET_SUBSTRING_END_LAST"] = "to last letter"; -Blockly.Msg["TEXT_GET_SUBSTRING_HELPURL"] = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; -Blockly.Msg["TEXT_GET_SUBSTRING_INPUT_IN_TEXT"] = "in text"; -Blockly.Msg["TEXT_GET_SUBSTRING_START_FIRST"] = "get substring from first letter"; -Blockly.Msg["TEXT_GET_SUBSTRING_START_FROM_END"] = "get substring from letter # from end"; -Blockly.Msg["TEXT_GET_SUBSTRING_START_FROM_START"] = "get substring from letter #"; -Blockly.Msg["TEXT_GET_SUBSTRING_TAIL"] = ""; -Blockly.Msg["TEXT_GET_SUBSTRING_TOOLTIP"] = "Returns a specified portion of the text."; -Blockly.Msg["TEXT_INDEXOF_HELPURL"] = "https://github.com/google/blockly/wiki/Text#finding-text"; -Blockly.Msg["TEXT_INDEXOF_OPERATOR_FIRST"] = "find first occurrence of text"; -Blockly.Msg["TEXT_INDEXOF_OPERATOR_LAST"] = "find last occurrence of text"; -Blockly.Msg["TEXT_INDEXOF_TITLE"] = "in text %1 %2 %3"; -Blockly.Msg["TEXT_INDEXOF_TOOLTIP"] = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; -Blockly.Msg["TEXT_ISEMPTY_HELPURL"] = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; -Blockly.Msg["TEXT_ISEMPTY_TITLE"] = "%1 is empty"; -Blockly.Msg["TEXT_ISEMPTY_TOOLTIP"] = "Returns true if the provided text is empty."; -Blockly.Msg["TEXT_JOIN_HELPURL"] = "https://github.com/google/blockly/wiki/Text#text-creation"; -Blockly.Msg["TEXT_JOIN_TITLE_CREATEWITH"] = "create text with"; -Blockly.Msg["TEXT_JOIN_TOOLTIP"] = "Create a piece of text by joining together any number of items."; -Blockly.Msg["TEXT_LENGTH_HELPURL"] = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg["TEXT_LENGTH_TITLE"] = "length of %1"; -Blockly.Msg["TEXT_LENGTH_TOOLTIP"] = "Returns the number of letters (including spaces) in the provided text."; -Blockly.Msg["TEXT_PRINT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#printing-text"; -Blockly.Msg["TEXT_PRINT_TITLE"] = "print %1"; -Blockly.Msg["TEXT_PRINT_TOOLTIP"] = "Print the specified text, number or other value."; -Blockly.Msg["TEXT_PROMPT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; -Blockly.Msg["TEXT_PROMPT_TOOLTIP_NUMBER"] = "Prompt for user for a number."; -Blockly.Msg["TEXT_PROMPT_TOOLTIP_TEXT"] = "Prompt for user for some text."; -Blockly.Msg["TEXT_PROMPT_TYPE_NUMBER"] = "prompt for number with message"; -Blockly.Msg["TEXT_PROMPT_TYPE_TEXT"] = "prompt for text with message"; -Blockly.Msg["TEXT_REPLACE_HELPURL"] = "https://github.com/google/blockly/wiki/Text#replacing-substrings"; -Blockly.Msg["TEXT_REPLACE_MESSAGE0"] = "replace %1 with %2 in %3"; -Blockly.Msg["TEXT_REPLACE_TOOLTIP"] = "Replace all occurances of some text within some other text."; -Blockly.Msg["TEXT_REVERSE_HELPURL"] = "https://github.com/google/blockly/wiki/Text#reversing-text"; -Blockly.Msg["TEXT_REVERSE_MESSAGE0"] = "reverse %1"; -Blockly.Msg["TEXT_REVERSE_TOOLTIP"] = "Reverses the order of the characters in the text."; -Blockly.Msg["TEXT_TEXT_HELPURL"] = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg["TEXT_TEXT_TOOLTIP"] = "A letter, word, or line of text."; -Blockly.Msg["TEXT_TRIM_HELPURL"] = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; -Blockly.Msg["TEXT_TRIM_OPERATOR_BOTH"] = "trim spaces from both sides of"; -Blockly.Msg["TEXT_TRIM_OPERATOR_LEFT"] = "trim spaces from left side of"; -Blockly.Msg["TEXT_TRIM_OPERATOR_RIGHT"] = "trim spaces from right side of"; -Blockly.Msg["TEXT_TRIM_TOOLTIP"] = "Return a copy of the text with spaces removed from one or both ends."; -Blockly.Msg["TODAY"] = "Today"; -Blockly.Msg["UNDO"] = "Undo"; -Blockly.Msg["UNNAMED_KEY"] = "unnamed"; -Blockly.Msg["VARIABLES_DEFAULT_NAME"] = "item"; -Blockly.Msg["VARIABLES_GET_CREATE_SET"] = "Create 'set %1'"; -Blockly.Msg["VARIABLES_GET_HELPURL"] = "https://github.com/google/blockly/wiki/Variables#get"; -Blockly.Msg["VARIABLES_GET_TOOLTIP"] = "Returns the value of this variable."; -Blockly.Msg["VARIABLES_SET"] = "set %1 to %2"; -Blockly.Msg["VARIABLES_SET_CREATE_GET"] = "Create 'get %1'"; -Blockly.Msg["VARIABLES_SET_HELPURL"] = "https://github.com/google/blockly/wiki/Variables#set"; -Blockly.Msg["VARIABLES_SET_TOOLTIP"] = "Sets this variable to be equal to the input."; -Blockly.Msg["VARIABLE_ALREADY_EXISTS"] = "A variable named '%1' already exists."; -Blockly.Msg["VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE"] = "A variable named '%1' already exists for another type: '%2'."; -Blockly.Msg["WORKSPACE_ARIA_LABEL"] = "Blockly Workspace"; -Blockly.Msg["WORKSPACE_COMMENT_DEFAULT_TEXT"] = "Say something..."; -Blockly.Msg["CONTROLS_FOREACH_INPUT_DO"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"]; -Blockly.Msg["CONTROLS_FOR_INPUT_DO"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"]; -Blockly.Msg["CONTROLS_IF_ELSEIF_TITLE_ELSEIF"] = Blockly.Msg["CONTROLS_IF_MSG_ELSEIF"]; -Blockly.Msg["CONTROLS_IF_ELSE_TITLE_ELSE"] = Blockly.Msg["CONTROLS_IF_MSG_ELSE"]; -Blockly.Msg["CONTROLS_IF_IF_TITLE_IF"] = Blockly.Msg["CONTROLS_IF_MSG_IF"]; -Blockly.Msg["CONTROLS_IF_MSG_THEN"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"]; -Blockly.Msg["CONTROLS_WHILEUNTIL_INPUT_DO"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"]; -Blockly.Msg["LISTS_CREATE_WITH_ITEM_TITLE"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"]; -Blockly.Msg["LISTS_GET_INDEX_HELPURL"] = Blockly.Msg["LISTS_INDEX_OF_HELPURL"]; -Blockly.Msg["LISTS_GET_INDEX_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"]; -Blockly.Msg["LISTS_GET_SUBLIST_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"]; -Blockly.Msg["LISTS_INDEX_OF_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"]; -Blockly.Msg["LISTS_SET_INDEX_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"]; -Blockly.Msg["MATH_CHANGE_TITLE_ITEM"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"]; -Blockly.Msg["PROCEDURES_DEFRETURN_COMMENT"] = Blockly.Msg["PROCEDURES_DEFNORETURN_COMMENT"]; -Blockly.Msg["PROCEDURES_DEFRETURN_DO"] = Blockly.Msg["PROCEDURES_DEFNORETURN_DO"]; -Blockly.Msg["PROCEDURES_DEFRETURN_PROCEDURE"] = Blockly.Msg["PROCEDURES_DEFNORETURN_PROCEDURE"]; -Blockly.Msg["PROCEDURES_DEFRETURN_TITLE"] = Blockly.Msg["PROCEDURES_DEFNORETURN_TITLE"]; -Blockly.Msg["TEXT_APPEND_VARIABLE"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"]; -Blockly.Msg["TEXT_CREATE_JOIN_ITEM_TITLE_ITEM"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"]; - -Blockly.Msg["MATH_HUE"] = "230"; -Blockly.Msg["LOOPS_HUE"] = "120"; -Blockly.Msg["LISTS_HUE"] = "260"; -Blockly.Msg["LOGIC_HUE"] = "210"; -Blockly.Msg["VARIABLES_HUE"] = "330"; -Blockly.Msg["TEXTS_HUE"] = "160"; -Blockly.Msg["PROCEDURES_HUE"] = "290"; -Blockly.Msg["COLOUR_HUE"] = "20"; -Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310"; \ No newline at end of file diff --git a/google-blockly/msg/js/ja.js b/google-blockly/msg/js/ja.js deleted file mode 100644 index da05836..0000000 --- a/google-blockly/msg/js/ja.js +++ /dev/null @@ -1,425 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -var Blockly = Blockly || { Msg: Object.create(null) }; - -Blockly.Msg["ADD_COMMENT"] = "コメントを追加"; -Blockly.Msg["CANNOT_DELETE_VARIABLE_PROCEDURE"] = "変数 '%1' は関数 '%2' の定義の一部であるため、削除できません"; -Blockly.Msg["CHANGE_VALUE_TITLE"] = "値を変える:"; -Blockly.Msg["CLEAN_UP"] = "ブロックを整理する"; -Blockly.Msg["COLLAPSED_WARNINGS_WARNING"] = "つぶしたブロックには警告が入っています。"; -Blockly.Msg["COLLAPSE_ALL"] = "ブロックを折りたたむ"; -Blockly.Msg["COLLAPSE_BLOCK"] = "ブロックを折りたたむ"; -Blockly.Msg["COLOUR_BLEND_COLOUR1"] = "色 1"; -Blockly.Msg["COLOUR_BLEND_COLOUR2"] = "色 2"; -Blockly.Msg["COLOUR_BLEND_HELPURL"] = "https://meyerweb.com/eric/tools/color-blend/#:::rgbp"; // untranslated -Blockly.Msg["COLOUR_BLEND_RATIO"] = "比率"; -Blockly.Msg["COLOUR_BLEND_TITLE"] = "ブレンド"; -Blockly.Msg["COLOUR_BLEND_TOOLTIP"] = "2色を与えられた比率(0.0~1.0)で混ぜます。"; -Blockly.Msg["COLOUR_PICKER_HELPURL"] = "https://ja.wikipedia.org/wiki/色"; -Blockly.Msg["COLOUR_PICKER_TOOLTIP"] = "パレットから色を選んでください。"; -Blockly.Msg["COLOUR_RANDOM_HELPURL"] = "http://randomcolour.com"; // untranslated -Blockly.Msg["COLOUR_RANDOM_TITLE"] = "ランダムな色"; -Blockly.Msg["COLOUR_RANDOM_TOOLTIP"] = "ランダムに色を選ぶ。"; -Blockly.Msg["COLOUR_RGB_BLUE"] = "青"; -Blockly.Msg["COLOUR_RGB_GREEN"] = "緑"; -Blockly.Msg["COLOUR_RGB_HELPURL"] = "https://www.december.com/html/spec/colorpercompact.html"; // untranslated -Blockly.Msg["COLOUR_RGB_RED"] = "赤"; -Blockly.Msg["COLOUR_RGB_TITLE"] = "色:"; -Blockly.Msg["COLOUR_RGB_TOOLTIP"] = "赤、緑、および青の指定された量で色を作成します。すべての値は 0 ~ 100 の間でなければなりません。"; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK"] = "ループから抜け出す"; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE"] = "ループの次の反復処理を続行します"; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK"] = "入っているループから抜け出します。"; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE"] = "このループの残りの部分をスキップして、ループの繰り返しを続けます。"; -Blockly.Msg["CONTROLS_FLOW_STATEMENTS_WARNING"] = "注意: このブロックは、ループ内でのみ使用できます。"; -Blockly.Msg["CONTROLS_FOREACH_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg["CONTROLS_FOREACH_TITLE"] = "リスト%2の各項目%1について"; -Blockly.Msg["CONTROLS_FOREACH_TOOLTIP"] = "リストの各項目について、その項目を変数'%1'として、いくつかのステートメントを実行します。"; -Blockly.Msg["CONTROLS_FOR_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg["CONTROLS_FOR_TITLE"] = "%1 を %2 から %3 まで %4 ずつカウントする"; -Blockly.Msg["CONTROLS_FOR_TOOLTIP"] = "変数 '%1' が開始番号から終了番号まで指定した間隔での値をとって、指定したブロックを実行する。"; -Blockly.Msg["CONTROLS_IF_ELSEIF_TOOLTIP"] = "「もしも」のブロックに条件を追加します。"; -Blockly.Msg["CONTROLS_IF_ELSE_TOOLTIP"] = "Ifブロックに、すべてをキャッチする条件を追加。"; -Blockly.Msg["CONTROLS_IF_HELPURL"] = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg["CONTROLS_IF_IF_TOOLTIP"] = "追加、削除、またはセクションを順序変更して、ブロックをこれを再構成します。"; -Blockly.Msg["CONTROLS_IF_MSG_ELSE"] = "そうでなければ"; -Blockly.Msg["CONTROLS_IF_MSG_ELSEIF"] = "そうでなくもし"; -Blockly.Msg["CONTROLS_IF_MSG_IF"] = "もし"; -Blockly.Msg["CONTROLS_IF_TOOLTIP_1"] = "値が true の場合、ステートメントを実行します。"; -Blockly.Msg["CONTROLS_IF_TOOLTIP_2"] = "値が true の場合は、最初のステートメントのブロックを実行します。それ以外の場合は、2番目のステートメントのブロックを実行します。"; -Blockly.Msg["CONTROLS_IF_TOOLTIP_3"] = "最初の値が true の場合は、最初のステートメントのブロックを実行します。それ以外の場合で、2番目の値が true の場合は、2番目のステートメントのブロックを実行します。"; -Blockly.Msg["CONTROLS_IF_TOOLTIP_4"] = "最初の値が true の場合は、最初のステートメントのブロックを実行します。それ以外の場合で、2番目の値が true の場合は、2番目のステートメントのブロックを実行します。すべての値が true でない場合は、最後のステートメントのブロックを実行します。"; -Blockly.Msg["CONTROLS_REPEAT_HELPURL"] = "https://ja.wikipedia.org/wiki/for文"; -Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"] = "実行"; -Blockly.Msg["CONTROLS_REPEAT_TITLE"] = "%1 回繰り返す"; -Blockly.Msg["CONTROLS_REPEAT_TOOLTIP"] = "いくつかのステートメントを数回実行します。"; -Blockly.Msg["CONTROLS_WHILEUNTIL_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg["CONTROLS_WHILEUNTIL_OPERATOR_UNTIL"] = "繰り返す:終わる条件"; -Blockly.Msg["CONTROLS_WHILEUNTIL_OPERATOR_WHILE"] = "繰り返す:続ける条件"; -Blockly.Msg["CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL"] = "値がfalseの間、いくつかのステートメントを実行する。"; -Blockly.Msg["CONTROLS_WHILEUNTIL_TOOLTIP_WHILE"] = "値がtrueの間、いくつかのステートメントを実行する。"; -Blockly.Msg["DELETE_ALL_BLOCKS"] = "%1個あるすべてのブロックを削除しますか?"; -Blockly.Msg["DELETE_BLOCK"] = "ブロックを削除"; -Blockly.Msg["DELETE_VARIABLE"] = "変数 '%1' を削除"; -Blockly.Msg["DELETE_VARIABLE_CONFIRMATION"] = "%1か所で使われている変数 '%2' を削除しますか?"; -Blockly.Msg["DELETE_X_BLOCKS"] = "%1個のブロックを削除"; -Blockly.Msg["DIALOG_CANCEL"] = "キャンセル"; -Blockly.Msg["DIALOG_OK"] = "OK"; -Blockly.Msg["DISABLE_BLOCK"] = "ブロックを無効にする"; -Blockly.Msg["DUPLICATE_BLOCK"] = "複製"; -Blockly.Msg["DUPLICATE_COMMENT"] = "コメントを複製"; -Blockly.Msg["ENABLE_BLOCK"] = "ブロックを有効にする"; -Blockly.Msg["EXPAND_ALL"] = "ブロックを展開する"; -Blockly.Msg["EXPAND_BLOCK"] = "ブロックを展開する"; -Blockly.Msg["EXTERNAL_INPUTS"] = "外部入力"; -Blockly.Msg["HELP"] = "ヘルプ"; -Blockly.Msg["INLINE_INPUTS"] = "インライン入力"; -Blockly.Msg["LISTS_CREATE_EMPTY_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg["LISTS_CREATE_EMPTY_TITLE"] = "空のリストを作成"; -Blockly.Msg["LISTS_CREATE_EMPTY_TOOLTIP"] = "長さ0でデータ・レコードを含まない空のリストを返す"; -Blockly.Msg["LISTS_CREATE_WITH_CONTAINER_TITLE_ADD"] = "リスト"; -Blockly.Msg["LISTS_CREATE_WITH_CONTAINER_TOOLTIP"] = "追加、削除、またはセクションの順序変更をして、このリスト・ブロックを再構成する。"; -Blockly.Msg["LISTS_CREATE_WITH_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg["LISTS_CREATE_WITH_INPUT_WITH"] = "以下を使ってリストを作成:"; -Blockly.Msg["LISTS_CREATE_WITH_ITEM_TOOLTIP"] = "リストに項目を追加。"; -Blockly.Msg["LISTS_CREATE_WITH_TOOLTIP"] = "項目数が不定のリストを作成。"; -Blockly.Msg["LISTS_GET_INDEX_FIRST"] = "最初"; -Blockly.Msg["LISTS_GET_INDEX_FROM_END"] = "位置:後ろから"; -Blockly.Msg["LISTS_GET_INDEX_FROM_START"] = "#"; -Blockly.Msg["LISTS_GET_INDEX_GET"] = "取得"; -Blockly.Msg["LISTS_GET_INDEX_GET_REMOVE"] = "取得して削除"; -Blockly.Msg["LISTS_GET_INDEX_LAST"] = "最後"; -Blockly.Msg["LISTS_GET_INDEX_RANDOM"] = "ランダム"; -Blockly.Msg["LISTS_GET_INDEX_REMOVE"] = "削除"; -Blockly.Msg["LISTS_GET_INDEX_TAIL"] = ""; // untranslated -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_FIRST"] = "リストの最初の項目を返します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_FROM"] = "リスト内の指定位置にある項目を返します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_LAST"] = "リストの最後の項目を返します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_RANDOM"] = "ランダム アイテム リストを返します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST"] = "リスト内の最初の項目を削除し返します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM"] = "リスト内の指定位置にある項目を削除し、返します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST"] = "リスト内の最後の項目を削除したあと返します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM"] = "リストのランダムなアイテムを削除し返します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST"] = "リスト内の最初の項目を削除します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM"] = "リスト内の指定された項目を削除します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST"] = "リスト内の最後の項目を削除します。"; -Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM"] = "リスト内にあるアイテムをランダムに削除します。"; -Blockly.Msg["LISTS_GET_SUBLIST_END_FROM_END"] = "終了位置:後ろから"; -Blockly.Msg["LISTS_GET_SUBLIST_END_FROM_START"] = "終了位置:"; -Blockly.Msg["LISTS_GET_SUBLIST_END_LAST"] = "最後まで"; -Blockly.Msg["LISTS_GET_SUBLIST_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg["LISTS_GET_SUBLIST_START_FIRST"] = "最初からサブリストを取得する。"; -Blockly.Msg["LISTS_GET_SUBLIST_START_FROM_END"] = "端から #のサブリストを取得します。"; -Blockly.Msg["LISTS_GET_SUBLIST_START_FROM_START"] = "# からサブディレクトリのリストを取得します。"; -Blockly.Msg["LISTS_GET_SUBLIST_TAIL"] = ""; // untranslated -Blockly.Msg["LISTS_GET_SUBLIST_TOOLTIP"] = "リストの指定された部分のコピーを作成します。"; -Blockly.Msg["LISTS_INDEX_FROM_END_TOOLTIP"] = "%1 は、最後の項目です。"; -Blockly.Msg["LISTS_INDEX_FROM_START_TOOLTIP"] = "%1 は、最初の項目です。"; -Blockly.Msg["LISTS_INDEX_OF_FIRST"] = "で以下のアイテムの最初の出現箇所を検索:"; -Blockly.Msg["LISTS_INDEX_OF_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg["LISTS_INDEX_OF_LAST"] = "で以下のテキストの最後の出現箇所を検索:"; -Blockly.Msg["LISTS_INDEX_OF_TOOLTIP"] = "リスト項目の最初/最後に出現するインデックス位置を返します。項目が見つからない場合は %1 を返します。"; -Blockly.Msg["LISTS_INLIST"] = "リスト"; -Blockly.Msg["LISTS_ISEMPTY_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg["LISTS_ISEMPTY_TITLE"] = "%1が空"; -Blockly.Msg["LISTS_ISEMPTY_TOOLTIP"] = "リストが空の場合は、true を返します。"; -Blockly.Msg["LISTS_LENGTH_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg["LISTS_LENGTH_TITLE"] = "%1の長さ"; -Blockly.Msg["LISTS_LENGTH_TOOLTIP"] = "リストの長さを返します。"; -Blockly.Msg["LISTS_REPEAT_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg["LISTS_REPEAT_TITLE"] = "項目%1を%2回繰り返したリストを作成"; -Blockly.Msg["LISTS_REPEAT_TOOLTIP"] = "与えられた値を指定された回数繰り返してリストを作成。"; -Blockly.Msg["LISTS_REVERSE_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#reversing-a-list"; // untranslated -Blockly.Msg["LISTS_REVERSE_MESSAGE0"] = "%1を逆順に"; -Blockly.Msg["LISTS_REVERSE_TOOLTIP"] = "リストのコピーを逆順にする。"; -Blockly.Msg["LISTS_SET_INDEX_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg["LISTS_SET_INDEX_INPUT_TO"] = "値:"; -Blockly.Msg["LISTS_SET_INDEX_INSERT"] = "挿入位置:"; -Blockly.Msg["LISTS_SET_INDEX_SET"] = "セット"; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST"] = "リストの先頭に項目を挿入します。"; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_FROM"] = "リスト内の指定位置に項目を挿入します。"; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_LAST"] = "リストの末尾に項目を追加します。"; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM"] = "リストに項目をランダムに挿入します。"; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_FIRST"] = "リスト内に最初の項目を設定します。"; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_FROM"] = "リスト内の指定された位置に項目を設定します。"; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_LAST"] = "リスト内の最後の項目を設定します。"; -Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_RANDOM"] = "リスト内にランダムなアイテムを設定します。"; -Blockly.Msg["LISTS_SORT_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg["LISTS_SORT_ORDER_ASCENDING"] = "昇順"; -Blockly.Msg["LISTS_SORT_ORDER_DESCENDING"] = "降順"; -Blockly.Msg["LISTS_SORT_TITLE"] = "%1 ( %2 ) に %3 を並び替える"; -Blockly.Msg["LISTS_SORT_TOOLTIP"] = "リストのコピーを並べ替え"; -Blockly.Msg["LISTS_SORT_TYPE_IGNORECASE"] = "アルファベット順(大文字・小文字の区別無し)"; -Blockly.Msg["LISTS_SORT_TYPE_NUMERIC"] = "数値順"; -Blockly.Msg["LISTS_SORT_TYPE_TEXT"] = "アルファベット順"; -Blockly.Msg["LISTS_SPLIT_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg["LISTS_SPLIT_LIST_FROM_TEXT"] = "テキストからリストを作る"; -Blockly.Msg["LISTS_SPLIT_TEXT_FROM_LIST"] = "リストからテキストを作る"; -Blockly.Msg["LISTS_SPLIT_TOOLTIP_JOIN"] = "テキストのリストを区切り記号で区切られた一つのテキストにする"; -Blockly.Msg["LISTS_SPLIT_TOOLTIP_SPLIT"] = "テキストを区切り記号で分割したリストにする"; -Blockly.Msg["LISTS_SPLIT_WITH_DELIMITER"] = "区切り記号"; -Blockly.Msg["LOGIC_BOOLEAN_FALSE"] = "false"; -Blockly.Msg["LOGIC_BOOLEAN_HELPURL"] = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg["LOGIC_BOOLEAN_TOOLTIP"] = "true または false を返します。"; -Blockly.Msg["LOGIC_BOOLEAN_TRUE"] = "true"; -Blockly.Msg["LOGIC_COMPARE_HELPURL"] = "https://ja.wikipedia.org/wiki/不等式"; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_EQ"] = "両方の入力が互いに等しい場合に true を返します。"; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_GT"] = "最初の入力が 2 番目の入力よりも大きい場合は true を返します。"; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_GTE"] = "最初の入力が 2 番目の入力以上の場合に true を返します。"; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_LT"] = "最初の入力が 2 番目の入力よりも小さい場合は true を返します。"; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_LTE"] = "最初の入力が 2 番目の入力以下の場合に true を返します。"; -Blockly.Msg["LOGIC_COMPARE_TOOLTIP_NEQ"] = "両方の入力が互いに等しくない場合に true を返します。"; -Blockly.Msg["LOGIC_NEGATE_HELPURL"] = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg["LOGIC_NEGATE_TITLE"] = "%1ではない"; -Blockly.Msg["LOGIC_NEGATE_TOOLTIP"] = "入力が false の場合は、true を返します。入力が true の場合は false を返します。"; -Blockly.Msg["LOGIC_NULL"] = "null"; -Blockly.Msg["LOGIC_NULL_HELPURL"] = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg["LOGIC_NULL_TOOLTIP"] = "null を返します。"; -Blockly.Msg["LOGIC_OPERATION_AND"] = "かつ"; -Blockly.Msg["LOGIC_OPERATION_HELPURL"] = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg["LOGIC_OPERATION_OR"] = "または"; -Blockly.Msg["LOGIC_OPERATION_TOOLTIP_AND"] = "両方の入力が true のときに true を返します。"; -Blockly.Msg["LOGIC_OPERATION_TOOLTIP_OR"] = "少なくとも 1 つの入力が true のときに true を返します。"; -Blockly.Msg["LOGIC_TERNARY_CONDITION"] = "テスト"; -Blockly.Msg["LOGIC_TERNARY_HELPURL"] = "https://ja.wikipedia.org/wiki/%3F:"; -Blockly.Msg["LOGIC_TERNARY_IF_FALSE"] = "false の場合"; -Blockly.Msg["LOGIC_TERNARY_IF_TRUE"] = "true の場合"; -Blockly.Msg["LOGIC_TERNARY_TOOLTIP"] = "'テスト' の条件をチェックします。条件が true の場合、'true' の値を返します。それ以外の場合 'false' のを返します。"; -Blockly.Msg["MATH_ADDITION_SYMBOL"] = "+"; // untranslated -Blockly.Msg["MATH_ARITHMETIC_HELPURL"] = "https://ja.wikipedia.org/wiki/算術"; -Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_ADD"] = "2 つの数の合計を返します。"; -Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_DIVIDE"] = "2 つの数の商を返します。"; -Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_MINUS"] = "2 つの数の差を返します。"; -Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_MULTIPLY"] = "2 つの数の積を返します。"; -Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_POWER"] = "最初の数を2 番目の値で累乗した結果を返します。"; -Blockly.Msg["MATH_ATAN2_HELPURL"] = "https://ja.wikipedia.org/wiki/Atan2"; -Blockly.Msg["MATH_ATAN2_TITLE"] = "X:%1 Y:%2のatan2"; -Blockly.Msg["MATH_ATAN2_TOOLTIP"] = "アークタンジェントを用いて、点 (X, Y) の角度を -180度から 180度で返します。"; -Blockly.Msg["MATH_CHANGE_HELPURL"] = "https://ja.wikipedia.org/wiki/加法"; -Blockly.Msg["MATH_CHANGE_TITLE"] = "%1 を %2 増やす"; -Blockly.Msg["MATH_CHANGE_TOOLTIP"] = "変数'%1'に数をたす。"; -Blockly.Msg["MATH_CONSTANT_HELPURL"] = "https://ja.wikipedia.org/wiki/数学定数"; -Blockly.Msg["MATH_CONSTANT_TOOLTIP"] = "いずれかの共通の定数のを返す: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (無限)."; -Blockly.Msg["MATH_CONSTRAIN_HELPURL"] = "https://en.wikipedia.org/wiki/Clamping_(graphics)"; // untranslated -Blockly.Msg["MATH_CONSTRAIN_TITLE"] = "%1 を %2 以上 %3 以下の範囲に制限"; -Blockly.Msg["MATH_CONSTRAIN_TOOLTIP"] = "指定した上限と下限の間に値を制限する(上限と下限の値を含む)。"; -Blockly.Msg["MATH_DIVISION_SYMBOL"] = "÷"; // untranslated -Blockly.Msg["MATH_IS_DIVISIBLE_BY"] = "は以下で割りきれる:"; -Blockly.Msg["MATH_IS_EVEN"] = "は偶数"; -Blockly.Msg["MATH_IS_NEGATIVE"] = "は負"; -Blockly.Msg["MATH_IS_ODD"] = "は奇数"; -Blockly.Msg["MATH_IS_POSITIVE"] = "は正"; -Blockly.Msg["MATH_IS_PRIME"] = "は素数"; -Blockly.Msg["MATH_IS_TOOLTIP"] = "数字が、偶数、奇数、素数、整数、正数、負数、または特定の数で割り切れるかどうかを判定し、true か false を返します。"; -Blockly.Msg["MATH_IS_WHOLE"] = "は整数"; -Blockly.Msg["MATH_MODULO_HELPURL"] = "https://ja.wikipedia.org/wiki/剰余演算"; -Blockly.Msg["MATH_MODULO_TITLE"] = "%1÷%2の余り"; -Blockly.Msg["MATH_MODULO_TOOLTIP"] = "2つの数値の割り算の余りを返す。"; -Blockly.Msg["MATH_MULTIPLICATION_SYMBOL"] = "×"; // untranslated -Blockly.Msg["MATH_NUMBER_HELPURL"] = "https://ja.wikipedia.org/wiki/数"; -Blockly.Msg["MATH_NUMBER_TOOLTIP"] = "数です。"; -Blockly.Msg["MATH_ONLIST_HELPURL"] = ""; // untranslated -Blockly.Msg["MATH_ONLIST_OPERATOR_AVERAGE"] = "リストの平均"; -Blockly.Msg["MATH_ONLIST_OPERATOR_MAX"] = "リストの最大値"; -Blockly.Msg["MATH_ONLIST_OPERATOR_MEDIAN"] = "リストの中央値"; -Blockly.Msg["MATH_ONLIST_OPERATOR_MIN"] = "リストの最小値"; -Blockly.Msg["MATH_ONLIST_OPERATOR_MODE"] = "リストの最頻値"; -Blockly.Msg["MATH_ONLIST_OPERATOR_RANDOM"] = "リストからランダムに選ばれた項目"; -Blockly.Msg["MATH_ONLIST_OPERATOR_STD_DEV"] = "リストの標準偏差"; -Blockly.Msg["MATH_ONLIST_OPERATOR_SUM"] = "リストの合計"; -Blockly.Msg["MATH_ONLIST_TOOLTIP_AVERAGE"] = "リストの数値の平均 (算術平均) を返す。"; -Blockly.Msg["MATH_ONLIST_TOOLTIP_MAX"] = "リストの最大値を返す。"; -Blockly.Msg["MATH_ONLIST_TOOLTIP_MEDIAN"] = "リストの中央値を返す。"; -Blockly.Msg["MATH_ONLIST_TOOLTIP_MIN"] = "リストの最小値を返す。"; -Blockly.Msg["MATH_ONLIST_TOOLTIP_MODE"] = "リスト中の最頻項目のリストを返す。"; -Blockly.Msg["MATH_ONLIST_TOOLTIP_RANDOM"] = "リストからランダムに選ばれた要素を返す。"; -Blockly.Msg["MATH_ONLIST_TOOLTIP_STD_DEV"] = "リストの標準偏差を返す。"; -Blockly.Msg["MATH_ONLIST_TOOLTIP_SUM"] = "リストの数値を足して返す。"; -Blockly.Msg["MATH_POWER_SYMBOL"] = "^"; // untranslated -Blockly.Msg["MATH_RANDOM_FLOAT_HELPURL"] = "https://ja.wikipedia.org/wiki/疑似乱数"; -Blockly.Msg["MATH_RANDOM_FLOAT_TITLE_RANDOM"] = "1未満の正の乱数"; -Blockly.Msg["MATH_RANDOM_FLOAT_TOOLTIP"] = "0.0以上で1.0未満の範囲の乱数を返します。"; -Blockly.Msg["MATH_RANDOM_INT_HELPURL"] = "https://ja.wikipedia.org/wiki/疑似乱数"; -Blockly.Msg["MATH_RANDOM_INT_TITLE"] = "%1から%2までのランダムな整数"; -Blockly.Msg["MATH_RANDOM_INT_TOOLTIP"] = "指定された(上下限を含む)範囲のランダムな整数を返します。"; -Blockly.Msg["MATH_ROUND_HELPURL"] = "https://ja.wikipedia.org/wiki/端数処理"; -Blockly.Msg["MATH_ROUND_OPERATOR_ROUND"] = "四捨五入"; -Blockly.Msg["MATH_ROUND_OPERATOR_ROUNDDOWN"] = "切り捨て"; -Blockly.Msg["MATH_ROUND_OPERATOR_ROUNDUP"] = "切り上げ"; -Blockly.Msg["MATH_ROUND_TOOLTIP"] = "数値を切り上げるか切り捨てる"; -Blockly.Msg["MATH_SINGLE_HELPURL"] = "https://ja.wikipedia.org/wiki/平方根"; -Blockly.Msg["MATH_SINGLE_OP_ABSOLUTE"] = "絶対値"; -Blockly.Msg["MATH_SINGLE_OP_ROOT"] = "平方根"; -Blockly.Msg["MATH_SINGLE_TOOLTIP_ABS"] = "絶対値を返す。"; -Blockly.Msg["MATH_SINGLE_TOOLTIP_EXP"] = "ネイピア数eの数値乗を返す。"; -Blockly.Msg["MATH_SINGLE_TOOLTIP_LN"] = "数値の自然対数を返す。"; -Blockly.Msg["MATH_SINGLE_TOOLTIP_LOG10"] = "底が10の対数を返す。"; -Blockly.Msg["MATH_SINGLE_TOOLTIP_NEG"] = "負の数を返す。"; -Blockly.Msg["MATH_SINGLE_TOOLTIP_POW10"] = "10の数値乗を返す。"; -Blockly.Msg["MATH_SINGLE_TOOLTIP_ROOT"] = "平方根を返す。"; -Blockly.Msg["MATH_SUBTRACTION_SYMBOL"] = "-"; // untranslated -Blockly.Msg["MATH_TRIG_ACOS"] = "acos"; -Blockly.Msg["MATH_TRIG_ASIN"] = "asin"; -Blockly.Msg["MATH_TRIG_ATAN"] = "atan"; -Blockly.Msg["MATH_TRIG_COS"] = "cos"; -Blockly.Msg["MATH_TRIG_HELPURL"] = "https://ja.wikipedia.org/wiki/三角関数"; -Blockly.Msg["MATH_TRIG_SIN"] = "sin"; -Blockly.Msg["MATH_TRIG_TAN"] = "tan"; -Blockly.Msg["MATH_TRIG_TOOLTIP_ACOS"] = "アークコサイン(arccosin)を返す。"; -Blockly.Msg["MATH_TRIG_TOOLTIP_ASIN"] = "アークサイン(arcsin)を返す。"; -Blockly.Msg["MATH_TRIG_TOOLTIP_ATAN"] = "アークタンジェント(arctan)を返す。"; -Blockly.Msg["MATH_TRIG_TOOLTIP_COS"] = "(ラジアンではなく)度数の余弦(cosin)を返す。"; -Blockly.Msg["MATH_TRIG_TOOLTIP_SIN"] = "(ラジアンではなく)度数の正弦(sin)を返す。"; -Blockly.Msg["MATH_TRIG_TOOLTIP_TAN"] = "(ラジアンではなく)度数の正接(tan)を返す。"; -Blockly.Msg["NEW_COLOUR_VARIABLE"] = "色の変数を作る..."; -Blockly.Msg["NEW_NUMBER_VARIABLE"] = "数の変数を作る..."; -Blockly.Msg["NEW_STRING_VARIABLE"] = "文字列の変数を作る..."; -Blockly.Msg["NEW_VARIABLE"] = "変数の作成…"; -Blockly.Msg["NEW_VARIABLE_TITLE"] = "新しい変数の名前:"; -Blockly.Msg["NEW_VARIABLE_TYPE_TITLE"] = "新しい変数の型:"; -Blockly.Msg["ORDINAL_NUMBER_SUFFIX"] = ""; // untranslated -Blockly.Msg["PROCEDURES_ALLOW_STATEMENTS"] = "ステートメントを許可"; -Blockly.Msg["PROCEDURES_BEFORE_PARAMS"] = "引数:"; -Blockly.Msg["PROCEDURES_CALLNORETURN_HELPURL"] = "https://ja.wikipedia.org/wiki/サブルーチン"; -Blockly.Msg["PROCEDURES_CALLNORETURN_TOOLTIP"] = "ユーザー定義関数 '%1' を実行します。"; -Blockly.Msg["PROCEDURES_CALLRETURN_HELPURL"] = "https://ja.wikipedia.org/wiki/サブルーチン"; -Blockly.Msg["PROCEDURES_CALLRETURN_TOOLTIP"] = "ユーザー定義関数 '%1' を実行し、その出力を使用します。"; -Blockly.Msg["PROCEDURES_CALL_BEFORE_PARAMS"] = "引数:"; -Blockly.Msg["PROCEDURES_CREATE_DO"] = "'%1' を作成"; -Blockly.Msg["PROCEDURES_DEFNORETURN_COMMENT"] = "この関数の説明…"; -Blockly.Msg["PROCEDURES_DEFNORETURN_DO"] = ""; // untranslated -Blockly.Msg["PROCEDURES_DEFNORETURN_HELPURL"] = "https://en.wikipedia.org/wiki/Subroutine"; // untranslated -Blockly.Msg["PROCEDURES_DEFNORETURN_PROCEDURE"] = "何かする"; -Blockly.Msg["PROCEDURES_DEFNORETURN_TITLE"] = "関数"; -Blockly.Msg["PROCEDURES_DEFNORETURN_TOOLTIP"] = "出力なしの関数を作成します。"; -Blockly.Msg["PROCEDURES_DEFRETURN_HELPURL"] = "https://en.wikipedia.org/wiki/Subroutine"; // untranslated -Blockly.Msg["PROCEDURES_DEFRETURN_RETURN"] = "返す"; -Blockly.Msg["PROCEDURES_DEFRETURN_TOOLTIP"] = "一つの出力を持つ関数を作成します。"; -Blockly.Msg["PROCEDURES_DEF_DUPLICATE_WARNING"] = "警告: この関数には重複するパラメーターがあります。"; -Blockly.Msg["PROCEDURES_HIGHLIGHT_DEF"] = "関数の内容を強調表示します。"; -Blockly.Msg["PROCEDURES_IFRETURN_HELPURL"] = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg["PROCEDURES_IFRETURN_TOOLTIP"] = "1番目の値が true の場合、2番目の値を返します。"; -Blockly.Msg["PROCEDURES_IFRETURN_WARNING"] = "警告: このブロックは、関数定義内でのみ使用できます。"; -Blockly.Msg["PROCEDURES_MUTATORARG_TITLE"] = "入力名:"; -Blockly.Msg["PROCEDURES_MUTATORARG_TOOLTIP"] = "関数への入力の追加。"; -Blockly.Msg["PROCEDURES_MUTATORCONTAINER_TITLE"] = "入力"; -Blockly.Msg["PROCEDURES_MUTATORCONTAINER_TOOLTIP"] = "この関数への入力の追加、削除、順番変更。"; -Blockly.Msg["REDO"] = "やり直す"; -Blockly.Msg["REMOVE_COMMENT"] = "コメントを削除"; -Blockly.Msg["RENAME_VARIABLE"] = "変数の名前を変える…"; -Blockly.Msg["RENAME_VARIABLE_TITLE"] = "選択した%1個すべての変数の名前を変える:"; -Blockly.Msg["TEXT_APPEND_HELPURL"] = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg["TEXT_APPEND_TITLE"] = "項目 %1 へテキストを追加 %2"; -Blockly.Msg["TEXT_APPEND_TOOLTIP"] = "変数 '%1' にテキストを追加。"; -Blockly.Msg["TEXT_CHANGECASE_HELPURL"] = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg["TEXT_CHANGECASE_OPERATOR_LOWERCASE"] = "小文字に"; -Blockly.Msg["TEXT_CHANGECASE_OPERATOR_TITLECASE"] = "タイトル ケースに"; -Blockly.Msg["TEXT_CHANGECASE_OPERATOR_UPPERCASE"] = "大文字に"; -Blockly.Msg["TEXT_CHANGECASE_TOOLTIP"] = "別のケースに、テキストのコピーを返します。"; -Blockly.Msg["TEXT_CHARAT_FIRST"] = "最初の文字を得る"; -Blockly.Msg["TEXT_CHARAT_FROM_END"] = "の、後ろから以下の数字番目の文字:"; -Blockly.Msg["TEXT_CHARAT_FROM_START"] = "の、以下の数字番目の文字:"; -Blockly.Msg["TEXT_CHARAT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg["TEXT_CHARAT_LAST"] = "最後の文字を得る"; -Blockly.Msg["TEXT_CHARAT_RANDOM"] = "ランダムな文字を得る"; -Blockly.Msg["TEXT_CHARAT_TAIL"] = ""; // untranslated -Blockly.Msg["TEXT_CHARAT_TITLE"] = "テキスト %1 %2"; -Blockly.Msg["TEXT_CHARAT_TOOLTIP"] = "指定された位置に文字を返します。"; -Blockly.Msg["TEXT_COUNT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#counting-substrings"; // untranslated -Blockly.Msg["TEXT_COUNT_MESSAGE0"] = "%2に含まれる%1の数を数える"; -Blockly.Msg["TEXT_COUNT_TOOLTIP"] = "とある文が別の文のなかに使われた回数を数える。"; -Blockly.Msg["TEXT_CREATE_JOIN_ITEM_TOOLTIP"] = "テキストへ項目を追加。"; -Blockly.Msg["TEXT_CREATE_JOIN_TITLE_JOIN"] = "結合"; -Blockly.Msg["TEXT_CREATE_JOIN_TOOLTIP"] = "セクションを追加、削除、または順序変更して、ブロックを再構成。"; -Blockly.Msg["TEXT_GET_SUBSTRING_END_FROM_END"] = "終了位置:後ろから"; -Blockly.Msg["TEXT_GET_SUBSTRING_END_FROM_START"] = "終了位置:"; -Blockly.Msg["TEXT_GET_SUBSTRING_END_LAST"] = "最後の文字"; -Blockly.Msg["TEXT_GET_SUBSTRING_HELPURL"] = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg["TEXT_GET_SUBSTRING_INPUT_IN_TEXT"] = "テキスト"; -Blockly.Msg["TEXT_GET_SUBSTRING_START_FIRST"] = "の部分文字列を取得;最初から"; -Blockly.Msg["TEXT_GET_SUBSTRING_START_FROM_END"] = "の部分文字列を取得;開始位置:後ろから"; -Blockly.Msg["TEXT_GET_SUBSTRING_START_FROM_START"] = "の部分文字列を取得;開始位置:"; -Blockly.Msg["TEXT_GET_SUBSTRING_TAIL"] = ""; // untranslated -Blockly.Msg["TEXT_GET_SUBSTRING_TOOLTIP"] = "テキストの指定部分を返します。"; -Blockly.Msg["TEXT_INDEXOF_HELPURL"] = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg["TEXT_INDEXOF_OPERATOR_FIRST"] = "で以下のテキストの最初の出現箇所を検索:"; -Blockly.Msg["TEXT_INDEXOF_OPERATOR_LAST"] = "で以下のテキストの最後の出現箇所を検索:"; -Blockly.Msg["TEXT_INDEXOF_TITLE"] = "テキスト %1 %2 %3"; -Blockly.Msg["TEXT_INDEXOF_TOOLTIP"] = "二番目のテキストの中で一番目のテキストが最初/最後に出現したインデックスを返す。テキストが見つからない場合は%1を返す。"; -Blockly.Msg["TEXT_ISEMPTY_HELPURL"] = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg["TEXT_ISEMPTY_TITLE"] = "%1が空"; -Blockly.Msg["TEXT_ISEMPTY_TOOLTIP"] = "与えられたテキストが空の場合は true を返す。"; -Blockly.Msg["TEXT_JOIN_HELPURL"] = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg["TEXT_JOIN_TITLE_CREATEWITH"] = "テキストを結合して作成:"; -Blockly.Msg["TEXT_JOIN_TOOLTIP"] = "任意の数の項目一部を一緒に接合してテキストを作成。"; -Blockly.Msg["TEXT_LENGTH_HELPURL"] = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg["TEXT_LENGTH_TITLE"] = "%1の長さ"; -Blockly.Msg["TEXT_LENGTH_TOOLTIP"] = "与えられたテキストの(スペースを含む)文字数を返す。"; -Blockly.Msg["TEXT_PRINT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg["TEXT_PRINT_TITLE"] = "%1 を表示"; -Blockly.Msg["TEXT_PRINT_TOOLTIP"] = "指定したテキスト、番号または他の値を印刷します。"; -Blockly.Msg["TEXT_PROMPT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg["TEXT_PROMPT_TOOLTIP_NUMBER"] = "ユーザーに数値のインプットを求める。"; -Blockly.Msg["TEXT_PROMPT_TOOLTIP_TEXT"] = "ユーザーにテキスト入力を求める。"; -Blockly.Msg["TEXT_PROMPT_TYPE_NUMBER"] = "メッセージで番号の入力を求める"; -Blockly.Msg["TEXT_PROMPT_TYPE_TEXT"] = "メッセージでテキスト入力を求める"; -Blockly.Msg["TEXT_REPLACE_HELPURL"] = "https://github.com/google/blockly/wiki/Text#replacing-substrings"; // untranslated -Blockly.Msg["TEXT_REPLACE_MESSAGE0"] = "%3に含まれる%1を%2に置換"; -Blockly.Msg["TEXT_REPLACE_TOOLTIP"] = "文に含まれるキーワードを置換する。"; -Blockly.Msg["TEXT_REVERSE_HELPURL"] = "https://github.com/google/blockly/wiki/Text#reversing-text"; // untranslated -Blockly.Msg["TEXT_REVERSE_MESSAGE0"] = "%1を逆順に"; -Blockly.Msg["TEXT_REVERSE_TOOLTIP"] = "文の文字を逆順にする。"; -Blockly.Msg["TEXT_TEXT_HELPURL"] = "https://ja.wikipedia.org/wiki/文字列"; -Blockly.Msg["TEXT_TEXT_TOOLTIP"] = "文字、単語、または行のテキスト。"; -Blockly.Msg["TEXT_TRIM_HELPURL"] = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg["TEXT_TRIM_OPERATOR_BOTH"] = "両端のスペースを取り除く"; -Blockly.Msg["TEXT_TRIM_OPERATOR_LEFT"] = "左端のスペースを取り除く"; -Blockly.Msg["TEXT_TRIM_OPERATOR_RIGHT"] = "右端のスペースを取り除く"; -Blockly.Msg["TEXT_TRIM_TOOLTIP"] = "スペースを 1 つまたは両方の端から削除したのち、テキストのコピーを返します。"; -Blockly.Msg["TODAY"] = "今日"; -Blockly.Msg["UNDO"] = "取り消す"; -Blockly.Msg["UNNAMED_KEY"] = "名前なし"; -Blockly.Msg["VARIABLES_DEFAULT_NAME"] = "項目"; -Blockly.Msg["VARIABLES_GET_CREATE_SET"] = "'セット%1を作成します。"; -Blockly.Msg["VARIABLES_GET_HELPURL"] = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg["VARIABLES_GET_TOOLTIP"] = "この変数の値を返します。"; -Blockly.Msg["VARIABLES_SET"] = "%1 に %2 をセット"; -Blockly.Msg["VARIABLES_SET_CREATE_GET"] = "'%1 を取得' を作成します。"; -Blockly.Msg["VARIABLES_SET_HELPURL"] = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg["VARIABLES_SET_TOOLTIP"] = "この入力を変数と等しくなるように設定します。"; -Blockly.Msg["VARIABLE_ALREADY_EXISTS"] = "変数名 '%1' は既に存在しています。"; -Blockly.Msg["VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE"] = "'%2' 型の '%1' という名前の変数が既に存在します。"; -Blockly.Msg["WORKSPACE_ARIA_LABEL"] = "Blocklyワークスペース"; -Blockly.Msg["WORKSPACE_COMMENT_DEFAULT_TEXT"] = "ここへ入力"; -Blockly.Msg["CONTROLS_FOREACH_INPUT_DO"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"]; -Blockly.Msg["CONTROLS_FOR_INPUT_DO"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"]; -Blockly.Msg["CONTROLS_IF_ELSEIF_TITLE_ELSEIF"] = Blockly.Msg["CONTROLS_IF_MSG_ELSEIF"]; -Blockly.Msg["CONTROLS_IF_ELSE_TITLE_ELSE"] = Blockly.Msg["CONTROLS_IF_MSG_ELSE"]; -Blockly.Msg["CONTROLS_IF_IF_TITLE_IF"] = Blockly.Msg["CONTROLS_IF_MSG_IF"]; -Blockly.Msg["CONTROLS_IF_MSG_THEN"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"]; -Blockly.Msg["CONTROLS_WHILEUNTIL_INPUT_DO"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"]; -Blockly.Msg["LISTS_CREATE_WITH_ITEM_TITLE"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"]; -Blockly.Msg["LISTS_GET_INDEX_HELPURL"] = Blockly.Msg["LISTS_INDEX_OF_HELPURL"]; -Blockly.Msg["LISTS_GET_INDEX_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"]; -Blockly.Msg["LISTS_GET_SUBLIST_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"]; -Blockly.Msg["LISTS_INDEX_OF_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"]; -Blockly.Msg["LISTS_SET_INDEX_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"]; -Blockly.Msg["MATH_CHANGE_TITLE_ITEM"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"]; -Blockly.Msg["PROCEDURES_DEFRETURN_COMMENT"] = Blockly.Msg["PROCEDURES_DEFNORETURN_COMMENT"]; -Blockly.Msg["PROCEDURES_DEFRETURN_DO"] = Blockly.Msg["PROCEDURES_DEFNORETURN_DO"]; -Blockly.Msg["PROCEDURES_DEFRETURN_PROCEDURE"] = Blockly.Msg["PROCEDURES_DEFNORETURN_PROCEDURE"]; -Blockly.Msg["PROCEDURES_DEFRETURN_TITLE"] = Blockly.Msg["PROCEDURES_DEFNORETURN_TITLE"]; -Blockly.Msg["TEXT_APPEND_VARIABLE"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"]; -Blockly.Msg["TEXT_CREATE_JOIN_ITEM_TITLE_ITEM"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"]; - -Blockly.Msg["MATH_HUE"] = "230"; -Blockly.Msg["LOOPS_HUE"] = "120"; -Blockly.Msg["LISTS_HUE"] = "260"; -Blockly.Msg["LOGIC_HUE"] = "210"; -Blockly.Msg["VARIABLES_HUE"] = "330"; -Blockly.Msg["TEXTS_HUE"] = "160"; -Blockly.Msg["PROCEDURES_HUE"] = "290"; -Blockly.Msg["COLOUR_HUE"] = "20"; -Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310"; \ No newline at end of file diff --git a/google-blockly/msg/json/en.json b/google-blockly/msg/json/en.json deleted file mode 100644 index 3830c17..0000000 --- a/google-blockly/msg/json/en.json +++ /dev/null @@ -1,397 +0,0 @@ -{ - "@metadata": { - "author": "Ellen Spertus ", - "lastupdated": "2021-07-01 14:44:40.033432", - "locale": "en", - "messagedocumentation" : "qqq" - }, - "VARIABLES_DEFAULT_NAME": "item", - "UNNAMED_KEY": "unnamed", - "TODAY": "Today", - "DUPLICATE_BLOCK": "Duplicate", - "ADD_COMMENT": "Add Comment", - "REMOVE_COMMENT": "Remove Comment", - "DUPLICATE_COMMENT": "Duplicate Comment", - "EXTERNAL_INPUTS": "External Inputs", - "INLINE_INPUTS": "Inline Inputs", - "DELETE_BLOCK": "Delete Block", - "DELETE_X_BLOCKS": "Delete %1 Blocks", - "DELETE_ALL_BLOCKS": "Delete all %1 blocks?", - "CLEAN_UP": "Clean up Blocks", - "COLLAPSE_BLOCK": "Collapse Block", - "COLLAPSE_ALL": "Collapse Blocks", - "EXPAND_BLOCK": "Expand Block", - "EXPAND_ALL": "Expand Blocks", - "DISABLE_BLOCK": "Disable Block", - "ENABLE_BLOCK": "Enable Block", - "HELP": "Help", - "UNDO": "Undo", - "REDO": "Redo", - "CHANGE_VALUE_TITLE": "Change value:", - "RENAME_VARIABLE": "Rename variable...", - "RENAME_VARIABLE_TITLE": "Rename all '%1' variables to:", - "NEW_VARIABLE": "Create variable...", - "NEW_STRING_VARIABLE": "Create string variable...", - "NEW_NUMBER_VARIABLE": "Create number variable...", - "NEW_COLOUR_VARIABLE": "Create colour variable...", - "NEW_VARIABLE_TYPE_TITLE": "New variable type:", - "NEW_VARIABLE_TITLE": "New variable name:", - "VARIABLE_ALREADY_EXISTS": "A variable named '%1' already exists.", - "VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE": "A variable named '%1' already exists for another type: '%2'.", - "DELETE_VARIABLE_CONFIRMATION": "Delete %1 uses of the '%2' variable?", - "CANNOT_DELETE_VARIABLE_PROCEDURE": "Can't delete the variable '%1' because it's part of the definition of the function '%2'", - "DELETE_VARIABLE": "Delete the '%1' variable", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Choose a colour from the palette.", - "COLOUR_RANDOM_HELPURL": "http://randomcolour.com", - "COLOUR_RANDOM_TITLE": "random colour", - "COLOUR_RANDOM_TOOLTIP": "Choose a colour at random.", - "COLOUR_RGB_HELPURL": "https://www.december.com/html/spec/colorpercompact.html", - "COLOUR_RGB_TITLE": "colour with", - "COLOUR_RGB_RED": "red", - "COLOUR_RGB_GREEN": "green", - "COLOUR_RGB_BLUE": "blue", - "COLOUR_RGB_TOOLTIP": "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100.", - "COLOUR_BLEND_HELPURL": "https://meyerweb.com/eric/tools/color-blend/#:::rgbp", - "COLOUR_BLEND_TITLE": "blend", - "COLOUR_BLEND_COLOUR1": "colour 1", - "COLOUR_BLEND_COLOUR2": "colour 2", - "COLOUR_BLEND_RATIO": "ratio", - "COLOUR_BLEND_TOOLTIP": "Blends two colours together with a given ratio (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "repeat %1 times", - "CONTROLS_REPEAT_INPUT_DO": "do", - "CONTROLS_REPEAT_TOOLTIP": "Do some statements several times.", - "CONTROLS_WHILEUNTIL_HELPURL": "https://github.com/google/blockly/wiki/Loops#repeat", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repeat while", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repeat until", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "While a value is true, then do some statements.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "While a value is false, then do some statements.", - "CONTROLS_FOR_HELPURL": "https://github.com/google/blockly/wiki/Loops#count-with", - "CONTROLS_FOR_TOOLTIP": "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.", - "CONTROLS_FOR_TITLE": "count with %1 from %2 to %3 by %4", - "CONTROLS_FOREACH_HELPURL": "https://github.com/google/blockly/wiki/Loops#for-each", - "CONTROLS_FOREACH_TITLE": "for each item %1 in list %2", - "CONTROLS_FOREACH_TOOLTIP": "For each item in a list, set the variable '%1' to the item, and then do some statements.", - "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "break out of loop", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continue with next iteration of loop", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Break out of the containing loop.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Skip the rest of this loop, and continue with the next iteration.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Warning: This block may only be used within a loop.", - "CONTROLS_IF_HELPURL": "https://github.com/google/blockly/wiki/IfElse", - "CONTROLS_IF_TOOLTIP_1": "If a value is true, then do some statements.", - "CONTROLS_IF_TOOLTIP_2": "If a value is true, then do the first block of statements. Otherwise, do the second block of statements.", - "CONTROLS_IF_TOOLTIP_3": "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements.", - "CONTROLS_IF_TOOLTIP_4": "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements.", - "CONTROLS_IF_MSG_IF": "if", - "CONTROLS_IF_MSG_ELSEIF": "else if", - "CONTROLS_IF_MSG_ELSE": "else", - "CONTROLS_IF_IF_TOOLTIP": "Add, remove, or reorder sections to reconfigure this if block.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Add a condition to the if block.", - "CONTROLS_IF_ELSE_TOOLTIP": "Add a final, catch-all condition to the if block.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Return true if both inputs equal each other.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Return true if both inputs are not equal to each other.", - "LOGIC_COMPARE_TOOLTIP_LT": "Return true if the first input is smaller than the second input.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Return true if the first input is smaller than or equal to the second input.", - "LOGIC_COMPARE_TOOLTIP_GT": "Return true if the first input is greater than the second input.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Return true if the first input is greater than or equal to the second input.", - "LOGIC_OPERATION_HELPURL": "https://github.com/google/blockly/wiki/Logic#logical-operations", - "LOGIC_OPERATION_TOOLTIP_AND": "Return true if both inputs are true.", - "LOGIC_OPERATION_AND": "and", - "LOGIC_OPERATION_TOOLTIP_OR": "Return true if at least one of the inputs is true.", - "LOGIC_OPERATION_OR": "or", - "LOGIC_NEGATE_HELPURL": "https://github.com/google/blockly/wiki/Logic#not", - "LOGIC_NEGATE_TITLE": "not %1", - "LOGIC_NEGATE_TOOLTIP": "Returns true if the input is false. Returns false if the input is true.", - "LOGIC_BOOLEAN_HELPURL": "https://github.com/google/blockly/wiki/Logic#values", - "LOGIC_BOOLEAN_TRUE": "true", - "LOGIC_BOOLEAN_FALSE": "false", - "LOGIC_BOOLEAN_TOOLTIP": "Returns either true or false.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Returns null.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "if true", - "LOGIC_TERNARY_IF_FALSE": "if false", - "LOGIC_TERNARY_TOOLTIP": "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "A number.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Return the sum of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Return the difference of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Return the product of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Return the quotient of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Return the first number raised to the power of the second number.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "square root", - "MATH_SINGLE_TOOLTIP_ROOT": "Return the square root of a number.", - "MATH_SINGLE_OP_ABSOLUTE": "absolute", - "MATH_SINGLE_TOOLTIP_ABS": "Return the absolute value of a number.", - "MATH_SINGLE_TOOLTIP_NEG": "Return the negation of a number.", - "MATH_SINGLE_TOOLTIP_LN": "Return the natural logarithm of a number.", - "MATH_SINGLE_TOOLTIP_LOG10": "Return the base 10 logarithm of a number.", - "MATH_SINGLE_TOOLTIP_EXP": "Return e to the power of a number.", - "MATH_SINGLE_TOOLTIP_POW10": "Return 10 to the power of a number.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Return the sine of a degree (not radian).", - "MATH_TRIG_TOOLTIP_COS": "Return the cosine of a degree (not radian).", - "MATH_TRIG_TOOLTIP_TAN": "Return the tangent of a degree (not radian).", - "MATH_TRIG_TOOLTIP_ASIN": "Return the arcsine of a number.", - "MATH_TRIG_TOOLTIP_ACOS": "Return the arccosine of a number.", - "MATH_TRIG_TOOLTIP_ATAN": "Return the arctangent of a number.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).", - "MATH_IS_EVEN": "is even", - "MATH_IS_ODD": "is odd", - "MATH_IS_PRIME": "is prime", - "MATH_IS_WHOLE": "is whole", - "MATH_IS_POSITIVE": "is positive", - "MATH_IS_NEGATIVE": "is negative", - "MATH_IS_DIVISIBLE_BY": "is divisible by", - "MATH_IS_TOOLTIP": "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "change %1 by %2", - "MATH_CHANGE_TOOLTIP": "Add a number to variable '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Round a number up or down.", - "MATH_ROUND_OPERATOR_ROUND": "round", - "MATH_ROUND_OPERATOR_ROUNDUP": "round up", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "round down", - "MATH_ONLIST_HELPURL": "", - "MATH_ONLIST_OPERATOR_SUM": "sum of list", - "MATH_ONLIST_TOOLTIP_SUM": "Return the sum of all the numbers in the list.", - "MATH_ONLIST_OPERATOR_MIN": "min of list", - "MATH_ONLIST_TOOLTIP_MIN": "Return the smallest number in the list.", - "MATH_ONLIST_OPERATOR_MAX": "max of list", - "MATH_ONLIST_TOOLTIP_MAX": "Return the largest number in the list.", - "MATH_ONLIST_OPERATOR_AVERAGE": "average of list", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Return the average (arithmetic mean) of the numeric values in the list.", - "MATH_ONLIST_OPERATOR_MEDIAN": "median of list", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Return the median number in the list.", - "MATH_ONLIST_OPERATOR_MODE": "modes of list", - "MATH_ONLIST_TOOLTIP_MODE": "Return a list of the most common item(s) in the list.", - "MATH_ONLIST_OPERATOR_STD_DEV": "standard deviation of list", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Return the standard deviation of the list.", - "MATH_ONLIST_OPERATOR_RANDOM": "random item of list", - "MATH_ONLIST_TOOLTIP_RANDOM": "Return a random element from the list.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "remainder of %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Return the remainder from dividing the two numbers.", - "MATH_CONSTRAIN_HELPURL": "https://en.wikipedia.org/wiki/Clamping_(graphics)", - "MATH_CONSTRAIN_TITLE": "constrain %1 low %2 high %3", - "MATH_CONSTRAIN_TOOLTIP": "Constrain a number to be between the specified limits (inclusive).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "random integer from %1 to %2", - "MATH_RANDOM_INT_TOOLTIP": "Return a random integer between the two specified limits, inclusive.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "random fraction", - "MATH_RANDOM_FLOAT_TOOLTIP": "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).", - "MATH_ATAN2_HELPURL": "https://en.wikipedia.org/wiki/Atan2", - "MATH_ATAN2_TITLE": "atan2 of X:%1 Y:%2", - "MATH_ATAN2_TOOLTIP": "Return the arctangent of point (X, Y) in degrees from -180 to 180.", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "A letter, word, or line of text.", - "TEXT_JOIN_HELPURL": "https://github.com/google/blockly/wiki/Text#text-creation", - "TEXT_JOIN_TITLE_CREATEWITH": "create text with", - "TEXT_JOIN_TOOLTIP": "Create a piece of text by joining together any number of items.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "join", - "TEXT_CREATE_JOIN_TOOLTIP": "Add, remove, or reorder sections to reconfigure this text block.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Add an item to the text.", - "TEXT_APPEND_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_APPEND_TITLE": "to %1 append text %2", - "TEXT_APPEND_TOOLTIP": "Append some text to variable '%1'.", - "TEXT_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_LENGTH_TITLE": "length of %1", - "TEXT_LENGTH_TOOLTIP": "Returns the number of letters (including spaces) in the provided text.", - "TEXT_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Text#checking-for-empty-text", - "TEXT_ISEMPTY_TITLE": "%1 is empty", - "TEXT_ISEMPTY_TOOLTIP": "Returns true if the provided text is empty.", - "TEXT_INDEXOF_HELPURL": "https://github.com/google/blockly/wiki/Text#finding-text", - "TEXT_INDEXOF_TOOLTIP": "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found.", - "TEXT_INDEXOF_TITLE": "in text %1 %2 %3", - "TEXT_INDEXOF_OPERATOR_FIRST": "find first occurrence of text", - "TEXT_INDEXOF_OPERATOR_LAST": "find last occurrence of text", - "TEXT_CHARAT_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-text", - "TEXT_CHARAT_TITLE": "in text %1 %2", - "TEXT_CHARAT_FROM_START": "get letter #", - "TEXT_CHARAT_FROM_END": "get letter # from end", - "TEXT_CHARAT_FIRST": "get first letter", - "TEXT_CHARAT_LAST": "get last letter", - "TEXT_CHARAT_RANDOM": "get random letter", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "Returns the letter at the specified position.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Returns a specified portion of the text.", - "TEXT_GET_SUBSTRING_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in text", - "TEXT_GET_SUBSTRING_START_FROM_START": "get substring from letter #", - "TEXT_GET_SUBSTRING_START_FROM_END": "get substring from letter # from end", - "TEXT_GET_SUBSTRING_START_FIRST": "get substring from first letter", - "TEXT_GET_SUBSTRING_END_FROM_START": "to letter #", - "TEXT_GET_SUBSTRING_END_FROM_END": "to letter # from end", - "TEXT_GET_SUBSTRING_END_LAST": "to last letter", - "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_HELPURL": "https://github.com/google/blockly/wiki/Text#adjusting-text-case", - "TEXT_CHANGECASE_TOOLTIP": "Return a copy of the text in a different case.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "to UPPER CASE", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "to lower case", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "to Title Case", - "TEXT_TRIM_HELPURL": "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces", - "TEXT_TRIM_TOOLTIP": "Return a copy of the text with spaces removed from one or both ends.", - "TEXT_TRIM_OPERATOR_BOTH": "trim spaces from both sides of", - "TEXT_TRIM_OPERATOR_LEFT": "trim spaces from left side of", - "TEXT_TRIM_OPERATOR_RIGHT": "trim spaces from right side of", - "TEXT_PRINT_HELPURL": "https://github.com/google/blockly/wiki/Text#printing-text", - "TEXT_PRINT_TITLE": "print %1", - "TEXT_PRINT_TOOLTIP": "Print the specified text, number or other value.", - "TEXT_PROMPT_HELPURL": "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user", - "TEXT_PROMPT_TYPE_TEXT": "prompt for text with message", - "TEXT_PROMPT_TYPE_NUMBER": "prompt for number with message", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Prompt for user for a number.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Prompt for user for some text.", - "TEXT_COUNT_MESSAGE0": "count %1 in %2", - "TEXT_COUNT_HELPURL": "https://github.com/google/blockly/wiki/Text#counting-substrings", - "TEXT_COUNT_TOOLTIP": "Count how many times some text occurs within some other text.", - "TEXT_REPLACE_MESSAGE0": "replace %1 with %2 in %3", - "TEXT_REPLACE_HELPURL": "https://github.com/google/blockly/wiki/Text#replacing-substrings", - "TEXT_REPLACE_TOOLTIP": "Replace all occurances of some text within some other text.", - "TEXT_REVERSE_MESSAGE0": "reverse %1", - "TEXT_REVERSE_HELPURL": "https://github.com/google/blockly/wiki/Text#reversing-text", - "TEXT_REVERSE_TOOLTIP": "Reverses the order of the characters in the text.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "create empty list", - "LISTS_CREATE_EMPTY_TOOLTIP": "Returns a list, of length 0, containing no data records", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Create a list with any number of items.", - "LISTS_CREATE_WITH_INPUT_WITH": "create list with", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "list", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Add, remove, or reorder sections to reconfigure this list block.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Add an item to the list.", - "LISTS_REPEAT_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_REPEAT_TOOLTIP": "Creates a list consisting of the given value repeated the specified number of times.", - "LISTS_REPEAT_TITLE": "create list with item %1 repeated %2 times", - "LISTS_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Lists#length-of", - "LISTS_LENGTH_TITLE": "length of %1", - "LISTS_LENGTH_TOOLTIP": "Returns the length of a list.", - "LISTS_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#is-empty", - "LISTS_ISEMPTY_TITLE": "%1 is empty", - "LISTS_ISEMPTY_TOOLTIP": "Returns true if the list is empty.", - "LISTS_INLIST": "in list", - "LISTS_INDEX_OF_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list", - "LISTS_INDEX_OF_FIRST": "find first occurrence of item", - "LISTS_INDEX_OF_LAST": "find last occurrence of item", - "LISTS_INDEX_OF_TOOLTIP": "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found.", - "LISTS_GET_INDEX_GET": "get", - "LISTS_GET_INDEX_GET_REMOVE": "get and remove", - "LISTS_GET_INDEX_REMOVE": "remove", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# from end", - "LISTS_GET_INDEX_FIRST": "first", - "LISTS_GET_INDEX_LAST": "last", - "LISTS_GET_INDEX_RANDOM": "random", - "LISTS_GET_INDEX_TAIL": "", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 is the first item.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 is the last item.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Returns the item at the specified position in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Returns the first item in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Returns the last item in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Returns a random item in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Removes and returns the item at the specified position in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Removes and returns the first item in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Removes and returns the last item in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Removes and returns a random item in a list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Removes the item at the specified position in a list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Removes the first item in a list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Removes the last item in a list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Removes a random item in a list.", - "LISTS_SET_INDEX_HELPURL": "https://github.com/google/blockly/wiki/Lists#in-list--set", - "LISTS_SET_INDEX_SET": "set", - "LISTS_SET_INDEX_INSERT": "insert at", - "LISTS_SET_INDEX_INPUT_TO": "as", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Sets the item at the specified position in a list.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Sets the first item in a list.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Sets the last item in a list.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Sets a random item in a list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Inserts the item at the specified position in a list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Inserts the item at the start of a list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Append the item to the end of a list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Inserts the item randomly in a list.", - "LISTS_GET_SUBLIST_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-a-sublist", - "LISTS_GET_SUBLIST_START_FROM_START": "get sub-list from #", - "LISTS_GET_SUBLIST_START_FROM_END": "get sub-list from # from end", - "LISTS_GET_SUBLIST_START_FIRST": "get sub-list from first", - "LISTS_GET_SUBLIST_END_FROM_START": "to #", - "LISTS_GET_SUBLIST_END_FROM_END": "to # from end", - "LISTS_GET_SUBLIST_END_LAST": "to last", - "LISTS_GET_SUBLIST_TAIL": "", - "LISTS_GET_SUBLIST_TOOLTIP": "Creates a copy of the specified portion of a list.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "sort %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Sort a copy of a list.", - "LISTS_SORT_ORDER_ASCENDING": "ascending", - "LISTS_SORT_ORDER_DESCENDING": "descending", - "LISTS_SORT_TYPE_NUMERIC": "numeric", - "LISTS_SORT_TYPE_TEXT": "alphabetic", - "LISTS_SORT_TYPE_IGNORECASE": "alphabetic, ignore case", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "make list from text", - "LISTS_SPLIT_TEXT_FROM_LIST": "make text from list", - "LISTS_SPLIT_WITH_DELIMITER": "with delimiter", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Split text into a list of texts, breaking at each delimiter.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Join a list of texts into one text, separated by a delimiter.", - "LISTS_REVERSE_HELPURL": "https://github.com/google/blockly/wiki/Lists#reversing-a-list", - "LISTS_REVERSE_MESSAGE0": "reverse %1", - "LISTS_REVERSE_TOOLTIP": "Reverse a copy of a list.", - "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_HELPURL": "https://github.com/google/blockly/wiki/Variables#get", - "VARIABLES_GET_TOOLTIP": "Returns the value of this variable.", - "VARIABLES_GET_CREATE_SET": "Create 'set %1'", - "VARIABLES_SET_HELPURL": "https://github.com/google/blockly/wiki/Variables#set", - "VARIABLES_SET": "set %1 to %2", - "VARIABLES_SET_TOOLTIP": "Sets this variable to be equal to the input.", - "VARIABLES_SET_CREATE_GET": "Create 'get %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Subroutine", - "PROCEDURES_DEFNORETURN_TITLE": "to", - "PROCEDURES_DEFNORETURN_PROCEDURE": "do something", - "PROCEDURES_BEFORE_PARAMS": "with:", - "PROCEDURES_CALL_BEFORE_PARAMS": "with:", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Creates a function with no output.", - "PROCEDURES_DEFNORETURN_COMMENT": "Describe this function...", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Subroutine", - "PROCEDURES_DEFRETURN_RETURN": "return", - "PROCEDURES_DEFRETURN_TOOLTIP": "Creates a function with an output.", - "PROCEDURES_ALLOW_STATEMENTS": "allow statements", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Warning: This function has duplicate parameters.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Subroutine", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Run the user-defined function '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Subroutine", - "PROCEDURES_CALLRETURN_TOOLTIP": "Run the user-defined function '%1' and use its output.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "inputs", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Add, remove, or reorder inputs to this function.", - "PROCEDURES_MUTATORARG_TITLE": "input name:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Add an input to the function.", - "PROCEDURES_HIGHLIGHT_DEF": "Highlight function definition", - "PROCEDURES_CREATE_DO": "Create '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "If a value is true, then return a second value.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Warning: This block may be used only within a function definition.", - "WORKSPACE_COMMENT_DEFAULT_TEXT": "Say something...", - "WORKSPACE_ARIA_LABEL": "Blockly Workspace", - "COLLAPSED_WARNINGS_WARNING": "Collapsed blocks contain warnings.", - "DIALOG_OK": "OK", - "DIALOG_CANCEL": "Cancel" -} diff --git a/google-blockly/msg/json/ja.json b/google-blockly/msg/json/ja.json deleted file mode 100644 index c57368a..0000000 --- a/google-blockly/msg/json/ja.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Aefgh39622", - "Gimite", - "Gulpin", - "Kebhr", - "Kkairri", - "Oda", - "Omotecho", - "Otokoume", - "RYU N", - "Sgk", - "Shirayuki", - "Suiato", - "Sujiniku", - "TAKAHASHI Shuuji", - "Tokoroten", - "しぃ", - "ネイ", - "아라" - ] - }, - "VARIABLES_DEFAULT_NAME": "項目", - "UNNAMED_KEY": "名前なし", - "TODAY": "今日", - "DUPLICATE_BLOCK": "複製", - "ADD_COMMENT": "コメントを追加", - "REMOVE_COMMENT": "コメントを削除", - "DUPLICATE_COMMENT": "コメントを複製", - "EXTERNAL_INPUTS": "外部入力", - "INLINE_INPUTS": "インライン入力", - "DELETE_BLOCK": "ブロックを削除", - "DELETE_X_BLOCKS": "%1個のブロックを削除", - "DELETE_ALL_BLOCKS": "%1個あるすべてのブロックを削除しますか?", - "CLEAN_UP": "ブロックを整理する", - "COLLAPSE_BLOCK": "ブロックを折りたたむ", - "COLLAPSE_ALL": "ブロックを折りたたむ", - "EXPAND_BLOCK": "ブロックを展開する", - "EXPAND_ALL": "ブロックを展開する", - "DISABLE_BLOCK": "ブロックを無効にする", - "ENABLE_BLOCK": "ブロックを有効にする", - "HELP": "ヘルプ", - "UNDO": "取り消す", - "REDO": "やり直す", - "CHANGE_VALUE_TITLE": "値を変える:", - "RENAME_VARIABLE": "変数の名前を変える…", - "RENAME_VARIABLE_TITLE": "選択した%1個すべての変数の名前を変える:", - "NEW_VARIABLE": "変数の作成…", - "NEW_STRING_VARIABLE": "文字列の変数を作る...", - "NEW_NUMBER_VARIABLE": "数の変数を作る...", - "NEW_COLOUR_VARIABLE": "色の変数を作る...", - "NEW_VARIABLE_TYPE_TITLE": "新しい変数の型:", - "NEW_VARIABLE_TITLE": "新しい変数の名前:", - "VARIABLE_ALREADY_EXISTS": "変数名 '%1' は既に存在しています。", - "VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE": "'%2' 型の '%1' という名前の変数が既に存在します。", - "DELETE_VARIABLE_CONFIRMATION": "%1か所で使われている変数 '%2' を削除しますか?", - "CANNOT_DELETE_VARIABLE_PROCEDURE": "変数 '%1' は関数 '%2' の定義の一部であるため、削除できません", - "DELETE_VARIABLE": "変数 '%1' を削除", - "COLOUR_PICKER_HELPURL": "https://ja.wikipedia.org/wiki/色", - "COLOUR_PICKER_TOOLTIP": "パレットから色を選んでください。", - "COLOUR_RANDOM_TITLE": "ランダムな色", - "COLOUR_RANDOM_TOOLTIP": "ランダムに色を選ぶ。", - "COLOUR_RGB_TITLE": "色:", - "COLOUR_RGB_RED": "赤", - "COLOUR_RGB_GREEN": "緑", - "COLOUR_RGB_BLUE": "青", - "COLOUR_RGB_TOOLTIP": "赤、緑、および青の指定された量で色を作成します。すべての値は 0 ~ 100 の間でなければなりません。", - "COLOUR_BLEND_TITLE": "ブレンド", - "COLOUR_BLEND_COLOUR1": "色 1", - "COLOUR_BLEND_COLOUR2": "色 2", - "COLOUR_BLEND_RATIO": "比率", - "COLOUR_BLEND_TOOLTIP": "2色を与えられた比率(0.0~1.0)で混ぜます。", - "CONTROLS_REPEAT_HELPURL": "https://ja.wikipedia.org/wiki/for文", - "CONTROLS_REPEAT_TITLE": "%1 回繰り返す", - "CONTROLS_REPEAT_INPUT_DO": "実行", - "CONTROLS_REPEAT_TOOLTIP": "いくつかのステートメントを数回実行します。", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "繰り返す:続ける条件", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "繰り返す:終わる条件", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "値がtrueの間、いくつかのステートメントを実行する。", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "値がfalseの間、いくつかのステートメントを実行する。", - "CONTROLS_FOR_TOOLTIP": "変数 '%1' が開始番号から終了番号まで指定した間隔での値をとって、指定したブロックを実行する。", - "CONTROLS_FOR_TITLE": "%1 を %2 から %3 まで %4 ずつカウントする", - "CONTROLS_FOREACH_TITLE": "リスト%2の各項目%1について", - "CONTROLS_FOREACH_TOOLTIP": "リストの各項目について、その項目を変数'%1'として、いくつかのステートメントを実行します。", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "ループから抜け出す", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "ループの次の反復処理を続行します", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "入っているループから抜け出します。", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "このループの残りの部分をスキップして、ループの繰り返しを続けます。", - "CONTROLS_FLOW_STATEMENTS_WARNING": "注意: このブロックは、ループ内でのみ使用できます。", - "CONTROLS_IF_TOOLTIP_1": "値が true の場合、ステートメントを実行します。", - "CONTROLS_IF_TOOLTIP_2": "値が true の場合は、最初のステートメントのブロックを実行します。それ以外の場合は、2番目のステートメントのブロックを実行します。", - "CONTROLS_IF_TOOLTIP_3": "最初の値が true の場合は、最初のステートメントのブロックを実行します。それ以外の場合で、2番目の値が true の場合は、2番目のステートメントのブロックを実行します。", - "CONTROLS_IF_TOOLTIP_4": "最初の値が true の場合は、最初のステートメントのブロックを実行します。それ以外の場合で、2番目の値が true の場合は、2番目のステートメントのブロックを実行します。すべての値が true でない場合は、最後のステートメントのブロックを実行します。", - "CONTROLS_IF_MSG_IF": "もし", - "CONTROLS_IF_MSG_ELSEIF": "そうでなくもし", - "CONTROLS_IF_MSG_ELSE": "そうでなければ", - "CONTROLS_IF_IF_TOOLTIP": "追加、削除、またはセクションを順序変更して、ブロックをこれを再構成します。", - "CONTROLS_IF_ELSEIF_TOOLTIP": "「もしも」のブロックに条件を追加します。", - "CONTROLS_IF_ELSE_TOOLTIP": "Ifブロックに、すべてをキャッチする条件を追加。", - "LOGIC_COMPARE_HELPURL": "https://ja.wikipedia.org/wiki/不等式", - "LOGIC_COMPARE_TOOLTIP_EQ": "両方の入力が互いに等しい場合に true を返します。", - "LOGIC_COMPARE_TOOLTIP_NEQ": "両方の入力が互いに等しくない場合に true を返します。", - "LOGIC_COMPARE_TOOLTIP_LT": "最初の入力が 2 番目の入力よりも小さい場合は true を返します。", - "LOGIC_COMPARE_TOOLTIP_LTE": "最初の入力が 2 番目の入力以下の場合に true を返します。", - "LOGIC_COMPARE_TOOLTIP_GT": "最初の入力が 2 番目の入力よりも大きい場合は true を返します。", - "LOGIC_COMPARE_TOOLTIP_GTE": "最初の入力が 2 番目の入力以上の場合に true を返します。", - "LOGIC_OPERATION_TOOLTIP_AND": "両方の入力が true のときに true を返します。", - "LOGIC_OPERATION_AND": "かつ", - "LOGIC_OPERATION_TOOLTIP_OR": "少なくとも 1 つの入力が true のときに true を返します。", - "LOGIC_OPERATION_OR": "または", - "LOGIC_NEGATE_TITLE": "%1ではない", - "LOGIC_NEGATE_TOOLTIP": "入力が false の場合は、true を返します。入力が true の場合は false を返します。", - "LOGIC_BOOLEAN_TRUE": "true", - "LOGIC_BOOLEAN_FALSE": "false", - "LOGIC_BOOLEAN_TOOLTIP": "true または false を返します。", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "null を返します。", - "LOGIC_TERNARY_HELPURL": "https://ja.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "テスト", - "LOGIC_TERNARY_IF_TRUE": "true の場合", - "LOGIC_TERNARY_IF_FALSE": "false の場合", - "LOGIC_TERNARY_TOOLTIP": "'テスト' の条件をチェックします。条件が true の場合、'true' の値を返します。それ以外の場合 'false' のを返します。", - "MATH_NUMBER_HELPURL": "https://ja.wikipedia.org/wiki/数", - "MATH_NUMBER_TOOLTIP": "数です。", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://ja.wikipedia.org/wiki/算術", - "MATH_ARITHMETIC_TOOLTIP_ADD": "2 つの数の合計を返します。", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "2 つの数の差を返します。", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "2 つの数の積を返します。", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "2 つの数の商を返します。", - "MATH_ARITHMETIC_TOOLTIP_POWER": "最初の数を2 番目の値で累乗した結果を返します。", - "MATH_SINGLE_HELPURL": "https://ja.wikipedia.org/wiki/平方根", - "MATH_SINGLE_OP_ROOT": "平方根", - "MATH_SINGLE_TOOLTIP_ROOT": "平方根を返す。", - "MATH_SINGLE_OP_ABSOLUTE": "絶対値", - "MATH_SINGLE_TOOLTIP_ABS": "絶対値を返す。", - "MATH_SINGLE_TOOLTIP_NEG": "負の数を返す。", - "MATH_SINGLE_TOOLTIP_LN": "数値の自然対数を返す。", - "MATH_SINGLE_TOOLTIP_LOG10": "底が10の対数を返す。", - "MATH_SINGLE_TOOLTIP_EXP": "ネイピア数eの数値乗を返す。", - "MATH_SINGLE_TOOLTIP_POW10": "10の数値乗を返す。", - "MATH_TRIG_HELPURL": "https://ja.wikipedia.org/wiki/三角関数", - "MATH_TRIG_TOOLTIP_SIN": "(ラジアンではなく)度数の正弦(sin)を返す。", - "MATH_TRIG_TOOLTIP_COS": "(ラジアンではなく)度数の余弦(cosin)を返す。", - "MATH_TRIG_TOOLTIP_TAN": "(ラジアンではなく)度数の正接(tan)を返す。", - "MATH_TRIG_TOOLTIP_ASIN": "アークサイン(arcsin)を返す。", - "MATH_TRIG_TOOLTIP_ACOS": "アークコサイン(arccosin)を返す。", - "MATH_TRIG_TOOLTIP_ATAN": "アークタンジェント(arctan)を返す。", - "MATH_CONSTANT_HELPURL": "https://ja.wikipedia.org/wiki/数学定数", - "MATH_CONSTANT_TOOLTIP": "いずれかの共通の定数のを返す: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (無限).", - "MATH_IS_EVEN": "は偶数", - "MATH_IS_ODD": "は奇数", - "MATH_IS_PRIME": "は素数", - "MATH_IS_WHOLE": "は整数", - "MATH_IS_POSITIVE": "は正", - "MATH_IS_NEGATIVE": "は負", - "MATH_IS_DIVISIBLE_BY": "は以下で割りきれる:", - "MATH_IS_TOOLTIP": "数字が、偶数、奇数、素数、整数、正数、負数、または特定の数で割り切れるかどうかを判定し、true か false を返します。", - "MATH_CHANGE_HELPURL": "https://ja.wikipedia.org/wiki/加法", - "MATH_CHANGE_TITLE": "%1 を %2 増やす", - "MATH_CHANGE_TOOLTIP": "変数'%1'に数をたす。", - "MATH_ROUND_HELPURL": "https://ja.wikipedia.org/wiki/端数処理", - "MATH_ROUND_TOOLTIP": "数値を切り上げるか切り捨てる", - "MATH_ROUND_OPERATOR_ROUND": "四捨五入", - "MATH_ROUND_OPERATOR_ROUNDUP": "切り上げ", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "切り捨て", - "MATH_ONLIST_OPERATOR_SUM": "リストの合計", - "MATH_ONLIST_TOOLTIP_SUM": "リストの数値を足して返す。", - "MATH_ONLIST_OPERATOR_MIN": "リストの最小値", - "MATH_ONLIST_TOOLTIP_MIN": "リストの最小値を返す。", - "MATH_ONLIST_OPERATOR_MAX": "リストの最大値", - "MATH_ONLIST_TOOLTIP_MAX": "リストの最大値を返す。", - "MATH_ONLIST_OPERATOR_AVERAGE": "リストの平均", - "MATH_ONLIST_TOOLTIP_AVERAGE": "リストの数値の平均 (算術平均) を返す。", - "MATH_ONLIST_OPERATOR_MEDIAN": "リストの中央値", - "MATH_ONLIST_TOOLTIP_MEDIAN": "リストの中央値を返す。", - "MATH_ONLIST_OPERATOR_MODE": "リストの最頻値", - "MATH_ONLIST_TOOLTIP_MODE": "リスト中の最頻項目のリストを返す。", - "MATH_ONLIST_OPERATOR_STD_DEV": "リストの標準偏差", - "MATH_ONLIST_TOOLTIP_STD_DEV": "リストの標準偏差を返す。", - "MATH_ONLIST_OPERATOR_RANDOM": "リストからランダムに選ばれた項目", - "MATH_ONLIST_TOOLTIP_RANDOM": "リストからランダムに選ばれた要素を返す。", - "MATH_MODULO_HELPURL": "https://ja.wikipedia.org/wiki/剰余演算", - "MATH_MODULO_TITLE": "%1÷%2の余り", - "MATH_MODULO_TOOLTIP": "2つの数値の割り算の余りを返す。", - "MATH_CONSTRAIN_TITLE": "%1 を %2 以上 %3 以下の範囲に制限", - "MATH_CONSTRAIN_TOOLTIP": "指定した上限と下限の間に値を制限する(上限と下限の値を含む)。", - "MATH_RANDOM_INT_HELPURL": "https://ja.wikipedia.org/wiki/疑似乱数", - "MATH_RANDOM_INT_TITLE": "%1から%2までのランダムな整数", - "MATH_RANDOM_INT_TOOLTIP": "指定された(上下限を含む)範囲のランダムな整数を返します。", - "MATH_RANDOM_FLOAT_HELPURL": "https://ja.wikipedia.org/wiki/疑似乱数", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "1未満の正の乱数", - "MATH_RANDOM_FLOAT_TOOLTIP": "0.0以上で1.0未満の範囲の乱数を返します。", - "MATH_ATAN2_HELPURL": "https://ja.wikipedia.org/wiki/Atan2", - "MATH_ATAN2_TITLE": "X:%1 Y:%2のatan2", - "MATH_ATAN2_TOOLTIP": "アークタンジェントを用いて、点 (X, Y) の角度を -180度から 180度で返します。", - "TEXT_TEXT_HELPURL": "https://ja.wikipedia.org/wiki/文字列", - "TEXT_TEXT_TOOLTIP": "文字、単語、または行のテキスト。", - "TEXT_JOIN_TITLE_CREATEWITH": "テキストを結合して作成:", - "TEXT_JOIN_TOOLTIP": "任意の数の項目一部を一緒に接合してテキストを作成。", - "TEXT_CREATE_JOIN_TITLE_JOIN": "結合", - "TEXT_CREATE_JOIN_TOOLTIP": "セクションを追加、削除、または順序変更して、ブロックを再構成。", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "テキストへ項目を追加。", - "TEXT_APPEND_TITLE": "項目 %1 へテキストを追加 %2", - "TEXT_APPEND_TOOLTIP": "変数 '%1' にテキストを追加。", - "TEXT_LENGTH_TITLE": "%1の長さ", - "TEXT_LENGTH_TOOLTIP": "与えられたテキストの(スペースを含む)文字数を返す。", - "TEXT_ISEMPTY_TITLE": "%1が空", - "TEXT_ISEMPTY_TOOLTIP": "与えられたテキストが空の場合は true を返す。", - "TEXT_INDEXOF_TOOLTIP": "二番目のテキストの中で一番目のテキストが最初/最後に出現したインデックスを返す。テキストが見つからない場合は%1を返す。", - "TEXT_INDEXOF_TITLE": "テキスト %1 %2 %3", - "TEXT_INDEXOF_OPERATOR_FIRST": "で以下のテキストの最初の出現箇所を検索:", - "TEXT_INDEXOF_OPERATOR_LAST": "で以下のテキストの最後の出現箇所を検索:", - "TEXT_CHARAT_TITLE": "テキスト %1 %2", - "TEXT_CHARAT_FROM_START": "の、以下の数字番目の文字:", - "TEXT_CHARAT_FROM_END": "の、後ろから以下の数字番目の文字:", - "TEXT_CHARAT_FIRST": "最初の文字を得る", - "TEXT_CHARAT_LAST": "最後の文字を得る", - "TEXT_CHARAT_RANDOM": "ランダムな文字を得る", - "TEXT_CHARAT_TOOLTIP": "指定された位置に文字を返します。", - "TEXT_GET_SUBSTRING_TOOLTIP": "テキストの指定部分を返します。", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "テキスト", - "TEXT_GET_SUBSTRING_START_FROM_START": "の部分文字列を取得;開始位置:", - "TEXT_GET_SUBSTRING_START_FROM_END": "の部分文字列を取得;開始位置:後ろから", - "TEXT_GET_SUBSTRING_START_FIRST": "の部分文字列を取得;最初から", - "TEXT_GET_SUBSTRING_END_FROM_START": "終了位置:", - "TEXT_GET_SUBSTRING_END_FROM_END": "終了位置:後ろから", - "TEXT_GET_SUBSTRING_END_LAST": "最後の文字", - "TEXT_CHANGECASE_TOOLTIP": "別のケースに、テキストのコピーを返します。", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "大文字に", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "小文字に", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "タイトル ケースに", - "TEXT_TRIM_TOOLTIP": "スペースを 1 つまたは両方の端から削除したのち、テキストのコピーを返します。", - "TEXT_TRIM_OPERATOR_BOTH": "両端のスペースを取り除く", - "TEXT_TRIM_OPERATOR_LEFT": "左端のスペースを取り除く", - "TEXT_TRIM_OPERATOR_RIGHT": "右端のスペースを取り除く", - "TEXT_PRINT_TITLE": "%1 を表示", - "TEXT_PRINT_TOOLTIP": "指定したテキスト、番号または他の値を印刷します。", - "TEXT_PROMPT_TYPE_TEXT": "メッセージでテキスト入力を求める", - "TEXT_PROMPT_TYPE_NUMBER": "メッセージで番号の入力を求める", - "TEXT_PROMPT_TOOLTIP_NUMBER": "ユーザーに数値のインプットを求める。", - "TEXT_PROMPT_TOOLTIP_TEXT": "ユーザーにテキスト入力を求める。", - "TEXT_COUNT_MESSAGE0": "%2に含まれる%1の数を数える", - "TEXT_COUNT_TOOLTIP": "とある文が別の文のなかに使われた回数を数える。", - "TEXT_REPLACE_MESSAGE0": "%3に含まれる%1を%2に置換", - "TEXT_REPLACE_TOOLTIP": "文に含まれるキーワードを置換する。", - "TEXT_REVERSE_MESSAGE0": "%1を逆順に", - "TEXT_REVERSE_TOOLTIP": "文の文字を逆順にする。", - "LISTS_CREATE_EMPTY_TITLE": "空のリストを作成", - "LISTS_CREATE_EMPTY_TOOLTIP": "長さ0でデータ・レコードを含まない空のリストを返す", - "LISTS_CREATE_WITH_TOOLTIP": "項目数が不定のリストを作成。", - "LISTS_CREATE_WITH_INPUT_WITH": "以下を使ってリストを作成:", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "リスト", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "追加、削除、またはセクションの順序変更をして、このリスト・ブロックを再構成する。", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "リストに項目を追加。", - "LISTS_REPEAT_TOOLTIP": "与えられた値を指定された回数繰り返してリストを作成。", - "LISTS_REPEAT_TITLE": "項目%1を%2回繰り返したリストを作成", - "LISTS_LENGTH_TITLE": "%1の長さ", - "LISTS_LENGTH_TOOLTIP": "リストの長さを返します。", - "LISTS_ISEMPTY_TITLE": "%1が空", - "LISTS_ISEMPTY_TOOLTIP": "リストが空の場合は、true を返します。", - "LISTS_INLIST": "リスト", - "LISTS_INDEX_OF_FIRST": "で以下のアイテムの最初の出現箇所を検索:", - "LISTS_INDEX_OF_LAST": "で以下のテキストの最後の出現箇所を検索:", - "LISTS_INDEX_OF_TOOLTIP": "リスト項目の最初/最後に出現するインデックス位置を返します。項目が見つからない場合は %1 を返します。", - "LISTS_GET_INDEX_GET": "取得", - "LISTS_GET_INDEX_GET_REMOVE": "取得して削除", - "LISTS_GET_INDEX_REMOVE": "削除", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "位置:後ろから", - "LISTS_GET_INDEX_FIRST": "最初", - "LISTS_GET_INDEX_LAST": "最後", - "LISTS_GET_INDEX_RANDOM": "ランダム", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 は、最初の項目です。", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 は、最後の項目です。", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "リスト内の指定位置にある項目を返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "リストの最初の項目を返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "リストの最後の項目を返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "ランダム アイテム リストを返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "リスト内の指定位置にある項目を削除し、返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "リスト内の最初の項目を削除し返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "リスト内の最後の項目を削除したあと返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "リストのランダムなアイテムを削除し返します。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "リスト内の指定された項目を削除します。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "リスト内の最初の項目を削除します。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "リスト内の最後の項目を削除します。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "リスト内にあるアイテムをランダムに削除します。", - "LISTS_SET_INDEX_SET": "セット", - "LISTS_SET_INDEX_INSERT": "挿入位置:", - "LISTS_SET_INDEX_INPUT_TO": "値:", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "リスト内の指定された位置に項目を設定します。", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "リスト内に最初の項目を設定します。", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "リスト内の最後の項目を設定します。", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "リスト内にランダムなアイテムを設定します。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "リスト内の指定位置に項目を挿入します。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "リストの先頭に項目を挿入します。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "リストの末尾に項目を追加します。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "リストに項目をランダムに挿入します。", - "LISTS_GET_SUBLIST_START_FROM_START": "# からサブディレクトリのリストを取得します。", - "LISTS_GET_SUBLIST_START_FROM_END": "端から #のサブリストを取得します。", - "LISTS_GET_SUBLIST_START_FIRST": "最初からサブリストを取得する。", - "LISTS_GET_SUBLIST_END_FROM_START": "終了位置:", - "LISTS_GET_SUBLIST_END_FROM_END": "終了位置:後ろから", - "LISTS_GET_SUBLIST_END_LAST": "最後まで", - "LISTS_GET_SUBLIST_TOOLTIP": "リストの指定された部分のコピーを作成します。", - "LISTS_SORT_TITLE": "%1 ( %2 ) に %3 を並び替える", - "LISTS_SORT_TOOLTIP": "リストのコピーを並べ替え", - "LISTS_SORT_ORDER_ASCENDING": "昇順", - "LISTS_SORT_ORDER_DESCENDING": "降順", - "LISTS_SORT_TYPE_NUMERIC": "数値順", - "LISTS_SORT_TYPE_TEXT": "アルファベット順", - "LISTS_SORT_TYPE_IGNORECASE": "アルファベット順(大文字・小文字の区別無し)", - "LISTS_SPLIT_LIST_FROM_TEXT": "テキストからリストを作る", - "LISTS_SPLIT_TEXT_FROM_LIST": "リストからテキストを作る", - "LISTS_SPLIT_WITH_DELIMITER": "区切り記号", - "LISTS_SPLIT_TOOLTIP_SPLIT": "テキストを区切り記号で分割したリストにする", - "LISTS_SPLIT_TOOLTIP_JOIN": "テキストのリストを区切り記号で区切られた一つのテキストにする", - "LISTS_REVERSE_MESSAGE0": "%1を逆順に", - "LISTS_REVERSE_TOOLTIP": "リストのコピーを逆順にする。", - "VARIABLES_GET_TOOLTIP": "この変数の値を返します。", - "VARIABLES_GET_CREATE_SET": "'セット%1を作成します。", - "VARIABLES_SET": "%1 に %2 をセット", - "VARIABLES_SET_TOOLTIP": "この入力を変数と等しくなるように設定します。", - "VARIABLES_SET_CREATE_GET": "'%1 を取得' を作成します。", - "PROCEDURES_DEFNORETURN_TITLE": "関数", - "PROCEDURES_DEFNORETURN_PROCEDURE": "何かする", - "PROCEDURES_BEFORE_PARAMS": "引数:", - "PROCEDURES_CALL_BEFORE_PARAMS": "引数:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "出力なしの関数を作成します。", - "PROCEDURES_DEFNORETURN_COMMENT": "この関数の説明…", - "PROCEDURES_DEFRETURN_RETURN": "返す", - "PROCEDURES_DEFRETURN_TOOLTIP": "一つの出力を持つ関数を作成します。", - "PROCEDURES_ALLOW_STATEMENTS": "ステートメントを許可", - "PROCEDURES_DEF_DUPLICATE_WARNING": "警告: この関数には重複するパラメーターがあります。", - "PROCEDURES_CALLNORETURN_HELPURL": "https://ja.wikipedia.org/wiki/サブルーチン", - "PROCEDURES_CALLNORETURN_TOOLTIP": "ユーザー定義関数 '%1' を実行します。", - "PROCEDURES_CALLRETURN_HELPURL": "https://ja.wikipedia.org/wiki/サブルーチン", - "PROCEDURES_CALLRETURN_TOOLTIP": "ユーザー定義関数 '%1' を実行し、その出力を使用します。", - "PROCEDURES_MUTATORCONTAINER_TITLE": "入力", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "この関数への入力の追加、削除、順番変更。", - "PROCEDURES_MUTATORARG_TITLE": "入力名:", - "PROCEDURES_MUTATORARG_TOOLTIP": "関数への入力の追加。", - "PROCEDURES_HIGHLIGHT_DEF": "関数の内容を強調表示します。", - "PROCEDURES_CREATE_DO": "'%1' を作成", - "PROCEDURES_IFRETURN_TOOLTIP": "1番目の値が true の場合、2番目の値を返します。", - "PROCEDURES_IFRETURN_WARNING": "警告: このブロックは、関数定義内でのみ使用できます。", - "WORKSPACE_COMMENT_DEFAULT_TEXT": "ここへ入力", - "WORKSPACE_ARIA_LABEL": "Blocklyワークスペース", - "COLLAPSED_WARNINGS_WARNING": "つぶしたブロックには警告が入っています。", - "DIALOG_OK": "OK", - "DIALOG_CANCEL": "キャンセル" -} diff --git a/google-blockly/msg/messages.js b/google-blockly/msg/messages.js deleted file mode 100644 index 37311df..0000000 --- a/google-blockly/msg/messages.js +++ /dev/null @@ -1,1599 +0,0 @@ -/** - * @license - * Copyright 2012 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview English strings. - * - * After modifying this file, run: - * - * npm run generate:langfiles - * - * to regenerate json/{en,qqq,constants,synonyms}.json. - * - * To convert all of the json files to .js files, run: - * - * npm run build:langfiles - */ -'use strict'; - - -/** - * Due to the frequency of long strings, the 80-column wrap rule need not apply - * to message files. - */ - -/** - * Each message is preceded with a triple-slash comment that becomes the - * message descriptor. The build process extracts these descriptors, adds - * them to msg/json/qqq.json, and they show up in the translation console. - */ - -/** @type {string} */ -/// {{Notranslate}} Hue value for all logic blocks. -Blockly.Msg.LOGIC_HUE = '210'; -/** @type {string} */ -/// {{Notranslate}} Hue value for all loop blocks. -Blockly.Msg.LOOPS_HUE = '120'; -/** @type {string} */ -/// {{Notranslate}} Hue value for all math blocks. -Blockly.Msg.MATH_HUE = '230'; -/** @type {string} */ -/// {{Notranslate}} Hue value for all text blocks. -Blockly.Msg.TEXTS_HUE = '160'; -/** @type {string} */ -/// {{Notranslate}} Hue value for all list blocks. -Blockly.Msg.LISTS_HUE = '260'; -/** @type {string} */ -/// {{Notranslate}} Hue value for all colour blocks. -Blockly.Msg.COLOUR_HUE = '20'; -/** @type {string} */ -/// {{Notranslate}} Hue value for all variable blocks. -Blockly.Msg.VARIABLES_HUE = '330'; -/** @type {string} */ -/// {{Notranslate}} Hue value for all variable dynamic blocks. -Blockly.Msg.VARIABLES_DYNAMIC_HUE = '310'; -/** @type {string} */ -/// {{Notranslate}} Hue value for all procedure blocks. -Blockly.Msg.PROCEDURES_HUE = '290'; - -/** @type {string} */ -/// default name - A simple, general default name for a variable, preferably short. -/// For more context, see -/// [[Translating:Blockly#infrequent_message_types]].\n{{Identical|Item}} -Blockly.Msg.VARIABLES_DEFAULT_NAME = 'item'; -/** @type {string} */ -/// default name - A simple, default name for an unnamed function or variable. Preferably indicates that the item is unnamed. -Blockly.Msg.UNNAMED_KEY = 'unnamed'; -/** @type {string} */ -/// button text - Button that sets a calendar to today's date.\n{{Identical|Today}} -Blockly.Msg.TODAY = 'Today'; - -// Context menus. -/** @type {string} */ -/// context menu - Make a copy of the selected block (and any blocks it contains).\n{{Identical|Duplicate}} -Blockly.Msg.DUPLICATE_BLOCK = 'Duplicate'; -/** @type {string} */ -/// context menu - Add a descriptive comment to the selected block. -Blockly.Msg.ADD_COMMENT = 'Add Comment'; -/** @type {string} */ -/// context menu - Remove the descriptive comment from the selected block. -Blockly.Msg.REMOVE_COMMENT = 'Remove Comment'; -/** @type {string} */ -/// context menu - Make a copy of the selected workspace comment.\n{{Identical|Duplicate}} -Blockly.Msg.DUPLICATE_COMMENT = 'Duplicate Comment'; -/** @type {string} */ -/// context menu - Change from 'external' to 'inline' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]]. -Blockly.Msg.EXTERNAL_INPUTS = 'External Inputs'; -/** @type {string} */ -/// context menu - Change from 'internal' to 'external' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]]. -Blockly.Msg.INLINE_INPUTS = 'Inline Inputs'; -/** @type {string} */ -/// context menu - Permanently delete the selected block. -Blockly.Msg.DELETE_BLOCK = 'Delete Block'; -/** @type {string} */ -/// context menu - Permanently delete the %1 selected blocks.\n\nParameters:\n* %1 - an integer greater than 1. -Blockly.Msg.DELETE_X_BLOCKS = 'Delete %1 Blocks'; -/** @type {string} */ -/// confirmation prompt - Question the user if they really wanted to permanently delete all %1 blocks.\n\nParameters:\n* %1 - an integer greater than 1. -Blockly.Msg.DELETE_ALL_BLOCKS = 'Delete all %1 blocks?'; -/** @type {string} */ -/// context menu - Reposition all the blocks so that they form a neat line. -Blockly.Msg.CLEAN_UP = 'Clean up Blocks'; -/** @type {string} */ -/// context menu - Make the appearance of the selected block smaller by hiding some information about it. -Blockly.Msg.COLLAPSE_BLOCK = 'Collapse Block'; -/** @type {string} */ -/// context menu - Make the appearance of all blocks smaller by hiding some information about it. Use the same terminology as in the previous message. -Blockly.Msg.COLLAPSE_ALL = 'Collapse Blocks'; -/** @type {string} */ -/// context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier. -Blockly.Msg.EXPAND_BLOCK = 'Expand Block'; -/** @type {string} */ -/// context menu - Restore the appearance of all blocks by showing information about it that was hidden (collapsed) earlier. Use the same terminology as in the previous message. -Blockly.Msg.EXPAND_ALL = 'Expand Blocks'; -/** @type {string} */ -/// context menu - Make the selected block have no effect (unless reenabled). -Blockly.Msg.DISABLE_BLOCK = 'Disable Block'; -/** @type {string} */ -/// context menu - Make the selected block have effect (after having been disabled earlier). -Blockly.Msg.ENABLE_BLOCK = 'Enable Block'; -/** @type {string} */ -/// context menu - Provide helpful information about the selected block.\n{{Identical|Help}} -Blockly.Msg.HELP = 'Help'; -/** @type {string} */ -/// context menu - Undo the previous action.\n{{Identical|Undo}} -Blockly.Msg.UNDO = 'Undo'; -/** @type {string} */ -/// context menu - Undo the previous undo action.\n{{Identical|Redo}} -Blockly.Msg.REDO = 'Redo'; - -// Variable renaming. -/** @type {string} */ -/// prompt - This message is only seen in the Opera browser. With most browsers, users can edit numeric values in blocks by just clicking and typing. Opera does not allows this, so we have to open a new window and prompt users with this message to chanage a value. -Blockly.Msg.CHANGE_VALUE_TITLE = 'Change value:'; -/** @type {string} */ -/// dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices. It is used to rename the current variable. See [https://github.com/google/blockly/wiki/Variables#dropdown-menu https://github.com/google/blockly/wiki/Variables#dropdown-menu]. -Blockly.Msg.RENAME_VARIABLE = 'Rename variable...'; -/** @type {string} */ -/// prompt - Prompts the user to enter the new name for the selected variable. See [https://github.com/google/blockly/wiki/Variables#dropdown-menu https://github.com/google/blockly/wiki/Variables#dropdown-menu].\n\nParameters:\n* %1 - the name of the variable to be renamed. -Blockly.Msg.RENAME_VARIABLE_TITLE = 'Rename all "%1" variables to:'; - -// Variable creation -/** @type {string} */ -/// button text - Text on the button used to launch the variable creation dialogue. -Blockly.Msg.NEW_VARIABLE = 'Create variable...'; -/** @type {string} */ -/// button text - Text on the button used to launch the variable creation dialogue. -Blockly.Msg.NEW_STRING_VARIABLE = 'Create string variable...'; -/** @type {string} */ -/// button text - Text on the button used to launch the variable creation dialogue. -Blockly.Msg.NEW_NUMBER_VARIABLE = 'Create number variable...'; -/** @type {string} */ -/// button text - Text on the button used to launch the variable creation dialogue. -Blockly.Msg.NEW_COLOUR_VARIABLE = 'Create colour variable...'; -/** @type {string} */ -/// prompt - Prompts the user to enter the type for a variable. -Blockly.Msg.NEW_VARIABLE_TYPE_TITLE = 'New variable type:'; -/** @type {string} */ -/// prompt - Prompts the user to enter the name for a new variable. See [https://github.com/google/blockly/wiki/Variables#dropdown-menu https://github.com/google/blockly/wiki/Variables#dropdown-menu]. -Blockly.Msg.NEW_VARIABLE_TITLE = 'New variable name:'; -/** @type {string} */ -/// alert - Tells the user that the name they entered is already in use. -Blockly.Msg.VARIABLE_ALREADY_EXISTS = 'A variable named "%1" already exists.'; -/** @type {string} */ -/// alert - Tells the user that the name they entered is already in use for another type. -Blockly.Msg.VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE = 'A variable named "%1" already exists for another type: "%2".'; - -// Variable deletion. -/** @type {string} */ -/// confirm - Ask the user to confirm their deletion of multiple uses of a variable. -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = 'Delete %1 uses of the "%2" variable?'; -/** @type {string} */ -/// alert - Tell the user that they can't delete a variable because it's part of the definition of a function. -Blockly.Msg.CANNOT_DELETE_VARIABLE_PROCEDURE = 'Can\'t delete the variable "%1" because it\'s part of the definition of the function "%2"'; -/** @type {string} */ -/// dropdown choice - Delete the currently selected variable. -Blockly.Msg.DELETE_VARIABLE = 'Delete the "%1" variable'; - -// Colour Blocks. -/** @type {string} */ -/// {{Optional}} url - Information about colour. -Blockly.Msg.COLOUR_PICKER_HELPURL = 'https://en.wikipedia.org/wiki/Color'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Colour#picking-a-colour-from-a-palette https://github.com/google/blockly/wiki/Colour#picking-a-colour-from-a-palette]. -Blockly.Msg.COLOUR_PICKER_TOOLTIP = 'Choose a colour from the palette.'; -/** @type {string} */ -/// {{Optional}} url - A link that displays a random colour each time you visit it. -Blockly.Msg.COLOUR_RANDOM_HELPURL = 'http://randomcolour.com'; -/** @type {string} */ -/// block text - Title of block that generates a colour at random. -Blockly.Msg.COLOUR_RANDOM_TITLE = 'random colour'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Colour#generating-a-random-colour https://github.com/google/blockly/wiki/Colour#generating-a-random-colour]. -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = 'Choose a colour at random.'; -/** @type {string} */ -/// {{Optional}} url - A link for colour codes with percentages (0-100%) for each component, instead of the more common 0-255, which may be more difficult for beginners. -Blockly.Msg.COLOUR_RGB_HELPURL = 'https://www.december.com/html/spec/colorpercompact.html'; -/** @type {string} */ -/// block text - Title of block for [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components]. -Blockly.Msg.COLOUR_RGB_TITLE = 'colour with'; -/** @type {string} */ -/// block input text - The amount of red (from 0 to 100) to use when [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components].\n{{Identical|Red}} -Blockly.Msg.COLOUR_RGB_RED = 'red'; -/** @type {string} */ -/// block input text - The amount of green (from 0 to 100) to use when [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components]. -Blockly.Msg.COLOUR_RGB_GREEN = 'green'; -/** @type {string} */ -/// block input text - The amount of blue (from 0 to 100) to use when [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components].\n{{Identical|Blue}} -Blockly.Msg.COLOUR_RGB_BLUE = 'blue'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components]. -Blockly.Msg.COLOUR_RGB_TOOLTIP = 'Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100.'; -/** @type {string} */ -/// {{Optional}} url - A useful link that displays blending of two colours. -Blockly.Msg.COLOUR_BLEND_HELPURL = 'https://meyerweb.com/eric/tools/color-blend/#:::rgbp'; -/** @type {string} */ -/// block text - A verb for blending two shades of paint. -Blockly.Msg.COLOUR_BLEND_TITLE = 'blend'; -/** @type {string} */ -/// block input text - The first of two colours to [https://github.com/google/blockly/wiki/Colour#blending-colours blend]. -Blockly.Msg.COLOUR_BLEND_COLOUR1 = 'colour 1'; -/** @type {string} */ -/// block input text - The second of two colours to [https://github.com/google/blockly/wiki/Colour#blending-colours blend]. -Blockly.Msg.COLOUR_BLEND_COLOUR2 = 'colour 2'; -/** @type {string} */ -/// block input text - The proportion of the [https://github.com/google/blockly/wiki/Colour#blending-colours blend] containing the first colour; the remaining proportion is of the second colour. For example, if the first colour is red and the second colour blue, a ratio of 1 would yield pure red, a ratio of .5 would yield purple (equal amounts of red and blue), and a ratio of 0 would yield pure blue.\n{{Identical|Ratio}} -Blockly.Msg.COLOUR_BLEND_RATIO = 'ratio'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Colour#blending-colours https://github.com/google/blockly/wiki/Colour#blending-colours]. -Blockly.Msg.COLOUR_BLEND_TOOLTIP = 'Blends two colours together with a given ratio (0.0 - 1.0).'; - -// Loop Blocks. -/** @type {string} */ -/// {{Optional}} url - Describes 'repeat loops' in computer programs; consider using the translation of the page [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow]. -Blockly.Msg.CONTROLS_REPEAT_HELPURL = 'https://en.wikipedia.org/wiki/For_loop'; -/** @type {string} */ -/// block input text - Title of [https://github.com/google/blockly/wiki/Loops#repeat repeat block].\n\nParameters:\n* %1 - the number of times the body of the loop should be repeated. -Blockly.Msg.CONTROLS_REPEAT_TITLE = 'repeat %1 times'; -/** @type {string} */ -/// block text - Preceding the blocks in the body of the loop. See [https://github.com/google/blockly/wiki/Loops https://github.com/google/blockly/wiki/Loops].\n{{Identical|Do}} -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = 'do'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#repeat https://github.com/google/blockly/wiki/Loops#repeat]. -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = 'Do some statements several times.'; -/** @type {string} */ -/// {{Optional}} url - Describes 'while loops' in computer programs; consider using the translation of [https://en.wikipedia.org/wiki/While_loop https://en.wikipedia.org/wiki/While_loop], if present, or [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow]. -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = 'https://github.com/google/blockly/wiki/Loops#repeat'; -/** @type {string} */ -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -/** @type {string} */ -/// dropdown - Specifies that a loop should [https://github.com/google/blockly/wiki/Loops#repeat-while repeat while] the following condition is true. -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = 'repeat while'; -/** @type {string} */ -/// dropdown - Specifies that a loop should [https://github.com/google/blockly/wiki/Loops#repeat-until repeat until] the following condition becomes true. -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = 'repeat until'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#repeat-while Loops#repeat-while https://github.com/google/blockly/wiki/Loops#repeat-while Loops#repeat-while]. -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = 'While a value is true, then do some statements.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#repeat-until https://github.com/google/blockly/wiki/Loops#repeat-until]. -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = 'While a value is false, then do some statements.'; - -/** @type {string} */ -/// {{Optional}} url - Describes 'for loops' in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/For_loop https://en.wikipedia.org/wiki/For_loop], if present. -Blockly.Msg.CONTROLS_FOR_HELPURL = 'https://github.com/google/blockly/wiki/Loops#count-with'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#count-with https://github.com/google/blockly/wiki/Loops#count-with].\n\nParameters:\n* %1 - the name of the loop variable. -Blockly.Msg.CONTROLS_FOR_TOOLTIP = 'Have the variable "%1" take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.'; -/** @type {string} */ -/// block text - Repeatedly counts a variable (%1) -/// starting with a (usually lower) number in a range (%2), -/// ending with a (usually higher) number in a range (%3), and counting the -/// iterations by a number of steps (%4). As in -/// [https://github.com/google/blockly/wiki/Loops#count-with -/// https://github.com/google/blockly/wiki/Loops#count-with]. -/// [[File:Blockly-count-with.png]] -Blockly.Msg.CONTROLS_FOR_TITLE = 'count with %1 from %2 to %3 by %4'; -/** @type {string} */ -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; - -/** @type {string} */ -/// {{Optional}} url - Describes 'for-each loops' in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/Foreach https://en.wikipedia.org/wiki/Foreach] if present. -Blockly.Msg.CONTROLS_FOREACH_HELPURL = 'https://github.com/google/blockly/wiki/Loops#for-each'; -/** @type {string} */ -/// block text - Title of [https://github.com/google/blockly/wiki/Loops#for-each for each block]. -/// Sequentially assigns every item in array %2 to the valiable %1. -Blockly.Msg.CONTROLS_FOREACH_TITLE = 'for each item %1 in list %2'; -/** @type {string} */ -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -/** @type {string} */ -/// block text - Description of [https://github.com/google/blockly/wiki/Loops#for-each for each blocks].\n\nParameters:\n* %1 - the name of the loop variable. -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = 'For each item in a list, set the variable "%1" to the item, and then do some statements.'; - -/** @type {string} */ -/// {{Optional}} url - Describes control flow in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow], if it exists. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = 'https://github.com/google/blockly/wiki/Loops#loop-termination-blocks'; -/** @type {string} */ -/// dropdown - The current loop should be exited. See [https://github.com/google/blockly/wiki/Loops#break https://github.com/google/blockly/wiki/Loops#break]. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = 'break out of loop'; -/** @type {string} */ -/// dropdown - The current iteration of the loop should be ended and the next should begin. See [https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration]. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = 'continue with next iteration of loop'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#break-out-of-loop https://github.com/google/blockly/wiki/Loops#break-out-of-loop]. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = 'Break out of the containing loop.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration]. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = 'Skip the rest of this loop, and continue with the next iteration.'; -/** @type {string} */ -/// warning - The user has tried placing a block outside of a loop (for each, while, repeat, etc.), but this type of block may only be used within a loop. See [https://github.com/google/blockly/wiki/Loops#loop-termination-blocks https://github.com/google/blockly/wiki/Loops#loop-termination-blocks]. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = 'Warning: This block may only be used within a loop.'; - -// Logic Blocks. -/** @type {string} */ -/// {{Optional}} url - Describes conditional statements (if-then-else) in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_else https://en.wikipedia.org/wiki/If_else], if present. -Blockly.Msg.CONTROLS_IF_HELPURL = 'https://github.com/google/blockly/wiki/IfElse'; -/** @type {string} */ -/// tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-blocks 'if' blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present. -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = 'If a value is true, then do some statements.'; -/** @type {string} */ -/// tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-else-blocks if-else blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present. -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = 'If a value is true, then do the first block of statements. Otherwise, do the second block of statements.'; -/** @type {string} */ -/// tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-else-if-blocks if-else-if blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present. -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = 'If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements.'; -/** @type {string} */ -/// tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-else-if-else-blocks if-else-if-else blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present. -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = 'If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements.'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/IfElse https://github.com/google/blockly/wiki/IfElse]. -/// It is recommended, but not essential, that this have text in common with the translation of 'else if'\n{{Identical|If}} -Blockly.Msg.CONTROLS_IF_MSG_IF = 'if'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/IfElse https://github.com/google/blockly/wiki/IfElse]. The English words "otherwise if" would probably be clearer than "else if", but the latter is used because it is traditional and shorter. -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = 'else if'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/IfElse https://github.com/google/blockly/wiki/IfElse]. The English word "otherwise" would probably be superior to "else", but the latter is used because it is traditional and shorter. -Blockly.Msg.CONTROLS_IF_MSG_ELSE = 'else'; -/** @type {string} */ -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -/** @type {string} */ -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -/** @type {string} */ -/// tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#block-modification if block modification]. -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this if block.'; -/** @type {string} */ -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -/** @type {string} */ -/// tooltip - Describes the 'else if' subblock during [https://github.com/google/blockly/wiki/IfElse#block-modification if block modification]. -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = 'Add a condition to the if block.'; -/** @type {string} */ -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -/** @type {string} */ -/// tooltip - Describes the 'else' subblock during [https://github.com/google/blockly/wiki/IfElse#block-modification if block modification]. -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = 'Add a final, catch-all condition to the if block.'; - -/** @type {string} */ -/// {{Optional}} url - Information about comparisons. -Blockly.Msg.LOGIC_COMPARE_HELPURL = 'https://en.wikipedia.org/wiki/Inequality_(mathematics)'; -/** @type {string} */ -/// tooltip - Describes the equals (=) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = 'Return true if both inputs equal each other.'; -/** @type {string} */ -/// tooltip - Describes the not equals (≠) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = 'Return true if both inputs are not equal to each other.'; -/** @type {string} */ -/// tooltip - Describes the less than (<) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = 'Return true if the first input is smaller than the second input.'; -/** @type {string} */ -/// tooltip - Describes the less than or equals (≤) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = 'Return true if the first input is smaller than or equal to the second input.'; -/** @type {string} */ -/// tooltip - Describes the greater than (>) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = 'Return true if the first input is greater than the second input.'; -/** @type {string} */ -/// tooltip - Describes the greater than or equals (≥) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = 'Return true if the first input is greater than or equal to the second input.'; - -/** @type {string} */ -/// {{Optional}} url - Information about the Boolean conjunction ("and") and disjunction ("or") operators. Consider using the translation of [https://en.wikipedia.org/wiki/Boolean_logic https://en.wikipedia.org/wiki/Boolean_logic], if it exists in your language. -Blockly.Msg.LOGIC_OPERATION_HELPURL = 'https://github.com/google/blockly/wiki/Logic#logical-operations'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Logical_conjunction https://en.wikipedia.org/wiki/Logical_conjunction]. -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = 'Return true if both inputs are true.'; -/** @type {string} */ -/// block text - See [https://en.wikipedia.org/wiki/Logical_conjunction https://en.wikipedia.org/wiki/Logical_conjunction].\n{{Identical|And}} -Blockly.Msg.LOGIC_OPERATION_AND = 'and'; -/** @type {string} */ -/// block text - See [https://en.wikipedia.org/wiki/Disjunction https://en.wikipedia.org/wiki/Disjunction]. -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = 'Return true if at least one of the inputs is true.'; -/** @type {string} */ -/// block text - See [https://en.wikipedia.org/wiki/Disjunction https://en.wikipedia.org/wiki/Disjunction].\n{{Identical|Or}} -Blockly.Msg.LOGIC_OPERATION_OR = 'or'; - -/** @type {string} */ -/// {{Optional}} url - Information about logical negation. The translation of [https://en.wikipedia.org/wiki/Logical_negation https://en.wikipedia.org/wiki/Logical_negation] is recommended if it exists in the target language. -Blockly.Msg.LOGIC_NEGATE_HELPURL = 'https://github.com/google/blockly/wiki/Logic#not'; -/** @type {string} */ -/// block text - This is a unary operator that returns ''false'' when the input is ''true'', and ''true'' when the input is ''false''. -/// \n\nParameters:\n* %1 - the input (which should be either the value "true" or "false") -Blockly.Msg.LOGIC_NEGATE_TITLE = 'not %1'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Logical_negation https://en.wikipedia.org/wiki/Logical_negation]. -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = 'Returns true if the input is false. Returns false if the input is true.'; - -/** @type {string} */ -/// {{Optional}} url - Information about the logic values ''true'' and ''false''. Consider using the translation of [https://en.wikipedia.org/wiki/Truth_value https://en.wikipedia.org/wiki/Truth_value] if it exists in your language. -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = 'https://github.com/google/blockly/wiki/Logic#values'; -/** @type {string} */ -/// block text - The word for the [https://en.wikipedia.org/wiki/Truth_value logical value] ''true''.\n{{Identical|True}} -Blockly.Msg.LOGIC_BOOLEAN_TRUE = 'true'; -/** @type {string} */ -/// block text - The word for the [https://en.wikipedia.org/wiki/Truth_value logical value] ''false''.\n{{Identical|False}} -Blockly.Msg.LOGIC_BOOLEAN_FALSE = 'false'; -/** @type {string} */ -/// tooltip - Indicates that the block returns either of the two possible [https://en.wikipedia.org/wiki/Truth_value logical values]. -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = 'Returns either true or false.'; - -/** @type {string} */ -/// {{Optional}} url - Provide a link to the translation of [https://en.wikipedia.org/wiki/Nullable_type https://en.wikipedia.org/wiki/Nullable_type], if it exists in your language; otherwise, do not worry about translating this advanced concept. -Blockly.Msg.LOGIC_NULL_HELPURL = 'https://en.wikipedia.org/wiki/Nullable_type'; -/** @type {string} */ -/// block text - In computer languages, ''null'' is a special value that indicates that no value has been set. You may use your language's word for "nothing" or "invalid".\n{{Identical|Null}} -Blockly.Msg.LOGIC_NULL = 'null'; -/** @type {string} */ -/// tooltip - This should use the word from the previous message. -Blockly.Msg.LOGIC_NULL_TOOLTIP = 'Returns null.'; - -/** @type {string} */ -/// {{Optional}} url - Describes the programming language operator known as the ''ternary'' or ''conditional'' operator. It is recommended that you use the translation of [https://en.wikipedia.org/wiki/%3F: https://en.wikipedia.org/wiki/%3F:] if it exists. -Blockly.Msg.LOGIC_TERNARY_HELPURL = 'https://en.wikipedia.org/wiki/%3F:'; -/** @type {string} */ -/// block input text - Label for the input whose value determines which of the other two inputs is returned. In some programming languages, this is called a ''''predicate''''. -Blockly.Msg.LOGIC_TERNARY_CONDITION = 'test'; -/** @type {string} */ -/// block input text - Indicates that the following input should be returned (used as output) if the test input is true. Remember to try to keep block text terse (short). -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = 'if true'; -/** @type {string} */ -/// block input text - Indicates that the following input should be returned (used as output) if the test input is false. -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = 'if false'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/%3F: https://en.wikipedia.org/wiki/%3F:]. -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = 'Check the condition in "test". If the condition is true, returns the "if true" value; otherwise returns the "if false" value.'; - -// Math Blocks. -/** @type {string} */ -/// {{Optional}} url - Information about (real) numbers. -Blockly.Msg.MATH_NUMBER_HELPURL = 'https://en.wikipedia.org/wiki/Number'; -/** @type {string} */ -/// tooltip - Any positive or negative number, not necessarily an integer. -Blockly.Msg.MATH_NUMBER_TOOLTIP = 'A number.'; - -/** @type {string} */ -/// {{Optional}} math - The symbol for the binary operation addition. -Blockly.Msg.MATH_ADDITION_SYMBOL = '+'; -/** @type {string} */ -/// {{Optional}} math - The symbol for the binary operation indicating that the right operand should be -/// subtracted from the left operand. -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = '-'; -/** @type {string} */ -/// {{Optional}} math - The binary operation indicating that the left operand should be divided by -/// the right operand. -Blockly.Msg.MATH_DIVISION_SYMBOL = '÷'; -/** @type {string} */ -/// {{Optional}} math - The symbol for the binary operation multiplication. -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = '×'; -/** @type {string} */ -/// {{Optional}} math - The symbol for the binary operation exponentiation. Specifically, if the -/// value of the left operand is L and the value of the right operand (the exponent) is -/// R, multiply L by itself R times. (Fractional and negative exponents are also legal.) -Blockly.Msg.MATH_POWER_SYMBOL = '^'; - -/** @type {string} */ -/// math - The short name of the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine]. -Blockly.Msg.MATH_TRIG_SIN = 'sin'; -/** @type {string} */ -/// math - The short name of the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine]. -Blockly.Msg.MATH_TRIG_COS = 'cos'; -/** @type {string} */ -/// math - The short name of the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent]. -Blockly.Msg.MATH_TRIG_TAN = 'tan'; -/** @type {string} */ -/// math - The short name of the ''inverse of'' the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine]. -Blockly.Msg.MATH_TRIG_ASIN = 'asin'; -/** @type {string} */ -/// math - The short name of the ''inverse of'' the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine]. -Blockly.Msg.MATH_TRIG_ACOS = 'acos'; -/** @type {string} */ -/// math - The short name of the ''inverse of'' the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent]. -Blockly.Msg.MATH_TRIG_ATAN = 'atan'; - -/** @type {string} */ -/// {{Optional}} url - Information about addition, subtraction, multiplication, division, and exponentiation. -Blockly.Msg.MATH_ARITHMETIC_HELPURL = 'https://en.wikipedia.org/wiki/Arithmetic'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Addition https://en.wikipedia.org/wiki/Addition]. -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = 'Return the sum of the two numbers.'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Subtraction https://en.wikipedia.org/wiki/Subtraction]. -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = 'Return the difference of the two numbers.'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Multiplication https://en.wikipedia.org/wiki/Multiplication]. -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = 'Return the product of the two numbers.'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Division_(mathematics) https://en.wikipedia.org/wiki/Division_(mathematics)]. -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = 'Return the quotient of the two numbers.'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Exponentiation https://en.wikipedia.org/wiki/Exponentiation]. -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = 'Return the first number raised to the power of the second number.'; - -/** @type {string} */ -/// {{Optional}} url - Information about the square root operation. -Blockly.Msg.MATH_SINGLE_HELPURL = 'https://en.wikipedia.org/wiki/Square_root'; -/** @type {string} */ -/// dropdown - This computes the positive [https://en.wikipedia.org/wiki/Square_root square root] of its input. For example, the square root of 16 is 4. -Blockly.Msg.MATH_SINGLE_OP_ROOT = 'square root'; -/** @type {string} */ -/// tooltip - Please use the same term as in the previous message. -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = 'Return the square root of a number.'; -/** @type {string} */ -/// dropdown - This leaves positive numeric inputs changed and inverts negative inputs. For example, the absolute value of 5 is 5; the absolute value of -5 is also 5. For more information, see [https://en.wikipedia.org/wiki/Absolute_value https://en.wikipedia.org/wiki/Absolute_value]. -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = 'absolute'; -/** @type {string} */ -/// tooltip - Please use the same term as in the previous message. -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = 'Return the absolute value of a number.'; - -/** @type {string} */ -/// tooltip - Calculates '''0-n''', where '''n''' is the single numeric input. -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = 'Return the negation of a number.'; -/** @type {string} */ -/// tooltip - Calculates the [https://en.wikipedia.org/wiki/Natural_logarithm|natural logarithm] of its single numeric input. -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = 'Return the natural logarithm of a number.'; -/** @type {string} */ -/// tooltip - Calculates the [https://en.wikipedia.org/wiki/Common_logarithm common logarithm] of its single numeric input. -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = 'Return the base 10 logarithm of a number.'; -/** @type {string} */ -/// tooltip - Multiplies [https://en.wikipedia.org/wiki/E_(mathematical_constant) e] by itself n times, where n is the single numeric input. -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = 'Return e to the power of a number.'; -/** @type {string} */ -/// tooltip - Multiplies 10 by itself n times, where n is the single numeric input. -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = 'Return 10 to the power of a number.'; - -/** @type {string} */ -/// {{Optional}} url - Information about the trigonometric functions sine, cosine, tangent, and their inverses (ideally using degrees, not radians). -Blockly.Msg.MATH_TRIG_HELPURL = 'https://en.wikipedia.org/wiki/Trigonometric_functions'; -/** @type {string} */ -/// tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = 'Return the sine of a degree (not radian).'; -/** @type {string} */ -/// tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = 'Return the cosine of a degree (not radian).'; -/** @type {string} */ -/// tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = 'Return the tangent of a degree (not radian).'; -/** @type {string} */ -/// tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent sine function], using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = 'Return the arcsine of a number.'; -/** @type {string} */ -/// tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent cosine] function, using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = 'Return the arccosine of a number.'; -/** @type {string} */ -/// tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent tangent] function, using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = 'Return the arctangent of a number.'; - -/** @type {string} */ -/// {{Optional}} url - Information about the mathematical constants Pi (π), e, the golden ratio (φ), √ 2, √ 1/2, and infinity (∞). -Blockly.Msg.MATH_CONSTANT_HELPURL = 'https://en.wikipedia.org/wiki/Mathematical_constant'; -/** @type {string} */ -/// tooltip - Provides the specified [https://en.wikipedia.org/wiki/Mathematical_constant mathematical constant]. -Blockly.Msg.MATH_CONSTANT_TOOLTIP = 'Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).'; -/** @type {string} */ -/// dropdown - A number is '''even''' if it is a multiple of 2. For example, 4 is even (yielding true), but 3 is not (false). -Blockly.Msg.MATH_IS_EVEN = 'is even'; -/** @type {string} */ -/// dropdown - A number is '''odd''' if it is not a multiple of 2. For example, 3 is odd (yielding true), but 4 is not (false). The opposite of "odd" is "even". -Blockly.Msg.MATH_IS_ODD = 'is odd'; -/** @type {string} */ -/// dropdown - A number is [https://en.wikipedia.org/wiki/Prime prime] if it cannot be evenly divided by any positive integers except for 1 and itself. For example, 5 is prime, but 6 is not because 2 × 3 = 6. -Blockly.Msg.MATH_IS_PRIME = 'is prime'; -/** @type {string} */ -/// dropdown - A number is '''whole''' if it is an [https://en.wikipedia.org/wiki/Integer integer]. For example, 5 is whole, but 5.1 is not. -Blockly.Msg.MATH_IS_WHOLE = 'is whole'; -/** @type {string} */ -/// dropdown - A number is '''positive''' if it is greater than 0. (0 is neither negative nor positive.) -Blockly.Msg.MATH_IS_POSITIVE = 'is positive'; -/** @type {string} */ -/// dropdown - A number is '''negative''' if it is less than 0. (0 is neither negative nor positive.) -Blockly.Msg.MATH_IS_NEGATIVE = 'is negative'; -/** @type {string} */ -/// dropdown - A number x is divisible by y if y goes into x evenly. For example, 10 is divisible by 5, but 10 is not divisible by 3. -Blockly.Msg.MATH_IS_DIVISIBLE_BY = 'is divisible by'; -/** @type {string} */ -/// tooltip - This block lets the user specify via a dropdown menu whether to check if the numeric input is even, odd, prime, whole, positive, negative, or divisible by a given value. -Blockly.Msg.MATH_IS_TOOLTIP = 'Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false.'; - -/** @type {string} */ -/// {{Optional}} url - Information about incrementing (increasing the value of) a variable. -/// For other languages, just use the translation of the Wikipedia page about -/// addition ([https://en.wikipedia.org/wiki/Addition https://en.wikipedia.org/wiki/Addition]). -Blockly.Msg.MATH_CHANGE_HELPURL = 'https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter'; -/** @type {string} */ -/// - As in: ''change'' [the value of variable] ''item'' ''by'' 1 (e.g., if the variable named 'item' had the value 5, change it to 6). -/// %1 is a variable name. -/// %2 is the amount of change. -Blockly.Msg.MATH_CHANGE_TITLE = 'change %1 by %2'; -/** @type {string} */ -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -/** @type {string} */ -/// tooltip - This updates the value of the variable by adding to it the following numeric input.\n\nParameters:\n* %1 - the name of the variable whose value should be increased. -Blockly.Msg.MATH_CHANGE_TOOLTIP = 'Add a number to variable "%1".'; - -/** @type {string} */ -/// {{Optional}} url - Information about how numbers are rounded to the nearest integer -Blockly.Msg.MATH_ROUND_HELPURL = 'https://en.wikipedia.org/wiki/Rounding'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Rounding https://en.wikipedia.org/wiki/Rounding]. -Blockly.Msg.MATH_ROUND_TOOLTIP = 'Round a number up or down.'; -/** @type {string} */ -/// dropdown - This rounds its input to the nearest whole number. For example, 3.4 is rounded to 3. -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = 'round'; -/** @type {string} */ -/// dropdown - This rounds its input up to the nearest whole number. For example, if the input was 2.2, the result would be 3. -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = 'round up'; -/** @type {string} */ -/// dropdown - This rounds its input down to the nearest whole number. For example, if the input was 3.8, the result would be 3. -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = 'round down'; - -/** @type {string} */ -/// {{Optional}} url - Information about applying a function to a list of numbers. (We were unable to find such information in English. Feel free to skip this and any other URLs that are difficult.) -Blockly.Msg.MATH_ONLIST_HELPURL = ''; -/** @type {string} */ -/// dropdown - This computes the sum of the numeric elements in the list. For example, the sum of the list {1, 4} is 5. -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = 'sum of list'; -/** @type {string} */ -/// tooltip - Please use the same term for "sum" as in the previous message. -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = 'Return the sum of all the numbers in the list.'; -/** @type {string} */ -/// dropdown - This finds the smallest (minimum) number in a list. For example, the smallest number in the list [-5, 0, 3] is -5. -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = 'min of list'; -/** @type {string} */ -/// tooltip - Please use the same term for "min" or "minimum" as in the previous message. -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = 'Return the smallest number in the list.'; -/** @type {string} */ -/// dropdown - This finds the largest (maximum) number in a list. For example, the largest number in the list [-5, 0, 3] is 3. -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = 'max of list'; -/** @type {string} */ -/// tooltip -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = 'Return the largest number in the list.'; -/** @type {string} */ -/// dropdown - This adds up all of the numbers in a list and divides the sum by the number of elements in the list. For example, the [https://en.wikipedia.org/wiki/Arithmetic_mean average] of the list [1, 2, 3, 4] is 2.5 (10/4). -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = 'average of list'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Arithmetic_mean https://en.wikipedia.org/wiki/Arithmetic_mean] for more informatin. -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = 'Return the average (arithmetic mean) of the numeric values in the list.'; -/** @type {string} */ -/// dropdown - This finds the [https://en.wikipedia.org/wiki/Median median] of the numeric values in a list. For example, the median of the list {1, 2, 7, 12, 13} is 7. -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = 'median of list'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Median median https://en.wikipedia.org/wiki/Median median] for more information. -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = 'Return the median number in the list.'; -/** @type {string} */ -/// dropdown - This finds the most common numbers ([https://en.wikipedia.org/wiki/Mode_(statistics) modes]) in a list. For example, the modes of the list {1, 3, 9, 3, 9} are {3, 9}. -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = 'modes of list'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Mode_(statistics) https://en.wikipedia.org/wiki/Mode_(statistics)] for more information. -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = 'Return a list of the most common item(s) in the list.'; -/** @type {string} */ -/// dropdown - This finds the [https://en.wikipedia.org/wiki/Standard_deviation standard deviation] of the numeric values in a list. -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = 'standard deviation of list'; -/** @type {string} */ -/// tooltip - See [https://en.wikipedia.org/wiki/Standard_deviation https://en.wikipedia.org/wiki/Standard_deviation] for more information. -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = 'Return the standard deviation of the list.'; -/** @type {string} */ -/// dropdown - This choose an element at random from a list. Each element is chosen with equal probability. -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = 'random item of list'; -/** @type {string} */ -/// tooltip - Please use same term for 'random' as in previous entry. -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = 'Return a random element from the list.'; - -/** @type {string} */ -/// {{Optional}} url - information about the modulo (remainder) operation. -Blockly.Msg.MATH_MODULO_HELPURL = 'https://en.wikipedia.org/wiki/Modulo_operation'; -/** @type {string} */ -/// block text - Title of block providing the remainder when dividing the first numerical input by the second. For example, the remainder of 10 divided by 3 is 1.\n\nParameters:\n* %1 - the dividend (10, in our example)\n* %2 - the divisor (3 in our example). -Blockly.Msg.MATH_MODULO_TITLE = 'remainder of %1 ÷ %2'; -/** @type {string} */ -/// tooltip - For example, the remainder of 10 divided by 3 is 1. -Blockly.Msg.MATH_MODULO_TOOLTIP = 'Return the remainder from dividing the two numbers.'; - -/** @type {string} */ -/// {{Optional}} url - Information about constraining a numeric value to be in a specific range. (The English URL is not ideal. Recall that translating URLs is the lowest priority.) -Blockly.Msg.MATH_CONSTRAIN_HELPURL = 'https://en.wikipedia.org/wiki/Clamping_(graphics)'; -/** @type {string} */ -/// block text - The title of the block that '''constrain'''s (forces) a number to be in a given range. -///For example, if the number 150 is constrained to be between 5 and 100, the result will be 100. -///\n\nParameters:\n* %1 - the value to constrain (e.g., 150)\n* %2 - the minimum value (e.g., 5)\n* %3 - the maximum value (e.g., 100). -Blockly.Msg.MATH_CONSTRAIN_TITLE = 'constrain %1 low %2 high %3'; -/** @type {string} */ -/// tooltip - This compares a number ''x'' to a low value ''L'' and a high value ''H''. If ''x'' is less then ''L'', the result is ''L''. If ''x'' is greater than ''H'', the result is ''H''. Otherwise, the result is ''x''. -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = 'Constrain a number to be between the specified limits (inclusive).'; - -/** @type {string} */ -/// {{Optional}} url - Information about how computers generate random numbers. -Blockly.Msg.MATH_RANDOM_INT_HELPURL = 'https://en.wikipedia.org/wiki/Random_number_generation'; -/** @type {string} */ -/// block text - The title of the block that generates a random integer (whole number) in the specified range. For example, if the range is from 5 to 7, this returns 5, 6, or 7 with equal likelihood. %1 is a placeholder for the lower number, %2 is the placeholder for the larger number. -Blockly.Msg.MATH_RANDOM_INT_TITLE = 'random integer from %1 to %2'; -/** @type {string} */ -/// tooltip - Return a random integer between two values specified as inputs. For example, if one input was 7 and another 9, any of the numbers 7, 8, or 9 could be produced. -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = 'Return a random integer between the two specified limits, inclusive.'; - -/** @type {string} */ -/// {{Optional}} url - Information about how computers generate random numbers (specifically, numbers in the range from 0 to just below 1). -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = 'https://en.wikipedia.org/wiki/Random_number_generation'; -/** @type {string} */ -/// block text - The title of the block that generates a random number greater than or equal to 0 and less than 1. -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = 'random fraction'; -/** @type {string} */ -/// tooltip - Return a random fraction between 0 and 1. The value may be equal to 0 but must be less than 1. -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = 'Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).'; - -/** @type {string} */ -/// {{Optional}} url - Information about how to calculate atan2. -Blockly.Msg.MATH_ATAN2_HELPURL = 'https://en.wikipedia.org/wiki/Atan2'; -/** @type {string} */ -/// block text - The title of the block that calculates atan2 of point (X, Y). For example, if the point is (-1, -1), this returns -135. %1 is a placeholder for the X coordinate, %2 is the placeholder for the Y coordinate. -Blockly.Msg.MATH_ATAN2_TITLE = 'atan2 of X:%1 Y:%2'; -/** @type {string} */ -/// tooltip - Return the arctangent of point (X, Y) in degrees from -180 to 180. For example, if the point is (-1, -1) this returns -135. -Blockly.Msg.MATH_ATAN2_TOOLTIP = 'Return the arctangent of point (X, Y) in degrees from -180 to 180.'; - -// Text Blocks. -/** @type {string} */ -/// {{Optional}} url - Information about how computers represent text (sometimes referred to as ''string''s). -Blockly.Msg.TEXT_TEXT_HELPURL = 'https://en.wikipedia.org/wiki/String_(computer_science)'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Text https://github.com/google/blockly/wiki/Text]. -Blockly.Msg.TEXT_TEXT_TOOLTIP = 'A letter, word, or line of text.'; - -/** @type {string} */ -/// {{Optional}} url - Information on concatenating/appending pieces of text. -Blockly.Msg.TEXT_JOIN_HELPURL = 'https://github.com/google/blockly/wiki/Text#text-creation'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation]. -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = 'create text with'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Text#text-creation create text with] for more information. -Blockly.Msg.TEXT_JOIN_TOOLTIP = 'Create a piece of text by joining together any number of items.'; - -/** @type {string} */ -/// block text - This is shown when the programmer wants to change the number of pieces of text being joined together. See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation], specifically the last picture in the 'Text creation' section.\n{{Identical|Join}} -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = 'join'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation], specifically the last picture in the 'Text creation' section. -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this text block.'; -/** @type {string} */ -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation], specifically the last picture in the 'Text creation' section. -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = 'Add an item to the text.'; - -/** @type {string} */ -/// {{Optional}} url - This and the other text-related URLs are going to be hard to translate. As always, it is okay to leave untranslated or paste in the English-language URL. For these URLs, you might also consider a general URL about how computers represent text (such as the translation of [https://en.wikipedia.org/wiki/String_(computer_science) this Wikipedia page]). -Blockly.Msg.TEXT_APPEND_HELPURL = 'https://github.com/google/blockly/wiki/Text#text-modification'; -/** @type {string} */ -/// block input text - Message that the variable name at %1 will have the item at %2 appended to it. -/// [[File:blockly-append-text.png]] -Blockly.Msg.TEXT_APPEND_TITLE = 'to %1 append text %2'; -/** @type {string} */ -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Text#text-modification https://github.com/google/blockly/wiki/Text#text-modification] for more information.\n\nParameters:\n* %1 - the name of the variable to which text should be appended -Blockly.Msg.TEXT_APPEND_TOOLTIP = 'Append some text to variable "%1".'; - -/** @type {string} */ -/// {{Optional}} url - Information about text on computers (usually referred to as 'strings'). -Blockly.Msg.TEXT_LENGTH_HELPURL = 'https://github.com/google/blockly/wiki/Text#text-modification'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/Text#text-length https://github.com/google/blockly/wiki/Text#text-length]. -/// \n\nParameters:\n* %1 - the piece of text to take the length of -Blockly.Msg.TEXT_LENGTH_TITLE = 'length of %1'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Text#text-length https://github.com/google/blockly/wiki/Text#text-length]. -Blockly.Msg.TEXT_LENGTH_TOOLTIP = 'Returns the number of letters (including spaces) in the provided text.'; - -/** @type {string} */ -/// {{Optional}} url - Information about empty pieces of text on computers (usually referred to as 'empty strings'). -Blockly.Msg.TEXT_ISEMPTY_HELPURL = 'https://github.com/google/blockly/wiki/Text#checking-for-empty-text'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/Text#checking-for-empty-text https://github.com/google/blockly/wiki/Text#checking-for-empty-text]. -/// \n\nParameters:\n* %1 - the piece of text to test for emptiness -Blockly.Msg.TEXT_ISEMPTY_TITLE = '%1 is empty'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Text#checking-for-empty-text https://github.com/google/blockly/wiki/Text#checking-for-empty-text]. -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = 'Returns true if the provided text is empty.'; - -/** @type {string} */ -/// {{Optional}} url - Information about finding a character in a piece of text. -Blockly.Msg.TEXT_INDEXOF_HELPURL = 'https://github.com/google/blockly/wiki/Text#finding-text'; -/** @type {string} */ -/// tooltip - %1 will be replaced by either the number 0 or -1 depending on the indexing mode. See [https://github.com/google/blockly/wiki/Text#finding-text https://github.com/google/blockly/wiki/Text#finding-text]. -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = 'Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found.'; -/** @type {string} */ -/// block text - Title of blocks allowing users to find text. See -/// [https://github.com/google/blockly/wiki/Text#finding-text -/// https://github.com/google/blockly/wiki/Text#finding-text]. -/// [[File:Blockly-find-text.png]]. -/// In English the expanded message is "in text %1 find (first|last) occurance of text %3" -/// where %1 and %3 are added by the user. See TEXT_INDEXOF_OPERATOR_FIRST and -/// TEXT_INDEXOF_OPERATOR_LAST for the dropdown text that replaces %2. -Blockly.Msg.TEXT_INDEXOF_TITLE = 'in text %1 %2 %3'; -/** @type {string} */ -/// dropdown - See [https://github.com/google/blockly/wiki/Text#finding-text -/// https://github.com/google/blockly/wiki/Text#finding-text]. -/// [[File:Blockly-find-text.png]]. -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = 'find first occurrence of text'; -/** @type {string} */ -/// dropdown - See [https://github.com/google/blockly/wiki/Text#finding-text -/// https://github.com/google/blockly/wiki/Text#finding-text]. This would -/// replace "find first occurrence of text" below. (For more information on -/// how common text is factored out of dropdown menus, see -/// [https://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus -/// https://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus)].) -/// [[File:Blockly-find-text.png]]. -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = 'find last occurrence of text'; -/** @type {string} */ - -/// {{Optional}} url - Information about extracting characters (letters, number, symbols, etc.) from text. -Blockly.Msg.TEXT_CHARAT_HELPURL = 'https://github.com/google/blockly/wiki/Text#extracting-text'; -/** @type {string} */ -/// block text - Text for a block to extract a letter (or number, -/// punctuation character, etc.) from a string, as shown below. %1 is added by -/// the user and %2 is replaced by a dropdown of options, possibly followed by -/// another user supplied string. TEXT_CHARAT_TAIL is then added to the end. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_TITLE = 'in text %1 %2'; -/** @type {string} */ -/// dropdown - Indicates that the letter (or number, punctuation character, etc.) with the -/// specified index should be obtained from the preceding piece of text. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_FROM_START = 'get letter #'; -/** @type {string} */ -/// block text - Indicates that the letter (or number, punctuation character, etc.) with the -/// specified index from the end of a given piece of text should be obtained. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_FROM_END = 'get letter # from end'; -/** @type {string} */ -/// block text - Indicates that the first letter of the following piece of text should be -/// retrieved. See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_FIRST = 'get first letter'; -/** @type {string} */ -/// block text - Indicates that the last letter (or number, punctuation mark, etc.) of the -/// following piece of text should be retrieved. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_LAST = 'get last letter'; -/** @type {string} */ -/// block text - Indicates that any letter (or number, punctuation mark, etc.) in the -/// following piece of text should be randomly selected. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_RANDOM = 'get random letter'; -/** @type {string} */ -/// block text - Text that goes after the rightmost block/dropdown when getting a single letter from -/// a piece of text, as in [https://blockly-demo.appspot.com/static/apps/code/index.html#3m23km these -/// blocks] or shown below. For most languages, this will be blank. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_TAIL = ''; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_TOOLTIP = 'Returns the letter at the specified position.'; - -/** @type {string} */ -/// See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = 'Returns a specified portion of the text.'; -/** @type {string} */ -/// {{Optional}} url - Information about extracting characters from text. Reminder: urls are the -/// lowest priority translations. Feel free to skip. -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = 'https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text'; -/** @type {string} */ -/// block text - Precedes a piece of text from which a portion should be extracted. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = 'in text'; -/** @type {string} */ -/// dropdown - Indicates that the following number specifies the position (relative to the start -/// position) of the beginning of the region of text that should be obtained from the preceding -/// piece of text. See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = 'get substring from letter #'; -/** @type {string} */ -/// dropdown - Indicates that the following number specifies the position (relative to the end -/// position) of the beginning of the region of text that should be obtained from the preceding -/// piece of text. See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// Note: If {{msg-blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will -/// automatically appear ''after'' this and any other -/// [https://translatewiki.net/wiki/Translating:Blockly#Ordinal_numbers ordinal numbers] -/// on this block. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = 'get substring from letter # from end'; -/** @type {string} */ -/// block text - Indicates that a region starting with the first letter of the preceding piece -/// of text should be extracted. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = 'get substring from first letter'; -/** @type {string} */ -/// dropdown - Indicates that the following number specifies the position (relative to -/// the start position) of the end of the region of text that should be obtained from the -/// preceding piece of text. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = 'to letter #'; -/** @type {string} */ -/// dropdown - Indicates that the following number specifies the position (relative to the -/// end position) of the end of the region of text that should be obtained from the preceding -/// piece of text. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = 'to letter # from end'; -/** @type {string} */ -/// block text - Indicates that a region ending with the last letter of the preceding piece -/// of text should be extracted. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = 'to last letter'; -/** @type {string} */ -/// block text - Text that should go after the rightmost block/dropdown when -/// [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// extracting a region of text]. In most languages, this will be the empty string. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ''; - -/** @type {string} */ -/// {{Optional}} url - Information about the case of letters (upper-case and lower-case). -Blockly.Msg.TEXT_CHANGECASE_HELPURL = 'https://github.com/google/blockly/wiki/Text#adjusting-text-case'; -/** @type {string} */ -/// tooltip - Describes a block to adjust the case of letters. For more information on this block, -/// see [https://github.com/google/blockly/wiki/Text#adjusting-text-case -/// https://github.com/google/blockly/wiki/Text#adjusting-text-case]. -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = 'Return a copy of the text in a different case.'; -/** @type {string} */ -/// block text - Indicates that all of the letters in the following piece of text should be -/// capitalized. If your language does not use case, you may indicate that this is not -/// applicable to your language. For more information on this block, see -/// [https://github.com/google/blockly/wiki/Text#adjusting-text-case -/// https://github.com/google/blockly/wiki/Text#adjusting-text-case]. -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = 'to UPPER CASE'; -/** @type {string} */ -/// block text - Indicates that all of the letters in the following piece of text should be converted to lower-case. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://github.com/google/blockly/wiki/Text#adjusting-text-case https://github.com/google/blockly/wiki/Text#adjusting-text-case]. -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = 'to lower case'; -/** @type {string} */ -/// block text - Indicates that the first letter of each of the following words should be capitalized and the rest converted to lower-case. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://github.com/google/blockly/wiki/Text#adjusting-text-case https://github.com/google/blockly/wiki/Text#adjusting-text-case]. -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = 'to Title Case'; - -/** @type {string} */ -/// {{Optional}} url - Information about trimming (removing) text off the beginning and ends of pieces of text. -Blockly.Msg.TEXT_TRIM_HELPURL = 'https://github.com/google/blockly/wiki/Text#trimming-removing-spaces'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces -/// https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. -Blockly.Msg.TEXT_TRIM_TOOLTIP = 'Return a copy of the text with spaces removed from one or both ends.'; -/** @type {string} */ -/// dropdown - Removes spaces from the beginning and end of a piece of text. See -/// [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces -/// https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. Note that neither -/// this nor the other options modify the original piece of text (that follows); -/// the block just returns a version of the text without the specified spaces. -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = 'trim spaces from both sides of'; -/** @type {string} */ -/// dropdown - Removes spaces from the beginning of a piece of text. See -/// [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces -/// https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. -/// Note that in right-to-left scripts, this will remove spaces from the right side. -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = 'trim spaces from left side of'; -/** @type {string} */ -/// dropdown - Removes spaces from the end of a piece of text. See -/// [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces -/// https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. -/// Note that in right-to-left scripts, this will remove spaces from the left side. -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = 'trim spaces from right side of'; - -/** @type {string} */ -/// {{Optional}} url - Information about displaying text on computers. -Blockly.Msg.TEXT_PRINT_HELPURL = 'https://github.com/google/blockly/wiki/Text#printing-text'; -/** @type {string} */ -/// block text - Display the input on the screen. See -/// [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -/// \n\nParameters:\n* %1 - the value to print -Blockly.Msg.TEXT_PRINT_TITLE = 'print %1'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -Blockly.Msg.TEXT_PRINT_TOOLTIP = 'Print the specified text, number or other value.'; -/** @type {string} */ -/// {{Optional}} url - Information about getting text from users. -Blockly.Msg.TEXT_PROMPT_HELPURL = 'https://github.com/google/blockly/wiki/Text#getting-input-from-the-user'; -/** @type {string} */ -/// dropdown - Specifies that a piece of text should be requested from the user with -/// the following message. See [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = 'prompt for text with message'; -/** @type {string} */ -/// dropdown - Specifies that a number should be requested from the user with the -/// following message. See [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = 'prompt for number with message'; -/** @type {string} */ -/// dropdown - Precedes the message with which the user should be prompted for -/// a number. See [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = 'Prompt for user for a number.'; -/** @type {string} */ -/// dropdown - Precedes the message with which the user should be prompted for some text. -/// See [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = 'Prompt for user for some text.'; - -/** @type {string} */ -/// block text - Title of a block that counts the number of instances of -/// a smaller pattern (%1) inside a longer string (%2). -Blockly.Msg.TEXT_COUNT_MESSAGE0 = 'count %1 in %2'; -/** @type {string} */ -/// {{Optional}} url - Information about counting how many times a string appears in another string. -Blockly.Msg.TEXT_COUNT_HELPURL = 'https://github.com/google/blockly/wiki/Text#counting-substrings'; -/** @type {string} */ -/// tooltip - Short description of a block that counts how many times some text occurs within some other text. -Blockly.Msg.TEXT_COUNT_TOOLTIP = 'Count how many times some text occurs within some other text.'; - -/** @type {string} */ -/// block text - Title of a block that returns a copy of text (%3) with all -/// instances of some smaller text (%1) replaced with other text (%2). -Blockly.Msg.TEXT_REPLACE_MESSAGE0 = 'replace %1 with %2 in %3'; -/** @type {string} */ -/// {{Optional}} url - Information about replacing each copy text (or string, in computer lingo) with other text. -Blockly.Msg.TEXT_REPLACE_HELPURL = 'https://github.com/google/blockly/wiki/Text#replacing-substrings'; -/** @type {string} */ -/// tooltip - Short description of a block that replaces copies of text in a large text with other text. -Blockly.Msg.TEXT_REPLACE_TOOLTIP = 'Replace all occurances of some text within some other text.'; - -/** @type {string} */ -/// block text - Title of block that returns a copy of text (%1) with the order -/// of letters and characters reversed. -Blockly.Msg.TEXT_REVERSE_MESSAGE0 = 'reverse %1'; -/** @type {string} */ -/// {{Optional}} url - Information about reversing a letters/characters in text. -Blockly.Msg.TEXT_REVERSE_HELPURL = 'https://github.com/google/blockly/wiki/Text#reversing-text'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Text]. -Blockly.Msg.TEXT_REVERSE_TOOLTIP = 'Reverses the order of the characters in the text.'; - -// Lists Blocks. -/** @type {string} */ -/// {{Optional}} url - Information on empty lists. -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = 'https://github.com/google/blockly/wiki/Lists#create-empty-list'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/Lists#create-empty-list https://github.com/google/blockly/wiki/Lists#create-empty-list]. -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = 'create empty list'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/Lists#create-empty-list https://github.com/google/blockly/wiki/Lists#create-empty-list]. -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = 'Returns a list, of length 0, containing no data records'; - -/** @type {string} */ -/// {{Optional}} url - Information on building lists. -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = 'https://github.com/google/blockly/wiki/Lists#create-list-with'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#create-list-with https://github.com/google/blockly/wiki/Lists#create-list-with]. -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = 'Create a list with any number of items.'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/Lists#create-list-with https://github.com/google/blockly/wiki/Lists#create-list-with]. -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = 'create list with'; -/** @type {string} */ -/// block text - This appears in a sub-block when [https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs changing the number of inputs in a ''''create list with'''' block].\n{{Identical|List}} -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = 'list'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs]. -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this list block.'; -/** @type {string} */ -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs]. -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = 'Add an item to the list.'; - -/** @type {string} */ -/// {{Optional}} url - Information about [https://github.com/google/blockly/wiki/Lists#create-list-with creating a list with multiple copies of a single item]. -Blockly.Msg.LISTS_REPEAT_HELPURL = 'https://github.com/google/blockly/wiki/Lists#create-list-with'; -/** @type {string} */ -/// {{Optional}} url - See [https://github.com/google/blockly/wiki/Lists#create-list-with creating a list with multiple copies of a single item]. -Blockly.Msg.LISTS_REPEAT_TOOLTIP = 'Creates a list consisting of the given value repeated the specified number of times.'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/Lists#create-list-with -/// https://github.com/google/blockly/wiki/Lists#create-list-with]. -///\n\nParameters:\n* %1 - the item (text) to be repeated\n* %2 - the number of times to repeat it -Blockly.Msg.LISTS_REPEAT_TITLE = 'create list with item %1 repeated %2 times'; - -/** @type {string} */ -/// {{Optional}} url - Information about how the length of a list is computed (i.e., by the total number of elements, not the number of different elements). -Blockly.Msg.LISTS_LENGTH_HELPURL = 'https://github.com/google/blockly/wiki/Lists#length-of'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/Lists#length-of https://github.com/google/blockly/wiki/Lists#length-of]. -/// \n\nParameters:\n* %1 - the list whose length is desired -Blockly.Msg.LISTS_LENGTH_TITLE = 'length of %1'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#length-of https://github.com/google/blockly/wiki/Lists#length-of Blockly:Lists:length of]. -Blockly.Msg.LISTS_LENGTH_TOOLTIP = 'Returns the length of a list.'; - -/** @type {string} */ -/// {{Optional}} url - See [https://github.com/google/blockly/wiki/Lists#is-empty https://github.com/google/blockly/wiki/Lists#is-empty]. -Blockly.Msg.LISTS_ISEMPTY_HELPURL = 'https://github.com/google/blockly/wiki/Lists#is-empty'; -/** @type {string} */ -/// block text - See [https://github.com/google/blockly/wiki/Lists#is-empty -/// https://github.com/google/blockly/wiki/Lists#is-empty]. -/// \n\nParameters:\n* %1 - the list to test -Blockly.Msg.LISTS_ISEMPTY_TITLE = '%1 is empty'; -/** @type {string} */ -/// block tooltip - See [https://github.com/google/blockly/wiki/Lists#is-empty -/// https://github.com/google/blockly/wiki/Lists#is-empty]. -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = 'Returns true if the list is empty.'; - -/** @type {string} */ -/// block text - Title of blocks operating on [https://github.com/google/blockly/wiki/Lists lists]. -Blockly.Msg.LISTS_INLIST = 'in list'; - -/** @type {string} */ -/// {{Optional}} url - See [https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list -/// https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list]. -Blockly.Msg.LISTS_INDEX_OF_HELPURL = 'https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list'; -/** @type {string} */ -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -/** @type {string} */ -/// dropdown - See [https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list -/// Lists#finding-items-in-a-list]. -/// [[File:Blockly-list-find.png]] -Blockly.Msg.LISTS_INDEX_OF_FIRST = 'find first occurrence of item'; -/** @type {string} */ -/// dropdown - See [https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list -/// https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list]. -/// [[File:Blockly-list-find.png]] -Blockly.Msg.LISTS_INDEX_OF_LAST = 'find last occurrence of item'; -/** @type {string} */ -/// tooltip - %1 will be replaced by either the number 0 or -1 depending on the indexing mode. See [https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list -/// https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list]. -/// [[File:Blockly-list-find.png]] -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = 'Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found.'; - -/** @type {string} */ -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -/** @type {string} */ -/// dropdown - Indicates that the user wishes to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item -/// get an item from a list] without removing it from the list. -Blockly.Msg.LISTS_GET_INDEX_GET = 'get'; -/** @type {string} */ -/// dropdown - Indicates that the user wishes to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item -/// get and remove an item from a list], as opposed to merely getting -/// it without modifying the list. -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = 'get and remove'; -/** @type {string} */ -/// dropdown - Indicates that the user wishes to -/// [https://github.com/google/blockly/wiki/Lists#removing-an-item -/// remove an item from a list].\n{{Identical|Remove}} -Blockly.Msg.LISTS_GET_INDEX_REMOVE = 'remove'; -/** @type {string} */ -/// dropdown - Indicates that an index relative to the front of the list should be used to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item get and/or remove -/// an item from a list]. Note: If {{msg-blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will -/// automatically appear ''after'' this number (and any other ordinal numbers on this block). -/// See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_FROM_START = '#'; -/** @type {string} */ -/// dropdown - Indicates that an index relative to the end of the list should be used -/// to [https://github.com/google/blockly/wiki/Lists#getting-a-single-item access an item in a list]. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_FROM_END = '# from end'; -/** @type {string} */ -/// dropdown - Indicates that the '''first''' item should be -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item accessed in a list]. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_FIRST = 'first'; -/** @type {string} */ -/// dropdown - Indicates that the '''last''' item should be -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item accessed in a list]. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_LAST = 'last'; -/** @type {string} */ -/// dropdown - Indicates that a '''random''' item should be -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item accessed in a list]. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_RANDOM = 'random'; -/** @type {string} */ -/// block text - Text that should go after the rightmost block/dropdown when -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item -/// accessing an item from a list]. In most languages, this will be the empty string. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_TAIL = ''; -/** @type {string} */ -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -/** @type {string} */ -/// tooltip - Indicates the ordinal number that the first item in a list is referenced by. %1 will be replaced by either "#0" or "#1" depending on the indexing mode. -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = '%1 is the first item.'; -/** @type {string} */ -/// tooltip - Indicates the ordinal number that the last item in a list is referenced by. %1 will be replaced by either "#0" or "#1" depending on the indexing mode. -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = '%1 is the last item.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = 'Returns the item at the specified position in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = 'Returns the first item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = 'Returns the last item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = 'Returns a random item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for '#' or '# from end'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = 'Removes and returns the item at the specified position in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'first'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = 'Removes and returns the first item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'last'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = 'Removes and returns the last item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'random'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = 'Removes and returns a random item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for '#' or '# from end'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = 'Removes the item at the specified position in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'first'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = 'Removes the first item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'last'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = 'Removes the last item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'random'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = 'Removes a random item in a list.'; -/** @type {string} */ -/// {{Optional}} url - Information about putting items in lists. -Blockly.Msg.LISTS_SET_INDEX_HELPURL = 'https://github.com/google/blockly/wiki/Lists#in-list--set'; -/** @type {string} */ -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -/** @type {string} */ -/// block text - [https://github.com/google/blockly/wiki/Lists#in-list--set -/// Replaces an item in a list]. -/// [[File:Blockly-in-list-set-insert.png]] -Blockly.Msg.LISTS_SET_INDEX_SET = 'set'; -/** @type {string} */ -/// block text - [https://github.com/google/blockly/wiki/Lists#in-list--insert-at -/// Inserts an item into a list]. -/// [[File:Blockly-in-list-set-insert.png]] -Blockly.Msg.LISTS_SET_INDEX_INSERT = 'insert at'; -/** @type {string} */ -/// block text - The word(s) after the position in the list and before the item to be set/inserted. -/// [[File:Blockly-in-list-set-insert.png]] -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = 'as'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "set" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = 'Sets the item at the specified position in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "set" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = 'Sets the first item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "set" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = 'Sets the last item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "set" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = 'Sets a random item in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "insert" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = 'Inserts the item at the specified position in a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "insert" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = 'Inserts the item at the start of a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "insert" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = 'Append the item to the end of a list.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "insert" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = 'Inserts the item randomly in a list.'; - -/** @type {string} */ -/// {{Optional}} url - Information describing extracting a sublist from an existing list. -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = 'https://github.com/google/blockly/wiki/Lists#getting-a-sublist'; -/** @type {string} */ -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -/** @type {string} */ -/// dropdown - Indicates that an index relative to the front of the list should be used -/// to specify the beginning of the range from which to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. -/// [[File:Blockly-get-sublist.png]] -/// Note: If {{msg-blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will -/// automatically appear ''after'' this number (and any other ordinal numbers on this block). -/// See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly. -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = 'get sub-list from #'; -/** @type {string} */ -/// dropdown - Indicates that an index relative to the end of the list should be used -/// to specify the beginning of the range from which to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = 'get sub-list from # from end'; -/** @type {string} */ -/// dropdown - Indicates that the -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist sublist to extract] -/// should begin with the list's first item. -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = 'get sub-list from first'; -/** @type {string} */ -/// dropdown - Indicates that an index relative to the front of the list should be -/// used to specify the end of the range from which to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. -/// [[File:Blockly-get-sublist.png]] -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = 'to #'; -/** @type {string} */ -/// dropdown - Indicates that an index relative to the end of the list should be -/// used to specify the end of the range from which to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. -/// [[File:Blockly-get-sublist.png]] -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = 'to # from end'; -/** @type {string} */ -/// dropdown - Indicates that the '''last''' item in the given list should be -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist the end -/// of the selected sublist]. -/// [[File:Blockly-get-sublist.png]] -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = 'to last'; -/** @type {string} */ -/// block text - This appears in the rightmost position ("tail") of the -/// sublist block, as described at -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist -/// https://github.com/google/blockly/wiki/Lists#getting-a-sublist]. -/// In English and most other languages, this is the empty string. -/// [[File:Blockly-get-sublist.png]] -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ''; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-sublist -/// https://github.com/google/blockly/wiki/Lists#getting-a-sublist] for more information. -/// [[File:Blockly-get-sublist.png]] -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = 'Creates a copy of the specified portion of a list.'; - -/** @type {string} */ -/// {{Optional}} url - Information describing sorting a list. -Blockly.Msg.LISTS_SORT_HELPURL = 'https://github.com/google/blockly/wiki/Lists#sorting-a-list'; -/** @type {string} */ -/// Sort as type %1 (numeric or alphabetic) in order %2 (ascending or descending) a list of items %3.\n{{Identical|Sort}} -Blockly.Msg.LISTS_SORT_TITLE = 'sort %1 %2 %3'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#sorting-a-list]. -Blockly.Msg.LISTS_SORT_TOOLTIP = 'Sort a copy of a list.'; -/** @type {string} */ -/// sorting order or direction from low to high value for numeric, or A-Z for alphabetic.\n{{Identical|Ascending}} -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = 'ascending'; -/** @type {string} */ -/// sorting order or direction from high to low value for numeric, or Z-A for alphabetic.\n{{Identical|Descending}} -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = 'descending'; -/** @type {string} */ -/// sort by treating each item as a number. -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = 'numeric'; -/** @type {string} */ -/// sort by treating each item alphabetically, case-sensitive. -Blockly.Msg.LISTS_SORT_TYPE_TEXT = 'alphabetic'; -/** @type {string} */ -/// sort by treating each item alphabetically, ignoring differences in case. -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = 'alphabetic, ignore case'; - -/** @type {string} */ -/// {{Optional}} url - Information describing splitting text into a list, or joining a list into text. -Blockly.Msg.LISTS_SPLIT_HELPURL = 'https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists'; -/** @type {string} */ -/// dropdown - Indicates that text will be split up into a list (e.g. "a-b-c" -> ["a", "b", "c"]). -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = 'make list from text'; -/** @type {string} */ -/// dropdown - Indicates that a list will be joined together to form text (e.g. ["a", "b", "c"] -> "a-b-c"). -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = 'make text from list'; -/** @type {string} */ -/// block text - Prompts for a letter to be used as a separator when splitting or joining text. -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = 'with delimiter'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#make-list-from-text -/// https://github.com/google/blockly/wiki/Lists#make-list-from-text] for more information. -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = 'Split text into a list of texts, breaking at each delimiter.'; -/** @type {string} */ -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#make-text-from-list -/// https://github.com/google/blockly/wiki/Lists#make-text-from-list] for more information. -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = 'Join a list of texts into one text, separated by a delimiter.'; - -/** @type {string} */ -/// {{Optional}} url - Information describing reversing a list. -Blockly.Msg.LISTS_REVERSE_HELPURL = 'https://github.com/google/blockly/wiki/Lists#reversing-a-list'; -/** @type {string} */ -/// block text - Title of block that returns a copy of a list (%1) with the order of items reversed. -Blockly.Msg.LISTS_REVERSE_MESSAGE0 = 'reverse %1'; -/** @type {string} */ -/// tooltip - Short description for a block that reverses a copy of a list. -Blockly.Msg.LISTS_REVERSE_TOOLTIP = 'Reverse a copy of a list.'; - -/** @type {string} */ -/// grammar - Text that follows an ordinal number (a number that indicates -/// position relative to other numbers). In most languages, such text appears -/// before the number, so this should be blank. An exception is Hungarian. -/// See [[Translating:Blockly#Ordinal_numbers]] for more information. -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ''; - -// Variables Blocks. -/** @type {string} */ -/// {{Optional}} url - Information about ''variables'' in computer programming. Consider using your language's translation of [https://en.wikipedia.org/wiki/Variable_(computer_science) https://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists. -Blockly.Msg.VARIABLES_GET_HELPURL = 'https://github.com/google/blockly/wiki/Variables#get'; -/** @type {string} */ -/// tooltip - This gets the value of the named variable without modifying it. -Blockly.Msg.VARIABLES_GET_TOOLTIP = 'Returns the value of this variable.'; -/** @type {string} */ -/// context menu - Selecting this creates a block to set (change) the value of this variable. -/// \n\nParameters:\n* %1 - the name of the variable. -Blockly.Msg.VARIABLES_GET_CREATE_SET = 'Create "set %1"'; - -/** @type {string} */ -/// {{Optional}} url - Information about ''variables'' in computer programming. Consider using your language's translation of [https://en.wikipedia.org/wiki/Variable_(computer_science) https://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists. -Blockly.Msg.VARIABLES_SET_HELPURL = 'https://github.com/google/blockly/wiki/Variables#set'; -/** @type {string} */ -/// block text - Change the value of a mathematical variable: '''set [the value of] x to 7'''.\n\nParameters:\n* %1 - the name of the variable.\n* %2 - the value to be assigned. -Blockly.Msg.VARIABLES_SET = 'set %1 to %2'; -/** @type {string} */ -/// tooltip - This initializes or changes the value of the named variable. -Blockly.Msg.VARIABLES_SET_TOOLTIP = 'Sets this variable to be equal to the input.'; -/** @type {string} */ -/// context menu - Selecting this creates a block to get (change) the value of -/// this variable.\n\nParameters:\n* %1 - the name of the variable. -Blockly.Msg.VARIABLES_SET_CREATE_GET = 'Create "get %1"'; - -// Procedures Blocks. -/** @type {string} */ -/// {{Optional}} url - Information about defining [https://en.wikipedia.org/wiki/Subroutine functions] that do not have return values. -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = 'https://en.wikipedia.org/wiki/Subroutine'; -/** @type {string} */ -/// block text - This precedes the name of the function when defining it. See -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample -/// function definition]. -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = 'to'; -/** @type {string} */ -/// default name - This acts as a placeholder for the name of a function on a -/// function definition block, as shown on -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#w7cfju this block]. -/// The user will replace it with the function's name. -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = 'do something'; -/** @type {string} */ -/// block text - This precedes the list of parameters on a function's definition block. See -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#voztpd this sample -/// function with parameters]. -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = 'with:'; -/** @type {string} */ -/// block text - This precedes the list of parameters on a function's caller block. See -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#voztpd this sample -/// function with parameters]. -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = 'with:'; -/** @type {string} */ -/// block text - This appears next to the function's "body", the blocks that should be -/// run when the function is called, as shown in -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#voztpd this sample -/// function definition]. -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ''; -/** @type {string} */ -/// tooltip -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = 'Creates a function with no output.'; -/** @type {string} */ -/// Placeholder text that the user is encouraged to replace with a description of what their function does. -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = 'Describe this function...'; -/** @type {string} */ -/// {{Optional}} url - Information about defining [https://en.wikipedia.org/wiki/Subroutine functions] that have return values. -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = 'https://en.wikipedia.org/wiki/Subroutine'; -/** @type {string} */ -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -/** @type {string} */ -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -/** @type {string} */ -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -/** @type {string} */ -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; -/** @type {string} */ -/// block text - This imperative or infinite verb precedes the value that is used as the return value -/// (output) of this function. See -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample -/// function that returns a value]. -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = 'return'; -/** @type {string} */ -/// tooltip -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = 'Creates a function with an output.'; -/** @type {string} */ -/// Label for a checkbox that controls if statements are allowed in a function. -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = 'allow statements'; - -/** @type {string} */ -/// alert - The user has created a function with two parameters that have the same name. Every parameter must have a different name. -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = 'Warning: This function has duplicate parameters.'; - -/** @type {string} */ -/// {{Optional}} url - Information about calling [https://en.wikipedia.org/wiki/Subroutine functions] that do not return values. -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = 'https://en.wikipedia.org/wiki/Subroutine'; -/** @type {string} */ -/// tooltip - This block causes the body (blocks inside) of the named function definition to be run. -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = 'Run the user-defined function "%1".'; - -/** @type {string} */ -/// {{Optional}} url - Information about calling [https://en.wikipedia.org/wiki/Subroutine functions] that return values. -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = 'https://en.wikipedia.org/wiki/Subroutine'; -/** @type {string} */ -/// tooltip - This block causes the body (blocks inside) of the named function definition to be run.\n\nParameters:\n* %1 - the name of the function. -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = 'Run the user-defined function "%1" and use its output.'; - -/** @type {string} */ -/// block text - This text appears on a block in a window that appears when the user clicks -/// on the plus sign or star on a function definition block. It refers to the set of parameters -/// (referred to by the simpler term "inputs") to the function. See -/// [[Translating:Blockly#function_definitions]].\n{{Identical|Input}} -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = 'inputs'; -/** @type {string} */ -/// tooltip -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = 'Add, remove, or reorder inputs to this function.'; -/** @type {string} */ -/// block text - This text appears on a block in a window that appears when the user clicks -/// on the plus sign or star on a function definition block]. It appears on the block for -/// adding an individual parameter (referred to by the simpler term "inputs") to the function. -/// See [[Translating:Blockly#function_definitions]]. -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = 'input name:'; -/** @type {string} */ -/// tooltip -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = 'Add an input to the function.'; - -/** @type {string} */ -/// context menu - This appears on the context menu for function calls. Selecting -/// it causes the corresponding function definition to be highlighted (as shown at -/// [[Translating:Blockly#context_menus]]. -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = 'Highlight function definition'; -/** @type {string} */ -/// context menu - This appears on the context menu for function definitions. -/// Selecting it creates a block to call the function.\n\nParameters:\n* %1 - the name of the function.\n{{Identical|Create}} -Blockly.Msg.PROCEDURES_CREATE_DO = 'Create "%1"'; - -/** @type {string} */ -/// tooltip - If the first value is true, this causes the second value to be returned -/// immediately from the enclosing function. -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = 'If a value is true, then return a second value.'; -/** @type {string} */ -/// {{Optional}} url - Information about guard clauses. -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = 'http://c2.com/cgi/wiki?GuardClause'; -/** @type {string} */ -/// warning - This appears if the user tries to use this block outside of a function definition. -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = 'Warning: This block may be used only within a function definition.'; - -/** @type {string} */ -/// comment text - This text appears in a new workspace comment, to hint that -/// the user can type here. -Blockly.Msg.WORKSPACE_COMMENT_DEFAULT_TEXT = 'Say something...'; - -/** @type {string} */ -/// workspace - This text is read out when a user navigates to the workspace while -/// using a screen reader. -Blockly.Msg.WORKSPACE_ARIA_LABEL = 'Blockly Workspace'; - -/** @type {string} */ -/// warning - This appears if the user collapses a block, and blocks inside -/// that block have warnings attached to them. It should inform the user that the -/// block they collapsed contains blocks that have warnings. -Blockly.Msg.COLLAPSED_WARNINGS_WARNING = 'Collapsed blocks contain warnings.'; - -/** @type {string} */ -/// button label - Pressing this button closes help information.\n{{Identical|OK}} -Blockly.Msg.DIALOG_OK = 'OK'; - -/** @type {string} */ -/// button label - Pressing this button cancels a proposed action.\n{{Identical|Cancel}} -Blockly.Msg.DIALOG_CANCEL = 'Cancel'; diff --git a/google-blockly/python_compressed.js b/google-blockly/python_compressed.js deleted file mode 100644 index 9b83d3b..0000000 --- a/google-blockly/python_compressed.js +++ /dev/null @@ -1,254 +0,0 @@ -// Do not edit this file; automatically generated. - -/* eslint-disable */ -;(function(root, factory) { - if (typeof define === 'function' && define.amd) { // AMD - define(["./blockly_compressed.js"], factory); - } else if (typeof exports === 'object') { // Node.js - module.exports = factory(require("./blockly_compressed.js")); - } else { // Browser - var factoryExports = factory(root.Blockly); - root.Blockly.Python = factoryExports.pythonGenerator; - root.Blockly.Python.__namespace__ = factoryExports.__namespace__; - } -}(this, function(__parent__) { -var $=__parent__.__namespace__; -var module$exports$Blockly$Python={},module$contents$Blockly$Python_stringUtils=$.module$build$src$core$utils$string,module$contents$Blockly$Python_Variables=$.module$build$src$core$variables,module$contents$Blockly$Python_Generator=$.Generator$$module$build$src$core$generator,module$contents$Blockly$Python_inputTypes=$.module$build$src$core$input_types.inputTypes,module$contents$Blockly$Python_Names=$.module$build$src$core$names.Names,module$contents$Blockly$Python_NameType=$.NameType$$module$build$src$core$names; -module$exports$Blockly$Python.pythonGenerator=new $.Generator$$module$build$src$core$generator("Python");module$exports$Blockly$Python.pythonGenerator.addReservedWords("False,None,True,and,as,assert,break,class,continue,def,del,elif,else,except,exec,finally,for,from,global,if,import,in,is,lambda,nonlocal,not,or,pass,print,raise,return,try,while,with,yield,NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,ArithmeticError,AssertionError,AttributeError,BaseException,BlockingIOError,BrokenPipeError,BufferError,BytesWarning,ChildProcessError,ConnectionAbortedError,ConnectionError,ConnectionRefusedError,ConnectionResetError,DeprecationWarning,EOFError,Ellipsis,EnvironmentError,Exception,FileExistsError,FileNotFoundError,FloatingPointError,FutureWarning,GeneratorExit,IOError,ImportError,ImportWarning,IndentationError,IndexError,InterruptedError,IsADirectoryError,KeyError,KeyboardInterrupt,LookupError,MemoryError,ModuleNotFoundError,NameError,NotADirectoryError,NotImplemented,NotImplementedError,OSError,OverflowError,PendingDeprecationWarning,PermissionError,ProcessLookupError,RecursionError,ReferenceError,ResourceWarning,RuntimeError,RuntimeWarning,StandardError,StopAsyncIteration,StopIteration,SyntaxError,SyntaxWarning,SystemError,SystemExit,TabError,TimeoutError,TypeError,UnboundLocalError,UnicodeDecodeError,UnicodeEncodeError,UnicodeError,UnicodeTranslateError,UnicodeWarning,UserWarning,ValueError,Warning,ZeroDivisionError,_,__build_class__,__debug__,__doc__,__import__,__loader__,__name__,__package__,__spec__,abs,all,any,apply,ascii,basestring,bin,bool,buffer,bytearray,bytes,callable,chr,classmethod,cmp,coerce,compile,complex,copyright,credits,delattr,dict,dir,divmod,enumerate,eval,exec,execfile,exit,file,filter,float,format,frozenset,getattr,globals,hasattr,hash,help,hex,id,input,int,intern,isinstance,issubclass,iter,len,license,list,locals,long,map,max,memoryview,min,next,object,oct,open,ord,pow,print,property,quit,range,raw_input,reduce,reload,repr,reversed,round,set,setattr,slice,sorted,staticmethod,str,sum,super,tuple,type,unichr,unicode,vars,xrange,zip"); -module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC=0;module$exports$Blockly$Python.pythonGenerator.ORDER_COLLECTION=1;module$exports$Blockly$Python.pythonGenerator.ORDER_STRING_CONVERSION=1;module$exports$Blockly$Python.pythonGenerator.ORDER_MEMBER=2.1;module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL=2.2;module$exports$Blockly$Python.pythonGenerator.ORDER_EXPONENTIATION=3;module$exports$Blockly$Python.pythonGenerator.ORDER_UNARY_SIGN=4; -module$exports$Blockly$Python.pythonGenerator.ORDER_BITWISE_NOT=4;module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE=5;module$exports$Blockly$Python.pythonGenerator.ORDER_ADDITIVE=6;module$exports$Blockly$Python.pythonGenerator.ORDER_BITWISE_SHIFT=7;module$exports$Blockly$Python.pythonGenerator.ORDER_BITWISE_AND=8;module$exports$Blockly$Python.pythonGenerator.ORDER_BITWISE_XOR=9;module$exports$Blockly$Python.pythonGenerator.ORDER_BITWISE_OR=10; -module$exports$Blockly$Python.pythonGenerator.ORDER_RELATIONAL=11;module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_NOT=12;module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_AND=13;module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_OR=14;module$exports$Blockly$Python.pythonGenerator.ORDER_CONDITIONAL=15;module$exports$Blockly$Python.pythonGenerator.ORDER_LAMBDA=16;module$exports$Blockly$Python.pythonGenerator.ORDER_NONE=99; -module$exports$Blockly$Python.pythonGenerator.ORDER_OVERRIDES=[[module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL,module$exports$Blockly$Python.pythonGenerator.ORDER_MEMBER],[module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL,module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL],[module$exports$Blockly$Python.pythonGenerator.ORDER_MEMBER,module$exports$Blockly$Python.pythonGenerator.ORDER_MEMBER],[module$exports$Blockly$Python.pythonGenerator.ORDER_MEMBER, -module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL],[module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_NOT,module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_NOT],[module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_AND,module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_AND],[module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_OR,module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_OR]]; -module$exports$Blockly$Python.pythonGenerator.isInitialized=!1; -module$exports$Blockly$Python.pythonGenerator.init=function(a){Object.getPrototypeOf(this).init.call(this);this.PASS=this.INDENT+"pass\n";this.nameDB_?this.nameDB_.reset():this.nameDB_=new $.module$build$src$core$names.Names(this.RESERVED_WORDS_);this.nameDB_.setVariableMap(a.getVariableMap());this.nameDB_.populateVariables(a);this.nameDB_.populateProcedures(a);const b=[];var c=$.module$build$src$core$variables.allDeveloperVariables(a);for(let d=0;dc?"int("+a+" - "+-c+")":"int("+a+")",d&&(a="-"+a));return a};var module$exports$Blockly$Python$variables={},module$contents$Blockly$Python$variables_NameType=$.NameType$$module$build$src$core$names;module$exports$Blockly$Python.pythonGenerator.variables_get=function(a){return[module$exports$Blockly$Python.pythonGenerator.nameDB_.getName(a.getFieldValue("VAR"),$.NameType$$module$build$src$core$names.VARIABLE),module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC]}; -module$exports$Blockly$Python.pythonGenerator.variables_set=function(a){const b=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"VALUE",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0";return module$exports$Blockly$Python.pythonGenerator.nameDB_.getName(a.getFieldValue("VAR"),$.NameType$$module$build$src$core$names.VARIABLE)+" = "+b+"\n"};var module$exports$Blockly$Python$variablesDynamic={};module$exports$Blockly$Python.pythonGenerator.variables_get_dynamic=module$exports$Blockly$Python.pythonGenerator.variables_get;module$exports$Blockly$Python.pythonGenerator.variables_set_dynamic=module$exports$Blockly$Python.pythonGenerator.variables_set;var module$exports$Blockly$Python$texts={},module$contents$Blockly$Python$texts_stringUtils=$.module$build$src$core$utils$string,module$contents$Blockly$Python$texts_NameType=$.NameType$$module$build$src$core$names;module$exports$Blockly$Python.pythonGenerator.text=function(a){return[module$exports$Blockly$Python.pythonGenerator.quote_(a.getFieldValue("TEXT")),module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC]}; -module$exports$Blockly$Python.pythonGenerator.text_multiline=function(a){a=module$exports$Blockly$Python.pythonGenerator.multiline_quote_(a.getFieldValue("TEXT"));const b=-1!==a.indexOf("+")?module$exports$Blockly$Python.pythonGenerator.ORDER_ADDITIVE:module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC;return[a,b]}; -var module$contents$Blockly$Python$texts_strRegExp=/^\s*'([^']|\\')*'\s*$/,module$contents$Blockly$Python$texts_forceString=function(a){return module$contents$Blockly$Python$texts_strRegExp.test(a)?[a,module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC]:["str("+a+")",module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL]}; -module$exports$Blockly$Python.pythonGenerator.text_join=function(a){switch(a.itemCount_){case 0:return["''",module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC];case 1:return a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"ADD0",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"''",module$contents$Blockly$Python$texts_forceString(a);case 2:var b=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"ADD0",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)|| -"''";a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"ADD1",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"''";return[module$contents$Blockly$Python$texts_forceString(b)[0]+" + "+module$contents$Blockly$Python$texts_forceString(a)[0],module$exports$Blockly$Python.pythonGenerator.ORDER_ADDITIVE];default:b=[];for(let c=0;ca?module$exports$Blockly$Python.pythonGenerator.ORDER_UNARY_SIGN:module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC;return[a,b]}; -module$exports$Blockly$Python.pythonGenerator.math_arithmetic=function(a){var b={ADD:[" + ",module$exports$Blockly$Python.pythonGenerator.ORDER_ADDITIVE],MINUS:[" - ",module$exports$Blockly$Python.pythonGenerator.ORDER_ADDITIVE],MULTIPLY:[" * ",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE],DIVIDE:[" / ",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE],POWER:[" ** ",module$exports$Blockly$Python.pythonGenerator.ORDER_EXPONENTIATION]}[a.getFieldValue("OP")]; -const c=b[0];b=b[1];const d=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"A",b)||"0";a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"B",b)||"0";return[d+c+a,b]}; -module$exports$Blockly$Python.pythonGenerator.math_single=function(a){const b=a.getFieldValue("OP");let c;if("NEG"===b)return c=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"NUM",module$exports$Blockly$Python.pythonGenerator.ORDER_UNARY_SIGN)||"0",["-"+c,module$exports$Blockly$Python.pythonGenerator.ORDER_UNARY_SIGN];module$exports$Blockly$Python.pythonGenerator.definitions_.import_math="import math";a="SIN"===b||"COS"===b||"TAN"===b?module$exports$Blockly$Python.pythonGenerator.valueToCode(a, -"NUM",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE)||"0":module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"NUM",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0";switch(b){case "ABS":c="math.fabs("+a+")";break;case "ROOT":c="math.sqrt("+a+")";break;case "LN":c="math.log("+a+")";break;case "LOG10":c="math.log10("+a+")";break;case "EXP":c="math.exp("+a+")";break;case "POW10":c="math.pow(10,"+a+")";break;case "ROUND":c="round("+a+")";break;case "ROUNDUP":c= -"math.ceil("+a+")";break;case "ROUNDDOWN":c="math.floor("+a+")";break;case "SIN":c="math.sin("+a+" / 180.0 * math.pi)";break;case "COS":c="math.cos("+a+" / 180.0 * math.pi)";break;case "TAN":c="math.tan("+a+" / 180.0 * math.pi)"}if(c)return[c,module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL];switch(b){case "ASIN":c="math.asin("+a+") / math.pi * 180";break;case "ACOS":c="math.acos("+a+") / math.pi * 180";break;case "ATAN":c="math.atan("+a+") / math.pi * 180";break;default:throw Error("Unknown math operator: "+ -b);}return[c,module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE]}; -module$exports$Blockly$Python.pythonGenerator.math_constant=function(a){const b={PI:["math.pi",module$exports$Blockly$Python.pythonGenerator.ORDER_MEMBER],E:["math.e",module$exports$Blockly$Python.pythonGenerator.ORDER_MEMBER],GOLDEN_RATIO:["(1 + math.sqrt(5)) / 2",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE],SQRT2:["math.sqrt(2)",module$exports$Blockly$Python.pythonGenerator.ORDER_MEMBER],SQRT1_2:["math.sqrt(1.0 / 2)",module$exports$Blockly$Python.pythonGenerator.ORDER_MEMBER], -INFINITY:["float('inf')",module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC]};a=a.getFieldValue("CONSTANT");"INFINITY"!==a&&(module$exports$Blockly$Python.pythonGenerator.definitions_.import_math="import math");return b[a]}; -module$exports$Blockly$Python.pythonGenerator.math_number_property=function(a){var b={EVEN:[" % 2 == 0",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE,module$exports$Blockly$Python.pythonGenerator.ORDER_RELATIONAL],ODD:[" % 2 == 1",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE,module$exports$Blockly$Python.pythonGenerator.ORDER_RELATIONAL],WHOLE:[" % 1 == 0",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE,module$exports$Blockly$Python.pythonGenerator.ORDER_RELATIONAL], -POSITIVE:[" > 0",module$exports$Blockly$Python.pythonGenerator.ORDER_RELATIONAL,module$exports$Blockly$Python.pythonGenerator.ORDER_RELATIONAL],NEGATIVE:[" < 0",module$exports$Blockly$Python.pythonGenerator.ORDER_RELATIONAL,module$exports$Blockly$Python.pythonGenerator.ORDER_RELATIONAL],DIVISIBLE_BY:[null,module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE,module$exports$Blockly$Python.pythonGenerator.ORDER_RELATIONAL],PRIME:[null,module$exports$Blockly$Python.pythonGenerator.ORDER_NONE, -module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL]};const c=a.getFieldValue("PROPERTY"),[d,e,f]=b[c];b=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"NUMBER_TO_CHECK",e)||"0";if("PRIME"===c)module$exports$Blockly$Python.pythonGenerator.definitions_.import_math="import math",module$exports$Blockly$Python.pythonGenerator.definitions_.from_numbers_import_Number="from numbers import Number",a=module$exports$Blockly$Python.pythonGenerator.provideFunction_("math_isPrime",` -def ${module$exports$Blockly$Python.pythonGenerator.FUNCTION_NAME_PLACEHOLDER_}(n): - # https://en.wikipedia.org/wiki/Primality_test#Naive_methods - # If n is not a number but a string, try parsing it. - if not isinstance(n, Number): - try: - n = float(n) - except: - return False - if n == 2 or n == 3: - return True - # False if n is negative, is 1, or not whole, or if n is divisible by 2 or 3. - if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0: - return False - # Check all the numbers of form 6k +/- 1, up to sqrt(n). - for x in range(6, int(math.sqrt(n)) + 2, 6): - if n % (x - 1) == 0 or n % (x + 1) == 0: - return False - return True -`)+"("+b+")";else if("DIVISIBLE_BY"===c){a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"DIVISOR",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE)||"0";if("0"===a)return["False",module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC];a=b+" % "+a+" == 0"}else a=b+d;return[a,f]}; -module$exports$Blockly$Python.pythonGenerator.math_change=function(a){module$exports$Blockly$Python.pythonGenerator.definitions_.from_numbers_import_Number="from numbers import Number";const b=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"DELTA",module$exports$Blockly$Python.pythonGenerator.ORDER_ADDITIVE)||"0";a=module$exports$Blockly$Python.pythonGenerator.nameDB_.getName(a.getFieldValue("VAR"),$.NameType$$module$build$src$core$names.VARIABLE);return a+" = ("+a+" if isinstance("+ -a+", Number) else 0) + "+b+"\n"};module$exports$Blockly$Python.pythonGenerator.math_round=module$exports$Blockly$Python.pythonGenerator.math_single;module$exports$Blockly$Python.pythonGenerator.math_trig=module$exports$Blockly$Python.pythonGenerator.math_single; -module$exports$Blockly$Python.pythonGenerator.math_on_list=function(a){var b=a.getFieldValue("OP");a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"LIST",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"[]";switch(b){case "SUM":b="sum("+a+")";break;case "MIN":b="min("+a+")";break;case "MAX":b="max("+a+")";break;case "AVERAGE":module$exports$Blockly$Python.pythonGenerator.definitions_.from_numbers_import_Number="from numbers import Number";b=module$exports$Blockly$Python.pythonGenerator.provideFunction_("math_mean", -` -def ${module$exports$Blockly$Python.pythonGenerator.FUNCTION_NAME_PLACEHOLDER_}(myList): - localList = [e for e in myList if isinstance(e, Number)] - if not localList: return - return float(sum(localList)) / len(localList) -`)+"("+a+")";break;case "MEDIAN":module$exports$Blockly$Python.pythonGenerator.definitions_.from_numbers_import_Number="from numbers import Number";b=module$exports$Blockly$Python.pythonGenerator.provideFunction_("math_median",` -def ${module$exports$Blockly$Python.pythonGenerator.FUNCTION_NAME_PLACEHOLDER_}(myList): - localList = sorted([e for e in myList if isinstance(e, Number)]) - if not localList: return - if len(localList) % 2 == 0: - return (localList[len(localList) // 2 - 1] + localList[len(localList) // 2]) / 2.0 - else: - return localList[(len(localList) - 1) // 2] -`)+"("+a+")";break;case "MODE":b=module$exports$Blockly$Python.pythonGenerator.provideFunction_("math_modes",` -def ${module$exports$Blockly$Python.pythonGenerator.FUNCTION_NAME_PLACEHOLDER_}(some_list): - modes = [] - # Using a lists of [item, count] to keep count rather than dict - # to avoid "unhashable" errors when the counted item is itself a list or dict. - counts = [] - maxCount = 1 - for item in some_list: - found = False - for count in counts: - if count[0] == item: - count[1] += 1 - maxCount = max(maxCount, count[1]) - found = True - if not found: - counts.append([item, 1]) - for counted_item, item_count in counts: - if item_count == maxCount: - modes.append(counted_item) - return modes -`)+"("+a+")";break;case "STD_DEV":module$exports$Blockly$Python.pythonGenerator.definitions_.import_math="import math";b=module$exports$Blockly$Python.pythonGenerator.provideFunction_("math_standard_deviation",` -def ${module$exports$Blockly$Python.pythonGenerator.FUNCTION_NAME_PLACEHOLDER_}(numbers): - n = len(numbers) - if n == 0: return - mean = float(sum(numbers)) / n - variance = sum((x - mean) ** 2 for x in numbers) / n - return math.sqrt(variance) -`)+"("+a+")";break;case "RANDOM":module$exports$Blockly$Python.pythonGenerator.definitions_.import_random="import random";b="random.choice("+a+")";break;default:throw Error("Unknown operator: "+b);}return[b,module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL]}; -module$exports$Blockly$Python.pythonGenerator.math_modulo=function(a){const b=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"DIVIDEND",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE)||"0";a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"DIVISOR",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE)||"0";return[b+" % "+a,module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE]}; -module$exports$Blockly$Python.pythonGenerator.math_constrain=function(a){const b=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"VALUE",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0",c=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"LOW",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0";a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"HIGH",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"float('inf')";return["min(max("+ -b+", "+c+"), "+a+")",module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL]}; -module$exports$Blockly$Python.pythonGenerator.math_random_int=function(a){module$exports$Blockly$Python.pythonGenerator.definitions_.import_random="import random";const b=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"FROM",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0";a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"TO",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0";return["random.randint("+b+", "+a+")",module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL]}; -module$exports$Blockly$Python.pythonGenerator.math_random_float=function(a){module$exports$Blockly$Python.pythonGenerator.definitions_.import_random="import random";return["random.random()",module$exports$Blockly$Python.pythonGenerator.ORDER_FUNCTION_CALL]}; -module$exports$Blockly$Python.pythonGenerator.math_atan2=function(a){module$exports$Blockly$Python.pythonGenerator.definitions_.import_math="import math";const b=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"X",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0";return["math.atan2("+(module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"Y",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0")+", "+b+") / math.pi * 180",module$exports$Blockly$Python.pythonGenerator.ORDER_MULTIPLICATIVE]};var module$exports$Blockly$Python$loops={},module$contents$Blockly$Python$loops_stringUtils=$.module$build$src$core$utils$string,module$contents$Blockly$Python$loops_NameType=$.NameType$$module$build$src$core$names; -module$exports$Blockly$Python.pythonGenerator.controls_repeat_ext=function(a){let b;b=a.getField("TIMES")?String(parseInt(a.getFieldValue("TIMES"),10)):module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"TIMES",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0";b=$.module$build$src$core$utils$string.isNumber(b)?parseInt(b,10):"int("+b+")";let c=module$exports$Blockly$Python.pythonGenerator.statementToCode(a,"DO");c=module$exports$Blockly$Python.pythonGenerator.addLoopTrap(c,a)|| -module$exports$Blockly$Python.pythonGenerator.PASS;return"for "+module$exports$Blockly$Python.pythonGenerator.nameDB_.getDistinctName("count",$.NameType$$module$build$src$core$names.VARIABLE)+" in range("+b+"):\n"+c};module$exports$Blockly$Python.pythonGenerator.controls_repeat=module$exports$Blockly$Python.pythonGenerator.controls_repeat_ext; -module$exports$Blockly$Python.pythonGenerator.controls_whileUntil=function(a){const b="UNTIL"===a.getFieldValue("MODE");let c=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"BOOL",b?module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_NOT:module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"False",d=module$exports$Blockly$Python.pythonGenerator.statementToCode(a,"DO");d=module$exports$Blockly$Python.pythonGenerator.addLoopTrap(d,a)||module$exports$Blockly$Python.pythonGenerator.PASS; -b&&(c="not "+c);return"while "+c+":\n"+d}; -module$exports$Blockly$Python.pythonGenerator.controls_for=function(a){const b=module$exports$Blockly$Python.pythonGenerator.nameDB_.getName(a.getFieldValue("VAR"),$.NameType$$module$build$src$core$names.VARIABLE);var c=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"FROM",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0",d=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"TO",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"0",e=module$exports$Blockly$Python.pythonGenerator.valueToCode(a, -"BY",module$exports$Blockly$Python.pythonGenerator.ORDER_NONE)||"1";let f=module$exports$Blockly$Python.pythonGenerator.statementToCode(a,"DO");f=module$exports$Blockly$Python.pythonGenerator.addLoopTrap(f,a)||module$exports$Blockly$Python.pythonGenerator.PASS;let g="";const h=function(){return module$exports$Blockly$Python.pythonGenerator.provideFunction_("upRange",` -def ${module$exports$Blockly$Python.pythonGenerator.FUNCTION_NAME_PLACEHOLDER_}(start, stop, step): - while start <= stop: - yield start - start += abs(step) -`)},k=function(){return module$exports$Blockly$Python.pythonGenerator.provideFunction_("downRange",` -def ${module$exports$Blockly$Python.pythonGenerator.FUNCTION_NAME_PLACEHOLDER_}(start, stop, step): - while start >= stop: - yield start - start -= abs(step) -`)};a=function(l,m,n){return"("+l+" <= "+m+") and "+h()+"("+l+", "+m+", "+n+") or "+k()+"("+l+", "+m+", "+n+")"};if($.module$build$src$core$utils$string.isNumber(c)&&$.module$build$src$core$utils$string.isNumber(d)&&$.module$build$src$core$utils$string.isNumber(e))c=Number(c),d=Number(d),e=Math.abs(Number(e)),0===c%1&&0===d%1&&0===e%1?(c<=d?(d++,a=0===c&&1===e?d:c+", "+d,1!==e&&(a+=", "+e)):(d--,a=c+", "+d+", -"+e),a="range("+a+")"):(a=c",GTE:">="}[a.getFieldValue("OP")],c=module$exports$Blockly$Python.pythonGenerator.ORDER_RELATIONAL,d=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"A",c)||"0";a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]}; -module$exports$Blockly$Python.pythonGenerator.logic_operation=function(a){const b="AND"===a.getFieldValue("OP")?"and":"or",c="and"===b?module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_AND:module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_OR;let d=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"A",c);a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"B",c);if(d||a){const e="and"===b?"True":"False";d||(d=e);a||(a=e)}else a=d="False";return[d+" "+b+" "+a, -c]};module$exports$Blockly$Python.pythonGenerator.logic_negate=function(a){return["not "+(module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"BOOL",module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_NOT)||"True"),module$exports$Blockly$Python.pythonGenerator.ORDER_LOGICAL_NOT]};module$exports$Blockly$Python.pythonGenerator.logic_boolean=function(a){return["TRUE"===a.getFieldValue("BOOL")?"True":"False",module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC]}; -module$exports$Blockly$Python.pythonGenerator.logic_null=function(a){return["None",module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC]}; -module$exports$Blockly$Python.pythonGenerator.logic_ternary=function(a){const b=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"IF",module$exports$Blockly$Python.pythonGenerator.ORDER_CONDITIONAL)||"False",c=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"THEN",module$exports$Blockly$Python.pythonGenerator.ORDER_CONDITIONAL)||"None";a=module$exports$Blockly$Python.pythonGenerator.valueToCode(a,"ELSE",module$exports$Blockly$Python.pythonGenerator.ORDER_CONDITIONAL)||"None"; -return[c+" if "+b+" else "+a,module$exports$Blockly$Python.pythonGenerator.ORDER_CONDITIONAL]};var module$exports$Blockly$Python$lists={},module$contents$Blockly$Python$lists_stringUtils=$.module$build$src$core$utils$string,module$contents$Blockly$Python$lists_NameType=$.NameType$$module$build$src$core$names;module$exports$Blockly$Python.pythonGenerator.lists_create_empty=function(a){return["[]",module$exports$Blockly$Python.pythonGenerator.ORDER_ATOMIC]}; -module$exports$Blockly$Python.pythonGenerator.lists_create_with=function(a){const b=Array(a.itemCount_);for(let c=0;c>> print(','.join(sorted(dir(__builtins__))))\n // https://docs.python.org/3/library/functions.html\n // https://docs.python.org/2/library/functions.html\n 'ArithmeticError,AssertionError,AttributeError,BaseException,' +\n 'BlockingIOError,BrokenPipeError,BufferError,BytesWarning,' +\n 'ChildProcessError,ConnectionAbortedError,ConnectionError,' +\n 'ConnectionRefusedError,ConnectionResetError,DeprecationWarning,EOFError,' +\n 'Ellipsis,EnvironmentError,Exception,FileExistsError,FileNotFoundError,' +\n 'FloatingPointError,FutureWarning,GeneratorExit,IOError,ImportError,' +\n 'ImportWarning,IndentationError,IndexError,InterruptedError,' +\n 'IsADirectoryError,KeyError,KeyboardInterrupt,LookupError,MemoryError,' +\n 'ModuleNotFoundError,NameError,NotADirectoryError,NotImplemented,' +\n 'NotImplementedError,OSError,OverflowError,PendingDeprecationWarning,' +\n 'PermissionError,ProcessLookupError,RecursionError,ReferenceError,' +\n 'ResourceWarning,RuntimeError,RuntimeWarning,StandardError,' +\n 'StopAsyncIteration,StopIteration,SyntaxError,SyntaxWarning,SystemError,' +\n 'SystemExit,TabError,TimeoutError,TypeError,UnboundLocalError,' +\n 'UnicodeDecodeError,UnicodeEncodeError,UnicodeError,' +\n 'UnicodeTranslateError,UnicodeWarning,UserWarning,ValueError,Warning,' +\n 'ZeroDivisionError,_,__build_class__,__debug__,__doc__,__import__,' +\n '__loader__,__name__,__package__,__spec__,abs,all,any,apply,ascii,' +\n 'basestring,bin,bool,buffer,bytearray,bytes,callable,chr,classmethod,cmp,' +\n 'coerce,compile,complex,copyright,credits,delattr,dict,dir,divmod,' +\n 'enumerate,eval,exec,execfile,exit,file,filter,float,format,frozenset,' +\n 'getattr,globals,hasattr,hash,help,hex,id,input,int,intern,isinstance,' +\n 'issubclass,iter,len,license,list,locals,long,map,max,memoryview,min,' +\n 'next,object,oct,open,ord,pow,print,property,quit,range,raw_input,reduce,' +\n 'reload,repr,reversed,round,set,setattr,slice,sorted,staticmethod,str,' +\n 'sum,super,tuple,type,unichr,unicode,vars,xrange,zip');\n\n/**\n * Order of operation ENUMs.\n * http://docs.python.org/reference/expressions.html#summary\n */\nPython.ORDER_ATOMIC = 0; // 0 \"\" ...\nPython.ORDER_COLLECTION = 1; // tuples, lists, dictionaries\nPython.ORDER_STRING_CONVERSION = 1; // `expression...`\nPython.ORDER_MEMBER = 2.1; // . []\nPython.ORDER_FUNCTION_CALL = 2.2; // ()\nPython.ORDER_EXPONENTIATION = 3; // **\nPython.ORDER_UNARY_SIGN = 4; // + -\nPython.ORDER_BITWISE_NOT = 4; // ~\nPython.ORDER_MULTIPLICATIVE = 5; // * / // %\nPython.ORDER_ADDITIVE = 6; // + -\nPython.ORDER_BITWISE_SHIFT = 7; // << >>\nPython.ORDER_BITWISE_AND = 8; // &\nPython.ORDER_BITWISE_XOR = 9; // ^\nPython.ORDER_BITWISE_OR = 10; // |\nPython.ORDER_RELATIONAL = 11; // in, not in, is, is not,\n // <, <=, >, >=, <>, !=, ==\nPython.ORDER_LOGICAL_NOT = 12; // not\nPython.ORDER_LOGICAL_AND = 13; // and\nPython.ORDER_LOGICAL_OR = 14; // or\nPython.ORDER_CONDITIONAL = 15; // if else\nPython.ORDER_LAMBDA = 16; // lambda\nPython.ORDER_NONE = 99; // (...)\n\n/**\n * List of outer-inner pairings that do NOT require parentheses.\n * @type {!Array>}\n */\nPython.ORDER_OVERRIDES = [\n // (foo()).bar -> foo().bar\n // (foo())[0] -> foo()[0]\n [Python.ORDER_FUNCTION_CALL, Python.ORDER_MEMBER],\n // (foo())() -> foo()()\n [Python.ORDER_FUNCTION_CALL, Python.ORDER_FUNCTION_CALL],\n // (foo.bar).baz -> foo.bar.baz\n // (foo.bar)[0] -> foo.bar[0]\n // (foo[0]).bar -> foo[0].bar\n // (foo[0])[1] -> foo[0][1]\n [Python.ORDER_MEMBER, Python.ORDER_MEMBER],\n // (foo.bar)() -> foo.bar()\n // (foo[0])() -> foo[0]()\n [Python.ORDER_MEMBER, Python.ORDER_FUNCTION_CALL],\n\n // not (not foo) -> not not foo\n [Python.ORDER_LOGICAL_NOT, Python.ORDER_LOGICAL_NOT],\n // a and (b and c) -> a and b and c\n [Python.ORDER_LOGICAL_AND, Python.ORDER_LOGICAL_AND],\n // a or (b or c) -> a or b or c\n [Python.ORDER_LOGICAL_OR, Python.ORDER_LOGICAL_OR]\n];\n\n/**\n * Whether the init method has been called.\n * @type {?boolean}\n */\nPython.isInitialized = false;\n\n/**\n * Initialise the database of variable names.\n * @param {!Workspace} workspace Workspace to generate code from.\n * @this {Generator}\n */\nPython.init = function(workspace) {\n // Call Blockly.Generator's init.\n Object.getPrototypeOf(this).init.call(this);\n\n /**\n * Empty loops or conditionals are not allowed in Python.\n */\n this.PASS = this.INDENT + 'pass\\n';\n\n if (!this.nameDB_) {\n this.nameDB_ = new Names(this.RESERVED_WORDS_);\n } else {\n this.nameDB_.reset();\n }\n\n this.nameDB_.setVariableMap(workspace.getVariableMap());\n this.nameDB_.populateVariables(workspace);\n this.nameDB_.populateProcedures(workspace);\n\n const defvars = [];\n // Add developer variables (not created or named by the user).\n const devVarList = Variables.allDeveloperVariables(workspace);\n for (let i = 0; i < devVarList.length; i++) {\n defvars.push(\n this.nameDB_.getName(devVarList[i], Names.DEVELOPER_VARIABLE_TYPE) +\n ' = None');\n }\n\n // Add user variables, but only ones that are being used.\n const variables = Variables.allUsedVarModels(workspace);\n for (let i = 0; i < variables.length; i++) {\n defvars.push(\n this.nameDB_.getName(variables[i].getId(), NameType.VARIABLE) +\n ' = None');\n }\n\n this.definitions_['variables'] = defvars.join('\\n');\n this.isInitialized = true;\n};\n\n/**\n * Prepend the generated code with import statements and variable definitions.\n * @param {string} code Generated code.\n * @return {string} Completed code.\n */\nPython.finish = function(code) {\n // Convert the definitions dictionary into a list.\n const imports = [];\n const definitions = [];\n for (let name in this.definitions_) {\n const def = this.definitions_[name];\n if (def.match(/^(from\\s+\\S+\\s+)?import\\s+\\S+/)) {\n imports.push(def);\n } else {\n definitions.push(def);\n }\n }\n // Call Blockly.Generator's finish.\n code = Object.getPrototypeOf(this).finish.call(this, code);\n this.isInitialized = false;\n\n this.nameDB_.reset();\n const allDefs = imports.join('\\n') + '\\n\\n' + definitions.join('\\n\\n');\n return allDefs.replace(/\\n\\n+/g, '\\n\\n').replace(/\\n*$/, '\\n\\n\\n') + code;\n};\n\n/**\n * Naked values are top-level blocks with outputs that aren't plugged into\n * anything.\n * @param {string} line Line of generated code.\n * @return {string} Legal line of code.\n */\nPython.scrubNakedValue = function(line) {\n return line + '\\n';\n};\n\n/**\n * Encode a string as a properly escaped Python string, complete with quotes.\n * @param {string} string Text to encode.\n * @return {string} Python string.\n * @protected\n */\nPython.quote_ = function(string) {\n // Can't use goog.string.quote since % must also be escaped.\n string = string.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, '\\\\\\n');\n\n // Follow the CPython behaviour of repr() for a non-byte string.\n let quote = '\\'';\n if (string.indexOf('\\'') !== -1) {\n if (string.indexOf('\"') === -1) {\n quote = '\"';\n } else {\n string = string.replace(/'/g, '\\\\\\'');\n }\n }\n return quote + string + quote;\n};\n\n/**\n * Encode a string as a properly escaped multiline Python string, complete\n * with quotes.\n * @param {string} string Text to encode.\n * @return {string} Python string.\n * @protected\n */\nPython.multiline_quote_ = function(string) {\n const lines = string.split(/\\n/g).map(this.quote_);\n // Join with the following, plus a newline:\n // + '\\n' +\n return lines.join(' + \\'\\\\n\\' + \\n');\n};\n\n/**\n * Common tasks for generating Python from blocks.\n * Handles comments for the specified block and any connected value blocks.\n * Calls any statements following this block.\n * @param {!Block} block The current block.\n * @param {string} code The Python code created for this block.\n * @param {boolean=} opt_thisOnly True to generate code for only this statement.\n * @return {string} Python code with comments and subsequent blocks added.\n * @protected\n */\nPython.scrub_ = function(block, code, opt_thisOnly) {\n let commentCode = '';\n // Only collect comments for blocks that aren't inline.\n if (!block.outputConnection || !block.outputConnection.targetConnection) {\n // Collect comment for this block.\n let comment = block.getCommentText();\n if (comment) {\n comment = stringUtils.wrap(comment, this.COMMENT_WRAP - 3);\n commentCode += this.prefixLines(comment + '\\n', '# ');\n }\n // Collect comments for all value arguments.\n // Don't collect comments for nested statements.\n for (let i = 0; i < block.inputList.length; i++) {\n if (block.inputList[i].type === inputTypes.VALUE) {\n const childBlock = block.inputList[i].connection.targetBlock();\n if (childBlock) {\n comment = this.allNestedComments(childBlock);\n if (comment) {\n commentCode += this.prefixLines(comment, '# ');\n }\n }\n }\n }\n }\n const nextBlock = block.nextConnection && block.nextConnection.targetBlock();\n const nextCode = opt_thisOnly ? '' : this.blockToCode(nextBlock);\n return commentCode + code + nextCode;\n};\n\n/**\n * Gets a property and adjusts the value, taking into account indexing.\n * If a static int, casts to an integer, otherwise returns a code string.\n * @param {!Block} block The block.\n * @param {string} atId The property ID of the element to get.\n * @param {number=} opt_delta Value to add.\n * @param {boolean=} opt_negate Whether to negate the value.\n * @return {string|number}\n */\nPython.getAdjustedInt = function(block, atId, opt_delta, opt_negate) {\n let delta = opt_delta || 0;\n if (block.workspace.options.oneBasedIndex) {\n delta--;\n }\n const defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0';\n const atOrder = delta ? this.ORDER_ADDITIVE : this.ORDER_NONE;\n let at = this.valueToCode(block, atId, atOrder) || defaultAtIndex;\n\n if (stringUtils.isNumber(at)) {\n // If the index is a naked number, adjust it right now.\n at = parseInt(at, 10) + delta;\n if (opt_negate) {\n at = -at;\n }\n } else {\n // If the index is dynamic, adjust it in code.\n if (delta > 0) {\n at = 'int(' + at + ' + ' + delta + ')';\n } else if (delta < 0) {\n at = 'int(' + at + ' - ' + -delta + ')';\n } else {\n at = 'int(' + at + ')';\n }\n if (opt_negate) {\n at = '-' + at;\n }\n }\n return at;\n};\n\nexports.pythonGenerator = Python;\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Generating Python for variable blocks.\n */\n'use strict';\n\ngoog.module('Blockly.Python.variables');\n\nconst {NameType} = goog.require('Blockly.Names');\nconst {pythonGenerator: Python} = goog.require('Blockly.Python');\n\n\nPython['variables_get'] = function(block) {\n // Variable getter.\n const code =\n Python.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE);\n return [code, Python.ORDER_ATOMIC];\n};\n\nPython['variables_set'] = function(block) {\n // Variable setter.\n const argument0 =\n Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || '0';\n const varName =\n Python.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE);\n return varName + ' = ' + argument0 + '\\n';\n};\n","/**\n * @license\n * Copyright 2018 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Generating Python for dynamic variable blocks.\n */\n'use strict';\n\ngoog.module('Blockly.Python.variablesDynamic');\n\nconst {pythonGenerator: Python} = goog.require('Blockly.Python');\n/** @suppress {extraRequire} */\ngoog.require('Blockly.Python.variables');\n\n\n// Python is dynamically typed.\nPython['variables_get_dynamic'] = Python['variables_get'];\nPython['variables_set_dynamic'] = Python['variables_set'];\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Generating Python for text blocks.\n */\n'use strict';\n\ngoog.module('Blockly.Python.texts');\n\nconst stringUtils = goog.require('Blockly.utils.string');\nconst {NameType} = goog.require('Blockly.Names');\nconst {pythonGenerator: Python} = goog.require('Blockly.Python');\n\n\nPython['text'] = function(block) {\n // Text value.\n const code = Python.quote_(block.getFieldValue('TEXT'));\n return [code, Python.ORDER_ATOMIC];\n};\n\nPython['text_multiline'] = function(block) {\n // Text value.\n const code = Python.multiline_quote_(block.getFieldValue('TEXT'));\n const order =\n code.indexOf('+') !== -1 ? Python.ORDER_ADDITIVE : Python.ORDER_ATOMIC;\n return [code, order];\n};\n\n/**\n * Regular expression to detect a single-quoted string literal.\n */\nconst strRegExp = /^\\s*'([^']|\\\\')*'\\s*$/;\n\n/**\n * Enclose the provided value in 'str(...)' function.\n * Leave string literals alone.\n * @param {string} value Code evaluating to a value.\n * @return {Array} Array containing code evaluating to a string\n * and\n * the order of the returned code.[string, number]\n */\nconst forceString = function(value) {\n if (strRegExp.test(value)) {\n return [value, Python.ORDER_ATOMIC];\n }\n return ['str(' + value + ')', Python.ORDER_FUNCTION_CALL];\n};\n\nPython['text_join'] = function(block) {\n // Create a string made up of any number of elements of any type.\n // Should we allow joining by '-' or ',' or any other characters?\n switch (block.itemCount_) {\n case 0:\n return [\"''\", Python.ORDER_ATOMIC];\n case 1: {\n const element =\n Python.valueToCode(block, 'ADD0', Python.ORDER_NONE) || \"''\";\n const codeAndOrder = forceString(element);\n return codeAndOrder;\n }\n case 2: {\n const element0 =\n Python.valueToCode(block, 'ADD0', Python.ORDER_NONE) || \"''\";\n const element1 =\n Python.valueToCode(block, 'ADD1', Python.ORDER_NONE) || \"''\";\n const code = forceString(element0)[0] + ' + ' + forceString(element1)[0];\n return [code, Python.ORDER_ADDITIVE];\n }\n default: {\n const elements = [];\n for (let i = 0; i < block.itemCount_; i++) {\n elements[i] =\n Python.valueToCode(block, 'ADD' + i, Python.ORDER_NONE) || \"''\";\n }\n const tempVar = Python.nameDB_.getDistinctName('x', NameType.VARIABLE);\n const code = '\\'\\'.join([str(' + tempVar + ') for ' + tempVar + ' in [' +\n elements.join(', ') + ']])';\n return [code, Python.ORDER_FUNCTION_CALL];\n }\n }\n};\n\nPython['text_append'] = function(block) {\n // Append to a variable in place.\n const varName =\n Python.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE);\n const value = Python.valueToCode(block, 'TEXT', Python.ORDER_NONE) || \"''\";\n return varName + ' = str(' + varName + ') + ' + forceString(value)[0] + '\\n';\n};\n\nPython['text_length'] = function(block) {\n // Is the string null or array empty?\n const text = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || \"''\";\n return ['len(' + text + ')', Python.ORDER_FUNCTION_CALL];\n};\n\nPython['text_isEmpty'] = function(block) {\n // Is the string null or array empty?\n const text = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || \"''\";\n const code = 'not len(' + text + ')';\n return [code, Python.ORDER_LOGICAL_NOT];\n};\n\nPython['text_indexOf'] = function(block) {\n // Search the text for a substring.\n // Should we allow for non-case sensitive???\n const operator = block.getFieldValue('END') === 'FIRST' ? 'find' : 'rfind';\n const substring =\n Python.valueToCode(block, 'FIND', Python.ORDER_NONE) || \"''\";\n const text =\n Python.valueToCode(block, 'VALUE', Python.ORDER_MEMBER) || \"''\";\n const code = text + '.' + operator + '(' + substring + ')';\n if (block.workspace.options.oneBasedIndex) {\n return [code + ' + 1', Python.ORDER_ADDITIVE];\n }\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['text_charAt'] = function(block) {\n // Get letter at index.\n // Note: Until January 2013 this block did not have the WHERE input.\n const where = block.getFieldValue('WHERE') || 'FROM_START';\n const textOrder =\n (where === 'RANDOM') ? Python.ORDER_NONE : Python.ORDER_MEMBER;\n const text = Python.valueToCode(block, 'VALUE', textOrder) || \"''\";\n switch (where) {\n case 'FIRST': {\n const code = text + '[0]';\n return [code, Python.ORDER_MEMBER];\n }\n case 'LAST': {\n const code = text + '[-1]';\n return [code, Python.ORDER_MEMBER];\n }\n case 'FROM_START': {\n const at = Python.getAdjustedInt(block, 'AT');\n const code = text + '[' + at + ']';\n return [code, Python.ORDER_MEMBER];\n }\n case 'FROM_END': {\n const at = Python.getAdjustedInt(block, 'AT', 1, true);\n const code = text + '[' + at + ']';\n return [code, Python.ORDER_MEMBER];\n }\n case 'RANDOM': {\n Python.definitions_['import_random'] = 'import random';\n const functionName = Python.provideFunction_('text_random_letter', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(text):\n x = int(random.random() * len(text))\n return text[x]\n`);\n const code = functionName + '(' + text + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n }\n }\n throw Error('Unhandled option (text_charAt).');\n};\n\nPython['text_getSubstring'] = function(block) {\n // Get substring.\n const where1 = block.getFieldValue('WHERE1');\n const where2 = block.getFieldValue('WHERE2');\n const text =\n Python.valueToCode(block, 'STRING', Python.ORDER_MEMBER) || \"''\";\n let at1;\n switch (where1) {\n case 'FROM_START':\n at1 = Python.getAdjustedInt(block, 'AT1');\n if (at1 === 0) {\n at1 = '';\n }\n break;\n case 'FROM_END':\n at1 = Python.getAdjustedInt(block, 'AT1', 1, true);\n break;\n case 'FIRST':\n at1 = '';\n break;\n default:\n throw Error('Unhandled option (text_getSubstring)');\n }\n\n let at2;\n switch (where2) {\n case 'FROM_START':\n at2 = Python.getAdjustedInt(block, 'AT2', 1);\n break;\n case 'FROM_END':\n at2 = Python.getAdjustedInt(block, 'AT2', 0, true);\n // Ensure that if the result calculated is 0 that sub-sequence will\n // include all elements as expected.\n if (!stringUtils.isNumber(String(at2))) {\n Python.definitions_['import_sys'] = 'import sys';\n at2 += ' or sys.maxsize';\n } else if (at2 === 0) {\n at2 = '';\n }\n break;\n case 'LAST':\n at2 = '';\n break;\n default:\n throw Error('Unhandled option (text_getSubstring)');\n }\n const code = text + '[' + at1 + ' : ' + at2 + ']';\n return [code, Python.ORDER_MEMBER];\n};\n\nPython['text_changeCase'] = function(block) {\n // Change capitalization.\n const OPERATORS = {\n 'UPPERCASE': '.upper()',\n 'LOWERCASE': '.lower()',\n 'TITLECASE': '.title()'\n };\n const operator = OPERATORS[block.getFieldValue('CASE')];\n const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || \"''\";\n const code = text + operator;\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['text_trim'] = function(block) {\n // Trim spaces.\n const OPERATORS = {\n 'LEFT': '.lstrip()',\n 'RIGHT': '.rstrip()',\n 'BOTH': '.strip()'\n };\n const operator = OPERATORS[block.getFieldValue('MODE')];\n const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || \"''\";\n const code = text + operator;\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['text_print'] = function(block) {\n // Print statement.\n const msg = Python.valueToCode(block, 'TEXT', Python.ORDER_NONE) || \"''\";\n return 'print(' + msg + ')\\n';\n};\n\nPython['text_prompt_ext'] = function(block) {\n // Prompt function.\n const functionName = Python.provideFunction_('text_prompt', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(msg):\n try:\n return raw_input(msg)\n except NameError:\n return input(msg)\n`);\n let msg;\n if (block.getField('TEXT')) {\n // Internal message.\n msg = Python.quote_(block.getFieldValue('TEXT'));\n } else {\n // External message.\n msg = Python.valueToCode(block, 'TEXT', Python.ORDER_NONE) || \"''\";\n }\n let code = functionName + '(' + msg + ')';\n const toNumber = block.getFieldValue('TYPE') === 'NUMBER';\n if (toNumber) {\n code = 'float(' + code + ')';\n }\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['text_prompt'] = Python['text_prompt_ext'];\n\nPython['text_count'] = function(block) {\n const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || \"''\";\n const sub = Python.valueToCode(block, 'SUB', Python.ORDER_NONE) || \"''\";\n const code = text + '.count(' + sub + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['text_replace'] = function(block) {\n const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || \"''\";\n const from = Python.valueToCode(block, 'FROM', Python.ORDER_NONE) || \"''\";\n const to = Python.valueToCode(block, 'TO', Python.ORDER_NONE) || \"''\";\n const code = text + '.replace(' + from + ', ' + to + ')';\n return [code, Python.ORDER_MEMBER];\n};\n\nPython['text_reverse'] = function(block) {\n const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || \"''\";\n const code = text + '[::-1]';\n return [code, Python.ORDER_MEMBER];\n};\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Generating Python for procedure blocks.\n */\n'use strict';\n\ngoog.module('Blockly.Python.procedures');\n\nconst Variables = goog.require('Blockly.Variables');\nconst {NameType} = goog.require('Blockly.Names');\nconst {pythonGenerator: Python} = goog.require('Blockly.Python');\n\n\nPython['procedures_defreturn'] = function(block) {\n // Define a procedure with a return value.\n // First, add a 'global' statement for every variable that is not shadowed by\n // a local parameter.\n const globals = [];\n const workspace = block.workspace;\n const usedVariables = Variables.allUsedVarModels(workspace) || [];\n for (let i = 0, variable; (variable = usedVariables[i]); i++) {\n const varName = variable.name;\n if (block.getVars().indexOf(varName) === -1) {\n globals.push(Python.nameDB_.getName(varName, NameType.VARIABLE));\n }\n }\n // Add developer variables.\n const devVarList = Variables.allDeveloperVariables(workspace);\n for (let i = 0; i < devVarList.length; i++) {\n globals.push(\n Python.nameDB_.getName(devVarList[i], NameType.DEVELOPER_VARIABLE));\n }\n\n const globalString = globals.length ?\n Python.INDENT + 'global ' + globals.join(', ') + '\\n' :\n '';\n const funcName =\n Python.nameDB_.getName(block.getFieldValue('NAME'), NameType.PROCEDURE);\n let xfix1 = '';\n if (Python.STATEMENT_PREFIX) {\n xfix1 += Python.injectId(Python.STATEMENT_PREFIX, block);\n }\n if (Python.STATEMENT_SUFFIX) {\n xfix1 += Python.injectId(Python.STATEMENT_SUFFIX, block);\n }\n if (xfix1) {\n xfix1 = Python.prefixLines(xfix1, Python.INDENT);\n }\n let loopTrap = '';\n if (Python.INFINITE_LOOP_TRAP) {\n loopTrap = Python.prefixLines(\n Python.injectId(Python.INFINITE_LOOP_TRAP, block), Python.INDENT);\n }\n let branch = Python.statementToCode(block, 'STACK');\n let returnValue =\n Python.valueToCode(block, 'RETURN', Python.ORDER_NONE) || '';\n let xfix2 = '';\n if (branch && returnValue) {\n // After executing the function body, revisit this block for the return.\n xfix2 = xfix1;\n }\n if (returnValue) {\n returnValue = Python.INDENT + 'return ' + returnValue + '\\n';\n } else if (!branch) {\n branch = Python.PASS;\n }\n const args = [];\n const variables = block.getVars();\n for (let i = 0; i < variables.length; i++) {\n args[i] = Python.nameDB_.getName(variables[i], NameType.VARIABLE);\n }\n let code = 'def ' + funcName + '(' + args.join(', ') + '):\\n' + globalString +\n xfix1 + loopTrap + branch + xfix2 + returnValue;\n code = Python.scrub_(block, code);\n // Add % so as not to collide with helper functions in definitions list.\n Python.definitions_['%' + funcName] = code;\n return null;\n};\n\n// Defining a procedure without a return value uses the same generator as\n// a procedure with a return value.\nPython['procedures_defnoreturn'] = Python['procedures_defreturn'];\n\nPython['procedures_callreturn'] = function(block) {\n // Call a procedure with a return value.\n const funcName =\n Python.nameDB_.getName(block.getFieldValue('NAME'), NameType.PROCEDURE);\n const args = [];\n const variables = block.getVars();\n for (let i = 0; i < variables.length; i++) {\n args[i] = Python.valueToCode(block, 'ARG' + i, Python.ORDER_NONE) || 'None';\n }\n const code = funcName + '(' + args.join(', ') + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['procedures_callnoreturn'] = function(block) {\n // Call a procedure with no return value.\n // Generated code is for a function call as a statement is the same as a\n // function call as a value, with the addition of line ending.\n const tuple = Python['procedures_callreturn'](block);\n return tuple[0] + '\\n';\n};\n\nPython['procedures_ifreturn'] = function(block) {\n // Conditionally return value from a procedure.\n const condition =\n Python.valueToCode(block, 'CONDITION', Python.ORDER_NONE) || 'False';\n let code = 'if ' + condition + ':\\n';\n if (Python.STATEMENT_SUFFIX) {\n // Inject any statement suffix here since the regular one at the end\n // will not get executed if the return is triggered.\n code += Python.prefixLines(\n Python.injectId(Python.STATEMENT_SUFFIX, block), Python.INDENT);\n }\n if (block.hasReturnValue_) {\n const value =\n Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || 'None';\n code += Python.INDENT + 'return ' + value + '\\n';\n } else {\n code += Python.INDENT + 'return\\n';\n }\n return code;\n};\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Generating Python for math blocks.\n */\n'use strict';\n\ngoog.module('Blockly.Python.math');\n\nconst {NameType} = goog.require('Blockly.Names');\nconst {pythonGenerator: Python} = goog.require('Blockly.Python');\n\n\n// If any new block imports any library, add that library name here.\nPython.addReservedWords('math,random,Number');\n\nPython['math_number'] = function(block) {\n // Numeric value.\n let code = Number(block.getFieldValue('NUM'));\n let order;\n if (code === Infinity) {\n code = 'float(\"inf\")';\n order = Python.ORDER_FUNCTION_CALL;\n } else if (code === -Infinity) {\n code = '-float(\"inf\")';\n order = Python.ORDER_UNARY_SIGN;\n } else {\n order = code < 0 ? Python.ORDER_UNARY_SIGN : Python.ORDER_ATOMIC;\n }\n return [code, order];\n};\n\nPython['math_arithmetic'] = function(block) {\n // Basic arithmetic operators, and power.\n const OPERATORS = {\n 'ADD': [' + ', Python.ORDER_ADDITIVE],\n 'MINUS': [' - ', Python.ORDER_ADDITIVE],\n 'MULTIPLY': [' * ', Python.ORDER_MULTIPLICATIVE],\n 'DIVIDE': [' / ', Python.ORDER_MULTIPLICATIVE],\n 'POWER': [' ** ', Python.ORDER_EXPONENTIATION],\n };\n const tuple = OPERATORS[block.getFieldValue('OP')];\n const operator = tuple[0];\n const order = tuple[1];\n const argument0 = Python.valueToCode(block, 'A', order) || '0';\n const argument1 = Python.valueToCode(block, 'B', order) || '0';\n const code = argument0 + operator + argument1;\n return [code, order];\n // In case of 'DIVIDE', division between integers returns different results\n // in Python 2 and 3. However, is not an issue since Blockly does not\n // guarantee identical results in all languages. To do otherwise would\n // require every operator to be wrapped in a function call. This would kill\n // legibility of the generated code.\n};\n\nPython['math_single'] = function(block) {\n // Math operators with single operand.\n const operator = block.getFieldValue('OP');\n let code;\n let arg;\n if (operator === 'NEG') {\n // Negation is a special case given its different operator precedence.\n code = Python.valueToCode(block, 'NUM', Python.ORDER_UNARY_SIGN) || '0';\n return ['-' + code, Python.ORDER_UNARY_SIGN];\n }\n Python.definitions_['import_math'] = 'import math';\n if (operator === 'SIN' || operator === 'COS' || operator === 'TAN') {\n arg = Python.valueToCode(block, 'NUM', Python.ORDER_MULTIPLICATIVE) || '0';\n } else {\n arg = Python.valueToCode(block, 'NUM', Python.ORDER_NONE) || '0';\n }\n // First, handle cases which generate values that don't need parentheses\n // wrapping the code.\n switch (operator) {\n case 'ABS':\n code = 'math.fabs(' + arg + ')';\n break;\n case 'ROOT':\n code = 'math.sqrt(' + arg + ')';\n break;\n case 'LN':\n code = 'math.log(' + arg + ')';\n break;\n case 'LOG10':\n code = 'math.log10(' + arg + ')';\n break;\n case 'EXP':\n code = 'math.exp(' + arg + ')';\n break;\n case 'POW10':\n code = 'math.pow(10,' + arg + ')';\n break;\n case 'ROUND':\n code = 'round(' + arg + ')';\n break;\n case 'ROUNDUP':\n code = 'math.ceil(' + arg + ')';\n break;\n case 'ROUNDDOWN':\n code = 'math.floor(' + arg + ')';\n break;\n case 'SIN':\n code = 'math.sin(' + arg + ' / 180.0 * math.pi)';\n break;\n case 'COS':\n code = 'math.cos(' + arg + ' / 180.0 * math.pi)';\n break;\n case 'TAN':\n code = 'math.tan(' + arg + ' / 180.0 * math.pi)';\n break;\n }\n if (code) {\n return [code, Python.ORDER_FUNCTION_CALL];\n }\n // Second, handle cases which generate values that may need parentheses\n // wrapping the code.\n switch (operator) {\n case 'ASIN':\n code = 'math.asin(' + arg + ') / math.pi * 180';\n break;\n case 'ACOS':\n code = 'math.acos(' + arg + ') / math.pi * 180';\n break;\n case 'ATAN':\n code = 'math.atan(' + arg + ') / math.pi * 180';\n break;\n default:\n throw Error('Unknown math operator: ' + operator);\n }\n return [code, Python.ORDER_MULTIPLICATIVE];\n};\n\nPython['math_constant'] = function(block) {\n // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.\n const CONSTANTS = {\n 'PI': ['math.pi', Python.ORDER_MEMBER],\n 'E': ['math.e', Python.ORDER_MEMBER],\n 'GOLDEN_RATIO': ['(1 + math.sqrt(5)) / 2', Python.ORDER_MULTIPLICATIVE],\n 'SQRT2': ['math.sqrt(2)', Python.ORDER_MEMBER],\n 'SQRT1_2': ['math.sqrt(1.0 / 2)', Python.ORDER_MEMBER],\n 'INFINITY': ['float(\\'inf\\')', Python.ORDER_ATOMIC],\n };\n const constant = block.getFieldValue('CONSTANT');\n if (constant !== 'INFINITY') {\n Python.definitions_['import_math'] = 'import math';\n }\n return CONSTANTS[constant];\n};\n\nPython['math_number_property'] = function(block) {\n // Check if a number is even, odd, prime, whole, positive, or negative\n // or if it is divisible by certain number. Returns true or false.\n const PROPERTIES = {\n 'EVEN': [' % 2 == 0', Python.ORDER_MULTIPLICATIVE, Python.ORDER_RELATIONAL],\n 'ODD': [' % 2 == 1', Python.ORDER_MULTIPLICATIVE, Python.ORDER_RELATIONAL],\n 'WHOLE': [' % 1 == 0', Python.ORDER_MULTIPLICATIVE,\n Python.ORDER_RELATIONAL],\n 'POSITIVE': [' > 0', Python.ORDER_RELATIONAL, Python.ORDER_RELATIONAL],\n 'NEGATIVE': [' < 0', Python.ORDER_RELATIONAL, Python.ORDER_RELATIONAL],\n 'DIVISIBLE_BY': [null, Python.ORDER_MULTIPLICATIVE,\n Python.ORDER_RELATIONAL],\n 'PRIME': [null, Python.ORDER_NONE, Python.ORDER_FUNCTION_CALL],\n }\n const dropdownProperty = block.getFieldValue('PROPERTY');\n const [suffix, inputOrder, outputOrder] = PROPERTIES[dropdownProperty];\n const numberToCheck = Python.valueToCode(block, 'NUMBER_TO_CHECK',\n inputOrder) || '0';\n let code;\n if (dropdownProperty === 'PRIME') {\n // Prime is a special case as it is not a one-liner test.\n Python.definitions_['import_math'] = 'import math';\n Python.definitions_['from_numbers_import_Number'] =\n 'from numbers import Number';\n const functionName = Python.provideFunction_('math_isPrime', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(n):\n # https://en.wikipedia.org/wiki/Primality_test#Naive_methods\n # If n is not a number but a string, try parsing it.\n if not isinstance(n, Number):\n try:\n n = float(n)\n except:\n return False\n if n == 2 or n == 3:\n return True\n # False if n is negative, is 1, or not whole, or if n is divisible by 2 or 3.\n if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0:\n return False\n # Check all the numbers of form 6k +/- 1, up to sqrt(n).\n for x in range(6, int(math.sqrt(n)) + 2, 6):\n if n % (x - 1) == 0 or n % (x + 1) == 0:\n return False\n return True\n`);\n code = functionName + '(' + numberToCheck + ')';\n } else if (dropdownProperty === 'DIVISIBLE_BY') {\n const divisor = Python.valueToCode(block, 'DIVISOR',\n Python.ORDER_MULTIPLICATIVE) || '0';\n // If 'divisor' is some code that evals to 0, Python will raise an error.\n if (divisor === '0') {\n return ['False', Python.ORDER_ATOMIC];\n }\n code = numberToCheck + ' % ' + divisor + ' == 0';\n } else {\n code = numberToCheck + suffix;\n };\n return [code, outputOrder];\n};\n\nPython['math_change'] = function(block) {\n // Add to a variable in place.\n Python.definitions_['from_numbers_import_Number'] =\n 'from numbers import Number';\n const argument0 =\n Python.valueToCode(block, 'DELTA', Python.ORDER_ADDITIVE) || '0';\n const varName =\n Python.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE);\n return varName + ' = (' + varName + ' if isinstance(' + varName +\n ', Number) else 0) + ' + argument0 + '\\n';\n};\n\n// Rounding functions have a single operand.\nPython['math_round'] = Python['math_single'];\n// Trigonometry functions have a single operand.\nPython['math_trig'] = Python['math_single'];\n\nPython['math_on_list'] = function(block) {\n // Math functions for lists.\n const func = block.getFieldValue('OP');\n const list = Python.valueToCode(block, 'LIST', Python.ORDER_NONE) || '[]';\n let code;\n switch (func) {\n case 'SUM':\n code = 'sum(' + list + ')';\n break;\n case 'MIN':\n code = 'min(' + list + ')';\n break;\n case 'MAX':\n code = 'max(' + list + ')';\n break;\n case 'AVERAGE': {\n Python.definitions_['from_numbers_import_Number'] =\n 'from numbers import Number';\n // This operation excludes null and values that aren't int or float:\n // math_mean([null, null, \"aString\", 1, 9]) -> 5.0\n const functionName = Python.provideFunction_('math_mean', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(myList):\n localList = [e for e in myList if isinstance(e, Number)]\n if not localList: return\n return float(sum(localList)) / len(localList)\n`);\n code = functionName + '(' + list + ')';\n break;\n }\n case 'MEDIAN': {\n Python.definitions_['from_numbers_import_Number'] =\n 'from numbers import Number';\n // This operation excludes null values:\n // math_median([null, null, 1, 3]) -> 2.0\n const functionName = Python.provideFunction_( 'math_median', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(myList):\n localList = sorted([e for e in myList if isinstance(e, Number)])\n if not localList: return\n if len(localList) % 2 == 0:\n return (localList[len(localList) // 2 - 1] + localList[len(localList) // 2]) / 2.0\n else:\n return localList[(len(localList) - 1) // 2]\n`);\n code = functionName + '(' + list + ')';\n break;\n }\n case 'MODE': {\n // As a list of numbers can contain more than one mode,\n // the returned result is provided as an array.\n // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]\n const functionName = Python.provideFunction_('math_modes', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(some_list):\n modes = []\n # Using a lists of [item, count] to keep count rather than dict\n # to avoid \"unhashable\" errors when the counted item is itself a list or dict.\n counts = []\n maxCount = 1\n for item in some_list:\n found = False\n for count in counts:\n if count[0] == item:\n count[1] += 1\n maxCount = max(maxCount, count[1])\n found = True\n if not found:\n counts.append([item, 1])\n for counted_item, item_count in counts:\n if item_count == maxCount:\n modes.append(counted_item)\n return modes\n`);\n code = functionName + '(' + list + ')';\n break;\n }\n case 'STD_DEV': {\n Python.definitions_['import_math'] = 'import math';\n const functionName = Python.provideFunction_('math_standard_deviation', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(numbers):\n n = len(numbers)\n if n == 0: return\n mean = float(sum(numbers)) / n\n variance = sum((x - mean) ** 2 for x in numbers) / n\n return math.sqrt(variance)\n`);\n code = functionName + '(' + list + ')';\n break;\n }\n case 'RANDOM':\n Python.definitions_['import_random'] = 'import random';\n code = 'random.choice(' + list + ')';\n break;\n default:\n throw Error('Unknown operator: ' + func);\n }\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['math_modulo'] = function(block) {\n // Remainder computation.\n const argument0 =\n Python.valueToCode(block, 'DIVIDEND', Python.ORDER_MULTIPLICATIVE) || '0';\n const argument1 =\n Python.valueToCode(block, 'DIVISOR', Python.ORDER_MULTIPLICATIVE) || '0';\n const code = argument0 + ' % ' + argument1;\n return [code, Python.ORDER_MULTIPLICATIVE];\n};\n\nPython['math_constrain'] = function(block) {\n // Constrain a number between two limits.\n const argument0 =\n Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || '0';\n const argument1 = Python.valueToCode(block, 'LOW', Python.ORDER_NONE) || '0';\n const argument2 =\n Python.valueToCode(block, 'HIGH', Python.ORDER_NONE) || 'float(\\'inf\\')';\n const code =\n 'min(max(' + argument0 + ', ' + argument1 + '), ' + argument2 + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['math_random_int'] = function(block) {\n // Random integer between [X] and [Y].\n Python.definitions_['import_random'] = 'import random';\n const argument0 = Python.valueToCode(block, 'FROM', Python.ORDER_NONE) || '0';\n const argument1 = Python.valueToCode(block, 'TO', Python.ORDER_NONE) || '0';\n const code = 'random.randint(' + argument0 + ', ' + argument1 + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['math_random_float'] = function(block) {\n // Random fraction between 0 and 1.\n Python.definitions_['import_random'] = 'import random';\n return ['random.random()', Python.ORDER_FUNCTION_CALL];\n};\n\nPython['math_atan2'] = function(block) {\n // Arctangent of point (X, Y) in degrees from -180 to 180.\n Python.definitions_['import_math'] = 'import math';\n const argument0 = Python.valueToCode(block, 'X', Python.ORDER_NONE) || '0';\n const argument1 = Python.valueToCode(block, 'Y', Python.ORDER_NONE) || '0';\n return [\n 'math.atan2(' + argument1 + ', ' + argument0 + ') / math.pi * 180',\n Python.ORDER_MULTIPLICATIVE\n ];\n};\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Generating Python for loop blocks.\n */\n'use strict';\n\ngoog.module('Blockly.Python.loops');\n\nconst stringUtils = goog.require('Blockly.utils.string');\nconst {NameType} = goog.require('Blockly.Names');\nconst {pythonGenerator: Python} = goog.require('Blockly.Python');\n\n\nPython['controls_repeat_ext'] = function(block) {\n // Repeat n times.\n let repeats;\n if (block.getField('TIMES')) {\n // Internal number.\n repeats = String(parseInt(block.getFieldValue('TIMES'), 10));\n } else {\n // External number.\n repeats = Python.valueToCode(block, 'TIMES', Python.ORDER_NONE) || '0';\n }\n if (stringUtils.isNumber(repeats)) {\n repeats = parseInt(repeats, 10);\n } else {\n repeats = 'int(' + repeats + ')';\n }\n let branch = Python.statementToCode(block, 'DO');\n branch = Python.addLoopTrap(branch, block) || Python.PASS;\n const loopVar = Python.nameDB_.getDistinctName('count', NameType.VARIABLE);\n const code = 'for ' + loopVar + ' in range(' + repeats + '):\\n' + branch;\n return code;\n};\n\nPython['controls_repeat'] = Python['controls_repeat_ext'];\n\nPython['controls_whileUntil'] = function(block) {\n // Do while/until loop.\n const until = block.getFieldValue('MODE') === 'UNTIL';\n let argument0 = Python.valueToCode(\n block, 'BOOL',\n until ? Python.ORDER_LOGICAL_NOT : Python.ORDER_NONE) ||\n 'False';\n let branch = Python.statementToCode(block, 'DO');\n branch = Python.addLoopTrap(branch, block) || Python.PASS;\n if (until) {\n argument0 = 'not ' + argument0;\n }\n return 'while ' + argument0 + ':\\n' + branch;\n};\n\nPython['controls_for'] = function(block) {\n // For loop.\n const variable0 =\n Python.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE);\n let argument0 = Python.valueToCode(block, 'FROM', Python.ORDER_NONE) || '0';\n let argument1 = Python.valueToCode(block, 'TO', Python.ORDER_NONE) || '0';\n let increment = Python.valueToCode(block, 'BY', Python.ORDER_NONE) || '1';\n let branch = Python.statementToCode(block, 'DO');\n branch = Python.addLoopTrap(branch, block) || Python.PASS;\n\n let code = '';\n let range;\n\n // Helper functions.\n const defineUpRange = function() {\n return Python.provideFunction_('upRange', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(start, stop, step):\n while start <= stop:\n yield start\n start += abs(step)\n`);\n };\n const defineDownRange = function() {\n return Python.provideFunction_('downRange', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(start, stop, step):\n while start >= stop:\n yield start\n start -= abs(step)\n`);\n };\n // Arguments are legal Python code (numbers or strings returned by scrub()).\n const generateUpDownRange = function(start, end, inc) {\n return '(' + start + ' <= ' + end + ') and ' + defineUpRange() + '(' +\n start + ', ' + end + ', ' + inc + ') or ' + defineDownRange() + '(' +\n start + ', ' + end + ', ' + inc + ')';\n };\n\n if (stringUtils.isNumber(argument0) && stringUtils.isNumber(argument1) &&\n stringUtils.isNumber(increment)) {\n // All parameters are simple numbers.\n argument0 = Number(argument0);\n argument1 = Number(argument1);\n increment = Math.abs(Number(increment));\n if (argument0 % 1 === 0 && argument1 % 1 === 0 && increment % 1 === 0) {\n // All parameters are integers.\n if (argument0 <= argument1) {\n // Count up.\n argument1++;\n if (argument0 === 0 && increment === 1) {\n // If starting index is 0, omit it.\n range = argument1;\n } else {\n range = argument0 + ', ' + argument1;\n }\n // If increment isn't 1, it must be explicit.\n if (increment !== 1) {\n range += ', ' + increment;\n }\n } else {\n // Count down.\n argument1--;\n range = argument0 + ', ' + argument1 + ', -' + increment;\n }\n range = 'range(' + range + ')';\n } else {\n // At least one of the parameters is not an integer.\n if (argument0 < argument1) {\n range = defineUpRange();\n } else {\n range = defineDownRange();\n }\n range += '(' + argument0 + ', ' + argument1 + ', ' + increment + ')';\n }\n } else {\n // Cache non-trivial values to variables to prevent repeated look-ups.\n const scrub = function(arg, suffix) {\n if (stringUtils.isNumber(arg)) {\n // Simple number.\n arg = Number(arg);\n } else if (!arg.match(/^\\w+$/)) {\n // Not a variable, it's complicated.\n const varName = Python.nameDB_.getDistinctName(\n variable0 + suffix, NameType.VARIABLE);\n code += varName + ' = ' + arg + '\\n';\n arg = varName;\n }\n return arg;\n };\n const startVar = scrub(argument0, '_start');\n const endVar = scrub(argument1, '_end');\n const incVar = scrub(increment, '_inc');\n\n if (typeof startVar === 'number' && typeof endVar === 'number') {\n if (startVar < endVar) {\n range = defineUpRange();\n } else {\n range = defineDownRange();\n }\n range += '(' + startVar + ', ' + endVar + ', ' + incVar + ')';\n } else {\n // We cannot determine direction statically.\n range = generateUpDownRange(startVar, endVar, incVar);\n }\n }\n code += 'for ' + variable0 + ' in ' + range + ':\\n' + branch;\n return code;\n};\n\nPython['controls_forEach'] = function(block) {\n // For each loop.\n const variable0 =\n Python.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE);\n const argument0 =\n Python.valueToCode(block, 'LIST', Python.ORDER_RELATIONAL) || '[]';\n let branch = Python.statementToCode(block, 'DO');\n branch = Python.addLoopTrap(branch, block) || Python.PASS;\n const code = 'for ' + variable0 + ' in ' + argument0 + ':\\n' + branch;\n return code;\n};\n\nPython['controls_flow_statements'] = function(block) {\n // Flow statements: continue, break.\n let xfix = '';\n if (Python.STATEMENT_PREFIX) {\n // Automatic prefix insertion is switched off for this block. Add manually.\n xfix += Python.injectId(Python.STATEMENT_PREFIX, block);\n }\n if (Python.STATEMENT_SUFFIX) {\n // Inject any statement suffix here since the regular one at the end\n // will not get executed if the break/continue is triggered.\n xfix += Python.injectId(Python.STATEMENT_SUFFIX, block);\n }\n if (Python.STATEMENT_PREFIX) {\n const loop = block.getSurroundLoop();\n if (loop && !loop.suppressPrefixSuffix) {\n // Inject loop's statement prefix here since the regular one at the end\n // of the loop will not get executed if 'continue' is triggered.\n // In the case of 'break', a prefix is needed due to the loop's suffix.\n xfix += Python.injectId(Python.STATEMENT_PREFIX, loop);\n }\n }\n switch (block.getFieldValue('FLOW')) {\n case 'BREAK':\n return xfix + 'break\\n';\n case 'CONTINUE':\n return xfix + 'continue\\n';\n }\n throw Error('Unknown flow statement.');\n};\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Generating Python for logic blocks.\n */\n'use strict';\n\ngoog.module('Blockly.Python.logic');\n\nconst {pythonGenerator: Python} = goog.require('Blockly.Python');\n\n\nPython['controls_if'] = function(block) {\n // If/elseif/else condition.\n let n = 0;\n let code = '', branchCode, conditionCode;\n if (Python.STATEMENT_PREFIX) {\n // Automatic prefix insertion is switched off for this block. Add manually.\n code += Python.injectId(Python.STATEMENT_PREFIX, block);\n }\n do {\n conditionCode =\n Python.valueToCode(block, 'IF' + n, Python.ORDER_NONE) || 'False';\n branchCode = Python.statementToCode(block, 'DO' + n) || Python.PASS;\n if (Python.STATEMENT_SUFFIX) {\n branchCode =\n Python.prefixLines(\n Python.injectId(Python.STATEMENT_SUFFIX, block), Python.INDENT) +\n branchCode;\n }\n code += (n === 0 ? 'if ' : 'elif ') + conditionCode + ':\\n' + branchCode;\n n++;\n } while (block.getInput('IF' + n));\n\n if (block.getInput('ELSE') || Python.STATEMENT_SUFFIX) {\n branchCode = Python.statementToCode(block, 'ELSE') || Python.PASS;\n if (Python.STATEMENT_SUFFIX) {\n branchCode =\n Python.prefixLines(\n Python.injectId(Python.STATEMENT_SUFFIX, block), Python.INDENT) +\n branchCode;\n }\n code += 'else:\\n' + branchCode;\n }\n return code;\n};\n\nPython['controls_ifelse'] = Python['controls_if'];\n\nPython['logic_compare'] = function(block) {\n // Comparison operator.\n const OPERATORS =\n {'EQ': '==', 'NEQ': '!=', 'LT': '<', 'LTE': '<=', 'GT': '>', 'GTE': '>='};\n const operator = OPERATORS[block.getFieldValue('OP')];\n const order = Python.ORDER_RELATIONAL;\n const argument0 = Python.valueToCode(block, 'A', order) || '0';\n const argument1 = Python.valueToCode(block, 'B', order) || '0';\n const code = argument0 + ' ' + operator + ' ' + argument1;\n return [code, order];\n};\n\nPython['logic_operation'] = function(block) {\n // Operations 'and', 'or'.\n const operator = (block.getFieldValue('OP') === 'AND') ? 'and' : 'or';\n const order =\n (operator === 'and') ? Python.ORDER_LOGICAL_AND : Python.ORDER_LOGICAL_OR;\n let argument0 = Python.valueToCode(block, 'A', order);\n let argument1 = Python.valueToCode(block, 'B', order);\n if (!argument0 && !argument1) {\n // If there are no arguments, then the return value is false.\n argument0 = 'False';\n argument1 = 'False';\n } else {\n // Single missing arguments have no effect on the return value.\n const defaultArgument = (operator === 'and') ? 'True' : 'False';\n if (!argument0) {\n argument0 = defaultArgument;\n }\n if (!argument1) {\n argument1 = defaultArgument;\n }\n }\n const code = argument0 + ' ' + operator + ' ' + argument1;\n return [code, order];\n};\n\nPython['logic_negate'] = function(block) {\n // Negation.\n const argument0 =\n Python.valueToCode(block, 'BOOL', Python.ORDER_LOGICAL_NOT) || 'True';\n const code = 'not ' + argument0;\n return [code, Python.ORDER_LOGICAL_NOT];\n};\n\nPython['logic_boolean'] = function(block) {\n // Boolean values true and false.\n const code = (block.getFieldValue('BOOL') === 'TRUE') ? 'True' : 'False';\n return [code, Python.ORDER_ATOMIC];\n};\n\nPython['logic_null'] = function(block) {\n // Null data type.\n return ['None', Python.ORDER_ATOMIC];\n};\n\nPython['logic_ternary'] = function(block) {\n // Ternary operator.\n const value_if =\n Python.valueToCode(block, 'IF', Python.ORDER_CONDITIONAL) || 'False';\n const value_then =\n Python.valueToCode(block, 'THEN', Python.ORDER_CONDITIONAL) || 'None';\n const value_else =\n Python.valueToCode(block, 'ELSE', Python.ORDER_CONDITIONAL) || 'None';\n const code = value_then + ' if ' + value_if + ' else ' + value_else;\n return [code, Python.ORDER_CONDITIONAL];\n};\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Generating Python for list blocks.\n */\n'use strict';\n\ngoog.module('Blockly.Python.lists');\n\nconst stringUtils = goog.require('Blockly.utils.string');\nconst {NameType} = goog.require('Blockly.Names');\nconst {pythonGenerator: Python} = goog.require('Blockly.Python');\n\n\nPython['lists_create_empty'] = function(block) {\n // Create an empty list.\n return ['[]', Python.ORDER_ATOMIC];\n};\n\nPython['lists_create_with'] = function(block) {\n // Create a list with any number of elements of any type.\n const elements = new Array(block.itemCount_);\n for (let i = 0; i < block.itemCount_; i++) {\n elements[i] =\n Python.valueToCode(block, 'ADD' + i, Python.ORDER_NONE) || 'None';\n }\n const code = '[' + elements.join(', ') + ']';\n return [code, Python.ORDER_ATOMIC];\n};\n\nPython['lists_repeat'] = function(block) {\n // Create a list with one element repeated.\n const item = Python.valueToCode(block, 'ITEM', Python.ORDER_NONE) || 'None';\n const times =\n Python.valueToCode(block, 'NUM', Python.ORDER_MULTIPLICATIVE) || '0';\n const code = '[' + item + '] * ' + times;\n return [code, Python.ORDER_MULTIPLICATIVE];\n};\n\nPython['lists_length'] = function(block) {\n // String or array length.\n const list = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || '[]';\n return ['len(' + list + ')', Python.ORDER_FUNCTION_CALL];\n};\n\nPython['lists_isEmpty'] = function(block) {\n // Is the string null or array empty?\n const list = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || '[]';\n const code = 'not len(' + list + ')';\n return [code, Python.ORDER_LOGICAL_NOT];\n};\n\nPython['lists_indexOf'] = function(block) {\n // Find an item in the list.\n const item = Python.valueToCode(block, 'FIND', Python.ORDER_NONE) || '[]';\n const list = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || \"''\";\n let errorIndex = ' -1';\n let firstIndexAdjustment = '';\n let lastIndexAdjustment = ' - 1';\n\n if (block.workspace.options.oneBasedIndex) {\n errorIndex = ' 0';\n firstIndexAdjustment = ' + 1';\n lastIndexAdjustment = '';\n }\n\n let functionName;\n if (block.getFieldValue('END') === 'FIRST') {\n functionName = Python.provideFunction_('first_index', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(my_list, elem):\n try: index = my_list.index(elem)${firstIndexAdjustment}\n except: index =${errorIndex}\n return index\n`);\n } else {\n functionName = Python.provideFunction_('last_index', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(my_list, elem):\n try: index = len(my_list) - my_list[::-1].index(elem)${lastIndexAdjustment}\n except: index =${errorIndex}\n return index\n`);\n }\n const code = functionName + '(' + list + ', ' + item + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['lists_getIndex'] = function(block) {\n // Get element at index.\n // Note: Until January 2013 this block did not have MODE or WHERE inputs.\n const mode = block.getFieldValue('MODE') || 'GET';\n const where = block.getFieldValue('WHERE') || 'FROM_START';\n const listOrder =\n (where === 'RANDOM') ? Python.ORDER_NONE : Python.ORDER_MEMBER;\n const list = Python.valueToCode(block, 'VALUE', listOrder) || '[]';\n\n switch (where) {\n case 'FIRST':\n if (mode === 'GET') {\n const code = list + '[0]';\n return [code, Python.ORDER_MEMBER];\n } else if (mode === 'GET_REMOVE') {\n const code = list + '.pop(0)';\n return [code, Python.ORDER_FUNCTION_CALL];\n } else if (mode === 'REMOVE') {\n return list + '.pop(0)\\n';\n }\n break;\n case 'LAST':\n if (mode === 'GET') {\n const code = list + '[-1]';\n return [code, Python.ORDER_MEMBER];\n } else if (mode === 'GET_REMOVE') {\n const code = list + '.pop()';\n return [code, Python.ORDER_FUNCTION_CALL];\n } else if (mode === 'REMOVE') {\n return list + '.pop()\\n';\n }\n break;\n case 'FROM_START': {\n const at = Python.getAdjustedInt(block, 'AT');\n if (mode === 'GET') {\n const code = list + '[' + at + ']';\n return [code, Python.ORDER_MEMBER];\n } else if (mode === 'GET_REMOVE') {\n const code = list + '.pop(' + at + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n } else if (mode === 'REMOVE') {\n return list + '.pop(' + at + ')\\n';\n }\n break;\n }\n case 'FROM_END': {\n const at = Python.getAdjustedInt(block, 'AT', 1, true);\n if (mode === 'GET') {\n const code = list + '[' + at + ']';\n return [code, Python.ORDER_MEMBER];\n } else if (mode === 'GET_REMOVE') {\n const code = list + '.pop(' + at + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n } else if (mode === 'REMOVE') {\n return list + '.pop(' + at + ')\\n';\n }\n break;\n }\n case 'RANDOM':\n Python.definitions_['import_random'] = 'import random';\n if (mode === 'GET') {\n const code = 'random.choice(' + list + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n } else {\n const functionName =\n Python.provideFunction_('lists_remove_random_item', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(myList):\n x = int(random.random() * len(myList))\n return myList.pop(x)\n`);\n const code = functionName + '(' + list + ')';\n if (mode === 'GET_REMOVE') {\n return [code, Python.ORDER_FUNCTION_CALL];\n } else if (mode === 'REMOVE') {\n return code + '\\n';\n }\n }\n break;\n }\n throw Error('Unhandled combination (lists_getIndex).');\n};\n\nPython['lists_setIndex'] = function(block) {\n // Set element at index.\n // Note: Until February 2013 this block did not have MODE or WHERE inputs.\n let list = Python.valueToCode(block, 'LIST', Python.ORDER_MEMBER) || '[]';\n const mode = block.getFieldValue('MODE') || 'GET';\n const where = block.getFieldValue('WHERE') || 'FROM_START';\n const value = Python.valueToCode(block, 'TO', Python.ORDER_NONE) || 'None';\n // Cache non-trivial values to variables to prevent repeated look-ups.\n // Closure, which accesses and modifies 'list'.\n function cacheList() {\n if (list.match(/^\\w+$/)) {\n return '';\n }\n const listVar =\n Python.nameDB_.getDistinctName('tmp_list', NameType.VARIABLE);\n const code = listVar + ' = ' + list + '\\n';\n list = listVar;\n return code;\n }\n\n switch (where) {\n case 'FIRST':\n if (mode === 'SET') {\n return list + '[0] = ' + value + '\\n';\n } else if (mode === 'INSERT') {\n return list + '.insert(0, ' + value + ')\\n';\n }\n break;\n case 'LAST':\n if (mode === 'SET') {\n return list + '[-1] = ' + value + '\\n';\n } else if (mode === 'INSERT') {\n return list + '.append(' + value + ')\\n';\n }\n break;\n case 'FROM_START': {\n const at = Python.getAdjustedInt(block, 'AT');\n if (mode === 'SET') {\n return list + '[' + at + '] = ' + value + '\\n';\n } else if (mode === 'INSERT') {\n return list + '.insert(' + at + ', ' + value + ')\\n';\n }\n break;\n }\n case 'FROM_END': {\n const at = Python.getAdjustedInt(block, 'AT', 1, true);\n if (mode === 'SET') {\n return list + '[' + at + '] = ' + value + '\\n';\n } else if (mode === 'INSERT') {\n return list + '.insert(' + at + ', ' + value + ')\\n';\n }\n break;\n }\n case 'RANDOM': {\n Python.definitions_['import_random'] = 'import random';\n let code = cacheList();\n const xVar = Python.nameDB_.getDistinctName('tmp_x', NameType.VARIABLE);\n code += xVar + ' = int(random.random() * len(' + list + '))\\n';\n if (mode === 'SET') {\n code += list + '[' + xVar + '] = ' + value + '\\n';\n return code;\n } else if (mode === 'INSERT') {\n code += list + '.insert(' + xVar + ', ' + value + ')\\n';\n return code;\n }\n break;\n }\n }\n throw Error('Unhandled combination (lists_setIndex).');\n};\n\nPython['lists_getSublist'] = function(block) {\n // Get sublist.\n const list = Python.valueToCode(block, 'LIST', Python.ORDER_MEMBER) || '[]';\n const where1 = block.getFieldValue('WHERE1');\n const where2 = block.getFieldValue('WHERE2');\n let at1;\n switch (where1) {\n case 'FROM_START':\n at1 = Python.getAdjustedInt(block, 'AT1');\n if (at1 === 0) {\n at1 = '';\n }\n break;\n case 'FROM_END':\n at1 = Python.getAdjustedInt(block, 'AT1', 1, true);\n break;\n case 'FIRST':\n at1 = '';\n break;\n default:\n throw Error('Unhandled option (lists_getSublist)');\n }\n\n let at2;\n switch (where2) {\n case 'FROM_START':\n at2 = Python.getAdjustedInt(block, 'AT2', 1);\n break;\n case 'FROM_END':\n at2 = Python.getAdjustedInt(block, 'AT2', 0, true);\n // Ensure that if the result calculated is 0 that sub-sequence will\n // include all elements as expected.\n if (!stringUtils.isNumber(String(at2))) {\n Python.definitions_['import_sys'] = 'import sys';\n at2 += ' or sys.maxsize';\n } else if (at2 === 0) {\n at2 = '';\n }\n break;\n case 'LAST':\n at2 = '';\n break;\n default:\n throw Error('Unhandled option (lists_getSublist)');\n }\n const code = list + '[' + at1 + ' : ' + at2 + ']';\n return [code, Python.ORDER_MEMBER];\n};\n\nPython['lists_sort'] = function(block) {\n // Block for sorting a list.\n const list = (Python.valueToCode(block, 'LIST', Python.ORDER_NONE) || '[]');\n const type = block.getFieldValue('TYPE');\n const reverse = block.getFieldValue('DIRECTION') === '1' ? 'False' : 'True';\n const sortFunctionName = Python.provideFunction_('lists_sort', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(my_list, type, reverse):\n def try_float(s):\n try:\n return float(s)\n except:\n return 0\n key_funcs = {\n \"NUMERIC\": try_float,\n \"TEXT\": str,\n \"IGNORE_CASE\": lambda s: str(s).lower()\n }\n key_func = key_funcs[type]\n list_cpy = list(my_list)\n return sorted(list_cpy, key=key_func, reverse=reverse)\n`);\n\n const code =\n sortFunctionName + '(' + list + ', \"' + type + '\", ' + reverse + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['lists_split'] = function(block) {\n // Block for splitting text into a list, or joining a list into text.\n const mode = block.getFieldValue('MODE');\n let code;\n if (mode === 'SPLIT') {\n const value_input =\n Python.valueToCode(block, 'INPUT', Python.ORDER_MEMBER) || \"''\";\n const value_delim = Python.valueToCode(block, 'DELIM', Python.ORDER_NONE);\n code = value_input + '.split(' + value_delim + ')';\n } else if (mode === 'JOIN') {\n const value_input =\n Python.valueToCode(block, 'INPUT', Python.ORDER_NONE) || '[]';\n const value_delim =\n Python.valueToCode(block, 'DELIM', Python.ORDER_MEMBER) || \"''\";\n code = value_delim + '.join(' + value_input + ')';\n } else {\n throw Error('Unknown mode: ' + mode);\n }\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['lists_reverse'] = function(block) {\n // Block for reversing a list.\n const list = Python.valueToCode(block, 'LIST', Python.ORDER_NONE) || '[]';\n const code = 'list(reversed(' + list + '))';\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n","/**\n * @license\n * Copyright 2012 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Generating Python for colour blocks.\n */\n'use strict';\n\ngoog.module('Blockly.Python.colour');\n\nconst {pythonGenerator: Python} = goog.require('Blockly.Python');\n\n\nPython['colour_picker'] = function(block) {\n // Colour picker.\n const code = Python.quote_(block.getFieldValue('COLOUR'));\n return [code, Python.ORDER_ATOMIC];\n};\n\nPython['colour_random'] = function(block) {\n // Generate a random colour.\n Python.definitions_['import_random'] = 'import random';\n const code = '\\'#%06x\\' % random.randint(0, 2**24 - 1)';\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['colour_rgb'] = function(block) {\n // Compose a colour from RGB components expressed as percentages.\n const functionName = Python.provideFunction_('colour_rgb', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(r, g, b):\n r = round(min(100, max(0, r)) * 2.55)\n g = round(min(100, max(0, g)) * 2.55)\n b = round(min(100, max(0, b)) * 2.55)\n return '#%02x%02x%02x' % (r, g, b)\n`);\n const r = Python.valueToCode(block, 'RED', Python.ORDER_NONE) || 0;\n const g = Python.valueToCode(block, 'GREEN', Python.ORDER_NONE) || 0;\n const b = Python.valueToCode(block, 'BLUE', Python.ORDER_NONE) || 0;\n const code = functionName + '(' + r + ', ' + g + ', ' + b + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n\nPython['colour_blend'] = function(block) {\n // Blend two colours together.\n const functionName = Python.provideFunction_('colour_blend', `\ndef ${Python.FUNCTION_NAME_PLACEHOLDER_}(colour1, colour2, ratio):\n r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)\n g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)\n b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)\n ratio = min(1, max(0, ratio))\n r = round(r1 * (1 - ratio) + r2 * ratio)\n g = round(g1 * (1 - ratio) + g2 * ratio)\n b = round(b1 * (1 - ratio) + b2 * ratio)\n return '#%02x%02x%02x' % (r, g, b)\n`);\n const colour1 =\n Python.valueToCode(block, 'COLOUR1', Python.ORDER_NONE) || '\\'#000000\\'';\n const colour2 =\n Python.valueToCode(block, 'COLOUR2', Python.ORDER_NONE) || '\\'#000000\\'';\n const ratio = Python.valueToCode(block, 'RATIO', Python.ORDER_NONE) || 0;\n const code =\n functionName + '(' + colour1 + ', ' + colour2 + ', ' + ratio + ')';\n return [code, Python.ORDER_FUNCTION_CALL];\n};\n","/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Complete helper functions for generating Python for\n * blocks. This is the entrypoint for python_compressed.js.\n * @suppress {extraRequire}\n */\n'use strict';\n\ngoog.module('Blockly.Python.all');\n\nconst moduleExports = goog.require('Blockly.Python');\ngoog.require('Blockly.Python.colour');\ngoog.require('Blockly.Python.lists');\ngoog.require('Blockly.Python.logic');\ngoog.require('Blockly.Python.loops');\ngoog.require('Blockly.Python.math');\ngoog.require('Blockly.Python.procedures');\ngoog.require('Blockly.Python.texts');\ngoog.require('Blockly.Python.variables');\ngoog.require('Blockly.Python.variablesDynamic');\n\nexports = moduleExports;\n"]} \ No newline at end of file diff --git a/index.html b/index.html index 9845256..ec014bb 100644 --- a/index.html +++ b/index.html @@ -662,6 +662,18 @@ + + + + + + + + + + ラベル + スコア + @@ -1017,12 +1029,12 @@ - - - - - - + + + + + + diff --git a/index.js b/index.js index f032fc2..6793647 100644 --- a/index.js +++ b/index.js @@ -196,6 +196,21 @@ Blockly.registry.register( Blockly.registry.Type.TOOLBOX_ITEM, Blockly.ToolboxCategory.registrationName, CustomCategory, true); + +// Always await function call +Blockly.JavaScript['procedures_callreturn'] = function (block) { + // Call a procedure with a return value. + var funcName = Blockly.JavaScript.variableDB_.getName( + block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); + var args = []; + var variables = block.getVars(); + for (var i = 0; i < variables.length; i++) { + args[i] = Blockly.JavaScript.valueToCode(block, 'ARG' + i, + Blockly.JavaScript.ORDER_NONE) || 'null'; + } + var code = 'await ' + funcName + '(' + args.join(', ') + ')'; + return [code, Blockly.JavaScript.ORDER_AWAIT]; +}; //============ User Customize End =============== @@ -330,7 +345,8 @@ const ugj_generateCode = () => { code = ''; } } else { // Javascript コード出力 - code = Blockly.JavaScript.workspaceToCode(workspace); + code = Blockly.JavaScript.workspaceToCode(workspace).replace(/(?<=^|\n)function \w+\(.*\)/g, 'async $&'); + // .replace 以降は、関数の常時非同期化のため } return code; } @@ -578,7 +594,7 @@ var workspace = Blockly.inject(blocklyDiv, }, zoom: { startScale: 1.0, controls: true }, trashcan: true, - media: './google-blockly/media/' + media: './node_modules/blockly/media/' }); var onresize = function (e) { // Compute the absolute coordinates and dimensions of blocklyArea. diff --git a/package-lock.json b/package-lock.json index df5a5cb..8ef8434 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ocoge", - "version": "0.1.8", + "version": "0.1.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ocoge", - "version": "0.1.8", + "version": "0.1.9", "license": "ISC", "dependencies": { "@ocoge.club/pigpio": "file:local_modules/pigpio", @@ -14,65 +14,22 @@ "@tensorflow-models/knn-classifier": "^1.2.4", "@tensorflow-models/mobilenet": "^2.1.0", "@tensorflow-models/speech-commands": "^0.5.4", - "@tensorflow/tfjs": "^4.1.0", - "@tensorflow/tfjs-backend-wasm": "^4.1.0", - "axios": "^1.2.0", + "@tensorflow/tfjs-node": "^4.1.0", + "axios": "^1.2.1", + "blockly": "^9.2.0", "node-abi": "^3.30.0", - "nodemailer": "^6.8.0", - "tensorset": "^1.2.9" + "nodemailer": "^6.8.0" }, "devDependencies": { "@electron-forge/cli": "^6.0.4", "@electron-forge/maker-deb": "^6.0.4", - "electron": "^22.0.0", - "electron-rebuild": "^3.2.9" - } - }, - "local_modules/@ocoge.club/pigpio": { - "version": "0.0.1", - "extraneous": true, - "license": "MIT", - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^1.7.1" - } - }, - "local_modules/@ocogeclub/amg8833": { - "version": "0.0.1", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@ocogeclub/pigpio": "file:../pigpio" - } - }, - "local_modules/@ocogeclub/bme280": { - "version": "0.0.1", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@ocogeclub/pigpio": "file:../pigpio" - } - }, - "local_modules/@ocogeclub/paj7620": { - "version": "0.0.1", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@ocogeclub/pigpio": "file:../pigpio" - } - }, - "local_modules/@ocogeclub/pigpio": { - "version": "0.0.1", - "extraneous": true, - "license": "MIT", - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^1.7.1" + "@electron/rebuild": "^3.2.10", + "electron": "^22.0.0" } }, "local_modules/pigpio": { - "name": "@ocoge.club/pigpio", "version": "0.0.1", + "hasInstallScript": true, "license": "MIT", "dependencies": { "bindings": "^1.5.0", @@ -426,9 +383,9 @@ } }, "node_modules/@electron/osx-sign": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.1.tgz", - "integrity": "sha512-WkUcva+qkt809bI6uxxEG/uOWfl8HAw0m8aPijpKmGMIpZ1CWWB808YG6aY3wckUO86xZdmiOsUJTM4keLhY8A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.4.tgz", + "integrity": "sha512-xfhdEcIOfAZg7scZ9RQPya1G1lWo8/zMCwUXAulq0SfY7ONIW+b9qGyKdMyuMctNYwllrIS+vmxfijSfjeh97g==", "dev": true, "dependencies": { "compare-version": "^0.1.2", @@ -446,23 +403,6 @@ "node": ">=12.0.0" } }, - "node_modules/@electron/osx-sign/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/@electron/rebuild": { "version": "3.2.10", "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.2.10.tgz", @@ -491,47 +431,6 @@ "node": ">=12.13.0" } }, - "node_modules/@electron/rebuild/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@electron/rebuild/node_modules/yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@electron/rebuild/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@electron/universal": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.3.4.tgz", @@ -615,6 +514,62 @@ "node": ">= 12.13.0" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", + "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -651,9 +606,9 @@ } }, "node_modules/@npmcli/fs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.0.tgz", - "integrity": "sha512-DmfBvNXGaetMxj9LTp8NAN9vEidXURrf5ZTslQzEAi/6GbW+4yjaLFQc6Tue5cpZ9Frlk4OBo/Snf1Bh/S7qTQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dev": true, "dependencies": { "@gar/promisify": "^1.1.3", @@ -664,9 +619,10 @@ } }, "node_modules/@npmcli/move-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.0.tgz", - "integrity": "sha512-UR6D5f4KEGWJV6BGPH3Qb2EtgH+t+1XQ1Tt85c7qicN6cezzuHPdZwwAxqZr4JLtnQu0LZsTza/5gmNmSl8XLg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", "dev": true, "dependencies": { "mkdirp": "^1.0.4", @@ -676,16 +632,19 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/@npmcli/move-file/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" + "dependencies": { + "glob": "^7.1.3" }, - "engines": { - "node": ">=10" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@ocoge.club/pigpio": { @@ -789,28 +748,6 @@ "@tensorflow/tfjs-core": "4.1.0" } }, - "node_modules/@tensorflow/tfjs-backend-cpu/node_modules/@types/seedrandom": { - "version": "2.4.30", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz", - "integrity": "sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==" - }, - "node_modules/@tensorflow/tfjs-backend-cpu/node_modules/seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" - }, - "node_modules/@tensorflow/tfjs-backend-wasm": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-wasm/-/tfjs-backend-wasm-4.1.0.tgz", - "integrity": "sha512-1bB+hsgRKywNa01shHRZm61UQbCSbRVS9EpJUv0HWcPnMQxKGGZ0L+Sc4lNbLutMHJtWtsEFgB3PifE7iubuWQ==", - "dependencies": { - "@tensorflow/tfjs-backend-cpu": "4.1.0", - "@types/emscripten": "~0.0.34" - }, - "peerDependencies": { - "@tensorflow/tfjs-core": "4.1.0" - } - }, "node_modules/@tensorflow/tfjs-backend-webgl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-4.1.0.tgz", @@ -829,16 +766,6 @@ "@tensorflow/tfjs-core": "4.1.0" } }, - "node_modules/@tensorflow/tfjs-backend-webgl/node_modules/@types/seedrandom": { - "version": "2.4.30", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz", - "integrity": "sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==" - }, - "node_modules/@tensorflow/tfjs-backend-webgl/node_modules/seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" - }, "node_modules/@tensorflow/tfjs-converter": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-4.1.0.tgz", @@ -870,16 +797,6 @@ "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz", "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==" }, - "node_modules/@tensorflow/tfjs-core/node_modules/@types/seedrandom": { - "version": "2.4.30", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz", - "integrity": "sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==" - }, - "node_modules/@tensorflow/tfjs-core/node_modules/seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" - }, "node_modules/@tensorflow/tfjs-data": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-4.1.0.tgz", @@ -902,32 +819,143 @@ "@tensorflow/tfjs-core": "4.1.0" } }, + "node_modules/@tensorflow/tfjs-node": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-node/-/tfjs-node-4.1.0.tgz", + "integrity": "sha512-2H7UJqVafuM9fbsMdzUkcfWLpH/owgvVHWES+gQsiueIqyOjpq6ZGSQLDxyuKtHP2D/8/kWeVIbnzAjnIRniuA==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "1.0.9", + "@tensorflow/tfjs": "4.1.0", + "adm-zip": "^0.5.2", + "google-protobuf": "^3.9.2", + "https-proxy-agent": "^2.2.1", + "progress": "^2.0.0", + "rimraf": "^2.6.2", + "tar": "^4.4.6" + }, + "engines": { + "node": ">=8.11.0" + } + }, + "node_modules/@tensorflow/tfjs-node/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/@tensorflow/tfjs-node/node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/@tensorflow/tfjs-node/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/@tensorflow/tfjs-node/node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/@tensorflow/tfjs-node/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/@tensorflow/tfjs-node/node_modules/tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "dependencies": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/@tensorflow/tfjs-node/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/@tensorflow/tfjs/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/@tensorflow/tfjs/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tensorflow/tfjs/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, "engines": { "node": ">= 10" } }, "node_modules/@types/cacheable-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", - "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", "dev": true, "dependencies": { "@types/http-cache-semantics": "*", - "@types/keyv": "*", + "@types/keyv": "^3.1.4", "@types/node": "*", - "@types/responselike": "*" + "@types/responselike": "^1.0.0" } }, - "node_modules/@types/emscripten": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-0.0.34.tgz", - "integrity": "sha512-QSb9ojDincskc+uKMI0KXp8e1NALFINCrMlp8VGKGcTSxeEyRTTKyjWw75NYrCZHUsVEEEpr1tYHpbtaC++/sQ==" - }, "node_modules/@types/fs-extra": { "version": "9.0.13", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", @@ -956,9 +984,9 @@ "dev": true }, "node_modules/@types/keyv": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", - "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", "dev": true, "dependencies": { "@types/node": "*" @@ -970,21 +998,21 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "dev": true, "optional": true }, "node_modules/@types/node": { - "version": "17.0.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", - "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==" + "version": "18.11.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz", + "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==" }, "node_modules/@types/node-fetch": { - "version": "2.5.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", - "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", + "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", "dependencies": { "@types/node": "*", "form-data": "^3.0.0" @@ -1005,9 +1033,9 @@ } }, "node_modules/@types/seedrandom": { - "version": "2.4.27", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.27.tgz", - "integrity": "sha1-nbVjk33YaRX2kJK8QyWdL0hXjkE=" + "version": "2.4.30", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz", + "integrity": "sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==" }, "node_modules/@types/webgl-ext": { "version": "0.0.30", @@ -1029,22 +1057,61 @@ "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.21.tgz", "integrity": "sha512-pUrWq3V5PiSGFLeLxoGqReTZmiiXwY3jRkIG5sLLKjyqNxrwm/04b4nw7LSmGWJcKk59XOM/YRTUwOzo4MMlow==" }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" + "node_modules/acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 6.0.0" + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.0.0" } }, "node_modules/agentkeepalive": { @@ -1114,34 +1181,18 @@ "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "node_modules/are-we-there-yet": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", - "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "node": ">=10" } }, "node_modules/argparse": { @@ -1153,9 +1204,10 @@ } }, "node_modules/asar": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/asar/-/asar-3.1.0.tgz", - "integrity": "sha512-vyxPxP5arcAqN4F/ebHd/HhwnAiZtwhglvdmc7BR2f0ywbVNTOpSeyhLDbGXtE/y58hv1oC75TaNIXutnsOZsQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", + "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==", + "deprecated": "Please use @electron/asar moving forward. There is no API change, just a package name change", "dev": true, "optional": true, "dependencies": { @@ -1196,7 +1248,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -1210,16 +1262,16 @@ "node_modules/author-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz", - "integrity": "sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA=", + "integrity": "sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==", "dev": true, "engines": { "node": ">=0.8" } }, "node_modules/axios": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.0.tgz", - "integrity": "sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz", + "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -1242,8 +1294,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64-js": { "version": "1.5.1", @@ -1284,18 +1335,12 @@ "readable-stream": "^3.4.0" } }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, + "node_modules/blockly": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/blockly/-/blockly-9.2.0.tgz", + "integrity": "sha512-rygZJupS5u4DMGGQ70gExH71c34vUEUjTVVBzhgVH7PCAK2RaitCNwr2yF6hGj/QTVodkjjEOdTzbHqLbuPipQ==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "jsdom": "20.0.3" } }, "node_modules/bluebird": { @@ -1305,9 +1350,9 @@ "dev": true }, "node_modules/boolean": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.4.tgz", - "integrity": "sha512-3hx0kwU3uzG6ReQ3pnaFQPSktpBw6RHN3/ivDKEuU8g1XSfafowyvDnadjv1xp8IZqhtSukxlwv9bF6FhX8m0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", "dev": true, "optional": true }, @@ -1315,7 +1360,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1360,7 +1404,7 @@ "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, "engines": { "node": "*" @@ -1385,9 +1429,9 @@ "dev": true }, "node_modules/cacache": { - "version": "16.1.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.1.tgz", - "integrity": "sha512-VDKN+LHyCQXaaYZ7rA/qtkURU+/yYhviUdvqEv2LT6QPZU8jpyzEkEVAcKlKLt5dJ5BRp11ym8lo3NKLluEPLg==", + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, "dependencies": { "@npmcli/fs": "^2.1.0", @@ -1407,7 +1451,7 @@ "rimraf": "^3.0.2", "ssri": "^9.0.0", "tar": "^6.1.11", - "unique-filename": "^1.1.1" + "unique-filename": "^2.0.0" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" @@ -1441,19 +1485,10 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.12.0.tgz", - "integrity": "sha512-OIP3DwzRZDfLg9B9VP/huWBlpvbkmbfiBy8xmsXp4RPmE4A3MhwNozc5ZJ3fWnSg8fDcdlE/neRTPG2ycEKliw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", + "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -1462,16 +1497,61 @@ "node": ">=10" } }, - "node_modules/cacache/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/cacache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, "bin": { - "mkdirp": "bin/cmd.js" + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/cacache/node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=10" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, "node_modules/cacheable-lookup": { @@ -1501,19 +1581,14 @@ "node": ">=8" } }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, + "optional": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/chalk": { @@ -1535,7 +1610,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, "engines": { "node": ">=10" } @@ -1543,7 +1617,7 @@ "node_modules/chromium-pickle-js": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", - "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", "dev": true }, "node_modules/clean-stack": { @@ -1568,9 +1642,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", "dev": true, "engines": { "node": ">=6" @@ -1596,19 +1670,23 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, "engines": { "node": ">=0.8" @@ -1646,7 +1724,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, "bin": { "color-support": "bin.js" } @@ -1689,19 +1766,17 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" }, "node_modules/core-js": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.0.tgz", - "integrity": "sha512-YUdI3fFu4TF/2WykQ2xzSiTQdldLB4KVuL9WeAy5XONZYt5Cun/fpQvctoKbCgvPhmzADeesTk/j2Rdx77AcKQ==", + "version": "3.26.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz", + "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -1768,11 +1843,44 @@ "node": ">= 10" } }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -1788,13 +1896,18 @@ "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, "optional": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -1822,13 +1935,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, "node_modules/defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "dependencies": { "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/defer-to-connect": { @@ -1841,22 +1962,26 @@ } }, "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", "dev": true, "optional": true, "dependencies": { - "object-keys": "^1.0.12" + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { "node": ">=0.4.0" } @@ -1864,8 +1989,7 @@ "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, "node_modules/depd": { "version": "1.1.2", @@ -1880,7 +2004,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", - "dev": true, "engines": { "node": ">=8" } @@ -1902,6 +2025,17 @@ "minimatch": "^3.0.4" } }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/electron": { "version": "22.0.0", "resolved": "https://registry.npmjs.org/electron/-/electron-22.0.0.tgz", @@ -2036,16 +2170,6 @@ "node": ">= 10" } }, - "node_modules/electron-installer-debian/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, "node_modules/electron-installer-debian/node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -2225,88 +2349,10 @@ "url": "https://github.com/electron/electron-packager?sponsor=1" } }, - "node_modules/electron-packager/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-packager/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-rebuild": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-3.2.9.tgz", - "integrity": "sha512-FkEZNFViUem3P0RLYbZkUjC8LUFIK+wKq09GHoOITSJjfDAVQv964hwaNseTTWt58sITQX3/5fHNYcTefqaCWw==", - "dev": true, - "dependencies": { - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "lzma-native": "^8.0.5", - "node-abi": "^3.0.0", - "node-api-version": "^0.1.4", - "node-gyp": "^9.0.0", - "ora": "^5.1.0", - "semver": "^7.3.5", - "tar": "^6.0.5", - "yargs": "^17.0.1" - }, - "bin": { - "electron-rebuild": "lib/src/cli.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/electron-rebuild/node_modules/yargs": { - "version": "17.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", - "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-rebuild/node_modules/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/electron/node_modules/@types/node": { - "version": "16.11.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.27.tgz", - "integrity": "sha512-C1pD3kgLoZ56Uuy5lhfOxie4aZlA3UMGLX9rXteq4WitEZH6Rl80mwactt9QG0w0gLFlN/kLBTFnGXtDVWvWQw==", + "version": "16.18.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", + "integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==", "dev": true }, "node_modules/emoji-regex": { @@ -2324,19 +2370,6 @@ "iconv-lite": "^0.6.2" } }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -2346,6 +2379,17 @@ "once": "^1.4.0" } }, + "node_modules/entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -2377,6 +2421,19 @@ "dev": true, "optional": true }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -2386,12 +2443,65 @@ } }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "optional": true, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" } }, "node_modules/execa": { @@ -2428,6 +2538,18 @@ "node": ">=4.8" } }, + "node_modules/execa/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/execa/node_modules/path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -2511,21 +2633,6 @@ "@types/yauzl": "^2.9.1" } }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -2542,10 +2649,15 @@ "node": ">=8.6.0" } }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -2554,7 +2666,7 @@ "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "dependencies": { "pend": "~1.2.0" @@ -2697,9 +2809,9 @@ } }, "node_modules/fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -2714,7 +2826,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -2725,8 +2836,7 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/function-bind": { "version": "1.1.1", @@ -2791,22 +2901,22 @@ "optional": true }, "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", "dependencies": { "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" + "wide-align": "^1.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=10" } }, "node_modules/get-caller-file": { @@ -2840,6 +2950,21 @@ "global-modules": "1.0.0" } }, + "node_modules/get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "dev": true, + "optional": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-info": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-1.0.0.tgz", @@ -2871,27 +2996,29 @@ "dev": true }, "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "dependencies": { "pump": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -2975,9 +3102,9 @@ } }, "node_modules/globalthis": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", - "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dev": true, "optional": true, "dependencies": { @@ -2990,10 +3117,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" + }, "node_modules/got": { - "version": "11.8.5", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", - "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "dev": true, "dependencies": { "@sindresorhus/is": "^4.0.0", @@ -3016,9 +3148,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, "node_modules/has": { @@ -3041,11 +3173,36 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "optional": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, "node_modules/homedir-polyfill": { "version": "1.0.3", @@ -3065,6 +3222,17 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -3075,7 +3243,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -3085,6 +3252,17 @@ "node": ">= 6" } }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/http2-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", @@ -3099,16 +3277,23 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dependencies": { - "agent-base": "6", - "debug": "4" + "agent-base": "^4.3.0", + "debug": "^3.1.0" }, "engines": { - "node": ">= 6" + "node": ">= 4.5.0" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" } }, "node_modules/humanize-ms": { @@ -3120,6 +3305,17 @@ "ms": "^2.0.0" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -3167,8 +3363,7 @@ "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3177,8 +3372,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ini": { "version": "1.3.8", @@ -3196,9 +3390,9 @@ } }, "node_modules/ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true }, "node_modules/is-arrayish": { @@ -3287,6 +3481,11 @@ "node": ">=0.12.0" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, "node_modules/is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -3344,9 +3543,89 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/jsdom/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3356,7 +3635,7 @@ "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true, "optional": true }, @@ -3390,10 +3669,22 @@ "json-buffer": "3.0.1" } }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/listr2": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.5.tgz", - "integrity": "sha512-DpBel6fczu7oQKTXMekeprc0o3XDgGMkD7JNYyX+X0xbwK+xgrx9dcyKoXKqpLSUvAWfmoePS7kavniOcq3r4w==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.6.tgz", + "integrity": "sha512-u60KxKBy1BR2uLJNTWNptzWQ1ob/gjMzIJPZffAENzpZqbMZ/5PrXXOomDcevIS/+IB7s1mmCEtSlT2qHWMqag==", "dev": true, "dependencies": { "cli-truncate": "^2.1.0", @@ -3401,7 +3692,7 @@ "log-update": "^4.0.0", "p-map": "^4.0.0", "rfdc": "^1.3.0", - "rxjs": "^7.5.6", + "rxjs": "^7.5.7", "through": "^2.3.8", "wrap-ansi": "^7.0.0" }, @@ -3539,14 +3830,12 @@ } }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/lzma-native": { @@ -3567,24 +3856,32 @@ "node": ">=10.0.0" } }, - "node_modules/lzma-native/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "semver": "^6.0.0" }, "engines": { - "node": ">= 6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" } }, "node_modules/make-fetch-happen": { - "version": "10.1.8", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.1.8.tgz", - "integrity": "sha512-0ASJbG12Au6+N5I84W+8FhGS6iM8MyzvZady+zaQAu+6IOaESFzCLLD0AR1sAFF3Jufi8bxm586ABN6hWd3k7g==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dev": true, "dependencies": { "agentkeepalive": "^4.2.1", @@ -3608,13 +3905,29 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.12.0.tgz", - "integrity": "sha512-OIP3DwzRZDfLg9B9VP/huWBlpvbkmbfiBy8xmsXp4RPmE4A3MhwNozc5ZJ3fWnSg8fDcdlE/neRTPG2ycEKliw==", + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, + "dependencies": { + "debug": "4" + }, "engines": { - "node": ">=12" + "node": ">= 6.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, "node_modules/map-age-cleaner": { @@ -3642,19 +3955,6 @@ "node": ">=10" } }, - "node_modules/matcher/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mem": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", @@ -3692,19 +3992,19 @@ } }, "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -3729,10 +4029,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.1.tgz", - "integrity": "sha512-reLxBcKUPNBnc/sVtAbxgRVFSegoGeLaSjmphNhcwcolhYLRgtJscn5mRl6YRZNQv40Y7P6JM2YhSIsbL9OB5A==", - "dev": true, + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3744,16 +4043,14 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "dev": true, + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dependencies": { "yallist": "^4.0.0" }, @@ -3774,9 +4071,9 @@ } }, "node_modules/minipass-fetch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.0.tgz", - "integrity": "sha512-H9U4UVBGXEyyWJnqYDCLp1PwD8XIkJ4akNHp1aGVI+2Ym7wQMlxDKi4IB4JbmyU+pl9pEs/cVrK6cOuvmbK4Sg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, "dependencies": { "minipass": "^3.1.6", @@ -3830,7 +4127,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -3839,11 +4135,21 @@ "node": ">= 8" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/negotiator": { "version": "0.6.3", @@ -3905,17 +4211,36 @@ } } }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-gyp": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.0.0.tgz", - "integrity": "sha512-Ma6p4s+XCTPxCuAMrOA/IJRmVy16R8Sdhtwl4PrCr7IBlj4cPawF0vg/l7nOT1jPbuNS7lIRJpBSvVsXwEZuzw==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", + "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", "dev": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.0.3", - "nopt": "^5.0.0", + "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", "semver": "^7.3.5", @@ -3926,13 +4251,13 @@ "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^12.22 || ^14.13 || >=16" + "node": "^12.13 || ^14.13 || >=16" } }, "node_modules/node-gyp-build": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", - "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", + "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", "dev": true, "bin": { "node-gyp-build": "bin.js", @@ -3940,6 +4265,83 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/nodemailer": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.8.0.tgz", @@ -3952,7 +4354,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, "dependencies": { "abbrev": "1" }, @@ -4018,18 +4419,27 @@ } }, "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "dependencies": { - "are-we-there-yet": "^3.0.0", + "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", + "gauge": "^3.0.0", "set-blocking": "^2.0.0" - }, + } + }, + "node_modules/nwsapi": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=0.10.0" } }, "node_modules/object-keys": { @@ -4045,8 +4455,7 @@ "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dependencies": { "wrappy": "1" } @@ -4066,6 +4475,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -4182,7 +4607,7 @@ "node_modules/parse-author": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz", - "integrity": "sha1-00YL8d3Q367tQtp1QkLmX7aEqB8=", + "integrity": "sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw==", "dev": true, "dependencies": { "author-regex": "^1.0.0" @@ -4212,6 +4637,17 @@ "node": ">=0.10.0" } }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4224,8 +4660,7 @@ "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "engines": { "node": ">=0.10.0" } @@ -4260,7 +4695,7 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, "node_modules/picomatch": { @@ -4361,11 +4796,18 @@ "node": ">=6" } }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -4394,6 +4836,11 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -4404,6 +4851,19 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4542,6 +5002,19 @@ "node": ">=4" } }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -4555,14 +5028,14 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "engines": { "node": ">=0.10.0" } @@ -4574,6 +5047,11 @@ "dev": true, "optional": true }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -4674,18 +5152,14 @@ "dev": true }, "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, "node_modules/roarr": { @@ -4737,9 +5211,9 @@ } }, "node_modules/rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", "dev": true, "dependencies": { "tslib": "^2.1.0" @@ -4767,19 +5241,28 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "optional": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } }, "node_modules/seedrandom": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.3.tgz", - "integrity": "sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw=" + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" }, "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -4793,10 +5276,21 @@ "node_modules/semver-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "dev": true, "optional": true }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/serialize-error": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", @@ -4829,8 +5323,7 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "node_modules/shebang-command": { "version": "2.0.0", @@ -4856,8 +5349,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/slice-ansi": { "version": "3.0.0", @@ -4884,12 +5376,12 @@ } }, "node_modules/socks": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", - "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dev": true, "dependencies": { - "ip": "^1.1.5", + "ip": "^2.0.0", "smart-buffer": "^4.2.0" }, "engines": { @@ -4911,11 +5403,23 @@ "node": ">= 10" } }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -4965,7 +5469,7 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/ssri": { "version": "9.0.1", @@ -5041,6 +5545,15 @@ "node": ">=0.10.0" } }, + "node_modules/strip-outer/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/sudo-prompt": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", @@ -5082,160 +5595,64 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", + "minipass": "^4.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, "engines": { "node": ">=10" } }, - "node_modules/tensorset": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/tensorset/-/tensorset-1.2.9.tgz", - "integrity": "sha512-xlMAotSaXkGf3U8/4n/n+svHgvT1HvwrssMTaRgSo2PQcYFVseYWPg9qnppi+/fnf4EdQpQdtqIYXyu8jSK73A==", + "node_modules/tar/node_modules/minipass": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.0.tgz", + "integrity": "sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==", "dependencies": { - "@tensorflow/tfjs": "^2.0.1" - } - }, - "node_modules/tensorset/node_modules/@tensorflow/tfjs": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-2.8.6.tgz", - "integrity": "sha512-/Hk3YCAreNicuQJsAIG32UGHaQj8UwX8y8ZrKVb/CrXOhrRyZmxGSZt9KMVe8MDoydenuGhZCqJUIaWdIKIA5g==", - "dependencies": { - "@tensorflow/tfjs-backend-cpu": "2.8.6", - "@tensorflow/tfjs-backend-webgl": "2.8.6", - "@tensorflow/tfjs-converter": "2.8.6", - "@tensorflow/tfjs-core": "2.8.6", - "@tensorflow/tfjs-data": "2.8.6", - "@tensorflow/tfjs-layers": "2.8.6", - "argparse": "^1.0.10", - "chalk": "^4.1.0", - "core-js": "3", - "regenerator-runtime": "^0.13.5", - "yargs": "^16.0.3" - }, - "bin": { - "tfjs-custom-bundle": "dist/tools/custom_bundle/cli.js" - } - }, - "node_modules/tensorset/node_modules/@tensorflow/tfjs-backend-cpu": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-2.8.6.tgz", - "integrity": "sha512-x9WTTE9p3Pon2D0d6HH1UCIJsU1w3v9sF3vxJcp+YStrjDefWoW5pwxHCckEKTRra7GWg3CwMKK3Si2dat4H1A==", - "dependencies": { - "@types/seedrandom": "2.4.27", - "seedrandom": "2.4.3" + "yallist": "^4.0.0" }, "engines": { - "yarn": ">= 1.3.2" - }, - "peerDependencies": { - "@tensorflow/tfjs-core": "2.8.6" + "node": ">=8" } }, - "node_modules/tensorset/node_modules/@tensorflow/tfjs-backend-webgl": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-2.8.6.tgz", - "integrity": "sha512-kPgm3Dim0Li5MleybYKSZVUCu91ipDjZtTA5RrJx/Dli115qwWdiRGOHYwsIEY61hZoE0m3amjWLUBxtwMW1Nw==", - "dependencies": { - "@tensorflow/tfjs-backend-cpu": "2.8.6", - "@types/offscreencanvas": "~2019.3.0", - "@types/seedrandom": "2.4.27", - "@types/webgl-ext": "0.0.30", - "@types/webgl2": "0.0.5", - "seedrandom": "2.4.3" - }, - "engines": { - "yarn": ">= 1.3.2" - }, - "peerDependencies": { - "@tensorflow/tfjs-core": "2.8.6" - } - }, - "node_modules/tensorset/node_modules/@tensorflow/tfjs-converter": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-2.8.6.tgz", - "integrity": "sha512-Uv4YC66qjVC9UwBxz0IeLZ8KS2CReh63WlGRtHcSwDEYiwsa7cvp9H6lFSSPT7kiJmrK6JtHeJGIVcTuNnSt9w==", - "peerDependencies": { - "@tensorflow/tfjs-core": "2.8.6" - } - }, - "node_modules/tensorset/node_modules/@tensorflow/tfjs-core": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-2.8.6.tgz", - "integrity": "sha512-jS28M1POUOjnWgx3jp1v5D45DUQE8USsAHHkL/01z75KnYCAAmgqJSH4YKLiYACg3eBLWXH/KTcSc6dHAX7Kfg==", - "dependencies": { - "@types/offscreencanvas": "~2019.3.0", - "@types/seedrandom": "2.4.27", - "@types/webgl-ext": "0.0.30", - "node-fetch": "~2.6.1", - "seedrandom": "2.4.3" - }, - "engines": { - "yarn": ">= 1.3.2" - } - }, - "node_modules/tensorset/node_modules/@tensorflow/tfjs-data": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-2.8.6.tgz", - "integrity": "sha512-zoDUfd5TfkYdviqu2bObwyJGXJiOvBckOTP9j36PUs6s+4DbTIDttyxdfeEaiiLX9ZUFU58CoW+3LI/dlFVyoQ==", - "dependencies": { - "@types/node-fetch": "^2.1.2", - "node-fetch": "~2.6.1" - }, - "peerDependencies": { - "@tensorflow/tfjs-core": "2.8.6", - "seedrandom": "~2.4.3" - } - }, - "node_modules/tensorset/node_modules/@tensorflow/tfjs-layers": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-2.8.6.tgz", - "integrity": "sha512-fdZ0i/R2dIKmy8OB5tBAsm5IbAHfJpI6AlbjxpgoU3aWj1HCdDo+pMji928MkDJhP01ISgFTgw/7PseGNaUflw==", - "peerDependencies": { - "@tensorflow/tfjs-core": "2.8.6" - } - }, - "node_modules/tensorset/node_modules/@types/webgl2": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.5.tgz", - "integrity": "sha512-oGaKsBbxQOY5+aJFV3KECDhGaXt+yZJt2y/OZsnQGLRkH6Fvr7rv4pCt3SRH1somIHfej/c4u7NSpCyd9x+1Ow==" - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, "node_modules/tiny-each-async": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/tiny-each-async/-/tiny-each-async-2.0.3.tgz", - "integrity": "sha1-jru/1tYpXxNwAD+7NxYq/loKUdE=", + "integrity": "sha512-5ROII7nElnAirvFn8g7H7MtpfV1daMcyfTGQwsn/x2VtyV+VPiO5CjReCJtWLvoKTDEDmZocf3cNPraiMnBXLA==", "dev": true, "optional": true }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "optional": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, "node_modules/tmp-promise": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", @@ -5246,17 +5663,20 @@ "tmp": "^0.2.0" } }, - "node_modules/tmp-promise/node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "node_modules/tmp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "optional": true, "dependencies": { - "rimraf": "^3.0.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=8.17.0" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/to-regex-range": { @@ -5271,10 +5691,38 @@ "node": ">=8.0" } }, + "node_modules/tough-cookie": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } }, "node_modules/trim-repeated": { "version": "1.0.0", @@ -5288,12 +5736,32 @@ "node": ">=0.10.0" } }, + "node_modules/trim-repeated/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", "dev": true }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", @@ -5307,21 +5775,27 @@ } }, "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, "dependencies": { - "unique-slug": "^2.0.0" + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/universalify": { @@ -5333,6 +5807,15 @@ "node": ">= 10.0.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/username": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/username/-/username-5.1.0.tgz", @@ -5349,8 +5832,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/validate-npm-package-license": { "version": "3.0.4", @@ -5362,27 +5844,63 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, "dependencies": { "defaults": "^1.0.3" } }, "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "engines": { + "node": ">=12" + } }, "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/which": { @@ -5403,7 +5921,7 @@ "node_modules/which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", "dev": true, "optional": true }, @@ -5411,7 +5929,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -5420,8 +5937,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "optional": true, "engines": { "node": ">=0.10.0" } @@ -5445,8 +5960,35 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "engines": { + "node": ">=12" + } }, "node_modules/xmlbuilder": { "version": "15.1.1", @@ -5457,6 +5999,11 @@ "node": ">=8.0" } }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -5471,28 +6018,30 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yarn-or-npm": { @@ -5582,7 +6131,7 @@ "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", @@ -5860,9 +6409,9 @@ } }, "@electron/osx-sign": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.1.tgz", - "integrity": "sha512-WkUcva+qkt809bI6uxxEG/uOWfl8HAw0m8aPijpKmGMIpZ1CWWB808YG6aY3wckUO86xZdmiOsUJTM4keLhY8A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.4.tgz", + "integrity": "sha512-xfhdEcIOfAZg7scZ9RQPya1G1lWo8/zMCwUXAulq0SfY7ONIW+b9qGyKdMyuMctNYwllrIS+vmxfijSfjeh97g==", "dev": true, "requires": { "compare-version": "^0.1.2", @@ -5871,17 +6420,6 @@ "isbinaryfile": "^4.0.8", "minimist": "^1.2.6", "plist": "^3.0.5" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - } } }, "@electron/rebuild": { @@ -5904,40 +6442,6 @@ "semver": "^7.3.5", "tar": "^6.0.5", "yargs": "^17.0.1" - }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } } }, "@electron/universal": { @@ -5993,6 +6497,49 @@ "cross-spawn": "^7.0.1" } }, + "@mapbox/node-pre-gyp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", + "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -6020,9 +6567,9 @@ } }, "@npmcli/fs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.0.tgz", - "integrity": "sha512-DmfBvNXGaetMxj9LTp8NAN9vEidXURrf5ZTslQzEAi/6GbW+4yjaLFQc6Tue5cpZ9Frlk4OBo/Snf1Bh/S7qTQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dev": true, "requires": { "@gar/promisify": "^1.1.3", @@ -6030,20 +6577,23 @@ } }, "@npmcli/move-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.0.tgz", - "integrity": "sha512-UR6D5f4KEGWJV6BGPH3Qb2EtgH+t+1XQ1Tt85c7qicN6cezzuHPdZwwAxqZr4JLtnQu0LZsTza/5gmNmSl8XLg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", "dev": true, "requires": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" }, "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -6112,6 +6662,37 @@ "core-js": "3", "regenerator-runtime": "^0.13.5", "yargs": "^16.0.3" + }, + "dependencies": { + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + } } }, "@tensorflow/tfjs-backend-cpu": { @@ -6121,27 +6702,6 @@ "requires": { "@types/seedrandom": "^2.4.28", "seedrandom": "^3.0.5" - }, - "dependencies": { - "@types/seedrandom": { - "version": "2.4.30", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz", - "integrity": "sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==" - }, - "seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" - } - } - }, - "@tensorflow/tfjs-backend-wasm": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-wasm/-/tfjs-backend-wasm-4.1.0.tgz", - "integrity": "sha512-1bB+hsgRKywNa01shHRZm61UQbCSbRVS9EpJUv0HWcPnMQxKGGZ0L+Sc4lNbLutMHJtWtsEFgB3PifE7iubuWQ==", - "requires": { - "@tensorflow/tfjs-backend-cpu": "4.1.0", - "@types/emscripten": "~0.0.34" } }, "@tensorflow/tfjs-backend-webgl": { @@ -6154,18 +6714,6 @@ "@types/seedrandom": "^2.4.28", "@types/webgl-ext": "0.0.30", "seedrandom": "^3.0.5" - }, - "dependencies": { - "@types/seedrandom": { - "version": "2.4.30", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz", - "integrity": "sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==" - }, - "seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" - } } }, "@tensorflow/tfjs-converter": { @@ -6192,16 +6740,6 @@ "version": "2019.7.0", "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz", "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==" - }, - "@types/seedrandom": { - "version": "2.4.30", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz", - "integrity": "sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==" - }, - "seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" } } }, @@ -6220,29 +6758,97 @@ "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-4.1.0.tgz", "integrity": "sha512-lzHNTZu1GwKl7hW5tt2COSpflE0m7xrsOf8AzRzpTDVJYYRx/x5ScMt/y//5jbRuaDOnb3EjT1FxWxwkD44/sg==" }, + "@tensorflow/tfjs-node": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-node/-/tfjs-node-4.1.0.tgz", + "integrity": "sha512-2H7UJqVafuM9fbsMdzUkcfWLpH/owgvVHWES+gQsiueIqyOjpq6ZGSQLDxyuKtHP2D/8/kWeVIbnzAjnIRniuA==", + "requires": { + "@mapbox/node-pre-gyp": "1.0.9", + "@tensorflow/tfjs": "4.1.0", + "adm-zip": "^0.5.2", + "google-protobuf": "^3.9.2", + "https-proxy-agent": "^2.2.1", + "progress": "^2.0.0", + "rimraf": "^2.6.2", + "tar": "^4.4.6" + }, + "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "requires": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" }, "@types/cacheable-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", - "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", "dev": true, "requires": { "@types/http-cache-semantics": "*", - "@types/keyv": "*", + "@types/keyv": "^3.1.4", "@types/node": "*", - "@types/responselike": "*" + "@types/responselike": "^1.0.0" } }, - "@types/emscripten": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-0.0.34.tgz", - "integrity": "sha512-QSb9ojDincskc+uKMI0KXp8e1NALFINCrMlp8VGKGcTSxeEyRTTKyjWw75NYrCZHUsVEEEpr1tYHpbtaC++/sQ==" - }, "@types/fs-extra": { "version": "9.0.13", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", @@ -6271,9 +6877,9 @@ "dev": true }, "@types/keyv": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", - "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", "dev": true, "requires": { "@types/node": "*" @@ -6285,21 +6891,21 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "dev": true, "optional": true }, "@types/node": { - "version": "17.0.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", - "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==" + "version": "18.11.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz", + "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==" }, "@types/node-fetch": { - "version": "2.5.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", - "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", + "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", "requires": { "@types/node": "*", "form-data": "^3.0.0" @@ -6320,9 +6926,9 @@ } }, "@types/seedrandom": { - "version": "2.4.27", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.27.tgz", - "integrity": "sha1-nbVjk33YaRX2kJK8QyWdL0hXjkE=" + "version": "2.4.30", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz", + "integrity": "sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==" }, "@types/webgl-ext": { "version": "0.0.30", @@ -6344,19 +6950,46 @@ "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.21.tgz", "integrity": "sha512-pUrWq3V5PiSGFLeLxoGqReTZmiiXwY3jRkIG5sLLKjyqNxrwm/04b4nw7LSmGWJcKk59XOM/YRTUwOzo4MMlow==" }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" + }, + "acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "requires": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + }, + "adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==" }, "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "requires": { - "debug": "4" + "es6-promisify": "^5.0.0" } }, "agentkeepalive": { @@ -6405,30 +7038,15 @@ "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "are-we-there-yet": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", - "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "requires": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } } }, "argparse": { @@ -6440,9 +7058,9 @@ } }, "asar": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/asar/-/asar-3.1.0.tgz", - "integrity": "sha512-vyxPxP5arcAqN4F/ebHd/HhwnAiZtwhglvdmc7BR2f0ywbVNTOpSeyhLDbGXtE/y58hv1oC75TaNIXutnsOZsQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", + "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==", "dev": true, "optional": true, "requires": { @@ -6471,7 +7089,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "at-least-node": { "version": "1.0.0", @@ -6482,13 +7100,13 @@ "author-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz", - "integrity": "sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA=", + "integrity": "sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==", "dev": true }, "axios": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.0.tgz", - "integrity": "sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz", + "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==", "requires": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -6510,8 +7128,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { "version": "1.5.1", @@ -6536,19 +7153,14 @@ "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + } + }, + "blockly": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/blockly/-/blockly-9.2.0.tgz", + "integrity": "sha512-rygZJupS5u4DMGGQ70gExH71c34vUEUjTVVBzhgVH7PCAK2RaitCNwr2yF6hGj/QTVodkjjEOdTzbHqLbuPipQ==", + "requires": { + "jsdom": "20.0.3" } }, "bluebird": { @@ -6558,9 +7170,9 @@ "dev": true }, "boolean": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.4.tgz", - "integrity": "sha512-3hx0kwU3uzG6ReQ3pnaFQPSktpBw6RHN3/ivDKEuU8g1XSfafowyvDnadjv1xp8IZqhtSukxlwv9bF6FhX8m0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", "dev": true, "optional": true }, @@ -6568,7 +7180,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6596,7 +7207,7 @@ "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true }, "buffer-equal": { @@ -6612,9 +7223,9 @@ "dev": true }, "cacache": { - "version": "16.1.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.1.tgz", - "integrity": "sha512-VDKN+LHyCQXaaYZ7rA/qtkURU+/yYhviUdvqEv2LT6QPZU8jpyzEkEVAcKlKLt5dJ5BRp11ym8lo3NKLluEPLg==", + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, "requires": { "@npmcli/fs": "^2.1.0", @@ -6634,7 +7245,7 @@ "rimraf": "^3.0.2", "ssri": "^9.0.0", "tar": "^6.1.11", - "unique-filename": "^1.1.1" + "unique-filename": "^2.0.0" }, "dependencies": { "brace-expansion": { @@ -6659,26 +7270,58 @@ "once": "^1.3.0" } }, - "lru-cache": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.12.0.tgz", - "integrity": "sha512-OIP3DwzRZDfLg9B9VP/huWBlpvbkmbfiBy8xmsXp4RPmE4A3MhwNozc5ZJ3fWnSg8fDcdlE/neRTPG2ycEKliw==", - "dev": true - }, "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", + "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", "dev": true, "requires": { "brace-expansion": "^2.0.1" } }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } } } }, @@ -6701,19 +7344,15 @@ "lowercase-keys": "^2.0.0", "normalize-url": "^6.0.1", "responselike": "^2.0.0" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - } } }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "optional": true + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6726,13 +7365,12 @@ "chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, "chromium-pickle-js": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", - "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", "dev": true }, "clean-stack": { @@ -6751,9 +7389,9 @@ } }, "cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", "dev": true }, "cli-truncate": { @@ -6767,19 +7405,20 @@ } }, "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "requires": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true }, "clone-response": { @@ -6807,8 +7446,7 @@ "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, "colorette": { "version": "2.0.19", @@ -6839,19 +7477,17 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" }, "core-js": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.0.tgz", - "integrity": "sha512-YUdI3fFu4TF/2WykQ2xzSiTQdldLB4KVuL9WeAy5XONZYt5Cun/fpQvctoKbCgvPhmzADeesTk/j2Rdx77AcKQ==" + "version": "3.26.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz", + "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==" }, "cross-spawn": { "version": "7.0.3", @@ -6886,11 +7522,40 @@ } } }, + "cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + } + } + }, + "data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "requires": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + } + }, "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { "ms": "2.1.2" } @@ -6898,10 +7563,15 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, "optional": true }, + "decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, "decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -6919,10 +7589,15 @@ } } }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "requires": { "clone": "^1.0.2" @@ -6935,25 +7610,25 @@ "dev": true }, "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", "dev": true, "optional": true, "requires": { - "object-keys": "^1.0.12" + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" } }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, "depd": { "version": "1.1.2", @@ -6964,8 +7639,7 @@ "detect-libc": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", - "dev": true + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" }, "detect-node": { "version": "2.1.0", @@ -6984,6 +7658,14 @@ "minimatch": "^3.0.4" } }, + "domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "requires": { + "webidl-conversions": "^7.0.0" + } + }, "electron": { "version": "22.0.0", "resolved": "https://registry.npmjs.org/electron/-/electron-22.0.0.tgz", @@ -6996,9 +7678,9 @@ }, "dependencies": { "@types/node": { - "version": "16.11.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.27.tgz", - "integrity": "sha512-C1pD3kgLoZ56Uuy5lhfOxie4aZlA3UMGLX9rXteq4WitEZH6Rl80mwactt9QG0w0gLFlN/kLBTFnGXtDVWvWQw==", + "version": "16.18.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", + "integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==", "dev": true } } @@ -7074,13 +7756,6 @@ "cross-spawn": "^7.0.1" } }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "optional": true - }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -7224,70 +7899,6 @@ "resolve": "^1.1.6", "semver": "^7.1.3", "yargs-parser": "^21.1.1" - }, - "dependencies": { - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "electron-rebuild": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-3.2.9.tgz", - "integrity": "sha512-FkEZNFViUem3P0RLYbZkUjC8LUFIK+wKq09GHoOITSJjfDAVQv964hwaNseTTWt58sITQX3/5fHNYcTefqaCWw==", - "dev": true, - "requires": { - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "lzma-native": "^8.0.5", - "node-abi": "^3.0.0", - "node-api-version": "^0.1.4", - "node-gyp": "^9.0.0", - "ora": "^5.1.0", - "semver": "^7.3.5", - "tar": "^6.0.5", - "yargs": "^17.0.1" - }, - "dependencies": { - "yargs": { - "version": "17.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", - "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", - "dev": true - } } }, "emoji-regex": { @@ -7303,18 +7914,6 @@ "optional": true, "requires": { "iconv-lite": "^0.6.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } } }, "end-of-stream": { @@ -7326,6 +7925,11 @@ "once": "^1.4.0" } }, + "entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" + }, "env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -7354,16 +7958,57 @@ "dev": true, "optional": true }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "requires": { + "es6-promise": "^4.0.3" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "optional": true + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "execa": { "version": "1.0.0", @@ -7393,6 +8038,15 @@ "which": "^1.2.9" } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -7450,17 +8104,6 @@ "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - } } }, "fast-glob": { @@ -7476,10 +8119,15 @@ "micromatch": "^4.0.4" } }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -7488,7 +8136,7 @@ "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "requires": { "pend": "~1.2.0" @@ -7589,9 +8237,9 @@ } }, "fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "requires": { "graceful-fs": "^4.2.0", @@ -7603,7 +8251,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, "requires": { "minipass": "^3.0.0" } @@ -7611,8 +8258,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "function-bind": { "version": "1.1.1", @@ -7676,19 +8322,19 @@ "optional": true }, "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", "requires": { "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" + "wide-align": "^1.1.2" } }, "get-caller-file": { @@ -7716,6 +8362,18 @@ "global-modules": "1.0.0" } }, + "get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "dev": true, + "optional": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, "get-package-info": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-1.0.0.tgz", @@ -7746,24 +8404,23 @@ } }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { "pump": "^3.0.0" } }, "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } @@ -7828,19 +8485,24 @@ } }, "globalthis": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", - "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dev": true, "optional": true, "requires": { "define-properties": "^1.1.3" } }, + "google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" + }, "got": { - "version": "11.8.5", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", - "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "dev": true, "requires": { "@sindresorhus/is": "^4.0.0", @@ -7857,9 +8519,9 @@ } }, "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, "has": { @@ -7876,11 +8538,27 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "optional": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "optional": true + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, "homedir-polyfill": { "version": "1.0.3", @@ -7897,6 +8575,14 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, + "html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "requires": { + "whatwg-encoding": "^2.0.0" + } + }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -7907,11 +8593,20 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, "requires": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + } } }, "http2-wrapper": { @@ -7925,13 +8620,22 @@ } }, "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "requires": { - "agent-base": "6", - "debug": "4" + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } } }, "humanize-ms": { @@ -7943,6 +8647,14 @@ "ms": "^2.0.0" } }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -7970,8 +8682,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -7980,8 +8691,7 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "1.3.8", @@ -7996,9 +8706,9 @@ "dev": true }, "ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true }, "is-arrayish": { @@ -8060,6 +8770,11 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -8096,9 +8811,71 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "requires": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + } + } + }, "json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -8108,7 +8885,7 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true, "optional": true }, @@ -8137,10 +8914,19 @@ "json-buffer": "3.0.1" } }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, "listr2": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.5.tgz", - "integrity": "sha512-DpBel6fczu7oQKTXMekeprc0o3XDgGMkD7JNYyX+X0xbwK+xgrx9dcyKoXKqpLSUvAWfmoePS7kavniOcq3r4w==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.6.tgz", + "integrity": "sha512-u60KxKBy1BR2uLJNTWNptzWQ1ob/gjMzIJPZffAENzpZqbMZ/5PrXXOomDcevIS/+IB7s1mmCEtSlT2qHWMqag==", "dev": true, "requires": { "cli-truncate": "^2.1.0", @@ -8148,7 +8934,7 @@ "log-update": "^4.0.0", "p-map": "^4.0.0", "rfdc": "^1.3.0", - "rxjs": "^7.5.6", + "rxjs": "^7.5.7", "through": "^2.3.8", "wrap-ansi": "^7.0.0" } @@ -8244,12 +9030,10 @@ "dev": true }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "dev": true }, "lzma-native": { "version": "8.0.6", @@ -8260,25 +9044,27 @@ "node-addon-api": "^3.1.0", "node-gyp-build": "^4.2.1", "readable-stream": "^3.6.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" }, "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, "make-fetch-happen": { - "version": "10.1.8", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.1.8.tgz", - "integrity": "sha512-0ASJbG12Au6+N5I84W+8FhGS6iM8MyzvZady+zaQAu+6IOaESFzCLLD0AR1sAFF3Jufi8bxm586ABN6hWd3k7g==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dev": true, "requires": { "agentkeepalive": "^4.2.1", @@ -8299,11 +9085,24 @@ "ssri": "^9.0.0" }, "dependencies": { - "lru-cache": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.12.0.tgz", - "integrity": "sha512-OIP3DwzRZDfLg9B9VP/huWBlpvbkmbfiBy8xmsXp4RPmE4A3MhwNozc5ZJ3fWnSg8fDcdlE/neRTPG2ycEKliw==", - "dev": true + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } } } }, @@ -8324,15 +9123,6 @@ "optional": true, "requires": { "escape-string-regexp": "^4.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "optional": true - } } }, "mem": { @@ -8363,16 +9153,16 @@ } }, "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" } }, "mimic-fn": { @@ -8388,10 +9178,9 @@ "dev": true }, "minimatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.1.tgz", - "integrity": "sha512-reLxBcKUPNBnc/sVtAbxgRVFSegoGeLaSjmphNhcwcolhYLRgtJscn5mRl6YRZNQv40Y7P6JM2YhSIsbL9OB5A==", - "dev": true, + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } @@ -8399,14 +9188,12 @@ "minimist": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" }, "minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "dev": true, + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "requires": { "yallist": "^4.0.0" } @@ -8421,9 +9208,9 @@ } }, "minipass-fetch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.0.tgz", - "integrity": "sha512-H9U4UVBGXEyyWJnqYDCLp1PwD8XIkJ4akNHp1aGVI+2Ym7wQMlxDKi4IB4JbmyU+pl9pEs/cVrK6cOuvmbK4Sg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, "requires": { "encoding": "^0.1.13", @@ -8463,17 +9250,20 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, "requires": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "negotiator": { "version": "0.6.3", @@ -8516,30 +9306,109 @@ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "requires": { "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } } }, "node-gyp": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.0.0.tgz", - "integrity": "sha512-Ma6p4s+XCTPxCuAMrOA/IJRmVy16R8Sdhtwl4PrCr7IBlj4cPawF0vg/l7nOT1jPbuNS7lIRJpBSvVsXwEZuzw==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", + "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", "dev": true, "requires": { "env-paths": "^2.2.0", "glob": "^7.1.4", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.0.3", - "nopt": "^5.0.0", + "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.2", "which": "^2.0.2" + }, + "dependencies": { + "are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "requires": { + "abbrev": "^1.0.0" + } + }, + "npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "node-gyp-build": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", - "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", + "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", "dev": true }, "nodemailer": { @@ -8551,7 +9420,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, "requires": { "abbrev": "1" } @@ -8600,17 +9468,26 @@ } }, "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "requires": { - "are-we-there-yet": "^3.0.0", + "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", + "gauge": "^3.0.0", "set-blocking": "^2.0.0" } }, + "nwsapi": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -8621,8 +9498,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "requires": { "wrappy": "1" } @@ -8636,6 +9512,19 @@ "mimic-fn": "^2.1.0" } }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, "ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -8713,7 +9602,7 @@ "parse-author": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz", - "integrity": "sha1-00YL8d3Q367tQtp1QkLmX7aEqB8=", + "integrity": "sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw==", "dev": true, "requires": { "author-regex": "^1.0.0" @@ -8734,6 +9623,14 @@ "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", "dev": true }, + "parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "requires": { + "entities": "^4.4.0" + } + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8743,8 +9640,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-key": { "version": "3.1.1", @@ -8770,7 +9666,7 @@ "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, "picomatch": { @@ -8843,11 +9739,15 @@ "xmlbuilder": "^15.1.1" } }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, "promise-inflight": { "version": "1.0.1", @@ -8870,6 +9770,11 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -8880,6 +9785,16 @@ "once": "^1.3.1" } }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -8973,6 +9888,16 @@ } } }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -8983,14 +9908,14 @@ } }, "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, "require-main-filename": { "version": "2.0.0", @@ -8999,6 +9924,11 @@ "dev": true, "optional": true }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -9073,10 +10003,9 @@ "dev": true }, "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "requires": { "glob": "^7.1.3" } @@ -9115,9 +10044,9 @@ } }, "rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", "dev": true, "requires": { "tslib": "^2.1.0" @@ -9131,27 +10060,43 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "optional": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "requires": { + "xmlchars": "^2.2.0" + } }, "seedrandom": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.3.tgz", - "integrity": "sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw=" + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "requires": { "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + } } }, "semver-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "dev": true, "optional": true }, @@ -9177,8 +10122,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "shebang-command": { "version": "2.0.0", @@ -9198,8 +10142,7 @@ "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "slice-ansi": { "version": "3.0.0", @@ -9219,12 +10162,12 @@ "dev": true }, "socks": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", - "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dev": true, "requires": { - "ip": "^1.1.5", + "ip": "^2.0.0", "smart-buffer": "^4.2.0" } }, @@ -9237,13 +10180,24 @@ "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + } } }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "devOptional": true }, "source-map-support": { "version": "0.5.21", @@ -9290,7 +10244,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "ssri": { "version": "9.0.1", @@ -9346,6 +10300,14 @@ "dev": true, "requires": { "escape-string-regexp": "^1.0.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + } } }, "sudo-prompt": { @@ -9377,127 +10339,69 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", + "minipass": "^4.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "tensorset": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/tensorset/-/tensorset-1.2.9.tgz", - "integrity": "sha512-xlMAotSaXkGf3U8/4n/n+svHgvT1HvwrssMTaRgSo2PQcYFVseYWPg9qnppi+/fnf4EdQpQdtqIYXyu8jSK73A==", - "requires": { - "@tensorflow/tfjs": "^2.0.1" - }, - "dependencies": { - "@tensorflow/tfjs": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-2.8.6.tgz", - "integrity": "sha512-/Hk3YCAreNicuQJsAIG32UGHaQj8UwX8y8ZrKVb/CrXOhrRyZmxGSZt9KMVe8MDoydenuGhZCqJUIaWdIKIA5g==", + "minipass": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.0.tgz", + "integrity": "sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==", "requires": { - "@tensorflow/tfjs-backend-cpu": "2.8.6", - "@tensorflow/tfjs-backend-webgl": "2.8.6", - "@tensorflow/tfjs-converter": "2.8.6", - "@tensorflow/tfjs-core": "2.8.6", - "@tensorflow/tfjs-data": "2.8.6", - "@tensorflow/tfjs-layers": "2.8.6", - "argparse": "^1.0.10", - "chalk": "^4.1.0", - "core-js": "3", - "regenerator-runtime": "^0.13.5", - "yargs": "^16.0.3" + "yallist": "^4.0.0" } - }, - "@tensorflow/tfjs-backend-cpu": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-2.8.6.tgz", - "integrity": "sha512-x9WTTE9p3Pon2D0d6HH1UCIJsU1w3v9sF3vxJcp+YStrjDefWoW5pwxHCckEKTRra7GWg3CwMKK3Si2dat4H1A==", - "requires": { - "@types/seedrandom": "2.4.27", - "seedrandom": "2.4.3" - } - }, - "@tensorflow/tfjs-backend-webgl": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-2.8.6.tgz", - "integrity": "sha512-kPgm3Dim0Li5MleybYKSZVUCu91ipDjZtTA5RrJx/Dli115qwWdiRGOHYwsIEY61hZoE0m3amjWLUBxtwMW1Nw==", - "requires": { - "@tensorflow/tfjs-backend-cpu": "2.8.6", - "@types/offscreencanvas": "~2019.3.0", - "@types/seedrandom": "2.4.27", - "@types/webgl-ext": "0.0.30", - "@types/webgl2": "0.0.5", - "seedrandom": "2.4.3" - } - }, - "@tensorflow/tfjs-converter": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-2.8.6.tgz", - "integrity": "sha512-Uv4YC66qjVC9UwBxz0IeLZ8KS2CReh63WlGRtHcSwDEYiwsa7cvp9H6lFSSPT7kiJmrK6JtHeJGIVcTuNnSt9w==" - }, - "@tensorflow/tfjs-core": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-2.8.6.tgz", - "integrity": "sha512-jS28M1POUOjnWgx3jp1v5D45DUQE8USsAHHkL/01z75KnYCAAmgqJSH4YKLiYACg3eBLWXH/KTcSc6dHAX7Kfg==", - "requires": { - "@types/offscreencanvas": "~2019.3.0", - "@types/seedrandom": "2.4.27", - "@types/webgl-ext": "0.0.30", - "node-fetch": "~2.6.1", - "seedrandom": "2.4.3" - } - }, - "@tensorflow/tfjs-data": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-2.8.6.tgz", - "integrity": "sha512-zoDUfd5TfkYdviqu2bObwyJGXJiOvBckOTP9j36PUs6s+4DbTIDttyxdfeEaiiLX9ZUFU58CoW+3LI/dlFVyoQ==", - "requires": { - "@types/node-fetch": "^2.1.2", - "node-fetch": "~2.6.1" - } - }, - "@tensorflow/tfjs-layers": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-2.8.6.tgz", - "integrity": "sha512-fdZ0i/R2dIKmy8OB5tBAsm5IbAHfJpI6AlbjxpgoU3aWj1HCdDo+pMji928MkDJhP01ISgFTgw/7PseGNaUflw==" - }, - "@types/webgl2": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.5.tgz", - "integrity": "sha512-oGaKsBbxQOY5+aJFV3KECDhGaXt+yZJt2y/OZsnQGLRkH6Fvr7rv4pCt3SRH1somIHfej/c4u7NSpCyd9x+1Ow==" } } }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, "tiny-each-async": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/tiny-each-async/-/tiny-each-async-2.0.3.tgz", - "integrity": "sha1-jru/1tYpXxNwAD+7NxYq/loKUdE=", + "integrity": "sha512-5ROII7nElnAirvFn8g7H7MtpfV1daMcyfTGQwsn/x2VtyV+VPiO5CjReCJtWLvoKTDEDmZocf3cNPraiMnBXLA==", "dev": true, "optional": true }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "optional": true, + "requires": { + "rimraf": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "tmp-promise": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", @@ -9506,18 +10410,6 @@ "optional": true, "requires": { "tmp": "^0.2.0" - }, - "dependencies": { - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "optional": true, - "requires": { - "rimraf": "^3.0.0" - } - } } }, "to-regex-range": { @@ -9529,10 +10421,31 @@ "is-number": "^7.0.0" } }, + "tough-cookie": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "dependencies": { + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" + } + } + }, "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "requires": { + "punycode": "^2.1.1" + } }, "trim-repeated": { "version": "1.0.0", @@ -9541,14 +10454,30 @@ "dev": true, "requires": { "escape-string-regexp": "^1.0.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + } } }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", "dev": true }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "requires": { + "prelude-ls": "~1.1.2" + } + }, "type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", @@ -9556,18 +10485,18 @@ "dev": true }, "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, "requires": { - "unique-slug": "^2.0.0" + "unique-slug": "^3.0.0" } }, "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, "requires": { "imurmurhash": "^0.1.4" @@ -9579,6 +10508,15 @@ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "username": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/username/-/username-5.1.0.tgz", @@ -9592,8 +10530,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "validate-npm-package-license": { "version": "3.0.4", @@ -9605,27 +10542,48 @@ "spdx-expression-parse": "^3.0.0" } }, + "w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "requires": { + "xml-name-validator": "^4.0.0" + } + }, "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, "requires": { "defaults": "^1.0.3" } }, "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "requires": { + "iconv-lite": "0.6.3" + } + }, + "whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==" }, "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" } }, "which": { @@ -9640,7 +10598,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", "dev": true, "optional": true }, @@ -9648,7 +10606,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, "requires": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -9656,9 +10613,7 @@ "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "optional": true + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, "wrap-ansi": { "version": "7.0.0", @@ -9673,8 +10628,17 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==" + }, + "xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==" }, "xmlbuilder": { "version": "15.1.1", @@ -9682,6 +10646,11 @@ "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", "dev": true }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -9693,23 +10662,25 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "dev": true, "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" } }, "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true }, "yarn-or-npm": { "version": "3.0.1", @@ -9775,7 +10746,7 @@ "yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, "requires": { "buffer-crc32": "~0.2.3", diff --git a/package.json b/package.json index 42c61a4..42059fc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ocoge", - "version": "0.1.8", + "version": "0.1.9", "description": "ブロックベースビジュアルプログラム開発・実行環境", "main": "main.js", "scripts": { @@ -24,8 +24,8 @@ "devDependencies": { "@electron-forge/cli": "^6.0.4", "@electron-forge/maker-deb": "^6.0.4", - "electron": "^22.0.0", - "electron-rebuild": "^3.2.9" + "@electron/rebuild": "^3.2.10", + "electron": "^22.0.0" }, "dependencies": { "@ocoge.club/pigpio": "file:local_modules/pigpio", @@ -33,12 +33,11 @@ "@tensorflow-models/knn-classifier": "^1.2.4", "@tensorflow-models/mobilenet": "^2.1.0", "@tensorflow-models/speech-commands": "^0.5.4", - "@tensorflow/tfjs": "^4.1.0", - "@tensorflow/tfjs-backend-wasm": "^4.1.0", - "axios": "^1.2.0", + "@tensorflow/tfjs-node": "^4.1.0", + "axios": "^1.2.1", + "blockly": "^9.2.0", "node-abi": "^3.30.0", - "nodemailer": "^6.8.0", - "tensorset": "^1.2.9" + "nodemailer": "^6.8.0" }, "config": { "forge": { diff --git a/ugj_blocks.js b/ugj_blocks.js index a71f208..3c69ac2 100644 --- a/ugj_blocks.js +++ b/ugj_blocks.js @@ -950,16 +950,12 @@ Blockly.Blocks['ugj_face_init'] = { }; Blockly.JavaScript['ugj_face_init'] = function (block) { Blockly.JavaScript.provideFunction_( - 'require_tfjs', [`const _tf = require('@tensorflow/tfjs');`] - ); - Blockly.JavaScript.provideFunction_( - 'require_tfjs_wasm', [`require('@tensorflow/tfjs-backend-wasm');`] + 'require_tfjs', [`const _tf = require('@tensorflow/tfjs-node');`] ); Blockly.JavaScript.provideFunction_( 'require_blazeface', [`const _blazeface = require('@tensorflow-models/blazeface');`] ); var code = [ - `await _tf.setBackend('wasm');`, "const _videoEl = document.getElementById('subdisplay');", `const _displaySize = { width: _videoEl.width, height: _videoEl.height };`, "const _stream = await navigator.mediaDevices.getUserMedia({ audio: false, video: _displaySize });", @@ -1074,6 +1070,84 @@ Blockly.JavaScript['ugj_face_draw'] = function (block) { return code; }; +/******************************* */ +/** Speech Commands Recognizer * */ +/******************************* */ +Blockly.Blocks['oc_speechcommands_init'] = { + init: function () { + this.appendValueInput("custom_model") + .setCheck("String") + .appendField("音声コマンド認識を開始:カスタムモデル") + // .appendField(""); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip("Tensorflow 音声コマンド認識モデルを初期化します。Google Teachable Machine で作成したカスタムモデルのフォルダパスを指定します。(空欄可)"); + this.setHelpUrl(""); + this.setStyle('multimedia_blocks'); + } +}; +Blockly.JavaScript['oc_speechcommands_init'] = function (block) { + var value_custom_model = Blockly.JavaScript.valueToCode(block, 'custom_model', Blockly.JavaScript.ORDER_NONE); + Blockly.JavaScript.provideFunction_( + 'require_tfjs', [`const _tf = require('@tensorflow/tfjs-node');`] + ); + Blockly.JavaScript.provideFunction_( + 'require_speechcommands', [`const _speechcommands = require('@tensorflow-models/speech-commands');`] + ); + // Check empty + let cp = undefined, md = undefined; + if (value_custom_model != "''") { + let cm = value_custom_model.replace(/(^'|'$)/g, ''); + cp = `'file://${elutil.path.join(cm, 'model.json')}'`; + md = `'file://${elutil.path.join(cm, 'metadata.json')}'`; + } + var code = `const _checkpointURL = ${cp}; +const _metadataURL = ${md}; +const _recognizer = _speechcommands.create( + "BROWSER_FFT", + undefined, + _checkpointURL, + _metadataURL); +await _recognizer.ensureModelLoaded(); +`; + return code; +}; +Blockly.Blocks['oc_speechcommand_listen'] = { + init: function () { + this.appendDummyInput() + .appendField("音声コマンドの") + .appendField(new Blockly.FieldVariable("ラベル"), "classlabels") + .appendField(new Blockly.FieldVariable("スコア"), "scores") + .appendField("を認識したら"); + this.appendStatementInput("do") + .setCheck(null); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip("音声コマンドを認識するとステートメントをします。「ラベル」「スコア」はリストです。"); + this.setHelpUrl(""); + this.setStyle('multimedia_blocks'); + } +}; +Blockly.JavaScript['oc_speechcommand_listen'] = function (block) { + var variable_classlabels = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('classlabels'), Blockly.Names.NameType.VARIABLE); + var variable_scores = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('scores'), Blockly.Names.NameType.VARIABLE); + var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); + var code = `${variable_classlabels} = _recognizer.wordLabels(); +_recognizer.listen(_result => { + ${variable_scores} = _result.scores; + ${statements_do} +}, { + // includeSpectrogram: true, + // invokeCallbackOnNoiseAndUnknown: true, + // overlapFactor: 0.50, + probabilityThreshold: 0.75 +}); +`; + return code; +}; + /**************************** */ /** Say while some seconds ** */ /**************************** */ @@ -2928,4 +3002,4 @@ Blockly.Python['ugj_controls_foreach'] = function (block) { // var statements_do = Blockly.JavaScript.statementToCode(block, 'do'); // var code = `let _interval = setTimeout(async () => {\n${statements_do}}, ${value_sec}*1000);\n`; // return code; -// }; \ No newline at end of file +// };