mirror of
https://github.com/marktext/marktext.git
synced 2025-05-12 06:50:32 +08:00
feat: export Markdown but list in blockquote has bug
This commit is contained in:
parent
23fa376152
commit
814bd6d3d5
@ -75,6 +75,13 @@ class ContentState {
|
|||||||
|
|
||||||
// getBlocks
|
// getBlocks
|
||||||
getBlocks () {
|
getBlocks () {
|
||||||
|
let key
|
||||||
|
let cm
|
||||||
|
for ([ key, cm ] of this.codeBlocks.entries()) {
|
||||||
|
const value = cm.getValue()
|
||||||
|
const block = this.getBlock(key)
|
||||||
|
if (block) block.text = value
|
||||||
|
}
|
||||||
return this.blocks
|
return this.blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ export const setInlineEmoji = (node, emoji, selection) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Emoji {
|
class Emoji {
|
||||||
constructor (event) {
|
constructor () {
|
||||||
this.cache = new Map()
|
this.cache = new Map()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,14 +8,16 @@ 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, operateClassName } from './utils/domManipulate'
|
import { findNearestParagraph, operateClassName } from './utils/domManipulate'
|
||||||
|
import ExportMarkdown from './utils/exportMarkdown'
|
||||||
|
import fs from 'fs'
|
||||||
|
|
||||||
class Aganippe {
|
class Aganippe {
|
||||||
constructor (container, options) {
|
constructor (container, options) {
|
||||||
this.container = container
|
this.container = container
|
||||||
this.eventCenter = eventCenter
|
this.eventCenter = eventCenter
|
||||||
this.floatBox = floatBox
|
this.floatBox = floatBox
|
||||||
this.contentState = new ContentState(this.floatBox)
|
this.contentState = new ContentState()
|
||||||
this.emoji = new Emoji(this.eventCenter) // emoji instance: has search(text) clear() methods.
|
this.emoji = new Emoji() // emoji instance: has search(text) clear() methods.
|
||||||
|
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
@ -39,6 +41,15 @@ class Aganippe {
|
|||||||
this.contentState.history.undo()
|
this.contentState.history.undo()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
eventCenter.bind('command+s', event => {
|
||||||
|
const blocks = this.contentState.getBlocks()
|
||||||
|
const markdown = new ExportMarkdown(blocks).generate()
|
||||||
|
console.log(blocks)
|
||||||
|
fs.writeFile('./src/editor/output.md', markdown, 'utf-8', (err, data) => {
|
||||||
|
if (err) console.log(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
// 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))
|
||||||
|
|
||||||
|
5
src/editor/output.md
Normal file
5
src/editor/output.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
> hello
|
||||||
|
>
|
||||||
|
- > hello
|
||||||
|
>
|
||||||
|
- > owowow
|
@ -56,7 +56,7 @@ class StateRender {
|
|||||||
if (block.children.length) {
|
if (block.children.length) {
|
||||||
return h(blockSelector, block.children.map(child => renderBlock(child)))
|
return h(blockSelector, block.children.map(child => renderBlock(child)))
|
||||||
} else {
|
} else {
|
||||||
const children = block.text
|
let children = block.text
|
||||||
? tokenizer(block.text).reduce((acc, token) => {
|
? tokenizer(block.text).reduce((acc, token) => {
|
||||||
const chunk = this[token.type](h, cursor, block, token)
|
const chunk = this[token.type](h, cursor, block, token)
|
||||||
return Array.isArray(chunk) ? [...acc, ...chunk] : [...acc, chunk]
|
return Array.isArray(chunk) ? [...acc, ...chunk] : [...acc, chunk]
|
||||||
@ -74,6 +74,7 @@ class StateRender {
|
|||||||
if (block.type === 'pre') {
|
if (block.type === 'pre') {
|
||||||
if (block.lang) Object.assign(data.dataset, { lang: block.lang })
|
if (block.lang) Object.assign(data.dataset, { lang: block.lang })
|
||||||
blockSelector += `.${CLASS_OR_ID['AG_CODE_BLOCK']}`
|
blockSelector += `.${CLASS_OR_ID['AG_CODE_BLOCK']}`
|
||||||
|
children = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block.temp) {
|
if (block.temp) {
|
||||||
|
148
src/editor/utils/exportMarkdown.js
Normal file
148
src/editor/utils/exportMarkdown.js
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
const LINE_BREAKS = /\n/
|
||||||
|
|
||||||
|
class ExportMarkdown {
|
||||||
|
constructor (blocks) {
|
||||||
|
this.blocks = blocks
|
||||||
|
this.listType = [] // 'ul' or 'ol'
|
||||||
|
this.blockquoteType = []
|
||||||
|
}
|
||||||
|
|
||||||
|
generate () {
|
||||||
|
this.addDepth2Block(this.blocks, 0)
|
||||||
|
return this.translateBlocks2Markdown(this.blocks, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
translateBlocks2Markdown (blocks, inLen) {
|
||||||
|
const result = []
|
||||||
|
const len = blocks.length
|
||||||
|
const indent = ' '.repeat(inLen)
|
||||||
|
let i
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
const block = blocks[i]
|
||||||
|
switch (block.type) {
|
||||||
|
case 'p':
|
||||||
|
this.insertLineBreak(result, indent)
|
||||||
|
result.push(this.normalizeParagraphText(block, indent))
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'h1':
|
||||||
|
case 'h2':
|
||||||
|
case 'h3':
|
||||||
|
case 'h4':
|
||||||
|
case 'h5':
|
||||||
|
case 'h6':
|
||||||
|
this.insertLineBreak(result, indent)
|
||||||
|
result.push(this.normalizeHeaderText(block, indent))
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'li':
|
||||||
|
this.insertLineBreak(result, indent)
|
||||||
|
result.push(this.normalizeListItem(block, indent))
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'ul':
|
||||||
|
this.insertLineBreak(result, indent)
|
||||||
|
this.listType.push({ type: 'ul' })
|
||||||
|
result.push(this.normalizeList(block, indent))
|
||||||
|
this.listType.pop()
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'ol':
|
||||||
|
this.insertLineBreak(result, indent)
|
||||||
|
const listCount = block.start !== undefined ? block.start : 1
|
||||||
|
this.listType.push({ type: 'ol', listCount })
|
||||||
|
result.push(this.normalizeList(block, indent))
|
||||||
|
this.listType.pop()
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'pre':
|
||||||
|
this.insertLineBreak(result, indent)
|
||||||
|
result.push(this.normalizeCodeBlock(block, indent))
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'blockquote':
|
||||||
|
this.insertLineBreak(result, indent)
|
||||||
|
this.blockquoteType.push({ type: 'blockquote' })
|
||||||
|
result.push(this.normalizeBlockquote(block, indent))
|
||||||
|
this.blockquoteType.pop()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(result)
|
||||||
|
return result.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
insertLineBreak (result, indent) {
|
||||||
|
if (result.length > 0) {
|
||||||
|
const depth = this.blockquoteType.length
|
||||||
|
const blockquotePrefix = depth ? `${'>'.repeat(depth)} ` : ''
|
||||||
|
result.push(blockquotePrefix ? `${indent}${blockquotePrefix}\n` : '\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
insertBlockquotePrefix (text, indent) {
|
||||||
|
const depth = this.blockquoteType.length
|
||||||
|
const blockquotePrefix = depth ? `${'> '.repeat(depth)}` : ''
|
||||||
|
return `${indent}${blockquotePrefix}${text}\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizeHeaderText (block, indent) {
|
||||||
|
const match = block.text.match(/(#{1,6})(.*)/)
|
||||||
|
const text = `${match[1]} ${match[2].trim()}`
|
||||||
|
return this.insertBlockquotePrefix(text, indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizeParagraphText (block, indent) {
|
||||||
|
return this.insertBlockquotePrefix(block.text, indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizeBlockquote (block, indent) {
|
||||||
|
const { children } = block
|
||||||
|
return this.translateBlocks2Markdown(children, indent.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizeCodeBlock (block, indent) {
|
||||||
|
const result = []
|
||||||
|
const textList = block.text.split(LINE_BREAKS)
|
||||||
|
result.push(this.insertBlockquotePrefix(block.lang ? '```' + block.lang : '```', indent))
|
||||||
|
|
||||||
|
textList.forEach(text => {
|
||||||
|
result.push(this.insertBlockquotePrefix(text, indent))
|
||||||
|
})
|
||||||
|
result.push(this.insertBlockquotePrefix('```', indent))
|
||||||
|
return result.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizeList (block, indent) {
|
||||||
|
const { children } = block
|
||||||
|
return this.translateBlocks2Markdown(children, indent.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizeListItem (block, indent) {
|
||||||
|
const result = []
|
||||||
|
const listInfo = this.listType[this.listType.length - 1]
|
||||||
|
const itemMarker = listInfo.type === 'ul' ? '- ' : `${listInfo.listCount++}. `
|
||||||
|
const { children } = block
|
||||||
|
|
||||||
|
result.push(`${indent}${itemMarker}`)
|
||||||
|
result.push(this.translateBlocks2Markdown(children, indent.length + itemMarker.length).trimLeft())
|
||||||
|
|
||||||
|
return result.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
addDepth2Block (blocks, initDepth) {
|
||||||
|
const len = blocks.length
|
||||||
|
let i
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
const block = blocks[i]
|
||||||
|
block.depth = initDepth
|
||||||
|
const { children } = block
|
||||||
|
if (children.length) {
|
||||||
|
this.addDepth2Block(children, initDepth + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ExportMarkdown
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<ul ref="editor">
|
<div ref="editor">
|
||||||
</ul>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
Loading…
Reference in New Issue
Block a user