├── .gitignore
├── src
├── components
│ ├── game
│ │ ├── index.js
│ │ ├── GameArea.jsx
│ │ └── Engine.js
│ ├── blocky
│ │ ├── index.jsx
│ │ ├── custom
│ │ │ ├── playerX
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── playerY
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── canvasWidth
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── canvasHeight
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── gameEndGame
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── overWrite.js
│ │ │ ├── gameTarget
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── gameObstacle
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── playerDeadDuck
│ │ │ │ ├── index.js
│ │ │ │ └── definition.js
│ │ │ ├── setPlayerIcon
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── textSize
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── gameMoveTargetX
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── gameMoveTargetY
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── gameMoveObstacleX
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── gameMoveObstacleY
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── canvasSetTextColor
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── backgroundColor
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── gameSetPlayerPositionX
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── gameSetPlayerPositionY
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── playerDuck
│ │ │ │ ├── index.js
│ │ │ │ └── definition.js
│ │ │ ├── playerChicken
│ │ │ │ ├── index.js
│ │ │ │ └── definition.js
│ │ │ ├── playerDeadChicken
│ │ │ │ ├── index.js
│ │ │ │ └── definition.js
│ │ │ ├── canvasSetTextAlign
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── canvasSetCursor
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── gameSetPlayerPosition
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── canvasDrawRectangle
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── gameSetup
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── initialize.js
│ │ ├── BlocklyEditor.jsx
│ │ └── toolbox.js
│ ├── Wrapper.jsx
│ ├── ContentWrapper.jsx
│ ├── Navigator.jsx
│ └── Settings.jsx
├── WorkspaceContext.js
├── constants.js
├── utils
│ └── debounce.js
├── main.jsx
├── favicon.svg
├── App.jsx
├── logo.svg
└── index.css
├── public
└── images
│ ├── duck.png
│ ├── chicken.png
│ ├── deadDuck.png
│ ├── deadChicken.png
│ ├── deadDuck.svg
│ ├── duck.svg
│ ├── chicken.svg
│ └── deadChicken.svg
├── README.md
├── vite.config.js
├── index.html
├── package.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | dist-ssr
5 | *.local
--------------------------------------------------------------------------------
/src/components/game/index.js:
--------------------------------------------------------------------------------
1 | export { GameArea } from './GameArea';
2 |
--------------------------------------------------------------------------------
/src/components/blocky/index.jsx:
--------------------------------------------------------------------------------
1 | export { BlocklyEditor } from './BlocklyEditor';
2 |
--------------------------------------------------------------------------------
/public/images/duck.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drFabio/blockly-game-creator/main/public/images/duck.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # blockly game creator
2 |
3 | A blockly based game engine for teaching entry level coding classes
4 |
--------------------------------------------------------------------------------
/public/images/chicken.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drFabio/blockly-game-creator/main/public/images/chicken.png
--------------------------------------------------------------------------------
/public/images/deadDuck.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drFabio/blockly-game-creator/main/public/images/deadDuck.png
--------------------------------------------------------------------------------
/public/images/deadChicken.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drFabio/blockly-game-creator/main/public/images/deadChicken.png
--------------------------------------------------------------------------------
/src/WorkspaceContext.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | export const WorkspaceContext = createContext();
4 |
--------------------------------------------------------------------------------
/src/components/Wrapper.jsx:
--------------------------------------------------------------------------------
1 | export const Wrapper = ({ children }) => {
2 | return
{children}
;
3 | };
4 |
--------------------------------------------------------------------------------
/src/constants.js:
--------------------------------------------------------------------------------
1 | export const PAGE_CODE = 0;
2 | export const PAGE_MIX = 1;
3 | export const PAGE_APP = 2;
4 | export const PAGE_SETTINGS = 3;
5 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerX/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'player_x',
3 | message0: 'PLAYER_X',
4 | output: null,
5 | colour: '#FFAABB',
6 | tooltip: '',
7 | helpUrl: '',
8 | };
9 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerY/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'player_y',
3 | message0: 'PLAYER_Y',
4 | output: null,
5 | colour: '#FFAABB',
6 | tooltip: '',
7 | helpUrl: '',
8 | };
9 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasWidth/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'canvas_width',
3 | message0: 'CANVAS_WIDTH',
4 | output: null,
5 | colour: '#6600cc',
6 | tooltip: '',
7 | helpUrl: '',
8 | };
9 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasHeight/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'canvas_height',
3 | message0: 'CANVAS_HEIGHT',
4 | output: null,
5 | colour: '#6600cc',
6 | tooltip: '',
7 | helpUrl: '',
8 | };
9 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | base: '/blockly-player/',
8 | });
9 |
--------------------------------------------------------------------------------
/src/utils/debounce.js:
--------------------------------------------------------------------------------
1 | export function debounce(func, timeout = 300) {
2 | let timer;
3 | return (...args) => {
4 | clearTimeout(timer);
5 | timer = setTimeout(() => {
6 | func.apply(this, args);
7 | }, timeout);
8 | };
9 | }
10 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameEndGame/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'game_end_game',
3 | message0: 'end game',
4 | previousStatement: null,
5 | nextStatement: null,
6 | colour: '#FFAABB',
7 | tooltip: '',
8 | helpUrl: '',
9 | };
10 |
--------------------------------------------------------------------------------
/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import './index.css'
4 | import App from './App'
5 |
6 | ReactDOM.render(
7 |
8 |
9 | ,
10 | document.getElementById('root')
11 | )
12 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/overWrite.js:
--------------------------------------------------------------------------------
1 | export function overWrite(Blockly) {
2 | Blockly.JavaScript['text_print'] = function (block) {
3 | const msg = Blockly.JavaScript.valueToCode(block, 'TEXT', Blockly.JavaScript.ORDER_NONE) || "''";
4 | return `engine.writeText(${msg});\n`;
5 | };
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameTarget/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: "game_target",
3 | message0: "Target %1",
4 | args0: [
5 | {
6 | type: "input_statement",
7 | name: "target",
8 | },
9 | ],
10 | previousStatement: null,
11 | nextStatement: null,
12 | colour: "#FFAABB",
13 | tooltip: "",
14 | helpUrl: "",
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameObstacle/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'game_obstacle',
3 | message0: 'Obstacle %1',
4 | args0: [
5 | {
6 | type: 'input_statement',
7 | name: 'obstacle',
8 | },
9 | ],
10 | previousStatement: null,
11 | nextStatement: null,
12 | colour: '#FFAABB',
13 | tooltip: '',
14 | helpUrl: '',
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerDeadDuck/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from "./definition";
2 | export const playerDeadDuck = (Blockly) => {
3 | Blockly.Blocks["game_dead_duck"] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 | Blockly.JavaScript["game_dead_duck"] = function (block) {
9 | return "PLAYER_DEAD_DUCK";
10 | };
11 | };
12 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameEndGame/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 |
3 | export const gameEndGame = (Blockly) => {
4 | Blockly.Blocks['game_end_game'] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript['game_end_game'] = function (block) {
10 | return `engine.endGame();\n`;
11 | };
12 | };
13 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/setPlayerIcon/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: "game_set_player_icon",
3 | message0: "set player icon %1",
4 | args0: [
5 | {
6 | type: "input_statement",
7 | name: "playerIcon",
8 | },
9 | ],
10 | previousStatement: null,
11 | nextStatement: null,
12 | colour: "#FFAABB",
13 | tooltip: "",
14 | helpUrl: "",
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/textSize/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'canvas_text_size',
3 | message0: 'Text size %1',
4 | args0: [
5 | {
6 | type: 'input_value',
7 | name: 'textSize',
8 | check: 'Number',
9 | },
10 | ],
11 | previousStatement: null,
12 | nextStatement: null,
13 | colour: '#6600cc',
14 | tooltip: '',
15 | helpUrl: '',
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameMoveTargetX/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: "game_move_target_x",
3 | message0: "move target x %1",
4 | args0: [
5 | {
6 | type: "input_value",
7 | name: "x",
8 | check: "Number",
9 | },
10 | ],
11 | previousStatement: null,
12 | nextStatement: null,
13 | colour: "#FFAABB",
14 | tooltip: "",
15 | helpUrl: "",
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameMoveTargetY/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: "game_move_target_y",
3 | message0: "move target y %1",
4 | args0: [
5 | {
6 | type: "input_value",
7 | name: "y",
8 | check: "Number",
9 | },
10 | ],
11 | previousStatement: null,
12 | nextStatement: null,
13 | colour: "#FFAABB",
14 | tooltip: "",
15 | helpUrl: "",
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameMoveObstacleX/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'game_move_obstacle_x',
3 | message0: 'move obstacle x %1',
4 | args0: [
5 | {
6 | type: 'input_value',
7 | name: 'x',
8 | check: 'Number',
9 | },
10 | ],
11 | previousStatement: null,
12 | nextStatement: null,
13 | colour: '#FFAABB',
14 | tooltip: '',
15 | helpUrl: '',
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameMoveObstacleY/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'game_move_obstacle_y',
3 | message0: 'move obstacle y %1',
4 | args0: [
5 | {
6 | type: 'input_value',
7 | name: 'y',
8 | check: 'Number',
9 | },
10 | ],
11 | previousStatement: null,
12 | nextStatement: null,
13 | colour: '#FFAABB',
14 | tooltip: '',
15 | helpUrl: '',
16 | };
17 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasSetTextColor/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'canvas_set_text_color',
3 | message0: 'text color %1',
4 | args0: [
5 | {
6 | type: 'input_value',
7 | name: 'textColor',
8 | check: 'Colour',
9 | },
10 | ],
11 | previousStatement: null,
12 | nextStatement: null,
13 | colour: '#6600cc',
14 | tooltip: '',
15 | helpUrl: '',
16 | };
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "blocky-app",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "dev": "vite",
6 | "build": "vite build",
7 | "serve": "vite preview --host"
8 | },
9 | "dependencies": {
10 | "blockly": "^6.20210701.0",
11 | "react": "^17.0.0",
12 | "react-dom": "^17.0.0"
13 | },
14 | "devDependencies": {
15 | "@vitejs/plugin-react": "^1.0.0",
16 | "vite": "^2.6.4"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/backgroundColor/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'canvas_background_color',
3 | message0: 'background color %1',
4 | args0: [
5 | {
6 | type: 'input_value',
7 | name: 'backgroundColor',
8 | check: 'Colour',
9 | },
10 | ],
11 | previousStatement: null,
12 | nextStatement: null,
13 | colour: '#6600cc',
14 | tooltip: '',
15 | helpUrl: '',
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameSetPlayerPositionX/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: "game_set_player_position_x",
3 | message0: "Set Player position X %1",
4 | args0: [
5 | {
6 | type: "input_value",
7 | name: "x",
8 | check: "Number",
9 | },
10 | ],
11 | colour: "#FFAABB",
12 | tooltip: "",
13 | helpUrl: "",
14 | previousStatement: null,
15 | nextStatement: null,
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameSetPlayerPositionY/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: "game_set_player_position_y",
3 | message0: "Set Player position Y %1",
4 | args0: [
5 | {
6 | type: "input_value",
7 | name: "y",
8 | check: "Number",
9 | },
10 | ],
11 | colour: "#FFAABB",
12 | tooltip: "",
13 | helpUrl: "",
14 | previousStatement: null,
15 | nextStatement: null,
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerDuck/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 | export const playerDuck = (Blockly) => {
3 | Blockly.Blocks['game_duck'] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 | Blockly.JavaScript['game_duck'] = function (block) {
9 | // TODO: Assemble JavaScript into code variable.
10 | var code = 'PLAYER_DUCK';
11 | return code;
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerChicken/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 | export const playerChicken = (Blockly) => {
3 | Blockly.Blocks['game_chicken'] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 | Blockly.JavaScript['game_chicken'] = function (block) {
9 | // TODO: Assemble JavaScript into code variable.
10 | var code = 'PLAYER_CHICKEN';
11 | return code;
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/src/components/ContentWrapper.jsx:
--------------------------------------------------------------------------------
1 | import { PAGE_APP, PAGE_CODE, PAGE_MIX, PAGE_SETTINGS } from '../constants';
2 |
3 | export const ContentWrapper = ({ children, currentPage }) => {
4 | const classMap = {
5 | [PAGE_APP]: 'is-app',
6 | [PAGE_CODE]: 'is-code',
7 | [PAGE_MIX]: 'is-mix',
8 | [PAGE_SETTINGS]: 'is-settings',
9 | };
10 | let className = `content-wrapper ${classMap[currentPage]}`;
11 | return {children}
;
12 | };
13 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerChicken/definition.js:
--------------------------------------------------------------------------------
1 | import src from '/images/chicken.png';
2 |
3 | export const definition = {
4 | type: 'game_chicken',
5 | message0: 'Chicken %1',
6 | args0: [
7 | {
8 | type: 'field_image',
9 | src,
10 | width: 40,
11 | height: 40,
12 | alt: 'chicken',
13 | flipRtl: false,
14 | },
15 | ],
16 | colour: '#FFAABB',
17 | tooltip: '',
18 | helpUrl: '',
19 | previousStatement: null,
20 | };
21 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerDeadChicken/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from "./definition";
2 | export const playerDeadChicken = (Blockly) => {
3 | Blockly.Blocks["game_dead_chicken"] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 | Blockly.JavaScript["game_dead_chicken"] = function (block) {
9 | // TODO: Assemble JavaScript into code variable.
10 | var code = "PLAYER_DEAD_CHICKEN";
11 | return code;
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerDuck/definition.js:
--------------------------------------------------------------------------------
1 | import duckImage from "/images/duck.svg";
2 |
3 | export const definition = {
4 | type: "game_duck",
5 | message0: "Duck %1",
6 | args0: [
7 | {
8 | type: "field_image",
9 | src: duckImage,
10 | width: 40,
11 | height: 40,
12 | alt: "duck",
13 | flipRtl: false,
14 | },
15 | ],
16 | colour: "#FFAABB",
17 | tooltip: "",
18 | helpUrl: "",
19 | previousStatement: null,
20 | };
21 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/setPlayerIcon/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from "./definition";
2 | export const setPlayerIcon = (Blockly) => {
3 | Blockly.Blocks["game_set_player_icon"] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 |
9 | Blockly.JavaScript["game_set_player_icon"] = function (block) {
10 | const avatar = Blockly.JavaScript.statementToCode(block, "playerIcon");
11 | return `engine.setAvatar(${avatar});\n`;
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerDeadChicken/definition.js:
--------------------------------------------------------------------------------
1 | import src from "/images/deadChicken.svg";
2 |
3 | export const definition = {
4 | type: "game_dead_chicken",
5 | message0: "Dead Chicken %1",
6 | args0: [
7 | {
8 | type: "field_image",
9 | src,
10 | width: 40,
11 | height: 40,
12 | alt: "dead chicken",
13 | flipRtl: false,
14 | },
15 | ],
16 | colour: "#FFAABB",
17 | tooltip: "",
18 | helpUrl: "",
19 | previousStatement: null,
20 | };
21 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerDeadDuck/definition.js:
--------------------------------------------------------------------------------
1 | import duckImage from "/images/deadDuck.svg";
2 |
3 | export const definition = {
4 | type: "game_dead_duck",
5 | message0: "Dead Duck %1",
6 | args0: [
7 | {
8 | type: "field_image",
9 | src: duckImage,
10 | width: 40,
11 | height: 40,
12 | alt: "dead duck",
13 | flipRtl: false,
14 | },
15 | ],
16 | colour: "#FFAABB",
17 | tooltip: "",
18 | helpUrl: "",
19 | previousStatement: null,
20 | };
21 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasSetTextAlign/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'canvas_set_text_align',
3 | message0: 'setTextAlign %1',
4 | args0: [
5 | {
6 | type: 'field_dropdown',
7 | name: 'align',
8 | options: [
9 | ['left', 'left'],
10 | ['right', 'right'],
11 | ['center', 'center'],
12 | ],
13 | },
14 | ],
15 | previousStatement: null,
16 | nextStatement: null,
17 | colour: '#6600cc',
18 | tooltip: '',
19 | helpUrl: '',
20 | };
21 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasSetTextAlign/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 | export const canvasSetTextAlign = (Blockly) => {
3 | Blockly.Blocks['canvas_set_text_align'] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 | Blockly.JavaScript['canvas_set_text_align'] = function (block) {
9 | // TODO: Assemble JavaScript into code variable.
10 | const align = block.getFieldValue('align');
11 | return `engine.setTextAlign('${align}');\n`;
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerX/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 |
3 | export const playerX = (Blockly) => {
4 | Blockly.Blocks['player_x'] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript['player_x'] = function (block) {
10 | // TODO: Assemble JavaScript into code variable.
11 | const code = 'engine.getPlayerX()';
12 | // TODO: Change ORDER_NONE to the correct strength.
13 | return [code, Blockly.JavaScript.ORDER_NONE];
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/playerY/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 |
3 | export const playerY = (Blockly) => {
4 | Blockly.Blocks['player_y'] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript['player_y'] = function (block) {
10 | // TODO: Assemble JavaScript into code variable.
11 | const code = 'engine.getPlayerY()';
12 | // TODO: Change ORDER_NONE to the correct strength.
13 | return [code, Blockly.JavaScript.ORDER_NONE];
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasWidth/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 |
3 | export const canvasWidth = (Blockly) => {
4 | Blockly.Blocks['canvas_width'] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript['canvas_width'] = function (block) {
10 | // TODO: Assemble JavaScript into code variable.
11 | const code = 'canvas.width';
12 | // TODO: Change ORDER_NONE to the correct strength.
13 | return [code, Blockly.JavaScript.ORDER_NONE];
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasHeight/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 |
3 | export const canvasHeight = (Blockly) => {
4 | Blockly.Blocks['canvas_height'] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript['canvas_height'] = function (block) {
10 | // TODO: Assemble JavaScript into code variable.
11 | const code = 'canvas.width';
12 | // TODO: Change ORDER_NONE to the correct strength.
13 | return [code, Blockly.JavaScript.ORDER_NONE];
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasSetCursor/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'canvas_set_cursor',
3 | message0: 'Set Text Cursor %1 X %2 Y %3',
4 | args0: [
5 | {
6 | type: 'input_dummy',
7 | },
8 | {
9 | type: 'input_value',
10 | name: 'x',
11 | check: 'Number',
12 | },
13 | {
14 | type: 'input_value',
15 | name: 'y',
16 | check: 'Number',
17 | },
18 | ],
19 | colour: '#6600cc',
20 | tooltip: '',
21 | helpUrl: '',
22 | previousStatement: null,
23 | nextStatement: null,
24 | };
25 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/textSize/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 | export const textSize = (Blockly) => {
3 | Blockly.Blocks['canvas_text_size'] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 | Blockly.JavaScript['canvas_text_size'] = function (block) {
9 | // TODO: Assemble JavaScript into code variable.
10 | const size = Blockly.JavaScript.valueToCode(block, 'textSize', Blockly.JavaScript.ORDER_NONE) || "''";
11 | var code = `engine.setTextSize(${size});\n`;
12 | return code;
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameSetPlayerPosition/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'game_set_player_position',
3 | message0: 'Set Player position %1 X %2 Y %3',
4 | args0: [
5 | {
6 | type: 'input_dummy',
7 | },
8 | {
9 | type: 'input_value',
10 | name: 'x',
11 | check: 'Number',
12 | },
13 | {
14 | type: 'input_value',
15 | name: 'y',
16 | check: 'Number',
17 | },
18 | ],
19 | colour: '#FFAABB',
20 | tooltip: '',
21 | helpUrl: '',
22 | previousStatement: null,
23 | nextStatement: null,
24 | };
25 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasSetCursor/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 | export const canvasSetCursor = (Blockly) => {
3 | Blockly.Blocks['canvas_set_cursor'] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 |
9 | Blockly.JavaScript['canvas_set_cursor'] = function (block) {
10 | const x = Blockly.JavaScript.valueToCode(block, 'x', Blockly.JavaScript.ORDER_ATOMIC) || 0;
11 | const y = Blockly.JavaScript.valueToCode(block, 'y', Blockly.JavaScript.ORDER_ATOMIC) || 0;
12 | return `engine.setCursor(${x}, ${y});\n`;
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameSetPlayerPositionX/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from "./definition";
2 | export const gameSetPlayerPositionX = (Blockly) => {
3 | Blockly.Blocks["game_set_player_position_x"] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 |
9 | Blockly.JavaScript["game_set_player_position_x"] = function (block) {
10 | const x =
11 | Blockly.JavaScript.valueToCode(
12 | block,
13 | "x",
14 | Blockly.JavaScript.ORDER_ATOMIC
15 | ) || 0;
16 |
17 | return `engine.setPlayerPosition(${x});\n`;
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasSetTextColor/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 | export const canvasSetTextColor = (Blockly) => {
3 | Blockly.Blocks['canvas_set_text_color'] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 | Blockly.JavaScript['canvas_set_text_color'] = function (block) {
9 | // TODO: Assemble JavaScript into code variable.
10 | const color = Blockly.JavaScript.valueToCode(block, 'textColor', Blockly.JavaScript.ORDER_NONE) || "''";
11 | var code = `engine.setTextColor(${color});\n`;
12 | return code;
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/backgroundColor/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 | export const backgroundColor = (Blockly) => {
3 | Blockly.Blocks['canvas_background_color'] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 | Blockly.JavaScript['canvas_background_color'] = function (block) {
9 | // TODO: Assemble JavaScript into code variable.
10 | const color = Blockly.JavaScript.valueToCode(block, 'backgroundColor', Blockly.JavaScript.ORDER_NONE) || "''";
11 | var code = `engine.drawBackground(${color});\n`;
12 | return code;
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameSetPlayerPositionY/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from "./definition";
2 | export const gameSetPlayerPositionY = (Blockly) => {
3 | Blockly.Blocks["game_set_player_position_y"] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 |
9 | Blockly.JavaScript["game_set_player_position_y"] = function (block) {
10 | const y =
11 | Blockly.JavaScript.valueToCode(
12 | block,
13 | "y",
14 | Blockly.JavaScript.ORDER_ATOMIC
15 | ) || 0;
16 |
17 | return `engine.setPlayerPosition(undefined,${y});\n`;
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameMoveObstacleX/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 |
3 | export const gameMoveObstacleX = (Blockly) => {
4 | Blockly.Blocks['game_move_obstacle_x'] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript['game_move_obstacle_x'] = function (block) {
10 | // TODO: Assemble JavaScript into code variable.
11 | const x = Blockly.JavaScript.valueToCode(block, 'x', Blockly.JavaScript.ORDER_ATOMIC);
12 | // TODO: Change ORDER_NONE to the correct strength.
13 | return `engine.moveObstacleX(${x});`;
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameTarget/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from "./definition";
2 |
3 | export const gameTarget = (Blockly) => {
4 | Blockly.Blocks["game_target"] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript["game_target"] = function (block) {
10 | // TODO: Assemble JavaScript into code variable.
11 | const target = Blockly.JavaScript.statementToCode(block, "target");
12 | // TODO: Assemble JavaScript into code variable.
13 | return `
14 | engine.setTarget(() => {
15 | ${target}
16 | })
17 | ;\n`;
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameSetPlayerPosition/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 | export const gameSetPlayerPosition = (Blockly) => {
3 | Blockly.Blocks['game_set_player_position'] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 |
9 | Blockly.JavaScript['game_set_player_position'] = function (block) {
10 | const x = Blockly.JavaScript.valueToCode(block, 'x', Blockly.JavaScript.ORDER_ATOMIC) || 0;
11 | const y = Blockly.JavaScript.valueToCode(block, 'y', Blockly.JavaScript.ORDER_ATOMIC) || 0;
12 | return `engine.setPlayerPosition(${x}, ${y});\n`;
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameObstacle/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 |
3 | export const gameObstacle = (Blockly) => {
4 | Blockly.Blocks['game_obstacle'] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript['game_obstacle'] = function (block) {
10 | // TODO: Assemble JavaScript into code variable.
11 | const obstacles = Blockly.JavaScript.statementToCode(block, 'obstacle');
12 | // TODO: Assemble JavaScript into code variable.
13 | return `
14 | engine.setObstacles(() => {
15 | ${obstacles}
16 | })
17 | ;\n`;
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameMoveTargetX/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from "./definition";
2 |
3 | export const gameMoveTargetX = (Blockly) => {
4 | Blockly.Blocks["game_move_target_x"] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript["game_move_target_x"] = function (block) {
10 | // TODO: Assemble JavaScript into code variable.
11 | const x = Blockly.JavaScript.valueToCode(
12 | block,
13 | "x",
14 | Blockly.JavaScript.ORDER_ATOMIC
15 | );
16 | // TODO: Change ORDER_NONE to the correct strength.
17 | return `engine.moveTargetX(${x});`;
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameMoveTargetY/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from "./definition";
2 |
3 | export const gameMoveTargetY = (Blockly) => {
4 | Blockly.Blocks["game_move_target_y"] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript["game_move_target_y"] = function (block) {
10 | // TODO: Assemble JavaScript into code variable.
11 | const y = Blockly.JavaScript.valueToCode(
12 | block,
13 | "y",
14 | Blockly.JavaScript.ORDER_ATOMIC
15 | );
16 | // TODO: Change ORDER_NONE to the correct strength.
17 | return `engine.moveTargetY(${y});`;
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameMoveObstacleY/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from "./definition";
2 |
3 | export const gameMoveObstacleY = (Blockly) => {
4 | Blockly.Blocks["game_move_obstacle_y"] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript["game_move_obstacle_y"] = function (block) {
10 | // TODO: Assemble JavaScript into code variable.
11 | const y = Blockly.JavaScript.valueToCode(
12 | block,
13 | "y",
14 | Blockly.JavaScript.ORDER_ATOMIC
15 | );
16 | // TODO: Change ORDER_NONE to the correct strength.
17 | return `engine.moveObstacleY(${y});`;
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/src/components/Navigator.jsx:
--------------------------------------------------------------------------------
1 | import { PAGE_APP, PAGE_CODE, PAGE_MIX, PAGE_SETTINGS } from '../constants';
2 |
3 | export const Navigator = ({ onCode, onMix, onApp, onSettings, currentPage }) => {
4 | return (
5 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasDrawRectangle/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: 'canvas_draw_rectangle',
3 | message0: 'drawRectangle %1 x %2 y %3 width %4 height %5 Colour %6',
4 | args0: [
5 | {
6 | type: 'input_dummy',
7 | },
8 | {
9 | type: 'input_value',
10 | name: 'x',
11 | check: 'Number',
12 | },
13 | {
14 | type: 'input_value',
15 | name: 'y',
16 | check: 'Number',
17 | },
18 | {
19 | type: 'input_value',
20 | name: 'width',
21 | check: 'Number',
22 | },
23 | {
24 | type: 'input_value',
25 | name: 'height',
26 | check: 'Number',
27 | },
28 | {
29 | type: 'input_value',
30 | name: 'color',
31 | check: 'Colour',
32 | },
33 | ],
34 | colour: '#6600cc',
35 | tooltip: '',
36 | helpUrl: '',
37 | previousStatement: null,
38 | nextStatement: null,
39 | };
40 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/canvasDrawRectangle/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from './definition';
2 |
3 | export const canvasDrawRectangle = (Blockly) => {
4 | Blockly.Blocks['canvas_draw_rectangle'] = {
5 | init: function () {
6 | this.jsonInit(definition);
7 | },
8 | };
9 | Blockly.JavaScript['canvas_draw_rectangle'] = function (block) {
10 | const x = Blockly.JavaScript.valueToCode(block, 'x', Blockly.JavaScript.ORDER_ATOMIC);
11 | const y = Blockly.JavaScript.valueToCode(block, 'y', Blockly.JavaScript.ORDER_ATOMIC);
12 | const width = Blockly.JavaScript.valueToCode(block, 'width', Blockly.JavaScript.ORDER_ATOMIC);
13 | const height = Blockly.JavaScript.valueToCode(block, 'height', Blockly.JavaScript.ORDER_ATOMIC);
14 | const color = Blockly.JavaScript.valueToCode(block, 'color', Blockly.JavaScript.ORDER_ATOMIC);
15 | return `engine.drawRectangle(${x || 0}, ${y || 0}, ${width || 0}, ${height || 0}, ${color})`;
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/src/components/blocky/initialize.js:
--------------------------------------------------------------------------------
1 | import { initializeCustomBlocks } from "./custom";
2 | import { toolbox } from "./toolbox";
3 | import Blockly from "blockly/core";
4 | import "blockly";
5 | import "blockly/javascript";
6 | import "blockly/blocks";
7 |
8 | import locale from "blockly/msg/en";
9 | import { debounce } from "../../utils/debounce";
10 |
11 | export function initialize(
12 | editor,
13 | setGetJsCode,
14 | setWorkspaceXml,
15 | { initialXml, ...props }
16 | ) {
17 | initializeCustomBlocks(Blockly);
18 | console.log(`initializing blockly`);
19 | Blockly.setLocale(locale);
20 |
21 | const workspace = Blockly.inject(editor, {
22 | toolbox,
23 | ...props,
24 | });
25 | const localStorageKey = "blockly_saved_workspace"; // 'blocklySavedWorkspace'
26 |
27 | const onChange = (event) => {
28 | const xml = Blockly.Xml.workspaceToDom(workspace);
29 | const text = Blockly.Xml.domToText(xml);
30 | setWorkspaceXml(text);
31 | localStorage.setItem(localStorageKey, text);
32 | setGetJsCode(Blockly.JavaScript.workspaceToCode(workspace));
33 | };
34 | const savedXML = localStorage.getItem(localStorageKey);
35 | setWorkspaceXml(savedXML);
36 | workspace.addChangeListener(debounce(onChange, 500));
37 | Blockly.Xml.domToWorkspace(
38 | Blockly.Xml.textToDom(savedXML || initialXml),
39 | workspace
40 | );
41 | setGetJsCode(Blockly.JavaScript.workspaceToCode(workspace));
42 |
43 | return workspace;
44 | }
45 |
--------------------------------------------------------------------------------
/src/favicon.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/src/components/blocky/BlocklyEditor.jsx:
--------------------------------------------------------------------------------
1 | import React, { useRef, useEffect, useContext } from 'react';
2 | import { WorkspaceContext } from '../../WorkspaceContext';
3 | import Blockly from 'blockly/core';
4 | import { initialize } from './initialize';
5 |
6 | export const BlocklyEditor = ({ currentPage, children: toolBox, ...props }) => {
7 | const editorRef = useRef();
8 | const containerRef = useRef();
9 | let workspaceRef = useRef();
10 | const { setGetJsCode, setWorkspaceXml } = useContext(WorkspaceContext);
11 | function resizeBlockly() {
12 | if (!workspaceRef.current || !containerRef.current) {
13 | return;
14 | }
15 |
16 | Blockly.svgResize(workspaceRef.current);
17 | // TODO!: Possible blockly bug, might want to conttribute, resize does not always resize height
18 | const { height, width } = containerRef.current.getBoundingClientRect();
19 | console.info(`Resizing blockly to ${height}`);
20 | if (!height) {
21 | return;
22 | }
23 | editorRef.current.querySelector('.blocklySvg').setAttribute('height', `${height}px`);
24 | editorRef.current.querySelector('.blocklySvg').setAttribute('width', `${width}px`);
25 | }
26 | useEffect(() => {
27 | if (workspaceRef.current) return;
28 | workspaceRef.current = initialize(editorRef.current, setGetJsCode, setWorkspaceXml, props);
29 |
30 | new ResizeObserver(resizeBlockly).observe(containerRef.current);
31 | });
32 |
33 | useEffect(() => {}, [currentPage]);
34 | return (
35 |
38 | );
39 | };
40 |
--------------------------------------------------------------------------------
/src/components/Settings.jsx:
--------------------------------------------------------------------------------
1 | import { WorkspaceContext } from '../WorkspaceContext';
2 | import { useContext } from 'react';
3 |
4 | export const Settings = () => {
5 | const { getWorkspaceXml } = useContext(WorkspaceContext);
6 |
7 | const showFile = async (e) => {
8 | e.preventDefault();
9 | const reader = new FileReader();
10 | reader.onload = async (e) => {
11 | const text = e.target.result;
12 | localStorage.setItem('blockly_saved_workspace', text);
13 | };
14 | reader.readAsText(e.target.files[0]);
15 | };
16 |
17 | const exportFile = () => {
18 | const blob = new Blob([getWorkspaceXml], { type: 'application/xml' });
19 | const dlink = document.createElement('a');
20 | dlink.download = 'munich_coding_club.xml';
21 | dlink.href = window.URL.createObjectURL(blob);
22 | dlink.onclick = function (e) {
23 | const that = this;
24 | setTimeout(function () {
25 | window.URL.revokeObjectURL(that.href);
26 | }, 1500);
27 | };
28 | dlink.click();
29 | dlink.remove();
30 | };
31 | return (
32 |
33 |
Settings
34 |
35 |
36 |
44 |
49 |
50 |
51 | );
52 | };
53 |
--------------------------------------------------------------------------------
/src/components/game/GameArea.jsx:
--------------------------------------------------------------------------------
1 | import { useContext, useEffect, useRef, useState } from 'react';
2 | import { PAGE_CODE } from '../../constants';
3 | import { WorkspaceContext } from '../../WorkspaceContext';
4 | import { Engine } from './Engine';
5 |
6 | export const GameArea = ({ currentPage }) => {
7 | const containerRef = useRef();
8 | const canvasRef = useRef();
9 | const engineRef = useRef();
10 | const [isGameRunning,setGameRunning] = useState(false)
11 | const { getJsCode } = useContext(WorkspaceContext);
12 |
13 | useEffect(() => {
14 | if (!engineRef.current) {
15 |
16 | return
17 | };
18 | if (isGameRunning) {
19 | engineRef.current.onGameUpdated()
20 | }
21 | engineRef.current.proccessBlocks(getJsCode);
22 | }, [getJsCode]);
23 |
24 | function resizeCanvas() {
25 | const { height, width } = containerRef.current.getBoundingClientRect();
26 | if (!width && !height) {
27 | return;
28 | }
29 | engineRef.current.resize(width, height);
30 | }
31 | useEffect(() => {
32 | if (engineRef.current) {
33 | return
34 | }
35 | engineRef.current = new Engine(canvasRef.current, () => setGameRunning(true), () => setGameRunning(false));
36 | resizeCanvas();
37 | engineRef.current.proccessBlocks(getJsCode);
38 |
39 | return () => {
40 | engineRef.current.tearDown();
41 | };
42 |
43 | // engineRef.current.drawImage(duckImage, 10, 10, 50, 50);
44 | }, [getJsCode]);
45 | const info = isGameRunning ? 'Game Running' : 'Game stopped. Press enter to play'
46 | useEffect(() => {
47 | window.addEventListener('resize', resizeCanvas);
48 | return () => window.removeEventListener('resize', resizeCanvas);
49 | }, []);
50 | useEffect(() => {
51 | if (!containerRef.current) return;
52 | resizeCanvas();
53 | }, [currentPage]);
54 | return (
55 |
56 |
{info}
57 |
58 |
62 |
63 |
64 |
65 | );
66 | };
67 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameSetup/definition.js:
--------------------------------------------------------------------------------
1 | export const definition = {
2 | type: "game_setup",
3 | colour: "#FFAABB",
4 | hat: "cap",
5 | message0:
6 | "Game setup %1 initial speed %2 Enemy generation speed %3 target generation speed %4 %5 player %6 on start %7 on update %8 onEnemyGeneration %9 on end %10 on colision %11 on up key %12 on down key %13 on forward key %14 on back key %15 on obstacle outside %16 on target generation %17 on target grabbed %18",
7 | args0: [
8 | {
9 | type: "input_dummy",
10 | },
11 | {
12 | type: "input_value",
13 | name: "initialSpeedDefault",
14 | },
15 | {
16 | type: "input_value",
17 | name: "enemyGenerationSpeed",
18 | check: "Number",
19 | },
20 | {
21 | type: "input_value",
22 | name: "targetGenerationSpeed",
23 | check: "Number",
24 | },
25 | {
26 | type: "input_dummy",
27 | },
28 | {
29 | type: "input_statement",
30 | name: "player",
31 | check: [
32 | "game_duck",
33 | "game_chicken",
34 | "game_dead_duck",
35 | "game_dead_chicken",
36 | ],
37 | },
38 | {
39 | type: "input_statement",
40 | name: "onStart",
41 | },
42 | {
43 | type: "input_statement",
44 | name: "onUpdate",
45 | },
46 | {
47 | type: "input_statement",
48 | name: "onEnemyGeneration",
49 | },
50 | {
51 | type: "input_statement",
52 | name: "onEnd",
53 | },
54 | {
55 | type: "input_statement",
56 | name: "onColision",
57 | },
58 | {
59 | type: "input_statement",
60 | name: "onUp",
61 | },
62 | {
63 | type: "input_statement",
64 | name: "onDown",
65 | },
66 | {
67 | type: "input_statement",
68 | name: "onForward",
69 | },
70 | {
71 | type: "input_statement",
72 | name: "onBackward",
73 | },
74 | {
75 | type: "input_statement",
76 | name: "onObstacleOutside",
77 | },
78 | {
79 | type: "input_statement",
80 | name: "onTargetGenerated",
81 | },
82 | {
83 | type: "input_statement",
84 | name: "onTargetGrabbed",
85 | },
86 | ],
87 | inputsInline: false,
88 | previousStatement: null,
89 | nextStatement: null,
90 | tooltip: "Configures the game settings",
91 | helpUrl: "",
92 | };
93 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/index.js:
--------------------------------------------------------------------------------
1 | import { gameSetup } from "./gameSetup";
2 | import { playerDuck } from "./playerDuck";
3 | import { playerDeadDuck } from "./playerDeadDuck";
4 | import { playerDeadChicken } from "./playerDeadChicken";
5 | import { playerChicken } from "./playerChicken";
6 | import { overWrite } from "./overWrite";
7 | import { backgroundColor } from "./backgroundColor";
8 | import { textSize } from "./textSize";
9 | import { canvasWidth } from "./canvasWidth";
10 | import { canvasHeight } from "./canvasHeight";
11 | import { canvasSetTextColor } from "./canvasSetTextColor";
12 | import { canvasSetCursor } from "./canvasSetCursor";
13 | import { canvasDrawRectangle } from "./canvasDrawRectangle";
14 | import { canvasSetTextAlign } from "./canvasSetTextAlign";
15 | import { playerX } from "./playerX";
16 | import { playerY } from "./playerY";
17 | import { gameObstacle } from "./gameObstacle";
18 | import { gameTarget } from "./gameTarget";
19 | import { gameSetPlayerPosition } from "./gameSetPlayerPosition";
20 | import { gameSetPlayerPositionX } from "./gameSetPlayerPositionX";
21 | import { gameSetPlayerPositionY } from "./gameSetPlayerPositionY";
22 | import { gameMoveObstacleX } from "./gameMoveObstacleX";
23 | import { gameMoveObstacleY } from "./gameMoveObstacleY";
24 | import { gameMoveTargetX } from "./gameMoveTargetX";
25 | import { gameMoveTargetY } from "./gameMoveTargetY";
26 | import { gameEndGame } from "./gameEndGame";
27 | import { setPlayerIcon } from "./setPlayerIcon";
28 |
29 | // TODO avoid this
30 | export function initializeCustomBlocks(Blockly) {
31 | gameSetup(Blockly);
32 | playerDuck(Blockly);
33 | playerChicken(Blockly);
34 | overWrite(Blockly);
35 | backgroundColor(Blockly);
36 | textSize(Blockly);
37 | canvasWidth(Blockly);
38 | canvasHeight(Blockly);
39 | canvasSetCursor(Blockly);
40 | canvasSetTextAlign(Blockly);
41 | canvasSetTextColor(Blockly);
42 | canvasDrawRectangle(Blockly);
43 | playerY(Blockly);
44 | playerX(Blockly);
45 | gameSetPlayerPosition(Blockly);
46 | gameSetPlayerPositionX(Blockly);
47 | gameSetPlayerPositionY(Blockly);
48 | gameObstacle(Blockly);
49 | gameTarget(Blockly);
50 | gameMoveObstacleX(Blockly);
51 | gameMoveObstacleY(Blockly);
52 | gameMoveTargetX(Blockly);
53 | gameMoveTargetY(Blockly);
54 | gameEndGame(Blockly);
55 | playerDeadDuck(Blockly);
56 | playerDeadChicken(Blockly);
57 | setPlayerIcon(Blockly);
58 | }
59 |
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { Wrapper } from './components/Wrapper';
3 | import { Navigator } from './components/Navigator';
4 | import { GameArea } from './components/game';
5 | import { Settings } from './components/Settings';
6 | import { ContentWrapper } from './components/ContentWrapper';
7 | import { BlocklyEditor } from './components/blocky';
8 | import { PAGE_APP, PAGE_CODE, PAGE_MIX, PAGE_SETTINGS } from './constants';
9 | import { WorkspaceContext } from './WorkspaceContext';
10 |
11 | function App() {
12 | const [currentPage, setCurrentPage] = useState(PAGE_MIX);
13 | const [getJsCode, setGetJsCode] = useState(() => '');
14 | const [getWorkspaceXml, setWorkspaceXml] = useState(() => '');
15 |
16 | return (
17 |
18 |
19 | setCurrentPage(PAGE_APP)}
21 | onCode={() => setCurrentPage(PAGE_CODE)}
22 | onMix={() => setCurrentPage(PAGE_MIX)}
23 | onSettings={() => setCurrentPage(PAGE_SETTINGS)}
24 | currentPage={currentPage}
25 | />
26 |
27 | {(currentPage === PAGE_MIX || currentPage === PAGE_CODE) && (
28 |
44 | #33ccffOlá
45 | `}
46 | >
47 | )}
48 | {(currentPage === PAGE_MIX || currentPage === PAGE_APP) && }
49 | {currentPage === PAGE_SETTINGS && }
50 |
51 |
52 |
53 | );
54 | }
55 |
56 | export default App;
57 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body,
2 | html {
3 | margin: 0;
4 | height: 100%;
5 | }
6 | #root {
7 | width: 100%;
8 | height: 100%;
9 | min-height: 100vh;
10 | }
11 | .wrapper {
12 | width: 100%;
13 | height: 100%;
14 | position: relative;
15 | display: flex;
16 | flex-direction: column;
17 | }
18 |
19 | .navigator {
20 | display: flex;
21 | justify-content: space-evenly;
22 | }
23 | .menu-item {
24 | flex-grow: 1;
25 | text-align: center;
26 | }
27 | .menu-item[data-is-current="true"] {
28 | font-weight: bold;
29 | }
30 | .menu-item:hover {
31 | cursor: pointer;
32 | }
33 |
34 | .content-wrapper {
35 | flex-grow: 1;
36 | display: grid;
37 | grid-template-rows: 1fr 1fr 1fr 1fr;
38 | grid-template-columns: 1fr 1fr 1fr 1fr;
39 | }
40 | .blockly-container {
41 | height: 100%;
42 | width: 100%;
43 | grid-area: blockly;
44 | position: relative;
45 | }
46 | #blocklyDiv {
47 | position: absolute;
48 | width: 100%;
49 | height: 100%;
50 | }
51 |
52 | .game-area {
53 | height: 100%;
54 | width: 100%;
55 | grid-area: game;
56 | display: grid;
57 | background-color: whitesmoke;
58 | grid-template-columns: 1fr;
59 | grid-template-rows: min-content 1fr;
60 | }
61 |
62 | .settings {
63 | height: 100%;
64 | width: 100%;
65 | grid-area: settings;
66 | background-color: whitesmoke;
67 | }
68 | .content-wrapper.is-code {
69 | grid-template-areas:
70 | "blockly blockly blockly blockly"
71 | "blockly blockly blockly blockly"
72 | "blockly blockly blockly blockly"
73 | "blockly blockly blockly blockly";
74 | }
75 | .content-wrapper.is-settings {
76 | grid-template-areas:
77 | "settings settings settings settings"
78 | "settings settings settings settings"
79 | "settings settings settings settings"
80 | "settings settings settings settings";
81 | }
82 | .content-wrapper.is-app {
83 | grid-template-areas:
84 | "game game game game"
85 | "game game game game"
86 | "game game game game"
87 | "game game game game";
88 | }
89 |
90 | .content-wrapper.is-mix {
91 | grid-template-areas:
92 | "blockly blockly game game"
93 | "blockly blockly game game"
94 | "blockly blockly game game"
95 | "blockly blockly game game";
96 | }
97 | * {
98 | box-sizing: border-box;
99 | }
100 | canvas {
101 | background-color: black;
102 | }
103 | label {
104 | min-width: 10rem;
105 | padding-right: 0.5rem;
106 | text-align: right;
107 | font-weight: bold;
108 | }
109 |
110 | .innerWrapper {
111 | width: 100%;
112 | margin: 0 auto;
113 | display: flex;
114 | flex-direction: column;
115 | max-width: 20rem;
116 | }
117 |
118 | .settings {
119 | position: relative;
120 | }
121 |
--------------------------------------------------------------------------------
/src/components/blocky/custom/gameSetup/index.js:
--------------------------------------------------------------------------------
1 | import { definition } from "./definition";
2 | export const gameSetup = (Blockly) => {
3 | Blockly.Blocks["game_setup"] = {
4 | init: function () {
5 | this.jsonInit(definition);
6 | },
7 | };
8 | Blockly.JavaScript["game_setup"] = function (block) {
9 | const initialSpeed = Blockly.JavaScript.valueToCode(
10 | block,
11 | "initialSpeedDefault",
12 | Blockly.JavaScript.ORDER_ATOMIC
13 | );
14 | const enemyGenerationSpeed = Blockly.JavaScript.valueToCode(
15 | block,
16 | "enemyGenerationSpeed",
17 | Blockly.JavaScript.ORDER_ATOMIC
18 | );
19 | const targetGenerationSpeed = Blockly.JavaScript.valueToCode(
20 | block,
21 | "targetGenerationSpeed",
22 | Blockly.JavaScript.ORDER_ATOMIC
23 | );
24 |
25 | const player = Blockly.JavaScript.statementToCode(block, "player");
26 | var onStart = Blockly.JavaScript.statementToCode(block, "onStart");
27 | var onUpdate = Blockly.JavaScript.statementToCode(block, "onUpdate");
28 | var onEnd = Blockly.JavaScript.statementToCode(block, "onEnd");
29 | const onUpKey = Blockly.JavaScript.statementToCode(block, "onUp");
30 | const onDownKey = Blockly.JavaScript.statementToCode(block, "onDown");
31 | const onForwardKey = Blockly.JavaScript.statementToCode(block, "onForward");
32 | const onBackwardKey = Blockly.JavaScript.statementToCode(
33 | block,
34 | "onBackward"
35 | );
36 | const onColision = Blockly.JavaScript.statementToCode(block, "onColision");
37 | const onEnemyGeneration = Blockly.JavaScript.statementToCode(
38 | block,
39 | "onEnemyGeneration"
40 | );
41 | const onObstacleOutside = Blockly.JavaScript.statementToCode(
42 | block,
43 | "onObstacleOutside"
44 | );
45 | const onTargetGrabbed = Blockly.JavaScript.statementToCode(
46 | block,
47 | "onTargetGrabbed"
48 | );
49 | const onTargetGenerated = Blockly.JavaScript.statementToCode(
50 | block,
51 | "onTargetGenerated"
52 | );
53 |
54 | // TODO: Assemble JavaScript into code variable.
55 | const code = `engine.setScenario(
56 | {
57 | initialSpeed: ${initialSpeed || 500},
58 | enemyGenerationSpeed: ${enemyGenerationSpeed || 500},
59 | targetGenerationSpeed: ${targetGenerationSpeed || 500},
60 | player: ${player || "null"},
61 | onStart: () => {
62 | ${onStart}
63 | },
64 | onUpdate: () => {
65 | ${onUpdate}
66 | },
67 | onEnd: () => {
68 | ${onEnd}
69 | },
70 | onEnemyGeneration: () => {
71 | ${onEnemyGeneration}
72 | },
73 | onUpKey: () => {
74 | ${onUpKey}
75 | },
76 | onDownKey: () => {
77 | ${onDownKey}
78 | },
79 | onForwardKey: () => {
80 | ${onForwardKey}
81 | },
82 | onBackwardKey: () => {
83 | ${onBackwardKey}
84 | },
85 | onColision: () => {
86 | ${onColision}
87 | },
88 | onObstacleOutside: () => {
89 | ${onObstacleOutside}
90 | },
91 | onTargetGrabbed: () => {
92 | ${onTargetGrabbed}
93 | },
94 | onTargetGenerated: () => {
95 | ${onTargetGenerated}
96 | }
97 | });\n`;
98 | return code;
99 | };
100 | };
101 |
--------------------------------------------------------------------------------
/public/images/deadDuck.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
110 |
--------------------------------------------------------------------------------
/public/images/duck.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
168 |
--------------------------------------------------------------------------------
/public/images/chicken.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
191 |
--------------------------------------------------------------------------------
/src/components/game/Engine.js:
--------------------------------------------------------------------------------
1 | import duckImage from "/images/duck.png";
2 | import chickenImage from "/images/chicken.png";
3 | import deadDuckImage from "/images/deadDuck.png";
4 | import deadChickenImage from "/images/deadChicken.png";
5 |
6 | const PLAYER_DUCK = Symbol("PLAYER_DUCK");
7 | const PLAYER_CHICKEN = Symbol("PLAYER_CHICKEN");
8 | const PLAYER_DEAD_DUCK = Symbol("PLAYER_DEAD_DUCK");
9 | const PLAYER_DEAD_CHICKEN = Symbol("PLAYER_DEAD_CHICKEN");
10 |
11 | const imageMap = {
12 | [PLAYER_DUCK]: duckImage,
13 | [PLAYER_CHICKEN]: chickenImage,
14 | [PLAYER_DEAD_DUCK]: deadDuckImage,
15 | [PLAYER_DEAD_CHICKEN]: deadChickenImage,
16 | };
17 | export class Engine {
18 | canvas;
19 | ctx;
20 | textSizeInPercentage = 5;
21 | textCursor = [0, 0];
22 | textColor = "black";
23 | textAlign = "left";
24 | customCursor = false;
25 | scenario = {};
26 | currentScenario = {};
27 | currentCode;
28 | isGameRunning = false;
29 | playerPosition = [10, 10];
30 | playerSize = 10;
31 | withinObstacleGuard = false;
32 | withinTargetGuard = false;
33 | obstacles = [];
34 | targets = [];
35 | gameHud = [];
36 | gameInterval;
37 | enemyInterval;
38 | onGameStart = () => {};
39 | onGameEnd = () => {};
40 | handleStart() {
41 | console.log(`Will start interactions`);
42 | this.proccessBlocks(this.currentCode);
43 | }
44 | startGame() {
45 | console.log(`Should start the game with `, this.currentScenario);
46 | this.scenario = { ...this.currentScenario };
47 | if (!this.scenario || this.isGameRunning || !this.scenario?.onStart) {
48 | return;
49 | }
50 | this.onGameStart();
51 | console.log(`Starting game`);
52 | this.isGameRunning = true;
53 | this.obstacles = [];
54 | this.targets = [];
55 | this.gameHud = [];
56 | try {
57 | console.log(`Calling onStart`, this.scenario.onStart);
58 | this.intepretCode(this.scenario.onStart());
59 | this.renderFrame();
60 | this.gameInterval = setInterval(() => {
61 | this.gameHud = [];
62 | this.intepretCode(this.scenario.onUpdate());
63 | // this.renderFrame();
64 | }, this.scenario.initialSpeed || 500);
65 | this.renderInterval = setInterval(() => {
66 | this.renderFrame();
67 | }, this.scenario.initialSpeed || 100);
68 | this.enemyInterval = setInterval(() => {
69 | this.intepretCode(this.scenario?.onEnemyGeneration());
70 | //this.renderFrame();
71 | }, this.scenario.enemyGenerationSpeed || 500);
72 | this.targetGenerationInterval = setInterval(() => {
73 | this.intepretCode(this.scenario?.onTargetGenerated());
74 | //this.renderFrame();
75 | }, this.scenario.targetGenerationSpeed || 500);
76 | } catch (error) {
77 | console.error(error);
78 | }
79 | }
80 | listenToKeys(ev) {
81 | if (ev.code === "Enter") {
82 | this.startGame();
83 | }
84 | const { scenario } = this;
85 | if (!this.isGameRunning) return;
86 | try {
87 | if (ev.code === "ArrowUp") {
88 | this.intepretCode(scenario.onUpKey());
89 | }
90 | if (ev.code === "ArrowDown") {
91 | this.intepretCode(scenario.onDownKey());
92 | }
93 | if (ev.code === "ArrowRight") {
94 | this.intepretCode(scenario.onForwardKey());
95 | }
96 | if (ev.code === "ArrowLeft") {
97 | this.intepretCode(scenario.onBackwardKey());
98 | }
99 | } catch (error) {
100 | console.error(error);
101 | }
102 | }
103 | resize(width, height) {
104 | if (!width && !height) {
105 | return;
106 | }
107 | const newSize = 100 * Math.floor(Math.min(height, width) / 100);
108 | if (newSize === this.size) return;
109 | this.size = newSize;
110 | console.log(`Resizing canvas to ${newSize}`);
111 | this.canvas.setAttribute("width", `${newSize}px`);
112 | this.canvas.setAttribute("height", `${newSize}px`);
113 | this.proccessBlocks(this.currentCode);
114 | }
115 | constructor(canvas, onGameStart, onGameEnd) {
116 | this.canvas = canvas;
117 | this.onGameStart = onGameStart;
118 | this.onGameEnd = onGameEnd;
119 | this.ctx = canvas.getContext("2d");
120 | this.ctx.font = "20px arial";
121 | document.addEventListener("keydown", this.listenToKeys.bind(this));
122 | }
123 |
124 | tearDown() {
125 | console.log(`Tearing game down`);
126 | this.clearGameLoop();
127 | document.removeEventListener("keydown", this.listenToKeys.bind(this));
128 | }
129 | clearGameLoop() {
130 | this.isGameRunning = false;
131 | window.clearInterval(this.renderInterval);
132 | window.clearInterval(this.gameInterval);
133 | window.clearInterval(this.targetGenerationInterval);
134 | window.clearInterval(this.enemyInterval);
135 | }
136 | drawImage(src, x, y, width = undefined, height = undefined) {
137 | const drawing = new Image();
138 | drawing.src = src; // can also be a remote URL e.g. http://
139 | drawing.onload = () => {
140 | this.ctx.drawImage(
141 | drawing,
142 | 0,
143 | 0,
144 | drawing.width,
145 | drawing.height,
146 | x,
147 | y,
148 | width,
149 | height
150 | );
151 | };
152 | }
153 |
154 | proccessBlocks(code) {
155 | this.currentCode = code;
156 | console.log(`Interpreting code \n${code}`);
157 | this.textSizeInPercentage = 5;
158 | this.textCursor = [0, 0];
159 | this.textColor = "black";
160 | this.textAlign = "left";
161 | this.customCursor = false;
162 | this.playerPosition = [10, 10];
163 | this.playerSize = 10;
164 | this.intepretCode(code);
165 | }
166 | intepretCode(code) {
167 | if (!code) return;
168 | ("use strict");
169 |
170 | const engine = this;
171 | const canvas = this.canvas;
172 | if (engine && canvas) {
173 | // Useless if so optimization does not stip it
174 | try {
175 | eval(code);
176 | } catch (error) {
177 | console.error(error);
178 | }
179 | }
180 | }
181 |
182 | drawBackground(color) {
183 | if (!color) {
184 | color = this.backgroundColor;
185 | }
186 | if (!color) {
187 | return;
188 | }
189 | const { ctx, size } = this;
190 | ctx.fillStyle = color;
191 | this.backgroundColor = color;
192 | ctx.fillRect(0, 0, size, size);
193 | }
194 |
195 | writeText(text, isHud) {
196 | // So hackish
197 | if (this.isGameRunning && !isHud) {
198 | this.gameHud.push(() => this.writeText(text, true));
199 | return;
200 | }
201 | const { ctx, canvas } = this;
202 | const textSize = (canvas.height * this.textSizeInPercentage) / 100;
203 | ctx.font = `${textSize}px Arial`;
204 | ctx.fillStyle = this.textColor;
205 | ctx.textAlign = this.textAlign;
206 | const [x, y] = this.textCursor;
207 |
208 | let xPos = x;
209 | if (!this.customCursor) {
210 | switch (this.textAlign) {
211 | case "left":
212 | xPos = 0;
213 | break;
214 | case "center":
215 | xPos = canvas.width / 2;
216 | break;
217 | case "right":
218 | xPos = canvas.width;
219 | break;
220 | }
221 | }
222 | ctx.fillText(text, xPos, y + textSize);
223 | this.textCursor[1] = y + textSize;
224 |
225 | this.customCursor = false;
226 | }
227 | setTextSize(size, isHud) {
228 | // So hackish
229 | if (this.isGameRunning && !isHud) {
230 | this.gameHud.push(() => this.setTextSize(size, true));
231 | return;
232 | }
233 | this.textSizeInPercentage = size;
234 | }
235 | setTextAlign(align, isHud) {
236 | // SO HACKISH
237 | if (this.isGameRunning && !isHud) {
238 | this.gameHud.push(() => this.setTextAlign(align, true));
239 | return;
240 | }
241 | this.textAlign = align;
242 | }
243 | setCursor(x = 0, y = 0, isHud) {
244 | // SO HACKISH
245 | if (this.isGameRunning && !isHud) {
246 | this.gameHud.push(() => this.setCursor(x, y, true));
247 | return;
248 | }
249 | this.textCursor = [x, y];
250 | }
251 |
252 | setTextColor(color, isHud) {
253 | // SO HACKISH
254 | if (this.isGameRunning && !isHud) {
255 | this.gameHud.push(() => this.setTextColor(color, true));
256 | return;
257 | }
258 | this.textColor = color;
259 | }
260 |
261 | setPlayer(player) {
262 | this.player = player;
263 | }
264 |
265 | setScenario(scenario) {
266 | console.log(`settign scenario`, scenario);
267 | this.currentScenario = { ...scenario };
268 | const { player } = scenario;
269 | console.log({ player });
270 | this.renderGame(this.currentScenario);
271 | }
272 |
273 | renderGame(scenarioToRender) {
274 | try {
275 | const { player } = scenarioToRender;
276 | console.log(`rendering the game`, scenarioToRender);
277 | if (!player) {
278 | console.log(`No game without a player`);
279 | return;
280 | }
281 | this.renderFrame(scenarioToRender);
282 | } catch (error) {
283 | console.error(error);
284 | }
285 | }
286 | getPlayerX() {
287 | return this.playerPosition[0];
288 | }
289 | getPlayerY() {
290 | return this.playerPosition[1];
291 | }
292 | setPlayerPosition(x, y) {
293 | if (typeof x === "undefined") {
294 | x = this.getPlayerX();
295 | }
296 | if (typeof y === "undefined") {
297 | y = this.getPlayerY();
298 | }
299 | this.playerPosition = [x, y];
300 | console.log(`Setting player to ${(x, y)}`);
301 | this.renderFrame();
302 | }
303 | renderPlayer(scenarioToRender) {
304 | const { player } = scenarioToRender || this.scenario;
305 |
306 | const { canvas, ctx } = this;
307 |
308 | const size = (canvas.height * this.playerSize) / 100;
309 | const [percentX, percentY] = this.playerPosition;
310 | // position is always in porcentages
311 | const x = Math.min(
312 | canvas.width,
313 | Math.max(0, (canvas.width * percentX) / 100 - size / 2)
314 | );
315 | const y = Math.min(
316 | canvas.height,
317 | Math.max(0, (canvas.height * percentY) / 100 - size / 2)
318 | );
319 | this.drawImage(imageMap[player], x, y, size, size);
320 | }
321 | setAvatar(newAvatar) {
322 | this.scenario.player = newAvatar;
323 | }
324 |
325 | renderFrame(scenarioToRender, isRerender) {
326 | const { ctx, canvas } = this;
327 | this.clearFrame();
328 | this.drawBackground();
329 |
330 | this.renderPlayer(scenarioToRender);
331 | this.obstacles.forEach(({ x, y, recWidth, recHeight, color }) => {
332 | this.drawRectangle(
333 | x,
334 | y,
335 | recWidth,
336 | recHeight,
337 | color,
338 | true,
339 | false,
340 | isRerender
341 | );
342 | });
343 | this.targets = this.targets.filter(
344 | ({ x, y, recWidth, recHeight, color }) => {
345 | const collided = this.drawRectangle(
346 | x,
347 | y,
348 | recWidth,
349 | recHeight,
350 | color,
351 | false,
352 | true,
353 | isRerender
354 | );
355 | return !collided;
356 | }
357 | );
358 | this.gameHud.forEach((fn, index) => {
359 | fn();
360 | });
361 | }
362 | clearFrame() {
363 | const { ctx, canvas } = this;
364 |
365 | ctx.clearRect(0, 0, canvas.width, canvas.height);
366 | ctx.beginPath();
367 | ctx.moveTo(0, 0);
368 | ctx.lineTo(canvas.width, canvas.height);
369 | ctx.stroke();
370 | }
371 | drawRectangle(
372 | x,
373 | y,
374 | recWidth,
375 | recHeight,
376 | color,
377 | forceObstacle,
378 | forceTarget,
379 | isRerender
380 | ) {
381 | const { ctx, canvas } = this;
382 | const { height, width } = canvas;
383 | const isObstacle = forceObstacle || this.withinObstacleGuard;
384 | const isTarget = forceTarget || this.withinObstacleGuard;
385 | ctx.fillStyle = color;
386 | if (this.withinObstacleGuard) {
387 | this.obstacles.push({ x, y, recWidth, recHeight, color });
388 | }
389 | if (this.withinTargetGuard) {
390 | this.targets.push({ x, y, recWidth, recHeight, color });
391 | }
392 | const absoluteX = (x * width) / 100;
393 | const absoluteY = (y * height) / 100;
394 | const absoluteWidth = (recWidth * width) / 100;
395 | const absoluteHeight = (recHeight * height) / 100;
396 | ctx.fillRect(absoluteX, absoluteY, absoluteWidth, absoluteHeight);
397 | let collided = false;
398 | if (!isRerender) {
399 | collided = this.checkColision(
400 | absoluteX,
401 | absoluteY,
402 | absoluteWidth,
403 | absoluteHeight
404 | );
405 | }
406 |
407 | if (collided) {
408 | if (isObstacle) {
409 | this.intepretCode(this.scenario?.onColision());
410 | } else if (isTarget) {
411 | this.intepretCode(this.scenario?.onTargetGrabbed());
412 | this.renderFrame(this.scenario, true);
413 | }
414 | }
415 | return collided;
416 | }
417 |
418 | checkColision(obstacleX, obstacleY, obstacleWidth, obstacleHeight) {
419 | if (!this.isGameRunning) {
420 | return false;
421 | }
422 | const { canvas } = this;
423 | const size = (canvas.height * this.playerSize) / 100;
424 | const [percentX, percentY] = this.playerPosition;
425 | // position is always in porcentages
426 | const x = Math.min(
427 | canvas.width,
428 | Math.max(0, (canvas.width * percentX) / 100 - size / 2)
429 | );
430 | const y = Math.min(
431 | canvas.height,
432 | Math.max(0, (canvas.height * percentY) / 100 - size / 2)
433 | );
434 |
435 | if (
436 | x < obstacleX + obstacleWidth &&
437 | x + size > obstacleX &&
438 | y < obstacleY + obstacleHeight &&
439 | size + y > obstacleY
440 | ) {
441 | return true;
442 | }
443 | return false;
444 | }
445 | setObstacles(obstacleRender) {
446 | if (!obstacleRender) return;
447 | this.withinObstacleGuard = true;
448 | obstacleRender();
449 | this.withinObstacleGuard = false;
450 | }
451 | setTarget(targetRenderer) {
452 | if (!targetRenderer) return;
453 | this.withinTargetGuard = true;
454 | targetRenderer();
455 | this.withinTargetGuard = false;
456 | }
457 | moveObstacleX(deltaX) {
458 | const { width } = this.canvas;
459 |
460 | const newObstacles = [];
461 | this.obstacles.forEach(({ x, recWidth, ...other }, index) => {
462 | const obstacle = { x: x + deltaX, recWidth, ...other };
463 | const absoluteX = (x * width) / 100;
464 | const absoluteWidth = (recWidth * width) / 100;
465 | if (absoluteX + absoluteWidth > 0) {
466 | newObstacles.push(obstacle);
467 | } else {
468 | this.scenario?.onObstacleOutside();
469 | console.log(`removing obstacle`);
470 | }
471 | });
472 | this.obstacles = newObstacles;
473 | }
474 |
475 | moveObstacleY(deltaY) {
476 | const { height } = this.canvas;
477 |
478 | const newObstacles = [];
479 | this.obstacles.forEach(({ y, recHeight, ...other }, index) => {
480 | const obstacle = { y: y + deltaY, recHeight, ...other };
481 | const absoluteY = (y * height) / 100;
482 | const absoluteHeight = (recHeight * height) / 100;
483 | if (absoluteY + absoluteHeight > 0) {
484 | newObstacles.push(obstacle);
485 | } else {
486 | console.log(`removing obstacle`);
487 | }
488 | });
489 | this.obstacles = newObstacles;
490 | }
491 | moveTargetX(deltaX) {
492 | const { width } = this.canvas;
493 |
494 | const newTargets = [];
495 | this.targets.forEach((originalTarget, index) => {
496 | const { x, recWidth, ...other } = originalTarget;
497 | const target = { x: x + deltaX, recWidth, ...other };
498 | const absoluteX = (x * width) / 100;
499 | const absoluteWidth = (recWidth * width) / 100;
500 | console.log({ absoluteX, absoluteWidth, deltaX, x, recWidth });
501 | if (absoluteX + absoluteWidth > 0) {
502 | newTargets.push(target);
503 | } else {
504 | console.log(`removing target, ${absoluteX + absoluteWidth}`, {
505 | absoluteX,
506 | absoluteWidth,
507 | deltaX,
508 | x,
509 | recWidth,
510 | originalTarget,
511 | });
512 | }
513 | });
514 | this.targets = newTargets;
515 | }
516 | moveTargetY(deltaY) {
517 | const { height } = this.canvas;
518 | console.log(`Move target y ${deltaY}`);
519 | const newTargets = [];
520 | this.targets.forEach(({ y, recHeight, ...other }, index) => {
521 | const target = { y: y + deltaY, recHeight, ...other };
522 | const absoluteY = (y * height) / 100;
523 | const absoluteHeight = (recHeight * height) / 100;
524 | if (absoluteY + absoluteHeight > 0) {
525 | newTargets.push(target);
526 | } else {
527 | console.log(`removing target`);
528 | }
529 | });
530 | this.targets = newTargets;
531 | }
532 | endGame() {
533 | this.clearGameLoop();
534 | window.setTimeout(() => {
535 | this.intepretCode(this.scenario.onEnd());
536 | this.renderFrame(this.scenario, true);
537 | }, 100);
538 |
539 | this.onGameEnd();
540 | }
541 |
542 | onGameUpdated() {
543 | if (this.isGameRunning) {
544 | this.clearGameLoop();
545 | this.onGameEnd();
546 | }
547 | }
548 | }
549 |
--------------------------------------------------------------------------------
/public/images/deadChicken.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
206 |
--------------------------------------------------------------------------------
/src/components/blocky/toolbox.js:
--------------------------------------------------------------------------------
1 | export const toolbox = {
2 | kind: "categoryToolbox",
3 | contents: [
4 | {
5 | kind: "category",
6 | name: "Loops",
7 | colour: "#5ba55b",
8 | contents: [
9 | {
10 | kind: "block",
11 | blockxml: `
12 |
13 |
14 | 10
15 |
16 |
17 | `,
18 | },
19 | {
20 | kind: "block",
21 | blockxml: `
22 | WHILE
23 | `,
24 | },
25 | {
26 | kind: "block",
27 | blockxml: `
28 | i
29 |
30 |
31 | 1
32 |
33 |
34 |
35 |
36 | 10
37 |
38 |
39 |
40 |
41 | 1
42 |
43 |
44 | `,
45 | },
46 | {
47 | kind: "block",
48 | blockxml: `
49 | j
50 | `,
51 | },
52 | {
53 | kind: "block",
54 | blockxml: `
55 |
56 | BREAK
57 | `,
58 | },
59 | ],
60 | },
61 | {
62 | kind: "category",
63 | name: "logic",
64 | colour: "210",
65 | contents: [
66 | {
67 | kind: "block",
68 | type: "controls_if",
69 | },
70 | {
71 | kind: "block",
72 | type: "controls_whileUntil",
73 | },
74 | {
75 | kind: "block",
76 | blockxml: `
77 | EQ
78 | `,
79 | },
80 | {
81 | kind: "block",
82 | blockxml: `
83 | AND
84 | `,
85 | },
86 | {
87 | kind: "block",
88 | blockxml: `
89 | TRUE
90 | `,
91 | },
92 | { kind: "block", type: "logic_negate" },
93 | { kind: "block", type: "logic_null" },
94 | { kind: "block", type: "logic_ternary" },
95 | ],
96 | },
97 | {
98 | kind: "category",
99 | name: "Math",
100 | colour: "#5b67a5",
101 | contents: [
102 | {
103 | kind: "block",
104 | blockxml: `
105 | 0
106 | `,
107 | },
108 | {
109 | kind: "block",
110 | blockxml: `
111 | ADD
112 |
113 |
114 | 1
115 |
116 |
117 |
118 |
119 | 1
120 |
121 |
122 | `,
123 | },
124 | {
125 | kind: "block",
126 | blockxml: `
127 | ROOT
128 |
129 |
130 | 9
131 |
132 |
133 | `,
134 | },
135 | {
136 | kind: "block",
137 | blockxml: `
138 | SIN
139 |
140 |
141 | 45
142 |
143 |
144 | `,
145 | },
146 | {
147 | kind: "block",
148 | blockxml: `
149 | PI
150 | `,
151 | },
152 | {
153 | kind: "block",
154 | blockxml: `
155 |
156 | EVEN
157 |
158 |
159 | 0
160 |
161 |
162 | `,
163 | },
164 | {
165 | kind: "block",
166 | blockxml: `
167 | ROUND
168 |
169 |
170 | 3.1
171 |
172 |
173 | `,
174 | },
175 | {
176 | kind: "block",
177 | blockxml: `
178 |
179 | SUM
180 | `,
181 | },
182 | {
183 | kind: "block",
184 | blockxml: `
185 |
186 |
187 | 64
188 |
189 |
190 |
191 |
192 | 10
193 |
194 |
195 | `,
196 | },
197 | {
198 | kind: "block",
199 | blockxml: `
200 |
201 |
202 | 50
203 |
204 |
205 |
206 |
207 | 1
208 |
209 |
210 |
211 |
212 | 100
213 |
214 |
215 | `,
216 | },
217 | {
218 | kind: "block",
219 | blockxml: `
220 |
221 |
222 | 1
223 |
224 |
225 |
226 |
227 | 100
228 |
229 |
230 | `,
231 | },
232 | { kind: "block", type: "math_random_float" },
233 | ],
234 | },
235 | {
236 | kind: "category",
237 | name: "text",
238 | colour: "#5ba58c",
239 | contents: [
240 | {
241 | kind: "block",
242 | blockxml: `
243 |
244 | `,
245 | },
246 | {
247 | kind: "block",
248 | blockxml: `
249 |
250 |
251 | `,
252 | },
253 | {
254 | kind: "block",
255 | blockxml: `
256 | item
257 |
258 |
259 |
260 |
261 |
262 | `,
263 | },
264 | {
265 | kind: "block",
266 | blockxml: `
267 |
268 |
269 |
270 | abc
271 |
272 |
273 | `,
274 | },
275 | {
276 | kind: "block",
277 | blockxml: `
278 |
279 |
280 |
281 |
282 |
283 |
284 | `,
285 | },
286 | {
287 | kind: "block",
288 | blockxml: `
289 | FIRST
290 |
291 |
292 | text
293 |
294 |
295 |
296 |
297 | abc
298 |
299 |
300 | `,
301 | },
302 | {
303 | kind: "block",
304 | blockxml: `
305 |
306 | FROM_START
307 |
308 |
309 | text
310 |
311 |
312 | `,
313 | },
314 | {
315 | kind: "block",
316 | blockxml: `
317 |
318 | FROM_START
319 | FROM_START
320 |
321 |
322 | text
323 |
324 |
325 | `,
326 | },
327 | {
328 | kind: "block",
329 | blockxml: `
330 | UPPERCASE
331 |
332 |
333 | abc
334 |
335 |
336 | `,
337 | },
338 | {
339 | kind: "block",
340 | blockxml: `
341 | BOTH
342 |
343 |
344 | abc
345 |
346 |
347 | `,
348 | },
349 | {
350 | kind: "block",
351 | blockxml: `
352 |
353 |
354 | abc
355 |
356 |
357 | `,
358 | },
359 | /* {
360 | kind: 'block',
361 | blockxml: `
362 |
363 | TEXT
364 |
365 |
366 | abc
367 |
368 |
369 | `,
370 | }, */
371 | ],
372 | },
373 | {
374 | kind: "category",
375 | name: "Lists",
376 | colour: "#745ba5",
377 | contents: [
378 | {
379 | kind: "block",
380 | blockxml: `
381 |
382 | `,
383 | },
384 | {
385 | kind: "block",
386 | blockxml: `
387 |
388 | `,
389 | },
390 | {
391 | kind: "block",
392 | blockxml: `
393 |
394 |
395 | 5
396 |
397 |
398 | `,
399 | },
400 | { kind: "block", type: "lists_length" },
401 | {
402 | kind: "block",
403 | blockxml: `
404 | FIRST
405 |
406 |
407 | list
408 |
409 |
410 | `,
411 | },
412 | {
413 | kind: "block",
414 | blockxml: `
415 |
416 | GET
417 | FROM_START
418 |
419 |
420 | list
421 |
422 |
423 | `,
424 | },
425 | {
426 | kind: "block",
427 | blockxml: `
428 |
429 | SET
430 | FROM_START
431 |
432 |
433 | list
434 |
435 |
436 | `,
437 | },
438 | {
439 | kind: "block",
440 | blockxml: `
441 |
442 | FROM_START
443 | FROM_START
444 |
445 |
446 | list
447 |
448 |
449 | `,
450 | },
451 | {
452 | kind: "block",
453 | blockxml: `
454 |
455 | SPLIT
456 |
457 |
458 | ,
459 |
460 |
461 | `,
462 | },
463 | {
464 | kind: "block",
465 | blockxml: `
466 | NUMERIC
467 | 1
468 | `,
469 | },
470 | ],
471 | },
472 | {
473 | kind: "category",
474 | name: "Colour",
475 | colour: "#a5745b",
476 | contents: [
477 | {
478 | kind: "block",
479 | blockxml: `
480 | #ff0000
481 | `,
482 | },
483 | { kind: "block", type: "colour_random" },
484 | {
485 | kind: "block",
486 | blockxml: `
487 |
488 |
489 | 100
490 |
491 |
492 |
493 |
494 | 50
495 |
496 |
497 |
498 |
499 | 0
500 |
501 |
502 | `,
503 | },
504 | {
505 | kind: "block",
506 | blockxml: `
507 |
508 |
509 | #ff0000
510 |
511 |
512 |
513 |
514 | #3333ff
515 |
516 |
517 |
518 |
519 | 0.5
520 |
521 |
522 | `,
523 | },
524 | ],
525 | },
526 | { kind: "sep" },
527 | {
528 | kind: "category",
529 | name: "Variables",
530 | colour: "#a55b80",
531 | custom: "VARIABLE",
532 | },
533 | {
534 | kind: "category",
535 | name: "Procedures",
536 | colour: "#995ba5",
537 | custom: "PROCEDURE",
538 | },
539 | { kind: "sep" },
540 | {
541 | kind: "category",
542 | name: "canvas",
543 | colour: "#6600cc",
544 | contents: [
545 | {
546 | kind: "block",
547 | blockxml: `
548 |
549 |
550 | #33ccff
551 |
552 |
553 | `,
554 | },
555 | {
556 | kind: "block",
557 | blockxml: `
558 |
559 |
560 | #000000
561 |
562 |
563 | `,
564 | },
565 | { kind: "block", type: "canvas_set_text_align" },
566 | {
567 | kind: "block",
568 | blockxml: `
569 |
570 |
571 | 3
572 |
573 |
574 |
575 | `,
576 | },
577 | {
578 | kind: "block",
579 | blockxml: `
580 |
581 |
582 | #00FF00
583 |
584 |
585 |
586 |
587 |
588 | 0
589 |
590 |
591 |
592 |
593 | 0
594 |
595 |
596 |
597 |
598 | 5
599 |
600 |
601 |
602 |
603 | 35
604 |
605 |
606 | `,
607 | },
608 | { kind: "block", type: "canvas_width" },
609 | { kind: "block", type: "canvas_height" },
610 | {
611 | kind: "block",
612 | blockxml: `
613 |
614 |
615 | 0
616 |
617 |
618 |
619 |
620 |
621 | 0
622 |
623 |
624 |
625 | `,
626 | },
627 | ],
628 | },
629 | {
630 | kind: "category",
631 | name: "game",
632 | colour: "#FFAABB",
633 | contents: [
634 | {
635 | kind: "block",
636 |
637 | blockxml: `
638 |
639 |
640 | 500
641 |
642 |
643 |
644 |
645 | 900
646 |
647 |
648 |
649 |
650 |
651 | 2000
652 |
653 |
654 |
655 | `,
656 | },
657 | { kind: "block", type: "game_duck" },
658 | { kind: "block", type: "game_dead_duck" },
659 | { kind: "block", type: "game_chicken" },
660 | { kind: "block", type: "game_dead_chicken" },
661 |
662 | { kind: "block", type: "player_x" },
663 | { kind: "block", type: "player_y" },
664 | { kind: "block", type: "game_set_player_position" },
665 | { kind: "block", type: "game_set_player_position_x" },
666 | { kind: "block", type: "game_set_player_position_y" },
667 | { kind: "block", type: "game_set_player_icon" },
668 | { kind: "block", type: "game_obstacle" },
669 | { kind: "block", type: "game_target" },
670 | { kind: "block", type: "game_move_obstacle_x" },
671 | { kind: "block", type: "game_move_obstacle_y" },
672 | { kind: "block", type: "game_move_target_x" },
673 | { kind: "block", type: "game_move_target_y" },
674 | { kind: "block", type: "game_end_game" },
675 | ],
676 | },
677 | ],
678 | };
679 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.15.8":
6 | version "7.15.8"
7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503"
8 | integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==
9 | dependencies:
10 | "@babel/highlight" "^7.14.5"
11 |
12 | "@babel/compat-data@^7.15.0":
13 | version "7.15.0"
14 | resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176"
15 | integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==
16 |
17 | "@babel/core@^7.15.5":
18 | version "7.15.8"
19 | resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10"
20 | integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==
21 | dependencies:
22 | "@babel/code-frame" "^7.15.8"
23 | "@babel/generator" "^7.15.8"
24 | "@babel/helper-compilation-targets" "^7.15.4"
25 | "@babel/helper-module-transforms" "^7.15.8"
26 | "@babel/helpers" "^7.15.4"
27 | "@babel/parser" "^7.15.8"
28 | "@babel/template" "^7.15.4"
29 | "@babel/traverse" "^7.15.4"
30 | "@babel/types" "^7.15.6"
31 | convert-source-map "^1.7.0"
32 | debug "^4.1.0"
33 | gensync "^1.0.0-beta.2"
34 | json5 "^2.1.2"
35 | semver "^6.3.0"
36 | source-map "^0.5.0"
37 |
38 | "@babel/generator@^7.15.4", "@babel/generator@^7.15.8":
39 | version "7.15.8"
40 | resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1"
41 | integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==
42 | dependencies:
43 | "@babel/types" "^7.15.6"
44 | jsesc "^2.5.1"
45 | source-map "^0.5.0"
46 |
47 | "@babel/helper-annotate-as-pure@^7.14.5":
48 | version "7.15.4"
49 | resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz#3d0e43b00c5e49fdb6c57e421601a7a658d5f835"
50 | integrity sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA==
51 | dependencies:
52 | "@babel/types" "^7.15.4"
53 |
54 | "@babel/helper-compilation-targets@^7.15.4":
55 | version "7.15.4"
56 | resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9"
57 | integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==
58 | dependencies:
59 | "@babel/compat-data" "^7.15.0"
60 | "@babel/helper-validator-option" "^7.14.5"
61 | browserslist "^4.16.6"
62 | semver "^6.3.0"
63 |
64 | "@babel/helper-function-name@^7.15.4":
65 | version "7.15.4"
66 | resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc"
67 | integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==
68 | dependencies:
69 | "@babel/helper-get-function-arity" "^7.15.4"
70 | "@babel/template" "^7.15.4"
71 | "@babel/types" "^7.15.4"
72 |
73 | "@babel/helper-get-function-arity@^7.15.4":
74 | version "7.15.4"
75 | resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b"
76 | integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==
77 | dependencies:
78 | "@babel/types" "^7.15.4"
79 |
80 | "@babel/helper-hoist-variables@^7.15.4":
81 | version "7.15.4"
82 | resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df"
83 | integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==
84 | dependencies:
85 | "@babel/types" "^7.15.4"
86 |
87 | "@babel/helper-member-expression-to-functions@^7.15.4":
88 | version "7.15.4"
89 | resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz#bfd34dc9bba9824a4658b0317ec2fd571a51e6ef"
90 | integrity sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==
91 | dependencies:
92 | "@babel/types" "^7.15.4"
93 |
94 | "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.15.4":
95 | version "7.15.4"
96 | resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f"
97 | integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==
98 | dependencies:
99 | "@babel/types" "^7.15.4"
100 |
101 | "@babel/helper-module-transforms@^7.15.8":
102 | version "7.15.8"
103 | resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz#d8c0e75a87a52e374a8f25f855174786a09498b2"
104 | integrity sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==
105 | dependencies:
106 | "@babel/helper-module-imports" "^7.15.4"
107 | "@babel/helper-replace-supers" "^7.15.4"
108 | "@babel/helper-simple-access" "^7.15.4"
109 | "@babel/helper-split-export-declaration" "^7.15.4"
110 | "@babel/helper-validator-identifier" "^7.15.7"
111 | "@babel/template" "^7.15.4"
112 | "@babel/traverse" "^7.15.4"
113 | "@babel/types" "^7.15.6"
114 |
115 | "@babel/helper-optimise-call-expression@^7.15.4":
116 | version "7.15.4"
117 | resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz#f310a5121a3b9cc52d9ab19122bd729822dee171"
118 | integrity sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==
119 | dependencies:
120 | "@babel/types" "^7.15.4"
121 |
122 | "@babel/helper-plugin-utils@^7.14.5":
123 | version "7.14.5"
124 | resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9"
125 | integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==
126 |
127 | "@babel/helper-replace-supers@^7.15.4":
128 | version "7.15.4"
129 | resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz#52a8ab26ba918c7f6dee28628b07071ac7b7347a"
130 | integrity sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==
131 | dependencies:
132 | "@babel/helper-member-expression-to-functions" "^7.15.4"
133 | "@babel/helper-optimise-call-expression" "^7.15.4"
134 | "@babel/traverse" "^7.15.4"
135 | "@babel/types" "^7.15.4"
136 |
137 | "@babel/helper-simple-access@^7.15.4":
138 | version "7.15.4"
139 | resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b"
140 | integrity sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==
141 | dependencies:
142 | "@babel/types" "^7.15.4"
143 |
144 | "@babel/helper-split-export-declaration@^7.15.4":
145 | version "7.15.4"
146 | resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257"
147 | integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==
148 | dependencies:
149 | "@babel/types" "^7.15.4"
150 |
151 | "@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7":
152 | version "7.15.7"
153 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
154 | integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
155 |
156 | "@babel/helper-validator-option@^7.14.5":
157 | version "7.14.5"
158 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3"
159 | integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==
160 |
161 | "@babel/helpers@^7.15.4":
162 | version "7.15.4"
163 | resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43"
164 | integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==
165 | dependencies:
166 | "@babel/template" "^7.15.4"
167 | "@babel/traverse" "^7.15.4"
168 | "@babel/types" "^7.15.4"
169 |
170 | "@babel/highlight@^7.14.5":
171 | version "7.14.5"
172 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
173 | integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
174 | dependencies:
175 | "@babel/helper-validator-identifier" "^7.14.5"
176 | chalk "^2.0.0"
177 | js-tokens "^4.0.0"
178 |
179 | "@babel/parser@^7.15.4", "@babel/parser@^7.15.8":
180 | version "7.15.8"
181 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016"
182 | integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==
183 |
184 | "@babel/plugin-syntax-jsx@^7.14.5":
185 | version "7.14.5"
186 | resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz#000e2e25d8673cce49300517a3eda44c263e4201"
187 | integrity sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==
188 | dependencies:
189 | "@babel/helper-plugin-utils" "^7.14.5"
190 |
191 | "@babel/plugin-transform-react-jsx-development@^7.14.5":
192 | version "7.14.5"
193 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.14.5.tgz#1a6c73e2f7ed2c42eebc3d2ad60b0c7494fcb9af"
194 | integrity sha512-rdwG/9jC6QybWxVe2UVOa7q6cnTpw8JRRHOxntG/h6g/guAOe6AhtQHJuJh5FwmnXIT1bdm5vC2/5huV8ZOorQ==
195 | dependencies:
196 | "@babel/plugin-transform-react-jsx" "^7.14.5"
197 |
198 | "@babel/plugin-transform-react-jsx-self@^7.14.9":
199 | version "7.14.9"
200 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.14.9.tgz#33041e665453391eb6ee54a2ecf3ba1d46bd30f4"
201 | integrity sha512-Fqqu0f8zv9W+RyOnx29BX/RlEsBRANbOf5xs5oxb2aHP4FKbLXxIaVPUiCti56LAR1IixMH4EyaixhUsKqoBHw==
202 | dependencies:
203 | "@babel/helper-plugin-utils" "^7.14.5"
204 |
205 | "@babel/plugin-transform-react-jsx-source@^7.14.5":
206 | version "7.14.5"
207 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.14.5.tgz#79f728e60e6dbd31a2b860b0bf6c9765918acf1d"
208 | integrity sha512-1TpSDnD9XR/rQ2tzunBVPThF5poaYT9GqP+of8fAtguYuI/dm2RkrMBDemsxtY0XBzvW7nXjYM0hRyKX9QYj7Q==
209 | dependencies:
210 | "@babel/helper-plugin-utils" "^7.14.5"
211 |
212 | "@babel/plugin-transform-react-jsx@^7.14.5", "@babel/plugin-transform-react-jsx@^7.14.9":
213 | version "7.14.9"
214 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz#3314b2163033abac5200a869c4de242cd50a914c"
215 | integrity sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==
216 | dependencies:
217 | "@babel/helper-annotate-as-pure" "^7.14.5"
218 | "@babel/helper-module-imports" "^7.14.5"
219 | "@babel/helper-plugin-utils" "^7.14.5"
220 | "@babel/plugin-syntax-jsx" "^7.14.5"
221 | "@babel/types" "^7.14.9"
222 |
223 | "@babel/template@^7.15.4":
224 | version "7.15.4"
225 | resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194"
226 | integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==
227 | dependencies:
228 | "@babel/code-frame" "^7.14.5"
229 | "@babel/parser" "^7.15.4"
230 | "@babel/types" "^7.15.4"
231 |
232 | "@babel/traverse@^7.15.4":
233 | version "7.15.4"
234 | resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d"
235 | integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==
236 | dependencies:
237 | "@babel/code-frame" "^7.14.5"
238 | "@babel/generator" "^7.15.4"
239 | "@babel/helper-function-name" "^7.15.4"
240 | "@babel/helper-hoist-variables" "^7.15.4"
241 | "@babel/helper-split-export-declaration" "^7.15.4"
242 | "@babel/parser" "^7.15.4"
243 | "@babel/types" "^7.15.4"
244 | debug "^4.1.0"
245 | globals "^11.1.0"
246 |
247 | "@babel/types@^7.14.9", "@babel/types@^7.15.4", "@babel/types@^7.15.6":
248 | version "7.15.6"
249 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f"
250 | integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==
251 | dependencies:
252 | "@babel/helper-validator-identifier" "^7.14.9"
253 | to-fast-properties "^2.0.0"
254 |
255 | "@rollup/pluginutils@^4.1.1":
256 | version "4.1.1"
257 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.1.tgz#1d4da86dd4eded15656a57d933fda2b9a08d47ec"
258 | integrity sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==
259 | dependencies:
260 | estree-walker "^2.0.1"
261 | picomatch "^2.2.2"
262 |
263 | "@vitejs/plugin-react@^1.0.0":
264 | version "1.0.2"
265 | resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-1.0.2.tgz#08147baff5bcc0c66740209823169103d73437b3"
266 | integrity sha512-nhB4LkAzhOy2T+8fsYuK+4DQWTueMvzfC0+MMMaX9qVvKqGQMOgz1nF3qTMl9ht9ZzhDnR++4XZmHWI/MytgeA==
267 | dependencies:
268 | "@babel/core" "^7.15.5"
269 | "@babel/plugin-transform-react-jsx" "^7.14.9"
270 | "@babel/plugin-transform-react-jsx-development" "^7.14.5"
271 | "@babel/plugin-transform-react-jsx-self" "^7.14.9"
272 | "@babel/plugin-transform-react-jsx-source" "^7.14.5"
273 | "@rollup/pluginutils" "^4.1.1"
274 | react-refresh "^0.10.0"
275 | resolve "^1.20.0"
276 |
277 | abab@^2.0.0:
278 | version "2.0.5"
279 | resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
280 | integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
281 |
282 | acorn-globals@^4.3.2:
283 | version "4.3.4"
284 | resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7"
285 | integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==
286 | dependencies:
287 | acorn "^6.0.1"
288 | acorn-walk "^6.0.1"
289 |
290 | acorn-walk@^6.0.1:
291 | version "6.2.0"
292 | resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
293 | integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
294 |
295 | acorn@^6.0.1:
296 | version "6.4.2"
297 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
298 | integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
299 |
300 | acorn@^7.1.0:
301 | version "7.4.1"
302 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
303 | integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
304 |
305 | ajv@^6.12.3:
306 | version "6.12.6"
307 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
308 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
309 | dependencies:
310 | fast-deep-equal "^3.1.1"
311 | fast-json-stable-stringify "^2.0.0"
312 | json-schema-traverse "^0.4.1"
313 | uri-js "^4.2.2"
314 |
315 | ansi-styles@^3.2.1:
316 | version "3.2.1"
317 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
318 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
319 | dependencies:
320 | color-convert "^1.9.0"
321 |
322 | array-equal@^1.0.0:
323 | version "1.0.0"
324 | resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
325 | integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
326 |
327 | asn1@~0.2.3:
328 | version "0.2.4"
329 | resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
330 | integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
331 | dependencies:
332 | safer-buffer "~2.1.0"
333 |
334 | assert-plus@1.0.0, assert-plus@^1.0.0:
335 | version "1.0.0"
336 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
337 | integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
338 |
339 | asynckit@^0.4.0:
340 | version "0.4.0"
341 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
342 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
343 |
344 | aws-sign2@~0.7.0:
345 | version "0.7.0"
346 | resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
347 | integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
348 |
349 | aws4@^1.8.0:
350 | version "1.11.0"
351 | resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
352 | integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
353 |
354 | bcrypt-pbkdf@^1.0.0:
355 | version "1.0.2"
356 | resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
357 | integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
358 | dependencies:
359 | tweetnacl "^0.14.3"
360 |
361 | blockly@^6.20210701.0:
362 | version "6.20210701.0"
363 | resolved "https://registry.yarnpkg.com/blockly/-/blockly-6.20210701.0.tgz#578dbdc59a61339a6ba29a69d0dc7bebeb8a19d1"
364 | integrity sha512-cNrwFOAxXE5Pbs1FJAyLTlSRzpNW/C+0gPT2rGQDOJVVKcyF3vhFC1StgnxvQNsv//ueuksKWIXxDuSWh1VI4w==
365 | dependencies:
366 | jsdom "15.2.1"
367 |
368 | browser-process-hrtime@^1.0.0:
369 | version "1.0.0"
370 | resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
371 | integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
372 |
373 | browserslist@^4.16.6:
374 | version "4.17.3"
375 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.3.tgz#2844cd6eebe14d12384b0122d217550160d2d624"
376 | integrity sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ==
377 | dependencies:
378 | caniuse-lite "^1.0.30001264"
379 | electron-to-chromium "^1.3.857"
380 | escalade "^3.1.1"
381 | node-releases "^1.1.77"
382 | picocolors "^0.2.1"
383 |
384 | caniuse-lite@^1.0.30001264:
385 | version "1.0.30001265"
386 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz#0613c9e6c922e422792e6fcefdf9a3afeee4f8c3"
387 | integrity sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==
388 |
389 | caseless@~0.12.0:
390 | version "0.12.0"
391 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
392 | integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
393 |
394 | chalk@^2.0.0:
395 | version "2.4.2"
396 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
397 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
398 | dependencies:
399 | ansi-styles "^3.2.1"
400 | escape-string-regexp "^1.0.5"
401 | supports-color "^5.3.0"
402 |
403 | color-convert@^1.9.0:
404 | version "1.9.3"
405 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
406 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
407 | dependencies:
408 | color-name "1.1.3"
409 |
410 | color-name@1.1.3:
411 | version "1.1.3"
412 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
413 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
414 |
415 | combined-stream@^1.0.6, combined-stream@~1.0.6:
416 | version "1.0.8"
417 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
418 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
419 | dependencies:
420 | delayed-stream "~1.0.0"
421 |
422 | convert-source-map@^1.7.0:
423 | version "1.8.0"
424 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
425 | integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
426 | dependencies:
427 | safe-buffer "~5.1.1"
428 |
429 | core-util-is@1.0.2:
430 | version "1.0.2"
431 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
432 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
433 |
434 | cssom@^0.4.1:
435 | version "0.4.4"
436 | resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
437 | integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==
438 |
439 | cssom@~0.3.6:
440 | version "0.3.8"
441 | resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
442 | integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
443 |
444 | cssstyle@^2.0.0:
445 | version "2.3.0"
446 | resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852"
447 | integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==
448 | dependencies:
449 | cssom "~0.3.6"
450 |
451 | dashdash@^1.12.0:
452 | version "1.14.1"
453 | resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
454 | integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
455 | dependencies:
456 | assert-plus "^1.0.0"
457 |
458 | data-urls@^1.1.0:
459 | version "1.1.0"
460 | resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe"
461 | integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==
462 | dependencies:
463 | abab "^2.0.0"
464 | whatwg-mimetype "^2.2.0"
465 | whatwg-url "^7.0.0"
466 |
467 | debug@^4.1.0:
468 | version "4.3.2"
469 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
470 | integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
471 | dependencies:
472 | ms "2.1.2"
473 |
474 | deep-is@~0.1.3:
475 | version "0.1.4"
476 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
477 | integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
478 |
479 | delayed-stream@~1.0.0:
480 | version "1.0.0"
481 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
482 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
483 |
484 | domexception@^1.0.1:
485 | version "1.0.1"
486 | resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90"
487 | integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==
488 | dependencies:
489 | webidl-conversions "^4.0.2"
490 |
491 | ecc-jsbn@~0.1.1:
492 | version "0.1.2"
493 | resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
494 | integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
495 | dependencies:
496 | jsbn "~0.1.0"
497 | safer-buffer "^2.1.0"
498 |
499 | electron-to-chromium@^1.3.857:
500 | version "1.3.861"
501 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.861.tgz#981e37a79af7a7b29bbaeed36376f4795527de13"
502 | integrity sha512-GZyflmpMnZRdZ1e2yAyvuFwz1MPSVQelwHX4TJZyXypB8NcxdPvPNwy5lOTxnlkrK13EiQzyTPugRSnj6cBgKg==
503 |
504 | esbuild-android-arm64@0.13.4:
505 | version "0.13.4"
506 | resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.4.tgz#5178a20d2b7aba741a31c19609f9e67b346996b9"
507 | integrity sha512-elDJt+jNyoHFId0/dKsuVYUPke3EcquIyUwzJCH17a3ERglN3A9aMBI5zbz+xNZ+FbaDNdpn0RaJHCFLbZX+fA==
508 |
509 | esbuild-darwin-64@0.13.4:
510 | version "0.13.4"
511 | resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.4.tgz#7a3e66c8e1271b650541b25eed65c84f3564a69d"
512 | integrity sha512-zJQGyHRAdZUXlRzbN7W+7ykmEiGC+bq3Gc4GxKYjjWTgDRSEly98ym+vRNkDjXwXYD3gGzSwvH35+MiHAtWvLA==
513 |
514 | esbuild-darwin-arm64@0.13.4:
515 | version "0.13.4"
516 | resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.4.tgz#793feca6032b2a57ef291eb9b2d33768d60a49d6"
517 | integrity sha512-r8oYvAtqSGq8HNTZCAx4TdLE7jZiGhX9ooGi5AQAey37MA6XNaP8ZNlw9OCpcgpx3ryU2WctXwIqPzkHO7a8dg==
518 |
519 | esbuild-freebsd-64@0.13.4:
520 | version "0.13.4"
521 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.4.tgz#294aec3c2cf4b41fb6900212fc9c33dd8fbbb4a2"
522 | integrity sha512-u9DRGkn09EN8+lCh6z7FKle7awi17PJRBuAKdRNgSo5ZrH/3m+mYaJK2PR2URHMpAfXiwJX341z231tSdVe3Yw==
523 |
524 | esbuild-freebsd-arm64@0.13.4:
525 | version "0.13.4"
526 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.4.tgz#09fe66c751c12f9b976976b1d83f3de594cb2787"
527 | integrity sha512-q3B2k68Uf6gfjATjcK16DqxvjqRQkHL8aPoOfj4op+lSqegdXvBacB1d8jw8PxbWJ8JHpdTLdAVUYU80kotQXA==
528 |
529 | esbuild-linux-32@0.13.4:
530 | version "0.13.4"
531 | resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.4.tgz#a9f0793d7bcc9cef4f4ffa4398c525877fba5839"
532 | integrity sha512-UUYJPHSiKAO8KoN3Ls/iZtgDLZvK5HarES96aolDPWZnq9FLx4dIHM/x2z4Rxv9IYqQ/DxlPoE2Co1UPBIYYeA==
533 |
534 | esbuild-linux-64@0.13.4:
535 | version "0.13.4"
536 | resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.4.tgz#c0d0b4c9d62e3bbf8bdf2cece37403aa6d60fc2e"
537 | integrity sha512-+RnohAKiiUW4UHLGRkNR1AnENW1gCuDWuygEtd4jxTNPIoeC7lbXGor7rtgjj9AdUzFgOEvAXyNNX01kJ8NueQ==
538 |
539 | esbuild-linux-arm64@0.13.4:
540 | version "0.13.4"
541 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.4.tgz#1292d97bfa64a08d12728f8a7837bf92776c779b"
542 | integrity sha512-+A188cAdd6QuSRxMIwRrWLjgphQA0LDAQ/ECVlrPVJwnx+1i64NjDZivoqPYLOTkSPIKntiWwMhhf0U5/RrPHQ==
543 |
544 | esbuild-linux-arm@0.13.4:
545 | version "0.13.4"
546 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.4.tgz#186cd9b8885ac132b9953a4a0afe668168debd10"
547 | integrity sha512-BH5gKve4jglS7UPSsfwHSX79I5agC/lm4eKoRUEyo8lwQs89frQSRp2Xup+6SFQnxt3md5EsKcd2Dbkqeb3gPA==
548 |
549 | esbuild-linux-mips64le@0.13.4:
550 | version "0.13.4"
551 | resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.4.tgz#42049bf72bc586817b4a51cc9e32148d13e5e807"
552 | integrity sha512-0xkwtPaUkG5xMTFGaQPe1AadSe5QAiQuD4Gix1O9k5Xo/U8xGIkw9UFUTvfEUeu71vFb6ZgsIacfP1NLoFjWNw==
553 |
554 | esbuild-linux-ppc64le@0.13.4:
555 | version "0.13.4"
556 | resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.4.tgz#adf1ce2ef2302757c4383887da6ac4dd25be9d4f"
557 | integrity sha512-E1+oJPP7A+j23GPo3CEpBhGwG1bni4B8IbTA3/3rvzjURwUMZdcN3Fhrz24rnjzdLSHmULtOE4VsbT42h1Om4Q==
558 |
559 | esbuild-openbsd-64@0.13.4:
560 | version "0.13.4"
561 | resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.4.tgz#1c8122101898c52a20c8786935cf3eb7a19b83b4"
562 | integrity sha512-xEkI1o5HYxDzbv9jSox0EsDxpwraG09SRiKKv0W8pH6O3bt+zPSlnoK7+I7Q69tkvONkpIq5n2o+c55uq0X7cw==
563 |
564 | esbuild-sunos-64@0.13.4:
565 | version "0.13.4"
566 | resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.4.tgz#4ec95faa14a60f295fe485bebffefff408739337"
567 | integrity sha512-bjXUMcODMnB6hQicLBBmmnBl7OMDyVpFahKvHGXJfDChIi5udiIRKCmFUFIRn+AUAKVlfrofRKdyPC7kBsbvGQ==
568 |
569 | esbuild-windows-32@0.13.4:
570 | version "0.13.4"
571 | resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.4.tgz#3182c380487b797b04d0ec2c80c2945666869080"
572 | integrity sha512-z4CH07pfyVY0XF98TCsGmLxKCl0kyvshKDbdpTekW9f2d+dJqn5mmoUyWhpSVJ0SfYWJg86FoD9nMbbaMVyGdg==
573 |
574 | esbuild-windows-64@0.13.4:
575 | version "0.13.4"
576 | resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.4.tgz#b9e995f92d81f433a04f33611e603e82f9232e69"
577 | integrity sha512-uVL11vORRPjocGLYam67rwFLd0LvkrHEs+JG+1oJN4UD9MQmNGZPa4gBHo6hDpF+kqRJ9kXgQSeDqUyRy0tj/Q==
578 |
579 | esbuild-windows-arm64@0.13.4:
580 | version "0.13.4"
581 | resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.4.tgz#fb239532f07b764d158f4cc787178ef4c6fadb5c"
582 | integrity sha512-vA6GLvptgftRcDcWngD5cMlL4f4LbL8JjU2UMT9yJ0MT5ra6hdZNFWnOeOoEtY4GtJ6OjZ0i+81sTqhAB0fMkg==
583 |
584 | esbuild@^0.13.2:
585 | version "0.13.4"
586 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.4.tgz#ce2deb56c4fb360938311cbfc67f8e467bb6841b"
587 | integrity sha512-wMA5eUwpavTBiNl+It6j8OQuKVh69l6z4DKDLzoTIqC+gChnPpcmqdA8WNHptUHRnfyML+mKEQPlW7Mybj8gHg==
588 | optionalDependencies:
589 | esbuild-android-arm64 "0.13.4"
590 | esbuild-darwin-64 "0.13.4"
591 | esbuild-darwin-arm64 "0.13.4"
592 | esbuild-freebsd-64 "0.13.4"
593 | esbuild-freebsd-arm64 "0.13.4"
594 | esbuild-linux-32 "0.13.4"
595 | esbuild-linux-64 "0.13.4"
596 | esbuild-linux-arm "0.13.4"
597 | esbuild-linux-arm64 "0.13.4"
598 | esbuild-linux-mips64le "0.13.4"
599 | esbuild-linux-ppc64le "0.13.4"
600 | esbuild-openbsd-64 "0.13.4"
601 | esbuild-sunos-64 "0.13.4"
602 | esbuild-windows-32 "0.13.4"
603 | esbuild-windows-64 "0.13.4"
604 | esbuild-windows-arm64 "0.13.4"
605 |
606 | escalade@^3.1.1:
607 | version "3.1.1"
608 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
609 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
610 |
611 | escape-string-regexp@^1.0.5:
612 | version "1.0.5"
613 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
614 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
615 |
616 | escodegen@^1.11.1:
617 | version "1.14.3"
618 | resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
619 | integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
620 | dependencies:
621 | esprima "^4.0.1"
622 | estraverse "^4.2.0"
623 | esutils "^2.0.2"
624 | optionator "^0.8.1"
625 | optionalDependencies:
626 | source-map "~0.6.1"
627 |
628 | esprima@^4.0.1:
629 | version "4.0.1"
630 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
631 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
632 |
633 | estraverse@^4.2.0:
634 | version "4.3.0"
635 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
636 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
637 |
638 | estree-walker@^2.0.1:
639 | version "2.0.2"
640 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
641 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
642 |
643 | esutils@^2.0.2:
644 | version "2.0.3"
645 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
646 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
647 |
648 | extend@~3.0.2:
649 | version "3.0.2"
650 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
651 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
652 |
653 | extsprintf@1.3.0:
654 | version "1.3.0"
655 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
656 | integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
657 |
658 | extsprintf@^1.2.0:
659 | version "1.4.0"
660 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
661 | integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
662 |
663 | fast-deep-equal@^3.1.1:
664 | version "3.1.3"
665 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
666 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
667 |
668 | fast-json-stable-stringify@^2.0.0:
669 | version "2.1.0"
670 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
671 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
672 |
673 | fast-levenshtein@~2.0.6:
674 | version "2.0.6"
675 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
676 | integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
677 |
678 | forever-agent@~0.6.1:
679 | version "0.6.1"
680 | resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
681 | integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
682 |
683 | form-data@~2.3.2:
684 | version "2.3.3"
685 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
686 | integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
687 | dependencies:
688 | asynckit "^0.4.0"
689 | combined-stream "^1.0.6"
690 | mime-types "^2.1.12"
691 |
692 | fsevents@~2.3.2:
693 | version "2.3.2"
694 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
695 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
696 |
697 | function-bind@^1.1.1:
698 | version "1.1.1"
699 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
700 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
701 |
702 | gensync@^1.0.0-beta.2:
703 | version "1.0.0-beta.2"
704 | resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
705 | integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
706 |
707 | getpass@^0.1.1:
708 | version "0.1.7"
709 | resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
710 | integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
711 | dependencies:
712 | assert-plus "^1.0.0"
713 |
714 | globals@^11.1.0:
715 | version "11.12.0"
716 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
717 | integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
718 |
719 | har-schema@^2.0.0:
720 | version "2.0.0"
721 | resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
722 | integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
723 |
724 | har-validator@~5.1.3:
725 | version "5.1.5"
726 | resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
727 | integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
728 | dependencies:
729 | ajv "^6.12.3"
730 | har-schema "^2.0.0"
731 |
732 | has-flag@^3.0.0:
733 | version "3.0.0"
734 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
735 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
736 |
737 | has@^1.0.3:
738 | version "1.0.3"
739 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
740 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
741 | dependencies:
742 | function-bind "^1.1.1"
743 |
744 | html-encoding-sniffer@^1.0.2:
745 | version "1.0.2"
746 | resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8"
747 | integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==
748 | dependencies:
749 | whatwg-encoding "^1.0.1"
750 |
751 | http-signature@~1.2.0:
752 | version "1.2.0"
753 | resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
754 | integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
755 | dependencies:
756 | assert-plus "^1.0.0"
757 | jsprim "^1.2.2"
758 | sshpk "^1.7.0"
759 |
760 | iconv-lite@0.4.24:
761 | version "0.4.24"
762 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
763 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
764 | dependencies:
765 | safer-buffer ">= 2.1.2 < 3"
766 |
767 | ip-regex@^2.1.0:
768 | version "2.1.0"
769 | resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
770 | integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=
771 |
772 | is-core-module@^2.2.0:
773 | version "2.7.0"
774 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.7.0.tgz#3c0ef7d31b4acfc574f80c58409d568a836848e3"
775 | integrity sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==
776 | dependencies:
777 | has "^1.0.3"
778 |
779 | is-typedarray@~1.0.0:
780 | version "1.0.0"
781 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
782 | integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
783 |
784 | isstream@~0.1.2:
785 | version "0.1.2"
786 | resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
787 | integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
788 |
789 | "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
790 | version "4.0.0"
791 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
792 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
793 |
794 | jsbn@~0.1.0:
795 | version "0.1.1"
796 | resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
797 | integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
798 |
799 | jsdom@15.2.1:
800 | version "15.2.1"
801 | resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-15.2.1.tgz#d2feb1aef7183f86be521b8c6833ff5296d07ec5"
802 | integrity sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g==
803 | dependencies:
804 | abab "^2.0.0"
805 | acorn "^7.1.0"
806 | acorn-globals "^4.3.2"
807 | array-equal "^1.0.0"
808 | cssom "^0.4.1"
809 | cssstyle "^2.0.0"
810 | data-urls "^1.1.0"
811 | domexception "^1.0.1"
812 | escodegen "^1.11.1"
813 | html-encoding-sniffer "^1.0.2"
814 | nwsapi "^2.2.0"
815 | parse5 "5.1.0"
816 | pn "^1.1.0"
817 | request "^2.88.0"
818 | request-promise-native "^1.0.7"
819 | saxes "^3.1.9"
820 | symbol-tree "^3.2.2"
821 | tough-cookie "^3.0.1"
822 | w3c-hr-time "^1.0.1"
823 | w3c-xmlserializer "^1.1.2"
824 | webidl-conversions "^4.0.2"
825 | whatwg-encoding "^1.0.5"
826 | whatwg-mimetype "^2.3.0"
827 | whatwg-url "^7.0.0"
828 | ws "^7.0.0"
829 | xml-name-validator "^3.0.0"
830 |
831 | jsesc@^2.5.1:
832 | version "2.5.2"
833 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
834 | integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
835 |
836 | json-schema-traverse@^0.4.1:
837 | version "0.4.1"
838 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
839 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
840 |
841 | json-schema@0.2.3:
842 | version "0.2.3"
843 | resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
844 | integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
845 |
846 | json-stringify-safe@~5.0.1:
847 | version "5.0.1"
848 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
849 | integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
850 |
851 | json5@^2.1.2:
852 | version "2.2.0"
853 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
854 | integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
855 | dependencies:
856 | minimist "^1.2.5"
857 |
858 | jsprim@^1.2.2:
859 | version "1.4.1"
860 | resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
861 | integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
862 | dependencies:
863 | assert-plus "1.0.0"
864 | extsprintf "1.3.0"
865 | json-schema "0.2.3"
866 | verror "1.10.0"
867 |
868 | levn@~0.3.0:
869 | version "0.3.0"
870 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
871 | integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
872 | dependencies:
873 | prelude-ls "~1.1.2"
874 | type-check "~0.3.2"
875 |
876 | lodash.sortby@^4.7.0:
877 | version "4.7.0"
878 | resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
879 | integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
880 |
881 | lodash@^4.17.19:
882 | version "4.17.21"
883 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
884 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
885 |
886 | loose-envify@^1.1.0:
887 | version "1.4.0"
888 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
889 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
890 | dependencies:
891 | js-tokens "^3.0.0 || ^4.0.0"
892 |
893 | mime-db@1.50.0:
894 | version "1.50.0"
895 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f"
896 | integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==
897 |
898 | mime-types@^2.1.12, mime-types@~2.1.19:
899 | version "2.1.33"
900 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb"
901 | integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==
902 | dependencies:
903 | mime-db "1.50.0"
904 |
905 | minimist@^1.2.5:
906 | version "1.2.5"
907 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
908 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
909 |
910 | ms@2.1.2:
911 | version "2.1.2"
912 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
913 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
914 |
915 | nanoid@^3.1.28:
916 | version "3.1.29"
917 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.29.tgz#214fb2d7a33e1a5bef4757b779dfaeb6a4e5aeb4"
918 | integrity sha512-dW2pUSGZ8ZnCFIlBIA31SV8huOGCHb6OwzVCc7A69rb/a+SgPBwfmLvK5TKQ3INPbRkcI8a/Owo0XbiTNH19wg==
919 |
920 | node-releases@^1.1.77:
921 | version "1.1.77"
922 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e"
923 | integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==
924 |
925 | nwsapi@^2.2.0:
926 | version "2.2.0"
927 | resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
928 | integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
929 |
930 | oauth-sign@~0.9.0:
931 | version "0.9.0"
932 | resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
933 | integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
934 |
935 | object-assign@^4.1.1:
936 | version "4.1.1"
937 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
938 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
939 |
940 | optionator@^0.8.1:
941 | version "0.8.3"
942 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
943 | integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
944 | dependencies:
945 | deep-is "~0.1.3"
946 | fast-levenshtein "~2.0.6"
947 | levn "~0.3.0"
948 | prelude-ls "~1.1.2"
949 | type-check "~0.3.2"
950 | word-wrap "~1.2.3"
951 |
952 | parse5@5.1.0:
953 | version "5.1.0"
954 | resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2"
955 | integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==
956 |
957 | path-parse@^1.0.6:
958 | version "1.0.7"
959 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
960 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
961 |
962 | performance-now@^2.1.0:
963 | version "2.1.0"
964 | resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
965 | integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
966 |
967 | picocolors@^0.2.1:
968 | version "0.2.1"
969 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
970 | integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==
971 |
972 | picomatch@^2.2.2:
973 | version "2.3.0"
974 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
975 | integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
976 |
977 | pn@^1.1.0:
978 | version "1.1.0"
979 | resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
980 | integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==
981 |
982 | postcss@^8.3.8:
983 | version "8.3.9"
984 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.9.tgz#98754caa06c4ee9eb59cc48bd073bb6bd3437c31"
985 | integrity sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw==
986 | dependencies:
987 | nanoid "^3.1.28"
988 | picocolors "^0.2.1"
989 | source-map-js "^0.6.2"
990 |
991 | prelude-ls@~1.1.2:
992 | version "1.1.2"
993 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
994 | integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
995 |
996 | psl@^1.1.28:
997 | version "1.8.0"
998 | resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
999 | integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
1000 |
1001 | punycode@^2.1.0, punycode@^2.1.1:
1002 | version "2.1.1"
1003 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
1004 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
1005 |
1006 | qs@~6.5.2:
1007 | version "6.5.2"
1008 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
1009 | integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
1010 |
1011 | react-dom@^17.0.0:
1012 | version "17.0.2"
1013 | resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
1014 | integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
1015 | dependencies:
1016 | loose-envify "^1.1.0"
1017 | object-assign "^4.1.1"
1018 | scheduler "^0.20.2"
1019 |
1020 | react-refresh@^0.10.0:
1021 | version "0.10.0"
1022 | resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.10.0.tgz#2f536c9660c0b9b1d500684d9e52a65e7404f7e3"
1023 | integrity sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==
1024 |
1025 | react@^17.0.0:
1026 | version "17.0.2"
1027 | resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
1028 | integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
1029 | dependencies:
1030 | loose-envify "^1.1.0"
1031 | object-assign "^4.1.1"
1032 |
1033 | request-promise-core@1.1.4:
1034 | version "1.1.4"
1035 | resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
1036 | integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==
1037 | dependencies:
1038 | lodash "^4.17.19"
1039 |
1040 | request-promise-native@^1.0.7:
1041 | version "1.0.9"
1042 | resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28"
1043 | integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==
1044 | dependencies:
1045 | request-promise-core "1.1.4"
1046 | stealthy-require "^1.1.1"
1047 | tough-cookie "^2.3.3"
1048 |
1049 | request@^2.88.0:
1050 | version "2.88.2"
1051 | resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
1052 | integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
1053 | dependencies:
1054 | aws-sign2 "~0.7.0"
1055 | aws4 "^1.8.0"
1056 | caseless "~0.12.0"
1057 | combined-stream "~1.0.6"
1058 | extend "~3.0.2"
1059 | forever-agent "~0.6.1"
1060 | form-data "~2.3.2"
1061 | har-validator "~5.1.3"
1062 | http-signature "~1.2.0"
1063 | is-typedarray "~1.0.0"
1064 | isstream "~0.1.2"
1065 | json-stringify-safe "~5.0.1"
1066 | mime-types "~2.1.19"
1067 | oauth-sign "~0.9.0"
1068 | performance-now "^2.1.0"
1069 | qs "~6.5.2"
1070 | safe-buffer "^5.1.2"
1071 | tough-cookie "~2.5.0"
1072 | tunnel-agent "^0.6.0"
1073 | uuid "^3.3.2"
1074 |
1075 | resolve@^1.20.0:
1076 | version "1.20.0"
1077 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
1078 | integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
1079 | dependencies:
1080 | is-core-module "^2.2.0"
1081 | path-parse "^1.0.6"
1082 |
1083 | rollup@^2.57.0:
1084 | version "2.58.0"
1085 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.58.0.tgz#a643983365e7bf7f5b7c62a8331b983b7c4c67fb"
1086 | integrity sha512-NOXpusKnaRpbS7ZVSzcEXqxcLDOagN6iFS8p45RkoiMqPHDLwJm758UF05KlMoCRbLBTZsPOIa887gZJ1AiXvw==
1087 | optionalDependencies:
1088 | fsevents "~2.3.2"
1089 |
1090 | safe-buffer@^5.0.1, safe-buffer@^5.1.2:
1091 | version "5.2.1"
1092 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
1093 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
1094 |
1095 | safe-buffer@~5.1.1:
1096 | version "5.1.2"
1097 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
1098 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
1099 |
1100 | "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
1101 | version "2.1.2"
1102 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
1103 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
1104 |
1105 | saxes@^3.1.9:
1106 | version "3.1.11"
1107 | resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b"
1108 | integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==
1109 | dependencies:
1110 | xmlchars "^2.1.1"
1111 |
1112 | scheduler@^0.20.2:
1113 | version "0.20.2"
1114 | resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
1115 | integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
1116 | dependencies:
1117 | loose-envify "^1.1.0"
1118 | object-assign "^4.1.1"
1119 |
1120 | semver@^6.3.0:
1121 | version "6.3.0"
1122 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
1123 | integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
1124 |
1125 | source-map-js@^0.6.2:
1126 | version "0.6.2"
1127 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
1128 | integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
1129 |
1130 | source-map@^0.5.0:
1131 | version "0.5.7"
1132 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
1133 | integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
1134 |
1135 | source-map@~0.6.1:
1136 | version "0.6.1"
1137 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
1138 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
1139 |
1140 | sshpk@^1.7.0:
1141 | version "1.16.1"
1142 | resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
1143 | integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
1144 | dependencies:
1145 | asn1 "~0.2.3"
1146 | assert-plus "^1.0.0"
1147 | bcrypt-pbkdf "^1.0.0"
1148 | dashdash "^1.12.0"
1149 | ecc-jsbn "~0.1.1"
1150 | getpass "^0.1.1"
1151 | jsbn "~0.1.0"
1152 | safer-buffer "^2.0.2"
1153 | tweetnacl "~0.14.0"
1154 |
1155 | stealthy-require@^1.1.1:
1156 | version "1.1.1"
1157 | resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
1158 | integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
1159 |
1160 | supports-color@^5.3.0:
1161 | version "5.5.0"
1162 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
1163 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
1164 | dependencies:
1165 | has-flag "^3.0.0"
1166 |
1167 | symbol-tree@^3.2.2:
1168 | version "3.2.4"
1169 | resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
1170 | integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
1171 |
1172 | to-fast-properties@^2.0.0:
1173 | version "2.0.0"
1174 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
1175 | integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
1176 |
1177 | tough-cookie@^2.3.3, tough-cookie@~2.5.0:
1178 | version "2.5.0"
1179 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
1180 | integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
1181 | dependencies:
1182 | psl "^1.1.28"
1183 | punycode "^2.1.1"
1184 |
1185 | tough-cookie@^3.0.1:
1186 | version "3.0.1"
1187 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2"
1188 | integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==
1189 | dependencies:
1190 | ip-regex "^2.1.0"
1191 | psl "^1.1.28"
1192 | punycode "^2.1.1"
1193 |
1194 | tr46@^1.0.1:
1195 | version "1.0.1"
1196 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
1197 | integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=
1198 | dependencies:
1199 | punycode "^2.1.0"
1200 |
1201 | tunnel-agent@^0.6.0:
1202 | version "0.6.0"
1203 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
1204 | integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
1205 | dependencies:
1206 | safe-buffer "^5.0.1"
1207 |
1208 | tweetnacl@^0.14.3, tweetnacl@~0.14.0:
1209 | version "0.14.5"
1210 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
1211 | integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
1212 |
1213 | type-check@~0.3.2:
1214 | version "0.3.2"
1215 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
1216 | integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
1217 | dependencies:
1218 | prelude-ls "~1.1.2"
1219 |
1220 | uri-js@^4.2.2:
1221 | version "4.4.1"
1222 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
1223 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
1224 | dependencies:
1225 | punycode "^2.1.0"
1226 |
1227 | uuid@^3.3.2:
1228 | version "3.4.0"
1229 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
1230 | integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
1231 |
1232 | verror@1.10.0:
1233 | version "1.10.0"
1234 | resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
1235 | integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
1236 | dependencies:
1237 | assert-plus "^1.0.0"
1238 | core-util-is "1.0.2"
1239 | extsprintf "^1.2.0"
1240 |
1241 | vite@^2.6.4:
1242 | version "2.6.4"
1243 | resolved "https://registry.yarnpkg.com/vite/-/vite-2.6.4.tgz#b932735f1ecdf69256ce6eaae0d41a7b15d77599"
1244 | integrity sha512-zNGZgjKGprdLKJ1g1taAvNt51JbGAdrAUU9hpLzgtlks+cXBxTZUsEAGEtLbF3UvlYOVAPXS8r9E9gxYAv6z+A==
1245 | dependencies:
1246 | esbuild "^0.13.2"
1247 | postcss "^8.3.8"
1248 | resolve "^1.20.0"
1249 | rollup "^2.57.0"
1250 | optionalDependencies:
1251 | fsevents "~2.3.2"
1252 |
1253 | w3c-hr-time@^1.0.1:
1254 | version "1.0.2"
1255 | resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
1256 | integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==
1257 | dependencies:
1258 | browser-process-hrtime "^1.0.0"
1259 |
1260 | w3c-xmlserializer@^1.1.2:
1261 | version "1.1.2"
1262 | resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794"
1263 | integrity sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==
1264 | dependencies:
1265 | domexception "^1.0.1"
1266 | webidl-conversions "^4.0.2"
1267 | xml-name-validator "^3.0.0"
1268 |
1269 | webidl-conversions@^4.0.2:
1270 | version "4.0.2"
1271 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
1272 | integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
1273 |
1274 | whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5:
1275 | version "1.0.5"
1276 | resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
1277 | integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
1278 | dependencies:
1279 | iconv-lite "0.4.24"
1280 |
1281 | whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0:
1282 | version "2.3.0"
1283 | resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
1284 | integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
1285 |
1286 | whatwg-url@^7.0.0:
1287 | version "7.1.0"
1288 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
1289 | integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
1290 | dependencies:
1291 | lodash.sortby "^4.7.0"
1292 | tr46 "^1.0.1"
1293 | webidl-conversions "^4.0.2"
1294 |
1295 | word-wrap@~1.2.3:
1296 | version "1.2.3"
1297 | resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
1298 | integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
1299 |
1300 | ws@^7.0.0:
1301 | version "7.5.5"
1302 | resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881"
1303 | integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==
1304 |
1305 | xml-name-validator@^3.0.0:
1306 | version "3.0.0"
1307 | resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
1308 | integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
1309 |
1310 | xmlchars@^2.1.1:
1311 | version "2.2.0"
1312 | resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
1313 | integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
1314 |
--------------------------------------------------------------------------------