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 { ComponentReplacer, DO_NOT_REPLACE } from '../../replace-components/component-replacer'
|
||||
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 { concatCssClasses } from '../../../../utils/concat-css-classes'
|
||||
|
||||
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.
|
||||
*/
|
||||
export class ProxyImageReplacer extends ComponentReplacer {
|
||||
public replace(node: Element): NodeReplacement {
|
||||
return node.name !== 'img' ? (
|
||||
DO_NOT_REPLACE
|
||||
) : (
|
||||
<EventEmittingProxyImageFrame
|
||||
if (node.name !== 'img') {
|
||||
return DO_NOT_REPLACE
|
||||
}
|
||||
|
||||
const linkedImage = isDescendantOfLink(node)
|
||||
const ImageFrame = linkedImage ? ProxyImageFrame : EventEmittingProxyImageFrame
|
||||
return (
|
||||
<ImageFrame
|
||||
id={node.attribs.id}
|
||||
className={`${node.attribs.class} cursor-zoom-in`}
|
||||
className={concatCssClasses(node.attribs.class, {
|
||||
'cursor-zoom-in': !linkedImage
|
||||
})}
|
||||
src={node.attribs.src}
|
||||
alt={node.attribs.alt}
|
||||
title={node.attribs.title}
|
||||
|
||||
Reference in New Issue
Block a user