-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🧱 NoneBlockly basic framework implementation (#1)
- Loading branch information
Showing
48 changed files
with
4,705 additions
and
3,830 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
|
||
<title>NoneBlockly for NoneBot2</title> | ||
</head> | ||
|
||
<body> | ||
<div id="app"></div> | ||
<script type="module" src="./src/main.ts"></script> | ||
</body> | ||
</html> | ||
|
||
<style lang="scss"> | ||
html { | ||
font-family: "Inter", sans-serif; | ||
line-height: 1.2; | ||
font-size: 1.1rem; | ||
overflow-x: hidden; | ||
text-rendering: optimizeLegibility; | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); | ||
overflow-y: auto; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,37 @@ | ||
{ | ||
"name": "@noneblockly/app", | ||
"version": "0.0.0", | ||
"main": "index.js", | ||
"version": "0.1.0", | ||
"main": "main.ts", | ||
"private": true, | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"build": "webpack --mode production", | ||
"start": "webpack serve --open --mode development" | ||
"dev": "vite", | ||
"build": "vite build", | ||
"preview": "vite preview" | ||
}, | ||
"keywords": [ | ||
"blockly" | ||
], | ||
"author": "", | ||
"license": "Apache-2.0", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"css-loader": "^6.11.0", | ||
"html-webpack-plugin": "^5.6.0", | ||
"source-map-loader": "^4.0.2", | ||
"style-loader": "^3.3.4", | ||
"ts-loader": "^9.5.1", | ||
"typescript": "^5.4.4", | ||
"webpack": "^5.91.0", | ||
"webpack-cli": "^4.10.0", | ||
"webpack-dev-server": "^4.15.2" | ||
"@blockly/theme-dark": "^7.0.1", | ||
"@highlightjs/vue-plugin": "^2.1.0", | ||
"@mdi/js": "^7.4.47", | ||
"@types/file-saver": "^2.0.7", | ||
"@vitejs/plugin-vue": "^5.0.5", | ||
"typescript": "^5.5.2", | ||
"vite": "^5.3.1", | ||
"vite-plugin-static-copy": "^1.0.5", | ||
"vite-plugin-vuetify": "^2.0.3", | ||
"vue-tsc": "^2.0.21" | ||
}, | ||
"dependencies": { | ||
"blockly": "^10.4.3" | ||
"blockly": "^11.1.1", | ||
"file-saver": "^2.0.5", | ||
"highlight.js": "^11.9.0", | ||
"jszip": "^3.10.1", | ||
"sass": "^1.77.6", | ||
"vue": "^3.4.29", | ||
"vuetify": "^3.6.10" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<script setup lang="ts"> | ||
import { onMounted, shallowRef } from "vue"; | ||
// Components | ||
import ContentCard from "@/components/ContentCard.vue"; | ||
import BlocklyTab from "@/components/BlocklyTab.vue"; | ||
import TutorialTab from "@/components/TutorialTab.vue"; | ||
import CodeTab from "@/components/CodeTab.vue"; | ||
import ConfigTab from "@/components/ConfigTab.vue"; | ||
import ButtonPanel from "@/components/ButtonPanel.vue"; | ||
// Workspace | ||
import { loadJson, generateCode } from "@/workspace"; | ||
import { optionsStore, workspaceStore } from "@/workspace"; | ||
// Workspace data | ||
import { startBlocks } from "@/default"; | ||
// Blockly config | ||
import * as Blockly from "blockly"; | ||
import { blocks } from "@/blocks"; | ||
import { toolbox } from "@/toolbox"; | ||
import { generators } from "@/generators"; | ||
import { pythonGenerator } from "blockly/python"; | ||
import * as ZhHans from "blockly/msg/zh-hans"; | ||
Blockly.common.defineBlocks(blocks); | ||
generators.forEach((generator) => { | ||
Object.assign(pythonGenerator.forBlock, generator); | ||
}); | ||
pythonGenerator.addReservedWords( | ||
"json,Annotated,Matcher,Message,EventMessage,CommandArg,on_command,on_message,on_alconna,to_me", | ||
); | ||
Blockly.setLocale(ZhHans); | ||
// Set store data | ||
optionsStore.toolbox = toolbox; | ||
workspaceStore.startBlocks = startBlocks; | ||
const workspace = Blockly.getMainWorkspace(); | ||
workspaceStore.workspace = workspace; | ||
onMounted(() => { | ||
loadJson(); | ||
const workspace = Blockly.getMainWorkspace(); | ||
workspace.addChangeListener(generateCode); | ||
}); | ||
</script> | ||
|
||
<template> | ||
<v-app> | ||
<v-card class="rounded-0"> | ||
<div class="pa-0 ma-0"> | ||
<ContentCard> | ||
<template v-slot:tab-0> | ||
<BlocklyTab | ||
id="blockly-div" | ||
:options="optionsStore" | ||
ref="workspace" | ||
/> | ||
</template> | ||
<template v-slot:tab-1> | ||
<TutorialTab /> | ||
</template> | ||
<template v-slot:tab-2> | ||
<CodeTab /> | ||
</template> | ||
<template v-slot:tab-3> | ||
<ConfigTab /> | ||
</template> | ||
</ContentCard> | ||
<ButtonPanel /> | ||
</div> | ||
</v-card> | ||
</v-app> | ||
</template> | ||
|
||
<style lang="scss" scoped> | ||
@import url("https://fonts.googleapis.com/css?family=Open+Sans"); | ||
@import url("https://fonts.googleapis.com/css?family=Inter"); | ||
</style> | ||
|
||
<script lang="ts"> | ||
import hljs from "highlight.js/lib/core"; | ||
import python from "highlight.js/lib/languages/python"; | ||
hljs.registerLanguage("python", python); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import * as Blockly from "blockly/core"; | ||
|
||
export function getAlconnaArg(block: Blockly.Block): string[] { | ||
let args: string[] = []; | ||
// get top block | ||
let parent = block.getParent(); | ||
if (parent == null) { | ||
return []; | ||
} | ||
while (parent.type != "nonebot_on_alconna") { | ||
parent = parent.getParent(); | ||
if (parent == null) { | ||
return []; | ||
} | ||
} | ||
// get all arg blocks of alconna top block | ||
for (let n = 0; n < (parent as any).itemCount_; n++) { | ||
const arg_block = parent | ||
.getInput("ARG" + String(n)) | ||
?.connection?.targetConnection?.getSourceBlock(); | ||
const arg_type = arg_block?.type; | ||
if (arg_type === "alconna_arg") { | ||
const arg_name = arg_block?.getFieldValue("NAME"); | ||
if (arg_name) { | ||
args.push(arg_name); | ||
} | ||
} | ||
} | ||
return args; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/** | ||
* @fileoverview A function that creates a minus button used for mutation. | ||
*/ | ||
|
||
import * as Blockly from "blockly/core"; | ||
import { getExtraBlockState } from "./serialization_helper"; | ||
|
||
/** | ||
* Creates a minus image field used for mutation. | ||
* @param {Object=} args Untyped args passed to block.minus when the field | ||
* is clicked. | ||
* @returns {Blockly.FieldImage} The minus field. | ||
*/ | ||
export function createMinusField(args?: Object): Blockly.FieldImage { | ||
const minus = new Blockly.FieldImage(minusImage, 15, 15, undefined, onClick_); | ||
/** | ||
* Untyped args passed to block.minus when the field is clicked. | ||
* @type {?(Object|undefined)} | ||
* @private | ||
*/ | ||
(minus as any).args_ = args; | ||
return minus; | ||
} | ||
|
||
/** | ||
* Calls block.minus(args) when the minus field is clicked. | ||
* @param {Blockly.FieldImage} minusField The field being clicked. | ||
* @private | ||
*/ | ||
function onClick_(minusField: Blockly.FieldImage) { | ||
// TODO: This is a dupe of the mutator code, anyway to unify? | ||
const block = minusField.getSourceBlock() as Blockly.BlockSvg; | ||
|
||
if (block.isInFlyout) { | ||
return; | ||
} | ||
|
||
Blockly.Events.setGroup(true); | ||
const oldExtraState = getExtraBlockState(block); | ||
(block as any).minus((minusField as any).args_); | ||
const newExtraState = getExtraBlockState(block); | ||
|
||
if (oldExtraState != newExtraState) { | ||
Blockly.Events.fire( | ||
new Blockly.Events.BlockChange( | ||
block, | ||
"mutation", | ||
null, | ||
oldExtraState, | ||
newExtraState, | ||
), | ||
); | ||
} | ||
Blockly.Events.setGroup(false); | ||
} | ||
|
||
const minusImage = | ||
"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAw" + | ||
"MC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48cGF0aCBkPS" + | ||
"JNMTggMTFoLTEyYy0xLjEwNCAwLTIgLjg5Ni0yIDJzLjg5NiAyIDIgMmgxMmMxLjEwNCAw" + | ||
"IDItLjg5NiAyLTJzLS44OTYtMi0yLTJ6IiBmaWxsPSJ3aGl0ZSIgLz48L3N2Zz4K"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/** | ||
* @fileoverview A field for a plus button used for mutation. | ||
*/ | ||
|
||
import * as Blockly from "blockly/core"; | ||
import { getExtraBlockState } from "./serialization_helper"; | ||
|
||
/** | ||
* Creates a plus image field used for mutation. | ||
* @param {Object=} args Untyped args passed to block.minus when the field | ||
* is clicked. | ||
* @returns {Blockly.FieldImage} The Plus field. | ||
*/ | ||
export function createPlusField(args?: Object): Blockly.FieldImage { | ||
const plus = new Blockly.FieldImage(plusImage, 15, 15, undefined, onClick_); | ||
/** | ||
* Untyped args passed to block.plus when the field is clicked. | ||
* @type {?(Object|undefined)} | ||
* @private | ||
*/ | ||
(plus as any).args_ = args; | ||
return plus; | ||
} | ||
|
||
/** | ||
* Calls block.plus(args) when the plus field is clicked. | ||
* @param {!Blockly.FieldImage} plusField The field being clicked. | ||
* @private | ||
*/ | ||
function onClick_(plusField: Blockly.FieldImage) { | ||
// TODO: This is a dupe of the mutator code, anyway to unify? | ||
const block = plusField.getSourceBlock() as Blockly.BlockSvg; | ||
|
||
if (block.isInFlyout) { | ||
return; | ||
} | ||
|
||
Blockly.Events.setGroup(true); | ||
const oldExtraState = getExtraBlockState(block); | ||
(block as any).plus((plusField as any).args_); | ||
const newExtraState = getExtraBlockState(block); | ||
|
||
if (oldExtraState != newExtraState) { | ||
Blockly.Events.fire( | ||
new Blockly.Events.BlockChange( | ||
block, | ||
"mutation", | ||
null, | ||
oldExtraState, | ||
newExtraState, | ||
), | ||
); | ||
} | ||
Blockly.Events.setGroup(false); | ||
} | ||
|
||
const plusImage = | ||
"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC" + | ||
"9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48cGF0aCBkPSJNMT" + | ||
"ggMTBoLTR2LTRjMC0xLjEwNC0uODk2LTItMi0ycy0yIC44OTYtMiAybC4wNzEgNGgtNC4wNz" + | ||
"FjLTEuMTA0IDAtMiAuODk2LTIgMnMuODk2IDIgMiAybDQuMDcxLS4wNzEtLjA3MSA0LjA3MW" + | ||
"MwIDEuMTA0Ljg5NiAyIDIgMnMyLS44OTYgMi0ydi00LjA3MWw0IC4wNzFjMS4xMDQgMCAyLS" + | ||
"44OTYgMi0ycy0uODk2LTItMi0yeiIgZmlsbD0id2hpdGUiIC8+PC9zdmc+Cg=="; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* @license | ||
* Copyright 2022 Google LLC | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import * as Blockly from "blockly/core"; | ||
|
||
/** | ||
* Returns the extra state of the given block (either as XML or a JSO, depending | ||
* on the block's definition). | ||
* @param {!Blockly.BlockSvg} block The block to get the extra state of. | ||
* @returns {string} A stringified version of the extra state of the given | ||
* block. | ||
*/ | ||
export function getExtraBlockState(block: Blockly.BlockSvg): string { | ||
// TODO: This is a dupe of the BlockChange.getExtraBlockState code, do we | ||
// want to make that public? | ||
if (block.saveExtraState) { | ||
const state = block.saveExtraState(); | ||
return state ? JSON.stringify(state) : ""; | ||
} else if (block.mutationToDom) { | ||
const state = block.mutationToDom(); | ||
return state ? Blockly.Xml.domToText(state) : ""; | ||
} | ||
return ""; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import * as Blockly from "blockly/core"; | ||
import { BlockDefinition } from "blockly/core/blocks"; | ||
|
||
import { pythonDict } from "./python_dict"; | ||
import { definitions as nonebotBasic } from "./nonebot_basic"; | ||
import { definitions as nonebotAlconna } from "./nonebot_alconna"; | ||
import { definitions as nonebotStore } from "./nonebot_store"; | ||
import { definitions as nonebotScheduler } from "./nonebot_scheduler"; | ||
import { definitions as nonebotRequest } from "./nonebot_request"; | ||
|
||
// Array of all block definitions | ||
let blockDefinitions: BlockDefinition[] = []; | ||
blockDefinitions = blockDefinitions | ||
.concat(pythonDict) | ||
.concat(nonebotBasic) | ||
.concat(nonebotAlconna) | ||
.concat(nonebotStore) | ||
.concat(nonebotScheduler) | ||
.concat(nonebotRequest); | ||
|
||
export const blocks = | ||
Blockly.common.createBlockDefinitionsFromJsonArray(blockDefinitions); |
Oops, something went wrong.