T-T
This commit is contained in:
parent
6817734ed9
commit
99c294a9ba
14 changed files with 19528 additions and 19413 deletions
|
|
@ -23,8 +23,6 @@
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"dev": "tsc --watch",
|
"dev": "tsc --watch",
|
||||||
"prefetch": "bun scripts/prefetch",
|
"prefetch": "bun scripts/prefetch",
|
||||||
"native:build": "node-gyp build",
|
|
||||||
"native:rebuild": "node-gyp rebuild",
|
|
||||||
"vanilla:defs": "bun scripts/vanilladefs",
|
"vanilla:defs": "bun scripts/vanilladefs",
|
||||||
"gen:enums": "bun scripts/enum",
|
"gen:enums": "bun scripts/enum",
|
||||||
"gen:items": "bun scripts/items",
|
"gen:items": "bun scripts/items",
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ function toCamelCase(str: string) {
|
||||||
const intelliSense: string[] = [
|
const intelliSense: string[] = [
|
||||||
'import { Type as T } from "../enums/Type.js"\n',
|
'import { Type as T } from "../enums/Type.js"\n',
|
||||||
"export type Namespace = keyof IntelliSense;",
|
"export type Namespace = keyof IntelliSense;",
|
||||||
"export type Element<T extends Namespace> = IntelliSense[T]",
|
"export type Element<T extends Namespace> = Extract<keyof IntelliSense[T], string>",
|
||||||
"export type VanillaType<T extends Namespace, K extends Element<T>> = IntelliSense[T][K]\n",
|
"export type VanillaType<T extends Namespace, K extends Element<T>> = IntelliSense[T][K]\n",
|
||||||
"export type IntelliSense = {",
|
"export type IntelliSense = {",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ for (const key in schema) {
|
||||||
const data = schema[key]
|
const data = schema[key]
|
||||||
if (data.enum) {
|
if (data.enum) {
|
||||||
const enumName = key.match(/\w+$/)?.[0].toCamelCase(true)!
|
const enumName = key.match(/\w+$/)?.[0].toCamelCase(true)!
|
||||||
console.log(enumName)
|
|
||||||
index.push(`export { ${enumName} } from "./${enumName}.js"`)
|
index.push(`export { ${enumName} } from "./${enumName}.js"`)
|
||||||
const count = new Map<string, number>()
|
const count = new Map<string, number>()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,49 @@
|
||||||
import { Class } from "../components/Class.js"
|
import { Class } from "../components/Class.js"
|
||||||
|
import { UI } from "../components/UI.js"
|
||||||
|
import { Renderer } from "../types/enums/Renderer.js"
|
||||||
|
import { Type } from "../types/enums/Type.js"
|
||||||
|
|
||||||
export class Memory extends Class {}
|
type Element = UI<Type, Renderer | null>
|
||||||
|
interface FileInterface {
|
||||||
|
namespace: string
|
||||||
|
elements: Element[]
|
||||||
|
}
|
||||||
|
type Files = Map<string, FileInterface>
|
||||||
|
|
||||||
|
export class Memory extends Class {
|
||||||
|
protected static files: Files = new Map<string, FileInterface>()
|
||||||
|
|
||||||
|
public static add(element: UI<Type, Renderer | null>) {
|
||||||
|
let file = Memory.files.get(element.path)
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
file = { namespace: element.namespace, elements: [] }
|
||||||
|
Memory.files.set(element.path, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.namespace === element.namespace) file.elements.push(element)
|
||||||
|
else {
|
||||||
|
console.error(`Namespace mismatch on ${element.name} (${element.namespace} !== ${file.namespace})`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static build() {
|
||||||
|
const data: Map<string, any> = new Map()
|
||||||
|
|
||||||
|
Memory.files.entries().forEach(([path, { elements, namespace }]) => {
|
||||||
|
const record: Record<string, any> = {}
|
||||||
|
|
||||||
|
elements.forEach(element => {
|
||||||
|
record[element.name] = element
|
||||||
|
})
|
||||||
|
|
||||||
|
data.set(path, {
|
||||||
|
namespace,
|
||||||
|
...record,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
import { Memory } from "./Memory.js"
|
import { Memory } from "./Memory.js"
|
||||||
|
|
||||||
process.on("beforeExit", () => {})
|
process.on("beforeExit", () => {
|
||||||
|
// console.log(Memory.build())
|
||||||
|
})
|
||||||
|
|
|
||||||
|
|
@ -42,93 +42,6 @@ export function Lexer(input: string, start: number = 0, end?: number) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
case "`": {
|
|
||||||
const tsTokens: TSToken[] = []
|
|
||||||
const start = index
|
|
||||||
|
|
||||||
const tokenization = (start: number) => {
|
|
||||||
while (index < input.length) {
|
|
||||||
const char = input[index]
|
|
||||||
if (char === "`") {
|
|
||||||
index++
|
|
||||||
eatString()
|
|
||||||
} else if (char === "}") {
|
|
||||||
tsTokens.push({
|
|
||||||
kind: TSTokenKind.EXPRESSION,
|
|
||||||
tokens: Lexer(input, start + 1, index),
|
|
||||||
})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const stringification = (start: number) => {
|
|
||||||
while (index < input.length) {
|
|
||||||
const char = input[index]
|
|
||||||
if (char === "`") {
|
|
||||||
if (start + 1 !== index)
|
|
||||||
tsTokens.push({
|
|
||||||
kind: TSTokenKind.STRING,
|
|
||||||
tokens: {
|
|
||||||
kind: TokenKind.STRING,
|
|
||||||
start: start + 1,
|
|
||||||
length: index - start + 1,
|
|
||||||
value: `'${input.slice(start + 1, index)}'`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
break
|
|
||||||
} else if (char === "$" && input[index + 1] === "{") {
|
|
||||||
tsTokens.push({
|
|
||||||
kind: TSTokenKind.STRING,
|
|
||||||
tokens: {
|
|
||||||
value: `'${input.slice(start + 1, index)}'`,
|
|
||||||
kind: TokenKind.STRING,
|
|
||||||
length: index - start + 1,
|
|
||||||
start,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
tokenization(++index)
|
|
||||||
start = index
|
|
||||||
}
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const eatString = () => {
|
|
||||||
while (index < input.length) {
|
|
||||||
const char = input[index]
|
|
||||||
|
|
||||||
if (char === "`") {
|
|
||||||
break
|
|
||||||
} else if (char === "$" && input[index + 1] === "{") {
|
|
||||||
index++
|
|
||||||
eatTemplate()
|
|
||||||
}
|
|
||||||
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const eatTemplate = () => {
|
|
||||||
while (index < input.length) {
|
|
||||||
const char = input[index]
|
|
||||||
if (char === "`") {
|
|
||||||
eatString()
|
|
||||||
} else if (char === "}") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stringification(index++)
|
|
||||||
tokens.push(makeToken(tsTokens, TokenKind.TEMPLATE_STRING, start, index - start + 1))
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
case ",":
|
case ",":
|
||||||
tokens.push(makeToken(input, TokenKind.COMMA, index))
|
tokens.push(makeToken(input, TokenKind.COMMA, index))
|
||||||
break
|
break
|
||||||
|
|
@ -165,6 +78,92 @@ export function Lexer(input: string, start: number = 0, end?: number) {
|
||||||
else tokens.push(makeToken(input, TokenKind.OPERATOR, index))
|
else tokens.push(makeToken(input, TokenKind.OPERATOR, index))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
case "f":
|
||||||
|
case "F": {
|
||||||
|
if (input[index + 1] === "'") {
|
||||||
|
const tsTokens: TSToken[] = []
|
||||||
|
const start = ++index
|
||||||
|
|
||||||
|
const tokenization = (start: number) => {
|
||||||
|
while (index < input.length) {
|
||||||
|
const char = input[index]
|
||||||
|
if (char === "'") {
|
||||||
|
index++
|
||||||
|
eatString()
|
||||||
|
} else if (char === "}") {
|
||||||
|
tsTokens.push({
|
||||||
|
kind: TSTokenKind.EXPRESSION,
|
||||||
|
tokens: Lexer(input, start + 1, index),
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const stringification = (start: number) => {
|
||||||
|
while (index < input.length) {
|
||||||
|
const char = input[index]
|
||||||
|
if (char === "'") {
|
||||||
|
if (start + 1 !== index)
|
||||||
|
tsTokens.push({
|
||||||
|
kind: TSTokenKind.STRING,
|
||||||
|
tokens: {
|
||||||
|
kind: TokenKind.STRING,
|
||||||
|
start: start + 1,
|
||||||
|
length: index - start + 1,
|
||||||
|
value: `'${input.slice(start + 1, index)}'`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
break
|
||||||
|
} else if (char === "#" && input[index + 1] === "{") {
|
||||||
|
tsTokens.push({
|
||||||
|
kind: TSTokenKind.STRING,
|
||||||
|
tokens: {
|
||||||
|
value: `'${input.slice(start + 1, index)}'`,
|
||||||
|
kind: TokenKind.STRING,
|
||||||
|
length: index - start + 1,
|
||||||
|
start,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
tokenization(++index)
|
||||||
|
start = index
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const eatString = () => {
|
||||||
|
while (index < input.length) {
|
||||||
|
const char = input[index]
|
||||||
|
if (char === "'") {
|
||||||
|
break
|
||||||
|
} else if (char === "#" && input[index + 1] === "{") {
|
||||||
|
index++
|
||||||
|
eatTemplate()
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const eatTemplate = () => {
|
||||||
|
while (index < input.length) {
|
||||||
|
const char = input[index]
|
||||||
|
if (char === "'") {
|
||||||
|
eatString()
|
||||||
|
} else if (char === "}") {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stringification(index++)
|
||||||
|
tokens.push(makeToken(tsTokens, TokenKind.TEMPLATE_STRING, start - 1, index - start + 1))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
let start = index
|
let start = index
|
||||||
|
|
||||||
|
|
@ -176,7 +175,7 @@ export function Lexer(input: string, start: number = 0, end?: number) {
|
||||||
tokens.push(makeToken(input, TokenKind.WORD, start, index - start + 1))
|
tokens.push(makeToken(input, TokenKind.WORD, start, index - start + 1))
|
||||||
} else if (!Checker.isBlankChar(token)) {
|
} else if (!Checker.isBlankChar(token)) {
|
||||||
console.error(
|
console.error(
|
||||||
`\x1b[31m${input.slice(0, index)}>>>${token}<<<${input.slice(index + 1)}\nInvalid character.\x1b[0m`,
|
`\x1b[31merror: ${input + "\n" + " ".repeat(index + 7) + "^"}\nInvalid character.\x1b[0m`,
|
||||||
)
|
)
|
||||||
throw new Error()
|
throw new Error()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ export class Parser {
|
||||||
constructor(private input: string) {
|
constructor(private input: string) {
|
||||||
this.tokens = Lexer(this.input)
|
this.tokens = Lexer(this.input)
|
||||||
this.output = this.parseExpression()
|
this.output = this.parseExpression()
|
||||||
|
|
||||||
|
if (this.at()) {
|
||||||
|
this.expect(TokenKind.EOF, "Unexpected token!")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
at() {
|
at() {
|
||||||
|
|
@ -247,7 +251,12 @@ export class Parser {
|
||||||
)
|
)
|
||||||
return <string>callerToken.value
|
return <string>callerToken.value
|
||||||
} else {
|
} else {
|
||||||
this.expect(TokenKind.WORD, "Unexpected token!")
|
if (callerToken.kind === TokenKind.WORD)
|
||||||
|
this.warn(
|
||||||
|
`Implicit string literal '${callerToken.value}'. Use quoted string ('${callerToken.value}') for clarity!`,
|
||||||
|
callerToken,
|
||||||
|
)
|
||||||
|
else this.expect(TokenKind.WORD, "Unexpected token!")
|
||||||
return <string>callerToken.value
|
return <string>callerToken.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -274,14 +283,11 @@ export class Parser {
|
||||||
|
|
||||||
private warn(err: string, token?: Token) {
|
private warn(err: string, token?: Token) {
|
||||||
const prev = token || this.at()
|
const prev = token || this.at()
|
||||||
console.warn(`\x1b[33m${this.getPointer(prev)}\n` + `[WARNING]: ${err}\x1b[0m`)
|
console.warn(`\x1b[33mwarn:${this.getPointer(prev, true)}\n` + `[WARNING]: ${err}\x1b[0m`)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPointer(token: Token) {
|
private getPointer(token: Token, isWarn = false) {
|
||||||
return `${this.input.slice(0, token.start)}>>>${this.input.slice(
|
return this.input + "\n" + " ".repeat(token.start + (isWarn ? 5 : 7)) + "^".repeat(token.length)
|
||||||
token.start,
|
|
||||||
token.start + token.length,
|
|
||||||
)}<<<${this.input.slice(token.start + token.length)}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out(): { gen?: BindingItem[]; out: Expression } {
|
out(): { gen?: BindingItem[]; out: Expression } {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ export enum TokenKind {
|
||||||
|
|
||||||
OPERATOR,
|
OPERATOR,
|
||||||
COMMA,
|
COMMA,
|
||||||
|
|
||||||
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TSTokenKind {
|
export enum TSTokenKind {
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,29 @@
|
||||||
import { isCompileBinding } from "../compilers/bindings/Checker.js"
|
import { isCompileBinding } from "../compilers/bindings/Checker.js"
|
||||||
import { Parser } from "../compilers/bindings/Parser.js"
|
import { Parser } from "../compilers/bindings/Parser.js"
|
||||||
import { FormatProperties } from "../compilers/FormatProperties.js"
|
import { FormatProperties } from "../compilers/FormatProperties.js"
|
||||||
|
import { Memory } from "../compilers/Memory.js"
|
||||||
import { BindingType } from "../types/enums/BindingType.js"
|
import { BindingType } from "../types/enums/BindingType.js"
|
||||||
import { Renderer } from "../types/enums/Renderer.js"
|
import { Renderer } from "../types/enums/Renderer.js"
|
||||||
import { Type } from "../types/enums/Type.js"
|
import { Type } from "../types/enums/Type.js"
|
||||||
import { Properties } from "../types/properties/components.js"
|
import { Properties } from "../types/properties/components.js"
|
||||||
import { BindingItem } from "../types/properties/value.js"
|
import { BindingItem } from "../types/properties/value.js"
|
||||||
import { Class } from "./Class.js"
|
import { Class } from "./Class.js"
|
||||||
import { RandomString } from "./Utils.js"
|
import { ExtendsOf, RandomString } from "./Utils.js"
|
||||||
|
|
||||||
import util from "node:util"
|
import util from "node:util"
|
||||||
|
|
||||||
export class UI<T extends Type, K extends Renderer | null = null> extends Class {
|
export class UI<T extends Type, K extends Renderer | null = null> extends Class {
|
||||||
path: string
|
readonly path: string
|
||||||
|
|
||||||
name: string
|
readonly name: string
|
||||||
namespace: string
|
readonly namespace: string
|
||||||
extend?: UI<Type, Renderer | null>
|
readonly extend?: UI<Type, Renderer | null>
|
||||||
|
|
||||||
extendable: boolean
|
readonly extendable: boolean
|
||||||
|
|
||||||
controls = new Map<string, [UI<Type, Renderer | null>, Properties<Type, Renderer | null>]>()
|
readonly controls = new Map<string, [UI<Type, Renderer | null>, Properties<Type, Renderer | null>]>()
|
||||||
bindings: BindingItem[] = []
|
readonly bindings: BindingItem[] = []
|
||||||
|
readonly extendType?: Type
|
||||||
properties: Properties<T, K> = <any>{}
|
properties: Properties<T, K> = <any>{}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -37,6 +39,11 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (namespace && !/^\w+$/.test(namespace)) {
|
||||||
|
console.error(`The '${namespace}' cannot be used as a namespace`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
this.name = name?.match(/^(\w|\/)+/)?.[0] || RandomString(16)
|
this.name = name?.match(/^(\w|\/)+/)?.[0] || RandomString(16)
|
||||||
this.namespace = namespace || RandomString(16)
|
this.namespace = namespace || RandomString(16)
|
||||||
|
|
||||||
|
|
@ -44,6 +51,29 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
|
||||||
else this.path = path
|
else this.path = path
|
||||||
|
|
||||||
this.extendable = this.name.search("/") === -1
|
this.extendable = this.name.search("/") === -1
|
||||||
|
|
||||||
|
Memory.add(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected UI_JSON() {
|
||||||
|
const obj: any = {
|
||||||
|
...FormatProperties(this.properties),
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.type) {
|
||||||
|
obj.type = this.type
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.bindings.length) {
|
||||||
|
obj.bindings = this.bindings
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.controls.size) {
|
||||||
|
obj.controls = []
|
||||||
|
this.controls.forEach((e, key) => obj.controls.push({ [key + e[0]]: e[1] }))
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
setProperties(properties: Properties<T, K>) {
|
setProperties(properties: Properties<T, K>) {
|
||||||
|
|
@ -77,32 +107,19 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
clone(properties?: Properties<T, K>, name?: string, namespace?: string) {
|
||||||
|
return ExtendsOf(this, properties, name, namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected toString() {
|
||||||
return `@${this.namespace}.${this.name}`
|
return `@${this.namespace}.${this.name}`
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON() {
|
protected toJSON() {
|
||||||
const obj: any = {
|
return this.UI_JSON()
|
||||||
...FormatProperties(this.properties),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.type) {
|
protected [util.inspect.custom]($: any, opts: any) {
|
||||||
obj.type = this.type
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.bindings.length) {
|
|
||||||
obj.bindings = this.bindings
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.controls.size) {
|
|
||||||
obj.controls = []
|
|
||||||
this.controls.forEach((e, key) => obj.controls.push({ [key + e[0]]: e[1] }))
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
|
|
||||||
[util.inspect.custom]($: any, opts: any) {
|
|
||||||
const obj: any = {
|
const obj: any = {
|
||||||
...FormatProperties(this.properties),
|
...FormatProperties(this.properties),
|
||||||
}
|
}
|
||||||
|
|
@ -116,8 +133,10 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
|
||||||
this.controls.forEach((e, key) => obj.controls.push({ [key + e[0]]: e[1] }))
|
this.controls.forEach((e, key) => obj.controls.push({ [key + e[0]]: e[1] }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const elementType = this.type || (this.extend ? `${this.extendType || "unknown"}:${this.extend}` : "unknown")
|
||||||
|
|
||||||
return `\x1b[33mUI\x1b[0m<\x1b[92m${
|
return `\x1b[33mUI\x1b[0m<\x1b[92m${
|
||||||
this.type || this.extend ? `${this.extend}` : "ANY"
|
elementType
|
||||||
}\x1b[0m> \x1b[92m"${this}\x1b[92m"\x1b[0m ${util.inspect(obj, opts)}\n`
|
}\x1b[0m> \x1b[92m"${this}\x1b[92m"\x1b[0m ${util.inspect(obj, opts)}\n`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -127,4 +146,9 @@ export class ModifyUI<T extends Type> extends UI<T, null> {
|
||||||
if (!path) throw new Error("ModifyUI cannot have a path")
|
if (!path) throw new Error("ModifyUI cannot have a path")
|
||||||
super(undefined, name, namespace, path)
|
super(undefined, name, namespace, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected toJSON() {
|
||||||
|
const obj = this.UI_JSON()
|
||||||
|
return obj
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import { Element, Namespace, VanillaType } from "../types/vanilla/intellisense.j
|
||||||
import { paths } from "../types/vanilla/paths.js"
|
import { paths } from "../types/vanilla/paths.js"
|
||||||
|
|
||||||
const CHARS = "0123456789abcdefghijklmnopqrstuvwxyz"
|
const CHARS = "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||||
|
type CompileBinding = `[${string}]`
|
||||||
|
|
||||||
export function Color(hex: string | number): Array3<number> {
|
export function Color(hex: string | number): Array3<number> {
|
||||||
if (typeof hex === "number") {
|
if (typeof hex === "number") {
|
||||||
|
|
@ -87,110 +88,134 @@ export function GetItemByAuxID(auxID: number) {
|
||||||
if (item) return `minecraft:${item.toLowerCase()}`
|
if (item) return `minecraft:${item.toLowerCase()}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Binding
|
||||||
|
/**
|
||||||
|
* Return format string binding input
|
||||||
|
* @param input
|
||||||
|
* @returns {CompileBinding}
|
||||||
|
*/
|
||||||
|
export function f(input: string): CompileBinding {
|
||||||
|
if (/^'.+'$/.test(input)) input = `f${input}`
|
||||||
|
else if (!/^f'.+'$/.test(input)) input = `f'${input}'`
|
||||||
|
return b(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return bracket binding input
|
||||||
|
* @param input
|
||||||
|
* @returns {CompileBinding}
|
||||||
|
*/
|
||||||
|
export function b(input: string): CompileBinding {
|
||||||
|
return `[ ${input} ]`
|
||||||
|
}
|
||||||
|
|
||||||
// Quick Elements
|
// Quick Elements
|
||||||
export function Modify<T extends Namespace, K extends Element<T>>(namespace: T, name: K) {
|
export function Modify<T extends Namespace, K extends Element<T>>(namespace: T, name: K) {
|
||||||
// @ts-ignore -- TS cannot prove this, but runtime guarantees it
|
// @ts-ignore -- TS cannot prove this, but runtime guarantees it
|
||||||
return new ModifyUI<VanillaType<T, K>>(name, namespace, paths[namespace][name])
|
return new ModifyUI<VanillaType<T, K>>(name, namespace, paths[namespace][name])
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Panel(properties?: Panel, name?: string, namespace?: string) {
|
export function Panel(properties?: Panel, namespace?: string, name?: string) {
|
||||||
return new UI(Type.PANEL, name, namespace).setProperties(properties || {})
|
return new UI(Type.PANEL, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CollectionPanel(properties?: CollectionPanel, name?: string, namespace?: string) {
|
export function CollectionPanel(properties?: CollectionPanel, namespace?: string, name?: string) {
|
||||||
return new UI(Type.COLLECTION_PANEL, name, namespace).setProperties(properties || {})
|
return new UI(Type.COLLECTION_PANEL, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function StackPanel(properties?: StackPanel, name?: string, namespace?: string) {
|
export function StackPanel(properties?: StackPanel, namespace?: string, name?: string) {
|
||||||
return new UI(Type.STACK_PANEL, name, namespace).setProperties(properties || {})
|
return new UI(Type.STACK_PANEL, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function InputPanel(properties?: InputPanel, name?: string, namespace?: string) {
|
export function InputPanel(properties?: InputPanel, namespace?: string, name?: string) {
|
||||||
return new UI(Type.INPUT_PANEL, name, namespace).setProperties(properties || {})
|
return new UI(Type.INPUT_PANEL, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Gird(properties?: Grid, name?: string, namespace?: string) {
|
export function Gird(properties?: Grid, namespace?: string, name?: string) {
|
||||||
return new UI(Type.GRID, name, namespace).setProperties(properties || {})
|
return new UI(Type.GRID, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Screen(properties?: Screen, name?: string, namespace?: string) {
|
export function Screen(properties?: Screen, namespace?: string, name?: string) {
|
||||||
return new UI(Type.SCREEN, name, namespace).setProperties(properties || {})
|
return new UI(Type.SCREEN, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Image(properties?: Image, name?: string, namespace?: string) {
|
export function Image(properties?: Image, namespace?: string, name?: string) {
|
||||||
return new UI(Type.IMAGE, name, namespace).setProperties(properties || {})
|
return new UI(Type.IMAGE, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Label(properties?: Label, name?: string, namespace?: string) {
|
export function Label(properties?: Label, namespace?: string, name?: string) {
|
||||||
return new UI(Type.LABEL, name, namespace).setProperties(properties || {})
|
return new UI(Type.LABEL, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Custom<R extends Renderer>(
|
export function Custom<R extends Renderer>(
|
||||||
renderer: R,
|
renderer: R,
|
||||||
properties?: Properties<Type.CUSTOM, R>,
|
properties?: Properties<Type.CUSTOM, R>,
|
||||||
name?: string,
|
|
||||||
namespace?: string,
|
namespace?: string,
|
||||||
|
name?: string,
|
||||||
) {
|
) {
|
||||||
const custom = new UI<Type.CUSTOM, R>(Type.CUSTOM, name, namespace)
|
const custom = new UI<Type.CUSTOM, R>(Type.CUSTOM, name, namespace)
|
||||||
if (properties) custom.setProperties({ renderer, ...properties })
|
if (properties) custom.setProperties({ renderer, ...properties })
|
||||||
return custom
|
return custom
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TooltipTrigger(properties?: TooltipTrigger, name?: string, namespace?: string) {
|
export function TooltipTrigger(properties?: TooltipTrigger, namespace?: string, name?: string) {
|
||||||
return new UI(Type.TOOLTIP_TRIGGER, name, namespace).setProperties(properties || {})
|
return new UI(Type.TOOLTIP_TRIGGER, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Button(properties?: Button, name?: string, namespace?: string) {
|
export function Button(properties?: Button, namespace?: string, name?: string) {
|
||||||
return new UI(Type.BUTTON, name, namespace).setProperties(properties || {})
|
return new UI(Type.BUTTON, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Toggle(properties?: Toggle, name?: string, namespace?: string) {
|
export function Toggle(properties?: Toggle, namespace?: string, name?: string) {
|
||||||
return new UI(Type.TOGGLE, name, namespace).setProperties(properties || {})
|
return new UI(Type.TOGGLE, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Dropdown(properties?: Dropdown, name?: string, namespace?: string) {
|
export function Dropdown(properties?: Dropdown, namespace?: string, name?: string) {
|
||||||
return new UI(Type.DROPDOWN, name, namespace).setProperties(properties || {})
|
return new UI(Type.DROPDOWN, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SelectionWheel(properties?: SelectionWheel, name?: string, namespace?: string) {
|
export function SelectionWheel(properties?: SelectionWheel, namespace?: string, name?: string) {
|
||||||
return new UI(Type.SELECTION_WHEEL, name, namespace).setProperties(properties || {})
|
return new UI(Type.SELECTION_WHEEL, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EditBox(properties?: EditBox, name?: string, namespace?: string) {
|
export function EditBox(properties?: EditBox, namespace?: string, name?: string) {
|
||||||
return new UI(Type.EDIT_BOX, name, namespace).setProperties(properties || {})
|
return new UI(Type.EDIT_BOX, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ScrollbarBox(properties?: ScrollbarBox, name?: string, namespace?: string) {
|
export function ScrollbarBox(properties?: ScrollbarBox, namespace?: string, name?: string) {
|
||||||
return new UI(Type.SCROLLBAR_BOX, name, namespace).setProperties(properties || {})
|
return new UI(Type.SCROLLBAR_BOX, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ScrollbarTrack(properties?: ScrollbarTrack, name?: string, namespace?: string) {
|
export function ScrollbarTrack(properties?: ScrollbarTrack, namespace?: string, name?: string) {
|
||||||
return new UI(Type.SCROLL_TRACK, name, namespace).setProperties(properties || {})
|
return new UI(Type.SCROLL_TRACK, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ScrollView(properties?: ScrollView, name?: string, namespace?: string) {
|
export function ScrollView(properties?: ScrollView, namespace?: string, name?: string) {
|
||||||
return new UI(Type.SCROLL_VIEW, name, namespace).setProperties(properties || {})
|
return new UI(Type.SCROLL_VIEW, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Slider(properties?: Slider, name?: string, namespace?: string) {
|
export function Slider(properties?: Slider, namespace?: string, name?: string) {
|
||||||
return new UI(Type.SLIDER, name, namespace).setProperties(properties || {})
|
return new UI(Type.SLIDER, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SliderBox(properties?: SliderBox, name?: string, namespace?: string) {
|
export function SliderBox(properties?: SliderBox, namespace?: string, name?: string) {
|
||||||
return new UI(Type.SLIDER_BOX, name, namespace).setProperties(properties || {})
|
return new UI(Type.SLIDER_BOX, name, namespace).setProperties(properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ExtendsOf<T extends Type, K extends Renderer | null>(
|
export function ExtendsOf<T extends Type, K extends Renderer | null>(
|
||||||
element: UI<T, K>,
|
element: UI<T, K>,
|
||||||
properties?: Properties<T, K>,
|
properties?: Properties<T, K>,
|
||||||
name?: string,
|
|
||||||
namespace?: string,
|
namespace?: string,
|
||||||
|
name?: string,
|
||||||
) {
|
) {
|
||||||
if (!element.extendable) {
|
if (!element.extendable) {
|
||||||
throw new Error("Cannot extend a UI that cannot be extended")
|
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)
|
||||||
if (properties) ui.setProperties(properties)
|
if (properties) ui.setProperties(properties)
|
||||||
|
// @ts-ignore
|
||||||
ui.extend = element
|
ui.extend = element
|
||||||
|
// @ts-ignore
|
||||||
|
ui.extendType = element.type || element.extendType
|
||||||
return ui as typeof element
|
return ui as typeof element
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ export type BindingItem = {
|
||||||
source_property_name?: Value<string | Binding | bind.Binding>
|
source_property_name?: Value<string | Binding | bind.Binding>
|
||||||
target_property_name?: Value<Binding | bind.Binding>
|
target_property_name?: Value<Binding | bind.Binding>
|
||||||
resolve_sibling_scope?: Value<boolean>
|
resolve_sibling_scope?: Value<boolean>
|
||||||
|
resolve_ancestor_scope?: Value<boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FocusContainerCustom = Array<{
|
export type FocusContainerCustom = Array<{
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
15
test/app.ts
15
test/app.ts
|
|
@ -1 +1,14 @@
|
||||||
import {} from ".."
|
import { BagBinding, f, ItemAuxID, Label } from ".."
|
||||||
|
|
||||||
|
const text = Label({
|
||||||
|
text: "#text",
|
||||||
|
[BagBinding.ITEM_ID_AUX]: ItemAuxID.DIAMOND,
|
||||||
|
"#x": 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
text.addBindings({
|
||||||
|
source_property_name: f(`Test: #{ -(${BagBinding.ITEM_ID_AUX} % #x) == 0 }`),
|
||||||
|
target_property_name: BagBinding.TEXT,
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(text)
|
||||||
|
|
|
||||||
Reference in a new issue