Skip to content

Commit

Permalink
loader system and fix the bug of too much chunk file
Browse files Browse the repository at this point in the history
  • Loading branch information
fs-context committed Dec 21, 2024
1 parent c828f80 commit 64ff88c
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 84 deletions.
113 changes: 44 additions & 69 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,45 @@
import * as exceptions from "@framework/exceptions";
import { AnyArg, ColorDefine } from "@framework/internal";
import { Block, BlockType, Collaborator, Extension, Menu, Translator, Version } from "@framework/structs";
import { ColorDefine, InputLoader } from "@framework/internal";
import { Block, Collaborator, Extension, Menu, Translator, Version } from "@framework/structs";
import { GlobalContext, Unnecessary } from "@framework/tools";
import { html, json, vector2, vector3 } from "@framework/built-ins/loaders";
const translator = Translator.create("zh-cn", {
name: "我的拓展",
des: "这是我的第一个拓展",
alert: "向窗口中弹窗$sth,后缀为_suffix",
eat: "吃掉水果,$fruit",
eatenTip: "你吃了一个"
des: "这是我的第一个拓展"
});
translator.store("en", {
name: "My Extension",
des: "This is my first extension",
alert: "alert $sth to window with suffix _suffix",
eat: "eat fruit,$fruit",
eatenTip: "You ate a(n)"
des: "This is my first extension"
});
export default class MyExtension extends Extension {
__Unimportant = 0;
loaders: Record<string, InputLoader> = { vector2, json, html, vector3 };
blocks: Block<MyExtension>[] = [
Block.create("TestBlock $vec2 $vec3 $json $html", {
arguments: [
{
name: "$vec2",
inputType: "vector2"
},
{
name: "$vec3",
inputType: "vector3"
},
{
name: "$json",
inputType: "json"
},
{
name: "$html",
inputType: "html"
}
]
}, function (args) {
console.log(args);
})
];
id = "myextension";
displayName = translator.load("name");
version = new Version(1, 0, 0);
blocks: Block<MyExtension>[] = [
Block.create(
translator.load("alert"),
{
arguments: [
{
name: "$sth",
value: "Hello World",
inputType: "string"
},
{
name: "_suffix",
value: new Menu("suffixes", [
{ name: "已打印", value: "printed" },
{ name: "已输出", value: "output" },
{ name: "已显示", value: "displayed" }
]),
inputType: "menu"
}
],
},
function alertSth(args) {
alert(args.$sth + " " + args._suffix);
dataStore.write("alertedSth", args.$sth.toString());
dataStore.write("lastSuffix", args._suffix.toString());
}
),
Block.create(
translator.load("eat"),
{
arguments: [
{
name: "$fruit",
value: "fruits",
inputType: "menu"
}
]
},
function eat(args) {
dataStore.write("fruitsEaten", args.$fruit.toString());
alert(`${translator.load("eatenTip")} ${args.$fruit}`);
}
)
];
menus = [
new Menu("fruits", [
{ name: "苹果", value: "apple" },
Expand Down Expand Up @@ -92,20 +67,20 @@ export default class MyExtension extends Extension {
theme: "#ff0000"
};
autoDeriveColors = true;
@BlockType.Command("alert[sth:string=hello]with suffix[suffix:menu=suffixes]")
alertTest(args: AnyArg) {
alert(args.sth + " " + args.suffix);
dataStore.write("alertedSth", args.sth.toString());
dataStore.write("lastSuffix", args.suffix.toString());
};
@BlockType.Reporter("getAlertedSth")
getAlertedSth() {
return dataStore.read("alertedSth");
};
@BlockType.Reporter("getLastSuffix")
getLastSuffix() {
return dataStore.read("lastSuffix");
};
// @BlockType.Command("alert[sth:string=hello]with suffix[suffix:menu=suffixes]")
// alertTest(args: AnyArg) {
// alert(args.sth + " " + args.suffix);
// dataStore.write("alertedSth", args.sth.toString());
// dataStore.write("lastSuffix", args.suffix.toString());
// };
// @BlockType.Reporter("getAlertedSth")
// getAlertedSth() {
// return dataStore.read("alertedSth");
// };
// @BlockType.Reporter("getLastSuffix")
// getLastSuffix() {
// return dataStore.read("lastSuffix");
// };
};
const dataStore = GlobalContext.createDataStore(MyExtension, {
alertedSth: [] as string[],
Expand Down
40 changes: 40 additions & 0 deletions src/fs-context/built-ins/loaders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { InputLoader } from "@framework/internal";
export const vector2: InputLoader = {
load(src) {
let splited = src.split(" ");
if (splited.length < 2) splited.push("");
let x = Number(splited[0]);
if (Number.isNaN(x)) { x = 0; };
let y = Number(splited[1]);
if (Number.isNaN(y)) { y = 0; };
return { x, y };
},
format: /(.*?) (.*?)/
};
export const vector3: InputLoader = {
load(src) {
let splited = src.split(" ");
if (splited.length < 3) splited.push("", "");
let x = Number(splited[0]);
if (Number.isNaN(x)) { x = 0; };
let y = Number(splited[1]);
if (Number.isNaN(y)) { y = 0; };
let z = Number(splited[2]);
if (Number.isNaN(z)) { z = 0; };
return { x, y, z };
},
format: /(.*?) (.*?) (.*?)/
};
export const json: InputLoader = {
load(src) {
return JSON.parse(src);
},
format: /\[(.*)\]|\{(.*)\}|"(.*)"/
};
export const html: InputLoader = {
load(src) {
let parser = new DOMParser();
return parser.parseFromString(src, "text/html");
},
format: /\<(.*)\>/
};
60 changes: 55 additions & 5 deletions src/fs-context/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import { ExtensionLoadError, UncognizedError } from "./exceptions";
import { ArgumentPlain, BlockPlain, ExtensionPlain, GlobalResourceMachine, HexColorString, LoaderConfig, MenuPlain, ObjectInclude, PlatformSupported, Scratch, ScratchWaterBoxed } from "./internal";
import { CastError, ExtensionLoadError, MissingError, UncognizedError } from "./exceptions";
import type {
ArgumentPlain,
BlockPlain,
ExtensionPlain,
GlobalResourceMachine,
HexColorString,
LoaderConfig,
MenuPlain,
ObjectInclude,
PlatformSupported,
Scratch,
ScratchWaterBoxed
} from "./internal";
import { AcceptedInputType } from "./internal";
import type { Extension } from "./structs";
import loaderConfig from "@config/loader";
import type { Extension } from "./structs";
if (!window._FSContext) {
Expand Down Expand Up @@ -52,6 +66,11 @@ export namespace Extensions {
const currentArg: ArgumentPlain = {
type: Unnecessary.castInputType(arg.inputType),
};
if (!AcceptedInputType.includes(arg.inputType)) {
if (Object.keys(ext.loaders).includes(arg.inputType)) {
currentArg.type = "string";
};
};
if (arg.inputType === "menu") {
currentArg.menu = arg.value as string;
} else {
Expand Down Expand Up @@ -89,9 +108,40 @@ export namespace Extensions {
}
};
ext.blocks.forEach(block => {
result[block.opcode] = Unnecessary.isAsyncFunction(block.method)
? async (arg: ObjectInclude) => JSON.stringify(await block.method.call(ext, arg))
: (arg: ObjectInclude) => JSON.stringify(block.method.call(ext, arg));
function _processArg(arg: Record<string, any>) {
argList.forEach(e => {
if (e && e.loader) {
if (!e.loader.format?.test(arg[e.name])) {
console.error(`Invalid arg input: ${arg[e.name]}`);
};
arg[e.name] = e.loader.load(arg[e.name]);
};
});
};
const argList = block.arguments.map(arg => {
return AcceptedInputType.includes(arg.inputType)
? undefined
: {
name: arg.content,
loader: Object.keys(ext.loaders).includes(arg.inputType) ? ext.loaders[arg.inputType] : undefined
};
}).filter(Boolean);
argList.forEach(arg => {
if (arg && !arg.loader) {
throw new MissingError(`Cannot find valid arg loader: ${arg.name}`);
};
});
if (Unnecessary.isAsyncFunction(block.method)) {
result[block.opcode] = async (arg: ObjectInclude) => {
_processArg(arg);
JSON.stringify(await block.method.call(ext, arg))
};
} else {
result[block.opcode] = (arg: ObjectInclude) => {
_processArg(arg);
JSON.stringify(block.method.call(ext, arg))
};
};
});
return result;
};
Expand Down
8 changes: 6 additions & 2 deletions src/fs-context/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class ArgumentPart {
export interface ArgumentDefine<T extends ValidArgumentName = ValidArgumentName> {
name: T;
value?: AcceptedArgType;
inputType?: InputType;
inputType?: InputType | string;
}
export type ValidArgumentName = `${"$" | "_"}${string}`;
export type MethodFunction<T> = (this: Extension, args: T) => any;
Expand Down Expand Up @@ -179,7 +179,7 @@ export type ExtensionPlain = {
getInfo: () => ExtensionInfo;
} & {
[key: string]: MethodFunction<any>;
};
}
export interface ExtensionInfo {
id: string;
name: string;
Expand All @@ -188,4 +188,8 @@ export interface ExtensionInfo {
color1: HexColorString;
color2: HexColorString;
color3: HexColorString;
}
export interface InputLoader {
format?: RegExp;
load: (data: string) => any;
}
1 change: 0 additions & 1 deletion src/fs-context/samples/fs-iframe/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export default class FSIFrame extends Extension {
dataStore.read("rootBase").child(iframe);
dataStore.write("iframes", iframe);
setInterval(() => {
console.log(this);
if (this.canvas) {
iframe
.style("width", `${this.canvas.clientWidth * iframe.data("ratio-x")}px`)
Expand Down
18 changes: 11 additions & 7 deletions src/fs-context/structs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Extensions } from ".";
import {
import type {
ArgumentDefine,
ArgumentPart,
BlockTypePlain,
ColorDefine,
MenuItem,
Expand All @@ -14,8 +13,12 @@ import {
ObjectInclude,
VersionString,
BlockConfigA,
MenuDefine
MenuDefine,
InputLoader,
InputType
} from "./internal";
import { ArgumentPart } from "./internal";
import md5 from "md5";
import { MenuParser, TextParser, Unnecessary } from "./tools";
import { MissingError, OnlyInstanceWarn } from "./exceptions";
export class Extension {
Expand All @@ -24,7 +27,7 @@ export class Extension {
version: Version = new Version("1.0.0");
allowSandboxed: boolean = true;
requires: ObjectInclude<Version> = {};
blocks: Block<this & any>[] = [];
blocks: Block<any>[] = [];
menus: Menu[] = [];
description: string = "An example extension";
collaborators: Collaborator[] = [];
Expand All @@ -34,6 +37,7 @@ export class Extension {
};
runtime?: Scratch;
canvas?: HTMLCanvasElement;
loaders: ObjectInclude<InputLoader> = {};
private static instance?: Extension;
static get onlyInstance(): Extension {
if (!this.instance) {
Expand Down Expand Up @@ -95,8 +99,8 @@ export class Block<O extends Extension = Extension> {
const messages = Unnecessary.splitTextPart(text, _arguments.map(i => i.name));
const args = Unnecessary.splitArgBoxPart(text, _arguments.map(i => i.name));
for (let i = 0; i < messages.length; i++) {
textLoaded.push(messages[i].replaceAll("[", "[").replaceAll("]", "]"));
const current = _arguments.find(e => e.name === args[i]) as ArgumentDefine;
textLoaded.push(messages[i].replaceAll("[", "\\[").replaceAll("]", "\\]"));
const current = _arguments.find(e => e.name === args[i]);
if (current) {
textLoaded.push(current);
};
Expand All @@ -118,7 +122,7 @@ export class Block<O extends Extension = Extension> {
currentArgument.name,
"input",
currentArgument.value,
currentArgument.inputType
currentArgument.inputType as InputType
);
}
this.arguments.push(currentPart);
Expand Down

0 comments on commit 64ff88c

Please sign in to comment.