Skip to content
This repository has been archived by the owner on Oct 18, 2024. It is now read-only.

Commit

Permalink
fix(edusharing-asset): Fix some embedded content types overflowing th…
Browse files Browse the repository at this point in the history
…eir container
  • Loading branch information
LarsTheGlidingSquirrel committed Dec 19, 2023
1 parent a9a68fc commit d167b24
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 75 deletions.
58 changes: 30 additions & 28 deletions src/frontend/plugins/edusharing-asset/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function EdusharingAssetEditor({
}: EdusharingAssetProps) {
const [modalIsOpen, setModalIsOpen] = useState(false)
const iframeRef = useRef<HTMLIFrameElement>()
const { edusharingAsset, height } = state
const { edusharingAsset, widthInPercent } = state

useEffect(() => {
function handleIFrameEvent({ data, source }: MessageEvent) {
Expand Down Expand Up @@ -61,21 +61,8 @@ export function EdusharingAssetEditor({
: undefined
}
ltik={config.ltik}
height={height.value}
widthInPercent={widthInPercent.value}
/>
{!edusharingAsset.defined || focused ? (
<div className="w-full relative">
<div className="flex flex-col items-center absolute bottom-2 left-2">
<button
className="ece-button-blue text-sm"
onClick={() => setModalIsOpen(true)}
data-testid="edusharing-plugin-button"
>
Datei von edu-sharing einbinden
</button>
</div>
</div>
) : null}
</>
)

Expand All @@ -89,23 +76,38 @@ export function EdusharingAssetEditor({
pluginSettings={
<>
<button
onClick={() =>
height.set((currentValue) => Math.min(currentValue + 2, 100))
}
onClick={() => setModalIsOpen(true)}
className="mr-2 rounded-md border border-gray-500 px-1 text-sm transition-all hover:bg-editor-primary-200 focus-visible:bg-editor-primary-200"
data-qa="plugin-edusharing-bigger-button"
>
Größer
</button>
<button
onClick={() =>
height.set((currentValue) => Math.max(currentValue - 2, 2))
}
className="mr-2 rounded-md border border-gray-500 px-1 text-sm transition-all hover:bg-editor-primary-200 focus-visible:bg-editor-primary-200"
data-qa="plugin-edusharing-smaller-button"
>
Kleiner
Inhalt wählen
</button>
{edusharingAsset.defined ? (
<>
<button
onClick={() =>
widthInPercent.set((currentValue) =>
Math.min(currentValue + 10, 100),
)
}
className="mr-2 rounded-md border border-gray-500 px-1 text-sm transition-all hover:bg-editor-primary-200 focus-visible:bg-editor-primary-200"
data-qa="plugin-edusharing-bigger-button"
>
Größer
</button>
<button
onClick={() =>
widthInPercent.set((currentValue) =>
Math.max(currentValue - 10, 10),
)
}
className="mr-2 rounded-md border border-gray-500 px-1 text-sm transition-all hover:bg-editor-primary-200 focus-visible:bg-editor-primary-200"
data-qa="plugin-edusharing-smaller-button"
>
Kleiner
</button>
</>
) : null}
</>
}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/plugins/edusharing-asset/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const state = object({
nodeId: string(''),
}),
),
height: number(20),
widthInPercent: number(100),
})

export function createEdusharingAssetPlugin(
Expand Down
127 changes: 83 additions & 44 deletions src/frontend/plugins/edusharing-asset/renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ export function EdusharingAssetRenderer(props: {
nodeId?: string
repositoryId?: string
ltik: string
height: number
widthInPercent: number
}) {
const { nodeId, repositoryId, ltik, height } = props
const { nodeId, repositoryId, ltik, widthInPercent } = props

const [embedHtml, setEmbedHtml] = useState<string | null>(null)
let [embedHtml, setEmbedHtml] = useState<string | null>(null)

useEffect(() => {
async function fetchEmbedHtml() {
Expand Down Expand Up @@ -42,76 +42,115 @@ export function EdusharingAssetRenderer(props: {
return
}

setEmbedHtml(result.detailsSnippet)
// HTML snipped returned by edu-sharing cannot be used as is.
const newEmbedHtml = embedHtmlFor(result.detailsSnippet)

setEmbedHtml(newEmbedHtml)
}

void fetchEmbedHtml()
}, [nodeId, repositoryId, ltik])

return (
<figure
className={clsx(
'flex items-center',
embedHtml && 'justify-start',
!embedHtml && 'h-40 w-full justify-center',
)}
>
<figure className="w-full">
{embedHtml ? (
renderEmbed()
) : (
<Image
className="block opacity-50"
src="/edusharing.svg"
alt="Edusharing Logo"
width="100"
height="100"
/>
<div className="flex justify-center">
<Image
className="block opacity-50"
src="/edusharing.svg"
alt="Edusharing Logo"
width="100"
height="100"
/>
</div>
)}
</figure>
)

function renderEmbed() {
if (embedHtml == null) return

function embedHtmlFor(detailsSnipped: string) {
const parser = new DOMParser()
let document = parser.parseFromString(embedHtml, 'text/html')
let htmlDocument = parser.parseFromString(detailsSnipped, 'text/html')

const contentWrapperElement = document.querySelector(
'.edusharing_rendering_content_wrapper',
// Image
const image = htmlDocument.querySelector(
'.edusharing_rendering_content_wrapper > img',
)
const isImageSnippet =
image && !image.classList.contains('edusharing_rendering_content_preview')
if (isImageSnippet) {
// Create completely new <img> element because patching the existing one is more work/error-prone
const imageSnippet = `
<img style="width: 100%; object-fit: contain;" src="${image.getAttribute(
'src',
)}" alt="${image.getAttribute('alt')}" title="${image.getAttribute(
'title',
)}" />
`
return imageSnippet
}

if (contentWrapperElement) {
// Embed html sent by edusharing includes "width: 0px"
contentWrapperElement.style.width = ''
// .docx, .pptx
const isFilePreview =
image && image.classList.contains('edusharing_rendering_content_preview')
if (isFilePreview) {
// Make preview image visible
image.removeAttribute('width')
image.removeAttribute('height')
return htmlDocument.body.innerHTML
}

const imgElement = document.querySelector(
'.edusharing_rendering_content_wrapper > img',
// Video
const video = htmlDocument.querySelector(
'.edusharing_rendering_content_video_wrapper > video',
)

if (imgElement) {
imgElement.style.height = `${height}rem`
imgElement.style.objectFit = 'contain'
// Embed html sent by edusharing includes "width: 0px" for images.
imgElement.style.width = ''
const isVideoSnippet = video !== null
if (isVideoSnippet) {
// Create completely new <video> element because patching the existing one is more work/error-prone
const videoSnippet = `
<video style="width: 100%; object-fit: contain;" src="${video.getAttribute(
'src',
)}" controls controlsList="nodownload" oncontextmenu="return false;"></video>
`
return videoSnippet
}

const videoElement = document.querySelector('.videoWrapperInner > video')
const iframe = htmlDocument.querySelector('iframe')

// H5P
const isH5P = iframe && iframe.getAttribute('src').includes('h5p')
if (isH5P) {
// Remove footer because it covers up exercise
const footer = htmlDocument.querySelector(
'.edusharing_rendering_content_footer',
)
if (footer) {
footer.remove()
}
return htmlDocument.body.innerHTML
}

if (videoElement) {
videoElement.style.height = `${height}rem`
imgElement.style.objectFit = 'contain'
// Embed html sent by edusharing includes "width: 0px" for videos.
imgElement.style.width = ''
const isPdf = iframe.id === 'docFrame'
if (isPdf) {
// Do not adjust height based on container size
iframe.style.height = 'auto'
return htmlDocument.body.innerHTML
}

const updatedEmbedHtml = document.body.innerHTML
// If the detailsSnipped was not handled by one of the handlers above, change nothing in html snippet
return detailsSnipped
}

function renderEmbed() {
if (embedHtml == null) return

// TODO: Sanatize embed html? But I observed that embedHtml for videos contains <script>
return (
<div
className="not-prose h-full w-full overflow-auto"
dangerouslySetInnerHTML={{ __html: updatedEmbedHtml }}
className={`not-prose overflow-auto`}
style={{ width: `${widthInPercent}%` }}
dangerouslySetInnerHTML={{ __html: embedHtml }}
/>
)
}
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/plugins/edusharing-asset/static.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ export function EdusharingAssetStaticRenderer(
const nodeId = props.state.edusharingAsset?.nodeId
const repositoryId = props.state.edusharingAsset?.repositoryId

const { height } = props.state
const { widthInPercent } = props.state

const ltik = useContext(LtikContext)

return (
<EdusharingAssetRenderer
nodeId={nodeId}
repositoryId={repositoryId}
height={height}
widthInPercent={widthInPercent}
ltik={ltik}
/>
)
Expand Down

0 comments on commit d167b24

Please sign in to comment.