mirror of
https://github.com/marktext/marktext.git
synced 2025-05-10 22:12:29 +08:00
image click
This commit is contained in:
parent
79bd0975fd
commit
a9d570c686
3
TODO.md
3
TODO.md
@ -66,4 +66,5 @@ Bugs:
|
|||||||
|
|
||||||
* [ ] 处理嵌套在 item 中的 codeblock 的方向键。
|
* [ ] 处理嵌套在 item 中的 codeblock 的方向键。
|
||||||
* [ ] codeblock 中光标在 begining 的时候,向上箭头失效。
|
* [ ] codeblock 中光标在 begining 的时候,向上箭头失效。
|
||||||
* [ ] codeblock 中 language input 输入,enter 后,codeblock 没有自动获取焦点。
|
* [ ] codeblock 中 language input 输入,enter 后,codeblock 没有自动获取焦点。
|
||||||
|
* [ ] 图片段落下面有新的段落,编辑跳动现象。
|
@ -81,7 +81,7 @@ const enterCtrl = ContentState => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.removeBlock(block)
|
this.removeBlock(block)
|
||||||
} else if (parent.type === 'li') {
|
} else if (parent && parent.type === 'li') {
|
||||||
newBlock = this.createBlockLi()
|
newBlock = this.createBlockLi()
|
||||||
this.insertAfter(newBlock, parent)
|
this.insertAfter(newBlock, parent)
|
||||||
const index = this.findIndex(parent.children, block)
|
const index = this.findIndex(parent.children, block)
|
||||||
|
@ -7,7 +7,7 @@ import { search } from './codeMirror'
|
|||||||
import { checkEditLanguage, replaceLanguage } from './codeMirror/language'
|
import { checkEditLanguage, replaceLanguage } from './codeMirror/language'
|
||||||
import Emoji, { checkEditEmoji, setInlineEmoji } from './emojis'
|
import Emoji, { checkEditEmoji, setInlineEmoji } from './emojis'
|
||||||
import floatBox from './floatBox'
|
import floatBox from './floatBox'
|
||||||
import { findNearestParagraph } from './utils/domManipulate'
|
import { findNearestParagraph, operateClassName } from './utils/domManipulate'
|
||||||
|
|
||||||
class Aganippe {
|
class Aganippe {
|
||||||
constructor (container, options) {
|
constructor (container, options) {
|
||||||
@ -42,6 +42,7 @@ class Aganippe {
|
|||||||
// if you dont click the keyboard after 1 second, the garbageCollection will run.
|
// if you dont click the keyboard after 1 second, the garbageCollection will run.
|
||||||
eventCenter.attachDOMEvent(container, 'keydown', debounce(() => this.contentState.garbageCollection(), 1000))
|
eventCenter.attachDOMEvent(container, 'keydown', debounce(() => this.contentState.garbageCollection(), 1000))
|
||||||
|
|
||||||
|
this.imageClick()
|
||||||
this.dispatchArrow()
|
this.dispatchArrow()
|
||||||
this.dispatchBackspace()
|
this.dispatchBackspace()
|
||||||
this.dispatchEnter()
|
this.dispatchEnter()
|
||||||
@ -231,6 +232,25 @@ class Aganippe {
|
|||||||
eventCenter.attachDOMEvent(container, 'keyup', changeHandler)
|
eventCenter.attachDOMEvent(container, 'keyup', changeHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imageClick () {
|
||||||
|
const { container, eventCenter } = this
|
||||||
|
const handler = event => {
|
||||||
|
const target = event.target
|
||||||
|
const markedImageText = target.previousElementSibling
|
||||||
|
if (markedImageText && markedImageText.classList.contains(CLASS_OR_ID['AG_IMAGE_MARKED_TEXT'])) {
|
||||||
|
const textLen = markedImageText.textContent.length
|
||||||
|
operateClassName(markedImageText, 'remove', CLASS_OR_ID['AG_HIDE'])
|
||||||
|
operateClassName(markedImageText, 'add', CLASS_OR_ID['AG_GRAY'])
|
||||||
|
selection.importSelection({
|
||||||
|
start: textLen,
|
||||||
|
end: textLen
|
||||||
|
}, markedImageText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eventCenter.attachDOMEvent(container, 'click', handler)
|
||||||
|
}
|
||||||
|
|
||||||
destroy () {
|
destroy () {
|
||||||
this.eventCenter.detachAllDomEvents()
|
this.eventCenter.detachAllDomEvents()
|
||||||
this.emoji.clear() // clear emoji cache for memory recycle
|
this.emoji.clear() // clear emoji cache for memory recycle
|
||||||
|
@ -1,354 +0,0 @@
|
|||||||
import {
|
|
||||||
updateBlock, createEmptyElement, findNearestParagraph,
|
|
||||||
operateClassName, insertBefore, insertAfter, removeNode, isFirstChildElement,
|
|
||||||
wrapperElementWithTag, nestElementWithTag, isOnlyChildElement, isLastChildElement,
|
|
||||||
chopBlockQuote, removeAndInsertBefore, removeAndInsertPreList, replaceElement,
|
|
||||||
replacementLists, insertBeforeBlockQuote, isAganippeEditorElement,
|
|
||||||
findOutMostParagraph, createInputInCodeBlock, isCodeBlockParagraph, hr2P
|
|
||||||
} from './utils/domManipulate'
|
|
||||||
|
|
||||||
import codeMirror, { setMode, search, setCursorAtLastLine,
|
|
||||||
isCursorAtFirstLine, isCursorAtLastLine, isCursorAtBegin, // eslint-disable-line no-unused-vars
|
|
||||||
isCursorAtEnd, setCursorAtFirstLine, onlyHaveOneLine // eslint-disable-line no-unused-vars
|
|
||||||
} from './codeMirror'
|
|
||||||
|
|
||||||
import FloatBox from './floatBox'
|
|
||||||
|
|
||||||
import {
|
|
||||||
checkInlineUpdate, checkMarkedTextUpdate, markedText2Html, checkLineBreakUpdate,
|
|
||||||
chopHeader, checkEditEmoji, setInlineEmoji, checkBackspaceCase, checkEditLanguage,
|
|
||||||
replaceLanguage
|
|
||||||
} from './syntax'
|
|
||||||
|
|
||||||
import {
|
|
||||||
throttle,
|
|
||||||
debounce
|
|
||||||
} from './utils'
|
|
||||||
|
|
||||||
import {
|
|
||||||
CLASS_OR_ID, LOWERCASE_TAGS, EVENT_KEYS, codeMirrorConfig
|
|
||||||
} from './config'
|
|
||||||
|
|
||||||
import Selection from './selection'
|
|
||||||
import Event from './event'
|
|
||||||
import Emoji from './emojis'
|
|
||||||
|
|
||||||
const selection = new Selection(document)
|
|
||||||
|
|
||||||
class Aganippe {
|
|
||||||
constructor (container, options) {
|
|
||||||
this.container = container
|
|
||||||
this.activeParagraph = null
|
|
||||||
this.ids = new Set() // use to store element's id
|
|
||||||
this.codeBlocks = new Map()
|
|
||||||
this.eventCenter = new Event()
|
|
||||||
this.emoji = new Emoji(this.eventCenter) // emoji instance: has search(text) clear() methods.
|
|
||||||
this.floatBox = new FloatBox(this.eventCenter)
|
|
||||||
this.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
init () {
|
|
||||||
this.ensureContainerDiv()
|
|
||||||
const { container, eventCenter } = this
|
|
||||||
|
|
||||||
container.setAttribute('contenteditable', true)
|
|
||||||
container.setAttribute(CLASS_OR_ID['AG_EDITOR_ATTR'], true)
|
|
||||||
container.classList.add(CLASS_OR_ID['mousetrap']) // for use of mousetrap
|
|
||||||
container.id = CLASS_OR_ID['AG_EDITOR_ID']
|
|
||||||
|
|
||||||
// listen to customEvent `markedTextChange` event, and change markedText to html.
|
|
||||||
eventCenter.subscribe('markedTextChange', this.subscribeMarkedText.bind(this))
|
|
||||||
this.dispatchMarkedText()
|
|
||||||
|
|
||||||
eventCenter.subscribe('editEmoji', throttle(this.subscribeEditEmoji.bind(this), 200))
|
|
||||||
this.dispatchEditeEmoji()
|
|
||||||
|
|
||||||
eventCenter.subscribe('paragraphChange', this.subscribeParagraphChange.bind(this))
|
|
||||||
this.dispatchParagraphChange()
|
|
||||||
|
|
||||||
eventCenter.subscribe('elementUpdate', this.subscribeElementUpdate.bind(this))
|
|
||||||
this.dispatchElementUpdate()
|
|
||||||
eventCenter.subscribe('editLanguage', throttle(this.subscribeEditLanguage.bind(this)))
|
|
||||||
this.dispatchEditLanguage()
|
|
||||||
|
|
||||||
eventCenter.subscribe('hideFloatBox', this.subscribeHideFloatBox.bind(this))
|
|
||||||
this.dispatchHideFloatBox()
|
|
||||||
|
|
||||||
eventCenter.bind('enter', this.enterKeyHandler.bind(this))
|
|
||||||
|
|
||||||
eventCenter.subscribe('backspace', this.backspaceHandler.bind(this))
|
|
||||||
this.dispatchBackspace()
|
|
||||||
|
|
||||||
eventCenter.subscribe('arrow', this.arrowHander.bind(this))
|
|
||||||
this.dispatchArrow()
|
|
||||||
// if you dont click the keyboard after 1 second, the garbageCollection will run.
|
|
||||||
eventCenter.attachDOMEvent(container, 'keydown', debounce(this.garbageCollection.bind(this), 1000))
|
|
||||||
|
|
||||||
this.handlerSelectHr()
|
|
||||||
this.imageClick()
|
|
||||||
this.generateLastEmptyParagraph()
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchParagraphChange () {
|
|
||||||
const { container, eventCenter } = this
|
|
||||||
|
|
||||||
const changeHandler = event => {
|
|
||||||
const { id: preId, paragraph: preParagraph } = this.activeParagraph
|
|
||||||
let node = selection.getSelectionStart()
|
|
||||||
if (isAganippeEditorElement(node)) {
|
|
||||||
event.preventDefault()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// handle click img
|
|
||||||
if (event.type === 'click') {
|
|
||||||
const target = event.target
|
|
||||||
if (target.tagName.toLowerCase() === LOWERCASE_TAGS.img) {
|
|
||||||
node = target
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let paragraph = findNearestParagraph(node)
|
|
||||||
if (paragraph.tagName.toLowerCase() === LOWERCASE_TAGS.li) {
|
|
||||||
paragraph = paragraph.children[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
const id = paragraph.id
|
|
||||||
if (id !== preId) {
|
|
||||||
const autoFocus = event.key && event.key === EVENT_KEYS.Enter
|
|
||||||
eventCenter.dispatch('paragraphChange', paragraph, preParagraph, autoFocus)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eventCenter.attachDOMEvent(container, 'click', changeHandler)
|
|
||||||
eventCenter.attachDOMEvent(container, 'keyup', changeHandler)
|
|
||||||
}
|
|
||||||
// newParagrpha and oldParagraph must be h1~6\p\pre element. can not be `li` or `blockquote`
|
|
||||||
subscribeParagraphChange (newParagraph, oldParagraph, autofocus) {
|
|
||||||
const { eventCenter, ids } = this
|
|
||||||
const oldContext = oldParagraph.textContent
|
|
||||||
const oldTagName = oldParagraph.tagName.toLowerCase()
|
|
||||||
const lineBreakUpdate = checkLineBreakUpdate(oldContext)
|
|
||||||
|
|
||||||
if (oldParagraph.classList.contains(CLASS_OR_ID['AG_TEMP'])) {
|
|
||||||
if (!oldContext) {
|
|
||||||
removeNode(oldParagraph)
|
|
||||||
} else {
|
|
||||||
operateClassName(oldParagraph, 'remove', CLASS_OR_ID['AG_TEMP'])
|
|
||||||
}
|
|
||||||
} else if (lineBreakUpdate && oldTagName !== lineBreakUpdate.type) {
|
|
||||||
switch (lineBreakUpdate.type) {
|
|
||||||
case LOWERCASE_TAGS.pre: {
|
|
||||||
// exchange of newParagraph and oldParagraph
|
|
||||||
const codeMirrorWrapper = updateBlock(oldParagraph, lineBreakUpdate.type)
|
|
||||||
operateClassName(codeMirrorWrapper, 'add', CLASS_OR_ID['AG_CODE_BLOCK'])
|
|
||||||
|
|
||||||
codeMirrorWrapper.innerHTML = ''
|
|
||||||
const config = Object.assign(codeMirrorConfig, {
|
|
||||||
autofocus
|
|
||||||
})
|
|
||||||
const codeBlock = codeMirror(codeMirrorWrapper, config)
|
|
||||||
const input = createInputInCodeBlock(codeMirrorWrapper)
|
|
||||||
|
|
||||||
const handler = langMode => {
|
|
||||||
const { mode } = langMode
|
|
||||||
setMode(codeBlock, mode)
|
|
||||||
.then(mode => {
|
|
||||||
codeMirrorWrapper.setAttribute('lang', mode.name)
|
|
||||||
input.value = mode.name
|
|
||||||
input.blur()
|
|
||||||
setCursorAtLastLine(codeBlock)
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.warn(err)
|
|
||||||
})
|
|
||||||
this.floatBox.hideIfNeeded()
|
|
||||||
}
|
|
||||||
|
|
||||||
handler({mode: lineBreakUpdate.info})
|
|
||||||
|
|
||||||
eventCenter.attachDOMEvent(input, 'keyup', () => {
|
|
||||||
const value = input.value
|
|
||||||
eventCenter.dispatch('editLanguage', input, value.trim(), handler)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!isLastChildElement(newParagraph) && autofocus) {
|
|
||||||
removeNode(newParagraph)
|
|
||||||
}
|
|
||||||
if (autofocus) {
|
|
||||||
operateClassName(codeMirrorWrapper, 'add', CLASS_OR_ID['AG_ACTIVE'])
|
|
||||||
this.activeParagraph = {
|
|
||||||
id: codeMirrorWrapper.id,
|
|
||||||
paragraph: codeMirrorWrapper
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.codeBlocks.set(codeMirrorWrapper.id, codeBlock)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
case LOWERCASE_TAGS.hr: {
|
|
||||||
oldParagraph = updateBlock(oldParagraph, LOWERCASE_TAGS.hr)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (oldContext && oldTagName !== LOWERCASE_TAGS.pre) {
|
|
||||||
oldParagraph.innerHTML = markedText2Html(ids, oldParagraph.textContent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// set and remove active className
|
|
||||||
if (oldParagraph) {
|
|
||||||
operateClassName(oldParagraph, 'remove', CLASS_OR_ID['AG_ACTIVE'])
|
|
||||||
}
|
|
||||||
if (newParagraph) {
|
|
||||||
operateClassName(newParagraph, 'add', CLASS_OR_ID['AG_ACTIVE'])
|
|
||||||
this.activeParagraph = {
|
|
||||||
id: newParagraph.id,
|
|
||||||
paragraph: newParagraph
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// dispach arrow event
|
|
||||||
dispatchArrow () {
|
|
||||||
const { container, eventCenter } = this
|
|
||||||
const handler = event => {
|
|
||||||
switch (event.key) {
|
|
||||||
case EVENT_KEYS.ArrowUp: // fallthrough
|
|
||||||
case EVENT_KEYS.ArrowDown: // fallthrough
|
|
||||||
case EVENT_KEYS.ArrowLeft: // fallthrough
|
|
||||||
case EVENT_KEYS.ArrowRight: // fallthrough
|
|
||||||
eventCenter.dispatch('arrow', event)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
eventCenter.attachDOMEvent(container, 'keydown', handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
arrowHander (event) {
|
|
||||||
// when the float box is show, use up and down to select item.
|
|
||||||
const { list, index, show } = this.floatBox
|
|
||||||
const node = selection.getSelectionStart()
|
|
||||||
const paragraph = findNearestParagraph(node)
|
|
||||||
console.log(node)
|
|
||||||
const outMostParagraph = findOutMostParagraph(node)
|
|
||||||
const { left, right } = selection.getCaretOffsets(paragraph)
|
|
||||||
let preParagraph = outMostParagraph.previousElementSibling
|
|
||||||
let nextParagraph = outMostParagraph.nextElementSibling
|
|
||||||
if (show && (event.key === EVENT_KEYS.ArrowUp || event.key === EVENT_KEYS.ArrowDown)) {
|
|
||||||
event.preventDefault()
|
|
||||||
switch (event.key) {
|
|
||||||
case EVENT_KEYS.ArrowDown:
|
|
||||||
if (index < list.length - 1) {
|
|
||||||
this.floatBox.setOptions(list, index + 1)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case EVENT_KEYS.ArrowUp:
|
|
||||||
if (index > 0) {
|
|
||||||
this.floatBox.setOptions(list, index - 1)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else if (isCodeBlockParagraph(paragraph)) {
|
|
||||||
// handle cursor in code block. the case at firstline or lastline.
|
|
||||||
const codeBlockId = paragraph.id
|
|
||||||
const cm = this.codeBlocks.get(codeBlockId)
|
|
||||||
|
|
||||||
event.preventDefault()
|
|
||||||
switch (event.key) {
|
|
||||||
case EVENT_KEYS.ArrowLeft: // fallthrough
|
|
||||||
case EVENT_KEYS.ArrowUp:
|
|
||||||
if (
|
|
||||||
(event.key === EVENT_KEYS.ArrowUp && isCursorAtFirstLine(cm) && preParagraph) ||
|
|
||||||
(event.key === EVENT_KEYS.ArrowLeft && isCursorAtBegin(cm) && preParagraph)
|
|
||||||
) {
|
|
||||||
if (isCodeBlockParagraph(preParagraph)) {
|
|
||||||
const newParagraph = createEmptyElement(this.ids, LOWERCASE_TAGS.p)
|
|
||||||
operateClassName(newParagraph, 'add', CLASS_OR_ID['AG_TEMP'])
|
|
||||||
insertAfter(newParagraph, preParagraph)
|
|
||||||
preParagraph = newParagraph
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preParagraph.tagName.toLowerCase() === LOWERCASE_TAGS.hr) {
|
|
||||||
hr2P(preParagraph, selection)
|
|
||||||
} else {
|
|
||||||
selection.importSelection({
|
|
||||||
start: preParagraph.textContent.length,
|
|
||||||
end: preParagraph.textContent.length
|
|
||||||
}, preParagraph)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case EVENT_KEYS.ArrowRight: // fallthrough
|
|
||||||
case EVENT_KEYS.ArrowDown:
|
|
||||||
if (
|
|
||||||
(event.key === EVENT_KEYS.ArrowDown && isCursorAtLastLine(cm) && nextParagraph) ||
|
|
||||||
(event.key === EVENT_KEYS.ArrowRight && isCursorAtEnd(cm) && nextParagraph)
|
|
||||||
) {
|
|
||||||
if (isCodeBlockParagraph(nextParagraph)) {
|
|
||||||
const newParagraph = createEmptyElement(this.ids, LOWERCASE_TAGS.p)
|
|
||||||
operateClassName(newParagraph, 'add', CLASS_OR_ID['AG_TEMP'])
|
|
||||||
insertBefore(newParagraph, nextParagraph)
|
|
||||||
nextParagraph = newParagraph
|
|
||||||
}
|
|
||||||
if (nextParagraph.tagName.toLowerCase() === LOWERCASE_TAGS.hr) {
|
|
||||||
hr2P(nextParagraph, selection)
|
|
||||||
} else {
|
|
||||||
selection.importSelection({
|
|
||||||
start: 0,
|
|
||||||
end: 0
|
|
||||||
}, nextParagraph)
|
|
||||||
}
|
|
||||||
} else if (!nextParagraph) {
|
|
||||||
const newParagraph = createEmptyElement(this.ids, LOWERCASE_TAGS.p)
|
|
||||||
insertAfter(newParagraph, paragraph)
|
|
||||||
selection.moveCursor(newParagraph, 0)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else if (
|
|
||||||
(isCodeBlockParagraph(preParagraph) && event.key === EVENT_KEYS.ArrowUp) ||
|
|
||||||
(isCodeBlockParagraph(preParagraph) && event.key === EVENT_KEYS.ArrowLeft && left === 0)
|
|
||||||
) {
|
|
||||||
event.preventDefault()
|
|
||||||
const codeBlockId = preParagraph.id
|
|
||||||
const cm = this.codeBlocks.get(codeBlockId)
|
|
||||||
return setCursorAtLastLine(cm)
|
|
||||||
} else if (
|
|
||||||
(isCodeBlockParagraph(nextParagraph) && event.key === EVENT_KEYS.ArrowDown) ||
|
|
||||||
(isCodeBlockParagraph(nextParagraph) && event.key === EVENT_KEYS.ArrowRight && right === 0)
|
|
||||||
) {
|
|
||||||
event.preventDefault()
|
|
||||||
const codeBlockId = nextParagraph.id
|
|
||||||
const cm = this.codeBlocks.get(codeBlockId)
|
|
||||||
return setCursorAtFirstLine(cm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
imageClick () {
|
|
||||||
const { container, eventCenter } = this
|
|
||||||
const handler = event => {
|
|
||||||
const target = event.target
|
|
||||||
const markedImageText = target.previousElementSibling
|
|
||||||
if (markedImageText && markedImageText.classList.contains(CLASS_OR_ID['AG_IMAGE_MARKED_TEXT'])) {
|
|
||||||
const textLen = markedImageText.textContent.length
|
|
||||||
operateClassName(markedImageText, 'remove', CLASS_OR_ID['AG_HIDE'])
|
|
||||||
operateClassName(markedImageText, 'add', CLASS_OR_ID['AG_GRAY'])
|
|
||||||
selection.importSelection({
|
|
||||||
start: textLen,
|
|
||||||
end: textLen
|
|
||||||
}, markedImageText)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eventCenter.attachDOMEvent(container, 'click', handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
getMarkdown () {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
getHtml () {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Aganippe
|
|
@ -105,7 +105,7 @@ export const findPreviousSibling = node => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var previousSibling = node.previousSibling
|
let previousSibling = node.previousSibling
|
||||||
while (!previousSibling && !isAganippeEditorElement(node.parentNode)) {
|
while (!previousSibling && !isAganippeEditorElement(node.parentNode)) {
|
||||||
node = node.parentNode
|
node = node.parentNode
|
||||||
previousSibling = node.previousSibling
|
previousSibling = node.previousSibling
|
||||||
@ -159,10 +159,6 @@ export const createInputInCodeBlock = codeEle => {
|
|||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isCodeBlockParagraph = paragraph => {
|
|
||||||
return paragraph && paragraph.classList.contains(CLASS_OR_ID['AG_CODE_BLOCK'])
|
|
||||||
}
|
|
||||||
|
|
||||||
// DOM operations
|
// DOM operations
|
||||||
export const insertAfter = (newNode, originNode) => {
|
export const insertAfter = (newNode, originNode) => {
|
||||||
const parentNode = originNode.parentNode
|
const parentNode = originNode.parentNode
|
||||||
|
Loading…
Reference in New Issue
Block a user