Merge branch 'matrix'
diff --git a/Makefile b/Makefile
index b8d12ef..906bfa0 100644
--- a/Makefile
+++ b/Makefile
@@ -140,6 +140,7 @@
$(SED_IN_PLACE) s/{VERSION}/v$(VERSION)/ $@
$(NODE_MODULES_INSTALLED): package.json
+ test -e $(NODE_MODULES_INSTALLED) || rm -rf ./node_modules/ # robust against previous botched npm install
NODE_ENV=development npm install
touch $(NODE_MODULES_INSTALLED)
diff --git a/docs/Api_Methods.md b/docs/Api_Methods.md
index b7db00c..a776774 100644
--- a/docs/Api_Methods.md
+++ b/docs/Api_Methods.md
@@ -190,7 +190,7 @@
Move the cursor to the left/right end of the editable field, respectively. These are shorthand for [`.moveToDirEnd(L/R)`](#movetodirenddirection), respectively.
-## .movetoDirEnd(direction)
+## .moveToDirEnd(direction)
Moves the cursor to the end of the mathfield in the direction specified. The direction can be one of `MQ.L` or `MQ.R`. These are constants, where `MQ.L === -MQ.R` and vice versa. This function may be easier to use than [moveToLeftEnd or moveToRightEnd](#movetoleftend-movetorightend) if used in the [`moveOutOf` handler](Config.md#outof-handlers).
diff --git a/script/screenshots.js b/script/screenshots.js
index 63d9374..547669b 100644
--- a/script/screenshots.js
+++ b/script/screenshots.js
@@ -116,8 +116,8 @@
.spread(function(scrollHeight, viewportHeight) {
console.log(sessionName, 'get scrollHeight, clientHeight', scrollHeight, viewportHeight);
- // the easy case: Firefox and IE return a screenshot of the entire webpage
- if (cfg.browserName === 'Firefox' || cfg.browserName === 'Internet Explorer') {
+ // the easy case: IE and Firefox on Linux return a screenshot of the entire webpage
+ if (cfg.browserName === 'Internet Explorer'|| (cfg.browserName === 'Firefox' && cfg.platform === 'Linux')) {
return browserDriver.saveScreenshot(baseDir + '/imgs/' + fileName + '.png')
.then(willLog(sessionName, 'saveScreenshot'))
// the hard case: for Chrome, Safari, and Edge, scroll through the page and
diff --git a/src/commands/math/LatexCommandInput.js b/src/commands/math/LatexCommandInput.js
index 4382041..bae3718 100644
--- a/src/commands/math/LatexCommandInput.js
+++ b/src/commands/math/LatexCommandInput.js
@@ -33,7 +33,7 @@
if (ch.match(/[a-z]/i)) VanillaSymbol(ch).createLeftOf(cursor);
else {
this.parent.renderCommand(cursor);
- if (ch !== '\\' || !this.isEmpty()) this.parent.parent.write(cursor, ch);
+ if (ch !== '\\' || !this.isEmpty()) cursor.parent.write(cursor, ch);
}
};
this.ends[L].keystroke = function(key, e, ctrlr) {
diff --git a/src/commands/math/commands.js b/src/commands/math/commands.js
index ae35e48..3e7eb7a 100644
--- a/src/commands/math/commands.js
+++ b/src/commands/math/commands.js
@@ -81,6 +81,8 @@
LatexCmds.overline = LatexCmds.bar = bind(Style, '\\overline', 'span', 'class="mq-non-leaf mq-overline"');
LatexCmds.overrightarrow = bind(Style, '\\overrightarrow', 'span', 'class="mq-non-leaf mq-overarrow mq-arrow-right"');
LatexCmds.overleftarrow = bind(Style, '\\overleftarrow', 'span', 'class="mq-non-leaf mq-overarrow mq-arrow-left"');
+LatexCmds.overleftrightarrow = bind(Style, '\\overleftrightarrow', 'span', 'class="mq-non-leaf mq-overarrow mq-arrow-both"');
+LatexCmds.overarc = bind(Style, '\\overarc', 'span', 'class="mq-non-leaf mq-overarc"');
LatexCmds.dot = P(MathCommand, function(_, super_) {
_.init = function() {
super_.init.call(this, '\\dot', '<span class="mq-non-leaf"><span class="mq-dot-recurring-inner">'
@@ -328,6 +330,15 @@
this.sup.downOutOf = insLeftOfMeUnlessAtEnd;
super_.finalizeTree.call(this);
};
+ _.reflow = function() {
+ var $block = this.jQ;//mq-supsub
+
+ var h = $block.prev().innerHeight() ;
+ h *= 0.6 ;
+
+ $block.css( 'vertical-align', h + 'px' ) ;
+
+ } ;
});
var SummationNotation = P(MathCommand, function(_, super_) {
diff --git a/src/commands/text.js b/src/commands/text.js
index 59614ee..5af2946 100644
--- a/src/commands/text.js
+++ b/src/commands/text.js
@@ -65,7 +65,7 @@
_.latex = function() {
var contents = this.textContents();
if (contents.length === 0) return '';
- return '\\text{' + contents + '}';
+ return '\\text{' + contents.replace(/\\/g, '\\backslash ').replace(/[{}]/g, '\\$&') + '}';
};
_.html = function() {
return (
diff --git a/src/css/font.less b/src/css/font.less
index 6c7b1dc..234b162 100644
--- a/src/css/font.less
+++ b/src/css/font.less
@@ -1,4 +1,4 @@
-@omit-font-face:;
+@omit-font-face:~"";
.font-face;
.font-face() when not (@omit-font-face) {
@font-face {
@@ -7,7 +7,7 @@
}
}
-@basic:;
+@basic:~"";
.font-srcs() when not (@basic) {
src: url(fonts/Symbola.eot);
src:
diff --git a/src/css/math.less b/src/css/math.less
index b27a3ab..f170de6 100644
--- a/src/css/math.less
+++ b/src/css/math.less
@@ -350,10 +350,24 @@
font-family: @symbola;
}
+ .mq-overarc {
+ border-top: 1px solid black;
+ -webkit-border-top-right-radius: 50% .3em;
+ -moz-border-radius-topright: 50% .3em;
+ border-top-right-radius: 50% .3em;
+ -webkit-border-top-left-radius: 50% .3em;
+ -moz-border-radius-topleft: 50% .3em;
+ border-top-left-radius: 50% .3em;
+ margin-top: 1px;
+ padding-top: 0.15em;
+ }
+
.mq-overarrow {
+ min-width: .5em;
border-top: 1px solid black;
margin-top: 1px;
padding-top: 0.2em;
+ text-align: center;
&:before {
display: block;
@@ -372,6 +386,35 @@
filter: FlipH;
-ms-filter: "FlipH";
}
+ &.mq-arrow-both {
+ vertical-align: text-bottom;
+
+ &.mq-empty {
+ min-height: 1.23em;
+
+ &:after {
+ top: -0.34em;
+ }
+ }
+ &:before{
+ -moz-transform: scaleX(-1);
+ -o-transform: scaleX(-1);
+ -webkit-transform: scaleX(-1);
+ transform: scaleX(-1);
+ filter: FlipH;
+ -ms-filter: "FlipH";
+ }
+ &:after {
+ display: block;
+ position: relative;
+ top: -2.3em;
+ font-size: 0.5em;
+ line-height: 0em;
+ content: '\27A4';
+ visibility: visible; //must override .mq-editable-field.mq-empty:after
+ text-align: right;
+ }
+ }
}
.mq-matrix {
diff --git a/src/publicapi.js b/src/publicapi.js
index d3d1ab3..c8fedf4 100644
--- a/src/publicapi.js
+++ b/src/publicapi.js
@@ -160,6 +160,15 @@
if (this.__controller.blurred) this.__controller.cursor.hide().parent.blur();
return this;
};
+ _.empty = function() {
+ var root = this.__controller.root, cursor = this.__controller.cursor;
+ root.eachChild('postOrder', 'dispose');
+ root.ends[L] = root.ends[R] = 0;
+ root.jQ.empty();
+ delete cursor.selection;
+ cursor.insAtRightEnd(root);
+ return this;
+ };
_.cmd = function(cmd) {
var ctrlr = this.__controller.notify(), cursor = ctrlr.cursor;
if (/^\\[a-z]+$/i.test(cmd)) {
diff --git a/src/services/keystroke.js b/src/services/keystroke.js
index fc3fc8e..a53cb5a 100644
--- a/src/services/keystroke.js
+++ b/src/services/keystroke.js
@@ -241,11 +241,15 @@
_.ctrlDeleteDir = function(dir) {
prayDirection(dir);
var cursor = this.cursor;
- if (!cursor[L] || cursor.selection) return this.deleteDir();
+ if (!cursor[dir] || cursor.selection) return this.deleteDir(dir);
this.notify('edit');
- Fragment(cursor.parent.ends[L], cursor[L]).remove();
- cursor.insAtDirEnd(L, cursor.parent);
+ if (dir === L) {
+ Fragment(cursor.parent.ends[L], cursor[L]).remove();
+ } else {
+ Fragment(cursor[R], cursor.parent.ends[R]).remove();
+ };
+ cursor.insAtDirEnd(dir, cursor.parent);
if (cursor[L].siblingDeleted) cursor[L].siblingDeleted(cursor.options, R);
if (cursor[R].siblingDeleted) cursor[R].siblingDeleted(cursor.options, L);
diff --git a/test/unit/publicapi.test.js b/test/unit/publicapi.test.js
index 4395cc8..f980855 100644
--- a/test/unit/publicapi.test.js
+++ b/test/unit/publicapi.test.js
@@ -108,7 +108,7 @@
mq.latex('x+y');
assert.equal(mq.html(), '<var>x</var><span class="mq-binary-operator">+</span><var>y</var>');
});
-
+
test('.text() with incomplete commands', function() {
assert.equal(mq.text(), '');
mq.typedText('\\');
@@ -157,6 +157,12 @@
assert.equal(mq.__controller.cursor[L].ctrlSeq, '0');
assert.equal(mq.__controller.cursor[R], 0);
});
+
+ test('.empty()', function() {
+ mq.latex('xyz');
+ mq.empty();
+ assert.equal(mq.latex(), '');
+ });
});
test('edit handler interface versioning', function() {
@@ -515,7 +521,7 @@
});
test('backslashes', function() {
assertPaste('something \\pi something \\asdf',
- '\\text{something \\pi something \\asdf}');
+ '\\text{something \\backslash pi something \\backslash asdf}');
});
// TODO: braces (currently broken)
test('actual math LaTeX wrapped in dollar signs', function() {
diff --git a/test/unit/typing.test.js b/test/unit/typing.test.js
index 7e8a400..bcc073f 100644
--- a/test/unit/typing.test.js
+++ b/test/unit/typing.test.js
@@ -57,6 +57,11 @@
mq.typedText('$');
assertLatex('\\$');
});
+
+ test('\\text followed by command', function() {
+ mq.typedText('\\text{');
+ assertLatex('\\text{\\{}');
+ });
});
suite('auto-expanding parens', function() {
@@ -472,6 +477,26 @@
assertLatex('\\left(1+2\\right)+3+4+5');
});
+ test('typing Ctrl-Backspace deletes everything to the left of the cursor', function () {
+ mq.typedText('12345');
+ assertLatex('12345');
+ mq.keystroke('Left Left');
+ mq.keystroke('Ctrl-Backspace');
+ assertLatex('45');
+ mq.keystroke('Ctrl-Backspace');
+ assertLatex('45');
+ });
+
+ test('typing Ctrl-Del deletes everything to the right of the cursor', function () {
+ mq.typedText('12345');
+ assertLatex('12345');
+ mq.keystroke('Left Left');
+ mq.keystroke('Ctrl-Del');
+ assertLatex('123');
+ mq.keystroke('Ctrl-Del');
+ assertLatex('123');
+ });
+
suite('pipes', function() {
test('typing then backspacing a pipe in the middle of 1+2+3+4', function() {
mq.typedText('1+2+3+4');
diff --git a/test/visual.html b/test/visual.html
index 42a9684..d8518b7 100644
--- a/test/visual.html
+++ b/test/visual.html
@@ -212,7 +212,15 @@
<tr><td><span class="mathquill-static-math">\vec x + \tilde x + \vec A + \tilde A + \vec{abcd} + \tilde{abcd}</span><td><span>\vec x + \tilde x + \vec A + \tilde A + \vec{abcd} + \tilde{abcd}</span>^M
<tr><td><span class="mathquill-static-math">\int _{\phi =0}^{2\pi }\int _{\theta =0}^{\pi }\int _{r=0}^{\infty }f(r,\theta ,\phi )r^2\sin \theta drd\theta d\phi </span><td><span>\int _{\phi =0}^{2\pi }\int _{\theta =0}^{\pi }\int _{r=0}^{\infty }f(r,\theta ,\phi )r^2\sin \theta drd\theta d\phi </span>
<tr><td><span class="mathquill-static-math">\int_0^{\frac{\frac{1}{2}}{3}} \int_0^{\frac{1}{\frac{2}{3}}} \int_0^{\frac{1}{\frac{2}{\frac{3}{\frac{4}{5}}}}}</span><td><span>\int_0^{\frac{\frac{1}{2}}{3}} \int_0^{\frac{1}{\frac{2}{3}}} \int_0^{\frac{1}{\frac{2}{\frac{3}{\frac{4}{5}}}}}</span>
+<<<<<<< HEAD
+<tr><td><span class="mathquill-static-math">\overline{abc}</span><td><span>\overline{abc}</span>
+<tr><td><span class="mathquill-static-math">\overleftarrow{abc}</span><td><span>\overleftarrow{abc}</span>
+<tr><td><span class="mathquill-static-math">\overrightarrow{abc}</span><td><span>\overrightarrow{abc}</span>
+<tr><td><span class="mathquill-static-math">\overleftrightarrow{abc}</span><td><span>\overleftrightarrow{abc}</span>
+<tr><td><span class="mathquill-static-math">\overarc{abc}</span><td><span>\overarc{abc}</span>
+=======
<tr><td><span class="mathquill-static-math">\begin{Vmatrix}x&y\\1&2\end{Vmatrix}</span><td><span>\begin{Vmatrix}x&y\\1&2\end{Vmatrix}</span>
+>>>>>>> matrix
<tr><td colspan=2><span id="sixes"></span>
<script>
$(function() {