diff --git a/src/index.html b/src/index.html
index d46f663..eb64780 100644
--- a/src/index.html
+++ b/src/index.html
@@ -64,6 +64,17 @@
fill: #cbcbba;
}
+ .subexp .subexp-label {
+ font-size: 10px;
+ }
+
+ .subexp .subexp-outline {
+ stroke: #a0a0a0;
+ stroke-dasharray: 6,2;
+ stroke-width: 2px;
+ fill: transparent;
+ }
+
.placeholder text {
fill: #fff;
font-weight: bold;
diff --git a/src/js/parser/javascript/grammar.peg b/src/js/parser/javascript/grammar.peg
index 490d844..8e803cb 100644
--- a/src/js/parser/javascript/grammar.peg
+++ b/src/js/parser/javascript/grammar.peg
@@ -16,7 +16,7 @@ grammar JavascriptRegexp
/ "{" _min:[0-9]+ ",}"
/ "{" _exact:[0-9]+ "}" )
repeat_greedy <- "?"
- subexp <- "(" ( subexp_no_capture / subexp_positive_lookahead / subexp_negative_lookahead )? regexp ")"
+ subexp <- "(" _capture:( subexp_no_capture / subexp_positive_lookahead / subexp_negative_lookahead )? regexp ")"
subexp_no_capture <- "?:"
subexp_positive_lookahead <- "?="
subexp_negative_lookahead <- "?!"
diff --git a/src/js/parser/javascript/subexp.js b/src/js/parser/javascript/subexp.js
index 8e7a429..d6a64c0 100644
--- a/src/js/parser/javascript/subexp.js
+++ b/src/js/parser/javascript/subexp.js
@@ -2,5 +2,67 @@ import _ from 'lodash';
import Base from './base.js';
export default _.extend({}, Base, {
- type: 'subexp'
+ type: 'subexp',
+
+ labelMap: {
+ '?:': '',
+ '?=': 'positive lookahead',
+ '?!': 'negative lookahead'
+ },
+
+ render() {
+ var label = this.groupLabel();
+
+ if (label) {
+ this.container.addClass('subexp');
+
+ this.label = this.container.text()
+ .addClass('subexp-label')
+ .attr({
+ text: label
+ });
+
+ this.outline = this.container.rect()
+ .addClass('subexp-outline')
+ .attr({
+ rx: 3,
+ ry: 3
+ });
+
+ this.regexp.container = this.container.group().transform(Snap.matrix()
+ .translate(10, 10));
+ this.regexp.render();
+ } else {
+ this.regexp.container = this.container;
+ this.regexp.render();
+ }
+ },
+
+ position() {
+ var box;
+
+ this.regexp.position();
+
+ if (this.outline) {
+ box = this.regexp.container.getBBox();
+
+ this.outline.attr({
+ width: box.width + 20,
+ height: box.height + 20
+ });
+
+ this.container.path(Snap.format('M0,{content.cy}h10M{content.x2},{content.cy}H{container.x2}', {
+ container: this.container.getBBox(),
+ content: box
+ }));
+ }
+ },
+
+ groupLabel() {
+ if (_.has(this.labelMap, this._capture.textValue)) {
+ return this.labelMap[this._capture.textValue];
+ } else {
+ return 'group #TBA';
+ }
+ }
});