Skip to content

Commit

Permalink
Handle images that do not have data-width or data-height
Browse files Browse the repository at this point in the history
  • Loading branch information
audiodude committed Dec 10, 2024
1 parent 1763a23 commit 5b00f29
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 37 deletions.
85 changes: 48 additions & 37 deletions src/renderers/wikimedia-mobile.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class WikimediaMobileRenderer extends MobileRenderer {
}
} catch (err) {
logger.error(err.message)
throw new Error(err.message)
throw err

Check warning on line 83 in src/renderers/wikimedia-mobile.renderer.ts

View check run for this annotation

Codecov / codecov/patch

src/renderers/wikimedia-mobile.renderer.ts#L83

Added line #L83 was not covered by tests
}
}

Expand Down Expand Up @@ -110,6 +110,10 @@ export class WikimediaMobileRenderer extends MobileRenderer {
height: parseInt(span.getAttribute('data-height') || '0', 10),
}

if (preparedData.width === 0 || preparedData.height === 0) {
return { preparedData: null, originalData: null, maxData: null }

Check warning on line 114 in src/renderers/wikimedia-mobile.renderer.ts

View check run for this annotation

Codecov / codecov/patch

src/renderers/wikimedia-mobile.renderer.ts#L114

Added line #L114 was not covered by tests
}

