getArticleSelection.ts 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. // import { textToHtml } from '#shared/utils/helpers.ts'
  3. import { getCurrentSelectionData } from '#shared/utils/selection.ts'
  4. const closest = (node: Node, selector: string) => {
  5. while (node.parentNode) {
  6. if ('matches' in node && (node as Element).matches(selector)) return node
  7. node = node.parentNode
  8. }
  9. return null
  10. }
  11. const isInsideSelectionBoundary = (node: Element, articleId: number) => {
  12. // node can be textNode, it doesn't have "closest" method
  13. return !!closest(node, `#article-${articleId} .Content`)
  14. }
  15. const containsNode = (selection: Selection, node: Element) => {
  16. return !!selection.containsNode(node, false)
  17. }
  18. export const getArticleSelection = (articleId: number) => {
  19. const selection = window.getSelection()
  20. if (!selection || selection.rangeCount <= 0) return undefined
  21. const range = selection.getRangeAt(0)
  22. const articleContent = document.querySelector(
  23. `#article-${articleId} .Content`,
  24. ) as HTMLDivElement | null
  25. if (!articleContent) return undefined
  26. const startInsideArticle = isInsideSelectionBoundary(
  27. range.startContainer as Element,
  28. articleId,
  29. )
  30. const endInsideArticle = isInsideSelectionBoundary(
  31. range.endContainer as Element,
  32. articleId,
  33. )
  34. const contains = containsNode(selection, articleContent)
  35. const canQuote = startInsideArticle || endInsideArticle || contains
  36. if (!canQuote) return undefined
  37. // Fixes Issue #3539 - When replying quote article content only
  38. if (!startInsideArticle && endInsideArticle) {
  39. range.setStart(articleContent, 0)
  40. } else if (startInsideArticle && !endInsideArticle) {
  41. range.setEnd(articleContent, articleContent.childNodes.length)
  42. } else if (contains) {
  43. range.setStart(articleContent, 0)
  44. range.setEnd(articleContent, articleContent.childNodes.length)
  45. }
  46. return getCurrentSelectionData()
  47. }