mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2026-08-07 07:14:49 +00:00
feat(renderer): do not open lightbox on images with links
Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
committed by
Philip Molares
parent
bc03f33fa5
commit
230f901323
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
import { EventEmittingProxyImageFrame } from './event-emitting-proxy-image-frame'
|
||||||
|
import { ProxyImageFrame } from './proxy-image-frame'
|
||||||
|
import { ProxyImageReplacer } from './proxy-image-replacer'
|
||||||
|
import { Element } from 'domhandler'
|
||||||
|
import type { ReactElement } from 'react'
|
||||||
|
|
||||||
|
describe('ProxyImageReplacer', () => {
|
||||||
|
const replacer = new ProxyImageReplacer()
|
||||||
|
|
||||||
|
it('uses the lightbox image frame for standalone images', () => {
|
||||||
|
const image = new Element('img', { src: 'https://example.com/image.png' })
|
||||||
|
|
||||||
|
const replacement = replacer.replace(image) as ReactElement
|
||||||
|
|
||||||
|
expect(replacement.type).toBe(EventEmittingProxyImageFrame)
|
||||||
|
expect(replacement.props.className).toBe('cursor-zoom-in')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not use the lightbox image frame for images inside links', () => {
|
||||||
|
const image = new Element('img', { src: 'https://example.com/image.png' })
|
||||||
|
const span = new Element('span', {}, [image])
|
||||||
|
const link = new Element('a', { href: 'https://example.com' }, [span])
|
||||||
|
image.parent = span
|
||||||
|
span.parent = link
|
||||||
|
|
||||||
|
const replacement = replacer.replace(image) as ReactElement
|
||||||
|
|
||||||
|
expect(replacement.type).toBe(ProxyImageFrame)
|
||||||
|
expect(replacement.props.className).toBe('')
|
||||||
|
})
|
||||||
|
})
|
||||||
+35
-6
@@ -6,22 +6,51 @@
|
|||||||
import type { NodeReplacement } from '../../replace-components/component-replacer'
|
import type { NodeReplacement } from '../../replace-components/component-replacer'
|
||||||
import { ComponentReplacer, DO_NOT_REPLACE } from '../../replace-components/component-replacer'
|
import { ComponentReplacer, DO_NOT_REPLACE } from '../../replace-components/component-replacer'
|
||||||
import { EventEmittingProxyImageFrame } from './event-emitting-proxy-image-frame'
|
import { EventEmittingProxyImageFrame } from './event-emitting-proxy-image-frame'
|
||||||
import type { Element } from 'domhandler'
|
import { ProxyImageFrame } from './proxy-image-frame'
|
||||||
|
import { isTag, type Element } from 'domhandler'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { concatCssClasses } from '../../../../utils/concat-css-classes'
|
||||||
|
|
||||||
export type ImageClickHandler = (event: React.MouseEvent<HTMLImageElement, MouseEvent>) => void
|
export type ImageClickHandler = (event: React.MouseEvent<HTMLImageElement, MouseEvent>) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Traverses the DOM upwards to check if one parent element of the current one is a link.
|
||||||
|
* Stops when reaching the body element.
|
||||||
|
*
|
||||||
|
* @param node The node from which to start checking.
|
||||||
|
* @returns true if the given node has some link parent in the DOM, false otherwise
|
||||||
|
*/
|
||||||
|
const isDescendantOfLink = (node: Element): boolean => {
|
||||||
|
let parent = node.parent
|
||||||
|
while (parent) {
|
||||||
|
if (isTag(parent) && parent.name === 'a') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (isTag(parent) && parent.name === 'body') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
parent = parent.parent
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detects image tags and loads them via image proxy if configured.
|
* Detects image tags and loads them via image proxy if configured.
|
||||||
*/
|
*/
|
||||||
export class ProxyImageReplacer extends ComponentReplacer {
|
export class ProxyImageReplacer extends ComponentReplacer {
|
||||||
public replace(node: Element): NodeReplacement {
|
public replace(node: Element): NodeReplacement {
|
||||||
return node.name !== 'img' ? (
|
if (node.name !== 'img') {
|
||||||
DO_NOT_REPLACE
|
return DO_NOT_REPLACE
|
||||||
) : (
|
}
|
||||||
<EventEmittingProxyImageFrame
|
|
||||||
|
const linkedImage = isDescendantOfLink(node)
|
||||||
|
const ImageFrame = linkedImage ? ProxyImageFrame : EventEmittingProxyImageFrame
|
||||||
|
return (
|
||||||
|
<ImageFrame
|
||||||
id={node.attribs.id}
|
id={node.attribs.id}
|
||||||
className={`${node.attribs.class} cursor-zoom-in`}
|
className={concatCssClasses(node.attribs.class, {
|
||||||
|
'cursor-zoom-in': !linkedImage
|
||||||
|
})}
|
||||||
src={node.attribs.src}
|
src={node.attribs.src}
|
||||||
alt={node.attribs.alt}
|
alt={node.attribs.alt}
|
||||||
title={node.attribs.title}
|
title={node.attribs.title}
|
||||||
|
|||||||
Reference in New Issue
Block a user