From 6fe5b85f8ce201d618a9c7c175d7502c2ff8c395 Mon Sep 17 00:00:00 2001 From: Florrie Date: Fri, 20 Dec 2019 17:46:21 -0400 Subject: begin the site! --- index.js | 445 --------------------------------------------------------------- 1 file changed, 445 deletions(-) delete mode 100644 index.js (limited to 'index.js') diff --git a/index.js b/index.js deleted file mode 100644 index b62db99..0000000 --- a/index.js +++ /dev/null @@ -1,445 +0,0 @@ -'use strict'; - -const { Project } = require('./sb-edit'); -const fs = require('fs'); -const path = require('path'); -const util = require('util'); - -const readFile = util.promisify(fs.readFile); - -// TODO: set prefix to \t -function indent(string, prefix = ' ') { - return string.split('\n').map(l => prefix + l).join('\n'); -} - -function input(inp, target, flag = false) { - if (!inp) { - return ''; - } - switch (inp.type) { - case 'number': - case 'angle': - return `(${inp.value})`; - - case 'string': - return `[${inp.value}]`; - - case 'variable': - case 'list': - case 'graphicEffect': - case 'rotationStyle': - case 'greaterThanMenu': - case 'stopMenu': - case 'dragModeMenu': - case 'propertyOfMenu': - case 'currentMenu': - case 'mathopMenu': - case 'frontBackMenu': - case 'forwardBackwardMenu': - case 'costumeNumberName': - return `[${inp.value} v]`; - - case 'costume': - case 'sound': - case 'goToTarget': - case 'pointTowardsTarget': - case 'penColorParam': - case 'target': - case 'cloneTarget': - case 'touchingTarget': - case 'distanceToMenu': - return `(${inp.value} v)`; - - case 'broadcast': - case 'backdrop': - case 'key': - if (flag) { - return `[${inp.value} v]`; - } else { - return `(${inp.value} v)`; - } - - case 'color': - const hex = k => inp.value[k].toString(16).padStart(2, '0') - return `[#${hex('r') + hex('g') + hex('b')}]`; - - case 'block': - if (flag) { - return '\n' + indent(blockToScratchblocks(inp.value, target)) + '\n'; - } else { - return blockToScratchblocks(inp.value, target); - } - - case 'blocks': - return '\n' + indent(blocksToScratchblocks(inp.value, target)) + '\n'; - - default: - return `\x1b[33m<${inp.type}>\x1b[0m`; - } -} - -function blockToScratchblocks(block, target) { - if (!target) { - throw new Error('expected target'); - } - - const i = (key, ...args) => input(block.inputs[key], target, ...args); - const operator = op => `(${i('NUM1')} ${op} ${i('NUM2')})`; - const boolop = op => `<${i('OPERAND1')} ${op} ${i('OPERAND2')}>`; - - switch (block.opcode) { - - // motion ------------------------------------------------------ // - case 'motion_movesteps': - return `move ${i('STEPS')} steps`; - case 'motion_turnright': - return `turn cw ${i('DEGREES')} degrees`; - case 'motion_turnleft': - return `turn ccw ${i('DEGREES')} degrees`; - case 'motion_goto': - return `go to ${i('TO')}`; - case 'motion_gotoxy': - return `go to x: ${i('X')} y: ${i('Y')}`; - case `motion_glideto`: - return `glide ${i('SECS')} secs to ${i('TO')}`; - case `motion_glidesecstoxy`: - return `glide ${i('SECS')} secs to x: ${i('X')} y: ${i('Y')}`; - case 'motion_pointindirection': - return `point in direction ${i('DIRECTION')}`; - case 'motion_pointtowards': - return `point towards ${i('TOWARDS')}`; - case 'motion_changexby': - return `change x by ${i('DX')}`; - case 'motion_setx': - return `set x to ${i('X')}`; - case 'motion_changeyby': - return `change y by ${i('DY')}`; - case 'motion_sety': - return `set y to ${i('Y')}`; - case 'motion_ifonedgebounce': - return 'if on edge, bounce'; - case 'motion_setrotationstyle': - return `set rotation style ${i('STYLE')}`; - case 'motion_xposition': - return '(x position)'; - case 'motion_yposition': - return '(y position)'; - case 'motion_direction': - return '(direction)'; - - // looks ------------------------------------------------------- // - case 'looks_sayforsecs': - return `say ${i('MESSAGE')} for ${i('SECS')} seconds`; - case 'looks_say': - return `say ${i('MESSAGE')}`; - case 'looks_thinkforsecs': - return `think ${i('MESSAGE')} for ${i('SECS')} seconds`; - case 'looks_think': - return `think ${i('MESSAGE')}`; - case 'looks_switchcostumeto': - return `switch costume to ${i('COSTUME')}`; - case 'looks_nextcostume': - return 'next costume'; - case 'looks_switchbackdropto': - return `switch backdrop to ${i('BACKDROP')}`; - case 'looks_nextbackdrop': - return `next backdrop`; - case 'looks_changesizeby': - return `change size by ${i('CHANGE')}`; - case 'looks_setsizeto': - return `set size to ${i('SIZE')}%`; - case 'looks_changeeffectby': - return `change ${i('EFFECT')} effect by ${i('CHANGE')} :: looks`; - case 'looks_seteffectto': - return `set ${i('EFFECT')} effect to ${i('VALUE')} :: looks`; - case 'looks_cleargraphiceffects': - return 'clear graphic effects'; - case 'looks_show': - return 'show'; - case 'looks_hide': - return 'hide'; - case 'looks_gotofrontback': - return `go to ${i('FRONT_BACK')} layer`; - case 'looks_goforwardbackwardlayers': - return `go ${i('FORWARD_BACKWARD')} ${i('NUM')} layers`; - case 'looks_costumenumbername': - return `(costume ${i('NUMBER_NAME')})`; - case 'looks_backdropnumbername': - return `(backdrop ${i('NUMBER_NAME')})`; - case 'looks_size': - return '(size)'; - case 'looks_hideallsprites': - return 'hide all sprites :: looks'; - case 'looks_switchbackdroptoandwait': - return `switch backdrop to ${i('BACKDROP')} and wait`; - case 'looks_changestretchby': - return `change stretch by ${i('CHANGE')} :: looks`; - case 'looks_setstretchto': - return `set stretch to ${i('STRETCH')} % :: looks`; - - // sound ------------------------------------------------------- // - case 'sound_playuntildone': - return `play sound ${i('SOUND_MENU')} until done`; - case 'sound_play': - return `start sound ${i('SOUND_MENU')}`; - case 'sound_stopallsounds': - return 'stop all sounds'; - case 'sound_changeeffectby': - return `change ${i('EFFECT')} effect by ${i('VALUE')} :: sound`; - case 'sound_seteffectto': - return `set ${i('EFFECT')} effect to ${i('VALUE')} :: sound`; - case 'sound_cleareffects': - return 'clear sound effects'; - case 'sound_changevolumeby': - return `change volume by ${i('VOLUME')}`; - case 'sound_setvolumeto': - return `set volume to ${i('VOLUME')} %`; - case 'sound_volume': - return '(volume)'; - - // events ------------------------------------------------------ // - case 'event_whenflagclicked': - return 'when green flag clicked'; - case 'event_whenkeypressed': - return `when ${i('KEY_OPTION', true)} key pressed`; - case 'event_whenthisspriteclicked': - return 'when this sprite clicked'; - case 'event_whenbackdropswitchesto': - return `when backdrop switches to ${i('BACKDROP', true)}`; - case 'event_whengreaterthan': - return `when ${i('WHENGREATERTHANMENU')} > ${i('VALUE')}`; - case 'event_whenbroadcastreceived': - return `when I receive ${i('BROADCAST_OPTION', true)}`; - case 'event_broadcast': - return `broadcast ${i('BROADCAST_INPUT')}`; - case 'event_broadcastandwait': - return `broadcast ${i('BROADCAST_INPUT')} and wait`; - - // control ----------------------------------------------------- // - case 'control_wait': - return `wait ${i('DURATION')} seconds`; - case 'control_repeat': - return `repeat ${i('TIMES')}` + i('SUBSTACK', true) + 'end'; - case 'control_forever': - return 'forever' + i('SUBSTACK', true) + 'end'; - case 'control_if': - return `if ${i('CONDITION') || '<>'} then` + i('SUBSTACK', true) + 'end'; - case 'control_if_else': - return `if ${i('CONDITION') || '<>'} then` + i('SUBSTACK', true) + 'else' + i('SUBSTACK2', true) + 'end'; - case 'control_wait_until': - return `wait until ${i('CONDITION') || '<>'}`; - case 'control_repeat_until': - return `repeat until ${i('CONDITION') || '<>'}` + i('SUBSTACK', true) + 'end'; - case 'control_stop': - return `stop ${i('STOP_OPTION')}`; - case 'control_start_as_clone': - return 'when I start as a clone'; - case 'control_create_clone_of': - return `create clone of ${i('CLONE_OPTION')}`; - case 'control_delete_this_clone': - return 'delete this clone'; - - // sensing ----------------------------------------------------- // - case 'sensing_touchingobject': - return ``; - case 'sensing_touchingcolor': - return ``; - case 'sensing_coloristouchingcolor': - return `<${i('COLOR')} is touching ${i('COLOR2')} ?>`; - case 'sensing_distanceto': - return `(distance to ${i('DISTANCETOMENU')})`; - case 'sensing_askandwait': - return `ask ${i('QUESTION')} and wait`; - case 'sensing_answer': - return '(answer)'; - case 'sensing_keypressed': - return ``; - case 'sensing_mousedown': - return ''; - case 'sensing_mousex': - return '(mouse x)'; - case 'sensing_mousey': - return '(mouse y)'; - case 'sensing_setdragmode': - return `set drag mode ${i('DRAG_MODE')}`; - case 'sensing_loudness': - return '(loudness)'; - case 'sensing_loud': - return ''; - case 'sensing_timer': - return '(timer)'; - case 'sensing_resettimer': - return 'reset timer'; - case 'sensing_of': - return `(${i('PROPERTY')} of ${i('OBJECT')})`; - case 'sensing_current': - return `(current ${i('CURRENTMENU')})`; - case 'sensing_dayssince2000': - return '(days since 2000)'; - case 'sensing_username': - return '(username)'; - case 'sensing_userid': - return '(user id :: sensing)'; - - // operators --------------------------------------------------- // - case 'operator_add': - return operator('+'); - case 'operator_subtract': - return operator('-'); - case 'operator_multiply': - return operator('*'); - case 'operator_divide': - return operator('/'); - case 'operator_random': - return `(pick random ${i('FROM')} to ${i('TO')})`; - case 'operator_gt': - return boolop('>'); - case 'operator_lt': - return boolop('<'); - case 'operator_equals': - return boolop('='); - case 'operator_and': - return boolop('and'); - case 'operator_or': - return boolop('or'); - case 'operator_not': - return ``; - case 'operator_join': - return `(join ${i('STRING1')} ${i('STRING2')})`; - case 'operator_letter_of': - return `(letter ${i('LETTER')} of ${i('STRING')}`; - case 'operator_length': - return `(length of ${i('STRING')}`; - case 'operator_contains': - return `<${i('STRING1')} contains ${i('STRING2')} ? :: operators>`; - case 'operator_mod': - return operator('mod'); - case 'operator_round': - return `(round ${i('NUM')})`; - case 'operator_mathop': - return `(${i('OPERATOR')} of ${i('NUM')})`; - - // data -------------------------------------------------------- // - case 'data_variable': - return `(${block.inputs.VARIABLE.value} :: variables)`; - case 'data_setvariableto': - return `set ${i('VARIABLE')} to ${i('VALUE')}`; - case 'data_changevariableby': - return `change ${i('VARIABLE')} by ${i('VALUE')}`; - case 'data_showvariable': - return `show variable ${i('VARIABLE')}`; - case 'data_hidevariable': - return `hide variable ${i('VARIABLE')}`; - case 'data_listcontents': - return `(${block.inputs.LIST.value} :: list)`; - case 'data_addtolist': - return `add ${i('ITEM')} to ${i('LIST')}`; - case 'data_deleteoflist': - return `delete ${i('INDEX')} of ${i('LIST')}`; - case 'data_deletealloflist': - return `delete all of ${i('LIST')}`; - case 'data_insertatlist': - return `insert ${i('ITEM')} at ${i('INDEX')} of ${i('LIST')}`; - case 'data_replaceitemoflist': - return `replace item ${i('INDEX')} of ${i('LIST')} with ${i('ITEM')}`; - case 'data_itemoflist': - return `(item ${i('INDEX')} of ${i('LIST')})`; - case 'data_itemnumoflist': - return `(item # of ${i('ITEM')} in ${i('LIST')})`; - case 'data_lengthoflist': - return `(length of ${i('LIST')})`; - case 'data_listcontainsitem': - return `<${i('LIST')} contains ${i('ITEM')} ? :: list>`; - case 'data_showlist': - return `show list ${i('LIST')}`; - case 'data_hidelist': - return `hide list ${i('LIST')}`; - - // custom blocks ----------------------------------------------- // - case 'procedures_definition': - const spec = block.inputs.ARGUMENTS.value.map(({ type, name }) => { - switch (type) { - case 'label': - return name.replace(/\//g, '\\/'); - case 'numberOrString': - return `(${name})`; - case 'boolean': - return `<${name}>`; - } - }).join(' '); - return `define ${spec}` + (block.inputs.WARP.value ? ' // run without screen fresh' : ''); - case 'procedures_call': - const definition = target.scripts.map(s => s.blocks[0]).find(b => b.opcode === 'procedures_definition' && b.inputs.PROCCODE.value === block.inputs.PROCCODE.value); - if (definition) { - let index = 0; - return definition.inputs.ARGUMENTS.value.map(({ type, name }) => { - switch (type) { - case 'label': - return name.replace(/\//g, '\\/'); - default: - // TODO: deal with empty boolean inputs, which can't even load yet - return input(block.inputs.INPUTS.value[index++], target); - } - }).join(' ') + ' :: custom'; - } else { - return `... // missing custom block definition for ${block.inputs.PROCCODE.value}`; - } - case 'argument_reporter_string_number': - return `(${block.inputs.VALUE.value} :: custom-arg)`; - case 'argument_reporter_boolean': - return `<${block.inputs.VALUE.value} :: custom-arg>`; - - // extension: pen ---------------------------------------------- // - case 'pen_clear': - return 'erase all'; - case 'pen_stamp': - return 'stamp'; - case 'pen_penDown': - return 'pen down'; - case 'pen_penUp': - return 'pen up'; - case 'pen_setPenColorToColor': - return `set pen color to ${i('COLOR')}`; - case 'pen_changePenColorParamBy': - return `change pen ${i('COLOR_PARAM')} by ${i('VALUE')}`; - case 'pen_setPenColorParamTo': - return `set pen ${i('COLOR_PARAM')} to ${i('VALUE')}`; - case 'pen_changePenSizeBy': - return `change pen size by ${i('SIZE')}`; - case 'pen_setPenSizeTo': - return `set pen size to ${i('SIZE')}`; - case 'pen_changePenShadeBy': - return `change pen shade by ${i('SHADE')}`; - case 'pen_setPenShadeToNumber': - return `set pen shade to ${i('SHADE')}`; - case 'pen_changePenHueBy': - return `change pen color by ${i('HUE')}`; - case 'pen_setPenHueTo': - return `set pen hue to ${i('HUE')}`; - - default: - return `\x1b[33m${block.opcode} (${Object.keys(block.inputs).join(', ')})\x1b[0m`; - - } -} - -function blocksToScratchblocks(blocks, target) { - return blocks.map(b => blockToScratchblocks(b, target)).join('\n'); -} - -function scriptToScratchblocks(script, target) { - return blocksToScratchblocks(script.blocks, target); -} - -async function main() { - const sb3 = process.argv[2]; - if (!sb3) { - console.error('Please pass an sb3 file.'); - process.exit(1); - } - const file = await readFile(sb3); - const project = await Project.fromSb3(file); - console.log(scriptToScratchblocks(project.sprites[1].scripts[0], project.sprites[1])); -} - -main().catch(err => console.error(err)); -- cgit 1.3.0-6-gf8a5