starlight-cli 1.1.16 → 1.1.18
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/dist/index.js +559 -152
- package/package.json +1 -1
- package/src/evaluator.js +498 -11
- package/src/parser.js +58 -139
- package/src/starlight.js +2 -2
package/dist/index.js
CHANGED
|
@@ -10213,7 +10213,6 @@ const fs = __nccwpck_require__(896);
|
|
|
10213
10213
|
const Lexer = __nccwpck_require__(211);
|
|
10214
10214
|
const Parser = __nccwpck_require__(222);
|
|
10215
10215
|
const path = __nccwpck_require__(928);
|
|
10216
|
-
|
|
10217
10216
|
class ReturnValue {
|
|
10218
10217
|
constructor(value) { this.value = value; }
|
|
10219
10218
|
}
|
|
@@ -10414,7 +10413,51 @@ formatValue(value, seen = new Set()) {
|
|
|
10414
10413
|
if (arg && typeof arg === 'object') return Object.keys(arg).length;
|
|
10415
10414
|
return 0;
|
|
10416
10415
|
});
|
|
10416
|
+
this.global.define('lower', arg => {
|
|
10417
|
+
if (typeof arg !== 'string') return String(arg).toLowerCase();
|
|
10418
|
+
return arg.toLowerCase();
|
|
10419
|
+
});
|
|
10420
|
+
this.global.define('toStr', arg => String(arg));
|
|
10417
10421
|
|
|
10422
|
+
this.global.define('upper', arg => {
|
|
10423
|
+
if (typeof arg !== 'string') return String(arg).toUpperCase();
|
|
10424
|
+
return arg.toUpperCase();
|
|
10425
|
+
});
|
|
10426
|
+
|
|
10427
|
+
this.global.define('trim', arg => {
|
|
10428
|
+
if (typeof arg !== 'string') return String(arg).trim();
|
|
10429
|
+
return arg.trim();
|
|
10430
|
+
});
|
|
10431
|
+
|
|
10432
|
+
this.global.define('startsWith', (str, prefix) => {
|
|
10433
|
+
if (typeof str !== 'string') str = String(str);
|
|
10434
|
+
if (typeof prefix !== 'string') prefix = String(prefix);
|
|
10435
|
+
return str.startsWith(prefix);
|
|
10436
|
+
});
|
|
10437
|
+
|
|
10438
|
+
this.global.define('endsWith', (str, suffix) => {
|
|
10439
|
+
if (typeof str !== 'string') str = String(str);
|
|
10440
|
+
if (typeof suffix !== 'string') suffix = String(suffix);
|
|
10441
|
+
return str.endsWith(suffix);
|
|
10442
|
+
});
|
|
10443
|
+
|
|
10444
|
+
this.global.define('includes', (str, substr) => {
|
|
10445
|
+
if (typeof str !== 'string') str = String(str);
|
|
10446
|
+
if (typeof substr !== 'string') substr = String(substr);
|
|
10447
|
+
return str.includes(substr);
|
|
10448
|
+
});
|
|
10449
|
+
|
|
10450
|
+
this.global.define('repeat', (str, times) => {
|
|
10451
|
+
if (typeof str !== 'string') str = String(str);
|
|
10452
|
+
return str.repeat(Number(times) || 0);
|
|
10453
|
+
});
|
|
10454
|
+
|
|
10455
|
+
this.global.define('replace', (str, search, replacement) => {
|
|
10456
|
+
if (typeof str !== 'string') str = String(str);
|
|
10457
|
+
if (typeof search !== 'string') search = String(search);
|
|
10458
|
+
if (typeof replacement !== 'string') replacement = String(replacement);
|
|
10459
|
+
return str.split(search).join(replacement);
|
|
10460
|
+
});
|
|
10418
10461
|
this.global.define('print', arg => { console.log(arg); return null; });
|
|
10419
10462
|
this.global.define('type', arg => {
|
|
10420
10463
|
if (Array.isArray(arg)) return 'array';
|
|
@@ -10423,6 +10466,8 @@ formatValue(value, seen = new Set()) {
|
|
|
10423
10466
|
this.global.define('isNaN', arg => {
|
|
10424
10467
|
return typeof arg !== 'number' || Number.isNaN(arg);
|
|
10425
10468
|
});
|
|
10469
|
+
|
|
10470
|
+
|
|
10426
10471
|
this.global.define('random', (min, max) => {
|
|
10427
10472
|
if (max === undefined) {
|
|
10428
10473
|
// Only one argument → random between 0 and min
|
|
@@ -10525,6 +10570,9 @@ this.global.define('encodeURLComponent', arg => {
|
|
|
10525
10570
|
|
|
10526
10571
|
return acc;
|
|
10527
10572
|
});
|
|
10573
|
+
this.global.define('hasOwn', (obj, prop) => {
|
|
10574
|
+
return Object.prototype.hasOwnProperty.call(obj, prop)
|
|
10575
|
+
});
|
|
10528
10576
|
|
|
10529
10577
|
this.global.define('keys', arg => arg && typeof arg === 'object' ? Object.keys(arg) : []);
|
|
10530
10578
|
this.global.define('values', arg => arg && typeof arg === 'object' ? Object.values(arg) : []);
|
|
@@ -10563,6 +10611,72 @@ this.global.define('range', (...args) => {
|
|
|
10563
10611
|
|
|
10564
10612
|
return result;
|
|
10565
10613
|
});
|
|
10614
|
+
this.global.define('floor', arg => Math.floor(Number(arg)));
|
|
10615
|
+
this.global.define('ceil', arg => Math.ceil(Number(arg)));
|
|
10616
|
+
this.global.define('round', arg => Math.round(Number(arg)));
|
|
10617
|
+
this.global.define('abs', arg => Math.abs(Number(arg)));
|
|
10618
|
+
this.global.define('pow', (base, exp) => Math.pow(Number(base), Number(exp)));
|
|
10619
|
+
this.global.define('sqrt', arg => Math.sqrt(Number(arg)));
|
|
10620
|
+
this.global.define('min', (...args) => Math.min(...args.map(Number)));
|
|
10621
|
+
this.global.define('max', (...args) => Math.max(...args.map(Number)));
|
|
10622
|
+
this.global.define('randomFloat', (min, max) => {
|
|
10623
|
+
min = Number(min); max = Number(max);
|
|
10624
|
+
if (isNaN(min) || isNaN(max)) return 0;
|
|
10625
|
+
return Math.random() * (max - min) + min;
|
|
10626
|
+
});
|
|
10627
|
+
|
|
10628
|
+
this.global.define('push', (arr, val) => {
|
|
10629
|
+
if (!Array.isArray(arr)) throw new RuntimeError('push() expects an array', null, this.source);
|
|
10630
|
+
arr.push(val); return arr.length;
|
|
10631
|
+
});
|
|
10632
|
+
this.global.define('pop', arr => {
|
|
10633
|
+
if (!Array.isArray(arr)) throw new RuntimeError('pop() expects an array', null, this.source);
|
|
10634
|
+
return arr.pop();
|
|
10635
|
+
});
|
|
10636
|
+
this.global.define('shift', arr => {
|
|
10637
|
+
if (!Array.isArray(arr)) throw new RuntimeError('shift() expects an array', null, this.source);
|
|
10638
|
+
return arr.shift();
|
|
10639
|
+
});
|
|
10640
|
+
this.global.define('unshift', (arr, val) => {
|
|
10641
|
+
if (!Array.isArray(arr)) throw new RuntimeError('unshift() expects an array', null, this.source);
|
|
10642
|
+
arr.unshift(val); return arr.length;
|
|
10643
|
+
});
|
|
10644
|
+
this.global.define('sort', (arr, fn) => {
|
|
10645
|
+
if (!Array.isArray(arr)) throw new RuntimeError('sort() expects an array', null, this.source);
|
|
10646
|
+
if (fn && typeof fn === 'function') return arr.sort(fn);
|
|
10647
|
+
return arr.sort();
|
|
10648
|
+
});
|
|
10649
|
+
this.global.define('reverse', arr => {
|
|
10650
|
+
if (!Array.isArray(arr)) throw new RuntimeError('reverse() expects an array', null, this.source);
|
|
10651
|
+
return arr.reverse();
|
|
10652
|
+
});
|
|
10653
|
+
|
|
10654
|
+
this.global.define('has', (obj, key) => obj && typeof obj === 'object' ? obj.hasOwnProperty(key) : false);
|
|
10655
|
+
this.global.define('merge', (obj1, obj2) => {
|
|
10656
|
+
if (!obj1 || typeof obj1 !== 'object') obj1 = {};
|
|
10657
|
+
if (!obj2 || typeof obj2 !== 'object') obj2 = {};
|
|
10658
|
+
return { ...obj1, ...obj2 };
|
|
10659
|
+
});
|
|
10660
|
+
|
|
10661
|
+
this.global.define('uuid', () => {
|
|
10662
|
+
// simple random UUID v4
|
|
10663
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
10664
|
+
const r = Math.random() * 16 | 0;
|
|
10665
|
+
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
10666
|
+
return v.toString(16);
|
|
10667
|
+
});
|
|
10668
|
+
});
|
|
10669
|
+
this.global.define('timestamp', () => Date.now());
|
|
10670
|
+
this.global.define('clone', arg => {
|
|
10671
|
+
if (Array.isArray(arg)) return [...arg];
|
|
10672
|
+
if (arg && typeof arg === 'object') return { ...arg };
|
|
10673
|
+
return arg; // primitive types
|
|
10674
|
+
});
|
|
10675
|
+
this.global.define('typeOf', arg => {
|
|
10676
|
+
if (arg === null) return 'null';
|
|
10677
|
+
if (Array.isArray(arg)) return 'array';
|
|
10678
|
+
return typeof arg;
|
|
10679
|
+
});
|
|
10566
10680
|
|
|
10567
10681
|
this.global.define('ask', prompt => {
|
|
10568
10682
|
const readlineSync = __nccwpck_require__(552);
|
|
@@ -10619,6 +10733,271 @@ this.global.define('sleep', async (ms) => {
|
|
|
10619
10733
|
this.global.define('str', arg => {
|
|
10620
10734
|
return String(arg);
|
|
10621
10735
|
});
|
|
10736
|
+
this.global.define('now', () => Date.now());
|
|
10737
|
+
this.global.define('formatDate', (timestamp, locale = 'en-US', options = {}) => {
|
|
10738
|
+
if (timestamp === null || timestamp === undefined) timestamp = Date.now();
|
|
10739
|
+
const t = typeof timestamp === 'number' ? timestamp : Number(timestamp);
|
|
10740
|
+
if (isNaN(t)) t = Date.now();
|
|
10741
|
+
return new Date(t).toLocaleString(locale, options);
|
|
10742
|
+
});
|
|
10743
|
+
|
|
10744
|
+
this.global.define('readFile', path => {
|
|
10745
|
+
if (typeof path !== 'string') path = String(path);
|
|
10746
|
+
try {
|
|
10747
|
+
return fs.readFileSync(path, 'utf-8');
|
|
10748
|
+
} catch (e) {
|
|
10749
|
+
throw new RuntimeError('readFile error: ' + e.message, null, this.source);
|
|
10750
|
+
}
|
|
10751
|
+
});
|
|
10752
|
+
this.global.define('writeFile', (path, content) => {
|
|
10753
|
+
if (typeof path !== 'string') path = String(path);
|
|
10754
|
+
if (typeof content !== 'string') content = String(content);
|
|
10755
|
+
try {
|
|
10756
|
+
fs.writeFileSync(path, content, 'utf-8');
|
|
10757
|
+
return true;
|
|
10758
|
+
} catch (e) {
|
|
10759
|
+
throw new RuntimeError('writeFile error: ' + e.message, null, this.source);
|
|
10760
|
+
}
|
|
10761
|
+
});
|
|
10762
|
+
|
|
10763
|
+
this.global.define('split', (str, separator) => {
|
|
10764
|
+
if (typeof str !== 'string') str = String(str);
|
|
10765
|
+
if (separator === undefined) separator = '';
|
|
10766
|
+
return str.split(separator);
|
|
10767
|
+
});
|
|
10768
|
+
|
|
10769
|
+
this.global.define('join', (arr, separator = '') => {
|
|
10770
|
+
if (!Array.isArray(arr)) throw new RuntimeError('join() expects an array', null, this.source);
|
|
10771
|
+
return arr.join(separator);
|
|
10772
|
+
});
|
|
10773
|
+
|
|
10774
|
+
this.global.define('substring', (str, start, end) => {
|
|
10775
|
+
if (typeof str !== 'string') str = String(str);
|
|
10776
|
+
start = Number(start) || 0;
|
|
10777
|
+
end = end !== undefined ? Number(end) : undefined;
|
|
10778
|
+
return str.substring(start, end);
|
|
10779
|
+
});
|
|
10780
|
+
|
|
10781
|
+
this.global.define('padStart', (str, targetLength, padString = ' ') => {
|
|
10782
|
+
if (typeof str !== 'string') str = String(str);
|
|
10783
|
+
targetLength = Number(targetLength) || 0;
|
|
10784
|
+
return str.padStart(targetLength, padString);
|
|
10785
|
+
});
|
|
10786
|
+
|
|
10787
|
+
this.global.define('padEnd', (str, targetLength, padString = ' ') => {
|
|
10788
|
+
if (typeof str !== 'string') str = String(str);
|
|
10789
|
+
targetLength = Number(targetLength) || 0;
|
|
10790
|
+
return str.padEnd(targetLength, padString);
|
|
10791
|
+
});
|
|
10792
|
+
this.global.define('unique', arr => {
|
|
10793
|
+
if (!Array.isArray(arr)) throw new RuntimeError('unique() expects an array', null, this.source);
|
|
10794
|
+
return [...new Set(arr)];
|
|
10795
|
+
});
|
|
10796
|
+
|
|
10797
|
+
this.global.define('indexOf', (arr, val) => {
|
|
10798
|
+
if (!Array.isArray(arr)) throw new RuntimeError('indexOf() expects an array', null, this.source);
|
|
10799
|
+
return arr.indexOf(val);
|
|
10800
|
+
});
|
|
10801
|
+
|
|
10802
|
+
this.global.define('includesArr', (arr, val) => {
|
|
10803
|
+
if (!Array.isArray(arr)) throw new RuntimeError('includesArr() expects an array', null, this.source);
|
|
10804
|
+
return arr.includes(val);
|
|
10805
|
+
});
|
|
10806
|
+
|
|
10807
|
+
this.global.define('flatten', arr => {
|
|
10808
|
+
if (!Array.isArray(arr)) throw new RuntimeError('flatten() expects an array', null, this.source);
|
|
10809
|
+
return arr.flat(Infinity);
|
|
10810
|
+
});
|
|
10811
|
+
|
|
10812
|
+
this.global.define('randomChoice', arr => {
|
|
10813
|
+
if (!Array.isArray(arr)) throw new RuntimeError('randomChoice() expects an array', null, this.source);
|
|
10814
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
10815
|
+
});
|
|
10816
|
+
|
|
10817
|
+
this.global.define('entries', obj => {
|
|
10818
|
+
if (!obj || typeof obj !== 'object') throw new RuntimeError('entries() expects an object', null, this.source);
|
|
10819
|
+
return Object.entries(obj);
|
|
10820
|
+
});
|
|
10821
|
+
|
|
10822
|
+
this.global.define('invert', obj => {
|
|
10823
|
+
if (!obj || typeof obj !== 'object') throw new RuntimeError('invert() expects an object', null, this.source);
|
|
10824
|
+
const result = {};
|
|
10825
|
+
for (const key in obj) result[obj[key]] = key;
|
|
10826
|
+
return result;
|
|
10827
|
+
});
|
|
10828
|
+
|
|
10829
|
+
this.global.define('isEmpty', arg => {
|
|
10830
|
+
if (arg == null) return true;
|
|
10831
|
+
if (Array.isArray(arg) || typeof arg === 'string') return arg.length === 0;
|
|
10832
|
+
if (typeof arg === 'object') return Object.keys(arg).length === 0;
|
|
10833
|
+
return false;
|
|
10834
|
+
});
|
|
10835
|
+
|
|
10836
|
+
this.global.define('deepClone', arg => {
|
|
10837
|
+
return JSON.parse(JSON.stringify(arg));
|
|
10838
|
+
});
|
|
10839
|
+
|
|
10840
|
+
this.global.define('capitalize', str => {
|
|
10841
|
+
if (typeof str !== 'string') str = String(str);
|
|
10842
|
+
if (str.length === 0) return '';
|
|
10843
|
+
return str[0].toUpperCase() + str.slice(1);
|
|
10844
|
+
});
|
|
10845
|
+
|
|
10846
|
+
this.global.define('reverseStr', str => {
|
|
10847
|
+
if (typeof str !== 'string') str = String(str);
|
|
10848
|
+
return str.split('').reverse().join('');
|
|
10849
|
+
});
|
|
10850
|
+
|
|
10851
|
+
this.global.define('trimStart', str => {
|
|
10852
|
+
if (typeof str !== 'string') str = String(str);
|
|
10853
|
+
return str.trimStart();
|
|
10854
|
+
});
|
|
10855
|
+
|
|
10856
|
+
this.global.define('trimEnd', str => {
|
|
10857
|
+
if (typeof str !== 'string') str = String(str);
|
|
10858
|
+
return str.trimEnd();
|
|
10859
|
+
});
|
|
10860
|
+
|
|
10861
|
+
this.global.define('clamp', (value, min, max) => {
|
|
10862
|
+
value = Number(value); min = Number(min); max = Number(max);
|
|
10863
|
+
return Math.min(Math.max(value, min), max);
|
|
10864
|
+
});
|
|
10865
|
+
|
|
10866
|
+
this.global.define('sign', value => {
|
|
10867
|
+
value = Number(value);
|
|
10868
|
+
return Math.sign(value);
|
|
10869
|
+
});
|
|
10870
|
+
|
|
10871
|
+
this.global.define('appendFile', (path, content) => {
|
|
10872
|
+
if (typeof path !== 'string') path = String(path);
|
|
10873
|
+
if (typeof content !== 'string') content = String(content);
|
|
10874
|
+
try {
|
|
10875
|
+
fs.appendFileSync(path, content, 'utf-8');
|
|
10876
|
+
return true;
|
|
10877
|
+
} catch (e) {
|
|
10878
|
+
throw new RuntimeError('appendFile error: ' + e.message, null, this.source);
|
|
10879
|
+
}
|
|
10880
|
+
});
|
|
10881
|
+
|
|
10882
|
+
this.global.define('exists', path => {
|
|
10883
|
+
if (typeof path !== 'string') path = String(path);
|
|
10884
|
+
return fs.existsSync(path);
|
|
10885
|
+
});
|
|
10886
|
+
|
|
10887
|
+
this.global.define('mkdir', path => {
|
|
10888
|
+
if (typeof path !== 'string') path = String(path);
|
|
10889
|
+
if (!fs.existsSync(path)) fs.mkdirSync(path, { recursive: true });
|
|
10890
|
+
return true;
|
|
10891
|
+
});
|
|
10892
|
+
this.global.define('count', (arr, value) => {
|
|
10893
|
+
if (!Array.isArray(arr)) throw new RuntimeError('count() expects an array', null, this.source);
|
|
10894
|
+
return arr.filter(x => x === value).length;
|
|
10895
|
+
});
|
|
10896
|
+
|
|
10897
|
+
this.global.define('uniqueBy', (arr, fn) => {
|
|
10898
|
+
if (!Array.isArray(arr)) throw new RuntimeError('uniqueBy() expects an array', null, this.source);
|
|
10899
|
+
const seen = new Set();
|
|
10900
|
+
const result = [];
|
|
10901
|
+
for (const item of arr) {
|
|
10902
|
+
const key = fn ? fn(item) : item;
|
|
10903
|
+
if (!seen.has(key)) {
|
|
10904
|
+
seen.add(key);
|
|
10905
|
+
result.push(item);
|
|
10906
|
+
}
|
|
10907
|
+
}
|
|
10908
|
+
return result;
|
|
10909
|
+
});
|
|
10910
|
+
this.global.define('getProp', (obj, key, defaultValue = null) => {
|
|
10911
|
+
if (!obj || typeof obj !== 'object') return defaultValue;
|
|
10912
|
+
const keys = key.split('.');
|
|
10913
|
+
let current = obj;
|
|
10914
|
+
for (const k of keys) {
|
|
10915
|
+
if (current[k] === undefined) return defaultValue;
|
|
10916
|
+
current = current[k];
|
|
10917
|
+
}
|
|
10918
|
+
return current;
|
|
10919
|
+
});
|
|
10920
|
+
|
|
10921
|
+
this.global.define('setProp', (obj, key, value) => {
|
|
10922
|
+
if (!obj || typeof obj !== 'object') throw new RuntimeError('setProp() expects an object', null, this.source);
|
|
10923
|
+
const keys = key.split('.');
|
|
10924
|
+
let current = obj;
|
|
10925
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
10926
|
+
if (!current[keys[i]] || typeof current[keys[i]] !== 'object') current[keys[i]] = {};
|
|
10927
|
+
current = current[keys[i]];
|
|
10928
|
+
}
|
|
10929
|
+
current[keys[keys.length - 1]] = value;
|
|
10930
|
+
return obj;
|
|
10931
|
+
});
|
|
10932
|
+
|
|
10933
|
+
this.global.define('mergeDeep', (obj1, obj2) => {
|
|
10934
|
+
const isObject = val => val && typeof val === 'object';
|
|
10935
|
+
const result = {...obj1};
|
|
10936
|
+
for (const key in obj2) {
|
|
10937
|
+
if (isObject(obj2[key]) && isObject(result[key])) {
|
|
10938
|
+
result[key] = this.global.get('mergeDeep')(result[key], obj2[key]);
|
|
10939
|
+
} else {
|
|
10940
|
+
result[key] = obj2[key];
|
|
10941
|
+
}
|
|
10942
|
+
}
|
|
10943
|
+
return result;
|
|
10944
|
+
});
|
|
10945
|
+
this.global.define('camelCase', str => {
|
|
10946
|
+
if (typeof str !== 'string') str = String(str);
|
|
10947
|
+
return str
|
|
10948
|
+
.replace(/[-_ ]+./g, s => s.charAt(s.length - 1).toUpperCase())
|
|
10949
|
+
.replace(/^[A-Z]/, s => s.toLowerCase());
|
|
10950
|
+
});
|
|
10951
|
+
|
|
10952
|
+
this.global.define('kebabCase', str => {
|
|
10953
|
+
if (typeof str !== 'string') str = String(str);
|
|
10954
|
+
return str
|
|
10955
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
10956
|
+
.replace(/\s+/g, '-')
|
|
10957
|
+
.replace(/_+/g, '-')
|
|
10958
|
+
.toLowerCase();
|
|
10959
|
+
});
|
|
10960
|
+
|
|
10961
|
+
this.global.define('repeatStr', (str, times) => {
|
|
10962
|
+
if (typeof str !== 'string') str = String(str);
|
|
10963
|
+
return str.repeat(Number(times) || 0);
|
|
10964
|
+
});
|
|
10965
|
+
this.global.define('randomInt', (min, max) => {
|
|
10966
|
+
min = Number(min); max = Number(max);
|
|
10967
|
+
if (isNaN(min) || isNaN(max)) return 0;
|
|
10968
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
10969
|
+
});
|
|
10970
|
+
|
|
10971
|
+
this.global.define('lerp', (a, b, t) => {
|
|
10972
|
+
a = Number(a); b = Number(b); t = Number(t);
|
|
10973
|
+
return a + (b - a) * t;
|
|
10974
|
+
});
|
|
10975
|
+
|
|
10976
|
+
this.global.define('degToRad', deg => Number(deg) * (Math.PI / 180));
|
|
10977
|
+
this.global.define('radToDeg', rad => Number(rad) * (180 / Math.PI));
|
|
10978
|
+
this.global.define('readJSON', path => {
|
|
10979
|
+
const content = this.global.get('readFile')(path);
|
|
10980
|
+
return JSON.parse(content);
|
|
10981
|
+
});
|
|
10982
|
+
|
|
10983
|
+
this.global.define('writeJSON', (path, obj) => {
|
|
10984
|
+
const content = JSON.stringify(obj, null, 2);
|
|
10985
|
+
return this.global.get('writeFile')(path, content);
|
|
10986
|
+
});
|
|
10987
|
+
|
|
10988
|
+
this.global.define('deleteFile', path => {
|
|
10989
|
+
if (typeof path !== 'string') path = String(path);
|
|
10990
|
+
if (!fs.existsSync(path)) return false;
|
|
10991
|
+
fs.unlinkSync(path);
|
|
10992
|
+
return true;
|
|
10993
|
+
});
|
|
10994
|
+
|
|
10995
|
+
this.global.define('rmdir', path => {
|
|
10996
|
+
if (typeof path !== 'string') path = String(path);
|
|
10997
|
+
if (!fs.existsSync(path)) return false;
|
|
10998
|
+
fs.rmSync(path, { recursive: true, force: true });
|
|
10999
|
+
return true;
|
|
11000
|
+
});
|
|
10622
11001
|
|
|
10623
11002
|
}
|
|
10624
11003
|
|
|
@@ -10748,8 +11127,6 @@ async evalProgram(node, env) {
|
|
|
10748
11127
|
async evalSlice(node, env) {
|
|
10749
11128
|
try {
|
|
10750
11129
|
const arr = await this.evaluate(node.object, env);
|
|
10751
|
-
const start = node.start ? await this.evaluate(node.start, env) : 0;
|
|
10752
|
-
const end = node.end ? await this.evaluate(node.end, env) : arr.length;
|
|
10753
11130
|
|
|
10754
11131
|
if (!Array.isArray(arr)) {
|
|
10755
11132
|
throw new RuntimeError(
|
|
@@ -10760,10 +11137,37 @@ async evalSlice(node, env) {
|
|
|
10760
11137
|
);
|
|
10761
11138
|
}
|
|
10762
11139
|
|
|
10763
|
-
|
|
10764
|
-
|
|
11140
|
+
let start = node.start ? await this.evaluate(node.start, env) : 0;
|
|
11141
|
+
let end = node.end ? await this.evaluate(node.end, env) : arr.length;
|
|
11142
|
+
let step = node.step ? await this.evaluate(node.step, env) : 1;
|
|
11143
|
+
|
|
11144
|
+
if (step === 0) {
|
|
11145
|
+
throw new RuntimeError(
|
|
11146
|
+
'Slice step cannot be zero',
|
|
11147
|
+
node,
|
|
11148
|
+
this.source,
|
|
11149
|
+
env
|
|
11150
|
+
);
|
|
11151
|
+
}
|
|
11152
|
+
start = start < 0 ? arr.length + start : start;
|
|
11153
|
+
end = end < 0 ? arr.length + end : end;
|
|
11154
|
+
|
|
11155
|
+
start = Math.min(Math.max(start, 0), arr.length);
|
|
11156
|
+
end = Math.min(Math.max(end, 0), arr.length);
|
|
10765
11157
|
|
|
10766
|
-
|
|
11158
|
+
const result = [];
|
|
11159
|
+
|
|
11160
|
+
if (step > 0) {
|
|
11161
|
+
for (let i = start; i < end; i += step) {
|
|
11162
|
+
result.push(arr[i]);
|
|
11163
|
+
}
|
|
11164
|
+
} else {
|
|
11165
|
+
for (let i = start; i > end; i += step) {
|
|
11166
|
+
result.push(arr[i]);
|
|
11167
|
+
}
|
|
11168
|
+
}
|
|
11169
|
+
|
|
11170
|
+
return result;
|
|
10767
11171
|
|
|
10768
11172
|
} catch (err) {
|
|
10769
11173
|
if (err instanceof RuntimeError) throw err;
|
|
@@ -10776,6 +11180,7 @@ async evalSlice(node, env) {
|
|
|
10776
11180
|
}
|
|
10777
11181
|
}
|
|
10778
11182
|
|
|
11183
|
+
|
|
10779
11184
|
async evalStartStatement(node, env) {
|
|
10780
11185
|
try {
|
|
10781
11186
|
const value = await this.evaluate(node.discriminant, env);
|
|
@@ -11300,12 +11705,49 @@ async evalLogical(node, env) {
|
|
|
11300
11705
|
|
|
11301
11706
|
async evalUnary(node, env) {
|
|
11302
11707
|
try {
|
|
11708
|
+
// Handle prefix update operators
|
|
11709
|
+
if (node.type === 'UpdateExpression' && node.prefix) {
|
|
11710
|
+
if (node.argument.type !== 'Identifier') {
|
|
11711
|
+
throw new RuntimeError(
|
|
11712
|
+
`Invalid operand for update operator: ${node.operator}`,
|
|
11713
|
+
node,
|
|
11714
|
+
this.source,
|
|
11715
|
+
env
|
|
11716
|
+
);
|
|
11717
|
+
}
|
|
11718
|
+
|
|
11719
|
+
const varName = node.argument.name;
|
|
11720
|
+
let currentVal = await env.get(varName); // assuming env.get returns the variable value
|
|
11721
|
+
|
|
11722
|
+
switch (node.operator) {
|
|
11723
|
+
case 'PLUSPLUS':
|
|
11724
|
+
currentVal++;
|
|
11725
|
+
await env.set(varName, currentVal);
|
|
11726
|
+
return currentVal;
|
|
11727
|
+
case 'MINUSMINUS':
|
|
11728
|
+
currentVal--;
|
|
11729
|
+
await env.set(varName, currentVal);
|
|
11730
|
+
return currentVal;
|
|
11731
|
+
default:
|
|
11732
|
+
throw new RuntimeError(
|
|
11733
|
+
`Unknown update operator: ${node.operator}`,
|
|
11734
|
+
node,
|
|
11735
|
+
this.source,
|
|
11736
|
+
env
|
|
11737
|
+
);
|
|
11738
|
+
}
|
|
11739
|
+
}
|
|
11740
|
+
|
|
11741
|
+
// Evaluate the argument first
|
|
11303
11742
|
const val = await this.evaluate(node.argument, env);
|
|
11304
11743
|
|
|
11305
11744
|
switch (node.operator) {
|
|
11306
|
-
case 'NOT':
|
|
11307
|
-
|
|
11308
|
-
case '
|
|
11745
|
+
case 'NOT':
|
|
11746
|
+
return !val;
|
|
11747
|
+
case 'MINUS':
|
|
11748
|
+
return -val;
|
|
11749
|
+
case 'PLUS':
|
|
11750
|
+
return +val;
|
|
11309
11751
|
default:
|
|
11310
11752
|
throw new RuntimeError(
|
|
11311
11753
|
`Unknown unary operator: ${node.operator}`,
|
|
@@ -11314,7 +11756,6 @@ async evalUnary(node, env) {
|
|
|
11314
11756
|
env
|
|
11315
11757
|
);
|
|
11316
11758
|
}
|
|
11317
|
-
|
|
11318
11759
|
} catch (e) {
|
|
11319
11760
|
if (e instanceof RuntimeError) throw e;
|
|
11320
11761
|
throw new RuntimeError(
|
|
@@ -11326,6 +11767,51 @@ async evalUnary(node, env) {
|
|
|
11326
11767
|
}
|
|
11327
11768
|
}
|
|
11328
11769
|
|
|
11770
|
+
// Handle postfix updates (x++ or x--)
|
|
11771
|
+
async evalPostfixUpdate(node, env) {
|
|
11772
|
+
if (node.type !== 'UpdateExpression' || node.prefix) {
|
|
11773
|
+
throw new RuntimeError(
|
|
11774
|
+
`Invalid postfix update node`,
|
|
11775
|
+
node,
|
|
11776
|
+
this.source,
|
|
11777
|
+
env
|
|
11778
|
+
);
|
|
11779
|
+
}
|
|
11780
|
+
|
|
11781
|
+
if (node.argument.type !== 'Identifier') {
|
|
11782
|
+
throw new RuntimeError(
|
|
11783
|
+
`Invalid operand for postfix update operator: ${node.operator}`,
|
|
11784
|
+
node,
|
|
11785
|
+
this.source,
|
|
11786
|
+
env
|
|
11787
|
+
);
|
|
11788
|
+
}
|
|
11789
|
+
|
|
11790
|
+
const varName = node.argument.name;
|
|
11791
|
+
let currentVal = await env.get(varName);
|
|
11792
|
+
|
|
11793
|
+
let returnVal = currentVal;
|
|
11794
|
+
|
|
11795
|
+
switch (node.operator) {
|
|
11796
|
+
case 'PLUSPLUS':
|
|
11797
|
+
currentVal++;
|
|
11798
|
+
await env.set(varName, currentVal);
|
|
11799
|
+
return returnVal; // return original value
|
|
11800
|
+
case 'MINUSMINUS':
|
|
11801
|
+
currentVal--;
|
|
11802
|
+
await env.set(varName, currentVal);
|
|
11803
|
+
return returnVal; // return original value
|
|
11804
|
+
default:
|
|
11805
|
+
throw new RuntimeError(
|
|
11806
|
+
`Unknown postfix operator: ${node.operator}`,
|
|
11807
|
+
node,
|
|
11808
|
+
this.source,
|
|
11809
|
+
env
|
|
11810
|
+
);
|
|
11811
|
+
}
|
|
11812
|
+
}
|
|
11813
|
+
|
|
11814
|
+
|
|
11329
11815
|
async evalIf(node, env) {
|
|
11330
11816
|
let test = await this.evaluate(node.test, env);
|
|
11331
11817
|
test = !!test; // coerce to boolean
|
|
@@ -11604,7 +12090,8 @@ async evalIndex(node, env) {
|
|
|
11604
12090
|
env
|
|
11605
12091
|
);
|
|
11606
12092
|
}
|
|
11607
|
-
}
|
|
12093
|
+
}
|
|
12094
|
+
|
|
11608
12095
|
async evalObject(node, env) {
|
|
11609
12096
|
try {
|
|
11610
12097
|
const out = {};
|
|
@@ -13243,192 +13730,111 @@ unary() {
|
|
|
13243
13730
|
|
|
13244
13731
|
return this.postfix();
|
|
13245
13732
|
}
|
|
13733
|
+
|
|
13246
13734
|
postfix() {
|
|
13247
13735
|
let node = this.primary();
|
|
13248
13736
|
|
|
13249
13737
|
while (true) {
|
|
13250
13738
|
const t = this.current;
|
|
13251
13739
|
|
|
13252
|
-
|
|
13253
|
-
|
|
13254
|
-
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
let start = null;
|
|
13258
|
-
let end = null;
|
|
13259
|
-
let step = null;
|
|
13260
|
-
|
|
13261
|
-
if (this.current.type === 'COLON') {
|
|
13262
|
-
this.eat('COLON');
|
|
13263
|
-
|
|
13264
|
-
if (this.current.type !== 'RBRACKET' && this.current.type !== 'COLON') {
|
|
13265
|
-
end = this.expression();
|
|
13266
|
-
}
|
|
13267
|
-
|
|
13268
|
-
if (this.current.type === 'COLON') {
|
|
13269
|
-
this.eat('COLON');
|
|
13270
|
-
if (this.current.type !== 'RBRACKET') {
|
|
13271
|
-
step = this.expression();
|
|
13272
|
-
}
|
|
13273
|
-
}
|
|
13274
|
-
|
|
13275
|
-
if (this.current.type !== 'RBRACKET') {
|
|
13276
|
-
throw new ParseError(
|
|
13277
|
-
"Expected ']' after slice",
|
|
13278
|
-
this.current,
|
|
13279
|
-
this.source
|
|
13280
|
-
);
|
|
13281
|
-
}
|
|
13282
|
-
|
|
13283
|
-
this.eat('RBRACKET');
|
|
13284
|
-
|
|
13285
|
-
node = {
|
|
13286
|
-
type: 'SliceExpression',
|
|
13287
|
-
object: node,
|
|
13288
|
-
start,
|
|
13289
|
-
end,
|
|
13290
|
-
step,
|
|
13291
|
-
line: startLine,
|
|
13292
|
-
column: startCol
|
|
13293
|
-
};
|
|
13294
|
-
|
|
13295
|
-
} else {
|
|
13296
|
-
start = this.expression();
|
|
13297
|
-
|
|
13298
|
-
if (this.current.type === 'COLON') {
|
|
13299
|
-
this.eat('COLON');
|
|
13740
|
+
// Handle indexing / slicing
|
|
13741
|
+
if (t.type === 'LBRACKET') {
|
|
13742
|
+
const startLine = t.line;
|
|
13743
|
+
const startCol = t.column;
|
|
13744
|
+
this.eat('LBRACKET');
|
|
13300
13745
|
|
|
13301
|
-
|
|
13302
|
-
|
|
13303
|
-
|
|
13746
|
+
let start = null;
|
|
13747
|
+
let end = null;
|
|
13748
|
+
let step = null;
|
|
13304
13749
|
|
|
13750
|
+
// Slice: [:end:step] or [start:end:step]
|
|
13305
13751
|
if (this.current.type === 'COLON') {
|
|
13306
13752
|
this.eat('COLON');
|
|
13753
|
+
if (this.current.type !== 'RBRACKET' && this.current.type !== 'COLON') {
|
|
13754
|
+
end = this.expression();
|
|
13755
|
+
}
|
|
13756
|
+
if (this.current.type === 'COLON') {
|
|
13757
|
+
this.eat('COLON');
|
|
13758
|
+
if (this.current.type !== 'RBRACKET') {
|
|
13759
|
+
step = this.expression();
|
|
13760
|
+
}
|
|
13761
|
+
}
|
|
13307
13762
|
if (this.current.type !== 'RBRACKET') {
|
|
13308
|
-
|
|
13763
|
+
throw new ParseError("Expected ']' after slice", this.current, this.source);
|
|
13309
13764
|
}
|
|
13310
|
-
|
|
13765
|
+
this.eat('RBRACKET');
|
|
13311
13766
|
|
|
13312
|
-
|
|
13313
|
-
|
|
13314
|
-
|
|
13315
|
-
|
|
13316
|
-
|
|
13317
|
-
|
|
13318
|
-
|
|
13319
|
-
|
|
13320
|
-
|
|
13321
|
-
|
|
13322
|
-
|
|
13323
|
-
|
|
13324
|
-
|
|
13325
|
-
|
|
13326
|
-
|
|
13327
|
-
|
|
13328
|
-
|
|
13329
|
-
|
|
13330
|
-
|
|
13767
|
+
node = { type: 'SliceExpression', object: node, start, end, step, line: startLine, column: startCol };
|
|
13768
|
+
} else {
|
|
13769
|
+
// Normal index or slice starting with an expression
|
|
13770
|
+
start = this.expression();
|
|
13771
|
+
if (this.current.type === 'COLON') {
|
|
13772
|
+
this.eat('COLON');
|
|
13773
|
+
if (this.current.type !== 'RBRACKET' && this.current.type !== 'COLON') {
|
|
13774
|
+
end = this.expression();
|
|
13775
|
+
}
|
|
13776
|
+
if (this.current.type === 'COLON') {
|
|
13777
|
+
this.eat('COLON');
|
|
13778
|
+
if (this.current.type !== 'RBRACKET') {
|
|
13779
|
+
step = this.expression();
|
|
13780
|
+
}
|
|
13781
|
+
}
|
|
13782
|
+
if (this.current.type !== 'RBRACKET') {
|
|
13783
|
+
throw new ParseError("Expected ']' after slice", this.current, this.source);
|
|
13784
|
+
}
|
|
13785
|
+
this.eat('RBRACKET');
|
|
13331
13786
|
|
|
13332
|
-
|
|
13333
|
-
|
|
13334
|
-
|
|
13335
|
-
|
|
13336
|
-
|
|
13337
|
-
|
|
13338
|
-
|
|
13339
|
-
column: startCol
|
|
13340
|
-
};
|
|
13787
|
+
node = { type: 'SliceExpression', object: node, start, end, step, line: startLine, column: startCol };
|
|
13788
|
+
} else {
|
|
13789
|
+
this.eat('RBRACKET');
|
|
13790
|
+
node = { type: 'IndexExpression', object: node, indexer: start, line: startLine, column: startCol };
|
|
13791
|
+
}
|
|
13792
|
+
}
|
|
13793
|
+
continue; // continue to allow . or () after []
|
|
13341
13794
|
}
|
|
13342
|
-
}
|
|
13343
|
-
}
|
|
13344
|
-
|
|
13345
|
-
|
|
13346
13795
|
|
|
13796
|
+
// Handle function call
|
|
13347
13797
|
if (t.type === 'LPAREN') {
|
|
13348
13798
|
const startLine = t.line;
|
|
13349
13799
|
const startCol = t.column;
|
|
13350
13800
|
this.eat('LPAREN');
|
|
13351
13801
|
|
|
13352
13802
|
const args = [];
|
|
13353
|
-
|
|
13354
13803
|
while (this.current.type !== 'RPAREN') {
|
|
13355
13804
|
if (this.current.type === 'EOF') {
|
|
13356
|
-
throw new ParseError(
|
|
13357
|
-
"Unterminated function call",
|
|
13358
|
-
this.current,
|
|
13359
|
-
this.source,
|
|
13360
|
-
"Did you forget to close ')'?"
|
|
13361
|
-
);
|
|
13805
|
+
throw new ParseError("Unterminated function call", this.current, this.source, "Did you forget to close ')'?");
|
|
13362
13806
|
}
|
|
13363
|
-
|
|
13364
13807
|
args.push(this.expression());
|
|
13365
|
-
|
|
13366
|
-
if (this.current.type === 'COMMA') {
|
|
13367
|
-
this.eat('COMMA');
|
|
13368
|
-
} else {
|
|
13369
|
-
break;
|
|
13370
|
-
}
|
|
13371
|
-
}
|
|
13372
|
-
|
|
13373
|
-
if (this.current.type !== 'RPAREN') {
|
|
13374
|
-
throw new ParseError(
|
|
13375
|
-
"Expected ')' after function arguments",
|
|
13376
|
-
this.current,
|
|
13377
|
-
this.source,
|
|
13378
|
-
"Function calls must be closed with ')'"
|
|
13379
|
-
);
|
|
13808
|
+
if (this.current.type === 'COMMA') this.eat('COMMA');
|
|
13380
13809
|
}
|
|
13381
13810
|
|
|
13382
13811
|
this.eat('RPAREN');
|
|
13383
13812
|
|
|
13384
|
-
node = {
|
|
13385
|
-
type: 'CallExpression',
|
|
13386
|
-
callee: node,
|
|
13387
|
-
arguments: args,
|
|
13388
|
-
line: startLine,
|
|
13389
|
-
column: startCol
|
|
13390
|
-
};
|
|
13813
|
+
node = { type: 'CallExpression', callee: node, arguments: args, line: startLine, column: startCol };
|
|
13391
13814
|
continue;
|
|
13392
13815
|
}
|
|
13393
13816
|
|
|
13817
|
+
// Handle member access
|
|
13394
13818
|
if (t.type === 'DOT') {
|
|
13395
13819
|
const startLine = t.line;
|
|
13396
13820
|
const startCol = t.column;
|
|
13397
13821
|
this.eat('DOT');
|
|
13398
13822
|
|
|
13399
13823
|
if (this.current.type !== 'IDENTIFIER') {
|
|
13400
|
-
throw new ParseError(
|
|
13401
|
-
"Expected property name after '.'",
|
|
13402
|
-
this.current,
|
|
13403
|
-
this.source,
|
|
13404
|
-
"Member access requires a property name, e.g. obj.value"
|
|
13405
|
-
);
|
|
13824
|
+
throw new ParseError("Expected property name after '.'", this.current, this.source, "Member access requires a property name, e.g. obj.value");
|
|
13406
13825
|
}
|
|
13407
13826
|
|
|
13408
13827
|
const property = this.current.value;
|
|
13409
13828
|
this.eat('IDENTIFIER');
|
|
13410
13829
|
|
|
13411
|
-
node = {
|
|
13412
|
-
type: 'MemberExpression',
|
|
13413
|
-
object: node,
|
|
13414
|
-
property,
|
|
13415
|
-
line: startLine,
|
|
13416
|
-
column: startCol
|
|
13417
|
-
};
|
|
13830
|
+
node = { type: 'MemberExpression', object: node, property, line: startLine, column: startCol };
|
|
13418
13831
|
continue;
|
|
13419
13832
|
}
|
|
13420
13833
|
|
|
13834
|
+
// Handle postfix update operators
|
|
13421
13835
|
if (t.type === 'PLUSPLUS' || t.type === 'MINUSMINUS') {
|
|
13422
13836
|
this.eat(t.type);
|
|
13423
|
-
|
|
13424
|
-
node = {
|
|
13425
|
-
type: 'UpdateExpression',
|
|
13426
|
-
operator: t.type,
|
|
13427
|
-
argument: node,
|
|
13428
|
-
prefix: false,
|
|
13429
|
-
line: t.line,
|
|
13430
|
-
column: t.column
|
|
13431
|
-
};
|
|
13837
|
+
node = { type: 'UpdateExpression', operator: t.type, argument: node, prefix: false, line: t.line, column: t.column };
|
|
13432
13838
|
continue;
|
|
13433
13839
|
}
|
|
13434
13840
|
|
|
@@ -13438,6 +13844,7 @@ postfix() {
|
|
|
13438
13844
|
return node;
|
|
13439
13845
|
}
|
|
13440
13846
|
|
|
13847
|
+
|
|
13441
13848
|
arrowFunction(params) {
|
|
13442
13849
|
const t = this.current;
|
|
13443
13850
|
this.eat('ARROW');
|
|
@@ -13788,8 +14195,8 @@ if (t.type === 'FUNC') {
|
|
|
13788
14195
|
}
|
|
13789
14196
|
|
|
13790
14197
|
}
|
|
13791
|
-
|
|
13792
|
-
|
|
14198
|
+
module.exports = Parser;
|
|
14199
|
+
|
|
13793
14200
|
|
|
13794
14201
|
/***/ }),
|
|
13795
14202
|
|
|
@@ -13969,7 +14376,7 @@ const Lexer = __nccwpck_require__(211);
|
|
|
13969
14376
|
const Parser = __nccwpck_require__(222);
|
|
13970
14377
|
const Evaluator = __nccwpck_require__(112);
|
|
13971
14378
|
|
|
13972
|
-
const VERSION = '1.1.
|
|
14379
|
+
const VERSION = '1.1.18';
|
|
13973
14380
|
|
|
13974
14381
|
const COLOR = {
|
|
13975
14382
|
reset: '\x1b[0m',
|
|
@@ -14129,7 +14536,7 @@ Usage:
|
|
|
14129
14536
|
|
|
14130
14537
|
if (args[0] === '-v' || args[0] === '--version') {
|
|
14131
14538
|
console.log(`${COLOR.bold}Starlight CLI v${VERSION}${COLOR.reset}`);
|
|
14132
|
-
console.log(`${COLOR.magenta}Developed by Macedon${COLOR.reset}`);
|
|
14539
|
+
console.log(`${COLOR.magenta}Developed by Dominex Macedon${COLOR.reset}`);
|
|
14133
14540
|
process.exit(0);
|
|
14134
14541
|
}
|
|
14135
14542
|
|