Comments (3)
@erotavlas My apologies -- I deleted my last response because it was hugely inaccurate. Here's a better one:
Jexl v1 (which is receiving updates only for security issues and major bugs with existing features) only supports webpack (or similar) builds, as well as commonjs require()
. The decision was made for Jexl v2 (see this branch) to drop prebuilt frontend versions of this library due to the sheer number of frameworks and formats to be supported, and the overwhelming popularity of build steps in the frontend development workflow.
So, my suggestion: If you foresee yourself using something like webpack or browserify, You're all set now and in the future. If not, I recommend a build step with Gulp, Grunt, or any of the other numerous options to compile any dependencies that don't explicitly expose a AMD compatibility, and wraps them with a function that provides it.
Sorry this isn't the best answer for your use case!
from jexl.
thanks for the quick reply.
I haven't yet worked with build tools like Grunt or Gulp yet. Just a little exposure to webpack, I was considering using that in my Dojo project. So I'm not sure I understand this part " compile any dependencies that don't explicitly expose a AMD compatibility, and wraps them with a function that provides it"
I did get it working as a module. what I did was rename all instances of 'require' inside the distribution (jexl.min.js) to 'jexlrequire', then incorporated this into my own module and returned the jexl object from that. seems to work ok so far.
What I was trying to do at first was incorporate the original source code into my project as is, so that later on I can build it along with the rest of my project. But do you think the way i did it is good enough?
define([
], function () {
jexlrequire = function e(t, r, n) { function a(i, s) { if (!r[i]) { if (!t[i]) { var p = "function" == typeof jexlrequire && jexlrequire; if (!s && p) return p(i, !0); if (o) return o(i, !0); var u = new Error("Cannot find module '" + i + "'"); throw u.code = "MODULE_NOT_FOUND", u } var c = r[i] = { exports: {} }; t[i][0].call(c.exports, function (e) { var r = t[i][1][e]; return a(r ? r : e) }, c, c.exports, e, t, r, n) } return r[i].exports } for (var o = "function" == typeof jexlrequire && jexlrequire, i = 0; i < n.length; i++) a(n[i]); return a }({ 1: [function (e, t) { function r(e) { this._grammar = e } var n = /^-?(?:(?:[0-9]*\.[0-9]+)|[0-9]+)$/, a = /^[a-zA-Z_\$][a-zA-Z0-9_\$]*$/, o = /\\\\/, i = ["'(?:(?:\\\\')?[^'])*'", '"(?:(?:\\\\")?[^"])*"', "\\s+", "\\btrue\\b", "\\bfalse\\b"], s = ["\\b[a-zA-Z_\\$][a-zA-Z0-9_\\$]*\\b", "(?:(?:[0-9]*\\.[0-9]+)|[0-9]+)"], p = ["binaryOp", "unaryOp", "openParen", "openBracket", "question", "colon"]; r.prototype.getElements = function (e) { var t = this._getSplitRegex(); return e.split(t).filter(function (e) { return e }) }, r.prototype.getTokens = function (e) { for (var t = [], r = !1, n = 0; n < e.length; n++) this._isWhitespace(e[n]) ? t.length && (t[t.length - 1].raw += e[n]) : "-" === e[n] && this._isNegative(t) ? r = !0 : (r && (e[n] = "-" + e[n], r = !1), t.push(this._createToken(e[n]))); return r && t.push(this._createToken("-")), t }, r.prototype.tokenize = function (e) { var t = this.getElements(e); return this.getTokens(t) }, r.prototype._createToken = function (e) { var t = { type: "literal", value: e, raw: e }; if ('"' == e[0] || "'" == e[0]) t.value = this._unquote(e); else if (e.match(n)) t.value = parseFloat(e); else if ("true" === e || "false" === e) t.value = "true" === e; else if (this._grammar[e]) t.type = this._grammar[e].type; else { if (!e.match(a)) throw new Error("Invalid expression token: " + e); t.type = "identifier" } return t }, r.prototype._escapeRegExp = function (e) { return e = e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), e.match(a) && (e = "\\b" + e + "\\b"), e }, r.prototype._getSplitRegex = function () { if (!this._splitRegex) { var e = Object.keys(this._grammar); e = e.sort(function (e, t) { return t.length - e.length }).map(function (e) { return this._escapeRegExp(e) }, this), this._splitRegex = new RegExp("(" + [i.join("|"), e.join("|"), s.join("|")].join("|") + ")") } return this._splitRegex }, r.prototype._isNegative = function (e) { return e.length ? p.some(function (t) { return t === e[e.length - 1].type }) : !0 }, r.prototype._isWhitespace = function (e) { for (var t = 0; t < e.length; t++) if (" " != e[t]) return !1; return !0 }, r.prototype._unquote = function (e) { var t = e[0], r = new RegExp("\\\\" + t, "g"); return e.substr(1, e.length - 2).replace(r, t).replace(o, "\\") }, t.exports = r }, {}], 2: [function (e, t) { var r = e("./handlers"), n = function (e, t, r, n) { this._grammar = e, this._transforms = t || {}, this._context = r || {}, this._relContext = n || this._context }; n.prototype.eval = function (e) { var t = this; return Promise.resolve().then(function () { return r[e.type].call(t, e) }) }, n.prototype.evalArray = function (e) { return Promise.all(e.map(function (e) { return this.eval(e) }, this)) }, n.prototype.evalMap = function (e) { var t = Object.keys(e), r = {}, n = t.map(function (t) { return this.eval(e[t]) }, this); return Promise.all(n).then(function (e) { return e.forEach(function (e, n) { r[t[n]] = e }), r }) }, n.prototype._filterRelative = function (e, t) { var r = []; return Array.isArray(e) || (e = [e]), e.forEach(function (e) { var a = new n(this._grammar, this._transforms, this._context, e); r.push(a.eval(t)) }, this), Promise.all(r).then(function (t) { var r = []; return t.forEach(function (t, n) { t && r.push(e[n]) }), r }) }, n.prototype._filterStatic = function (e, t) { return this.eval(t).then(function (t) { return "boolean" == typeof t ? t ? e : void 0 : e[t] }) }, t.exports = n }, { "./handlers": 3 }], 3: [function (e, t, r) { r.ArrayLiteral = function (e) { return this.evalArray(e.value) }, r.BinaryExpression = function (e) { var t = this; return Promise.all([this.eval(e.left), this.eval(e.right)]).then(function (r) { return t._grammar[e.operator].eval(r[0], r[1]) }) }, r.ConditionalExpression = function (e) { var t = this; return this.eval(e.test).then(function (r) { return r ? e.consequent ? t.eval(e.consequent) : r : t.eval(e.alternate) }) }, r.FilterExpression = function (e) { var t = this; return this.eval(e.subject).then(function (r) { return e.relative ? t._filterRelative(r, e.expr) : t._filterStatic(r, e.expr) }) }, r.Identifier = function (e) { return e.from ? this.eval(e.from).then(function (t) { return void 0 === t ? void 0 : (Array.isArray(t) && (t = t[0]), t ? t[e.value] : void 0) }) : e.relative ? this._relContext[e.value] : this._context[e.value] }, r.Literal = function (e) { return e.value }, r.ObjectLiteral = function (e) { return this.evalMap(e.value) }, r.Transform = function (e) { var t = this._transforms[e.name]; if (!t) throw new Error("Transform '" + e.name + "' is not defined."); return Promise.all([this.eval(e.subject), this.evalArray(e.args || [])]).then(function (e) { return t.apply(null, [e[0]].concat(e[1])) }) }, r.UnaryExpression = function (e) { var t = this; return this.eval(e.right).then(function (r) { return t._grammar[e.operator].eval(r) }) } }, {}], 4: [function (e, t, r) { r.elements = { ".": { type: "dot" }, "[": { type: "openBracket" }, "]": { type: "closeBracket" }, "|": { type: "pipe" }, "{": { type: "openCurl" }, "}": { type: "closeCurl" }, ":": { type: "colon" }, ",": { type: "comma" }, "(": { type: "openParen" }, ")": { type: "closeParen" }, "?": { type: "question" }, "+": { type: "binaryOp", precedence: 30, eval: function (e, t) { return e + t } }, "-": { type: "binaryOp", precedence: 30, eval: function (e, t) { return e - t } }, "*": { type: "binaryOp", precedence: 40, eval: function (e, t) { return e * t } }, "/": { type: "binaryOp", precedence: 40, eval: function (e, t) { return e / t } }, "//": { type: "binaryOp", precedence: 40, eval: function (e, t) { return Math.floor(e / t) } }, "%": { type: "binaryOp", precedence: 50, eval: function (e, t) { return e % t } }, "^": { type: "binaryOp", precedence: 50, eval: function (e, t) { return Math.pow(e, t) } }, "==": { type: "binaryOp", precedence: 20, eval: function (e, t) { return e == t } }, "!=": { type: "binaryOp", precedence: 20, eval: function (e, t) { return e != t } }, ">": { type: "binaryOp", precedence: 20, eval: function (e, t) { return e > t } }, ">=": { type: "binaryOp", precedence: 20, eval: function (e, t) { return e >= t } }, "<": { type: "binaryOp", precedence: 20, eval: function (e, t) { return t > e } }, "<=": { type: "binaryOp", precedence: 20, eval: function (e, t) { return t >= e } }, "&&": { type: "binaryOp", precedence: 10, eval: function (e, t) { return e && t } }, "||": { type: "binaryOp", precedence: 10, eval: function (e, t) { return e || t } }, "in": { type: "binaryOp", precedence: 20, eval: function (e, t) { return "string" == typeof t ? -1 !== t.indexOf(e) : Array.isArray(t) ? t.some(function (t) { return t == e }) : !1 } }, "!": { type: "unaryOp", precedence: 1 / 0, eval: function (e) { return !e } } } }, {}], 5: [function (e, t) { function r(e, t, r) { this._grammar = e, this._state = "expectOperand", this._tree = null, this._exprStr = t || "", this._relative = !1, this._stopMap = r || {} } var n = e("./handlers"), a = e("./states").states; r.prototype.addToken = function (e) { if ("complete" == this._state) throw new Error("Cannot add a new token to a completed Parser"); var t = a[this._state], r = this._exprStr; if (this._exprStr += e.raw, t.subHandler) { this._subParser || this._startSubExpression(r); var o = this._subParser.addToken(e); if (o) { if (this._endSubExpression(), this._parentStop) return o; this._state = o } } else { if (!t.tokenTypes[e.type]) { if (this._stopMap[e.type]) return this._stopMap[e.type]; throw new Error("Token " + e.raw + " (" + e.type + ") unexpected in expression: " + this._exprStr) } var i = t.tokenTypes[e.type], s = n[e.type]; i.handler && (s = i.handler), s && s.call(this, e), i.toState && (this._state = i.toState) } return !1 }, r.prototype.addTokens = function (e) { e.forEach(this.addToken, this) }, r.prototype.complete = function () { if (this._cursor && !a[this._state].completable) throw new Error("Unexpected end of expression: " + this._exprStr); return this._subParser && this._endSubExpression(), this._state = "complete", this._cursor ? this._tree : null }, r.prototype.isRelative = function () { return this._relative }, r.prototype._endSubExpression = function () { a[this._state].subHandler.call(this, this._subParser.complete()), this._subParser = null }, r.prototype._placeAtCursor = function (e) { this._cursor ? (this._cursor.right = e, this._setParent(e, this._cursor)) : this._tree = e, this._cursor = e }, r.prototype._placeBeforeCursor = function (e) { this._cursor = this._cursor._parent, this._placeAtCursor(e) }, r.prototype._setParent = function (e, t) { Object.defineProperty(e, "_parent", { value: t, writable: !0 }) }, r.prototype._startSubExpression = function (e) { var t = a[this._state].endStates; t || (this._parentStop = !0, t = this._stopMap), this._subParser = new r(this._grammar, e, t) }, t.exports = r }, { "./handlers": 6, "./states": 7 }], 6: [function (e, t, r) { r.argVal = function (e) { this._cursor.args.push(e) }, r.arrayStart = function () { this._placeAtCursor({ type: "ArrayLiteral", value: [] }) }, r.arrayVal = function (e) { e && this._cursor.value.push(e) }, r.binaryOp = function (e) { for (var t = this._grammar[e.value].precedence || 0, r = this._cursor._parent; r && r.operator && this._grammar[r.operator].precedence >= t;) this._cursor = r, r = r._parent; var n = { type: "BinaryExpression", operator: e.value, left: this._cursor }; this._setParent(this._cursor, n), this._cursor = r, this._placeAtCursor(n) }, r.dot = function () { this._nextIdentEncapsulate = this._cursor && ("BinaryExpression" != this._cursor.type || "BinaryExpression" == this._cursor.type && this._cursor.right) && "UnaryExpression" != this._cursor.type, this._nextIdentRelative = !this._cursor || this._cursor && !this._nextIdentEncapsulate, this._nextIdentRelative && (this._relative = !0) }, r.filter = function (e) { this._placeBeforeCursor({ type: "FilterExpression", expr: e, relative: this._subParser.isRelative(), subject: this._cursor }) }, r.identifier = function (e) { var t = { type: "Identifier", value: e.value }; this._nextIdentEncapsulate ? (t.from = this._cursor, this._placeBeforeCursor(t), this._nextIdentEncapsulate = !1) : (this._nextIdentRelative && (t.relative = !0), this._placeAtCursor(t)) }, r.literal = function (e) { this._placeAtCursor({ type: "Literal", value: e.value }) }, r.objKey = function (e) { this._curObjKey = e.value }, r.objStart = function () { this._placeAtCursor({ type: "ObjectLiteral", value: {} }) }, r.objVal = function (e) { this._cursor.value[this._curObjKey] = e }, r.subExpression = function (e) { this._placeAtCursor(e) }, r.ternaryEnd = function (e) { this._cursor.alternate = e }, r.ternaryMid = function (e) { this._cursor.consequent = e }, r.ternaryStart = function () { this._tree = { type: "ConditionalExpression", test: this._tree }, this._cursor = this._tree }, r.transform = function (e) { this._placeBeforeCursor({ type: "Transform", name: e.value, args: [], subject: this._cursor }) }, r.unaryOp = function (e) { this._placeAtCursor({ type: "UnaryExpression", operator: e.value }) } }, {}], 7: [function (e, t, r) { var n = e("./handlers"); r.states = { expectOperand: { tokenTypes: { literal: { toState: "expectBinOp" }, identifier: { toState: "identifier" }, unaryOp: {}, openParen: { toState: "subExpression" }, openCurl: { toState: "expectObjKey", handler: n.objStart }, dot: { toState: "traverse" }, openBracket: { toState: "arrayVal", handler: n.arrayStart } } }, expectBinOp: { tokenTypes: { binaryOp: { toState: "expectOperand" }, pipe: { toState: "expectTransform" }, dot: { toState: "traverse" }, question: { toState: "ternaryMid", handler: n.ternaryStart } }, completable: !0 }, expectTransform: { tokenTypes: { identifier: { toState: "postTransform", handler: n.transform } } }, expectObjKey: { tokenTypes: { identifier: { toState: "expectKeyValSep", handler: n.objKey }, closeCurl: { toState: "expectBinOp" } } }, expectKeyValSep: { tokenTypes: { colon: { toState: "objVal" } } }, postTransform: { tokenTypes: { openParen: { toState: "argVal" }, binaryOp: { toState: "expectOperand" }, dot: { toState: "traverse" }, openBracket: { toState: "filter" }, pipe: { toState: "expectTransform" } }, completable: !0 }, postTransformArgs: { tokenTypes: { binaryOp: { toState: "expectOperand" }, dot: { toState: "traverse" }, openBracket: { toState: "filter" }, pipe: { toState: "expectTransform" } }, completable: !0 }, identifier: { tokenTypes: { binaryOp: { toState: "expectOperand" }, dot: { toState: "traverse" }, openBracket: { toState: "filter" }, pipe: { toState: "expectTransform" }, question: { toState: "ternaryMid", handler: n.ternaryStart } }, completable: !0 }, traverse: { tokenTypes: { identifier: { toState: "identifier" } } }, filter: { subHandler: n.filter, endStates: { closeBracket: "identifier" } }, subExpression: { subHandler: n.subExpression, endStates: { closeParen: "expectBinOp" } }, argVal: { subHandler: n.argVal, endStates: { comma: "argVal", closeParen: "postTransformArgs" } }, objVal: { subHandler: n.objVal, endStates: { comma: "expectObjKey", closeCurl: "expectBinOp" } }, arrayVal: { subHandler: n.arrayVal, endStates: { comma: "arrayVal", closeBracket: "expectBinOp" } }, ternaryMid: { subHandler: n.ternaryMid, endStates: { colon: "ternaryEnd" } }, ternaryEnd: { subHandler: n.ternaryEnd, completable: !0 } } }, { "./handlers": 6 }], Jexl: [function (e, t) { function r() { this._customGrammar = null, this._lexer = null, this._transforms = {} } var n = e("./evaluator/Evaluator"), a = e("./Lexer"), o = e("./parser/Parser"), i = e("./grammar").elements; r.prototype.addBinaryOp = function (e, t, r) { this._addGrammarElement(e, { type: "binaryOp", precedence: t, eval: r }) }, r.prototype.addUnaryOp = function (e, t) { this._addGrammarElement(e, { type: "unaryOp", weight: 1 / 0, eval: t }) }, r.prototype.addTransform = function (e, t) { this._transforms[e] = t }, r.prototype.addTransforms = function (e) { for (var t in e) e.hasOwnProperty(t) && (this._transforms[t] = e[t]) }, r.prototype.getTransform = function (e) { return this._transforms[e] }, r.prototype.eval = function (e, t, r) { "function" == typeof t ? (r = t, t = {}) : t || (t = {}); var n = this._eval(e, t); if (r) { var a = !1; return n.then(function (e) { a = !0, setTimeout(r.bind(null, null, e), 0) })["catch"](function (e) { a || setTimeout(r.bind(null, e), 0) }) } return n }, r.prototype.removeOp = function (e) { var t = this._getCustomGrammar(); !t[e] || "binaryOp" != t[e].type && "unaryOp" != t[e].type || (delete t[e], this._lexer = null) }, r.prototype._addGrammarElement = function (e, t) { var r = this._getCustomGrammar(); r[e] = t, this._lexer = null }, r.prototype._eval = function (e, t) { var r = this, a = this._getGrammar(), i = new o(a), s = new n(a, this._transforms, t); return Promise.resolve().then(function () { return i.addTokens(r._getLexer().tokenize(e)), s.eval(i.complete()) }) }, r.prototype._getCustomGrammar = function () { if (!this._customGrammar) { this._customGrammar = {}; for (var e in i) i.hasOwnProperty(e) && (this._customGrammar[e] = i[e]) } return this._customGrammar }, r.prototype._getGrammar = function () { return this._customGrammar || i }, r.prototype._getLexer = function () { return this._lexer || (this._lexer = new a(this._getGrammar())), this._lexer }, t.exports = new r, t.exports.Jexl = r }, { "./Lexer": 1, "./evaluator/Evaluator": 2, "./grammar": 4, "./parser/Parser": 5 }] }, {}, []);
var jexl = jexlrequire('Jexl');
return jexl;
});
from jexl.
Nice solution! That's exactly what I meant by wrapping it in a function-- I wasn't thinking to rename the require
calls (but if that conflicts with dojo then that was good thinking), but getting the jexl instance and just returning that within a define
was my thought. I'm glad you got it!
In v2, if you don't end up with something like webpack, it should be fairly trivial to run browserify to get a frontend-compatible copy of jexl. Actually, I think renaming the require
call to something else (or omitting it entirely) is a feature of browserify, so it might even make sense to look into doing it that way now before v2 is released, as it would take away your need to manually edit the code when new versions come out.
All the best!
from jexl.
Related Issues (20)
- Match operator not recognized HOT 2
- Opinions on functions vs transforms? HOT 3
- '&&' and '||' priority HOT 1
- -a(2,3) HOT 1
- Scientific number notation: 1e2, 2.1e-3 etc HOT 3
- Cannot index into static array or object HOT 4
- Is this project maintained? Do you want a hand? HOT 8
- Errors for bad identifiers HOT 1
- Object's prototype methods return undefined for token type
- Security? does it use actual JS eval function? HOT 1
- Problem with inline if HOT 1
- How to convert AST to an expression string? HOT 5
- Object keys with a space HOT 2
- Run in browser?
- Cannot read properties of undefined (reading '0')
- Backslashes are wrongly unescaped
- Keys with hyphens evaluate to null HOT 1
- Inconsistency between null and undefined operations HOT 1
- Transform Confusion HOT 1
- Minus token is confused for binaryOp in function arguments HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jexl.