oakscriptjs 0.11.7 → 0.12.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.
Files changed (40) hide show
  1. package/dist/cjs/drawing/registry.d.ts +2 -0
  2. package/dist/cjs/drawing/registry.d.ts.map +1 -1
  3. package/dist/cjs/drawing/registry.js +7 -0
  4. package/dist/cjs/drawing/registry.js.map +2 -2
  5. package/dist/cjs/index.d.ts +3 -3
  6. package/dist/cjs/index.d.ts.map +1 -1
  7. package/dist/cjs/index.js +2 -1
  8. package/dist/cjs/index.js.map +2 -2
  9. package/dist/cjs/runtime/types.d.ts +69 -0
  10. package/dist/cjs/runtime/types.d.ts.map +1 -1
  11. package/dist/cjs/runtime/types.js.map +1 -1
  12. package/dist/cjs/script/index.d.ts +41 -2
  13. package/dist/cjs/script/index.d.ts.map +1 -1
  14. package/dist/cjs/script/index.js +74 -24
  15. package/dist/cjs/script/index.js.map +2 -2
  16. package/dist/cjs/types/metadata.d.ts +8 -0
  17. package/dist/cjs/types/metadata.d.ts.map +1 -1
  18. package/dist/cjs/types/metadata.js.map +1 -1
  19. package/dist/esm/drawing/registry.d.ts +2 -0
  20. package/dist/esm/drawing/registry.d.ts.map +1 -1
  21. package/dist/esm/drawing/registry.js +8 -0
  22. package/dist/esm/drawing/registry.js.map +1 -1
  23. package/dist/esm/index.d.ts +3 -3
  24. package/dist/esm/index.d.ts.map +1 -1
  25. package/dist/esm/index.js +2 -2
  26. package/dist/esm/index.js.map +1 -1
  27. package/dist/esm/runtime/types.d.ts +69 -0
  28. package/dist/esm/runtime/types.d.ts.map +1 -1
  29. package/dist/esm/script/index.d.ts +41 -2
  30. package/dist/esm/script/index.d.ts.map +1 -1
  31. package/dist/esm/script/index.js +73 -18
  32. package/dist/esm/script/index.js.map +1 -1
  33. package/dist/esm/types/metadata.d.ts +8 -0
  34. package/dist/esm/types/metadata.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/drawing/registry.ts +10 -0
  37. package/src/index.ts +5 -1
  38. package/src/runtime/types.ts +65 -0
  39. package/src/script/index.ts +99 -24
  40. package/src/types/metadata.ts +8 -0
@@ -88,7 +88,7 @@ import * as tableCore from '../table/index.js';
88
88
  import * as chartPointCore from '../chartpoint/index.js';
89
89
  import * as textCore from '../text/index.js';
90
90
  import * as mathCore from '../math/index.js';
91
- import { resetDrawings, setDrawingBar, setDrawingLimits } from '../drawing/registry.js';
91
+ import { createdDrawingKinds, resetDrawings, setDrawingBar, setDrawingLimits, type DrawingKind } from '../drawing/registry.js';
92
92
  export { holdDrawing, releaseDrawing, varDrawing, type DrawingVariable } from '../drawing/registry.js';
93
93
  import { drawingOutputs } from '../drawing/output.js';
94
94
  import * as timeframeCore from '../timeframe/index.js';
