mirror of
https://github.com/marktext/marktext.git
synced 2025-05-09 23:33:44 +08:00
feat: align and delete in table tool bar
This commit is contained in:
parent
9f5f1ed1d9
commit
2e73062cb4
5
TODO.md
5
TODO.md
@ -7,6 +7,7 @@
|
||||
- [ ] 在通过 Aganippe 打开文件时,无法通过右键选择 Aganippe。(严重 bug)
|
||||
- [ ] 在通过 Aganippe 打开文件时,通过右键选择软件,但是打开无内容。(严重 bug)
|
||||
- [ ] export html: (3) keyframe 和 font-face 以及 bar-top 的样式都可以删除。(4) 打包后的应用 axios 获取样式有问题。(5) 输出的 html 中 a 标签无法点击
|
||||
- [ ] table: 1. table 前面不能够点击出现光标。2. 处理 table 内容选中后的backspace, enter 等。
|
||||
|
||||
**菜单**
|
||||
|
||||
@ -151,11 +152,11 @@ _ 底线
|
||||
|
||||
**表格功能**
|
||||
|
||||
* [ ] 输入`|xxx|xxx|`回车或其他失去 active 的操作生成2 * 2 表格。如果是回车,p (1, 1)自动获取光标。
|
||||
* [x] 输入`|xxx|xxx|`回车或其他失去 active 的操作生成2 * 2 表格。如果是回车,p (1, 1)自动获取光标。
|
||||
|
||||
block 类型包括 table、thead、tr、th、tbody、td
|
||||
|
||||
* [ ] 处理表格内部的 enter、cmd + enter、backspace 键。
|
||||
* [x] 处理表格内部的 enter、cmd + enter、backspace 键。
|
||||
|
||||
enter 光标跳转到下一行第一个cell。如果已经是最后一行,光标跳转到下一的段落。
|
||||
|
||||
|
1
src/editor/assets/icons/align-center.svg
Normal file
1
src/editor/assets/icons/align-center.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="128px" height="120.47px" viewBox="0 0 1088 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#515151" d="M1088 124.032C1088 157.184 1061.12 184.064 1027.968 184.064L126.72 184.064C93.568 184.064 66.688 157.184 66.688 124.032L66.688 124.032C66.688 90.88 93.568 64 126.72 64L1027.968 64C1061.12 64 1088 90.88 1088 124.032L1088 124.032 1088 124.032ZM1088 892.032C1088 925.184 1061.12 952.064 1027.968 952.064L126.72 952.064C93.568 952.064 66.688 925.184 66.688 892.032L66.688 892.032C66.688 858.88 93.568 832 126.72 832L1027.968 832C1061.12 832 1088 858.88 1088 892.032L1088 892.032 1088 892.032ZM1088 508.032C1088 541.184 1061.12 568.064 1027.968 568.064L126.72 568.064C93.568 568.064 66.688 541.184 66.688 508.032L66.688 508.032C66.688 474.88 93.568 448 126.72 448L1027.968 448C1061.12 448 1088 474.88 1088 508.032L1088 508.032 1088 508.032ZM896 700.032C896 733.184 869.12 760.064 835.968 760.064L318.72 760.064C285.568 760.064 258.688 733.184 258.688 700.032L258.688 700.032C258.688 666.88 285.568 640 318.72 640L835.968 640C869.12 640 896 666.88 896 700.032L896 700.032 896 700.032ZM896 316.032C896 349.184 869.12 376.064 835.968 376.064L318.72 376.064C285.568 376.064 258.688 349.184 258.688 316.032L258.688 316.032C258.688 282.88 285.568 256 318.72 256L835.968 256C869.12 256 896 282.88 896 316.032L896 316.032 896 316.032Z" /></svg>
|
After Width: | Height: | Size: 1.5 KiB |
1
src/editor/assets/icons/align-left.svg
Normal file
1
src/editor/assets/icons/align-left.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="128px" height="128.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#515151" d="M1023.934464 768.016384l0 73.138176q0 14.856192-10.856448 25.71264t-25.71264 10.856448l-950.796288 0q-14.856192 0-25.71264-10.856448t-10.856448-25.71264l0-73.138176q0-14.856192 10.856448-25.71264t25.71264-10.856448l950.796288 0q14.856192 0 25.71264 10.856448t10.856448 25.71264zm-219.414528-219.414528l0 73.138176q0 14.856192-10.856448 25.71264t-25.71264 10.856448l-731.38176 0q-14.856192 0-25.71264-10.856448t-10.856448-25.71264l0-73.138176q0-14.856192 10.856448-25.71264t25.71264-10.856448l731.38176 0q14.856192 0 25.71264 10.856448t10.856448 25.71264zm146.276352-219.414528l0 73.138176q0 14.856192-10.856448 25.71264t-25.71264 10.856448l-877.658112 0q-14.856192 0-25.71264-10.856448t-10.856448-25.71264l0-73.138176q0-14.856192 10.856448-25.71264t25.71264-10.856448l877.658112 0q14.856192 0 25.71264 10.856448t10.856448 25.71264zm-219.414528-219.414528l0 73.138176q0 14.856192-10.856448 25.71264t-25.71264 10.856448l-658.243584 0q-14.856192 0-25.71264-10.856448t-10.856448-25.71264l0-73.138176q0-14.856192 10.856448-25.71264t25.71264-10.856448l658.243584 0q14.856192 0 25.71264 10.856448t10.856448 25.71264z" /></svg>
|
After Width: | Height: | Size: 1.4 KiB |
1
src/editor/assets/icons/align-right.svg
Normal file
1
src/editor/assets/icons/align-right.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="128px" height="128.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#515151" d="M1024 768l0 73.142857q0 14.857143-10.857143 25.714286t-25.714286 10.857143l-950.857143 0q-14.857143 0-25.714286-10.857143t-10.857143-25.714286l0-73.142857q0-14.857143 10.857143-25.714286t25.714286-10.857143l950.857143 0q14.857143 0 25.714286 10.857143t10.857143 25.714286zm0-219.428571l0 73.142857q0 14.857143-10.857143 25.714286t-25.714286 10.857143l-731.428571 0q-14.857143 0-25.714286-10.857143t-10.857143-25.714286l0-73.142857q0-14.857143 10.857143-25.714286t25.714286-10.857143l731.428571 0q14.857143 0 25.714286 10.857143t10.857143 25.714286zm0-219.428571l0 73.142857q0 14.857143-10.857143 25.714286t-25.714286 10.857143l-877.714286 0q-14.857143 0-25.714286-10.857143t-10.857143-25.714286l0-73.142857q0-14.857143 10.857143-25.714286t25.714286-10.857143l877.714286 0q14.857143 0 25.714286 10.857143t10.857143 25.714286zm0-219.428571l0 73.142857q0 14.857143-10.857143 25.714286t-25.714286 10.857143l-658.285714 0q-14.857143 0-25.714286-10.857143t-10.857143-25.714286l0-73.142857q0-14.857143 10.857143-25.714286t25.714286-10.857143l658.285714 0q14.857143 0 25.714286 10.857143t10.857143 25.714286z" /></svg>
|
After Width: | Height: | Size: 1.4 KiB |
1
src/editor/assets/icons/delete.svg
Normal file
1
src/editor/assets/icons/delete.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="128px" height="128.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#515151" d="M704 128c-8.384-49.536-50.56-64-92.8-64L407.872 64C365.632 64 328.448 78.464 320 128l0 64 384 0L704 128zM204.8 412.416l0 473.216C204.8 934.144 228.288 960 281.6 960l460.8 0c53.376 0 76.8-25.856 76.8-74.368L819.2 412.416c53.952 0 76.8-29.76 76.8-78.208C896 285.696 872.512 256 819.2 256L550.4 256 204.8 256C151.488 256 128 285.696 128 334.208 128 382.656 151.488 412.416 204.8 412.416zM576 387.968C576 386.496 576.576 385.408 576.704 384l62.656 0C639.488 385.408 640 386.496 640 387.968l0 414.464c0 39.424-64 39.424-64 0L576 387.968zM384 387.968C384 386.496 384.448 385.408 384.64 384l59.136 0c0.128 1.408 0.704 2.496 0.704 3.968l0 414.464c0 39.424-60.48 39.424-60.48 0L384 387.968z" /></svg>
|
After Width: | Height: | Size: 973 B |
1
src/editor/assets/icons/delete_1.svg
Normal file
1
src/editor/assets/icons/delete_1.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="128px" height="128.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#515151" d="M512 0C229.29408 0 0 229.248 0 512c0 282.76736 229.26336 512 512 512 282.76736 0 512-229.18144 512-512C1024 229.29408 794.76736 0 512 0z m209.90976 654.09024a47.5904 47.5904 0 0 1 14.08512 33.90976 47.95392 47.95392 0 0 1-47.99488 47.99488 47.75936 47.75936 0 0 1-33.90976-14.08512L512 579.89632l-141.99296 142.05952a47.9488 47.9488 0 0 1-34.00704 14.08512c-26.45504 0-47.95904-21.45792-47.95904-48.01536A47.68768 47.68768 0 0 1 302.08 654.15168L444.15488 512 302.1056 369.95584a47.88224 47.88224 0 0 1-14.03904-33.95584 47.99488 47.99488 0 0 1 81.92-33.95584l141.99296 142.07488L654.07488 302.08a47.92832 47.92832 0 0 1 33.90976-14.03904c26.48576 0 47.99488 21.45792 47.99488 47.99488a47.75424 47.75424 0 0 1-14.08512 33.95584l-141.99808 141.99296 142.01344 142.1056z m0 0" /></svg>
|
After Width: | Height: | Size: 1.0 KiB |
1
src/editor/assets/icons/table.svg
Normal file
1
src/editor/assets/icons/table.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="128px" height="128.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#515151" d="M329.142857 786.285714v-109.714285q0-8-5.142857-13.142858t-13.142857-5.142857H128q-8 0-13.142857 5.142857t-5.142857 13.142858v109.714285q0 8 5.142857 13.142857t13.142857 5.142858h182.857143q8 0 13.142857-5.142858t5.142857-13.142857z m0-219.428571V457.142857q0-8-5.142857-13.142857t-13.142857-5.142857H128q-8 0-13.142857 5.142857t-5.142857 13.142857v109.714286q0 8 5.142857 13.142857t13.142857 5.142857h182.857143q8 0 13.142857-5.142857t5.142857-13.142857z m292.571429 219.428571v-109.714285q0-8-5.142857-13.142858t-13.142858-5.142857H420.571429q-8 0-13.142858 5.142857t-5.142857 13.142858v109.714285q0 8 5.142857 13.142857t13.142858 5.142858h182.857142q8 0 13.142858-5.142858t5.142857-13.142857zM329.142857 347.428571V237.714286q0-8-5.142857-13.142857t-13.142857-5.142858H128q-8 0-13.142857 5.142858t-5.142857 13.142857v109.714285q0 8 5.142857 13.142858t13.142857 5.142857h182.857143q8 0 13.142857-5.142857t5.142857-13.142858z m292.571429 219.428572V457.142857q0-8-5.142857-13.142857t-13.142858-5.142857H420.571429q-8 0-13.142858 5.142857t-5.142857 13.142857v109.714286q0 8 5.142857 13.142857t13.142858 5.142857h182.857142q8 0 13.142858-5.142857t5.142857-13.142857z m292.571428 219.428571v-109.714285q0-8-5.142857-13.142858t-13.142857-5.142857h-182.857143q-8 0-13.142857 5.142857t-5.142857 13.142858v109.714285q0 8 5.142857 13.142857t13.142857 5.142858h182.857143q8 0 13.142857-5.142858t5.142857-13.142857z m-292.571428-438.857143V237.714286q0-8-5.142857-13.142857t-13.142858-5.142858H420.571429q-8 0-13.142858 5.142858t-5.142857 13.142857v109.714285q0 8 5.142857 13.142858t13.142858 5.142857h182.857142q8 0 13.142858-5.142857t5.142857-13.142858z m292.571428 219.428572V457.142857q0-8-5.142857-13.142857t-13.142857-5.142857h-182.857143q-8 0-13.142857 5.142857t-5.142857 13.142857v109.714286q0 8 5.142857 13.142857t13.142857 5.142857h182.857143q8 0 13.142857-5.142857t5.142857-13.142857z m0-219.428572V237.714286q0-8-5.142857-13.142857t-13.142857-5.142858h-182.857143q-8 0-13.142857 5.142858t-5.142857 13.142857v109.714285q0 8 5.142857 13.142858t13.142857 5.142857h182.857143q8 0 13.142857-5.142857t5.142857-13.142858z m73.142857-182.857142v621.714285q0 37.714286-26.857142 64.571429t-64.571429 26.857143H128q-37.714286 0-64.571429-26.857143T36.571429 786.285714V164.571429q0-37.714286 26.857142-64.571429t64.571429-26.857143h768q37.714286 0 64.571429 26.857143t26.857142 64.571429z" /></svg>
|
After Width: | Height: | Size: 2.6 KiB |
@ -77,7 +77,8 @@ export const CLASS_OR_ID = genUpper2LowerKeyHash([
|
||||
'AG_BULLET_LIST_ITEM',
|
||||
'AG_TASK_LIST',
|
||||
'AG_TASK_LIST_ITEM',
|
||||
'AG_TASK_LIST_ITEM_CHECKBOX'
|
||||
'AG_TASK_LIST_ITEM_CHECKBOX',
|
||||
'AG_TABLE_TOOL_BAR'
|
||||
])
|
||||
|
||||
export const codeMirrorConfig = {
|
||||
|
@ -15,11 +15,15 @@ const enterCtrl = ContentState => {
|
||||
this.insertAfter(container, parent)
|
||||
}
|
||||
|
||||
ContentState.prototype.createRow = function (columns) {
|
||||
ContentState.prototype.createRow = function (row) {
|
||||
const trBlock = this.createBlock('tr')
|
||||
const len = row.children.length
|
||||
let i
|
||||
for (i = 0; i < columns; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
const tdBlock = this.createBlock('td')
|
||||
const preChild = row.children[i]
|
||||
tdBlock.column = i
|
||||
tdBlock.align = preChild.align
|
||||
this.appendChild(trBlock, tdBlock)
|
||||
}
|
||||
return trBlock
|
||||
@ -110,13 +114,14 @@ const enterCtrl = ContentState => {
|
||||
if (!nextSibling) {
|
||||
const rowContainer = this.getBlock(row.parent)
|
||||
const table = this.getBlock(rowContainer.parent)
|
||||
const figure = this.getBlock(table.parent)
|
||||
if (rowContainer.type === 'thead') {
|
||||
nextSibling = table.children[1]
|
||||
} else if (table.nextSibling) {
|
||||
nextSibling = this.getBlock(table.nextSibling)
|
||||
} else if (figure.nextSibling) {
|
||||
nextSibling = this.getBlock(figure.nextSibling)
|
||||
} else {
|
||||
nextSibling = this.createBlock('p')
|
||||
this.insertAfter(nextSibling, table)
|
||||
this.insertAfter(nextSibling, figure)
|
||||
}
|
||||
}
|
||||
return this.firstInDescendant(nextSibling)
|
||||
@ -127,7 +132,7 @@ const enterCtrl = ContentState => {
|
||||
const rowContainer = this.getBlock(row.parent)
|
||||
|
||||
if (event.metaKey) {
|
||||
const nextRow = this.createRow(row.children.length)
|
||||
const nextRow = this.createRow(row)
|
||||
if (rowContainer.type === 'thead') {
|
||||
const tBody = this.getBlock(rowContainer.nextSibling)
|
||||
this.insertBefore(nextRow, tBody.children[0])
|
||||
|
@ -76,9 +76,9 @@ class ContentState {
|
||||
|
||||
render () {
|
||||
const { blocks, cursor } = this
|
||||
const activeBlockKey = this.getActiveBlockKey()
|
||||
const activeBlocks = this.getActiveBlocks()
|
||||
|
||||
this.stateRender.render(blocks, cursor, activeBlockKey)
|
||||
this.stateRender.render(blocks, cursor, activeBlocks)
|
||||
this.setCursor()
|
||||
this.pre2CodeMirror()
|
||||
console.log('render')
|
||||
@ -237,13 +237,15 @@ class ContentState {
|
||||
remove(this.blocks, block)
|
||||
}
|
||||
|
||||
getActiveBlockKey () {
|
||||
let block = this.getBlock(this.cursor.key)
|
||||
if (!block) return null
|
||||
while (block.parent) {
|
||||
getActiveBlocks () {
|
||||
let result = []
|
||||
let block = this.getBlock(this.cursor.start.key)
|
||||
if (block) result.push(block)
|
||||
while (block && block.parent) {
|
||||
block = this.getBlock(block.parent)
|
||||
result.push(block)
|
||||
}
|
||||
return block.key
|
||||
return result
|
||||
}
|
||||
|
||||
getCursorBlock () {
|
||||
|
@ -1,9 +1,14 @@
|
||||
import { isLengthEven } from '../utils'
|
||||
import TableIcon from '../assets/icons/table.svg'
|
||||
import LeftIcon from '../assets/icons/align-left.svg'
|
||||
import CenterIcon from '../assets/icons/align-center.svg'
|
||||
import RightIcon from '../assets/icons/align-right.svg'
|
||||
import DeleteIcon from '../assets/icons/delete.svg'
|
||||
|
||||
const TABLE_BLOCK_REG = /^\|.*?(\\*)\|.*?(\\*)\|/
|
||||
|
||||
const tableBlockCtrl = ContentState => {
|
||||
ContentState.prototype.createTable = function (block) {
|
||||
ContentState.prototype.initTable = function (block) {
|
||||
const { text } = block
|
||||
const rowHeader = []
|
||||
const len = text.length
|
||||
@ -22,6 +27,7 @@ const tableBlockCtrl = ContentState => {
|
||||
}
|
||||
}
|
||||
const colLen = rowHeader.length
|
||||
const table = this.createBlock('table')
|
||||
const tHead = this.createBlock('thead')
|
||||
const headRow = this.createBlock('tr')
|
||||
const tBody = this.createBlock('tbody')
|
||||
@ -31,23 +37,102 @@ const tableBlockCtrl = ContentState => {
|
||||
for (i = 0; i < colLen; i++) {
|
||||
const headCell = this.createBlock('th', rowHeader[i])
|
||||
const bodyCell = this.createBlock('td')
|
||||
headCell.column = i
|
||||
headCell.align = ''
|
||||
bodyCell.column = i
|
||||
bodyCell.align = ''
|
||||
|
||||
this.appendChild(headRow, headCell)
|
||||
this.appendChild(bodyRow, bodyCell)
|
||||
if (i === 0) result = bodyCell
|
||||
}
|
||||
block.type = 'table'
|
||||
this.appendChild(table, tHead)
|
||||
this.appendChild(table, tBody)
|
||||
|
||||
const toolBar = this.createBlock('div')
|
||||
toolBar.editable = false
|
||||
const ul = this.createBlock('ul')
|
||||
const tools = [{
|
||||
label: 'table',
|
||||
icon: TableIcon
|
||||
}, {
|
||||
label: 'left',
|
||||
icon: LeftIcon
|
||||
}, {
|
||||
label: 'center',
|
||||
icon: CenterIcon
|
||||
}, {
|
||||
label: 'right',
|
||||
icon: RightIcon
|
||||
}, {
|
||||
label: 'delete',
|
||||
icon: DeleteIcon
|
||||
}]
|
||||
|
||||
tools.forEach(tool => {
|
||||
const toolBlock = this.createBlock('li')
|
||||
const imgBlock = this.createBlock('img')
|
||||
imgBlock.src = tool.icon
|
||||
toolBlock.label = tool.label
|
||||
this.appendChild(toolBlock, imgBlock)
|
||||
this.appendChild(ul, toolBlock)
|
||||
})
|
||||
this.appendChild(toolBar, ul)
|
||||
|
||||
block.type = 'figure'
|
||||
block.text = ''
|
||||
block.children = []
|
||||
this.appendChild(block, tHead)
|
||||
this.appendChild(block, tBody)
|
||||
this.appendChild(block, toolBar)
|
||||
this.appendChild(block, table)
|
||||
return result
|
||||
}
|
||||
|
||||
ContentState.prototype.tableToolBarClick = function (type) {
|
||||
const { start: { key } } = this.cursor
|
||||
const block = this.getBlock(key)
|
||||
if (!(/td|th/.test(block.type))) throw new Error('table is not active')
|
||||
const { column, align } = block
|
||||
const getTable = td => {
|
||||
const row = this.getBlock(block.parent)
|
||||
const rowContainer = this.getBlock(row.parent)
|
||||
return this.getBlock(rowContainer.parent)
|
||||
}
|
||||
const table = getTable(block)
|
||||
switch (type) {
|
||||
case 'left':
|
||||
case 'center':
|
||||
case 'right': {
|
||||
const newAlign = align === type ? '' : type
|
||||
table.children.forEach(rowContainer => {
|
||||
rowContainer.children.forEach(row => {
|
||||
row.children[column].align = newAlign
|
||||
})
|
||||
})
|
||||
this.render()
|
||||
break
|
||||
}
|
||||
case 'delete': {
|
||||
const figure = this.getBlock(table.parent)
|
||||
figure.children = []
|
||||
figure.type = 'p'
|
||||
figure.text = ''
|
||||
const key = figure.key
|
||||
const offset = 0
|
||||
this.cursor = {
|
||||
start: { key, offset },
|
||||
end: { key, offset }
|
||||
}
|
||||
this.render()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentState.prototype.tableBlockUpdate = function (block) {
|
||||
const { type, text } = block
|
||||
if (type !== 'li' && type !== 'p') return false
|
||||
const match = TABLE_BLOCK_REG.exec(text)
|
||||
return (match && isLengthEven(match[1]) && isLengthEven(match[2])) ? this.createTable(block) : false
|
||||
return (match && isLengthEven(match[1]) && isLengthEven(match[2])) ? this.initTable(block) : false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ const updateCtrl = ContentState => {
|
||||
}
|
||||
|
||||
ContentState.prototype.checkInlineUpdate = function (block) {
|
||||
if (/th|td/.test(block.type)) return false
|
||||
if (/th|td|figure/.test(block.type)) return false
|
||||
const { text } = block
|
||||
const parent = this.getParent(block)
|
||||
const [match, bullet, tasklist, order, header, blockquote, hr] = text.match(INLINE_UPDATE_REG) || []
|
||||
|
@ -21,10 +21,58 @@ h6.ag-active::before {
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
figure {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-top: 18px;
|
||||
position: relative;
|
||||
}
|
||||
.ag-table-tool-bar {
|
||||
user-select: none;
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
left: 0;
|
||||
display: none;
|
||||
}
|
||||
.ag-table-tool-bar ul {
|
||||
height: 18px;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
}
|
||||
.ag-table-tool-bar ul li {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
padding: 2px;
|
||||
margin-right: 3px;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.ag-table-tool-bar ul li img {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.ag-table-tool-bar ul li.active {
|
||||
background: lightblue;
|
||||
}
|
||||
|
||||
.ag-table-tool-bar ul li:hover {
|
||||
background: #bbb;
|
||||
}
|
||||
|
||||
figure.ag-active .ag-table-tool-bar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #ebeef5;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -58,6 +58,7 @@ class Aganippe {
|
||||
this.dispatchEnter()
|
||||
this.dispatchUpdateState()
|
||||
this.dispatchCopyCut()
|
||||
this.dispatchTableToolBar()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -269,9 +270,26 @@ class Aganippe {
|
||||
eventCenter.attachDOMEvent(container, 'keydown', handler)
|
||||
}
|
||||
|
||||
dispatchTableToolBar () {
|
||||
const { container, eventCenter } = this
|
||||
const handler = event => {
|
||||
const target = event.target
|
||||
const parent = target.parentNode
|
||||
if (parent && parent.hasAttribute('data-label')) {
|
||||
const type = parent.getAttribute('data-label')
|
||||
this.contentState.tableToolBarClick(type)
|
||||
}
|
||||
}
|
||||
|
||||
eventCenter.attachDOMEvent(container, 'click', handler)
|
||||
}
|
||||
|
||||
dispatchUpdateState () {
|
||||
const { container, eventCenter } = this
|
||||
const changeHandler = event => {
|
||||
// const target = event.target
|
||||
// const style = getComputedStyle(target)
|
||||
// if (event.type === 'click' && !style.contenteditable) return
|
||||
if (!this._isEditChinese || event.type === 'input') {
|
||||
this.contentState.updateState(event)
|
||||
}
|
||||
|
@ -49,12 +49,12 @@ class StateRender {
|
||||
* [render]: 2 steps:
|
||||
* render vdom
|
||||
*/
|
||||
render (blocks, cursor, activeBlockKey) {
|
||||
render (blocks, cursor, activeBlocks) {
|
||||
const selector = `${LOWERCASE_TAGS.div}#${CLASS_OR_ID['AG_EDITOR_ID']}`
|
||||
|
||||
const renderBlock = block => {
|
||||
const type = block.type === 'hr' ? 'p' : block.type
|
||||
const isActive = block.key === activeBlockKey || block.key === cursor.start.key
|
||||
const isActive = activeBlocks.some(b => b.key === block.key) || block.key === cursor.start.key
|
||||
|
||||
let blockSelector = isActive
|
||||
? `${type}#${block.key}.${CLASS_OR_ID['AG_PARAGRAPH']}.${CLASS_OR_ID['AG_ACTIVE']}`
|
||||
@ -66,6 +66,10 @@ class StateRender {
|
||||
}
|
||||
|
||||
if (block.children.length) {
|
||||
if (/div/.test(block.type) && !block.editable) {
|
||||
blockSelector += `.${CLASS_OR_ID['AG_TABLE_TOOL_BAR']}`
|
||||
Object.assign(data.attrs, { contenteditable: 'false' })
|
||||
}
|
||||
if (/ul|ol/.test(block.type) && block.listType) {
|
||||
switch (block.listType) {
|
||||
case 'order':
|
||||
@ -81,6 +85,15 @@ class StateRender {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (block.type === 'li' && block.label) {
|
||||
const { label } = block
|
||||
const { align } = activeBlocks[0]
|
||||
|
||||
if (align && block.label === align) {
|
||||
blockSelector += '.active'
|
||||
}
|
||||
Object.assign(data.dataset, { label })
|
||||
}
|
||||
if (block.type === 'li' && block.listItemType) {
|
||||
switch (block.listItemType) {
|
||||
case 'order':
|
||||
@ -109,6 +122,18 @@ class StateRender {
|
||||
}, [])
|
||||
: [ h(LOWERCASE_TAGS.br) ]
|
||||
|
||||
if (/th|td/.test(block.type)) {
|
||||
const { align } = block
|
||||
if (align) {
|
||||
Object.assign(data.attrs, { style: `text-align:${align}` })
|
||||
}
|
||||
}
|
||||
|
||||
if (/img/.test(block.type)) {
|
||||
const { src } = block
|
||||
Object.assign(data.attrs, { src })
|
||||
children = ''
|
||||
}
|
||||
if (/^h\d$/.test(block.type)) {
|
||||
Object.assign(data.dataset, { head: block.type })
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user