From 900c98f9058eefe993f4a08f012fe0999fee8217 Mon Sep 17 00:00:00 2001 From: Bernhard Prattes Date: Fri, 15 May 2020 20:24:22 +0200 Subject: [PATCH 001/124] BLOCKS-84 implement brick support checker in python using docker [BP] --- .../workflows/interval_brickcheck_action.yaml | 18 +++ brick-support-checker-action/Dockerfile | 41 ++++++ brick-support-checker-action/action.yml | 11 ++ brick-support-checker-action/entrypoint.sh | 17 +++ .../require/checker.py | 136 ++++++++++++++++++ 5 files changed, 223 insertions(+) create mode 100644 .github/workflows/interval_brickcheck_action.yaml create mode 100644 brick-support-checker-action/Dockerfile create mode 100644 brick-support-checker-action/action.yml create mode 100755 brick-support-checker-action/entrypoint.sh create mode 100644 brick-support-checker-action/require/checker.py diff --git a/.github/workflows/interval_brickcheck_action.yaml b/.github/workflows/interval_brickcheck_action.yaml new file mode 100644 index 00000000..266802d7 --- /dev/null +++ b/.github/workflows/interval_brickcheck_action.yaml @@ -0,0 +1,18 @@ +name: Interval Action for Brick Support Check + +on: + schedule: + - cron: '0 7 * * 1' # Mondays 7AM UTC + +jobs: + runDocker: + if: github.repository == 'Catrobat/Catblocks' + name: checkout repo and check supported bricks + runs-on: ubuntu-latest + steps: + - name: checkout repo + uses: actions/checkout@v2 + - name: run checker for brick support + uses: ./brick-support-checker-action/ + with: + slack_webhook: ${{ secrets.SLACK_WEBHOOK_URL }} \ No newline at end of file diff --git a/brick-support-checker-action/Dockerfile b/brick-support-checker-action/Dockerfile new file mode 100644 index 00000000..2a50d657 --- /dev/null +++ b/brick-support-checker-action/Dockerfile @@ -0,0 +1,41 @@ +FROM alpine + +MAINTAINER Catblocks "https://github.com/Catrobat/Catblocks" + +ARG CATBLOCKSREPO="https://github.com/Catrobat/Catblocks.git" +ARG CATROIDREPO="https://github.com/Catrobat/Catroid.git" +ARG WORKDIR="/checker/" + +# enable new repositories +RUN \ + echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \ + && echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \ + && echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories + +# update and upgrade +RUN apk --no-cache update \ + && apk --no-cache upgrade + +# install build dependencies +RUN apk add --no-cache --virtual .build-deps python3 py3-pip + +RUN apk add --no-cache --virtual udev git + +# install required python packages +RUN pip3 install --upgrade pip +RUN pip3 install requests + +# remove cache +RUN rm -rf /var/cache/apk/* /tmp/* + +ENV CATBLOCKS=${CATBLOCKSREPO} +ENV CATROID=${CATROIDREPO} +ENV WORKDIR=${WORKDIR} + +# copy python script to docker +COPY require/checker.py /checker.py + +# cmd +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] diff --git a/brick-support-checker-action/action.yml b/brick-support-checker-action/action.yml new file mode 100644 index 00000000..b76c894c --- /dev/null +++ b/brick-support-checker-action/action.yml @@ -0,0 +1,11 @@ +name: "Catroid Brick Support Checker Action" +description: "Compares Catroid bricks with Catblocks bricks and sends the new bricks to Slack" +inputs: + slack_webhook: + description: 'Webhook to post on in #catblocks Slack channel' + required: true +runs: + using: 'docker' + image: 'Dockerfile' + args: + - ${{ inputs.slack_webhook }} \ No newline at end of file diff --git a/brick-support-checker-action/entrypoint.sh b/brick-support-checker-action/entrypoint.sh new file mode 100755 index 00000000..d590e1f0 --- /dev/null +++ b/brick-support-checker-action/entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# +: ' +Catrobat Brick Support Checker Action +' + +# Create directory where the Catroid and Catblocks projects should be cloned to +mkdir $WORKDIR && cd $WORKDIR + +git clone $CATBLOCKS +git clone $CATROID + +# copy the json-files to the working directory +cp -r Catblocks/src/js/blocks/categories categories + +# run checker & send report +python3 /checker.py "$WORKDIR" "$1" \ No newline at end of file diff --git a/brick-support-checker-action/require/checker.py b/brick-support-checker-action/require/checker.py new file mode 100644 index 00000000..12b7c7b4 --- /dev/null +++ b/brick-support-checker-action/require/checker.py @@ -0,0 +1,136 @@ +# This script automatically compares supported Catroid and Catblocks bricks and sends the report with a given slack webhook. +# Required Parameters: Working Directory of Catblocks & Catroid Project and a Slack Webhook. + +import json +import os +import sys +import requests + +# if some files should be excluded for the checks, add them here +excluded_js_files = ['index.js'] +excluded_java_files = ['Brick.java', 'BrickBaseType.java', 'BroadcastMessageBrick.java', 'CompositeBrick.java', 'ScriptBrick.java', + 'UserVariableBrickInterface.java', 'BrickSpinner.java', 'FormulaBrick.java', 'ScriptBrickBaseType.java', 'UserListBrick.java', + 'UserVariableBrick.java', 'UserVariableBrickWithFormula.java', 'VisualPlacementBrick.java'] +excluded_js_bricks = ['WhenClonedScript', 'StartScript', 'WhenScript', 'WhenTouchDownScript', 'BroadcastScript', 'WhenConditionScript', + 'WhenBounceOffScript', 'WhenBackgroundChangesScript'] + + +# Loads the bricks supported by Catblocks from the JSON data. +def loadCatblocksBricks(base_dir): + path = base_dir + '/categories/' + files = os.listdir(path) + + js_bricks = [] + + for filename in files: + if filename in excluded_js_files: + continue + + filename = path + filename + f = open(filename, 'r') + content = f.read() + json_str = content[content.find('{'):content.rfind(';')].replace('`', '"') + #print(json_str) + parsed_json = json.loads(json_str) + + for brick_name in parsed_json: + if brick_name in excluded_js_bricks: + continue + + js_bricks.append(brick_name) + + return js_bricks + + +# Loads the bricks supported by Catroid by searching in the bricks-folder of Catroid. +# Each .java-file is one brick. +def loadCatroidBricks(base_dir): + path = base_dir + '/Catroid/catroid/src/main/java/org/catrobat/catroid/content/bricks/' + files = os.listdir(path) + + java_bricks = [] + + for filename in files: + if not filename.endswith('.java') or filename in excluded_java_files: + continue + java_bricks.append(filename.replace('.java', '')) + + return java_bricks + + +# Compares the two arrays +def compareBricks(java_bricks, js_bricks): + in_js_not_java = [] + in_java_not_js = [] + + for java_brick in java_bricks: + if java_brick not in js_bricks: + in_java_not_js.append(java_brick) + + for js_brick in js_bricks: + if js_brick not in java_bricks: + in_js_not_java.append(js_brick) + + return in_java_not_js, in_js_not_java + + +# Builds the report for the missing bricks +def generateSlackMessage(missing_bricks, categories): + msg = '*Missing Bricks in Catblocks*:\n' + for brick in missing_bricks: + category = getCategoryForJavaBrick(brick, categories) + if category is not None: + msg += brick + ' [' + category + ']\n' + else: + msg += brick + '\n' + return msg.strip() + + +# Loads the .java-file where bricks are but in categories. +# First the import-statements are removed +def loadJavaCategoryClass(base_dir): + path = base_dir + '/Catroid/catroid/src/main/java/org/catrobat/catroid/ui/fragment/CategoryBricksFactory.java' + f = open(path, 'r') + content = f.read() + content = content[content.find("public class"):] + return content + + +# Searches the CategoryBricksFactory for the line where the brick is put in the +# category list +def getCategoryForJavaBrick(blockname, category_class): + for line in category_class: + if blockname in line: + if '.add' in line: + try: + return line.split('.')[0].replace('List', '').strip() + except: + return None + return None + + +def sendSlackMessage(webhook, message): + json_data = { 'text': message } + requests.post(webhook, json=json_data) + + +# Requires the following Args: +# [1] Path to the parent folder of Catblocks & Catroid project +# [2] Slack Webhook URL +def main(): + path = sys.argv[1] + slack_webhook = sys.argv[2] + + java_bricks = loadCatroidBricks(path) + js_bricks = loadCatblocksBricks(path) + + in_java_not_js, in_js_not_java = compareBricks(java_bricks, js_bricks) + + if in_java_not_js is not None and len(in_java_not_js) > 0: + category_class = loadJavaCategoryClass(path).splitlines() + slack_msg = generateSlackMessage(in_java_not_js, category_class) + sendSlackMessage(slack_webhook, slack_msg) + + +if __name__ == '__main__': + main() \ No newline at end of file From 45780dff4a131d237dc1c1f18b31e4bddd204935 Mon Sep 17 00:00:00 2001 From: Patrick Lovric Date: Thu, 28 May 2020 17:01:41 +0200 Subject: [PATCH 002/124] BLOCKS-109: fixed tests - changed from "!= undefined" to "!= null" --- test/jsunit/share/share.test.js | 124 ++++++++++++++++---------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/test/jsunit/share/share.test.js b/test/jsunit/share/share.test.js index 6e92a8c0..4c4aea3b 100644 --- a/test/jsunit/share/share.test.js +++ b/test/jsunit/share/share.test.js @@ -23,12 +23,12 @@ describe('Share basic tests', () => { return (accordionContainer.id === 'sceneID-accordionObjects' && sceneContainer.id === 'sceneID' - && sceneContainer.querySelector('#sceneID-header') !== undefined + && sceneContainer.querySelector('#sceneID-header') !== null && sceneContainer.querySelector('#sceneID-header').innerText.startsWith('Name of the scene') && sceneContainer.querySelector('#sceneID-header').getAttribute('data-target') === '#sceneID-collapseOne' && sceneContainer.getAttribute('class') === 'catblocks-scene card' - && sceneContainer.querySelector('.catblocks-object-container') !== undefined + && sceneContainer.querySelector('.catblocks-object-container') !== null && sceneObjContainer.getAttribute('data-parent') === '#accordionID'); })).toBeTruthy(); }); @@ -44,20 +44,20 @@ describe('Share basic tests', () => { return (objectCard.id === 'tobject' && objectCard.getAttribute('class') === 'catblocks-object card' - && container.querySelector('#tobject-header') !== undefined + && container.querySelector('#tobject-header') !== null && container.querySelector('#tobject-header').innerText.startsWith('objectName') - && container.querySelector('#tobject-collapseOneScene') !== undefined + && container.querySelector('#tobject-collapseOneScene') !== null && container.querySelector('#tobject-collapseOneScene').getAttribute('data-parent') === '#sceneID-accordionObjects' - && container.querySelector('.tab-content') !== undefined - && container.querySelector('#tobject-tabs') !== undefined + && container.querySelector('.tab-content') !== null + && container.querySelector('#tobject-tabs') !== null - && container.querySelector('#tobject-scripts-tab') !== undefined - && container.querySelector('#tobject-looks-tab') !== undefined - && container.querySelector('#tobject-sounds-tab') !== undefined - && container.querySelector(container.querySelector('#tobject-scripts-tab').getAttribute('href')) !== undefined - && container.querySelector(container.querySelector('#tobject-looks-tab').getAttribute('href')) !== undefined - && container.querySelector(container.querySelector('#tobject-sounds-tab').getAttribute('href')) !== undefined); + && container.querySelector('#tobject-scripts-tab') !== null + && container.querySelector('#tobject-looks-tab') !== null + && container.querySelector('#tobject-sounds-tab') !== null + && container.querySelector(container.querySelector('#tobject-scripts-tab').getAttribute('href')) !== null + && container.querySelector(container.querySelector('#tobject-looks-tab').getAttribute('href')) !== null + && container.querySelector(container.querySelector('#tobject-sounds-tab').getAttribute('href')) !== null); })).toBeTruthy(); }); }); @@ -109,11 +109,11 @@ describe('Share catroid program rendering tests', () => { share.renderProgramJSON('programID', shareTestContainer, catObj, catXml); - return (shareTestContainer.querySelector('.catblocks-scene') !== undefined + return (shareTestContainer.querySelector('.catblocks-scene') !== null && shareTestContainer.querySelector('.catblocks-scene-header').innerHTML.length > 0 - && shareTestContainer.querySelector('.catblocks-object-container') !== undefined - && shareTestContainer.querySelector('.accordion') !== undefined - && shareTestContainer.querySelector('.catblocks-object .card-header') !== undefined + && shareTestContainer.querySelector('.catblocks-object-container') !== null + && shareTestContainer.querySelector('.accordion') !== null + && shareTestContainer.querySelector('.catblocks-object .card-header') !== null && shareTestContainer.querySelector('.catblocks-object .card-header').innerHTML.startsWith('No objects found')); })).toBeTruthy(); }); @@ -132,10 +132,10 @@ describe('Share catroid program rendering tests', () => { share.renderProgramJSON('programID', shareTestContainer, catObj, catXml); - return (shareTestContainer.querySelector('.catblocks-scene') !== undefined + return (shareTestContainer.querySelector('.catblocks-scene') !== null && shareTestContainer.querySelector('.catblocks-scene-header').innerHTML.length > 0 - && shareTestContainer.querySelector('.catblocks-object-container') !== undefined - && shareTestContainer.querySelector('.accordion') !== undefined + && shareTestContainer.querySelector('.catblocks-object-container') !== null + && shareTestContainer.querySelector('.accordion') !== null && shareTestContainer.getElementsByClassName('catblocks-object').length === 2 && shareTestContainer.querySelector('.catblocks-object .card-header').innerHTML.startsWith('No objects found')); })).toBeTruthy(); @@ -149,17 +149,17 @@ describe('Share catroid program rendering tests', () => { scenes: [{ name: 'tscene', objectList: [{ - name: 'toobject' + name: 'tobject' }] }] }; share.renderProgramJSON('programID', shareTestContainer, catObj, catXml); - return (shareTestContainer.querySelector('.catblocks-object .card-header') !== undefined - && shareTestContainer.querySelector('.catblocks-object .card-header').innerHTML.startsWith('
toobject
') - && shareTestContainer.querySelector('.tab-pane') !== undefined - && shareTestContainer.querySelector('.catblocks-script') !== undefined); + return (shareTestContainer.querySelector('.catblocks-object .card-header') !== null + && shareTestContainer.querySelector('.catblocks-object .card-header').innerHTML.startsWith('
tobject
') + && shareTestContainer.querySelector('.tab-pane') !== null + && shareTestContainer.querySelector('.catblocks-script') === null); })).toBeTruthy(); }); @@ -181,17 +181,17 @@ describe('Share catroid program rendering tests', () => { share.renderProgramJSON('programID', shareTestContainer, catObj, catXml); const sceneID = shareUtils.generateID('programID-tscene'); - const obj1ID = shareUtils.generateID('programID-tscene-toobject1'); - const obj2ID = shareUtils.generateID('programID-tscene-toobject2'); - - return (shareTestContainer.querySelector('#'+shareUtils.generateID('programID')) !== undefined - && shareTestContainer.querySelector('#'+sceneID) !== undefined - && shareTestContainer.querySelector('#'+obj1ID+'-scripts-tab') !== undefined - && shareTestContainer.querySelector('#'+obj1ID+'-looks') !== undefined - && shareTestContainer.querySelector('#'+obj1ID+'-sounds .catblocks-empty-text') !== undefined - && shareTestContainer.querySelector('#'+obj2ID+'-scripts-tab') !== undefined - && shareTestContainer.querySelector('#'+obj2ID+'-looks') !== undefined - && shareTestContainer.querySelector('#'+obj2ID+'-sounds .catblocks-empty-text') !== undefined); + const obj1ID = shareUtils.generateID('programID-tscene-tobject1'); + const obj2ID = shareUtils.generateID('programID-tscene-tobject2'); + + return (shareTestContainer.querySelector('#'+shareUtils.generateID('programID')) !== null + && shareTestContainer.querySelector('#'+sceneID) !== null + && shareTestContainer.querySelector('#'+obj1ID+'-scripts-tab') !== null + && shareTestContainer.querySelector('#'+obj1ID+'-looks') !== null + && shareTestContainer.querySelector('#'+obj1ID+'-sounds .catblocks-empty-text') !== null + && shareTestContainer.querySelector('#'+obj2ID+'-scripts-tab') !== null + && shareTestContainer.querySelector('#'+obj2ID+'-looks') !== null + && shareTestContainer.querySelector('#'+obj2ID+'-sounds .catblocks-empty-text') !== null); })).toBeTruthy(); }); @@ -208,7 +208,7 @@ describe('Share catroid program rendering tests', () => { }, { name: 'tscene2', objectList: [{ - name: 'toobject2' + name: 'tobject2' }] }] }; @@ -217,22 +217,22 @@ describe('Share catroid program rendering tests', () => { const scene1ID = shareUtils.generateID('programID-tscene1'); const scene2ID = shareUtils.generateID('programID-tscene2'); - const obj1ID = shareUtils.generateID('programID-tscene1-toobject1'); - const obj2ID = shareUtils.generateID('programID-tscene2-toobject2'); + const obj1ID = shareUtils.generateID('programID-tscene1-tobject1'); + const obj2ID = shareUtils.generateID('programID-tscene2-tobject2'); - return (shareTestContainer.querySelector('#'+shareUtils.generateID('programID')) !== undefined - && shareTestContainer.querySelector('#'+scene1ID) !== undefined - && shareTestContainer.querySelector('#'+scene2ID) !== undefined + return (shareTestContainer.querySelector('#'+shareUtils.generateID('programID')) !== null + && shareTestContainer.querySelector('#'+scene1ID) !== null + && shareTestContainer.querySelector('#'+scene2ID) !== null - && shareTestContainer.querySelector('#'+obj1ID+'-scripts-tab') !== undefined - && shareTestContainer.querySelector('#'+obj1ID+'-looks') !== undefined - && shareTestContainer.querySelector('#'+obj1ID+'-sounds') !== undefined - && shareTestContainer.querySelector('#'+obj1ID+'-sounds .catblocks-empty-text') !== undefined + && shareTestContainer.querySelector('#'+obj1ID+'-scripts-tab') !== null + && shareTestContainer.querySelector('#'+obj1ID+'-looks') !== null + && shareTestContainer.querySelector('#'+obj1ID+'-sounds') !== null + && shareTestContainer.querySelector('#'+obj1ID+'-sounds .catblocks-empty-text') !== null - && shareTestContainer.querySelector('#'+obj2ID+'-scripts-tab') !== undefined - && shareTestContainer.querySelector('#'+obj2ID+'-looks') !== undefined - && shareTestContainer.querySelector('#'+obj2ID+'-sounds') !== undefined - && shareTestContainer.querySelector('#'+obj2ID+'-sounds .catblocks-empty-text') !== undefined); + && shareTestContainer.querySelector('#'+obj2ID+'-scripts-tab') !== null + && shareTestContainer.querySelector('#'+obj2ID+'-looks') !== null + && shareTestContainer.querySelector('#'+obj2ID+'-sounds') !== null + && shareTestContainer.querySelector('#'+obj2ID+'-sounds .catblocks-empty-text') !== null); })).toBeTruthy(); }); @@ -242,9 +242,9 @@ describe('Share catroid program rendering tests', () => { const scriptXml = (new DOMParser).parseFromString(scriptString, 'text/xml'); const svg = share.domToSvg(scriptXml); - return (svg !== undefined + return (svg !== null && svg.getAttribute('class') === 'catblocks-svg' - && svg.querySelector('path.blocklyPath') !== undefined); + && svg.querySelector('path.blocklyPath') !== null); })).toBeTruthy(); }); @@ -254,7 +254,7 @@ describe('Share catroid program rendering tests', () => { const scriptXml = (new DOMParser).parseFromString(scriptString, 'text/xml'); const svg = share.domToSvg(scriptXml); - return (svg !== undefined + return (svg !== null && svg.getAttribute('width').replace('px', '') > 0 && svg.getAttribute('height').replace('px', '') > 0); })).toBeTruthy(); @@ -278,8 +278,8 @@ describe('Share catroid program rendering tests', () => { share.renderProgramJSON('programID', shareTestContainer, catObj, catXml); - const objID = shareUtils.generateID('programID-tscene-toobject'); - return (shareTestContainer.querySelector('#'+objID+' #'+objID+'-scripts .catblocks-script svg.catblocks-svg') !== undefined); + const objID = shareUtils.generateID('programID-tscene-tobject'); + return (shareTestContainer.querySelector('#'+objID+' #'+objID+'-scripts .catblocks-script svg.catblocks-svg') !== null); })).toBeTruthy(); }); @@ -334,7 +334,7 @@ describe('Share catroid program rendering tests', () => { share.renderProgramJSON('programID', shareTestContainer, catObj, catXml); - const objID = shareUtils.generateID('programID-tscene-toobject'); + const objID = shareUtils.generateID('programID-tscene-tobject'); return (shareTestContainer.querySelector('#'+objID+' #'+objID+'-scripts .catblocks-script svg.catblocks-svg') == null); })).toBeTruthy(); }); @@ -375,11 +375,11 @@ describe('Share catroid program rendering tests', () => { share.renderProgramJSON('programID', shareTestContainer, catObj, catXml); - return (shareTestContainer.querySelector('.catblocks-scene') !== undefined + return (shareTestContainer.querySelector('.catblocks-scene') !== null && shareTestContainer.querySelector('.catblocks-scene-header').innerHTML.length > 0 - && shareTestContainer.querySelector('.catblocks-object-container') !== undefined - && shareTestContainer.querySelector('.accordion') !== undefined - && shareTestContainer.querySelector('.catblocks-object .card-header') !== undefined + && shareTestContainer.querySelector('.catblocks-object-container') !== null + && shareTestContainer.querySelector('.accordion') !== null + && shareTestContainer.querySelector('.catblocks-object .card-header') !== null && shareTestContainer.querySelector('.catblocks-object .card-header').innerHTML.startsWith('No objects found')); })).toBeTruthy(); }); @@ -407,16 +407,16 @@ describe('Share catroid program rendering tests', () => { scenes: [{ name: 'tscene', objectList: [{ - name: 'toobject' + name: 'tobject' }] }] }; share.renderProgramJSON('programID', shareTestContainer, catObj, catXml); const expectedSceneHeaderTextCollapsed = '
tscene
chevron_left'; - const expectedCardHeaderTextCollapsed = '
toobject
chevron_left'; + const expectedCardHeaderTextCollapsed = '
tobject
chevron_left'; const expectedSceneHeaderTextExpanded = '
tscene
expand_more'; - const expectedCardHeaderTextExpanded = '
toobject
expand_more'; + const expectedCardHeaderTextExpanded = '
tobject
expand_more'; const sceneHeader = shareTestContainer.querySelector('.catblocks-scene-header'); const cardHeader = shareTestContainer.querySelector('.catblocks-object .card-header'); const sceneHeaderInitialText = sceneHeader.innerHTML; From 0c8e491c03d5757de91da9be7d0345908d972a8e Mon Sep 17 00:00:00 2001 From: Georg Schuh Date: Sat, 30 May 2020 19:02:11 +0200 Subject: [PATCH 003/124] BLOCKS-124 setting display language is working again [GS] --- src/js/index.js | 12 +++++------- test/jsunit/msg/msg.test.js | 30 ++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/js/index.js b/src/js/index.js index 95bd3208..5fcfe314 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -33,12 +33,12 @@ import { renderAllPrograms } from './render/render'; } case 'share': { const programPath = 'assets/'; - initShareAndRenderPrograms(programPath); + initShareAndRenderPrograms(programPath, language); break; } case 'render': { const programPath = 'assets/programs/'; - initShareAndRenderPrograms(programPath); + initShareAndRenderPrograms(programPath, language); break; } case 'testing': { @@ -46,20 +46,17 @@ import { renderAllPrograms } from './render/render'; window.playground = new Playground(); window.share = new Share(); window.shareUtils = shareUtils; - // make playground window.playground.workspace = Blockly.inject('playworkspace', { media: '../media/', zoom: { startScale: 0.75 }, toolbox: window.playground.getToolbox(true), renderer: 'zelos' }); - // make share window.share.init({ 'container': 'share', 'renderSize': 0.75, 'shareRoot': '', 'media': 'media/', + 'language': language, 'noImageFound': 'No_Image_Available.jpg', }); - // set global workspace variables which are used by the tests - // currently your tests just use {shareWS, playgroundWS, toolboxWS} window.parser = window.share.parser; window.shareWS = window.share.workspace; window.playgroundWS = window.playground.workspace; @@ -72,7 +69,7 @@ import { renderAllPrograms } from './render/render'; } })(); -function initShareAndRenderPrograms(programPath) { +function initShareAndRenderPrograms(programPath, language) { const catblocksWorkspaceContainer = 'catblocks-workspace-container'; const programContainer = document.getElementById('catblocks-programs-container'); const share = new Share(); @@ -81,6 +78,7 @@ function initShareAndRenderPrograms(programPath) { 'renderSize': 0.75, 'shareRoot': '', 'media': 'media/', + 'language': language, 'noImageFound': 'No_Image_Available.jpg', }); renderAllPrograms(share, programContainer, programPath); diff --git a/test/jsunit/msg/msg.test.js b/test/jsunit/msg/msg.test.js index ced3c249..79c15ef0 100644 --- a/test/jsunit/msg/msg.test.js +++ b/test/jsunit/msg/msg.test.js @@ -1,7 +1,7 @@ /** * @description Msg tests */ -/* global page, SERVER, playground, playgroundWS, toolboxWS, Blockly */ +/* global share, page, SERVER, playground, playgroundWS, toolboxWS, Blockly */ /* eslint no-global-assign:0 */ 'use strict'; @@ -60,12 +60,9 @@ describe('Filesystem msg tests', () => { describe('Webview test', () => { - beforeAll(async () => { + beforeEach(async () => { await page.goto(`${SERVER}`, { waitUntil: 'networkidle0' }); page.on('console', message => console.log(message.text())); - }); - - beforeEach(async () => { // clean workspace before each test await page.evaluate(() => { playgroundWS.clear(); @@ -143,4 +140,25 @@ describe('Webview test', () => { }); }, languageObject, languageToTest)).toBeFalsy(); }); -}); + + test('Changing language on share page is working', async () => { + const languageToTest = 'de'; + const testLanguageObject = JSON.parse(utils.readFileSync(`${utils.PATHS.CATBLOCKS_MSGS}${languageToTest}.json`)); + const defaultLanguage = 'en'; + const defaultLanguageObject = JSON.parse(utils.readFileSync(`${utils.PATHS.CATBLOCKS_MSGS}${defaultLanguage}.json`)); + + expect(await page.evaluate((testLanguageObject, defaultLanguageObject, languageToTest) => { + const defaultBlock = share.workspace.newBlock("WaitBrick"); + defaultBlock.initSvg(); + defaultBlock.render(false); + return Blockly.CatblocksMsgs.setLocale(languageToTest) + .then(() => { + const testBlock = share.workspace.newBlock("WaitBrick"); + testBlock.initSvg(); + testBlock.render(false); + return (defaultLanguageObject['CONTROL_WAIT'].startsWith(defaultBlock.getFieldValue()) + && testLanguageObject['CONTROL_WAIT'].startsWith(testBlock.getFieldValue())); + }); + }, testLanguageObject, defaultLanguageObject, languageToTest)).toBeTruthy(); + }); +}); \ No newline at end of file From f652d648dcd7d761ece3e407500947595778879b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 7 Jun 2020 21:39:10 +0000 Subject: [PATCH 004/124] Bump websocket-extensions from 0.1.3 to 0.1.4 Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4. - [Release notes](https://github.com/faye/websocket-extensions-node/releases) - [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md) - [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ba6998d1..2d95df88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8014,9 +8014,9 @@ websocket-driver@>=0.5.1: websocket-extensions ">=0.1.1" websocket-extensions@>=0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" - integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5: version "1.0.5" From a941619f8ad150b4b07a841c3475ebc72bffaa71 Mon Sep 17 00:00:00 2001 From: Bernhard Prattes Date: Sun, 31 May 2020 18:31:18 +0200 Subject: [PATCH 005/124] BLOCKS-104 implement paste-listener, url param parser and file loader [BP] --- src/js/render/file_dropper.js | 178 ++++---------------------------- src/js/render/file_loader.js | 68 ++++++++++++ src/js/render/paste_listener.js | 83 +++++++++++++++ src/js/render/render.js | 41 +++++++- src/js/render/utils.js | 172 ++++++++++++++++++++++++++++++ 5 files changed, 384 insertions(+), 158 deletions(-) create mode 100644 src/js/render/file_loader.js create mode 100644 src/js/render/paste_listener.js create mode 100644 src/js/render/utils.js diff --git a/src/js/render/file_dropper.js b/src/js/render/file_dropper.js index 1f200400..3714a60a 100644 --- a/src/js/render/file_dropper.js +++ b/src/js/render/file_dropper.js @@ -1,6 +1,7 @@ import $ from "jquery"; -import JSZip from "jszip"; import { MessageBox } from "./message_box"; +import { loadArchive, updateView } from "./utils"; +import { PasteListener } from "./paste_listener"; /** * Initialize Drag & Drop Field and handle Files. @@ -96,156 +97,6 @@ export class FileDropper { } - /** - * Show or Hide loading overlay. - * @private - * @param {string} event - onDone / onStart - * @memberof FileDropper - */ - _updateView(event) { - switch (event) { - case 'onStart': - $('#loading-overlay').show(); - break; - - case 'onDone': - $('#loading-overlay').hide(); - break; - - default: - console.warn(`Ignore file dropper event: ${event}`); - } - } - - - /** - * Returns the Base64 Src String for HTML. - * @private - * @param {string} fileName relative Path to File - * @param {string} fileExt contains either exact file ending or a string which should contain the file ending - * @param {string} base64 encoded file - * @memberof FileDropper - */ - _generateBase64Src(fileName, fileExt, base64) { - - // images - if (fileExt.toLowerCase() === 'png' || fileExt.toLowerCase().includes('png')) { - return 'data:image/png;charset=utf-8;base64,' + base64; - } - if (fileExt.toLowerCase() === 'jpg' || fileExt.toLowerCase().includes('jpg')) { - return 'data:image/jpg;charset=utf-8;base64,' + base64; - } - if (fileExt.toLowerCase() === 'jpeg' || fileExt.toLowerCase().includes('jpeg')) { - return 'data:image/jpeg;charset=utf-8;base64,' + base64; - } - - // sound - if (fileExt.toLowerCase() === 'wav' || fileExt.toLowerCase().includes('wav')) { - return 'data:audio/wav;charset=utf-8;base64,' + base64; - } - if (fileExt.toLowerCase() === 'mp3' || fileExt.toLowerCase().includes('mp3')) { - return 'data:audio/mp3;charset=utf-8;base64,' + base64; - } - - // video - if (fileExt.toLowerCase() === 'mp4' || fileExt.toLowerCase().includes('mp4')) { - return 'data:video/mp4;charset=utf-8;base64,' + base64; - } - - // last try - if (fileName.includes('/images/')) { - console.warn('FileDropper: guessing Image type for ' + fileName); - return 'data:image/png;charset=utf-8;base64,' + base64; - } - if (fileName.includes('/sounds/')) { - console.warn('FileDropper: guessing Sound type for ' + fileName); - return 'data:audio/mp3;charset=utf-8;base64,' + base64; - } - - // ignore the rest - console.warn('FileDropper: Ignoring File ' + fileName); - return ""; - } - - - /** - * Load .catrobat / .zip file - * @private - * @param {file} containerfile - * @param {number} containerCounter - * @returns {Promise} - * @memberof FileDropper - */ - _loadArchive(containerfile, containerCounter) { - return new Promise((resolve) => { - // open ZIP - const zip = new JSZip(); - zip.loadAsync(containerfile, { - createFolders: true - }).then(element => { - - if (element.files['code.xml'] == null) { - throw new Error('Code.xml not found'); - } - - const fileMap = {}; - let codeXML = ""; - - const zipFileKeys = Object.keys(element.files); - const filePromises = []; - - for (const key of zipFileKeys) { - const file = element.files[key]; - - if (!file.dir) { - - if (file.name.toLowerCase() === 'code.xml') { - const promise = zip.file(file.name).async('string'); - filePromises.push(promise); - - promise.then(str => { - codeXML = str; - }); - - } else { - const promise = zip.file(file.name).async('base64'); - filePromises.push(promise); - - promise.then(base64 => { - let fileEnding = file.name.split('.'); - - if (fileEnding.length > 1) { - fileEnding = fileEnding[fileEnding.length - 1]; - fileMap[file.name] = this._generateBase64Src(file.name, fileEnding, base64); - } else { - fileMap[file.name] = this._generateBase64Src(file.name, atob(base64).substr(0, 32), base64); - } - - }); - } - } - } - - Promise.all(filePromises).then(response => { - if (response.length !== Object.keys(fileMap).length + 1) { - MessageBox.show('' + containerfile.name + ': Number of Files in Archive do not match number of read files.'); - console.error('Number of Files in ZIP do not match number of read files'); - } - - const fd = FileDropper.getInstance(); - try { - fd.renderProgram(fd.share, fd.container, codeXML, containerfile.name, containerCounter, fileMap); - resolve(true); - } catch (error) { - console.error(error); - MessageBox.show('' + containerfile.name + ': ' + error); - resolve(false); - } - }); - }); - }); - } - /** * Unpack Archive and start rendering of code.xml @@ -253,7 +104,7 @@ export class FileDropper { * @memberof FileDropper */ computeFiles(inputFiles) { - this._updateView('onStart'); + updateView('onStart'); let containerCounter = 0; let finished = 0; const renderPromises = []; @@ -263,10 +114,18 @@ export class FileDropper { const ext = fileArray[fileArray.length - 1]; if (ext === 'zip' || ext === 'catrobat') { - const promise = this._loadArchive(containerfile, containerCounter++); + const promise = loadArchive(containerfile); + containerCounter++; renderPromises.push(promise); - promise.then(() => { - MessageBox.show(`Rendered ${++finished}/${containerCounter} Programs`, 4000); + promise.then((result) => { + if(result !== null) { + try { + this.renderProgram(this.share, this.container, result.codeXML, containerfile.name, containerCounter, result.fileMap); + MessageBox.show(`Rendered ${++finished}/${containerCounter} Programs`, 4000); + } catch(error) { + MessageBox.show('' + containerfile.name + ': ' + error); + } + } }); } else { MessageBox.show(`File "${containerfile.name}" is not of type .catrobat/.zip`); @@ -278,14 +137,19 @@ export class FileDropper { for (const res of result) { if (res !== undefined && res) { $('#catblocks-file-dropper').hide(); + try { + PasteListener.getInstance().disablePasteListener(); + } catch(error) { + // ignore + } break; } } - this._updateView('onDone'); + updateView('onDone'); }); } else { - this._updateView('onDone'); + updateView('onDone'); } } diff --git a/src/js/render/file_loader.js b/src/js/render/file_loader.js new file mode 100644 index 00000000..f9844f6c --- /dev/null +++ b/src/js/render/file_loader.js @@ -0,0 +1,68 @@ +import {loadArchive, updateView} from "./utils"; +import {MessageBox} from "./message_box"; + +/** + * Try to load .catrobat file from a given URL and handle Files. + * + * @author b.prattes@student.tugraz.at + */ + +export class FileLoader { + constructor(url, share, container, renderProgram) { + this.url = url; + this.share = share; + this.container = container; + this.renderProgram = renderProgram; + this.downloadUrl = url; + } + + /** + * Fixes CORS-Error for GH URLs. + */ + fixCorsForGithubUrl() { + if(this.url.startsWith("https://github.com")) { + this.downloadUrl = this.url.replace("https://github.com", "https://raw.githubusercontent.com").replace("/raw/", "/"); + } + } + + /** + * Downloads the file from the passed URL and calls the render function. + */ + loadAndRenderProgram() { + return new Promise((resolve) => { + const containerCounter = 1; + updateView('onStart'); + this.fixCorsForGithubUrl(); + fetch(this.downloadUrl) + .then(resp => { + if(resp.status == 200 && resp.ok) { + const zipPromise = loadArchive(resp.arrayBuffer()); + zipPromise.then((result) => { + if(result !== null) { + try { + this.renderProgram(this.share, this.container, result.codeXML, this.url, containerCounter, result.fileMap); + updateView('onDone'); + MessageBox.show(`Rendered ${this.url}`, 4000); + resolve(true); + } catch(error) { + updateView('onDone'); + MessageBox.show('' + this.url + ':
' + error); + resolve(false); + } + } + else { + updateView('onDone'); + resolve(false); + } + }).catch(e => { + resolve(false); + }); + } + }).catch(error => { + updateView('onDone'); + MessageBox.show('' + this.url + ':
' + error); + resolve(false); + }); + }); + } +} \ No newline at end of file diff --git a/src/js/render/paste_listener.js b/src/js/render/paste_listener.js new file mode 100644 index 00000000..61b59cf7 --- /dev/null +++ b/src/js/render/paste_listener.js @@ -0,0 +1,83 @@ +import $ from "jquery"; +import {FileLoader} from "./file_loader"; + +/** + * Initialize Drag & Drop Field and handle Files. + * + * @author b.prattes@student.tugraz.at + */ + +let pasteListenerInstance = null; +export class PasteListener { + constructor(share, container, renderProgram) { + this.share = share; + this.container = container; + this.renderProgram = renderProgram; + this.ctrlDown = false; + this.enabled = false; + } + + /** + * Creates or returns Singleton instance. + * @static + * @param {*} share + * @param {*} container + * @param {*} renderProgram + * @returns {PasteListener} + * @memberof PasteListener + */ + static createInstance(share, container, renderProgram) { + if(pasteListenerInstance == null) { + pasteListenerInstance = new PasteListener(share, container, renderProgram); + pasteListenerInstance.initListener(); + } + return pasteListenerInstance; + } + + /** + * returns the singleton instance of PasteListener + * throws an error if not initialized + * @static + */ + static getInstance() { + if(pasteListenerInstance == null) { + throw new Error("Paste Listener not initialized!"); + } + return pasteListenerInstance; + } + + /** + * Register paste event on body. + */ + initListener() { + document.getElementsByTagName('body')[0].addEventListener('paste', function(e) { + const pl = PasteListener.getInstance(); + if(!pl.enabled) { + return; + } + + e.stopPropagation(); + e.preventDefault(); + + const pastedData = (e.clipboardData || window.clipboardData).getData('Text'); + + if(pastedData) { + const fl = new FileLoader(pastedData, pl.share, pl.container, pl.renderProgram); + fl.loadAndRenderProgram().then(result => { + if(result) { + $('#catblocks-file-dropper').hide(); + pl.disablePasteListener(); + } + }); + } + }); + } + + enablePasteListener() { + this.enabled = true; + } + + disablePasteListener() { + this.enabled = false; + } +} \ No newline at end of file diff --git a/src/js/render/render.js b/src/js/render/render.js index b7eb9c97..cfd51374 100644 --- a/src/js/render/render.js +++ b/src/js/render/render.js @@ -1,5 +1,8 @@ import { FileDropper } from "./file_dropper"; import $ from "jquery"; +import { getSearchParam } from "./utils"; +import { FileLoader } from "./file_loader"; +import { PasteListener } from "./paste_listener"; /** * Render all programs into one page @@ -26,6 +29,24 @@ export const renderAllPrograms = (share, container, path) => { .then(text => { const page = (new DOMParser()).parseFromString(text, 'text/html'); if (page === undefined) { + const urlToRender = getSearchParam(window.location.search, 'programurl'); + if(urlToRender !== undefined) { + // if there is a program passed via url: try to parse + const fl = new FileLoader(urlToRender, share, container, renderProgramByLocalFile); + fl.loadAndRenderProgram().then(success => { + if(!success) { + const pasteListener = PasteListener.createInstance(share, container, renderProgramByLocalFile); + pasteListener.enablePasteListener(); + + const fd = FileDropper.createInstance(share, container, renderProgramByLocalFile); + fd.enableDragAndDrop(); + } + }); + return; + } + const pasteListener = PasteListener.createInstance(share, container, renderProgramByLocalFile); + pasteListener.enablePasteListener(); + const fd = FileDropper.createInstance(share, container, renderProgramByLocalFile); fd.enableDragAndDrop(); return; @@ -33,8 +54,26 @@ export const renderAllPrograms = (share, container, path) => { const files = page.getElementsByTagName('ul')[0] || undefined; if (files === undefined) { + const urlToRender = getSearchParam(window.location.search, 'programurl'); + if(urlToRender !== undefined) { + // if there is a program passed via url: try to parse + const fl = new FileLoader(urlToRender, share, container, renderProgramByLocalFile); + fl.loadAndRenderProgram().then(success => { + if(!success) { + const pasteListener = PasteListener.createInstance(share, container, renderProgramByLocalFile); + pasteListener.enablePasteListener(); + + const fd = FileDropper.createInstance(share, container, renderProgramByLocalFile); + fd.enableDragAndDrop(); + } + }); + return; + } + const pasteListener = PasteListener.createInstance(share, container, renderProgramByLocalFile); + pasteListener.enablePasteListener(); + const fd = FileDropper.createInstance(share, container, renderProgramByLocalFile); - fd.enableDragAndDrop(); + fd.enableDragAndDrop(); return; } diff --git a/src/js/render/utils.js b/src/js/render/utils.js new file mode 100644 index 00000000..7e966b33 --- /dev/null +++ b/src/js/render/utils.js @@ -0,0 +1,172 @@ +import JSZip from "jszip"; +import { MessageBox } from "./message_box"; +import $ from "jquery"; + +/** + * Gets the requested param from a passed URLSearchParam + * @param {search_params} string formatted like window.location.search + * @param {key} string key of the requested value + * @returns {string} value or undefined if it does not exist + */ +export const getSearchParam = (search_params, key) => { + if(search_params === undefined || search_params === null || search_params === "") { + return undefined; + } + const urlSearchParams = new URLSearchParams(search_params); + if(urlSearchParams === undefined || urlSearchParams === null) { + return undefined; + } + if(!urlSearchParams.has(key)) { + return undefined; + } + const value = urlSearchParams.get(key); + return value ? value : undefined; +}; + +/** + * Show or Hide loading overlay. + * @private + * @param {string} event - onDone / onStart + * @memberof FileDropper + */ +export const updateView = (event) => { + switch (event) { + case 'onStart': + $('#loading-overlay').show(); + break; + + case 'onDone': + $('#loading-overlay').hide(); + break; + + default: + console.warn(`Ignore file dropper event: ${event}`); + } +}; + +/** + * Returns the Base64 Src String for HTML. + * @private + * @param {string} fileName relative Path to File + * @param {string} fileExt contains either exact file ending or a string which should contain the file ending + * @param {string} base64 encoded file + * @memberof FileDropper + */ +export const generateBase64Src = (fileName, fileExt, base64) => { + // images + if (fileExt.toLowerCase() === 'png' || fileExt.toLowerCase().includes('png')) { + return 'data:image/png;charset=utf-8;base64,' + base64; + } + if (fileExt.toLowerCase() === 'jpg' || fileExt.toLowerCase().includes('jpg')) { + return 'data:image/jpg;charset=utf-8;base64,' + base64; + } + if (fileExt.toLowerCase() === 'jpeg' || fileExt.toLowerCase().includes('jpeg')) { + return 'data:image/jpeg;charset=utf-8;base64,' + base64; + } + + // sound + if (fileExt.toLowerCase() === 'wav' || fileExt.toLowerCase().includes('wav')) { + return 'data:audio/wav;charset=utf-8;base64,' + base64; + } + if (fileExt.toLowerCase() === 'mp3' || fileExt.toLowerCase().includes('mp3')) { + return 'data:audio/mp3;charset=utf-8;base64,' + base64; + } + + // video + if (fileExt.toLowerCase() === 'mp4' || fileExt.toLowerCase().includes('mp4')) { + return 'data:video/mp4;charset=utf-8;base64,' + base64; + } + + // last try + if (fileName.includes('/images/')) { + console.warn('generateBase64Src: guessing Image type for ' + fileName); + return 'data:image/png;charset=utf-8;base64,' + base64; + } + if (fileName.includes('/sounds/')) { + console.warn('generateBase64Src: guessing Sound type for ' + fileName); + return 'data:audio/mp3;charset=utf-8;base64,' + base64; + } + + // ignore the rest + console.warn('generateBase64Src: Ignoring File ' + fileName); + return ""; +}; + + +/** + * Load .catrobat / .zip file + * @private + * @param {file} containerfile + * @param {number} containerCounter + * @returns {Promise} + */ +export const loadArchive = (containerfile) => { + return new Promise((resolve) => { + // open ZIP + const zip = new JSZip(); + zip.loadAsync(containerfile, { + createFolders: true + }).then(element => { + + if (element.files['code.xml'] == null) { + throw new Error('Code.xml not found'); + } + + const fileMap = {}; + let codeXML = ""; + + const zipFileKeys = Object.keys(element.files); + const filePromises = []; + + for (const key of zipFileKeys) { + const file = element.files[key]; + + if (!file.dir) { + + if (file.name.toLowerCase() === 'code.xml') { + const promise = zip.file(file.name).async('string'); + filePromises.push(promise); + + promise.then(str => { + codeXML = str; + }); + + } else { + const promise = zip.file(file.name).async('base64'); + filePromises.push(promise); + + promise.then(base64 => { + let fileEnding = file.name.split('.'); + + if (fileEnding.length > 1) { + fileEnding = fileEnding[fileEnding.length - 1]; + fileMap[file.name] = generateBase64Src(file.name, fileEnding, base64); + } else { + fileMap[file.name] = generateBase64Src(file.name, atob(base64).substr(0, 32), base64); + } + + }); + } + } + } + + Promise.all(filePromises).then(response => { + if (response.length !== Object.keys(fileMap).length + 1) { + MessageBox.show('' + containerfile.name + ': Number of Files in Archive do not match number of read files.'); + console.error('Number of Files in ZIP do not match number of read files'); + } + + try { + resolve({'fileMap': fileMap, 'codeXML': codeXML}); + } catch(error) { + console.error(error); + MessageBox.show('' + containerfile.name + ': ' + error); + resolve(null); + } + }); + }, error => { + MessageBox.show('Error: The file could not be loaded. Maybe you passed an invalid .catrobat/.zip file.'); + resolve(null); + }); + }); +}; \ No newline at end of file From fbef0b6d982e112b200547b3afd304f1a946ca87 Mon Sep 17 00:00:00 2001 From: Michael Flucher Date: Mon, 8 Jun 2020 14:45:41 +0200 Subject: [PATCH 006/124] BLOCKS-128 check for count of listed files [MF] --- src/js/render/render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/render/render.js b/src/js/render/render.js index b7eb9c97..6d94a535 100644 --- a/src/js/render/render.js +++ b/src/js/render/render.js @@ -32,7 +32,7 @@ export const renderAllPrograms = (share, container, path) => { } const files = page.getElementsByTagName('ul')[0] || undefined; - if (files === undefined) { + if (files === undefined || files.childElementCount === 0) { const fd = FileDropper.createInstance(share, container, renderProgramByLocalFile); fd.enableDragAndDrop(); return; From 459296d8970f62e945ebfc345d808dba4bfdf853 Mon Sep 17 00:00:00 2001 From: Georg Schuh Date: Sun, 31 May 2020 18:26:39 +0200 Subject: [PATCH 007/124] BLOCKS-117 added UI language translations in share [GS] --- i18n/strings_to_json_mapping.json | 5 ++- src/js/share/share.js | 47 +++++++++++++++----------- test/jsunit/msg/msg.test.js | 55 ++++++++++++++++++++++++++++++- 3 files changed, 86 insertions(+), 21 deletions(-) diff --git a/i18n/strings_to_json_mapping.json b/i18n/strings_to_json_mapping.json index bb907b94..f7b9e78d 100644 --- a/i18n/strings_to_json_mapping.json +++ b/i18n/strings_to_json_mapping.json @@ -506,5 +506,8 @@ "@GravityType": "GravityType", "GRAVITY_DYNAMIC": "${brick_set_physics_object_type_dynamic}", "GRAVITY_FIXED": "${brick_set_physics_object_type_fixed}", - "GRAVITY_NONE": "${brick_set_physics_object_type_no}" + "GRAVITY_NONE": "${brick_set_physics_object_type_no}", + "SCRIPTS": "${scripts}", + "LOOKS": "${looks}", + "SOUNDS": "${sounds}" } \ No newline at end of file diff --git a/src/js/share/share.js b/src/js/share/share.js index b86898b3..851be9de 100644 --- a/src/js/share/share.js +++ b/src/js/share/share.js @@ -360,15 +360,15 @@ export class Share { 'aria-labelledby': objHeadingID, 'data-parent': `#${accordionID}` }); - - this.generateTabs(objectContentContainer, objectID, object); + const currentLocaleValues = Blockly.CatblocksMsgs.getCurrentLocaleValues(); + this.generateTabs(objectContentContainer, objectID, object, currentLocaleValues); const contentContainer = injectNewDom(objectContentContainer, 'div', { class: 'tab-content card-body' }); - this.generateScripts(contentContainer, objectID, object, xmlObject, options); - this.generateLooks(contentContainer, objectID, object, options); - this.generateSounds(contentContainer, objectID, object, options); + this.generateScripts(contentContainer, objectID, object, xmlObject, currentLocaleValues, options); + this.generateLooks(contentContainer, objectID, object, currentLocaleValues, options); + this.generateSounds(contentContainer, objectID, object, currentLocaleValues, options); } /** @@ -376,9 +376,10 @@ export class Share { * @param {Element} container * @param {string} objectID * @param {Object} object + * @param {Object} currentLocaleValues * @param {Object} [options=defaultOptions.object] */ - generateSounds(container, objectID, object, options = defaultOptions.object) { + generateSounds(container, objectID, object, currentLocaleValues, options = defaultOptions.object) { const soundsContainer = injectNewDom(container, 'div', { class: 'tab-pane fade p-3', id: `${objectID}-sounds`, @@ -386,10 +387,11 @@ export class Share { 'aria-labelledby': `${objectID}-sounds-tab` }); + const noSoundsText = 'No ' + currentLocaleValues['SOUNDS'] + ' found'; if (!object || !object.soundList || object.soundList.length <= 0) { soundsContainer.appendChild(injectNewDom(soundsContainer, 'p', { class: 'catblocks-empty-text' - }, 'No Sounds found')); + }, noSoundsText)); return; } @@ -442,9 +444,10 @@ export class Share { } if (failed > 0) { + const failedSoundsText = 'ERROR parsing ' + failed + ' ' + currentLocaleValues['SOUNDS']; soundsContainer.appendChild(injectNewDom(soundsContainer, 'p', { class: 'catblocks-empty-text' - }, `Failed to parse ${failed} sounds(s) properly.`)); + }, failedSoundsText)); } } @@ -453,9 +456,10 @@ export class Share { * @param {Element} container * @param {string} objectID * @param {Object} object + * @param {Oject} currentLocaleValues * @param {Object} [options=defaultOptions.object] */ - generateLooks(container, objectID, object, options = defaultOptions.object) { + generateLooks(container, objectID, object, currentLocaleValues, options = defaultOptions.object) { const looksContainer = injectNewDom(container, 'div', { class: 'tab-pane fade p-3', id: `${objectID}-looks`, @@ -463,10 +467,11 @@ export class Share { 'aria-labelledby': `${objectID}-looks-tab` }); + const noLooksText = 'No ' + currentLocaleValues['LOOKS'] + ' found'; if (!object || !object.lookList || object.lookList.length <= 0) { looksContainer.appendChild(injectNewDom(looksContainer, 'p', { class: 'catblocks-empty-text' - }, 'No Looks found')); + }, noLooksText)); return; } @@ -511,9 +516,10 @@ export class Share { } if (failed > 0) { + const failedLooksText = 'ERROR parsing ' + failed + ' ' + currentLocaleValues['LOOKS']; looksContainer.appendChild(injectNewDom(looksContainer, 'p', { class: 'catblocks-empty-text' - }, `Failed to parse ${failed} look(s) properly.`)); + }, failedLooksText)); } } @@ -523,9 +529,10 @@ export class Share { * @param {string} objectID * @param {Object} object * @param {XMLDocument} + * @param {Object} currentLocaleValues * @param {Object} [options=defaultOptions.object] */ - generateScripts(container, objectID, object, xmlObject, options = defaultOptions.object) { + generateScripts(container, objectID, object, xmlObject, currentLocaleValues, options = defaultOptions.object) { const wrapperContainer = injectNewDom(container, 'div', { class: 'tab-pane show active fade p-3', id: `${objectID}-scripts`, @@ -537,9 +544,10 @@ export class Share { object.scriptList.length <= 0 || !hasChildren(xmlObject) || object.scriptList.length !== xmlObject.children.length) { + const noScriptText = 'No ' + currentLocaleValues['SCRIPTS'] + ' found'; wrapperContainer.appendChild(injectNewDom(wrapperContainer, 'p', { class: 'catblocks-empty-text' - }, 'No Scripts found')); + }, noScriptText)); return; } @@ -561,9 +569,10 @@ export class Share { } if (failed > 0) { + const failedScriptText = 'ERROR parsing ' + failed + ' ' + currentLocaleValues['SCRIPTS']; wrapperContainer.appendChild(injectNewDom(wrapperContainer, 'p', { class: 'catblocks-empty-text' - }, `Failed to parse ${failed} script(s) properly.`)); + }, failedScriptText)); } } @@ -572,9 +581,9 @@ export class Share { * @param {Element} container * @param {string} objectID * @param {Object} object - * @param {Object} [options=defaultOptions.object] + * @param {Object} currentLocaleValues */ - generateTabs(container, objectID, object) { + generateTabs(container, objectID, object, currentLocaleValues) { if (!object) { object = { @@ -614,7 +623,7 @@ export class Share { role: 'tab', 'aria-controls': 'scripts', 'aria-selected': 'true' - }, `Scripts (${object.scriptList.length})`); + }, `${currentLocaleValues['SCRIPTS']} (${object.scriptList.length})`); const liLooks = injectNewDom(ul, 'li', { class: 'nav-item' @@ -627,7 +636,7 @@ export class Share { role: 'tab', 'aria-controls': 'looks', 'aria-selected': 'false' - }, `Looks (${object.lookList.length})`); + }, `${currentLocaleValues['LOOKS']} (${object.lookList.length})`); const liSounds = injectNewDom(ul, 'li', { class: 'nav-item' @@ -640,7 +649,7 @@ export class Share { role: 'tab', 'aria-controls': 'sounds', 'aria-selected': 'false' - }, `Sounds (${object.soundList.length})`); + }, `${currentLocaleValues['SOUNDS']} (${object.soundList.length})`); } /** diff --git a/test/jsunit/msg/msg.test.js b/test/jsunit/msg/msg.test.js index 79c15ef0..120d5ec2 100644 --- a/test/jsunit/msg/msg.test.js +++ b/test/jsunit/msg/msg.test.js @@ -1,7 +1,7 @@ /** * @description Msg tests */ -/* global share, page, SERVER, playground, playgroundWS, toolboxWS, Blockly */ +/* global share, shareUtils, page, SERVER, playground, playgroundWS, toolboxWS, Blockly */ /* eslint no-global-assign:0 */ 'use strict'; @@ -161,4 +161,57 @@ describe('Webview test', () => { }); }, testLanguageObject, defaultLanguageObject, languageToTest)).toBeTruthy(); }); +}); + +describe('share displays language of UI elements correctly', () => { + + beforeEach(async () => { + await page.goto(`${SERVER}`, { waitUntil: 'networkidle0' }); + page.on('console', message => console.log(message.text())); + }); + + test('check >en< language of tabs and error messages of scripts, looks and sounds', async () => { + const defaultLanguage = 'en'; + const defaultLanguageObject = JSON.parse(utils.readFileSync(`${utils.PATHS.CATBLOCKS_MSGS}${defaultLanguage}.json`)); + await page.evaluate((defaultLanguage) => { + return Blockly.CatblocksMsgs.setLocale(defaultLanguage); + }, defaultLanguage); + expect(await executeShareLanguageUITest(defaultLanguageObject)).toBeTruthy(); + }); + + test('check >de< language of tabs and error messages of scripts, looks and sounds', async () => { + const testLanguage = 'de'; + const testLanguageObject = JSON.parse(utils.readFileSync(`${utils.PATHS.CATBLOCKS_MSGS}${testLanguage}.json`)); + await page.evaluate((testLanguage) => { + return Blockly.CatblocksMsgs.setLocale(testLanguage); + }, testLanguage); + expect(await executeShareLanguageUITest(testLanguageObject)).toBeTruthy(); + }); + + async function executeShareLanguageUITest(languageObject) { + return await page.evaluate((languageObject) => { + const shareTestContainer = document.getElementById('shareprogs'); + const xmlString = ``; + const catXml = (new DOMParser).parseFromString(xmlString, 'text/xml'); + const catObj = { + scenes: [{ + name: 'tscene', + objectList: [{ + name: 'toobject' + }] + }] + }; + share.renderProgramJSON('programID', shareTestContainer, catObj, catXml); + const obj1ID = shareUtils.generateID('programID-tscene-toobject'); + const scriptsText = shareTestContainer.querySelector('#'+obj1ID+'-scripts').textContent; + const scriptsTabText = shareTestContainer.querySelector('#'+obj1ID+'-scripts-tab').textContent; + const looksText = shareTestContainer.querySelector('#'+obj1ID+'-looks').textContent; + const looksTabText = shareTestContainer.querySelector('#'+obj1ID+'-looks-tab').textContent; + const soundsText = shareTestContainer.querySelector('#'+obj1ID+'-sounds').textContent; + const soundsTabText = shareTestContainer.querySelector('#'+obj1ID+'-sounds-tab').textContent; + return (scriptsTabText.includes(languageObject['SCRIPTS']) && scriptsText.includes(languageObject['SCRIPTS']) + && looksTabText.includes(languageObject['LOOKS']) && looksText.includes(languageObject['LOOKS']) + && soundsTabText.includes(languageObject['SOUNDS']) && soundsText.includes(languageObject['SOUNDS'])); + }, languageObject); + } }); \ No newline at end of file From aa9125cf2d66f38cce62bb4436fde5f52d2a34a3 Mon Sep 17 00:00:00 2001 From: Michael Flucher Date: Tue, 9 Jun 2020 10:35:37 +0200 Subject: [PATCH 008/124] BLOCKS-100 prettier and eslint config + github action [MF] --- .eslintignore | 6 ++++-- .eslintrc | 13 ++++++++++++- .github/workflows/pull_request_actions.yml | 14 ++++++++++++++ .prettierignore | 4 ++++ .prettierrc | 7 +++++++ package.json | 8 +++++++- webpack.config.js | 4 +++- yarn.lock | 10 ++++++++++ 8 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.eslintignore b/.eslintignore index d89b3173..500e60fb 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,4 @@ -babel.config.js -webpack.config.js \ No newline at end of file +**/*config.js +dist/ +release/ +tools/ \ No newline at end of file diff --git a/.eslintrc b/.eslintrc index b6d0ae77..83059cc4 100755 --- a/.eslintrc +++ b/.eslintrc @@ -27,8 +27,19 @@ "warn" ], "indent": [ + "warn", + 2, + { "SwitchCase": 1 } + ], + "curly": [ "error", - 2 + "all" + ], + "no-multi-spaces": [ + "error" + ], + "no-multi-assign": [ + "error" ], "no-mixed-spaces-and-tabs": [ "error" diff --git a/.github/workflows/pull_request_actions.yml b/.github/workflows/pull_request_actions.yml index 42d8baaf..5bb5299d 100644 --- a/.github/workflows/pull_request_actions.yml +++ b/.github/workflows/pull_request_actions.yml @@ -38,3 +38,17 @@ jobs: with: name: DockerCatblocks path: ./docker/po-review/ + + + lintCode: + name: Lint Code + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: borales/actions-yarn@v2.0.0 + with: + cmd: install + - uses: borales/actions-yarn@v2.0.0 + with: + cmd: lint + diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..5879565d --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +**/*config.js +dist/ +release/ +tools/ \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..e4c9400d --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "printWidth": 120, + "useTabs": false, + "singleQuote": true, + "arrowParens": "avoid", + "trailingComma": "none" +} \ No newline at end of file diff --git a/package.json b/package.json index 5bcb9b8d..b00c8cbc 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,11 @@ "initiate": "yarn translate", "translate": "node i18n/create_json.js && node i18n/create_msg.js", "clean": "rimraf dist ; rimraf release", - "release": "yarn initiate && webpack --config release.config.js" + "release": "yarn initiate && webpack --config release.config.js", + "lint:es": "yarn eslint --ext .js ./", + "lint:pr": "yarn prettier -c **.js", + "lint": "yarn lint:es --max-warnings 0 && yarn lint:pr", + "lint:fix": "yarn lint:es --fix && yarn lint:pr --write" }, "dependencies": { "@babel/core": "^7.6.4", @@ -55,6 +59,8 @@ "jest": "^24.9.0", "jest-environment-node": "^24.9.0", "jest-puppeteer": "^4.3.0", + "prettier": "^2.0.5", + "prettier-webpack-plugin": "^1.2.0", "puppeteer": "^2.0.0", "rimraf": "^3.0.0" } diff --git a/webpack.config.js b/webpack.config.js index bfe9bc2b..a6839266 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -3,6 +3,7 @@ const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CopyPlugin = require('copy-webpack-plugin'); +const PrettierPlugin = require("prettier-webpack-plugin"); const devMode = process.env.NODE_ENV !== 'production'; module.exports = { @@ -75,7 +76,8 @@ module.exports = { NODE_ENV: 'development', TYPE: 'catblocks', DISPLAY_LANGUAGE: process.env.DISPLAY_LANGUAGE ? process.env.DISPLAY_LANGUAGE : "" - }) + }), + new PrettierPlugin() ], // watch: true, devtool: 'source-map', diff --git a/yarn.lock b/yarn.lock index ba6998d1..4f2802ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6152,6 +6152,16 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= +prettier-webpack-plugin@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/prettier-webpack-plugin/-/prettier-webpack-plugin-1.2.0.tgz#4a5635f054741160936c7f509f0a9b1f928e5550" + integrity sha512-icoIPxDpOo/q7SUCHSW152dCr83z7QS/6s2V3phweKu1bfJcXSObVAq/Z8OeSX7ykuXrcV2UpZbfljRI2rIOMg== + +prettier@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" + integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== + pretty-error@^2.0.2: version "2.1.1" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" From cd7691481df735fc52d84aadf9fba87fcf201da4 Mon Sep 17 00:00:00 2001 From: Michael Flucher Date: Tue, 9 Jun 2020 10:36:12 +0200 Subject: [PATCH 009/124] BLOCKS-100 [REFACTOR] applied yarn lint:fix [MF] --- i18n/create_json.js | 103 +-- i18n/create_msg.js | 6 +- i18n/lang_codes_mapping.js | 484 +++++------ src/css/share.css | 230 ++--- src/css/style.css | 25 +- src/html/testing.html | 37 +- src/js/blocks/bricks.js | 29 +- src/js/blocks/categories/arduino.js | 38 +- src/js/blocks/categories/control.js | 254 +++--- src/js/blocks/categories/data.js | 224 ++--- src/js/blocks/categories/drone.js | 174 ++-- src/js/blocks/categories/event.js | 86 +- src/js/blocks/categories/index.js | 33 +- src/js/blocks/categories/jumpingSumo.js | 112 +-- src/js/blocks/categories/legoEV3.js | 86 +- src/js/blocks/categories/legoNXT.js | 68 +- src/js/blocks/categories/looks.js | 302 +++---- src/js/blocks/categories/motion.js | 316 +++---- src/js/blocks/categories/pen.js | 54 +- src/js/blocks/categories/phiro.js | 130 +-- src/js/blocks/categories/raspi.js | 94 +-- src/js/blocks/categories/sound.js | 94 +-- src/js/blocks/categories/stitch.js | 52 +- src/js/blocks/colours.js | 41 +- src/js/blocks/index.js | 2 +- src/js/catblocks_msgs.js | 157 ++-- src/js/index.js | 114 +-- src/js/parser/formula.js | 94 ++- src/js/parser/parser.js | 523 +++++++----- src/js/playground/playground.js | 72 +- src/js/release.js | 178 ++-- src/js/render/file_dropper.js | 184 ++-- src/js/render/message_box.js | 14 +- src/js/render/render.js | 34 +- src/js/share/share.js | 355 +++++--- src/js/share/utils.js | 116 ++- test/jsunit/block/block.test.js | 292 ++++--- test/jsunit/commonUtils.js | 40 +- test/jsunit/msg/msg.test.js | 228 ++--- test/jsunit/parser/parser.test.js | 789 ++++++++++------- test/jsunit/share/share.test.js | 1028 +++++++++++++---------- test/jsunit/share/share.utils.test.js | 193 +++-- test/jsunit/xml/xml.test.js | 77 +- 43 files changed, 4123 insertions(+), 3439 deletions(-) diff --git a/i18n/create_json.js b/i18n/create_json.js index 57489148..91400f22 100644 --- a/i18n/create_json.js +++ b/i18n/create_json.js @@ -4,11 +4,11 @@ /** * @author Andreas Karner * @description generate crowdin json files based on build mapping and string templates from catroid - * + * * @changelog 2019-08-14: initial version * 2019-08-21: fixed some bugs, update to support different xml tags * 2019-08-23: added some more comments, refactor code - * 2019-11-05: [MF] updated to new structure + * 2019-11-05: [MF] updated to new structure * 2020-03-30: [AK] updated to use xml2js module * 2020-03-31: [AK] updated code to use default value for missing in current language * 2020-04-01: [AK] updated default language to 'values-en-rAU' @@ -34,51 +34,51 @@ const JSON_DIR = path.join('i18n', 'json'); /** * Parse/prepare dirname from localfilesystem to use in code - * @param {*} dirname + * @param {*} dirname */ -const prepareStringFolderName = (dirname) => dirname.replace('values-', '').replace('-r', '-').replace('-', '_'); +const prepareStringFolderName = dirname => dirname.replace('values-', '').replace('-r', '-').replace('-', '_'); /** * Escape received string values from strings xml and return value - * @param {*} value + * @param {*} value */ -const escapeStringValue = (value) => value ? value.replace(/\r?\n|\r|\\n|\\"/g, '') : ''; +const escapeStringValue = value => (value ? value.replace(/\r?\n|\r|\\n|\\"/g, '') : ''); /** - * Parse json string stream from catroid string files and return object for value substitution - * @param {*} stream + * Parse json string stream from catroid string files and return object for value substitution + * @param {*} stream * @return Object */ -const parseStringFile = (stream) => { +const parseStringFile = stream => { const values = {}; const data = stream.resources; Object.keys(data).forEach(xmltag => { switch (xmltag) { - case "string": - data.string.forEach(stringpair => { - values[stringpair.$.name] = escapeStringValue(stringpair._); - }); - break; - case "plurals": - data.plurals.forEach(pluralpair => { - pluralpair.item.forEach(pluralitem => { - values[`${pluralpair.$.name}.${pluralitem.$.quantity}`] = escapeStringValue(pluralitem._); + case 'string': + data.string.forEach(stringpair => { + values[stringpair.$.name] = escapeStringValue(stringpair._); }); - }); - break; - default: - console.warn(`Skip not supported xml tag from ${STRINGS_FILE}`); - break; + break; + case 'plurals': + data.plurals.forEach(pluralpair => { + pluralpair.item.forEach(pluralitem => { + values[`${pluralpair.$.name}.${pluralitem.$.quantity}`] = escapeStringValue(pluralitem._); + }); + }); + break; + default: + console.warn(`Skip not supported xml tag from ${STRINGS_FILE}`); + break; } }); return values; }; /** - * substitute variables with corresponding data - * @param {String} variable - * @param {Object} data + * substitute variables with corresponding data + * @param {String} variable + * @param {Object} data * @param {Object} defdata * @return String */ @@ -96,60 +96,65 @@ const substituteVariableData = (variable, data, defdata) => { } }); return result; -} +}; /** * Read catroid string file and parse it into a js object - * @param {*} file - * @param {*} enc + * @param {*} file + * @param {*} enc * @return Object */ const readStringFile = async (file, enc = 'utf-8') => { const payload = fs.readFileSync(file, { encoding: enc }); return parseStringFile(await xml2json.parseStringPromise(payload)); -} +}; /** * Generate language mapping - * @param {*} values + * @param {*} values * @return Object */ const generateLangValues = (values, defvalues) => { const result = {}; - Object.keys(MAPPING).filter(key => !key.startsWith(MAPPING_COMMENT)).forEach(rule => { - const value = substituteVariableData(MAPPING[rule], values, defvalues); - result[rule] = value.split('"').join(''); - }); + Object.keys(MAPPING) + .filter(key => !key.startsWith(MAPPING_COMMENT)) + .forEach(rule => { + const value = substituteVariableData(MAPPING[rule], values, defvalues); + result[rule] = value.split('"').join(''); + }); return result; -} +}; /** * Create language file based on MAPPING and values * Dump result as json file into JSON_DIR - * @param {*} lang - * @param {*} values + * @param {*} lang + * @param {*} values */ const dumpStringFile = (lang, values) => { const langname = prepareStringFolderName(lang); const jsonfile = path.join(JSON_DIR, langname + '.json'); - values["DROPDOWN_NAME"] = locales[langname] ? locales[langname] : langname; + values['DROPDOWN_NAME'] = locales[langname] ? locales[langname] : langname; fs.writeFileSync(jsonfile, JSON.stringify(values), { encoding: 'utf-8' }); -} - +}; (async () => { - if (!fs.existsSync(JSON_DIR)) fs.mkdirSync(JSON_DIR); + if (!fs.existsSync(JSON_DIR)) { + fs.mkdirSync(JSON_DIR); + } const def_string = await readStringFile(DEF_LANG_FILE); const def_values = generateLangValues(def_string, def_string); dumpStringFile(DEF_LANG, def_values); const languages = fs.readdirSync(STRINGS_DIR, { encoding: 'utf-8' }); - languages.filter(lang => (lang != DEF_LANG)).forEach(async langname => { - const lang_file = path.join(STRINGS_DIR, langname, STRINGS_FILE); - const lang_string = await readStringFile(lang_file); - const lang_values = generateLangValues(lang_string, def_string); - dumpStringFile(langname, lang_values); - }); -})(); \ No newline at end of file + languages + .filter(lang => lang != DEF_LANG) + .forEach(async langname => { + const lang_file = path.join(STRINGS_DIR, langname, STRINGS_FILE); + const lang_string = await readStringFile(lang_file); + const lang_values = generateLangValues(lang_string, def_string); + dumpStringFile(langname, lang_values); + }); +})(); diff --git a/i18n/create_msg.js b/i18n/create_msg.js index 71a44f3e..257b0710 100644 --- a/i18n/create_msg.js +++ b/i18n/create_msg.js @@ -4,7 +4,7 @@ /** * @author Andreas Karner * @description generate crowdin message file based on msg/*.json files, please run first create_msg_json.js if needed - * + * * @changelog 2019-08-14: initial version * 2019-08-23: added some more comments, refactor code * 2019-09-06: changed logic to generate just one catblocks_msgs.js file @@ -108,7 +108,7 @@ langfiles.forEach(langfile => { fs.writeSync(message_fd, ` "${lang_name}": {`); Object.keys(json_object).forEach(key => { - if (key === "DROPDOWN_NAME") { + if (key === 'DROPDOWN_NAME') { fs.writeSync(message_fd, ` "${key}": "${json_object[key]}" `); } }); @@ -116,4 +116,4 @@ langfiles.forEach(langfile => { } }); fs.writeSync(message_fd, `};`); -fs.closeSync(message_fd); \ No newline at end of file +fs.closeSync(message_fd); diff --git a/i18n/lang_codes_mapping.js b/i18n/lang_codes_mapping.js index 4b3e19f6..9af6c72e 100644 --- a/i18n/lang_codes_mapping.js +++ b/i18n/lang_codes_mapping.js @@ -16,247 +16,247 @@ // } const locales = { - "af": "Afrikaans", - "af_ZA": "Afrikaans (South Africa)", - "ar": "Arabic", - "ar_AE": "Arabic (U.A.E.)", - "ar_BH": "Arabic (Bahrain)", - "ar_DZ": "Arabic (Algeria)", - "ar_EG": "Arabic (Egypt)", - "ar_IQ": "Arabic (Iraq)", - "ar_JO": "Arabic (Jordan)", - "ar_KW": "Arabic (Kuwait)", - "ar_LB": "Arabic (Lebanon)", - "ar_LY": "Arabic (Libya)", - "ar_MA": "Arabic (Morocco)", - "ar_OM": "Arabic (Oman)", - "ar_QA": "Arabic (Qatar)", - "ar_SA": "Arabic (Saudi Arabia)", - "ar_SY": "Arabic (Syria)", - "ar_TN": "Arabic (Tunisia)", - "ar_YE": "Arabic (Yemen)", - "az": "Azeri (Latin)", - "az_AZ": "Azeri (Cyrillic) (Azerbaijan)", - "be": "Belarusian", - "be_BY": "Belarusian (Belarus)", - "bg": "Bulgarian", - "bg_BG": "Bulgarian (Bulgaria)", - "bs_BA": "Bosnian (Bosnia and Herzegovina)", - "ca": "Catalan", - "ca_ES": "Catalan (Spain)", - "cs": "Czech", - "cs_CZ": "Czech (Czech Republic)", - "cy": "Welsh", - "cy_GB": "Welsh (United Kingdom)", - "da": "Danish", - "da_DK": "Danish (Denmark)", - "de": "German", - "de_AT": "German (Austria)", - "de_CH": "German (Switzerland)", - "de_DE": "German (Germany)", - "de_LI": "German (Liechtenstein)", - "de_LU": "German (Luxembourg)", - "dv": "Divehi", - "dv_MV": "Divehi (Maldives)", - "el": "Greek", - "el_GR": "Greek (Greece)", - "en": "English", - "en_AU": "English (Australia)", - "en_BZ": "English (Belize)", - "en_CA": "English (Canada)", - "en_CB": "English (Caribbean)", - "en_GB": "English (United Kingdom)", - "en_IE": "English (Ireland)", - "en_JM": "English (Jamaica)", - "en_NZ": "English (New Zealand)", - "en_PH": "English (Republic of the Philippines)", - "en_TT": "English (Trinidad and Tobago)", - "en_US": "English (United States)", - "en_ZA": "English (South Africa)", - "en_ZW": "English (Zimbabwe)", - "eo": "Esperanto", - "es": "Spanish", - "es_AR": "Spanish (Argentina)", - "es_BO": "Spanish (Bolivia)", - "es_CL": "Spanish (Chile)", - "es_CO": "Spanish (Colombia)", - "es_CR": "Spanish (Costa Rica)", - "es_DO": "Spanish (Dominican Republic)", - "es_EC": "Spanish (Ecuador)", - "es_ES": "Spanish (Spain)", - "es_GT": "Spanish (Guatemala)", - "es_HN": "Spanish (Honduras)", - "es_MX": "Spanish (Mexico)", - "es_NI": "Spanish (Nicaragua)", - "es_PA": "Spanish (Panama)", - "es_PE": "Spanish (Peru)", - "es_PR": "Spanish (Puerto Rico)", - "es_PY": "Spanish (Paraguay)", - "es_SV": "Spanish (El Salvador)", - "es_UY": "Spanish (Uruguay)", - "es_VE": "Spanish (Venezuela)", - "et": "Estonian", - "et_EE": "Estonian (Estonia)", - "eu": "Basque", - "eu_ES": "Basque (Spain)", - "fa": "Farsi", - "fa_IR": "Farsi (Iran)", - "fi": "Finnish", - "fi_FI": "Finnish (Finland)", - "fo": "Faroese", - "fo_FO": "Faroese (Faroe Islands)", - "fr": "French", - "fr_BE": "French (Belgium)", - "fr_CA": "French (Canada)", - "fr_CH": "French (Switzerland)", - "fr_FR": "French (France)", - "fr_LU": "French (Luxembourg)", - "fr_MC": "French (Principality of Monaco)", - "gl": "Galician", - "gl_ES": "Galician (Spain)", - "gu": "Gujarati", - "gu_IN": "Gujarati (India)", - "he": "Hebrew", - "he_IL": "Hebrew (Israel)", - "hi": "Hindi", - "hi_IN": "Hindi (India)", - "hr": "Croatian", - "hr_BA": "Croatian (Bosnia and Herzegovina)", - "hr_HR": "Croatian (Croatia)", - "hu": "Hungarian", - "hu_HU": "Hungarian (Hungary)", - "hy": "Armenian", - "hy_AM": "Armenian (Armenia)", - "id": "Indonesian", - "id_ID": "Indonesian (Indonesia)", - "in_ID": "Indonesien (Indonesia)", - "ig_NG": "Igbo (Nigeria)", - "is": "Icelandic", - "is_IS": "Icelandic (Iceland)", - "it": "Italian", - "it_CH": "Italian (Switzerland)", - "it_IT": "Italian (Italy)", - "iw_IL": "Hebrew (Israel)", - "ja": "Japanese", - "ja_JP": "Japanese (Japan)", - "ka": "Georgian", - "ka_GE": "Georgian (Georgia)", - "kk": "Kazakh", - "kk_KZ": "Kazakh (Kazakhstan)", - "kn": "Kannada", - "kn_IN": "Kannada (India)", - "ko": "Korean", - "ko_KR": "Korean (Korea)", - "kok": "Konkani", - "kok_IN": "Konkani (India)", - "ky": "Kyrgyz", - "ky_KG": "Kyrgyz (Kyrgyzstan)", - "lt": "Lithuanian", - "lt_LT": "Lithuanian (Lithuania)", - "lv": "Latvian", - "lv_LV": "Latvian (Latvia)", - "mi": "Maori", - "mi_NZ": "Maori (New Zealand)", - "mk": "FYRO Macedonian", - "mk_MK": "FYRO Macedonian (Former Yugoslav Republic of Macedonia)", - "mn": "Mongolian", - "mn_MN": "Mongolian (Mongolia)", - "mr": "Marathi", - "mr_IN": "Marathi (India)", - "ms": "Malay", - "ms_BN": "Malay (Brunei Darussalam)", - "ms_MY": "Malay (Malaysia)", - "mt": "Maltese", - "mt_MT": "Maltese (Malta)", - "nb": "Norwegian (Bokm?l)", - "nb_NO": "Norwegian (Bokm?l) (Norway)", - "nl": "Dutch", - "nl_BE": "Dutch (Belgium)", - "nl_NL": "Dutch (Netherlands)", - "nn_NO": "Norwegian (Nynorsk) (Norway)", - "ns": "Northern Sotho", - "ns_ZA": "Northern Sotho (South Africa)", - "pa": "Punjabi", - "pa_IN": "Punjabi (India)", - "pl": "Polish", - "pl_PL": "Polish (Poland)", - "ps": "Pashto", - "ps_AR": "Pashto (Afghanistan)", - "pt": "Portuguese", - "pt_BR": "Portuguese (Brazil)", - "pt_PT": "Portuguese (Portugal)", - "qu": "Quechua", - "qu_BO": "Quechua (Bolivia)", - "qu_EC": "Quechua (Ecuador)", - "qu_PE": "Quechua (Peru)", - "ro": "Romanian", - "ro_RO": "Romanian (Romania)", - "ru": "Russian", - "ru_RU": "Russian (Russia)", - "sa": "Sanskrit", - "sa_IN": "Sanskrit (India)", - "sd_PK": "Sindh (Pakistan)", - "se": "Sami (Northern)", - "se_FI": "Sami (Inari) (Finland)", - "se_NO": "Sami (Southern) (Norway)", - "se_SE": "Sami (Southern) (Sweden)", - "sk": "Slovak", - "sk_SK": "Slovak (Slovakia)", - "sl": "Slovenian", - "sl_SI": "Slovenian (Slovenia)", - "sq": "Albanian", - "sq_AL": "Albanian (Albania)", - "sr_BA": "Serbian (Cyrillic) (Bosnia and Herzegovina)", - "sr_SP": "Serbian (Cyrillic) (Serbia and Montenegro)", - "sr_CS": "Serbian (Latin)", - "si_LK": "Sinhala (Sri Lanka)", - "sv": "Swedish", - "sv_FI": "Swedish (Finland)", - "sv_SE": "Swedish (Sweden)", - "sw": "Swahili", - "sw_KE": "Swahili (Kenya)", - "syr": "Syriac", - "syr_SY": "Syriac (Syria)", - "ta": "Tamil", - "ta_IN": "Tamil (India)", - "te": "Telugu", - "te_IN": "Telugu (India)", - "th": "Thai", - "th_TH": "Thai (Thailand)", - "tl": "Tagalog", - "tl_PH": "Tagalog (Philippines)", - "tn": "Tswana", - "tn_ZA": "Tswana (South Africa)", - "tr": "Turkish", - "tr_TR": "Turkish (Turkey)", - "tt": "Tatar", - "tt_RU": "Tatar (Russia)", - "ts": "Tsonga", - "tw_TW": "Twi", - "uk": "Ukrainian", - "uk_UA": "Ukrainian (Ukraine)", - "ur": "Urdu", - "ur_PK": "Urdu (Islamic Republic of Pakistan)", - "uz": "Uzbek (Latin)", - "uz_UZ": "Uzbek (Cyrillic) (Uzbekistan)", - "vi": "Vietnamese", - "vi_VN": "Vietnamese (Viet Nam)", - "xh": "Xhosa", - "xh_ZA": "Xhosa (South Africa)", - "zh": "Chinese", - "zh_CN": "Chinese (S)", - "zh_HK": "Chinese (Hong Kong)", - "zh_MO": "Chinese (Macau)", - "zh_SG": "Chinese (Singapore)", - "zh_TW": "Chinese (T)", - "zu": "Zulu", - "zu_ZA": "Zulu (South Africa)", - "bn_BD": "Bengali", - "fa_AF": "Persian", - "ha_HG": "Hausa", - "ml_IN": "Malayalam", - "no_NO": "Norwegian", - "ps_AF": "Pushto" + af: 'Afrikaans', + af_ZA: 'Afrikaans (South Africa)', + ar: 'Arabic', + ar_AE: 'Arabic (U.A.E.)', + ar_BH: 'Arabic (Bahrain)', + ar_DZ: 'Arabic (Algeria)', + ar_EG: 'Arabic (Egypt)', + ar_IQ: 'Arabic (Iraq)', + ar_JO: 'Arabic (Jordan)', + ar_KW: 'Arabic (Kuwait)', + ar_LB: 'Arabic (Lebanon)', + ar_LY: 'Arabic (Libya)', + ar_MA: 'Arabic (Morocco)', + ar_OM: 'Arabic (Oman)', + ar_QA: 'Arabic (Qatar)', + ar_SA: 'Arabic (Saudi Arabia)', + ar_SY: 'Arabic (Syria)', + ar_TN: 'Arabic (Tunisia)', + ar_YE: 'Arabic (Yemen)', + az: 'Azeri (Latin)', + az_AZ: 'Azeri (Cyrillic) (Azerbaijan)', + be: 'Belarusian', + be_BY: 'Belarusian (Belarus)', + bg: 'Bulgarian', + bg_BG: 'Bulgarian (Bulgaria)', + bs_BA: 'Bosnian (Bosnia and Herzegovina)', + ca: 'Catalan', + ca_ES: 'Catalan (Spain)', + cs: 'Czech', + cs_CZ: 'Czech (Czech Republic)', + cy: 'Welsh', + cy_GB: 'Welsh (United Kingdom)', + da: 'Danish', + da_DK: 'Danish (Denmark)', + de: 'German', + de_AT: 'German (Austria)', + de_CH: 'German (Switzerland)', + de_DE: 'German (Germany)', + de_LI: 'German (Liechtenstein)', + de_LU: 'German (Luxembourg)', + dv: 'Divehi', + dv_MV: 'Divehi (Maldives)', + el: 'Greek', + el_GR: 'Greek (Greece)', + en: 'English', + en_AU: 'English (Australia)', + en_BZ: 'English (Belize)', + en_CA: 'English (Canada)', + en_CB: 'English (Caribbean)', + en_GB: 'English (United Kingdom)', + en_IE: 'English (Ireland)', + en_JM: 'English (Jamaica)', + en_NZ: 'English (New Zealand)', + en_PH: 'English (Republic of the Philippines)', + en_TT: 'English (Trinidad and Tobago)', + en_US: 'English (United States)', + en_ZA: 'English (South Africa)', + en_ZW: 'English (Zimbabwe)', + eo: 'Esperanto', + es: 'Spanish', + es_AR: 'Spanish (Argentina)', + es_BO: 'Spanish (Bolivia)', + es_CL: 'Spanish (Chile)', + es_CO: 'Spanish (Colombia)', + es_CR: 'Spanish (Costa Rica)', + es_DO: 'Spanish (Dominican Republic)', + es_EC: 'Spanish (Ecuador)', + es_ES: 'Spanish (Spain)', + es_GT: 'Spanish (Guatemala)', + es_HN: 'Spanish (Honduras)', + es_MX: 'Spanish (Mexico)', + es_NI: 'Spanish (Nicaragua)', + es_PA: 'Spanish (Panama)', + es_PE: 'Spanish (Peru)', + es_PR: 'Spanish (Puerto Rico)', + es_PY: 'Spanish (Paraguay)', + es_SV: 'Spanish (El Salvador)', + es_UY: 'Spanish (Uruguay)', + es_VE: 'Spanish (Venezuela)', + et: 'Estonian', + et_EE: 'Estonian (Estonia)', + eu: 'Basque', + eu_ES: 'Basque (Spain)', + fa: 'Farsi', + fa_IR: 'Farsi (Iran)', + fi: 'Finnish', + fi_FI: 'Finnish (Finland)', + fo: 'Faroese', + fo_FO: 'Faroese (Faroe Islands)', + fr: 'French', + fr_BE: 'French (Belgium)', + fr_CA: 'French (Canada)', + fr_CH: 'French (Switzerland)', + fr_FR: 'French (France)', + fr_LU: 'French (Luxembourg)', + fr_MC: 'French (Principality of Monaco)', + gl: 'Galician', + gl_ES: 'Galician (Spain)', + gu: 'Gujarati', + gu_IN: 'Gujarati (India)', + he: 'Hebrew', + he_IL: 'Hebrew (Israel)', + hi: 'Hindi', + hi_IN: 'Hindi (India)', + hr: 'Croatian', + hr_BA: 'Croatian (Bosnia and Herzegovina)', + hr_HR: 'Croatian (Croatia)', + hu: 'Hungarian', + hu_HU: 'Hungarian (Hungary)', + hy: 'Armenian', + hy_AM: 'Armenian (Armenia)', + id: 'Indonesian', + id_ID: 'Indonesian (Indonesia)', + in_ID: 'Indonesien (Indonesia)', + ig_NG: 'Igbo (Nigeria)', + is: 'Icelandic', + is_IS: 'Icelandic (Iceland)', + it: 'Italian', + it_CH: 'Italian (Switzerland)', + it_IT: 'Italian (Italy)', + iw_IL: 'Hebrew (Israel)', + ja: 'Japanese', + ja_JP: 'Japanese (Japan)', + ka: 'Georgian', + ka_GE: 'Georgian (Georgia)', + kk: 'Kazakh', + kk_KZ: 'Kazakh (Kazakhstan)', + kn: 'Kannada', + kn_IN: 'Kannada (India)', + ko: 'Korean', + ko_KR: 'Korean (Korea)', + kok: 'Konkani', + kok_IN: 'Konkani (India)', + ky: 'Kyrgyz', + ky_KG: 'Kyrgyz (Kyrgyzstan)', + lt: 'Lithuanian', + lt_LT: 'Lithuanian (Lithuania)', + lv: 'Latvian', + lv_LV: 'Latvian (Latvia)', + mi: 'Maori', + mi_NZ: 'Maori (New Zealand)', + mk: 'FYRO Macedonian', + mk_MK: 'FYRO Macedonian (Former Yugoslav Republic of Macedonia)', + mn: 'Mongolian', + mn_MN: 'Mongolian (Mongolia)', + mr: 'Marathi', + mr_IN: 'Marathi (India)', + ms: 'Malay', + ms_BN: 'Malay (Brunei Darussalam)', + ms_MY: 'Malay (Malaysia)', + mt: 'Maltese', + mt_MT: 'Maltese (Malta)', + nb: 'Norwegian (Bokm?l)', + nb_NO: 'Norwegian (Bokm?l) (Norway)', + nl: 'Dutch', + nl_BE: 'Dutch (Belgium)', + nl_NL: 'Dutch (Netherlands)', + nn_NO: 'Norwegian (Nynorsk) (Norway)', + ns: 'Northern Sotho', + ns_ZA: 'Northern Sotho (South Africa)', + pa: 'Punjabi', + pa_IN: 'Punjabi (India)', + pl: 'Polish', + pl_PL: 'Polish (Poland)', + ps: 'Pashto', + ps_AR: 'Pashto (Afghanistan)', + pt: 'Portuguese', + pt_BR: 'Portuguese (Brazil)', + pt_PT: 'Portuguese (Portugal)', + qu: 'Quechua', + qu_BO: 'Quechua (Bolivia)', + qu_EC: 'Quechua (Ecuador)', + qu_PE: 'Quechua (Peru)', + ro: 'Romanian', + ro_RO: 'Romanian (Romania)', + ru: 'Russian', + ru_RU: 'Russian (Russia)', + sa: 'Sanskrit', + sa_IN: 'Sanskrit (India)', + sd_PK: 'Sindh (Pakistan)', + se: 'Sami (Northern)', + se_FI: 'Sami (Inari) (Finland)', + se_NO: 'Sami (Southern) (Norway)', + se_SE: 'Sami (Southern) (Sweden)', + sk: 'Slovak', + sk_SK: 'Slovak (Slovakia)', + sl: 'Slovenian', + sl_SI: 'Slovenian (Slovenia)', + sq: 'Albanian', + sq_AL: 'Albanian (Albania)', + sr_BA: 'Serbian (Cyrillic) (Bosnia and Herzegovina)', + sr_SP: 'Serbian (Cyrillic) (Serbia and Montenegro)', + sr_CS: 'Serbian (Latin)', + si_LK: 'Sinhala (Sri Lanka)', + sv: 'Swedish', + sv_FI: 'Swedish (Finland)', + sv_SE: 'Swedish (Sweden)', + sw: 'Swahili', + sw_KE: 'Swahili (Kenya)', + syr: 'Syriac', + syr_SY: 'Syriac (Syria)', + ta: 'Tamil', + ta_IN: 'Tamil (India)', + te: 'Telugu', + te_IN: 'Telugu (India)', + th: 'Thai', + th_TH: 'Thai (Thailand)', + tl: 'Tagalog', + tl_PH: 'Tagalog (Philippines)', + tn: 'Tswana', + tn_ZA: 'Tswana (South Africa)', + tr: 'Turkish', + tr_TR: 'Turkish (Turkey)', + tt: 'Tatar', + tt_RU: 'Tatar (Russia)', + ts: 'Tsonga', + tw_TW: 'Twi', + uk: 'Ukrainian', + uk_UA: 'Ukrainian (Ukraine)', + ur: 'Urdu', + ur_PK: 'Urdu (Islamic Republic of Pakistan)', + uz: 'Uzbek (Latin)', + uz_UZ: 'Uzbek (Cyrillic) (Uzbekistan)', + vi: 'Vietnamese', + vi_VN: 'Vietnamese (Viet Nam)', + xh: 'Xhosa', + xh_ZA: 'Xhosa (South Africa)', + zh: 'Chinese', + zh_CN: 'Chinese (S)', + zh_HK: 'Chinese (Hong Kong)', + zh_MO: 'Chinese (Macau)', + zh_SG: 'Chinese (Singapore)', + zh_TW: 'Chinese (T)', + zu: 'Zulu', + zu_ZA: 'Zulu (South Africa)', + bn_BD: 'Bengali', + fa_AF: 'Persian', + ha_HG: 'Hausa', + ml_IN: 'Malayalam', + no_NO: 'Norwegian', + ps_AF: 'Pushto' }; -module.exports = { locales }; \ No newline at end of file +module.exports = { locales }; diff --git a/src/css/share.css b/src/css/share.css index 8674e91c..63ba2365 100644 --- a/src/css/share.css +++ b/src/css/share.css @@ -1,112 +1,118 @@ -.card { - border-radius: 0; - box-shadow: 0 2px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 4px 0 rgba(0, 0, 0, .12); -} - -.card-header { - background: none; - font-size: .9rem; - border-bottom: 0; -} - -.card-header.collapsed { - border-bottom: 2px solid #eee; -} - -.card-body { - padding: 0; -} - -.card-body .card-header { - font-size: .8rem; - padding-left: 3.5em; -} - -.card-body .card-body { - padding: 0; -} - -.card-header[aria-expanded="true"], .collapse.show .card-header, .collapse.show .card-body { - background: rgba(0, 0, 0, .04); - transition: .5s background ease; -} - -.catro-tabs .nav-tabs { - padding: 0; - border-bottom: 1px solid #e0e0e0; - background: rgba(0, 0, 0, .04); -} - -.catro-tabs .nav-link { - text-decoration: none; - padding: .9em; - border: 0; - color: rgba(0, 0, 0, .8); - font-size: .8em; -} - -.catro-tabs .nav-link.active { - font-weight: 700; - border-bottom: 2px solid #00acc1; - color: black; - background: none; -} - -img { - border-radius: 10%; -} - -.list-group-item { - font-size: .8em; - border-bottom: 0; - background: none; - display: flex; - align-items: center; -} - -.tab-pane { - background: none; -} - -.material-icons { - vertical-align: middle; -} - -.blocklyText { - fill: #fff; - font-family: "Helvetica Neue", "Segoe UI", Helvetica, sans-serif; - font-size: 12pt; - font-weight: bold; -} - -.blocklyNonEditableText>rect:not(.blocklyDropdownRect), .blocklyEditableText>rect:not(.blocklyDropdownRect) { - fill: #fff; -} - -.blocklyNonEditableText>text, .blocklyEditableText>text, .blocklyNonEditableText>g>text, .blocklyEditableText>g>text { - fill: #575E75; -} - -.blocklyDropdownText { - fill: #fff !important; -} - -.card-header { - cursor: pointer; -} - -.catblocks-script { - padding: 0 20px; -} - -.catblocks-script+.catblocks-script { - margin-top: 20px; -} - -.catblocks-empty-text { - padding: 20px; -} - -.catblocks-object-sound-item { - width: 100%; -} \ No newline at end of file +.card { + border-radius: 0; + box-shadow: 0 2px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 4px 0 rgba(0, 0, 0, 0.12); +} + +.card-header { + background: none; + font-size: 0.9rem; + border-bottom: 0; +} + +.card-header.collapsed { + border-bottom: 2px solid #eee; +} + +.card-body { + padding: 0; +} + +.card-body .card-header { + font-size: 0.8rem; + padding-left: 3.5em; +} + +.card-body .card-body { + padding: 0; +} + +.card-header[aria-expanded='true'], +.collapse.show .card-header, +.collapse.show .card-body { + background: rgba(0, 0, 0, 0.04); + transition: 0.5s background ease; +} + +.catro-tabs .nav-tabs { + padding: 0; + border-bottom: 1px solid #e0e0e0; + background: rgba(0, 0, 0, 0.04); +} + +.catro-tabs .nav-link { + text-decoration: none; + padding: 0.9em; + border: 0; + color: rgba(0, 0, 0, 0.8); + font-size: 0.8em; +} + +.catro-tabs .nav-link.active { + font-weight: 700; + border-bottom: 2px solid #00acc1; + color: black; + background: none; +} + +img { + border-radius: 10%; +} + +.list-group-item { + font-size: 0.8em; + border-bottom: 0; + background: none; + display: flex; + align-items: center; +} + +.tab-pane { + background: none; +} + +.material-icons { + vertical-align: middle; +} + +.blocklyText { + fill: #fff; + font-family: 'Helvetica Neue', 'Segoe UI', Helvetica, sans-serif; + font-size: 12pt; + font-weight: bold; +} + +.blocklyNonEditableText > rect:not(.blocklyDropdownRect), +.blocklyEditableText > rect:not(.blocklyDropdownRect) { + fill: #fff; +} + +.blocklyNonEditableText > text, +.blocklyEditableText > text, +.blocklyNonEditableText > g > text, +.blocklyEditableText > g > text { + fill: #575e75; +} + +.blocklyDropdownText { + fill: #fff !important; +} + +.card-header { + cursor: pointer; +} + +.catblocks-script { + padding: 0 20px; +} + +.catblocks-script + .catblocks-script { + margin-top: 20px; +} + +.catblocks-empty-text { + padding: 20px; +} + +.catblocks-object-sound-item { + width: 100%; +} diff --git a/src/css/style.css b/src/css/style.css index 1b96790f..914a8025 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -1,4 +1,5 @@ -html, body { +html, +body { padding: 0; margin: 0; box-sizing: border-box; @@ -28,7 +29,7 @@ h1 { margin-left: 10px; } -#collaborators>img { +#collaborators > img { margin-right: 5px; height: 30px; padding-bottom: 5px; @@ -54,8 +55,8 @@ h1 { height: 50%; outline: 4px dashed darkgreen; outline-offset: -15px; - -webkit-transition: outline-offset .15s ease-in-out, background-color .15s linear; - transition: outline-offset .15s ease-in-out, background-color .15s linear; + -webkit-transition: outline-offset 0.15s ease-in-out, background-color 0.15s linear; + transition: outline-offset 0.15s ease-in-out, background-color 0.15s linear; } #catblocks-file-dropper.hover { @@ -117,7 +118,7 @@ h1 { right: 0; width: 100%; height: 100%; - background: rgba(0,0,0,0.3); + background: rgba(0, 0, 0, 0.3); display: none; } @@ -140,15 +141,18 @@ h1 { } @keyframes spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } } .hidden { display: none; } - /* message box */ .message-box { position: fixed; @@ -167,7 +171,7 @@ h1 { background-color: #f5faff; border-color: #0a6ed1; color: #32363a; - box-shadow: 0 0 0 0.0625rem rgba(0,0,0,0.42), 0 0.625rem 1.875rem 0 rgba(0,0,0,0.3); + box-shadow: 0 0 0 0.0625rem rgba(0, 0, 0, 0.42), 0 0.625rem 1.875rem 0 rgba(0, 0, 0, 0.3); font-size: 0.9em; } @@ -177,7 +181,6 @@ h1 { padding: 0; } - .message-box li { padding: 5px; -} \ No newline at end of file +} diff --git a/src/html/testing.html b/src/html/testing.html index b3d1faca..909f8f08 100644 --- a/src/html/testing.html +++ b/src/html/testing.html @@ -1,22 +1,21 @@ + + + + Testing Page + - - - - Testing Page - - - -
-
-

