Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

feat(widget): safely render Markdown images for product photos and payment QR

Abierto
#9 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
38/100
Tipo de issue
Nueva funcionalidad
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
html, markdown, typescript

Línea de trabajo

Start by reading packages/dewee-webchat/src/widget/markdown.ts and the existing security expectations in packages/dewee-webchat/test/markdown.test.ts; these define the parser and the invariant that raw model-supplied HTML stays escaped. Then trace the public widget options and README to see where image-host configuration belongs, and inspect src/widget/styles.ts for responsive styling. Done means the acceptance criteria are covered by new tests in markdown.test.ts, with pnpm test, pnpm typecheck, and pnpm build passing.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

ai-handle enhancement

Context

The current safe Markdown renderer in packages/dewee-webchat/src/widget/markdown.ts builds DOM nodes directly (no innerHTML), supporting text, links, tables, code blocks, etc., but does not parse the Markdown image syntax ![alt](url) into an actual image.

Verified on main at 42dfbc4628f45c2d006a2408a3b656a949680abb:

  • INLINE_SRC recognizes [label](url) but has no image token; leading ! is treated as plain text.
  • renderInline creates <a> elements for safe links but never <img>.
  • packages/dewee-webchat/test/markdown.test.ts explicitly asserts that raw untrusted <img src=... onerror=...> must remain escaped. This is a security property to preserve, not a test to delete.
  • packages/dewee-webchat/src/widget/styles.ts has no responsive Markdown image styles.
Why it matters

A Dewee sales agent using a Storefront MCP server should be able to show product images alongside names, prices, descriptions, and comparison tables. A Payment/SePay/VietQR MCP tool may return a payment QR image URL. Today, the chat can show image URLs as text/links but not render them natively in Markdown.

This issue covers safe Markdown image rendering (first usable step). Interactive product cards, product carousels, and a richer checkout/QR message component should be built later on a typed rich-message contract rather than embedding executable HTML in LLM output.

Requirements

1. Markdown image parsing and rendering
  • Add support for ![alt text](https://example.com/product.jpg) and relevant safe relative URLs while preserving existing text/link syntax. Nested/escaped syntax should be handled deliberately and covered by tests.
  • Create <img> DOM elements with document.createElement, assign src/text safely, and never use innerHTML or arbitrary HTML supplied by the model.
  • Set alt, loading="lazy", decoding="async" and referrerPolicy="no-referrer"; avoid content jumping via sensible container sizing if feasible.
  • Product and payment QR images must fit the chat bubble on mobile and desktop, retain correct aspect ratio, and not overflow horizontally.
  • Broken/rejected images should fall back gracefully to alt text or a safe clickable link.
2. Image URL trust/privacy policy
  • Images are fetched by the visitor's browser; untrusted remote images can track visitor IPs or send requests to unexpected origins. Do not reuse safeHref unmodified as the image policy.
  • Reject unsafe schemes (javascript:, data:, blob:, file:, etc.), protocol-relative URLs, control/obfuscated schemes, and suspicious inputs. Support approved HTTPS origins and safe same-origin URLs.
  • Provide a host-configurable image origin allowlist / opt-in for third-party images so a site's trusted Storefront CDN and payment-QR host can be explicitly approved; fail safely for unapproved sources.
  • Never allow onerror/event handlers, inline SVG, arbitrary HTML attributes, or user-supplied script. Consider SVG file/image handling explicitly in the threat model.
  • Apply the policy consistently to streamed replies, conversation history, inline widget mode, and floating mode.
3. Public API and styling
  • Expose the required image-host configuration through the appropriate public widget options and wrappers (vanilla/script, React, Vue, Astro) without breaking existing options.
  • Add styles in src/widget/styles.ts for responsive images, rounded corners, sensible max-size, and accessible alt/fallbacks.
  • Document the Markdown syntax, security policy, and how to allow a Storefront CDN or VietQR image host in the package README.
  • Keep the bundle lightweight and do not add a large Markdown/HTML framework just for images.
4. Tests / acceptance criteria
  • Valid trusted ![Product](https://trusted-shop.example/photo.jpg) renders an <img> with correct alt/source and privacy attributes when the host is allowed.
  • Valid QR image URL from an explicitly allowed payment origin displays without distortion.
  • Plain links [text](url), autolinks, fenced/inline code, bold/italic, tables, and lists still render as before.
  • An untrusted literal <img src=x onerror=...> remains escaped and never becomes an image.
  • URLs with disallowed schemes, origins, malformed encoding, or injected attributes never lead to unsafe DOM nodes or outbound image fetches.
  • Markdown image syntax inside code spans/fences stays literal.
  • Failure/unavailable image has an accessible fallback; mobile widths do not overflow.
  • Streaming / history rerenders have consistent behavior and do not duplicate nodes.
  • pnpm test, pnpm typecheck, and pnpm build pass; add tests in packages/dewee-webchat/test/markdown.test.ts and a widget-level regression test where useful.

Implementation approach

  1. Introduce a dedicated image token/parser branch that precedes link parsing, without sacrificing the renderer's current safe DOM construction.
  2. Centralize URL validation and widget host policy rather than relying on regex alone; normalize URLs using URL and compare normalized origins against a site-owned allowlist.
  3. Render with restricted attributes and CSS classes, then add coverage for adversarial inputs and view-mode parity.
  4. Document approved CDN/QR host examples as configuration placeholders, not hard-coded trusted services.

Explicit non-goals for this issue

  • No direct integration with Storefront MCP, SePay, or VietQR API in this repository.
  • No order creation, payment verification, checkout state changes, or business logic in the renderer.
  • No arbitrary HTML/JS execution or generalized remote content embed.
  • Typed product_card, product_comparison, payment_qr/checkout components: propose separately once image support is stable.

References

Lenguaje dominante
TypeScript
Estrellas
7
Forks
1
Merge medio
1 d 6 h
PR fusionados (30 d)
5

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de nextlevelbuilder/dewee-webchat

Todos los issues de nextlevelbuilder/dewee-webchat

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.