Spaces:
Running
Running
owenkaplinsky
commited on
Commit
Β·
7660e27
1
Parent(s):
1e62dc6
Make user message block; infinite
Browse files- {hello-world β project}/.npmignore +0 -0
- {hello-world β project}/app.py +0 -0
- {hello-world β project}/package-lock.json +9 -0
- {hello-world β project}/package.json +2 -1
- {hello-world β project}/src/blocks/text.js +19 -11
- {hello-world β project}/src/generators/python.js +6 -1
- {hello-world β project}/src/index.css +0 -0
- {hello-world β project}/src/index.html +0 -0
- {hello-world β project}/src/index.js +52 -27
- {hello-world β project}/src/serialization.js +0 -0
- {hello-world β project}/src/toolbox.js +23 -54
- {hello-world β project}/webpack.config.js +0 -0
{hello-world β project}/.npmignore
RENAMED
|
File without changes
|
{hello-world β project}/app.py
RENAMED
|
File without changes
|
{hello-world β project}/package-lock.json
RENAMED
|
@@ -9,6 +9,7 @@
|
|
| 9 |
"version": "1.0.0",
|
| 10 |
"license": "Apache-2.0",
|
| 11 |
"dependencies": {
|
|
|
|
| 12 |
"blockly": "^11.0.0"
|
| 13 |
},
|
| 14 |
"devDependencies": {
|
|
@@ -33,6 +34,14 @@
|
|
| 33 |
"lru-cache": "^10.4.3"
|
| 34 |
}
|
| 35 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
"node_modules/@csstools/color-helpers": {
|
| 37 |
"version": "5.1.0",
|
| 38 |
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
|
|
|
|
| 9 |
"version": "1.0.0",
|
| 10 |
"license": "Apache-2.0",
|
| 11 |
"dependencies": {
|
| 12 |
+
"@blockly/toolbox-search": "^3.0.2",
|
| 13 |
"blockly": "^11.0.0"
|
| 14 |
},
|
| 15 |
"devDependencies": {
|
|
|
|
| 34 |
"lru-cache": "^10.4.3"
|
| 35 |
}
|
| 36 |
},
|
| 37 |
+
"node_modules/@blockly/toolbox-search": {
|
| 38 |
+
"version": "3.0.2",
|
| 39 |
+
"resolved": "https://registry.npmjs.org/@blockly/toolbox-search/-/toolbox-search-3.0.2.tgz",
|
| 40 |
+
"integrity": "sha512-NnwK9hjyxhCOmCuF1FGH8Ca+wiZ7E7LWFdx+X8Bi4szZkPBLd9ZY3lp8bWi9WlmQax3sXQ3QAMC9/bq2OXAkdw==",
|
| 41 |
+
"peerDependencies": {
|
| 42 |
+
"blockly": "^12.0.0"
|
| 43 |
+
}
|
| 44 |
+
},
|
| 45 |
"node_modules/@csstools/color-helpers": {
|
| 46 |
"version": "5.1.0",
|
| 47 |
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
|
{hello-world β project}/package.json
RENAMED
|
@@ -24,6 +24,7 @@
|
|
| 24 |
"webpack-dev-server": "^4.11.1"
|
| 25 |
},
|
| 26 |
"dependencies": {
|
|
|
|
| 27 |
"blockly": "^11.0.0"
|
| 28 |
}
|
| 29 |
-
}
|
|
|
|
| 24 |
"webpack-dev-server": "^4.11.1"
|
| 25 |
},
|
| 26 |
"dependencies": {
|
| 27 |
+
"@blockly/toolbox-search": "^3.0.2",
|
| 28 |
"blockly": "^11.0.0"
|
| 29 |
}
|
| 30 |
+
}
|
{hello-world β project}/src/blocks/text.js
RENAMED
|
@@ -1,21 +1,19 @@
|
|
| 1 |
-
/**
|
| 2 |
-
* @license
|
| 3 |
-
* Copyright 2023 Google LLC
|
| 4 |
-
* SPDX-License-Identifier: Apache-2.0
|
| 5 |
-
*/
|
| 6 |
-
|
| 7 |
import * as Blockly from 'blockly/core';
|
| 8 |
|
| 9 |
const whenUserSends = {
|
| 10 |
type: 'when_user_sends',
|
| 11 |
-
message0: 'when user sends
|
| 12 |
args0: [
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
{
|
| 14 |
"type": "input_dummy"
|
| 15 |
},
|
| 16 |
{
|
| 17 |
"type": "input_statement",
|
| 18 |
-
"name": "
|
| 19 |
}
|
| 20 |
],
|
| 21 |
inputsInline: true,
|
|
@@ -43,7 +41,7 @@ const assistantReply = {
|
|
| 43 |
|
| 44 |
const getAssistantResponse = {
|
| 45 |
type: 'get_assistant_response',
|
| 46 |
-
message0: 'call model %1 with prompt %2
|
| 47 |
args0: [
|
| 48 |
{
|
| 49 |
type: 'field_dropdown',
|
|
@@ -62,8 +60,8 @@ const getAssistantResponse = {
|
|
| 62 |
type: 'field_dropdown',
|
| 63 |
name: 'HISTORY',
|
| 64 |
options: [
|
| 65 |
-
["
|
| 66 |
-
["
|
| 67 |
]
|
| 68 |
},
|
| 69 |
],
|
|
@@ -74,8 +72,18 @@ const getAssistantResponse = {
|
|
| 74 |
helpUrl: '',
|
| 75 |
};
|
| 76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
export const blocks = Blockly.common.createBlockDefinitionsFromJsonArray([
|
| 78 |
whenUserSends,
|
| 79 |
assistantReply,
|
| 80 |
getAssistantResponse,
|
|
|
|
| 81 |
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import * as Blockly from 'blockly/core';
|
| 2 |
|
| 3 |
const whenUserSends = {
|
| 4 |
type: 'when_user_sends',
|
| 5 |
+
message0: 'when user sends %1 do %2 %3',
|
| 6 |
args0: [
|
| 7 |
+
{
|
| 8 |
+
"type": "input_value",
|
| 9 |
+
"name": "DUPLICATE"
|
| 10 |
+
},
|
| 11 |
{
|
| 12 |
"type": "input_dummy"
|
| 13 |
},
|
| 14 |
{
|
| 15 |
"type": "input_statement",
|
| 16 |
+
"name": "CODE"
|
| 17 |
}
|
| 18 |
],
|
| 19 |
inputsInline: true,
|
|
|
|
| 41 |
|
| 42 |
const getAssistantResponse = {
|
| 43 |
type: 'get_assistant_response',
|
| 44 |
+
message0: 'call model %1 with prompt %2 %3 history',
|
| 45 |
args0: [
|
| 46 |
{
|
| 47 |
type: 'field_dropdown',
|
|
|
|
| 60 |
type: 'field_dropdown',
|
| 61 |
name: 'HISTORY',
|
| 62 |
options: [
|
| 63 |
+
["with", "True"],
|
| 64 |
+
["without", "False"]
|
| 65 |
]
|
| 66 |
},
|
| 67 |
],
|
|
|
|
| 72 |
helpUrl: '',
|
| 73 |
};
|
| 74 |
|
| 75 |
+
const user_message = {
|
| 76 |
+
type: "user_message",
|
| 77 |
+
message0: "user message",
|
| 78 |
+
output: "String",
|
| 79 |
+
colour: "#47A8D1",
|
| 80 |
+
tooltip: "",
|
| 81 |
+
helpUrl: "",
|
| 82 |
+
};
|
| 83 |
+
|
| 84 |
export const blocks = Blockly.common.createBlockDefinitionsFromJsonArray([
|
| 85 |
whenUserSends,
|
| 86 |
assistantReply,
|
| 87 |
getAssistantResponse,
|
| 88 |
+
user_message
|
| 89 |
]);
|
{hello-world β project}/src/generators/python.js
RENAMED
|
@@ -4,7 +4,7 @@ export const forBlock = Object.create(null);
|
|
| 4 |
|
| 5 |
// Generates a Python function that runs when the user sends a message
|
| 6 |
forBlock['when_user_sends'] = function (block, generator) {
|
| 7 |
-
const body = generator.statementToCode(block, '
|
| 8 |
const code = `def on_user_send(user_message):\n${body} return\n`;
|
| 9 |
return code;
|
| 10 |
};
|
|
@@ -23,4 +23,9 @@ forBlock['get_assistant_response'] = function (block, generator) {
|
|
| 23 |
|
| 24 |
const code = `get_assistant_response(${prompt}, model="${model}", use_history=${history})`;
|
| 25 |
return [code, Order.NONE];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
};
|
|
|
|
| 4 |
|
| 5 |
// Generates a Python function that runs when the user sends a message
|
| 6 |
forBlock['when_user_sends'] = function (block, generator) {
|
| 7 |
+
const body = generator.statementToCode(block, 'CODE') || "";
|
| 8 |
const code = `def on_user_send(user_message):\n${body} return\n`;
|
| 9 |
return code;
|
| 10 |
};
|
|
|
|
| 23 |
|
| 24 |
const code = `get_assistant_response(${prompt}, model="${model}", use_history=${history})`;
|
| 25 |
return [code, Order.NONE];
|
| 26 |
+
};
|
| 27 |
+
|
| 28 |
+
forBlock['user_message'] = function (block, generator) {
|
| 29 |
+
const code = `user_message`;
|
| 30 |
+
return [code, generator.ORDER_NONE];
|
| 31 |
};
|
{hello-world β project}/src/index.css
RENAMED
|
File without changes
|
{hello-world β project}/src/index.html
RENAMED
|
File without changes
|
{hello-world β project}/src/index.js
RENAMED
|
@@ -1,15 +1,10 @@
|
|
| 1 |
-
/**
|
| 2 |
-
* @license
|
| 3 |
-
* Copyright 2023 Google LLC
|
| 4 |
-
* SPDX-License-Identifier: Apache-2.0
|
| 5 |
-
*/
|
| 6 |
-
|
| 7 |
import * as Blockly from 'blockly';
|
| 8 |
import { blocks } from './blocks/text';
|
| 9 |
import { forBlock } from './generators/python';
|
| 10 |
import { pythonGenerator } from 'blockly/python';
|
| 11 |
import { save, load } from './serialization';
|
| 12 |
import { toolbox } from './toolbox';
|
|
|
|
| 13 |
import './index.css';
|
| 14 |
|
| 15 |
// Register the blocks and generator with Blockly
|
|
@@ -48,21 +43,16 @@ const myTheme = Blockly.Theme.defineTheme('myScratchTheme', {
|
|
| 48 |
// Inject Blockly with theme + renderer
|
| 49 |
const ws = Blockly.inject(blocklyDiv, {
|
| 50 |
toolbox,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
renderer: 'zelos',
|
| 52 |
theme: myTheme,
|
| 53 |
});
|
| 54 |
|
| 55 |
-
if (!ws.getVariable('user_message')) {
|
| 56 |
-
ws.createVariable('user_message');
|
| 57 |
-
}
|
| 58 |
-
|
| 59 |
-
ws.updateUserMessage = (message) => {
|
| 60 |
-
let variable = ws.getVariable('user_message');
|
| 61 |
-
if (!variable) ws.createVariable('user_message');
|
| 62 |
-
ws.variableValues = ws.variableValues || {};
|
| 63 |
-
ws.variableValues['user_message'] = message;
|
| 64 |
-
};
|
| 65 |
-
|
| 66 |
const updateCode = () => {
|
| 67 |
let code = pythonGenerator.workspaceToCode(ws);
|
| 68 |
const codeEl = document.querySelector('#generatedCode code');
|
|
@@ -120,8 +110,45 @@ updateCode();
|
|
| 120 |
ws.addChangeListener((e) => {
|
| 121 |
if (e.isUiEvent) return;
|
| 122 |
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
}
|
| 126 |
|
| 127 |
save(ws);
|
|
@@ -141,16 +168,14 @@ window.addEventListener("message", (event) => {
|
|
| 141 |
});
|
| 142 |
|
| 143 |
function handleUserMessage(message) {
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
|
|
|
| 148 |
}
|
| 149 |
|
| 150 |
if (typeof window.userSendHandler === "function") {
|
| 151 |
-
console.log("[PARENT] userSendHandler exists, invoking it");
|
| 152 |
window.userSendHandler(message);
|
| 153 |
-
} else {
|
| 154 |
-
console.warn("[PARENT] userSendHandler is undefined!");
|
| 155 |
}
|
| 156 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import * as Blockly from 'blockly';
|
| 2 |
import { blocks } from './blocks/text';
|
| 3 |
import { forBlock } from './generators/python';
|
| 4 |
import { pythonGenerator } from 'blockly/python';
|
| 5 |
import { save, load } from './serialization';
|
| 6 |
import { toolbox } from './toolbox';
|
| 7 |
+
import '@blockly/toolbox-search';
|
| 8 |
import './index.css';
|
| 9 |
|
| 10 |
// Register the blocks and generator with Blockly
|
|
|
|
| 43 |
// Inject Blockly with theme + renderer
|
| 44 |
const ws = Blockly.inject(blocklyDiv, {
|
| 45 |
toolbox,
|
| 46 |
+
grid: {
|
| 47 |
+
spacing: 35,
|
| 48 |
+
length: 3,
|
| 49 |
+
colour: '#ccc',
|
| 50 |
+
snap: false
|
| 51 |
+
},
|
| 52 |
renderer: 'zelos',
|
| 53 |
theme: myTheme,
|
| 54 |
});
|
| 55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
const updateCode = () => {
|
| 57 |
let code = pythonGenerator.workspaceToCode(ws);
|
| 58 |
const codeEl = document.querySelector('#generatedCode code');
|
|
|
|
| 110 |
ws.addChangeListener((e) => {
|
| 111 |
if (e.isUiEvent) return;
|
| 112 |
|
| 113 |
+
save(ws);
|
| 114 |
+
});
|
| 115 |
+
|
| 116 |
+
ws.addChangeListener((event) => {
|
| 117 |
+
if (event.isUiEvent) return;
|
| 118 |
+
|
| 119 |
+
if (event.type === Blockly.Events.BLOCK_MOVE) {
|
| 120 |
+
if (event.oldParentId && !event.newParentId) {
|
| 121 |
+
const removedBlock = ws.getBlockById(event.blockId);
|
| 122 |
+
const oldParent = ws.getBlockById(event.oldParentId);
|
| 123 |
+
|
| 124 |
+
if (
|
| 125 |
+
removedBlock &&
|
| 126 |
+
oldParent &&
|
| 127 |
+
removedBlock.type === 'user_message' &&
|
| 128 |
+
oldParent.type === 'when_user_sends'
|
| 129 |
+
) {
|
| 130 |
+
console.log('[DISCONNECT] user_message removed from when_user_sends');
|
| 131 |
+
|
| 132 |
+
if (event.oldInputName) {
|
| 133 |
+
Blockly.Events.disable();
|
| 134 |
+
try {
|
| 135 |
+
const newMsgBlock = ws.newBlock('user_message');
|
| 136 |
+
newMsgBlock.initSvg();
|
| 137 |
+
newMsgBlock.render();
|
| 138 |
+
|
| 139 |
+
const input = oldParent.getInput(event.oldInputName);
|
| 140 |
+
if (input) {
|
| 141 |
+
input.connection.connect(newMsgBlock.outputConnection);
|
| 142 |
+
console.log('[REPLACE] user_message restored instantly (no blink)');
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
ws.render(); // ensure workspace updates immediately
|
| 146 |
+
} finally {
|
| 147 |
+
Blockly.Events.enable();
|
| 148 |
+
}
|
| 149 |
+
}
|
| 150 |
+
}
|
| 151 |
+
}
|
| 152 |
}
|
| 153 |
|
| 154 |
save(ws);
|
|
|
|
| 168 |
});
|
| 169 |
|
| 170 |
function handleUserMessage(message) {
|
| 171 |
+
const blocks = ws.getAllBlocks();
|
| 172 |
+
const msgBlock = blocks.find(b => b.type === 'user_message');
|
| 173 |
+
if (msgBlock) {
|
| 174 |
+
msgBlock.setFieldValue(message, 'TEXT');
|
| 175 |
+
console.log(`[Blockly] Updated user_message with: ${message}`);
|
| 176 |
}
|
| 177 |
|
| 178 |
if (typeof window.userSendHandler === "function") {
|
|
|
|
| 179 |
window.userSendHandler(message);
|
|
|
|
|
|
|
| 180 |
}
|
| 181 |
+
}
|
{hello-world β project}/src/serialization.js
RENAMED
|
File without changes
|
{hello-world β project}/src/toolbox.js
RENAMED
|
@@ -1,20 +1,14 @@
|
|
| 1 |
-
/**
|
| 2 |
-
* @license
|
| 3 |
-
* Copyright 2023 Google LLC
|
| 4 |
-
* SPDX-License-Identifier: Apache-2.0
|
| 5 |
-
*/
|
| 6 |
-
|
| 7 |
-
/*
|
| 8 |
-
This toolbox contains nearly every single built-in block that Blockly offers,
|
| 9 |
-
in addition to the custom block 'add_text' this sample app adds.
|
| 10 |
-
You probably don't need every single block, and should consider either rewriting
|
| 11 |
-
your toolbox from scratch, or carefully choosing whether you need each block
|
| 12 |
-
listed here.
|
| 13 |
-
*/
|
| 14 |
-
|
| 15 |
export const toolbox = {
|
| 16 |
kind: 'categoryToolbox',
|
| 17 |
contents: [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
{
|
| 19 |
kind: 'category',
|
| 20 |
name: 'Custom',
|
|
@@ -23,6 +17,14 @@ export const toolbox = {
|
|
| 23 |
{
|
| 24 |
kind: 'block',
|
| 25 |
type: 'when_user_sends',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
},
|
| 27 |
{
|
| 28 |
kind: 'block',
|
|
@@ -34,17 +36,16 @@ export const toolbox = {
|
|
| 34 |
inputs: {
|
| 35 |
PROMPT: {
|
| 36 |
shadow: {
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
VAR: {
|
| 40 |
-
name: "user_message",
|
| 41 |
-
type: "String"
|
| 42 |
-
}
|
| 43 |
-
}
|
| 44 |
}
|
| 45 |
},
|
| 46 |
},
|
| 47 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
]
|
| 49 |
},
|
| 50 |
{
|
|
@@ -497,24 +498,6 @@ export const toolbox = {
|
|
| 497 |
kind: 'block',
|
| 498 |
type: 'lists_create_with',
|
| 499 |
},
|
| 500 |
-
{
|
| 501 |
-
kind: 'block',
|
| 502 |
-
type: 'lists_create_with',
|
| 503 |
-
},
|
| 504 |
-
{
|
| 505 |
-
kind: 'block',
|
| 506 |
-
type: 'lists_repeat',
|
| 507 |
-
inputs: {
|
| 508 |
-
NUM: {
|
| 509 |
-
shadow: {
|
| 510 |
-
type: 'math_number',
|
| 511 |
-
fields: {
|
| 512 |
-
NUM: 5,
|
| 513 |
-
},
|
| 514 |
-
},
|
| 515 |
-
},
|
| 516 |
-
},
|
| 517 |
-
},
|
| 518 |
{
|
| 519 |
kind: 'block',
|
| 520 |
type: 'lists_length',
|
|
@@ -567,20 +550,6 @@ export const toolbox = {
|
|
| 567 |
},
|
| 568 |
},
|
| 569 |
},
|
| 570 |
-
{
|
| 571 |
-
kind: 'block',
|
| 572 |
-
type: 'lists_split',
|
| 573 |
-
inputs: {
|
| 574 |
-
DELIM: {
|
| 575 |
-
shadow: {
|
| 576 |
-
type: 'text',
|
| 577 |
-
fields: {
|
| 578 |
-
TEXT: ',',
|
| 579 |
-
},
|
| 580 |
-
},
|
| 581 |
-
},
|
| 582 |
-
},
|
| 583 |
-
},
|
| 584 |
{
|
| 585 |
kind: 'block',
|
| 586 |
type: 'lists_sort',
|
|
@@ -602,7 +571,7 @@ export const toolbox = {
|
|
| 602 |
},
|
| 603 |
{
|
| 604 |
kind: 'category',
|
| 605 |
-
name: '
|
| 606 |
categorystyle: 'procedure_category',
|
| 607 |
custom: 'PROCEDURE',
|
| 608 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
export const toolbox = {
|
| 2 |
kind: 'categoryToolbox',
|
| 3 |
contents: [
|
| 4 |
+
{
|
| 5 |
+
'kind': 'search',
|
| 6 |
+
'name': 'Search',
|
| 7 |
+
'contents': [],
|
| 8 |
+
},
|
| 9 |
+
{
|
| 10 |
+
'kind': 'sep',
|
| 11 |
+
},
|
| 12 |
{
|
| 13 |
kind: 'category',
|
| 14 |
name: 'Custom',
|
|
|
|
| 17 |
{
|
| 18 |
kind: 'block',
|
| 19 |
type: 'when_user_sends',
|
| 20 |
+
inputs: {
|
| 21 |
+
DUPLICATE: {
|
| 22 |
+
block: {
|
| 23 |
+
kind: "block",
|
| 24 |
+
type: "user_message"
|
| 25 |
+
}
|
| 26 |
+
},
|
| 27 |
+
},
|
| 28 |
},
|
| 29 |
{
|
| 30 |
kind: 'block',
|
|
|
|
| 36 |
inputs: {
|
| 37 |
PROMPT: {
|
| 38 |
shadow: {
|
| 39 |
+
kind: "block",
|
| 40 |
+
type: "user_message"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
}
|
| 42 |
},
|
| 43 |
},
|
| 44 |
},
|
| 45 |
+
{
|
| 46 |
+
kind: 'block',
|
| 47 |
+
type: 'user_message',
|
| 48 |
+
},
|
| 49 |
]
|
| 50 |
},
|
| 51 |
{
|
|
|
|
| 498 |
kind: 'block',
|
| 499 |
type: 'lists_create_with',
|
| 500 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 501 |
{
|
| 502 |
kind: 'block',
|
| 503 |
type: 'lists_length',
|
|
|
|
| 550 |
},
|
| 551 |
},
|
| 552 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 553 |
{
|
| 554 |
kind: 'block',
|
| 555 |
type: 'lists_sort',
|
|
|
|
| 571 |
},
|
| 572 |
{
|
| 573 |
kind: 'category',
|
| 574 |
+
name: 'Tools',
|
| 575 |
categorystyle: 'procedure_category',
|
| 576 |
custom: 'PROCEDURE',
|
| 577 |
},
|
{hello-world β project}/webpack.config.js
RENAMED
|
File without changes
|