This commit is contained in:
Asaki Yuki 2026-02-23 15:58:03 +07:00
parent 41d402625b
commit af3c42f7e8
10 changed files with 170 additions and 75 deletions

4
config.d.ts vendored
View file

@ -16,6 +16,10 @@ export interface Config {
buildFolder?: string
fileExtension?: string
uiBuildFolder?: string
obfuscateStringName?: boolean
allowRandomStringName?: boolean
namespaceCount?: number
forceRandomStringLength?: number
}
ui_analyzer?: {

View file

@ -13,6 +13,9 @@ export const config = {
autoImport: true,
autoEnable: true,
importToPreview: false,
obfuscateStringName: true,
allowRandomStringName: true,
forceRandomStringLength: 16,
},
binding_functions: {
custom_abs: function (number) {

View file

@ -58,12 +58,17 @@ if (!fs.existsSync("asajs.config.js")) {
}
export const config: Config = createRequire(import.meta.url)(path.resolve(process.cwd(), "asajs.config.js")).config
export const debugMode = options["debug"] ?? false
export const isBuildMode = options["build"] ?? config.compiler?.enabled ?? false
export const isLinkMode = options["link"] ?? config.compiler?.autoImport ?? false
export const unLinked = options["unlink"] ?? !(config.compiler?.autoImport ?? true)
export const buildFolder = config.compiler?.buildFolder || "build"
export const uiBuildFolder = config.compiler?.uiBuildFolder || "asajs"
export const isNotObfuscate = debugMode || !(config.compiler?.obfuscateStringName ?? false)
export const allowRandomStringName = !debugMode || (config.compiler?.allowRandomStringName ?? true)
export const namespaceCount = debugMode ? 5 : (config.compiler?.namespaceCount ?? 15)
export const forceRandomStringLength = debugMode ? 10 : config.compiler?.forceRandomStringLength
export const bindingFuntions = config.binding_functions

View file

@ -1,7 +0,0 @@
import { RandomString } from "../components/Utils.js"
const namespaces = Array.from({ length: 15 }, () => RandomString(16))
export function RandomNamespace() {
return namespaces[Math.floor(Math.random() * namespaces.length)]
}

View file

@ -1,4 +1,4 @@
import { RandomBindingString, RandomString, ResolveBinding } from "../../components/Utils.js"
import { bs, RandomBindingString, RandomString, ResolveBinding } from "../../components/Utils.js"
import { BindingItem } from "../../types/properties/value.js"
import { bindingFuntions } from "../Configuration.js"
import { isBinding, isNumber, isString } from "./Checker.js"
@ -6,6 +6,7 @@ import { Expression, GenBinding } from "./types.js"
type CallbackRet = {
genBindings?: GenBinding[]
doNotAddParentesis?: boolean
value: Expression
}
type Callback = (...args: Expression[]) => CallbackRet
@ -239,6 +240,14 @@ export const defaultFunctions = {
}
},
bs: input_binding => {
if (!isBinding(input_binding)) throw new Error("Invalid input binding")
return {
doNotAddParentesis: true,
value: bs(<`#${string}`>input_binding),
}
},
/**
* Return a translatable string
* @param key

View file

@ -407,9 +407,9 @@ export class Parser {
if (!func) {
return this.expect(TokenKind.WORD, "Function not found!")!
} else {
const { genBindings, value } = func(...params)
const { genBindings, value, doNotAddParentesis } = func(...params)
if (genBindings) this.genBindings.push(...genBindings)
return `(${value})`
return doNotAddParentesis ? value : `(${value})`
}
}

View file

@ -4,8 +4,7 @@ import { AnimType } from "../types/enums/AnimType.js"
import { KeyframeAnimationProperties } from "../types/properties/element/Animation.js"
import { Animation } from "./Animation.js"
import { Class } from "./Class.js"
import { RandomString } from "./Utils.js"
import { RandomNamespace } from "../compilers/Random.js"
import { RandomNamespace, RandomString } from "./Utils.js"
import util from "node:util"

View file

@ -10,12 +10,11 @@ import { BindingItem, ButtonMapping, ModificationItem, VariableItem, Variables }
import { Animation } from "./Animation.js"
import { AnimationKeyframe } from "./AnimationKeyframe.js"
import { Class } from "./Class.js"
import { RandomString, ResolveBinding } from "./Utils.js"
import { RandomNamespace } from "../compilers/Random.js"
import { defaultNamespace, RandomNamespace, RandomString, ResolveBinding } from "./Utils.js"
import nodepath from "path"
import util from "node:util"
import { config, uiBuildFolder } from "../compilers/Configuration.js"
import { config, isNotObfuscate, uiBuildFolder } from "../compilers/Configuration.js"
interface ExtendUI {
name: string
@ -52,6 +51,7 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
name?: string,
namespace?: string,
path?: string,
allowObfuscate?: boolean,
) {
super()
@ -60,8 +60,13 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
process.exit(1)
}
if (isNotObfuscate || !(allowObfuscate ?? true)) {
this.name = name?.match(/^(\w|\/)+/)?.[0] || RandomString(16)
this.namespace = namespace || RandomNamespace()
this.namespace = namespace || defaultNamespace || RandomNamespace()
} else {
this.name = RandomString(16)
this.namespace = RandomNamespace()
}
if (!path) this.path = nodepath.join(uiBuildFolder, `${this.namespace}${fileExt}`)
else this.path = path
@ -204,7 +209,7 @@ export class ModifyUI<T extends Type = Type.PANEL, S extends string = string> ex
protected modifications: ModificationItem[] = []
constructor(namespace: string, name: string, path: string) {
super(undefined, name, namespace, path)
super(undefined, name, namespace, path, false)
}
/**

View file

@ -40,6 +40,12 @@ import { SmartAnimation } from "../types/enums/SmartAnimation.js"
import { MemoryModify } from "../compilers/Memory.js"
import { Lexer } from "../compilers/bindings/Lexer.js"
import { Token, TokenKind, TSToken, TSTokenKind } from "../compilers/bindings/types.js"
import {
allowRandomStringName,
forceRandomStringLength,
isNotObfuscate,
namespaceCount,
} from "../compilers/Configuration.js"
type CompileBinding = `[${string}]`
@ -145,9 +151,18 @@ export function ResolveBinding(cache: Map<string, unknown>, ...bindings: Binding
return result
}
export function RandomString(length: number, base: number = 32) {
export let defaultNamespace: string | null = null
export function SetDefaultNamespace(input: string) {
defaultNamespace = input
}
export function ClearDefaultNamespace() {
defaultNamespace = null
}
export function GenRandomString(length: number, base = 32) {
const chars = "0123456789abcdefghijklmnopqrstuvwxyz".slice(0, base)
const out = new Array<string>(length)
if (forceRandomStringLength) length = forceRandomStringLength
try {
const buffer = new Uint8Array(length)
@ -164,8 +179,53 @@ export function RandomString(length: number, base: number = 32) {
return out.join("")
}
export function RandomBindingString(length: number = 16, base: number = 32): Binding {
return `#${RandomString(length, base)}`
const StringID = GenRandomString(5, undefined)
const nspl = allowRandomStringName
? Array.from({ length: namespaceCount }, () => RandomString(16))
: (() => {
return Array.from({ length: namespaceCount }, (i, index) => `${StringID}_namespace_${index + 1}`)
})()
export function RandomNamespace() {
return nspl[Math.floor(Math.random() * nspl.length)]
}
let rndStr = 1
export function RandomString(length: number, base: number = 32, force?: boolean) {
if (force || allowRandomStringName) return GenRandomString(length, base)
else return `${StringID}_string_${rndStr++}`
}
let rndStrBind = 1
export function RandomBindingString(length: number = 16, base: number = 32, force?: boolean): Binding {
if (force || allowRandomStringName) return `#${GenRandomString(length, base)}`
else return `#${StringID}_binding_${rndStrBind++}`
}
const rndMap = new Map<string, string>()
export function s(input: string) {
if (isNotObfuscate) return input
else {
if (rndMap.has(input)) return rndMap.get(input) as string
else {
const ret = RandomBindingString()
rndMap.set(input, ret)
return ret
}
}
}
export function bs(input: `#${string}`): `#${string}` {
if (isNotObfuscate) return input
else {
if (rndMap.has(input)) return rndMap.get(input) as `#${string}`
else {
const ret = RandomBindingString()
rndMap.set(input, ret)
return ret
}
}
}
export function GetItemByAuxID(auxID: number) {
@ -224,36 +284,41 @@ export function Modify<T extends Namespace, K extends Element<T>>(namespace: T,
return modifyUI
}
export function Panel(properties?: Panel, namespace?: string, name?: string) {
return new UI(Type.PANEL, name, namespace).setProperties(properties || {})
export function Panel(properties?: Panel, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.PANEL, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function CollectionPanel(properties?: CollectionPanel, namespace?: string, name?: string) {
return new UI(Type.COLLECTION_PANEL, name, namespace).setProperties(properties || {})
export function CollectionPanel(
properties?: CollectionPanel,
namespace?: string,
name?: string,
allowObfuscate?: boolean,
) {
return new UI(Type.COLLECTION_PANEL, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function StackPanel(properties?: StackPanel, namespace?: string, name?: string) {
return new UI(Type.STACK_PANEL, name, namespace).setProperties(properties || {})
export function StackPanel(properties?: StackPanel, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.STACK_PANEL, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function InputPanel(properties?: InputPanel, namespace?: string, name?: string) {
return new UI(Type.INPUT_PANEL, name, namespace).setProperties(properties || {})
export function InputPanel(properties?: InputPanel, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.INPUT_PANEL, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function Gird(properties?: Grid, namespace?: string, name?: string) {
return new UI(Type.GRID, name, namespace).setProperties(properties || {})
export function Gird(properties?: Grid, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.GRID, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function Screen(properties?: Screen, namespace?: string, name?: string) {
return new UI(Type.SCREEN, name, namespace).setProperties(properties || {})
export function Screen(properties?: Screen, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.SCREEN, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function Image(properties?: Image, namespace?: string, name?: string) {
return new UI(Type.IMAGE, name, namespace).setProperties(properties || {})
export function Image(properties?: Image, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.IMAGE, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function Label(properties?: Label, namespace?: string, name?: string) {
return new UI(Type.LABEL, name, namespace).setProperties(properties || {})
export function Label(properties?: Label, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.LABEL, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function Custom<R extends Renderer>(
@ -261,54 +326,70 @@ export function Custom<R extends Renderer>(
properties?: Properties<Type.CUSTOM, R>,
namespace?: string,
name?: string,
allowObfuscate?: boolean,
) {
const custom = new UI<Type.CUSTOM, R>(Type.CUSTOM, name, namespace)
const custom = new UI<Type.CUSTOM, R>(Type.CUSTOM, name, namespace, undefined, allowObfuscate)
if (properties) custom.setProperties({ renderer, ...properties })
return custom
}
export function TooltipTrigger(properties?: TooltipTrigger, namespace?: string, name?: string) {
return new UI(Type.TOOLTIP_TRIGGER, name, namespace).setProperties(properties || {})
export function TooltipTrigger(
properties?: TooltipTrigger,
namespace?: string,
name?: string,
allowObfuscate?: boolean,
) {
return new UI(Type.TOOLTIP_TRIGGER, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function Button(properties?: Button, namespace?: string, name?: string) {
return new UI(Type.BUTTON, name, namespace).setProperties(properties || {})
export function Button(properties?: Button, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.BUTTON, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function Toggle(properties?: Toggle, namespace?: string, name?: string) {
return new UI(Type.TOGGLE, name, namespace).setProperties(properties || {})
export function Toggle(properties?: Toggle, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.TOGGLE, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function Dropdown(properties?: Dropdown, namespace?: string, name?: string) {
return new UI(Type.DROPDOWN, name, namespace).setProperties(properties || {})
export function Dropdown(properties?: Dropdown, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.DROPDOWN, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function SelectionWheel(properties?: SelectionWheel, namespace?: string, name?: string) {
return new UI(Type.SELECTION_WHEEL, name, namespace).setProperties(properties || {})
export function SelectionWheel(
properties?: SelectionWheel,
namespace?: string,
name?: string,
allowObfuscate?: boolean,
) {
return new UI(Type.SELECTION_WHEEL, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function EditBox(properties?: EditBox, namespace?: string, name?: string) {
return new UI(Type.EDIT_BOX, name, namespace).setProperties(properties || {})
export function EditBox(properties?: EditBox, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.EDIT_BOX, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function ScrollbarBox(properties?: ScrollbarBox, namespace?: string, name?: string) {
return new UI(Type.SCROLLBAR_BOX, name, namespace).setProperties(properties || {})
export function ScrollbarBox(properties?: ScrollbarBox, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.SCROLLBAR_BOX, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function ScrollbarTrack(properties?: ScrollbarTrack, namespace?: string, name?: string) {
return new UI(Type.SCROLL_TRACK, name, namespace).setProperties(properties || {})
export function ScrollbarTrack(
properties?: ScrollbarTrack,
namespace?: string,
name?: string,
allowObfuscate?: boolean,
) {
return new UI(Type.SCROLL_TRACK, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function ScrollView(properties?: ScrollView, namespace?: string, name?: string) {
return new UI(Type.SCROLL_VIEW, name, namespace).setProperties(properties || {})
export function ScrollView(properties?: ScrollView, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.SCROLL_VIEW, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function Slider(properties?: Slider, namespace?: string, name?: string) {
return new UI(Type.SLIDER, name, namespace).setProperties(properties || {})
export function Slider(properties?: Slider, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.SLIDER, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function SliderBox(properties?: SliderBox, namespace?: string, name?: string) {
return new UI(Type.SLIDER_BOX, name, namespace).setProperties(properties || {})
export function SliderBox(properties?: SliderBox, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.SLIDER_BOX, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
}
export function ExtendsOf<T extends Type, K extends Renderer | null>(
@ -316,9 +397,10 @@ export function ExtendsOf<T extends Type, K extends Renderer | null>(
properties?: Properties<T, K>,
namespace?: string,
name?: string,
allowObfuscate?: boolean,
) {
if (!element.extendable) throw new Error("Cannot extend a UI that cannot be extended")
const ui = new UI<T, K>(undefined, name, namespace)
const ui = new UI<T, K>(undefined, name, namespace, undefined, allowObfuscate)
if (properties) ui.setProperties(properties)
// @ts-ignore
ui.extend = element

View file

@ -1,16 +1,11 @@
import { Anchor, Label, Modify } from ".."
import { Label, Modify, Panel } from ".."
const label = Label(
{
text: "Hello World from my Custom UI!",
shadow: true,
anchor: Anchor.TOP_MIDDLE,
offset: [0, 10],
},
"test",
).addBindings({
source_property_name: `[ custom_abs(#a) ]`,
target_property_name: "#text",
})
const panel = Panel()
Modify("start", "start_screen_content").insertChild(label)
panel.addChild(
Label({
text: "Hello World",
}),
)
Modify("start", "start_screen_content").insertChild(panel)