Ver código fonte

improvement: ‘====’分页符切割页面逻辑

ChenYangfan 6 anos atrás
pai
commit
63c619d49d

+ 75 - 32
src/components/editor/EditableItem.vue

@@ -1,16 +1,16 @@
 <template>
   <component
     ref="element"
-    :is="tagName"
+    :is="showInfo.tagName"
     :id="item.id"
     @compositionstart.stop="handleCompositionStart"
     @compositionend.stop="handleCompositionEnd"
     @input.stop="handleInput"
     @keydown.stop="handleKeyDown"
     contenteditable
-    v-html="contentForShow"
-    :class="contentForShow ? '' : 'placeholder'"
-    :placeholder="item.placeholder"
+    v-html="showInfo.content"
+    :class="showInfo.className"
+    :placeholder="showInfo.placeholder"
   >
   </component>
 </template>
@@ -34,31 +34,55 @@ export default {
     return {
       isCompositionStarted: false,
       range: null,
-      tagName: 'div',
-      contentForShow: ''
+      type: 'div'
     }
   },
   mounted() {
-    this.init()
+    this.type = this.matchType(this.item.content)
   },
   updated() {
-    this.init()
+    this.type = this.matchType(this.item.content)
+  },
+  computed: {
+    showInfo() {
+      if (this.type === 'slideBreak') {
+        const content = ''
+        return {
+          tagName: 'div',
+          className: {
+            placeholder: true,
+            slideBreak: true
+          },
+          content,
+          placeholder: this.item.placeholder
+        }
+      } else if (this.type === 'div') {
+        const content = this.item.content
+        return {
+          tagName: 'div',
+          className: { placeholder: content === '' },
+          content,
+          placeholder: this.item.placeholder
+        }
+      } else {
+        const content = this.item.content.replace(blockTypeRegs[this.type], '')
+        return {
+          tagName: this.type,
+          className: { placeholder: content === '' },
+          content,
+          placeholder: this.item.placeholder
+        }
+      }
+    }
   },
   methods: {
-    init() {
-      this.tagName = this.matchTagName()
-      this.contentForShow =
-        this.tagName === 'div'
-          ? this.item.content
-          : this.item.content.replace(blockTypeRegs[this.tagName], '')
-    },
-    matchTagName() {
+    matchType(content) {
       let res = 'div'
       Object.entries(blockTypeRegs)
-        .map(array => ({ tagName: array[0], reg: array[1] }))
-        .some(({ tagName, reg }) => {
-          if (reg.test(this.item.content)) {
-            res = tagName
+        .map(array => ({ type: array[0], reg: array[1] }))
+        .some(({ type, reg }) => {
+          if (reg.test(content)) {
+            res = type
           }
         })
       return res
@@ -91,18 +115,15 @@ export default {
             this.range = window.getSelection().getRangeAt(0)
             const offset = this.range.startOffset
 
-            if (
-              offset === 0 &&
-              this.range.collapsed &&
-              this.tagName !== 'div'
-            ) {
+            if (offset === 0 && this.range.collapsed && this.type !== 'div') {
               this.$store.commit(MODIFY_ITEM, {
                 id: this.item.id,
                 diff: {
                   placeholder: defaultPlaceholder['div'],
-                  content: this.contentForShow
+                  content: this.showInfo.content
                 }
               })
+
               this.$store.commit(SET_FOCUS, {
                 diff: { focusId: this.item.id, offset }
               })
@@ -124,6 +145,9 @@ export default {
             break
 
           default:
+            if (this.type === 'slideBreak') {
+              e.preventDefault()
+            }
             break
         }
       }
@@ -140,10 +164,10 @@ export default {
     },
     handleInputValue(e) {
       const diff = {
-        content: defaultMarkdownFagment[this.tagName] + e.target.textContent
+        content: defaultMarkdownFagment[this.type] + e.target.textContent
       }
-      if (this.tagName === 'div' && this.matchTagName() !== this.tagName) {
-        diff.placeholder = defaultPlaceholder[this.matchTagName()]
+      if (this.type === 'div' && this.matchType(diff.content) !== this.type) {
+        diff.placeholder = defaultPlaceholder[this.matchType(diff.content)]
       }
 
       this.$store.commit(MODIFY_ITEM, {
@@ -151,10 +175,21 @@ export default {
         diff
       })
 
-      this.range = window.getSelection().getRangeAt(0)
-      const offset = this.range.startOffset
+      if (this.matchType(diff.content) === 'slideBreak') {
+        this.$store.commit(ADD_ITEM_AFTER, { id: this.item.id })
 
-      this.$store.commit(SET_FOCUS, { diff: { focusId: this.item.id, offset } })
+        this.$store.commit(SET_FOCUS_AFTER, {
+          focusId: this.item.id,
+          offset: 0
+        })
+      } else {
+        this.range = window.getSelection().getRangeAt(0)
+        const offset = this.range.startOffset
+
+        this.$store.commit(SET_FOCUS, {
+          diff: { focusId: this.item.id, offset }
+        })
+      }
     }
   }
 }
@@ -179,4 +214,12 @@ export default {
     color: #bbb;
   }
 }
+.slideBreak {
+  color: lightblue;
+
+  &:empty:before {
+    content: attr(placeholder);
+    color: lightblue;
+  }
+}
 </style>

+ 1 - 4
src/components/editor/EditingPage.vue

@@ -1,10 +1,7 @@
 <template>
   <section class="page">
     <template v-for="item in page.items">
-      <editable-item-vue
-        :key="item.id"
-        :item="item"
-      />
+      <editable-item-vue :key="item.id" :item="item" />
     </template>
   </section>
 </template>

+ 10 - 4
src/components/editor/Editor.vue

@@ -26,15 +26,21 @@ export default {
       let lastIndex = 0
       let times = 0
       items.forEach((item, index) => {
-        if (item.content === '===') {
-          pages.push({ items: [...items].slice(lastIndex, index) })
-          lastIndex = index
+        if (item.content === '====') {
+          pages.push({ items: [...items].slice(lastIndex, index + 1) })
+          lastIndex = index + 1
         }
         times = index
       })
       if (times !== items.length) {
-        pages.push({ items: [...items].slice(lastIndex) })
+        const page = { items: [...items].slice(lastIndex) }
+        // if (page.items.length === 0) {
+        //   const id = items[items.length - 1].id
+        //   this.$store.commit(ADD_ITEM_AFTER, { id })
+        // }
+        pages.push(page)
       }
+
       return pages
     },
     focus() {

+ 3 - 3
src/utils/block-type-regs.js

@@ -15,12 +15,12 @@ blockTypeRegs.blockquote = new RegExp(/^>\s/)
 
 blockTypeRegs.hr = new RegExp(/---/)
 
-blockTypeRegs.slideBreakReg = new RegExp(/===/)
+blockTypeRegs.slideBreak = new RegExp(/====/)
 
 blockTypeRegs.pre = new RegExp(/^```([\\s\\S]*?)```$/)
 
-blockTypeRegs.ulItemReg = new RegExp(/^[\\s]-\s/)
+blockTypeRegs.ulli = new RegExp(/^[\\s]-\s/)
 
-blockTypeRegs.olItemReg = new RegExp(/^[\\s][0-9]+\s/)
+blockTypeRegs.olli = new RegExp(/^[\\s][0-9]+\s/)
 
 export default blockTypeRegs

+ 3 - 2
src/utils/default-markdown-fagment.js

@@ -7,7 +7,8 @@ defaultMarkdownFagment.h4 = '#### '
 defaultMarkdownFagment.h5 = '#####'
 defaultMarkdownFagment.h6 = '######'
 defaultMarkdownFagment.blockquote = '> '
-defaultMarkdownFagment.ol = '1. '
-defaultMarkdownFagment.ul = '- '
+defaultMarkdownFagment.olli = '1. '
+defaultMarkdownFagment.ulli = '- '
+defaultMarkdownFagment.slideBreak = '===='
 
 export default defaultMarkdownFagment

+ 1 - 0
src/utils/default-placeholder.js

@@ -9,5 +9,6 @@ defaultPlaceholder.h6 = '未编辑小标题'
 defaultPlaceholder.blockquote = '未编辑引用项'
 defaultPlaceholder.ol = '未编辑有序列表'
 defaultPlaceholder.ul = '未编辑无序列表'
+defaultPlaceholder.slideBreak = '(分页符)'
 
 export default defaultPlaceholder