diff --git a/.github/badges/coverage.svg b/.github/badges/coverage.svg index 7af3dc5..f487f4e 100644 --- a/.github/badges/coverage.svg +++ b/.github/badges/coverage.svg @@ -1,20 +1,20 @@ - - test coverage: 79.5% - + + test coverage: 83.6% + - - + + - - + + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d1d02f..34e0d62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Change Log +## [0.7.4] - 2025-12-27 - Plot styles fix + PineScript transpiler coverage + +### Added + +- Unit-tests for PineToJS transpiler branch bringing the total coverage back to > 80% + +### Fixed + +- plot styles were missing in the generated code (e.g plot.style_columns ...etc ) + ## [0.7.3] - 2025-12-24 - Plot Functions & PineScript Types Enhancement ### Added diff --git a/package.json b/package.json index 529197e..b81b510 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pinets", - "version": "0.7.3", + "version": "0.7.4", "description": "", "main": "dist/pinets.min.cjs", "module": "dist/pinets.min.es.js", diff --git a/src/Context.class.ts b/src/Context.class.ts index c0bf8eb..654a624 100644 --- a/src/Context.class.ts +++ b/src/Context.class.ts @@ -166,7 +166,30 @@ export class Context { const plotHelper = new PlotHelper(this); const hlineHelper = new HlineHelper(this); - this.bindContextObject(plotHelper, ['plot', 'plotchar', 'plotshape', 'plotarrow']); + this.bindContextObject(plotHelper, ['plotchar', 'plotshape', 'plotarrow']); + this.bindContextObject( + plotHelper, + [ + 'any', + 'param', + 'linestyle_dashed', + 'linestyle_dotted', + 'linestyle_solid', + 'style_area', + 'style_areabr', + 'style_circles', + 'style_columns', + 'style_cross', + 'style_histogram', + 'style_line', + 'style_linebr', + 'style_stepline', + 'style_stepline_diamond', + 'style_steplinebr', + ], + 'plot' + ); + this.bindContextObject(hlineHelper, ['any', 'style_dashed', 'style_solid', 'style_dotted', 'param'], 'hline'); } diff --git a/src/namespaces/Plots.ts b/src/namespaces/Plots.ts index 448da33..3116a52 100644 --- a/src/namespaces/Plots.ts +++ b/src/namespaces/Plots.ts @@ -53,6 +53,53 @@ export class PlotHelper { return _options; } + public get linestyle_dashed() { + return 'linestyle_dashed'; + } + public get linestyle_dotted() { + return 'linestyle_dotted'; + } + public get linestyle_solid() { + return 'linestyle_solid'; + } + public get style_area() { + return 'style_area'; + } + public get style_areabr() { + return 'style_areabr'; + } + public get style_circles() { + return 'style_circles'; + } + public get style_columns() { + return 'style_columns'; + } + public get style_cross() { + return 'style_cross'; + } + public get style_histogram() { + return 'style_histogram'; + } + public get style_line() { + return 'style_line'; + } + public get style_linebr() { + return 'style_linebr'; + } + public get style_stepline() { + return 'style_stepline'; + } + public get style_stepline_diamond() { + return 'style_stepline_diamond'; + } + public get style_steplinebr() { + return 'style_steplinebr'; + } + + param(source: any, index: number = 0, name?: string) { + return Series.from(source).get(index); + } + //in the current implementation, plot functions are only used to collect data for the plots array and map it to the market data plotchar(...args) { // if (!this.context.plots[title]) { @@ -64,10 +111,12 @@ export class PlotHelper { // value: value, // options: { ...this.extractPlotOptions(options), style: 'char' }, // }); - this.plot(...args); + this.any(...args); } - plot(...args) { + //this will map to plot() - see README.md for more details + + any(...args) { const _parsed = parseArgsForPineParams(args, PLOT_SIGNATURE, PLOT_ARGS_TYPES); const { series, title, ...others } = _parsed; const options = this.extractPlotOptions(others); @@ -156,6 +205,7 @@ export class HlineHelper { //this will map to hline() any(price, title, color, linestyle, linewidth, editable, display) { - return this.context.pine.plot(price, { title, color, linestyle, linewidth, editable, display }); + //plot.any is mapped to plot() at runtime + return this.context.pine.plot.any(price, { title, color, linestyle, linewidth, editable, display }); } } diff --git a/src/namespaces/Types.ts b/src/namespaces/Types.ts index 0434387..b2dd776 100644 --- a/src/namespaces/Types.ts +++ b/src/namespaces/Types.ts @@ -146,7 +146,6 @@ const types = { location, size, format, - plot, }; export default types; diff --git a/src/namespaces/utils.ts b/src/namespaces/utils.ts index b8a37d2..7ff71a2 100644 --- a/src/namespaces/utils.ts +++ b/src/namespaces/utils.ts @@ -1,7 +1,7 @@ import { Series } from '../Series'; const TYPE_CHECK = { - series: (arg) => arg instanceof Series || typeof arg === 'number', + series: (arg) => arg instanceof Series || typeof arg === 'number' || typeof arg === 'string' || typeof arg === 'boolean', string: (arg) => typeof arg === 'string', number: (arg) => typeof arg === 'number', boolean: (arg) => typeof arg === 'boolean', diff --git a/src/transpiler/settings.ts b/src/transpiler/settings.ts index 63a73db..268318a 100644 --- a/src/transpiler/settings.ts +++ b/src/transpiler/settings.ts @@ -2,7 +2,7 @@ export const KNOWN_NAMESPACES = ['ta', 'math', 'request', 'array', 'input']; // This is used to transform ns() calls to ns.any() calls -export const NAMESPACES_LIKE = ['hline']; +export const NAMESPACES_LIKE = ['hline', 'plot']; // Async methods that require await keyword (format: 'namespace.method') export const ASYNC_METHODS = ['request.security', 'request.security_lower_tf']; diff --git a/tests/indicators/pine_supertrend.test.ts b/tests/indicators/pine_supertrend.test.ts index e6d6fb7..ee5f8de 100644 --- a/tests/indicators/pine_supertrend.test.ts +++ b/tests/indicators/pine_supertrend.test.ts @@ -11,7 +11,7 @@ describe('Indicators', () => { const ta = context.ta; const { close, hl2 } = context.data; - const { na, nz, plot } = context.core; + const { na, nz, plot } = context.pine; function pine_supertrend(factor, atrPeriod) { const src = hl2; diff --git a/tests/transpiler/pinescript-to-js.test.ts b/tests/transpiler/pinescript-to-js.test.ts new file mode 100644 index 0000000..e120a0a --- /dev/null +++ b/tests/transpiler/pinescript-to-js.test.ts @@ -0,0 +1,747 @@ +// SPDX-License-Identifier: AGPL-3.0-only +// Copyright (C) 2025 Alaa-eddine KADDOURI + +/** + * Pine Script to JavaScript Transpiler Test Suite + * + * This test suite validates the consistency of native Pine Script v6 code transpilation to executable JavaScript. + * Each test case focuses on specific Pine Script features to ensure proper transformation through the full + * 2-stage transpilation pipeline: + * Stage 1 (pineToJS): Pine Script → PineTS JavaScript syntax + * Stage 2 (transpile): PineTS JavaScript → Executable low-level JS + * + * Coverage Goals: + * - Lexer: Tokenization, indentation handling, literals, operators + * - Parser: AST construction for all Pine Script syntax elements + * - CodeGen: JavaScript code generation from AST + * - Full transpilation pipeline integrity + */ + +import { describe, it, expect } from 'vitest'; +import { transpile } from '../../src/transpiler/index'; +import { extractPineScriptVersion } from '../../src/transpiler/pineToJS/pineToJS.index'; + +describe('Pine Script Version Detection', () => { + it('should extract version 5 from source code', () => { + const code = '//@version=5\nindicator("Test")'; + const version = extractPineScriptVersion(code); + expect(version).toBe(5); + }); + + it('should extract version 6 from source code', () => { + const code = '//@version=6\nindicator("Test")'; + const version = extractPineScriptVersion(code); + expect(version).toBe(6); + }); + + it('should return null when version is missing', () => { + const code = 'indicator("Test")'; + const version = extractPineScriptVersion(code); + expect(version).toBeNull(); + }); + + it('should handle version comment with extra whitespace', () => { + const code = '// @version = 6 \nindicator("Test")'; + const version = extractPineScriptVersion(code); + expect(version).toBe(6); + }); +}); + +describe('Pine Script Transpilation - Basic Features', () => { + it('should transpile simple variable declarations', () => { + const code = ` +//@version=6 +indicator("Simple Variable Test") + +x = 10 +y = 20 +z = x + y + +plot(z, title="Sum") + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toBeDefined(); + expect(jsCode).toContain('$.let.glb1_x = $.init($.let.glb1_x, 10)'); + expect(jsCode).toContain('$.let.glb1_y = $.init($.let.glb1_y, 20)'); + expect(jsCode).toContain('$.let.glb1_z = $.init($.let.glb1_z, $.get($.let.glb1_x, 0) + $.get($.let.glb1_y, 0))'); + }); + + it('should transpile ternary operator', () => { + const code = ` +//@version=6 +indicator("Ternary Test") + +result = close > open ? 1 : 0 +plot(result) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('?'); + expect(jsCode).toContain(':'); + expect(jsCode).toContain('$.get(close, 0) > $.get(open, 0)'); + }); + + it('should reject Pine Script version < 5', () => { + const code = '//@version=4\nindicator("Test")'; + + expect(() => transpile(code)).toThrow('Unsupported Pine Script version 4'); + }); + + it('should fail gracefully when version is missing', () => { + const code = 'indicator("Test")'; + + // When version is missing, it's treated as PineTS syntax, which should transpile + const result = transpile(code); + expect(result).toBeDefined(); + }); +}); + +describe('Pine Script Transpilation - Control Flow', () => { + it('should transpile if-else statements', () => { + const code = ` +//@version=6 +indicator("If Test") + +price = close +signal = 0 + +if price > 100 + signal := 1 +else + signal := -1 + +plot(signal) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('if ('); + expect(jsCode).toContain('} else {'); + expect(jsCode).toContain('$.set($.let.glb1_signal, 1)'); + expect(jsCode).toContain('$.set($.let.glb1_signal, -1)'); + }); + + it('should transpile for loops', () => { + const code = ` +//@version=6 +indicator("For Loop Test") + +sum = 0.0 +for i = 0 to 10 + sum := sum + i + +plot(sum) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('for ('); + expect(jsCode).toContain('let i = 0; i <= 10; i++'); + }); + + it('should transpile while loops', () => { + const code = ` +//@version=6 +indicator("While Loop Test") + +counter = 0 +value = 10 + +while counter < 5 + value := value + counter + counter := counter + 1 + +plot(value) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('while ('); + expect(jsCode).toContain('$.get($.let.glb1_counter, 0) < 5'); + }); + + it('should transpile switch expressions', () => { + const code = ` +//@version=6 +indicator("Switch Test") + +mode = 1 +result = switch mode + 1 => 10 + 2 => 20 + => 30 + +plot(result) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + // Switch is converted to if-else chain or ternary + expect(jsCode).toBeDefined(); + }); +}); + +describe('Pine Script Transpilation - Functions', () => { + it('should transpile simple function', () => { + const code = ` +//@version=6 +indicator("Function Test") + +add(a, b) => + a + b + +result = add(10, 20) +plot(result) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('function add(a, b)'); + expect(jsCode).toContain('return $.precision('); + }); + + it('should transpile function with multiple statements', () => { + const code = ` +//@version=6 +indicator("Function Test") + +calculate(x, y) => + sum = x + y + product = x * y + sum + product + +result = calculate(5, 3) +plot(result) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('function calculate(x, y)'); + expect(jsCode).toContain('$.let.fn'); + }); + + it('should transpile function returning tuple', () => { + const code = ` +//@version=6 +indicator("Tuple Test") + +calcMinMax(a, b) => + [math.min(a, b), math.max(a, b)] + +[minVal, maxVal] = calcMinMax(close, open) +plot(minVal) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('function calcMinMax'); + // Tuple handling + expect(jsCode).toBeDefined(); + }); +}); + +describe('Pine Script Transpilation - Variables', () => { + it('should transpile var keyword', () => { + const code = ` +//@version=6 +indicator("Var Test") + +var float counter = 0 +counter := counter + 1 + +plot(counter) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + // var means initialize only once with initVar + expect(jsCode).toContain('$.initVar('); + expect(jsCode).toContain('$.set('); + expect(jsCode).toContain('$.var.glb1_counter'); + }); + + it('should transpile varip keyword', () => { + const code = ` +//@version=6 +indicator("Varip Test") + +varip int tick_counter = 0 +tick_counter := tick_counter + 1 + +plot(tick_counter) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + // varip uses initVar like var + expect(jsCode).toContain('$.initVar('); + expect(jsCode).toContain('$.var.glb1_tick_counter'); + }); + + it('should transpile reassignment operator :=', () => { + const code = ` +//@version=6 +indicator("Reassignment Test") + +x = 10 +x := 20 + +plot(x) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('$.init('); + expect(jsCode).toContain('$.set('); + }); +}); + +describe('Pine Script Transpilation - Operators', () => { + it('should transpile logical operators', () => { + const code = ` +//@version=6 +indicator("Logical Test") + +bull = close > open and volume > 1000 +bear = close < open or volume < 500 +not_bull = not bull + +plot(bull ? 1 : 0) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('&&'); + expect(jsCode).toContain('||'); + expect(jsCode).toContain('!'); + }); + + it('should transpile comparison operators', () => { + const code = ` +//@version=6 +indicator("Comparison Test") + +eq = close == open +neq = close != open +gt = close > open +lt = close < open +gte = close >= open +lte = close <= open + +plot(gt ? 1 : 0) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('$.math.__eq('); + expect(jsCode).toContain('>'); + expect(jsCode).toContain('<'); + expect(jsCode).toContain('>='); + expect(jsCode).toContain('<='); + }); + + it('should transpile arithmetic operators', () => { + const code = ` +//@version=6 +indicator("Arithmetic Test") + +sum = 10 + 20 +diff = 10 - 5 +prod = 10 * 2 +quot = 10 / 2 +mod = 10 % 3 + +plot(sum) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('+'); + expect(jsCode).toContain('-'); + expect(jsCode).toContain('*'); + expect(jsCode).toContain('/'); + expect(jsCode).toContain('%'); + }); +}); + +describe('Pine Script Transpilation - Series and Arrays', () => { + it('should transpile historical reference operator []', () => { + const code = ` +//@version=6 +indicator("Series Test") + +prev_close = close[1] +prev_prev_close = close[2] +high_5 = high[5] + +plot(prev_close) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('close, 1'); + expect(jsCode).toContain('close, 2'); + expect(jsCode).toContain('high, 5'); + }); + + it('should transpile array operations', () => { + const code = ` +//@version=6 +indicator("Array Test") + +prices = array.new_float(5, 0.0) +array.push(prices, close) +size = array.size(prices) + +plot(size) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('array.new_float'); + expect(jsCode).toContain('array.push'); + expect(jsCode).toContain('array.size'); + }); + + it('should transpile method call syntax', () => { + const code = ` +//@version=6 +indicator("Method Test") + +arr = array.new_float(0) +arr.push(close) +size = arr.size() + +plot(size) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('.push('); + expect(jsCode).toContain('.size()'); + }); +}); + +describe('Pine Script Transpilation - Built-in Functions', () => { + it('should transpile ta functions', () => { + const code = ` +//@version=6 +indicator("TA Functions Test") + +sma_val = ta.sma(close, 20) +ema_val = ta.ema(close, 20) +rsi_val = ta.rsi(close, 14) + +plot(sma_val) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('ta.sma'); + expect(jsCode).toContain('ta.ema'); + expect(jsCode).toContain('ta.rsi'); + }); + + it('should transpile math functions', () => { + const code = ` +//@version=6 +indicator("Math Test") + +abs_val = math.abs(-10) +max_val = math.max(close, open) +sqrt_val = math.sqrt(close) + +plot(max_val) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('math.abs'); + expect(jsCode).toContain('math.max'); + expect(jsCode).toContain('math.sqrt'); + }); + + it('should transpile input functions', () => { + const code = ` +//@version=6 +indicator("Input Test") + +length = input.int(14, "Length", minval=1, maxval=200) +src = input.source(close, "Source") +multiplier = input.float(2.0, "Multiplier") + +plot(src) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('input.int'); + expect(jsCode).toContain('input.source'); + expect(jsCode).toContain('input.float'); + }); + + it('should transpile string functions', () => { + const code = ` +//@version=6 +indicator("String Test") + +text = "Hello World" +length = str.length(text) +contains = str.contains(text, "Hello") + +plot(length) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('str.length'); + expect(jsCode).toContain('str.contains'); + }); + + it('should transpile color functions', () => { + const code = ` +//@version=6 +indicator("Color Test") + +base = color.blue +trans = color.new(color.blue, 50) +rgb = color.rgb(255, 0, 0) +dynamic = close > open ? color.green : color.red + +plot(close, color=dynamic) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('color.blue'); + expect(jsCode).toContain('color.new'); + expect(jsCode).toContain('color.rgb'); + expect(jsCode).toContain('color.green'); + expect(jsCode).toContain('color.red'); + }); +}); + +describe('Pine Script Transpilation - Special Values', () => { + it('should transpile na (not available)', () => { + const code = ` +//@version=6 +indicator("NA Test") + +var float prev = na +is_na = na(prev) +safe = nz(prev, close) + +plot(safe) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('NaN'); + }); + + it('should handle boolean values', () => { + const code = ` +//@version=6 +indicator("Boolean Test") + +flag = true +flag2 = false + +result = flag ? 1 : 0 +plot(result) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('true'); + expect(jsCode).toContain('false'); + }); +}); + +describe('Pine Script Transpilation - Comments', () => { + it('should handle single-line comments', () => { + const code = ` +//@version=6 +indicator("Comment Test") + +// This is a comment +x = 10 // Inline comment + +plot(x) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + // Comments should be filtered out or preserved based on options + expect(jsCode).toBeDefined(); + }); + + it('should handle indicator declaration', () => { + const code = ` +//@version=6 +indicator("My Indicator", shorttitle="MI", overlay=true) + +plot(close) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('indicator'); + expect(jsCode).toContain('My Indicator'); + }); +}); + +describe('Pine Script Transpilation - Complex Expressions', () => { + it('should transpile nested ternary operators', () => { + const code = ` +//@version=6 +indicator("Nested Ternary") + +signal = close > open ? 1 : (close < open ? -1 : 0) +plot(signal) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('?'); + expect(jsCode).toContain(':'); + }); + + it('should transpile complex boolean expressions', () => { + const code = ` +//@version=6 +indicator("Complex Boolean") + +condition = (close > open and volume > 1000) or (close < open and volume < 500) +plot(condition ? 1 : 0) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('&&'); + expect(jsCode).toContain('||'); + }); + + it('should transpile function calls with expressions', () => { + const code = ` +//@version=6 +indicator("Expression Test") + +result = ta.sma(close > open ? close : open, 14) +plot(result) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('ta.sma'); + }); +}); + +describe('Pine Script Transpilation - Error Handling', () => { + it('should handle syntax errors gracefully', () => { + const code = ` +//@version=6 +indicator("Error Test") + +x = +plot(x) + `; + + // transpile may throw an error or produce incomplete output + try { + const result = transpile(code); + const jsCode = result.toString(); + // If it doesn't throw, it should at least produce some output + expect(jsCode).toBeDefined(); + } catch (error) { + // Error is expected and acceptable for invalid syntax + expect(error).toBeDefined(); + } + }); + + it('should handle invalid indentation', () => { + const code = ` +//@version=6 +indicator("Indent Error") + +if close > open +plot(close) + `; + + // Should either succeed with warning or fail with descriptive error + try { + const result = transpile(code); + expect(result).toBeDefined(); + } catch (error) { + // Error is acceptable for invalid syntax + expect(error).toBeDefined(); + } + }); +}); + +describe('Pine Script Transpilation - Real-World Example (MACD)', () => { + it('should transpile complete MACD indicator', () => { + const code = ` +//@version=6 +indicator("MACD", shorttitle="MACD") + +fast_length = input.int(12, "Fast Length", minval=1) +slow_length = input.int(26, "Slow Length", minval=1) +signal_length = input.int(9, "Signal Length", minval=1) +src = input.source(close, "Source") + +fast_ma = ta.ema(src, fast_length) +slow_ma = ta.ema(src, slow_length) +macd = fast_ma - slow_ma +signal = ta.ema(macd, signal_length) +hist = macd - signal + +plot(hist, title="Histogram", style=plot.style_histogram, color=color.blue) +plot(macd, title="MACD", color=color.blue) +plot(signal, title="Signal", color=color.orange) + `; + + const result = transpile(code); + const jsCode = result.toString(); + + expect(jsCode).toContain('input.int'); + expect(jsCode).toContain('ta.ema'); + expect(jsCode).toContain('plot'); + expect(jsCode).toContain('$.let.glb1_macd'); + expect(jsCode).toContain('$.let.glb1_signal'); + expect(jsCode).toContain('$.let.glb1_hist'); + }); +}); diff --git a/tests/core/transpiler.test.ts b/tests/transpiler/pinets-source-to-js.test.ts similarity index 97% rename from tests/core/transpiler.test.ts rename to tests/transpiler/pinets-source-to-js.test.ts index 1901bff..905cfc8 100644 --- a/tests/core/transpiler.test.ts +++ b/tests/transpiler/pinets-source-to-js.test.ts @@ -408,15 +408,16 @@ let src_open = input.any({ title: 'Open Source', defval: open }); const expected_code = `async $ => { const {ta, plot, na, bool} = $.pine; $.let.glb1_highUsePivot = $.init($.let.glb1_highUsePivot, 10); - const p0 = $.param($.let.glb1_highUsePivot, undefined, 'p0'); + const p0 = plot.param($.let.glb1_highUsePivot, undefined, 'p0'); const p1 = ta.param($.let.glb1_highUsePivot, undefined, 'p1'); const temp_1 = ta.change(p1, "_ta0"); const p2 = $.param(temp_1, undefined, 'p2'); - const p3 = $.param(bool(p2) ? NaN : "#FF0000", undefined, 'p3'); - const p4 = $.param({ + const p3 = plot.param(bool(p2) ? NaN : "#FF0000", undefined, 'p3'); + const p4 = plot.param({ color: p3 }, undefined, 'p4'); - plot(p0, p4); + const temp_2 = plot.any(p0, p4); + temp_2; }`; expect(result).toBe(expected_code); @@ -575,24 +576,27 @@ let src_open = input.any({ title: 'Open Source', defval: open }); const {close, open} = $.data; const {plot} = $.core; $.const.glb1_res = $.init($.const.glb1_res, open); - const p0 = $.param(close && open ? 1 : $.get($.const.glb1_res, 0), undefined, 'p0'); - const p1 = $.param("plot1", undefined, 'p1'); - const p2 = $.param({ + const p0 = plot.param(close && open ? 1 : $.get($.const.glb1_res, 0), undefined, 'p0'); + const p1 = plot.param("plot1", undefined, 'p1'); + const p2 = plot.param({ color: "white" }, undefined, 'p2'); - plot(p0, p1, p2); - const p3 = $.param($.get(close, 0) && $.get(open, 0), undefined, 'p3'); - const p4 = $.param("plot2", undefined, 'p4'); - const p5 = $.param({ + const temp_1 = plot.any(p0, p1, p2); + temp_1; + const p3 = plot.param($.get(close, 0) && $.get(open, 0), undefined, 'p3'); + const p4 = plot.param("plot2", undefined, 'p4'); + const p5 = plot.param({ color: "white" }, undefined, 'p5'); - plot(p3, p4, p5); - const p6 = $.param(-$.get($.const.glb1_res, 0), undefined, 'p6'); - const p7 = $.param("plot3", undefined, 'p7'); - const p8 = $.param({ + const temp_2 = plot.any(p3, p4, p5); + temp_2; + const p6 = plot.param(-$.get($.const.glb1_res, 0), undefined, 'p6'); + const p7 = plot.param("plot3", undefined, 'p7'); + const p8 = plot.param({ color: "white" }, undefined, 'p8'); - plot(p6, p7, p8); + const temp_3 = plot.any(p6, p7, p8); + temp_3; }`; expect(result).toBe(expected_code);