Skip to content

Commit

Permalink
Merge pull request #2235 from nextcloud/feature/114/tables
Browse files Browse the repository at this point in the history
Feature/114/tables
  • Loading branch information
max-nextcloud authored Mar 31, 2022
2 parents 0db660b + 52c36ba commit 2a26764
Show file tree
Hide file tree
Showing 62 changed files with 1,460 additions and 43 deletions.
1 change: 1 addition & 0 deletions .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ jobs:
config: defaultCommandTimeout=10000,video=false
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
npm_package_name: ${{ env.APP_NAME }}

- name: Upload test failure screenshots
uses: actions/upload-artifact@v2
Expand Down
8 changes: 8 additions & 0 deletions css/icons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
@include icon-black-white('ol', 'text', 1);
@include icon-black-white('ul', 'text', 1);
@include icon-black-white('tasklist', 'text', 1);
@include icon-black-white('table', 'text', 1);
@include icon-black-white('hr', 'text', 1);
@include icon-black-white('quote', 'text', 1);
@include icon-black-white('paragraph', 'text', 1);
Expand All @@ -23,3 +24,10 @@
@include icon-black-white('h4', 'text', 1);
@include icon-black-white('h5', 'text', 1);
@include icon-black-white('h6', 'text', 1);
@include icon-black-white('add_col_before', 'text', 1);
@include icon-black-white('add_col_after', 'text', 1);
@include icon-black-white('add_row_before', 'text', 1);
@include icon-black-white('add_row_after', 'text', 1);
@include icon-black-white('delete_col', 'text', 1);
@include icon-black-white('delete_row', 'text', 1);
@include icon-black-white('table_settings', 'text', 1);
62 changes: 62 additions & 0 deletions css/prosemirror.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@use "sass:selector";

/* Document rendering styles */
div.ProseMirror {
margin-top: 44px;
Expand Down Expand Up @@ -252,6 +254,66 @@ div.ProseMirror {
}
}

// table variables
@at-root :root {
--table-color-border: var(--color-border);
--table-color-heading: var(--color-text-maxcontrast);
--table-color-heading-border: var(--color-border-dark);
--table-color-background: var(--color-main-background);
--table-color-background-hover: var(--color-primary-light);
--table-border-radius: var(--border-radius);
}

table {
border-spacing: 0;
width: calc(100% - 50px);
table-layout: fixed;
white-space: normal; // force text to wrapping
margin-bottom: 1em;
+ & {
margin-top: 1em;
}


td, th {
border: 1px solid var(--table-color-border);
border-left: 0;
vertical-align: top;
max-width: 100%;
&:first-child {
border-left: 1px solid var(--table-color-border);
}
}
td {
padding: 0.5em 0.75em;
border-top: 0;
color: var(--color-main-text);
}
th {
padding: 0 0 0 0.75em;
font-weight: normal;
border-bottom-color: var(--table-color-heading-border);
color: var(--table-color-heading);
}
tr {
background-color: var(--table-color-background);
&:hover, &:active, &:focus {
background-color: var(--table-color-background-hover);
}
}

tr:first-child {
th:first-child { border-top-left-radius: var(--table-border-radius); }
th:last-child { border-top-right-radius: var(--table-border-radius); }
}

tr:last-child {
td:first-child { border-bottom-left-radius: var(--table-border-radius); }
td:last-child { border-bottom-right-radius: var(--table-border-radius); }
}

}

}