@@ -137,6 +137,11 @@ export interface ScriptRunResult {
137
137
  barColorConfig: BarColorConfig[];
138
138
  /** plotcandle() / plotbar() declarations */
139
139
  candleConfig: CandleConfig[];
140
+ /**
141
+ * The kinds of drawing objects (label.new, line.new, box.new, linefill.new, polyline.new, table.new) the run
142
+ * created, even the ones deleted since: the drawing groups a user can show or hide.
143
+ */
144
+ drawingKinds: DrawingKind[];
140
145
  /**
141
146
  * The plot(), plotshape(), plotchar(), plotarrow(), plotcandle() and plotbar() declarations in the order the
142
147
  * script made them (the id of each in its own config). PineScript numbers a script's outputs in this order.
@@ -362,6 +367,7 @@ export function executeScript(
362
367
  arrowConfig: c.arrowConfig,
363
368
  barColorConfig: c.barColorConfig,
364
369
  candleConfig: c.candleConfig,
370
+ drawingKinds: createdDrawingKinds(),
365
371
  outputs: c.outputs,
366
372
  defaultInputs: c.defaultInputs,
367
373
  alertConfig: c.alertConfig,
@@ -698,17 +704,37 @@ export interface ScriptPlotOptions {
698
704
  histbase?: number;
699
705
  /** Draw on the main chart pane even when the script is not an overlay (PineScript `force_overlay`); default false. */
700
706
  force_overlay?: boolean;
707
+ /** False: not listed in the Style settings of the study (PineScript `editable`); default true. */
708
+ editable?: boolean;
701
709
  }
702
710
 
711
+ /**
712
+ * Titles of untitled outputs, as the PineScript compiler names them (reference metadata of a script whose outputs have
713
+ * no title): the Style settings and the alert output lists show them.
714
+ */
715
+ export const DEFAULT_OUTPUT_TITLES = {
716
+ plot: 'Plot',
717
+ hline: 'Level',
718
+ plotFill: 'Plots Background',
719
+ hlineFill: 'Hlines Background',
720
+ shape: 'Shapes',
721
+ char: 'Chars',
722
+ arrow: 'Arrows',
723
+ bgcolor: 'Background Color',
724
+ barcolor: 'Bar Color',
725
+ candle: 'PlotCandle',
726
+ bar: 'PlotBar',
727
+ } as const;
728
+
703
729
  /** PineScript `plot()` — declares the plot and supplies its data in one call. */
