diff --git a/spec/parser/javascript/match_fragment_spec.js b/spec/parser/javascript/match_fragment_spec.js index 2ae23b4..7b280e2 100644 --- a/spec/parser/javascript/match_fragment_spec.js +++ b/spec/parser/javascript/match_fragment_spec.js @@ -77,11 +77,11 @@ describe('parser/javascript/match_fragment.js', function() { this.node.content.render.and.returnValue(this.renderDeferred.promise); this.node.repeat = { - contentPosition: 'example position' + contentPosition: 'example position', + skipPath: jasmine.createSpy('skipPath').and.returnValue('skip path'), + loopPath: jasmine.createSpy('loopPath').and.returnValue('loop path') }; - spyOn(this.node, 'skipPath').and.returnValue('skip path'); - spyOn(this.node, 'loopPath').and.returnValue('loop path'); spyOn(this.node, 'loopLabel'); }); @@ -107,8 +107,8 @@ describe('parser/javascript/match_fragment.js', function() { it('renders a skip path and loop path', function(done) { this.node._render() .then(() => { - expect(this.node.skipPath).toHaveBeenCalledWith('content bbox'); - expect(this.node.loopPath).toHaveBeenCalledWith('content bbox'); + expect(this.node.repeat.skipPath).toHaveBeenCalledWith('content bbox'); + expect(this.node.repeat.loopPath).toHaveBeenCalledWith('content bbox'); expect(this.node.container.path).toHaveBeenCalledWith('skip pathloop path'); done(); }); @@ -126,85 +126,6 @@ describe('parser/javascript/match_fragment.js', function() { }); - describe('#skipPath', function() { - - beforeEach(function() { - this.node = new javascript.Parser('a').__consume__match_fragment(); - - this.node.repeat = {}; - - this.box = { - y: 11, - ay: 22, - width: 33 - }; - }); - - it('returns nothing when there is no skip', function() { - this.node.repeat.hasSkip = false; - expect(this.node.skipPath(this.box)).toEqual([]); - }); - - it('returns a path when there is a skip', function() { - this.node.repeat.hasSkip = true; - this.node.repeat.greedy = true; - expect(this.node.skipPath(this.box)).toEqual([ - 'M0,22q10,0 10,-10v-1q0,-10 10,-10h23q10,0 10,10v1q0,10 10,10' - ]); - }); - - it('returns a path with arrow when there is a non-greedy skip', function() { - this.node.repeat.hasSkip = true; - this.node.repeat.greedy = false; - expect(this.node.skipPath(this.box)).toEqual([ - 'M0,22q10,0 10,-10v-1q0,-10 10,-10h23q10,0 10,10v1q0,10 10,10', - 'M10,7l5,5m-5,-5l-5,5' - ]); - }); - - - }); - - describe('#loopPath', function() { - - beforeEach(function() { - this.node = new javascript.Parser('a').__consume__match_fragment(); - - this.node.repeat = {}; - - this.box = { - x: 11, - x2: 22, - ay: 33, - y2: 44, - width: 55 - }; - }); - - it('returns nothing when there is no loop', function() { - this.node.repeat.hasLoop = false; - expect(this.node.loopPath(this.box)).toEqual([]); - }); - - it('returns a path when there is a loop', function() { - this.node.repeat.hasLoop = true; - this.node.repeat.greedy = false; - expect(this.node.loopPath(this.box)).toEqual([ - 'M11,33q-10,0 -10,10v1q0,10 10,10h55q10,0 10,-10v-1q0,-10 -10,-10' - ]); - }); - - it('returns a path with arrow when there is a greedy loop', function() { - this.node.repeat.hasLoop = true; - this.node.repeat.greedy = true; - expect(this.node.loopPath(this.box)).toEqual([ - 'M11,33q-10,0 -10,10v1q0,10 10,10h55q10,0 10,-10v-1q0,-10 -10,-10', - 'M32,48l5,-5m-5,5l-5,-5' - ]); - }); - - }); - describe('#loopLabel', function() { beforeEach(function() { diff --git a/spec/parser/javascript/repeat_spec.js b/spec/parser/javascript/repeat_spec.js index da7cbea..fa803de 100644 --- a/spec/parser/javascript/repeat_spec.js +++ b/spec/parser/javascript/repeat_spec.js @@ -253,4 +253,78 @@ describe('parser/javascript/repeat.js', function() { }); + describe('#skipPath', function() { + + beforeEach(function() { + this.node = new javascript.Parser('*').__consume__repeat(); + + this.box = { + y: 11, + ay: 22, + width: 33 + }; + }); + + it('returns nothing when there is no skip', function() { + this.node.hasSkip = false; + expect(this.node.skipPath(this.box)).toEqual([]); + }); + + it('returns a path when there is a skip', function() { + this.node.hasSkip = true; + this.node.greedy = true; + expect(this.node.skipPath(this.box)).toEqual([ + 'M0,22q10,0 10,-10v-1q0,-10 10,-10h23q10,0 10,10v1q0,10 10,10' + ]); + }); + + it('returns a path with arrow when there is a non-greedy skip', function() { + this.node.hasSkip = true; + this.node.greedy = false; + expect(this.node.skipPath(this.box)).toEqual([ + 'M0,22q10,0 10,-10v-1q0,-10 10,-10h23q10,0 10,10v1q0,10 10,10', + 'M10,7l5,5m-5,-5l-5,5' + ]); + }); + + }); + + describe('#loopPath', function() { + + beforeEach(function() { + this.node = new javascript.Parser('*').__consume__repeat(); + + this.box = { + x: 11, + x2: 22, + ay: 33, + y2: 44, + width: 55 + }; + }); + + it('returns nothing when there is no loop', function() { + this.node.hasLoop = false; + expect(this.node.loopPath(this.box)).toEqual([]); + }); + + it('returns a path when there is a loop', function() { + this.node.hasLoop = true; + this.node.greedy = false; + expect(this.node.loopPath(this.box)).toEqual([ + 'M11,33q-10,0 -10,10v1q0,10 10,10h55q10,0 10,-10v-1q0,-10 -10,-10' + ]); + }); + + it('returns a path with arrow when there is a greedy loop', function() { + this.node.hasLoop = true; + this.node.greedy = true; + expect(this.node.loopPath(this.box)).toEqual([ + 'M11,33q-10,0 -10,10v1q0,10 10,10h55q10,0 10,-10v-1q0,-10 -10,-10', + 'M32,48l5,-5m-5,5l-5,-5' + ]); + }); + + }); + }); diff --git a/src/js/parser/javascript/match_fragment.js b/src/js/parser/javascript/match_fragment.js index e200613..cd23ecb 100644 --- a/src/js/parser/javascript/match_fragment.js +++ b/src/js/parser/javascript/match_fragment.js @@ -38,8 +38,8 @@ export default { // Add skip or repeat paths to the container. paths = _.flatten([ - this.skipPath(box), - this.loopPath(box) + this.repeat.skipPath(box), + this.repeat.loopPath(box) ]); this.container.prepend( @@ -49,45 +49,6 @@ export default { }); }, - // Returns the path spec to render the line that skips over the content for - // fragments that are optionally matched. - skipPath(box) { - var paths = []; - - if (this.repeat.hasSkip) { - let vert = Math.max(0, box.ay - box.y - 10), - horiz = box.width - 10; - - paths.push(`M0,${box.ay}q10,0 10,-10v${-vert}q0,-10 10,-10h${horiz}q10,0 10,10v${vert}q0,10 10,10`); - - // When the repeat is not greedy, the skip path gets a preference arrow. - if (!this.repeat.greedy) { - paths.push(`M10,${box.ay - 15}l5,5m-5,-5l-5,5`); - } - } - - return paths; - }, - - // Returns the path spec to render the line that repeats the content for - // fragments that are matched more than once. - loopPath(box) { - var paths = []; - - if (this.repeat.hasLoop) { - let vert = box.y2 - box.ay - 10; - - paths.push(`M${box.x},${box.ay}q-10,0 -10,10v${vert}q0,10 10,10h${box.width}q10,0 10,-10v${-vert}q0,-10 -10,-10`); - - // When the repeat is greedy, the loop path gets the preference arrow. - if (this.repeat.greedy) { - paths.push(`M${box.x2 + 10},${box.ay + 15}l5,-5m-5,5l-5,-5`); - } - } - - return paths; - }, - // Renders label for the loop path indicating how many times the content may // be matched. loopLabel() { diff --git a/src/js/parser/javascript/repeat.js b/src/js/parser/javascript/repeat.js index c201e9e..e753d02 100644 --- a/src/js/parser/javascript/repeat.js +++ b/src/js/parser/javascript/repeat.js @@ -47,6 +47,45 @@ export default { } }, + // Returns the path spec to render the line that skips over the content for + // fragments that are optionally matched. + skipPath(box) { + var paths = []; + + if (this.hasSkip) { + let vert = Math.max(0, box.ay - box.y - 10), + horiz = box.width - 10; + + paths.push(`M0,${box.ay}q10,0 10,-10v${-vert}q0,-10 10,-10h${horiz}q10,0 10,10v${vert}q0,10 10,10`); + + // When the repeat is not greedy, the skip path gets a preference arrow. + if (!this.greedy) { + paths.push(`M10,${box.ay - 15}l5,5m-5,-5l-5,5`); + } + } + + return paths; + }, + + // Returns the path spec to render the line that repeats the content for + // fragments that are matched more than once. + loopPath(box) { + var paths = []; + + if (this.hasLoop) { + let vert = box.y2 - box.ay - 10; + + paths.push(`M${box.x},${box.ay}q-10,0 -10,10v${vert}q0,10 10,10h${box.width}q10,0 10,-10v${-vert}q0,-10 -10,-10`); + + // When the repeat is greedy, the loop path gets the preference arrow. + if (this.greedy) { + paths.push(`M${box.x2 + 10},${box.ay + 15}l5,-5m-5,5l-5,-5`); + } + } + + return paths; + }, + setup() { this.minimum = this.properties.spec.minimum; this.maximum = this.properties.spec.maximum;