@px-petals/roku.motion-web 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bands/bands.js +3 -1
- package/bundle/bundle.js +56 -0
- package/list/list.js +12 -1
- package/lottie/lottie.layers.js +64 -11
- package/lottie/lottie.paint.js +30 -0
- package/lottie/lottie.paths.js +19 -4
- package/lottie/lottie.props.js +18 -8
- package/lottie/lottie.shapes.js +2 -1
- package/mixer/mixer.js +31 -8
- package/mixer/mixer.mix.js +17 -0
- package/motion/motion.convert.js +32 -1
- package/motion/motion.flow.js +20 -2
- package/motion/motion.machine.js +28 -13
- package/motion/motion.values.js +13 -9
- package/motion.js +196 -20
- package/package.json +10 -16
- package/player/player.js +25 -5
- package/readme.md +78 -3
- package/script/luau/lib/base/base.js +202 -0
- package/script/luau/lib/base/base.table.js +189 -0
- package/script/luau/lib/lib.args.js +152 -0
- package/script/luau/lib/lib.js +23 -0
- package/script/luau/lib/math/math.bit32.js +144 -0
- package/script/luau/lib/math/math.js +288 -0
- package/script/luau/lib/math/math.vector.js +125 -0
- package/script/luau/lib/string/string.format.js +143 -0
- package/script/luau/lib/string/string.js +160 -0
- package/script/luau/lib/string/string.pattern.js +505 -0
- package/script/luau/load/load.js +362 -0
- package/script/luau/load/load.ops.js +79 -0
- package/script/luau/luau.convert.js +259 -0
- package/script/luau/luau.js +132 -0
- package/script/luau/luau.md +111 -0
- package/script/luau/vm/vm.js +167 -0
- package/script/luau/vm/vm.meta.js +401 -0
- package/script/luau/vm/vm.num.js +236 -0
- package/script/luau/vm/vm.run.js +842 -0
- package/script/luau/vm/vm.value.js +406 -0
- package/script/play/play.js +199 -0
- package/script/play/play.objects.js +295 -0
- package/script/play/play.scope.js +91 -0
- package/script/rive/api/api.statics.js +31 -0
- package/script/rive/api/api.type.js +188 -0
- package/script/rive/api/artboard/artboard.js +89 -0
- package/script/rive/api/assets/assets.js +72 -0
- package/script/rive/api/data/data.value.js +99 -0
- package/script/rive/api/draw/draw.contours.js +163 -0
- package/script/rive/api/draw/draw.measure.js +196 -0
- package/script/rive/api/draw/draw.paint.js +235 -0
- package/script/rive/api/draw/draw.path.js +153 -0
- package/script/rive/api/draw/draw.renderer.js +117 -0
- package/script/rive/api/math/math.color.js +96 -0
- package/script/rive/api/math/math.mat2d.js +180 -0
- package/script/rive/api/math/math.vector.js +121 -0
- package/script/rive/api/media/media.audio.js +113 -0
- package/script/rive/api/media/media.draw.js +73 -0
- package/script/rive/api/media/media.image.js +61 -0
- package/script/rive/api/media/media.mesh.js +50 -0
- package/script/rive/api/pointer/pointer.event.js +64 -0
- package/script/rive/api/pointer/pointer.route.js +69 -0
- package/script/rive/api/text/text.font.js +129 -0
- package/script/rive/api/text/text.js +278 -0
- package/script/rive/api/text/text.layout.js +259 -0
- package/script/rive/context/context.js +76 -0
- package/script/rive/context/context.memory.js +196 -0
- package/script/rive/context/context.viewmodel.js +302 -0
- package/script/rive/context/lists/lists.js +160 -0
- package/script/rive/context/lists/lists.values.js +281 -0
- package/script/rive/host/host.globals.js +44 -0
- package/script/rive/host/host.js +533 -0
- package/script/rive/host/host.node.js +45 -0
- package/script/rive/rive.js +23 -0
- package/script/rive/rive.md +180 -0
- package/script/script.js +11 -0
- package/skin/skin.deform.js +514 -0
- package/skin/skin.ik.js +260 -0
- package/skin/skin.js +297 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `vector` library: the three-component vector value's functions.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { LuaTable, Vector, fround } from '../../vm/vm.value.js'
|
|
6
|
+
import { sign } from '../../vm/vm.num.js'
|
|
7
|
+
import { checkNumber, register, typeError } from '../lib.args.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {any[]} args
|
|
11
|
+
* @param {number} i
|
|
12
|
+
* @param {string} name
|
|
13
|
+
* @returns {Vector}
|
|
14
|
+
*/
|
|
15
|
+
function checkVector(args, i, name) {
|
|
16
|
+
const v = args[i]
|
|
17
|
+
if (!(v instanceof Vector)) throw typeError(args, i, name, 'vector')
|
|
18
|
+
return v
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {Vector} v
|
|
23
|
+
* @returns {number}
|
|
24
|
+
*/
|
|
25
|
+
function magnitude(v) {
|
|
26
|
+
return fround(Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {import('../../vm/vm.js').VM} vm
|
|
31
|
+
* @param {LuaTable} G
|
|
32
|
+
*/
|
|
33
|
+
export function installVector(vm, G) {
|
|
34
|
+
const lib = new LuaTable()
|
|
35
|
+
G.set('vector', lib)
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A function of one vector that maps each component.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} name
|
|
41
|
+
* @param {(n: number) => number} f
|
|
42
|
+
*/
|
|
43
|
+
const mapped = function (name, f) {
|
|
44
|
+
lib.set(name, vm.native('vector.' + name, function (vm2, args) {
|
|
45
|
+
const v = checkVector(args, 0, name)
|
|
46
|
+
return new Vector(f(v.x), f(v.y), f(v.z))
|
|
47
|
+
}))
|
|
48
|
+
}
|
|
49
|
+
mapped('floor', Math.floor)
|
|
50
|
+
mapped('ceil', Math.ceil)
|
|
51
|
+
mapped('abs', Math.abs)
|
|
52
|
+
mapped('sign', sign)
|
|
53
|
+
|
|
54
|
+
register(lib, {
|
|
55
|
+
create(vm, args) {
|
|
56
|
+
return new Vector(checkNumber(args, 0, 'create'), checkNumber(args, 1, 'create'), args[2] === undefined ? 0 : checkNumber(args, 2, 'create'))
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
magnitude(vm, args) {
|
|
60
|
+
return magnitude(checkVector(args, 0, 'magnitude'))
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
normalize(vm, args) {
|
|
64
|
+
const v = checkVector(args, 0, 'normalize')
|
|
65
|
+
const m = magnitude(v)
|
|
66
|
+
return new Vector(v.x / m, v.y / m, v.z / m)
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
dot(vm, args) {
|
|
70
|
+
const a = checkVector(args, 0, 'dot')
|
|
71
|
+
const b = checkVector(args, 1, 'dot')
|
|
72
|
+
return fround(a.x * b.x + a.y * b.y + a.z * b.z)
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
cross(vm, args) {
|
|
76
|
+
const a = checkVector(args, 0, 'cross')
|
|
77
|
+
const b = checkVector(args, 1, 'cross')
|
|
78
|
+
return new Vector(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x)
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
angle(vm, args) {
|
|
82
|
+
const a = checkVector(args, 0, 'angle')
|
|
83
|
+
const b = checkVector(args, 1, 'angle')
|
|
84
|
+
const cx = a.y * b.z - a.z * b.y
|
|
85
|
+
const cy = a.z * b.x - a.x * b.z
|
|
86
|
+
const cz = a.x * b.y - a.y * b.x
|
|
87
|
+
return Math.atan2(Math.sqrt(cx * cx + cy * cy + cz * cz), a.x * b.x + a.y * b.y + a.z * b.z)
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
clamp(vm, args) {
|
|
91
|
+
const v = checkVector(args, 0, 'clamp')
|
|
92
|
+
const lo = checkVector(args, 1, 'clamp')
|
|
93
|
+
const hi = checkVector(args, 2, 'clamp')
|
|
94
|
+
return new Vector(Math.min(Math.max(v.x, lo.x), hi.x), Math.min(Math.max(v.y, lo.y), hi.y), Math.min(Math.max(v.z, lo.z), hi.z))
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
min(vm, args) {
|
|
98
|
+
let r = checkVector(args, 0, 'min')
|
|
99
|
+
for (let i = 1; i < args.length; i++) {
|
|
100
|
+
const v = checkVector(args, i, 'min')
|
|
101
|
+
r = new Vector(Math.min(r.x, v.x), Math.min(r.y, v.y), Math.min(r.z, v.z))
|
|
102
|
+
}
|
|
103
|
+
return r
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
max(vm, args) {
|
|
107
|
+
let r = checkVector(args, 0, 'max')
|
|
108
|
+
for (let i = 1; i < args.length; i++) {
|
|
109
|
+
const v = checkVector(args, i, 'max')
|
|
110
|
+
r = new Vector(Math.max(r.x, v.x), Math.max(r.y, v.y), Math.max(r.z, v.z))
|
|
111
|
+
}
|
|
112
|
+
return r
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
lerp(vm, args) {
|
|
116
|
+
const a = checkVector(args, 0, 'lerp')
|
|
117
|
+
const b = checkVector(args, 1, 'lerp')
|
|
118
|
+
const t = checkNumber(args, 2, 'lerp')
|
|
119
|
+
return new Vector(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t)
|
|
120
|
+
},
|
|
121
|
+
}, 'vector.')
|
|
122
|
+
|
|
123
|
+
lib.set('zero', new Vector(0, 0, 0))
|
|
124
|
+
lib.set('one', new Vector(1, 1, 1))
|
|
125
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `string.format`: C's printf conversions as Lua uses them.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { fail } from '../../vm/vm.value.js'
|
|
6
|
+
import { formatE, formatF, formatG, repeat, trunc } from '../../vm/vm.num.js'
|
|
7
|
+
import { checkNumber, checkString } from '../lib.args.js'
|
|
8
|
+
|
|
9
|
+
const SPEC = /^%([-+ #0]*)(\d*)(?:\.(\d*))?([a-zA-Z%])/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Pads `body` (with its sign or prefix split off) to `width`.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} sign '-', '+', ' ', a `0x` prefix or ''
|
|
15
|
+
* @param {string} body
|
|
16
|
+
* @param {number} width
|
|
17
|
+
* @param {string} flags
|
|
18
|
+
* @param {boolean} zeroOk whether the 0 flag pads with zeros here
|
|
19
|
+
* @returns {string}
|
|
20
|
+
*/
|
|
21
|
+
function pad(sign, body, width, flags, zeroOk) {
|
|
22
|
+
const n = width - sign.length - body.length
|
|
23
|
+
if (n <= 0) return sign + body
|
|
24
|
+
if (flags.indexOf('-') >= 0) return sign + body + repeat(' ', n)
|
|
25
|
+
if (flags.indexOf('0') >= 0 && zeroOk) return sign + repeat('0', n) + body
|
|
26
|
+
return repeat(' ', n) + sign + body
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} s
|
|
31
|
+
* @returns {string} s as a Lua string literal that reads back as s (`%q`)
|
|
32
|
+
*/
|
|
33
|
+
function quote(s) {
|
|
34
|
+
let out = '"'
|
|
35
|
+
for (let i = 0; i < s.length; i++) {
|
|
36
|
+
const c = s.charCodeAt(i)
|
|
37
|
+
const ch = s.charAt(i)
|
|
38
|
+
if (ch === '"' || ch === '\\') out += '\\' + ch
|
|
39
|
+
else if (c === 10) out += '\\\n'
|
|
40
|
+
else if (c === 13) out += '\\r'
|
|
41
|
+
else if (c === 0) out += '\\000'
|
|
42
|
+
else out += ch
|
|
43
|
+
}
|
|
44
|
+
return out + '"'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {import('../../vm/vm.js').VM} vm
|
|
49
|
+
* @param {any[]} args the format string, then the values
|
|
50
|
+
* @returns {string}
|
|
51
|
+
*/
|
|
52
|
+
export function format(vm, args) {
|
|
53
|
+
const fmt = checkString(args, 0, 'format')
|
|
54
|
+
let out = ''
|
|
55
|
+
let arg = 0
|
|
56
|
+
let i = 0
|
|
57
|
+
while (i < fmt.length) {
|
|
58
|
+
const pct = fmt.indexOf('%', i)
|
|
59
|
+
if (pct < 0) {
|
|
60
|
+
out += fmt.substring(i)
|
|
61
|
+
break
|
|
62
|
+
}
|
|
63
|
+
out += fmt.substring(i, pct)
|
|
64
|
+
const m = SPEC.exec(fmt.substring(pct))
|
|
65
|
+
if (m === null) throw fail("invalid option '%" + fmt.charAt(pct + 1) + "' to 'format'")
|
|
66
|
+
i = pct + m[0].length
|
|
67
|
+
const flags = m[1]
|
|
68
|
+
const width = m[2] === '' ? 0 : parseInt(m[2], 10)
|
|
69
|
+
const hasPrecision = m[3] !== undefined
|
|
70
|
+
const precision = hasPrecision ? (m[3] === '' ? 0 : parseInt(m[3], 10)) : -1
|
|
71
|
+
const conv = m[4]
|
|
72
|
+
if (conv === '%') {
|
|
73
|
+
out += '%'
|
|
74
|
+
continue
|
|
75
|
+
}
|
|
76
|
+
arg++
|
|
77
|
+
if (arg >= args.length) throw fail('missing argument #' + (arg + 1))
|
|
78
|
+
const signOf = function (/** @type {boolean} */ negative) {
|
|
79
|
+
return negative ? '-' : flags.indexOf('+') >= 0 ? '+' : flags.indexOf(' ') >= 0 ? ' ' : ''
|
|
80
|
+
}
|
|
81
|
+
switch (conv) {
|
|
82
|
+
case 'd':
|
|
83
|
+
case 'i':
|
|
84
|
+
case 'u': {
|
|
85
|
+
const n = trunc(checkNumber(args, arg, 'format'))
|
|
86
|
+
let body = String(Math.abs(n))
|
|
87
|
+
if (hasPrecision) while (body.length < precision) body = '0' + body
|
|
88
|
+
out += pad(signOf(n < 0), body, width, flags, !hasPrecision)
|
|
89
|
+
break
|
|
90
|
+
}
|
|
91
|
+
case 'c':
|
|
92
|
+
out += pad('', String.fromCharCode(trunc(checkNumber(args, arg, 'format')) & 255), width, flags, false)
|
|
93
|
+
break
|
|
94
|
+
case 'x':
|
|
95
|
+
case 'X':
|
|
96
|
+
case 'o': {
|
|
97
|
+
let n = trunc(checkNumber(args, arg, 'format'))
|
|
98
|
+
if (n < 0) n += 4294967296
|
|
99
|
+
let body = n.toString(conv === 'o' ? 8 : 16)
|
|
100
|
+
if (conv === 'X') body = body.toUpperCase()
|
|
101
|
+
if (hasPrecision) while (body.length < precision) body = '0' + body
|
|
102
|
+
const prefix = flags.indexOf('#') >= 0 && n !== 0 ? (conv === 'o' ? '0' : conv === 'x' ? '0x' : '0X') : ''
|
|
103
|
+
out += pad(prefix, body, width, flags, !hasPrecision)
|
|
104
|
+
break
|
|
105
|
+
}
|
|
106
|
+
case 'e':
|
|
107
|
+
case 'E':
|
|
108
|
+
case 'f':
|
|
109
|
+
case 'F':
|
|
110
|
+
case 'g':
|
|
111
|
+
case 'G': {
|
|
112
|
+
const n = checkNumber(args, arg, 'format')
|
|
113
|
+
const upper = conv === 'E' || conv === 'G' || conv === 'F'
|
|
114
|
+
const alt = flags.indexOf('#') >= 0
|
|
115
|
+
const finite = n === n && n !== Infinity && n !== -Infinity
|
|
116
|
+
const neg = n < 0 || (n === 0 && 1 / n < 0)
|
|
117
|
+
let body
|
|
118
|
+
if (!finite) body = n !== n ? 'nan' : 'inf'
|
|
119
|
+
else {
|
|
120
|
+
const p = hasPrecision ? precision : 6
|
|
121
|
+
const a = Math.abs(n)
|
|
122
|
+
const lower = conv.toLowerCase()
|
|
123
|
+
body = lower === 'e' ? formatE(a, p, alt) : lower === 'f' ? formatF(a, p, alt) : formatG(a, p, alt)
|
|
124
|
+
}
|
|
125
|
+
if (upper) body = body.toUpperCase()
|
|
126
|
+
out += pad(signOf(neg), body, width, flags, finite)
|
|
127
|
+
break
|
|
128
|
+
}
|
|
129
|
+
case 'q':
|
|
130
|
+
out += quote(checkString(args, arg, 'format'))
|
|
131
|
+
break
|
|
132
|
+
case 's': {
|
|
133
|
+
let s = checkString(args, arg, 'format')
|
|
134
|
+
if (hasPrecision) s = s.substring(0, precision)
|
|
135
|
+
out += pad('', s, width, flags, false)
|
|
136
|
+
break
|
|
137
|
+
}
|
|
138
|
+
default:
|
|
139
|
+
throw fail("invalid option '%" + conv + "' to 'format'")
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return out
|
|
143
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `string` library, and the string metatable that makes `("x"):upper()`
|
|
3
|
+
* work. Strings are byte strings, so `upper` and `lower` change ASCII letters
|
|
4
|
+
* only, as C's locale does.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { LuaTable, fail, typeName } from '../../vm/vm.value.js'
|
|
8
|
+
import { numberToString, repeat } from '../../vm/vm.num.js'
|
|
9
|
+
import { argError, checkFunction, checkInt, checkString, optInt, optString, register, typeError } from '../lib.args.js'
|
|
10
|
+
import { format } from './string.format.js'
|
|
11
|
+
import { find, gmatch, gsub } from './string.pattern.js'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {number} i a 1-based position, negative from the end
|
|
15
|
+
* @param {number} len
|
|
16
|
+
* @returns {number}
|
|
17
|
+
*/
|
|
18
|
+
function posrelat(i, len) {
|
|
19
|
+
return i >= 0 ? i : -i > len ? 0 : len + i + 1
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {import('../../vm/vm.js').VM} vm
|
|
24
|
+
* @param {LuaTable} G
|
|
25
|
+
*/
|
|
26
|
+
export function installString(vm, G) {
|
|
27
|
+
const string = new LuaTable()
|
|
28
|
+
G.set('string', string)
|
|
29
|
+
|
|
30
|
+
register(string, {
|
|
31
|
+
len(vm, args) {
|
|
32
|
+
return checkString(args, 0, 'len').length
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
sub(vm, args) {
|
|
36
|
+
const s = checkString(args, 0, 'sub')
|
|
37
|
+
let i = posrelat(checkInt(args, 1, 'sub'), s.length)
|
|
38
|
+
let j = posrelat(optInt(args, 2, 'sub', -1), s.length)
|
|
39
|
+
if (i < 1) i = 1
|
|
40
|
+
if (j > s.length) j = s.length
|
|
41
|
+
return i > j ? '' : s.substring(i - 1, j)
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
upper(vm, args) {
|
|
45
|
+
return checkString(args, 0, 'upper').replace(/[a-z]+/g, function (m) { return m.toUpperCase() })
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
lower(vm, args) {
|
|
49
|
+
return checkString(args, 0, 'lower').replace(/[A-Z]+/g, function (m) { return m.toLowerCase() })
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
rep(vm, args) {
|
|
53
|
+
const s = checkString(args, 0, 'rep')
|
|
54
|
+
const n = checkInt(args, 1, 'rep')
|
|
55
|
+
if (n <= 0) return ''
|
|
56
|
+
if (s.length * n > 1e9) throw fail('resulting string too large')
|
|
57
|
+
return repeat(s, n)
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
reverse(vm, args) {
|
|
61
|
+
const s = checkString(args, 0, 'reverse')
|
|
62
|
+
let out = ''
|
|
63
|
+
for (let i = s.length - 1; i >= 0; i--) out += s.charAt(i)
|
|
64
|
+
return out
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
byte(vm, args) {
|
|
68
|
+
const s = checkString(args, 0, 'byte')
|
|
69
|
+
const i = posrelat(optInt(args, 1, 'byte', 1), s.length)
|
|
70
|
+
let j = posrelat(optInt(args, 2, 'byte', i), s.length)
|
|
71
|
+
const start = Math.max(i, 1)
|
|
72
|
+
if (j > s.length) j = s.length
|
|
73
|
+
const out = []
|
|
74
|
+
for (let n = start; n <= j; n++) out.push(s.charCodeAt(n - 1))
|
|
75
|
+
return out
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
char(vm, args) {
|
|
79
|
+
let out = ''
|
|
80
|
+
for (let i = 0; i < args.length; i++) {
|
|
81
|
+
const c = checkInt(args, i, 'char')
|
|
82
|
+
if (c < 0 || c > 255) throw argError(i + 1, 'char', 'invalid value')
|
|
83
|
+
out += String.fromCharCode(c)
|
|
84
|
+
}
|
|
85
|
+
return out
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
find(vm, args) {
|
|
89
|
+
const s = checkString(args, 0, 'find')
|
|
90
|
+
const r = find(s, checkString(args, 1, 'find'), optInt(args, 2, 'find', 1), args[3] !== undefined && args[3] !== false, true)
|
|
91
|
+
return r === undefined ? undefined : r
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
match(vm, args) {
|
|
95
|
+
const s = checkString(args, 0, 'match')
|
|
96
|
+
const r = find(s, checkString(args, 1, 'match'), optInt(args, 2, 'match', 1), false, false)
|
|
97
|
+
return r === undefined ? undefined : r
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
gmatch(vm, args) {
|
|
101
|
+
const next = gmatch(checkString(args, 0, 'gmatch'), checkString(args, 1, 'gmatch'))
|
|
102
|
+
return vm.native('gmatch_iterator', function () {
|
|
103
|
+
const r = next()
|
|
104
|
+
return r === undefined ? undefined : r
|
|
105
|
+
})
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
gsub(vm, args) {
|
|
109
|
+
const s = checkString(args, 0, 'gsub')
|
|
110
|
+
const pat = checkString(args, 1, 'gsub')
|
|
111
|
+
const repl = args[2]
|
|
112
|
+
const max = args[3] === undefined ? s.length + 1 : checkInt(args, 3, 'gsub')
|
|
113
|
+
/** @type {string | null} */
|
|
114
|
+
let template = null
|
|
115
|
+
/** @type {(c: (string | number)[]) => any} */
|
|
116
|
+
let replace = function () { return undefined }
|
|
117
|
+
if (typeof repl === 'string') template = repl
|
|
118
|
+
else if (typeof repl === 'number') template = numberToString(repl)
|
|
119
|
+
else if (repl instanceof LuaTable) {
|
|
120
|
+
replace = function (c) {
|
|
121
|
+
return convertReplacement(repl.get(c[0]))
|
|
122
|
+
}
|
|
123
|
+
} else if (repl !== undefined && typeName(repl) === 'function') {
|
|
124
|
+
checkFunction(args, 2, 'gsub')
|
|
125
|
+
replace = function (c) {
|
|
126
|
+
return convertReplacement(vm.call(repl, c)[0])
|
|
127
|
+
}
|
|
128
|
+
} else throw typeError(args, 2, 'gsub', 'string/function/table')
|
|
129
|
+
return gsub(s, pat, replace, template, max)
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
format(vm, args) {
|
|
133
|
+
return format(vm, args)
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
split(vm, args) {
|
|
137
|
+
const s = checkString(args, 0, 'split')
|
|
138
|
+
const sep = optString(args, 1, 'split', ',')
|
|
139
|
+
const t = new LuaTable()
|
|
140
|
+
const parts = sep === '' ? [ s ] : s.split(sep)
|
|
141
|
+
t.setRange(1, parts, 0, parts.length)
|
|
142
|
+
return t
|
|
143
|
+
},
|
|
144
|
+
}, 'string.')
|
|
145
|
+
|
|
146
|
+
const meta = new LuaTable()
|
|
147
|
+
meta.set('__index', string)
|
|
148
|
+
vm.stringMeta = meta
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @param {any} v what a gsub callback or table gave
|
|
153
|
+
* @returns {string | number | boolean | undefined}
|
|
154
|
+
*/
|
|
155
|
+
function convertReplacement(v) {
|
|
156
|
+
if (v === undefined || v === false) return v
|
|
157
|
+
if (typeof v === 'string') return v
|
|
158
|
+
if (typeof v === 'number') return numberToString(v)
|
|
159
|
+
throw fail('invalid replacement value (a ' + typeName(v) + ')')
|
|
160
|
+
}
|