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 buildFolder?: string
fileExtension?: string fileExtension?: string
uiBuildFolder?: string uiBuildFolder?: string
obfuscateStringName?: boolean
allowRandomStringName?: boolean
namespaceCount?: number
forceRandomStringLength?: number
} }
ui_analyzer?: { ui_analyzer?: {

View file

@ -13,6 +13,9 @@ export const config = {
autoImport: true, autoImport: true,
autoEnable: true, autoEnable: true,
importToPreview: false, importToPreview: false,
obfuscateStringName: true,
allowRandomStringName: true,
forceRandomStringLength: 16,
}, },
binding_functions: { binding_functions: {
custom_abs: function (number) { 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 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 isBuildMode = options["build"] ?? config.compiler?.enabled ?? false
export const isLinkMode = options["link"] ?? config.compiler?.autoImport ?? false export const isLinkMode = options["link"] ?? config.compiler?.autoImport ?? false
export const unLinked = options["unlink"] ?? !(config.compiler?.autoImport ?? true) export const unLinked = options["unlink"] ?? !(config.compiler?.autoImport ?? true)
export const buildFolder = config.compiler?.buildFolder || "build" export const buildFolder = config.compiler?.buildFolder || "build"
export const uiBuildFolder = config.compiler?.uiBuildFolder || "asajs" 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 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 { BindingItem } from "../../types/properties/value.js"
import { bindingFuntions } from "../Configuration.js" import { bindingFuntions } from "../Configuration.js"
import { isBinding, isNumber, isString } from "./Checker.js" import { isBinding, isNumber, isString } from "./Checker.js"
@ -6,6 +6,7 @@ import { Expression, GenBinding } from "./types.js"
type CallbackRet = { type CallbackRet = {
genBindings?: GenBinding[] genBindings?: GenBinding[]
doNotAddParentesis?: boolean
value: Expression value: Expression
} }
type Callback = (...args: Expression[]) => CallbackRet 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 * Return a translatable string
* @param key * @param key

View file

@ -407,9 +407,9 @@ export class Parser {
if (!func) { if (!func) {
return this.expect(TokenKind.WORD, "Function not found!")! return this.expect(TokenKind.WORD, "Function not found!")!
} else { } else {
const { genBindings, value } = func(...params) const { genBindings, value, doNotAddParentesis } = func(...params)
if (genBindings) this.genBindings.push(...genBindings) 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 { KeyframeAnimationProperties } from "../types/properties/element/Animation.js"
import { Animation } from "./Animation.js" import { Animation } from "./Animation.js"
import { Class } from "./Class.js" import { Class } from "./Class.js"
import { RandomString } from "./Utils.js" import { RandomNamespace, RandomString } from "./Utils.js"
import { RandomNamespace } from "../compilers/Random.js"
import util from "node:util" import util from "node:util"

View file

@ -10,12 +10,11 @@ import { BindingItem, ButtonMapping, ModificationItem, VariableItem, Variables }
import { Animation } from "./Animation.js" import { Animation } from "./Animation.js"
import { AnimationKeyframe } from "./AnimationKeyframe.js" import { AnimationKeyframe } from "./AnimationKeyframe.js"
import { Class } from "./Class.js" import { Class } from "./Class.js"
import { RandomString, ResolveBinding } from "./Utils.js" import { defaultNamespace, RandomNamespace, RandomString, ResolveBinding } from "./Utils.js"
import { RandomNamespace } from "../compilers/Random.js"
import nodepath from "path" import nodepath from "path"
import util from "node:util" import util from "node:util"
import { config, uiBuildFolder } from "../compilers/Configuration.js" import { config, isNotObfuscate, uiBuildFolder } from "../compilers/Configuration.js"
interface ExtendUI { interface ExtendUI {
name: string name: string
@ -52,6 +51,7 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
name?: string, name?: string,
namespace?: string, namespace?: string,
path?: string, path?: string,
allowObfuscate?: boolean,
) { ) {
super() super()
@ -60,8 +60,13 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
process.exit(1) process.exit(1)
} }
if (isNotObfuscate || !(allowObfuscate ?? true)) {
this.name = name?.match(/^(\w|\/)+/)?.[0] || RandomString(16) 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}`) if (!path) this.path = nodepath.join(uiBuildFolder, `${this.namespace}${fileExt}`)
else this.path = path else this.path = path
@ -204,7 +209,7 @@ export class ModifyUI<T extends Type = Type.PANEL, S extends string = string> ex
protected modifications: ModificationItem[] = [] protected modifications: ModificationItem[] = []
constructor(namespace: string, name: string, path: string) { 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 { MemoryModify } from "../compilers/Memory.js"
import { Lexer } from "../compilers/bindings/Lexer.js" import { Lexer } from "../compilers/bindings/Lexer.js"
import { Token, TokenKind, TSToken, TSTokenKind } from "../compilers/bindings/types.js" import { Token, TokenKind, TSToken, TSTokenKind } from "../compilers/bindings/types.js"
import {
allowRandomStringName,
forceRandomStringLength,
isNotObfuscate,
namespaceCount,
} from "../compilers/Configuration.js"
type CompileBinding = `[${string}]` type CompileBinding = `[${string}]`
@ -145,9 +151,18 @@ export function ResolveBinding(cache: Map<string, unknown>, ...bindings: Binding
return result 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 chars = "0123456789abcdefghijklmnopqrstuvwxyz".slice(0, base)
const out = new Array<string>(length) const out = new Array<string>(length)
if (forceRandomStringLength) length = forceRandomStringLength
try { try {
const buffer = new Uint8Array(length) const buffer = new Uint8Array(length)
@ -164,8 +179,53 @@ export function RandomString(length: number, base: number = 32) {
return out.join("") return out.join("")
} }
export function RandomBindingString(length: number = 16, base: number = 32): Binding { const StringID = GenRandomString(5, undefined)
return `#${RandomString(length, base)}` 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) { export function GetItemByAuxID(auxID: number) {
@ -224,36 +284,41 @@ export function Modify<T extends Namespace, K extends Element<T>>(namespace: T,
return modifyUI return modifyUI
} }
export function Panel(properties?: Panel, namespace?: string, name?: string) { export function Panel(properties?: Panel, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.PANEL, name, namespace).setProperties(properties || {}) return new UI(Type.PANEL, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function CollectionPanel(properties?: CollectionPanel, namespace?: string, name?: string) { export function CollectionPanel(
return new UI(Type.COLLECTION_PANEL, name, namespace).setProperties(properties || {}) 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) { export function StackPanel(properties?: StackPanel, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.STACK_PANEL, name, namespace).setProperties(properties || {}) return new UI(Type.STACK_PANEL, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function InputPanel(properties?: InputPanel, namespace?: string, name?: string) { export function InputPanel(properties?: InputPanel, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.INPUT_PANEL, name, namespace).setProperties(properties || {}) return new UI(Type.INPUT_PANEL, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function Gird(properties?: Grid, namespace?: string, name?: string) { export function Gird(properties?: Grid, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.GRID, name, namespace).setProperties(properties || {}) return new UI(Type.GRID, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function Screen(properties?: Screen, namespace?: string, name?: string) { export function Screen(properties?: Screen, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.SCREEN, name, namespace).setProperties(properties || {}) return new UI(Type.SCREEN, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function Image(properties?: Image, namespace?: string, name?: string) { export function Image(properties?: Image, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.IMAGE, name, namespace).setProperties(properties || {}) return new UI(Type.IMAGE, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function Label(properties?: Label, namespace?: string, name?: string) { export function Label(properties?: Label, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.LABEL, name, namespace).setProperties(properties || {}) return new UI(Type.LABEL, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function Custom<R extends Renderer>( export function Custom<R extends Renderer>(
@ -261,54 +326,70 @@ export function Custom<R extends Renderer>(
properties?: Properties<Type.CUSTOM, R>, properties?: Properties<Type.CUSTOM, R>,
namespace?: string, namespace?: string,
name?: 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 }) if (properties) custom.setProperties({ renderer, ...properties })
return custom return custom
} }
export function TooltipTrigger(properties?: TooltipTrigger, namespace?: string, name?: string) { export function TooltipTrigger(
return new UI(Type.TOOLTIP_TRIGGER, name, namespace).setProperties(properties || {}) 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) { export function Button(properties?: Button, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.BUTTON, name, namespace).setProperties(properties || {}) return new UI(Type.BUTTON, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function Toggle(properties?: Toggle, namespace?: string, name?: string) { export function Toggle(properties?: Toggle, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.TOGGLE, name, namespace).setProperties(properties || {}) return new UI(Type.TOGGLE, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function Dropdown(properties?: Dropdown, namespace?: string, name?: string) { export function Dropdown(properties?: Dropdown, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.DROPDOWN, name, namespace).setProperties(properties || {}) return new UI(Type.DROPDOWN, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function SelectionWheel(properties?: SelectionWheel, namespace?: string, name?: string) { export function SelectionWheel(
return new UI(Type.SELECTION_WHEEL, name, namespace).setProperties(properties || {}) 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) { export function EditBox(properties?: EditBox, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.EDIT_BOX, name, namespace).setProperties(properties || {}) return new UI(Type.EDIT_BOX, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function ScrollbarBox(properties?: ScrollbarBox, namespace?: string, name?: string) { export function ScrollbarBox(properties?: ScrollbarBox, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.SCROLLBAR_BOX, name, namespace).setProperties(properties || {}) return new UI(Type.SCROLLBAR_BOX, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function ScrollbarTrack(properties?: ScrollbarTrack, namespace?: string, name?: string) { export function ScrollbarTrack(
return new UI(Type.SCROLL_TRACK, name, namespace).setProperties(properties || {}) 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) { export function ScrollView(properties?: ScrollView, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.SCROLL_VIEW, name, namespace).setProperties(properties || {}) return new UI(Type.SCROLL_VIEW, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function Slider(properties?: Slider, namespace?: string, name?: string) { export function Slider(properties?: Slider, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.SLIDER, name, namespace).setProperties(properties || {}) return new UI(Type.SLIDER, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function SliderBox(properties?: SliderBox, namespace?: string, name?: string) { export function SliderBox(properties?: SliderBox, namespace?: string, name?: string, allowObfuscate?: boolean) {
return new UI(Type.SLIDER_BOX, name, namespace).setProperties(properties || {}) return new UI(Type.SLIDER_BOX, name, namespace, undefined, allowObfuscate).setProperties(properties || {})
} }
export function ExtendsOf<T extends Type, K extends Renderer | null>( 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>, properties?: Properties<T, K>,
namespace?: string, namespace?: string,
name?: string, name?: string,
allowObfuscate?: boolean,
) { ) {
if (!element.extendable) throw new Error("Cannot extend a UI that cannot be extended") 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) if (properties) ui.setProperties(properties)
// @ts-ignore // @ts-ignore
ui.extend = element ui.extend = element

View file

@ -1,16 +1,11 @@
import { Anchor, Label, Modify } from ".." import { Label, Modify, Panel } from ".."
const label = Label( const panel = Panel()
{
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",
})
Modify("start", "start_screen_content").insertChild(label) panel.addChild(
Label({
text: "Hello World",
}),
)
Modify("start", "start_screen_content").insertChild(panel)