Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/text.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/nodes
diff options
context:
space:
mode:
authorVinicius Reis <vinicius.reis@nextcloud.com>2022-08-16 22:10:58 +0300
committerVinicius Reis <vinicius.reis@nextcloud.com>2022-08-17 17:42:59 +0300
commit381797c4c6730c918e0c0fa57e3e838059d828d2 (patch)
tree30145e9f80568f7f4893857382b6527b884f2c31 /src/nodes
parent27fbf269951d7384b0bb99f5f79fb86b0002bd24 (diff)
♻️ (#107): split heading logic: extractHeadings
Signed-off-by: Vinicius Reis <vinicius.reis@nextcloud.com>
Diffstat (limited to 'src/nodes')
-rw-r--r--src/nodes/Heading.js107
-rw-r--r--src/nodes/Heading/extractor.js68
-rw-r--r--src/nodes/Heading/index.js40
-rw-r--r--src/nodes/Heading/slug.js10
4 files changed, 118 insertions, 107 deletions
diff --git a/src/nodes/Heading.js b/src/nodes/Heading.js
deleted file mode 100644
index 6270731aa..000000000
--- a/src/nodes/Heading.js
+++ /dev/null
@@ -1,107 +0,0 @@
-import TipTapHeading from '@tiptap/extension-heading'
-import debounce from 'debounce'
-import { v4 as uuidv4 } from 'uuid'
-
-import store from '../store/index.js'
-
-const regexSpaces = /\s+/g
-const regexInvalidCaracters = /[^\p{Letter}\p{Mark}\w\s-]/gu
-
-const slugify = (str) => String(str)
- .toLowerCase()
- .replace(regexInvalidCaracters, '')
- .trim()
- .replace(regexSpaces, '-')
-
-const setHeadings = (val) => store.dispatch('setHeadings', val)
-
-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 }) {
- 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)
-
- }, 900),
-
-})
-
-export default Heading
diff --git a/src/nodes/Heading/extractor.js b/src/nodes/Heading/extractor.js
new file mode 100644
index 000000000..ae9245154
--- /dev/null
+++ b/src/nodes/Heading/extractor.js
@@ -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,
+}
diff --git a/src/nodes/Heading/index.js b/src/nodes/Heading/index.js
new file mode 100644
index 000000000..258b094fb
--- /dev/null
+++ b/src/nodes/Heading/index.js
@@ -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
diff --git a/src/nodes/Heading/slug.js b/src/nodes/Heading/slug.js
new file mode 100644
index 000000000..266a42ed3
--- /dev/null
+++ b/src/nodes/Heading/slug.js
@@ -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 }