704
- function plotImpl(series: Series, title?: string, options: ScriptPlotOptions = {}): PlotHandle {
730
+ function plotImpl(series: Series, title: string = DEFAULT_OUTPUT_TITLES.plot, options: ScriptPlotOptions = {}): PlotHandle {
705
731
  const c = collector();
706
732
  const id = `plot${c.plotConfig.length}`;
707
733
  const perBar = Array.isArray(options.color) ? options.color : undefined;
708
734
  const staticColor = typeof options.color === 'string' ? options.color : (perBar?.[perBar.length - 1] ?? '#2962FF');
709
735
  c.plotConfig.push({
710
736
  id,
711
- title: title ?? id,
737
+ title,
712
738
  color: staticColor,
713
739
  lineWidth: options.linewidth,
714
740
  style: options.style,
@@ -716,8 +742,9 @@ function plotImpl(series: Series, title?: string, options: ScriptPlotOptions = {
716
742
  display: options.display,
717
743
  histbase: options.histbase,
718
744
  forceOverlay: options.force_overlay,
745
+ ...(options.editable === false ? { editable: false } : {}),
719
746
  });
720
- c.outputs.push({ kind: 'plot', id, title: title ?? id });
747
+ c.outputs.push({ kind: 'plot', id, title });
721
748
  const values = series.toArray();
722
749
  const b = bars();
723
750
  const data: TimeValue[] = [];
@@ -756,10 +783,12 @@ export interface ScriptHLineOptions {
756
783
  /** Line style; default dashed (PineScript). */
757
784
  linestyle?: HLineConfig['linestyle'];
758
785
  linewidth?: number;
786
+ /** False: not listed in the Style settings of the study (PineScript `editable`); default true. */
787
+ editable?: boolean;
759
788
  }
760
789
 
761
790
  /** PineScript `hline()` — a static horizontal level. Default line style: dashed (PineScript). */
762
- function hlineImpl(price: number, title?: string, options: ScriptHLineOptions = {}): PlotHandle {
791
+ function hlineImpl(price: number, title: string = DEFAULT_OUTPUT_TITLES.hline, options: ScriptHLineOptions = {}): PlotHandle {
763
792
  const c = collector();
764
793
  const id = `hline${c.hlineConfig.length}`;
765
794
  c.hlineConfig.push({
@@ -769,6 +798,7 @@ function hlineImpl(price: number, title?: string, options: ScriptHLineOptions =
769
798
  color: options.color,
770
799
  linestyle: options.linestyle ?? 'dashed',
771
800
  linewidth: options.linewidth,
801
+ ...(options.editable === false ? { editable: false } : {}),
772
802
  });
773
803
  return { id, kind: 'hline' };
774
804
  }
@@ -784,6 +814,8 @@ export interface ScriptFillOptions {
784
814
  /** Static color, or a per-bar color array from color.when(). */
785
815
  color?: string | string[];
786
816
  title?: string;
817
+ /** False: not listed in the Style settings of the study (PineScript `editable`); default true. */
818
+ editable?: boolean;
787
819
  }
788
820
 
789
821
  /** A fill colour argument: a colour, na (null / undefined), or a per-bar array from color.when(). */
@@ -801,14 +833,20 @@ function perBarColors(c: ScriptFillColor, n: number): Array<string | null> {
801
833
  return new Array<string | null>(n).fill(c ?? null);
802
834
  }
803
835
 
836
+ /** The colour of every bar when it is the same on all of them (and not na). */
837
+ function sameColor(colors: Array<string | null>): string | undefined {
838
+ const first = colors[0];
839
+ return first && colors.every((x) => x === first) ? first : undefined;
840
+ }
841
+
804
842
  /**
805
843
  * PineScript `fill()`, with the three PineScript overloads (positional arguments), for two plots or two hlines:
806
844
  * - `fill(p1, p2, color?, title?, ...)`
807
845
  * - `fill(p1, p2, top_value, bottom_value, top_color, bottom_color, title?, ...)`: gradient fill; values and colours
808
846
  * can change per bar (a Series / a color.when() array)
809
847
  * - `fill(p1, p2, { color, title })`: options object (oakscriptjs form, kept for existing scripts)
810
- * Arguments that change only how the chart shows the fill (`editable`, `show_last`, `fillgaps`, `display`) are
811
- * accepted and not used.
848
+ * `editable = false` keeps the fill out of the Style settings; `show_last`, `fillgaps` and `display` are accepted
849
+ * and not used. Every fill has an id in `fillConfig` (the fills between plots also list it on their data).
812
850
  */
813
851
  export function fill(a: PlotHandle, b: PlotHandle, options?: ScriptFillOptions): void;
814
852
  export function fill(a: PlotHandle, b: PlotHandle, color: ScriptFillColor, title?: string, ...rest: unknown[]): void;
@@ -829,6 +867,7 @@ export function fill(a: PlotHandle, b: PlotHandle, ...args: unknown[]): void {
829
867
  let staticColor: string | undefined;
830
868
  let title: string | undefined;
831
869
  let gradient: FillGradient | undefined;
870
+ let editable: unknown;
832
871
  if (typeof third === 'number' || third instanceof Series) {
833
872
  const n = ctxBars.bars.length;
834
873
  gradient = {
@@ -838,30 +877,40 @@ export function fill(a: PlotHandle, b: PlotHandle, ...args: unknown[]): void {
838
877
  bottomColor: perBarColors(args[3] as ScriptFillColor, n),
839
878
  };
840
879
  title = args[4] as string | undefined;
880
+ editable = args[5];
841
881
  } else if (third !== null && typeof third === 'object' && !Array.isArray(third)) {
842
882
  const options = third as ScriptFillOptions;
843
883
  perBar = Array.isArray(options.color) ? options.color : undefined;
844
884
  staticColor = typeof options.color === 'string' ? options.color : undefined;
845
885
  title = options.title;
886
+ editable = options.editable;
846
887
  } else {
847
888
  const color = third as ScriptFillColor;
848
889
  perBar = Array.isArray(color) ? color.map((x) => x ?? '') : undefined;
849
890
  staticColor = typeof color === 'string' ? color : undefined;
850
891
  title = args[1] as string | undefined;
892
+ editable = args[2];
851
893
  }
852
- if (a.kind === 'hline' && b.kind === 'hline') {
853
- c.fillConfig.push({
854
- id: `fill${c.fillConfig.length}`,
855
- plot1: a.id,
856
- plot2: b.id,
857
- color: staticColor,
858
- colors: perBar,
859
- gradient,
860
- title,
861
- });
862
- return;
863
- }
894
+ const id = `fill${c.fillConfig.length}`;
895
+ title ??= a.kind === 'hline' && b.kind === 'hline' ? DEFAULT_OUTPUT_TITLES.hlineFill : DEFAULT_OUTPUT_TITLES.plotFill;
896
+ const topColor = gradient && sameColor(gradient.topColor);
897
+ const bottomColor = gradient && sameColor(gradient.bottomColor);
898
+ const hlines = a.kind === 'hline' && b.kind === 'hline';
899
+ c.fillConfig.push({
900
+ id,
901
+ plot1: a.id,
902
+ plot2: b.id,
903
+ color: staticColor,
904
+ // the per-bar data of a fill between plots is in the result
905
+ ...(hlines ? { colors: perBar, gradient } : {}),
906
+ title,
907
+ ...(topColor ? { topColor } : {}),
908
+ ...(bottomColor ? { bottomColor } : {}),
909
+ ...(editable === false ? { editable: false } : {}),
910
+ });
911
+ if (hlines) return;
864
912
  c.fills.push({
913
+ id,
865
914
  plot1: a.id,
866
915
  plot2: b.id,
867
916
  options: { color: staticColor, title },
@@ -883,6 +932,8 @@ export interface PlotShapeOptions {
883
932
  tooltip?: string;
884
933
  /** Draw on the main chart pane even when the script is not an overlay (PineScript `force_overlay`); default false. */
885
934
  force_overlay?: boolean;
935
+ /** False: not listed in the Style settings of the study (PineScript `editable`); default true. */
936
+ editable?: boolean;
886
937
  }
887
938
 
888
939
  export interface PlotCharOptions extends Omit<PlotShapeOptions, 'style'> {
@@ -949,6 +1000,7 @@ function emitMarkers(
949
1000
  ): void {
950
1001
  const c = collector();
951
1002
  const id = `${kind}${c.shapeConfig.filter((s) => s.kind === kind).length}`;
1003
+ title ??= DEFAULT_OUTPUT_TITLES[kind];
952
1004
  const style: ShapeStyle | 'char' = kind === 'shape' ? (options.style ?? 'xcross') : 'char';
953
1005
  const char = kind === 'char' ? (options.char ?? '*') : undefined;
954
1006
  const location = options.location ?? 'abovebar';
@@ -965,6 +1017,7 @@ function emitMarkers(
965
1017
  size: options.size,
966
1018
  offset: options.offset,
967
1019
  forceOverlay: options.force_overlay,
1020
+ ...(options.editable === false ? { editable: false } : {}),
968
1021
  });
969
1022
  c.outputs.push({ kind, id, title });
970
1023
  const shapeStyle = kind === 'shape' ? (style as ShapeStyle) : undefined;
@@ -1018,6 +1071,8 @@ export interface PlotArrowOptions {
1018
1071
  display?: ArrowConfig['display'];
1019
1072
  /** Draw on the main chart pane even when the script is not an overlay (PineScript `force_overlay`); default false. */
1020
1073
  force_overlay?: boolean;
1074
+ /** False: not listed in the Style settings of the study (PineScript `editable`); default true. */
1075
+ editable?: boolean;
1021
1076
  }
1022
1077
 
1023
1078
  /**
@@ -1028,6 +1083,7 @@ export interface PlotArrowOptions {
1028
1083
  export function plotarrow(series: Series, title?: string, options: PlotArrowOptions = {}): void {
1029
1084
  const c = collector();
1030
1085
  const id = `arrow${c.arrowConfig.length}`;
1086
+ title ??= DEFAULT_OUTPUT_TITLES.arrow;
1031
1087
  const pick = (col: string | Array<string | undefined> | undefined, fallback: string, i: number): string | undefined =>
1032
1088
  col === undefined ? fallback : typeof col === 'string' ? col : col[i];
1033
1089
  const colorup = typeof options.colorup === 'string' ? options.colorup : '#00FF00';
@@ -1042,6 +1098,7 @@ export function plotarrow(series: Series, title?: string, options: PlotArrowOpti
1042
1098
  offset: options.offset,
1043
1099
  display: options.display,
1044
1100
  forceOverlay: options.force_overlay,
1101
+ ...(options.editable === false ? { editable: false } : {}),
1045
1102
  });
1046
1103
  c.outputs.push({ kind: 'arrow', id, title });
1047
1104
  const values = series.toArray();
@@ -1065,11 +1122,21 @@ export function plotarrow(series: Series, title?: string, options: PlotArrowOpti
1065
1122
  function emitBarColors(
1066
1123
  kind: 'bgcolor' | 'barcolor',
1067
1124
  colors: string | Array<string | undefined>,
1068
- options: { offset?: number; title?: string; force_overlay?: boolean }
1125
+ options: { offset?: number; title?: string; force_overlay?: boolean; editable?: boolean }
1069
1126
  ): void {
1070
1127
  const c = collector();
1071
1128
  const id = `${kind}${c.barColorConfig.filter((x) => x.kind === kind).length}`;
1072
- c.barColorConfig.push({ id, kind, title: options.title, offset: options.offset, forceOverlay: options.force_overlay });
1129
+ c.barColorConfig.push({
1130
+ id,
1131
+ kind,
1132
+ title: options.title ?? DEFAULT_OUTPUT_TITLES[kind],
1133
+ offset: options.offset,
1134
+ forceOverlay: options.force_overlay,
1135
+ // a constant colour is a palette of one colour (PineScript)
1136
+ ...(typeof colors === 'string' ? { palette: [colors] } : {}),
1137
+ ...(options.editable === false ? { editable: false } : {}),
1138
+ outputIndex: c.outputs.length,
1139
+ });
1073
1140
  const b = bars();
1074
1141
  const off = options.offset ?? 0;
1075
1142
  const target: BgColorData[] = kind === 'bgcolor' ? c.bgColors : c.barColors;
@@ -1079,7 +1146,7 @@ function emitBarColors(
1079
1146
  if (!col) continue;
1080
1147
  const j = i + off;
1081
1148
  if (j < 0 || j >= b.length) continue;
1082
- target.push(forceOverlay ? { time: b[j]!.time, color: col, forceOverlay } : { time: b[j]!.time, color: col });
1149
+ target.push(forceOverlay ? { time: b[j]!.time, color: col, id, forceOverlay } : { time: b[j]!.time, color: col, id });
1083
1150
  }
1084
1151
  }
1085
1152
 
@@ -1089,7 +1156,7 @@ function emitBarColors(
1089
1156
  */
1090
1157
  export function bgcolor(
1091
1158
  colors: string | Array<string | undefined>,
1092
- options: { offset?: number; title?: string; force_overlay?: boolean } = {}
1159
+ options: { offset?: number; title?: string; force_overlay?: boolean; editable?: boolean } = {}
1093
1160
  ): void {
1094
1161
  emitBarColors('bgcolor', colors, options);
1095
1162
  }
@@ -1097,7 +1164,7 @@ export function bgcolor(
1097
1164
  /** PineScript `barcolor()` — per-bar candle color override. */
1098
1165
  export function barcolor(
1099
1166
  colors: string | Array<string | undefined>,
1100
- options: { title?: string } = {}
1167
+ options: { title?: string; editable?: boolean } = {}
1101
1168
  ): void {
1102
1169
  emitBarColors('barcolor', colors, options);
1103
1170
  }
@@ -1115,6 +1182,8 @@ export interface PlotCandleOptions {
1115
1182
  display?: CandleConfig['display'];
1116
1183
  /** Draw on the main chart pane even when the script is not an overlay (PineScript `force_overlay`); default false. */
1117
1184
  force_overlay?: boolean;
1185
+ /** False: not listed in the Style settings of the study (PineScript `editable`); default true. */
1186
+ editable?: boolean;
1118
1187
  }
1119
1188
 
1120
1189
  export interface PlotBarOptions {
@@ -1123,6 +1192,8 @@ export interface PlotBarOptions {
1123
1192
  display?: CandleConfig['display'];
1124
1193
  /** Draw on the main chart pane even when the script is not an overlay (PineScript `force_overlay`); default false. */
1125
1194
  force_overlay?: boolean;
1195
+ /** False: not listed in the Style settings of the study (PineScript `editable`); default true. */
1196
+ editable?: boolean;
1126
1197
  }
1127
1198
 
1128
1199
  /** Colour of bar i: undefined when the argument is not given, 'transparent' for an na entry. */
@@ -1169,6 +1240,7 @@ export function plotcandle(
1169
1240
  ): void {
1170
1241
  const c = collector();
1171
1242
  const id = `plotcandle${c.candleConfig.filter((x) => x.kind === 'candle').length}`;
1243
+ title ??= DEFAULT_OUTPUT_TITLES.candle;
1172
1244
  c.candleConfig.push({
1173
1245
  id,
1174
1246
  kind: 'candle',
@@ -1178,6 +1250,7 @@ export function plotcandle(
1178
1250
  borderColor: staticColor(options.bordercolor),
1179
1251
  display: options.display,
1180
1252
  forceOverlay: options.force_overlay,
1253
+ ...(options.editable === false ? { editable: false } : {}),
1181
1254
  });
1182
1255
  c.outputs.push({ kind: 'candle', id, title });
1183
1256
  const b = bars();
@@ -1208,6 +1281,7 @@ export function plotbar(
1208
1281
  ): void {
1209
1282
  const c = collector();
1210
1283
  const id = `plotbar${c.candleConfig.filter((x) => x.kind === 'bar').length}`;
1284
+ title ??= DEFAULT_OUTPUT_TITLES.bar;
1211
1285
  c.candleConfig.push({
1212
1286
  id,
1213
1287
  kind: 'bar',
@@ -1215,6 +1289,7 @@ export function plotbar(
1215
1289
  color: staticColor(options.color),
1216
1290
  display: options.display,
1217
1291
  forceOverlay: options.force_overlay,
1292
+ ...(options.editable === false ? { editable: false } : {}),
1218
1293
  });
1219
1294
  c.outputs.push({ kind: 'bar', id, title });
1220
1295
  const b = bars();
@@ -184,6 +184,8 @@ export interface PlotData {
184
184
  * Horizontal line data
185
185
  */
186
186
  export interface HLineData {
187
+ /** Id of the declaration that produced it (its config entry) */
188
+ id?: string;
187
189
  /** Y-axis value */
188
190
  value: number;
189
191
  /** Line options */
@@ -194,6 +196,8 @@ export interface HLineData {
194
196
  * Fill data (area between two plots)
195
197
  */
196
198
  export interface FillData {
199
+ /** Id of the declaration that produced it (its config entry) */
200
+ id?: string;
197
201
  /** First plot index or name */
198
202
  plot1: number | string;
199
203
  /** Second plot index or name */
@@ -345,6 +349,8 @@ export interface ArrowData {
345
349
  * Per-bar candle color (barcolor() output)
346
350
  */
347
351
  export interface BarColorData {
352
+ /** Id of the declaration that produced it (its config entry) */
353
+ id?: string;
348
354
  /** Time of the colored bar (offset already applied) */
349
355
  time: number;
350
356
  /** Color */
@@ -355,6 +361,8 @@ export interface BarColorData {
355
361
  * Per-bar background color (bgcolor() output)
356
362
  */
357
363
  export interface BgColorData {
364
+ /** Id of the declaration that produced it (its config entry) */
365
+ id?: string;
358
366
  /** Time of the colored bar (offset already applied) */
359
367
  time: number;
360
368
  /** Color (with its transparency) */