@tokens-studio/tokenscript-interpreter 0.36.4 → 0.37.1
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/chunk-3D6X7EAK.js +6605 -0
- package/dist/chunk-3D6X7EAK.js.map +1 -0
- package/dist/chunk-6KHDVYST.js +6616 -0
- package/dist/chunk-6KHDVYST.js.map +1 -0
- package/dist/chunk-6MXPTXGR.js +6591 -0
- package/dist/chunk-6MXPTXGR.js.map +1 -0
- package/dist/chunk-EM64RW7I.js +6592 -0
- package/dist/chunk-EM64RW7I.js.map +1 -0
- package/dist/chunk-H7YXFZ4I.js +6605 -0
- package/dist/chunk-H7YXFZ4I.js.map +1 -0
- package/dist/chunk-Z437BNC5.js +107 -0
- package/dist/chunk-Z437BNC5.js.map +1 -0
- package/dist/cli.js +149 -16
- package/dist/cli.js.map +1 -1
- package/dist/compliance-suite.js +3 -5
- package/dist/compliance-suite.js.map +1 -1
- package/dist/config-B-kbeoff.d.ts +927 -0
- package/dist/config-Mw_Iq324.d.ts +921 -0
- package/dist/lib/{chunk-S7WGJBSX.js → chunk-24FMHL6W.js} +16 -3
- package/dist/lib/chunk-24FMHL6W.js.map +1 -0
- package/dist/lib/{chunk-2BDFE7U4.js → chunk-4L54VFWU.js} +132 -15
- package/dist/lib/chunk-4L54VFWU.js.map +1 -0
- package/dist/lib/{chunk-UF6I25ED.cjs → chunk-KX5QZ5G2.cjs} +685 -567
- package/dist/lib/chunk-KX5QZ5G2.cjs.map +1 -0
- package/dist/lib/{chunk-K65UI6KX.cjs → chunk-OABJLZRZ.cjs} +113 -100
- package/dist/lib/chunk-OABJLZRZ.cjs.map +1 -0
- package/dist/lib/{chunk-AEOBCHBK.js → chunk-SLITBMFB.js} +10 -3
- package/dist/lib/chunk-SLITBMFB.js.map +1 -0
- package/dist/lib/{chunk-KHF2VXWO.cjs → chunk-ZMMIYWFF.cjs} +10 -2
- package/dist/lib/chunk-ZMMIYWFF.cjs.map +1 -0
- package/dist/lib/index.cjs +99 -91
- package/dist/lib/index.d.cts +4 -4
- package/dist/lib/index.d.ts +4 -4
- package/dist/lib/index.js +3 -3
- package/dist/lib/{interpreter-DdF_Hj-J.d.ts → interpreter-B7BcLEBz.d.cts} +54 -4
- package/dist/lib/{interpreter-Cz_vWDDa.d.cts → interpreter-wKto6JTb.d.ts} +54 -4
- package/dist/lib/interpreter.cjs +81 -73
- package/dist/lib/interpreter.d.cts +7 -6
- package/dist/lib/interpreter.d.ts +7 -6
- package/dist/lib/interpreter.js +3 -3
- package/dist/lib/processor-node.cjs +12 -12
- package/dist/lib/processor-node.d.cts +3 -3
- package/dist/lib/processor-node.d.ts +3 -3
- package/dist/lib/processor-node.js +3 -3
- package/dist/lib/processor.cjs +17 -17
- package/dist/lib/processor.d.cts +4 -4
- package/dist/lib/processor.d.ts +4 -4
- package/dist/lib/processor.js +3 -3
- package/dist/lib/schema.cjs +5 -5
- package/dist/lib/schema.d.cts +1 -1
- package/dist/lib/schema.d.ts +1 -1
- package/dist/lib/schema.js +3 -3
- package/dist/lib/syntax-highlighting.cjs +15 -15
- package/dist/lib/syntax-highlighting.d.cts +1 -1
- package/dist/lib/syntax-highlighting.d.ts +1 -1
- package/dist/lib/syntax-highlighting.js +2 -2
- package/dist/lib/{types-DRpZJjkx.d.ts → types-BHcQYEQ-.d.ts} +2 -2
- package/dist/lib/{types-CxQPMHn1.d.ts → types-BMYcHiSq.d.cts} +9 -1
- package/dist/lib/{types-CxQPMHn1.d.cts → types-BMYcHiSq.d.ts} +9 -1
- package/dist/lib/{types-6QQt-XVS.d.cts → types-BOyxzACN.d.cts} +2 -2
- package/dist/lib/types.cjs +10 -6
- package/dist/lib/types.d.cts +1 -1
- package/dist/lib/types.d.ts +1 -1
- package/dist/lib/types.js +1 -1
- package/dist/processor/index.d.ts +1 -1
- package/dist/processor/index.js +18 -2
- package/dist/processor/index.js.map +1 -1
- package/dist/repl.d.ts +15 -3
- package/dist/repl.js +6 -8
- package/dist/repl.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/package.json +1 -1
- package/dist/lib/chunk-2BDFE7U4.js.map +0 -1
- package/dist/lib/chunk-AEOBCHBK.js.map +0 -1
- package/dist/lib/chunk-K65UI6KX.cjs.map +0 -1
- package/dist/lib/chunk-KHF2VXWO.cjs.map +0 -1
- package/dist/lib/chunk-S7WGJBSX.js.map +0 -1
- package/dist/lib/chunk-UF6I25ED.cjs.map +0 -1
package/dist/compliance-suite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BaseSymbolType, InterpreterError, LexerError, ParserError,
|
|
2
|
-
import './chunk-
|
|
1
|
+
import { BaseSymbolType, InterpreterError, LexerError, ParserError, parseExpression, Config, Interpreter, ColorSymbol, ColorManager, isArray, isObject, NumberWithUnitSymbol } from './chunk-6KHDVYST.js';
|
|
2
|
+
import './chunk-Z437BNC5.js';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
|
|
@@ -93,9 +93,7 @@ function transformContextToSymbols(obj, config) {
|
|
|
93
93
|
]);
|
|
94
94
|
}
|
|
95
95
|
var runTest = (test) => {
|
|
96
|
-
const
|
|
97
|
-
const parser = new Parser(lexer);
|
|
98
|
-
const ast = parser.parse(test.inline);
|
|
96
|
+
const { ast } = parseExpression(test.input, { mode: test.inline ? "inline" : "script" });
|
|
99
97
|
let config;
|
|
100
98
|
if (test.schemas && test.schemas.length > 0) {
|
|
101
99
|
const colorManager = loadSchemas(test.schemas);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/interpreter/utils/coll.ts","../src/compliance-suite.ts"],"names":["config","path"],"mappings":";;;;;;AAyBO,SAAS,OAAA,CACd,GACA,IAAA,EACgB;AAChB,EAAA,MAAM,SAAS,EAAC;AAEhB,EAAA,KAAA,MAAW,QAAQ,IAAA,EAAM;AACvB,IAAA,MAAM,GAAA,GAAM,EAAE,IAAI,CAAA;AAClB,IAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,MAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AAAA,IACvB,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,CAAC,IAAI,CAAA;AAAA,IACrB;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;;;ACHA,IAAM,eAAA,GAA0C;AAAA,EAC9C,6EAAA,EACE,uCAAA;AAAA,EACF,8EAAA,EACE,wCAAA;AAAA,EACF,6EAAA,EACE,uCAAA;AAAA,EACF,8EAAA,EACE;AACJ,CAAA;AAEA,SAAS,YAAY,OAAA,EAAiC;AACpD,EAAA,MAAM,YAAA,GAAe,IAAI,YAAA,EAAa;AAEtC,EAAA,KAAA,MAAW,aAAa,OAAA,EAAS;AAC/B,IAAA,MAAM,QAAA,GAAW,gBAAgB,SAAS,CAAA;AAC1C,IAAA,IAAI,QAAA,IAAY,EAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AACvC,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,EAAA,CAAG,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAClD,QAAA,YAAA,CAAa,QAAA,CAAS,WAAW,QAAQ,CAAA;AAAA,MAC3C,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAK,CAAA,sBAAA,EAAyB,SAAS,CAAA,MAAA,EAAS,QAAQ,KAAK,KAAK,CAAA;AAAA,MAC5E;AAAA,IACF,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,kCAAA,EAAqC,SAAS,CAAA,CAAE,CAAA;AAAA,IAC/D;AAAA,EACF;AAEA,EAAA,OAAO,YAAA;AACT;AAEA,SAAS,yBAAyB,GAAA,EAAuB;AACvD,EAAA,IAAI,UAAoB,EAAC;AACzB,EAAA,MAAM,IAAA,GAAO,EAAA,CAAG,WAAA,CAAY,GAAG,CAAA;AAC/B,EAAA,IAAA,CAAK,OAAA,CAAQ,CAAC,IAAA,KAAS;AACrB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,IAAI,CAAA;AACpC,IAAA,MAAM,IAAA,GAAO,EAAA,CAAG,QAAA,CAAS,QAAQ,CAAA;AACjC,IAAA,IAAI,IAAA,EAAM,aAAY,EAAG;AACvB,MAAA,OAAA,GAAU,OAAA,CAAQ,MAAA,CAAO,wBAAA,CAAyB,QAAQ,CAAC,CAAA;AAAA,IAC7D,CAAA,MAAA,IAAW,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA,EAAG;AACjC,MAAA,OAAA,CAAQ,KAAK,QAAQ,CAAA;AAAA,IACvB;AAAA,EACF,CAAC,CAAA;AACD,EAAA,OAAO,OAAA;AACT;AAQA,IAAM,kBAAA,GAAqB,CAAC,IAAA,EAAc,QAAA,KAAiC;AACzE,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AACjC,IAAA,OAAO,CAAC,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAA,GAAI,CAAC,SAAS,CAAA,GAAI,SAAA;AAAA,EACnD,SAAS,EAAA,EAAI;AACX,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,QAAQ,CAAA,CAAE,CAAA;AAAA,EAC7D;AACF,CAAA;AAEA,SAAS,sBAAA,CACP,GAAA,EACA,MAAA,EACA,GAAA,EACK;AACL,EAAA,KAAA,MAAW,QAAQ,GAAA,EAAK;AACtB,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,EAAK,MAAM,CAAA;AACpC,IAAA,IAAI,OAAO,gBAAgB,WAAA,EAAa;AACtC,MAAA,OAAO,WAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,IAAI,OAAA,CAAQ,GAAG,CAAA,EAAG;AAChB,IAAA,OAAO,GAAA,CAAI,IAAI,CAAC,EAAA,KAAO,uBAAuB,EAAA,EAAI,MAAA,EAAQ,GAAG,CAAC,CAAA;AAAA,EAChE;AACA,EAAA,IAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AACjB,IAAA,MAAM,MAA2B,EAAC;AAClC,IAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AACxC,MAAA,GAAA,CAAI,CAAC,CAAA,GAAI,sBAAA,CAAuB,CAAA,EAAG,QAAQ,GAAG,CAAA;AAAA,IAChD;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,yBAAA,CAA0B,KAAU,MAAA,EAAqB;AAChE,EAAA,OAAO,sBAAA,CAAuB,KAAK,MAAA,EAAQ;AAAA,IACzC,CAAC,KAAUA,OAAAA,KAAmB;AAC5B,MAAA,IAAI,QAAA,CAAS,GAAG,CAAA,IAAK,GAAA,CAAI,SAAS,gBAAA,EAAkB;AAClD,QAAA,MAAM,SAAA,GAAY,GAAA;AAClB,QAAA,OAAO,IAAI,oBAAA,CAAqB,SAAA,CAAU,SAAS,IAAA,EAAM,SAAA,CAAU,MAAMA,OAAM,CAAA;AAAA,MACjF;AAAA,IACF;AAAA,GACD,CAAA;AACH;AAEA,IAAM,OAAA,GAAU,CAAC,IAAA,KAA4E;AAC3F,EAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,IAAA,CAAK,KAAK,CAAA;AAClC,EAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO,KAAK,CAAA;AAC/B,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA;AAEpC,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC3C,IAAA,MAAM,YAAA,GAAe,WAAA,CAAY,IAAA,CAAK,OAAO,CAAA;AAC7C,IAAA,MAAA,GAAS,IAAI,MAAA,CAAO,EAAE,YAAA,EAAc,CAAA;AAAA,EACtC,CAAA,MAAO;AACL,IAAA,MAAA,GAAS,IAAI,MAAA,EAAO;AAAA,EACtB;AAEA,EAAA,MAAM,UAAA,GAAa,KAAK,OAAA,GAAU,yBAAA,CAA0B,KAAK,OAAA,EAAS,MAAM,IAAI,EAAC;AACrF,EAAA,MAAM,cAAc,IAAI,WAAA,CAAY,KAAK,EAAE,UAAA,EAAY,QAAQ,CAAA;AAC/D,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,MAAA,EAAQ,YAAY,SAAA;AAAU,GAChC;AACF,CAAA;AAQA,IAAM,mCAAA,GAAsC,CAC1C,MAAA,EACA,WAAA,KACqB;AAErB,EAAA,IAAI,kBAAkB,WAAA,EAAa;AACjC,IAAA,OAAO;AAAA,MACL,YAAA,EAAc,WAAA,CAAY,MAAA,CAAO,YAAA,CAAa,kBAAkB,MAAM,CAAA;AAAA,MACtE,gBAAA,EAAkB,OAAO,WAAA;AAAY,KACvC;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,YAAA,EAAc,OAAO,QAAA,EAAS;AAAA,IAC9B,gBAAA,EAAkB,OAAO,WAAA;AAAY,GACvC;AACF,CAAA;AAEA,IAAM,cAAA,GAAiB,CACrB,gBAAA,EACA,QAAA,KACwB;AACxB,EAAA,MAAM,WAAA,GAAc,gBAAA,CAAiB,gBAAA,KAAqB,QAAA,CAAS,kBAAA;AAGnE,EAAA,IAAI,SAAS,iBAAA,EAAmB;AAC9B,IAAA,OAAO,WAAA,IAAe,gBAAA,CAAiB,eAAA,KAAoB,QAAA,CAAS,oBAChE,QAAA,GACA,QAAA;AAAA,EACN;AAGA,EAAA,OAAO,WAAA,IAAe,gBAAA,CAAiB,YAAA,KAAiB,QAAA,CAAS,iBAC7D,QAAA,GACA,QAAA;AACN,CAAA;AAEA,eAAsB,2BAA2B,MAAA,EAA0B;AACzE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,GACjB,CAAC,MAAA,CAAO,IAAI,CAAA,GACZ,MAAA,CAAO,GAAA,GACL,wBAAA,CAAyB,MAAA,CAAO,GAAG,IACnC,EAAC;AAEP,EAAA,MAAM,WAAA,GAA4B,KAAA,CAAM,OAAA,CAAQ,CAACC,KAAAA,KAAS;AACxD,IAAA,MAAM,OAAA,GAAU,EAAA,CAAG,YAAA,CAAaA,KAAAA,EAAM,OAAO,CAAA;AAC7C,IAAA,MAAM,SAAA,GAAwB,kBAAA,CAAmB,OAAA,EAASA,KAAI,CAAA;AAE9D,IAAA,OAAO,SAAA,CAAU,GAAA,CAAI,CAAC,QAAA,KAAa;AACjC,MAAA,IAAI,UAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAY,GAAI,QAAQ,QAAQ,CAAA;AAChD,QAAA,IAAI,EAAE,kBAAkB,cAAA,CAAA,EAAiB;AACvC,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,MAAM,CAAA,6BAAA,CAA+B,CAAA;AAAA,QAClE;AACA,QAAA,MAAM,gBAAA,GAAmB,mCAAA,CAAoC,MAAA,EAAQ,WAAW,CAAA;AAChF,QAAA,UAAA,GAAa;AAAA,UACX,GAAG,QAAA;AAAA,UACH,GAAG,gBAAA;AAAA,UACH,IAAA,EAAMA,KAAAA;AAAA,UACN,MAAA,EAAQ,cAAA,CAAe,gBAAA,EAAkB,QAAQ;AAAA,SACnD;AAAA,MACF,SAAS,CAAA,EAAQ;AACf,QAAA,IAAI,CAAA,YAAa,gBAAA,IAAoB,CAAA,YAAa,UAAA,IAAc,aAAa,WAAA,EAAa;AACxF,UAAA,MAAM,gBAAA,GAAqC;AAAA,YACzC,YAAA,EAAc,EAAE,eAAA,IAAmB,EAAA;AAAA,YACnC,gBAAA,EAAkB,OAAA;AAAA,YAClB,iBAAiB,CAAA,CAAE;AAAA,WACrB;AACA,UAAA,OAAO;AAAA,YACL,GAAG,QAAA;AAAA,YACH,GAAG,gBAAA;AAAA,YACH,IAAA,EAAMA,KAAAA;AAAA,YACN,MAAA,EAAQ,cAAA,CAAe,gBAAA,EAAkB,QAAQ,CAAA;AAAA,YACjD,KAAA,EAAO;AAAA,WACT;AAAA,QACF;AACA,QAAA,MAAM,CAAA;AAAA,MACR;AAEA,MAAA,OAAO;AAAA,QACL,GAAG,QAAA;AAAA,QACH,GAAG,UAAA;AAAA,QACH,MAAA,EAAQ,QAAA;AAAA,QACR,IAAA,EAAMA;AAAA,OACR;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AAED,EAAA,MAAM,EAAE,MAAA,GAAS,EAAC,EAAG,MAAA,GAAS,EAAC,EAAE,GAAI,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,WAAW,CAAA;AAGzE,EAAA,MAAM,iBAAiB,WAAA,CAAY,GAAA;AAAA,IACjC,CAAC;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA,EAAAA,KAAAA;AAAA,MACA,MAAA;AAAA,MACA,YAAA;AAAA,MACA,gBAAA;AAAA,MACA,eAAA;AAAA,MACA,cAAA;AAAA,MACA,kBAAA;AAAA,MACA,iBAAA;AAAA,MACA,GAAG;AAAA,KACL,MAAO;AAAA,MACL,IAAA;AAAA,MACA,IAAA,EAAAA,KAAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,KAAA;AAAA,MACA,YAAA;AAAA,MACA,gBAAA;AAAA,MACA,GAAI,eAAA,GAAkB,EAAE,eAAA,KAAoB,EAAC;AAAA,MAC7C,cAAA;AAAA,MACA,kBAAA;AAAA,MACA,GAAI,iBAAA,GAAoB,EAAE,iBAAA,KAAsB,EAAC;AAAA,MACjD,GAAG;AAAA,KACL;AAAA,GACF;AAEA,EAAA,MAAM,MAAA,GAA2B;AAAA,IAC/B,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,OAAA,EAAS;AAAA,GACX;AAEA,EAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,IAAA,EAAA,CAAG,aAAA,CAAc,OAAO,MAAA,EAAQ,IAAA,CAAK,UAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAA,EAAG,OAAO,CAAA;AAAA,EAC1E;AAEA,EAAA,OAAO,MAAA;AACT","file":"compliance-suite.js","sourcesContent":["/**\n * Groups elements of a collection by the result of applying a function to each element.\n * Returns a record where keys are the results of the grouping function and values are arrays\n * of the corresponding elements, preserving their original order.\n *\n * @param f - The grouping function to apply to each element\n * @param coll - The collection to group\n * @returns A record mapping grouping keys to arrays of elements\n *\n * @example\n * ```typescript\n * // Group strings by length\n * groupBy((s: string) => s.length, [\"a\", \"as\", \"asd\", \"aa\", \"asdf\", \"qwer\"])\n * // => { \"1\": [\"a\"], \"2\": [\"as\", \"aa\"], \"3\": [\"asd\"], \"4\": [\"asdf\", \"qwer\"] }\n *\n * // Group numbers by odd/even\n * groupBy((n: number) => n % 2 === 1, [0, 1, 2, 3, 4, 5])\n * // => { \"false\": [0, 2, 4], \"true\": [1, 3, 5] }\n *\n * // Group objects by property\n * groupBy((obj: {category: string}) => obj.category,\n * [{category: \"a\", id: 1}, {category: \"b\", id: 2}, {category: \"a\", id: 3}])\n * // => { \"a\": [{category: \"a\", id: 1}, {category: \"a\", id: 3}], \"b\": [{category: \"b\", id: 2}] }\n * ```\n */\nexport function groupBy<T, K extends PropertyKey>(\n f: (item: T) => K,\n coll: readonly T[],\n): Record<K, T[]> {\n const result = {} as Record<K, T[]>;\n\n for (const item of coll) {\n const key = f(item);\n if (key in result) {\n result[key].push(item);\n } else {\n result[key] = [item];\n }\n }\n\n return result;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Config } from \"@interpreter/config/config\";\nimport { ColorManager } from \"@interpreter/config/managers/color/manager\";\nimport { Interpreter, type InterpreterResult } from \"@interpreter/interpreter\";\nimport { Lexer } from \"@interpreter/lexer\";\nimport { Parser } from \"@interpreter/parser\";\nimport { BaseSymbolType, ColorSymbol, NumberWithUnitSymbol } from \"@interpreter/symbols\";\nimport { groupBy } from \"./interpreter/utils/coll\";\nimport { isArray, isObject } from \"./interpreter/utils/type\";\nimport { InterpreterError, type ISymbolType, LexerError, ParserError } from \"./lib\";\n\ninterface TestCase {\n name: string;\n input: string;\n expectedOutput?: any;\n expectedOutputType: string;\n expectedErrorCode?: string;\n inline: boolean;\n context?: Record<string, any>;\n schemas?: string[];\n path: string;\n}\n\ninterface TestResult extends TestCase {\n status: \"passed\" | \"failed\";\n actualOutput: any;\n actualOutputType: string;\n actualErrorCode?: string;\n error?: Error;\n}\n\ninterface ComplianceReport {\n passed: number;\n failed: number;\n results: TestResult[];\n}\n\nconst SCHEMA_FILE_MAP: Record<string, string> = {\n \"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/hsl-color/0/\":\n \"./data/specifications/colors/hsl.json\",\n \"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/srgb-color/0/\":\n \"./data/specifications/colors/srgb.json\",\n \"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/rgb-color/0/\":\n \"./data/specifications/colors/rgb.json\",\n \"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/lrgb-color/0/\":\n \"./data/specifications/colors/lrgb.json\",\n};\n\nfunction loadSchemas(schemas: string[]): ColorManager {\n const colorManager = new ColorManager();\n\n for (const schemaUri of schemas) {\n const filePath = SCHEMA_FILE_MAP[schemaUri];\n if (filePath && fs.existsSync(filePath)) {\n try {\n const specData = fs.readFileSync(filePath, \"utf-8\");\n colorManager.register(schemaUri, specData);\n } catch (error) {\n console.warn(`Failed to load schema ${schemaUri} from ${filePath}:`, error);\n }\n } else {\n console.warn(`No file mapping found for schema: ${schemaUri}`);\n }\n }\n\n return colorManager;\n}\n\nfunction readJsonFilesRecursively(dir: string): string[] {\n let results: string[] = [];\n const list = fs.readdirSync(dir);\n list.forEach((file) => {\n const filePath = path.join(dir, file);\n const stat = fs.statSync(filePath);\n if (stat?.isDirectory()) {\n results = results.concat(readJsonFilesRecursively(filePath));\n } else if (file.endsWith(\".json\")) {\n results.push(filePath);\n }\n });\n return results;\n}\n\ninterface ComplianceConfig {\n dir?: string;\n file?: string;\n output?: string;\n}\n\nconst parseTestCasesJson = (json: string, filePath: string): TestCase[] => {\n try {\n const testCases = JSON.parse(json);\n return !Array.isArray(testCases) ? [testCases] : testCases;\n } catch (_e) {\n throw new Error(`Could not parse json at path: ${filePath}`);\n }\n};\n\nfunction normalizeContextObject(\n obj: any,\n config: Config,\n fns: Array<(obj: any, config: Config) => any>,\n): any {\n for (const rule of fns) {\n const transformed = rule(obj, config);\n if (typeof transformed !== \"undefined\") {\n return transformed;\n }\n }\n if (isArray(obj)) {\n return obj.map((el) => normalizeContextObject(el, config, fns));\n }\n if (isObject(obj)) {\n const out: Record<string, any> = {};\n for (const [k, v] of Object.entries(obj)) {\n out[k] = normalizeContextObject(v, config, fns);\n }\n return out;\n }\n return obj;\n}\n\nfunction transformContextToSymbols(obj: any, config: Config): any {\n return normalizeContextObject(obj, config, [\n (val: any, config: Config) => {\n if (isObject(val) && val.type === \"NumberWithUnit\") {\n const numberVal = val as unknown as NumberWithUnitSymbol;\n return new NumberWithUnitSymbol(numberVal.value ?? null, numberVal.unit, config);\n }\n },\n ]);\n}\n\nconst runTest = (test: TestCase): { interpreter: Interpreter; result: InterpreterResult } => {\n const lexer = new Lexer(test.input);\n const parser = new Parser(lexer);\n const ast = parser.parse(test.inline);\n\n let config: Config;\n if (test.schemas && test.schemas.length > 0) {\n const colorManager = loadSchemas(test.schemas);\n config = new Config({ colorManager });\n } else {\n config = new Config();\n }\n\n const references = test.context ? transformContextToSymbols(test.context, config) : {};\n const interpreter = new Interpreter(ast, { references, config });\n return {\n interpreter,\n result: interpreter.interpret(),\n };\n};\n\ninterface ComplianceResult {\n actualOutput: string;\n actualOutputType: string;\n actualErrorCode?: string;\n}\n\nconst interpreterSymbolToComplianceResult = (\n symbol: ISymbolType,\n interpreter: Interpreter,\n): ComplianceResult => {\n // Colors need to be formatted using ColorManager, as we need the order rules\n if (symbol instanceof ColorSymbol) {\n return {\n actualOutput: interpreter.config.colorManager.formatColorMethod(symbol),\n actualOutputType: symbol.getTypeName(),\n };\n }\n\n return {\n actualOutput: symbol.toString(),\n actualOutputType: symbol.getTypeName(),\n };\n};\n\nconst compareResults = (\n complianceResult: ComplianceResult,\n testCase: TestCase,\n): \"passed\" | \"failed\" => {\n const typeMatches = complianceResult.actualOutputType === testCase.expectedOutputType;\n\n // When expectedErrorCode is set, match on error code (and type) only\n if (testCase.expectedErrorCode) {\n return typeMatches && complianceResult.actualErrorCode === testCase.expectedErrorCode\n ? \"passed\"\n : \"failed\";\n }\n\n // Otherwise match on output value and type\n return typeMatches && complianceResult.actualOutput === testCase.expectedOutput\n ? \"passed\"\n : \"failed\";\n};\n\nexport async function evaluateStandardCompliance(config: ComplianceConfig) {\n const files = config.file\n ? [config.file]\n : config.dir\n ? readJsonFilesRecursively(config.dir)\n : [];\n\n const testResults: TestResult[] = files.flatMap((path) => {\n const content = fs.readFileSync(path, \"utf-8\");\n const testCases: TestCase[] = parseTestCasesJson(content, path);\n\n return testCases.map((testCase) => {\n let testResult: TestResult;\n try {\n const { result, interpreter } = runTest(testCase);\n if (!(result instanceof BaseSymbolType)) {\n throw new Error(`result (${result}) in s not interpreter Symbol`);\n }\n const complianceResult = interpreterSymbolToComplianceResult(result, interpreter);\n testResult = {\n ...testCase,\n ...complianceResult,\n path: path,\n status: compareResults(complianceResult, testCase),\n };\n } catch (e: any) {\n if (e instanceof InterpreterError || e instanceof LexerError || e instanceof ParserError) {\n const complianceResult: ComplianceResult = {\n actualOutput: e.originalMessage || \"\",\n actualOutputType: \"Error\",\n actualErrorCode: e.code,\n };\n return {\n ...testCase,\n ...complianceResult,\n path: path,\n status: compareResults(complianceResult, testCase),\n error: e,\n };\n }\n throw e;\n }\n\n return {\n ...testCase,\n ...testResult,\n status: \"passed\",\n path: path,\n };\n });\n });\n\n const { passed = [], failed = [] } = groupBy((x) => x.status, testResults);\n\n // Order keys for json output\n const orderedResults = testResults.map(\n ({\n name,\n input,\n inline,\n context,\n path,\n status,\n actualOutput,\n actualOutputType,\n actualErrorCode,\n expectedOutput,\n expectedOutputType,\n expectedErrorCode,\n ...rest\n }) => ({\n name,\n path,\n status,\n inline,\n context,\n input,\n actualOutput,\n actualOutputType,\n ...(actualErrorCode ? { actualErrorCode } : {}),\n expectedOutput,\n expectedOutputType,\n ...(expectedErrorCode ? { expectedErrorCode } : {}),\n ...rest,\n }),\n );\n\n const report: ComplianceReport = {\n passed: passed.length,\n failed: failed.length,\n results: orderedResults,\n };\n\n if (config.output) {\n fs.writeFileSync(config.output, JSON.stringify(report, null, 2), \"utf-8\");\n }\n\n return report;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/interpreter/utils/coll.ts","../src/compliance-suite.ts"],"names":["config","path"],"mappings":";;;;;;AAyBO,SAAS,OAAA,CACd,GACA,IAAA,EACgB;AAChB,EAAA,MAAM,SAAS,EAAC;AAEhB,EAAA,KAAA,MAAW,QAAQ,IAAA,EAAM;AACvB,IAAA,MAAM,GAAA,GAAM,EAAE,IAAI,CAAA;AAClB,IAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,MAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AAAA,IACvB,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,CAAC,IAAI,CAAA;AAAA,IACrB;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;;;ACJA,IAAM,eAAA,GAA0C;AAAA,EAC9C,6EAAA,EACE,uCAAA;AAAA,EACF,8EAAA,EACE,wCAAA;AAAA,EACF,6EAAA,EACE,uCAAA;AAAA,EACF,8EAAA,EACE;AACJ,CAAA;AAEA,SAAS,YAAY,OAAA,EAAiC;AACpD,EAAA,MAAM,YAAA,GAAe,IAAI,YAAA,EAAa;AAEtC,EAAA,KAAA,MAAW,aAAa,OAAA,EAAS;AAC/B,IAAA,MAAM,QAAA,GAAW,gBAAgB,SAAS,CAAA;AAC1C,IAAA,IAAI,QAAA,IAAY,EAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AACvC,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,EAAA,CAAG,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAClD,QAAA,YAAA,CAAa,QAAA,CAAS,WAAW,QAAQ,CAAA;AAAA,MAC3C,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAK,CAAA,sBAAA,EAAyB,SAAS,CAAA,MAAA,EAAS,QAAQ,KAAK,KAAK,CAAA;AAAA,MAC5E;AAAA,IACF,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,kCAAA,EAAqC,SAAS,CAAA,CAAE,CAAA;AAAA,IAC/D;AAAA,EACF;AAEA,EAAA,OAAO,YAAA;AACT;AAEA,SAAS,yBAAyB,GAAA,EAAuB;AACvD,EAAA,IAAI,UAAoB,EAAC;AACzB,EAAA,MAAM,IAAA,GAAO,EAAA,CAAG,WAAA,CAAY,GAAG,CAAA;AAC/B,EAAA,IAAA,CAAK,OAAA,CAAQ,CAAC,IAAA,KAAS;AACrB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,IAAI,CAAA;AACpC,IAAA,MAAM,IAAA,GAAO,EAAA,CAAG,QAAA,CAAS,QAAQ,CAAA;AACjC,IAAA,IAAI,IAAA,EAAM,aAAY,EAAG;AACvB,MAAA,OAAA,GAAU,OAAA,CAAQ,MAAA,CAAO,wBAAA,CAAyB,QAAQ,CAAC,CAAA;AAAA,IAC7D,CAAA,MAAA,IAAW,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA,EAAG;AACjC,MAAA,OAAA,CAAQ,KAAK,QAAQ,CAAA;AAAA,IACvB;AAAA,EACF,CAAC,CAAA;AACD,EAAA,OAAO,OAAA;AACT;AAQA,IAAM,kBAAA,GAAqB,CAAC,IAAA,EAAc,QAAA,KAAiC;AACzE,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AACjC,IAAA,OAAO,CAAC,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAA,GAAI,CAAC,SAAS,CAAA,GAAI,SAAA;AAAA,EACnD,SAAS,EAAA,EAAI;AACX,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,QAAQ,CAAA,CAAE,CAAA;AAAA,EAC7D;AACF,CAAA;AAEA,SAAS,sBAAA,CACP,GAAA,EACA,MAAA,EACA,GAAA,EACK;AACL,EAAA,KAAA,MAAW,QAAQ,GAAA,EAAK;AACtB,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,EAAK,MAAM,CAAA;AACpC,IAAA,IAAI,OAAO,gBAAgB,WAAA,EAAa;AACtC,MAAA,OAAO,WAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,IAAI,OAAA,CAAQ,GAAG,CAAA,EAAG;AAChB,IAAA,OAAO,GAAA,CAAI,IAAI,CAAC,EAAA,KAAO,uBAAuB,EAAA,EAAI,MAAA,EAAQ,GAAG,CAAC,CAAA;AAAA,EAChE;AACA,EAAA,IAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AACjB,IAAA,MAAM,MAA2B,EAAC;AAClC,IAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AACxC,MAAA,GAAA,CAAI,CAAC,CAAA,GAAI,sBAAA,CAAuB,CAAA,EAAG,QAAQ,GAAG,CAAA;AAAA,IAChD;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,yBAAA,CAA0B,KAAU,MAAA,EAAqB;AAChE,EAAA,OAAO,sBAAA,CAAuB,KAAK,MAAA,EAAQ;AAAA,IACzC,CAAC,KAAUA,OAAAA,KAAmB;AAC5B,MAAA,IAAI,QAAA,CAAS,GAAG,CAAA,IAAK,GAAA,CAAI,SAAS,gBAAA,EAAkB;AAClD,QAAA,MAAM,SAAA,GAAY,GAAA;AAClB,QAAA,OAAO,IAAI,oBAAA,CAAqB,SAAA,CAAU,SAAS,IAAA,EAAM,SAAA,CAAU,MAAMA,OAAM,CAAA;AAAA,MACjF;AAAA,IACF;AAAA,GACD,CAAA;AACH;AAEA,IAAM,OAAA,GAAU,CAAC,IAAA,KAA4E;AAC3F,EAAA,MAAM,EAAE,GAAA,EAAI,GAAI,eAAA,CAAgB,IAAA,CAAK,KAAA,EAAO,EAAE,IAAA,EAAM,IAAA,CAAK,MAAA,GAAS,QAAA,GAAW,QAAA,EAAU,CAAA;AAEvF,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC3C,IAAA,MAAM,YAAA,GAAe,WAAA,CAAY,IAAA,CAAK,OAAO,CAAA;AAC7C,IAAA,MAAA,GAAS,IAAI,MAAA,CAAO,EAAE,YAAA,EAAc,CAAA;AAAA,EACtC,CAAA,MAAO;AACL,IAAA,MAAA,GAAS,IAAI,MAAA,EAAO;AAAA,EACtB;AAEA,EAAA,MAAM,UAAA,GAAa,KAAK,OAAA,GAAU,yBAAA,CAA0B,KAAK,OAAA,EAAS,MAAM,IAAI,EAAC;AACrF,EAAA,MAAM,cAAc,IAAI,WAAA,CAAY,KAAK,EAAE,UAAA,EAAY,QAAQ,CAAA;AAC/D,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,MAAA,EAAQ,YAAY,SAAA;AAAU,GAChC;AACF,CAAA;AAQA,IAAM,mCAAA,GAAsC,CAC1C,MAAA,EACA,WAAA,KACqB;AAErB,EAAA,IAAI,kBAAkB,WAAA,EAAa;AACjC,IAAA,OAAO;AAAA,MACL,YAAA,EAAc,WAAA,CAAY,MAAA,CAAO,YAAA,CAAa,kBAAkB,MAAM,CAAA;AAAA,MACtE,gBAAA,EAAkB,OAAO,WAAA;AAAY,KACvC;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,YAAA,EAAc,OAAO,QAAA,EAAS;AAAA,IAC9B,gBAAA,EAAkB,OAAO,WAAA;AAAY,GACvC;AACF,CAAA;AAEA,IAAM,cAAA,GAAiB,CACrB,gBAAA,EACA,QAAA,KACwB;AACxB,EAAA,MAAM,WAAA,GAAc,gBAAA,CAAiB,gBAAA,KAAqB,QAAA,CAAS,kBAAA;AAGnE,EAAA,IAAI,SAAS,iBAAA,EAAmB;AAC9B,IAAA,OAAO,WAAA,IAAe,gBAAA,CAAiB,eAAA,KAAoB,QAAA,CAAS,oBAChE,QAAA,GACA,QAAA;AAAA,EACN;AAGA,EAAA,OAAO,WAAA,IAAe,gBAAA,CAAiB,YAAA,KAAiB,QAAA,CAAS,iBAC7D,QAAA,GACA,QAAA;AACN,CAAA;AAEA,eAAsB,2BAA2B,MAAA,EAA0B;AACzE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,GACjB,CAAC,MAAA,CAAO,IAAI,CAAA,GACZ,MAAA,CAAO,GAAA,GACL,wBAAA,CAAyB,MAAA,CAAO,GAAG,IACnC,EAAC;AAEP,EAAA,MAAM,WAAA,GAA4B,KAAA,CAAM,OAAA,CAAQ,CAACC,KAAAA,KAAS;AACxD,IAAA,MAAM,OAAA,GAAU,EAAA,CAAG,YAAA,CAAaA,KAAAA,EAAM,OAAO,CAAA;AAC7C,IAAA,MAAM,SAAA,GAAwB,kBAAA,CAAmB,OAAA,EAASA,KAAI,CAAA;AAE9D,IAAA,OAAO,SAAA,CAAU,GAAA,CAAI,CAAC,QAAA,KAAa;AACjC,MAAA,IAAI,UAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAY,GAAI,QAAQ,QAAQ,CAAA;AAChD,QAAA,IAAI,EAAE,kBAAkB,cAAA,CAAA,EAAiB;AACvC,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,MAAM,CAAA,6BAAA,CAA+B,CAAA;AAAA,QAClE;AACA,QAAA,MAAM,gBAAA,GAAmB,mCAAA,CAAoC,MAAA,EAAQ,WAAW,CAAA;AAChF,QAAA,UAAA,GAAa;AAAA,UACX,GAAG,QAAA;AAAA,UACH,GAAG,gBAAA;AAAA,UACH,IAAA,EAAMA,KAAAA;AAAA,UACN,MAAA,EAAQ,cAAA,CAAe,gBAAA,EAAkB,QAAQ;AAAA,SACnD;AAAA,MACF,SAAS,CAAA,EAAQ;AACf,QAAA,IAAI,CAAA,YAAa,gBAAA,IAAoB,CAAA,YAAa,UAAA,IAAc,aAAa,WAAA,EAAa;AACxF,UAAA,MAAM,gBAAA,GAAqC;AAAA,YACzC,YAAA,EAAc,EAAE,eAAA,IAAmB,EAAA;AAAA,YACnC,gBAAA,EAAkB,OAAA;AAAA,YAClB,iBAAiB,CAAA,CAAE;AAAA,WACrB;AACA,UAAA,OAAO;AAAA,YACL,GAAG,QAAA;AAAA,YACH,GAAG,gBAAA;AAAA,YACH,IAAA,EAAMA,KAAAA;AAAA,YACN,MAAA,EAAQ,cAAA,CAAe,gBAAA,EAAkB,QAAQ,CAAA;AAAA,YACjD,KAAA,EAAO;AAAA,WACT;AAAA,QACF;AACA,QAAA,MAAM,CAAA;AAAA,MACR;AAEA,MAAA,OAAO;AAAA,QACL,GAAG,QAAA;AAAA,QACH,GAAG,UAAA;AAAA,QACH,MAAA,EAAQ,QAAA;AAAA,QACR,IAAA,EAAMA;AAAA,OACR;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AAED,EAAA,MAAM,EAAE,MAAA,GAAS,EAAC,EAAG,MAAA,GAAS,EAAC,EAAE,GAAI,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,WAAW,CAAA;AAGzE,EAAA,MAAM,iBAAiB,WAAA,CAAY,GAAA;AAAA,IACjC,CAAC;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA,EAAAA,KAAAA;AAAA,MACA,MAAA;AAAA,MACA,YAAA;AAAA,MACA,gBAAA;AAAA,MACA,eAAA;AAAA,MACA,cAAA;AAAA,MACA,kBAAA;AAAA,MACA,iBAAA;AAAA,MACA,GAAG;AAAA,KACL,MAAO;AAAA,MACL,IAAA;AAAA,MACA,IAAA,EAAAA,KAAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,KAAA;AAAA,MACA,YAAA;AAAA,MACA,gBAAA;AAAA,MACA,GAAI,eAAA,GAAkB,EAAE,eAAA,KAAoB,EAAC;AAAA,MAC7C,cAAA;AAAA,MACA,kBAAA;AAAA,MACA,GAAI,iBAAA,GAAoB,EAAE,iBAAA,KAAsB,EAAC;AAAA,MACjD,GAAG;AAAA,KACL;AAAA,GACF;AAEA,EAAA,MAAM,MAAA,GAA2B;AAAA,IAC/B,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,OAAA,EAAS;AAAA,GACX;AAEA,EAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,IAAA,EAAA,CAAG,aAAA,CAAc,OAAO,MAAA,EAAQ,IAAA,CAAK,UAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAA,EAAG,OAAO,CAAA;AAAA,EAC1E;AAEA,EAAA,OAAO,MAAA;AACT","file":"compliance-suite.js","sourcesContent":["/**\n * Groups elements of a collection by the result of applying a function to each element.\n * Returns a record where keys are the results of the grouping function and values are arrays\n * of the corresponding elements, preserving their original order.\n *\n * @param f - The grouping function to apply to each element\n * @param coll - The collection to group\n * @returns A record mapping grouping keys to arrays of elements\n *\n * @example\n * ```typescript\n * // Group strings by length\n * groupBy((s: string) => s.length, [\"a\", \"as\", \"asd\", \"aa\", \"asdf\", \"qwer\"])\n * // => { \"1\": [\"a\"], \"2\": [\"as\", \"aa\"], \"3\": [\"asd\"], \"4\": [\"asdf\", \"qwer\"] }\n *\n * // Group numbers by odd/even\n * groupBy((n: number) => n % 2 === 1, [0, 1, 2, 3, 4, 5])\n * // => { \"false\": [0, 2, 4], \"true\": [1, 3, 5] }\n *\n * // Group objects by property\n * groupBy((obj: {category: string}) => obj.category,\n * [{category: \"a\", id: 1}, {category: \"b\", id: 2}, {category: \"a\", id: 3}])\n * // => { \"a\": [{category: \"a\", id: 1}, {category: \"a\", id: 3}], \"b\": [{category: \"b\", id: 2}] }\n * ```\n */\nexport function groupBy<T, K extends PropertyKey>(\n f: (item: T) => K,\n coll: readonly T[],\n): Record<K, T[]> {\n const result = {} as Record<K, T[]>;\n\n for (const item of coll) {\n const key = f(item);\n if (key in result) {\n result[key].push(item);\n } else {\n result[key] = [item];\n }\n }\n\n return result;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Config } from \"@interpreter/config/config\";\nimport { ColorManager } from \"@interpreter/config/managers/color/manager\";\nimport { Interpreter, type InterpreterResult } from \"@interpreter/interpreter\";\nimport { parseExpression } from \"@interpreter/parser\";\nimport { BaseSymbolType, ColorSymbol, NumberWithUnitSymbol } from \"@interpreter/symbols\";\nimport { groupBy } from \"./interpreter/utils/coll\";\nimport { isArray, isObject } from \"./interpreter/utils/type\";\nimport { InterpreterError, type ISymbolType, LexerError, ParserError } from \"./lib\";\n\ninterface TestCase {\n name: string;\n input: string;\n expectedOutput?: any;\n expectedOutputType: string;\n expectedErrorCode?: string;\n inline: boolean;\n context?: Record<string, any>;\n schemas?: string[];\n path: string;\n}\n\ninterface TestResult extends TestCase {\n status: \"passed\" | \"failed\";\n actualOutput: any;\n actualOutputType: string;\n actualErrorCode?: string;\n error?: Error;\n}\n\ninterface ComplianceReport {\n passed: number;\n failed: number;\n results: TestResult[];\n}\n\nconst SCHEMA_FILE_MAP: Record<string, string> = {\n \"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/hsl-color/0/\":\n \"./data/specifications/colors/hsl.json\",\n \"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/srgb-color/0/\":\n \"./data/specifications/colors/srgb.json\",\n \"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/rgb-color/0/\":\n \"./data/specifications/colors/rgb.json\",\n \"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/lrgb-color/0/\":\n \"./data/specifications/colors/lrgb.json\",\n};\n\nfunction loadSchemas(schemas: string[]): ColorManager {\n const colorManager = new ColorManager();\n\n for (const schemaUri of schemas) {\n const filePath = SCHEMA_FILE_MAP[schemaUri];\n if (filePath && fs.existsSync(filePath)) {\n try {\n const specData = fs.readFileSync(filePath, \"utf-8\");\n colorManager.register(schemaUri, specData);\n } catch (error) {\n console.warn(`Failed to load schema ${schemaUri} from ${filePath}:`, error);\n }\n } else {\n console.warn(`No file mapping found for schema: ${schemaUri}`);\n }\n }\n\n return colorManager;\n}\n\nfunction readJsonFilesRecursively(dir: string): string[] {\n let results: string[] = [];\n const list = fs.readdirSync(dir);\n list.forEach((file) => {\n const filePath = path.join(dir, file);\n const stat = fs.statSync(filePath);\n if (stat?.isDirectory()) {\n results = results.concat(readJsonFilesRecursively(filePath));\n } else if (file.endsWith(\".json\")) {\n results.push(filePath);\n }\n });\n return results;\n}\n\ninterface ComplianceConfig {\n dir?: string;\n file?: string;\n output?: string;\n}\n\nconst parseTestCasesJson = (json: string, filePath: string): TestCase[] => {\n try {\n const testCases = JSON.parse(json);\n return !Array.isArray(testCases) ? [testCases] : testCases;\n } catch (_e) {\n throw new Error(`Could not parse json at path: ${filePath}`);\n }\n};\n\nfunction normalizeContextObject(\n obj: any,\n config: Config,\n fns: Array<(obj: any, config: Config) => any>,\n): any {\n for (const rule of fns) {\n const transformed = rule(obj, config);\n if (typeof transformed !== \"undefined\") {\n return transformed;\n }\n }\n if (isArray(obj)) {\n return obj.map((el) => normalizeContextObject(el, config, fns));\n }\n if (isObject(obj)) {\n const out: Record<string, any> = {};\n for (const [k, v] of Object.entries(obj)) {\n out[k] = normalizeContextObject(v, config, fns);\n }\n return out;\n }\n return obj;\n}\n\nfunction transformContextToSymbols(obj: any, config: Config): any {\n return normalizeContextObject(obj, config, [\n (val: any, config: Config) => {\n if (isObject(val) && val.type === \"NumberWithUnit\") {\n const numberVal = val as unknown as NumberWithUnitSymbol;\n return new NumberWithUnitSymbol(numberVal.value ?? null, numberVal.unit, config);\n }\n },\n ]);\n}\n\nconst runTest = (test: TestCase): { interpreter: Interpreter; result: InterpreterResult } => {\n const { ast } = parseExpression(test.input, { mode: test.inline ? \"inline\" : \"script\" });\n\n let config: Config;\n if (test.schemas && test.schemas.length > 0) {\n const colorManager = loadSchemas(test.schemas);\n config = new Config({ colorManager });\n } else {\n config = new Config();\n }\n\n const references = test.context ? transformContextToSymbols(test.context, config) : {};\n const interpreter = new Interpreter(ast, { references, config });\n return {\n interpreter,\n result: interpreter.interpret(),\n };\n};\n\ninterface ComplianceResult {\n actualOutput: string;\n actualOutputType: string;\n actualErrorCode?: string;\n}\n\nconst interpreterSymbolToComplianceResult = (\n symbol: ISymbolType,\n interpreter: Interpreter,\n): ComplianceResult => {\n // Colors need to be formatted using ColorManager, as we need the order rules\n if (symbol instanceof ColorSymbol) {\n return {\n actualOutput: interpreter.config.colorManager.formatColorMethod(symbol),\n actualOutputType: symbol.getTypeName(),\n };\n }\n\n return {\n actualOutput: symbol.toString(),\n actualOutputType: symbol.getTypeName(),\n };\n};\n\nconst compareResults = (\n complianceResult: ComplianceResult,\n testCase: TestCase,\n): \"passed\" | \"failed\" => {\n const typeMatches = complianceResult.actualOutputType === testCase.expectedOutputType;\n\n // When expectedErrorCode is set, match on error code (and type) only\n if (testCase.expectedErrorCode) {\n return typeMatches && complianceResult.actualErrorCode === testCase.expectedErrorCode\n ? \"passed\"\n : \"failed\";\n }\n\n // Otherwise match on output value and type\n return typeMatches && complianceResult.actualOutput === testCase.expectedOutput\n ? \"passed\"\n : \"failed\";\n};\n\nexport async function evaluateStandardCompliance(config: ComplianceConfig) {\n const files = config.file\n ? [config.file]\n : config.dir\n ? readJsonFilesRecursively(config.dir)\n : [];\n\n const testResults: TestResult[] = files.flatMap((path) => {\n const content = fs.readFileSync(path, \"utf-8\");\n const testCases: TestCase[] = parseTestCasesJson(content, path);\n\n return testCases.map((testCase) => {\n let testResult: TestResult;\n try {\n const { result, interpreter } = runTest(testCase);\n if (!(result instanceof BaseSymbolType)) {\n throw new Error(`result (${result}) in s not interpreter Symbol`);\n }\n const complianceResult = interpreterSymbolToComplianceResult(result, interpreter);\n testResult = {\n ...testCase,\n ...complianceResult,\n path: path,\n status: compareResults(complianceResult, testCase),\n };\n } catch (e: any) {\n if (e instanceof InterpreterError || e instanceof LexerError || e instanceof ParserError) {\n const complianceResult: ComplianceResult = {\n actualOutput: e.originalMessage || \"\",\n actualOutputType: \"Error\",\n actualErrorCode: e.code,\n };\n return {\n ...testCase,\n ...complianceResult,\n path: path,\n status: compareResults(complianceResult, testCase),\n error: e,\n };\n }\n throw e;\n }\n\n return {\n ...testCase,\n ...testResult,\n status: \"passed\",\n path: path,\n };\n });\n });\n\n const { passed = [], failed = [] } = groupBy((x) => x.status, testResults);\n\n // Order keys for json output\n const orderedResults = testResults.map(\n ({\n name,\n input,\n inline,\n context,\n path,\n status,\n actualOutput,\n actualOutputType,\n actualErrorCode,\n expectedOutput,\n expectedOutputType,\n expectedErrorCode,\n ...rest\n }) => ({\n name,\n path,\n status,\n inline,\n context,\n input,\n actualOutput,\n actualOutputType,\n ...(actualErrorCode ? { actualErrorCode } : {}),\n expectedOutput,\n expectedOutputType,\n ...(expectedErrorCode ? { expectedErrorCode } : {}),\n ...rest,\n }),\n );\n\n const report: ComplianceReport = {\n passed: passed.length,\n failed: failed.length,\n results: orderedResults,\n };\n\n if (config.output) {\n fs.writeFileSync(config.output, JSON.stringify(report, null, 2), \"utf-8\");\n }\n\n return report;\n}\n"]}
|