Merge branch 'matrix'
diff --git a/src/commands/math/LatexCommandInput.js b/src/commands/math/LatexCommandInput.js
index 19dfc82..bae3718 100644
--- a/src/commands/math/LatexCommandInput.js
+++ b/src/commands/math/LatexCommandInput.js
@@ -74,7 +74,7 @@
var latex = this.ends[L].latex();
if (!latex) latex = ' ';
- var cmd = LatexCmds[latex];
+ var cmd = LatexCmds[latex] || Environments[latex];
if (cmd) {
cmd = cmd(latex);
if (this._replacedFragment) cmd.replaces(this._replacedFragment);
diff --git a/src/commands/math/commands.js b/src/commands/math/commands.js
index 68838bb..3e7eb7a 100644
--- a/src/commands/math/commands.js
+++ b/src/commands/math/commands.js
@@ -862,3 +862,497 @@
;
};
});
+
+// LaTeX environments
+// Environments are delimited by an opening \begin{} and a closing
+// \end{}. Everything inside those tags will be formatted in a
+// special manner depending on the environment type.
+var Environments = {};
+
+LatexCmds.begin = P(MathCommand, function(_, super_) {
+ _.parser = function() {
+ var string = Parser.string;
+ var regex = Parser.regex;
+ return string('{')
+ .then(regex(/^[a-z]+/i))
+ .skip(string('}'))
+ .then(function (env) {
+ return (Environments[env] ?
+ Environments[env]().parser() :
+ Parser.fail('unknown environment type: '+env)
+ ).skip(string('\\end{'+env+'}'));
+ })
+ ;
+ };
+});
+
+var Environment = P(MathCommand, function(_, super_) {
+ _.template = [['\\begin{', '}'], ['\\end{', '}']];
+ _.wrappers = function () {
+ return [
+ _.template[0].join(this.environment),
+ _.template[1].join(this.environment)
+ ];
+ };
+});
+
+var Matrix =
+Environments.matrix = P(Environment, function(_, super_) {
+
+ var delimiters = {
+ column: '&',
+ row: '\\\\'
+ };
+ _.parentheses = {
+ left: null,
+ right: null
+ };
+ _.environment = 'matrix';
+
+ _.reflow = function() {
+ var blockjQ = this.jQ.children('table');
+
+ var height = blockjQ.outerHeight()/+blockjQ.css('fontSize').slice(0,-2);
+
+ var parens = this.jQ.children('.mq-paren');
+ if (parens.length) {
+ scale(parens, min(1 + .2*(height - 1), 1.2), 1.05*height);
+ }
+ };
+ _.latex = function() {
+ var latex = '';
+ var row;
+
+ this.eachChild(function (cell) {
+ if (typeof row !== 'undefined') {
+ latex += (row !== cell.row) ?
+ delimiters.row :
+ delimiters.column;
+ }
+ row = cell.row;
+ latex += cell.latex();
+ });
+
+ return this.wrappers().join(latex);
+ };
+ _.html = function() {
+ var cells = [], trs = '', i=0, row;
+
+ function parenHtml(paren) {
+ return (paren) ?
+ '<span class="mq-scaled mq-paren">'
+ + paren
+ + '</span>' : '';
+ }
+
+ // Build <tr><td>.. structure from cells
+ this.eachChild(function (cell) {
+ if (row !== cell.row) {
+ row = cell.row;
+ trs += '<tr>$tds</tr>';
+ cells[row] = [];
+ }
+ cells[row].push('<td>&'+(i++)+'</td>');
+ });
+
+ this.htmlTemplate =
+ '<span class="mq-matrix mq-non-leaf">'
+ + parenHtml(this.parentheses.left)
+ + '<table class="mq-non-leaf">'
+ + trs.replace(/\$tds/g, function () {
+ return cells.shift().join('');
+ })
+ + '</table>'
+ + parenHtml(this.parentheses.right)
+ + '</span>'
+ ;
+
+ return super_.html.call(this);
+ };
+ // Create default 4-cell matrix
+ _.createBlocks = function() {
+ this.blocks = [
+ MatrixCell(0, this),
+ MatrixCell(0, this),
+ MatrixCell(1, this),
+ MatrixCell(1, this)
+ ];
+ };
+ _.parser = function() {
+ var self = this;
+ var optWhitespace = Parser.optWhitespace;
+ var string = Parser.string;
+
+ return optWhitespace
+ .then(string(delimiters.column)
+ .or(string(delimiters.row))
+ .or(latexMathParser.block))
+ .many()
+ .skip(optWhitespace)
+ .then(function(items) {
+ var blocks = [];
+ var row = 0;
+ self.blocks = [];
+
+ function addCell() {
+ self.blocks.push(MatrixCell(row, self, blocks));
+ blocks = [];
+ }
+
+ for (var i=0; i<items.length; i+=1) {
+ if (items[i] instanceof MathBlock) {
+ blocks.push(items[i]);
+ } else {
+ addCell();
+ if (items[i] === delimiters.row) row+=1;
+ }
+ }
+ addCell();
+ self.autocorrect();
+ return Parser.succeed(self);
+ });
+ };
+ // Relink all the cells after parsing
+ _.finalizeTree = function() {
+ var table = this.jQ.find('table');
+ table.toggleClass('mq-rows-1', table.find('tr').length === 1);
+ this.relink();
+ };
+ // Enter the matrix at the top or bottom row if updown is configured.
+ _.getEntryPoint = function(dir, cursor, updown) {
+ if (updown === 'up') {
+ if (dir === L) {
+ return this.blocks[this.rowSize - 1];
+ } else {
+ return this.blocks[0];
+ }
+ } else { // updown === 'down'
+ if (dir === L) {
+ return this.blocks[this.blocks.length - 1];
+ } else {
+ return this.blocks[this.blocks.length - this.rowSize];
+ }
+ }
+ };
+ // Exit the matrix at the first and last columns if updown is configured.
+ _.atExitPoint = function(dir, cursor) {
+ // Which block are we in?
+ var i = this.blocks.indexOf(cursor.parent);
+ if (dir === L) {
+ // If we're on the left edge and moving left, we should exit.
+ return i % this.rowSize === 0;
+ } else {
+ // If we're on the right edge and moving right, we should exit.
+ return (i + 1) % this.rowSize === 0;
+ }
+ };
+ _.moveTowards = function(dir, cursor, updown) {
+ var entryPoint = updown && this.getEntryPoint(dir, cursor, updown);
+ cursor.insAtDirEnd(-dir, entryPoint || this.ends[-dir]);
+ };
+
+ // Set up directional pointers between cells
+ _.relink = function() {
+ var blocks = this.blocks;
+ var rows = [];
+ var row, column, cell;
+
+ // The row size will be used by other functions down the track.
+ // Begin by assuming we're a one-row matrix, and we'll overwrite this if we find another row.
+ this.rowSize = blocks.length;
+
+ // Use a for loop rather than eachChild
+ // as we're still making sure children()
+ // is set up properly
+ for (var i=0; i<blocks.length; i+=1) {
+ cell = blocks[i];
+ if (row !== cell.row) {
+ if (cell.row === 1) {
+ // We've just finished iterating the first row.
+ this.rowSize = column;
+ }
+ row = cell.row;
+ rows[row] = [];
+ column = 0;
+ }
+ rows[row][column] = cell;
+
+ // Set up horizontal linkage
+ cell[R] = blocks[i+1];
+ cell[L] = blocks[i-1];
+
+ // Set up vertical linkage
+ if (rows[row-1] && rows[row-1][column]) {
+ cell.upOutOf = rows[row-1][column];
+ rows[row-1][column].downOutOf = cell;
+ }
+
+ column+=1;
+ }
+
+ // set start and end blocks of matrix
+ this.ends[L] = blocks[0];
+ this.ends[R] = blocks[blocks.length-1];
+ };
+ // Ensure consistent row lengths
+ _.autocorrect = function(rows) {
+ var lengths = [], rows = [];
+ var blocks = this.blocks;
+ var maxLength, shortfall, position, row, i;
+
+ for (i=0; i<blocks.length; i+=1) {
+ row = blocks[i].row;
+ rows[row] = rows[row] || [];
+ rows[row].push(blocks[i]);
+ lengths[row] = rows[row].length;
+ }
+
+ maxLength = Math.max.apply(null, lengths);
+ if (maxLength !== Math.min.apply(null, lengths)) {
+ // Pad shorter rows to correct length
+ for (i=0; i<rows.length; i+=1) {
+ shortfall = maxLength - rows[i].length;
+ while (shortfall) {
+ position = maxLength*i + rows[i].length;
+ blocks.splice(position, 0, MatrixCell(i, this));
+ shortfall-=1;
+ }
+ }
+ this.relink();
+ }
+ };
+ // Deleting a cell will also delete the current row and
+ // column if they are empty, and relink the matrix.
+ _.deleteCell = function(currentCell) {
+ var rows = [], columns = [], myRow = [], myColumn = [];
+ var blocks = this.blocks, row, column;
+
+ // Create arrays for cells in the current row / column
+ this.eachChild(function (cell) {
+ if (row !== cell.row) {
+ row = cell.row;
+ rows[row] = [];
+ column = 0;
+ }
+ columns[column] = columns[column] || [];
+ columns[column].push(cell);
+ rows[row].push(cell);
+
+ if (cell === currentCell) {
+ myRow = rows[row];
+ myColumn = columns[column];
+ }
+
+ column+=1;
+ });
+
+ function isEmpty(cells) {
+ var empties = [];
+ for (var i=0; i<cells.length; i+=1) {
+ if (cells[i].isEmpty()) empties.push(cells[i]);
+ }
+ return empties.length === cells.length;
+ }
+
+ function remove(cells) {
+ for (var i=0; i<cells.length; i+=1) {
+ if (blocks.indexOf(cells[i]) > -1) {
+ cells[i].remove();
+ blocks.splice(blocks.indexOf(cells[i]), 1);
+ }
+ }
+ }
+
+ if (isEmpty(myRow) && myColumn.length > 1) {
+ row = rows.indexOf(myRow);
+ // Decrease all following row numbers
+ this.eachChild(function (cell) {
+ if (cell.row > row) cell.row-=1;
+ });
+ // Dispose of cells and remove <tr>
+ remove(myRow);
+ this.jQ.find('tr').eq(row).remove();
+ }
+ if (isEmpty(myColumn) && myRow.length > 1) {
+ remove(myColumn);
+ }
+ this.finalizeTree();
+ };
+ _.addRow = function(afterCell) {
+ var previous = [], newCells = [], next = [];
+ var newRow = $('<tr></tr>'), row = afterCell.row;
+ var columns = 0, block, column;
+
+ this.eachChild(function (cell) {
+ // Cache previous rows
+ if (cell.row <= row) {
+ previous.push(cell);
+ }
+ // Work out how many columns
+ if (cell.row === row) {
+ if (cell === afterCell) column = columns;
+ columns+=1;
+ }
+ // Cache cells after new row
+ if (cell.row > row) {
+ cell.row+=1;
+ next.push(cell);
+ }
+ });
+
+ // Add new cells, one for each column
+ for (var i=0; i<columns; i+=1) {
+ block = MatrixCell(row+1);
+ block.parent = this;
+ newCells.push(block);
+
+ // Create cell <td>s and add to new row
+ block.jQ = $('<td class="mq-empty">')
+ .attr(mqBlockId, block.id)
+ .appendTo(newRow);
+ }
+
+ // Insert the new row
+ this.jQ.find('tr').eq(row).after(newRow);
+ this.blocks = previous.concat(newCells, next);
+ return newCells[column];
+ };
+ _.addColumn = function(afterCell) {
+ var rows = [], newCells = [];
+ var column, block;
+
+ // Build rows array and find new column index
+ this.eachChild(function (cell) {
+ rows[cell.row] = rows[cell.row] || [];
+ rows[cell.row].push(cell);
+ if (cell === afterCell) column = rows[cell.row].length;
+ });
+
+ // Add new cells, one for each row
+ for (var i=0; i<rows.length; i+=1) {
+ block = MatrixCell(i);
+ block.parent = this;
+ newCells.push(block);
+ rows[i].splice(column, 0, block);
+
+ block.jQ = $('<td class="mq-empty">')
+ .attr(mqBlockId, block.id);
+ }
+
+ // Add cell <td> elements in correct positions
+ this.jQ.find('tr').each(function (i) {
+ $(this).find('td').eq(column-1).after(rows[i][column].jQ);
+ });
+
+ // Flatten the rows array-of-arrays
+ this.blocks = [].concat.apply([], rows);
+ return newCells[afterCell.row];
+ };
+ _.insert = function(method, afterCell) {
+ var cellToFocus = this[method](afterCell);
+ this.cursor = this.cursor || this.parent.cursor;
+ this.finalizeTree();
+ this.bubble('reflow').cursor.insAtRightEnd(cellToFocus);
+ };
+ _.backspace = function(cell, dir, cursor, finalDeleteCallback) {
+ var dirwards = cell[dir];
+ if (cell.isEmpty()) {
+ this.deleteCell(cell);
+ while (dirwards &&
+ dirwards[dir] &&
+ this.blocks.indexOf(dirwards) === -1) {
+ dirwards = dirwards[dir];
+ }
+ if (dirwards) {
+ cursor.insAtDirEnd(-dir, dirwards);
+ }
+ if (this.blocks.length === 1 && this.blocks[0].isEmpty()) {
+ finalDeleteCallback();
+ this.finalizeTree();
+ }
+ this.bubble('edited');
+ }
+ };
+});
+
+Environments.pmatrix = P(Matrix, function(_, super_) {
+ _.environment = 'pmatrix';
+ _.parentheses = {
+ left: '(',
+ right: ')'
+ };
+});
+
+Environments.bmatrix = P(Matrix, function(_, super_) {
+ _.environment = 'bmatrix';
+ _.parentheses = {
+ left: '[',
+ right: ']'
+ };
+});
+
+Environments.Bmatrix = P(Matrix, function(_, super_) {
+ _.environment = 'Bmatrix';
+ _.parentheses = {
+ left: '{',
+ right: '}'
+ };
+});
+
+Environments.vmatrix = P(Matrix, function(_, super_) {
+ _.environment = 'vmatrix';
+ _.parentheses = {
+ left: '|',
+ right: '|'
+ };
+});
+
+Environments.Vmatrix = P(Matrix, function(_, super_) {
+ _.environment = 'Vmatrix';
+ _.parentheses = {
+ left: '‖',
+ right: '‖'
+ };
+});
+
+// Replacement for mathblocks inside matrix cells
+// Adds matrix-specific keyboard commands
+var MatrixCell = P(MathBlock, function(_, super_) {
+ _.init = function(row, parent, replaces) {
+ super_.init.call(this);
+ this.row = row;
+ if (parent) {
+ this.adopt(parent, parent.ends[R], 0);
+ }
+ if (replaces) {
+ for (var i=0; i<replaces.length; i++) {
+ replaces[i].children().adopt(this, this.ends[R], 0);
+ }
+ }
+ };
+ _.keystroke = function(key, e, ctrlr) {
+ switch (key) {
+ case 'Shift-Spacebar':
+ e.preventDefault();
+ return this.parent.insert('addColumn', this);
+ break;
+ case 'Shift-Enter':
+ return this.parent.insert('addRow', this);
+ break;
+ }
+ return super_.keystroke.apply(this, arguments);
+ };
+ _.deleteOutOf = function(dir, cursor) {
+ var self = this, args = arguments;
+ this.parent.backspace(this, dir, cursor, function () {
+ // called when last cell gets deleted
+ return super_.deleteOutOf.apply(self, args);
+ });
+ };
+ _.moveOutOf = function(dir, cursor, updown) {
+ var atExitPoint = updown && this.parent.atExitPoint(dir, cursor);
+ // Step out of the matrix if we've moved past an edge column
+ if (!atExitPoint && this[dir]) cursor.insAtDirEnd(-dir, this[dir]);
+ else cursor.insDirOf(dir, this.parent);
+ };
+});
diff --git a/src/css/math.less b/src/css/math.less
index dfa53e2..f170de6 100644
--- a/src/css/math.less
+++ b/src/css/math.less
@@ -416,4 +416,29 @@
}
}
}
+
+ .mq-matrix {
+ vertical-align: middle;
+ margin-left: 0.1em;
+ margin-right: 0.1em;
+
+ table {
+ width: auto;
+ border-bottom: none;
+ border-spacing: 3px;
+ border-collapse: separate;
+ &.mq-rows-1 { /* better alignment when there's just one row */
+ vertical-align: middle;
+ margin-bottom: 1px;
+ }
+ }
+
+ td {
+ border: none;
+ width: auto; /* defensive resets */
+ padding: 0.1em 0.3em;
+ vertical-align: baseline;
+ }
+ }
+
}
diff --git a/src/publicapi.js b/src/publicapi.js
index 63cd46f..c8fedf4 100644
--- a/src/publicapi.js
+++ b/src/publicapi.js
@@ -173,7 +173,7 @@
var ctrlr = this.__controller.notify(), cursor = ctrlr.cursor;
if (/^\\[a-z]+$/i.test(cmd)) {
cmd = cmd.slice(1);
- var klass = LatexCmds[cmd];
+ var klass = LatexCmds[cmd] || Environments[cmd];
if (klass) {
cmd = klass(cmd);
if (cursor.selection) cmd.replaces(cursor.replaceSelection());
diff --git a/test/matrix.html b/test/matrix.html
new file mode 100644
index 0000000..fd3175f
--- /dev/null
+++ b/test/matrix.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+
+<title>MathQuill Matrix Test</title>
+
+<link rel="stylesheet" type="text/css" href="../build/mathquill.css">
+<script type="text/javascript" src="support/jquery-1.7.2.js"></script>
+<script type="text/javascript" src="../build/mathquill.js"></script>
+</head>
+<body>
+
+<h3>MathQuill Matrix Test</h3>
+<span id="example">
+\begin{Bmatrix}1&2\\x&y\end{Bmatrix}
+</span>
+
+<script>
+MathQuill = MathQuill.getInterface(1);
+instance = MathQuill.MathField(document.getElementById('example'));
+console.log(instance.latex());
+</script>
+
+</body>
+</html>
diff --git a/test/unit/latex.test.js b/test/unit/latex.test.js
index e6e4096..afa3a32 100644
--- a/test/unit/latex.test.js
+++ b/test/unit/latex.test.js
@@ -137,6 +137,18 @@
assertParsesLatex('\\square ');
});
+ test('matrices', function() {
+ assertParsesLatex('\\begin{matrix}x\\end{matrix}');
+ assertParsesLatex('\\begin{pmatrix}x\\end{pmatrix}');
+ assertParsesLatex('\\begin{Bmatrix}x\\end{Bmatrix}');
+ assertParsesLatex('\\begin{vmatrix}x&y\\\\1&2\\end{vmatrix}');
+ assertParsesLatex('\\begin{bmatrix}x&y&z&123&x^2\\\\23&s&\\sin \\theta &1&x\\\\e&h&a&1&y\\end{bmatrix}');
+
+ // Adds missing cells
+ assertParsesLatex('\\begin{Vmatrix}x&y\\\\1\\end{Vmatrix}', '\\begin{Vmatrix}x&y\\\\1&\\end{Vmatrix}');
+ assertParsesLatex('\\begin{Vmatrix}x\\\\x&y\\\\x\\end{Vmatrix}', '\\begin{Vmatrix}x&\\\\x&y\\\\x&\\end{Vmatrix}');
+ });
+
suite('public API', function() {
var mq;
setup(function() {
diff --git a/test/unit/typing.test.js b/test/unit/typing.test.js
index c77fc90..bcc073f 100644
--- a/test/unit/typing.test.js
+++ b/test/unit/typing.test.js
@@ -1107,4 +1107,125 @@
assertLatex('\\times');
});
});
+
+ suite('Matrices', function() {
+ test('add matrix via mq.write', function() {
+ mq.write('\\begin{matrix}x&y\\\\1&2\\end{matrix}');
+ assertLatex('\\begin{matrix}x&y\\\\1&2\\end{matrix}');
+ });
+
+ test('key bindings add rows and columns to matrix', function() {
+ mq.write('\\begin{matrix}x\\end{matrix}').keystroke('Left');
+
+ mq.keystroke('Shift-Spacebar');
+ assertLatex('\\begin{matrix}x&\\end{matrix}');
+
+ mq.keystroke('Shift-Enter');
+ assertLatex('\\begin{matrix}x&\\\\&\\end{matrix}');
+ });
+
+ test('key sequence populates matrix', function() {
+ mq.write('\\begin{matrix}x&\\\\&\\end{matrix}')
+ .keystroke('Left Left').typedText('a')
+ .keystroke('Right').typedText('b')
+ .keystroke('Up').typedText('y');
+
+ assertLatex('\\begin{matrix}x&y\\\\a&b\\end{matrix}');
+ });
+
+ test('cursor keys navigate around matrix', function() {
+ mq.write('\\begin{matrix}&&\\\\&&\\\\&&\\end{matrix}');
+
+ mq.keystroke('Left Left Left').typedText('a')
+ .keystroke('Up').typedText('b')
+ .keystroke('Right').typedText('c')
+ .keystroke('Down').typedText('d');
+
+ assertLatex('\\begin{matrix}&&\\\\b&c&\\\\a&d&\\end{matrix}');
+ });
+
+ test('passes over matrices when leftRightIntoCmdGoes is set to up', function() {
+ mq.config({ leftRightIntoCmdGoes: 'up' });
+
+ // 1 2 3
+ // 4 5 6
+ // 7 8 9
+ mq.write('\\begin{matrix}1&2&3\\\\4&5&6\\\\7&8&9\\end{matrix}');
+
+ mq.keystroke('Left Left Left Left Left Left Left').typedText('a')
+ .keystroke('Right Right Right Right Right Right Right').typedText('b')
+ .keystroke('Left Left Left Left').typedText('c');
+
+ // It should've entered the top of the matrix and exited at either end, leading to
+ // 1 2c 3
+ // a 4 5 6 b
+ // 7 8 9
+ assertLatex('a\\begin{matrix}1&2c&3\\\\4&5&6\\\\7&8&9\\end{matrix}b');
+ });
+
+ test('passes under matrices when leftRightIntoCmdGoes is set to down', function() {
+ mq.config({ leftRightIntoCmdGoes: 'down' });
+
+ // 1 2 3
+ // 4 5 6
+ // 7 8 9
+ mq.write('\\begin{matrix}1&2&3\\\\4&5&6\\\\7&8&9\\end{matrix}');
+
+ mq.keystroke('Left Left Left Left Left Left Left').typedText('a')
+ .keystroke('Right Right Right Right Right Right Right').typedText('b')
+ .keystroke('Left Left Left Left').typedText('c');
+
+ // It should've entered the bottom of the matrix and exited at either end, leading to
+ // 1 2 3
+ // a 4 5 6 b
+ // 7 8c 9
+ assertLatex('a\\begin{matrix}1&2&3\\\\4&5&6\\\\7&8c&9\\end{matrix}b');
+ });
+
+ test('exits out of matrices on their edges when leftRightIntoCmdGoes is set', function() {
+ mq.config({ leftRightIntoCmdGoes: 'up' });
+
+ // 1 2 3
+ // 4 5 6
+ // 7 8 9
+ mq.write('\\begin{matrix}1&2&3\\\\4&5&6\\\\7&8&9\\end{matrix}');
+
+ mq.keystroke('Left Left Left Down').typedText('a')
+ .keystroke('Right Right Right').typedText('b')
+
+ // It should've entered the top of the matrix and exited out the side, leading to
+ // 1 2 3
+ // 4 5a 6 b
+ // 7 8 9
+ assertLatex('\\begin{matrix}1&2&3\\\\4&5a&6\\\\7&8&9\\end{matrix}b');
+ });
+
+ test('delete key removes empty matrix row/column', function() {
+ mq.write('\\begin{matrix}a&&b\\\\&c&d\\\\&e&f\\end{matrix}');
+
+ // Row is not yet deleted as there was content
+ mq.keystroke('Left Backspace Left');
+ assertLatex('\\begin{matrix}a&&b\\\\&c&d\\\\&e&\\end{matrix}');
+
+ // Row is now deleted (delete e, then row)
+ mq.keystroke('Backspace Backspace');
+ assertLatex('\\begin{matrix}a&&b\\\\&c&d\\end{matrix}');
+
+ // Column is now deleted (delete c, then column)
+ mq.keystroke('Left Left Backspace Backspace');
+ assertLatex('\\begin{matrix}a&b\\\\&d\\end{matrix}');
+ });
+
+ test('brackets are scaled immediately', function() {
+ mq.write('\\begin{bmatrix}x\\end{bmatrix}');
+ function bracketHeight() {
+ return $(mq.el()).find('.mq-matrix .mq-paren.mq-scaled')[0].getBoundingClientRect().height;
+ }
+ var height = bracketHeight();
+ mq.keystroke('Left Shift-Enter');
+
+ assert.ok(bracketHeight() > height,
+ 'matrix bracket height should be increased when new row is added');
+ });
+ });
});
diff --git a/test/visual.html b/test/visual.html
index 3d091f5..d8518b7 100644
--- a/test/visual.html
+++ b/test/visual.html
@@ -178,9 +178,9 @@
<table id="dynamic-reflow">
<tr><th colspan=3><code>MQ(...).reflow()</code>
<tr>
- <td><span>\sqrt{ \left ( \frac{x^2 + y^2}{2} \right ) } + \binom{n}{k}</span>
- <td><span>\sqrt{ \left ( \frac{x^2 + y^2}{2} \right ) } + \binom{n}{k}</span>
- <td><span>\sqrt{ \left ( \frac{x^2 + y^2}{2} \right ) } + \binom{n}{k}</span>
+ <td><span>\sqrt{ \left ( \frac{x^2 + y^2}{2} \right ) } + \binom{n}{k} + \begin{bmatrix}x&y\\1&2\end{bmatrix}</span>
+ <td><span>\sqrt{ \left ( \frac{x^2 + y^2}{2} \right ) } + \binom{n}{k} + \begin{bmatrix}x&y\\1&2\end{bmatrix}</span>
+ <td><span>\sqrt{ \left ( \frac{x^2 + y^2}{2} \right ) } + \binom{n}{k} + \begin{bmatrix}x&y\\1&2\end{bmatrix}</span>
</table>
<h3>Static LaTeX rendering (<code>.mathquill-static-math</code>) tests</h3>
@@ -212,11 +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() {