diff --git a/build/build.sh b/build/build.sh index bc29c1a4..f0769341 100755 --- a/build/build.sh +++ b/build/build.sh @@ -31,4 +31,4 @@ then fi ./preprocess.sh $MODE ../src/paper.js "-d '{ \"browser\": true }' -i '../src/constants.js'" ../dist/paper.js -#./preprocess.sh $MODE ../src/paper.js "-d '{ \"server\": true }' -i '../src/constants.js'" ../dist/paper-server.js +#./preprocess.sh $MODE ../src/paper.js "-d '{ \"node\": true }' -i '../src/constants.js'" ../dist/paper-node.js diff --git a/build/preprocess.sh b/build/preprocess.sh index 3482a6a2..6acfb1e9 100755 --- a/build/preprocess.sh +++ b/build/preprocess.sh @@ -24,10 +24,19 @@ # commented Preprocessed, still formated and commented # stripped Preprocessed, formated but without comments -VERSION=0.8 +# Get the date from the git log: DATE=$(git log -1 --pretty=format:%ad) - -COMMAND="./prepro.js -d '{ \"version\": $VERSION, \"date\": \"$DATE\", \"parser\": \"acorn\", \"svg\": true, \"fatline\": false }' $3 $2" +# Extract the paper.js version from package.json: +VERSION=$(node -e " + process.stdout.write(require('../package.json').version) +") +# Load and evaluate the options from options.js, and convert it an escaped json: +OPTIONS=$(printf '%q' $(node -e " + eval(require('fs').readFileSync('../src/options.js', 'utf8')); + process.stdout.write(JSON.stringify(options)); +")) +# Build the prepo.js command out of it, passing on version and date as defines: +COMMAND="./prepro.js -d $OPTIONS -d '{ \"version\": \"$VERSION\", \"date\": \"$DATE\", \"stats\": false }' $3 $2" case $1 in commented) diff --git a/fatline/intersectTests.js b/fatline/intersectTests.js index 2dfc2632..e9730862 100644 --- a/fatline/intersectTests.js +++ b/fatline/intersectTests.js @@ -1,4 +1,5 @@ - +// Uncomment this to turn on fatline clipping in paper.js too +options.fatline = true; paper.install(window); /** @@ -235,40 +236,40 @@ function runTests() { prepareTest('Results - Boolean tests (Time taken per test)', container, 'big'); var x = 80.5, y = 15.5, width = 500, height = 190, i, txt, ny, yy = y + height, xx = x + width; - var ppaperfill = new Path(), pfatfill = new Path(); - var ppaper = new Path(), pfat = new Path(); - var max = testdata.reduce(function(a, b) { return Math.max(a, b.paperTime + b.fatTime); }, 0) + 20; + var ppaper = new Path(), + pfat = new Path(); + var max = testdata.reduce(function(a, b) { + return Math.max(a, b.paperTime + b.fatTime); + }, 0) + 20; var vscale = height / max, hscale = width / testdata.length; var caxes = '#999', ctxt = '#222', ctxt2 = '#555', cpaper = '#268BD2', cpaperfill ='#B5E1FF', cfat = '#D33682', cfatfill = '#FFADD4'; - new Path.Line(x, yy, xx, yy).style.strokeColor = caxes; - new Path.Line(x, yy, x, y).style.strokeColor = caxes; + new Path.Line(x, yy, xx, yy).strokeColor = caxes; + new Path.Line(x, yy, x, y).strokeColor = caxes; for (i = 0; i < 10 ; i++) { ny = yy - vscale * max * i / 10; - new Path.Line(x, ny, x-5, ny).style.strokeColor = caxes; + new Path.Line(x, ny, x-5, ny).strokeColor = caxes; txt = new PointText([x-10, ny]); txt.justification = 'right'; txt.fillColor = (i%2)? ctxt: ctxt2; txt.content = (max * i / 10).toFixed(1) + ((!i)? ' ms' : ''); } - ppaperfill.add(new Segment(x, yy)); - pfatfill.add(new Segment(x, yy)); + ppaper.add(x, yy); + pfat.add(x, yy); var vx = x, clr = ctxt; var coords = [], avgPaper = 0, avgFat = 0, maxSpeedup = -Infinity, minSpeedup = Infinity, avgSpeedup = 0; testdata.map(function(data) { avgPaper += data.paperTime; - ny = yy - (data.paperTime + data.fatTime) * vscale; - ppaper.add(new Segment([vx, ny])); - ppaperfill.add(new Segment([vx, ny])); + ny = yy - (data.paperTime /*+ data.fatTime */) * vscale; + ppaper.add(vx, ny); var np = new Point(vx, ny); np._data = data; np._datatype = 'paper'; coords.push(np); avgFat += data.fatTime; ny = yy - (data.fatTime) * vscale; - pfat.add(new Segment([vx, ny])); - pfatfill.add(new Segment([vx, ny])); + pfat.add(vx, ny); np = new Point(vx, ny); np._data = data; np._datatype = 'fat'; @@ -279,7 +280,7 @@ function runTests() { if (speedup < minSpeedup) minSpeedup = speedup; avgSpeedup += speedup; - new Path.Line(vx, yy, vx, yy + 5).style.strokeColor = caxes; + new Path.Line(vx, yy, vx, yy + 5).strokeColor = caxes; txt = new PointText([vx, yy+18]); txt.justification = 'left'; txt.fillColor = clr; @@ -288,23 +289,25 @@ function runTests() { if (!data.success) { var p = new Path.Line(vx, y, vx, yy); - p.style.strokeWidth = 5; - p.style.strokeColor = '#f00'; + p.strokeWidth = 5; + p.strokeColor = '#f00'; } clr = (clr === ctxt)? ctxt2 : ctxt; vx += hscale; }); - ppaper.style.strokeWidth = 2; - ppaper.style.strokeColor = cpaper; - ppaperfill.add(new Segment(vx-hscale, yy)); - ppaperfill.closed = true; - ppaperfill.style.fillColor = cpaperfill; - pfat.style.strokeWidth = 2; - pfat.style.strokeColor = cfat; - pfatfill.add(new Segment(vx-hscale, yy)); - pfatfill.closed = true; - pfatfill.style.fillColor = cfatfill; + ppaper.strokeWidth = 2; + ppaper.strokeColor = cpaper; + ppaper.add(vx-hscale, yy); + ppaper.closed = true; + ppaper.fillColor = cpaperfill; + ppaper.opacity = 0.75; + pfat.strokeWidth = 2; + pfat.strokeColor = cfat; + pfat.add(vx-hscale, yy); + pfat.closed = true; + pfat.fillColor = cfatfill; + pfat.opacity = 0.75; avgPaper/= testdata.length; avgFat/= testdata.length; @@ -312,13 +315,13 @@ function runTests() { maxSpeedup = Math.round(maxSpeedup); minSpeedup = Math.round(minSpeedup); ny = Math.round(yy - avgPaper * vscale) + 0.5; - new Path.Line(x, ny, xx, ny).style.strokeColor = cpaper; + new Path.Line(x, ny, xx, ny).strokeColor = cpaper; txt = new PointText([xx, ny]); txt.justification = 'right'; txt.fillColor = cpaper; txt.content = avgPaper.toFixed(1); ny = Math.round(yy - avgFat * vscale) + 0.5; - new Path.Line(x, ny, xx, ny).style.strokeColor = cfat; + new Path.Line(x, ny, xx, ny).strokeColor = cfat; txt = new PointText([xx, ny]); txt.justification = 'right'; txt.fillColor = cfat; @@ -358,10 +361,10 @@ function runTests() { if (dist > 500) { return; } if (pnt && data) { var p = new Path.Line(pnt.x+0.5, y, pnt.x+0.5, yy); - p.style.strokeColor = '#000'; + p.strokeColor = '#000'; p.removeOnMove(); p = new Path.Circle(pnt, 3); - p.style.fillColor = (type === 'fat')? '#D33682' :'#268BD2'; + p.fillColor = (type === 'fat')? '#D33682' :'#268BD2'; p.removeOnMove(); var txt = new PointText([ 500, 20 ]); txt.content = 'subdiv : ' + data.paperTime.toFixed(1) + ' ms'; @@ -563,8 +566,8 @@ function markPoint(pnt, t, c, tc, remove) { c = c || '#000'; if (remove === undefined) { remove = true; } var cir = new Path.Circle(pnt, 2); - cir.style.fillColor = c; - cir.style.strokeColor = tc; + cir.fillColor = c; + cir.strokeColor = tc; if (t !== undefined || t !== null) { var text = new PointText(pnt.add([0, -3])); text.justification = 'center'; @@ -588,7 +591,7 @@ function markCurve(crv, c, flag) { new Segment([crv[0], crv[1]], null, [crv[2] - crv[0], crv[3] - crv[1]]), new Segment([crv[6], crv[7]], [crv[4] - crv[6], crv[5] - crv[7]], null) ); - window.__p1.style.strokeColor = c; + window.__p1.strokeColor = c; // window.__p1.fullySelected = true; } else { if (window.__p2) window.__p2.remove(); @@ -596,7 +599,7 @@ function markCurve(crv, c, flag) { new Segment([crv[0], crv[1]], null, [crv[2] - crv[0], crv[3] - crv[1]]), new Segment([crv[6], crv[7]], [crv[4] - crv[6], crv[5] - crv[7]], null) ); - window.__p2.style.strokeColor = c; + window.__p2.strokeColor = c; // window.__p2.fullySelected = true; } view.draw(); @@ -624,8 +627,8 @@ function annotateSegment(s, t, c, tc, remove, skipCurves) { var t1 = crv.getNormal(0).normalize(10); var p = s.point.clone().add(t1); var cir = new Path.Circle(s.point, 2); - cir.style.fillColor = c; - cir.style.strokeColor = tc; + cir.fillColor = c; + cir.strokeColor = tc; var text = new PointText(p); text.justification = 'center'; text.fillColor = c; @@ -657,8 +660,8 @@ function annotateCurve(crv, t, c, tc, remove) { text.justification = 'center'; text.fillColor = tc; text.content = t; - l.style.strokeColor = l2.style.strokeColor = c; - cir.style.fillColor = c; + l.strokeColor = l2.strokeColor = c; + cir.fillColor = c; if (remove) { l.removeOnMove(); l2.removeOnMove(); @@ -677,11 +680,11 @@ function plotDataRandom(testdata) { testdata.sort(function(a,b) { return a.ratio - b.ratio; }); var vscale = height / max, hscale = width / testdata.length; var caxes = '#999', ctxt = '#222', cpaper = '#268BD2', cfat = '#D33682'; - new Path.Line(x, yy, xx, yy).style.strokeColor = caxes; - new Path.Line(x, yy, x, y).style.strokeColor = caxes; + new Path.Line(x, yy, xx, yy).strokeColor = caxes; + new Path.Line(x, yy, x, y).strokeColor = caxes; for (i = 0; i < 10 ; i++) { ny = yy - vscale * max * i / 10; - new Path.Line(x, ny, x-5, ny).style.strokeColor = caxes; + new Path.Line(x, ny, x-5, ny).strokeColor = caxes; txt = new PointText([x-10, ny]); txt.justification = 'right'; txt.fillColor = ctxt; @@ -699,13 +702,13 @@ function plotDataRandom(testdata) { var avgPaper = 0, avgFat = 0; testdata.map(function(data) { avgPaper += data.paperTime; - ny = yy - (data.paperTime + data.fatTime) * vscale; - ppaper.add(new Segment([vx, ny])); + ny = yy - (data.paperTime /* + data.fatTime*/) * vscale; + ppaper.add(vx, ny); avgFat += data.fatTime; ny = yy - (data.fatTime) * vscale; - pfat.add(new Segment([vx, ny])); + pfat.add(vx, ny); - new Path.Line(vx, yy, vx, yy + 5 + ((count%2)? step:0)).style.strokeColor = caxes; + new Path.Line(vx, yy, vx, yy + 5 + ((count%2)? step:0)).strokeColor = caxes; txt = new PointText([vx, yy+18 + ((count%2)? step:0) ]); txt.justification = 'center'; txt.fillColor = ctxt; @@ -718,29 +721,31 @@ function plotDataRandom(testdata) { if (!data.success) { var p = new Path.Line(vx, y, vx, yy); - p.style.strokeWidth = 5; - p.style.strokeColor = '#f00'; + p.strokeWidth = 5; + p.strokeColor = '#f00'; } ++count; vx += hscale; }); - ppaper.smooth(); - ppaper.style.strokeWidth = 2; - ppaper.style.strokeColor = cpaper; - pfat.smooth(); - pfat.style.strokeWidth = 2; - pfat.style.strokeColor = cfat; +// ppaper.smooth(); + ppaper.strokeWidth = 2; + ppaper.strokeColor = cpaper; + ppaper.opacity = 0.75; +// pfat.smooth(); + pfat.strokeWidth = 2; + pfat.strokeColor = cfat; + pfat.opacity = 0.75; avgPaper/= testdata.length; avgFat/= testdata.length; ny = Math.round(yy - avgPaper * vscale) + 0.5; - new Path.Line(x, ny, xx, ny).style.strokeColor = cpaper; + new Path.Line(x, ny, xx, ny).strokeColor = cpaper; txt = new PointText([xx, ny]); txt.justification = 'right'; txt.fillColor = cpaper; txt.content = avgPaper.toFixed(1); ny = Math.round(yy - avgFat * vscale) + 0.5; - new Path.Line(x, ny, xx, ny).style.strokeColor = cfat; + new Path.Line(x, ny, xx, ny).strokeColor = cfat; txt = new PointText([xx, ny]); txt.justification = 'right'; txt.fillColor = cfat; @@ -749,80 +754,78 @@ function plotDataRandom(testdata) { view.draw(); } - - function drawFatline(v1) { - function signum(num) { - return (num > 0)? 1 : (num < 0)? -1 : 0; - } - var l = new Line([v1[0], v1[1]], [v1[6], v1[7]], false); - var p1 = new Point(v1[2], v1[3]), p2 = new Point(v1[4], v1[5]); - var d1 = l.getSide(p1) * l.getDistance(p1) || 0; - var d2 = l.getSide(p2) * l.getDistance(p2) || 0; - var dmin, dmax; - if (d1 * d2 > 0) { - // 3/4 * min{0, d1, d2} - dmin = 0.75 * Math.min(0, d1, d2); - dmax = 0.75 * Math.max(0, d1, d2); - } else { - // 4/9 * min{0, d1, d2} - dmin = 4 * Math.min(0, d1, d2) / 9.0; - dmax = 4 * Math.max(0, d1, d2) / 9.0; - } - var ll = new Path.Line(v1[0], v1[1], v1[6], v1[7]); - window.__p3.push(ll); - window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9, 0.8); - var lp1 = ll.segments[0].point; - var lp2 = ll.segments[1].point; - var pm = l.vector, pm1 = pm.rotate(signum(dmin) * -90), pm2 = pm.rotate(signum(dmax) * -90); - var p11 = lp1.add(pm1.normalize(Math.abs(dmin))); - var p12 = lp2.add(pm1.normalize(Math.abs(dmin))); - var p21 = lp1.add(pm2.normalize(Math.abs(dmax))); - var p22 = lp2.add(pm2.normalize(Math.abs(dmax))); - window.__p3.push(new Path.Line(p11, p12)); - window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9); - window.__p3.push(new Path.Line(p21, p22)); - window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9); + function signum(num) { + return (num > 0)? 1 : (num < 0)? -1 : 0; + } + var l = new Line([v1[0], v1[1]], [v1[6], v1[7]], false); + var p1 = new Point(v1[2], v1[3]), p2 = new Point(v1[4], v1[5]); + var d1 = l.getSide(p1) * l.getDistance(p1) || 0; + var d2 = l.getSide(p2) * l.getDistance(p2) || 0; + var dmin, dmax; + if (d1 * d2 > 0) { + // 3/4 * min{0, d1, d2} + dmin = 0.75 * Math.min(0, d1, d2); + dmax = 0.75 * Math.max(0, d1, d2); + } else { + // 4/9 * min{0, d1, d2} + dmin = 4 * Math.min(0, d1, d2) / 9.0; + dmax = 4 * Math.max(0, d1, d2) / 9.0; + } + var ll = new Path.Line(v1[0], v1[1], v1[6], v1[7]); + window.__p3.push(ll); + window.__p3[window.__p3.length-1].strokeColor = new Color(0,0,0.9, 0.8); + var lp1 = ll.segments[0].point; + var lp2 = ll.segments[1].point; + var pm = l.vector, pm1 = pm.rotate(signum(dmin) * -90), pm2 = pm.rotate(signum(dmax) * -90); + var p11 = lp1.add(pm1.normalize(Math.abs(dmin))); + var p12 = lp2.add(pm1.normalize(Math.abs(dmin))); + var p21 = lp1.add(pm2.normalize(Math.abs(dmax))); + var p22 = lp2.add(pm2.normalize(Math.abs(dmax))); + window.__p3.push(new Path.Line(p11, p12)); + window.__p3[window.__p3.length-1].strokeColor = new Color(0,0,0.9); + window.__p3.push(new Path.Line(p21, p22)); + window.__p3[window.__p3.length-1].strokeColor = new Color(0,0,0.9); } function plotD_vs_t(x, y, arr, arr2, v, dmin, dmax, tmin, tmax, yscale, tvalue) { - yscale = yscale || 1; - new Path.Line(x, y-100, x, y+100).style.strokeColor = '#aaa'; - new Path.Line(x, y, x + 200, y).style.strokeColor = '#aaa'; + yscale = yscale || 1; + new Path.Line(x, y-100, x, y+100).strokeColor = '#aaa'; + new Path.Line(x, y, x + 200, y).strokeColor = '#aaa'; - var clr = (tvalue)? '#a00' : '#00a'; - if (window.__p3) window.__p3.map(function(a) {a.remove();}); + var clr = (tvalue)? '#a00' : '#00a'; + if (window.__p3) window.__p3.map(function(a) {a.remove();}); - window.__p3 = []; + window.__p3 = []; - drawFatline(v); + drawFatline(v); - window.__p3.push(new Path.Line(x, y + dmin * yscale, x + 200, y + dmin * yscale)); - window.__p3[window.__p3.length-1].style.strokeColor = '#000'; - window.__p3.push(new Path.Line(x, y + dmax * yscale, x + 200, y + dmax * yscale)); - window.__p3[window.__p3.length-1].style.strokeColor = '#000'; - window.__p3.push(new Path.Line(x + tmin * 190, y-100, x + tmin * 190, y+100)); - window.__p3[window.__p3.length-1].style.strokeColor = clr; - window.__p3.push(new Path.Line(x + tmax * 190, y-100, x + tmax * 190, y+100)); - window.__p3[window.__p3.length-1].style.strokeColor = clr; + window.__p3.push(new Path.Line(x, y + dmin * yscale, x + 200, y + dmin * yscale)); + window.__p3[window.__p3.length-1].strokeColor = '#000'; + window.__p3.push(new Path.Line(x, y + dmax * yscale, x + 200, y + dmax * yscale)); + window.__p3[window.__p3.length-1].strokeColor = '#000'; + window.__p3.push(new Path.Line(x + tmin * 190, y-100, x + tmin * 190, y+100)); + window.__p3[window.__p3.length-1].strokeColor = clr; + window.__p3.push(new Path.Line(x + tmax * 190, y-100, x + tmax * 190, y+100)); + window.__p3[window.__p3.length-1].strokeColor = clr; - for (var i = 0; i < arr.length; i++) { - window.__p3.push(new Path.Line(new Point(x + arr[i][0] * 190, y + arr[i][1] * yscale), - new Point(x + arr[i][2] * 190, y + arr[i][3] * yscale))); - window.__p3[window.__p3.length-1].style.strokeColor = '#999'; - } - var pnt = []; - var arr2x = [ 0.0, 0.333333333, 0.6666666666, 1.0 ]; - for (var i = 0; i < arr2.length; i++) { - pnt.push(new Point(x + arr2x[i] * 190, y + arr2[i] * yscale)); - window.__p3.push(new Path.Circle(pnt[pnt.length-1], 2)); - window.__p3[window.__p3.length-1].style.fillColor = '#000'; - } - // var pth = new Path(pnt[0], pnt[1], pnt[2], pnt[3]); - // pth.closed = true; - window.__p3.push(new Path( - new Segment(pnt[0], null, pnt[1].subtract(pnt[0])), - new Segment(pnt[3], pnt[2].subtract(pnt[3]), null))); - window.__p3[window.__p3.length-1].style.strokeColor = clr; - view.draw(); + for (var i = 0; i < arr.length; i++) { + window.__p3.push(new Path.Line(new Point(x + arr[i][0] * 190, y + arr[i][1] * yscale), + new Point(x + arr[i][2] * 190, y + arr[i][3] * yscale))); + window.__p3[window.__p3.length-1].strokeColor = '#999'; + } + var pnt = []; + var arr2x = [ 0.0, 0.333333333, 0.6666666666, 1.0 ]; + for (var i = 0; i < arr2.length; i++) { + pnt.push(new Point(x + arr2x[i] * 190, y + arr2[i] * yscale)); + window.__p3.push(new Path.Circle(pnt[pnt.length-1], 2)); + window.__p3[window.__p3.length-1].fillColor = '#000'; + } + // var pth = new Path(pnt[0], pnt[1], pnt[2], pnt[3]); + // pth.closed = true; + window.__p3.push(new Path( + new Segment(pnt[0], null, pnt[1].subtract(pnt[0])), + new Segment(pnt[3], pnt[2].subtract(pnt[3]), null))); + window.__p3[window.__p3.length-1].strokeColor = clr; + view.draw(); } diff --git a/lib/acorn-min.js b/lib/acorn-min.js index 80abac98..b9296864 100644 --- a/lib/acorn-min.js +++ b/lib/acorn-min.js @@ -1 +1 @@ -(function(e){return"object"==typeof exports&&"object"==typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):(e(this.acorn||(this.acorn={})),void 0)})(function(e){"use strict";function r(e){fr=e||{};for(var r in hr)fr.hasOwnProperty(r)||(fr[r]=hr[r]);mr=fr.sourceFile||null}function t(e,r){var t=vr(pr,e);r+=" ("+t.line+":"+t.column+")";var n=new SyntaxError(r);throw n.pos=e,n.loc=t,n.raisedAt=br,n}function n(e){function r(e){if(1==e.length)return t+="return str === "+JSON.stringify(e[0])+";";t+="switch(str){";for(var r=0;e.length>r;++r)t+="case "+JSON.stringify(e[r])+":";t+="return true}return false;"}e=e.split(" ");var t="",n=[];e:for(var a=0;e.length>a;++a){for(var o=0;n.length>o;++o)if(n[o][0].length==e[a].length){n[o].push(e[a]);continue e}n.push([e[a]])}if(n.length>3){n.sort(function(e,r){return r.length-e.length}),t+="switch(str.length){";for(var a=0;n.length>a;++a){var i=n[a];t+="case "+i[0].length+":",r(i)}t+="}"}else r(e);return Function("str",t)}function a(){this.line=Ar,this.column=br-Sr}function o(){Ar=1,br=Sr=0,Er=!0,u()}function i(e,r){gr=br,fr.locations&&(kr=new a),wr=e,u(),Cr=r,Er=e.beforeExpr}function s(){var e=fr.onComment&&fr.locations&&new a,r=br,n=pr.indexOf("*/",br+=2);if(-1===n&&t(br-2,"Unterminated comment"),br=n+2,fr.locations){Kt.lastIndex=r;for(var o;(o=Kt.exec(pr))&&br>o.index;)++Ar,Sr=o.index+o[0].length}fr.onComment&&fr.onComment(!0,pr.slice(r+2,n),r,br,e,fr.locations&&new a)}function c(){for(var e=br,r=fr.onComment&&fr.locations&&new a,t=pr.charCodeAt(br+=2);dr>br&&10!==t&&13!==t&&8232!==t&&8329!==t;)++br,t=pr.charCodeAt(br);fr.onComment&&fr.onComment(!1,pr.slice(e+2,br),e,br,r,fr.locations&&new a)}function u(){for(;dr>br;){var e=pr.charCodeAt(br);if(32===e)++br;else if(13===e){++br;var r=pr.charCodeAt(br);10===r&&++br,fr.locations&&(++Ar,Sr=br)}else if(10===e)++br,++Ar,Sr=br;else if(14>e&&e>8)++br;else if(47===e){var r=pr.charCodeAt(br+1);if(42===r)s();else{if(47!==r)break;c()}}else if(14>e&&e>8||32===e||160===e)++br;else{if(!(e>=5760&&Wt.test(String.fromCharCode(e))))break;++br}}}function l(){var e=pr.charCodeAt(br+1);return e>=48&&57>=e?E(!0):(++br,i(gt))}function f(){var e=pr.charCodeAt(br+1);return Er?(++br,k()):61===e?x(Ct,2):x(kt,1)}function p(){var e=pr.charCodeAt(br+1);return 61===e?x(Ct,2):x(Ot,1)}function d(e){var r=pr.charCodeAt(br+1);return r===e?x(124===e?It:Lt,2):61===r?x(Ct,2):x(124===e?Ut:Tt,1)}function m(){var e=pr.charCodeAt(br+1);return 61===e?x(Ct,2):x(Rt,1)}function h(e){var r=pr.charCodeAt(br+1);return r===e?x(At,2):61===r?x(Ct,2):x(Et,1)}function v(e){var r=pr.charCodeAt(br+1),t=1;return r===e?(t=62===e&&62===pr.charCodeAt(br+2)?3:2,61===pr.charCodeAt(br+t)?x(Ct,t+1):x(Ft,t)):(61===r&&(t=61===pr.charCodeAt(br+2)?3:2),x(qt,t))}function b(e){var r=pr.charCodeAt(br+1);return 61===r?x(Vt,61===pr.charCodeAt(br+2)?3:2):x(61===e?wt:St,1)}function y(e){switch(e){case 46:return l();case 40:return++br,i(mt);case 41:return++br,i(ht);case 59:return++br,i(bt);case 44:return++br,i(vt);case 91:return++br,i(lt);case 93:return++br,i(ft);case 123:return++br,i(pt);case 125:return++br,i(dt);case 58:return++br,i(yt);case 63:return++br,i(xt);case 48:var r=pr.charCodeAt(br+1);if(120===r||88===r)return C();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return E(!1);case 34:case 39:return A(e);case 47:return f(e);case 37:case 42:return p();case 124:case 38:return d(e);case 94:return m();case 43:case 45:return h(e);case 60:case 62:return v(e);case 61:case 33:return b(e);case 126:return x(St,1)}return!1}function g(e){if(e?br=yr+1:yr=br,fr.locations&&(xr=new a),e)return k();if(br>=dr)return i(Dr);var r=pr.charCodeAt(br);if(Qt(r)||92===r)return L();var n=y(r);if(n===!1){var o=String.fromCharCode(r);if("\\"===o||$t.test(o))return L();t(br,"Unexpected character '"+o+"'")}return n}function x(e,r){var t=pr.slice(br,br+r);br+=r,i(e,t)}function k(){for(var e,r,n="",a=br;;){br>=dr&&t(a,"Unterminated regular expression");var o=pr.charAt(br);if(Ht.test(o)&&t(a,"Unterminated regular expression"),e)e=!1;else{if("["===o)r=!0;else if("]"===o&&r)r=!1;else if("/"===o&&!r)break;e="\\"===o}++br}var n=pr.slice(a,br);++br;var s=I();return s&&!/^[gmsiy]*$/.test(s)&&t(a,"Invalid regexp flag"),i(Fr,RegExp(n,s))}function w(e,r){for(var t=br,n=0,a=0,o=null==r?1/0:r;o>a;++a){var i,s=pr.charCodeAt(br);if(i=s>=97?s-97+10:s>=65?s-65+10:s>=48&&57>=s?s-48:1/0,i>=e)break;++br,n=n*e+i}return br===t||null!=r&&br-t!==r?null:n}function C(){br+=2;var e=w(16);return null==e&&t(yr+2,"Expected hexadecimal number"),Qt(pr.charCodeAt(br))&&t(br,"Identifier directly after number"),i(qr,e)}function E(e){var r=br,n=!1,a=48===pr.charCodeAt(br);e||null!==w(10)||t(r,"Invalid number"),46===pr.charCodeAt(br)&&(++br,w(10),n=!0);var o=pr.charCodeAt(br);(69===o||101===o)&&(o=pr.charCodeAt(++br),(43===o||45===o)&&++br,null===w(10)&&t(r,"Invalid number"),n=!0),Qt(pr.charCodeAt(br))&&t(br,"Identifier directly after number");var s,c=pr.slice(r,br);return n?s=parseFloat(c):a&&1!==c.length?/[89]/.test(c)||Vr?t(r,"Invalid number"):s=parseInt(c,8):s=parseInt(c,10),i(qr,s)}function A(e){br++;for(var r="";;){br>=dr&&t(yr,"Unterminated string constant");var n=pr.charCodeAt(br);if(n===e)return++br,i(Or,r);if(92===n){n=pr.charCodeAt(++br);var a=/^[0-7]+/.exec(pr.slice(br,br+3));for(a&&(a=a[0]);a&&parseInt(a,8)>255;)a=a.slice(0,a.length-1);if("0"===a&&(a=null),++br,a)Vr&&t(br-2,"Octal literal in strict mode"),r+=String.fromCharCode(parseInt(a,8)),br+=a.length-1;else switch(n){case 110:r+="\n";break;case 114:r+="\r";break;case 120:r+=String.fromCharCode(S(2));break;case 117:r+=String.fromCharCode(S(4));break;case 85:r+=String.fromCharCode(S(8));break;case 116:r+=" ";break;case 98:r+="\b";break;case 118:r+="";break;case 102:r+="\f";break;case 48:r+="\0";break;case 13:10===pr.charCodeAt(br)&&++br;case 10:fr.locations&&(Sr=br,++Ar);break;default:r+=String.fromCharCode(n)}}else(13===n||10===n||8232===n||8329===n)&&t(yr,"Unterminated string constant"),r+=String.fromCharCode(n),++br}}function S(e){var r=w(16,e);return null===r&&t(yr,"Bad character escape sequence"),r}function I(){Dt=!1;for(var e,r=!0,n=br;;){var a=pr.charCodeAt(br);if(Yt(a))Dt&&(e+=pr.charAt(br)),++br;else{if(92!==a)break;Dt||(e=pr.slice(n,br)),Dt=!0,117!=pr.charCodeAt(++br)&&t(br,"Expecting Unicode escape sequence \\uXXXX"),++br;var o=S(4),i=String.fromCharCode(o);i||t(br-1,"Invalid Unicode escape"),(r?Qt(o):Yt(o))||t(br-4,"Invalid Unicode escape"),e+=i}r=!1}return Dt?e:pr.slice(n,br)}function L(){var e=I(),r=jr;return Dt||(Nt(e)?r=ut[e]:(fr.forbidReserved&&(3===fr.ecmaVersion?Bt:Mt)(e)||Vr&&zt(e))&&t(yr,"The keyword '"+e+"' is reserved")),i(r,e)}function U(){Ir=yr,Lr=gr,Ur=kr,g()}function R(e){for(Vr=e,br=Lr;Sr>br;)Sr=pr.lastIndexOf("\n",Sr-2)+1,--Ar;u(),g()}function T(){this.type=null,this.start=yr,this.end=null}function V(){this.start=xr,this.end=null,null!==mr&&(this.source=mr)}function q(){var e=new T;return fr.locations&&(e.loc=new V),fr.ranges&&(e.range=[yr,0]),e}function F(e){var r=new T;return r.start=e.start,fr.locations&&(r.loc=new V,r.loc.start=e.loc.start),fr.ranges&&(r.range=[e.range[0],0]),r}function O(e,r){return e.type=r,e.end=Lr,fr.locations&&(e.loc.end=Ur),fr.ranges&&(e.range[1]=Lr),e}function j(e){return fr.ecmaVersion>=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"use strict"===e.expression.value}function D(e){return wr===e?(U(),!0):void 0}function B(){return!fr.strictSemicolons&&(wr===Dr||wr===dt||Ht.test(pr.slice(Lr,yr)))}function M(){D(bt)||B()||X()}function z(e){wr===e?U():X()}function X(){t(yr,"Unexpected token")}function N(e){"Identifier"!==e.type&&"MemberExpression"!==e.type&&t(e.start,"Assigning to rvalue"),Vr&&"Identifier"===e.type&&Xt(e.name)&&t(e.start,"Assigning to "+e.name+" in strict mode")}function W(e){Ir=Lr=br,fr.locations&&(Ur=new a),Rr=Vr=null,Tr=[],g();var r=e||q(),t=!0;for(e||(r.body=[]);wr!==Dr;){var n=J();r.body.push(n),t&&j(n)&&R(!0),t=!1}return O(r,"Program")}function J(){wr===kt&&g(!0);var e=wr,r=q();switch(e){case Br:case Xr:U();var n=e===Br;D(bt)||B()?r.label=null:wr!==jr?X():(r.label=lr(),M());for(var a=0;Tr.length>a;++a){var o=Tr[a];if(null==r.label||o.name===r.label.name){if(null!=o.kind&&(n||"loop"===o.kind))break;if(r.label&&n)break}}return a===Tr.length&&t(r.start,"Unsyntactic "+e.keyword),O(r,n?"BreakStatement":"ContinueStatement");case Nr:return U(),M(),O(r,"DebuggerStatement");case Jr:return U(),Tr.push(Zt),r.body=J(),Tr.pop(),z(rt),r.test=P(),M(),O(r,"DoWhileStatement");case Gr:if(U(),Tr.push(Zt),z(mt),wr===bt)return G(r,null);if(wr===et){var i=q();return U(),K(i,!0),1===i.declarations.length&&D(ct)?H(r,i):G(r,i)}var i=Q(!1,!0);return D(ct)?(N(i),H(r,i)):G(r,i);case Hr:return U(),cr(r,!0);case Kr:return U(),r.test=P(),r.consequent=J(),r.alternate=D(Pr)?J():null,O(r,"IfStatement");case Qr:return Rr||t(yr,"'return' outside of function"),U(),D(bt)||B()?r.argument=null:(r.argument=Q(),M()),O(r,"ReturnStatement");case Yr:U(),r.discriminant=P(),r.cases=[],z(pt),Tr.push(_t);for(var s,c;wr!=dt;)if(wr===Mr||wr===Wr){var u=wr===Mr;s&&O(s,"SwitchCase"),r.cases.push(s=q()),s.consequent=[],U(),u?s.test=Q():(c&&t(Ir,"Multiple default clauses"),c=!0,s.test=null),z(yt)}else s||X(),s.consequent.push(J());return s&&O(s,"SwitchCase"),U(),Tr.pop(),O(r,"SwitchStatement");case Zr:return U(),Ht.test(pr.slice(Lr,yr))&&t(Lr,"Illegal newline after throw"),r.argument=Q(),M(),O(r,"ThrowStatement");case _r:if(U(),r.block=$(),r.handler=null,wr===zr){var l=q();U(),z(mt),l.param=lr(),Vr&&Xt(l.param.name)&&t(l.param.start,"Binding "+l.param.name+" in strict mode"),z(ht),l.guard=null,l.body=$(),r.handler=O(l,"CatchClause")}return r.finalizer=D($r)?$():null,r.handler||r.finalizer||t(r.start,"Missing catch or finally clause"),O(r,"TryStatement");case et:return U(),r=K(r),M(),r;case rt:return U(),r.test=P(),Tr.push(Zt),r.body=J(),Tr.pop(),O(r,"WhileStatement");case tt:return Vr&&t(yr,"'with' in strict mode"),U(),r.object=P(),r.body=J(),O(r,"WithStatement");case pt:return $();case bt:return U(),O(r,"EmptyStatement");default:var f=Cr,p=Q();if(e===jr&&"Identifier"===p.type&&D(yt)){for(var a=0;Tr.length>a;++a)Tr[a].name===f&&t(p.start,"Label '"+f+"' is already declared");var d=wr.isLoop?"loop":wr===Yr?"switch":null;return Tr.push({name:f,kind:d}),r.body=J(),Tr.pop(),r.label=p,O(r,"LabeledStatement")}return r.expression=p,M(),O(r,"ExpressionStatement")}}function P(){z(mt);var e=Q();return z(ht),e}function $(){var e,r=q(),t=!0,n=!1;for(r.body=[],z(pt);!D(dt);){var a=J();r.body.push(a),t&&j(a)&&(e=n,R(n=!0)),t=!1}return n&&!e&&R(!1),O(r,"BlockStatement")}function G(e,r){return e.init=r,z(bt),e.test=wr===bt?null:Q(),z(bt),e.update=wr===ht?null:Q(),z(ht),e.body=J(),Tr.pop(),O(e,"ForStatement")}function H(e,r){return e.left=r,e.right=Q(),z(ht),e.body=J(),Tr.pop(),O(e,"ForInStatement")}function K(e,r){for(e.declarations=[],e.kind="var";;){var n=q();if(n.id=lr(),Vr&&Xt(n.id.name)&&t(n.id.start,"Binding "+n.id.name+" in strict mode"),n.init=D(wt)?Q(!0,r):null,e.declarations.push(O(n,"VariableDeclarator")),!D(vt))break}return O(e,"VariableDeclaration")}function Q(e,r){var t=Y(r);if(!e&&wr===vt){var n=F(t);for(n.expressions=[t];D(vt);)n.expressions.push(Y(r));return O(n,"SequenceExpression")}return t}function Y(e){var r=Z(e);if(wr.isAssign){var t=F(r);return t.operator=Cr,t.left=r,U(),t.right=Y(e),N(r),O(t,"AssignmentExpression")}return r}function Z(e){var r=_(e);if(D(xt)){var t=F(r);return t.test=r,t.consequent=Q(!0),z(yt),t.alternate=Q(!0,e),O(t,"ConditionalExpression")}return r}function _(e){return er(rr(e),-1,e)}function er(e,r,t){var n=wr.binop;if(null!=n&&(!t||wr!==ct)&&n>r){var a=F(e);a.left=e,a.operator=Cr,U(),a.right=er(rr(t),n,t);var a=O(a,/&&|\|\|/.test(a.operator)?"LogicalExpression":"BinaryExpression");return er(a,r,t)}return e}function rr(e){if(wr.prefix){var r=q(),n=wr.isUpdate;return r.operator=Cr,r.prefix=!0,U(),r.argument=rr(e),n?N(r.argument):Vr&&"delete"===r.operator&&"Identifier"===r.argument.type&&t(r.start,"Deleting local variable in strict mode"),O(r,n?"UpdateExpression":"UnaryExpression")}for(var a=tr();wr.postfix&&!B();){var r=F(a);r.operator=Cr,r.prefix=!1,r.argument=a,N(a),U(),a=O(r,"UpdateExpression")}return a}function tr(){return nr(ar())}function nr(e,r){if(D(gt)){var t=F(e);return t.object=e,t.property=lr(!0),t.computed=!1,nr(O(t,"MemberExpression"),r)}if(D(lt)){var t=F(e);return t.object=e,t.property=Q(),t.computed=!0,z(ft),nr(O(t,"MemberExpression"),r)}if(!r&&D(mt)){var t=F(e);return t.callee=e,t.arguments=ur(ht,!1),nr(O(t,"CallExpression"),r)}return e}function ar(){switch(wr){case at:var e=q();return U(),O(e,"ThisExpression");case jr:return lr();case qr:case Or:case Fr:var e=q();return e.value=Cr,e.raw=pr.slice(yr,gr),U(),O(e,"Literal");case ot:case it:case st:var e=q();return e.value=wr.atomValue,e.raw=wr.keyword,U(),O(e,"Literal");case mt:var r=xr,t=yr;U();var n=Q();return n.start=t,n.end=gr,fr.locations&&(n.loc.start=r,n.loc.end=kr),fr.ranges&&(n.range=[t,gr]),z(ht),n;case lt:var e=q();return U(),e.elements=ur(ft,!0,!0),O(e,"ArrayExpression");case pt:return ir();case Hr:var e=q();return U(),cr(e,!1);case nt:return or();default:X()}}function or(){var e=q();return U(),e.callee=nr(ar(),!0),e.arguments=D(mt)?ur(ht,!1):[],O(e,"NewExpression")}function ir(){var e=q(),r=!0,n=!1;for(e.properties=[],U();!D(dt);){if(r)r=!1;else if(z(vt),fr.allowTrailingCommas&&D(dt))break;var a,o={key:sr()},i=!1;if(D(yt)?(o.value=Q(!0),a=o.kind="init"):fr.ecmaVersion>=5&&"Identifier"===o.key.type&&("get"===o.key.name||"set"===o.key.name)?(i=n=!0,a=o.kind=o.key.name,o.key=sr(),wr!==mt&&X(),o.value=cr(q(),!1)):X(),"Identifier"===o.key.type&&(Vr||n))for(var s=0;e.properties.length>s;++s){var c=e.properties[s];if(c.key.name===o.key.name){var u=a==c.kind||i&&"init"===c.kind||"init"===a&&("get"===c.kind||"set"===c.kind);u&&!Vr&&"init"===a&&"init"===c.kind&&(u=!1),u&&t(o.key.start,"Redefinition of property")}}e.properties.push(o)}return O(e,"ObjectExpression")}function sr(){return wr===qr||wr===Or?ar():lr(!0)}function cr(e,r){wr===jr?e.id=lr():r?X():e.id=null,e.params=[];var n=!0;for(z(mt);!D(ht);)n?n=!1:z(vt),e.params.push(lr());var a=Rr,o=Tr;if(Rr=!0,Tr=[],e.body=$(!0),Rr=a,Tr=o,Vr||e.body.body.length&&j(e.body.body[0]))for(var i=e.id?-1:0;e.params.length>i;++i){var s=0>i?e.id:e.params[i];if((zt(s.name)||Xt(s.name))&&t(s.start,"Defining '"+s.name+"' in strict mode"),i>=0)for(var c=0;i>c;++c)s.name===e.params[c].name&&t(s.start,"Argument name clash in strict mode")}return O(e,r?"FunctionDeclaration":"FunctionExpression")}function ur(e,r,t){for(var n=[],a=!0;!D(e);){if(a)a=!1;else if(z(vt),r&&fr.allowTrailingCommas&&D(e))break;t&&wr===vt?n.push(null):n.push(Q(!0))}return n}function lr(e){var r=q();return r.name=wr===jr?Cr:e&&!fr.forbidReserved&&wr.keyword||X(),U(),O(r,"Identifier")}e.version="0.2.01";var fr,pr,dr,mr;e.parse=function(e,t){return pr=e+"",dr=pr.length,r(t),o(),W(fr.program)};var hr=e.defaultOptions={ecmaVersion:5,strictSemicolons:!1,allowTrailingCommas:!0,forbidReserved:!1,locations:!1,onComment:null,ranges:!1,program:null,sourceFile:null},vr=e.getLineInfo=function(e,r){for(var t=1,n=0;;){Kt.lastIndex=n;var a=Kt.exec(e);if(!(a&&r>a.index))break;++t,n=a.index+a[0].length}return{line:t,column:r-n}};e.tokenize=function(e,t){function n(e){return g(e),a.start=yr,a.end=gr,a.startLoc=xr,a.endLoc=kr,a.type=wr,a.value=Cr,a}pr=e+"",dr=pr.length,r(t),o();var a={};return n.jumpTo=function(e,r){if(br=e,fr.locations){Ar=Sr=Kt.lastIndex=0;for(var t;(t=Kt.exec(pr))&&e>t.index;)++Ar,Sr=t.index+t[0].length}pr.charAt(e-1),Er=r,u()},n};var br,yr,gr,xr,kr,wr,Cr,Er,Ar,Sr,Ir,Lr,Ur,Rr,Tr,Vr,qr={type:"num"},Fr={type:"regexp"},Or={type:"string"},jr={type:"name"},Dr={type:"eof"},Br={keyword:"break"},Mr={keyword:"case",beforeExpr:!0},zr={keyword:"catch"},Xr={keyword:"continue"},Nr={keyword:"debugger"},Wr={keyword:"default"},Jr={keyword:"do",isLoop:!0},Pr={keyword:"else",beforeExpr:!0},$r={keyword:"finally"},Gr={keyword:"for",isLoop:!0},Hr={keyword:"function"},Kr={keyword:"if"},Qr={keyword:"return",beforeExpr:!0},Yr={keyword:"switch"},Zr={keyword:"throw",beforeExpr:!0},_r={keyword:"try"},et={keyword:"var"},rt={keyword:"while",isLoop:!0},tt={keyword:"with"},nt={keyword:"new",beforeExpr:!0},at={keyword:"this"},ot={keyword:"null",atomValue:null},it={keyword:"true",atomValue:!0},st={keyword:"false",atomValue:!1},ct={keyword:"in",binop:7,beforeExpr:!0},ut={"break":Br,"case":Mr,"catch":zr,"continue":Xr,"debugger":Nr,"default":Wr,"do":Jr,"else":Pr,"finally":$r,"for":Gr,"function":Hr,"if":Kr,"return":Qr,"switch":Yr,"throw":Zr,"try":_r,"var":et,"while":rt,"with":tt,"null":ot,"true":it,"false":st,"new":nt,"in":ct,"instanceof":{keyword:"instanceof",binop:7,beforeExpr:!0},"this":at,"typeof":{keyword:"typeof",prefix:!0,beforeExpr:!0},"void":{keyword:"void",prefix:!0,beforeExpr:!0},"delete":{keyword:"delete",prefix:!0,beforeExpr:!0}},lt={type:"[",beforeExpr:!0},ft={type:"]"},pt={type:"{",beforeExpr:!0},dt={type:"}"},mt={type:"(",beforeExpr:!0},ht={type:")"},vt={type:",",beforeExpr:!0},bt={type:";",beforeExpr:!0},yt={type:":",beforeExpr:!0},gt={type:"."},xt={type:"?",beforeExpr:!0},kt={binop:10,beforeExpr:!0},wt={isAssign:!0,beforeExpr:!0},Ct={isAssign:!0,beforeExpr:!0},Et={binop:9,prefix:!0,beforeExpr:!0},At={postfix:!0,prefix:!0,isUpdate:!0},St={prefix:!0,beforeExpr:!0},It={binop:1,beforeExpr:!0},Lt={binop:2,beforeExpr:!0},Ut={binop:3,beforeExpr:!0},Rt={binop:4,beforeExpr:!0},Tt={binop:5,beforeExpr:!0},Vt={binop:6,beforeExpr:!0},qt={binop:7,beforeExpr:!0},Ft={binop:8,beforeExpr:!0},Ot={binop:10,beforeExpr:!0};e.tokTypes={bracketL:lt,bracketR:ft,braceL:pt,braceR:dt,parenL:mt,parenR:ht,comma:vt,semi:bt,colon:yt,dot:gt,question:xt,slash:kt,eq:wt,name:jr,eof:Dr,num:qr,regexp:Fr,string:Or};for(var jt in ut)e.tokTypes[jt]=ut[jt];var Dt,Bt=n("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),Mt=n("class enum extends super const export import"),zt=n("implements interface let package private protected public static yield"),Xt=n("eval arguments"),Nt=n("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"),Wt=/[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/,Jt="\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",Pt="\u0371-\u0374\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f",$t=RegExp("["+Jt+"]"),Gt=RegExp("["+Jt+Pt+"]"),Ht=/[\n\r\u2028\u2029]/,Kt=/\r\n|[\n\r\u2028\u2029]/g,Qt=e.isIdentifierStart=function(e){return 65>e?36===e:91>e?!0:97>e?95===e:123>e?!0:e>=170&&$t.test(String.fromCharCode(e))},Yt=e.isIdentifierChar=function(e){return 48>e?36===e:58>e?!0:65>e?!1:91>e?!0:97>e?95===e:123>e?!0:e>=170&&Gt.test(String.fromCharCode(e))},Zt={kind:"loop"},_t={kind:"switch"}}); \ No newline at end of file +(function(e){return"object"==typeof exports&&"object"==typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):(e(this.acorn||(this.acorn={})),void 0)})(function(e){"use strict";function r(e){fr=e||{};for(var r in hr)fr.hasOwnProperty(r)||(fr[r]=hr[r]);mr=fr.sourceFile||null}function t(e,r){var t=vr(pr,e);r+=" ("+t.line+":"+t.column+")";var n=new SyntaxError(r);throw n.pos=e,n.loc=t,n.raisedAt=br,n}function n(e){function r(e){if(1==e.length)return t+="return str === "+JSON.stringify(e[0])+";";t+="switch(str){";for(var r=0;e.length>r;++r)t+="case "+JSON.stringify(e[r])+":";t+="return true}return false;"}e=e.split(" ");var t="",n=[];e:for(var a=0;e.length>a;++a){for(var o=0;n.length>o;++o)if(n[o][0].length==e[a].length){n[o].push(e[a]);continue e}n.push([e[a]])}if(n.length>3){n.sort(function(e,r){return r.length-e.length}),t+="switch(str.length){";for(var a=0;n.length>a;++a){var i=n[a];t+="case "+i[0].length+":",r(i)}t+="}"}else r(e);return Function("str",t)}function a(){this.line=Ar,this.column=br-Sr}function o(){Ar=1,br=Sr=0,Er=!0,u()}function i(e,r){gr=br,fr.locations&&(kr=new a),wr=e,u(),Cr=r,Er=e.beforeExpr}function s(){var e=fr.onComment&&fr.locations&&new a,r=br,n=pr.indexOf("*/",br+=2);if(-1===n&&t(br-2,"Unterminated comment"),br=n+2,fr.locations){Kt.lastIndex=r;for(var o;(o=Kt.exec(pr))&&br>o.index;)++Ar,Sr=o.index+o[0].length}fr.onComment&&fr.onComment(!0,pr.slice(r+2,n),r,br,e,fr.locations&&new a)}function c(){for(var e=br,r=fr.onComment&&fr.locations&&new a,t=pr.charCodeAt(br+=2);dr>br&&10!==t&&13!==t&&8232!==t&&8329!==t;)++br,t=pr.charCodeAt(br);fr.onComment&&fr.onComment(!1,pr.slice(e+2,br),e,br,r,fr.locations&&new a)}function u(){for(;dr>br;){var e=pr.charCodeAt(br);if(32===e)++br;else if(13===e){++br;var r=pr.charCodeAt(br);10===r&&++br,fr.locations&&(++Ar,Sr=br)}else if(10===e)++br,++Ar,Sr=br;else if(14>e&&e>8)++br;else if(47===e){var r=pr.charCodeAt(br+1);if(42===r)s();else{if(47!==r)break;c()}}else if(14>e&&e>8||32===e||160===e)++br;else{if(!(e>=5760&&Wt.test(String.fromCharCode(e))))break;++br}}}function l(){var e=pr.charCodeAt(br+1);return e>=48&&57>=e?E(!0):(++br,i(gt))}function f(){var e=pr.charCodeAt(br+1);return Er?(++br,k()):61===e?x(Ct,2):x(kt,1)}function p(){var e=pr.charCodeAt(br+1);return 61===e?x(Ct,2):x(Ot,1)}function d(e){var r=pr.charCodeAt(br+1);return r===e?x(124===e?It:Lt,2):61===r?x(Ct,2):x(124===e?Ut:Tt,1)}function m(){var e=pr.charCodeAt(br+1);return 61===e?x(Ct,2):x(Rt,1)}function h(e){var r=pr.charCodeAt(br+1);return r===e?x(At,2):61===r?x(Ct,2):x(Et,1)}function v(e){var r=pr.charCodeAt(br+1),t=1;return r===e?(t=62===e&&62===pr.charCodeAt(br+2)?3:2,61===pr.charCodeAt(br+t)?x(Ct,t+1):x(Ft,t)):(61===r&&(t=61===pr.charCodeAt(br+2)?3:2),x(qt,t))}function b(e){var r=pr.charCodeAt(br+1);return 61===r?x(Vt,61===pr.charCodeAt(br+2)?3:2):x(61===e?wt:St,1)}function y(e){switch(e){case 46:return l();case 40:return++br,i(mt);case 41:return++br,i(ht);case 59:return++br,i(bt);case 44:return++br,i(vt);case 91:return++br,i(lt);case 93:return++br,i(ft);case 123:return++br,i(pt);case 125:return++br,i(dt);case 58:return++br,i(yt);case 63:return++br,i(xt);case 48:var r=pr.charCodeAt(br+1);if(120===r||88===r)return C();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return E(!1);case 34:case 39:return A(e);case 47:return f(e);case 37:case 42:return p();case 124:case 38:return d(e);case 94:return m();case 43:case 45:return h(e);case 60:case 62:return v(e);case 61:case 33:return b(e);case 126:return x(St,1)}return!1}function g(e){if(e?br=yr+1:yr=br,fr.locations&&(xr=new a),e)return k();if(br>=dr)return i(Dr);var r=pr.charCodeAt(br);if(Qt(r)||92===r)return L();var n=y(r);if(n===!1){var o=String.fromCharCode(r);if("\\"===o||$t.test(o))return L();t(br,"Unexpected character '"+o+"'")}return n}function x(e,r){var t=pr.slice(br,br+r);br+=r,i(e,t)}function k(){for(var e,r,n="",a=br;;){br>=dr&&t(a,"Unterminated regular expression");var o=pr.charAt(br);if(Ht.test(o)&&t(a,"Unterminated regular expression"),e)e=!1;else{if("["===o)r=!0;else if("]"===o&&r)r=!1;else if("/"===o&&!r)break;e="\\"===o}++br}var n=pr.slice(a,br);++br;var s=I();return s&&!/^[gmsiy]*$/.test(s)&&t(a,"Invalid regexp flag"),i(Fr,RegExp(n,s))}function w(e,r){for(var t=br,n=0,a=0,o=null==r?1/0:r;o>a;++a){var i,s=pr.charCodeAt(br);if(i=s>=97?s-97+10:s>=65?s-65+10:s>=48&&57>=s?s-48:1/0,i>=e)break;++br,n=n*e+i}return br===t||null!=r&&br-t!==r?null:n}function C(){br+=2;var e=w(16);return null==e&&t(yr+2,"Expected hexadecimal number"),Qt(pr.charCodeAt(br))&&t(br,"Identifier directly after number"),i(qr,e)}function E(e){var r=br,n=!1,a=48===pr.charCodeAt(br);e||null!==w(10)||t(r,"Invalid number"),46===pr.charCodeAt(br)&&(++br,w(10),n=!0);var o=pr.charCodeAt(br);(69===o||101===o)&&(o=pr.charCodeAt(++br),(43===o||45===o)&&++br,null===w(10)&&t(r,"Invalid number"),n=!0),Qt(pr.charCodeAt(br))&&t(br,"Identifier directly after number");var s,c=pr.slice(r,br);return n?s=parseFloat(c):a&&1!==c.length?/[89]/.test(c)||Vr?t(r,"Invalid number"):s=parseInt(c,8):s=parseInt(c,10),i(qr,s)}function A(e){br++;for(var r="";;){br>=dr&&t(yr,"Unterminated string constant");var n=pr.charCodeAt(br);if(n===e)return++br,i(Or,r);if(92===n){n=pr.charCodeAt(++br);var a=/^[0-7]+/.exec(pr.slice(br,br+3));for(a&&(a=a[0]);a&&parseInt(a,8)>255;)a=a.slice(0,a.length-1);if("0"===a&&(a=null),++br,a)Vr&&t(br-2,"Octal literal in strict mode"),r+=String.fromCharCode(parseInt(a,8)),br+=a.length-1;else switch(n){case 110:r+="\n";break;case 114:r+="\r";break;case 120:r+=String.fromCharCode(S(2));break;case 117:r+=String.fromCharCode(S(4));break;case 85:r+=String.fromCharCode(S(8));break;case 116:r+=" ";break;case 98:r+="\b";break;case 118:r+="";break;case 102:r+="\f";break;case 48:r+="\0";break;case 13:10===pr.charCodeAt(br)&&++br;case 10:fr.locations&&(Sr=br,++Ar);break;default:r+=String.fromCharCode(n)}}else(13===n||10===n||8232===n||8329===n)&&t(yr,"Unterminated string constant"),r+=String.fromCharCode(n),++br}}function S(e){var r=w(16,e);return null===r&&t(yr,"Bad character escape sequence"),r}function I(){Dt=!1;for(var e,r=!0,n=br;;){var a=pr.charCodeAt(br);if(Yt(a))Dt&&(e+=pr.charAt(br)),++br;else{if(92!==a)break;Dt||(e=pr.slice(n,br)),Dt=!0,117!=pr.charCodeAt(++br)&&t(br,"Expecting Unicode escape sequence \\uXXXX"),++br;var o=S(4),i=String.fromCharCode(o);i||t(br-1,"Invalid Unicode escape"),(r?Qt(o):Yt(o))||t(br-4,"Invalid Unicode escape"),e+=i}r=!1}return Dt?e:pr.slice(n,br)}function L(){var e=I(),r=jr;return Dt||(Nt(e)?r=ut[e]:(fr.forbidReserved&&(3===fr.ecmaVersion?Bt:Mt)(e)||Vr&&zt(e))&&t(yr,"The keyword '"+e+"' is reserved")),i(r,e)}function U(){Ir=yr,Lr=gr,Ur=kr,g()}function R(e){for(Vr=e,br=Lr;Sr>br;)Sr=pr.lastIndexOf("\n",Sr-2)+1,--Ar;u(),g()}function T(){this.type=null,this.start=yr,this.end=null}function V(){this.start=xr,this.end=null,null!==mr&&(this.source=mr)}function q(){var e=new T;return fr.locations&&(e.loc=new V),fr.ranges&&(e.range=[yr,0]),e}function F(e){var r=new T;return r.start=e.start,fr.locations&&(r.loc=new V,r.loc.start=e.loc.start),fr.ranges&&(r.range=[e.range[0],0]),r}function O(e,r){return e.type=r,e.end=Lr,fr.locations&&(e.loc.end=Ur),fr.ranges&&(e.range[1]=Lr),e}function j(e){return fr.ecmaVersion>=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"use strict"===e.expression.value}function D(e){return wr===e?(U(),!0):void 0}function B(){return!fr.strictSemicolons&&(wr===Dr||wr===dt||Ht.test(pr.slice(Lr,yr)))}function M(){D(bt)||B()||X()}function z(e){wr===e?U():X()}function X(){t(yr,"Unexpected token")}function N(e){"Identifier"!==e.type&&"MemberExpression"!==e.type&&t(e.start,"Assigning to rvalue"),Vr&&"Identifier"===e.type&&Xt(e.name)&&t(e.start,"Assigning to "+e.name+" in strict mode")}function W(e){Ir=Lr=br,fr.locations&&(Ur=new a),Rr=Vr=null,Tr=[],g();var r=e||q(),t=!0;for(e||(r.body=[]);wr!==Dr;){var n=J();r.body.push(n),t&&j(n)&&R(!0),t=!1}return O(r,"Program")}function J(){wr===kt&&g(!0);var e=wr,r=q();switch(e){case Br:case Xr:U();var n=e===Br;D(bt)||B()?r.label=null:wr!==jr?X():(r.label=lr(),M());for(var a=0;Tr.length>a;++a){var o=Tr[a];if(null==r.label||o.name===r.label.name){if(null!=o.kind&&(n||"loop"===o.kind))break;if(r.label&&n)break}}return a===Tr.length&&t(r.start,"Unsyntactic "+e.keyword),O(r,n?"BreakStatement":"ContinueStatement");case Nr:return U(),M(),O(r,"DebuggerStatement");case Jr:return U(),Tr.push(Zt),r.body=J(),Tr.pop(),z(rt),r.test=P(),M(),O(r,"DoWhileStatement");case Gr:if(U(),Tr.push(Zt),z(mt),wr===bt)return G(r,null);if(wr===et){var i=q();return U(),K(i,!0),1===i.declarations.length&&D(ct)?H(r,i):G(r,i)}var i=Q(!1,!0);return D(ct)?(N(i),H(r,i)):G(r,i);case Hr:return U(),cr(r,!0);case Kr:return U(),r.test=P(),r.consequent=J(),r.alternate=D(Pr)?J():null,O(r,"IfStatement");case Qr:return Rr||t(yr,"'return' outside of function"),U(),D(bt)||B()?r.argument=null:(r.argument=Q(),M()),O(r,"ReturnStatement");case Yr:U(),r.discriminant=P(),r.cases=[],z(pt),Tr.push(_t);for(var s,c;wr!=dt;)if(wr===Mr||wr===Wr){var u=wr===Mr;s&&O(s,"SwitchCase"),r.cases.push(s=q()),s.consequent=[],U(),u?s.test=Q():(c&&t(Ir,"Multiple default clauses"),c=!0,s.test=null),z(yt)}else s||X(),s.consequent.push(J());return s&&O(s,"SwitchCase"),U(),Tr.pop(),O(r,"SwitchStatement");case Zr:return U(),Ht.test(pr.slice(Lr,yr))&&t(Lr,"Illegal newline after throw"),r.argument=Q(),M(),O(r,"ThrowStatement");case _r:if(U(),r.block=$(),r.handler=null,wr===zr){var l=q();U(),z(mt),l.param=lr(),Vr&&Xt(l.param.name)&&t(l.param.start,"Binding "+l.param.name+" in strict mode"),z(ht),l.guard=null,l.body=$(),r.handler=O(l,"CatchClause")}return r.finalizer=D($r)?$():null,r.handler||r.finalizer||t(r.start,"Missing catch or finally clause"),O(r,"TryStatement");case et:return U(),r=K(r),M(),r;case rt:return U(),r.test=P(),Tr.push(Zt),r.body=J(),Tr.pop(),O(r,"WhileStatement");case tt:return Vr&&t(yr,"'with' in strict mode"),U(),r.object=P(),r.body=J(),O(r,"WithStatement");case pt:return $();case bt:return U(),O(r,"EmptyStatement");default:var f=Cr,p=Q();if(e===jr&&"Identifier"===p.type&&D(yt)){for(var a=0;Tr.length>a;++a)Tr[a].name===f&&t(p.start,"Label '"+f+"' is already declared");var d=wr.isLoop?"loop":wr===Yr?"switch":null;return Tr.push({name:f,kind:d}),r.body=J(),Tr.pop(),r.label=p,O(r,"LabeledStatement")}return r.expression=p,M(),O(r,"ExpressionStatement")}}function P(){z(mt);var e=Q();return z(ht),e}function $(){var e,r=q(),t=!0,n=!1;for(r.body=[],z(pt);!D(dt);){var a=J();r.body.push(a),t&&j(a)&&(e=n,R(n=!0)),t=!1}return n&&!e&&R(!1),O(r,"BlockStatement")}function G(e,r){return e.init=r,z(bt),e.test=wr===bt?null:Q(),z(bt),e.update=wr===ht?null:Q(),z(ht),e.body=J(),Tr.pop(),O(e,"ForStatement")}function H(e,r){return e.left=r,e.right=Q(),z(ht),e.body=J(),Tr.pop(),O(e,"ForInStatement")}function K(e,r){for(e.declarations=[],e.kind="var";;){var n=q();if(n.id=lr(),Vr&&Xt(n.id.name)&&t(n.id.start,"Binding "+n.id.name+" in strict mode"),n.init=D(wt)?Q(!0,r):null,e.declarations.push(O(n,"VariableDeclarator")),!D(vt))break}return O(e,"VariableDeclaration")}function Q(e,r){var t=Y(r);if(!e&&wr===vt){var n=F(t);for(n.expressions=[t];D(vt);)n.expressions.push(Y(r));return O(n,"SequenceExpression")}return t}function Y(e){var r=Z(e);if(wr.isAssign){var t=F(r);return t.operator=Cr,t.left=r,U(),t.right=Y(e),N(r),O(t,"AssignmentExpression")}return r}function Z(e){var r=_(e);if(D(xt)){var t=F(r);return t.test=r,t.consequent=Q(!0),z(yt),t.alternate=Q(!0,e),O(t,"ConditionalExpression")}return r}function _(e){return er(rr(e),-1,e)}function er(e,r,t){var n=wr.binop;if(null!=n&&(!t||wr!==ct)&&n>r){var a=F(e);a.left=e,a.operator=Cr,U(),a.right=er(rr(t),n,t);var a=O(a,/&&|\|\|/.test(a.operator)?"LogicalExpression":"BinaryExpression");return er(a,r,t)}return e}function rr(e){if(wr.prefix){var r=q(),n=wr.isUpdate;return r.operator=Cr,r.prefix=!0,U(),r.argument=rr(e),n?N(r.argument):Vr&&"delete"===r.operator&&"Identifier"===r.argument.type&&t(r.start,"Deleting local variable in strict mode"),O(r,n?"UpdateExpression":"UnaryExpression")}for(var a=tr();wr.postfix&&!B();){var r=F(a);r.operator=Cr,r.prefix=!1,r.argument=a,N(a),U(),a=O(r,"UpdateExpression")}return a}function tr(){return nr(ar())}function nr(e,r){if(D(gt)){var t=F(e);return t.object=e,t.property=lr(!0),t.computed=!1,nr(O(t,"MemberExpression"),r)}if(D(lt)){var t=F(e);return t.object=e,t.property=Q(),t.computed=!0,z(ft),nr(O(t,"MemberExpression"),r)}if(!r&&D(mt)){var t=F(e);return t.callee=e,t.arguments=ur(ht,!1),nr(O(t,"CallExpression"),r)}return e}function ar(){switch(wr){case at:var e=q();return U(),O(e,"ThisExpression");case jr:return lr();case qr:case Or:case Fr:var e=q();return e.value=Cr,e.raw=pr.slice(yr,gr),U(),O(e,"Literal");case ot:case it:case st:var e=q();return e.value=wr.atomValue,e.raw=wr.keyword,U(),O(e,"Literal");case mt:var r=xr,t=yr;U();var n=Q();return n.start=t,n.end=gr,fr.locations&&(n.loc.start=r,n.loc.end=kr),fr.ranges&&(n.range=[t,gr]),z(ht),n;case lt:var e=q();return U(),e.elements=ur(ft,!0,!0),O(e,"ArrayExpression");case pt:return ir();case Hr:var e=q();return U(),cr(e,!1);case nt:return or();default:X()}}function or(){var e=q();return U(),e.callee=nr(ar(),!0),e.arguments=D(mt)?ur(ht,!1):[],O(e,"NewExpression")}function ir(){var e=q(),r=!0,n=!1;for(e.properties=[],U();!D(dt);){if(r)r=!1;else if(z(vt),fr.allowTrailingCommas&&D(dt))break;var a,o={key:sr()},i=!1;if(D(yt)?(o.value=Q(!0),a=o.kind="init"):fr.ecmaVersion>=5&&"Identifier"===o.key.type&&("get"===o.key.name||"set"===o.key.name)?(i=n=!0,a=o.kind=o.key.name,o.key=sr(),wr!==mt&&X(),o.value=cr(q(),!1)):X(),"Identifier"===o.key.type&&(Vr||n))for(var s=0;e.properties.length>s;++s){var c=e.properties[s];if(c.key.name===o.key.name){var u=a==c.kind||i&&"init"===c.kind||"init"===a&&("get"===c.kind||"set"===c.kind);u&&!Vr&&"init"===a&&"init"===c.kind&&(u=!1),u&&t(o.key.start,"Redefinition of property")}}e.properties.push(o)}return O(e,"ObjectExpression")}function sr(){return wr===qr||wr===Or?ar():lr(!0)}function cr(e,r){wr===jr?e.id=lr():r?X():e.id=null,e.params=[];var n=!0;for(z(mt);!D(ht);)n?n=!1:z(vt),e.params.push(lr());var a=Rr,o=Tr;if(Rr=!0,Tr=[],e.body=$(!0),Rr=a,Tr=o,Vr||e.body.body.length&&j(e.body.body[0]))for(var i=e.id?-1:0;e.params.length>i;++i){var s=0>i?e.id:e.params[i];if((zt(s.name)||Xt(s.name))&&t(s.start,"Defining '"+s.name+"' in strict mode"),i>=0)for(var c=0;i>c;++c)s.name===e.params[c].name&&t(s.start,"Argument name clash in strict mode")}return O(e,r?"FunctionDeclaration":"FunctionExpression")}function ur(e,r,t){for(var n=[],a=!0;!D(e);){if(a)a=!1;else if(z(vt),r&&fr.allowTrailingCommas&&D(e))break;t&&wr===vt?n.push(null):n.push(Q(!0))}return n}function lr(e){var r=q();return r.name=wr===jr?Cr:e&&!fr.forbidReserved&&wr.keyword||X(),U(),O(r,"Identifier")}e.version="0.2.01";var fr,pr,dr,mr;e.parse=function(e,t){return pr=e+"",dr=pr.length,r(t),o(),W(fr.program)};var hr=e.defaultOptions={ecmaVersion:5,strictSemicolons:!1,allowTrailingCommas:!0,forbidReserved:!1,locations:!1,onComment:null,ranges:!1,program:null,sourceFile:null},vr=e.getLineInfo=function(e,r){for(var t=1,n=0;;){Kt.lastIndex=n;var a=Kt.exec(e);if(!(a&&r>a.index))break;++t,n=a.index+a[0].length}return{line:t,column:r-n}};e.tokenize=function(e,t){function n(e){return g(e),a.start=yr,a.end=gr,a.startLoc=xr,a.endLoc=kr,a.type=wr,a.value=Cr,a}pr=e+"",dr=pr.length,r(t),o();var a={};return n.jumpTo=function(e,r){if(br=e,fr.locations){Ar=Sr=Kt.lastIndex=0;for(var t;(t=Kt.exec(pr))&&e>t.index;)++Ar,Sr=t.index+t[0].length}pr.charAt(e-1),Er=r,u()},n};var br,yr,gr,xr,kr,wr,Cr,Er,Ar,Sr,Ir,Lr,Ur,Rr,Tr,Vr,qr={type:"num"},Fr={type:"regexp"},Or={type:"string"},jr={type:"name"},Dr={type:"eof"},Br={keyword:"break"},Mr={keyword:"case",beforeExpr:!0},zr={keyword:"catch"},Xr={keyword:"continue"},Nr={keyword:"debugger"},Wr={keyword:"default"},Jr={keyword:"do",isLoop:!0},Pr={keyword:"else",beforeExpr:!0},$r={keyword:"finally"},Gr={keyword:"for",isLoop:!0},Hr={keyword:"function"},Kr={keyword:"if"},Qr={keyword:"return",beforeExpr:!0},Yr={keyword:"switch"},Zr={keyword:"throw",beforeExpr:!0},_r={keyword:"try"},et={keyword:"var"},rt={keyword:"while",isLoop:!0},tt={keyword:"with"},nt={keyword:"new",beforeExpr:!0},at={keyword:"this"},ot={keyword:"null",atomValue:null},it={keyword:"true",atomValue:!0},st={keyword:"false",atomValue:!1},ct={keyword:"in",binop:7,beforeExpr:!0},ut={"break":Br,"case":Mr,"catch":zr,"continue":Xr,"debugger":Nr,"default":Wr,"do":Jr,"else":Pr,"finally":$r,"for":Gr,"function":Hr,"if":Kr,"return":Qr,"switch":Yr,"throw":Zr,"try":_r,"var":et,"while":rt,"with":tt,"null":ot,"true":it,"false":st,"new":nt,"in":ct,"instanceof":{keyword:"instanceof",binop:7,beforeExpr:!0},"this":at,"typeof":{keyword:"typeof",prefix:!0,beforeExpr:!0},"void":{keyword:"void",prefix:!0,beforeExpr:!0},"delete":{keyword:"delete",prefix:!0,beforeExpr:!0}},lt={type:"[",beforeExpr:!0},ft={type:"]"},pt={type:"{",beforeExpr:!0},dt={type:"}"},mt={type:"(",beforeExpr:!0},ht={type:")"},vt={type:",",beforeExpr:!0},bt={type:";",beforeExpr:!0},yt={type:":",beforeExpr:!0},gt={type:"."},xt={type:"?",beforeExpr:!0},kt={binop:10,beforeExpr:!0},wt={isAssign:!0,beforeExpr:!0},Ct={isAssign:!0,beforeExpr:!0},Et={binop:9,prefix:!0,beforeExpr:!0},At={postfix:!0,prefix:!0,isUpdate:!0},St={prefix:!0,beforeExpr:!0},It={binop:1,beforeExpr:!0},Lt={binop:2,beforeExpr:!0},Ut={binop:3,beforeExpr:!0},Rt={binop:4,beforeExpr:!0},Tt={binop:5,beforeExpr:!0},Vt={binop:6,beforeExpr:!0},qt={binop:7,beforeExpr:!0},Ft={binop:8,beforeExpr:!0},Ot={binop:10,beforeExpr:!0};e.tokTypes={bracketL:lt,bracketR:ft,braceL:pt,braceR:dt,parenL:mt,parenR:ht,comma:vt,semi:bt,colon:yt,dot:gt,question:xt,slash:kt,eq:wt,name:jr,eof:Dr,num:qr,regexp:Fr,string:Or};for(var jt in ut)e.tokTypes[jt]=ut[jt];var Dt,Bt=n("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),Mt=n("class enum extends super const export import"),zt=n("implements interface let package private protected public static yield"),Xt=n("eval arguments"),Nt=n("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"),Wt=/[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/,Jt="\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",Pt="\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f",$t=RegExp("["+Jt+"]"),Gt=RegExp("["+Jt+Pt+"]"),Ht=/[\n\r\u2028\u2029]/,Kt=/\r\n|[\n\r\u2028\u2029]/g,Qt=e.isIdentifierStart=function(e){return 65>e?36===e:91>e?!0:97>e?95===e:123>e?!0:e>=170&&$t.test(String.fromCharCode(e))},Yt=e.isIdentifierChar=function(e){return 48>e?36===e:58>e?!0:65>e?!1:91>e?!0:97>e?95===e:123>e?!0:e>=170&&Gt.test(String.fromCharCode(e))},Zt={kind:"loop"},_t={kind:"switch"}}); \ No newline at end of file diff --git a/lib/acorn.js b/lib/acorn.js index 7b3b48b0..c9c540df 100644 --- a/lib/acorn.js +++ b/lib/acorn.js @@ -29,7 +29,7 @@ exports.version = "0.2.01"; - // The main exported interface (under `this.acorn` when in the + // The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and // returns an abstract syntax tree as specified by [Mozilla parser // API][api], with the caveat that the SpiderMonkey-specific syntax @@ -407,7 +407,7 @@ var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/; var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; - var nonASCIIidentifierChars = "\u0371-\u0374\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; + var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); @@ -1716,4 +1716,4 @@ return finishNode(node, "Identifier"); } -}); +}); \ No newline at end of file diff --git a/lib/straps.js b/lib/straps.js index ec487570..5fe27e28 100755 --- a/lib/straps.js +++ b/lib/straps.js @@ -1,36 +1,31 @@ /** - * Straps.js - Inheritance library with support for bean-style accessors and - * AOP patterns. + * straps.js - Class inheritance library with support for bean-style accessors * * Copyright (c) 2006 - 2013 Juerg Lehni * http://lehni.org/ * * Distributed under the MIT license. * - * straps.js was created by extracting and simplifying the inheritance code from - * boostrap.js, a JavaScript DOM library, also published by Juerg Lehni: + * straps.js was created by extracting and simplifying the inheritance framework + * from boostrap.js, a JavaScript DOM library, also published by Juerg Lehni: * https://github.com/lehni/bootstrap.js - * The name was changed due to Twitter's introduction of their CSS framework - * with the same name. * * Inspirations: * http://dean.edwards.name/weblog/2006/03/base/ * http://dev.helma.org/Wiki/JavaScript+Inheritance+Sugar/ */ -var Base = this.Base = new function() { // Straps scope +var Base = new function() { var hidden = /^(statics|generics|preserve|enumerable|prototype|toString|valueOf)$/, - proto = Object.prototype, - toString = proto.toString, + toString = Object.prototype.toString, proto = Array.prototype, - isArray = Array.isArray = Array.isArray || function(obj) { - return toString.call(obj) === '[object Array]'; - }, slice = proto.slice, + forEach = proto.forEach || function(iter, bind) { for (var i = 0, l = this.length; i < l; i++) iter.call(bind, this[i], i, this); }, + forIn = function(iter, bind) { // Do not use Object.keys for iteration as iterators might modify // the object we're iterating over, making the hasOwnProperty still @@ -39,52 +34,54 @@ var Base = this.Base = new function() { // Straps scope if (this.hasOwnProperty(i)) iter.call(bind, this[i], i, this); }, - // A ahort cut to a simplified version of Object.create that only + + isArray = Array.isArray = Array.isArray || function(obj) { + return toString.call(obj) === '[object Array]'; + }, + + // A short-cut to a simplified version of Object.create that only // supports the first parameter (in the emulation): create = Object.create || function(proto) { // From all browsers that do not offer Object.create(), we only - // support Firefox 3.5 & 3.5, and this hack works there: + // support Firefox 3.5 & 3.6, and this hack works there: return { __proto__: proto }; }, - _define = Object.defineProperty, - _describe = Object.getOwnPropertyDescriptor; - // Support a mixed environment of some ECMAScript 5 features present, - // along with __defineGetter/Setter__ functions, as found in browsers today. - function define(obj, name, desc) { - // Unfortunately Safari seems to ignore configurable: true and - // does not override existing properties, so we need to delete - // first: - if (_define) { - try { - delete obj[name]; - return _define(obj, name, desc); - } catch (e) {} - } - if ((desc.get || desc.set) && obj.__defineGetter__) { - if (desc.get) obj.__defineGetter__(name, desc.get); - if (desc.set) obj.__defineSetter__(name, desc.set); - } else { - obj[name] = desc.value; - } - return obj; - } + describe = Object.getOwnPropertyDescriptor || function(obj, name) { + // Emulate Object.getOwnPropertyDescriptor for outdated browsers + var get = obj.__lookupGetter__ && obj.__lookupGetter__(name); + return get + ? { get: get, set: obj.__lookupSetter__(name), + enumerable: true, configurable: true } + : obj.hasOwnProperty(name) + ? { value: obj[name], enumerable: true, + configurable: true, writable: true } + : null; + }, - function describe(obj, name) { - if (_describe) { - try { - return _describe(obj, name); - } catch (e) {} - } - var get = obj.__lookupGetter__ && obj.__lookupGetter__(name); - return get - ? { get: get, set: obj.__lookupSetter__(name), enumerable: true, - configurable: true } - : obj.hasOwnProperty(name) - ? { value: obj[name], enumerable: true, configurable: true, - writable: true } - : null; - } + _define = Object.defineProperty || function(obj, name, desc) { + // Emulate Object.defineProperty for outdated browsers + if ((desc.get || desc.set) && obj.__defineGetter__) { + if (desc.get) + obj.__defineGetter__(name, desc.get); + if (desc.set) + obj.__defineSetter__(name, desc.set); + } else { + obj[name] = desc.value; + } + return obj; + }, + + define = function(obj, name, desc) { + // Both Safari and Chrome at one point ignored configurable = true + // and did not allow overriding of existing properties: + // https://code.google.com/p/chromium/issues/detail?id=72736 + // https://bugs.webkit.org/show_bug.cgi?id=54289 + // The workaround is to delete the property first. + // TODO: Remove this fix in July 2014, and use _define directly. + delete obj[name]; + return _define(obj, name, desc); + }; /** * Private function that injects functions from src into dest, overriding @@ -109,58 +106,34 @@ var Base = this.Base = new function() { // Straps scope // string values starting with '#' if (typeof val === 'string' && val[0] === '#') val = src[val.substring(1)] || val; - var func = typeof val === 'function', + var isFunc = typeof val === 'function', res = val, // Only lookup previous value if we preserve or define a // function that might need it for this.base(). If we're // defining a getter, don't lookup previous value, but look if // the property exists (name in dest) and store result in prev - prev = preserve || func + prev = preserve || isFunc ? (val && val.get ? name in dest : dest[name]) : null; if ((dontCheck || val !== undefined && src.hasOwnProperty(name)) && (!preserve || !prev)) { - if (func) { - if (prev && /\bthis\.base\b/.test(val)) { - var fromBase = base && base[name] == prev; - res = function() { - // Look up the base function each time if we can, - // to reflect changes to the base class after - // inheritance. - var tmp = describe(this, 'base'); - define(this, 'base', { value: fromBase - ? base[name] : prev, configurable: true }); - try { - return val.apply(this, arguments); - } finally { - tmp ? define(this, 'base', tmp) - : delete this.base; - } - }; - // Make wrapping closure pretend to be the original - // function on inspection - res.toString = function() { - return val.toString(); - }; - res.valueOf = function() { - return val.valueOf(); - }; - } - // Produce bean properties if getters are specified. This - // does not produce properties for setter-only properties. - // Just collect beans for now, and look them up in dest at - // the end of fields injection. This ensures this.base() - // works in beans too, and inherits setters for redefined - // getters in subclasses. Only add getter beans if they do - // not expect arguments. Functions that should function both - // with optional arguments and as beans should not declare - // the parameters and use the arguments array internally - // instead. - if (beans && val.length === 0 - && (bean = name.match(/^(get|is)(([A-Z])(.*))$/))) - beans.push([ bean[3].toLowerCase() + bean[4], bean[2] ]); - } + // Expose the 'super' function (meaning the one this function is + // overriding) through #base: + if (isFunc && prev) + val.base = prev; + // Produce bean properties if getters are specified. This does + // not produce properties for setter-only properties. Just + // collect beans for now, and look them up in dest at the end of + // fields injection. This ensures base works for beans too, and + // inherits setters for redefined getters in subclasses. Only + // add getter beans if they do not expect arguments. Functions + // that should function both with optional arguments and as + // beans should not declare the parameters and use the arguments + // array internally instead. + if (isFunc && beans && val.length === 0 + && (bean = name.match(/^(get|is)(([A-Z])(.*))$/))) + beans.push([ bean[3].toLowerCase() + bean[4], bean[2] ]); // No need to look up getter if this is a function already. - if (!res || func || !res.get) + if (!res || isFunc || !res.get) res = { value: res, writable: true }; // Only set/change configurable and enumerable if this field is // configurable @@ -171,7 +144,7 @@ var Base = this.Base = new function() { // Straps scope } define(dest, name, res); } - if (generics && func && (!preserve || !generics[name])) { + if (generics && isFunc && (!preserve || !generics[name])) { generics[name] = function(bind) { // Do not call Array.slice generic here, as on Safari, // this seems to confuse scopes (calling another @@ -210,10 +183,11 @@ var Base = this.Base = new function() { // Straps scope function each(obj, iter, bind, asArray) { try { if (obj) - (asArray || asArray === undefined && isArray(obj) + (asArray || typeof asArray === 'undefined' && isArray(obj) ? forEach : forIn).call(obj, iter, bind = bind || obj); } catch (e) { - if (e !== Base.stop) throw e; + if (e !== Base.stop) + throw e; } return bind; } @@ -225,7 +199,8 @@ var Base = this.Base = new function() { // Straps scope } // Inject into new ctor object that's passed to inject(), and then returned - return inject(function() {}, { + // as the Base class. + return inject(function Base() {}, { inject: function(src/*, ... */) { if (src) { var proto = this.prototype, @@ -252,16 +227,19 @@ var Base = this.Base = new function() { // Straps scope }, extend: function(src/* , ... */) { - var ctor = function() { - // Call the constructor function, if defined - if (this.initialize) - return this.initialize.apply(this, arguments); + var base = this, + ctor; + // Look for an initialize function in all injection objects and use + // it directly as the actual constructor. + for (var i = 0, l = arguments.length; i < l; i++) + if (ctor = arguments[i].initialize) + break; + // If no initialize function is provided, create a constructor that + // simply calls the base constructor. + ctor = ctor || function() { + base.apply(this, arguments); }; ctor.prototype = create(this.prototype); - // Add a toString function that delegates to initialize if possible - ctor.toString = function() { - return (this.prototype.initialize || function() {}).toString(); - }; // The new prototype extends the constructor on which extend is // called. Fix constructor. define(ctor.prototype, 'constructor', @@ -320,8 +298,8 @@ var Base = this.Base = new function() { // Straps scope define: define, describe: describe, - // Base.create does something different from Object.create, it only - // works on constructors and uses their prototype. + // Base.create does something different from Object.create: + // It works on constructors and uses their prototype. create: function(ctor) { return create(ctor.prototype); }, @@ -331,10 +309,12 @@ var Base = this.Base = new function() { // Straps scope * plain Base object, as produced by Base.merge(). */ isPlainObject: function(obj) { - var proto = obj !== null && typeof obj === 'object' - && Object.getPrototypeOf(obj); - return proto && (proto === Object.prototype - || proto === Base.prototype); + var ctor = obj != null && obj.constructor; + // We also need to check for ctor.name === 'Object', in case + // this is an object from another global scope (e.g. an iframe, + // or another vm context in node.js). + return ctor && (ctor === Object || ctor === Base + || ctor.name === 'Object'); }, check: function(obj) { @@ -342,9 +322,8 @@ var Base = this.Base = new function() { // Straps scope }, /** - * Returns the first argument that is defined. - * Null is counted as defined too, since !== undefined is used for - * comparisons. In this it differs from Mootools! + * Returns the first argument that is defined. null is counted as + * defined too, as !== undefined is used for comparisons. */ pick: function() { for (var i = 0, l = arguments.length; i < l; i++) @@ -354,13 +333,10 @@ var Base = this.Base = new function() { // Straps scope }, /** - * A special constant, to be thrown by closures passed to each() + * Base.stop can be thrown by iterators passed to each() * - * $continue / Base.next is not implemented, as the same - * functionality can achieved by using return in the closure. - * In prototype, the implementation of $continue also leads to a - * huge speed decrease, as the closure is wrapped in another closure - * that does nothing else than handling $continue. + * continue (Base.next) is not implemented, as the same can achieved + * by using return in the iterator. */ stop: {} } diff --git a/package.json b/package.json index 9d102c4b..e7e33684 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "paper", - "version": "0.8.3", + "version": "0.9.0", "main": "./src/node/index.js", "engines": { "node": ">= 0.4.0" }, "dependencies": { diff --git a/src/basic/Line.js b/src/basic/Line.js index 9070bd6a..6002f77f 100644 --- a/src/basic/Line.js +++ b/src/basic/Line.js @@ -15,32 +15,33 @@ * * @class The Line object represents.. */ -var Line = this.Line = Base.extend(/** @lends Line# */{ +var Line = Base.extend(/** @lends Line# */{ // DOCS: document Line class and constructor /** * Creates a Line object. * * @param {Point} point1 * @param {Point} point2 - * @param {Boolean} [infinite=true] + * @param {Boolean} [asVector=false] */ - initialize: function(point1, point2, infinite) { - // Convention: With 3 parameters, both points are absolute, and infinite - // controls wether the line extends beyond the defining points, meaning - // intersection outside the line segment are allowed. - // With two parameters, the 2nd parameter is a direction, and infinite - // is automatially true, since we're describing an infinite line. - var _point1 = Point.read(arguments), - _point2 = Point.read(arguments), - _infinite = Base.read(arguments); - if (_infinite !== undefined) { - this.point = _point1; - this.vector = _point2.subtract(_point1); - this.infinite = _infinite; + initialize: function Line(arg0, arg1, arg2, arg3, arg4) { + var asVector = false; + if (arguments.length >= 4) { + this._px = arg0; + this._py = arg1; + this._vx = arg2; + this._vy = arg3; + asVector = arg4; } else { - this.point = _point1; - this.vector = _point2; - this.infinite = true; + this._px = arg0.x; + this._py = arg0.y; + this._vx = arg1.x; + this._vy = arg1.y; + asVector = arg2; + } + if (!asVector) { + this._vx -= this._px; + this._vy -= this._py; } }, @@ -50,6 +51,9 @@ var Line = this.Line = Base.extend(/** @lends Line# */{ * @name Line#point * @type Point */ + getPoint: function() { + return new Point(this._px, this._py); + }, /** * The vector of the line @@ -57,33 +61,21 @@ var Line = this.Line = Base.extend(/** @lends Line# */{ * @name Line#vector * @type Point */ - - /** - * Specifies whether the line extends infinitely - * - * @name Line#infinite - * @type Boolean - */ + getVector: function() { + return new Point(this._vx, this._vy); + }, /** * @param {Line} line + * @param {Boolean} [isInfinite=false] * @return {Point} the intersection point of the lines, {@code undefined} * if the two lines are colinear, or {@code null} if they don't intersect. */ - intersect: function(line) { - var cross = this.vector.cross(line.vector); - // Avoid divisions by 0, and errors when getting too close to 0 - if (Numerical.isZero(cross)) - return undefined; - var v = line.point.subtract(this.point), - t1 = v.cross(line.vector) / cross, - t2 = v.cross(this.vector) / cross; - // Check the ranges of t parameters if the line is not allowed to - // extend beyond the definition points. - return (this.infinite || 0 <= t1 && t1 <= 1) - && (line.infinite || 0 <= t2 && t2 <= 1) - ? this.point.add(this.vector.multiply(t1)) - : null; + intersect: function(line, isInfinite) { + return Line.intersect( + this._px, this._py, this._vx, this._vy, + line._px, line._py, line._vx, line._vy, + true, isInfinite); }, // DOCS: document Line#getSide(point) @@ -92,18 +84,9 @@ var Line = this.Line = Base.extend(/** @lends Line# */{ * @return {Number} */ getSide: function(point) { - var v1 = this.vector, - v2 = point.subtract(this.point), - ccw = v2.cross(v1); - if (ccw === 0) { - ccw = v2.dot(v1); - if (ccw > 0) { - ccw = v2.subtract(v1).dot(v1); - if (ccw < 0) - ccw = 0; - } - } - return ccw < 0 ? -1 : ccw > 0 ? 1 : 0; + return Line.getSide( + this._px, this._py, this._vx, this._vy, + point.x, point.y, true); }, // DOCS: document Line#getDistance(point) @@ -112,33 +95,70 @@ var Line = this.Line = Base.extend(/** @lends Line# */{ * @return {Number} */ getDistance: function(point) { - var m = this.vector.y / this.vector.x, // slope - b = this.point.y - (m * this.point.x); // y offset - // Distance to the linear equation - var dist = Math.abs(point.y - (m * point.x) - b) / Math.sqrt(m * m + 1); - return this.infinite ? dist : Math.min(dist, - point.getDistance(this.point), - point.getDistance(this.point.add(this.vector))); + return Math.abs(Line.getSignedDistance( + this._px, this._py, this._vx, this._vy, + point.x, point.y, true)); }, - statics: { - intersect: function(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, infinite) { - var adx = ax2 - ax1, - ady = ay2 - ay1, - bdx = bx2 - bx1, - bdy = by2 - by1, - dx = ax1 - bx1, - dy = ay1 - by1, - cross = bdy * adx - bdx * ady; - if (!Numerical.isZero(cross)) { - var ta = (bdx * dy - bdy * dx) / cross, - tb = (adx * dy - ady * dx) / cross; - if ((infinite || 0 <= ta && ta <= 1) - && (infinite || 0 <= tb && tb <= 1)) - return Point.create( - ax1 + ta * adx, - ay1 + ta * ady); + statics: /** @lends Line */{ + intersect: function(apx, apy, avx, avy, bpx, bpy, bvx, bvy, asVector, + isInfinite) { + // Convert 2nd points to vectors if they are not specified as such. + if (!asVector) { + avx -= apx; + avy -= apy; + bvx -= bpx; + bvy -= bpy; } + var cross = bvy * avx - bvx * avy; + // Avoid divisions by 0, and errors when getting too close to 0 + if (!Numerical.isZero(cross)) { + var dx = apx - bpx, + dy = apy - bpy, + ta = (bvx * dy - bvy * dx) / cross, + tb = (avx * dy - avy * dx) / cross; + // Check the ranges of t parameters if the line is not allowed + // to extend beyond the definition points. + if ((isInfinite || 0 <= ta && ta <= 1) + && (isInfinite || 0 <= tb && tb <= 1)) + return new Point( + apx + ta * avx, + apy + ta * avy); + } + }, + + getSide: function(px, py, vx, vy, x, y, asVector) { + if (!asVector) { + vx -= px; + vy -= py; + } + var v2x = x - px, + v2y = y - py, + ccw = v2x * vy - v2y * vx; // ccw = v2.cross(v1); + if (ccw === 0) { + ccw = v2x * vx + v2y * vy; // ccw = v2.dot(v1); + if (ccw > 0) { + // ccw = v2.subtract(v1).dot(v1); + v2x -= vx; + v2y -= vy; + ccw = v2x * vx + v2y * vy; + if (ccw < 0) + ccw = 0; + } + } + return ccw < 0 ? -1 : ccw > 0 ? 1 : 0; + }, + + getSignedDistance: function(px, py, vx, vy, x, y, asVector) { + if (!asVector) { + vx -= px; + vy -= py; + } + // Cache these values since they're used heavily in fatline code + var m = vy / vx, // slope + b = py - m * px; // y offset + // Distance to the linear equation + return (y - (m * x) - b) / Math.sqrt(m * m + 1); } } }); diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js index f472927f..c5d83e49 100644 --- a/src/basic/Matrix.js +++ b/src/basic/Matrix.js @@ -37,9 +37,7 @@ * knowledge of the underlying matrix (as opposed to say simply performing * matrix multiplication). */ -var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ - _class: 'Matrix', - +var Matrix = Base.extend(/** @lends Matrix# */{ /** * Creates a 2D affine transform. * @@ -50,7 +48,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * @param {Number} tx The translateX coordinate of the transform * @param {Number} ty The translateY coordinate of the transform */ - initialize: function(arg) { + initialize: function Matrix(arg) { var count = arguments.length, ok = true; if (count == 6) { @@ -101,7 +99,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * @return {Matrix} A copy of this transform. */ clone: function() { - return Matrix.create(this._a, this._c, this._b, this._d, + return new Matrix(this._a, this._c, this._b, this._d, this._tx, this._ty); }, @@ -518,7 +516,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ return { translation: this.getTranslation(), - scaling: Point.create(scaleX, scaleY), + scaling: new Point(scaleX, scaleY), rotation: -Math.atan2(b, a) * 180 / Math.PI, shearing: shear }; @@ -585,7 +583,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ */ getTranslation: function() { // No decomposition is required to extract translation, so treat this - return Point.create(this._tx, this._ty); + return new Point(this._tx, this._ty); }, /** @@ -620,7 +618,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ */ inverted: function() { var det = this._getDeterminant(); - return det && Matrix.create( + return det && new Matrix( this._d / det, -this._c / det, -this._b / det, @@ -630,7 +628,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ }, shiftless: function() { - return Matrix.create(this._a, this._c, this._b, this._d, 0, 0); + return new Matrix(this._a, this._c, this._b, this._d, 0, 0); }, /** @@ -640,13 +638,6 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ */ applyToContext: function(ctx) { ctx.transform(this._a, this._c, this._b, this._d, this._tx, this._ty); - }, - - statics: /** @lends Matrix */{ - // See Point.create() - create: function(a, c, b, d, tx, ty) { - return Base.create(Matrix).set(a, c, b, d, tx, ty); - } } }, new function() { return Base.each({ diff --git a/src/basic/Point.js b/src/basic/Point.js index ed8c0ab5..bb9f5216 100644 --- a/src/basic/Point.js +++ b/src/basic/Point.js @@ -23,8 +23,7 @@ * console.log(point.x); // 10 * console.log(point.y); // 5 */ -var Point = this.Point = Base.extend(/** @lends Point# */{ - _class: 'Point', +var Point = Base.extend(/** @lends Point# */{ // Tell Base.read that the Point constructor supports reading with index _readIndex: true, @@ -129,7 +128,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ * @param {Point} point * @name Point#initialize */ - initialize: function(arg0, arg1) { + initialize: function Point(arg0, arg1) { var type = typeof arg0; if (type === 'number') { var hasY = typeof arg1 === 'number'; @@ -217,7 +216,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ * @returns {Point} the cloned point */ clone: function() { - return Point.create(this.x, this.y); + return new Point(this.x, this.y); }, /** @@ -269,7 +268,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ */ add: function(point) { point = Point.read(arguments); - return Point.create(this.x + point.x, this.y + point.y); + return new Point(this.x + point.x, this.y + point.y); }, /** @@ -305,7 +304,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ */ subtract: function(point) { point = Point.read(arguments); - return Point.create(this.x - point.x, this.y - point.y); + return new Point(this.x - point.x, this.y - point.y); }, /** @@ -341,7 +340,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ */ multiply: function(point) { point = Point.read(arguments); - return Point.create(this.x * point.x, this.y * point.y); + return new Point(this.x * point.x, this.y * point.y); }, /** @@ -377,7 +376,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ */ divide: function(point) { point = Point.read(arguments); - return Point.create(this.x / point.x, this.y / point.y); + return new Point(this.x / point.x, this.y / point.y); }, /** @@ -410,11 +409,11 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ */ modulo: function(point) { point = Point.read(arguments); - return Point.create(this.x % point.x, this.y % point.y); + return new Point(this.x % point.x, this.y % point.y); }, negate: function() { - return Point.create(-this.x, -this.y); + return new Point(-this.x, -this.y); }, /** @@ -501,7 +500,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ length = 1; var current = this.getLength(), scale = current != 0 ? length / current : 0, - point = Point.create(this.x * scale, this.y * scale); + point = new Point(this.x * scale, this.y * scale); // Preserve angle. point._angle = this._angle; return point; @@ -650,7 +649,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ var point = center ? this.subtract(center) : this, s = Math.sin(angle), c = Math.cos(angle); - point = Point.create( + point = new Point( point.x * c - point.y * s, point.y * c + point.x * s ); @@ -754,10 +753,10 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ project: function(point) { point = Point.read(arguments); if (point.isZero()) { - return Point.create(0, 0); + return new Point(0, 0); } else { var scale = this.dot(point) / point.dot(point); - return Point.create( + return new Point( point.x * scale, point.y * scale ); @@ -775,23 +774,6 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ */ statics: /** @lends Point */{ - /** - * Provide a faster creator for Points out of two coordinates that - * does not rely on Point#initialize at all. This speeds up all math - * operations a lot. - * - * @ignore - */ - create: function(x, y) { - // Don't use the shorter form as we want absolute maximum - // performance here: - // return Base.create(Point).set(x, y); - var point = Base.create(Point); - point.x = x; - point.y = y; - return point; - }, - /** * Returns a new point object with the smallest {@link #x} and * {@link #y} of the supplied points. @@ -810,7 +792,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ min: function(point1, point2) { var _point1 = Point.read(arguments); _point2 = Point.read(arguments); - return Point.create( + return new Point( Math.min(_point1.x, _point2.x), Math.min(_point1.y, _point2.y) ); @@ -834,7 +816,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ max: function(point1, point2) { var _point1 = Point.read(arguments); _point2 = Point.read(arguments); - return Point.create( + return new Point( Math.max(_point1.x, _point2.x), Math.max(_point1.y, _point2.y) ); @@ -855,7 +837,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ * var point = maxPoint * randomPoint; */ random: function() { - return Point.create(Math.random(), Math.random()); + return new Point(Math.random(), Math.random()); } } }, new function() { // Scope for injecting round, ceil, floor, abs: @@ -922,7 +904,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ return Base.each(['round', 'ceil', 'floor', 'abs'], function(name) { var op = Math[name]; this[name] = function() { - return Point.create(op(this.x), op(this.y)); + return new Point(op(this.x), op(this.y)); }; }, {}); }); @@ -970,7 +952,7 @@ var LinkedPoint = Point.extend({ // through an optional parameter that can be passed to the getters. // See e.g. Rectangle#getPoint(true). if (dontLink) - return Point.create(x, y); + return new Point(x, y); var point = Base.create(LinkedPoint); point._x = x; point._y = y; diff --git a/src/basic/Rectangle.js b/src/basic/Rectangle.js index dd64ac61..36a7516d 100644 --- a/src/basic/Rectangle.js +++ b/src/basic/Rectangle.js @@ -17,8 +17,7 @@ * point (x, y), its width, and its height. It should not be confused with a * rectangular path, it is not an item. */ -var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{ - _class: 'Rectangle', +var Rectangle = Base.extend(/** @lends Rectangle# */{ // Tell Base.read that the Rectangle constructor supports reading with index _readIndex: true, @@ -72,7 +71,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{ * @name Rectangle#initialize * @param {Rectangle} rt */ - initialize: function(arg0, arg1, arg2, arg3) { + initialize: function Rectangle(arg0, arg1, arg2, arg3) { var type = typeof arg0, read = 0; if (type === 'number') { @@ -191,7 +190,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{ * Returns a copy of the rectangle. */ clone: function() { - return Rectangle.create(this.x, this.y, this.width, this.height); + return new Rectangle(this.x, this.y, this.width, this.height); }, /** @@ -652,7 +651,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{ y1 = Math.max(this.y, rect.y), x2 = Math.min(this.x + this.width, rect.x + rect.width), y2 = Math.min(this.y + this.height, rect.y + rect.height); - return Rectangle.create(x1, y1, x2 - x1, y2 - y1); + return new Rectangle(x1, y1, x2 - x1, y2 - y1); }, /** @@ -669,7 +668,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{ y1 = Math.min(this.y, rect.y), x2 = Math.max(this.x + this.width, rect.x + rect.width), y2 = Math.max(this.y + this.height, rect.y + rect.height); - return Rectangle.create(x1, y1, x2 - x1, y2 - y1); + return new Rectangle(x1, y1, x2 - x1, y2 - y1); }, /** @@ -692,7 +691,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{ y1 = Math.min(this.y, point.y), x2 = Math.max(this.x + this.width, point.x), y2 = Math.max(this.y + this.height, point.y); - return Rectangle.create(x1, y1, x2 - x1, y2 - y1); + return new Rectangle(x1, y1, x2 - x1, y2 - y1); }, /** @@ -716,7 +715,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{ expand: function(hor, ver) { if (ver === undefined) ver = hor; - return Rectangle.create(this.x - hor / 2, this.y - ver / 2, + return new Rectangle(this.x - hor / 2, this.y - ver / 2, this.width + hor, this.height + ver); }, @@ -740,13 +739,6 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{ scale: function(hor, ver) { return this.expand(this.width * hor - this.width, this.height * (ver === undefined ? hor : ver) - this.height); - }, - - statics: { - // See Point.create() - create: function(x, y, width, height) { - return Base.create(Rectangle).set(x, y, width, height); - } } }, new function() { return Base.each([ diff --git a/src/basic/Size.js b/src/basic/Size.js index 10dc970f..3981630b 100644 --- a/src/basic/Size.js +++ b/src/basic/Size.js @@ -22,8 +22,7 @@ * console.log(size.width); // 10 * console.log(size.height); // 5 */ -var Size = this.Size = Base.extend(/** @lends Size# */{ - _class: 'Size', +var Size = Base.extend(/** @lends Size# */{ // Tell Base.read that the Point constructor supports reading with index _readIndex: true, @@ -90,7 +89,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ * console.log(size.width); // 50 * console.log(size.height); // 50 */ - initialize: function(arg0, arg1) { + initialize: function Size(arg0, arg1) { var type = typeof arg0; if (type === 'number') { var hasHeight = typeof arg1 === 'number'; @@ -164,7 +163,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ * Returns a copy of the size. */ clone: function() { - return Size.create(this.width, this.height); + return new Size(this.width, this.height); }, /** @@ -214,7 +213,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ */ add: function(size) { size = Size.read(arguments); - return Size.create(this.width + size.width, this.height + size.height); + return new Size(this.width + size.width, this.height + size.height); }, /** @@ -249,7 +248,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ */ subtract: function(size) { size = Size.read(arguments); - return Size.create(this.width - size.width, this.height - size.height); + return new Size(this.width - size.width, this.height - size.height); }, /** @@ -283,7 +282,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ */ multiply: function(size) { size = Size.read(arguments); - return Size.create(this.width * size.width, this.height * size.height); + return new Size(this.width * size.width, this.height * size.height); }, /** @@ -317,7 +316,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ */ divide: function(size) { size = Size.read(arguments); - return Size.create(this.width / size.width, this.height / size.height); + return new Size(this.width / size.width, this.height / size.height); }, /** @@ -350,11 +349,11 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ */ modulo: function(size) { size = Size.read(arguments); - return Size.create(this.width % size.width, this.height % size.height); + return new Size(this.width % size.width, this.height % size.height); }, negate: function() { - return Size.create(-this.width, -this.height); + return new Size(-this.width, -this.height); }, /** @@ -377,11 +376,6 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ }, statics: /** @lends Size */{ - // See Point.create() - create: function(width, height) { - return Base.create(Size).set(width, height); - }, - /** * Returns a new size object with the smallest {@link #width} and * {@link #height} of the supplied sizes. @@ -398,7 +392,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ * console.log(minSize); // {width: 10, height: 5} */ min: function(size1, size2) { - return Size.create( + return new Size( Math.min(size1.width, size2.width), Math.min(size1.height, size2.height)); }, @@ -419,7 +413,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ * console.log(maxSize); // {width: 200, height: 100} */ max: function(size1, size2) { - return Size.create( + return new Size( Math.max(size1.width, size2.width), Math.max(size1.height, size2.height)); }, @@ -437,7 +431,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ * var size = maxSize * randomSize; */ random: function() { - return Size.create(Math.random(), Math.random()); + return new Size(Math.random(), Math.random()); } } }, new function() { // Scope for injecting round, ceil, floor, abs: @@ -505,7 +499,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ return Base.each(['round', 'ceil', 'floor', 'abs'], function(name) { var op = Math[name]; this[name] = function() { - return Size.create(op(this.width), op(this.height)); + return new Size(op(this.width), op(this.height)); }; }, {}); }); @@ -551,7 +545,7 @@ var LinkedSize = Size.extend({ create: function(owner, setter, width, height, dontLink) { // See LinkedPoint.create() for an explanation about dontLink. if (dontLink) - return Size.create(width, height); + return new Size(width, height); var size = Base.create(LinkedSize); size._width = width; size._height = height; diff --git a/src/canvas/CanvasProvider.js b/src/canvas/CanvasProvider.js index 4b9c6b03..91ad5b09 100644 --- a/src/canvas/CanvasProvider.js +++ b/src/canvas/CanvasProvider.js @@ -16,7 +16,7 @@ var CanvasProvider = { canvases: [], getCanvas: function(width, height) { - var size = height === undefined ? width : Size.create(width, height); + var size = height === undefined ? width : new Size(width, height); if (this.canvases.length) { var canvas = this.canvases.pop(); // If they are not the same size, we don't need to clear them diff --git a/src/core/Base.js b/src/core/Base.js index 6093ae47..bed032bd 100644 --- a/src/core/Base.js +++ b/src/core/Base.js @@ -17,7 +17,7 @@ */ // Extend Base with utility functions used across the library. Also set // this.Base on the injection scope, since straps.js ommits that. -this.Base = Base.inject(/** @lends Base# */{ +Base.inject(/** @lends Base# */{ // Have generics versions of #clone() and #toString(): generics: true, @@ -36,7 +36,7 @@ this.Base = Base.inject(/** @lends Base# */{ */ toString: function() { return this._id != null - ? (this._class || 'Object') + (this._name + ? (this.constructor.name || 'Object') + (this._name ? " '" + this._name + "'" : ' @' + this._id) : '{ ' + Base.each(this, function(value, key) { @@ -80,15 +80,17 @@ this.Base = Base.inject(/** @lends Base# */{ statics: /** @lends Base */{ - _classes: {}, + // Keep track of all named classes for serialization and exporting. + // Also register the Base class itself. + exports: new Base({ Base: Base }), - extend: function(src) { - // Override Base.extend() with a version that registers classes that - // define #_class inside the Base._classes lookup, for - // deserialization. - var res = this.base.apply(this, arguments); - if (src._class) - Base._classes[src._class] = res; + extend: function extend(src) { + // Override Base.extend() to register named classes in Base.exports, + // for deserialization and injection into PaperScope. + var res = extend.base.apply(this, arguments), + name = res.name; + if (name) + Base.exports[name] = res; return res; }, @@ -289,11 +291,12 @@ this.Base = Base.inject(/** @lends Base# */{ ref = this.references[id]; if (!ref) { this.length++; - var res = create.call(item); + var res = create.call(item), + name = item.constructor.name; // Also automatically insert class for dictionary // entries. - if (item._class && res[0] !== item._class) - res.unshift(item._class); + if (name && res[0] !== name) + res.unshift(name); this.definitions[id] = res; ref = this.references[id] = [id]; } @@ -306,13 +309,18 @@ this.Base = Base.inject(/** @lends Base# */{ // If we don't serialize to compact form (meaning no type // identifier), see if _serialize didn't already add the class, // e.g. for classes that do not support compact form. - if (obj._class && !compact && res[0] !== obj._class) - res.unshift(obj._class); + var name = obj.constructor.name; + if (name && !compact && !res._compact && res[0] !== name) + res.unshift(name); } else if (Array.isArray(obj)) { res = []; for (var i = 0, l = obj.length; i < l; i++) res[i] = Base.serialize(obj[i], options, compact, dictionary); + // Mark array as compact, so obj._serialize handling above + // doesn't add the constructor name again. + if (compact) + res._compact = true; } else if (Base.isPlainObject(obj)) { res = {}; for (var i in obj) @@ -332,7 +340,7 @@ this.Base = Base.inject(/** @lends Base# */{ /** * Deserializes from parsed JSON data. A simple convention is followed: * Array values with a string at the first position are links to - * deserializable types through Base._classes, and the values following + * deserializable types through Base.exports, and the values following * in the array are the arguments to their initialize function. * Any other value is passed on unmodified. * The passed data is recoursively traversed and converted, leaves first @@ -356,7 +364,7 @@ this.Base = Base.inject(/** @lends Base# */{ // if so return its definition instead. if (data.dictionary && obj.length == 1 && /^#/.test(type)) return data.dictionary[type]; - type = Base._classes[type]; + type = Base.exports[type]; } res = []; // Skip first type entry for arguments diff --git a/src/core/Callback.js b/src/core/Callback.js index 55ccd429..676a04c4 100644 --- a/src/core/Callback.js +++ b/src/core/Callback.js @@ -98,7 +98,7 @@ var Callback = { statics: { // Override inject() so that sub-classes automatically add the accessors // for the event handler functions (e.g. #onMouseDown) for each property - inject: function(/* src, ... */) { + inject: function inject(/* src, ... */) { for (var i = 0, l = arguments.length; i < l; i++) { var src = arguments[i], events = src._events; @@ -132,7 +132,7 @@ var Callback = { }); src._eventTypes = types; } - this.base(src); + inject.base.call(this, src); } return this; } diff --git a/src/core/PaperScope.js b/src/core/PaperScope.js index 9b25183c..c2d8f00b 100644 --- a/src/core/PaperScope.js +++ b/src/core/PaperScope.js @@ -32,7 +32,7 @@ * The global {@link paper} object is simply a reference to the currently active * {@code PaperScope}. */ -var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ +var PaperScope = Base.extend(/** @lends PaperScope# */{ /** * Creates a PaperScope object. @@ -40,7 +40,7 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ * @name PaperScope#initialize * @function */ - initialize: function(script) { + initialize: function PaperScope(script) { // script is only used internally, when creating scopes for PaperScript. // Whenever a PaperScope is created, it automatically becomes the active // one. @@ -71,11 +71,11 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ }, /** - * The version of Paper.js, as a float number. + * The version of Paper.js, as a string. * - * @type Number + * @type String */ - version: /*#=*/ options.version, + version: '/*#=*/ options.version', /** * The currently active project. @@ -139,7 +139,6 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ Base.each(['project', 'view', 'tool'], function(key) { Base.define(scope, key, { configurable: true, - writable: true, get: function() { return that[key]; } diff --git a/src/core/PaperScript.js b/src/core/PaperScript.js index 427d38fb..2e362cf9 100644 --- a/src/core/PaperScript.js +++ b/src/core/PaperScript.js @@ -20,8 +20,8 @@ /*#*/ } else if (options.parser == 'esprima') { /*#*/ include('../../lib/esprima-min.js'); /*#*/ } - -var PaperScript = this.PaperScript = new function() { + +var PaperScript = new function() { // Operators to overload var binaryOperators = { diff --git a/src/core/initialize.js b/src/core/initialize.js deleted file mode 100644 index ca05a307..00000000 --- a/src/core/initialize.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Paper.js - The Swiss Army Knife of Vector Graphics Scripting. - * http://paperjs.org/ - * - * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey - * http://lehni.org/ & http://jonathanpuckey.com/ - * - * Distributed under the MIT license. See LICENSE file for details. - * - * All rights reserved. - */ - -/*#*/ if (options.version == 'dev') { -// When in dev mode, also export all classes through PaperScope, to mimick -// scoping behavior of the built library. -Base.each(this, function(val, key) { - if (val && val.prototype instanceof Base || val === Base) - PaperScope.prototype[key] = val; -}); -// See paper.js for the non-dev version of this code. We cannot handle dev there -// due to the seperate loading of all source files, which are only availabe -// after the execution of paper.js -var paper = new PaperScope(); -/*#*/ } // options.version == 'dev' diff --git a/src/dom/DomElement.js b/src/dom/DomElement.js index 4e5c1a46..60d665c4 100644 --- a/src/dom/DomElement.js +++ b/src/dom/DomElement.js @@ -158,7 +158,7 @@ var DomElement = new function() { var doc = el.ownerDocument, view = doc.defaultView, html = doc.documentElement; - return Rectangle.create(0, 0, + return new Rectangle(0, 0, view.innerWidth || html.clientWidth, view.innerHeight || html.clientHeight ); diff --git a/src/dom/DomEvent.js b/src/dom/DomEvent.js index f2877636..8183dab0 100644 --- a/src/dom/DomEvent.js +++ b/src/dom/DomEvent.js @@ -49,7 +49,7 @@ var DomEvent = { ? event.targetTouches[0] : event.changedTouches[0] : event; - return Point.create( + return new Point( pos.pageX || pos.clientX + document.documentElement.scrollLeft, pos.pageY || pos.clientY + document.documentElement.scrollTop ); diff --git a/src/export.js b/src/export.js new file mode 100644 index 00000000..d18df8bc --- /dev/null +++ b/src/export.js @@ -0,0 +1,18 @@ +/* + * Paper.js - The Swiss Army Knife of Vector Graphics Scripting. + * http://paperjs.org/ + * + * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey + * http://lehni.org/ & http://jonathanpuckey.com/ + * + * Distributed under the MIT license. See LICENSE file for details. + * + * All rights reserved. + */ + +// Add PaperScript and Numerical to exports, inject all exports into PaperScope, +// and create the initial paper object, all in one condensed statement: +var paper = new (PaperScope.inject(Base.exports.inject({ + PaperScript: PaperScript, + Numerical: Numerical +})))(); diff --git a/src/item/Clip.js b/src/item/Clip.js index a311f223..f6061fa5 100644 --- a/src/item/Clip.js +++ b/src/item/Clip.js @@ -20,7 +20,10 @@ * * @extends Group */ -var Clip = this.Clip = Group.extend(/** @lends Clip# */{ - _class: 'Clip', - _applyMatrix: false +var Clip = Group.extend(/** @lends Clip# */{ + _applyMatrix: false, + + initialize: function Clip() { + Group.apply(this, arguments); + } }); diff --git a/src/item/Group.js b/src/item/Group.js index 6e42c04f..509eda70 100644 --- a/src/item/Group.js +++ b/src/item/Group.js @@ -19,8 +19,7 @@ * * @extends Item */ -var Group = this.Group = Item.extend(/** @lends Group# */{ - _class: 'Group', +var Group = Item.extend(/** @lends Group# */{ _serializeFields: { children: [] }, @@ -88,8 +87,8 @@ var Group = this.Group = Item.extend(/** @lends Group# */{ * position: view.center * }); */ - initialize: function(arg) { - this.base(); + initialize: function Group(arg) { + Item.call(this); // Allow Group to have children and named children this._children = []; this._namedChildren = {}; @@ -97,9 +96,12 @@ var Group = this.Group = Item.extend(/** @lends Group# */{ this.addChildren(Array.isArray(arg) ? arg : arguments); }, - _changed: function(flags) { - // Don't use this.base() for reasons of performance. - Item.prototype._changed.call(this, flags); + _changed: function _changed(flags) { + _changed.base.call(this, flags); + if (flags & /*#=*/ ChangeFlag.HIERARCHY && !this._matrix.isIdentity()) { + // Apply matrix now that we have content. + this.applyMatrix(); + } if (flags & (/*#=*/ ChangeFlag.HIERARCHY | /*#=*/ ChangeFlag.CLIPPING)) { // Clear cached clip item whenever hierarchy changes delete this._clipItem; diff --git a/src/item/HitResult.js b/src/item/HitResult.js index bf4f4e82..2bcc9ee5 100644 --- a/src/item/HitResult.js +++ b/src/item/HitResult.js @@ -17,8 +17,8 @@ * test. It is returned by {@link Item#hitTest(point)} and * {@link Project#hitTest(point)}. */ -var HitResult = this.HitResult = Base.extend(/** @lends HitResult# */{ - initialize: function(type, item, values) { +var HitResult = Base.extend(/** @lends HitResult# */{ + initialize: function HitResult(type, item, values) { this.type = type; this.item = item; // Inject passed values, so we can be flexible about the HitResult diff --git a/src/item/Item.js b/src/item/Item.js index 021d29c3..ecb3d159 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -20,23 +20,27 @@ * is unique to their type, but share the underlying properties and functions * that they inherit from Item. */ -var Item = this.Item = Base.extend(Callback, { +var Item = Base.extend(Callback, /** @lends Item# */{ statics: { /** * Override Item.extend() to merge the subclass' _serializeFields with * the parent class' _serializeFields. + * + * @private */ - extend: function(src) { + extend: function extend(src) { if (src._serializeFields) src._serializeFields = Base.merge( this.prototype._serializeFields, src._serializeFields); - // Derive the _type string from _class - if (src._class) - src._type = Base.hyphenate(src._class); - return this.base.apply(this, arguments); + var res = extend.base.apply(this, arguments), + name = res.name; + // Derive the _type string from constructor name + if (name) + res.prototype._type = Base.hyphenate(name); + return res; } - } -}, /** @lends Item# */{ + }, + // All items apply their matrix by default. // Exceptions are Raster, PlacedSymbol, Clip and Shape. _applyMatrix: true, @@ -55,7 +59,7 @@ var Item = this.Item = Base.extend(Callback, { data: {} }, - initialize: function(point) { + initialize: function Item(point) { // Define this Item's unique id. this._id = Item._id = (Item._id || 0) + 1; // If _project is already set, the item was already moved into the DOM @@ -168,7 +172,7 @@ var Item = this.Item = Base.extend(Callback, { serialize(this._style._defaults); // There is no compact form for Item serialization, we always keep the // type. - return [ this._class, props ]; + return [ this.constructor.name, props ]; }, /** @@ -198,7 +202,7 @@ var Item = this.Item = Base.extend(Callback, { this._clearBoundsCache(); } if (flags & /*#=*/ ChangeFlag.APPEARANCE) { - this._project._needsRedraw(); + this._project._needsRedraw = true; } // If this item is a symbol's definition, notify it of the change too if (this._parentSymbol) @@ -878,7 +882,7 @@ var Item = this.Item = Base.extend(Callback, { } } return isFinite(x1) - ? Rectangle.create(x1, y1, x2 - x1, y2 - y1) + ? new Rectangle(x1, y1, x2 - x1, y2 - y1) : new Rectangle(); }, @@ -1428,7 +1432,6 @@ var Item = this.Item = Base.extend(Callback, { * @param {Item} item The item to be added as a child */ addChild: function(item, _preserve) { - // Pass on internal _preserve boolean, for CompoundPath#insertChild return this.insertChild(undefined, item, _preserve); }, @@ -1441,21 +1444,8 @@ var Item = this.Item = Base.extend(Callback, { * @param {Item} item The item to be appended as a child */ insertChild: function(index, item, _preserve) { - // _preserve parameter is not used here, but CompoundPath#insertChild() - // needs it. - if (this._children) { - item._remove(true); - Base.splice(this._children, [item], index, 0); - item._parent = this; - item._setProject(this._project); - // Setting the name again makes sure all name lookup structures are - // kept in sync. - if (item._name) - item.setName(item._name); - this._changed(/*#=*/ Change.HIERARCHY); - return item; - } - return null; + var res = this.insertChildren(index, [item], _preserve); + return res && res[0]; }, /** @@ -1477,25 +1467,42 @@ var Item = this.Item = Base.extend(Callback, { * @param {Number} index * @param {Item[]} items The items to be appended as children */ - insertChildren: function(index, items, _preserve) { - // We need to clone items because it might be - // an Item#children array. Use Array.prototype.slice because - // in certain cases items is an arguments object - items = items && Array.prototype.slice.apply(items); - var children = this._children, - length = children.length, - i = index; - for (var j = 0, l = items && items.length; j < l; j++) { - if (this.insertChild(i, items[j], _preserve)) { - // We need to keep track of how much the list actually grows, - // bcause we might be removing and inserting into the same list, - // in which case the size would not chage. - var newLength = children.length; - i += newLength - length; - length = newLength; + insertChildren: function(index, items, _preserve, _type) { + // CompoundPath#insertChildren() requires _preserve and _type: + // _preserve avoids changing of the children's path orientation + // _type enforces the inserted type. + var children = this._children; + if (children && items && items.length > 0) { + // We need to clone items because it might be + // an Item#children array. Also, we're removing elements if they + // don't match _type. Use Array.prototype.slice becaus items can be + // an arguments object. + items = Array.prototype.slice.apply(items); + // Remove the items from their parents first, since they might be + // inserted into their own parents, affecting indices. + // Use the loop also to filter out wrong _type. + for (var i = items.length - 1; i >= 0; i--) { + var item = items[i]; + if (_type && item._type !== _type) + items.splice(i, 1); + else + item._remove(true); } + Base.splice(children, items, index, 0); + for (var i = 0, l = items.length; i < l; i++) { + var item = items[i]; + item._parent = this; + item._setProject(this._project); + // Setting the name again makes sure all name lookup structures + // are kept in sync. + if (item._name) + item.setName(item._name); + } + this._changed(/*#=*/ Change.HIERARCHY); + } else { + items = null; } - return i != index; + return items; }, /** @@ -2220,9 +2227,10 @@ var Item = this.Item = Base.extend(Callback, { }, _transformContent: function(matrix, applyMatrix) { - if (this._children) { - for (var i = 0, l = this._children.length; i < l; i++) - this._children[i].transform(matrix, applyMatrix); + var children = this._children; + if (children && children.length > 0) { + for (var i = 0, l = children.length; i < l; i++) + children[i].transform(matrix, applyMatrix); return true; } }, @@ -2332,7 +2340,7 @@ var Item = this.Item = Base.extend(Callback, { ? rectangle.width / bounds.width : rectangle.height / bounds.height, newBounds = new Rectangle(new Point(), - Size.create(bounds.width * scale, bounds.height * scale)); + new Size(bounds.width * scale, bounds.height * scale)); newBounds.setCenter(rectangle.getCenter()); this.setBounds(newBounds); }, @@ -2877,7 +2885,7 @@ var Item = this.Item = Base.extend(Callback, { // so we draw onto it, instead of the parentCtx parentCtx = ctx; ctx = CanvasProvider.getContext( - bounds.getSize().ceil().add(Size.create(1, 1))); + bounds.getSize().ceil().add(new Size(1, 1))); } ctx.save(); // Translate the context so the topLeft of the item is at (0, 0) diff --git a/src/item/Layer.js b/src/item/Layer.js index ff2afaf0..6a9c85aa 100644 --- a/src/item/Layer.js +++ b/src/item/Layer.js @@ -22,8 +22,7 @@ * * @extends Group */ -var Layer = this.Layer = Group.extend(/** @lends Layer# */{ - _class: 'Layer', +var Layer = Group.extend(/** @lends Layer# */{ // DOCS: improve constructor code example. /** * Creates a new Layer item and places it at the end of the @@ -57,11 +56,11 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{ * position: view.center * }); */ - initialize: function(items) { + initialize: function Layer(items) { this._project = paper.project; // Push it onto project.layers and set index: this._index = this._project.layers.push(this) - 1; - this.base.apply(this, arguments); + Group.apply(this, arguments); this.activate(); }, @@ -69,9 +68,9 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{ * Removes the layer from its project's layers list * or its parent's children list. */ - _remove: function(notify) { + _remove: function _remove(notify) { if (this._parent) - return this.base(notify); + return _remove.base.call(this, notify); if (this._index != null) { if (this._project.activeLayer === this) this._project.activeLayer = this.getNextSibling() @@ -79,24 +78,24 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{ Base.splice(this._project.layers, null, this._index, 1); // Tell project we need a redraw. This is similar to _changed() // mechanism. - this._project._needsRedraw(); + this._project._needsRedraw = true; return true; } return false; }, - getNextSibling: function() { - return this._parent ? this.base() + getNextSibling: function getNextSibling() { + return this._parent ? getNextSibling.base.call(this) : this._project.layers[this._index + 1] || null; }, - getPreviousSibling: function() { - return this._parent ? this.base() + getPreviousSibling: function getPreviousSibling() { + return this._parent ? getPreviousSibling.base.call(this) : this._project.layers[this._index - 1] || null; }, - isInserted: function() { - return this._parent ? this.base() : this._index != null; + isInserted: function isInserted() { + return this._parent ? isInserted.base.call(this) : this._index != null; }, /** @@ -114,7 +113,7 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{ } }, new function () { function insert(above) { - return function(item) { + return function insert(item) { // If the item is a layer and contained within Project#layers, use // our own version of move(). if (item instanceof Layer && !item._parent @@ -124,7 +123,7 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{ this._setProject(item._project); return true; } - return this.base(item); + return insert.base.call(this, item); }; } diff --git a/src/item/PlacedSymbol.js b/src/item/PlacedSymbol.js index 06298ac2..08b5f189 100644 --- a/src/item/PlacedSymbol.js +++ b/src/item/PlacedSymbol.js @@ -18,8 +18,7 @@ * * @extends Item */ -var PlacedSymbol = this.PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{ - _class: 'PlacedSymbol', +var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{ _applyMatrix: false, // PlacedSymbol uses strokeBounds for bounds _boundsGetter: { getBounds: 'getStrokeBounds' }, @@ -68,11 +67,11 @@ var PlacedSymbol = this.PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{ * instance.scale(0.25 + Math.random() * 0.75); * } */ - initialize: function(arg0, arg1) { + initialize: function PlacedSymbol(arg0, arg1) { // Support two forms of item initialization: Passing one object literal // describing all the different properties to be set, or a symbol (arg0) // and a point where it should be placed (arg1). - this.base(arg1 !== undefined && Point.read(arguments, 1)); + Item.call(this, arg1 !== undefined && Point.read(arguments, 1)); // If we can handle setting properties through object literal, we're all // set. Otherwise we need to set symbol. if (arg0 && !this._set(arg0)) diff --git a/src/item/Raster.js b/src/item/Raster.js index 5899222f..63022136 100644 --- a/src/item/Raster.js +++ b/src/item/Raster.js @@ -17,8 +17,7 @@ * * @extends Item */ -var Raster = this.Raster = Item.extend(/** @lends Raster# */{ - _class: 'Raster', +var Raster = Item.extend(/** @lends Raster# */{ _applyMatrix: false, // Raster doesn't make the distinction between the different bounds, // so use the same name for all of them @@ -72,11 +71,11 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{ * raster.scale(0.5); * raster.rotate(10); */ - initialize: function(object, position) { + initialize: function Raster(object, position) { // Support two forms of item initialization: Passing one object literal // describing all the different properties to be set, or an image // (object) and a point where it should be placed (point). - this.base(position !== undefined && Point.read(arguments, 1)); + Item.call(this, position !== undefined && Point.read(arguments, 1)); // If we can handle setting properties through object literal, we're all // set. Otherwise we need to check the type of object: if (object && !this._set(object)) { @@ -164,7 +163,7 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{ orig = new Point(0, 0).transform(matrix), u = new Point(1, 0).transform(matrix).subtract(orig), v = new Point(0, 1).transform(matrix).subtract(orig); - return Size.create( + return new Size( 72 / u.getLength(), 72 / v.getLength() ); @@ -218,7 +217,7 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{ if (this._canvas) CanvasProvider.release(this._canvas); this._canvas = canvas; - this._size = Size.create(canvas.width, canvas.height); + this._size = new Size(canvas.width, canvas.height); this._image = null; this._context = null; this._changed(/*#=*/ Change.GEOMETRY | /*#=*/ Change.PIXELS); @@ -239,10 +238,10 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{ CanvasProvider.release(this._canvas); this._image = image; /*#*/ if (options.browser) { - this._size = Size.create(image.naturalWidth, image.naturalHeight); -/*#*/ } else if (options.server) { - this._size = Size.create(image.width, image.height); -/*#*/ } // options.server + this._size = new Size(image.naturalWidth, image.naturalHeight); +/*#*/ } else if (options.node) { + this._size = new Size(image.width, image.height); +/*#*/ } // options.node this._canvas = null; this._context = null; this._changed(/*#=*/ Change.GEOMETRY); @@ -296,14 +295,22 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{ } else if (!image.src) { image.src = src; } -/*#*/ } else if (options.server) { - // If we're running on the server and it's a string, - // load it from disk: - // TODO: load images async, calling setImage once loaded as above - var image = new Image(); - image.src = fs.readFileSync(src); -/*#*/ } // options.server this.setImage(image); +/*#*/ } else if (options.node) { + var image = new Image(); + // If we're running on the server and it's a string, + // check if it is a data URL + if (/^data:/.test(src)) { + // Preserve the data in this._data since canvas-node eats it. + // TODO: Fix canvas-node instead + image.src = this._data = src; + } else { + // Load it from disk: + // TODO: load images async, calling setImage once loaded as above. + image.src = fs.readFileSync(src); + } + this.setImage(image); +/*#*/ } // options.node }, // DOCS: document Raster#getElement @@ -334,9 +341,14 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{ toDataURL: function() { // See if the linked image is base64 encoded already, if so reuse it, // otherwise try using canvas.toDataURL() +/*#*/ if (options.node) { + if (this._data) + return this._data; +/*#*/ } else { var src = this._image && this._image.src; if (/^data:/.test(src)) return src; +/*#*/ } var canvas = this.getCanvas(); return canvas ? canvas.toDataURL() : null; }, @@ -375,7 +387,7 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{ bounds = new Rectangle(object); } else if (object.x) { // Create a rectangle of 1px size around the specified coordinates - bounds = Rectangle.create(object.x - 0.5, object.y - 0.5, 1, 1); + bounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1); } // Use a sample size of max 32 x 32 pixels, into which the path is // scaled as a clipping path, and then the actual image is drawn in and diff --git a/src/item/Shape.js b/src/item/Shape.js index 3a11335f..100c1c66 100644 --- a/src/item/Shape.js +++ b/src/item/Shape.js @@ -17,12 +17,11 @@ * * @extends Item */ -var Shape = this.Shape = Item.extend(/** @lends Shape# */{ - _class: 'Shape', +var Shape = Item.extend(/** @lends Shape# */{ _applyMatrix: false, - initialize: function(type, point, size) { - this.base(point); + initialize: function Shape(type, point, size) { + Item.call(this, point); this._type = type; this._size = size; }, @@ -67,10 +66,10 @@ var Shape = this.Shape = Item.extend(/** @lends Shape# */{ } }, - _contains: function(point) { + _contains: function _contains(point) { switch (this._type) { case 'rect': - return this.base(point); + return _contains.base.call(this, point); case 'circle': case 'ellipse': return point.divide(this._size).getLength() <= 0.5; diff --git a/src/load.js b/src/load.js index 97430850..73a5d453 100644 --- a/src/load.js +++ b/src/load.js @@ -14,17 +14,7 @@ // 'preprocess' it on the fly in the browser, avoiding the step of having to // manually preprocess it after each change. -// Define options for compile-time preprocessing. -var options = { - parser: 'acorn', - version: 'dev', - browser: true, - stats: true, - svg: true, - fatline: true, - debug: false -}; - // This folder is specified relatively to the lib folder from which prepro.js is // loaded, and which is referenced as the root. +include('../src/options.js'); include('../src/paper.js'); diff --git a/src/node/index.js b/src/node/index.js index c9838a65..fe96aea3 100644 --- a/src/node/index.js +++ b/src/node/index.js @@ -16,24 +16,23 @@ var fs = require('fs'), // Node Canvas library: https://github.com/learnboost/node-canvas Canvas = require('canvas'), jsdom = require('jsdom'), - domToHtml = require('jsdom/lib/jsdom/browser/domtohtml').domToHtml, - json = require('../../package.json'); + domToHtml = require('jsdom/lib/jsdom/browser/domtohtml').domToHtml; -var options = { - parser: 'acorn', - // Use 'dev' for on-the fly compilation of separate files ,but update after. - version: 'dev', - server: true, - svg: true, - fatline: false -}; +// Load the options from load.js, but evaluate into local scope: +eval(fs.readFileSync(path.resolve(__dirname, '../options.js'), 'utf8')); +// Change node.js specific settings. Use 'dev' version for on-the fly +// compilation of separate files, and set to correct value after. +options.version = 'dev'; +options.browser = false; +options.node = true; +options.stats = false; // Create a document and a window using jsdom, e.g. for exportSVG() var doc = jsdom.jsdom("<html><body></body></html>"), win = doc.createWindow(); -// Define XMLSerializer. -// TODO: Put this into a simple node module, with dependency on jsdom +// Define XMLSerializer and DOMParser shims, to emulate browser behavior. +// TODO: Put this into a simple node module, with dependency on jsdom? function XMLSerializer() { } @@ -41,7 +40,7 @@ XMLSerializer.prototype.serializeToString = function(node) { var text = domToHtml(node); // Fix a jsdom issue where linearGradient gets converted to lineargradient: // https://github.com/tmpvar/jsdom/issues/620 - return text.replace(/(linear|radial)(gradient)/g, function(all, type) { + return text.replace(/(linear|radial)gradient/g, function(all, type) { return type + 'Gradient'; }); }; @@ -89,26 +88,13 @@ var context = vm.createContext({ // Load Paper.js library files: context.include('paper.js'); -// Since the context used for Paper.js compilation, and the context in which -// Node.js scripts are executed do not share the definition of Object, we need -// to redefine Base.isPlainObject() here. -// So instead of checking for Object.prototype, we're checking -// proto.constructor.name for 'Object' -var Base = context.Base; -Base.isPlainObject = function(obj) { - var proto = obj !== null && typeof obj === 'object' - && Object.getPrototypeOf(obj); - return proto && (proto.constructor.name === 'Object' - || proto === Base.prototype); -}; - context.PaperScope.inject({ // Expose the Canvas, XMLSerializer & DOMParser to PaperScope: Canvas: Canvas, XMLSerializer: XMLSerializer, DOMParser: DOMParser, - // Also fix version. Remove 2nd dot, so we can make a float out of it: - version: parseFloat(json.version.replace(/(.)(\d)$/, '$2')) + // Also set the correct version from package.json + version: require('../../package.json').version }); require.extensions['.pjs'] = function(module, uri) { diff --git a/src/options.js b/src/options.js new file mode 100644 index 00000000..20d1e802 --- /dev/null +++ b/src/options.js @@ -0,0 +1,24 @@ +/* + * Paper.js - The Swiss Army Knife of Vector Graphics Scripting. + * http://paperjs.org/ + * + * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey + * http://lehni.org/ & http://jonathanpuckey.com/ + * + * Distributed under the MIT license. See LICENSE file for details. + * + * All rights reserved. + */ + +// Define default options for compile-time preprocessing. These are also used +// for building, but some values are overridden (e.g. version, stats). + +var options = { + parser: 'acorn', + version: 'dev', + browser: true, + stats: true, + svg: true, + fatline: false, + debug: false +}; diff --git a/src/paper.js b/src/paper.js index 964f64fc..abceb5a1 100644 --- a/src/paper.js +++ b/src/paper.js @@ -35,14 +35,14 @@ var paper = new function() { // Inline Bootstrap core (the Base class) inside the paper scope first: /*#*/ include('../lib/straps.js'); -/*#*/ if (options.version == 'dev') { -/*#*/ include('constants.js'); -/*#*/ } // options.version == 'dev' - /*#*/ if (options.stats) { /*#*/ include('../lib/stats.js'); /*#*/ } // options.stats +/*#*/ if (options.version == 'dev') { +/*#*/ include('constants.js'); +/*#*/ } // options.version == 'dev' + /*#*/ include('core/Base.js'); /*#*/ include('core/Callback.js'); /*#*/ include('core/PaperScope.js'); @@ -53,7 +53,7 @@ var paper = new function() { // Include Paper classes, which are later injected into PaperScope by setting // them on the 'this' object, e.g.: -// var Point = this.Point = Base.extend(...); +// var Point = Base.extend(...); /*#*/ include('basic/Point.js'); /*#*/ include('basic/Size.js'); @@ -126,18 +126,7 @@ var paper = new function() { /*#*/ } // options.svg /*#*/ include('core/PaperScript.js'); -/*#*/ include('core/initialize.js'); -/*#*/ if (options.server) { +/*#*/ include('export.js'); return paper; -/*#*/ } else if (options.version != 'dev') { -// Finally inject the classes set on 'this' into the PaperScope class and create -// the first PaperScope and return it, all in one statement. -// The version for 'dev' of this happens in core/initialize.js, since it depends -// on sequentiality of include() loading. -// Mark this object as enumerable, so all the injected classes can be enumerated -// again in PaperScope#install(). -this.enumerable = true; -return new (PaperScope.inject(this)); -/*#*/ } // options.version != 'dev' }; diff --git a/src/path/CompoundPath.js b/src/path/CompoundPath.js index 9cf5a976..c78b34fb 100644 --- a/src/path/CompoundPath.js +++ b/src/path/CompoundPath.js @@ -20,8 +20,7 @@ * * @extends PathItem */ -var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath# */{ - _class: 'CompoundPath', +var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{ _serializeFields: { pathData: '' }, @@ -49,8 +48,8 @@ var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath# * // Move the inner circle 5pt to the right: * compoundPath.children[1].position.x += 5; */ - initialize: function(arg) { - this.base(); + initialize: function CompoundPath(arg) { + PathItem.call(this); // CompoundPath has children and supports named children. this._children = []; this._namedChildren = {}; @@ -58,18 +57,20 @@ var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath# this.addChildren(Array.isArray(arg) ? arg : arguments); }, - insertChild: function(index, item, _preserve) { - // Only allow the insertion of paths - if (item._type !== 'path') - return null; - item = this.base(index, item); + insertChildren: function insertChildren(index, items, _preserve) { + // Pass on 'path' for _type, to make sure that only paths are added as + // children. + items = insertChildren.base.call(this, index, items, _preserve, 'path'); // All children except for the bottom one (first one in list) are set // to anti-clockwise orientation, so that they appear as holes, but // only if their orientation was not already specified before // (= _clockwise is defined). - if (!_preserve && item && item._clockwise === undefined) - item.setClockwise(item._index == 0); - return item; + for (var i = 0, l = !_preserve && items && items.length; i < l; i++) { + var item = items[i]; + if (item._clockwise === undefined) + item.setClockwise(item._index === 0); + } + return items; }, /** @@ -223,8 +224,9 @@ var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath# return (children.length & 1) == 1 && children; }, - _hitTest: function(point, options) { - var res = this.base(point, Base.merge(options, { fill: false })); + _hitTest: function _hitTest(point, options) { + var res = _hitTest.base.call(this, point, + Base.merge(options, { fill: false })); if (!res && options.fill && this._style.getFillColor()) { res = this._contains(point); res = res ? new HitResult('fill', res[0]) : null; diff --git a/src/path/Curve.js b/src/path/Curve.js index 0ff336be..42101d65 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -24,7 +24,7 @@ * convenient ways to work with parts of the path, finding lengths, positions or * tangents at given offsets. */ -var Curve = this.Curve = Base.extend(/** @lends Curve# */{ +var Curve = Base.extend(/** @lends Curve# */{ /** * Creates a new curve object. * @@ -55,7 +55,7 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{ * @param {Number} x2 * @param {Number} y2 */ - initialize: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { var count = arguments.length; if (count === 0) { this._segment1 = new Segment(); @@ -243,7 +243,7 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{ var coords = this.getValues(), points = []; for (var i = 0; i < 8; i += 2) - points.push(Point.create(coords[i], coords[i + 1])); + points.push(new Point(coords[i], coords[i + 1])); return points; }, @@ -408,9 +408,9 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{ // Create the new segment, convert absolute -> relative: var x = left[6], y = left[7], - segment = new Segment(Point.create(x, y), - !isLinear && Point.create(left[4] - x, left[5] - y), - !isLinear && Point.create(right[2] - x, right[3] - y)); + segment = new Segment(new Point(x, y), + !isLinear && new Point(left[4] - x, left[5] - y), + !isLinear && new Point(right[2] - x, right[3] - y)); // Insert it in the segments list, if needed: if (this._path) { @@ -662,7 +662,7 @@ statics: { for (var i = 0; i < 2; i++) Curve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6], i, 0, min, max, roots); - return Rectangle.create(min[0], min[1], max[0] - min[0], max[1] - min[1]); + return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]); }, /** @@ -697,8 +697,8 @@ statics: { // Only add strokeWidth to bounds for points which lie within 0 < t < 1 // The corner cases for cap and join are handled in getStrokeBounds() add(v3, 0); - for (var j = 0; j < count; j++) { - var t = roots[j], + for (var i = 0; i < count; i++) { + var t = roots[i], u = 1 - t; // Test for good roots and only add to bounds if good. if (tMin < t && t < tMax) @@ -1023,7 +1023,7 @@ new function() { // Scope for methods that require numerical integration a, b, 16, /*#=*/ Numerical.TOLERANCE); } }; -}, new function() { // Scope for Curve intersection +}, new function() { // Scope for intersection using bezier fat-line clipping function addLocation(locations, curve1, parameter, point, curve2) { // Avoid duplicates when hitting segments (closed paths too) var first = locations[0], @@ -1033,7 +1033,7 @@ new function() { // Scope for methods that require numerical integration locations.push(new CurveLocation(curve1, parameter, point, curve2)); } - function getCurveIntersections(v1, v2, curve1, curve2, locations, + function addCurveIntersections(v1, v2, curve1, curve2, locations, range1, range2, recursion) { /*#*/ if (options.fatline) { // NOTE: range1 and range1 are only used for recusion @@ -1097,17 +1097,17 @@ new function() { // Scope for methods that require numerical integration if (range1[1] - range1[0] > range2[1] - range2[0]) { // subdivide v1 and recurse var t = (range1[0] + range1[1]) / 2; - getCurveIntersections(v1, v2, curve1, curve2, locations, + addCurveIntersections(v1, v2, curve1, curve2, locations, [ range1[0], t ], range2, recursion); - getCurveIntersections(v1, v2, curve1, curve2, locations, + addCurveIntersections(v1, v2, curve1, curve2, locations, [ t, range1[1] ], range2, recursion); break; } else { // subdivide v2 and recurse var t = (range2[0] + range2[1]) / 2; - getCurveIntersections(v1, v2, curve1, curve2, locations, + addCurveIntersections(v1, v2, curve1, curve2, locations, range1, [ range2[0], t ], recursion); - getCurveIntersections(v1, v2, curve1, curve2, locations, + addCurveIntersections(v1, v2, curve1, curve2, locations, range1, [ t, range2[1] ], recursion); break; } @@ -1123,12 +1123,16 @@ new function() { // Scope for methods that require numerical integration // Check if one of the parameter range has converged completely to a // point. Now things could get only worse if we iterate more for the // other curve to converge if it hasn't yet happened so. - var converged1 = Math.abs(range1[1] - range1[0]) < /*#=*/ Numerical.TOLERANCE, - converged2 = Math.abs(range2[1] - range2[0]) < /*#=*/ Numerical.TOLERANCE; - if (converged1 || converged2) { - addLocation(locations, curve1, null, converged1 - ? curve1.getPointAt(range1[0], true) - : curve2.getPointAt(range2[0], true), curve2); + if (Math.abs(range1[1] - range1[0]) < /*#=*/ Numerical.TOLERANCE) { + var t = (range1[0] + range1[1]) / 2; + addLocation(locations, curve1, t, + Curve.evaluate(v1, t, true, 0), curve2); + break; + } + if (Math.abs(range2[1] - range2[0]) < /*#=*/ Numerical.TOLERANCE) { + var t = (range2[0] + range2[1]) / 2; + addLocation(locations, curve2, t, + Curve.evaluate(v2, t, true, 0), curve1); break; } // see if either or both of the curves are flat enough to be treated @@ -1137,10 +1141,10 @@ new function() { // Scope for methods that require numerical integration flat2 = Curve.isFlatEnough(part2, /*#=*/ Numerical.TOLERANCE); if (flat1 || flat2) { (flat1 && flat2 - ? getLineLineIntersection + ? addLineIntersection // Use curve line intersection method while specifying // which curve to be treated as line - : getCurveLineIntersections)(part1, part2, + : addCurveLineIntersections)(part1, part2, curve1, curve2, locations, flat1); break; } @@ -1158,15 +1162,7 @@ new function() { // Scope for methods that require numerical integration && (Curve.isLinear(v2) || Curve.isFlatEnough(v2, /*#=*/ Numerical.TOLERANCE))) { // See if the parametric equations of the lines interesct. - // var point = new Line(v1[0], v1[1], v1[6], v1[7], false) - // .intersect(new Line(v2[0], v2[1], v2[6], v2[7], false)); - // Use static version without creation of Line objects, but it - // doesn't seem to yield measurable speed improvements! - var point = Line.intersect( - v1[0], v1[1], v1[6], v1[7], - v2[0], v2[1], v2[6], v2[7], false); - if (point) - addLocation(locations, curve1, null, point, curve2); + addLineIntersection(v1, v2, curve1, curve2, locations); } else { // Subdivide both curves, and see if they intersect. // If one of the curves is flat already, no further subdivion @@ -1200,6 +1196,7 @@ new function() { // Scope for methods that require numerical integration p2x = v1[4], p2y = v1[5], p3x = v1[6], p3y = v1[7], q0x = v2[0], q0y = v2[1], q1x = v2[2], q1y = v2[3], q2x = v2[4], q2y = v2[5], q3x = v2[6], q3y = v2[7], + getSignedDistance = Line.getSignedDistance, // Calculate the fat-line L for P is the baseline l and two // offsets which completely encloses the curve P. d1 = getSignedDistance(p0x, p0y, p3x, p3y, p1x, p1y) || 0, @@ -1213,20 +1210,19 @@ new function() { // Scope for methods that require numerical integration dq0 = getSignedDistance(p0x, p0y, p3x, p3y, q0x, q0y), dq1 = getSignedDistance(p0x, p0y, p3x, p3y, q1x, q1y), dq2 = getSignedDistance(p0x, p0y, p3x, p3y, q2x, q2y), - dq3 = getSignedDistance(p0x, p0y, p3x, p3y, q3x, q3y), - // Find the minimum and maximum distances from l, this is useful for - // checking whether the curves intersect with each other or not. - mindist = Math.min(dq0, dq1, dq2, dq3), - maxdist = Math.max(dq0, dq1, dq2, dq3); + dq3 = getSignedDistance(p0x, p0y, p3x, p3y, q3x, q3y); + // Find the minimum and maximum distances from l, this is useful for + // checking whether the curves intersect with each other or not. // If the fatlines don't overlap, we have no intersections! - if (dmin > maxdist || dmax < mindist) + if (dmin > Math.max(dq0, dq1, dq2, dq3) + || dmax < Math.min(dq0, dq1, dq2, dq3)) return 0; - var Dt = getConvexHull(dq0, dq1, dq2, dq3), - tmp; + var hull = getConvexHull(dq0, dq1, dq2, dq3), + swap; if (dq3 < dq0) { - tmp = dmin; + swap = dmin; dmin = dmax; - dmax = tmp; + dmax = swap; } // Calculate the convex hull for non-parametric bezier curve D(ti, di(t)) // Now we clip the convex hulls for D(ti, di(t)) with dmin and dmax @@ -1235,31 +1231,29 @@ new function() { // Scope for methods that require numerical integration var tmaxdmin = -Infinity, tmin = Infinity, tmax = -Infinity; - for (var i = 0, l = Dt.length; i < l; i++) { - var Dtl = Dt[i], - dtlx1 = Dtl[0], - dtly1 = Dtl[1], - dtlx2 = Dtl[2], - dtly2 = Dtl[3]; - if (dtly2 < dtly1) { - tmp = dtly2; - dtly2 = dtly1; - dtly1 = tmp; - tmp = dtlx2; - dtlx2 = dtlx1; - dtlx1 = tmp; + for (var i = 0, l = hull.length; i < l; i++) { + var p1 = hull[i], + p2 = hull[(i + 1) % l]; + if (p2[1] < p1[1]) { + swap = p2; + p2 = p1; + p1 = swap; } - // We know that (dtlx2 - dtlx1) is never 0 - var inv = (dtly2 - dtly1) / (dtlx2 - dtlx1); - if (dmin >= dtly1 && dmin <= dtly2) { - var ixdx = dtlx1 + (dmin - dtly1) / inv; + var x1 = p1[0], + y1 = p1[1], + x2 = p2[0], + y2 = p2[1]; + // We know that (x2 - x1) is never 0 + var inv = (y2 - y1) / (x2 - x1); + if (dmin >= y1 && dmin <= y2) { + var ixdx = x1 + (dmin - y1) / inv; if (ixdx < tmin) tmin = ixdx; if (ixdx > tmaxdmin) tmaxdmin = ixdx; } - if (dmax >= dtly1 && dmax <= dtly2) { - var ixdx = dtlx1 + (dmax - dtly1) / inv; + if (dmax >= y1 && dmax <= y2) { + var ixdx = x1 + (dmax - y1) / inv; if (ixdx > tmax) tmax = ixdx; if (ixdx < tmin) @@ -1269,11 +1263,11 @@ new function() { // Scope for methods that require numerical integration // Return the parameter values for v2 for which we can be sure that the // intersection with v1 lies within. if (tmin !== Infinity && tmax !== -Infinity) { - var mindmin = Math.min(dmin, dmax), - mindmax = Math.max(dmin, dmax); - if (dq3 > mindmin && dq3 < mindmax) + var min = Math.min(dmin, dmax), + max = Math.max(dmin, dmax); + if (dq3 > min && dq3 < max) tmax = 1; - if (dq0 > mindmin && dq0 < mindmax) + if (dq0 > min && dq0 < max) tmin = 0; if (tmaxdmin > tmax) tmax = 1; @@ -1304,79 +1298,48 @@ new function() { // Scope for methods that require numerical integration * Calculating convex-hull is much easier than a set of arbitrary points. */ function getConvexHull(dq0, dq1, dq2, dq3) { - var distq1 = getSignedDistance(0, dq0, 1, dq3, 1 / 3, dq1), - distq2 = getSignedDistance(0, dq0, 1, dq3, 2 / 3, dq2); - // Check if [1/3, dq1] and [2/3, dq2] are on the same side of line - // [0,dq0, 1,dq3] - if (distq1 * distq2 < 0) { - // dq1 and dq2 lie on different sides on [0, q0, 1, q3]. The hull is - // a quadrilateral and line [0, q0, 1, q3] is NOT part of the hull - // so we are pretty much done here. - return [ - [ 0, dq0, 1 / 3, dq1 ], - [ 1 / 3, dq1, 1, dq3 ], - [ 2 / 3, dq2, 0, dq0 ], - [ 1, dq3, 2 / 3, dq2 ] - ]; + var p0 = [ 0, dq0 ], + p1 = [ 1 / 3, dq1 ], + p2 = [ 2 / 3, dq2 ], + p3 = [ 1, dq3 ], + // Find signed distance of p1 and p2 from line [ p0, p3 ] + getSignedDistance = Line.getSignedDistance, + dist1 = getSignedDistance(0, dq0, 1, dq3, 1 / 3, dq1), + dist2 = getSignedDistance(0, dq0, 1, dq3, 2 / 3, dq2); + // Check if p1 and p2 are on the same side of the line [ p0, p3 ] + if (dist1 * dist2 < 0) { + // p1 and p2 lie on different sides of [ p0, p3 ]. The hull is a + // quadrilateral and line [ p0, p3 ] is NOT part of the hull so we + // are pretty much done here. + return [ p0, p1, p3, p2 ]; } - // dq1 and dq2 lie on the same sides on [0, q0, 1, q3]. The hull can be - // a triangle or a quadrilateral and line [0, q0, 1, q3] is part of the + // p1 and p2 lie on the same sides of [ p0, p3 ]. The hull can be + // a triangle or a quadrilateral and line [ p0, p3 ] is part of the // hull. Check if the hull is a triangle or a quadrilateral. - var dqMaxX, dqMaxY, vqa1a2X, vqa1a2Y, vqa1MaxX, vqa1MaxY, vqa1MinX, vqa1MinY; - if (Math.abs(distq1) > Math.abs(distq2)) { - dqMaxX = 1 / 3; - dqMaxY = dq1; + var pmax, cross; + if (Math.abs(dist1) > Math.abs(dist2)) { + pmax = p1; // apex is dq3 and the other apex point is dq0 vector // dqapex->dqapex2 or base vector which is already part of the hull. - vqa1a2X = 1; - vqa1a2Y = dq3 - dq0; - // vector dqapex->dqMax - vqa1MaxX = 2 / 3; - vqa1MaxY = dq3 - dq1; - // vector dqapex->dqmin - vqa1MinX = 1 / 3; - vqa1MinY = dq3 - dq2; + // cross = (vqa1a2X * vqa1MinY - vqa1a2Y * vqa1MinX) + // * (vqa1MaxX * vqa1MinY - vqa1MaxY * vqa1MinX) + cross = (dq3 - dq2 - (dq3 - dq0) / 3) + * (2 * (dq3 - dq2) - dq3 + dq1) / 3; } else { - dqMaxX = 2 / 3; - dqMaxY = dq2; + pmax = p2; // apex is dq0 in this case, and the other apex point is dq3 vector // dqapex->dqapex2 or base vector which is already part of the hull. - vqa1a2X = -1; - vqa1a2Y = dq0 - dq3; - // vector dqapex->dqMax - vqa1MaxX = -2 / 3; - vqa1MaxY = dq0 - dq2; - // vector dqapex->dqmin - vqa1MinX = -1 / 3; - vqa1MinY = dq0 - dq1; + cross = (dq1 - dq0 + (dq0 - dq3) / 3) + * (-2 * (dq0 - dq1) + dq0 - dq2) / 3; } - // Compare cross products of these vectors to determine, if - // point is in triangles [ dq3, dqMax, dq0 ] or [ dq0, dqMax, dq3 ] - var a1a2_a1Min = vqa1a2X * vqa1MinY - vqa1a2Y * vqa1MinX, - a1Max_a1Min = vqa1MaxX * vqa1MinY - vqa1MaxY * vqa1MinX; - return a1a2_a1Min * a1Max_a1Min < 0 - // Point [2/3, dq2] is inside the triangle, hull is a triangle. - ? [ - [ 0, dq0, dqMaxX, dqMaxY ], - [ dqMaxX, dqMaxY, 1, dq3 ], - [ 1, dq3, 0, dq0 ] - ] + // Compare cross products of these vectors to determine if the point is + // in the triangle [ p3, pmax, p0 ], or if it is a quadrilateral. + return cross < 0 + // p2 is inside the triangle, hull is a triangle. + ? [ p0, pmax, p3 ] // Convexhull is a quadrilateral and we need all lines in the - // correct order where line [0, q0, 1, q3] is part of the hull. - : [ - [ 0, dq0, 1 / 3, dq1 ], - [ 1 / 3, dq1, 2 / 3, dq2 ], - [ 2 / 3, dq2, 1, dq3 ], - [ 1, dq3, 0, dq0 ] - ]; - } - - // This is basically an "unrolled" version of #Line.getDistance() with sign - // May be a static method could be better! - function getSignedDistance(a1x, a1y, a2x, a2y, bx, by) { - var m = (a2y - a1y) / (a2x - a1x), - b = a1y - (m * a1x); - return (by - (m * bx) - b) / Math.sqrt(m * m + 1); + // correct order where line [ p1, p3 ] is part of the hull. + : [ p0, p1, p2, p3 ]; } /*#*/ } // options.fatline @@ -1386,7 +1349,7 @@ new function() { // Scope for methods that require numerical integration * line is on the X axis, and solve the implicit equations for the X axis * and the curve. */ - function getCurveLineIntersections(v1, v2, curve1, curve2, locations, flip) { + function addCurveLineIntersections(v1, v2, curve1, curve2, locations, flip) { if (flip === undefined) flip = Curve.isLinear(v1); var vc = flip ? v2 : v1, @@ -1432,17 +1395,17 @@ new function() { // Scope for methods that require numerical integration } } - function getLineLineIntersection(v1, v2, curve1, curve2, locations) { + function addLineIntersection(v1, v2, curve1, curve2, locations) { var point = Line.intersect( v1[0], v1[1], v1[6], v1[7], - v2[0], v2[1], v2[6], v2[7], false); + v2[0], v2[1], v2[6], v2[7]); // Passing null for parameter leads to lazy determination of parameter // values in CurveLocation#getParameter() only once they are requested. if (point) addLocation(locations, curve1, null, point, curve2); } - return { statics: { + return { statics: /** @lends Curve */{ // We need to provide the original left curve reference to the // #getIntersections() calls as it is required to create the resulting // CurveLocation objects. @@ -1452,10 +1415,10 @@ new function() { // Scope for methods that require numerical integration // Determine the correct intersection method based on values of // linear1 & 2: (linear1 && linear2 - ? getLineLineIntersection + ? addLineIntersection : linear1 || linear2 - ? getCurveLineIntersections - : getCurveIntersections)(v1, v2, curve1, curve2, locations); + ? addCurveLineIntersections + : addCurveIntersections)(v1, v2, curve1, curve2, locations); return locations; } }}; diff --git a/src/path/CurveLocation.js b/src/path/CurveLocation.js index 197ae76c..0846a563 100644 --- a/src/path/CurveLocation.js +++ b/src/path/CurveLocation.js @@ -26,7 +26,7 @@ * {@link PathItem#getIntersections(path)}, * etc. */ -var CurveLocation = this.CurveLocation = Base.extend(/** @lends CurveLocation# */{ +var CurveLocation = Base.extend(/** @lends CurveLocation# */{ // DOCS: CurveLocation class description: add these back when the mentioned // functioned have been added: {@link Path#split(location)} /** @@ -36,7 +36,8 @@ var CurveLocation = this.CurveLocation = Base.extend(/** @lends CurveLocation# * * @param {Number} parameter * @param {Point} point */ - initialize: function(curve, parameter, point, _otherCurve, _distance) { + initialize: function CurveLocation(curve, parameter, point, _otherCurve, + _distance) { // Define this CurveLocation's unique id. this._id = CurveLocation._id = (CurveLocation._id || 0) + 1; this._curve = curve; diff --git a/src/path/Path.Constructors.js b/src/path/Path.Constructors.js index 16632ab0..a4c00d6f 100644 --- a/src/path/Path.Constructors.js +++ b/src/path/Path.Constructors.js @@ -274,7 +274,7 @@ Path.inject({ statics: new function() { var center = Point.readNamed(arguments, 'center'), radius = Base.readNamed(arguments, 'radius'); return createEllipse(new Rectangle(center.subtract(radius), - Size.create(radius * 2, radius * 2))) + new Size(radius * 2, radius * 2))) .set(Base.getNamed(arguments)); }, diff --git a/src/path/Path.js b/src/path/Path.js index de5afa2c..59de01c8 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -18,8 +18,7 @@ * @extends PathItem */ // DOCS: Explain that path matrix is always applied with each transformation. -var Path = this.Path = PathItem.extend(/** @lends Path# */{ - _class: 'Path', +var Path = PathItem.extend(/** @lends Path# */{ _serializeFields: { segments: [], closed: false @@ -67,10 +66,10 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{ * selected: true * }); */ - initialize: function(arg) { + initialize: function Path(arg) { this._closed = false; this._segments = []; - this.base(); + Item.call(this); // arg can either be an object literal describing properties to be set // on the path, a list of segments to be set, or the first of multiple // arguments describing separate segments. @@ -788,12 +787,12 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{ this.setSelected(selected); }, - setSelected: function(selected) { + setSelected: function setSelected(selected) { // Deselect all segments when path is marked as not selected if (!selected) this._selectSegments(false); // No need to pass true for noChildren since Path has none anyway. - this.base(selected); + setSelected.base.call(this, selected); }, _selectSegments: function(selected) { @@ -1982,13 +1981,13 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{ segment.setHandleIn(handleIn.subtract(segment._point)); if (i < n) { segment.setHandleOut( - Point.create(x[i], y[i]).subtract(segment._point)); + new Point(x[i], y[i]).subtract(segment._point)); if (i < n - 1) - handleIn = Point.create( + handleIn = new Point( 2 * knots[i + 1]._x - x[i + 1], 2 * knots[i + 1]._y - y[i + 1]); else - handleIn = Point.create( + handleIn = new Point( (knots[n]._x + x[n - 1]) / 2, (knots[n]._y + y[n - 1]) / 2); } @@ -2104,11 +2103,11 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{ // Construct the two perpendicular middle lines to (from, through) // and (through, to), and intersect them to get the center var l1 = new Line(from.add(through).divide(2), - through.subtract(from).rotate(90)), + through.subtract(from).rotate(90), true), l2 = new Line(through.add(to).divide(2), - to.subtract(through).rotate(90)), - center = l1.intersect(l2), - line = new Line(from, to, true), + to.subtract(through).rotate(90), true), + center = l1.intersect(l2, true), + line = new Line(from, to), throughSide = line.getSide(through); if (!center) { // If the two lines are colinear, there cannot be an arc as the @@ -2179,7 +2178,7 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{ throughVector = Point.read(throughVector); toVector = Point.read(toVector); var current = getCurrentSegment(this)._point; - this.arcBy(current.add(throughVector), current.add(toVector)); + this.arcTo(current.add(throughVector), current.add(toVector)); }, closePath: function() { @@ -2283,7 +2282,7 @@ statics: { processSegment(segments[i]); if (closed) processSegment(first); - return Rectangle.create(min[0], min[1], max[0] - min[0], max[1] - min[1]); + return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]); }, /** @@ -2305,8 +2304,8 @@ statics: { // Get rotated hor and ver vectors, and determine rotation angle // and elipse values from them: var mx = matrix.shiftless(), - hor = mx.transform(Point.create(radius, 0)), - ver = mx.transform(Point.create(0, radius)), + hor = mx.transform(new Point(radius, 0)), + ver = mx.transform(new Point(0, radius)), phi = hor.getAngleInRadians(), a = hor.getLength(), b = ver.getLength(); @@ -2389,10 +2388,10 @@ statics: { normal2 = curve2.getNormalAt(0, true).normalize(miterRadius), // Intersect the two lines line1 = new Line(point.add(normal1), - Point.create(-normal1.y, normal1.x)), + new Point(-normal1.y, normal1.x), true), line2 = new Line(point.add(normal2), - Point.create(-normal2.y, normal2.x)), - corner = line1.intersect(line2); + new Point(-normal2.y, normal2.x), true), + corner = line1.intersect(line2, true); // Now measure the distance from the segment to the // intersection, which his half of the miter distance if (!corner || point.getDistance(corner) > miterLimit) { @@ -2466,7 +2465,7 @@ statics: { if (yx > y2) y2 = yx; } } - return Rectangle.create(x1, y1, x2 - x1, y2 - y1); + return new Rectangle(x1, y1, x2 - x1, y2 - y1); }, /** diff --git a/src/path/PathItem.Boolean.js b/src/path/PathItem.Boolean.js index f77961b1..fbbafd6c 100644 --- a/src/path/PathItem.Boolean.js +++ b/src/path/PathItem.Boolean.js @@ -158,7 +158,7 @@ PathItem.inject(new function() { if (segment.getPrevious()._invalid) segment.setHandleIn(intersection ? intersection._handleIn - : Point.create(0, 0)); + : new Point(0, 0)); do { segment._visited = true; if (segment._invalid && segment._intersection) { diff --git a/src/path/PathItem.js b/src/path/PathItem.js index c2d51f30..0abd3a8e 100644 --- a/src/path/PathItem.js +++ b/src/path/PathItem.js @@ -19,7 +19,11 @@ * * @extends Item */ -var PathItem = this.PathItem = Item.extend(/** @lends PathItem# */{ +var PathItem = Item.extend(/** @lends PathItem# */{ + initialize: function PathItem() { + Item.apply(this, arguments); + }, + /** * Returns all intersections between two {@link PathItem} items as an array * of {@link CurveLocation} objects. {@link CompoundPath} items are also diff --git a/src/path/Segment.js b/src/path/Segment.js index b8e036eb..9ed40a7c 100644 --- a/src/path/Segment.js +++ b/src/path/Segment.js @@ -22,9 +22,7 @@ * {@link Segment#handleOut}), describing the tangents of the two {@link Curve} * objects that are connected by this segment. */ -var Segment = this.Segment = Base.extend(/** @lends Segment# */{ - _class: 'Segment', - +var Segment = Base.extend(/** @lends Segment# */{ /** * Creates a new Segment object. * @@ -110,7 +108,7 @@ var Segment = this.Segment = Base.extend(/** @lends Segment# */{ * path.strokeColor = 'black'; * @ignore */ - initialize: function(arg0, arg1, arg2, arg3, arg4, arg5) { + initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) { var count = arguments.length, createPoint = SegmentPoint.create, point, handleIn, handleOut; diff --git a/src/project/Project.js b/src/project/Project.js index 5f71d2fa..d7be6c20 100644 --- a/src/project/Project.js +++ b/src/project/Project.js @@ -30,7 +30,7 @@ * An array of all open projects is accessible through the * {@link PaperScope#projects} variable. */ -var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{ +var Project = PaperScopeItem.extend(/** @lends Project# */{ _list: 'projects', _reference: 'project', @@ -44,10 +44,10 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{ * @param {View|HTMLCanvasElement} view Either a view object or an HTML * Canvas element that should be wrapped in a newly created view. */ - initialize: function(view) { + initialize: function Project(view) { // Activate straight away by passing true to base(), so paper.project is // set, as required by Layer and DoumentView constructors. - this.base(true); + PaperScopeItem.call(this, true); this.layers = []; this.symbols = []; this._currentStyle = new Style(); @@ -69,12 +69,8 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{ // into the active project automatically. We might want to add proper // project serialization later, but deserialization of a layers array // will always work. - return Base.serialize(this.layers, options, false, dictionary); - }, - - _needsRedraw: function() { - if (this.view) - this.view._redrawNeeded = true; + // Pass true for compact, so 'Project' does not get added as the class + return Base.serialize(this.layers, options, true, dictionary); }, /** @@ -97,8 +93,8 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{ * Removes this project from the {@link PaperScope#projects} list, and also * removes its view, if one was defined. */ - remove: function() { - if (!this.base()) + remove: function remove() { + if (!remove.base.call(this)) return false; if (this.view) this.view.remove(); @@ -271,6 +267,7 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{ // DOCS: Figure out a way to group these together with importSVG / exportSVG importJSON: function(json) { + this.activate(); return Base.importJSON(json); }, diff --git a/src/project/Symbol.js b/src/project/Symbol.js index 30eda0ba..02fa7aa7 100644 --- a/src/project/Symbol.js +++ b/src/project/Symbol.js @@ -19,9 +19,7 @@ * internal properties such as segment lists and gradient positions don't need * to be updated with every transformation. */ -var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{ - _class: 'Symbol', - +var Symbol = Base.extend(/** @lends Symbol# */{ /** * Creates a Symbol item. * @@ -59,7 +57,7 @@ var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{ * instance.scale(0.25 + Math.random() * 0.75); * } */ - initialize: function(item, dontCenter) { + initialize: function Symbol(item, dontCenter) { // Define this Symbols's unique id. this._id = Symbol._id = (Symbol._id || 0) + 1; this.project = paper.project; @@ -72,7 +70,7 @@ var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{ _serialize: function(options, dictionary) { return dictionary.add(this, function() { - return Base.serialize([this._class, this._definition], + return Base.serialize([this.constructor.name, this._definition], options, false, dictionary); }); }, diff --git a/src/style/Color.js b/src/style/Color.js index 52e402e8..13ed0a8c 100644 --- a/src/style/Color.js +++ b/src/style/Color.js @@ -40,7 +40,7 @@ * // converted to a Color. * circle.fillColor = '#ff0000'; */ -var Color = this.Color = Base.extend(new function() { +var Color = Base.extend(new function() { var types = { gray: ['gray'], @@ -275,7 +275,6 @@ var Color = this.Color = Base.extend(new function() { }; }, this); }, /** @lends Color# */{ - _class: 'Color', // Tell Base.read that the Point constructor supports reading with index _readIndex: true, @@ -436,7 +435,7 @@ var Color = this.Color = Base.extend(new function() { * // 100% and a lightness of 50%: * circle.fillColor = { hue: 90, saturation: 1, lightness: 0.5 }; */ - initialize: function(arg) { + initialize: function Color(arg) { // We are storing color internally as an array of components var slice = Array.prototype.slice, args = arguments, @@ -503,7 +502,7 @@ var Color = this.Color = Base.extend(new function() { : nameToRGB(arg); type = 'rgb'; } else if (argType === 'object') { - if (arg._class === 'Color') { + if (arg.constructor === Color) { type = arg._type; components = arg._components.slice(); alpha = arg._alpha; @@ -516,7 +515,7 @@ var Color = this.Color = Base.extend(new function() { components[i] = point.clone(); } } - } else if (arg._class === 'Gradient') { + } else if (arg.constructor === Gradient) { type = 'gradient'; values = args; } else { diff --git a/src/style/Gradient.js b/src/style/Gradient.js index e135f28f..468b1676 100644 --- a/src/style/Gradient.js +++ b/src/style/Gradient.js @@ -59,11 +59,9 @@ * destination: path.bounds.rightCenter * }; */ -var Gradient = this.Gradient = Base.extend(/** @lends Gradient# */{ - _class: 'Gradient', - +var Gradient = Base.extend(/** @lends Gradient# */{ // DOCS: Document #initialize() - initialize: function(stops, radial) { + initialize: function Gradient(stops, radial) { // Define this Gradient's unique id. this._id = Gradient._id = (Gradient._id || 0) + 1; if (stops && this._set(stops)) diff --git a/src/style/GradientStop.js b/src/style/GradientStop.js index d3602a0d..d9da5437 100644 --- a/src/style/GradientStop.js +++ b/src/style/GradientStop.js @@ -16,7 +16,7 @@ * * @class The GradientStop object. */ -var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{ +var GradientStop = Base.extend(/** @lends GradientStop# */{ /** * Creates a GradientStop object. * @@ -24,7 +24,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{ * @param {Number} [rampPoint=0] the position of the stop on the gradient * ramp as a value between 0 and 1. */ - initialize: function(arg0, arg1) { + initialize: function GradientStop(arg0, arg1) { if (arg0) { var color, rampPoint; if (arg1 === undefined && Array.isArray(arg0)) { diff --git a/src/style/Style.js b/src/style/Style.js index b965dbb8..5267ba49 100644 --- a/src/style/Style.js +++ b/src/style/Style.js @@ -65,7 +65,7 @@ * }; * */ -var Style = this.Style = Base.extend(new function() { +var Style = Base.extend(new function() { // windingRule / resolution / fillOverprint / strokeOverprint are currently // not supported. var defaults = { @@ -201,7 +201,7 @@ var Style = this.Style = Base.extend(new function() { Item.inject(item); return fields; }, /** @lends Style# */{ - initialize: function(style) { + initialize: function Style(style) { // We keep values in a separate object that we can iterate over. this._values = {}; if (this._item instanceof TextItem) @@ -223,9 +223,9 @@ var Style = this.Style = Base.extend(new function() { } }, - getLeading: function() { + getLeading: function getLeading() { // Override leading to return fontSize * 1.2 by default. - var leading = this.base(); + var leading = getLeading.base.call(this); return leading != null ? leading : this.getFontSize() * 1.2; }, diff --git a/src/svg/SVGExport.js b/src/svg/SVGExport.js index c2743b9c..053173b0 100644 --- a/src/svg/SVGExport.js +++ b/src/svg/SVGExport.js @@ -122,10 +122,10 @@ new function() { if (handle1.isOrthogonal(handle2)) { var from = segment._point, to = next._point, - // Find hte corner point by intersecting the lines described + // Find the corner point by intersecting the lines described // by both handles: - corner = new Line(from, handle1).intersect( - new Line(to, handle2)); + corner = new Line(from, handle1, true).intersect( + new Line(to, handle2, true), true); return corner && Numerical.isZero(handle1.getLength() / corner.subtract(from).getLength() - kappa) && Numerical.isZero(handle2.getLength() / diff --git a/src/svg/SVGImport.js b/src/svg/SVGImport.js index e48c7f82..769b0463 100644 --- a/src/svg/SVGImport.js +++ b/src/svg/SVGImport.js @@ -44,14 +44,14 @@ new function() { x = getValue(node, x, false, allowNull); y = getValue(node, y, false, allowNull); return allowNull && x == null && y == null ? null - : Point.create(x || 0, y || 0); + : new Point(x || 0, y || 0); } function getSize(node, w, h, allowNull) { w = getValue(node, w, false, allowNull); h = getValue(node, h, false, allowNull); return allowNull && w == null && h == null ? null - : Size.create(w || 0, h || 0); + : new Size(w || 0, h || 0); } // Converts a string attribute value to the specified type @@ -383,7 +383,8 @@ new function() { 'stop-color': function(item, value) { // http://www.w3.org/TR/SVG/pservers.html#StopColorProperty - item.setColor(value); + if (item.setColor) + item.setColor(value); }, 'stop-opacity': function(item, value) { diff --git a/src/text/PointText.js b/src/text/PointText.js index 77617d98..b6fcded9 100644 --- a/src/text/PointText.js +++ b/src/text/PointText.js @@ -19,9 +19,7 @@ * * @extends TextItem */ -var PointText = this.PointText = TextItem.extend(/** @lends PointText# */{ - _class: 'PointText', - +var PointText = TextItem.extend(/** @lends PointText# */{ /** * Creates a point text item * @@ -43,6 +41,9 @@ var PointText = this.PointText = TextItem.extend(/** @lends PointText# */{ * fontSize: 25 * }); */ + initialize: function PointText() { + TextItem.apply(this, arguments); + }, clone: function() { return this._clone(new PointText()); @@ -109,7 +110,7 @@ var PointText = this.PointText = TextItem.extend(/** @lends PointText# */{ x -= width / (justification === 'center' ? 2: 1); // Until we don't have baseline measuring, assume leading / 4 as a // rough guess: - var bounds = Rectangle.create(x, + var bounds = new Rectangle(x, count ? leading / 4 + (count - 1) * leading : 0, width, -count * leading); return matrix ? matrix._transformBounds(bounds, bounds) : bounds; diff --git a/src/text/TextItem.js b/src/text/TextItem.js index 91986253..2cf907f6 100644 --- a/src/text/TextItem.js +++ b/src/text/TextItem.js @@ -21,7 +21,7 @@ * * @extends Item */ -var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{ +var TextItem = Item.extend(/** @lends TextItem# */{ _boundsSelected: true, _serializeFields: { content: null @@ -30,7 +30,7 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{ // so use the same name for all of them _boundsGetter: 'getBounds', - initialize: function(arg) { + initialize: function TextItem(arg) { // Support two forms of item initialization: Passing one object literal // describing all the different properties to be set, or a point where // it should be placed (arg). @@ -38,7 +38,7 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{ // might be a properties object literal for #setPropeties() at the end. var hasProperties = arg && Base.isPlainObject(arg) && arg.x === undefined && arg.y === undefined; - this.base(hasProperties ? null : Point.read(arguments)); + Item.call(this, hasProperties ? null : Point.read(arguments)); this._content = ''; this._lines = []; if (hasProperties) @@ -77,9 +77,9 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{ * } */ - _clone: function(copy) { + _clone: function _clone(copy) { copy.setContent(this._content); - return this.base(copy); + return _clone.base.call(this, copy); }, getContent: function() { diff --git a/src/tool/Tool.js b/src/tool/Tool.js index fbdc2dfb..17e3ed04 100644 --- a/src/tool/Tool.js +++ b/src/tool/Tool.js @@ -42,7 +42,7 @@ * path.add(event.point); * } */ -var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{ +var Tool = PaperScopeItem.extend(/** @lends Tool# */{ _list: 'tools', _reference: '_tool', // PaperScope has accessor for #tool _events: [ 'onActivate', 'onDeactivate', 'onEditOptions', @@ -50,8 +50,8 @@ var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{ 'onKeyDown', 'onKeyUp' ], // DOCS: rewrite Tool constructor explanation - initialize: function(props) { - this.base(); + initialize: function Tool(props) { + PaperScopeItem.call(this); this._firstMove = true; this._count = 0; this._downCount = 0; @@ -322,7 +322,7 @@ var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{ return true; }, - fire: function(type, event) { + fire: function fire(type, event) { // Override Callback#fire() so we can handle items marked in removeOn*() // calls first,. var sets = Tool._removeSets; @@ -346,7 +346,7 @@ var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{ sets[type] = null; } } - return this.base(type, event); + return fire.base.call(this, type, event); }, _onHandleEvent: function(type, point, event) { diff --git a/src/tool/ToolEvent.js b/src/tool/ToolEvent.js index 72c0fead..644ae70a 100644 --- a/src/tool/ToolEvent.js +++ b/src/tool/ToolEvent.js @@ -21,11 +21,11 @@ * * @extends Event */ -var ToolEvent = this.ToolEvent = Event.extend(/** @lends ToolEvent# */{ +var ToolEvent = Event.extend(/** @lends ToolEvent# */{ // Have ToolEvent#item fall back to returning null, not undefined. _item: null, - initialize: function(tool, type, event) { + initialize: function ToolEvent(tool, type, event) { this.tool = tool; this.type = type; this.event = event; diff --git a/src/ui/CanvasView.js b/src/ui/CanvasView.js index 077f2b1e..6e4aa8ed 100644 --- a/src/ui/CanvasView.js +++ b/src/ui/CanvasView.js @@ -22,19 +22,19 @@ var CanvasView = View.extend(/** @lends CanvasView# */{ * @param {HTMLCanvasElement} canvas The canvas object that this view should * wrap */ - initialize: function(canvas) { + initialize: function CanvasView(canvas) { // Handle canvas argument if (!(canvas instanceof HTMLCanvasElement)) { // 2nd argument onwards could be view size, otherwise use default: var size = Size.read(arguments, 1); if (size.isZero()) - size = Size.create(1024, 768); + size = new Size(1024, 768); canvas = CanvasProvider.getCanvas(size); } this._context = canvas.getContext('2d'); // Have Item count installed mouse events. this._eventCounters = {}; - this.base(canvas); + View.call(this, canvas); }, /** @@ -44,7 +44,7 @@ var CanvasView = View.extend(/** @lends CanvasView# */{ * @function */ draw: function(checkRedraw) { - if (checkRedraw && !this._redrawNeeded) + if (checkRedraw && !this._project._needsRedraw) return false; // Initial tests conclude that clearing the canvas using clearRect // is always faster than setting canvas.width = canvas.width @@ -53,7 +53,7 @@ var CanvasView = View.extend(/** @lends CanvasView# */{ size = this._viewSize; ctx.clearRect(0, 0, size._width + 1, size._height + 1); this._project.draw(ctx, this._matrix); - this._redrawNeeded = false; + this._project._needsRedraw = false; return true; } }, new function() { // Item based mouse handling: @@ -169,8 +169,8 @@ var CanvasView = View.extend(/** @lends CanvasView# */{ }; }); -/*#*/ if (options.server) { -// Node.js server based image exporting code. +/*#*/ if (options.node) { +// Node.js based image exporting code. CanvasView.inject(new function() { // Utility function that converts a number to a string with // x amount of padded 0 digits: @@ -252,4 +252,4 @@ CanvasView.inject(new function() { } }; }); -/*#*/ } // options.server +/*#*/ } // options.node diff --git a/src/ui/Component.js b/src/ui/Component.js index 845df744..1ceda35b 100644 --- a/src/ui/Component.js +++ b/src/ui/Component.js @@ -14,7 +14,7 @@ * @name Component * @class */ -var Component = this.Component = Base.extend(Callback, /** @lends Component# */{ +var Component = Base.extend(Callback, /** @lends Component# */{ _events: [ 'onChange', 'onClick' ], _types: { @@ -58,7 +58,7 @@ var Component = this.Component = Base.extend(Callback, /** @lends Component# */{ } }, - initialize: function(obj) { + initialize: function Component(obj) { this._type = obj.type in this._types ? obj.type : 'options' in obj diff --git a/src/ui/Event.js b/src/ui/Event.js index 0001c7db..e4d38e5d 100644 --- a/src/ui/Event.js +++ b/src/ui/Event.js @@ -14,8 +14,8 @@ * @name Event * @class */ -var Event = this.Event = Base.extend(/** @lends Event# */{ - initialize: function(event) { +var Event = Base.extend(/** @lends Event# */{ + initialize: function Event(event) { this.event = event; }, diff --git a/src/ui/Key.js b/src/ui/Key.js index 9332f2f0..da9e5609 100644 --- a/src/ui/Key.js +++ b/src/ui/Key.js @@ -14,7 +14,7 @@ * @name Key * @namespace */ -var Key = this.Key = new function() { +var Key = new function() { // TODO: Make sure the keys are called the same as in Scriptographer // Missing: tab, cancel, clear, page-down, page-up, comma, minus, period, // slash, etc etc etc. diff --git a/src/ui/KeyEvent.js b/src/ui/KeyEvent.js index c1dcecec..a38f2efb 100644 --- a/src/ui/KeyEvent.js +++ b/src/ui/KeyEvent.js @@ -20,9 +20,9 @@ * * @extends Event */ -var KeyEvent = this.KeyEvent = Event.extend(/** @lends KeyEvent# */{ - initialize: function(down, key, character, event) { - this.base(event); +var KeyEvent = Event.extend(/** @lends KeyEvent# */{ + initialize: function KeyEvent(down, key, character, event) { + Event.call(this, event); this.type = down ? 'keydown' : 'keyup'; this.key = key; this.character = character; diff --git a/src/ui/MouseEvent.js b/src/ui/MouseEvent.js index a520e51b..64f32684 100644 --- a/src/ui/MouseEvent.js +++ b/src/ui/MouseEvent.js @@ -22,9 +22,9 @@ * * @extends Event */ -var MouseEvent = this.MouseEvent = Event.extend(/** @lends MouseEvent# */{ - initialize: function(type, event, point, target, delta) { - this.base(event); +var MouseEvent = Event.extend(/** @lends MouseEvent# */{ + initialize: function MouseEvent(type, event, point, target, delta) { + Event.call(this, event); this.type = type; this.point = point; this.target = target; diff --git a/src/ui/Palette.js b/src/ui/Palette.js index f2cbb936..bc1f888a 100644 --- a/src/ui/Palette.js +++ b/src/ui/Palette.js @@ -14,10 +14,10 @@ * @name Palette * @class */ -var Palette = this.Palette = Base.extend(Callback, /** @lends Palette# */{ +var Palette = Base.extend(Callback, /** @lends Palette# */{ _events: [ 'onChange' ], - initialize: function(title, components, values) { + initialize: function Palette(title, components, values) { var parent = DomElement.find('.palettejs-panel') || DomElement.find('body').appendChild( DomElement.create('div', { 'class': 'palettejs-panel' })); @@ -49,7 +49,6 @@ var Palette = this.Palette = Base.extend(Callback, /** @lends Palette# */{ Base.define(values, name, { enumerable: true, configurable: true, - writable: true, get: function() { return component._value; }, diff --git a/src/ui/View.js b/src/ui/View.js index ea3307f5..8be7b943 100644 --- a/src/ui/View.js +++ b/src/ui/View.js @@ -19,8 +19,8 @@ * center, both useful for constructing artwork that should appear centered on * screen. */ -var View = this.View = Base.extend(Callback, /** @lends View# */{ - initialize: function(element) { +var View = Base.extend(Callback, /** @lends View# */{ + initialize: function View(element) { // Store reference to the currently active global paper scope, and the // active project, which will be represented by this view this._scope = paper; @@ -60,7 +60,7 @@ var View = this.View = Base.extend(Callback, /** @lends View# */{ // If the element is invisible, we cannot directly access // element.width / height, because they would appear 0. // Reading the attributes still works. - size = Size.create(parseInt(element.getAttribute('width'), 10), + size = new Size(parseInt(element.getAttribute('width'), 10), parseInt(element.getAttribute('height'), 10)); // If no size was specified on the canvas, read it from CSS if (size.isNaN()) @@ -83,11 +83,11 @@ var View = this.View = Base.extend(Callback, /** @lends View# */{ style.top = offset.y + 'px'; document.body.appendChild(stats); } -/*#*/ } else if (options.server) { +/*#*/ } else if (options.node) { // Generate an id for this view this._id = 'view-' + View._id++; - size = Size.create(element.width, element.height); -/*#*/ } // options.server + size = new Size(element.width, element.height); +/*#*/ } // options.node // Keep track of views internally View._views.push(this); // Link this id to our view @@ -235,7 +235,7 @@ var View = this.View = Base.extend(Callback, /** @lends View# */{ }, _redraw: function() { - this._redrawNeeded = true; + this._project._needsRedraw = true; if (this._handlingFrame) return; if (this._animate) { diff --git a/src/util/Formatter.js b/src/util/Formatter.js index d9261d1a..d26069b5 100644 --- a/src/util/Formatter.js +++ b/src/util/Formatter.js @@ -30,6 +30,8 @@ var Formatter = Base.extend({ * @param {Number} num the number to be converted to a string */ number: function(val) { + // It would be nice to use Number#toFixed() instead, but it pads with 0, + // unecessarily consuming space. return Math.round(val * this.multiplier) / this.multiplier; }, diff --git a/src/util/Numerical.js b/src/util/Numerical.js index 08d44bda..db04302a 100644 --- a/src/util/Numerical.js +++ b/src/util/Numerical.js @@ -10,7 +10,7 @@ * All rights reserved. */ -var Numerical = this.Numerical = new function() { +var Numerical = new function() { // Lookup tables for abscissas and weights with values for n = 2 .. 16. // As values are symetric, only store half of them and addapt algorithm