.ProseMirror-focused .ProseMirror-gapcursor {
Expand Down
114 changes: 114 additions & 0 deletions cypress/fixtures/Table.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
## Preserve Tables

This is a table

| Header | other Header |
|--------|--------------|
| Cell | other cell |
| Cell | other cell |

---

This is a table

| Header | other Header |
|--------|--------------|
| Cell | other cell |
| Cell | other cell |

## Create a table

insertTable

---

| | | |
|--|--|--|
| | | |
| | | |

did insertTable

## Create second tables

| | | |
|--|--|--|
| | | |
| | | |

insertTable

---

| | | |
|--|--|--|
| | | |
| | | |

| | | |
|--|--|--|
| | | |
| | | |

did insertTable

## Add a new row at the end

| | | |
|--|--|--|
| | | |
| | | addRowAfter |


---

| | | |
|--|--|--|
| | | |
| | | did addRowAfter |
| | | |

## Add a new column at the end

| | | |
|--|--|--|
| | | |
| | | addColumnAfter |


---

| | | | |
|--|--|--|--|
| | | | |
| | | did addColumnAfter | |

## Delete row at the end

| | | |
|--|--|--|
| | | |
| | | deleteRow |


---

| | | |
|--|--|--|
| | | |

## Delete column at the end

| | | |
|--|--|--|
| | | |
| | | deleteColumn |


---

| | |
|--|--|
| | |
| | |

76 changes: 76 additions & 0 deletions cypress/integration/Table.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import Table from './../../src/nodes/Table'
import TableCell from './../../src/nodes/TableCell'
import TableHeader from './../../src/nodes/TableHeader'
import TableRow from './../../src/nodes/TableRow'
import TableHeadRow from './../../src/nodes/TableHeadRow'
import Markdown from './../../src/extensions/Markdown'
import markdownit from './../../src/markdownit'
import { createMarkdownSerializer } from './../../src/extensions/Markdown';
import { findChildren, findChildrenByType } from 'prosemirror-utils'
import createEditor from './../../src/tests/createEditor'
import testData from '../fixtures/Table.md'

describe('ListItem extension integrated in the editor', () => {

const editor = createEditor({
content: '',
extensions: [
Markdown,
Table,
TableCell,
TableHeader,
TableHeadRow,
TableRow,
],
})

for (const spec of testData.split(/#+\s+/)){
const [description, ...rest] = spec.split(/\n/)
const [input, output] = rest.join('\n').split(/\n\n---\n\n/)
if (!description) {
continue
}
it(description, () => {
expect(spec).to.include('\n')
expect(input).to.be.ok
expect(output).to.be.ok
loadMarkdown(input)
runCommands()
expectMarkdown(output.replace(/\n*$/, ''))
})
}

function loadMarkdown(markdown) {
editor.commands.setContent(markdownit.render(markdown))
}

function runCommands() {
let found
while (found = findCommand()) {
const name = found.node.text
editor.commands.setTextSelection(found.pos)
editor.commands[name]()
const updated = findCommand()
if (updated) {
editor.commands.setTextSelection(updated.pos)
editor.commands.insertContent('did ')
}
}
}

function findCommand() {
const doc = editor.state.doc
return findChildren(doc, child => {
return child.isText && editor.commands.hasOwnProperty(child.text)
})[0]
}

function expectMarkdown(markdown) {
expect(getMarkdown().replace(/\n$/, '')).to.equal(markdown)
}

function getMarkdown() {
const serializer = createMarkdownSerializer(editor.schema)
return serializer.serialize(editor.state.doc)
}
})
24 changes: 24 additions & 0 deletions cypress/integration/workspace.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,22 @@ describe('Workspace', function() {
menuButton('info').should('not.have.class', 'is-active')
})
})

it('inserts and removes a table', function() {
openWorkspace()
.type('Let\'s insert a Table')
toggleMoreActions()
popoverButton('table')
.click()
cy.get(`.ProseMirror`).type('content')
cy.get(`.ProseMirror table tr:first-child th:first-child`)
.should('contain', 'content')
cy.get(`.ProseMirror .table-settings`).click()
popoverButton('delete').click()
cy.get(`.ProseMirror`)
.should('not.contain', 'content')
})

})

const menuButton = (name) => {
Expand All @@ -223,6 +239,14 @@ const submenuButton = (name) => {
return cy.get(`#editor button .icon-${name}`)
}

const popoverButton = (name) => {
return cy.get(`.popover button .icon-${name}`)
}

const toggleMoreActions = () => {
cy.get('.menubar .action-item__menutoggle--default-icon').click()
}

const menuBubbleButton = submenuButton

const openWorkspace = () => {
Expand Down
9 changes: 3 additions & 6 deletions cypress/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@

const browserify = require('@cypress/browserify-preprocessor')
const webpack = require('@cypress/webpack-preprocessor')
const defaults = webpack.defaultOptions
const webpackOptions = require('@nextcloud/webpack-vue-config')

module.exports = (on, config) => {
on('file:preprocessor', browserify())
defaults.webpackOptions.module.rules.push({
test: /\.md/,
type: 'asset/source',
})
on('file:preprocessor', webpack(defaults))
webpackOptions.module.rules.push({ test: /\.md/, type: 'asset/source' })
on('file:preprocessor', webpack({webpackOptions}))
}
2 changes: 1 addition & 1 deletion img/add_col_after.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion img/add_col_before.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion img/add_row_after.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion img/add_row_before.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion img/delete_col.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion img/delete_row.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion img/table.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions img/table_settings.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions js/editor-collab.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/editor-collab.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/editor-rich.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/editor-rich.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/editor.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/editor.js.map

Large diffs are not rendered by default.

Loading

0 comments on commit 2a26764

Please sign in to comment.