vega2ol 1.0.0 → 1.1.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/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Vega2ol Contributors
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * vega2ol - Vega expression to OpenLayers expression transpiler
3
3
  */
4
- export { vega2ol, Vega2OLError, OLExpression, VegaNode } from './main.js';
4
+ export { vega2ol, Vega2OLError, VegaNode } from './main.js';
package/dist/main.d.ts CHANGED
@@ -1,8 +1,8 @@
1
+ import type { ExpressionValue } from "ol/expr/expression.js";
1
2
  /**
2
3
  * OpenLayers expression types
3
4
  * OL expressions are arrays: ['operator', arg1, arg2, ...] or ['case', condition, value, ...]
4
5
  */
5
- type OLExpression = any[] | string | number | boolean | null;
6
6
  /**
7
7
  * Vega AST node types (simplified)
8
8
  */
@@ -21,5 +21,5 @@ export declare class Vega2OLError extends Error {
21
21
  * @param vegaExpressionStr - A Vega expression string (e.g., "datum.value > 100 ? 'red' : 'blue'")
22
22
  * @returns OpenLayers expression array
23
23
  */
24
- export declare function vega2ol(vegaExpressionStr: string): Promise<OLExpression>;
25
- export { OLExpression, VegaNode };
24
+ export declare function vega2ol(vegaExpressionStr: string): ExpressionValue;
25
+ export { ExpressionValue as OLExpression, VegaNode };
package/dist/main.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { parseExpression } from "vega-expression";
1
2
  /**
2
3
  * Operator mapping from Vega operators to OpenLayers operators
3
4
  */
@@ -21,6 +22,21 @@ const OPERATOR_MAPPING = {
21
22
  // Other
22
23
  "**": "pow",
23
24
  };
25
+ /**
26
+ * Constants mapping from Vega constants to OpenLayers constants
27
+ */
28
+ const CONSTANTS_MAPPING = {
29
+ PI: Math.PI,
30
+ E: Math.E,
31
+ LN2: Math.LN2,
32
+ LN10: Math.LN10,
33
+ LOG2E: Math.LOG2E,
34
+ LOG10E: Math.LOG10E,
35
+ SQRT1_2: Math.SQRT1_2,
36
+ SQRT2: Math.SQRT2,
37
+ MIN_VALUE: Number.MIN_VALUE,
38
+ MAX_VALUE: Number.MAX_VALUE,
39
+ };
24
40
  /**
25
41
  * Function mapping from Vega functions to OpenLayers functions
26
42
  */
@@ -117,16 +133,6 @@ class VegaToOLVisitor {
117
133
  const { operator, left, right } = node;
118
134
  const leftOL = this.visit(left);
119
135
  const rightOL = this.visit(right);
120
- // Handle special cases
121
- if (operator === "in") {
122
- return ["in", leftOL, rightOL];
123
- }
124
- if (operator === "&&") {
125
- return ["all", leftOL, rightOL];
126
- }
127
- if (operator === "||") {
128
- return ["any", leftOL, rightOL];
129
- }
130
136
  const olOp = OPERATOR_MAPPING[operator];
131
137
  if (!olOp) {
132
138
  throw new Vega2OLError(`Unsupported binary operator: ${operator}`);
@@ -183,6 +189,17 @@ class VegaToOLVisitor {
183
189
  const { elements } = node;
184
190
  return elements.map((elem) => this.visit(elem));
185
191
  }
192
+ // Logical expressions
193
+ visitLogicalExpression(node) {
194
+ const { operator, left, right } = node;
195
+ const leftOL = this.visit(left);
196
+ const rightOL = this.visit(right);
197
+ const olOp = OPERATOR_MAPPING[operator];
198
+ if (!olOp) {
199
+ throw new Vega2OLError(`Unsupported logical operator: ${operator}`);
200
+ }
201
+ return [olOp, leftOL, rightOL];
202
+ }
186
203
  // Identifier/Variable: x, PI, etc.
187
204
  visitIdentifier(node) {
188
205
  const { name } = node;
@@ -190,21 +207,8 @@ class VegaToOLVisitor {
190
207
  if (name in this.scope) {
191
208
  return this.scope[name];
192
209
  }
193
- // Vega constants
194
- const vegaConstants = {
195
- PI: Math.PI,
196
- E: Math.E,
197
- LN2: Math.LN2,
198
- LN10: Math.LN10,
199
- LOG2E: Math.LOG2E,
200
- LOG10E: Math.LOG10E,
201
- SQRT1_2: Math.SQRT1_2,
202
- SQRT2: Math.SQRT2,
203
- MIN_VALUE: Number.MIN_VALUE,
204
- MAX_VALUE: Number.MAX_VALUE,
205
- };
206
- if (name in vegaConstants) {
207
- return vegaConstants[name];
210
+ if (name in CONSTANTS_MAPPING) {
211
+ return CONSTANTS_MAPPING[name];
208
212
  }
209
213
  // Return as string (might be a function or field)
210
214
  return name;
@@ -215,13 +219,11 @@ class VegaToOLVisitor {
215
219
  * @param vegaExpressionStr - A Vega expression string (e.g., "datum.value > 100 ? 'red' : 'blue'")
216
220
  * @returns OpenLayers expression array
217
221
  */
218
- export async function vega2ol(vegaExpressionStr) {
222
+ export function vega2ol(vegaExpressionStr) {
219
223
  if (typeof vegaExpressionStr !== "string") {
220
224
  throw new Vega2OLError("Input must be a string");
221
225
  }
222
226
  try {
223
- // Dynamically import parseExpression to handle ESM
224
- const { parseExpression } = await import("vega-expression");
225
227
  // Parse Vega expression to AST
226
228
  const ast = parseExpression(vegaExpressionStr);
227
229
  // Visit the AST and convert to OL expression
@@ -1,4 +1,4 @@
1
- import { vega2ol, Vega2OLError } from "../src/main.js";
1
+ import { vega2ol, Vega2OLError } from "../main.js";
2
2
  // Simple assertion helper
3
3
  function assertEqual(actual, expected, message) {
4
4
  const actualStr = JSON.stringify(actual);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vega2ol",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Vega expression to Open-Layers expression transpiler",
5
5
  "keywords": [
6
6
  "vega",
@@ -9,13 +9,13 @@
9
9
  "transpiler",
10
10
  "geospatial"
11
11
  ],
12
- "homepage": "https://github.com/nakul-py/vega2ol#readme",
12
+ "homepage": "https://github.com/geojupyter/vega2ol#readme",
13
13
  "bugs": {
14
- "url": "https://github.com/nakul-py/vega2ol/issues"
14
+ "url": "https://github.com/geojupyter/vega2ol/issues"
15
15
  },
16
16
  "repository": {
17
17
  "type": "git",
18
- "url": "git+https://github.com/nakul-py/vega2ol.git"
18
+ "url": "git+https://github.com/geojupyter/vega2ol.git"
19
19
  },
20
20
  "license": "BSD-3-Clause",
21
21
  "author": "nakul",
@@ -1,4 +0,0 @@
1
- /**
2
- * vega2ol - Vega expression to OpenLayers expression transpiler
3
- */
4
- export { vega2ol, Vega2OLError, VegaNode } from './main.js';
package/dist/src/index.js DELETED
@@ -1,4 +0,0 @@
1
- /**
2
- * vega2ol - Vega expression to OpenLayers expression transpiler
3
- */
4
- export { vega2ol, Vega2OLError } from './main.js';
@@ -1,25 +0,0 @@
1
- import type { ExpressionValue } from "ol/expr/expression.js";
2
- /**
3
- * OpenLayers expression types
4
- * OL expressions are arrays: ['operator', arg1, arg2, ...] or ['case', condition, value, ...]
5
- */
6
- /**
7
- * Vega AST node types (simplified)
8
- */
9
- interface VegaNode {
10
- type: string;
11
- [key: string]: any;
12
- }
13
- /**
14
- * Custom error class for Vega2OL transpilation errors
15
- */
16
- export declare class Vega2OLError extends Error {
17
- constructor(message: string);
18
- }
19
- /**
20
- * Main transpiler function
21
- * @param vegaExpressionStr - A Vega expression string (e.g., "datum.value > 100 ? 'red' : 'blue'")
22
- * @returns OpenLayers expression array
23
- */
24
- export declare function vega2ol(vegaExpressionStr: string): Promise<ExpressionValue>;
25
- export { ExpressionValue as OLExpression, VegaNode };
package/dist/src/main.js DELETED
@@ -1,240 +0,0 @@
1
- import { parseExpression } from "vega-expression";
2
- /**
3
- * Operator mapping from Vega operators to OpenLayers operators
4
- */
5
- const OPERATOR_MAPPING = {
6
- // Comparison operators
7
- "==": "==",
8
- "!=": "!=",
9
- "<": "<",
10
- "<=": "<=",
11
- ">": ">",
12
- ">=": ">=",
13
- // Logical operators
14
- "&&": "all",
15
- "||": "any",
16
- // Arithmetic operators
17
- "+": "+",
18
- "-": "-",
19
- "*": "*",
20
- "/": "/",
21
- "%": "%",
22
- // Other
23
- "**": "pow",
24
- };
25
- /**
26
- * Constants mapping from Vega constants to OpenLayers constants
27
- */
28
- const CONSTANTS_MAPPING = {
29
- PI: Math.PI,
30
- E: Math.E,
31
- LN2: Math.LN2,
32
- LN10: Math.LN10,
33
- LOG2E: Math.LOG2E,
34
- LOG10E: Math.LOG10E,
35
- SQRT1_2: Math.SQRT1_2,
36
- SQRT2: Math.SQRT2,
37
- MIN_VALUE: Number.MIN_VALUE,
38
- MAX_VALUE: Number.MAX_VALUE,
39
- };
40
- /**
41
- * Function mapping from Vega functions to OpenLayers functions
42
- */
43
- const FUNCTION_MAPPING = {
44
- // Math functions
45
- abs: "abs",
46
- floor: "floor",
47
- ceil: "ceil",
48
- round: "round",
49
- sqrt: "sqrt",
50
- pow: "pow",
51
- log: "log",
52
- exp: "exp",
53
- sin: "sin",
54
- cos: "cos",
55
- tan: "tan",
56
- // String functions
57
- tostring: "toString",
58
- upper: "toUpperCase",
59
- lower: "toLowerCase",
60
- substring: "substring",
61
- // Array functions
62
- length: "length",
63
- indexof: "indexOf",
64
- slice: "slice",
65
- // Type functions
66
- type: "type",
67
- isvalid: "isValid",
68
- isnumber: "isNumber",
69
- isstring: "isString",
70
- isboolean: "isBoolean",
71
- // Aggregation functions
72
- min: "min",
73
- max: "max",
74
- };
75
- /**
76
- * Custom error class for Vega2OL transpilation errors
77
- */
78
- export class Vega2OLError extends Error {
79
- constructor(message) {
80
- const fullMessage = `${message}, note that only a subset of Vega is supported`;
81
- super(fullMessage);
82
- this.name = "Vega2OLError";
83
- }
84
- }
85
- /**
86
- * Visitor class to convert Vega AST to OpenLayers expressions
87
- */
88
- class VegaToOLVisitor {
89
- constructor() {
90
- this.scope = {};
91
- }
92
- visit(node) {
93
- if (!node || !node.type) {
94
- throw new Vega2OLError("Invalid AST node");
95
- }
96
- const method = `visit${node.type}`;
97
- if (typeof this[method] === "function") {
98
- return this[method](node);
99
- }
100
- throw new Vega2OLError(`Unsupported ${node.type} node`);
101
- }
102
- // Literal values
103
- visitLiteral(node) {
104
- const { value } = node;
105
- if (value === null)
106
- return null;
107
- if (typeof value === "boolean")
108
- return value;
109
- if (typeof value === "number")
110
- return value;
111
- if (typeof value === "string")
112
- return value;
113
- throw new Vega2OLError(`Unsupported literal type: ${typeof value}`);
114
- }
115
- // Member access: datum.value, datum['value']
116
- visitMemberExpression(node) {
117
- const { object, property } = node;
118
- if (object.type === "Identifier" && object.name === "datum") {
119
- if (typeof property === "string") {
120
- return ["get", property];
121
- }
122
- // For computed properties - if property is an Identifier with 'name'
123
- if (property.type === "Identifier" && property.name) {
124
- return ["get", property.name];
125
- }
126
- // For computed properties like datum[variable]
127
- return ["get", this.visit(property)];
128
- }
129
- throw new Vega2OLError(`Unsupported member access`);
130
- }
131
- // Binary operations: a + b, a > b, etc.
132
- visitBinaryExpression(node) {
133
- const { operator, left, right } = node;
134
- const leftOL = this.visit(left);
135
- const rightOL = this.visit(right);
136
- const olOp = OPERATOR_MAPPING[operator];
137
- if (!olOp) {
138
- throw new Vega2OLError(`Unsupported binary operator: ${operator}`);
139
- }
140
- return [olOp, leftOL, rightOL];
141
- }
142
- // Unary operations: !x, -x, +x
143
- visitUnaryExpression(node) {
144
- const { operator, argument } = node;
145
- const argOL = this.visit(argument);
146
- if (operator === "!") {
147
- return ["!", argOL];
148
- }
149
- if (operator === "-") {
150
- return ["*", argOL, -1];
151
- }
152
- if (operator === "+") {
153
- return argOL;
154
- }
155
- throw new Vega2OLError(`Unsupported unary operator: ${operator}`);
156
- }
157
- // Conditional: test ? consequent : alternate
158
- visitConditionalExpression(node) {
159
- const { test, consequent, alternate } = node;
160
- const testOL = this.visit(test);
161
- const consequentOL = this.visit(consequent);
162
- const alternateOL = this.visit(alternate);
163
- // OL 'case' expression: ['case', condition1, value1, condition2, value2, ..., defaultValue]
164
- return ["case", testOL, consequentOL, alternateOL];
165
- }
166
- // Function calls: floor(x), ceil(y), etc.
167
- visitCallExpression(node) {
168
- const { callee, arguments: args } = node;
169
- let funcName;
170
- if (callee.type === "Identifier") {
171
- funcName = callee.name;
172
- }
173
- else if (callee.type === "MemberExpression" &&
174
- callee.object.name === "Math") {
175
- funcName = callee.property;
176
- }
177
- else {
178
- throw new Vega2OLError(`Unsupported function call`);
179
- }
180
- const olFunc = FUNCTION_MAPPING[funcName.toLowerCase()];
181
- if (!olFunc) {
182
- throw new Vega2OLError(`Unsupported function: ${funcName}`);
183
- }
184
- const olArgs = args.map((arg) => this.visit(arg));
185
- return [olFunc, ...olArgs];
186
- }
187
- // Array literal: [1, 2, 3]
188
- visitArrayExpression(node) {
189
- const { elements } = node;
190
- return elements.map((elem) => this.visit(elem));
191
- }
192
- // Logical expressions
193
- visitLogicalExpression(node) {
194
- const { operator, left, right } = node;
195
- const leftOL = this.visit(left);
196
- const rightOL = this.visit(right);
197
- const olOp = OPERATOR_MAPPING[operator];
198
- if (!olOp) {
199
- throw new Vega2OLError(`Unsupported logical operator: ${operator}`);
200
- }
201
- return [olOp, leftOL, rightOL];
202
- }
203
- // Identifier/Variable: x, PI, etc.
204
- visitIdentifier(node) {
205
- const { name } = node;
206
- // Check if it's in the current scope
207
- if (name in this.scope) {
208
- return this.scope[name];
209
- }
210
- if (name in CONSTANTS_MAPPING) {
211
- return CONSTANTS_MAPPING[name];
212
- }
213
- // Return as string (might be a function or field)
214
- return name;
215
- }
216
- }
217
- /**
218
- * Main transpiler function
219
- * @param vegaExpressionStr - A Vega expression string (e.g., "datum.value > 100 ? 'red' : 'blue'")
220
- * @returns OpenLayers expression array
221
- */
222
- export async function vega2ol(vegaExpressionStr) {
223
- if (typeof vegaExpressionStr !== "string") {
224
- throw new Vega2OLError("Input must be a string");
225
- }
226
- try {
227
- // Parse Vega expression to AST
228
- const ast = parseExpression(vegaExpressionStr);
229
- // Visit the AST and convert to OL expression
230
- const visitor = new VegaToOLVisitor();
231
- const olExpression = visitor.visit(ast);
232
- return olExpression;
233
- }
234
- catch (error) {
235
- if (error instanceof Vega2OLError) {
236
- throw error;
237
- }
238
- throw new Vega2OLError(`Failed to parse expression: ${error.message}`);
239
- }
240
- }