Browse Source

fix: Added checkbox support for md <-> html conversions

pull/7046/head
Muhammed Mustafa 1 year ago
parent
commit
c549433b71
  1. 57
      packages/nc-gui/components/cell/RichText.vue

57
packages/nc-gui/components/cell/RichText.vue

@ -4,7 +4,7 @@ import TaskItem from '@tiptap/extension-task-item'
import TaskList from '@tiptap/extension-task-list' import TaskList from '@tiptap/extension-task-list'
import { EditorContent, useEditor } from '@tiptap/vue-3' import { EditorContent, useEditor } from '@tiptap/vue-3'
import TurndownService from 'turndown' import TurndownService from 'turndown'
import { parse } from 'marked' import { marked } from 'marked'
import { generateJSON } from '@tiptap/html' import { generateJSON } from '@tiptap/html'
import Underline from '@tiptap/extension-underline' import Underline from '@tiptap/extension-underline'
import { Link } from '@/helpers/dbTiptapExtensions/links' import { Link } from '@/helpers/dbTiptapExtensions/links'
@ -21,6 +21,59 @@ const emits = defineEmits(['update:value'])
const turndownService = new TurndownService() const turndownService = new TurndownService()
turndownService.addRule('taskList', {
filter: (node) => {
return node.nodeName === 'LI' && !!node.getAttribute('data-checked')
},
replacement: (content) => {
// Remove the first \n\n and last \n\n
const processContent = content.replace(/^\n\n/, '').replace(/\n\n$/, '')
return `[ ] ${processContent}\n\n`
},
})
const checkListItem = {
name: 'checkListItem',
level: 'block',
tokenizer(src: string) {
src = src.split('\n\n')[0]
const isMatched = src.startsWith('[ ]') || src.startsWith('[x]') || src.startsWith('[X]')
if (isMatched) {
const isNotChecked = src.startsWith('[ ]')
let text = src.slice(3)
if (text[0] === ' ') text = text.slice(1)
const token = {
// Token to generate
type: 'checkListItem',
raw: src,
text,
tokens: [],
checked: !isNotChecked,
}
;(this as any).lexer.inline(token.text, token.tokens) // Queue this data to be processed for inline tokens
return token
}
return false
},
renderer(token: any) {
return `<ul data-type="taskList">
<li data-checked="false">
<label>
<input type="checkbox" />
</label>
<div>
<p>${(this as any).parser.parseInline(token.tokens)}</p>
</div>
</ul>` // parseInline to turn child tokens into HTML
},
}
marked.use({ extensions: [checkListItem] })
const editorDom = ref<HTMLElement | null>(null) const editorDom = ref<HTMLElement | null>(null)
const vModel = useVModel(props, 'value', emits, { defaultValue: '' }) const vModel = useVModel(props, 'value', emits, { defaultValue: '' })
@ -52,7 +105,7 @@ const setEditorContent = (contentMd: any) => {
const selection = editor.value.view.state.selection const selection = editor.value.view.state.selection
const contentHtml = contentMd ? parse(contentMd) : '<p></p>' const contentHtml = contentMd ? marked.parse(contentMd) : '<p></p>'
const content = generateJSON(contentHtml, tiptapExtensions) const content = generateJSON(contentHtml, tiptapExtensions)

Loading…
Cancel
Save