├── .babelrc ├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── browserslist ├── example ├── aligns.js ├── index.html ├── main.css ├── main.js └── value.js ├── lib ├── changes │ ├── clearCell.js │ ├── index.js │ ├── insertColumn.js │ ├── insertRow.js │ ├── insertTable.js │ ├── insertTableFragmentAtRange.js │ ├── moveSelection.js │ ├── moveSelectionBy.js │ ├── removeColumn.js │ ├── removeColumnByKey.js │ ├── removeRow.js │ ├── removeRowByKey.js │ ├── removeTable.js │ └── removeTableByKey.js ├── core.js ├── handlers │ ├── index.js │ ├── onBackspace.js │ ├── onCopy.js │ ├── onEnter.js │ ├── onKeyDown.js │ ├── onModEnter.js │ ├── onPaste.js │ ├── onTab.js │ └── onUpDown.js ├── index.js ├── options.js ├── utils │ ├── TablePosition.js │ ├── createCell.js │ ├── createRow.js │ ├── createTable.js │ ├── forEachCells.js │ ├── getCellsAtColumn.js │ ├── getCellsAtRow.js │ ├── getCopiedFragment.js │ ├── getPosition.js │ ├── getPositionByKey.js │ ├── getRow.js │ ├── index.js │ ├── isRangeInTable.js │ ├── isSelectionInTable.js │ └── isSelectionOutOfTable.js └── validation │ ├── index.js │ ├── schema.js │ └── validateNode.js ├── package.json ├── tests ├── all.js ├── backspace-after-inline │ ├── change.js │ └── input.js ├── backspace-cell-boundaries │ ├── change.js │ ├── expected.js │ └── input.js ├── backspace-clear-cells-with-multiple-blocks │ ├── change.js │ ├── expected.js │ └── input.js ├── backspace-clear-cells │ ├── change.js │ ├── expected.js │ └── input.js ├── backspace-collapsed │ ├── change.js │ ├── expected.js │ └── input.js ├── backspace-delete-void │ ├── change.js │ └── input.js ├── backspace-multiple-blocks-collapsed │ ├── change.js │ └── input.js ├── backspace-multiple-blocks-expanded │ ├── change.js │ └── input.js ├── backspace-same-block │ ├── change.js │ └── input.js ├── backspace-start-cell │ ├── change.js │ ├── expected.js │ └── input.js ├── backspace-whole-cell │ ├── change.js │ └── input.js ├── enter-split-block │ ├── change.js │ ├── expected.js │ └── input.js ├── get-cells-at-column │ ├── change.js │ ├── expected.js │ └── input.js ├── get-cells-at-row │ ├── change.js │ ├── expected.js │ └── input.js ├── get-position-by-key │ ├── change.js │ └── input.js ├── get-position │ ├── change.js │ └── input.js ├── hyperscript.js ├── insert-column-at │ ├── change.js │ ├── expected.js │ └── input.js ├── insert-column-preserve-data │ ├── change.js │ ├── expected.js │ └── input.js ├── insert-column │ ├── change.js │ ├── expected.js │ └── input.js ├── insert-row │ ├── change.js │ ├── expected.js │ └── input.js ├── insert-table │ ├── change.js │ ├── expected.js │ └── input.js ├── mod-enter-exit-table │ ├── change.js │ ├── expected.js │ └── input.js ├── move-selection-by │ ├── change.js │ ├── expected.js │ └── input.js ├── move-selection │ ├── change.js │ ├── expected.js │ └── input.js ├── on-shift-tab-first-cell │ ├── change.js │ ├── expected.js │ └── input.js ├── on-shift-tab │ ├── change.js │ ├── expected.js │ └── input.js ├── on-tab-last-cell │ ├── change.js │ ├── expected.js │ └── input.js ├── on-tab-last-column │ ├── change.js │ ├── expected.js │ └── input.js ├── on-tab │ ├── change.js │ ├── expected.js │ └── input.js ├── paste-content-into-cell │ ├── change.js │ ├── expected.js │ └── input.js ├── paste-empty-cell-into-cell │ ├── change.js │ ├── expected.js │ └── input.js ├── paste-multiple-cells-at-same-position │ ├── change.js │ ├── expected.js │ └── input.js ├── paste-multiple-cells-into-table │ ├── change.js │ ├── expected.js │ └── input.js ├── paste-multiple-cells-outside │ ├── change.js │ ├── expected.js │ └── input.js ├── paste-single-cell-into-cell │ ├── change.js │ ├── expected.js │ └── input.js ├── paste-single-cell-outside │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-column-at │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-column-first │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-column-last-one │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-column-preserve-data │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-column │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-row-at │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-row-first │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-row-last-one │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-row │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-table-and-move-to-next-block │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-table-and-move-to-previous-block │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-table-exit-with-none │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-table-exit-with-paragraph │ ├── change.js │ ├── expected.js │ └── input.js ├── remove-table │ ├── change.js │ ├── expected.js │ └── input.js ├── schema-no-blocks-within-rows │ ├── change.js │ ├── expected.js │ └── input.js ├── schema-no-blocks-within-table │ ├── change.js │ ├── expected.js │ └── input.js ├── schema-only-blocks-within-cells │ ├── change.js │ ├── expected.js │ └── input.js ├── schema-orphan-cells │ ├── change.js │ ├── expected.js │ └── input.js ├── schema-rows-cells-within-tables │ ├── change.js │ ├── expected.js │ └── input.js ├── schema-rows-require-same-columns-counts │ ├── change.js │ ├── expected.js │ └── input.js ├── schema-standard-table │ ├── change.js │ ├── expected.js │ └── input.js ├── schema-tables-contain-rows-empty │ ├── change.js │ ├── expected.js │ └── input.js ├── schema-tables-contain-rows-invalid │ ├── change.js │ ├── expected.js │ └── input.js ├── schema-tables-contain-rows-mixed │ ├── change.js │ ├── expected.js │ └── input.js ├── selection-in-table │ ├── change.js │ └── input.js ├── selection-outside-table │ ├── change.js │ └── input.js ├── shift-enter-split-block │ ├── change.js │ ├── expected.js │ └── input.js ├── undo-insert-column │ ├── change.js │ ├── expected.js │ └── input.js ├── undo-insert-row │ ├── change.js │ ├── expected.js │ └── input.js ├── undo-insert-table │ ├── change.js │ ├── expected.js │ └── input.js ├── undo-remove-column │ ├── change.js │ ├── expected.js │ └── input.js ├── undo-remove-row │ ├── change.js │ ├── expected.js │ └── input.js └── undo-remove-table │ ├── change.js │ ├── expected.js │ └── input.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env", 4 | "flow", 5 | "react", 6 | "stage-0" 7 | ], 8 | "env": { 9 | "test": { 10 | "plugins": ["transform-runtime"] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | example/bundle.js 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": [ 4 | "gitbook" 5 | ], 6 | "rules": { 7 | "no-param-reassign": 0, 8 | "import/no-commonjs": 2 9 | }, 10 | "plugins": [ 11 | "flowtype" 12 | ], 13 | "env": { 14 | "mocha": true 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [options] 2 | emoji=true 3 | esproposal.decorators=ignore 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | dist 40 | example/bundle.js 41 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | lib 2 | !dist 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | script: 4 | - yarn run test 5 | - yarn run lint 6 | # - yarn run flow 7 | node_js: 8 | - "9" 9 | -------------------------------------------------------------------------------- /browserslist: -------------------------------------------------------------------------------- 1 | last 2 Chrome versions 2 | last 2 Firefox versions 3 | last 2 Safari versions 4 | last 2 Edge versions 5 | IE 11 6 | >1% 7 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Slate • Table Edition 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/main.css: -------------------------------------------------------------------------------- 1 | #example { 2 | width: 100%; 3 | max-width: 600px; 4 | margin: 20px auto; 5 | position: relative; 6 | padding-top: 30px; 7 | } 8 | 9 | #example .toolbar { 10 | position: absolute; 11 | top: 0; 12 | } 13 | 14 | #example table { 15 | width: 100%; 16 | border-collapse: collapse; 17 | border-top: 1px solid black; 18 | } 19 | 20 | #example table tr { 21 | border: none; 22 | border-bottom: 1px solid black; 23 | border-right: 1px solid black; 24 | display: flex; 25 | flex-direction: row; 26 | flex-wrap: nowrap; 27 | } 28 | 29 | #example table tr:first-child { 30 | background: #f5f5f5; 31 | font-weight: bold; 32 | } 33 | 34 | #example table td { 35 | border: 1px solid black; 36 | border-top: none; 37 | border-bottom: none; 38 | border-right: none; 39 | flex: 1; 40 | word-break: break-all; 41 | } 42 | -------------------------------------------------------------------------------- /lib/changes/clearCell.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { Block, type Change } from '@gitbook/slate'; 3 | 4 | import type Options from '../options'; 5 | 6 | /** 7 | * Clear the content of the given cell 8 | */ 9 | function clearCell(opts: Options, change: Change, cell: Block): Change { 10 | const newBlock = Block.create({ type: opts.typeContent }); 11 | const { nodes } = cell; 12 | 13 | // Insert a new empty node 14 | change.insertNodeByKey(cell.key, 0, newBlock, { normalize: false }); 15 | 16 | // Remove all previous nodes 17 | nodes.forEach(node => { 18 | change.removeNodeByKey(node.key); 19 | }); 20 | 21 | change.normalizeNodeByKey(cell.key); 22 | 23 | return change; 24 | } 25 | 26 | export default clearCell; 27 | -------------------------------------------------------------------------------- /lib/changes/index.js: -------------------------------------------------------------------------------- 1 | import insertTable from './insertTable'; 2 | import insertTableFragmentAtRange from './insertTableFragmentAtRange'; 3 | import insertRow from './insertRow'; 4 | import removeRow from './removeRow'; 5 | import insertColumn from './insertColumn'; 6 | import removeColumn from './removeColumn'; 7 | import removeTable from './removeTable'; 8 | import removeRowByKey from './removeRowByKey'; 9 | import removeColumnByKey from './removeColumnByKey'; 10 | import removeTableByKey from './removeTableByKey'; 11 | import clearCell from './clearCell'; 12 | import moveSelection from './moveSelection'; 13 | import moveSelectionBy from './moveSelectionBy'; 14 | 15 | export { 16 | insertTable, 17 | insertTableFragmentAtRange, 18 | insertRow, 19 | removeRow, 20 | removeRowByKey, 21 | insertColumn, 22 | removeColumn, 23 | removeColumnByKey, 24 | removeTable, 25 | removeTableByKey, 26 | clearCell, 27 | moveSelection, 28 | moveSelectionBy 29 | }; 30 | -------------------------------------------------------------------------------- /lib/changes/insertColumn.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change, type Block } from '@gitbook/slate'; 3 | 4 | import { TablePosition, createCell } from '../utils'; 5 | import moveSelection from './moveSelection'; 6 | 7 | import type Options from '../options'; 8 | 9 | /** 10 | * Insert a new column in current table 11 | */ 12 | function insertColumn( 13 | opts: Options, 14 | change: Change, 15 | at?: number, // Column index 16 | getCell?: (column: number, row: number) => Block 17 | ): Change { 18 | const { value } = change; 19 | const { startKey } = value; 20 | 21 | const pos = TablePosition.create(opts, value.document, startKey); 22 | const { table } = pos; 23 | 24 | const columnIndex = 25 | typeof at === 'undefined' ? pos.getColumnIndex() + 1 : at; 26 | 27 | // Insert the new cell 28 | table.nodes.forEach((row, rowIndex) => { 29 | const newCell = getCell 30 | ? getCell(columnIndex, rowIndex) 31 | : createCell(opts); 32 | change.insertNodeByKey(row.key, columnIndex, newCell, { 33 | normalize: false 34 | }); 35 | }); 36 | 37 | // Update the selection (not doing can break the undo) 38 | return moveSelection( 39 | opts, 40 | change, 41 | pos.getColumnIndex() + 1, 42 | pos.getRowIndex() 43 | ); 44 | } 45 | 46 | export default insertColumn; 47 | -------------------------------------------------------------------------------- /lib/changes/insertRow.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change, type Block } from '@gitbook/slate'; 3 | 4 | import { TablePosition, createRow } from '../utils'; 5 | import type Options from '../options'; 6 | 7 | /** 8 | * Insert a new row in current table 9 | */ 10 | function insertRow( 11 | opts: Options, 12 | change: Change, 13 | at?: number, // row index 14 | getRow?: (columns: number) => Block // Generate the row yourself 15 | ) { 16 | const { value } = change; 17 | const { startKey } = value; 18 | 19 | const pos = TablePosition.create(opts, value.document, startKey); 20 | const { table } = pos; 21 | 22 | // Create a new row with the right count of cells 23 | const columns = table.nodes.get(0).nodes.size; 24 | const newRow = getRow ? getRow(columns) : createRow(opts, columns); 25 | 26 | if (typeof at === 'undefined') { 27 | at = pos.getRowIndex() + 1; 28 | } 29 | 30 | return change 31 | .insertNodeByKey(table.key, at, newRow) 32 | .collapseToEndOf(newRow.nodes.get(pos.getColumnIndex())); 33 | } 34 | 35 | export default insertRow; 36 | -------------------------------------------------------------------------------- /lib/changes/insertTable.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change, type Node } from '@gitbook/slate'; 3 | 4 | import { createTable } from '../utils'; 5 | import type Options from '../options'; 6 | 7 | /** 8 | * Insert a new table 9 | */ 10 | function insertTable( 11 | opts: Options, 12 | change: Change, 13 | columns?: number = 2, 14 | rows?: number = 2, 15 | getCellContent?: (column: number, row: number) => Node[] 16 | ): Change { 17 | const { value } = change; 18 | 19 | if (!value.selection.startKey) return change; 20 | 21 | // Create the table node 22 | const table = createTable(opts, columns, rows, getCellContent); 23 | 24 | return change.insertBlock(table); 25 | } 26 | 27 | export default insertTable; 28 | -------------------------------------------------------------------------------- /lib/changes/moveSelection.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change } from '@gitbook/slate'; 3 | 4 | import { TablePosition } from '../utils'; 5 | import type Options from '../options'; 6 | 7 | /** 8 | * Move selection to {x,y} 9 | */ 10 | function moveSelection( 11 | opts: Options, 12 | change: Change, 13 | x: number, 14 | y: number 15 | ): Change { 16 | const { value } = change; 17 | const { startKey } = value; 18 | const pos = TablePosition.create(opts, value.document, startKey); 19 | 20 | if (!pos.isInCell()) { 21 | throw new Error('moveSelection can only be applied from within a cell'); 22 | } 23 | 24 | const { table } = pos; 25 | const row = table.nodes.get(y); 26 | const cell = row.nodes.get(x); 27 | 28 | return change.collapseToStartOf(cell); 29 | } 30 | 31 | export default moveSelection; 32 | -------------------------------------------------------------------------------- /lib/changes/removeColumn.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change } from '@gitbook/slate'; 3 | 4 | import { TablePosition } from '../utils'; 5 | import removeColumnByKey from './removeColumnByKey'; 6 | 7 | import type Options from '../options'; 8 | 9 | /** 10 | * Delete current column in a table 11 | */ 12 | function removeColumn(opts: Options, change: Change, at: number): Change { 13 | const { value } = change; 14 | const { startKey } = value; 15 | 16 | const pos = TablePosition.create(opts, value.document, startKey); 17 | 18 | let columnKey; 19 | if (typeof at === 'undefined') { 20 | columnKey = pos.cell.key; 21 | } else { 22 | columnKey = pos.row.nodes.get(at).key; 23 | } 24 | 25 | return removeColumnByKey(opts, change, columnKey); 26 | } 27 | 28 | export default removeColumn; 29 | -------------------------------------------------------------------------------- /lib/changes/removeColumnByKey.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change } from '@gitbook/slate'; 3 | 4 | import { TablePosition } from '../utils'; 5 | import clearCell from './clearCell'; 6 | import type Options from '../options'; 7 | 8 | /** 9 | * Delete the column associated with the given cell key in a table 10 | */ 11 | function removeColumnByKey(opts: Options, change: Change, key: string): Change { 12 | const { value } = change; 13 | 14 | const pos = TablePosition.create(opts, value.document, key); 15 | const { table } = pos; 16 | 17 | const colIndex = pos.getColumnIndex(); 18 | 19 | const rows = table.nodes; 20 | 21 | // Remove the cell from every row 22 | if (pos.getWidth() > 1) { 23 | rows.forEach(row => { 24 | const cell = row.nodes.get(colIndex); 25 | change.removeNodeByKey(cell.key, { normalize: false }); 26 | }); 27 | } else { 28 | // If last column, clear text in cells instead 29 | rows.forEach(row => { 30 | row.nodes.forEach(cell => { 31 | cell.nodes.forEach(node => clearCell(opts, change, cell)); 32 | }); 33 | }); 34 | } 35 | 36 | // Replace the table 37 | return change; 38 | } 39 | 40 | export default removeColumnByKey; 41 | -------------------------------------------------------------------------------- /lib/changes/removeRow.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change } from '@gitbook/slate'; 3 | 4 | import { TablePosition } from '../utils'; 5 | import type Options from '../options'; 6 | import removeRowByKey from './removeRowByKey'; 7 | 8 | /** 9 | * Remove current row in a table. Clear it if last remaining row 10 | */ 11 | function removeRow(opts: Options, change: Change, at: number): Change { 12 | const { value } = change; 13 | const { startKey } = value; 14 | 15 | const pos = TablePosition.create(opts, value.document, startKey); 16 | 17 | let rowKey; 18 | if (typeof at === 'undefined') { 19 | rowKey = pos.row.key; 20 | } else { 21 | rowKey = pos.table.nodes.get(at).key; 22 | } 23 | 24 | return removeRowByKey(opts, change, rowKey); 25 | } 26 | 27 | export default removeRow; 28 | -------------------------------------------------------------------------------- /lib/changes/removeRowByKey.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change } from '@gitbook/slate'; 3 | 4 | import { TablePosition } from '../utils'; 5 | import clearCell from './clearCell'; 6 | import type Options from '../options'; 7 | 8 | /** 9 | * Remove the row associated to a given key in a table. 10 | * Clear thw row if last remaining row 11 | */ 12 | function removeRowByKey(opts: Options, change: Change, key: string): Change { 13 | const { value } = change; 14 | 15 | const pos = TablePosition.create(opts, value.document, key); 16 | 17 | // Update table by removing the row 18 | if (pos.getHeight() > 1) { 19 | change.removeNodeByKey(key); 20 | } else { 21 | // If last remaining row, clear it instead 22 | pos.row.nodes.forEach(cell => { 23 | cell.nodes.forEach(node => clearCell(opts, change, cell)); 24 | }); 25 | } 26 | 27 | return change; 28 | } 29 | 30 | export default removeRowByKey; 31 | -------------------------------------------------------------------------------- /lib/changes/removeTable.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change } from '@gitbook/slate'; 3 | 4 | import type Options from '../options'; 5 | import removeTableByKey from './removeTableByKey'; 6 | 7 | /** 8 | * Delete the whole table at position 9 | */ 10 | function removeTable(opts: Options, change: Change): Change { 11 | const { value } = change; 12 | const { startKey } = value; 13 | 14 | return removeTableByKey(opts, change, startKey); 15 | } 16 | 17 | export default removeTable; 18 | -------------------------------------------------------------------------------- /lib/handlers/index.js: -------------------------------------------------------------------------------- 1 | import onEnter from './onEnter'; 2 | import onModEnter from './onModEnter'; 3 | import onTab from './onTab'; 4 | import onBackspace from './onBackspace'; 5 | import onUpDown from './onUpDown'; 6 | import onKeyDown from './onKeyDown'; 7 | import onCopy from './onCopy'; 8 | import onPaste from './onPaste'; 9 | 10 | export { 11 | onEnter, 12 | onModEnter, 13 | onTab, 14 | onBackspace, 15 | onUpDown, 16 | onKeyDown, 17 | onCopy, 18 | onPaste 19 | }; 20 | -------------------------------------------------------------------------------- /lib/handlers/onCopy.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { cloneFragment, type Editor } from '@gitbook/slate-react'; 3 | import { type Change } from '@gitbook/slate'; 4 | 5 | import type Options from '../options'; 6 | import { getCopiedFragment } from '../utils'; 7 | 8 | /** 9 | * Handle copying content of tables 10 | */ 11 | function onCopy( 12 | // The plugin options 13 | opts?: Options, 14 | event: *, 15 | change: Change, 16 | editor: Editor 17 | ): Object { 18 | const copiedFragment = getCopiedFragment(opts, change.value); 19 | 20 | if (!copiedFragment) { 21 | // Default copy behavior 22 | return null; 23 | } 24 | 25 | // Override default onCopy 26 | cloneFragment(event, change.value, copiedFragment); 27 | return true; 28 | } 29 | 30 | export default onCopy; 31 | -------------------------------------------------------------------------------- /lib/handlers/onEnter.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change } from '@gitbook/slate'; 3 | 4 | import type Options from '../options'; 5 | import { TablePosition } from '../utils'; 6 | import { insertRow } from '../changes'; 7 | 8 | /** 9 | * Insert a new row when pressing "Enter" 10 | */ 11 | function onEnter( 12 | event: *, 13 | change: Change, 14 | editor: *, 15 | opts: Options 16 | ): void | Change { 17 | event.preventDefault(); 18 | const { selection, document } = change.value; 19 | const pos = TablePosition.create(opts, document, selection.startKey); 20 | 21 | if ( 22 | !selection.hasFocusAtStartOf(pos.cell) && 23 | !selection.hasFocusAtEndOf(pos.cell) 24 | ) { 25 | return undefined; 26 | } 27 | 28 | if (event.shiftKey) { 29 | return change 30 | .splitBlock() 31 | .setBlocks({ type: opts.typeContent, data: {} }); 32 | } 33 | 34 | return insertRow(opts, change); 35 | } 36 | 37 | export default onEnter; 38 | -------------------------------------------------------------------------------- /lib/handlers/onKeyDown.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import { type Change } from '@gitbook/slate'; 4 | 5 | import type Options from '../options'; 6 | import { isSelectionInTable } from '../utils'; 7 | 8 | import onEnter from './onEnter'; 9 | import onModEnter from './onModEnter'; 10 | import onTab from './onTab'; 11 | import onBackspace from './onBackspace'; 12 | import onUpDown from './onUpDown'; 13 | 14 | const KEY_ENTER = 'Enter'; 15 | const KEY_TAB = 'Tab'; 16 | const KEY_BACKSPACE = 'Backspace'; 17 | const KEY_DOWN = 'ArrowDown'; 18 | const KEY_UP = 'ArrowUp'; 19 | 20 | /** 21 | * User is pressing a key in the editor 22 | */ 23 | function onKeyDown( 24 | opts: Options, 25 | event: *, 26 | change: Change, 27 | editor: * 28 | ): void | any { 29 | // Only handle events in cells 30 | if (!isSelectionInTable(opts, change.value)) { 31 | return undefined; 32 | } 33 | 34 | // Build arguments list 35 | const args = [event, change, editor, opts]; 36 | 37 | switch (event.key) { 38 | case KEY_ENTER: 39 | if (event.metaKey && opts.exitBlockType) { 40 | return onModEnter(...args); 41 | } 42 | return onEnter(...args); 43 | 44 | case KEY_TAB: 45 | return onTab(...args); 46 | case KEY_BACKSPACE: 47 | return onBackspace(...args); 48 | case KEY_DOWN: 49 | case KEY_UP: 50 | return onUpDown(...args); 51 | default: 52 | return undefined; 53 | } 54 | } 55 | 56 | export default onKeyDown; 57 | -------------------------------------------------------------------------------- /lib/handlers/onModEnter.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { Block, Text, type Change } from '@gitbook/slate'; 3 | 4 | import { TablePosition } from '../utils'; 5 | import type Options from '../options'; 6 | 7 | /** 8 | * Exit the current table, by inserting a default block after the table. 9 | */ 10 | function onModEnter( 11 | event: *, 12 | change: Change, 13 | editor: *, 14 | opts: Options 15 | ): void | Change { 16 | const { value } = change; 17 | if (!value.isCollapsed) { 18 | return undefined; 19 | } 20 | 21 | event.preventDefault(); 22 | 23 | const exitBlock = Block.create({ 24 | type: opts.exitBlockType, 25 | nodes: [Text.create('')] 26 | }); 27 | 28 | const table = TablePosition.create(opts, value.document, value.startKey) 29 | .table; 30 | const tableParent = value.document.getParent(table.key); 31 | const insertionIndex = tableParent.nodes.indexOf(table) + 1; 32 | 33 | return change 34 | .insertNodeByKey(tableParent.key, insertionIndex, exitBlock) 35 | .collapseToStartOf(exitBlock); 36 | } 37 | 38 | export default onModEnter; 39 | -------------------------------------------------------------------------------- /lib/handlers/onPaste.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { getEventTransfer, type Editor } from '@gitbook/slate-react'; 3 | import { Range, type Change } from '@gitbook/slate'; 4 | 5 | import type Options from '../options'; 6 | import { isSelectionInTable, isRangeInTable } from '../utils'; 7 | import { insertTableFragmentAtRange } from '../changes'; 8 | 9 | /** 10 | * Handle pasting inside tables 11 | */ 12 | function onPaste( 13 | // The plugin options 14 | opts?: Options, 15 | event: *, 16 | change: Change, 17 | editor: Editor 18 | ): Object { 19 | // Outside of tables, do not alter paste behavior 20 | if (!isSelectionInTable(opts, change.value)) { 21 | return undefined; 22 | } 23 | 24 | const transfer = getEventTransfer(event); 25 | const { type, fragment } = transfer; 26 | 27 | if (type != 'fragment' || fragment.nodes.isEmpty()) { 28 | return null; 29 | } 30 | 31 | if ( 32 | !isRangeInTable( 33 | opts, 34 | fragment, 35 | Range.create({ 36 | anchorKey: fragment.getFirstText().key, 37 | focusKey: fragment.getLastText().key 38 | }) 39 | ) 40 | ) { 41 | return null; 42 | } 43 | 44 | return insertTableFragmentAtRange( 45 | opts, 46 | change, 47 | change.value.selection, 48 | fragment 49 | ); 50 | } 51 | 52 | export default onPaste; 53 | -------------------------------------------------------------------------------- /lib/handlers/onTab.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change } from '@gitbook/slate'; 3 | 4 | import { TablePosition } from '../utils'; 5 | import { moveSelectionBy, insertRow } from '../changes'; 6 | import type Options from '../options'; 7 | 8 | /** 9 | * Select all text of current block. 10 | */ 11 | function selectAllText(change: Change): Change { 12 | const { value } = change; 13 | const { startBlock } = value; 14 | 15 | return change.moveOffsetsTo(0).extend(startBlock.text.length); 16 | } 17 | 18 | /** 19 | * Pressing "Tab" moves the cursor to the next cell 20 | * and select the whole text 21 | */ 22 | function onTab( 23 | event: *, 24 | change: Change, 25 | editor: *, 26 | opts: Options 27 | ): void | Change { 28 | event.preventDefault(); 29 | const { value } = change; 30 | const direction = event.shiftKey ? -1 : +1; 31 | 32 | // Create new row if needed 33 | const { startKey, selection } = value; 34 | const pos = TablePosition.create(opts, value.document, startKey); 35 | if (pos.isFirstCell() && direction === -1) { 36 | insertRow(opts, change, 0); 37 | } else if (pos.isLastCell() && direction === 1) { 38 | insertRow(opts, change); 39 | } 40 | 41 | // Move back to initial cell (insertRow moves selection automatically). 42 | change.select(selection); 43 | 44 | // Move 45 | moveSelectionBy(opts, change, direction, 0); 46 | 47 | // Select all cell. 48 | return selectAllText(change); 49 | } 50 | 51 | export default onTab; 52 | -------------------------------------------------------------------------------- /lib/handlers/onUpDown.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Change } from '@gitbook/slate'; 3 | 4 | import { TablePosition } from '../utils'; 5 | import { moveSelectionBy } from '../changes'; 6 | import type Options from '../options'; 7 | 8 | function onUpDown( 9 | event: *, 10 | change: Change, 11 | editor: *, 12 | opts: Options 13 | ): void | Change { 14 | const { value } = change; 15 | const direction = event.key === 'ArrowUp' ? -1 : +1; 16 | const pos = TablePosition.create(opts, value.document, value.startKey); 17 | 18 | if ( 19 | (pos.isFirstRow() && direction === -1) || 20 | (pos.isLastRow() && direction === +1) 21 | ) { 22 | // Let the default behavior move out of the table 23 | return undefined; 24 | } 25 | 26 | if (direction === -1 && !pos.isTopOfCell()) { 27 | return undefined; 28 | } 29 | 30 | if (direction === +1 && !pos.isBottomOfCell()) { 31 | return undefined; 32 | } 33 | 34 | event.preventDefault(); 35 | 36 | moveSelectionBy(opts, change, 0, direction); 37 | 38 | return change; 39 | } 40 | 41 | export default onUpDown; 42 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Options, { type OptionsFormat } from './options'; 3 | import type { TablePosition as _TablePosition } from './utils/TablePosition'; 4 | import core from './core'; 5 | import { onKeyDown, onCopy, onPaste } from './handlers'; 6 | 7 | /** 8 | * Returns the full plugin object (behavior + rendering + schema) 9 | */ 10 | function EditTable( 11 | // The plugin options 12 | optionsParam?: OptionsFormat 13 | ): Object { 14 | const opts = new Options(optionsParam || {}); 15 | const corePlugin = core(opts); 16 | 17 | return { 18 | ...corePlugin, 19 | 20 | onKeyDown: onKeyDown.bind(null, opts), 21 | onCopy: onCopy.bind(null, opts), 22 | onPaste: onPaste.bind(null, opts) 23 | }; 24 | } 25 | 26 | export type TablePosition = _TablePosition; 27 | 28 | export default EditTable; 29 | -------------------------------------------------------------------------------- /lib/options.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import { Record } from 'immutable'; 4 | import type { Node } from '@gitbook/slate'; 5 | 6 | export type OptionsFormat = { 7 | typeTable?: string, 8 | typeRow?: string, 9 | typeCell?: string, 10 | typeContent?: string, 11 | exitBlockType?: string 12 | }; 13 | 14 | /** 15 | * The plugin options 16 | */ 17 | class Options extends Record({ 18 | typeTable: 'table', 19 | typeRow: 'table_row', 20 | typeCell: 'table_cell', 21 | typeContent: 'paragraph', 22 | exitBlockType: 'paragraph' 23 | }) { 24 | // The type of table blocks 25 | typeTable: string; 26 | // The type of row blocks 27 | typeRow: string; 28 | // The type of cell blocks 29 | typeCell: string; 30 | // The default type for blocks in cells 31 | typeContent: string; 32 | // The type of block inserted when exiting 33 | exitBlockType: string; 34 | 35 | /* 36 | * Return a node filter to find a cell. 37 | */ 38 | isCell = (node: Node): boolean => 39 | node.object == 'block' && node.type == this.typeCell; 40 | } 41 | 42 | export default Options; 43 | -------------------------------------------------------------------------------- /lib/utils/createCell.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { Block, Text, type Node } from '@gitbook/slate'; 3 | 4 | import type Options from '../options'; 5 | 6 | /** 7 | * Create a new cell 8 | */ 9 | function createCell(opts: Options, nodes?: Node[]): Block { 10 | return Block.create({ 11 | type: opts.typeCell, 12 | nodes: nodes || [createEmptyContent(opts)] 13 | }); 14 | } 15 | 16 | /** 17 | * Create a new default content block 18 | */ 19 | function createEmptyContent(opts: Options): Block { 20 | return Block.create({ 21 | type: opts.typeContent, 22 | nodes: [Text.create()] 23 | }); 24 | } 25 | 26 | export default createCell; 27 | -------------------------------------------------------------------------------- /lib/utils/createRow.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { Range } from 'immutable'; 3 | import { Block, type Node } from '@gitbook/slate'; 4 | 5 | import type Options from '../options'; 6 | import createCell from './createCell'; 7 | 8 | /** 9 | * Create a new row block 10 | */ 11 | function createRow( 12 | opts: Options, 13 | columns: number, 14 | getCellContent?: (column: number) => Node[] 15 | ): Block { 16 | const cellNodes = Range(0, columns) 17 | .map(i => 18 | createCell(opts, getCellContent ? getCellContent(i) : undefined) 19 | ) 20 | .toList(); 21 | 22 | return Block.create({ 23 | type: opts.typeRow, 24 | nodes: cellNodes 25 | }); 26 | } 27 | 28 | export default createRow; 29 | -------------------------------------------------------------------------------- /lib/utils/createTable.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { Range } from 'immutable'; 3 | import { Block, type Node } from '@gitbook/slate'; 4 | 5 | import type Options from '../options'; 6 | import createRow from './createRow'; 7 | 8 | /** 9 | * Create a table 10 | */ 11 | function createTable( 12 | opts: Options, 13 | columns: number, 14 | rows: number, 15 | getCellContent?: (row: number, column: number) => Node[] 16 | ): Block { 17 | const rowNodes = Range(0, rows) 18 | .map(i => 19 | createRow( 20 | opts, 21 | columns, 22 | getCellContent ? getCellContent.bind(null, i) : undefined 23 | ) 24 | ) 25 | .toList(); 26 | 27 | return Block.create({ 28 | type: opts.typeTable, 29 | nodes: rowNodes 30 | }); 31 | } 32 | 33 | export default createTable; 34 | -------------------------------------------------------------------------------- /lib/utils/forEachCells.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Block } from '@gitbook/slate'; 3 | 4 | import type Options from '../options'; 5 | 6 | /** 7 | * Run the given function against each cells of the table 8 | */ 9 | function forEachCells( 10 | opts: Options, 11 | // The table 12 | table: Block, 13 | fn: (cell: Block, row: number, column: number) => any 14 | ): void { 15 | return table.nodes.forEach((row, rowIndex) => 16 | row.nodes.forEach((cell, columnIndex) => 17 | fn(cell, rowIndex, columnIndex) 18 | ) 19 | ); 20 | } 21 | 22 | export default forEachCells; 23 | -------------------------------------------------------------------------------- /lib/utils/getCellsAtColumn.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Block } from '@gitbook/slate'; 3 | import { type List } from 'immutable'; 4 | 5 | import type Options from '../options'; 6 | 7 | /** 8 | * Returns the list of cells at the given column index 9 | */ 10 | function getCellsAtColumn( 11 | opts: Options, 12 | // The table 13 | table: Block, 14 | columnIndex: number 15 | ): List { 16 | return table.nodes.map(row => row.nodes.get(columnIndex)); 17 | } 18 | 19 | export default getCellsAtColumn; 20 | -------------------------------------------------------------------------------- /lib/utils/getCellsAtRow.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Block } from '@gitbook/slate'; 3 | import { type List } from 'immutable'; 4 | 5 | import type Options from '../options'; 6 | 7 | /** 8 | * Returns the list of cells at the given row index 9 | */ 10 | function getCellsAtRow( 11 | opts: Options, 12 | // The table 13 | table: Block, 14 | rowIndex: number 15 | ): List { 16 | return table.nodes.get(rowIndex).nodes; 17 | } 18 | 19 | export default getCellsAtRow; 20 | -------------------------------------------------------------------------------- /lib/utils/getPosition.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Value } from '@gitbook/slate'; 3 | 4 | import type Options from '../options'; 5 | 6 | import TablePosition from './TablePosition'; 7 | 8 | /** 9 | * The position of the selection start block, in the current table 10 | */ 11 | function getPosition( 12 | opts: Options, 13 | // The current value 14 | value: Value 15 | ): TablePosition { 16 | return TablePosition.create(opts, value.document, value.startKey); 17 | } 18 | 19 | export default getPosition; 20 | -------------------------------------------------------------------------------- /lib/utils/getPositionByKey.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Node } from '@gitbook/slate'; 3 | 4 | import type Options from '../options'; 5 | 6 | import TablePosition from './TablePosition'; 7 | 8 | /* 9 | * The position of a particular node, in the current table 10 | */ 11 | function getPositionByKey( 12 | opts: Options, 13 | // The current value 14 | containerNode: Node, 15 | // Key of the node in desired position 16 | key: string 17 | ): TablePosition { 18 | return TablePosition.create(opts, containerNode, key); 19 | } 20 | 21 | export default getPositionByKey; 22 | -------------------------------------------------------------------------------- /lib/utils/getRow.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { type Value } from '@gitbook/slate'; 3 | 4 | import type Options from '../options'; 5 | 6 | import TablePosition from './TablePosition'; 7 | 8 | /** 9 | * The position of the selection start block, in the current table 10 | */ 11 | function getPosition( 12 | opts: Options, 13 | // The current value 14 | value: Value 15 | ): TablePosition { 16 | return TablePosition.create(opts, value.document, value.startKey); 17 | } 18 | 19 | export default getPosition; 20 | -------------------------------------------------------------------------------- /lib/utils/index.js: -------------------------------------------------------------------------------- 1 | import createCell from './createCell'; 2 | import createRow from './createRow'; 3 | import createTable from './createTable'; 4 | import getPosition from './getPosition'; 5 | import getPositionByKey from './getPositionByKey'; 6 | import isRangeInTable from './isRangeInTable'; 7 | import isSelectionInTable from './isSelectionInTable'; 8 | import isSelectionOutOfTable from './isSelectionOutOfTable'; 9 | import TablePosition from './TablePosition'; 10 | import forEachCells from './forEachCells'; 11 | import getCellsAtRow from './getCellsAtRow'; 12 | import getCellsAtColumn from './getCellsAtColumn'; 13 | import getCopiedFragment from './getCopiedFragment'; 14 | 15 | export { 16 | getPosition, 17 | getPositionByKey, 18 | forEachCells, 19 | getCellsAtRow, 20 | getCellsAtColumn, 21 | isRangeInTable, 22 | isSelectionInTable, 23 | isSelectionOutOfTable, 24 | TablePosition, 25 | createCell, 26 | createRow, 27 | createTable, 28 | getCopiedFragment 29 | }; 30 | -------------------------------------------------------------------------------- /lib/utils/isRangeInTable.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import type { Node, Range } from '@gitbook/slate'; 4 | 5 | import TablePosition from './TablePosition'; 6 | import type Options from '../options'; 7 | 8 | /** 9 | * True if the given range is inside one table 10 | */ 11 | function isRangeInTable(opts: Options, node: Node, range: Range): boolean { 12 | const { startKey, endKey } = range; 13 | const startPosition = TablePosition.create(opts, node, startKey); 14 | const endPosition = TablePosition.create(opts, node, endKey); 15 | 16 | // Only handle events in tables 17 | if (!startPosition.isInTable() || !endPosition.isInTable()) { 18 | return false; 19 | } 20 | 21 | // Inside the same table 22 | return startPosition.table === endPosition.table; 23 | } 24 | 25 | export default isRangeInTable; 26 | -------------------------------------------------------------------------------- /lib/utils/isSelectionInTable.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import type { Value } from '@gitbook/slate'; 4 | 5 | import type Options from '../options'; 6 | import isRangeInTable from './isRangeInTable'; 7 | 8 | /** 9 | * Is the selection in a table 10 | */ 11 | function isSelectionInTable(opts: Options, value: Value): boolean { 12 | if (!value.selection.startKey) return false; 13 | return isRangeInTable(opts, value.document, value.selection); 14 | } 15 | 16 | export default isSelectionInTable; 17 | -------------------------------------------------------------------------------- /lib/utils/isSelectionOutOfTable.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import type { Value } from '@gitbook/slate'; 4 | 5 | import TablePosition from './TablePosition'; 6 | import type Options from '../options'; 7 | 8 | /** 9 | * Are the selection start and end outside a table. 10 | */ 11 | function isSelectionOutOfTable(opts: Options, value: Value): boolean { 12 | if (!value.selection.startKey) return false; 13 | 14 | const { startKey, endKey } = value; 15 | 16 | const startPosition = TablePosition.create(opts, value.document, startKey); 17 | const endPosition = TablePosition.create(opts, value.document, endKey); 18 | 19 | // Only handle events in tables 20 | return !startPosition.isInTable() && !endPosition.isInTable(); 21 | } 22 | 23 | export default isSelectionOutOfTable; 24 | -------------------------------------------------------------------------------- /lib/validation/index.js: -------------------------------------------------------------------------------- 1 | import schema from './schema'; 2 | import validateNode from './validateNode'; 3 | 4 | export { schema, validateNode }; 5 | -------------------------------------------------------------------------------- /lib/validation/validateNode.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import type Options from '../options'; 4 | import { createCell } from '../utils'; 5 | 6 | /* 7 | * Ensure each row has the same number of columns. 8 | */ 9 | function validateNode(opts: Options) { 10 | const isRow = node => node.type === opts.typeRow; 11 | const isCell = node => node.type === opts.typeCell; 12 | const countCells = row => row.nodes.count(isCell); 13 | 14 | return node => { 15 | if (node.type !== opts.typeTable) { 16 | return undefined; 17 | } 18 | 19 | const rows = node.nodes.filter(isRow); 20 | const maxColumns = Math.max( 21 | // Minimum 1 column 22 | 1, 23 | rows.map(countCells).max() 24 | ); 25 | const rowsMissingColumns = rows.filter( 26 | row => countCells(row) < maxColumns 27 | ); 28 | 29 | if (rowsMissingColumns.isEmpty()) { 30 | return undefined; 31 | } 32 | 33 | return change => { 34 | rowsMissingColumns.forEach(row => { 35 | const numberOfCellsToAdd = maxColumns - row.nodes.size; 36 | const cells = Array.from({ length: numberOfCellsToAdd }).map( 37 | () => createCell(opts) 38 | ); 39 | cells.forEach(cell => 40 | change.insertNodeByKey(row.key, row.nodes.size, cell, { 41 | normalize: false 42 | }) 43 | ); 44 | }); 45 | }; 46 | }; 47 | } 48 | 49 | export default validateNode; 50 | -------------------------------------------------------------------------------- /tests/backspace-after-inline/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | let isDefaultPrevented = false; 5 | const result = plugin.onKeyDown( 6 | { 7 | key: 'Backspace', 8 | preventDefault() { 9 | isDefaultPrevented = true; 10 | }, 11 | stopPropagation() {} 12 | }, 13 | change 14 | ); 15 | 16 | // It shouldn't alter the default behavior... 17 | expect(isDefaultPrevented).toBe(false); 18 | 19 | // ...and let Slate do the work 20 | expect(result).toBe(undefined); 21 | 22 | return change; 23 | } 24 | -------------------------------------------------------------------------------- /tests/backspace-cell-boundaries/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | return plugin.onKeyDown( 3 | { 4 | key: 'Backspace', 5 | preventDefault() {}, 6 | stopPropagation() {} 7 | }, 8 | change 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /tests/backspace-cell-boundaries/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/backspace-clear-cells-with-multiple-blocks/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const blockStart = value.document.getDescendant('anchor'); 4 | const blockEnd = value.document.getDescendant('focus'); 5 | 6 | const withCursor = change 7 | .collapseToStartOf(blockStart) 8 | .extendToEndOf(blockEnd); 9 | 10 | return plugin.onKeyDown( 11 | { 12 | key: 'Backspace', 13 | preventDefault() {}, 14 | stopPropagation() {} 15 | }, 16 | withCursor 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /tests/backspace-clear-cells-with-multiple-blocks/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Col 1, Row 2 36 | Second block 37 | 38 | 39 | Col 2, Row 2 40 | 41 | 42 |
43 |
44 |
45 | ); 46 | -------------------------------------------------------------------------------- /tests/backspace-clear-cells/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const blockStart = value.document.getDescendant('anchor'); 4 | const blockEnd = value.document.getDescendant('focus'); 5 | 6 | const withCursor = change 7 | .collapseToStartOf(blockStart) 8 | .extendToEndOf(blockEnd); 9 | 10 | return plugin.onKeyDown( 11 | { 12 | key: 'Backspace', 13 | preventDefault() {}, 14 | stopPropagation() {} 15 | }, 16 | withCursor 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /tests/backspace-clear-cells/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/backspace-clear-cells/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/backspace-collapsed/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const blockStart = value.document.getDescendant('anchor'); 4 | 5 | const withCursor = change.collapseToStartOf(blockStart); 6 | 7 | plugin.onKeyDown( 8 | { 9 | key: 'Backspace', 10 | preventDefault() {}, 11 | stopPropagation() {} 12 | }, 13 | withCursor 14 | ); 15 | 16 | return change; 17 | } 18 | -------------------------------------------------------------------------------- /tests/backspace-collapsed/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/backspace-collapsed/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/backspace-delete-void/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const res = plugin.onKeyDown( 5 | { 6 | key: 'Backspace', 7 | preventDefault() {}, 8 | stopPropagation() {} 9 | }, 10 | change 11 | ); 12 | 13 | expect(res).toBe(undefined); 14 | 15 | return change; 16 | } 17 | -------------------------------------------------------------------------------- /tests/backspace-multiple-blocks-collapsed/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const result = plugin.onKeyDown( 5 | { 6 | key: 'Backspace', 7 | preventDefault() {}, 8 | stopPropagation() {} 9 | }, 10 | change 11 | ); 12 | 13 | expect(result).toBe(undefined); 14 | 15 | return change; 16 | } 17 | -------------------------------------------------------------------------------- /tests/backspace-multiple-blocks-expanded/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const result = plugin.onKeyDown( 5 | { 6 | key: 'Backspace', 7 | preventDefault() {}, 8 | stopPropagation() {} 9 | }, 10 | change 11 | ); 12 | 13 | expect(result).toBe(undefined); 14 | 15 | return change; 16 | } 17 | -------------------------------------------------------------------------------- /tests/backspace-same-block/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | const blockStart = value.document.getDescendant('anchor'); 6 | const blockEnd = value.document.getDescendant('anchor'); 7 | 8 | const withCursor = change 9 | .collapseToStartOf(blockStart) 10 | .extendToEndOf(blockEnd); 11 | 12 | const result = plugin.onKeyDown( 13 | { 14 | key: 'Backspace', 15 | preventDefault() {}, 16 | stopPropagation() {} 17 | }, 18 | withCursor 19 | ); 20 | 21 | expect(result).toBe(undefined); 22 | 23 | return change; 24 | } 25 | -------------------------------------------------------------------------------- /tests/backspace-same-block/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/backspace-start-cell/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | const blockStart = value.document.getDescendant('anchor'); 6 | const withCursor = change.collapseToStartOf(blockStart); 7 | 8 | let isDefaultPrevented = false; 9 | const result = plugin.onKeyDown( 10 | { 11 | key: 'Backspace', 12 | preventDefault() { 13 | isDefaultPrevented = true; 14 | }, 15 | stopPropagation() {} 16 | }, 17 | withCursor 18 | ); 19 | 20 | // It should have prevented the default behavior... 21 | expect(isDefaultPrevented).toBe(true); 22 | 23 | // ...and left the change unchanged 24 | expect(result).toBe(change); 25 | 26 | return change; 27 | } 28 | -------------------------------------------------------------------------------- /tests/backspace-start-cell/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/backspace-start-cell/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/backspace-whole-cell/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const res = plugin.onKeyDown( 5 | { 6 | key: 'Backspace', 7 | preventDefault() {}, 8 | stopPropagation() {} 9 | }, 10 | change 11 | ); 12 | 13 | expect(res).toBe(undefined); 14 | 15 | return change; 16 | } 17 | -------------------------------------------------------------------------------- /tests/enter-split-block/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const blockStart = change.value.document.getDescendant('anchor'); 5 | const withCursor = change.collapseToEndOf(blockStart); 6 | 7 | const result = plugin.onKeyDown( 8 | { 9 | key: 'Enter', 10 | preventDefault() {}, 11 | stopPropagation() {} 12 | }, 13 | withCursor 14 | ); 15 | 16 | expect(result.value.startBlock.type).toBe('paragraph'); 17 | 18 | return result; 19 | } 20 | -------------------------------------------------------------------------------- /tests/enter-split-block/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/get-cells-at-column/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | const pos = plugin.utils.getPosition(change.value); 7 | 8 | const cells = plugin.utils.getCellsAtColumn( 9 | pos.table, 10 | pos.getColumnIndex() 11 | ); 12 | cells.forEach(cell => 13 | change.setNodeByKey(cell.key, { data: { custom: 'value' } }) 14 | ); 15 | return change; 16 | } 17 | -------------------------------------------------------------------------------- /tests/get-cells-at-column/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 1, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/get-cells-at-column/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 1, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/get-cells-at-row/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | const pos = plugin.utils.getPosition(change.value); 7 | 8 | const cells = plugin.utils.getCellsAtRow(pos.table, pos.getRowIndex()); 9 | cells.forEach(cell => 10 | change.setNodeByKey(cell.key, { data: { custom: 'value' } }) 11 | ); 12 | return change; 13 | } 14 | -------------------------------------------------------------------------------- /tests/get-cells-at-row/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 1, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/get-cells-at-row/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 1, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/get-position-by-key/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const table = change.value.document.getClosest( 5 | 'cell', 6 | el => el.key === 'table' 7 | ); 8 | const position = plugin.utils.getPositionByKey(table, 'cell'); 9 | 10 | expect(position.getWidth()).toEqual(3); 11 | expect(position.getHeight()).toEqual(3); 12 | expect(position.getRowIndex()).toEqual(1); 13 | expect(position.getColumnIndex()).toEqual(1); 14 | 15 | return change; 16 | } 17 | -------------------------------------------------------------------------------- /tests/get-position-by-key/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/get-position/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const position = plugin.utils.getPosition(change.value); 5 | 6 | expect(position.getWidth()).toEqual(3); 7 | expect(position.getHeight()).toEqual(3); 8 | expect(position.getRowIndex()).toEqual(1); 9 | expect(position.getColumnIndex()).toEqual(1); 10 | 11 | return change; 12 | } 13 | -------------------------------------------------------------------------------- /tests/hyperscript.js: -------------------------------------------------------------------------------- 1 | import { createHyperscript } from '@gitbook/slate-hyperscript'; 2 | 3 | const h = createHyperscript({ 4 | blocks: { 5 | heading: 'heading', 6 | paragraph: 'paragraph', 7 | table: 'table', 8 | table_row: 'table_row', 9 | table_cell: 'table_cell', 10 | image: { 11 | type: 'image', 12 | isVoid: true 13 | } 14 | }, 15 | inlines: { 16 | link: 'link' 17 | } 18 | }); 19 | 20 | export default h; 21 | -------------------------------------------------------------------------------- /tests/insert-column-at/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.insertColumn(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/insert-column-at/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | 14 | 15 | 16 | Col 1, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | 25 | 26 | 27 | Col 1, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | 36 | 37 | 38 | Col 1, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/insert-column-at/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 1, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/insert-column-preserve-data/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.insertColumn(change, 1); 7 | } 8 | -------------------------------------------------------------------------------- /tests/insert-column-preserve-data/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | 14 | 15 | 16 | Col 1, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | 25 | 26 | 27 | Col 1, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | 36 | 37 | 38 | Col 1, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/insert-column-preserve-data/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 1, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/insert-column/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.insertColumn(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/insert-column/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/insert-column/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 1, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/insert-row/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.insertRow(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/insert-row/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/insert-row/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/insert-table/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock).move(6); // Cursor here: Before|After 5 | 6 | return plugin.changes.insertTable(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/insert-table/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | Before 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | ); 29 | -------------------------------------------------------------------------------- /tests/insert-table/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | BeforeAfter 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /tests/mod-enter-exit-table/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const blockStart = change.value.document.getDescendant('anchor'); 5 | const withCursor = change.collapseToStartOf(blockStart); 6 | 7 | const result = plugin.onKeyDown( 8 | { 9 | key: 'Enter', 10 | metaKey: true, 11 | preventDefault() {}, 12 | stopPropagation() {} 13 | }, 14 | withCursor 15 | ); 16 | 17 | expect(result.value.startBlock.type).toBe('paragraph'); 18 | 19 | return result; 20 | } 21 | -------------------------------------------------------------------------------- /tests/mod-enter-exit-table/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 | 43 |
44 |
45 | ); 46 | -------------------------------------------------------------------------------- /tests/mod-enter-exit-table/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/move-selection-by/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | const cursorBlock = value.document.getDescendant('anchor'); 6 | const offset = 2; 7 | change.moveToRangeOf(cursorBlock).move(offset); 8 | 9 | plugin.changes.moveSelectionBy(change, -1, -1); 10 | 11 | expect(change.value.startBlock.text).toEqual('Col 0, Row 0'); 12 | const selection = change.value.selection; 13 | expect(selection.startKey).toEqual(selection.endKey); 14 | 15 | return change; 16 | } 17 | -------------------------------------------------------------------------------- /tests/move-selection-by/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/move-selection-by/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/move-selection/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | const cursorBlock = value.document.getDescendant('anchor'); 6 | const offset = 2; 7 | change.moveToRangeOf(cursorBlock).move(offset); 8 | 9 | plugin.changes.moveSelection(change, 2, 2); 10 | 11 | expect(change.value.startBlock.text).toEqual('Col 2, Row 2'); 12 | const selection = change.value.selection; 13 | expect(selection.startKey).toEqual(selection.endKey); 14 | 15 | return change; 16 | } 17 | -------------------------------------------------------------------------------- /tests/move-selection/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/move-selection/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/on-shift-tab-first-cell/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | change.moveToRangeOf(cursorBlock); 6 | 7 | plugin.onKeyDown( 8 | { 9 | key: 'Tab', 10 | shiftKey: true, 11 | preventDefault() {}, 12 | stopPropagation() {} 13 | }, 14 | change 15 | ); 16 | 17 | const position = plugin.utils.getPosition(change.value); 18 | 19 | // First row (new one) 20 | expect(position.getRowIndex()).toEqual(0); 21 | // Last cell 22 | expect(position.getColumnIndex()).toEqual(2); 23 | 24 | return change; 25 | } 26 | -------------------------------------------------------------------------------- /tests/on-shift-tab-first-cell/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Col 0, Row 0 22 | 23 | 24 | Col 1, Row 0 25 | 26 | 27 | Col 2, Row 0 28 | 29 | 30 | 31 | 32 | Col 0, Row 1 33 | 34 | 35 | Col 1, Row 1 36 | 37 | 38 | Col 2, Row 1 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/on-shift-tab-first-cell/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/on-shift-tab/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | change.moveToRangeOf(cursorBlock); 6 | 7 | const initialPosition = plugin.utils.getPosition(change.value); 8 | 9 | plugin.onKeyDown( 10 | { 11 | key: 'Tab', 12 | shiftKey: true, 13 | preventDefault() {}, 14 | stopPropagation() {} 15 | }, 16 | change 17 | ); 18 | 19 | const position = plugin.utils.getPosition(change.value); 20 | 21 | // Same row 22 | expect(position.getRowIndex()).toEqual(initialPosition.getRowIndex()); 23 | // Moved to previous column 24 | expect(position.getColumnIndex()).toEqual( 25 | initialPosition.getColumnIndex() - 1 26 | ); 27 | 28 | return change; 29 | } 30 | -------------------------------------------------------------------------------- /tests/on-shift-tab/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/on-shift-tab/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/on-tab-last-cell/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | change.moveToRangeOf(cursorBlock); 6 | 7 | plugin.onKeyDown( 8 | { 9 | key: 'Tab', 10 | preventDefault() {}, 11 | stopPropagation() {} 12 | }, 13 | change 14 | ); 15 | 16 | const position = plugin.utils.getPosition(change.value); 17 | 18 | // Last row (new one) 19 | expect(position.getRowIndex()).toEqual(2); 20 | // First cell 21 | expect(position.getColumnIndex()).toEqual(0); 22 | 23 | return change; 24 | } 25 | -------------------------------------------------------------------------------- /tests/on-tab-last-cell/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/on-tab-last-cell/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/on-tab-last-column/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | change.moveToRangeOf(cursorBlock); 6 | 7 | const initialPosition = plugin.utils.getPosition(change.value); 8 | 9 | plugin.onKeyDown( 10 | { 11 | key: 'Tab', 12 | preventDefault() {}, 13 | stopPropagation() {} 14 | }, 15 | change 16 | ); 17 | 18 | const position = plugin.utils.getPosition(change.value); 19 | 20 | // Next row 21 | expect(position.getRowIndex()).toEqual(initialPosition.getRowIndex() + 1); 22 | // Moved to first column 23 | expect(position.getColumnIndex()).toEqual(0); 24 | 25 | return change; 26 | } 27 | -------------------------------------------------------------------------------- /tests/on-tab-last-column/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/on-tab-last-column/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/on-tab/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | change.moveToRangeOf(cursorBlock); 6 | 7 | const initialPosition = plugin.utils.getPosition(change.value); 8 | 9 | plugin.onKeyDown( 10 | { 11 | key: 'Tab', 12 | preventDefault() {}, 13 | stopPropagation() {} 14 | }, 15 | change 16 | ); 17 | 18 | const position = plugin.utils.getPosition(change.value); 19 | 20 | // Same row 21 | expect(position.getRowIndex()).toEqual(initialPosition.getRowIndex()); 22 | // Moved to next column 23 | expect(position.getColumnIndex()).toEqual( 24 | initialPosition.getColumnIndex() + 1 25 | ); 26 | 27 | return change; 28 | } 29 | -------------------------------------------------------------------------------- /tests/on-tab/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/on-tab/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/paste-content-into-cell/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | 6 | // Copy the selection 7 | let copiedFragment = plugin.utils.getCopiedFragment(value); 8 | // Default copy in this case 9 | expect(copiedFragment).toBeFalsy(); 10 | 11 | copiedFragment = value.fragment; 12 | 13 | // Paste it 14 | return change 15 | .select({ 16 | anchorKey: 'cell', 17 | anchorOffset: 0, 18 | focusKey: 'cell', 19 | focusOffset: 5 20 | }) 21 | .insertFragment(copiedFragment); 22 | } 23 | -------------------------------------------------------------------------------- /tests/paste-content-into-cell/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Elsewhere, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 |
25 | Elsewhere 26 |
27 |
28 | ); 29 | -------------------------------------------------------------------------------- /tests/paste-content-into-cell/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | 14 | Col 1, Row 0 15 | 16 | 17 | 18 | 19 | 20 | Col 0, Row 1 21 | 22 | 23 | Col 1, Row 1 24 | 25 | 26 |
27 | 28 | 29 | Elsewhere 30 | 31 | 32 |
33 |
34 | ); 35 | -------------------------------------------------------------------------------- /tests/paste-empty-cell-into-cell/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | 6 | // Copy the selection 7 | const copiedFragment = plugin.utils.getCopiedFragment(value); 8 | expect(copiedFragment).toBeTruthy(); 9 | 10 | // Paste it 11 | return change 12 | .select({ 13 | anchorKey: 'paste-here', 14 | anchorOffset: 7, 15 | focusKey: 'paste-here', 16 | focusOffset: 7 17 | }) 18 | .insertFragment(copiedFragment); 19 | } 20 | -------------------------------------------------------------------------------- /tests/paste-empty-cell-into-cell/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 |
25 |
26 |
27 | ); 28 | -------------------------------------------------------------------------------- /tests/paste-empty-cell-into-cell/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | Col 0, Row 0 12 | 13 | 14 | 15 | 16 | Col 1, Row 0 17 | 18 | 19 | 20 | 21 | 22 | Col 0, Row 1 23 | 24 | 25 | Col 1, Row 1 26 | 27 | 28 |
29 |
30 |
31 | ); 32 | -------------------------------------------------------------------------------- /tests/paste-multiple-cells-at-same-position/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | 6 | // Copy the selection 7 | const copiedFragment = plugin.utils.getCopiedFragment(value); 8 | // Default copy in this case 9 | expect(copiedFragment).toBeTruthy(); 10 | 11 | // Paste it 12 | change.collapseToAnchor(); 13 | 14 | return plugin.changes.insertTableFragmentAtRange( 15 | change, 16 | change.value.selection, 17 | copiedFragment 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /tests/paste-multiple-cells-at-same-position/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0 19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 |
27 | ); 28 | -------------------------------------------------------------------------------- /tests/paste-multiple-cells-at-same-position/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | Col 0, Row 0 12 | 13 | 14 | 15 | Col 1, Row 0 16 | 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | 25 | Col 1, Row 1 26 | 27 | 28 |
29 |
30 |
31 | ); 32 | -------------------------------------------------------------------------------- /tests/paste-multiple-cells-into-table/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | 6 | // Copy the selection 7 | const copiedFragment = plugin.utils.getCopiedFragment(value); 8 | // Default copy in this case 9 | expect(copiedFragment).toBeTruthy(); 10 | 11 | // Paste it 12 | change.collapseToFocus(); 13 | 14 | return plugin.changes.insertTableFragmentAtRange( 15 | change, 16 | change.value.selection, 17 | copiedFragment 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /tests/paste-multiple-cells-into-table/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Row 0 19 | 20 | 21 | Col 1, Row 0 22 | 23 | 24 | 25 | 26 | Col 0 27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/paste-multiple-cells-into-table/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | Col 0, Row 0 12 | 13 | 14 | 15 | Col 1, Row 0 16 | 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | 25 | Col 1, Row 1 26 | 27 | 28 |
29 |
30 |
31 | ); 32 | -------------------------------------------------------------------------------- /tests/paste-multiple-cells-outside/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | 6 | // Copy the selection 7 | const copiedFragment = plugin.utils.getCopiedFragment(value); 8 | // Default copy in this case 9 | expect(copiedFragment).toBeTruthy(); 10 | 11 | // Paste it 12 | return change 13 | .select({ 14 | anchorKey: 'paste-here', 15 | anchorOffset: 4, 16 | focusKey: 'paste-here', 17 | focusOffset: 4 18 | }) 19 | .insertFragment(copiedFragment); 20 | } 21 | -------------------------------------------------------------------------------- /tests/paste-multiple-cells-outside/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 |
25 | Else 26 | 27 | 28 | 29 | 30 | 31 | 32 | Col 1, Row 0 33 | 34 | 35 | 36 | 37 | Col 0, Row 1 38 | 39 | 40 | 41 | 42 | 43 |
44 | where 45 |
46 |
47 | ); 48 | -------------------------------------------------------------------------------- /tests/paste-multiple-cells-outside/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | 14 | Col 1, Row 0 15 | 16 | 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | 25 | Col 1, Row 1 26 | 27 | 28 |
29 | 30 | Elsewhere 31 | 32 |
33 |
34 | ); 35 | -------------------------------------------------------------------------------- /tests/paste-single-cell-into-cell/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | 6 | // Copy the selection 7 | const copiedFragment = plugin.utils.getCopiedFragment(value); 8 | expect(copiedFragment).toBeTruthy(); 9 | 10 | // Paste it 11 | return change 12 | .select({ 13 | anchorKey: 'paste-here', 14 | anchorOffset: 7, 15 | focusKey: 'paste-here', 16 | focusOffset: 7 17 | }) 18 | .insertFragment(copiedFragment); 19 | } 20 | -------------------------------------------------------------------------------- /tests/paste-single-cell-into-cell/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Col 0, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 |
25 |
26 |
27 | ); 28 | -------------------------------------------------------------------------------- /tests/paste-single-cell-into-cell/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | Col 0, Row 0 12 | 13 | 14 | 15 | 16 | Col 1, Row 0 17 | 18 | 19 | 20 | 21 | 22 | Col 0, Row 1 23 | 24 | 25 | Col 1, Row 1 26 | 27 | 28 |
29 |
30 |
31 | ); 32 | -------------------------------------------------------------------------------- /tests/paste-single-cell-outside/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | 6 | // Copy the selection 7 | const copiedFragment = plugin.utils.getCopiedFragment(value); 8 | expect(copiedFragment).toBeTruthy(); 9 | 10 | // Paste it 11 | return change 12 | .select({ 13 | anchorKey: 'paste-here', 14 | anchorOffset: 4, 15 | focusKey: 'paste-here', 16 | focusOffset: 4 17 | }) 18 | .insertFragment(copiedFragment); 19 | } 20 | -------------------------------------------------------------------------------- /tests/paste-single-cell-outside/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 |
25 | ElseCol 0where 26 |
27 |
28 | ); 29 | -------------------------------------------------------------------------------- /tests/paste-single-cell-outside/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | Col 0, Row 0 12 | 13 | 14 | 15 | Col 1, Row 0 16 | 17 | 18 | 19 | 20 | Col 0, Row 1 21 | 22 | 23 | Col 1, Row 1 24 | 25 | 26 |
27 | 28 | Elsewhere 29 | 30 |
31 |
32 | ); 33 | -------------------------------------------------------------------------------- /tests/remove-column-at/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | return plugin.changes.removeColumn(change, 0); 3 | } 4 | -------------------------------------------------------------------------------- /tests/remove-column-at/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 1, Row 0 11 | 12 | 13 | Col 2, Row 0 14 | 15 | 16 | 17 | 18 | Col 1, Row 1 19 | 20 | 21 | Col 2, Row 1 22 | 23 | 24 | 25 | 26 | Col 1, Row 2 27 | 28 | 29 | Col 2, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/remove-column-first/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.removeColumn(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/remove-column-first/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 1, Row 0 11 | 12 | 13 | Col 2, Row 0 14 | 15 | 16 | 17 | 18 | Col 1, Row 1 19 | 20 | 21 | Col 2, Row 1 22 | 23 | 24 | 25 | 26 | Col 1, Row 2 27 | 28 | 29 | Col 2, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/remove-column-first/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/remove-column-last-one/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.removeColumn(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/remove-column-last-one/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 |
26 | ); 27 | -------------------------------------------------------------------------------- /tests/remove-column-last-one/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | 14 | 15 | Col 0, Row 1 16 | 17 | 18 | 19 | 20 | Col 0, Row 2 21 | 22 | 23 |
24 |
25 |
26 | ); 27 | -------------------------------------------------------------------------------- /tests/remove-column-preserve-data/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.removeColumn(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/remove-column-preserve-data/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 2, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 2, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 2, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/remove-column-preserve-data/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/remove-column/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToStartOf(cursorBlock); 5 | 6 | return plugin.changes.removeColumn(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/remove-column/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 2, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 2, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 2, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/remove-column/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/remove-row-at/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | return plugin.changes.removeRow(change, 1); 3 | } 4 | -------------------------------------------------------------------------------- /tests/remove-row-at/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 2 22 | 23 | 24 | Col 1, Row 2 25 | 26 | 27 | Col 2, Row 2 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/remove-row-first/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.removeRow(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/remove-row-first/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 1 11 | 12 | 13 | Col 1, Row 1 14 | 15 | 16 | Col 2, Row 1 17 | 18 | 19 | 20 | 21 | Col 0, Row 2 22 | 23 | 24 | Col 1, Row 2 25 | 26 | 27 | Col 2, Row 2 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/remove-row-first/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/remove-row-last-one/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.removeRow(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/remove-row-last-one/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |
22 | ); 23 | -------------------------------------------------------------------------------- /tests/remove-row-last-one/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 |
20 |
21 |
22 | ); 23 | -------------------------------------------------------------------------------- /tests/remove-row/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.removeRow(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/remove-row/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 2 22 | 23 | 24 | Col 1, Row 2 25 | 26 | 27 | Col 2, Row 2 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/remove-row/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/remove-table-and-move-to-next-block/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | change.moveToRangeOf(cursorBlock); 6 | 7 | plugin.changes.removeTable(change); 8 | expect(change.value.startBlock.key).toEqual('anchor_after'); 9 | expect(change.value.startOffset).toEqual(0); 10 | return change; 11 | } 12 | -------------------------------------------------------------------------------- /tests/remove-table-and-move-to-next-block/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | Before 8 | After 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /tests/remove-table-and-move-to-previous-block/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | change.moveToRangeOf(cursorBlock); 6 | 7 | plugin.changes.removeTable(change); 8 | expect(change.value.startBlock.key).toEqual('anchor_after'); 9 | expect(change.value.startOffset).toEqual( 10 | change.value.startBlock.text.length 11 | ); 12 | return change; 13 | } 14 | -------------------------------------------------------------------------------- /tests/remove-table-and-move-to-previous-block/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | Before 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /tests/remove-table-exit-with-none/change.js: -------------------------------------------------------------------------------- 1 | import EditTable from '../../lib'; 2 | 3 | export default function(prevPlugin, change) { 4 | const plugin = EditTable({ exitBlockType: null }); 5 | const cursorBlock = change.value.document.getDescendant('anchor'); 6 | change.moveToRangeOf(cursorBlock); 7 | 8 | return plugin.changes.removeTable(change); 9 | } 10 | -------------------------------------------------------------------------------- /tests/remove-table-exit-with-none/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /tests/remove-table-exit-with-paragraph/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | change.moveToRangeOf(cursorBlock); 6 | 7 | plugin.changes.removeTable(change); 8 | const { value } = change; 9 | expect(value.startBlock.type).toEqual('paragraph'); 10 | expect(change.value.startOffset) 11 | .toEqual(change.value.startBlock.text.length) 12 | .toEqual(0); 13 | return change; 14 | } 15 | -------------------------------------------------------------------------------- /tests/remove-table-exit-with-paragraph/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /tests/remove-table-exit-with-paragraph/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/remove-table/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const { value } = change; 3 | const cursorBlock = value.document.getDescendant('anchor'); 4 | change.moveToRangeOf(cursorBlock); 5 | 6 | return plugin.changes.removeTable(change); 7 | } 8 | -------------------------------------------------------------------------------- /tests/remove-table/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | Before 8 | After 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /tests/schema-no-blocks-within-rows/change.js: -------------------------------------------------------------------------------- 1 | import Slate from '@gitbook/slate'; 2 | 3 | export default (plugin, change) => { 4 | const schema = Slate.Schema.create(plugin.schema); 5 | return change.normalize(schema); 6 | }; 7 | -------------------------------------------------------------------------------- /tests/schema-no-blocks-within-rows/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Row 1, Col 1 11 | 12 | 13 | Row 1, Col 2 14 | 15 | 16 | Row 1, Col 3 17 | 18 | 19 | Row 1, Col 4 20 | 21 | 22 |
23 |
24 |
25 | ); 26 | -------------------------------------------------------------------------------- /tests/schema-no-blocks-within-rows/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Row 1, Col 1 11 | 12 | 13 | Row 1, Col 2 14 | 15 | 16 | Row 1, Col 3 17 | 18 | Row 1, Col 4 19 | 20 |
21 |
22 |
23 | ); 24 | -------------------------------------------------------------------------------- /tests/schema-no-blocks-within-table/change.js: -------------------------------------------------------------------------------- 1 | import Slate from '@gitbook/slate'; 2 | 3 | export default (plugin, change) => { 4 | const schema = Slate.Schema.create(plugin.schema); 5 | return change.normalize(schema); 6 | }; 7 | -------------------------------------------------------------------------------- /tests/schema-no-blocks-within-table/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Row 1, Col 1 11 | 12 | 13 | Row 1, Col 2 14 | 15 | 16 | Row 1, Col 3 17 | 18 | 19 |
20 |
21 |
22 | ); 23 | -------------------------------------------------------------------------------- /tests/schema-no-blocks-within-table/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Row 1, Col 1 11 | 12 | 13 | Row 1, Col 2 14 | 15 | 16 | Row 1, Col 3 17 | 18 | 19 | Row 1, Col 4 20 |
21 |
22 |
23 | ); 24 | -------------------------------------------------------------------------------- /tests/schema-only-blocks-within-cells/change.js: -------------------------------------------------------------------------------- 1 | import Slate from '@gitbook/slate'; 2 | 3 | export default (plugin, change) => { 4 | const schema = Slate.Schema.create(plugin.schema); 5 | return change.normalize(schema); 6 | }; 7 | -------------------------------------------------------------------------------- /tests/schema-only-blocks-within-cells/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | /* eslint-disable react/void-dom-elements-no-children */ 3 | import hyperscript from '../hyperscript'; 4 | 5 | export default ( 6 | 7 | 8 | 9 | 10 | 11 | Row 1, Col 1 12 | 13 | 14 | 15 | Row 1, Col 2 with some text 16 | 17 | 18 | 19 | Row 1, Col 3 20 | 21 | 22 |
23 |
24 |
25 | ); 26 | -------------------------------------------------------------------------------- /tests/schema-only-blocks-within-cells/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | /* eslint-disable react/void-dom-elements-no-children */ 3 | import hyperscript from '../hyperscript'; 4 | 5 | export default ( 6 | 7 | 8 | 9 | 10 | Row 1, Col 1 11 | 12 | 13 | Row 1, Col 2 with some text 14 | 15 | 16 | 17 | Row 1, Col 3 18 | 19 | 20 |
21 |
22 |
23 | ); 24 | -------------------------------------------------------------------------------- /tests/schema-orphan-cells/change.js: -------------------------------------------------------------------------------- 1 | import Slate from '@gitbook/slate'; 2 | 3 | export default (plugin, change) => { 4 | const schema = Slate.Schema.create(plugin.schema); 5 | return change.normalize(schema); 6 | }; 7 | -------------------------------------------------------------------------------- /tests/schema-orphan-cells/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Cell 1 11 | 12 | 13 |
14 | 15 | 16 | 17 | Cell 2 18 | 19 | 20 |
21 |
22 |
23 | ); 24 | -------------------------------------------------------------------------------- /tests/schema-orphan-cells/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | Cell 1 9 | 10 | 11 | Cell 2 12 | 13 | 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /tests/schema-rows-cells-within-tables/change.js: -------------------------------------------------------------------------------- 1 | import Slate from '@gitbook/slate'; 2 | 3 | export default (plugin, change) => { 4 | const schema = Slate.Schema.create(plugin.schema); 5 | return change.normalize(schema); 6 | }; 7 | -------------------------------------------------------------------------------- /tests/schema-rows-cells-within-tables/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | No table 11 | 12 | 13 |
14 | 15 | 16 | 17 | No rows 18 | 19 | 20 |
21 |
22 |
23 | ); 24 | -------------------------------------------------------------------------------- /tests/schema-rows-cells-within-tables/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | No table 8 | 9 | No rows 10 | 11 | 12 | 13 | ); 14 | -------------------------------------------------------------------------------- /tests/schema-rows-require-same-columns-counts/change.js: -------------------------------------------------------------------------------- 1 | import Slate from '@gitbook/slate'; 2 | 3 | export default (plugin, change) => { 4 | const schema = Slate.Schema.create(plugin.schema); 5 | return change.normalize(schema); 6 | }; 7 | -------------------------------------------------------------------------------- /tests/schema-rows-require-same-columns-counts/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Row 1, Col 1 11 | 12 | 13 | Row 1, Col 2 14 | 15 | 16 | Row 1, Col 3 17 | 18 | 19 | 20 | 21 | There is no columns here 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Row 3, Col 1 33 | 34 | 35 | Row 3, Col 2 36 | 37 | 38 | Row 3, Col 3 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/schema-rows-require-same-columns-counts/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Row 1, Col 1 11 | 12 | 13 | Row 1, Col 2 14 | 15 | 16 | Row 1, Col 3 17 | 18 | 19 | There is no columns here 20 | 21 | 22 | Row 3, Col 1 23 | 24 | Row 3, Col 2 25 | 26 | Row 3, Col 3 27 | 28 | 29 |
30 |
31 |
32 | ); 33 | -------------------------------------------------------------------------------- /tests/schema-standard-table/change.js: -------------------------------------------------------------------------------- 1 | import Slate from '@gitbook/slate'; 2 | 3 | export default (plugin, change) => { 4 | const schema = Slate.Schema.create(plugin.schema); 5 | return change.normalize(schema); 6 | }; 7 | -------------------------------------------------------------------------------- /tests/schema-standard-table/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/schema-standard-table/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/schema-tables-contain-rows-empty/change.js: -------------------------------------------------------------------------------- 1 | import Slate from '@gitbook/slate'; 2 | 3 | export default (plugin, change) => { 4 | const schema = Slate.Schema.create(plugin.schema); 5 | return change.normalize(schema); 6 | }; 7 | -------------------------------------------------------------------------------- /tests/schema-tables-contain-rows-empty/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /tests/schema-tables-contain-rows-empty/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | No rows
8 |
9 |
10 | ); 11 | -------------------------------------------------------------------------------- /tests/schema-tables-contain-rows-invalid/change.js: -------------------------------------------------------------------------------- 1 | import Slate from '@gitbook/slate'; 2 | 3 | export default (plugin, change) => { 4 | const schema = Slate.Schema.create(plugin.schema); 5 | return change.normalize(schema); 6 | }; 7 | -------------------------------------------------------------------------------- /tests/schema-tables-contain-rows-invalid/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Row 1, Col 1 11 | 12 | 13 | 14 | 15 | Row 3, Col 1 16 | 17 | 18 |
19 |
20 |
21 | ); 22 | -------------------------------------------------------------------------------- /tests/schema-tables-contain-rows-invalid/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Row 1, Col 1 11 | 12 | 13 | 14 | 15 | Row 2, Col 1 16 | 17 | 18 | 19 | 20 | Row 3, Col 1 21 | 22 | 23 |
24 |
25 |
26 | ); 27 | -------------------------------------------------------------------------------- /tests/schema-tables-contain-rows-mixed/change.js: -------------------------------------------------------------------------------- 1 | import Slate from '@gitbook/slate'; 2 | 3 | export default (plugin, change) => { 4 | const schema = Slate.Schema.create(plugin.schema); 5 | return change.normalize(schema); 6 | }; 7 | -------------------------------------------------------------------------------- /tests/schema-tables-contain-rows-mixed/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Row 1, Col 1 11 | 12 | 13 | 14 | 15 | Row 3, Col 1 16 | 17 | 18 |
19 |
20 |
21 | ); 22 | -------------------------------------------------------------------------------- /tests/schema-tables-contain-rows-mixed/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | No rows
8 | 9 | 10 | 11 | Row 1, Col 1 12 | 13 | 14 | 15 | 16 | Row 2, Col 1 17 | 18 | 19 | 20 | 21 | Row 3, Col 1 22 | 23 | 24 |
25 |
26 |
27 | ); 28 | -------------------------------------------------------------------------------- /tests/selection-in-table/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | const paragraph = value.document.getDescendant('paragraph'); 6 | const table11 = value.document.getDescendant('table11'); 7 | const table12 = value.document.getDescendant('table12'); 8 | const cellText = value.document.getDescendant('cellText'); 9 | const table2 = value.document.getDescendant('table2'); 10 | 11 | change.collapseToStartOf(paragraph); 12 | expect(plugin.utils.isSelectionInTable(change.value)).toBe(false); 13 | 14 | change.collapseToStartOf(cellText); 15 | expect(plugin.utils.isSelectionInTable(change.value)).toBe(true); 16 | 17 | change.collapseToStartOf(table11); 18 | expect(plugin.utils.isSelectionInTable(change.value)).toBe(true); 19 | 20 | change.extendToEndOf(table12); 21 | expect(plugin.utils.isSelectionInTable(change.value)).toBe(true); 22 | 23 | change.extendToEndOf(table2); 24 | expect(plugin.utils.isSelectionInTable(change.value)).toBe(false); 25 | } 26 | -------------------------------------------------------------------------------- /tests/selection-in-table/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | Paragraph 9 | 10 | 11 | 12 | 13 | 14 | Table 1 15 | 16 | 17 | 18 | 19 | Table 1 20 | 21 | 22 | 23 | 24 | Text directly in the table cell 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | Table 2 34 | 35 | 36 | 37 |
38 |
39 |
40 | ); 41 | -------------------------------------------------------------------------------- /tests/selection-outside-table/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const { value } = change; 5 | const paragraph = value.document.getDescendant('paragraph'); 6 | const table11 = value.document.getDescendant('table11'); 7 | const table12 = value.document.getDescendant('table12'); 8 | const cellText = value.document.getDescendant('cellText'); 9 | const table2 = value.document.getDescendant('table2'); 10 | 11 | change.collapseToStartOf(paragraph); 12 | expect(plugin.utils.isSelectionOutOfTable(change.value)).toBe(true); 13 | 14 | change.extendToEndOf(cellText); 15 | expect(plugin.utils.isSelectionOutOfTable(change.value)).toBe(false); 16 | 17 | change.collapseToStartOf(cellText); 18 | expect(plugin.utils.isSelectionOutOfTable(change.value)).toBe(false); 19 | 20 | change.collapseToStartOf(table11); 21 | expect(plugin.utils.isSelectionOutOfTable(change.value)).toBe(false); 22 | 23 | change.extendToEndOf(table12); 24 | expect(plugin.utils.isSelectionOutOfTable(change.value)).toBe(false); 25 | 26 | change.extendToEndOf(table2); 27 | expect(plugin.utils.isSelectionOutOfTable(change.value)).toBe(false); 28 | } 29 | -------------------------------------------------------------------------------- /tests/selection-outside-table/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | Paragraph 9 | 10 | 11 | 12 | 13 | 14 | Table 1 15 | 16 | 17 | 18 | 19 | Table 1 20 | 21 | 22 | 23 | 24 | Text directly in the table cell 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | Table 2 34 | 35 | 36 | 37 |
38 |
39 |
40 | ); 41 | -------------------------------------------------------------------------------- /tests/shift-enter-split-block/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const blockStart = change.value.document.getDescendant('anchor'); 5 | const withCursor = change.collapseToEndOf(blockStart); 6 | 7 | const result = plugin.onKeyDown( 8 | { 9 | key: 'Enter', 10 | shiftKey: true, 11 | preventDefault() {}, 12 | stopPropagation() {} 13 | }, 14 | withCursor 15 | ); 16 | 17 | expect(result.value.startBlock.type).toBe('paragraph'); 18 | 19 | return result; 20 | } 21 | -------------------------------------------------------------------------------- /tests/shift-enter-split-block/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/undo-insert-column/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | const initial = change.value.change({ save: false }); 6 | initial.moveToRangeOf(cursorBlock); 7 | const toTest = initial.value.change(); 8 | plugin.changes.insertColumn(toTest); 9 | toTest.undo(); 10 | 11 | // Back to previous cursor position 12 | expect(toTest.value.startBlock.text).toEqual('Col 1, Row 1'); 13 | 14 | return toTest; 15 | } 16 | -------------------------------------------------------------------------------- /tests/undo-insert-column/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 1, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/undo-insert-column/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | 17 | 18 | Col 0, Row 1 19 | 20 | 21 | Col 1, Row 1 22 | 23 | 24 | 25 | 26 | Col 0, Row 2 27 | 28 | 29 | Col 1, Row 2 30 | 31 | 32 |
33 |
34 |
35 | ); 36 | -------------------------------------------------------------------------------- /tests/undo-insert-row/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | const initial = change.value.change({ save: false }); 6 | initial.moveToRangeOf(cursorBlock); 7 | const toTest = initial.value.change(); 8 | plugin.changes.insertRow(toTest); 9 | 10 | toTest.undo(); 11 | 12 | // Back to previous cursor position 13 | expect(toTest.value.startBlock.text).toEqual('Col 1, Row 1'); 14 | 15 | return toTest; 16 | } 17 | -------------------------------------------------------------------------------- /tests/undo-insert-row/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/undo-insert-row/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 |
31 |
32 |
33 | ); 34 | -------------------------------------------------------------------------------- /tests/undo-insert-table/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | const initial = change.value.change({ save: false }); 6 | 7 | initial.moveToRangeOf(cursorBlock).move(6); // Cursor here: Before|After 8 | 9 | const toTest = initial.value.change(); 10 | 11 | plugin.changes.insertTable(toTest); 12 | 13 | toTest.undo(); 14 | 15 | // Back to previous cursor position 16 | expect(toTest.value.startBlock.text).toEqual('BeforeAfter'); 17 | 18 | return toTest; 19 | } 20 | -------------------------------------------------------------------------------- /tests/undo-insert-table/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | BeforeAfter 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /tests/undo-insert-table/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | BeforeAfter 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /tests/undo-remove-column/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const cursorBlock = change.value.document.getDescendant('anchor'); 3 | const initial = change.value.change({ save: false }); 4 | initial.moveToRangeOf(cursorBlock); 5 | const toTest = initial.value.change(); 6 | plugin.changes.removeColumn(toTest); 7 | toTest.undo(); 8 | 9 | return toTest; 10 | } 11 | -------------------------------------------------------------------------------- /tests/undo-remove-column/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/undo-remove-column/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/undo-remove-row/change.js: -------------------------------------------------------------------------------- 1 | export default function(plugin, change) { 2 | const cursorBlock = change.value.document.getDescendant('anchor'); 3 | const initial = change.value 4 | .change({ save: false }) 5 | .moveToRangeOf(cursorBlock); 6 | const toTest = initial.value.change(); 7 | plugin.changes.removeRow(toTest).undo(); 8 | 9 | return toTest; 10 | } 11 | -------------------------------------------------------------------------------- /tests/undo-remove-row/expected.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/undo-remove-row/input.js: -------------------------------------------------------------------------------- 1 | /** @jsx hyperscript */ 2 | import hyperscript from '../hyperscript'; 3 | 4 | export default ( 5 | 6 | 7 | 8 | 9 | 10 | Col 0, Row 0 11 | 12 | 13 | Col 1, Row 0 14 | 15 | 16 | Col 2, Row 0 17 | 18 | 19 | 20 | 21 | Col 0, Row 1 22 | 23 | 24 | Col 1, Row 1 25 | 26 | 27 | Col 2, Row 1 28 | 29 | 30 | 31 | 32 | Col 0, Row 2 33 | 34 | 35 | Col 1, Row 2 36 | 37 | 38 | Col 2, Row 2 39 | 40 | 41 |
42 |
43 |
44 | ); 45 | -------------------------------------------------------------------------------- /tests/undo-remove-table/change.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | export default function(plugin, change) { 4 | const cursorBlock = change.value.document.getDescendant('anchor'); 5 | const initial = change.value.change({ save: false }); 6 | initial.moveToRangeOf(cursorBlock); 7 | const toTest = initial.value.change(); 8 | toTest.call(plugin.changes.removeTable).undo(); 9 | 10 | // Back to previous cursor position 11 | expect(toTest.value.startBlock.text).toEqual('Before'); 12 | 13 | return toTest; 14 | } 15 | --------------------------------------------------------------------------------