Spaces:
Runtime error
Runtime error
| /* eslint-disable no-undef */ | |
| const formatMessage = require('format-message'); | |
| const BlockType = require('../../extension-support/block-type'); | |
| const ArgumentType = require('../../extension-support/argument-type'); | |
| const Cast = require('../../util/cast'); | |
| const { | |
| validateJSON, | |
| validateArray, | |
| stringToEqivalint, | |
| valueToString, | |
| validateRegex | |
| } = require('../../util/json-block-utilities'); | |
| // const Cast = require('../../util/cast'); | |
| /** | |
| * Class for JSON blocks | |
| * @constructor | |
| */ | |
| class JgJSONBlocks { | |
| constructor (runtime) { | |
| /** | |
| * The runtime instantiating this block package. | |
| * @type {Runtime} | |
| */ | |
| this.runtime = runtime; | |
| } | |
| /** | |
| * @returns {object} metadata for this extension and its blocks. | |
| */ | |
| getInfo () { | |
| return { | |
| id: 'jgJSON', | |
| name: 'JSON', | |
| color1: '#0FBD8C', | |
| color2: '#0EAF82', | |
| blocks: [ | |
| { | |
| opcode: 'json_validate', | |
| blockType: BlockType.BOOLEAN, | |
| arguments: { | |
| json: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "{}" | |
| } | |
| }, | |
| text: 'is json [json] valid?' | |
| }, | |
| "---", | |
| { | |
| opcode: 'getValueFromJSON', | |
| text: formatMessage({ | |
| id: 'jgJSON.blocks.getValueFromJSON', | |
| default: 'get [VALUE] from [JSON]', | |
| description: 'Gets a value from a JSON object.' | |
| }), | |
| disableMonitor: true, | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| VALUE: { | |
| type: ArgumentType.STRING, | |
| defaultValue: formatMessage({ | |
| id: 'jgJSON.getValueFromJSON_value', | |
| default: 'key', | |
| description: 'The name of the item you want to get from the JSON.' | |
| }) | |
| }, | |
| JSON: { | |
| type: ArgumentType.STRING, | |
| defaultValue: '{"key": "value"}' | |
| } | |
| } | |
| }, | |
| { | |
| opcode: 'getTreeValueFromJSON', | |
| text: 'get path [VALUE] from [JSON]', | |
| disableMonitor: true, | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| VALUE: { | |
| type: ArgumentType.STRING, | |
| defaultValue: 'first/second' | |
| }, | |
| JSON: { | |
| type: ArgumentType.STRING, | |
| defaultValue: '{"first": {"second": 2, "third": 3}}' | |
| } | |
| } | |
| }, | |
| { | |
| opcode: 'setValueToKeyInJSON', | |
| text: formatMessage({ | |
| id: 'jgJSON.blocks.setValueToKeyInJSON', | |
| default: 'set [KEY] to [VALUE] in [JSON]', | |
| description: 'Returns the JSON with the key set to the value.' | |
| }), | |
| disableMonitor: true, | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| VALUE: { | |
| type: ArgumentType.STRING, | |
| defaultValue: formatMessage({ | |
| id: 'jgJSON.setValueToKeyInJSON_value', | |
| default: 'value', | |
| description: 'The value of the key you are setting.' | |
| }) | |
| }, | |
| KEY: { | |
| type: ArgumentType.STRING, | |
| defaultValue: formatMessage({ | |
| id: 'jgJSON.setValueToKeyInJSON_key', | |
| default: 'key', | |
| description: 'The key you are setting in the JSON.' | |
| }) | |
| }, | |
| JSON: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "{}" | |
| } | |
| } | |
| }, | |
| { | |
| opcode: 'json_delete', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| json: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "{}" | |
| }, | |
| key: { | |
| type: ArgumentType.STRING, | |
| defaultValue: formatMessage({ | |
| id: 'jgJSON.setValueToKeyInJSON_key', | |
| default: 'key', | |
| description: 'The key you are setting in the JSON.' | |
| }) | |
| } | |
| }, | |
| text: 'in json [json] delete key [key]' | |
| }, | |
| { | |
| opcode: 'json_values', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| json: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "{}" | |
| } | |
| }, | |
| text: 'get all values from json [json]' | |
| }, | |
| { | |
| opcode: 'json_keys', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| json: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "{}" | |
| } | |
| }, | |
| text: 'get all keys from json [json]' | |
| }, | |
| { | |
| opcode: 'json_has', | |
| blockType: BlockType.BOOLEAN, | |
| arguments: { | |
| json: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "{}" | |
| }, | |
| key: { | |
| type: ArgumentType.STRING, | |
| defaultValue: formatMessage({ | |
| id: 'jgJSON.setValueToKeyInJSON_key', | |
| default: 'key', | |
| description: 'The key you are setting in the JSON.' | |
| }) | |
| } | |
| }, | |
| text: 'json [json] has key [key] ?' | |
| }, | |
| { | |
| opcode: 'json_combine', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| one: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "{}" | |
| }, | |
| two: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "{}" | |
| } | |
| }, | |
| text: 'combine json [one] and json [two]' | |
| }, | |
| { | |
| blockType: BlockType.LABEL, | |
| text: "Arrays" | |
| }, | |
| { | |
| opcode: 'json_array_validate', | |
| blockType: BlockType.BOOLEAN, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[]" | |
| } | |
| }, | |
| text: 'is array [array] valid?' | |
| }, | |
| { | |
| opcode: 'json_array_split', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| text: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "A, B, C" | |
| }, | |
| delimeter: { | |
| type: ArgumentType.STRING, | |
| defaultValue: ', ' | |
| } | |
| }, | |
| text: 'create an array from text [text] with delimeter [delimeter]' | |
| }, | |
| { | |
| opcode: 'json_array_join', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| delimeter: { | |
| type: ArgumentType.STRING, | |
| defaultValue: ', ' | |
| } | |
| }, | |
| text: 'create text from array [array] with delimeter [delimeter]' | |
| }, | |
| "---", | |
| { | |
| opcode: 'json_array_push', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| item: { | |
| type: ArgumentType.STRING, | |
| defaultValue: formatMessage({ | |
| id: 'jgJSON.setValueToKeyInJSON_value', | |
| default: 'value', | |
| description: 'The value of the key you are setting.' | |
| }) | |
| } | |
| }, | |
| text: 'in array [array] add [item]' | |
| }, | |
| "---", | |
| { | |
| opcode: 'json_array_concatLayer1', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array1: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| array2: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"D\", \"E\", \"F\"]" | |
| } | |
| }, | |
| text: 'add items from array [array2] to array [array1]' | |
| }, | |
| { | |
| opcode: 'json_array_concatLayer2', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array1: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| array2: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"D\", \"E\", \"F\"]" | |
| }, | |
| array3: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"G\", \"H\", \"I\"]" | |
| } | |
| }, | |
| text: 'add items from array [array2] and array [array3] to array [array1]' | |
| }, | |
| "---", | |
| { | |
| opcode: 'json_array_delete', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| index: { | |
| type: ArgumentType.NUMBER, | |
| defaultValue: 2 | |
| } | |
| }, | |
| text: 'in array [array] delete [index]' | |
| }, | |
| { | |
| opcode: 'json_array_reverse', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| } | |
| }, | |
| text: 'reverse array [array]' | |
| }, | |
| { | |
| opcode: 'json_array_insert', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| index: { | |
| type: ArgumentType.NUMBER, | |
| defaultValue: 2 | |
| }, | |
| value: { | |
| type: ArgumentType.STRING, | |
| defaultValue: formatMessage({ | |
| id: 'jgJSON.setValueToKeyInJSON_value', | |
| default: 'value', | |
| description: 'The value of the key you are setting.' | |
| }) | |
| } | |
| }, | |
| text: 'in array [array] insert [value] at [index]' | |
| }, | |
| { | |
| opcode: 'json_array_set', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| index: { | |
| type: ArgumentType.NUMBER, | |
| defaultValue: 2 | |
| }, | |
| value: { | |
| type: ArgumentType.STRING, | |
| defaultValue: formatMessage({ | |
| id: 'jgJSON.setValueToKeyInJSON_value', | |
| default: 'value', | |
| description: 'The value of the key you are setting.' | |
| }) | |
| } | |
| }, | |
| text: 'in array [array] set [index] to [value]' | |
| }, | |
| "---", | |
| { | |
| opcode: 'json_array_get', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| index: { | |
| type: ArgumentType.NUMBER, | |
| defaultValue: 2 | |
| } | |
| }, | |
| text: 'in array [array] get [index]' | |
| }, | |
| { | |
| opcode: 'json_array_indexofNostart', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| value: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "value" | |
| } | |
| }, | |
| text: 'in array [array] get index of [value]' | |
| }, | |
| { | |
| opcode: 'json_array_indexof', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| number: { | |
| type: ArgumentType.NUMBER, | |
| defaultValue: 2 | |
| }, | |
| value: { | |
| type: ArgumentType.STRING, | |
| defaultValue: formatMessage({ | |
| id: 'jgJSON.setValueToKeyInJSON_value', | |
| default: 'value', | |
| description: 'The value of the key you are setting.' | |
| }) | |
| } | |
| }, | |
| text: 'in array [array] from [number] get index of [value]' | |
| }, | |
| { | |
| opcode: 'json_array_length', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| } | |
| }, | |
| text: 'length of array [array]' | |
| }, | |
| { | |
| opcode: 'json_array_contains', | |
| blockType: BlockType.BOOLEAN, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| value: { | |
| type: ArgumentType.STRING, | |
| defaultValue: formatMessage({ | |
| id: 'jgJSON.setValueToKeyInJSON_value', | |
| default: 'value', | |
| description: 'The value of the key you are setting.' | |
| }) | |
| } | |
| }, | |
| text: 'array [array] contains [value] ?' | |
| }, | |
| "---", | |
| { | |
| opcode: 'json_array_flat', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[[\"A\", \"B\"], [\"C\", \"D\"]]" | |
| }, | |
| layer: { | |
| type: ArgumentType.NUMBER, | |
| defaultValue: 1 | |
| } | |
| }, | |
| text: 'flatten nested array [array] by [layer] layers' | |
| }, | |
| "---", | |
| { | |
| opcode: 'json_array_getrange', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| }, | |
| index1: { | |
| type: ArgumentType.NUMBER, | |
| defaultValue: 2 | |
| }, | |
| index2: { | |
| type: ArgumentType.NUMBER, | |
| defaultValue: 2 | |
| } | |
| }, | |
| text: 'in array [array] get all items from [index1] to [index2]' | |
| }, | |
| "---", | |
| { | |
| opcode: 'json_array_isempty', | |
| blockType: BlockType.BOOLEAN, | |
| arguments: { | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| } | |
| }, | |
| text: 'is array [array] empty?' | |
| }, | |
| "---", | |
| { | |
| opcode: 'json_array_listtoarray', | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| list: { | |
| type: ArgumentType.STRING, | |
| defaultValue: 'select a list', | |
| menu: 'lists' | |
| } | |
| }, | |
| hideFromPalette: true, | |
| text: 'get contents of list [list] as array' | |
| }, | |
| { | |
| opcode: 'json_array_tolist', | |
| blockType: BlockType.COMMAND, | |
| arguments: { | |
| list: { | |
| type: ArgumentType.STRING, | |
| defaultValue: 'select a list', | |
| menu: 'lists' | |
| }, | |
| array: { | |
| type: ArgumentType.STRING, | |
| defaultValue: "[\"A\", \"B\", \"C\"]" | |
| } | |
| }, | |
| hideFromPalette: true, | |
| text: 'set contents of list [list] to contents of array [array]' | |
| } | |
| ], | |
| menus: { | |
| lists: 'getAllLists' | |
| } | |
| }; | |
| } | |
| getAllLists () { | |
| const variables = [].concat( | |
| Object.values(vm.runtime.getTargetForStage().variables), | |
| Object.values(vm.editingTarget.variables) | |
| ); | |
| const lists = variables.filter(i => i.type === 'list'); | |
| if (lists.length === 0) { | |
| return [ | |
| { | |
| text: 'select a list', | |
| value: 'select a list' | |
| } | |
| ]; | |
| } | |
| return lists.map(i => ({ | |
| text: i.name, | |
| value: JSON.stringify({ | |
| id: i.id, | |
| name: i.name | |
| }) | |
| })); | |
| } | |
| getValueFromJSON (args) { | |
| const key = args.VALUE; | |
| const json = validateJSON(args.JSON).object; | |
| return valueToString(json[key]); | |
| } | |
| getTreeValueFromJSON (args) { | |
| const tree = Cast.toString(args.VALUE); | |
| let _json; | |
| if (Cast.toString(args.JSON).startsWith('[')) { | |
| _json = validateArray(args.JSON).array; | |
| } else { | |
| _json = validateJSON(args.JSON).object; | |
| } | |
| const json = _json; | |
| if (!tree.includes('/')) { | |
| // if we dont have a slash, treat it like | |
| // the get value block | |
| if (Array.isArray(json)) { | |
| return this.json_array_get({ | |
| array: Cast.toString(args.JSON), | |
| index: Cast.toNumber(args.VALUE) | |
| }); | |
| } | |
| return this.getValueFromJSON(args); | |
| } | |
| let value = ''; | |
| let currentObject = json; | |
| const treeSplit = tree.split('/'); | |
| for (const key of treeSplit) { | |
| value = ''; | |
| // check for array so we can do "object/array/3/value" | |
| if (Array.isArray(currentObject)) { | |
| currentObject = currentObject[Cast.toNumber(key)]; | |
| value = currentObject; | |
| continue; | |
| } | |
| if (typeof currentObject === 'object') { | |
| currentObject = currentObject[key]; | |
| value = currentObject; | |
| } else { | |
| value = currentObject; | |
| } | |
| } | |
| if (typeof value === "undefined") return ''; | |
| return valueToString(value); | |
| } | |
| setValueToKeyInJSON (args) { | |
| const json = validateJSON(args.JSON).object; | |
| const key = args.KEY; | |
| const value = args.VALUE; | |
| json[key] = stringToEqivalint(value); | |
| return JSON.stringify(json); | |
| } | |
| json_has (args) { | |
| const json = validateJSON(args.json).object; | |
| const key = args.key; | |
| return json.hasOwnProperty(key); | |
| } | |
| json_delete (args) { | |
| const json = validateJSON(args.json).object; | |
| const key = args.key; | |
| if (!json.hasOwnProperty(key)) return JSON.stringify(json); | |
| delete json[key]; | |
| return JSON.stringify(json); | |
| } | |
| json_values (args) { | |
| const json = validateJSON(args.json).object; | |
| return JSON.stringify(Object.values(json)); | |
| } | |
| json_keys (args) { | |
| const json = validateJSON(args.json).object; | |
| return JSON.stringify(Object.keys(json)); | |
| } | |
| json_array_length (args) { | |
| const array = validateArray(args.array).array; | |
| return array.length; | |
| } | |
| json_array_isempty (args) { | |
| const array = validateArray(args.array).array; | |
| return !array.length; | |
| } | |
| json_array_contains (args) { | |
| const array = validateArray(args.array).array; | |
| const value = args.value; | |
| return array.includes(stringToEqivalint(value)); | |
| } | |
| json_array_reverse (args) { | |
| const array = validateArray(args.array).array; | |
| return JSON.stringify(array.reverse()); | |
| } | |
| json_array_indexof (args) { | |
| const array = validateArray(args.array).array; | |
| const number = args.number; | |
| const value = args.value; | |
| return array.indexOf(stringToEqivalint(value), number); | |
| } | |
| json_array_indexofNostart (args) { | |
| const array = validateArray(args.array).array; | |
| const value = args.value; | |
| return array.indexOf(stringToEqivalint(value)); | |
| } | |
| json_array_set (args) { | |
| const array = validateArray(args.array).array; | |
| const index = args.index; | |
| const value = args.value; | |
| array[index] = stringToEqivalint(value); | |
| return JSON.stringify(array); | |
| } | |
| json_array_insert (args) { | |
| const array = validateArray(args.array).array; | |
| const index = args.index; | |
| const value = args.value; | |
| array.splice(index, 0, stringToEqivalint(value)); | |
| return JSON.stringify(array); | |
| } | |
| json_array_get (args) { | |
| const array = validateArray(args.array).array; | |
| const index = args.index; | |
| return valueToString(array[index]); | |
| } | |
| json_array_getrange (args) { | |
| const array = validateArray(args.array).array; | |
| const index1 = args.index1; | |
| const index2 = args.index2; | |
| return JSON.stringify(array.slice(index1, index2)); | |
| } | |
| json_array_push (args) { | |
| const array = validateArray(args.array).array; | |
| const value = args.item; | |
| array.push(stringToEqivalint(value)); | |
| return JSON.stringify(array); | |
| } | |
| json_array_concatLayer1 (args) { | |
| const array1 = validateArray(args.array1).array; | |
| const array2 = validateArray(args.array2).array; | |
| const array = array1.concat(array2); | |
| return JSON.stringify(array); | |
| } | |
| json_array_concatLayer2 (args) { | |
| const array1 = validateArray(args.array1).array; | |
| const array2 = validateArray(args.array2).array; | |
| const array3 = validateArray(args.array3).array; | |
| const array = array1.concat(array2, array3); | |
| return JSON.stringify(array); | |
| } | |
| json_array_flat (args) { | |
| const array = validateArray(args.array).array; | |
| const depth = Cast.toNumber(args.layer); | |
| const flattened = array.flat(depth); | |
| return JSON.stringify(flattened); | |
| } | |
| json_array_tolist (args, util) { | |
| let list; | |
| try { | |
| list = JSON.parse(args.list); | |
| } catch { | |
| return; | |
| } | |
| const array = validateArray(args.array).array; | |
| const content = util.target.lookupOrCreateList(list.id, list.name); | |
| content.value = array.map(x => valueToString(x)); | |
| } | |
| json_array_listtoarray (args, util) { | |
| let list; | |
| try { | |
| list = JSON.parse(args.list); | |
| } catch { | |
| return; | |
| } | |
| const content = util.target.lookupOrCreateList(list.id, list.name).value; | |
| return JSON.stringify(content.map(x => stringToEqivalint(x))); | |
| } | |
| json_array_delete (args) { | |
| const array = validateArray(args.array).array; | |
| const index = args.index; | |
| array.splice(index, 1); | |
| return JSON.stringify(array); | |
| } | |
| json_array_split (args) { | |
| return JSON.stringify(args.text.split(args.delimeter)); | |
| } | |
| json_array_join (args) { | |
| return validateArray(args.array).array.join(args.delimeter); | |
| } | |
| json_validate (args) { | |
| return validateJSON(args.json).isValid; | |
| } | |
| json_array_validate (args) { | |
| return validateArray(args.array).isValid; | |
| } | |
| json_combine (args) { | |
| const one = validateJSON(args.one).object; | |
| const two = validateJSON(args.two).object; | |
| return JSON.stringify(Object.assign(one, two)); | |
| } | |
| } | |
| module.exports = JgJSONBlocks; | |