// Calculate the ratio so we know if we're scaling down in the width or height dimension.
const widthHeightRatio = preparedData.width / preparedData.height
const scaleUsingHeight = widthHeightRatio > 1.0
Expand Down Expand Up @@ -161,50 +165,57 @@ export class WikimediaMobileRenderer extends MobileRenderer {
const spans = doc.querySelectorAll('.pcs-lazy-load-placeholder')

spans.forEach((span: DominoElement) => {
// Create a new img element that will replace the placeholder span.
const img = doc.createElement('img') as DominoElement
const { preparedData, originalData, maxData } = this.calculateImageDimensions(span)

const widthToData = {
[preparedData.width]: preparedData,
[maxData.width]: maxData,
[originalData?.width || 0]: originalData,
}

const minWidth = originalData ? Math.min(preparedData.width, maxData.width, originalData?.width) : Math.min(preparedData.width, maxData.width)
let selectedData = widthToData[minWidth]
if (preparedData === null) {
// The metadata for the lazy-loading span is something that we don't understand. Just copy the
// data-src attribute to the img element and hope for the best.
img.src = urlJoin(protocol, span.getAttribute('data-src'))
img.setAttribute('decoding', 'async')
img.className = span.getAttribute('data-class')

Check warning on line 177 in src/renderers/wikimedia-mobile.renderer.ts

View check run for this annotation

Codecov / codecov/patch

src/renderers/wikimedia-mobile.renderer.ts#L175-L177

Added lines #L175 - L177 were not covered by tests
} else {
const widthToData = {
[preparedData.width]: preparedData,
[maxData.width]: maxData,
[originalData?.width || 0]: originalData,
}

if (selectedData === maxData) {
// We've decided to scale down the image. Use URL hacking to create an image that scales to the size we want.
if (originalData) {
const match = THUMB_WIDTH_REGEX.exec(originalData.src)
if (match) {
selectedData.src = originalData.src.replace(`${match[1]}px`, `${selectedData.width}px`)
}
} else {
// No original src, or original src cannot be URL hacked.
const match = THUMB_WIDTH_REGEX.exec(preparedData.src)
if (match) {
selectedData.src = preparedData.src.replace(`${match[1]}px`, `${selectedData.width}px`)
const minWidth = originalData ? Math.min(preparedData.width, maxData.width, originalData?.width) : Math.min(preparedData.width, maxData.width)
let selectedData = widthToData[minWidth]
if (selectedData === maxData) {
// We've decided to scale down the image. Use URL hacking to create an image that scales to the size we want.
if (originalData) {
const match = THUMB_WIDTH_REGEX.exec(originalData.src)

Check warning on line 190 in src/renderers/wikimedia-mobile.renderer.ts

View check run for this annotation

Codecov / codecov/patch

src/renderers/wikimedia-mobile.renderer.ts#L190

Added line #L190 was not covered by tests
if (match) {
selectedData.src = originalData.src.replace(`${match[1]}px`, `${selectedData.width}px`)

Check warning on line 192 in src/renderers/wikimedia-mobile.renderer.ts

View check run for this annotation

Codecov / codecov/patch

src/renderers/wikimedia-mobile.renderer.ts#L192

Added line #L192 was not covered by tests
}
} else {
// No original src, or original src cannot be URL hacked.
const match = THUMB_WIDTH_REGEX.exec(preparedData.src)
if (match) {
selectedData.src = preparedData.src.replace(`${match[1]}px`, `${selectedData.width}px`)
}
}
}
}

if (selectedData.src === null) {
// We couldn't find a URL to hack, so use the smaller of the original or prepared data.
if (!originalData) {
selectedData = preparedData
} else {
const newMinWidth = Math.min(preparedData.width, originalData.width)
selectedData = widthToData[newMinWidth]
if (selectedData.src === null) {
// We couldn't find a URL to hack, so use the smaller of the original or prepared data.
if (!originalData) {
selectedData = preparedData
} else {
const newMinWidth = Math.min(preparedData.width, originalData.width)
selectedData = widthToData[newMinWidth]

Check warning on line 209 in src/renderers/wikimedia-mobile.renderer.ts

View check run for this annotation

Codecov / codecov/patch

src/renderers/wikimedia-mobile.renderer.ts#L207-L209

Added lines #L207 - L209 were not covered by tests
}
}
}

// Create a new img element
const img = doc.createElement('img') as DominoElement
img.src = urlJoin(protocol, selectedData.src)
img.setAttribute('decoding', 'async')
img.width = selectedData.width
img.height = selectedData.height
img.className = span.getAttribute('data-class')
img.src = urlJoin(protocol, selectedData.src)
img.setAttribute('decoding', 'async')
img.width = selectedData.width
img.height = selectedData.height
img.className = span.getAttribute('data-class')
}

// Replace the span with the img element
span.parentNode.replaceChild(img, span)
Expand Down
27 changes: 27 additions & 0 deletions test/unit/renderers/mobile.renderer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,33 @@ describe('mobile renderer', () => {
expect(imgs[0].width).toEqual(1200)
expect(imgs[0].height).toEqual(1500)
})
test('falls back to the data-src if the other data-* attributes are missing', async () => {
const test_window = domino.createWindow(
`
<span
class="mwe-math-fallback-image-inline mw-invert skin-invert gallery-img pcs-widen-image-override pcs-lazy-load-placeholder pcs-lazy-load-placeholder-pending"
style="width: 5.651ex;"
data-class="mwe-math-fallback-image-inline mw-invert skin-invert gallery-img pcs-widen-image-override"
data-style="vertical-align: -0.338ex; width:5.651ex; height:2.176ex;"
data-src="//wikimedia.org/api/rest_v1/media/math/render/svg/a5081dab37c84a998483d8066240c9542d311de7"
data-alt="{\displaystyle {\ce {LiOH}}}">
<span style="padding-top: 38.50645903379933%;"></span>
</span>
`,
'http://en.wikipedia.org/api/rest_v1/page/mobile-html/BMW',
)
const mobileRenderer = new WikimediaMobileRenderer()

const actual = mobileRenderer.INTERNAL.convertLazyLoadToImages(test_window.document)
const spans = actual.querySelectorAll('.pcs-lazy-load-placeholder')
const imgs = actual.querySelectorAll('img')

expect(spans.length).toBe(0)
expect(imgs.length).toBe(1)
expect(imgs[0].src).toEqual('https://wikimedia.org/api/rest_v1/media/math/render/svg/a5081dab37c84a998483d8066240c9542d311de7')
expect(imgs[0].width).toBe(0)
expect(imgs[0].height).toBe(0)
})
})
})
})

0 comments on commit 5b00f29

Please sign in to comment.