diff --git a/src/editor/contentState/index.js b/src/editor/contentState/index.js
index 9952ad17..bcfc7458 100644
--- a/src/editor/contentState/index.js
+++ b/src/editor/contentState/index.js
@@ -75,6 +75,13 @@ class ContentState {
// 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
}
diff --git a/src/editor/emojis/index.js b/src/editor/emojis/index.js
index 1f25ca35..80bc2c13 100644
--- a/src/editor/emojis/index.js
+++ b/src/editor/emojis/index.js
@@ -31,7 +31,7 @@ export const setInlineEmoji = (node, emoji, selection) => {
}
class Emoji {
- constructor (event) {
+ constructor () {
this.cache = new Map()
}
diff --git a/src/editor/index.js b/src/editor/index.js
index f93ef445..d552414f 100644
--- a/src/editor/index.js
+++ b/src/editor/index.js
@@ -8,14 +8,16 @@ import { checkEditLanguage, replaceLanguage } from './codeMirror/language'
import Emoji, { checkEditEmoji, setInlineEmoji } from './emojis'
import floatBox from './floatBox'
import { findNearestParagraph, operateClassName } from './utils/domManipulate'
+import ExportMarkdown from './utils/exportMarkdown'
+import fs from 'fs'
class Aganippe {
constructor (container, options) {
this.container = container
this.eventCenter = eventCenter
this.floatBox = floatBox
- this.contentState = new ContentState(this.floatBox)
- this.emoji = new Emoji(this.eventCenter) // emoji instance: has search(text) clear() methods.
+ this.contentState = new ContentState()
+ this.emoji = new Emoji() // emoji instance: has search(text) clear() methods.
this.init()
}
@@ -39,6 +41,15 @@ class Aganippe {
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.
eventCenter.attachDOMEvent(container, 'keydown', debounce(() => this.contentState.garbageCollection(), 1000))
diff --git a/src/editor/output.md b/src/editor/output.md
new file mode 100644
index 00000000..88e9d507
--- /dev/null
+++ b/src/editor/output.md
@@ -0,0 +1,5 @@
+> hello
+>
+- > hello
+>
+- > owowow
diff --git a/src/editor/parser/StateRender.js b/src/editor/parser/StateRender.js
index 04db79cc..fbfd7538 100644
--- a/src/editor/parser/StateRender.js
+++ b/src/editor/parser/StateRender.js
@@ -56,7 +56,7 @@ class StateRender {
if (block.children.length) {
return h(blockSelector, block.children.map(child => renderBlock(child)))
} else {
- const children = block.text
+ let children = block.text
? tokenizer(block.text).reduce((acc, token) => {
const chunk = this[token.type](h, cursor, block, token)
return Array.isArray(chunk) ? [...acc, ...chunk] : [...acc, chunk]
@@ -74,6 +74,7 @@ class StateRender {
if (block.type === 'pre') {
if (block.lang) Object.assign(data.dataset, { lang: block.lang })
blockSelector += `.${CLASS_OR_ID['AG_CODE_BLOCK']}`
+ children = ''
}
if (block.temp) {
diff --git a/src/editor/utils/exportMarkdown.js b/src/editor/utils/exportMarkdown.js
new file mode 100644
index 00000000..bf8e8b71
--- /dev/null
+++ b/src/editor/utils/exportMarkdown.js
@@ -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
diff --git a/src/renderer/components/Editor.vue b/src/renderer/components/Editor.vue
index 00dde1e3..9228a9dc 100644
--- a/src/renderer/components/Editor.vue
+++ b/src/renderer/components/Editor.vue
@@ -1,6 +1,6 @@
-
+
+