Playground testing

-
-
-
-

Share testing

-
-
-
- - \ No newline at end of file + +
+
+

Playground testing

+
+
+
+

Share testing

+
+
+
+ + diff --git a/src/js/blocks/bricks.js b/src/js/blocks/bricks.js index 5d131a30..9be9d445 100644 --- a/src/js/blocks/bricks.js +++ b/src/js/blocks/bricks.js @@ -3,8 +3,8 @@ * @author andreas.karner@student.tugraz.at */ -import Blockly from "blockly"; -import categories from "./categories"; +import Blockly from 'blockly'; +import categories from './categories'; /** * Remove all bricks from Blockly instance @@ -26,11 +26,22 @@ const removeAllBricks = (blockly = Blockly) => { * Shape bricks extention */ const shapeBricksExtention = () => { - return function() { + return function () { const blockName = this.type; // TODO: please find a better logic than this - if (['WhenClonedScript', 'StartScript', 'WhenScript', 'WhenTouchDownScript', 'BroadcastScript', 'WhenConditionScript', - 'WhenBounceOffScript', 'WhenBackgroundChangesScript', 'WhenRaspiPinChangedBrick'].includes(blockName)) { + if ( + [ + 'WhenClonedScript', + 'StartScript', + 'WhenScript', + 'WhenTouchDownScript', + 'BroadcastScript', + 'WhenConditionScript', + 'WhenBounceOffScript', + 'WhenBackgroundChangesScript', + 'WhenRaspiPinChangedBrick' + ].includes(blockName) + ) { this.hat = 'cap'; } else { this.setPreviousStatement(true, null); @@ -41,7 +52,7 @@ const shapeBricksExtention = () => { /** * Load all bricks from cats into Blockly - * @param {*} cats + * @param {*} cats * @param {*} blockly */ const loadBricks = (cats = categories, blockly = Blockly) => { @@ -62,7 +73,7 @@ const loadBricks = (cats = categories, blockly = Blockly) => { blockly.Bricks[brickName] = brickBody; blockly.Categories[catName].push(brickName); blockly.Blocks[brickName] = { - init: function() { + init: function () { this.jsonInit(blockly.Bricks[brickName]); } }; @@ -72,7 +83,7 @@ const loadBricks = (cats = categories, blockly = Blockly) => { /** * Init bricks for blockly - * @param {*} blockly + * @param {*} blockly */ const initBricks = (blockly = Blockly) => { removeAllBricks(blockly); @@ -84,4 +95,4 @@ const initBricks = (blockly = Blockly) => { */ (() => { initBricks(); -})(); \ No newline at end of file +})(); diff --git a/src/js/blocks/categories/arduino.js b/src/js/blocks/categories/arduino.js index 9a9da2d9..2e28ffa0 100644 --- a/src/js/blocks/categories/arduino.js +++ b/src/js/blocks/categories/arduino.js @@ -5,34 +5,34 @@ 'use strict'; export default { - "ArduinoSendDigitalValueBrick": { - "message0": "%{BKY_ARDUINO_SENDDIGITALVALUE}", - "args0": [ + ArduinoSendDigitalValueBrick: { + message0: '%{BKY_ARDUINO_SENDDIGITALVALUE}', + args0: [ { - "type": "field_input", - "name": "ARDUINO_DIGITAL_PIN_NUMBER", - "text": "unset" + type: 'field_input', + name: 'ARDUINO_DIGITAL_PIN_NUMBER', + text: 'unset' }, { - "type": "field_input", - "name": "ARDUINO_DIGITAL_PIN_VALUE", - "text": "unset" + type: 'field_input', + name: 'ARDUINO_DIGITAL_PIN_VALUE', + text: 'unset' } ] }, - "ArduinoSendPWMValueBrick": { - "message0": "%{BKY_ARDUINO_SENDPWMALVALUE}", - "args0": [ + ArduinoSendPWMValueBrick: { + message0: '%{BKY_ARDUINO_SENDPWMALVALUE}', + args0: [ { - "type": "field_input", - "name": "ARDUINO_ANALOG_PIN_NUMBER", - "text": "unset" + type: 'field_input', + name: 'ARDUINO_ANALOG_PIN_NUMBER', + text: 'unset' }, { - "type": "field_input", - "name": "ARDUINO_ANALOG_PIN_VALUE", - "text": "unset" + type: 'field_input', + name: 'ARDUINO_ANALOG_PIN_VALUE', + text: 'unset' } ] } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/control.js b/src/js/blocks/categories/control.js index 6ab65361..83243fbd 100644 --- a/src/js/blocks/categories/control.js +++ b/src/js/blocks/categories/control.js @@ -5,204 +5,204 @@ 'use strict'; export default { - "ForeverBrick": { - "message0": "%{BKY_CONTROL_FOREVER}", - "message1": "%1", - "message2": "%1", - "lastDummyAlign2": "RIGHT", - "args1": [ + ForeverBrick: { + message0: '%{BKY_CONTROL_FOREVER}', + message1: '%1', + message2: '%1', + lastDummyAlign2: 'RIGHT', + args1: [ { - "type": "input_statement", - "name": "SUBSTACK" + type: 'input_statement', + name: 'SUBSTACK' } ], - "args2": [ + args2: [ { - "type": "field_image", - "src": `${document.location.pathname}media/repeat.svg`, - "height": 24, - "width": 24, - "alt": "*", - "flip_rtl": true + type: 'field_image', + src: `${document.location.pathname}media/repeat.svg`, + height: 24, + width: 24, + alt: '*', + flip_rtl: true } ] }, - "WaitBrick": { - "message0": "%{BKY_CONTROL_WAIT}", - "args0": [ + WaitBrick: { + message0: '%{BKY_CONTROL_WAIT}', + args0: [ { - "type": "field_input", - "name": "TIME_TO_WAIT_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'TIME_TO_WAIT_IN_SECONDS', + text: 'unset' } ] }, - "NoteBrick": { - "message0": "%{BKY_CONTROL_NOTE}", - "args0": [ + NoteBrick: { + message0: '%{BKY_CONTROL_NOTE}', + args0: [ { - "type": "field_input", - "name": "NOTE", - "text": "unset" + type: 'field_input', + name: 'NOTE', + text: 'unset' } ] }, - "IfLogicBeginBrick": { - "type": "IfThenLogicBeginBrick", - "message0": "%{BKY_CONTROL_IFISTRUEELSEIF}", - "message1": "%1", - "message2": "%{BKY_CONTROL_IFISTRUEELSEELSE}", - "message3": "%1", - "args0": [ - { - "type": "field_input", - "name": "IF_CONDITION", - "text": "unset" + IfLogicBeginBrick: { + type: 'IfThenLogicBeginBrick', + message0: '%{BKY_CONTROL_IFISTRUEELSEIF}', + message1: '%1', + message2: '%{BKY_CONTROL_IFISTRUEELSEELSE}', + message3: '%1', + args0: [ + { + type: 'field_input', + name: 'IF_CONDITION', + text: 'unset' } ], - "args1": [ + args1: [ { - "type": "input_statement", - "name": "SUBSTACK" + type: 'input_statement', + name: 'SUBSTACK' } ], - "args3": [ + args3: [ { - "type": "input_statement", - "name": "SUBSTACK2" + type: 'input_statement', + name: 'SUBSTACK2' } ] }, - "IfThenLogicBeginBrick": { - "type": "IfLogicBeginBrick", - "message0": "%{BKY_CONTROL_IFISTRUEELSEIF}", - "message1": "%1", - "args0": [ + IfThenLogicBeginBrick: { + type: 'IfLogicBeginBrick', + message0: '%{BKY_CONTROL_IFISTRUEELSEIF}', + message1: '%1', + args0: [ { - "type": "field_input", - "name": "IF_CONDITION", - "text": "unset" + type: 'field_input', + name: 'IF_CONDITION', + text: 'unset' } ], - "args1": [ + args1: [ { - "type": "input_statement", - "name": "SUBSTACK" + type: 'input_statement', + name: 'SUBSTACK' } ] }, - "WaitUntilBrick": { - "message0": "%{BKY_CONTROL_WAITUNTILTRUE}", - "args0": [ + WaitUntilBrick: { + message0: '%{BKY_CONTROL_WAITUNTILTRUE}', + args0: [ { - "type": "field_input", - "name": "IF_CONDITION", - "text": "unset" + type: 'field_input', + name: 'IF_CONDITION', + text: 'unset' } ] }, - "RepeatBrick": { - "message0": "%{BKY_CONTROL_REPEATTIMES}", - "message1": "%1", - "message2": "%1", - "lastDummyAlign2": "RIGHT", - "args0": [ + RepeatBrick: { + message0: '%{BKY_CONTROL_REPEATTIMES}', + message1: '%1', + message2: '%1', + lastDummyAlign2: 'RIGHT', + args0: [ { - "type": "field_input", - "name": "TIMES_TO_REPEAT", - "text": "unset" + type: 'field_input', + name: 'TIMES_TO_REPEAT', + text: 'unset' } ], - "args1": [ + args1: [ { - "type": "input_statement", - "name": "SUBSTACK" + type: 'input_statement', + name: 'SUBSTACK' } ], - "args2": [ + args2: [ { - "type": "field_image", - "src": `${document.location.pathname}media/repeat.svg`, - "height": 24, - "width": 24, - "alt": "*", - "flip_rtl": true + type: 'field_image', + src: `${document.location.pathname}media/repeat.svg`, + height: 24, + width: 24, + alt: '*', + flip_rtl: true } ] }, - "RepeatUntilBrick": { - "message0": "%{BKY_CONTROL_REPEATUNTILISTRUE}", - "message1": "%1", - "message2": "%1", - "lastDummyAlign2": "RIGHT", - "args0": [ + RepeatUntilBrick: { + message0: '%{BKY_CONTROL_REPEATUNTILISTRUE}', + message1: '%1', + message2: '%1', + lastDummyAlign2: 'RIGHT', + args0: [ { - "type": "field_input", - "name": "REPEAT_UNTIL_CONDITION", - "text": "unset" + type: 'field_input', + name: 'REPEAT_UNTIL_CONDITION', + text: 'unset' } ], - "args1": [ + args1: [ { - "type": "input_statement", - "name": "SUBSTACK" + type: 'input_statement', + name: 'SUBSTACK' } ], - "args2": [ + args2: [ { - "type": "field_image", - "src": `${document.location.pathname}media/repeat.svg`, - "height": 24, - "width": 24, - "alt": "*", - "flip_rtl": true + type: 'field_image', + src: `${document.location.pathname}media/repeat.svg`, + height: 24, + width: 24, + alt: '*', + flip_rtl: true } ] }, - "SceneTransitionBrick": { - "message0": "%{BKY_CONTROL_CONTINUESCENE}", - "args0": [ + SceneTransitionBrick: { + message0: '%{BKY_CONTROL_CONTINUESCENE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "SceneStartBrick": { - "message0": "%{BKY_CONTROL_STARTSCENE}", - "args0": [ + SceneStartBrick: { + message0: '%{BKY_CONTROL_STARTSCENE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "StopScriptBrick": { - "message0": "%{BKY_CONTROL_STOPCAT}", - "args0": [ + StopScriptBrick: { + message0: '%{BKY_CONTROL_STOPCAT}', + args0: [ { - "type": "field_input", - "name": "SPINNER", - "text": "unset" + type: 'field_input', + name: 'SPINNER', + text: 'unset' } ] }, - "CloneBrick": { - "message0": "%{BKY_CONTROL_CREATECLONEOFCAT}", - "args0": [ + CloneBrick: { + message0: '%{BKY_CONTROL_CREATECLONEOFCAT}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "DeleteThisCloneBrick": { - "message0": "%{BKY_CONTROL_DELETETHISCLONE}" + DeleteThisCloneBrick: { + message0: '%{BKY_CONTROL_DELETETHISCLONE}' }, - "WhenClonedScript": { - "message0": "%{BKY_CONTROL_WHENYOUSTARTASACLONE}" + WhenClonedScript: { + message0: '%{BKY_CONTROL_WHENYOUSTARTASACLONE}' } }; diff --git a/src/js/blocks/categories/data.js b/src/js/blocks/categories/data.js index f4bad3f4..8e87e798 100644 --- a/src/js/blocks/categories/data.js +++ b/src/js/blocks/categories/data.js @@ -5,189 +5,189 @@ 'use strict'; export default { - "SetVariableBrick": { - "message0": "%{BKY_DATA_SETVARIABLETOCAT}", - "args0": [ + SetVariableBrick: { + message0: '%{BKY_DATA_SETVARIABLETOCAT}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "VARIABLE", - "text": "unset" + type: 'field_input', + name: 'VARIABLE', + text: 'unset' } ] }, - "ChangeVariableBrick": { - "message0": "%{BKY_DATA_CHANGEVARIABLEBY}", - "args0": [ + ChangeVariableBrick: { + message0: '%{BKY_DATA_CHANGEVARIABLEBY}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "VARIABLE_CHANGE", - "text": "unset" + type: 'field_input', + name: 'VARIABLE_CHANGE', + text: 'unset' } ] }, - "ShowTextBrick": { - "message0": "%{BKY_DATA_SHOWVARIABLEAT}", - "args0": [ + ShowTextBrick: { + message0: '%{BKY_DATA_SHOWVARIABLEAT}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "X_POSITION", - "text": "unset" + type: 'field_input', + name: 'X_POSITION', + text: 'unset' }, { - "type": "field_input", - "name": "Y_POSITION", - "text": "unset" + type: 'field_input', + name: 'Y_POSITION', + text: 'unset' } ] }, - "ShowTextColorSizeAlignmentBrick": { - "message0": "%{BKY_DATA_SHOWVARIABLEATSIZECOLORALIGNED}", - "args0": [ + ShowTextColorSizeAlignmentBrick: { + message0: '%{BKY_DATA_SHOWVARIABLEATSIZECOLORALIGNED}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "X_POSITION", - "text": "unset" + type: 'field_input', + name: 'X_POSITION', + text: 'unset' }, { - "type": "field_input", - "name": "Y_POSITION", - "text": "unset" + type: 'field_input', + name: 'Y_POSITION', + text: 'unset' }, { - "type": "field_input", - "name": "SIZE", - "text": "unset" + type: 'field_input', + name: 'SIZE', + text: 'unset' }, { - "type": "field_input", - "name": "COLOR", - "text": "unset" + type: 'field_input', + name: 'COLOR', + text: 'unset' }, { - "type": "field_input", - "name": "ALIGNMENT", - "text": "unset" + type: 'field_input', + name: 'ALIGNMENT', + text: 'unset' } ] }, - "DeleteItemOfUserListBrick": { - "message0": "%{BKY_DATA_DELETEITEMFROMLIST}", - "args0": [ + DeleteItemOfUserListBrick: { + message0: '%{BKY_DATA_DELETEITEMFROMLIST}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "LIST_DELETE_ITEM", - "text": "unset" + type: 'field_input', + name: 'LIST_DELETE_ITEM', + text: 'unset' } ] }, - "AddItemToUserListBrick": { - "message0": "%{BKY_DATA_ADDTOLIST}", - "args0": [ + AddItemToUserListBrick: { + message0: '%{BKY_DATA_ADDTOLIST}', + args0: [ { - "type": "field_input", - "name": "LIST_ADD_ITEM", - "text": "unset" + type: 'field_input', + name: 'LIST_ADD_ITEM', + text: 'unset' }, { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "InsertItemIntoUserListBrick": { - "message0": "%{BKY_DATA_INSERTINTOLIST}", - "args0": [ + InsertItemIntoUserListBrick: { + message0: '%{BKY_DATA_INSERTINTOLIST}', + args0: [ { - "type": "field_input", - "name": "INSERT_ITEM_INTO_USERLIST_VALUE", - "text": "unset" + type: 'field_input', + name: 'INSERT_ITEM_INTO_USERLIST_VALUE', + text: 'unset' }, { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "INSERT_ITEM_INTO_USERLIST_INDEX", - "text": "unset" + type: 'field_input', + name: 'INSERT_ITEM_INTO_USERLIST_INDEX', + text: 'unset' } ] }, - "ReplaceItemInUserListBrick": { - "message0": "%{BKY_DATA_REPLACEITEMINLIST}", - "args0": [ + ReplaceItemInUserListBrick: { + message0: '%{BKY_DATA_REPLACEITEMINLIST}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "REPLACE_ITEM_IN_USERLIST_INDEX", - "text": "unset" + type: 'field_input', + name: 'REPLACE_ITEM_IN_USERLIST_INDEX', + text: 'unset' }, { - "type": "field_input", - "name": "REPLACE_ITEM_IN_USERLIST_VALUE", - "text": "unset" + type: 'field_input', + name: 'REPLACE_ITEM_IN_USERLIST_VALUE', + text: 'unset' } ] }, - "HideTextBrick": { - "message0": "%{BKY_DATA_HIDEVARIABLE}", - "args0": [ + HideTextBrick: { + message0: '%{BKY_DATA_HIDEVARIABLE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "ReadVariableFromDeviceBrick": { - "message0": "%{BKY_DATA_READVARIABLE}", - "args0": [ + ReadVariableFromDeviceBrick: { + message0: '%{BKY_DATA_READVARIABLE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "WriteVariableOnDeviceBrick": { - "message0": "%{BKY_DATA_WRITEVARIABLE}", - "args0": [ + WriteVariableOnDeviceBrick: { + message0: '%{BKY_DATA_WRITEVARIABLE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/drone.js b/src/js/blocks/categories/drone.js index 5315ae42..de45aec2 100644 --- a/src/js/blocks/categories/drone.js +++ b/src/js/blocks/categories/drone.js @@ -5,146 +5,146 @@ 'use strict'; export default { - "DroneTakeOffLandBrick": { - "message0": "%{BKY_DRONE_TAKEOFFLAND}" + DroneTakeOffLandBrick: { + message0: '%{BKY_DRONE_TAKEOFFLAND}' }, - "DroneEmergencyBrick": { - "message0": "%{BKY_DRONE_EMERGENCY}" + DroneEmergencyBrick: { + message0: '%{BKY_DRONE_EMERGENCY}' }, - "DroneMoveUpBrick": { - "message0": "%{BKY_DRONE_MOVEUP}", - "args0": [ + DroneMoveUpBrick: { + message0: '%{BKY_DRONE_MOVEUP}', + args0: [ { - "type": "field_input", - "name": "DRONE_TIME_TO_FLY_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DRONE_TIME_TO_FLY_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "DRONE_POWER_IN_PERCENT", - "text": "unset" + type: 'field_input', + name: 'DRONE_POWER_IN_PERCENT', + text: 'unset' } ] }, - "DroneMoveDownBrick": { - "message0": "%{BKY_DRONE_MOVEDOWN}", - "args0": [ + DroneMoveDownBrick: { + message0: '%{BKY_DRONE_MOVEDOWN}', + args0: [ { - "type": "field_input", - "name": "DRONE_TIME_TO_FLY_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DRONE_TIME_TO_FLY_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "DRONE_POWER_IN_PERCENT", - "text": "unset" + type: 'field_input', + name: 'DRONE_POWER_IN_PERCENT', + text: 'unset' } ] }, - "DroneMoveLeftBrick": { - "message0": "%{BKY_DRONE_MOVELEFT}", - "args0": [ + DroneMoveLeftBrick: { + message0: '%{BKY_DRONE_MOVELEFT}', + args0: [ { - "type": "field_input", - "name": "DRONE_TIME_TO_FLY_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DRONE_TIME_TO_FLY_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "DRONE_POWER_IN_PERCENT", - "text": "unset" + type: 'field_input', + name: 'DRONE_POWER_IN_PERCENT', + text: 'unset' } ] }, - "DroneMoveRightBrick": { - "message0": "%{BKY_DRONE_MOVERIGHT}", - "args0": [ + DroneMoveRightBrick: { + message0: '%{BKY_DRONE_MOVERIGHT}', + args0: [ { - "type": "field_input", - "name": "DRONE_TIME_TO_FLY_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DRONE_TIME_TO_FLY_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "DRONE_POWER_IN_PERCENT", - "text": "unset" + type: 'field_input', + name: 'DRONE_POWER_IN_PERCENT', + text: 'unset' } ] }, - "DroneMoveForwardBrick": { - "message0": "%{BKY_DRONE_MOVEFORWARD}", - "args0": [ + DroneMoveForwardBrick: { + message0: '%{BKY_DRONE_MOVEFORWARD}', + args0: [ { - "type": "field_input", - "name": "DRONE_TIME_TO_FLY_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DRONE_TIME_TO_FLY_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "DRONE_POWER_IN_PERCENT", - "text": "unset" + type: 'field_input', + name: 'DRONE_POWER_IN_PERCENT', + text: 'unset' } ] }, - "DroneMoveBackwardBrick": { - "message0": "%{BKY_DRONE_MOVEBACKWARD}", - "args0": [ + DroneMoveBackwardBrick: { + message0: '%{BKY_DRONE_MOVEBACKWARD}', + args0: [ { - "type": "field_input", - "name": "DRONE_TIME_TO_FLY_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DRONE_TIME_TO_FLY_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "DRONE_POWER_IN_PERCENT", - "text": "unset" + type: 'field_input', + name: 'DRONE_POWER_IN_PERCENT', + text: 'unset' } ] }, - "DroneTurnLeftBrick": { - "message0": "%{BKY_DRONE_TURNLEFT}", - "args0": [ + DroneTurnLeftBrick: { + message0: '%{BKY_DRONE_TURNLEFT}', + args0: [ { - "type": "field_input", - "name": "DRONE_TIME_TO_FLY_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DRONE_TIME_TO_FLY_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "DRONE_POWER_IN_PERCENT", - "text": "unset" + type: 'field_input', + name: 'DRONE_POWER_IN_PERCENT', + text: 'unset' } ] }, - "DroneTurnRightBrick": { - "message0": "%{BKY_DRONE_TURNRIGHT}", - "args0": [ + DroneTurnRightBrick: { + message0: '%{BKY_DRONE_TURNRIGHT}', + args0: [ { - "type": "field_input", - "name": "DRONE_TIME_TO_FLY_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DRONE_TIME_TO_FLY_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "DRONE_POWER_IN_PERCENT", - "text": "unset" + type: 'field_input', + name: 'DRONE_POWER_IN_PERCENT', + text: 'unset' } ] }, - "DroneFlipBrick": { - "message0": "%{BKY_DRONE_FLIP}" + DroneFlipBrick: { + message0: '%{BKY_DRONE_FLIP}' }, - "DronePlayLedAnimationBrick": { - "message0": "%{BKY_DRONE_PLAYLEDANIMATION}", - "args0": [ + DronePlayLedAnimationBrick: { + message0: '%{BKY_DRONE_PLAYLEDANIMATION}', + args0: [ { - "type": "field_input", - "name": "ADRONEANIMATION", - "text": "unset" + type: 'field_input', + name: 'ADRONEANIMATION', + text: 'unset' } ] }, - "DroneSwitchCameraBrick": { - "message0": "%{BKY_DRONE_SWITCHCAMERA}" + DroneSwitchCameraBrick: { + message0: '%{BKY_DRONE_SWITCHCAMERA}' } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/event.js b/src/js/blocks/categories/event.js index 7e0083ee..b820c10a 100644 --- a/src/js/blocks/categories/event.js +++ b/src/js/blocks/categories/event.js @@ -5,73 +5,73 @@ 'use strict'; export default { - "StartScript": { - "message0": "%{BKY_EVENT_WHENSCENESTARTS}" + StartScript: { + message0: '%{BKY_EVENT_WHENSCENESTARTS}' }, - "WhenScript": { - "message0": "%{BKY_EVENT_WHENTAPPED}" + WhenScript: { + message0: '%{BKY_EVENT_WHENTAPPED}' }, - "WhenTouchDownScript": { - "message0": "%{BKY_EVENT_WHENSTAGEISTAPPED}" + WhenTouchDownScript: { + message0: '%{BKY_EVENT_WHENSTAGEISTAPPED}' }, - "BroadcastScript": { - "message0": "%{BKY_EVENT_WHENYOURECEIVE}", - "args0": [ + BroadcastScript: { + message0: '%{BKY_EVENT_WHENYOURECEIVE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "BroadcastBrick": { - "message0": "%{BKY_EVENT_BROADCAST_CB}", - "args0": [ + BroadcastBrick: { + message0: '%{BKY_EVENT_BROADCAST_CB}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "BroadcastWaitBrick": { - "message0": "%{BKY_EVENT_BROADCASTANDWAIT_CB}", - "args0": [ + BroadcastWaitBrick: { + message0: '%{BKY_EVENT_BROADCASTANDWAIT_CB}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "WhenConditionScript": { - "message0": "%{BKY_EVENT_WHENBECOMESTRUE}", - "args0": [ + WhenConditionScript: { + message0: '%{BKY_EVENT_WHENBECOMESTRUE}', + args0: [ { - "type": "field_input", - "name": "IF_CONDITION", - "text": "unset" + type: 'field_input', + name: 'IF_CONDITION', + text: 'unset' } ] }, - "WhenBounceOffScript": { - "message0": "%{BKY_EVENT_WHENYOUBOUNCEOFF}", - "args0": [ + WhenBounceOffScript: { + message0: '%{BKY_EVENT_WHENYOUBOUNCEOFF}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "WhenBackgroundChangesScript": { - "message0": "%{BKY_EVENT_WHENBACKGROUNDCHANGES}", - "args0": [ + WhenBackgroundChangesScript: { + message0: '%{BKY_EVENT_WHENBACKGROUNDCHANGES}', + args0: [ { - "type": "field_input", - "name": "look", - "text": "unset" + type: 'field_input', + name: 'look', + text: 'unset' } ] } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/index.js b/src/js/blocks/categories/index.js index 19bff920..733a3009 100644 --- a/src/js/blocks/categories/index.js +++ b/src/js/blocks/categories/index.js @@ -22,21 +22,20 @@ import raspi from './raspi'; import sound from './sound'; import stitch from './stitch'; - export default { - 'arduino': arduino, - 'control': control, - 'data': data, - 'drone': drone, - 'event': event, - 'jumpingSumo': jumpingSumo, - 'legoEV3': legoEV3, - 'legoNXT': legoNXT, - 'looks': looks, - 'motion': motion, - 'pen': pen, - 'phiro': phiro, - 'raspi': raspi, - 'sound': sound, - 'stitch': stitch -}; \ No newline at end of file + arduino: arduino, + control: control, + data: data, + drone: drone, + event: event, + jumpingSumo: jumpingSumo, + legoEV3: legoEV3, + legoNXT: legoNXT, + looks: looks, + motion: motion, + pen: pen, + phiro: phiro, + raspi: raspi, + sound: sound, + stitch: stitch +}; diff --git a/src/js/blocks/categories/jumpingSumo.js b/src/js/blocks/categories/jumpingSumo.js index 55eacc59..0bf7ed80 100644 --- a/src/js/blocks/categories/jumpingSumo.js +++ b/src/js/blocks/categories/jumpingSumo.js @@ -5,94 +5,94 @@ 'use strict'; export default { - "JumpingSumoAnimationsBrick": { - "message0": "%{BKY_SUMO_ANIMATION}", - "args0": [ + JumpingSumoAnimationsBrick: { + message0: '%{BKY_SUMO_ANIMATION}', + args0: [ { - "type": "field_input", - "name": "ANIMATION", - "text": "unset" + type: 'field_input', + name: 'ANIMATION', + text: 'unset' } ] }, - "JumpingSumoJumpHighBrick": { - "message0": "%{BKY_SUMO_JUMPHIGH}" + JumpingSumoJumpHighBrick: { + message0: '%{BKY_SUMO_JUMPHIGH}' }, - "JumpingSumoJumpLongBrick": { - "message0": "%{BKY_SUMO_JUMPLONG}" + JumpingSumoJumpLongBrick: { + message0: '%{BKY_SUMO_JUMPLONG}' }, - "JumpingSumoMoveBackwardBrick": { - "message0": "%{BKY_SUMO_MOVEBACKWARD}", - "args0": [ + JumpingSumoMoveBackwardBrick: { + message0: '%{BKY_SUMO_MOVEBACKWARD}', + args0: [ { - "type": "field_input", - "name": "JUMPING_SUMO_TIME_TO_DRIVE_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'JUMPING_SUMO_TIME_TO_DRIVE_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "JUMPING_SUMO_SPEED", - "text": "unset" + type: 'field_input', + name: 'JUMPING_SUMO_SPEED', + text: 'unset' } ] }, - "JumpingSumoMoveForwardBrick": { - "message0": "%{BKY_SUMO_MOVEFORWARD}", - "args0": [ + JumpingSumoMoveForwardBrick: { + message0: '%{BKY_SUMO_MOVEFORWARD}', + args0: [ { - "type": "field_input", - "name": "JUMPING_SUMO_TIME_TO_DRIVE_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'JUMPING_SUMO_TIME_TO_DRIVE_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "JUMPING_SUMO_SPEED", - "text": "unset" + type: 'field_input', + name: 'JUMPING_SUMO_SPEED', + text: 'unset' } ] }, - "JumpingSumoSoundBrick": { - "message0": "%{BKY_SUMO_SOUND}", - "args0": [ + JumpingSumoSoundBrick: { + message0: '%{BKY_SUMO_SOUND}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "JUMPING_SUMO_VOLUME", - "text": "unset" + type: 'field_input', + name: 'JUMPING_SUMO_VOLUME', + text: 'unset' } ] }, - "JumpingSumoNoSoundBrick": { - "message0": "%{BKY_SUMO_NOSOUND}" + JumpingSumoNoSoundBrick: { + message0: '%{BKY_SUMO_NOSOUND}' }, - "JumpingSumoRotateLeftBrick": { - "message0": "%{BKY_SUMO_ROTATELEFT}", - "args0": [ + JumpingSumoRotateLeftBrick: { + message0: '%{BKY_SUMO_ROTATELEFT}', + args0: [ { - "type": "field_input", - "name": "JUMPING_SUMO_ROTATE", - "text": "unset" + type: 'field_input', + name: 'JUMPING_SUMO_ROTATE', + text: 'unset' } ] }, - "JumpingSumoRotateRightBrick": { - "message0": "%{BKY_SUMO_ROTATERIGHT}", - "args0": [ + JumpingSumoRotateRightBrick: { + message0: '%{BKY_SUMO_ROTATERIGHT}', + args0: [ { - "type": "field_input", - "name": "JUMPING_SUMO_ROTATE", - "text": "unset" + type: 'field_input', + name: 'JUMPING_SUMO_ROTATE', + text: 'unset' } ] }, - "JumpingSumoTurnBrick": { - "message0": "%{BKY_SUMO_TURN}" + JumpingSumoTurnBrick: { + message0: '%{BKY_SUMO_TURN}' }, - "JumpingSumoTakingPictureBrick": { - "message0": "%{BKY_SUMO_TAKINGPICTURE}" + JumpingSumoTakingPictureBrick: { + message0: '%{BKY_SUMO_TAKINGPICTURE}' } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/legoEV3.js b/src/js/blocks/categories/legoEV3.js index f2fa14fc..db6851c8 100644 --- a/src/js/blocks/categories/legoEV3.js +++ b/src/js/blocks/categories/legoEV3.js @@ -5,74 +5,74 @@ 'use strict'; export default { - "LegoEv3MotorTurnAngleBrick": { - "message0": "%{BKY_LEGOEV3_MOTORTURNANGLE}", - "args0": [ + LegoEv3MotorTurnAngleBrick: { + message0: '%{BKY_LEGOEV3_MOTORTURNANGLE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "LEGO_EV3_DEGREES", - "text": "unset" + type: 'field_input', + name: 'LEGO_EV3_DEGREES', + text: 'unset' } ] }, - "LegoEv3MotorMoveBrick": { - "message0": "%{BKY_LEGOEV3_MOTORMOVE}", - "args0": [ + LegoEv3MotorMoveBrick: { + message0: '%{BKY_LEGOEV3_MOTORMOVE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "LEGO_NXT_SPEED", - "text": "unset" + type: 'field_input', + name: 'LEGO_NXT_SPEED', + text: 'unset' } ] }, - "LegoEv3MotorStopBrick": { - "message0": "%{BKY_LEGOEV3_MOTORSTOP}", - "args0": [ + LegoEv3MotorStopBrick: { + message0: '%{BKY_LEGOEV3_MOTORSTOP}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "LegoEv3PlayToneBrick": { - "message0": "%{BKY_LEGOEV3_PLAYTONE}", - "args0": [ + LegoEv3PlayToneBrick: { + message0: '%{BKY_LEGOEV3_PLAYTONE}', + args0: [ { - "type": "field_input", - "name": "LEGO_EV3_DURATION_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'LEGO_EV3_DURATION_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "LEGO_EV3_FREQUENCY", - "text": "unset" + type: 'field_input', + name: 'LEGO_EV3_FREQUENCY', + text: 'unset' }, { - "type": "field_input", - "name": "LEGO_EV3_VOLUME", - "text": "unset" + type: 'field_input', + name: 'LEGO_EV3_VOLUME', + text: 'unset' } ] }, - "LegoEv3SetLedBrick": { - "message0": "%{BKY_LEGOEV3_SETLED}", - "args0": [ + LegoEv3SetLedBrick: { + message0: '%{BKY_LEGOEV3_SETLED}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/legoNXT.js b/src/js/blocks/categories/legoNXT.js index 91f1ce02..8dfdc480 100644 --- a/src/js/blocks/categories/legoNXT.js +++ b/src/js/blocks/categories/legoNXT.js @@ -5,59 +5,59 @@ 'use strict'; export default { - "LegoNxtMotorTurnAngleBrick": { - "message0": "%{BKY_LEGONXT_MOTORTURNANGLE}", - "args0": [ + LegoNxtMotorTurnAngleBrick: { + message0: '%{BKY_LEGONXT_MOTORTURNANGLE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "LEGO_NXT_DEGREES", - "text": "unset" + type: 'field_input', + name: 'LEGO_NXT_DEGREES', + text: 'unset' } ] }, - "LegoNxtMotorStopBrick": { - "message0": "%{BKY_LEGONXT_MOTORSTOP}", - "args0": [ + LegoNxtMotorStopBrick: { + message0: '%{BKY_LEGONXT_MOTORSTOP}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "LegoNxtMotorMoveBrick": { - "message0": "%{BKY_LEGONXT_MOTORMOVE}", - "args0": [ + LegoNxtMotorMoveBrick: { + message0: '%{BKY_LEGONXT_MOTORMOVE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "LEGO_NXT_SPEED", - "text": "unset" + type: 'field_input', + name: 'LEGO_NXT_SPEED', + text: 'unset' } ] }, - "LegoNxtPlayToneBrick": { - "message0": "%{BKY_LEGONXT_PLAYTONE}", - "args0": [ + LegoNxtPlayToneBrick: { + message0: '%{BKY_LEGONXT_PLAYTONE}', + args0: [ { - "type": "field_input", - "name": "LEGO_NXT_DURATION_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'LEGO_NXT_DURATION_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "LEGO_NXT_FREQUENCY", - "text": "unset" + type: 'field_input', + name: 'LEGO_NXT_FREQUENCY', + text: 'unset' } ] } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/looks.js b/src/js/blocks/categories/looks.js index 220b4b8f..a1dda85e 100644 --- a/src/js/blocks/categories/looks.js +++ b/src/js/blocks/categories/looks.js @@ -5,253 +5,253 @@ 'use strict'; export default { - "SetLookBrick": { - "message0": "%{BKY_LOOKS_SWITCHTOLOOK}", - "args0": [ + SetLookBrick: { + message0: '%{BKY_LOOKS_SWITCHTOLOOK}', + args0: [ { - "type": "field_input", - "name": "look", - "text": "unset" + type: 'field_input', + name: 'look', + text: 'unset' } ] }, - "SetLookByIndexBrick": { - "message0": "%{BKY_LOOKS_SWITCHTOLOOKWITHNUMBER}", - "args0": [ + SetLookByIndexBrick: { + message0: '%{BKY_LOOKS_SWITCHTOLOOKWITHNUMBER}', + args0: [ { - "type": "field_input", - "name": "LOOK_INDEX", - "text": "unset" + type: 'field_input', + name: 'LOOK_INDEX', + text: 'unset' } ] }, - "NextLookBrick": { - "message0": "%{BKY_LOOKS_NEXTLOOK}" + NextLookBrick: { + message0: '%{BKY_LOOKS_NEXTLOOK}' }, - "PreviousLookBrick": { - "message0": "%{BKY_LOOKS_PREVIOUSLOOK}" + PreviousLookBrick: { + message0: '%{BKY_LOOKS_PREVIOUSLOOK}' }, - "SetSizeToBrick": { - "message0": "%{BKY_LOOKS_SETSIZETO}", - "args0": [ + SetSizeToBrick: { + message0: '%{BKY_LOOKS_SETSIZETO}', + args0: [ { - "type": "field_input", - "name": "SIZE", - "text": "unset" + type: 'field_input', + name: 'SIZE', + text: 'unset' } ] }, - "HideBrick": { - "message0": "%{BKY_LOOKS_HIDE}" + HideBrick: { + message0: '%{BKY_LOOKS_HIDE}' }, - "ShowBrick": { - "message0": "%{BKY_LOOKS_SHOW}" + ShowBrick: { + message0: '%{BKY_LOOKS_SHOW}' }, - "AskBrick": { - "message0": "%{BKY_LOOKS_ASKANDSTOREWRITTENANSWERIN}", - "args0": [ + AskBrick: { + message0: '%{BKY_LOOKS_ASKANDSTOREWRITTENANSWERIN}', + args0: [ { - "type": "field_input", - "name": "ASK_QUESTION", - "text": "unset" + type: 'field_input', + name: 'ASK_QUESTION', + text: 'unset' }, { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "SayBubbleBrick": { - "message0": "%{BKY_LOOKS_SAY_CAT}", - "args0": [ + SayBubbleBrick: { + message0: '%{BKY_LOOKS_SAY_CAT}', + args0: [ { - "type": "field_input", - "name": "STRING", - "text": "unset" + type: 'field_input', + name: 'STRING', + text: 'unset' } ] }, - "SayForBubbleBrick": { - "message0": "%{BKY_LOOKS_SAYFORSECOND}", - "args0": [ + SayForBubbleBrick: { + message0: '%{BKY_LOOKS_SAYFORSECOND}', + args0: [ { - "type": "field_input", - "name": "STRING", - "text": "unset" + type: 'field_input', + name: 'STRING', + text: 'unset' }, { - "type": "field_input", - "name": "DURATION_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DURATION_IN_SECONDS', + text: 'unset' } ] }, - "ThinkBubbleBrick": { - "message0": "%{BKY_LOOKS_THINK_CAT}", - "args0": [ + ThinkBubbleBrick: { + message0: '%{BKY_LOOKS_THINK_CAT}', + args0: [ { - "type": "field_input", - "name": "STRING", - "text": "unset" + type: 'field_input', + name: 'STRING', + text: 'unset' } ] }, - "ThinkForBubbleBrick": { - "message0": "%{BKY_LOOKS_THINKFORSECONDS}", - "args0": [ + ThinkForBubbleBrick: { + message0: '%{BKY_LOOKS_THINKFORSECONDS}', + args0: [ { - "type": "field_input", - "name": "STRING", - "text": "unset" + type: 'field_input', + name: 'STRING', + text: 'unset' }, { - "type": "field_input", - "name": "DURATION_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DURATION_IN_SECONDS', + text: 'unset' } ] }, - "SetTransparencyBrick": { - "message0": "%{BKY_LOOKS_SETTRANSPARENCYTO}", - "args0": [ + SetTransparencyBrick: { + message0: '%{BKY_LOOKS_SETTRANSPARENCYTO}', + args0: [ { - "type": "field_input", - "name": "TRANSPARENCY", - "text": "unset" + type: 'field_input', + name: 'TRANSPARENCY', + text: 'unset' } ] }, - "ChangeSizeByNBrick": { - "message0": "%{BKY_LOOKS_CHANGESIZEBY}", - "args0": [ + ChangeSizeByNBrick: { + message0: '%{BKY_LOOKS_CHANGESIZEBY}', + args0: [ { - "type": "field_input", - "name": "SIZE_CHANGE", - "text": "unset" + type: 'field_input', + name: 'SIZE_CHANGE', + text: 'unset' } ] }, - "ChangeTransparencyByNBrick": { - "message0": "%{BKY_LOOKS_CHANGETRANSPARENCYBY}", - "args0": [ + ChangeTransparencyByNBrick: { + message0: '%{BKY_LOOKS_CHANGETRANSPARENCYBY}', + args0: [ { - "type": "field_input", - "name": "TRANSPARENCY_CHANGE", - "text": "unset" + type: 'field_input', + name: 'TRANSPARENCY_CHANGE', + text: 'unset' } ] }, - "SetBrightnessBrick": { - "message0": "%{BKY_LOOKS_SETBRIGHTHNESSTO}", - "args0": [ + SetBrightnessBrick: { + message0: '%{BKY_LOOKS_SETBRIGHTHNESSTO}', + args0: [ { - "type": "field_input", - "name": "BRIGHTNESS", - "text": "unset" + type: 'field_input', + name: 'BRIGHTNESS', + text: 'unset' } ] }, - "ChangeBrightnessByNBrick": { - "message0": "%{BKY_LOOKS_CHANGEBRIGHTHNESSBY}", - "args0": [ + ChangeBrightnessByNBrick: { + message0: '%{BKY_LOOKS_CHANGEBRIGHTHNESSBY}', + args0: [ { - "type": "field_input", - "name": "BRIGHTNESS_CHANGE", - "text": "unset" + type: 'field_input', + name: 'BRIGHTNESS_CHANGE', + text: 'unset' } ] }, - "SetColorBrick": { - "message0": "%{BKY_LOOKS_SETCOLORTO}", - "args0": [ + SetColorBrick: { + message0: '%{BKY_LOOKS_SETCOLORTO}', + args0: [ { - "type": "field_input", - "name": "COLOR", - "text": "unset" + type: 'field_input', + name: 'COLOR', + text: 'unset' } ] }, - "ChangeColorByNBrick": { - "message0": "%{BKY_LOOKS_CHANGECOLORBY}", - "args0": [ + ChangeColorByNBrick: { + message0: '%{BKY_LOOKS_CHANGECOLORBY}', + args0: [ { - "type": "field_input", - "name": "COLOR_CHANGE", - "text": "unset" + type: 'field_input', + name: 'COLOR_CHANGE', + text: 'unset' } ] }, - "ClearGraphicEffectBrick": { - "message0": "%{BKY_LOOKS_CLEARGRAPHICEFFECTS_CAT}" + ClearGraphicEffectBrick: { + message0: '%{BKY_LOOKS_CLEARGRAPHICEFFECTS_CAT}' }, - "SetBackgroundBrick": { - "message0": "%{BKY_LOOKS_SETBACKGROUND}", - "args0": [ + SetBackgroundBrick: { + message0: '%{BKY_LOOKS_SETBACKGROUND}', + args0: [ { - "type": "field_input", - "name": "look", - "text": "unset" + type: 'field_input', + name: 'look', + text: 'unset' } ] }, - "SetBackgroundByIndexBrick": { - "message0": "%{BKY_LOOKS_SETBACKGROUNDTONUMBER}", - "args0": [ + SetBackgroundByIndexBrick: { + message0: '%{BKY_LOOKS_SETBACKGROUNDTONUMBER}', + args0: [ { - "type": "field_input", - "name": "LOOK_INDEX", - "text": "unset" + type: 'field_input', + name: 'LOOK_INDEX', + text: 'unset' } ] }, - "SetBackgroundAndWaitBrick": { - "message0": "%{BKY_LOOKS_SETBACKGROUNDANDWAIT}", - "args0": [ + SetBackgroundAndWaitBrick: { + message0: '%{BKY_LOOKS_SETBACKGROUNDANDWAIT}', + args0: [ { - "type": "field_input", - "name": "look", - "text": "unset" + type: 'field_input', + name: 'look', + text: 'unset' } ] }, - "SetBackgroundByIndexAndWaitBrick": { - "message0": "%{BKY_LOOKS_SETBACKGROUNDTONUMBERANDWAIT}", - "args0": [ + SetBackgroundByIndexAndWaitBrick: { + message0: '%{BKY_LOOKS_SETBACKGROUNDTONUMBERANDWAIT}', + args0: [ { - "type": "field_input", - "name": "LOOK_INDEX", - "text": "unset" + type: 'field_input', + name: 'LOOK_INDEX', + text: 'unset' } ] }, - "CameraBrick": { - "message0": "%{BKY_LOOKS_TURNCAMERA}", - "args0": [ + CameraBrick: { + message0: '%{BKY_LOOKS_TURNCAMERA}', + args0: [ { - "type": "field_input", - "name": "SPINNER", - "text": "unset" + type: 'field_input', + name: 'SPINNER', + text: 'unset' } ] }, - "ChooseCameraBrick": { - "message0": "%{BKY_LOOKS_USECAMERA}", - "args0": [ + ChooseCameraBrick: { + message0: '%{BKY_LOOKS_USECAMERA}', + args0: [ { - "type": "field_input", - "name": "SPINNER", - "text": "unset" + type: 'field_input', + name: 'SPINNER', + text: 'unset' } ] }, - "FlashBrick": { - "message0": "%{BKY_LOOKS_TURNFLASHLIGHT}", - "args0": [ + FlashBrick: { + message0: '%{BKY_LOOKS_TURNFLASHLIGHT}', + args0: [ { - "type": "field_input", - "name": "SPINNER", - "text": "unset" + type: 'field_input', + name: 'SPINNER', + text: 'unset' } ] } diff --git a/src/js/blocks/categories/motion.js b/src/js/blocks/categories/motion.js index 48713f70..4a2e8c95 100644 --- a/src/js/blocks/categories/motion.js +++ b/src/js/blocks/categories/motion.js @@ -5,265 +5,265 @@ 'use strict'; export default { - "PlaceAtBrick": { - "message0": "%{BKY_MOTION_PLACEATXY}", - "args0": [ + PlaceAtBrick: { + message0: '%{BKY_MOTION_PLACEATXY}', + args0: [ { - "type": "field_input", - "name": "X_POSITION", - "text": "unset" + type: 'field_input', + name: 'X_POSITION', + text: 'unset' }, { - "type": "field_input", - "name": "Y_POSITION", - "text": "unset" + type: 'field_input', + name: 'Y_POSITION', + text: 'unset' } ] }, - "SetXBrick": { - "message0": "%{BKY_MOTION_SETXTO}", - "args0": [ + SetXBrick: { + message0: '%{BKY_MOTION_SETXTO}', + args0: [ { - "type": "field_input", - "name": "X_POSITION", - "text": "unset" + type: 'field_input', + name: 'X_POSITION', + text: 'unset' } ] }, - "SetYBrick": { - "message0": "%{BKY_MOTION_SETYTO}", - "args0": [ + SetYBrick: { + message0: '%{BKY_MOTION_SETYTO}', + args0: [ { - "type": "field_input", - "name": "Y_POSITION", - "text": "unset" + type: 'field_input', + name: 'Y_POSITION', + text: 'unset' } ] }, - "ChangeXByNBrick": { - "message0": "%{BKY_MOTION_CHANGEXBY}", - "args0": [ + ChangeXByNBrick: { + message0: '%{BKY_MOTION_CHANGEXBY}', + args0: [ { - "type": "field_input", - "name": "X_POSITION_CHANGE", - "text": "unset" + type: 'field_input', + name: 'X_POSITION_CHANGE', + text: 'unset' } ] }, - "ChangeYByNBrick": { - "message0": "%{BKY_MOTION_CHANGEYBY}", - "args0": [ + ChangeYByNBrick: { + message0: '%{BKY_MOTION_CHANGEYBY}', + args0: [ { - "type": "field_input", - "name": "Y_POSITION_CHANGE", - "text": "unset" + type: 'field_input', + name: 'Y_POSITION_CHANGE', + text: 'unset' } ] }, - "GoToBrick": { - "message0": "%{BKY_MOTION_GOTO}", - "args0": [ + GoToBrick: { + message0: '%{BKY_MOTION_GOTO}', + args0: [ { - "type": "field_input", - "name": "SPINNER", - "text": "unset" + type: 'field_input', + name: 'SPINNER', + text: 'unset' } ] }, - "IfOnEdgeBounceBrick": { - "message0": "%{BKY_MOTION_IFONEDGEBOUNCE}" + IfOnEdgeBounceBrick: { + message0: '%{BKY_MOTION_IFONEDGEBOUNCE}' }, - "MoveNStepsBrick": { - "message0": "%{BKY_MOTION_MOVESTEPS}", - "args0": [ + MoveNStepsBrick: { + message0: '%{BKY_MOTION_MOVESTEPS}', + args0: [ { - "type": "field_input", - "name": "STEPS", - "text": "unset" + type: 'field_input', + name: 'STEPS', + text: 'unset' } ] }, - "TurnRightBrick": { - "message0": "%{BKY_MOTION_TURNRIGHTDEGREES}", - "args0": [ + TurnRightBrick: { + message0: '%{BKY_MOTION_TURNRIGHTDEGREES}', + args0: [ { - "type": "field_input", - "name": "TURN_RIGHT_DEGREES", - "text": "unset" + type: 'field_input', + name: 'TURN_RIGHT_DEGREES', + text: 'unset' } ] }, - "TurnLeftBrick": { - "message0": "%{BKY_MOTION_TURNLEFTDEGREES}", - "args0": [ + TurnLeftBrick: { + message0: '%{BKY_MOTION_TURNLEFTDEGREES}', + args0: [ { - "type": "field_input", - "name": "TURN_LEFT_DEGREES", - "text": "unset" + type: 'field_input', + name: 'TURN_LEFT_DEGREES', + text: 'unset' } ] }, - "PointInDirectionBrick": { - "message0": "%{BKY_MOTION_POINTINDIRECTIONDEGREES}", - "args0": [ + PointInDirectionBrick: { + message0: '%{BKY_MOTION_POINTINDIRECTIONDEGREES}', + args0: [ { - "type": "field_input", - "name": "DEGREES", - "text": "unset" + type: 'field_input', + name: 'DEGREES', + text: 'unset' } ] }, - "PointToBrick": { - "message0": "%{BKY_MOTION_POINTTOWARDS}", - "args0": [ + PointToBrick: { + message0: '%{BKY_MOTION_POINTTOWARDS}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "SetRotationStyleBrick": { - "message0": "%{BKY_MOTION_SETROTATIONSTYLE}", - "args0": [ + SetRotationStyleBrick: { + message0: '%{BKY_MOTION_SETROTATIONSTYLE}', + args0: [ { - "type": "field_input", - "name": "SPINNER", - "text": "unset" + type: 'field_input', + name: 'SPINNER', + text: 'unset' } ] }, - "GlideToBrick": { - "message0": "%{BKY_MOTION_GLIDESECONDTOXY}", - "args0": [ + GlideToBrick: { + message0: '%{BKY_MOTION_GLIDESECONDTOXY}', + args0: [ { - "type": "field_input", - "name": "DURATION_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'DURATION_IN_SECONDS', + text: 'unset' }, { - "type": "field_input", - "name": "X_DESTINATION", - "text": "unset" + type: 'field_input', + name: 'X_DESTINATION', + text: 'unset' }, { - "type": "field_input", - "name": "Y_DESTINATION", - "text": "unset" + type: 'field_input', + name: 'Y_DESTINATION', + text: 'unset' } ] }, - "GoNStepsBackBrick": { - "message0": "%{BKY_MOTION_GOBACKLAYER}", - "args0": [ + GoNStepsBackBrick: { + message0: '%{BKY_MOTION_GOBACKLAYER}', + args0: [ { - "type": "field_input", - "name": "STEPS", - "text": "unset" + type: 'field_input', + name: 'STEPS', + text: 'unset' } ] }, - "ComeToFrontBrick": { - "message0": "%{BKY_MOTION_GOTOFRONT}" + ComeToFrontBrick: { + message0: '%{BKY_MOTION_GOTOFRONT}' }, - "VibrationBrick": { - "message0": "%{BKY_MOTION_VIBRATEFORSECOND}", - "args0": [ + VibrationBrick: { + message0: '%{BKY_MOTION_VIBRATEFORSECOND}', + args0: [ { - "type": "field_input", - "name": "VIBRATE_DURATION_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'VIBRATE_DURATION_IN_SECONDS', + text: 'unset' } ] }, - "SetPhysicsObjectTypeBrick": { - "message0": "%{BKY_MOTION_SETYOURMOTIONTYPETO}", - "args0": [ + SetPhysicsObjectTypeBrick: { + message0: '%{BKY_MOTION_SETYOURMOTIONTYPETO}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "SetVelocityBrick": { - "message0": "%{BKY_MOTION_SETVELOCITYTO}", - "args0": [ + SetVelocityBrick: { + message0: '%{BKY_MOTION_SETVELOCITYTO}', + args0: [ { - "type": "field_input", - "name": "PHYSICS_VELOCITY_X", - "text": "unset" + type: 'field_input', + name: 'PHYSICS_VELOCITY_X', + text: 'unset' }, { - "type": "field_input", - "name": "PHYSICS_VELOCITY_Y", - "text": "unset" + type: 'field_input', + name: 'PHYSICS_VELOCITY_Y', + text: 'unset' } ] }, - "TurnLeftSpeedBrick": { - "message0": "%{BKY_MOTION_SPINLEFTDEGREESSECOND}", - "args0": [ + TurnLeftSpeedBrick: { + message0: '%{BKY_MOTION_SPINLEFTDEGREESSECOND}', + args0: [ { - "type": "field_input", - "name": "PHYSICS_TURN_LEFT_SPEED", - "text": "unset" + type: 'field_input', + name: 'PHYSICS_TURN_LEFT_SPEED', + text: 'unset' } ] }, - "TurnRightSpeedBrick": { - "message0": "%{BKY_MOTION_SPINRIGHTDEGREESSECOND}", - "args0": [ + TurnRightSpeedBrick: { + message0: '%{BKY_MOTION_SPINRIGHTDEGREESSECOND}', + args0: [ { - "type": "field_input", - "name": "PHYSICS_TURN_RIGHT_SPEED", - "text": "unset" + type: 'field_input', + name: 'PHYSICS_TURN_RIGHT_SPEED', + text: 'unset' } ] }, - "SetGravityBrick": { - "message0": "%{BKY_MOTION_SETGRAVITYFORALLACTORSANDOBJECTSTO}", - "args0": [ + SetGravityBrick: { + message0: '%{BKY_MOTION_SETGRAVITYFORALLACTORSANDOBJECTSTO}', + args0: [ { - "type": "field_input", - "name": "PHYSICS_GRAVITY_X", - "text": "unset" + type: 'field_input', + name: 'PHYSICS_GRAVITY_X', + text: 'unset' }, { - "type": "field_input", - "name": "PHYSICS_GRAVITY_Y", - "text": "unset" + type: 'field_input', + name: 'PHYSICS_GRAVITY_Y', + text: 'unset' } ] }, - "SetMassBrick": { - "message0": "%{BKY_MOTION_SETMASSTOKILOGRAM}", - "args0": [ + SetMassBrick: { + message0: '%{BKY_MOTION_SETMASSTOKILOGRAM}', + args0: [ { - "type": "field_input", - "name": "PHYSICS_MASS", - "text": "unset" + type: 'field_input', + name: 'PHYSICS_MASS', + text: 'unset' } ] }, - "SetBounceBrick": { - "message0": "%{BKY_MOTION_SETBOUNCEFACTORTO}", - "args0": [ + SetBounceBrick: { + message0: '%{BKY_MOTION_SETBOUNCEFACTORTO}', + args0: [ { - "type": "field_input", - "name": "PHYSICS_BOUNCE_FACTOR", - "text": "unset" + type: 'field_input', + name: 'PHYSICS_BOUNCE_FACTOR', + text: 'unset' } ] }, - "SetFrictionBrick": { - "message0": "%{BKY_MOTION_SETFRICTIONTO}", - "args0": [ + SetFrictionBrick: { + message0: '%{BKY_MOTION_SETFRICTIONTO}', + args0: [ { - "type": "field_input", - "name": "PHYSICS_FRICTION", - "text": "unset" + type: 'field_input', + name: 'PHYSICS_FRICTION', + text: 'unset' } ] } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/pen.js b/src/js/blocks/categories/pen.js index 6d109d14..04d7e7df 100644 --- a/src/js/blocks/categories/pen.js +++ b/src/js/blocks/categories/pen.js @@ -5,46 +5,46 @@ 'use strict'; export default { - "PenDownBrick": { - "message0": "%{BKY_PEN_PENDOWN}" + PenDownBrick: { + message0: '%{BKY_PEN_PENDOWN}' }, - "PenUpBrick": { - "message0": "%{BKY_PEN_PENUP}" + PenUpBrick: { + message0: '%{BKY_PEN_PENUP}' }, - "SetPenSizeBrick": { - "message0": "%{BKY_PEN_SETPENSIZETO}", - "args0": [ + SetPenSizeBrick: { + message0: '%{BKY_PEN_SETPENSIZETO}', + args0: [ { - "type": "field_input", - "name": "PEN_SIZE", - "text": "unset" + type: 'field_input', + name: 'PEN_SIZE', + text: 'unset' } ] }, - "SetPenColorBrick": { - "message0": "%{BKY_PEN_SETPENCOLORTO}", - "args0": [ + SetPenColorBrick: { + message0: '%{BKY_PEN_SETPENCOLORTO}', + args0: [ { - "type": "field_input", - "name": "PEN_COLOR_RED", - "text": "unset" + type: 'field_input', + name: 'PEN_COLOR_RED', + text: 'unset' }, { - "type": "field_input", - "name": "PEN_COLOR_GREEN", - "text": "unset" + type: 'field_input', + name: 'PEN_COLOR_GREEN', + text: 'unset' }, { - "type": "field_input", - "name": "PEN_COLOR_BLUE", - "text": "unset" + type: 'field_input', + name: 'PEN_COLOR_BLUE', + text: 'unset' } ] }, - "StampBrick": { - "message0": "%{BKY_PEN_STAMP}" + StampBrick: { + message0: '%{BKY_PEN_STAMP}' }, - "ClearBackgroundBrick": { - "message0": "%{BKY_PEN_CLEAR}" + ClearBackgroundBrick: { + message0: '%{BKY_PEN_CLEAR}' } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/phiro.js b/src/js/blocks/categories/phiro.js index 1ff6cf96..9d821d94 100644 --- a/src/js/blocks/categories/phiro.js +++ b/src/js/blocks/categories/phiro.js @@ -5,110 +5,110 @@ 'use strict'; export default { - "PhiroMotorMoveForwardBrick": { - "message0": "%{BKY_PHIRO_MOTORMOVEFORWARD}", - "args0": [ + PhiroMotorMoveForwardBrick: { + message0: '%{BKY_PHIRO_MOTORMOVEFORWARD}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "PHIRO_SPEED", - "text": "unset" + type: 'field_input', + name: 'PHIRO_SPEED', + text: 'unset' } ] }, - "PhiroMotorMoveBackwardBrick": { - "message0": "%{BKY_PHIRO_MOTORMOVEBACKWARD}", - "args0": [ + PhiroMotorMoveBackwardBrick: { + message0: '%{BKY_PHIRO_MOTORMOVEBACKWARD}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "PHIRO_SPEED", - "text": "unset" + type: 'field_input', + name: 'PHIRO_SPEED', + text: 'unset' } ] }, - "PhiroMotorStopBrick": { - "message0": "%{BKY_PHIRO_MOTORSTOP}", - "args0": [ + PhiroMotorStopBrick: { + message0: '%{BKY_PHIRO_MOTORSTOP}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] }, - "PhiroPlayToneBrick": { - "message0": "%{BKY_PHIRO_PLAYTONE}", - "args0": [ + PhiroPlayToneBrick: { + message0: '%{BKY_PHIRO_PLAYTONE}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "PHIRO_DURATION_IN_SECONDS", - "text": "unset" + type: 'field_input', + name: 'PHIRO_DURATION_IN_SECONDS', + text: 'unset' } ] }, - "PhiroRGBLightBrick": { - "message0": "%{BKY_PHIRO_RGBLIGHT}", - "args0": [ + PhiroRGBLightBrick: { + message0: '%{BKY_PHIRO_RGBLIGHT}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "PHIRO_LIGHT_RED", - "text": "unset" + type: 'field_input', + name: 'PHIRO_LIGHT_RED', + text: 'unset' }, { - "type": "field_input", - "name": "PHIRO_LIGHT_GREEN", - "text": "unset" + type: 'field_input', + name: 'PHIRO_LIGHT_GREEN', + text: 'unset' }, { - "type": "field_input", - "name": "PHIRO_LIGHT_BLUE", - "text": "unset" + type: 'field_input', + name: 'PHIRO_LIGHT_BLUE', + text: 'unset' } ] }, - "PhiroIfLogicBeginBrick": { - "type": "IfThenLogicBeginBrick", - "message0": "%{BKY_PHIRO_IFLOGICBEGINIF}", - "message1": "%1", - "message2": "%{BKY_PHIRO_IFLOGICBEGINELSE}", - "message3": "%1", - "args0": [ + PhiroIfLogicBeginBrick: { + type: 'IfThenLogicBeginBrick', + message0: '%{BKY_PHIRO_IFLOGICBEGINIF}', + message1: '%1', + message2: '%{BKY_PHIRO_IFLOGICBEGINELSE}', + message3: '%1', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ], - "args1": [ + args1: [ { - "type": "input_statement", - "name": "SUBSTACK" + type: 'input_statement', + name: 'SUBSTACK' } ], - "args3": [ + args3: [ { - "type": "input_statement", - "name": "SUBSTACK2" + type: 'input_statement', + name: 'SUBSTACK2' } ] } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/raspi.js b/src/js/blocks/categories/raspi.js index 4fc7fb60..12366001 100644 --- a/src/js/blocks/categories/raspi.js +++ b/src/js/blocks/categories/raspi.js @@ -5,80 +5,80 @@ 'use strict'; export default { - "WhenRaspiPinChangedBrick": { - "message0": "%{BKY_RASPI_WHENPINCHANGED}", - "args0": [ + WhenRaspiPinChangedBrick: { + message0: '%{BKY_RASPI_WHENPINCHANGED}', + args0: [ { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' }, { - "type": "field_input", - "name": "DROPDOWN2", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN2', + text: 'unset' } ] }, - "RaspiIfLogicBeginBrick": { - "type": "IfThenLogicBeginBrick", - "message0": "%{BKY_RASPI_IFLOGICBEGINIF}", - "message1": "%1", - "message2": "%{BKY_RASPI_IFLOGICBEGINELSE}", - "message3": "%1", - "args0": [ + RaspiIfLogicBeginBrick: { + type: 'IfThenLogicBeginBrick', + message0: '%{BKY_RASPI_IFLOGICBEGINIF}', + message1: '%1', + message2: '%{BKY_RASPI_IFLOGICBEGINELSE}', + message3: '%1', + args0: [ { - "type": "field_input", - "name": "IF_CONDITION", - "text": "unset" + type: 'field_input', + name: 'IF_CONDITION', + text: 'unset' } ], - "args1": [ + args1: [ { - "type": "input_statement", - "name": "SUBSTACK" + type: 'input_statement', + name: 'SUBSTACK' } ], - "args3": [ + args3: [ { - "type": "input_statement", - "name": "SUBSTACK2" + type: 'input_statement', + name: 'SUBSTACK2' } ] }, - "RaspiSendDigitalValueBrick": { - "message0": "%{BKY_RASPI_SENDDIGITALVALUE}", - "args0": [ + RaspiSendDigitalValueBrick: { + message0: '%{BKY_RASPI_SENDDIGITALVALUE}', + args0: [ { - "type": "field_input", - "name": "RASPI_DIGITAL_PIN_NUMBER", - "text": "unset" + type: 'field_input', + name: 'RASPI_DIGITAL_PIN_NUMBER', + text: 'unset' }, { - "type": "field_input", - "name": "RASPI_DIGITAL_PIN_VALUE", - "text": "unset" + type: 'field_input', + name: 'RASPI_DIGITAL_PIN_VALUE', + text: 'unset' } ] }, - "RaspiPwmBrick": { - "message0": "%{BKY_RASPI_PWM}", - "args0": [ + RaspiPwmBrick: { + message0: '%{BKY_RASPI_PWM}', + args0: [ { - "type": "field_input", - "name": "RASPI_DIGITAL_PIN_NUMBER", - "text": "unset" + type: 'field_input', + name: 'RASPI_DIGITAL_PIN_NUMBER', + text: 'unset' }, { - "type": "field_input", - "name": "RASPI_PWM_PERCENTAGE", - "text": "unset" + type: 'field_input', + name: 'RASPI_PWM_PERCENTAGE', + text: 'unset' }, { - "type": "field_input", - "name": "RASPI_PWM_FREQUENCY", - "text": "unset" + type: 'field_input', + name: 'RASPI_PWM_FREQUENCY', + text: 'unset' } ] } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/categories/sound.js b/src/js/blocks/categories/sound.js index 77419a73..a34468c9 100644 --- a/src/js/blocks/categories/sound.js +++ b/src/js/blocks/categories/sound.js @@ -5,81 +5,81 @@ 'use strict'; export default { - "PlaySoundBrick": { - "message0": "%{BKY_SOUND_STARTSOUND}", - "args0": [ + PlaySoundBrick: { + message0: '%{BKY_SOUND_STARTSOUND}', + args0: [ { - "type": "field_input", - "name": "sound", - "text": "unset" + type: 'field_input', + name: 'sound', + text: 'unset' } ] }, - "PlaySoundAndWaitBrick": { - "message0": "%{BKY_SOUND_STARTSOUNDANDWAIT}", - "args0": [ + PlaySoundAndWaitBrick: { + message0: '%{BKY_SOUND_STARTSOUNDANDWAIT}', + args0: [ { - "type": "field_input", - "name": "sound", - "text": "unset" + type: 'field_input', + name: 'sound', + text: 'unset' } ] }, - "StopAllSoundsBrick": { - "message0": "%{BKY_SOUND_STOPALLSOUNDS}" + StopAllSoundsBrick: { + message0: '%{BKY_SOUND_STOPALLSOUNDS}' }, - "SetVolumeToBrick": { - "message0": "%{BKY_SOUND_SETVOLUMETO}", - "args0": [ + SetVolumeToBrick: { + message0: '%{BKY_SOUND_SETVOLUMETO}', + args0: [ { - "type": "field_input", - "name": "VOLUME", - "text": "unset" + type: 'field_input', + name: 'VOLUME', + text: 'unset' } ] }, - "ChangeVolumeByNBrick": { - "message0": "%{BKY_SOUND_CHANGEVOLUMEBY}", - "args0": [ + ChangeVolumeByNBrick: { + message0: '%{BKY_SOUND_CHANGEVOLUMEBY}', + args0: [ { - "type": "field_input", - "name": "VOLUME_CHANGE", - "text": "unset" + type: 'field_input', + name: 'VOLUME_CHANGE', + text: 'unset' } ] }, - "SpeakBrick": { - "message0": "%{BKY_SOUND_SPEAK}", - "args0": [ + SpeakBrick: { + message0: '%{BKY_SOUND_SPEAK}', + args0: [ { - "type": "field_input", - "name": "SPEAK", - "text": "unset" + type: 'field_input', + name: 'SPEAK', + text: 'unset' } ] }, - "SpeakAndWaitBrick": { - "message0": "%{BKY_SOUND_SPEAKANDWAIT}", - "args0": [ + SpeakAndWaitBrick: { + message0: '%{BKY_SOUND_SPEAKANDWAIT}', + args0: [ { - "type": "field_input", - "name": "SPEAK", - "text": "unset" + type: 'field_input', + name: 'SPEAK', + text: 'unset' } ] }, - "AskSpeechBrick": { - "message0": "%{BKY_SOUND_ASKANDSTORESPOKENANSWERIN}", - "args0": [ + AskSpeechBrick: { + message0: '%{BKY_SOUND_ASKANDSTORESPOKENANSWERIN}', + args0: [ { - "type": "field_input", - "name": "ASK_SPEECH_QUESTION", - "text": "unset" + type: 'field_input', + name: 'ASK_SPEECH_QUESTION', + text: 'unset' }, { - "type": "field_input", - "name": "DROPDOWN", - "text": "unset" + type: 'field_input', + name: 'DROPDOWN', + text: 'unset' } ] } diff --git a/src/js/blocks/categories/stitch.js b/src/js/blocks/categories/stitch.js index 754f1f65..09a69061 100644 --- a/src/js/blocks/categories/stitch.js +++ b/src/js/blocks/categories/stitch.js @@ -5,45 +5,45 @@ 'use strict'; export default { - "StitchBrick": { - "message0": "%{BKY_STITCH}" + StitchBrick: { + message0: '%{BKY_STITCH}' }, - "RunningStitchBrick": { - "message0": "%{BKY_STITCH_RUNNING}", - "args0": [ + RunningStitchBrick: { + message0: '%{BKY_STITCH_RUNNING}', + args0: [ { - "type": "field_input", - "name": "EMBROIDERY_LENGTH", - "text": "unset" + type: 'field_input', + name: 'EMBROIDERY_LENGTH', + text: 'unset' } ] }, - "ZigZagStitchBrick": { - "message0": "%{BKY_STITCH_ZIGZAG}", - "args0": [ + ZigZagStitchBrick: { + message0: '%{BKY_STITCH_ZIGZAG}', + args0: [ { - "type": "field_input", - "name": "ZIGZAG_EMBROIDERY_LENGTH", - "text": "unset" + type: 'field_input', + name: 'ZIGZAG_EMBROIDERY_LENGTH', + text: 'unset' }, { - "type": "field_input", - "name": "ZIGZAG_EMBROIDERY_WIDTH", - "text": "unset" + type: 'field_input', + name: 'ZIGZAG_EMBROIDERY_WIDTH', + text: 'unset' } ] }, - "TripleStitchBrick": { - "message0": "%{BKY_STITCH_TRIPLE}", - "args0": [ + TripleStitchBrick: { + message0: '%{BKY_STITCH_TRIPLE}', + args0: [ { - "type": "field_input", - "name": "EMBROIDERY_LENGTH", - "text": "unset" + type: 'field_input', + name: 'EMBROIDERY_LENGTH', + text: 'unset' } ] }, - "StopRunningStitchBrick": { - "message0": "%{BKY_STITCH_STOP}" + StopRunningStitchBrick: { + message0: '%{BKY_STITCH_STOP}' } -}; \ No newline at end of file +}; diff --git a/src/js/blocks/colours.js b/src/js/blocks/colours.js index 44b9be2e..681fe342 100644 --- a/src/js/blocks/colours.js +++ b/src/js/blocks/colours.js @@ -4,32 +4,32 @@ import Blockly from 'blockly'; -'use strict'; +('use strict'); const colourCodes = { - 'arduino': { colourPrimary: '#34c8a5', colourSecondary: '#299377', colourTertiary: '#238770' }, - 'control': { colourPrimary: '#FFAB19', colourSecondary: '#e39613', colourTertiary: '#CF8B17' }, - 'data': { colourPrimary: '#FF6680', colourSecondary: '#ce4562', colourTertiary: '#FF3355' }, - 'drone': { colourPrimary: '#91d149', colourSecondary: '#6d9c36', colourTertiary: '#669334' }, - 'event': { colourPrimary: '#FF661A', colourSecondary: '#d44c00', colourTertiary: '#E64D00' }, - 'jumpingSumo': { colourPrimary: '#91d149', colourSecondary: '#6d9c36', colourTertiary: '#669334' }, - 'legoEV3': { colourPrimary: '#cbca3e', colourSecondary: '#aead38', colourTertiary: '#acab34' }, - 'legoNXT': { colourPrimary: '#cbca3e', colourSecondary: '#aead38', colourTertiary: '#acab34' }, - 'looks': { colourPrimary: '#59C059', colourSecondary: '#3c943c', colourTertiary: '#389438' }, - 'motion': { colourPrimary: '#4C97FF', colourSecondary: '#386bb8', colourTertiary: '#3373CC' }, - 'pen': { colourPrimary: '#0fBD8C', colourSecondary: '#0b8965', colourTertiary: '#0B8E69' }, - 'phiro': { colourPrimary: '#34c8a5', colourSecondary: '#299377', colourTertiary: '#238770' }, - 'raspi': { colourPrimary: '#34c8a5', colourSecondary: '#299377', colourTertiary: '#238770' }, - 'sound': { colourPrimary: '#9966FF', colourSecondary: '#6c51b4', colourTertiary: '#774DCB' }, - 'stitch': { colourPrimary: '#BC4793', colourSecondary: '#bb3a8d', colourTertiary: '#b72a86' }, - 'default': { colourPrimary: '#34c8a5', colourSecondary: '#299377', colourTertiary: '#238770' } + arduino: { colourPrimary: '#34c8a5', colourSecondary: '#299377', colourTertiary: '#238770' }, + control: { colourPrimary: '#FFAB19', colourSecondary: '#e39613', colourTertiary: '#CF8B17' }, + data: { colourPrimary: '#FF6680', colourSecondary: '#ce4562', colourTertiary: '#FF3355' }, + drone: { colourPrimary: '#91d149', colourSecondary: '#6d9c36', colourTertiary: '#669334' }, + event: { colourPrimary: '#FF661A', colourSecondary: '#d44c00', colourTertiary: '#E64D00' }, + jumpingSumo: { colourPrimary: '#91d149', colourSecondary: '#6d9c36', colourTertiary: '#669334' }, + legoEV3: { colourPrimary: '#cbca3e', colourSecondary: '#aead38', colourTertiary: '#acab34' }, + legoNXT: { colourPrimary: '#cbca3e', colourSecondary: '#aead38', colourTertiary: '#acab34' }, + looks: { colourPrimary: '#59C059', colourSecondary: '#3c943c', colourTertiary: '#389438' }, + motion: { colourPrimary: '#4C97FF', colourSecondary: '#386bb8', colourTertiary: '#3373CC' }, + pen: { colourPrimary: '#0fBD8C', colourSecondary: '#0b8965', colourTertiary: '#0B8E69' }, + phiro: { colourPrimary: '#34c8a5', colourSecondary: '#299377', colourTertiary: '#238770' }, + raspi: { colourPrimary: '#34c8a5', colourSecondary: '#299377', colourTertiary: '#238770' }, + sound: { colourPrimary: '#9966FF', colourSecondary: '#6c51b4', colourTertiary: '#774DCB' }, + stitch: { colourPrimary: '#BC4793', colourSecondary: '#bb3a8d', colourTertiary: '#b72a86' }, + default: { colourPrimary: '#34c8a5', colourSecondary: '#299377', colourTertiary: '#238770' } }; /** * Initiate colour codes for catblocks bricks * if no colour code is defined yet, we use the default one * @param {*} colours - * @param {*} blockly + * @param {*} blockly */ const initCatblocksColours = (colours = colourCodes, blockly = Blockly) => { if (colours) { @@ -38,7 +38,7 @@ const initCatblocksColours = (colours = colourCodes, blockly = Blockly) => { for (const catName in blockly.Categories) { const colourName = colours[catName] ? catName : 'default'; blockly.Colours[catName] = colours[colourName]; - + for (const brickName of blockly.Categories[catName]) { blockly.Bricks[brickName]['colour'] = colours[colourName]['colourPrimary']; blockly.Bricks[brickName]['colourSecondary'] = colours[colourName]['colourSecondary']; @@ -53,7 +53,6 @@ const initCatblocksColours = (colours = colourCodes, blockly = Blockly) => { } }; - (() => { initCatblocksColours(colourCodes, Blockly); -})(); \ No newline at end of file +})(); diff --git a/src/js/blocks/index.js b/src/js/blocks/index.js index 0d0f60e7..ccdfbbba 100644 --- a/src/js/blocks/index.js +++ b/src/js/blocks/index.js @@ -3,4 +3,4 @@ */ import './bricks'; -import './colours'; \ No newline at end of file +import './colours'; diff --git a/src/js/catblocks_msgs.js b/src/js/catblocks_msgs.js index 2448b3d7..c0aee1f2 100644 --- a/src/js/catblocks_msgs.js +++ b/src/js/catblocks_msgs.js @@ -1,19 +1,19 @@ // This file was automatically generated by create_msg.js // Please do not modify. /* eslint no-useless-escape: 0 */ -import Blockly from "blockly"; -import $ from "jquery"; +import Blockly from 'blockly'; +import $ from 'jquery'; Blockly.CatblocksMsgs = {}; Blockly.CatblocksMsgs.locales = {}; Blockly.CatblocksMsgs.currentLocale_ = 'en'; -Blockly.CatblocksMsgs.hasLocale = function(locale) { +Blockly.CatblocksMsgs.hasLocale = function (locale) { return Object.keys(Blockly.CatblocksMsgs.locales).includes(locale); }; -Blockly.CatblocksMsgs.setLocale = function(locale, filesLocation = undefined) { +Blockly.CatblocksMsgs.setLocale = function (locale, filesLocation = undefined) { if (Blockly.CatblocksMsgs.hasLocale(locale)) { if (Object.keys(Blockly.CatblocksMsgs.locales[locale]).length === 1) { return Blockly.CatblocksMsgs.loadNewLocale(locale, filesLocation).then(() => { @@ -31,102 +31,103 @@ Blockly.CatblocksMsgs.setLocale = function(locale, filesLocation = undefined) { } }; -Blockly.CatblocksMsgs.reloadCurrentLocale = function() { +Blockly.CatblocksMsgs.reloadCurrentLocale = function () { return Blockly.CatblocksMsgs.setLocale(Blockly.CatblocksMsgs.currentLocale_); }; -Blockly.CatblocksMsgs.getCurrentLocale = function() { +Blockly.CatblocksMsgs.getCurrentLocale = function () { return Blockly.CatblocksMsgs.currentLocale_; }; -Blockly.CatblocksMsgs.getCurrentLocaleValues = function() { +Blockly.CatblocksMsgs.getCurrentLocaleValues = function () { return Blockly.CatblocksMsgs.locales[Blockly.CatblocksMsgs.getCurrentLocale()]; }; -Blockly.CatblocksMsgs.loadNewLocale = function(locale, filesLocation) { +Blockly.CatblocksMsgs.loadNewLocale = function (locale, filesLocation) { let json_object = []; - let url = window.location.origin + "/i18n/" + locale + ".json"; + let url = window.location.origin + '/i18n/' + locale + '.json'; if (filesLocation != null) { - url = filesLocation + locale + ".json"; + url = filesLocation + locale + '.json'; } if (window.CatBlocks && window.CatBlocks.config && window.CatBlocks.config.i18n) { - url = window.CatBlocks.config.i18n + locale + ".json"; + url = window.CatBlocks.config.i18n + locale + '.json'; } return $.getJSON(url, function (result) { json_object = result; Object.keys(json_object).forEach(key => { - if (key !== "DROPDOWN_NAME") + if (key !== 'DROPDOWN_NAME') { Blockly.CatblocksMsgs.locales[locale][key] = json_object[key]; + } }); }); }; Blockly.CatblocksMsgs.locales = { - "af": { "DROPDOWN_NAME": "Afrikaans" }, - "ar": { "DROPDOWN_NAME": "Arabic" }, - "az": { "DROPDOWN_NAME": "Azeri (Latin)" }, - "bg": { "DROPDOWN_NAME": "Bulgarian" }, - "bn": { "DROPDOWN_NAME": "bn" }, - "bs": { "DROPDOWN_NAME": "bs" }, - "ca": { "DROPDOWN_NAME": "Catalan" }, - "cs": { "DROPDOWN_NAME": "Czech" }, - "da": { "DROPDOWN_NAME": "Danish" }, - "de": { "DROPDOWN_NAME": "German" }, - "el": { "DROPDOWN_NAME": "Greek" }, - "en": { "DROPDOWN_NAME": "English" }, - "en_AU": { "DROPDOWN_NAME": "English (Australia)" }, - "en_CA": { "DROPDOWN_NAME": "English (Canada)" }, - "en_GB": { "DROPDOWN_NAME": "English (United Kingdom)" }, - "es": { "DROPDOWN_NAME": "Spanish" }, - "fa": { "DROPDOWN_NAME": "Farsi" }, - "fi": { "DROPDOWN_NAME": "Finnish" }, - "fr": { "DROPDOWN_NAME": "French" }, - "gl": { "DROPDOWN_NAME": "Galician" }, - "gu": { "DROPDOWN_NAME": "Gujarati" }, - "ha": { "DROPDOWN_NAME": "ha" }, - "hi": { "DROPDOWN_NAME": "Hindi" }, - "hr": { "DROPDOWN_NAME": "Croatian" }, - "hu": { "DROPDOWN_NAME": "Hungarian" }, - "ig": { "DROPDOWN_NAME": "ig" }, - "in": { "DROPDOWN_NAME": "in" }, - "it": { "DROPDOWN_NAME": "Italian" }, - "iw": { "DROPDOWN_NAME": "iw" }, - "ja": { "DROPDOWN_NAME": "Japanese" }, - "kk": { "DROPDOWN_NAME": "Kazakh" }, - "kn": { "DROPDOWN_NAME": "Kannada" }, - "ko": { "DROPDOWN_NAME": "Korean" }, - "lt": { "DROPDOWN_NAME": "Lithuanian" }, - "mk": { "DROPDOWN_NAME": "FYRO Macedonian" }, - "ml": { "DROPDOWN_NAME": "ml" }, - "ms": { "DROPDOWN_NAME": "Malay" }, - "nl": { "DROPDOWN_NAME": "Dutch" }, - "no": { "DROPDOWN_NAME": "no" }, - "pl": { "DROPDOWN_NAME": "Polish" }, - "ps": { "DROPDOWN_NAME": "Pashto" }, - "pt": { "DROPDOWN_NAME": "Portuguese" }, - "pt_BR": { "DROPDOWN_NAME": "Portuguese (Brazil)" }, - "ro": { "DROPDOWN_NAME": "Romanian" }, - "ru": { "DROPDOWN_NAME": "Russian" }, - "sd": { "DROPDOWN_NAME": "sd" }, - "si": { "DROPDOWN_NAME": "si" }, - "sk": { "DROPDOWN_NAME": "Slovak" }, - "sl": { "DROPDOWN_NAME": "Slovenian" }, - "sq": { "DROPDOWN_NAME": "Albanian" }, - "sr": { "DROPDOWN_NAME": "sr" }, - "sr_CS": { "DROPDOWN_NAME": "Serbian (Latin)" }, - "sr_SP": { "DROPDOWN_NAME": "Serbian (Cyrillic) (Serbia and Montenegro)" }, - "sv": { "DROPDOWN_NAME": "Swedish" }, - "sw": { "DROPDOWN_NAME": "Swahili" }, - "ta": { "DROPDOWN_NAME": "Tamil" }, - "te": { "DROPDOWN_NAME": "Telugu" }, - "th": { "DROPDOWN_NAME": "Thai" }, - "tr": { "DROPDOWN_NAME": "Turkish" }, - "tw": { "DROPDOWN_NAME": "tw" }, - "uk": { "DROPDOWN_NAME": "Ukrainian" }, - "ur": { "DROPDOWN_NAME": "Urdu" }, - "vi": { "DROPDOWN_NAME": "Vietnamese" }, - "zh_CN": { "DROPDOWN_NAME": "Chinese (S)" }, - "zh_TW": { "DROPDOWN_NAME": "Chinese (T)" }, -}; \ No newline at end of file + af: { DROPDOWN_NAME: 'Afrikaans' }, + ar: { DROPDOWN_NAME: 'Arabic' }, + az: { DROPDOWN_NAME: 'Azeri (Latin)' }, + bg: { DROPDOWN_NAME: 'Bulgarian' }, + bn: { DROPDOWN_NAME: 'bn' }, + bs: { DROPDOWN_NAME: 'bs' }, + ca: { DROPDOWN_NAME: 'Catalan' }, + cs: { DROPDOWN_NAME: 'Czech' }, + da: { DROPDOWN_NAME: 'Danish' }, + de: { DROPDOWN_NAME: 'German' }, + el: { DROPDOWN_NAME: 'Greek' }, + en: { DROPDOWN_NAME: 'English' }, + en_AU: { DROPDOWN_NAME: 'English (Australia)' }, + en_CA: { DROPDOWN_NAME: 'English (Canada)' }, + en_GB: { DROPDOWN_NAME: 'English (United Kingdom)' }, + es: { DROPDOWN_NAME: 'Spanish' }, + fa: { DROPDOWN_NAME: 'Farsi' }, + fi: { DROPDOWN_NAME: 'Finnish' }, + fr: { DROPDOWN_NAME: 'French' }, + gl: { DROPDOWN_NAME: 'Galician' }, + gu: { DROPDOWN_NAME: 'Gujarati' }, + ha: { DROPDOWN_NAME: 'ha' }, + hi: { DROPDOWN_NAME: 'Hindi' }, + hr: { DROPDOWN_NAME: 'Croatian' }, + hu: { DROPDOWN_NAME: 'Hungarian' }, + ig: { DROPDOWN_NAME: 'ig' }, + in: { DROPDOWN_NAME: 'in' }, + it: { DROPDOWN_NAME: 'Italian' }, + iw: { DROPDOWN_NAME: 'iw' }, + ja: { DROPDOWN_NAME: 'Japanese' }, + kk: { DROPDOWN_NAME: 'Kazakh' }, + kn: { DROPDOWN_NAME: 'Kannada' }, + ko: { DROPDOWN_NAME: 'Korean' }, + lt: { DROPDOWN_NAME: 'Lithuanian' }, + mk: { DROPDOWN_NAME: 'FYRO Macedonian' }, + ml: { DROPDOWN_NAME: 'ml' }, + ms: { DROPDOWN_NAME: 'Malay' }, + nl: { DROPDOWN_NAME: 'Dutch' }, + no: { DROPDOWN_NAME: 'no' }, + pl: { DROPDOWN_NAME: 'Polish' }, + ps: { DROPDOWN_NAME: 'Pashto' }, + pt: { DROPDOWN_NAME: 'Portuguese' }, + pt_BR: { DROPDOWN_NAME: 'Portuguese (Brazil)' }, + ro: { DROPDOWN_NAME: 'Romanian' }, + ru: { DROPDOWN_NAME: 'Russian' }, + sd: { DROPDOWN_NAME: 'sd' }, + si: { DROPDOWN_NAME: 'si' }, + sk: { DROPDOWN_NAME: 'Slovak' }, + sl: { DROPDOWN_NAME: 'Slovenian' }, + sq: { DROPDOWN_NAME: 'Albanian' }, + sr: { DROPDOWN_NAME: 'sr' }, + sr_CS: { DROPDOWN_NAME: 'Serbian (Latin)' }, + sr_SP: { DROPDOWN_NAME: 'Serbian (Cyrillic) (Serbia and Montenegro)' }, + sv: { DROPDOWN_NAME: 'Swedish' }, + sw: { DROPDOWN_NAME: 'Swahili' }, + ta: { DROPDOWN_NAME: 'Tamil' }, + te: { DROPDOWN_NAME: 'Telugu' }, + th: { DROPDOWN_NAME: 'Thai' }, + tr: { DROPDOWN_NAME: 'Turkish' }, + tw: { DROPDOWN_NAME: 'tw' }, + uk: { DROPDOWN_NAME: 'Ukrainian' }, + ur: { DROPDOWN_NAME: 'Urdu' }, + vi: { DROPDOWN_NAME: 'Vietnamese' }, + zh_CN: { DROPDOWN_NAME: 'Chinese (S)' }, + zh_TW: { DROPDOWN_NAME: 'Chinese (T)' } +}; diff --git a/src/js/index.js b/src/js/index.js index 5fcfe314..20d3d2e2 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -1,8 +1,8 @@ -import "../css/style.css"; -import { Playground } from "./playground/playground"; -import { Share } from "./share/share"; +import '../css/style.css'; +import { Playground } from './playground/playground'; +import { Share } from './share/share'; import * as shareUtils from './share/utils'; -import Blockly from "blockly"; +import Blockly from 'blockly'; import { renderAllPrograms } from './render/render'; (async () => { @@ -16,8 +16,7 @@ import { renderAllPrograms } from './render/render'; if (values === undefined) { console.warn('no language found for ' + process.env.DISPLAY_LANGUAGE + '. set to default.'); language = 'en'; - } - else { + } else { language = process.env.DISPLAY_LANGUAGE; } } @@ -25,47 +24,54 @@ import { renderAllPrograms } from './render/render'; await Blockly.CatblocksMsgs.setLocale(language); switch (process.env.TYPE) { - case 'playground': { - const app = new Playground(); - app.init(); - window.Catblocks = app; - break; - } - case 'share': { - const programPath = 'assets/'; - initShareAndRenderPrograms(programPath, language); - break; - } - case 'render': { - const programPath = 'assets/programs/'; - initShareAndRenderPrograms(programPath, language); - break; - } - case 'testing': { - window.Blockly = Blockly; - window.playground = new Playground(); - window.share = new Share(); - window.shareUtils = shareUtils; - window.playground.workspace = Blockly.inject('playworkspace', { - media: '../media/', zoom: { startScale: 0.75 }, toolbox: window.playground.getToolbox(true), renderer: 'zelos' - }); - window.share.init({ - 'container': 'share', - 'renderSize': 0.75, - 'shareRoot': '', - 'media': 'media/', - 'language': language, - 'noImageFound': 'No_Image_Available.jpg', - }); - window.parser = window.share.parser; - window.shareWS = window.share.workspace; - window.playgroundWS = window.playground.workspace; - window.toolboxWS = Blockly.Workspace.getById(Object.keys(Blockly.Workspace.WorkspaceDB_).filter(key => ![window.shareWS.id, window.playgroundWS.id].includes(key))); - break; - } - default: { - console.warn(`Please set process.env.TYPE properly in package.json, current value: ${process.env.TYPE}`); - } + case 'playground': { + const app = new Playground(); + app.init(); + window.Catblocks = app; + break; + } + case 'share': { + const programPath = 'assets/'; + initShareAndRenderPrograms(programPath, language); + break; + } + case 'render': { + const programPath = 'assets/programs/'; + initShareAndRenderPrograms(programPath, language); + break; + } + case 'testing': { + window.Blockly = Blockly; + window.playground = new Playground(); + window.share = new Share(); + window.shareUtils = shareUtils; + window.playground.workspace = Blockly.inject('playworkspace', { + media: '../media/', + zoom: { startScale: 0.75 }, + toolbox: window.playground.getToolbox(true), + renderer: 'zelos' + }); + window.share.init({ + container: 'share', + renderSize: 0.75, + shareRoot: '', + media: 'media/', + language: language, + noImageFound: 'No_Image_Available.jpg' + }); + window.parser = window.share.parser; + window.shareWS = window.share.workspace; + window.playgroundWS = window.playground.workspace; + window.toolboxWS = Blockly.Workspace.getById( + Object.keys(Blockly.Workspace.WorkspaceDB_).filter( + key => ![window.shareWS.id, window.playgroundWS.id].includes(key) + ) + ); + break; + } + default: { + console.warn(`Please set process.env.TYPE properly in package.json, current value: ${process.env.TYPE}`); + } } })(); @@ -74,12 +80,12 @@ function initShareAndRenderPrograms(programPath, language) { const programContainer = document.getElementById('catblocks-programs-container'); const share = new Share(); share.init({ - 'container': catblocksWorkspaceContainer, - 'renderSize': 0.75, - 'shareRoot': '', - 'media': 'media/', - 'language': language, - 'noImageFound': 'No_Image_Available.jpg', + container: catblocksWorkspaceContainer, + renderSize: 0.75, + shareRoot: '', + media: 'media/', + language: language, + noImageFound: 'No_Image_Available.jpg' }); renderAllPrograms(share, programContainer, programPath); -} \ No newline at end of file +} diff --git a/src/js/parser/formula.js b/src/js/parser/formula.js index 7c3cc1aa..df1e1454 100644 --- a/src/js/parser/formula.js +++ b/src/js/parser/formula.js @@ -12,59 +12,67 @@ export default class Formula { } setLeft(leftBlock) { - if (this.left === null) this.left = leftBlock; - else this.left.setLeft(leftBlock); + if (this.left === null) { + this.left = leftBlock; + } else { + this.left.setLeft(leftBlock); + } } setRight(rightBlock) { - if (this.right === null) this.right = rightBlock; - else this.right.setRight(rightBlock); + if (this.right === null) { + this.right = rightBlock; + } else { + this.right.setRight(rightBlock); + } } static getAllLayouts() { return { - 'BRACKET': '(%l%r)', - 'USER_LIST': '*%v*', - 'STRING': '\'%v\'', - 'USER_VARIABLE': '"%v"', - 'SIN': '%v(%l)', - 'COS': '%v(%l)', - 'TAN': '%v(%l)', - 'LN': '%v(%l)', - 'LOG': '%v(%l)', - 'ABS': '%v(%l)', - 'ROUND': '%v(%l)', - 'ARCSIN': '%v(%l)', - 'ARCCOS': '%v(%l)', - 'ARCTAN': '%v(%l)', - 'FLOOR': '%v(%l)', - 'CEIL': '%v(%l)', - 'EXP': '%v(%l)', - 'SQRT': '%v(%l)', - 'MULTI_FINGER_X': '%v(%l)', - 'MULTI_FINGER_Y': '%v(%l)', - 'MULTI_FINGER_TOUCHED': '%v(%l)', - 'ARCTAN2': '%v(%l, %r)', - 'POWER': '%v(%l, %r)', - 'MOD': '%v(%l, %r)', - 'RAND': '%v(%l, %r)', - 'MAX': '%v(%l, %r)', - 'MIN': '%v(%l, %r)', - 'LENGTH': '%v(%l%)', - 'LETTER': '%v(%l, %r)', - 'JOIN': '%v(%l, %r)', - 'REGEX': '%v(%l, %r)', - 'CONTAINS': '%v(%l, %r)', - 'NUMBER_OF_ITEMS': '%v(%l)', - 'LIST_ITEM': '%v(%l, %r)', - 'DEFAULT': '%l %v %r' + BRACKET: '(%l%r)', + USER_LIST: '*%v*', + STRING: "'%v'", + USER_VARIABLE: '"%v"', + SIN: '%v(%l)', + COS: '%v(%l)', + TAN: '%v(%l)', + LN: '%v(%l)', + LOG: '%v(%l)', + ABS: '%v(%l)', + ROUND: '%v(%l)', + ARCSIN: '%v(%l)', + ARCCOS: '%v(%l)', + ARCTAN: '%v(%l)', + FLOOR: '%v(%l)', + CEIL: '%v(%l)', + EXP: '%v(%l)', + SQRT: '%v(%l)', + MULTI_FINGER_X: '%v(%l)', + MULTI_FINGER_Y: '%v(%l)', + MULTI_FINGER_TOUCHED: '%v(%l)', + ARCTAN2: '%v(%l, %r)', + POWER: '%v(%l, %r)', + MOD: '%v(%l, %r)', + RAND: '%v(%l, %r)', + MAX: '%v(%l, %r)', + MIN: '%v(%l, %r)', + LENGTH: '%v(%l%)', + LETTER: '%v(%l, %r)', + JOIN: '%v(%l, %r)', + REGEX: '%v(%l, %r)', + CONTAINS: '%v(%l, %r)', + NUMBER_OF_ITEMS: '%v(%l)', + LIST_ITEM: '%v(%l, %r)', + DEFAULT: '%l %v %r' }; } static getOpLayout(op) { if (op) { const layout = Formula.getAllLayouts()[op]; - if (layout) return layout; + if (layout) { + return layout; + } } return Formula.getAllLayouts()['DEFAULT']; } @@ -89,13 +97,15 @@ export default class Formula { static stringify(f) { const left = (() => { - if (f.left) + if (f.left) { return Formula.stringify(f.left); + } return ''; })(); const right = (() => { - if (f.right) + if (f.right) { return Formula.stringify(f.right); + } return ''; })(); diff --git a/src/js/parser/parser.js b/src/js/parser/parser.js index 1091a4c1..55043f67 100644 --- a/src/js/parser/parser.js +++ b/src/js/parser/parser.js @@ -46,16 +46,16 @@ const sceneList = []; let xmlDoc = undefined; const supportedAppVersion = 0.994; -const XML_BEGIN = ""; -const XML_END = "\n"; -const NEXT_BEGIN = "\n"; -const NEXT_END = "\n"; -const SUB1_BEGIN = "\n"; -const SUB2_BEGIN = "\n"; -const SUB_END = "\n"; +const XML_BEGIN = ''; +const XML_END = '\n'; +const NEXT_BEGIN = '\n'; +const NEXT_END = '\n'; +const SUB1_BEGIN = '\n'; +const SUB2_BEGIN = '\n'; +const SUB_END = '\n'; let MESSAGES = {}; -let XML = ""; +let XML = ''; // global log enable switch const DEBUG = false; @@ -71,22 +71,26 @@ const catLog = (msg, debug = DEBUG) => { } }; - /** * Escape script values in case unsafe characters are included * @param {*} unsafe */ -const escapeXml = (unsafe) => { +const escapeXml = unsafe => { if (unsafe === undefined || unsafe === null || unsafe.length === 0) { return unsafe; } else { - return unsafe.replace(/[<>&'"]/g, function(c) { + return unsafe.replace(/[<>&'"]/g, function (c) { switch (c) { - case '<': return '<'; - case '>': return '>'; - case '&': return '&'; - case '\'': return '''; - case '"': return '"'; + case '<': + return '<'; + case '>': + return '>'; + case '&': + return '&'; + case "'": + return '''; + case '"': + return '"'; } }); } @@ -136,7 +140,7 @@ function parseCatroidProgram(xml) { const xmlStream = generateShareXml(); catLog(xmlStream); try { - return (new DOMParser()).parseFromString(xmlStream, 'text/xml'); + return new DOMParser().parseFromString(xmlStream, 'text/xml'); } catch (e) { console.error(`Failed to parse generated catblocks string into a XMLDocument, please verify you input`); return undefined; @@ -152,7 +156,7 @@ function getCatroidProgramObject(xml) { for (let i = 0; i < scenes.length; i++) { sceneList.push(parseScenes(scenes[i])); } - return {scenes: sceneList}; + return { scenes: sceneList }; } /** * Flat/dereference xml nodes @@ -179,7 +183,7 @@ function escapeName(name) { function parseScenes(scene) { catLog(scene); - const name = escapeName(scene.getElementsByTagName("name")[0].childNodes[0].nodeValue); + const name = escapeName(scene.getElementsByTagName('name')[0].childNodes[0].nodeValue); const currentScene = new Scene(name); const objectList = scene.getElementsByTagName('objectList')[0].children; for (let i = 0; i < objectList.length; i++) { @@ -192,7 +196,7 @@ function parseObjects(object) { object = flatReference(object); catLog(object); - const name = escapeName(object.getAttribute("name")); + const name = escapeName(object.getAttribute('name')); if (name !== null) { const currentObject = new Object(name); const lookList = object.getElementsByTagName('lookList')[0].children; @@ -249,7 +253,7 @@ function parseObjects(object) { function parseScripts(script) { catLog(script); - const name = escapeName(script.getAttribute("type")); + const name = escapeName(script.getAttribute('type')); const currentScript = new Script(name); const brickList = script.getElementsByTagName('brickList')[0].children; for (let i = 0; i < script.childNodes.length; i++) { @@ -258,19 +262,46 @@ function parseScripts(script) { let positionInScriptBrickList = 0; for (let i = 0; i < brickList.length; i++) { - if (brickList[i].attributes[0].value === "RepeatBrick" && checkIfNewProgram("RepeatBrick", brickList)) { - const loopFinished = fillLoopControlBrick(brickList, currentScript, "RepeatBrick", i, positionInScriptBrickList, null,true); + if (brickList[i].attributes[0].value === 'RepeatBrick' && checkIfNewProgram('RepeatBrick', brickList)) { + const loopFinished = fillLoopControlBrick( + brickList, + currentScript, + 'RepeatBrick', + i, + positionInScriptBrickList, + null, + true + ); i = loopFinished + 1; - } - else if(brickList[i].attributes[0].value === "IfThenLogicBeginBrick" && checkIfNewProgram("IfThenLogicBeginBrick", brickList)) { - const ifFinished = fillLoopControlBrick(brickList, currentScript, "IfThenLogicBeginBrick", i, positionInScriptBrickList, null,true); + } else if ( + brickList[i].attributes[0].value === 'IfThenLogicBeginBrick' && + checkIfNewProgram('IfThenLogicBeginBrick', brickList) + ) { + const ifFinished = fillLoopControlBrick( + brickList, + currentScript, + 'IfThenLogicBeginBrick', + i, + positionInScriptBrickList, + null, + true + ); i = ifFinished + 1; - } - else if(brickList[i].attributes[0].value === "IfLogicBeginBrick" && checkIfNewProgram("IfLogicBeginBrick", brickList)) { - const ifFinished = fillLoopControlBrick(brickList, currentScript, "IfLogicBeginBrick", i, positionInScriptBrickList, null,true); + } else if ( + brickList[i].attributes[0].value === 'IfLogicBeginBrick' && + checkIfNewProgram('IfLogicBeginBrick', brickList) + ) { + const ifFinished = fillLoopControlBrick( + brickList, + currentScript, + 'IfLogicBeginBrick', + i, + positionInScriptBrickList, + null, + true + ); i = ifFinished + 1; - } - else { + } else { currentScript.brickList.push(parseBrick(brickList[i])); positionInScriptBrickList++; } @@ -280,56 +311,58 @@ function parseScripts(script) { function checkIfNewProgram(currentBrick, brickList) { let endBrick; - if(currentBrick === 'RepeatBrick') { - endBrick = "LoopEndBrick"; - } - else if(currentBrick === 'IfLogicBeginBrick') { - endBrick = "IfLogicEndBrick"; - } - else if(currentBrick === 'IfThenLogicBeginBrick') { - endBrick = "IfThenLogicEndBrick"; + if (currentBrick === 'RepeatBrick') { + endBrick = 'LoopEndBrick'; + } else if (currentBrick === 'IfLogicBeginBrick') { + endBrick = 'IfLogicEndBrick'; + } else if (currentBrick === 'IfThenLogicBeginBrick') { + endBrick = 'IfThenLogicEndBrick'; } - for(let i = 0; i < brickList.length; i++) { - if(brickList[i].attributes[0].value === endBrick) { + for (let i = 0; i < brickList.length; i++) { + if (brickList[i].attributes[0].value === endBrick) { return true; } } return false; } -function fillLoopControlBrick(brickList, currentScript, currentBrick, counter, positionInScriptBrickList, currentListToFill = null ,firstCall = false) { - +function fillLoopControlBrick( + brickList, + currentScript, + currentBrick, + counter, + positionInScriptBrickList, + currentListToFill = null, + firstCall = false +) { let i = counter; let endBrick; let elseBrick; - if(currentBrick === 'RepeatBrick') { - endBrick = "LoopEndBrick"; + if (currentBrick === 'RepeatBrick') { + endBrick = 'LoopEndBrick'; elseBrick = null; - } - else if(currentBrick === 'IfLogicBeginBrick') { - endBrick = "IfLogicEndBrick"; - elseBrick = "IfLogicElseBrick"; - } - else if(currentBrick === 'IfThenLogicBeginBrick') { - endBrick = "IfThenLogicEndBrick"; - elseBrick = "IfThenLogicElseBrick"; - } - if(firstCall){ + } else if (currentBrick === 'IfLogicBeginBrick') { + endBrick = 'IfLogicEndBrick'; + elseBrick = 'IfLogicElseBrick'; + } else if (currentBrick === 'IfThenLogicBeginBrick') { + endBrick = 'IfThenLogicEndBrick'; + elseBrick = 'IfThenLogicElseBrick'; + } + if (firstCall) { currentScript.brickList.push(parseBrick(brickList[i])); } positionInScriptBrickList++; let position = 0; - if(positionInScriptBrickList !== 0) { + if (positionInScriptBrickList !== 0) { position = positionInScriptBrickList - 1; } i++; let list; - if(currentListToFill === null){ + if (currentListToFill === null) { list = currentScript.brickList[position]; - } - else { + } else { list = currentListToFill; } @@ -337,61 +370,97 @@ function fillLoopControlBrick(brickList, currentScript, currentBrick, counter, p let listToFill = null; while (brickList[i].attributes[0].value !== endBrick) { - if(brickList[i].attributes[0].value === elseBrick && elseBrick !== null) { + if (brickList[i].attributes[0].value === elseBrick && elseBrick !== null) { i++; break; } - if(brickList[i].attributes[0].value === "IfLogicBeginBrick"){ + if (brickList[i].attributes[0].value === 'IfLogicBeginBrick') { list.loopOrIfBrickList.push(parseBrick(brickList[i])); lastIndex = list.loopOrIfBrickList.length - 1; listToFill = list.loopOrIfBrickList[lastIndex]; - const ifFinished = fillLoopControlBrick(brickList, currentScript, "IfLogicBeginBrick", i, positionInScriptBrickList, listToFill); + const ifFinished = fillLoopControlBrick( + brickList, + currentScript, + 'IfLogicBeginBrick', + i, + positionInScriptBrickList, + listToFill + ); i = ifFinished + 1; - } - else if(brickList[i].attributes[0].value === "IfThenLogicBeginBrick") { + } else if (brickList[i].attributes[0].value === 'IfThenLogicBeginBrick') { list.loopOrIfBrickList.push(parseBrick(brickList[i])); lastIndex = list.loopOrIfBrickList.length - 1; listToFill = list.loopOrIfBrickList[lastIndex]; - const ifFinished = fillLoopControlBrick(brickList, currentScript, "IfThenLogicBeginBrick", i, positionInScriptBrickList, listToFill); + const ifFinished = fillLoopControlBrick( + brickList, + currentScript, + 'IfThenLogicBeginBrick', + i, + positionInScriptBrickList, + listToFill + ); i = ifFinished + 1; - } - else if(brickList[i].attributes[0].value === "RepeatBrick") { + } else if (brickList[i].attributes[0].value === 'RepeatBrick') { list.loopOrIfBrickList.push(parseBrick(brickList[i])); lastIndex = list.loopOrIfBrickList.length - 1; listToFill = list.loopOrIfBrickList[lastIndex]; - const loopFinished = fillLoopControlBrick(brickList, currentScript, "RepeatBrick", i, positionInScriptBrickList, listToFill); + const loopFinished = fillLoopControlBrick( + brickList, + currentScript, + 'RepeatBrick', + i, + positionInScriptBrickList, + listToFill + ); i = loopFinished + 1; - } - else { + } else { list.loopOrIfBrickList.push(parseBrick(brickList[i])); i++; } } - if(elseBrick !== null) { + if (elseBrick !== null) { while (brickList[i].attributes[0].value !== endBrick) { - if(brickList[i].attributes[0].value === "IfLogicBeginBrick"){ + if (brickList[i].attributes[0].value === 'IfLogicBeginBrick') { list.elseBrickList.push(parseBrick(brickList[i])); lastIndex = list.elseBrickList.length - 1; listToFill = list.elseBrickList[lastIndex]; - const ifFinished = fillLoopControlBrick(brickList, currentScript, "IfLogicBeginBrick", i, positionInScriptBrickList, listToFill); + const ifFinished = fillLoopControlBrick( + brickList, + currentScript, + 'IfLogicBeginBrick', + i, + positionInScriptBrickList, + listToFill + ); i = ifFinished + 1; - } - else if(brickList[i].attributes[0].value === "IfThenLogicBeginBrick") { + } else if (brickList[i].attributes[0].value === 'IfThenLogicBeginBrick') { list.elseBrickList.push(parseBrick(brickList[i])); lastIndex = list.elseBrickList.length - 1; listToFill = list.elseBrickList[lastIndex]; - const ifFinished = fillLoopControlBrick(brickList, currentScript, "IfThenLogicBeginBrick", i, positionInScriptBrickList, listToFill); + const ifFinished = fillLoopControlBrick( + brickList, + currentScript, + 'IfThenLogicBeginBrick', + i, + positionInScriptBrickList, + listToFill + ); i = ifFinished + 1; - } - else if(brickList[i].attributes[0].value === "RepeatBrick") { + } else if (brickList[i].attributes[0].value === 'RepeatBrick') { list.elseBrickList.push(parseBrick(brickList[i])); lastIndex = list.elseBrickList.length - 1; listToFill = list.elseBrickList[lastIndex]; - const loopFinished = fillLoopControlBrick(brickList, currentScript, "RepeatBrick", i, positionInScriptBrickList, listToFill); + const loopFinished = fillLoopControlBrick( + brickList, + currentScript, + 'RepeatBrick', + i, + positionInScriptBrickList, + listToFill + ); i = loopFinished + 1; - } - else { + } else { list.elseBrickList.push(parseBrick(brickList[i])); i++; } @@ -403,7 +472,7 @@ function fillLoopControlBrick(brickList, currentScript, currentBrick, counter, p function parseBrick(brick) { catLog(brick); - const name = (brick.getAttribute("type") || 'emptyBlockName').match(/[a-zA-Z]+/)[0]; + const name = (brick.getAttribute('type') || 'emptyBlockName').match(/[a-zA-Z]+/)[0]; const currentBrick = new Brick(name); for (let i = 0; i < brick.childNodes.length; i++) { @@ -417,8 +486,10 @@ function parseBrick(brick) { * @param {*} key * @param {*} def */ -const getMsgValueOrDefault = (key, def = "---") => { - if (key === undefined) return def; +const getMsgValueOrDefault = (key, def = '---') => { + if (key === undefined) { + return def; + } const msgValue = MESSAGES[key]; return msgValue ? msgValue : def; }; @@ -428,7 +499,7 @@ const getMsgValueOrDefault = (key, def = "---") => { * @param {*} node * @param {*} def */ -const getNodeValueOrDefault = (node, def = "---") => { +const getNodeValueOrDefault = (node, def = '---') => { if (node === undefined || node.nodeValue === undefined) { return def; } @@ -437,129 +508,130 @@ const getNodeValueOrDefault = (node, def = "---") => { function checkUsage(list, location) { switch (list.nodeName) { - case 'broadcastMessage': - case 'spriteToBounceOffName': - case 'receivedMessage': - case 'sceneToStart': - case 'objectToClone': - case 'soundName': - case 'motor': - case 'tone': - case 'eye': - case 'pointedObject': - case 'ledStatus': - case 'sceneForTransition': { - location.formValues.set("DROPDOWN", getNodeValueOrDefault(list.childNodes[0])); - break; - } - - case 'spinnerSelectionID': { - const brickName = list.parentElement.getAttribute('type'); - const key = getNodeValueOrDefault(list.childNodes[0]); - if (brickName === 'CameraBrick') { - location.formValues.set("SPINNER", getMsgValueOrDefault(`CAMSPINNER_${key}`, key)); - } else if (brickName === 'ChooseCameraBrick') { - location.formValues.set("SPINNER", getMsgValueOrDefault(`CAMCHOOSESPINNER_${key}`, key)); - } else { - location.formValues.set("SPINNER", getMsgValueOrDefault(`FLASHSPINNER_${key}`, key)); + case 'broadcastMessage': + case 'spriteToBounceOffName': + case 'receivedMessage': + case 'sceneToStart': + case 'objectToClone': + case 'soundName': + case 'motor': + case 'tone': + case 'eye': + case 'pointedObject': + case 'ledStatus': + case 'sceneForTransition': { + location.formValues.set('DROPDOWN', getNodeValueOrDefault(list.childNodes[0])); + break; } - break; - } - case 'type': { - const key = getNodeValueOrDefault(list.childNodes[0]); - location.formValues.set("DROPDOWN", getMsgValueOrDefault(`GRAVITY_${key}`, key)); - break; - } + case 'spinnerSelectionID': { + const brickName = list.parentElement.getAttribute('type'); + const key = getNodeValueOrDefault(list.childNodes[0]); + if (brickName === 'CameraBrick') { + location.formValues.set('SPINNER', getMsgValueOrDefault(`CAMSPINNER_${key}`, key)); + } else if (brickName === 'ChooseCameraBrick') { + location.formValues.set('SPINNER', getMsgValueOrDefault(`CAMCHOOSESPINNER_${key}`, key)); + } else { + location.formValues.set('SPINNER', getMsgValueOrDefault(`FLASHSPINNER_${key}`, key)); + } + break; + } - case 'spinnerSelection': { - const key = getNodeValueOrDefault(list.childNodes[0]); - location.formValues.set("SPINNER", getMsgValueOrDefault(`SPINNER_${key}`, key)); - break; - } + case 'type': { + const key = getNodeValueOrDefault(list.childNodes[0]); + location.formValues.set('DROPDOWN', getMsgValueOrDefault(`GRAVITY_${key}`, key)); + break; + } - case 'alignmentSelection': { - const key = getNodeValueOrDefault(list.childNodes[0]); - location.formValues.set("ALIGNMENT", getMsgValueOrDefault(`ALIGNMENTS_${key}`, key)); - break; - } + case 'spinnerSelection': { + const key = getNodeValueOrDefault(list.childNodes[0]); + location.formValues.set('SPINNER', getMsgValueOrDefault(`SPINNER_${key}`, key)); + break; + } - case 'ledAnimationName': { - const key = getNodeValueOrDefault(list.childNodes[0]); - location.formValues.set("ADRONEANIMATION", getMsgValueOrDefault(key, key)); - break; - } + case 'alignmentSelection': { + const key = getNodeValueOrDefault(list.childNodes[0]); + location.formValues.set('ALIGNMENT', getMsgValueOrDefault(`ALIGNMENTS_${key}`, key)); + break; + } - case 'animationName': { - const key = getNodeValueOrDefault(list.childNodes[0]); - location.formValues.set("ANIMATION", getMsgValueOrDefault(`ANIMATION_${key}`, key)); - break; - } + case 'ledAnimationName': { + const key = getNodeValueOrDefault(list.childNodes[0]); + location.formValues.set('ADRONEANIMATION', getMsgValueOrDefault(key, key)); + break; + } - case 'selection': { - const key = getNodeValueOrDefault(list.childNodes[0]); - location.formValues.set("SPINNER", getMsgValueOrDefault(`POINTTO_${key}`, key)); - break; - } + case 'animationName': { + const key = getNodeValueOrDefault(list.childNodes[0]); + location.formValues.set('ANIMATION', getMsgValueOrDefault(`ANIMATION_${key}`, key)); + break; + } - case 'formulaMap': - case 'formulaList': { - const formulaList = list.children; - for (let j = 0; j < formulaList.length; j++) { - const formula = new Formula(); - workFormula(formula, formulaList[j]); - const attribute = formulaList[j].getAttribute("category"); - location.formValues.set(attribute, Formula.stringify(formula)); + case 'selection': { + const key = getNodeValueOrDefault(list.childNodes[0]); + location.formValues.set('SPINNER', getMsgValueOrDefault(`POINTTO_${key}`, key)); + break; } - break; - } - case 'ifBranchBricks': - case 'loopBricks': { - const loopOrIfBrickList = (list.children); - for (let j = 0; j < loopOrIfBrickList.length; j++) { - location.loopOrIfBrickList.push(parseBrick(loopOrIfBrickList[j])); + case 'formulaMap': + case 'formulaList': { + const formulaList = list.children; + for (let j = 0; j < formulaList.length; j++) { + const formula = new Formula(); + workFormula(formula, formulaList[j]); + const attribute = formulaList[j].getAttribute('category'); + location.formValues.set(attribute, Formula.stringify(formula)); + } + break; } - break; - } - case 'elseBranchBricks': { - const elseBrickList = (list.children); - for (let j = 0; j < elseBrickList.length; j++) { - location.elseBrickList.push(parseBrick(elseBrickList[j])); + case 'ifBranchBricks': + case 'loopBricks': { + const loopOrIfBrickList = list.children; + for (let j = 0; j < loopOrIfBrickList.length; j++) { + location.loopOrIfBrickList.push(parseBrick(loopOrIfBrickList[j])); + } + break; } - break; - } - case 'sound': - case 'look': { - const node = flatReference(list); - const name = node.getAttribute('name'); - location.formValues.set(list.nodeName, name); - break; - } + case 'elseBranchBricks': { + const elseBrickList = list.children; + for (let j = 0; j < elseBrickList.length; j++) { + location.elseBrickList.push(parseBrick(elseBrickList[j])); + } + break; + } - case 'userVariable': - case 'userList': { - const node = flatReference(list); - const nodeName = (node.querySelector(`${list.nodeName} name`)) ? - node.querySelector(`${list.nodeName} name`).textContent : 'node'; - location.formValues.set('DROPDOWN', nodeName); - break; - } + case 'sound': + case 'look': { + const node = flatReference(list); + const name = node.getAttribute('name'); + location.formValues.set(list.nodeName, name); + break; + } + + case 'userVariable': + case 'userList': { + const node = flatReference(list); + const nodeName = node.querySelector(`${list.nodeName} name`) + ? node.querySelector(`${list.nodeName} name`).textContent + : 'node'; + location.formValues.set('DROPDOWN', nodeName); + break; + } - default: + default: } } function workFormula(formula, input) { for (let i = 0; i < input.childNodes.length; i++) { - if (input.childNodes[i].nodeName === "leftChild") { + if (input.childNodes[i].nodeName === 'leftChild') { const newFormula = new Formula(); formula.setLeft(newFormula); workFormula(newFormula, input.childNodes[i]); } - if (input.childNodes[i].nodeName === "rightChild") { + if (input.childNodes[i].nodeName === 'rightChild') { const newFormula = new Formula(); formula.setRight(newFormula); workFormula(newFormula, input.childNodes[i]); @@ -567,11 +639,26 @@ function workFormula(formula, input) { if (input.childNodes[i].nodeName === 'type') { const typeValue = input.childNodes[i].innerHTML; - if (typeValue === 'BRACKET' || typeValue === 'USER_LIST' || typeValue === 'STRING' || typeValue === 'NUMBER' || typeValue === 'USER_VARIABLE') formula.operator = typeValue; + if ( + typeValue === 'BRACKET' || + typeValue === 'USER_LIST' || + typeValue === 'STRING' || + typeValue === 'NUMBER' || + typeValue === 'USER_VARIABLE' + ) { + formula.operator = typeValue; + } } - if (input.childNodes[i].nodeName === "value") { + if (input.childNodes[i].nodeName === 'value') { const operatorKey = getNodeValueOrDefault(input.childNodes[i].childNodes[0]); - if (formula.operator !== 'USER_LIST' && formula.operator !== 'STRING' && formula.operator !== 'NUMBER' && formula.operator !== 'USER_VARIABLE') formula.operator = operatorKey; + if ( + formula.operator !== 'USER_LIST' && + formula.operator !== 'STRING' && + formula.operator !== 'NUMBER' && + formula.operator !== 'USER_VARIABLE' + ) { + formula.operator = operatorKey; + } formula.value = getMsgValueOrDefault(operatorKey, operatorKey); } } @@ -604,17 +691,16 @@ function generateShareXml() { } function writeScriptsToXML(currScript) { - XML = XML.concat("\n"); + XML = XML.concat('\n'); for (const [key, value] of currScript.formValues) { - XML = XML.concat("\n" + escapeXml(value) + ""); + XML = XML.concat('\n' + escapeXml(value) + ''); } if (currScript.brickList.length !== 0) { writeBrickToXML(currScript, 0, true, 0); } - XML = XML.concat("\n"); + XML = XML.concat('\n'); } - function writeBrickToXML(currBrick, index, nextBrick, subBlock) { if (nextBrick === true) { XML = XML.concat(NEXT_BEGIN); @@ -629,10 +715,10 @@ function writeBrickToXML(currBrick, index, nextBrick, subBlock) { if (subBlock === 2) { currSubBrick = currBrick.elseBrickList[index]; } - XML = XML.concat("\n"); + XML = XML.concat('\n'); for (const [key, value] of currSubBrick.formValues) { - XML = XML.concat("\n" + escapeXml(value) + ""); + XML = XML.concat('\n' + escapeXml(value) + ''); } if (currSubBrick.loopOrIfBrickList.length !== 0) { XML = XML.concat(SUB1_BEGIN); @@ -644,16 +730,16 @@ function writeBrickToXML(currBrick, index, nextBrick, subBlock) { writeBrickToXML(currSubBrick, 0, false, 2); XML = XML.concat(SUB_END); } - if (subBlock === 0 && (currBrick.brickList.length > index + 1)) { + if (subBlock === 0 && currBrick.brickList.length > index + 1) { writeBrickToXML(currBrick, index + 1, true, 0); } - if (subBlock === 1 && (currBrick.loopOrIfBrickList.length > index + 1)) { + if (subBlock === 1 && currBrick.loopOrIfBrickList.length > index + 1) { writeBrickToXML(currBrick, index + 1, true, 1); } - if (subBlock === 2 && (currBrick.elseBrickList.length > index + 1)) { + if (subBlock === 2 && currBrick.elseBrickList.length > index + 1) { writeBrickToXML(currBrick, index + 1, true, 2); } - XML = XML.concat("\n"); + XML = XML.concat('\n'); if (nextBrick === true) { XML = XML.concat(NEXT_END); } @@ -664,7 +750,6 @@ function writeBrickToXML(currBrick, index, nextBrick, subBlock) { * Only those methodes are visible outside this module */ export default class Parser { - /** * Parse catroid script into catblocks * @param {XMLDocument} scriptDoc to parse @@ -676,7 +761,7 @@ export default class Parser { const catScript = parseScripts(scriptDoc.firstChild); writeScriptsToXML(catScript); try { - return (new DOMParser()).parseFromString(XML, 'text/xml'); + return new DOMParser().parseFromString(XML, 'text/xml'); } catch (e) { catLog(e); console.error('Failed to convert catblocks script into XMLDocument, verify input'); @@ -692,11 +777,13 @@ export default class Parser { static convertScriptString(scriptString) { if (typeof scriptString === 'string') { try { - const xml = (new window.DOMParser()).parseFromString(scriptString, 'text/xml'); + const xml = new window.DOMParser().parseFromString(scriptString, 'text/xml'); return Parser.convertScript(xml); } catch (e) { catLog(e); - console.error(`Failed to convert catroid script given as string into a XMLDocument, please verify that the string is a valid program`); + console.error( + `Failed to convert catroid script given as string into a XMLDocument, please verify that the string is a valid program` + ); return undefined; } } @@ -711,14 +798,18 @@ export default class Parser { static convertProgramString(xmlString) { if (typeof xmlString === 'string') { try { - const xml = (new window.DOMParser()).parseFromString(xmlString, 'text/xml'); - if (!isSupported(xml)) return undefined; + const xml = new window.DOMParser().parseFromString(xmlString, 'text/xml'); + if (!isSupported(xml)) { + return undefined; + } initParser(xml); return parseCatroidProgram(xml); } catch (e) { catLog(e); - console.error(`Failed to convert catroid program given as string into a XMLDocument, please verify that the string is a valid program`); + console.error( + `Failed to convert catroid program given as string into a XMLDocument, please verify that the string is a valid program` + ); return undefined; } } @@ -734,13 +825,15 @@ export default class Parser { const retVal = Parser.convertProgramString(xmlString); if (retVal === undefined) { - const xml = (new window.DOMParser()).parseFromString(xmlString, 'text/xml'); + const xml = new window.DOMParser().parseFromString(xmlString, 'text/xml'); const appVersion = xml.getElementsByTagName('catrobatLanguageVersion'); if (appVersion === undefined || appVersion.length < 1) { throw new Error(`Found program version "${appVersion}", minimum supported is ${supportedAppVersion}`); } else if (appVersion[0].innerHTML < supportedAppVersion) { - throw new Error(`Found program version ${appVersion[0].innerHTML}, minimum supported is ${supportedAppVersion}`); + throw new Error( + `Found program version ${appVersion[0].innerHTML}, minimum supported is ${supportedAppVersion}` + ); } initParser(xml); @@ -750,7 +843,6 @@ export default class Parser { return retVal; } - /** * Convert given XML to JSON object * @static @@ -760,21 +852,24 @@ export default class Parser { static convertProgramToJSON(xmlString) { if (typeof xmlString === 'string') { try { - const xml = (new window.DOMParser()).parseFromString(xmlString, 'text/xml'); - if (!isSupported(xml)) return undefined; + const xml = new window.DOMParser().parseFromString(xmlString, 'text/xml'); + if (!isSupported(xml)) { + return undefined; + } initParser(xml); return getCatroidProgramObject(xml); } catch (e) { catLog(e); - console.error(`Failed to convert catroid program given as string into a XMLDocument, please verify that the string is a valid program`); + console.error( + `Failed to convert catroid program given as string into a XMLDocument, please verify that the string is a valid program` + ); return undefined; } } return getCatroidProgramObject(xmlString); } - /** * Convert given XML to JSON object and return every error * @static @@ -785,13 +880,15 @@ export default class Parser { const obj = Parser.convertProgramToJSON(xmlString); if (obj === undefined) { - const xml = (new window.DOMParser()).parseFromString(xmlString, 'text/xml'); + const xml = new window.DOMParser().parseFromString(xmlString, 'text/xml'); const appVersion = xml.getElementsByTagName('catrobatLanguageVersion'); if (appVersion === undefined || appVersion.length < 1) { throw new Error(`Found program version "${appVersion}", minimum supported is ${supportedAppVersion}`); } else if (appVersion[0].innerHTML < supportedAppVersion) { - throw new Error(`Found program version ${appVersion[0].innerHTML}, minimum supported is ${supportedAppVersion}`); + throw new Error( + `Found program version ${appVersion[0].innerHTML}, minimum supported is ${supportedAppVersion}` + ); } initParser(xml); @@ -818,4 +915,4 @@ export default class Parser { return undefined; }); } -} \ No newline at end of file +} diff --git a/src/js/playground/playground.js b/src/js/playground/playground.js index 1a377526..153e5fbe 100644 --- a/src/js/playground/playground.js +++ b/src/js/playground/playground.js @@ -1,9 +1,9 @@ -import Blockly from "blockly"; -import "../catblocks_msgs"; -import "./../blocks"; -import {wrapElement, zebraChangeColor} from '../share/utils'; -import XStreamParser from "../parser/parser"; -import $ from "jquery"; +import Blockly from 'blockly'; +import '../catblocks_msgs'; +import './../blocks'; +import { wrapElement, zebraChangeColor } from '../share/utils'; +import XStreamParser from '../parser/parser'; +import $ from 'jquery'; export class Playground { constructor() { @@ -15,7 +15,6 @@ export class Playground { this.workspace = undefined; } init() { - this.bindListeners(); this.equalsXml = [ @@ -49,7 +48,7 @@ export class Playground { if (soundsEnabled === null) { soundsEnabled = true; } else { - soundsEnabled = (soundsEnabled === 'true'); + soundsEnabled = soundsEnabled === 'true'; } } else { soundsEnabled = true; @@ -66,7 +65,7 @@ export class Playground { document.forms.options.elements.side.value = side; // Setup locale - const select = document.getElementsByName("locale")[0]; + const select = document.getElementsByName('locale')[0]; Object.keys(this.Blockly.CatblocksMsgs.locales).forEach(locale => { const lcoale_opt = document.createElement('option'); lcoale_opt.value = locale; @@ -77,7 +76,10 @@ export class Playground { // Create main workspace. this.workspace = this.Blockly.inject('blocklyDiv', { - media: '../media/', zoom: { startScale: 0.75 }, toolbox: this.getToolbox(), renderer: 'zelos' + media: '../media/', + zoom: { startScale: 0.75 }, + toolbox: this.getToolbox(), + renderer: 'zelos' }); if (sessionStorage) { @@ -114,13 +116,13 @@ export class Playground { $('#importFromParser').click(() => this.fromParser()); const self = this; - $('#logCheck').click(function() { + $('#logCheck').click(function () { self.logEvents($(this).is(':checked')); }); - $('#logFlyoutCheck').click(function() { + $('#logFlyoutCheck').click(function () { self.logFlyoutEvents($(this).is(':checked')); }); - $('#soundsEnabled').click(function() { + $('#soundsEnabled').click(function () { self.setSoundsEnabled($(this).is(':checked')); }); @@ -140,7 +142,7 @@ export class Playground { } setSoundsEnabled(state) { const checkbox = document.getElementById('soundsEnabled'); - checkbox.checked = (state) ? 'checked' : ''; + checkbox.checked = state ? 'checked' : ''; if (sessionStorage) { sessionStorage.setItem('soundsEnabled', state); } @@ -163,7 +165,9 @@ export class Playground { brick.setAttribute('type', brickName); parentNode.append(brick); } - if (!simple) xml.append(parentNode); + if (!simple) { + xml.append(parentNode); + } } this.toolbox = xml; } @@ -208,8 +212,9 @@ export class Playground { sessionStorage.setItem('logFlyoutEvents', state ? 'checked' : ''); } - const flyoutWorkspace = (this.workspace.flyout_) ? this.workspace.flyout_.workspace_ : - this.workspace.toolbox_.flyout_.workspace_; + const flyoutWorkspace = this.workspace.flyout_ + ? this.workspace.flyout_.workspace_ + : this.workspace.toolbox_.flyout_.workspace_; if (state) { flyoutWorkspace.addChangeListener(this.logger); } else { @@ -235,8 +240,8 @@ export class Playground { const blocksXml = this.Parser.convertScriptString(input.value); console.log(blocksXml); - if (blocksXml === undefined || blocksXml === "") { - throw "no response from XStreamParser"; + if (blocksXml === undefined || blocksXml === '') { + throw 'no response from XStreamParser'; } else { this.Blockly.Xml.domToWorkspace(wrapElement(blocksXml.firstChild, 'xml'), this.workspace); } @@ -247,7 +252,6 @@ export class Playground { zebraChangeColor(blocks); } - glowBlock() { if (this.Blockly.selected) { this.workspace.glowBlock(this.Blockly.selected.id, true); @@ -279,36 +283,29 @@ export class Playground { const blockXML = blocks[Math.floor(Math.random() * blocks.length)]; const block = this.Blockly.Xml.domToBlock(blockXML, this.workspace); block.initSvg(); - block.moveBy( - Math.round(Math.random() * 450 + 40), - Math.round(Math.random() * 600 + 40) - ); + block.moveBy(Math.round(Math.random() * 450 + 40), Math.round(Math.random() * 600 + 40)); } } spaghetti(n) { - console.log("Starting spaghetti. This may take some time..."); + console.log('Starting spaghetti. This may take some time...'); let xml = this.spaghettiXml; // Nest if/else statements deeply. for (let i = 0; i < 2 * n; i++) { - xml = xml.replace(/()<\//g, - '$1' + this.spaghettiXml + ')<\//g, '$1' + this.spaghettiXml + ')<\//g, - '$1' + this.spaghettiXml + ')<\//g, '$1' + this.spaghettiXml + ')<\/shadow>/g, this.equalsXml); + equalsBlock = equalsBlock.replace(/()<\/shadow>/g, this.equalsXml); } // Put the nested boolean comparisons into if/else statements. - xml = xml.replace(/()<\/shadow>/g, - equalsBlock); + xml = xml.replace(/()<\/shadow>/g, equalsBlock); xml = '' + xml + ''; const dom = this.Blockly.Xml.textToDom(xml); @@ -318,10 +315,7 @@ export class Playground { } reportDemo() { if (this.Blockly.selected) { - this.workspace.reportValue( - this.Blockly.selected.id, - document.getElementById('reportValue').value - ); + this.workspace.reportValue(this.Blockly.selected.id, document.getElementById('reportValue').value); } } setLocale(locale) { @@ -331,6 +325,6 @@ export class Playground { const xml = this.Blockly.Xml.workspaceToDom(this.workspace); this.Blockly.Xml.clearWorkspaceAndLoadFromXml(xml, this.workspace); }) - .catch((error) => console.error(error)); + .catch(error => console.error(error)); } -} \ No newline at end of file +} diff --git a/src/js/release.js b/src/js/release.js index 3fcd35e1..586e11f8 100644 --- a/src/js/release.js +++ b/src/js/release.js @@ -1,90 +1,88 @@ -import { Share } from "./share/share"; -import { renderProgram } from "./render/render"; -import "./catblocks_msgs"; -import "./blocks"; - - -/** - * Initialize Share-Object and change Language - * @export - * @param {*} config - */ -export function init (config) { - if (!config) { - throw new Error("No configuration given"); - } - - this.config = config; - - preparePaths(this); - - this.share = new Share(); - this.share.init(config); -} - -/** - * Prepares all paths given in config - */ -function preparePaths(that) { - that.config.shareRoot = addTrailingSlash(that.config.shareRoot); - that.config.shareRoot = that.config.shareRoot.replace(/^\//, ""); - - that.config.media = addTrailingSlash(that.config.media); - that.config.i18n = addTrailingSlash(that.config.i18n); - - that.config.media = createURL(that, that.config.media); - that.config.i18n = createURL(that, that.config.i18n); - - if (!that.config.shareRoot.startsWith("http")) { - that.config.shareRoot = "/" + that.config.shareRoot; - } -} - -/** - * Create URL - * @param {*} path - * @returns - */ -function createURL(that, path) { - if (path.startsWith("http")) { - return path; - } - if (path.startsWith("/")) { - return window.location.origin + path; - } - - if (that.config.shareRoot.startsWith("http")) { - return that.config.shareRoot + path; - } - return window.location.origin + "/" + that.config.shareRoot + path; -} - -/** - * Be sure there is a trailing slash. Only one. - * @param {*} string - * @returns - */ -function addTrailingSlash (string) { - if (string) { - return string.replace(/\/$/, "") + "/"; - } -} - - -/** - * Render program from given path - * @export - * @param {*} path Path containing the program folders - * @param {*} name Name of program folder - * @returns Promise - */ -export function render (path, name) { - if (this.config == null || this.config.container == null) { - throw new Error("No Container specified"); - } else if (path == null) { - throw new Error("No path specified"); - } - - const programContainer = document.getElementById(this.config.container); - return renderProgram(this.share, programContainer, path, name); -} +import { Share } from './share/share'; +import { renderProgram } from './render/render'; +import './catblocks_msgs'; +import './blocks'; + +/** + * Initialize Share-Object and change Language + * @export + * @param {*} config + */ +export function init(config) { + if (!config) { + throw new Error('No configuration given'); + } + + this.config = config; + + preparePaths(this); + + this.share = new Share(); + this.share.init(config); +} + +/** + * Prepares all paths given in config + */ +function preparePaths(that) { + that.config.shareRoot = addTrailingSlash(that.config.shareRoot); + that.config.shareRoot = that.config.shareRoot.replace(/^\//, ''); + + that.config.media = addTrailingSlash(that.config.media); + that.config.i18n = addTrailingSlash(that.config.i18n); + + that.config.media = createURL(that, that.config.media); + that.config.i18n = createURL(that, that.config.i18n); + + if (!that.config.shareRoot.startsWith('http')) { + that.config.shareRoot = '/' + that.config.shareRoot; + } +} + +/** + * Create URL + * @param {*} path + * @returns + */ +function createURL(that, path) { + if (path.startsWith('http')) { + return path; + } + if (path.startsWith('/')) { + return window.location.origin + path; + } + + if (that.config.shareRoot.startsWith('http')) { + return that.config.shareRoot + path; + } + return window.location.origin + '/' + that.config.shareRoot + path; +} + +/** + * Be sure there is a trailing slash. Only one. + * @param {*} string + * @returns + */ +function addTrailingSlash(string) { + if (string) { + return string.replace(/\/$/, '') + '/'; + } +} + +/** + * Render program from given path + * @export + * @param {*} path Path containing the program folders + * @param {*} name Name of program folder + * @returns Promise + */ +export function render(path, name) { + if (this.config == null || this.config.container == null) { + throw new Error('No Container specified'); + } else if (path == null) { + throw new Error('No path specified'); + } + + const programContainer = document.getElementById(this.config.container); + return renderProgram(this.share, programContainer, path, name); +} diff --git a/src/js/render/file_dropper.js b/src/js/render/file_dropper.js index 1f200400..03243f55 100644 --- a/src/js/render/file_dropper.js +++ b/src/js/render/file_dropper.js @@ -1,10 +1,10 @@ -import $ from "jquery"; -import JSZip from "jszip"; -import { MessageBox } from "./message_box"; +import $ from 'jquery'; +import JSZip from 'jszip'; +import { MessageBox } from './message_box'; -/** +/** * Initialize Drag & Drop Field and handle Files. - * + * * @author michael.flucher@student.tugraz.at */ @@ -17,7 +17,6 @@ export class FileDropper { this.renderProgram = renderProgram; } - /** * Creates or returns Singleton instance. * @static @@ -35,7 +34,6 @@ export class FileDropper { return instance; } - /** * Returns Singleton instance. * @static @@ -46,7 +44,6 @@ export class FileDropper { return instance; } - /** * Register all Events for drag&drop area. * @memberof FileDropper @@ -54,21 +51,24 @@ export class FileDropper { enableDragAndDrop() { const $ele = $('#catblocks-file-dropper'); - $ele.on('drag dragstart dragend dragover dragenter dragleave drop', e => { - e.preventDefault(); - e.stopPropagation(); - }).on('dragover dragenter', () => { - $ele.addClass('hover'); - }).on('dragleave dragend drop', () => { - $ele.removeClass('hover'); - }).on('drop', this._handleFileDrop); + $ele + .on('drag dragstart dragend dragover dragenter dragleave drop', e => { + e.preventDefault(); + e.stopPropagation(); + }) + .on('dragover dragenter', () => { + $ele.addClass('hover'); + }) + .on('dragleave dragend drop', () => { + $ele.removeClass('hover'); + }) + .on('drop', this._handleFileDrop); $('#dropper-file-input').on('change', this._handleInputChange); $ele.css('display', 'flex'); } - /** * EventHandler for drop area. * @private @@ -95,7 +95,6 @@ export class FileDropper { } } - /** * Show or Hide loading overlay. * @private @@ -104,20 +103,19 @@ export class FileDropper { */ _updateView(event) { switch (event) { - case 'onStart': - $('#loading-overlay').show(); - break; - - case 'onDone': - $('#loading-overlay').hide(); - break; - - default: - console.warn(`Ignore file dropper event: ${event}`); + case 'onStart': + $('#loading-overlay').show(); + break; + + case 'onDone': + $('#loading-overlay').hide(); + break; + + default: + console.warn(`Ignore file dropper event: ${event}`); } } - /** * Returns the Base64 Src String for HTML. * @private @@ -127,11 +125,10 @@ export class FileDropper { * @memberof FileDropper */ _generateBase64Src(fileName, fileExt, base64) { - // images if (fileExt.toLowerCase() === 'png' || fileExt.toLowerCase().includes('png')) { return 'data:image/png;charset=utf-8;base64,' + base64; - } + } if (fileExt.toLowerCase() === 'jpg' || fileExt.toLowerCase().includes('jpg')) { return 'data:image/jpg;charset=utf-8;base64,' + base64; } @@ -164,10 +161,9 @@ export class FileDropper { // ignore the rest console.warn('FileDropper: Ignoring File ' + fileName); - return ""; + return ''; } - /** * Load .catrobat / .zip file * @private @@ -177,76 +173,75 @@ export class FileDropper { * @memberof FileDropper */ _loadArchive(containerfile, containerCounter) { - return new Promise((resolve) => { + return new Promise(resolve => { // open ZIP const zip = new JSZip(); - zip.loadAsync(containerfile, { - createFolders: true - }).then(element => { - - if (element.files['code.xml'] == null) { - throw new Error('Code.xml not found'); - } - - const fileMap = {}; - let codeXML = ""; - - const zipFileKeys = Object.keys(element.files); - const filePromises = []; - - for (const key of zipFileKeys) { - const file = element.files[key]; - - if (!file.dir) { - - if (file.name.toLowerCase() === 'code.xml') { - const promise = zip.file(file.name).async('string'); - filePromises.push(promise); - - promise.then(str => { - codeXML = str; - }); - - } else { - const promise = zip.file(file.name).async('base64'); - filePromises.push(promise); - - promise.then(base64 => { - let fileEnding = file.name.split('.'); + zip + .loadAsync(containerfile, { + createFolders: true + }) + .then(element => { + if (element.files['code.xml'] == null) { + throw new Error('Code.xml not found'); + } - if (fileEnding.length > 1) { - fileEnding = fileEnding[fileEnding.length - 1]; - fileMap[file.name] = this._generateBase64Src(file.name, fileEnding, base64); - } else { - fileMap[file.name] = this._generateBase64Src(file.name, atob(base64).substr(0, 32), base64); - } - - }); + const fileMap = {}; + let codeXML = ''; + + const zipFileKeys = Object.keys(element.files); + const filePromises = []; + + for (const key of zipFileKeys) { + const file = element.files[key]; + + if (!file.dir) { + if (file.name.toLowerCase() === 'code.xml') { + const promise = zip.file(file.name).async('string'); + filePromises.push(promise); + + promise.then(str => { + codeXML = str; + }); + } else { + const promise = zip.file(file.name).async('base64'); + filePromises.push(promise); + + promise.then(base64 => { + let fileEnding = file.name.split('.'); + + if (fileEnding.length > 1) { + fileEnding = fileEnding[fileEnding.length - 1]; + fileMap[file.name] = this._generateBase64Src(file.name, fileEnding, base64); + } else { + fileMap[file.name] = this._generateBase64Src(file.name, atob(base64).substr(0, 32), base64); + } + }); + } } } - } - Promise.all(filePromises).then(response => { - if (response.length !== Object.keys(fileMap).length + 1) { - MessageBox.show('' + containerfile.name + ': Number of Files in Archive do not match number of read files.'); - console.error('Number of Files in ZIP do not match number of read files'); - } - - const fd = FileDropper.getInstance(); - try { - fd.renderProgram(fd.share, fd.container, codeXML, containerfile.name, containerCounter, fileMap); - resolve(true); - } catch (error) { - console.error(error); - MessageBox.show('' + containerfile.name + ': ' + error); - resolve(false); - } + Promise.all(filePromises).then(response => { + if (response.length !== Object.keys(fileMap).length + 1) { + MessageBox.show( + '' + containerfile.name + ': Number of Files in Archive do not match number of read files.' + ); + console.error('Number of Files in ZIP do not match number of read files'); + } + + const fd = FileDropper.getInstance(); + try { + fd.renderProgram(fd.share, fd.container, codeXML, containerfile.name, containerCounter, fileMap); + resolve(true); + } catch (error) { + console.error(error); + MessageBox.show('' + containerfile.name + ': ' + error); + resolve(false); + } + }); }); - }); }); } - /** * Unpack Archive and start rendering of code.xml * @param {File} inputFiles @@ -287,6 +282,5 @@ export class FileDropper { } else { this._updateView('onDone'); } - } -} \ No newline at end of file +} diff --git a/src/js/render/message_box.js b/src/js/render/message_box.js index 4e6dce8d..1c409ead 100644 --- a/src/js/render/message_box.js +++ b/src/js/render/message_box.js @@ -1,5 +1,4 @@ - -import $ from "jquery"; +import $ from 'jquery'; // default display duration const DISPLAY_DURATION = 10000; @@ -7,8 +6,6 @@ const CONTAINER_ID = 'catblocks-message-container'; const messages = []; export class MessageBox { - - /** * Show Message in a Box on the bottom of the screen. * @static @@ -31,7 +28,6 @@ export class MessageBox { }, time); } - /** * Create/remove or redraw messagebox. * @static @@ -40,10 +36,9 @@ export class MessageBox { */ static _render() { if (messages.length === 0) { - $(`#${CONTAINER_ID}`).fadeOut("slow", () => { + $(`#${CONTAINER_ID}`).fadeOut('slow', () => { $(`#${CONTAINER_ID}`).remove(); }); - } else if ($(`#${CONTAINER_ID}`).length) { const $ul = $('