Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@blockly/block-dynamic-connection

Package Overview
Dependencies
Maintainers
2
Versions
87
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@blockly/block-dynamic-connection - npm Package Compare versions

Comparing version 0.4.3 to 0.5.0

2

./dist/index.js
/*! For license information please see index.js.LICENSE.txt */
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var n="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var i in n)("object"==typeof exports?exports:t)[i]=n[i]}}(this,(t=>(()=>{"use strict";var e={573:e=>{e.exports=t}},n={};function i(t){var s=n[t];if(void 0!==s)return s.exports;var o=n[t]={exports:{}};return e[t](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};return(()=>{i.r(s),i.d(s,{overrideOldBlockDefinitions:()=>p});var t=i(573);t.InsertionMarkerManager.prototype.update=function(e,n){var i;const s=this.getCandidate(e);this.wouldDeleteBlock=this.shouldDelete(!!s,n),(this.wouldDeleteBlock||this.shouldUpdatePreviews(s,e))&&((null===(i=null==s?void 0:s.closest)||void 0===i?void 0:i.sourceBlock_.onPendingConnection)&&(s.closest.sourceBlock_.onPendingConnection(s.closest),this.pendingBlocks||(this.pendingBlocks=new Set),this.pendingBlocks.add(s.closest.sourceBlock_)),t.Events.disable(),this.maybeHidePreview(s),this.maybeShowPreview(s),t.Events.enable())};const e=t.InsertionMarkerManager.prototype.dispose;t.InsertionMarkerManager.prototype.dispose=function(){this.pendingBlocks&&this.pendingBlocks.forEach((t=>{t.finalizeConnections&&t.finalizeConnections()})),e.call(this)};const n={inputCounter:1,minInputs:1,init(){this.setHelpUrl(t.Msg.CONTROLS_IF_HELPURL),this.setStyle("logic_blocks"),this.appendValueInput("IF0").setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_IF,"if"),this.appendStatementInput("DO0").appendField(t.Msg.CONTROLS_IF_MSG_THEN),this.setNextStatement(!0),this.setPreviousStatement(!0),this.setTooltip(t.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom(){const e=t.utils.xml.createElement("mutation"),n=this.inputList.filter((t=>t.name.includes("IF"))).map((t=>t.name.replace("IF",""))).join(",");e.setAttribute("inputs",n);const i=!!this.getInput("ELSE");return e.setAttribute("else",String(i)),e.setAttribute("next",String(this.inputCounter)),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){var n;const i=e.getAttribute("inputs");if(i){const e=i.split(",");this.getInput("IF0")&&this.removeInput("IF0"),this.getInput("DO0")&&this.removeInput("DO0");const n=e[0];this.appendValueInput("IF"+n).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_IF,"if"),this.appendStatementInput("DO"+n).appendField(t.Msg.CONTROLS_IF_MSG_THEN);for(let n=1;n<e.length;n++)this.appendValueInput("IF"+e[n]).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF,"elseif"),this.appendStatementInput("DO"+e[n]).appendField(t.Msg.CONTROLS_IF_MSG_THEN)}"true"==e.getAttribute("else")&&this.appendStatementInput("ELSE").appendField(t.Msg.CONTROLS_IF_MSG_ELSE,"else");const s=parseInt(null!==(n=e.getAttribute("next"))&&void 0!==n?n:"0",10)||0;this.inputCounter=s},deserializeCounts(e){var n,i;const s=parseInt(null!==(n=e.getAttribute("elseif"))&&void 0!==n?n:"0",10)||0,o=parseInt(null!==(i=e.getAttribute("else"))&&void 0!==i?i:"0",10)||0;for(let e=1;e<=s;e++)this.appendValueInput("IF"+e).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF),this.appendStatementInput("DO"+e).appendField(t.Msg.CONTROLS_IF_MSG_THEN);o&&this.appendStatementInput("ELSE").appendField(t.Msg.CONTROLS_IF_MSG_ELSE),this.inputCounter=s+1},findInputIndexForConnection(t){for(let e=0;e<this.inputList.length;e++)if(this.inputList[e].connection==t)return e;return null},insertElseIf(e){const n=this.inputCounter;this.appendValueInput("IF"+n).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF,"elseif"),this.appendStatementInput("DO"+n).appendField(t.Msg.CONTROLS_IF_MSG_THEN),this.moveInputBefore("IF"+n,this.inputList[e].name),this.moveInputBefore("DO"+n,this.inputList[e+1].name),this.inputCounter++},onPendingConnection(e){e.type!==t.NEXT_STATEMENT||this.getInput("ELSE")||this.appendStatementInput("ELSE").appendField(t.Msg.CONTROLS_IF_MSG_ELSE,"else");const n=this.findInputIndexForConnection(e);if(null===n)return;const i=this.inputList[n];if(e.targetConnection&&i.name.includes("IF")){const t=this.inputList[n+2];if(t&&"ELSE"!=t.name){const e=t&&t.connection&&t.connection.targetConnection;e&&!e.getSourceBlock().isInsertionMarker()&&this.insertElseIf(n+2)}else this.insertElseIf(n+2)}},finalizeConnections(){var e,n,i,s,o;const u=[];for(let t=2;t<this.inputList.length-1;t+=2){const i=this.inputList[t],s=this.inputList[t+1];(null===(e=i.connection)||void 0===e?void 0:e.targetConnection)||(null===(n=s.connection)||void 0===n?void 0:n.targetConnection)||(u.push(i.name),u.push(s.name))}u.forEach((t=>this.removeInput(t)));const p=this.getInput("ELSE");if(p&&!(null===(i=p.connection)||void 0===i?void 0:i.targetConnection)&&this.removeInput(p.name),this.inputList.length>2){const e=this.inputList[0],n=this.inputList[1],i=this.inputList[2];!i.name.includes("IF")||(null===(s=e.connection)||void 0===s?void 0:s.targetConnection)||(null===(o=n.connection)||void 0===o?void 0:o.targetConnection)||(this.removeInput(e.name),this.removeInput(n.name),i.removeField("elseif"),i.appendField(t.Msg.CONTROLS_IF_MSG_IF,"if"))}}};t.Blocks.dynamic_if=n;const o={inputCounter:2,minInputs:2,init(){this.setHelpUrl(t.Msg.TEXT_JOIN_HELPURL),this.setStyle("text_blocks"),this.appendValueInput("ADD0").appendField(t.Msg.TEXT_JOIN_TITLE_CREATEWITH),this.appendValueInput("ADD1"),this.setOutput(!0,"String"),this.setTooltip(t.Msg.TEXT_JOIN_TOOLTIP)},mutationToDom(){const e=t.utils.xml.createElement("mutation"),n=this.inputList.map((t=>t.name)).join(",");return e.setAttribute("inputs",n),e.setAttribute("next",String(this.inputCounter)),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){var n;const i=e.getAttribute("inputs");if(i){const e=i.split(",");this.inputList=[],e.forEach((t=>this.appendValueInput(t))),this.inputList[0].appendField(t.Msg.TEXT_JOIN_TITLE_CREATEWITH)}const s=parseInt(null!==(n=e.getAttribute("next"))&&void 0!==n?n:"0",10)||0;this.inputCounter=s},deserializeCounts(t){var e;const n=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t<n;t++)this.appendValueInput("ADD"+t);this.inputCounter=n},getIndexForNewInput(t){var e;if(!t.targetConnection)return null;let n=-1;for(let e=0;e<this.inputList.length;e++)this.inputList[e].connection==t&&(n=e);if(n==this.inputList.length-1)return this.inputList.length+1;const i=this.inputList[n+1],s=null===(e=null==i?void 0:i.connection)||void 0===e?void 0:e.targetConnection;return s&&!s.getSourceBlock().isInsertionMarker()?n+1:null},onPendingConnection(t){const e=this.getIndexForNewInput(t);null!=e&&(this.appendValueInput("ADD"+this.inputCounter++),this.moveNumberedInputBefore(this.inputList.length-1,e))},finalizeConnections(){if(this.inputList.length>this.minInputs){let e=[];this.inputList.forEach((t=>{var n;(null===(n=t.connection)||void 0===n?void 0:n.targetConnection)||e.push(t.name)})),this.inputList.length-e.length<this.minInputs&&(e=e.slice(this.minInputs)),e.forEach((t=>this.removeInput(t))),0==this.inputList[0].fieldRow.length&&this.inputList[0].appendField(t.Msg.TEXT_JOIN_TITLE_CREATEWITH)}}};t.Blocks.dynamic_text_join=o;const u={inputCounter:2,minInputs:2,init(){this.setHelpUrl(t.Msg.LISTS_CREATE_WITH_HELPURL),this.setStyle("list_blocks"),this.appendValueInput("ADD0").appendField(t.Msg.LISTS_CREATE_WITH_INPUT_WITH),this.appendValueInput("ADD1"),this.setOutput(!0,"Array"),this.setTooltip(t.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom(){const e=t.utils.xml.createElement("mutation"),n=this.inputList.map((t=>t.name)).join(",");return e.setAttribute("inputs",n),e.setAttribute("next",String(this.inputCounter)),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){var n;const i=e.getAttribute("inputs");if(i){const e=i.split(",");this.inputList=[],e.forEach((t=>this.appendValueInput(t))),this.inputList[0].appendField(t.Msg.LISTS_CREATE_WITH_INPUT_WITH)}const s=parseInt(null!==(n=e.getAttribute("next"))&&void 0!==n?n:"0",10)||0;this.inputCounter=s},deserializeCounts(t){var e;const n=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t<n;t++)this.appendValueInput("ADD"+t);this.inputCounter=n},getIndexForNewInput(t){var e;if(!t.targetConnection)return null;let n=-1;for(let e=0;e<this.inputList.length;e++)this.inputList[e].connection==t&&(n=e);if(n==this.inputList.length-1)return this.inputList.length+1;const i=this.inputList[n+1],s=null===(e=null==i?void 0:i.connection)||void 0===e?void 0:e.targetConnection;return s&&!s.getSourceBlock().isInsertionMarker()?n+1:null},onPendingConnection(t){const e=this.getIndexForNewInput(t);null!=e&&(this.appendValueInput("ADD"+this.inputCounter++),this.moveNumberedInputBefore(this.inputList.length-1,e))},finalizeConnections(){if(this.inputList.length>this.minInputs){let e=[];this.inputList.forEach((t=>{var n;(null===(n=t.connection)||void 0===n?void 0:n.targetConnection)||e.push(t.name)})),this.inputList.length-e.length<this.minInputs&&(e=e.slice(this.minInputs)),e.forEach((t=>this.removeInput(t))),0==this.inputList[0].fieldRow.length&&this.inputList[0].appendField(t.Msg.LISTS_CREATE_WITH_INPUT_WITH)}}};t.Blocks.dynamic_list_create=u;const p=function(){t.Blocks.lists_create_with=t.Blocks.dynamic_list_create,t.Blocks.text_join=t.Blocks.dynamic_text_join,t.Blocks.controls_if=t.Blocks.dynamic_if}})(),s})()));
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var n="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var i in n)("object"==typeof exports?exports:t)[i]=n[i]}}(this,(t=>(()=>{"use strict";var e={573:e=>{e.exports=t}},n={};function i(t){var s=n[t];if(void 0!==s)return s.exports;var o=n[t]={exports:{}};return e[t](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};return(()=>{i.r(s),i.d(s,{overrideOldBlockDefinitions:()=>u});var t=i(573);t.InsertionMarkerManager.prototype.update=function(e,n){var i;const s=this.getCandidate(e);this.wouldDeleteBlock=this.shouldDelete(!!s,n),(this.wouldDeleteBlock||this.shouldUpdatePreviews(s,e))&&((null===(i=null==s?void 0:s.closest)||void 0===i?void 0:i.sourceBlock_.onPendingConnection)&&(s.closest.sourceBlock_.onPendingConnection(s.closest),this.pendingBlocks||(this.pendingBlocks=new Set),this.pendingBlocks.add(s.closest.sourceBlock_)),t.Events.disable(),this.maybeHidePreview(s),this.maybeShowPreview(s),t.Events.enable())};const e=t.InsertionMarkerManager.prototype.dispose;t.InsertionMarkerManager.prototype.dispose=function(){this.pendingBlocks&&this.pendingBlocks.forEach((t=>{t.finalizeConnections&&t.finalizeConnections()})),e.call(this)};const n={minInputs:1,elseifCount:0,elseCount:0,init(){this.setHelpUrl(t.Msg.CONTROLS_IF_HELPURL),this.setStyle("logic_blocks"),this.addFirstCase(),this.setNextStatement(!0),this.setPreviousStatement(!0),this.setTooltip(t.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom(){if(t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable(),!this.elseifCount&&!this.elseCount)return null;const e=t.utils.xml.createElement("mutation");return this.elseifCount&&e.setAttribute("elseif",`${this.elseifCount}`),this.elseCount&&e.setAttribute("else","1"),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){const n=e.getAttribute("inputs");if(n){const e=n.split(",");this.getInput("IF0")&&this.removeInput("IF0"),this.getInput("DO0")&&this.removeInput("DO0");const i=e[0];this.appendValueInput("IF"+i).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_IF,"if"),this.appendStatementInput("DO"+i).appendField(t.Msg.CONTROLS_IF_MSG_THEN);for(let n=1;n<e.length;n++)this.appendValueInput("IF"+e[n]).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF,"elseif"),this.appendStatementInput("DO"+e[n]).appendField(t.Msg.CONTROLS_IF_MSG_THEN)}"true"==e.getAttribute("else")&&this.addElseInput()},deserializeCounts(t){var e,n;this.elseifCount=parseInt(null!==(e=t.getAttribute("elseif"))&&void 0!==e?e:"0",10)||0,this.elseCount=parseInt(null!==(n=t.getAttribute("else"))&&void 0!==n?n:"0",10)||0;for(let t=1;t<=this.elseifCount;t++)this.insertElseIf(this.inputList.length,t);this.elseCount&&this.addElseInput()},saveExtraState:function(){if(t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable(),!this.elseifCount&&!this.elseCount)return null;const e=Object.create(null);return this.elseifCount&&(e.elseIfCount=this.elseifCount),this.elseCount&&(e.hasElse=!0),e},loadExtraState:function(e){if("string"!=typeof e){this.elseifCount=e.elseIfCount||0,this.elseCount=e.hasElse?1:0;for(let t=1;t<=this.elseifCount;t++)this.insertElseIf(this.inputList.length,t);this.elseCount&&this.addElseInput()}else this.domToMutation(t.utils.xml.textToDom(e))},findInputIndexForConnection(t){for(let e=0;e<this.inputList.length;e++)if(this.inputList[e].connection==t)return e;return null},insertElseIf(e,n){const i=this.appendValueInput("IF"+n).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF,"elseif"),s=this.appendStatementInput("DO"+n).appendField(t.Msg.CONTROLS_IF_MSG_THEN);return this.moveInputBefore("IF"+n,this.inputList[e].name),this.moveInputBefore("DO"+n,this.inputList[e+1].name),{ifInput:i,doInput:s}},onPendingConnection(e){e.type!==t.NEXT_STATEMENT||this.getInput("ELSE")||this.addElseInput();const n=this.findInputIndexForConnection(e);if(null===n)return;const i=this.inputList[n];if(e.targetConnection&&i.name.includes("IF")){const e=this.inputList[n+2];if(e&&"ELSE"!=e.name){const i=e&&e.connection&&e.connection.targetConnection;i&&!i.getSourceBlock().isInsertionMarker()&&this.insertElseIf(n+2,t.utils.idGenerator.genUid())}else this.insertElseIf(n+2,t.utils.idGenerator.genUid())}},finalizeConnections(){var t,e,n;const i=this.collectTargetCaseConns(),s=null===(e=null===(t=this.getInput("ELSE"))||void 0===t?void 0:t.connection)||void 0===e?void 0:e.targetConnection;this.tearDownBlock(),this.addFirstCase(),this.addCaseInputs(i),s&&(null===(n=this.addElseInput().connection)||void 0===n||n.connect(s)),this.elseifCount=Math.max(i.length-1,0),this.elseCount=s?1:0},collectTargetCaseConns(){var t,e;const n=[];for(let i=0;i<this.inputList.length-1;i+=2){const s=null===(t=this.inputList[i].connection)||void 0===t?void 0:t.targetConnection,o=null===(e=this.inputList[i+1].connection)||void 0===e?void 0:e.targetConnection;(s||o)&&n.push({ifTarget:s,doTarget:o})}return n},tearDownBlock(){for(let t=this.inputList.length-1;t>=0;t--)this.removeInput(this.inputList[t].name)},addCaseInputs(t){var e,n;for(let i=0;i<t.length;i++){let s=this.getInput(`IF${i}`),o=this.getInput(`DO${i}`);s&&o||({ifInput:s,doInput:o}=this.insertElseIf(2*i,i));const{ifTarget:l,doTarget:u}=t[i];l&&(null===(e=s.connection)||void 0===e||e.connect(l)),u&&(null===(n=o.connection)||void 0===n||n.connect(u))}},addElseInput(){return this.appendStatementInput("ELSE").appendField(t.Msg.CONTROLS_IF_MSG_ELSE)},addFirstCase(){this.appendValueInput("IF0").setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_IF,"if"),this.appendStatementInput("DO0").appendField(t.Msg.CONTROLS_IF_MSG_THEN)}};t.Blocks.dynamic_if=n;const o={minInputs:2,itemCount:0,init(){this.itemCount=this.minInputs,this.setHelpUrl(t.Msg.TEXT_JOIN_HELPURL),this.setStyle("text_blocks"),this.addFirstInput();for(let t=1;t<this.minInputs;t++)this.appendValueInput(`ADD${t}`);this.setOutput(!0,"String"),this.setTooltip(t.Msg.TEXT_JOIN_TOOLTIP)},mutationToDom(){t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable();const e=t.utils.xml.createElement("mutation");return e.setAttribute("items",`${this.itemCount}`),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){const n=e.getAttribute("inputs");if(n){const e=n.split(",");this.inputList=[],e.forEach((t=>this.appendValueInput(t))),this.inputList[0].appendField(t.Msg.TEXT_JOIN_TITLE_CREATEWITH)}},deserializeCounts(t){var e;this.itemCount=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t<this.itemCount;t++)this.appendValueInput("ADD"+t)},saveExtraState:function(){return t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable(),{itemCount:this.itemCount}},loadExtraState:function(e){if("string"!=typeof e){this.itemCount=e.itemCount;for(let t=this.minInputs;t<this.itemCount;t++)this.appendValueInput("ADD"+t)}else this.domToMutation(t.utils.xml.textToDom(e))},findInputIndexForConnection(t){var e;if(!t.targetConnection)return null;let n=-1;for(let e=0;e<this.inputList.length;e++)this.inputList[e].connection==t&&(n=e);if(n==this.inputList.length-1)return this.inputList.length+1;const i=this.inputList[n+1],s=null===(e=null==i?void 0:i.connection)||void 0===e?void 0:e.targetConnection;return s&&!s.getSourceBlock().isInsertionMarker()?n+1:null},onPendingConnection(e){const n=this.findInputIndexForConnection(e);null!=n&&(this.appendValueInput(`ADD${t.utils.idGenerator.genUid()}`),this.moveNumberedInputBefore(this.inputList.length-1,n))},finalizeConnections(){const t=this.removeUnnecessaryEmptyConns(this.inputList.map((t=>{var e;return null===(e=t.connection)||void 0===e?void 0:e.targetConnection})));this.tearDownBlock(),this.addItemInputs(t),this.itemCount=t.length},tearDownBlock(){for(let t=this.inputList.length-1;t>=0;t--)this.removeInput(this.inputList[t].name)},removeUnnecessaryEmptyConns(t){const e=[...t];for(let t=e.length-1;t>=0;t--)!e[t]&&e.length>this.minInputs&&e.splice(t,1);return e},addItemInputs(t){var e,n;const i=this.addFirstInput(),s=t[0];s&&(null===(e=i.connection)||void 0===e||e.connect(s));for(let e=1;e<t.length;e++){const i=this.appendValueInput(`ADD${e}`),s=t[e];s&&(null===(n=i.connection)||void 0===n||n.connect(s))}},addFirstInput(){return this.appendValueInput("ADD0").appendField(t.Msg.TEXT_JOIN_TITLE_CREATEWITH)}};t.Blocks.dynamic_text_join=o;const l={minInputs:2,itemCount:0,init(){this.itemCount=this.minInputs,this.setHelpUrl(t.Msg.LISTS_CREATE_WITH_HELPURL),this.setStyle("list_blocks"),this.addFirstInput();for(let t=1;t<this.minInputs;t++)this.appendValueInput(`ADD${t}`);this.setOutput(!0,"Array"),this.setTooltip(t.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom(){t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable();const e=t.utils.xml.createElement("mutation");return e.setAttribute("items",`${this.itemCount}`),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){const n=e.getAttribute("inputs");if(n){const e=n.split(",");this.inputList=[],e.forEach((t=>this.appendValueInput(t))),this.inputList[0].appendField(t.Msg.LISTS_CREATE_WITH_INPUT_WITH)}},deserializeCounts(t){var e;this.itemCount=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t<this.itemCount;t++)this.appendValueInput("ADD"+t)},saveExtraState:function(){return t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable(),{itemCount:this.itemCount}},loadExtraState:function(e){if("string"!=typeof e){this.itemCount=e.itemCount;for(let t=this.minInputs;t<this.itemCount;t++)this.appendValueInput("ADD"+t)}else this.domToMutation(t.utils.xml.textToDom(e))},findInputIndexForConnection(t){var e;if(!t.targetConnection)return null;let n=-1;for(let e=0;e<this.inputList.length;e++)this.inputList[e].connection==t&&(n=e);if(n==this.inputList.length-1)return this.inputList.length+1;const i=this.inputList[n+1],s=null===(e=null==i?void 0:i.connection)||void 0===e?void 0:e.targetConnection;return s&&!s.getSourceBlock().isInsertionMarker()?n+1:null},onPendingConnection(e){const n=this.findInputIndexForConnection(e);null!=n&&(this.appendValueInput(`ADD${t.utils.idGenerator.genUid()}`),this.moveNumberedInputBefore(this.inputList.length-1,n))},finalizeConnections(){const t=this.removeUnnecessaryEmptyConns(this.inputList.map((t=>{var e;return null===(e=t.connection)||void 0===e?void 0:e.targetConnection})));this.tearDownBlock(),this.addItemInputs(t),this.itemCount=t.length},tearDownBlock(){for(let t=this.inputList.length-1;t>=0;t--)this.removeInput(this.inputList[t].name)},removeUnnecessaryEmptyConns(t){const e=[...t];for(let t=e.length-1;t>=0;t--)!e[t]&&e.length>this.minInputs&&e.splice(t,1);return e},addItemInputs(t){var e,n;const i=this.addFirstInput(),s=t[0];s&&(null===(e=i.connection)||void 0===e||e.connect(s));for(let e=1;e<t.length;e++){const i=this.appendValueInput(`ADD${e}`),s=t[e];s&&(null===(n=i.connection)||void 0===n||n.connect(s))}},addFirstInput(){return this.appendValueInput("ADD0").appendField(t.Msg.LISTS_CREATE_WITH_INPUT_WITH)}};t.Blocks.dynamic_list_create=l;const u=function(){t.Blocks.lists_create_with=t.Blocks.dynamic_list_create,t.Blocks.text_join=t.Blocks.dynamic_text_join,t.Blocks.controls_if=t.Blocks.dynamic_if}})(),s})()));
//# sourceMappingURL=index.js.map
/*! For license information please see index.js.LICENSE.txt */
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var n="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var i in n)("object"==typeof exports?exports:t)[i]=n[i]}}(this,(t=>(()=>{"use strict";var e={573:e=>{e.exports=t}},n={};function i(t){var s=n[t];if(void 0!==s)return s.exports;var o=n[t]={exports:{}};return e[t](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};return(()=>{i.r(s),i.d(s,{overrideOldBlockDefinitions:()=>p});var t=i(573);t.InsertionMarkerManager.prototype.update=function(e,n){var i;const s=this.getCandidate(e);this.wouldDeleteBlock=this.shouldDelete(!!s,n),(this.wouldDeleteBlock||this.shouldUpdatePreviews(s,e))&&((null===(i=null==s?void 0:s.closest)||void 0===i?void 0:i.sourceBlock_.onPendingConnection)&&(s.closest.sourceBlock_.onPendingConnection(s.closest),this.pendingBlocks||(this.pendingBlocks=new Set),this.pendingBlocks.add(s.closest.sourceBlock_)),t.Events.disable(),this.maybeHidePreview(s),this.maybeShowPreview(s),t.Events.enable())};const e=t.InsertionMarkerManager.prototype.dispose;t.InsertionMarkerManager.prototype.dispose=function(){this.pendingBlocks&&this.pendingBlocks.forEach((t=>{t.finalizeConnections&&t.finalizeConnections()})),e.call(this)};const n={inputCounter:1,minInputs:1,init(){this.setHelpUrl(t.Msg.CONTROLS_IF_HELPURL),this.setStyle("logic_blocks"),this.appendValueInput("IF0").setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_IF,"if"),this.appendStatementInput("DO0").appendField(t.Msg.CONTROLS_IF_MSG_THEN),this.setNextStatement(!0),this.setPreviousStatement(!0),this.setTooltip(t.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom(){const e=t.utils.xml.createElement("mutation"),n=this.inputList.filter((t=>t.name.includes("IF"))).map((t=>t.name.replace("IF",""))).join(",");e.setAttribute("inputs",n);const i=!!this.getInput("ELSE");return e.setAttribute("else",String(i)),e.setAttribute("next",String(this.inputCounter)),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){var n;const i=e.getAttribute("inputs");if(i){const e=i.split(",");this.getInput("IF0")&&this.removeInput("IF0"),this.getInput("DO0")&&this.removeInput("DO0");const n=e[0];this.appendValueInput("IF"+n).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_IF,"if"),this.appendStatementInput("DO"+n).appendField(t.Msg.CONTROLS_IF_MSG_THEN);for(let n=1;n<e.length;n++)this.appendValueInput("IF"+e[n]).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF,"elseif"),this.appendStatementInput("DO"+e[n]).appendField(t.Msg.CONTROLS_IF_MSG_THEN)}"true"==e.getAttribute("else")&&this.appendStatementInput("ELSE").appendField(t.Msg.CONTROLS_IF_MSG_ELSE,"else");const s=parseInt(null!==(n=e.getAttribute("next"))&&void 0!==n?n:"0",10)||0;this.inputCounter=s},deserializeCounts(e){var n,i;const s=parseInt(null!==(n=e.getAttribute("elseif"))&&void 0!==n?n:"0",10)||0,o=parseInt(null!==(i=e.getAttribute("else"))&&void 0!==i?i:"0",10)||0;for(let e=1;e<=s;e++)this.appendValueInput("IF"+e).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF),this.appendStatementInput("DO"+e).appendField(t.Msg.CONTROLS_IF_MSG_THEN);o&&this.appendStatementInput("ELSE").appendField(t.Msg.CONTROLS_IF_MSG_ELSE),this.inputCounter=s+1},findInputIndexForConnection(t){for(let e=0;e<this.inputList.length;e++)if(this.inputList[e].connection==t)return e;return null},insertElseIf(e){const n=this.inputCounter;this.appendValueInput("IF"+n).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF,"elseif"),this.appendStatementInput("DO"+n).appendField(t.Msg.CONTROLS_IF_MSG_THEN),this.moveInputBefore("IF"+n,this.inputList[e].name),this.moveInputBefore("DO"+n,this.inputList[e+1].name),this.inputCounter++},onPendingConnection(e){e.type!==t.NEXT_STATEMENT||this.getInput("ELSE")||this.appendStatementInput("ELSE").appendField(t.Msg.CONTROLS_IF_MSG_ELSE,"else");const n=this.findInputIndexForConnection(e);if(null===n)return;const i=this.inputList[n];if(e.targetConnection&&i.name.includes("IF")){const t=this.inputList[n+2];if(t&&"ELSE"!=t.name){const e=t&&t.connection&&t.connection.targetConnection;e&&!e.getSourceBlock().isInsertionMarker()&&this.insertElseIf(n+2)}else this.insertElseIf(n+2)}},finalizeConnections(){var e,n,i,s,o;const u=[];for(let t=2;t<this.inputList.length-1;t+=2){const i=this.inputList[t],s=this.inputList[t+1];(null===(e=i.connection)||void 0===e?void 0:e.targetConnection)||(null===(n=s.connection)||void 0===n?void 0:n.targetConnection)||(u.push(i.name),u.push(s.name))}u.forEach((t=>this.removeInput(t)));const p=this.getInput("ELSE");if(p&&!(null===(i=p.connection)||void 0===i?void 0:i.targetConnection)&&this.removeInput(p.name),this.inputList.length>2){const e=this.inputList[0],n=this.inputList[1],i=this.inputList[2];!i.name.includes("IF")||(null===(s=e.connection)||void 0===s?void 0:s.targetConnection)||(null===(o=n.connection)||void 0===o?void 0:o.targetConnection)||(this.removeInput(e.name),this.removeInput(n.name),i.removeField("elseif"),i.appendField(t.Msg.CONTROLS_IF_MSG_IF,"if"))}}};t.Blocks.dynamic_if=n;const o={inputCounter:2,minInputs:2,init(){this.setHelpUrl(t.Msg.TEXT_JOIN_HELPURL),this.setStyle("text_blocks"),this.appendValueInput("ADD0").appendField(t.Msg.TEXT_JOIN_TITLE_CREATEWITH),this.appendValueInput("ADD1"),this.setOutput(!0,"String"),this.setTooltip(t.Msg.TEXT_JOIN_TOOLTIP)},mutationToDom(){const e=t.utils.xml.createElement("mutation"),n=this.inputList.map((t=>t.name)).join(",");return e.setAttribute("inputs",n),e.setAttribute("next",String(this.inputCounter)),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){var n;const i=e.getAttribute("inputs");if(i){const e=i.split(",");this.inputList=[],e.forEach((t=>this.appendValueInput(t))),this.inputList[0].appendField(t.Msg.TEXT_JOIN_TITLE_CREATEWITH)}const s=parseInt(null!==(n=e.getAttribute("next"))&&void 0!==n?n:"0",10)||0;this.inputCounter=s},deserializeCounts(t){var e;const n=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t<n;t++)this.appendValueInput("ADD"+t);this.inputCounter=n},getIndexForNewInput(t){var e;if(!t.targetConnection)return null;let n=-1;for(let e=0;e<this.inputList.length;e++)this.inputList[e].connection==t&&(n=e);if(n==this.inputList.length-1)return this.inputList.length+1;const i=this.inputList[n+1],s=null===(e=null==i?void 0:i.connection)||void 0===e?void 0:e.targetConnection;return s&&!s.getSourceBlock().isInsertionMarker()?n+1:null},onPendingConnection(t){const e=this.getIndexForNewInput(t);null!=e&&(this.appendValueInput("ADD"+this.inputCounter++),this.moveNumberedInputBefore(this.inputList.length-1,e))},finalizeConnections(){if(this.inputList.length>this.minInputs){let e=[];this.inputList.forEach((t=>{var n;(null===(n=t.connection)||void 0===n?void 0:n.targetConnection)||e.push(t.name)})),this.inputList.length-e.length<this.minInputs&&(e=e.slice(this.minInputs)),e.forEach((t=>this.removeInput(t))),0==this.inputList[0].fieldRow.length&&this.inputList[0].appendField(t.Msg.TEXT_JOIN_TITLE_CREATEWITH)}}};t.Blocks.dynamic_text_join=o;const u={inputCounter:2,minInputs:2,init(){this.setHelpUrl(t.Msg.LISTS_CREATE_WITH_HELPURL),this.setStyle("list_blocks"),this.appendValueInput("ADD0").appendField(t.Msg.LISTS_CREATE_WITH_INPUT_WITH),this.appendValueInput("ADD1"),this.setOutput(!0,"Array"),this.setTooltip(t.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom(){const e=t.utils.xml.createElement("mutation"),n=this.inputList.map((t=>t.name)).join(",");return e.setAttribute("inputs",n),e.setAttribute("next",String(this.inputCounter)),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){var n;const i=e.getAttribute("inputs");if(i){const e=i.split(",");this.inputList=[],e.forEach((t=>this.appendValueInput(t))),this.inputList[0].appendField(t.Msg.LISTS_CREATE_WITH_INPUT_WITH)}const s=parseInt(null!==(n=e.getAttribute("next"))&&void 0!==n?n:"0",10)||0;this.inputCounter=s},deserializeCounts(t){var e;const n=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t<n;t++)this.appendValueInput("ADD"+t);this.inputCounter=n},getIndexForNewInput(t){var e;if(!t.targetConnection)return null;let n=-1;for(let e=0;e<this.inputList.length;e++)this.inputList[e].connection==t&&(n=e);if(n==this.inputList.length-1)return this.inputList.length+1;const i=this.inputList[n+1],s=null===(e=null==i?void 0:i.connection)||void 0===e?void 0:e.targetConnection;return s&&!s.getSourceBlock().isInsertionMarker()?n+1:null},onPendingConnection(t){const e=this.getIndexForNewInput(t);null!=e&&(this.appendValueInput("ADD"+this.inputCounter++),this.moveNumberedInputBefore(this.inputList.length-1,e))},finalizeConnections(){if(this.inputList.length>this.minInputs){let e=[];this.inputList.forEach((t=>{var n;(null===(n=t.connection)||void 0===n?void 0:n.targetConnection)||e.push(t.name)})),this.inputList.length-e.length<this.minInputs&&(e=e.slice(this.minInputs)),e.forEach((t=>this.removeInput(t))),0==this.inputList[0].fieldRow.length&&this.inputList[0].appendField(t.Msg.LISTS_CREATE_WITH_INPUT_WITH)}}};t.Blocks.dynamic_list_create=u;const p=function(){t.Blocks.lists_create_with=t.Blocks.dynamic_list_create,t.Blocks.text_join=t.Blocks.dynamic_text_join,t.Blocks.controls_if=t.Blocks.dynamic_if}})(),s})()));
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var n="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var i in n)("object"==typeof exports?exports:t)[i]=n[i]}}(this,(t=>(()=>{"use strict";var e={573:e=>{e.exports=t}},n={};function i(t){var s=n[t];if(void 0!==s)return s.exports;var o=n[t]={exports:{}};return e[t](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};return(()=>{i.r(s),i.d(s,{overrideOldBlockDefinitions:()=>u});var t=i(573);t.InsertionMarkerManager.prototype.update=function(e,n){var i;const s=this.getCandidate(e);this.wouldDeleteBlock=this.shouldDelete(!!s,n),(this.wouldDeleteBlock||this.shouldUpdatePreviews(s,e))&&((null===(i=null==s?void 0:s.closest)||void 0===i?void 0:i.sourceBlock_.onPendingConnection)&&(s.closest.sourceBlock_.onPendingConnection(s.closest),this.pendingBlocks||(this.pendingBlocks=new Set),this.pendingBlocks.add(s.closest.sourceBlock_)),t.Events.disable(),this.maybeHidePreview(s),this.maybeShowPreview(s),t.Events.enable())};const e=t.InsertionMarkerManager.prototype.dispose;t.InsertionMarkerManager.prototype.dispose=function(){this.pendingBlocks&&this.pendingBlocks.forEach((t=>{t.finalizeConnections&&t.finalizeConnections()})),e.call(this)};const n={minInputs:1,elseifCount:0,elseCount:0,init(){this.setHelpUrl(t.Msg.CONTROLS_IF_HELPURL),this.setStyle("logic_blocks"),this.addFirstCase(),this.setNextStatement(!0),this.setPreviousStatement(!0),this.setTooltip(t.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom(){if(t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable(),!this.elseifCount&&!this.elseCount)return null;const e=t.utils.xml.createElement("mutation");return this.elseifCount&&e.setAttribute("elseif",`${this.elseifCount}`),this.elseCount&&e.setAttribute("else","1"),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){const n=e.getAttribute("inputs");if(n){const e=n.split(",");this.getInput("IF0")&&this.removeInput("IF0"),this.getInput("DO0")&&this.removeInput("DO0");const i=e[0];this.appendValueInput("IF"+i).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_IF,"if"),this.appendStatementInput("DO"+i).appendField(t.Msg.CONTROLS_IF_MSG_THEN);for(let n=1;n<e.length;n++)this.appendValueInput("IF"+e[n]).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF,"elseif"),this.appendStatementInput("DO"+e[n]).appendField(t.Msg.CONTROLS_IF_MSG_THEN)}"true"==e.getAttribute("else")&&this.addElseInput()},deserializeCounts(t){var e,n;this.elseifCount=parseInt(null!==(e=t.getAttribute("elseif"))&&void 0!==e?e:"0",10)||0,this.elseCount=parseInt(null!==(n=t.getAttribute("else"))&&void 0!==n?n:"0",10)||0;for(let t=1;t<=this.elseifCount;t++)this.insertElseIf(this.inputList.length,t);this.elseCount&&this.addElseInput()},saveExtraState:function(){if(t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable(),!this.elseifCount&&!this.elseCount)return null;const e=Object.create(null);return this.elseifCount&&(e.elseIfCount=this.elseifCount),this.elseCount&&(e.hasElse=!0),e},loadExtraState:function(e){if("string"!=typeof e){this.elseifCount=e.elseIfCount||0,this.elseCount=e.hasElse?1:0;for(let t=1;t<=this.elseifCount;t++)this.insertElseIf(this.inputList.length,t);this.elseCount&&this.addElseInput()}else this.domToMutation(t.utils.xml.textToDom(e))},findInputIndexForConnection(t){for(let e=0;e<this.inputList.length;e++)if(this.inputList[e].connection==t)return e;return null},insertElseIf(e,n){const i=this.appendValueInput("IF"+n).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF,"elseif"),s=this.appendStatementInput("DO"+n).appendField(t.Msg.CONTROLS_IF_MSG_THEN);return this.moveInputBefore("IF"+n,this.inputList[e].name),this.moveInputBefore("DO"+n,this.inputList[e+1].name),{ifInput:i,doInput:s}},onPendingConnection(e){e.type!==t.NEXT_STATEMENT||this.getInput("ELSE")||this.addElseInput();const n=this.findInputIndexForConnection(e);if(null===n)return;const i=this.inputList[n];if(e.targetConnection&&i.name.includes("IF")){const e=this.inputList[n+2];if(e&&"ELSE"!=e.name){const i=e&&e.connection&&e.connection.targetConnection;i&&!i.getSourceBlock().isInsertionMarker()&&this.insertElseIf(n+2,t.utils.idGenerator.genUid())}else this.insertElseIf(n+2,t.utils.idGenerator.genUid())}},finalizeConnections(){var t,e,n;const i=this.collectTargetCaseConns(),s=null===(e=null===(t=this.getInput("ELSE"))||void 0===t?void 0:t.connection)||void 0===e?void 0:e.targetConnection;this.tearDownBlock(),this.addFirstCase(),this.addCaseInputs(i),s&&(null===(n=this.addElseInput().connection)||void 0===n||n.connect(s)),this.elseifCount=Math.max(i.length-1,0),this.elseCount=s?1:0},collectTargetCaseConns(){var t,e;const n=[];for(let i=0;i<this.inputList.length-1;i+=2){const s=null===(t=this.inputList[i].connection)||void 0===t?void 0:t.targetConnection,o=null===(e=this.inputList[i+1].connection)||void 0===e?void 0:e.targetConnection;(s||o)&&n.push({ifTarget:s,doTarget:o})}return n},tearDownBlock(){for(let t=this.inputList.length-1;t>=0;t--)this.removeInput(this.inputList[t].name)},addCaseInputs(t){var e,n;for(let i=0;i<t.length;i++){let s=this.getInput(`IF${i}`),o=this.getInput(`DO${i}`);s&&o||({ifInput:s,doInput:o}=this.insertElseIf(2*i,i));const{ifTarget:l,doTarget:u}=t[i];l&&(null===(e=s.connection)||void 0===e||e.connect(l)),u&&(null===(n=o.connection)||void 0===n||n.connect(u))}},addElseInput(){return this.appendStatementInput("ELSE").appendField(t.Msg.CONTROLS_IF_MSG_ELSE)},addFirstCase(){this.appendValueInput("IF0").setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_IF,"if"),this.appendStatementInput("DO0").appendField(t.Msg.CONTROLS_IF_MSG_THEN)}};t.Blocks.dynamic_if=n;const o={minInputs:2,itemCount:0,init(){this.itemCount=this.minInputs,this.setHelpUrl(t.Msg.TEXT_JOIN_HELPURL),this.setStyle("text_blocks"),this.addFirstInput();for(let t=1;t<this.minInputs;t++)this.appendValueInput(`ADD${t}`);this.setOutput(!0,"String"),this.setTooltip(t.Msg.TEXT_JOIN_TOOLTIP)},mutationToDom(){t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable();const e=t.utils.xml.createElement("mutation");return e.setAttribute("items",`${this.itemCount}`),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){const n=e.getAttribute("inputs");if(n){const e=n.split(",");this.inputList=[],e.forEach((t=>this.appendValueInput(t))),this.inputList[0].appendField(t.Msg.TEXT_JOIN_TITLE_CREATEWITH)}},deserializeCounts(t){var e;this.itemCount=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t<this.itemCount;t++)this.appendValueInput("ADD"+t)},saveExtraState:function(){return t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable(),{itemCount:this.itemCount}},loadExtraState:function(e){if("string"!=typeof e){this.itemCount=e.itemCount;for(let t=this.minInputs;t<this.itemCount;t++)this.appendValueInput("ADD"+t)}else this.domToMutation(t.utils.xml.textToDom(e))},findInputIndexForConnection(t){var e;if(!t.targetConnection)return null;let n=-1;for(let e=0;e<this.inputList.length;e++)this.inputList[e].connection==t&&(n=e);if(n==this.inputList.length-1)return this.inputList.length+1;const i=this.inputList[n+1],s=null===(e=null==i?void 0:i.connection)||void 0===e?void 0:e.targetConnection;return s&&!s.getSourceBlock().isInsertionMarker()?n+1:null},onPendingConnection(e){const n=this.findInputIndexForConnection(e);null!=n&&(this.appendValueInput(`ADD${t.utils.idGenerator.genUid()}`),this.moveNumberedInputBefore(this.inputList.length-1,n))},finalizeConnections(){const t=this.removeUnnecessaryEmptyConns(this.inputList.map((t=>{var e;return null===(e=t.connection)||void 0===e?void 0:e.targetConnection})));this.tearDownBlock(),this.addItemInputs(t),this.itemCount=t.length},tearDownBlock(){for(let t=this.inputList.length-1;t>=0;t--)this.removeInput(this.inputList[t].name)},removeUnnecessaryEmptyConns(t){const e=[...t];for(let t=e.length-1;t>=0;t--)!e[t]&&e.length>this.minInputs&&e.splice(t,1);return e},addItemInputs(t){var e,n;const i=this.addFirstInput(),s=t[0];s&&(null===(e=i.connection)||void 0===e||e.connect(s));for(let e=1;e<t.length;e++){const i=this.appendValueInput(`ADD${e}`),s=t[e];s&&(null===(n=i.connection)||void 0===n||n.connect(s))}},addFirstInput(){return this.appendValueInput("ADD0").appendField(t.Msg.TEXT_JOIN_TITLE_CREATEWITH)}};t.Blocks.dynamic_text_join=o;const l={minInputs:2,itemCount:0,init(){this.itemCount=this.minInputs,this.setHelpUrl(t.Msg.LISTS_CREATE_WITH_HELPURL),this.setStyle("list_blocks"),this.addFirstInput();for(let t=1;t<this.minInputs;t++)this.appendValueInput(`ADD${t}`);this.setOutput(!0,"Array"),this.setTooltip(t.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom(){t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable();const e=t.utils.xml.createElement("mutation");return e.setAttribute("items",`${this.itemCount}`),e},domToMutation(t){t.getAttribute("inputs")?this.deserializeInputs(t):this.deserializeCounts(t)},deserializeInputs(e){const n=e.getAttribute("inputs");if(n){const e=n.split(",");this.inputList=[],e.forEach((t=>this.appendValueInput(t))),this.inputList[0].appendField(t.Msg.LISTS_CREATE_WITH_INPUT_WITH)}},deserializeCounts(t){var e;this.itemCount=Math.max(parseInt(null!==(e=t.getAttribute("items"))&&void 0!==e?e:"0",10),this.minInputs);for(let t=this.minInputs;t<this.itemCount;t++)this.appendValueInput("ADD"+t)},saveExtraState:function(){return t.Events.disable(),this.finalizeConnections(),this instanceof t.BlockSvg&&this.initSvg(),t.Events.enable(),{itemCount:this.itemCount}},loadExtraState:function(e){if("string"!=typeof e){this.itemCount=e.itemCount;for(let t=this.minInputs;t<this.itemCount;t++)this.appendValueInput("ADD"+t)}else this.domToMutation(t.utils.xml.textToDom(e))},findInputIndexForConnection(t){var e;if(!t.targetConnection)return null;let n=-1;for(let e=0;e<this.inputList.length;e++)this.inputList[e].connection==t&&(n=e);if(n==this.inputList.length-1)return this.inputList.length+1;const i=this.inputList[n+1],s=null===(e=null==i?void 0:i.connection)||void 0===e?void 0:e.targetConnection;return s&&!s.getSourceBlock().isInsertionMarker()?n+1:null},onPendingConnection(e){const n=this.findInputIndexForConnection(e);null!=n&&(this.appendValueInput(`ADD${t.utils.idGenerator.genUid()}`),this.moveNumberedInputBefore(this.inputList.length-1,n))},finalizeConnections(){const t=this.removeUnnecessaryEmptyConns(this.inputList.map((t=>{var e;return null===(e=t.connection)||void 0===e?void 0:e.targetConnection})));this.tearDownBlock(),this.addItemInputs(t),this.itemCount=t.length},tearDownBlock(){for(let t=this.inputList.length-1;t>=0;t--)this.removeInput(this.inputList[t].name)},removeUnnecessaryEmptyConns(t){const e=[...t];for(let t=e.length-1;t>=0;t--)!e[t]&&e.length>this.minInputs&&e.splice(t,1);return e},addItemInputs(t){var e,n;const i=this.addFirstInput(),s=t[0];s&&(null===(e=i.connection)||void 0===e||e.connect(s));for(let e=1;e<t.length;e++){const i=this.appendValueInput(`ADD${e}`),s=t[e];s&&(null===(n=i.connection)||void 0===n||n.connect(s))}},addFirstInput(){return this.appendValueInput("ADD0").appendField(t.Msg.LISTS_CREATE_WITH_INPUT_WITH)}};t.Blocks.dynamic_list_create=l;const u=function(){t.Blocks.lists_create_with=t.Blocks.dynamic_list_create,t.Blocks.text_join=t.Blocks.dynamic_text_join,t.Blocks.controls_if=t.Blocks.dynamic_if}})(),s})()));
//# sourceMappingURL=index.js.map
{
"name": "@blockly/block-dynamic-connection",
"version": "0.4.3",
"version": "0.5.0",
"description": "A group of blocks that add connections dynamically.",

@@ -45,3 +45,3 @@ "scripts": {

"@blockly/dev-tools": "^7.1.0",
"blockly": "^10.0.0",
"blockly": "^10.2.0",
"chai": "^4.2.0",

@@ -51,3 +51,3 @@ "mocha": "^10.2.0"

"peerDependencies": {
"blockly": "^10.0.0"
"blockly": "^10.2.0"
},

@@ -64,3 +64,3 @@ "publishConfig": {

},
"gitHead": "9aa7cd200a6b1a396b5b3b908c7b9d574ddf8805"
"gitHead": "90bef04779f022f2650508a2e565274fdc1fb99c"
}

@@ -21,15 +21,12 @@ # @blockly/block-dynamic-connection [![Built on Blockly](https://tinyurl.com/built-on-blockly)](https://github.com/google/blockly)

dynamic connection blocks. This enables projects to use the dynamic block
plugin without changing existing XML.
Note that if you enable this, you will **never** be able to switch back to
non-dynamic connections, because this changes the way mutations are
serialized.
plugin without changing existing XML/JSON.
## XML
```xml
<block type="dynamic_text_join"></block>
<block type="dynamic_list_create"></block>
<block type="dynamic_if"></block>
```
## Blocks
* `dynamic_text_join` replaces `text_join`
* `dynamic_list_create` replaces `lists_create_with`
* `dynamic_if` replaces `controls_if`
## License
Apache 2.0

@@ -22,11 +22,32 @@ /**

interface CaseConnectionPair {
ifTarget?: Blockly.Connection | null;
doTarget?: Blockly.Connection | null;
}
interface CaseInputPair {
ifInput: Blockly.Input;
doInput: Blockly.Input;
}
/** Extra state for serializing controls_if blocks. */
interface IfExtraState {
elseIfCount?: number;
hasElse?: boolean;
}
/* eslint-disable @typescript-eslint/naming-convention */
const DYNAMIC_IF_MIXIN = {
/* eslint-enable @typescript-eslint/naming-convention */
/** Counter for the next input to add to this block. */
inputCounter: 1,
/** Minimum number of inputs for this block. */
/**
* Minimum number of inputs for this block.
* @deprecated This is unused.
*/
minInputs: 1,
/** Count of else-if cases. */
elseifCount: 0,
/** Count of else cases (either 0 or 1). */
elseCount: 0,
/**

@@ -39,9 +60,3 @@ * Block for if/elseif/else statements. Must have one if input.

this.setStyle('logic_blocks');
this.appendValueInput('IF0')
.setCheck('Boolean')
.appendField(Blockly.Msg['CONTROLS_IF_MSG_IF'], 'if');
this.appendStatementInput('DO0')
.appendField(Blockly.Msg['CONTROLS_IF_MSG_THEN']);
this.addFirstCase();
this.setNextStatement(true);

@@ -56,11 +71,19 @@ this.setPreviousStatement(true);

*/
mutationToDom(this: DynamicIfBlock): Element {
mutationToDom(this: DynamicIfBlock): Element|null {
// If we call finalizeConnections here without disabling events, we get into
// an event loop.
Blockly.Events.disable();
this.finalizeConnections();
if (this instanceof Blockly.BlockSvg) this.initSvg();
Blockly.Events.enable();
if (!this.elseifCount && !this.elseCount) return null;
const container = Blockly.utils.xml.createElement('mutation');
const inputNames = this.inputList
.filter((input: Blockly.Input) => input.name.includes('IF'))
.map((input: Blockly.Input) => input.name.replace('IF', '')).join(',');
container.setAttribute('inputs', inputNames);
const hasElse = !!this.getInput('ELSE');
container.setAttribute('else', String(hasElse));
container.setAttribute('next', String(this.inputCounter));
if (this.elseifCount) {
container.setAttribute('elseif', `${this.elseifCount}`);
}
if (this.elseCount) {
container.setAttribute('else', '1');
}
return container;

@@ -112,7 +135,4 @@ },

if (hasElse == 'true') {
this.appendStatementInput('ELSE')
.appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSE'], 'else');
this.addElseInput();
}
const next = parseInt(xmlElement.getAttribute('next') ?? '0', 10) || 0;
this.inputCounter = next;
},

@@ -125,19 +145,60 @@

deserializeCounts(this: DynamicIfBlock, xmlElement: Element): void {
const elseifCount = parseInt(
this.elseifCount = parseInt(
xmlElement.getAttribute('elseif') ?? '0', 10) || 0;
const elseCount = parseInt(xmlElement.getAttribute('else') ?? '0', 10) || 0;
for (let i = 1; i <= elseifCount; i++) {
this.appendValueInput('IF' + i).setCheck('Boolean').appendField(
Blockly.Msg['CONTROLS_IF_MSG_ELSEIF']);
this.appendStatementInput('DO' + i).appendField(
Blockly.Msg['CONTROLS_IF_MSG_THEN']);
this.elseCount = parseInt(xmlElement.getAttribute('else') ?? '0', 10) || 0;
for (let i = 1; i <= this.elseifCount; i++) {
this.insertElseIf(this.inputList.length, i);
}
if (elseCount) {
this.appendStatementInput('ELSE').appendField(
Blockly.Msg['CONTROLS_IF_MSG_ELSE']);
if (this.elseCount) {
this.addElseInput();
}
this.inputCounter = elseifCount + 1;
},
/**
* Returns the state of this block as a JSON serializable object.
* @returns The state of this block, ie the else if count and else state.
*/
saveExtraState: function(this: DynamicIfBlock): IfExtraState | null {
// If we call finalizeConnections here without disabling events, we get into
// an event loop.
Blockly.Events.disable();
this.finalizeConnections();
if (this instanceof Blockly.BlockSvg) this.initSvg();
Blockly.Events.enable();
if (!this.elseifCount && !this.elseCount) {
return null;
}
const state = Object.create(null);
if (this.elseifCount) {
state['elseIfCount'] = this.elseifCount;
}
if (this.elseCount) {
state['hasElse'] = true;
}
return state;
},
/**
* Applies the given state to this block.
* @param state The state to apply to this block, ie the else if count
* and else state.
*/
loadExtraState: function(this: DynamicIfBlock, state: IfExtraState | string) {
if (typeof state === 'string') {
this.domToMutation(Blockly.utils.xml.textToDom(state));
return;
}
this.elseifCount = state['elseIfCount'] || 0;
this.elseCount = state['hasElse'] ? 1 : 0;
for (let i = 1; i <= this.elseifCount; i++) {
this.insertElseIf(this.inputList.length, i);
}
if (this.elseCount) {
this.addElseInput();
}
},
/**
* Finds the index of a connection. Used to determine where in the block to

@@ -162,14 +223,17 @@ * insert new inputs.

* @param index Index of the input before which to add new inputs.
* @param id An ID to append to the case statement input names to make them
* unique.
* @returns The added inputs.
*/
insertElseIf(this: DynamicIfBlock, index: number): void {
const caseNumber = this.inputCounter;
this
.appendValueInput('IF' + caseNumber)
insertElseIf(
this: DynamicIfBlock, index: number, id: string | number
): CaseInputPair {
const ifInput = this.appendValueInput('IF' + id)
.setCheck('Boolean')
.appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSEIF'], 'elseif');
this.appendStatementInput('DO' + caseNumber)
const doInput = this.appendStatementInput('DO' + id)
.appendField(Blockly.Msg['CONTROLS_IF_MSG_THEN']);
this.moveInputBefore('IF' + caseNumber, this.inputList[index].name);
this.moveInputBefore('DO' + caseNumber, this.inputList[index + 1].name);
this.inputCounter++;
this.moveInputBefore('IF' + id, this.inputList[index].name);
this.moveInputBefore('DO' + id, this.inputList[index + 1].name);
return {ifInput, doInput};
},

@@ -186,4 +250,3 @@

if (connection.type === Blockly.NEXT_STATEMENT && !this.getInput('ELSE')) {
this.appendStatementInput('ELSE')
.appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSE'], 'else');
this.addElseInput();
}

@@ -198,3 +261,3 @@ const inputIndex = this.findInputIndexForConnection(connection);

if (!nextIfInput || nextIfInput.name == 'ELSE') {
this.insertElseIf(inputIndex + 2);
this.insertElseIf(inputIndex + 2, Blockly.utils.idGenerator.genUid());
} else {

@@ -209,3 +272,3 @@ const nextIfConnection =

) {
this.insertElseIf(inputIndex + 2);
this.insertElseIf(inputIndex + 2, Blockly.utils.idGenerator.genUid());
}

@@ -221,38 +284,88 @@ }

finalizeConnections(this: DynamicIfBlock): void {
const toRemove = [];
// Remove Else If inputs if neither the if nor the do has a connected block.
for (let i = 2; i < this.inputList.length - 1; i += 2) {
const ifConnection = this.inputList[i];
const doConnection = this.inputList[i + 1];
if (!ifConnection.connection?.targetConnection &&
!doConnection.connection?.targetConnection) {
toRemove.push(ifConnection.name);
toRemove.push(doConnection.name);
}
const targetCaseConns = this.collectTargetCaseConns();
const targetElseConn = this.getInput('ELSE')?.connection?.targetConnection;
this.tearDownBlock();
this.addFirstCase();
this.addCaseInputs(targetCaseConns);
if (targetElseConn) {
this.addElseInput().connection?.connect(targetElseConn);
}
toRemove.forEach((input) => this.removeInput(input));
// Remove Else input if it doesn't have a connected block.
const elseInput = this.getInput('ELSE');
if (elseInput && !elseInput.connection?.targetConnection) {
this.removeInput(elseInput.name);
this.elseifCount = Math.max(targetCaseConns.length - 1, 0);
this.elseCount = targetElseConn ? 1 : 0;
},
/**
* Collects all of the target blocks attached to case inputs. If neither the
* if nor the due input in a case has an attached block, that input is
* skipped. If only one of them has an attached block, the other value in
* the pair is undefined.
* @returns A list of target connections attached to case inputs.
*/
collectTargetCaseConns(this: DynamicIfBlock): CaseConnectionPair[] {
const targetConns = [];
for (let i = 0; i < this.inputList.length - 1; i += 2) {
const ifTarget =
this.inputList[i].connection?.targetConnection;
const doTarget =
this.inputList[i + 1].connection?.targetConnection;
if (!ifTarget && !doTarget) continue;
targetConns.push({ifTarget, doTarget});
}
return targetConns;
},
// Remove the If input if it is empty and there is at least one Else If
if (this.inputList.length > 2) {
const ifInput = this.inputList[0];
const doInput = this.inputList[1];
const nextInput = this.inputList[2];
if (nextInput.name.includes('IF') &&
!ifInput.connection?.targetConnection &&
!doInput.connection?.targetConnection) {
this.removeInput(ifInput.name);
this.removeInput(doInput.name);
nextInput.removeField('elseif');
nextInput.appendField(Blockly.Msg['CONTROLS_IF_MSG_IF'], 'if');
/** Deletes all inputs on the block so it can be rebuilt. */
tearDownBlock(this: DynamicIfBlock): void {
for (let i = this.inputList.length - 1; i >= 0; i--) {
this.removeInput(this.inputList[i].name);
}
},
/**
* Adds inputs for all of the given target connection pairs (if the input
* doesn't already exist), and connects the target connections to them.
*
* This is essentially rebuilding all of the cases with strictly ascending
* case numbers.
* @param targetConns The list of target connections to attach to this block.
*/
addCaseInputs(this: DynamicIfBlock, targetConns: CaseConnectionPair[]): void {
for (let i = 0; i < targetConns.length; i++) {
let ifInput = this.getInput(`IF${i}`);
let doInput = this.getInput(`DO${i}`);
if (!ifInput || !doInput) {
({ifInput, doInput} = this.insertElseIf(i * 2, i));
}
const {ifTarget, doTarget} = targetConns[i];
if (ifTarget) ifInput.connection?.connect(ifTarget);
if (doTarget) doInput.connection?.connect(doTarget);
}
},
/**
* Adds an else input to this block.
* @returns The appended input.
*/
addElseInput(this: DynamicIfBlock): Blockly.Input {
return this.appendStatementInput('ELSE')
.appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSE']);
},
/**
* Adds the first 'IF' and 'DO' inputs and their associated labels to this
* block.
*/
addFirstCase(this: DynamicIfBlock): void {
this.appendValueInput('IF0')
.setCheck('Boolean')
.appendField(Blockly.Msg['CONTROLS_IF_MSG_IF'], 'if');
this.appendStatementInput('DO0')
.appendField(Blockly.Msg['CONTROLS_IF_MSG_THEN']);
},
};
Blockly.Blocks['dynamic_if'] = DYNAMIC_IF_MIXIN;

@@ -25,15 +25,18 @@ /**

/* eslint-enable @typescript-eslint/naming-convention */
/** Counter for the next input to add to this block. */
inputCounter: 2,
/** Minimum number of inputs for this block. */
minInputs: 2,
/** Count of item inputs. */
itemCount: 0,
/** Block for concatenating any number of strings. */
init(this: DynamicListCreateBlock): void {
this.itemCount = this.minInputs;
this.setHelpUrl(Blockly.Msg['LISTS_CREATE_WITH_HELPURL']);
this.setStyle('list_blocks');
this.appendValueInput('ADD0')
.appendField(Blockly.Msg['LISTS_CREATE_WITH_INPUT_WITH']);
this.appendValueInput('ADD1');
this.addFirstInput();
for (let i = 1; i < this.minInputs; i++) {
this.appendValueInput(`ADD${i}`);
}
this.setOutput(true, 'Array');

@@ -48,7 +51,11 @@ this.setTooltip(Blockly.Msg['LISTS_CREATE_WITH_TOOLTIP']);

mutationToDom(this: DynamicListCreateBlock): Element {
// If we call finalizeConnections here without disabling events, we get into
// an event loop.
Blockly.Events.disable();
this.finalizeConnections();
if (this instanceof Blockly.BlockSvg) this.initSvg();
Blockly.Events.enable();
const container = Blockly.utils.xml.createElement('mutation');
const inputNames =
this.inputList.map((input: Blockly.Input) => input.name).join(',');
container.setAttribute('inputs', inputNames);
container.setAttribute('next', String(this.inputCounter));
container.setAttribute('items', `${this.itemCount}`);
return container;

@@ -82,4 +89,2 @@ },

}
const next = parseInt(xmlElement.getAttribute('next') ?? '0', 10) || 0;
this.inputCounter = next;
},

@@ -92,12 +97,46 @@

deserializeCounts(this: DynamicListCreateBlock, xmlElement: Element): void {
const itemCount = Math.max(
this.itemCount = Math.max(
parseInt(xmlElement.getAttribute('items') ?? '0', 10), this.minInputs);
// Two inputs are added automatically.
for (let i = this.minInputs; i < itemCount; i++) {
// minInputs are added automatically.
for (let i = this.minInputs; i < this.itemCount; i++) {
this.appendValueInput('ADD' + i);
}
this.inputCounter = itemCount;
},
/**
* Returns the state of this block as a JSON serializable object.
* @returns The state of this block, ie the item count.
*/
saveExtraState: function(this: DynamicListCreateBlock): {itemCount: number} {
// If we call finalizeConnections here without disabling events, we get into
// an event loop.
Blockly.Events.disable();
this.finalizeConnections();
if (this instanceof Blockly.BlockSvg) this.initSvg();
Blockly.Events.enable();
return {
'itemCount': this.itemCount,
};
},
/**
* Applies the given state to this block.
* @param state The state to apply to this block, ie the item count.
*/
loadExtraState: function(
this: DynamicListCreateBlock, state: ({[x: string]: any} | string)) {
if (typeof state === 'string') {
this.domToMutation(Blockly.utils.xml.textToDom(state));
return;
}
this.itemCount = state['itemCount'];
// minInputs are added automatically.
for (let i = this.minInputs; i < this.itemCount; i++) {
this.appendValueInput('ADD' + i);
}
},
/**
* Check whether a new input should be added and determine where it should go.

@@ -108,3 +147,3 @@ * @param connection The connection that has a pending connection.

*/
getIndexForNewInput(
findInputIndexForConnection(
this: DynamicListCreateBlock,

@@ -149,7 +188,7 @@ connection: Blockly.Connection): number | null {

this: DynamicListCreateBlock, connection: Blockly.Connection): void {
const insertIndex = this.getIndexForNewInput(connection);
const insertIndex = this.findInputIndexForConnection(connection);
if (insertIndex == null) {
return;
}
this.appendValueInput('ADD' + (this.inputCounter++));
this.appendValueInput(`ADD${Blockly.utils.idGenerator.genUid()}`);
this.moveNumberedInputBefore(this.inputList.length - 1, insertIndex);

@@ -163,25 +202,70 @@ },

finalizeConnections(this: DynamicListCreateBlock): void {
if (this.inputList.length > this.minInputs) {
let toRemove: string[] = [];
this.inputList.forEach((input: Blockly.Input) => {
if (!input.connection?.targetConnection) {
toRemove.push(input.name);
}
});
const targetConns =
this.removeUnnecessaryEmptyConns(
this.inputList.map((i) => i.connection?.targetConnection));
this.tearDownBlock();
this.addItemInputs(targetConns);
this.itemCount = targetConns.length;
},
if (this.inputList.length - toRemove.length < this.minInputs) {
// Always show at least two inputs
toRemove = toRemove.slice(this.minInputs);
/** Deletes all inputs on the block so it can be rebuilt. */
tearDownBlock(this: DynamicListCreateBlock): void {
for (let i = this.inputList.length - 1; i >= 0; i--) {
this.removeInput(this.inputList[i].name);
}
},
/**
* Filters the given target connections so that empty connections are removed,
* unless we need those to reach the minimum input count. Empty connections
* are removed starting at the end of the array.
* @param targetConns The list of connections associated with inputs.
* @returns A filtered list of connections (or null/undefined) which should
* be attached to inputs.
*/
removeUnnecessaryEmptyConns(
targetConns: Array<Blockly.Connection | undefined | null>
): Array<Blockly.Connection | undefined | null> {
const filteredConns = [...targetConns];
for (let i = filteredConns.length - 1; i >= 0; i--) {
if (!filteredConns[i] && filteredConns.length > this.minInputs) {
filteredConns.splice(i, 1);
}
toRemove.forEach((inputName) => this.removeInput(inputName));
// The first input should have the block text. If we removed the
// first input, add the block text to the new first input.
if (this.inputList[0].fieldRow.length == 0) {
this.inputList[0]
.appendField(Blockly.Msg['LISTS_CREATE_WITH_INPUT_WITH']);
}
}
return filteredConns;
},
/**
* Adds inputs based on the given array of target cons. An input is added for
* every entry in the array (if it does not already exist). If the entry is
* a connection and not null/undefined the connection will be connected to
* the input.
* @param targetConns The connections defining the inputs to add.
*/
addItemInputs(
this: DynamicListCreateBlock,
targetConns: Array<Blockly.Connection | undefined | null>,
): void {
const input = this.addFirstInput();
const firstConn = targetConns[0];
if (firstConn) input.connection?.connect(firstConn);
for (let i = 1; i < targetConns.length; i++) {
const input = this.appendValueInput(`ADD${i}`);
const targetConn = targetConns[i];
if (targetConn) input.connection?.connect(targetConn);
}
},
/**
* Adds the top input with the label to this block.
* @returns The added input.
*/
addFirstInput(this: DynamicListCreateBlock): Blockly.Input {
return this.appendValueInput('ADD0')
.appendField(Blockly.Msg['LISTS_CREATE_WITH_INPUT_WITH']);
},
};
Blockly.Blocks['dynamic_list_create'] = DYNAMIC_LIST_CREATE_MIXIN;

@@ -25,15 +25,16 @@ /**

/* eslint-enable @typescript-eslint/naming-convention */
/** Counter for the next input to add to this block. */
inputCounter: 2,
/** Minimum number of inputs for this block. */
minInputs: 2,
/** Count of the item inputs. */
itemCount: 0,
/** Block for concatenating any number of strings. */
init(this: DynamicTextJoinBlock): void {
this.itemCount = this.minInputs;
this.setHelpUrl(Blockly.Msg['TEXT_JOIN_HELPURL']);
this.setStyle('text_blocks');
this.appendValueInput('ADD0')
.appendField(Blockly.Msg['TEXT_JOIN_TITLE_CREATEWITH']);
this.appendValueInput('ADD1');
this.addFirstInput();
for (let i = 1; i < this.minInputs; i++) this.appendValueInput(`ADD${i}`);
this.setOutput(true, 'String');

@@ -48,7 +49,11 @@ this.setTooltip(Blockly.Msg['TEXT_JOIN_TOOLTIP']);

mutationToDom(this: DynamicTextJoinBlock): Element {
// If we call finalizeConnections here without disabling events, we get into
// an event loop.
Blockly.Events.disable();
this.finalizeConnections();
if (this instanceof Blockly.BlockSvg) this.initSvg();
Blockly.Events.enable();
const container = Blockly.utils.xml.createElement('mutation');
const inputNames =
this.inputList.map((input: Blockly.Input) => input.name).join(',');
container.setAttribute('inputs', inputNames);
container.setAttribute('next', String(this.inputCounter));
container.setAttribute('items', `${this.itemCount}`);
return container;

@@ -82,4 +87,2 @@ },

}
const next = parseInt(xmlElement.getAttribute('next') ?? '0', 10) || 0;
this.inputCounter = next;
},

@@ -92,12 +95,46 @@

deserializeCounts(this: DynamicTextJoinBlock, xmlElement: Element): void {
const itemCount = Math.max(
this.itemCount = Math.max(
parseInt(xmlElement.getAttribute('items') ?? '0', 10), this.minInputs);
// Two inputs are added automatically.
for (let i = this.minInputs; i < itemCount; i++) {
// minInputs are added automatically.
for (let i = this.minInputs; i < this.itemCount; i++) {
this.appendValueInput('ADD' + i);
}
this.inputCounter = itemCount;
},
/**
* Returns the state of this block as a JSON serializable object.
* @returns The state of this block, ie the item count.
*/
saveExtraState: function(this: DynamicTextJoinBlock): {itemCount: number} {
// If we call finalizeConnections here without disabling events, we get into
// an event loop.
Blockly.Events.disable();
this.finalizeConnections();
if (this instanceof Blockly.BlockSvg) this.initSvg();
Blockly.Events.enable();
return {
'itemCount': this.itemCount,
};
},
/**
* Applies the given state to this block.
* @param state The state to apply to this block, ie the item count.
*/
loadExtraState: function(
this: DynamicTextJoinBlock, state: ({[x: string]: any} | string)) {
if (typeof state === 'string') {
this.domToMutation(Blockly.utils.xml.textToDom(state));
return;
}
this.itemCount = state['itemCount'];
// minInputs are added automatically.
for (let i = this.minInputs; i < this.itemCount; i++) {
this.appendValueInput('ADD' + i);
}
},
/**
* Check whether a new input should be added and determine where it should go.

@@ -108,3 +145,3 @@ * @param connection The connection that has a pending connection.

*/
getIndexForNewInput(
findInputIndexForConnection(
this: DynamicTextJoinBlock,

@@ -150,7 +187,7 @@ connection: Blockly.Connection): number | null {

this: DynamicTextJoinBlock, connection: Blockly.Connection): void {
const insertIndex = this.getIndexForNewInput(connection);
const insertIndex = this.findInputIndexForConnection(connection);
if (insertIndex == null) {
return;
}
this.appendValueInput('ADD' + (this.inputCounter++));
this.appendValueInput(`ADD${Blockly.utils.idGenerator.genUid()}`);
this.moveNumberedInputBefore(this.inputList.length - 1, insertIndex);

@@ -164,25 +201,71 @@ },

finalizeConnections(this: DynamicTextJoinBlock): void {
if (this.inputList.length > this.minInputs) {
let toRemove: string[] = [];
this.inputList.forEach((input: Blockly.Input) => {
if (!input.connection?.targetConnection) {
toRemove.push(input.name);
}
});
const targetConns =
this.removeUnnecessaryEmptyConns(
this.inputList.map((i) => i.connection?.targetConnection));
this.tearDownBlock();
this.addItemInputs(targetConns);
this.itemCount = targetConns.length;
},
if (this.inputList.length - toRemove.length < this.minInputs) {
// Always show at least two inputs
toRemove = toRemove.slice(this.minInputs);
/** Deletes all inputs on this block so it can be rebuilt. */
tearDownBlock(this: DynamicTextJoinBlock): void {
for (let i = this.inputList.length - 1; i >= 0; i--) {
this.removeInput(this.inputList[i].name);
}
},
/**
* Filters the given target connections so that empty connections are removed,
* unless we need those to reach the minimum input count. Empty connections
* are removed starting at the end of the array.
* @param targetConns The list of connections associated with inputs.
* @returns A filtered list of connections (or null/undefined) which should
* be attached to inputs.
*/
removeUnnecessaryEmptyConns(
this: DynamicTextJoinBlock,
targetConns: Array<Blockly.Connection | undefined | null>
): Array<Blockly.Connection | undefined | null> {
const filteredConns = [...targetConns];
for (let i = filteredConns.length - 1; i >= 0; i--) {
if (!filteredConns[i] && filteredConns.length > this.minInputs) {
filteredConns.splice(i, 1);
}
toRemove.forEach((inputName) => this.removeInput(inputName));
// The first input should have the block text. If we removed the
// first input, add the block text to the new first input.
if (this.inputList[0].fieldRow.length == 0) {
this.inputList[0]
.appendField(Blockly.Msg['TEXT_JOIN_TITLE_CREATEWITH']);
}
}
return filteredConns;
},
/**
* Adds inputs based on the given array of target conns. An input is added for
* every entry in the array (if it does not already exist). If the entry is
* a connection and not null/undefined the connection will be connected to
* the input.
* @param targetConns The connections defining the inputs to add.
*/
addItemInputs(
this: DynamicTextJoinBlock,
targetConns: Array<Blockly.Connection | undefined | null>,
): void {
const input = this.addFirstInput();
const firstConn = targetConns[0];
if (firstConn) input.connection?.connect(firstConn);
for (let i = 1; i < targetConns.length; i++) {
const input = this.appendValueInput(`ADD${i}`);
const targetConn = targetConns[i];
if (targetConn) input.connection?.connect(targetConn);
}
},
/**
* Adds the top input with the label to this block.
* @returns The added input.
*/
addFirstInput(this: DynamicTextJoinBlock): Blockly.Input {
return this.appendValueInput('ADD0')
.appendField(Blockly.Msg['TEXT_JOIN_TITLE_CREATEWITH']);
},
};
Blockly.Blocks['dynamic_text_join'] = DYNAMIC_TEXT_JOIN_MIXIN;

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc