Skip to content

fix(embeds): resolve relative image paths in MarkdownEmbed#871

Merged
DeveloperAlly merged 2 commits intodocs-v2from
copilot/fix-github-embed-image-rendering
Apr 8, 2026
Merged

fix(embeds): resolve relative image paths in MarkdownEmbed#871
DeveloperAlly merged 2 commits intodocs-v2from
copilot/fix-github-embed-image-rendering

Conversation

Copy link
Copy Markdown

Copilot AI commented Apr 8, 2026

MarkdownEmbed fetched remote markdown and converted it to HTML but had no concept of a base URL, so relative image paths (e.g. <img src="streamplace-logo.svg"> in the Streamplace README) resolved against the docs origin instead of the remote file's directory — producing a broken image.

Root cause

The Streamplace README header uses a raw HTML <img> tag with a relative src:

<img src="streamplace-logo.svg" width=200>

The previous image handling only covered markdown-syntax images ![alt](src) and did no URL resolution at all.

Changes — snippets/components/integrators/embeds/DataEmbed.jsx

  • baseUrl — derived from url prop (substring up to last /), guarded for no-slash edge case
  • origin — extracted from baseUrl for root-relative path resolution (/foo.png)
  • resolveUrl(src) — passes through https://, //, data:, # unchanged; root-relative paths anchor to origin; bare relative paths prepend baseUrl
  • escapeAttr(str) — escapes &, ", <, > for values interpolated into HTML attributes from markdown source
  • Markdown image handler ![alt](src) updated to use resolveUrl + escapeAttr
  • Two new regex passes for raw HTML img tags — double-quoted src="..." and single-quoted src='...' — both run resolveUrl on the captured src
// Before — no resolution, only markdown syntax
.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img alt="$1" src="$2" style="max-width:100%" />')

// After — resolves both markdown and raw HTML img tags
const baseUrl = lastSlash >= 0 ? url.substring(0, lastSlash + 1) : ''
const resolveUrl = (src) => { /* passes absolute through, resolves relative */ }

.replace(/!\[([^\]]*)\]\(([^)]+)\)/g,
  (_, alt, src) => `<img alt="${escapeAttr(alt)}" src="${escapeAttr(resolveUrl(src))}" .../>`)
.replace(/<img\b([^>]*)src="([^"]*)"([^>]*)>/gi,
  (_, before, src, after) => `<img${before}src="${resolveUrl(src)}"${after}>`)
.replace(/<img\b([^>]*)src='([^']*)'([^>]*)>/gi,
  (_, before, src, after) => `<img${before}src="${resolveUrl(src)}"${after}>`)

Description

MarkdownEmbed now resolves relative image URLs in fetched remote markdown against the source file's base URL, fixing broken images on the Streamplace community page (/v2/solutions/streamplace/community #gitlab-&-github section).

Scope

snippets/components/integrators/embeds/DataEmbed.jsxMarkdownEmbed component only.

Validation

  • Logic verified with Node.js: relative → absolute resolution, absolute passthrough, fragment passthrough, root-relative, no-slash URL guard, escapeAttr output all confirmed correct
  • CodeQL scan: 0 alerts

Follow-up Tasks

none

Type of Change

  • Bug fix (fixes an issue)
  • New content (adds new documentation)
  • Content update (improves existing content)
  • Style/formatting fix
  • Information architecture change
  • Other (please describe)

Related Issues

Related to #

Changes Made

  • Added baseUrl / origin derivation from the url prop inside useEffect
  • Added resolveUrl() helper for relative → absolute URL resolution
  • Added escapeAttr() helper for HTML attribute sanitisation
  • Extended image handling to cover raw HTML <img src="..."> and <img src='...'>
  • Updated markdown image handler to use resolveUrl + escapeAttr

Testing

  • Tested locally with npm run dev
  • Verified all links work
  • Checked formatting and style
  • Reviewed against style guides
  • Screenshots (if UI changes)

Screenshots (if applicable)

Before — broken image (no src resolved):

broken image

Afterstreamplace-logo.svg resolves to https://raw.githubusercontent.com/streamplace/streamplace/next/streamplace-logo.svg and renders correctly.

Checklist

  • My changes follow the style guides
  • I've reviewed the Component Library for available components
  • I've updated related pages if needed
  • I've checked for broken links
  • My changes are clear and easy to understand
  • I've tested locally
  • I've added/updated keywords and metadata if needed

Additional Notes

The fix is scoped entirely to the MarkdownEmbed conversion pipeline and does not affect SolidityEmbed, PdfEmbed, or TwitterTimeline in the same file.

Governance Approval

Not required for this PR.

Copy Governance Gate - L5

Complete before requesting review. Every item must be checked or the PR is not ready.

Auto-checked by CI (lint-copy.js + lint-structure.js)

  • No Tier 1 banned words or phrases
  • No unresolved {/* REVIEW: */} flags in rendered content
  • No non-USD currency outside declared regional scope
  • No empty cells in decision tables
  • pageType, audience, lastVerified present in frontmatter

Human review required

Sequence (L2)

  • Page opens with operator outcome - value kept, no conditionals
  • Majority operator path is featured before variants
  • Introduced paths are developed on-page or linked

Completeness (L3)

  • Decision aids (tables, matrices, flowcharts) are complete - no placeholders
  • Every warning or consequence is followed by a prevention action and link
  • Primary actions and URLs appear in body copy (not only in accordions)

Tone (L4)

  • No sentence ends on a hedge, disclaimer, or restatement
  • No section ends with a Note that apologises rather than forward-points

Brief compliance

  • L0 (Q1-Q4) was completed before drafting
  • L1 persona mapping table was completed before drafting

If any structural item fails: fix before requesting review. Do not ask a reviewer to identify the issue.

If the same section fails review twice: do not attempt a third fix. Escalate to the documentation lead for L6 diagnostic.

Copilot AI linked an issue Apr 8, 2026 that may be closed by this pull request
2 tasks
- Derive baseUrl and origin from the url prop inside useEffect
- Add resolveUrl() helper that passes absolute URLs, protocol-relative,
  data URIs, and fragment links unchanged; anchors root-relative paths
  to origin; resolves relative paths against baseUrl
- Add escapeAttr() helper for sanitising markdown-derived alt/src values
- Apply resolveUrl to markdown-style images ![alt](src)
- Apply resolveUrl to raw HTML <img src="..."> (double-quoted)
- Apply resolveUrl to raw HTML <img src='...'> (single-quoted)

Fixes: broken streamplace-logo.svg in GitHub embed on
/v2/solutions/streamplace/community (#gitlab-&-github section)

Agent-Logs-Url: https://github.com/livepeer/docs/sessions/837ecd2d-1a07-49c5-b78d-64d964470846

Co-authored-by: DeveloperAlly <12529822+DeveloperAlly@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix GitHub embed image not rendering in home about area fix(embeds): resolve relative image paths in MarkdownEmbed Apr 8, 2026
Copilot AI requested a review from DeveloperAlly April 8, 2026 03:43
@DeveloperAlly DeveloperAlly marked this pull request as ready for review April 8, 2026 03:51
@DeveloperAlly DeveloperAlly merged commit 2e53041 into docs-v2 Apr 8, 2026
2 checks passed
@DeveloperAlly DeveloperAlly deleted the copilot/fix-github-embed-image-rendering branch April 8, 2026 03:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug]: Github Embed image not rendering

2 participants