Skip to content

Commit

Permalink
♻️ (#107): split heading logic: extractHeadings
Browse files Browse the repository at this point in the history
Signed-off-by: Vinicius Reis <vinicius.reis@nextcloud.com>
  • Loading branch information
Vinicius Reis committed Aug 16, 2022
1 parent 8042a2b commit 7651779
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 108 deletions.
2 changes: 1 addition & 1 deletion src/extensions/RichText.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import HardBreak from './HardBreak.js'
import KeepSyntax from './KeepSyntax.js'
import Table from './../nodes/Table.js'
import Image from './../nodes/Image.js'
import Heading from './../nodes/Heading.js'
import Heading from '../nodes/Heading/index.js'
import BulletList from './../nodes/BulletList.js'
import TaskList from './../nodes/TaskList.js'
import TaskItem from './../nodes/TaskItem.js'
Expand Down
107 changes: 0 additions & 107 deletions src/nodes/Heading.js

This file was deleted.

68 changes: 68 additions & 0 deletions src/nodes/Heading/extractor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@

import store from '../../store/index.js'
import { slugify } from './slug.js'
import { v4 as uuidv4 } from 'uuid'

const setHeadings = (val) => store.dispatch('setHeadings', val)

const extractHeadings = (editor) => {
const counter = new Map()
const headings = []
const tr = editor.state.tr

const getId = text => {
const id = slugify(text)

if (counter.has(id)) {
const next = counter.get(id)

// increment counter
counter.set(id, next + 1)

return `${id}--${next}`
}

// define counter
counter.set(id, 1)

return id
}

editor.state.doc.descendants((node, position) => {
if (node.type.name === 'heading') {
const text = node.textContent
const id = getId(text)
const uuid = node.attrs.uuid ?? uuidv4()

if (node.attrs.id !== id || !node.attrs.uuid) {
const attrs = {
...node.attrs,
uuid,
id,
}

tr.setNodeMarkup(position, undefined, attrs)
}

headings.push(Object.freeze({
level: node.attrs.level,
position,
text,
id,
uuid,
}))
}
})

tr.setMeta('addToHistory', false)
tr.setMeta('preventUpdate', true)

editor.view.dispatch(tr)

setHeadings(headings)
}

export {
extractHeadings,
setHeadings,
}
40 changes: 40 additions & 0 deletions src/nodes/Heading/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import TipTapHeading from '@tiptap/extension-heading'
import debounce from 'debounce'
import { setHeadings, extractHeadings } from './extractor.js'

const Heading = TipTapHeading.extend({
addAttributes() {
return {
...this.parent(),
id: {
default: undefined,
rendered: true,
},
uuid: {
default: undefined,
rendered: false,
},
}
},
addKeyboardShortcuts() {
return this.options.levels.reduce((items, level) => ({
...items,
[`Mod-Shift-${level}`]: () => this.editor.commands.toggleHeading({ level }),
}), {})
},

onDestroy() {
setHeadings([])

if (this.parent) {
this.parent()
}
},

onUpdate: debounce(function onUpdate({ editor }) {
extractHeadings(editor)
}, 900),

})

export default Heading
10 changes: 10 additions & 0 deletions src/nodes/Heading/slug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const regexSpaces = /\s+/g
const regexInvalidCaracters = /[^\p{Letter}\p{Mark}\w\s-]/gu

const slugify = (str) => String(str)
.toLowerCase()
.replace(regexInvalidCaracters, '')
.trim()
.replace(regexSpaces, '-')

export { slugify }

0 comments on commit 7651779

Please sign in to comment.