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

Commit

Permalink
Merge pull request #323 from serlo/fix-embedding-issues
Browse files Browse the repository at this point in the history
Fix embedding issues
  • Loading branch information
LarsTheGlidingSquirrel authored Jan 16, 2024
2 parents 8ca2618 + cb59099 commit de03e01
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/frontend/plugins/edusharing-asset/editor.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from 'react'
import { EdusharingAssetProps } from '.'
import type { EdusharingAssetProps } from '.'
import { EdusharingAssetDecoder } from '../../../shared/decoders'
import { PluginToolbar } from '@/serlo-editor/editor-ui/plugin-toolbar'
import { PluginDefaultTools } from '@/serlo-editor/editor-ui/plugin-toolbar/plugin-tool-menu/plugin-default-tools'
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 @@ -17,7 +17,7 @@ const state = object({
}),
),
height: optional(number(20)), // TODO: Remove before release. Not used any more. But removing this is a breaking change.
contentWidth: optional(string()), // Contains 'rem' size values, for example '40rem'
contentWidth: optional(string()), // Contains values like '40rem'. Possible values ['4rem', '6rem', ...]
})

export function createEdusharingAssetPlugin(
Expand Down
106 changes: 76 additions & 30 deletions src/frontend/plugins/edusharing-asset/renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { memo, useEffect, useState } from 'react'
import * as t from 'io-ts'
import Image from 'next/image'
import IframeResizer from 'iframe-resizer-react'
// import InnerHTML from 'dangerously-set-html-content'

type RenderMethod = 'dangerously-set-inner-html' | 'iframe'

Expand All @@ -20,6 +19,8 @@ export function EdusharingAssetRenderer(props: {
const [renderMethod, setRenderMethod] = useState<RenderMethod>(
'dangerously-set-inner-html',
)
const [defineContainerHeight, setDefineContainerHeight] =
useState<boolean>(false)

useEffect(() => {
async function fetchEmbedHtml() {
Expand Down Expand Up @@ -51,12 +52,12 @@ export function EdusharingAssetRenderer(props: {
}

// HTML snipped returned by edu-sharing cannot be used as it is.
const { html, renderMethod } = embedHtmlAndRenderMethod(
result.detailsSnippet,
)
const { html, renderMethod, defineContainerHeight } =
embedHtmlAndRenderMethod(result.detailsSnippet)

setEmbedHtml(html)
setRenderMethod(renderMethod)
setDefineContainerHeight(defineContainerHeight)
}

void fetchEmbedHtml()
Expand Down Expand Up @@ -85,9 +86,16 @@ export function EdusharingAssetRenderer(props: {
function embedHtmlAndRenderMethod(detailsSnippet: string): {
html: string
renderMethod: RenderMethod
defineContainerHeight: boolean
} {
// TODO: Hide metadata wrapper because it looks broken?
// detailsSnipped = detailsSnipped.replace('</script>', ' .edusharing_metadata_wrapper { display: none; }</script>')
// Remove all min-width
detailsSnippet = detailsSnippet.replaceAll(/min-width[^;]*;/g, '')

// Hide all footers
detailsSnippet = detailsSnippet.replaceAll(
/edusharing_rendering_content_footer \{/g,
'edusharing_rendering_content_footer { display: none;',
)

const parser = new DOMParser()
const htmlDocument = parser.parseFromString(detailsSnippet, 'text/html')
Expand All @@ -110,6 +118,7 @@ export function EdusharingAssetRenderer(props: {
return {
html: imageSnippet,
renderMethod: 'dangerously-set-inner-html',
defineContainerHeight: false,
}
}

Expand All @@ -118,27 +127,33 @@ export function EdusharingAssetRenderer(props: {
image && image.classList.contains('edusharing_rendering_content_preview')
if (isFilePreview) {
// Make preview image visible
image.removeAttribute('width')
image.removeAttribute('height')
detailsSnippet = detailsSnippet
.replace('width="0"', '')
.replace('height="0"', '')
return {
html: htmlDocument.body.innerHTML,
html: detailsSnippet,
renderMethod: 'dangerously-set-inner-html',
defineContainerHeight: false,
}
}

// Video
const isVideoSnippet = detailsSnippet.includes('videoFormat')
if (isVideoSnippet) {
// Video & audio
const isEmbedThatNeedsToFetchContent =
detailsSnippet.includes('get_resource')
if (isEmbedThatNeedsToFetchContent) {
// Converts a function within a <script> tag in the html snippet sent by edu-sharing. Fixes "token issue" when executing script.
detailsSnippet = detailsSnippet.replace(
'get_resource = function(authstring)',
'function get_resource(authstring)',
)
// Add iframe resizer script
const newEmbedHtml = `${detailsSnippet}<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.9/iframeResizer.contentWindow.min.js"></script>`
const newEmbedHtml =
detailsSnippet +
'<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.9/iframeResizer.contentWindow.min.js"></script>'
return {
html: newEmbedHtml,
renderMethod: 'iframe',
defineContainerHeight: false,
}
}

Expand All @@ -147,16 +162,12 @@ export function EdusharingAssetRenderer(props: {
// 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 {
html: htmlDocument.body.innerHTML,
renderMethod: 'dangerously-set-inner-html',
html:
detailsSnippet +
'<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.9/iframeResizer.contentWindow.min.js"></script>',
renderMethod: 'iframe',
defineContainerHeight: false,
}
}

Expand All @@ -167,13 +178,35 @@ export function EdusharingAssetRenderer(props: {
return {
html: htmlDocument.body.innerHTML,
renderMethod: 'dangerously-set-inner-html',
defineContainerHeight: true,
}
}

// Learning apps
if (detailsSnippet.includes('learningapps.org/')) {
let iframeHtmlElement = htmlDocument.querySelector('iframe')
if (!iframeHtmlElement) {
return {
html: 'Error. Please contact support. Details: Could not find iframe in learningapp embed html.',
renderMethod: 'dangerously-set-inner-html',
defineContainerHeight: false,
}
}
const iframeHtml = iframeHtmlElement.outerHTML
.replace('width="95%"', 'width="100%"')
.replace('height: 80vh', '')
return {
html: iframeHtml,
renderMethod: 'dangerously-set-inner-html',
defineContainerHeight: true,
}
}

// If the detailsSnipped was not handled by one of the handlers above, change nothing in html snippet
return {
html: detailsSnippet,
renderMethod: 'dangerously-set-inner-html',
defineContainerHeight: false,
}
}

Expand All @@ -185,7 +218,10 @@ export function EdusharingAssetRenderer(props: {
return (
<div
className={`not-prose overflow-auto max-w-full`}
style={{ width: contentWidth ? contentWidth : '100%' }}
style={{
width: contentWidth ? contentWidth : '100%',
aspectRatio: defineContainerHeight ? '16/9' : undefined,
}}
dangerouslySetInnerHTML={{ __html: embedHtml }}
/>
)
Expand All @@ -204,14 +240,24 @@ export function EdusharingAssetRenderer(props: {
return (
<div
className="max-w-full"
style={{ width: contentWidth ? contentWidth : '100%' }}
style={{
width: contentWidth ? contentWidth : '100%',
aspectRatio: defineContainerHeight ? '16/9' : undefined,
}}
>
<MemoizedIframeResizer
heightCalculationMethod="lowestElement"
checkOrigin={false}
srcDoc={embedHtml}
style={{ width: '1px', minWidth: '100%' }}
/>
{defineContainerHeight ? (
<iframe
srcDoc={embedHtml}
style={{ width: '100%', height: '100%' }}
/>
) : (
<MemoizedIframeResizer
heightCalculationMethod="lowestElement"
checkOrigin={false}
srcDoc={embedHtml}
style={{ width: '1px', minWidth: '100%' }}
/>
)}
</div>
)
}
Expand Down

1 comment on commit de03e01

@vercel
Copy link

@vercel vercel bot commented on de03e01 Jan 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.