Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
710b350
refactor(links): move linkBubble plugin to plugins/links
max-nextcloud Mar 15, 2024
e6049b0
refactor(links): pass editor via options to LinkBubblePluginView
max-nextcloud Mar 15, 2024
d871277
refactor(links): untangle LinkBubblePluginView from editor
max-nextcloud Mar 15, 2024
e4340f8
refactor(links): use prosemirror tr and state to track clicks
max-nextcloud Mar 17, 2024
90b99be
refactor(links): move click handling into link bubble plugin
max-nextcloud Mar 17, 2024
356509b
refactor(links): only hand link mark to updateTooltip
max-nextcloud Mar 17, 2024
e30c78c
refactor(links): introduce setActiveLink function
max-nextcloud Mar 18, 2024
d956fdd
fix(links): also update if active was unset
max-nextcloud Mar 18, 2024
e02c5ad
refactor(links): operate on state with `linkNodeFromSelection`
max-nextcloud Mar 18, 2024
c1e4bd8
refactor(links): move linkNodeFromSelection into helper
max-nextcloud Mar 18, 2024
96097aa
refactor(links): handle selection changes in plugin
max-nextcloud Mar 18, 2024
4a3165b
refactor(links): use hideLinkBubble command for esc
max-nextcloud Mar 19, 2024
ed923f4
fix(links): simplify updateTooltip and handle active null
max-nextcloud Mar 19, 2024
4bc7586
fix(links): remove special handling for clicked and focus
max-nextcloud Mar 19, 2024
7fe10f9
fix(links): handle esc in DOMEvents rather than prop
max-nextcloud Mar 19, 2024
d79b67c
fix(links) handle linkNodeFromSelection returning false
max-nextcloud Mar 19, 2024
4f5277e
enh(links): close link bubble when opening preview toggle
max-nextcloud Mar 19, 2024
d582f38
fix(lint): add missing jsdoc comments to new files
max-nextcloud Mar 19, 2024
322a752
docs(preview): improve jsdocs for markdownit preview plugin
max-nextcloud Mar 19, 2024
8e78cb7
refactor(links): only get mark from selection
max-nextcloud Mar 20, 2024
385b246
refactor(links): get active link from selection
max-nextcloud Mar 20, 2024
c2fd1e5
fix(links): show bubble with cursor on the end of the link
max-nextcloud Mar 20, 2024
fb0a8ce
tests(links): ignore link bubble when reading link text
max-nextcloud Mar 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refactor(links): move linkNodeFromSelection into helper
Signed-off-by: Max <[email protected]>
  • Loading branch information
max-nextcloud committed Mar 20, 2024
commit c1e4bd8da7a6d7a296ce5a97a2d4da74753f67a8
45 changes: 2 additions & 43 deletions src/plugins/LinkBubblePluginView.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import tippy from 'tippy.js'
import debounce from 'debounce'
import { domHref } from '../helpers/links.js'
import LinkBubbleView from '../components/Link/LinkBubbleView.vue'
import { linkNodeFromSelection } from './linkHelpers.js'

import { getViewerVue } from '../ViewerVue.js'

Expand Down Expand Up @@ -85,12 +86,9 @@ class LinkBubblePluginView {
const selectionChanged = !oldState?.selection.eq(view.state.selection)
const docChanged = !oldState?.doc.eq(view.state.doc)
return selectionChanged || docChanged

}

updateFromSelection = debounce((view) => {
// Don't update directly after updateFromClick. Prevents race condition in read-only documents in Chrome.

const { state } = view
const { selection } = state

Expand All @@ -100,7 +98,7 @@ class LinkBubblePluginView {

const resolved = view.state.doc.resolve(from)
const nodeStart = resolved.pos - resolved.textOffset
const linkNode = this.linkNodeFromSelection(state)
const linkNode = linkNodeFromSelection(state)

const hasBubbleFocus = this.#component.element.contains(document.activeElement)
const hasEditorFocus = view.hasFocus() || hasBubbleFocus
Expand Down Expand Up @@ -153,45 +151,6 @@ class LinkBubblePluginView {
document.removeEventListener('scroll', this.dragOrScrollHandler, { capture: true })
}

linkNodeFromSelection({ selection, doc }) {
// support for CellSelections
const { ranges } = selection
const from = Math.min(...ranges.map(range => range.$from.pos))
const to = Math.max(...ranges.map(range => range.$to.pos))

const resolved = doc.resolve(from)

// ignore links in previews
if (resolved.parent.type.name === 'preview') {
return false
}

const node = resolved.parent.maybeChild(resolved.index())
const nodeStart = resolved.pos - resolved.textOffset
const nodeEnd = nodeStart + node?.nodeSize

if (to > nodeEnd) {
// Selection spans further than one text node
return
}

return this.isLinkNode(node) ? node : null
}

isLinkNode(node) {
const linkMark = node?.marks.find(m => m.type.name === 'link')
if (!linkMark) {
return false
}

// Don't open link bubble for anchor links
if (linkMark.attrs.href.startsWith('#')) {
return false
}

return true
}

}

export default LinkBubblePluginView
58 changes: 58 additions & 0 deletions src/plugins/linkHelpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* @copyright Copyright (c) 2024 Max <[email protected]>
*
* @author Max <[email protected]>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

export function linkNodeFromSelection({ selection, doc }) {
// support for CellSelections
const { ranges } = selection
const from = Math.min(...ranges.map(range => range.$from.pos))
const to = Math.max(...ranges.map(range => range.$to.pos))

const resolved = doc.resolve(from)

// ignore links in previews
if (resolved.parent.type.name === 'preview') {
return false
}

const node = resolved.parent.maybeChild(resolved.index())
const nodeStart = resolved.pos - resolved.textOffset
const nodeEnd = nodeStart + node?.nodeSize

if (to > nodeEnd) {
// Selection spans further than one text node
return
}

return isLinkNode(node) ? node : null
}

function isLinkNode(node) {
const linkMark = node?.marks.find(m => m.type.name === 'link')
if (!linkMark) {
return false
}
// Don't open link bubble for anchor links
if (linkMark.attrs.href.startsWith('#')) {
return false
}
return true
}