南柯一梦
南柯一梦

Reputation: 1

How to add serial numbers to custom extensions in Tiptap Editor

I wrote a custom extension for inserting test questions based on tiptap. Now I encounter a problem: how to add an auto-increment serial number to the current custom node when executing insertQuestion

I am not very familiar with tiptap yet, guys. Can you give me an idea?

This is a screenshot of my editor

Below is my insertQuestion.js extension code

import { Node, mergeAttributes } from '@tiptap/core'
import { VueNodeViewRenderer } from '@tiptap/vue-3'

import Component from './InsertQuestionNodeView.vue'

export const InsertQuestion = Node.create({
  name: 'custom-question',

  group: 'block',

  atom: true,

  draggable: true,

  addAttributes() {
    return {
      questionData: {
        default: {},
      },
    }
  },

  parseHTML() {
    return [
      {
        tag: 'div[data-type=custom-question]',
      },
    ]
  },

  renderHTML({ node, HTMLAttributes }) {
    return [
      'div',
      mergeAttributes(
        HTMLAttributes,
        {
          'data-type': node.type.name,
        },
      ),
    ]
  },

  addCommands() {
    return {
      insertQuestion:
      options =>
        ({ commands, state, _editor }) => {
          const { to } = state.selection
          return commands
            .insertContentAt(to, {
              type: this.name,
              attrs: {
                ...options,
              },
            })
        },
    }
  },

  addNodeView() {
    return VueNodeViewRenderer(Component)
  },

})

InsertQuestionNodeView.vue

<template>
  <NodeViewWrapper
    as="div"
    class="question-item"
  >
    <div class="question-content">
      <div v-html="getQuestion.title" />
      <div
        v-for="(option, index) in getQuestion.options"
        :key="index"
      >
        <div class="my-2">
          <span class="inline-block">{{ `${String.fromCharCode(65 + index)}. ` }}</span>
          <span
            class="inline-block"
            v-html="option"
          />
        </div>
      </div>
    </div>
  </NodeViewWrapper>
</template>

<script setup>
import { NodeViewWrapper } from '@tiptap/vue-3'

import { onMounted } from 'vue'

const props = defineProps({
  editor: Object,
  node: Object,
  decorations: Object,
  selected: Boolean,
  getPos: Function,
  updateAttributes: Function,
  deleteNode: Function,
})

const getQuestion = computed(() => {
  return props.node.attrs.questionData
})

// function increase() {
//   props.updateAttributes({
//     count: props.node.attrs.count + 1,
//   })
// }

onMounted(() => {
  // console.log('%c [ props ]-11', 'font-size:13px; background:pink; color:#bf2c9f;', props.node)
})
</script>

<style lang="scss" scoped>
.question-item {
  @apply flex p-4
  rounded-md cursor-pointer
  border border-solid border-transparent
  hover:border-solid hover:border hover:border-gray-400 flex-wrap;

  .question-content {
    @apply w-full;
  }

  :deep(table td) {
    border: none;
  }
}
</style>

The following are the function points I need to complete

  1. When inserting a test question, the serial number will increase automatically.
  2. Need to reorder after encountering heading node
  3. For example, if I insert five questions 1 2 3 4 5 now, I delete question No. 2. All the test question nodes after the question must be reordered.

Upvotes: 0

Views: 167

Answers (0)

Related Questions