Skip to content

Add IETP multimedia embedding with responsive video, audio, and interactive images#159

Open
Copilot wants to merge 4 commits intocopilot/fix-cbfd652f-6179-4a6b-9443-2c01acced28efrom
copilot/experiment-ietp-features
Open

Add IETP multimedia embedding with responsive video, audio, and interactive images#159
Copilot wants to merge 4 commits intocopilot/fix-cbfd652f-6179-4a6b-9443-2c01acced28efrom
copilot/experiment-ietp-features

Conversation

Copy link
Contributor

Copilot AI commented Jan 14, 2026

Implements interactive multimedia embedding for the IETP system, enabling S1000D data modules to render video, audio, and images with responsive controls and accessibility features.

Implementation

MediaEmbed Component (assets/js/media-embed.js, 359 lines)

  • Auto-detects and enhances <video>, <audio>, <img> elements with interactive controls
  • Processes S1000D <multimedia> references via data-s1000d-multimedia attributes
  • Click-to-zoom modal for images with keyboard navigation (ESC to close)
  • Responsive containers maintaining aspect ratios across devices
  • Configurable: autoplay, controls, loop, aspectRatio

Responsive Styling (assets/css/media-embed.css, 411 lines)

  • Aspect ratio preservation (default 16:9 for video)
  • Custom play button overlay with hover states
  • Full-screen image zoom modal
  • Grid layout for multiple media items
  • Mobile/tablet/desktop breakpoints (768px, 1024px)
  • Accessibility: focus indicators, prefers-reduced-motion, high contrast mode

Build System Integration (build_ietp.py)

  • render_multimedia_object() converts S1000D <multimedia> elements to HTML
  • Extracts captions from <multimediaCaption>
  • Path resolution: maps multimedia types to directory structure
  • Includes media-embed assets in all generated pages

Usage

S1000D XML:

<multimedia>
  <multimediaObject multimediaCode="ICN-BWQ1-A-571010-V-001-01" 
                    multimediaType="video"/>
  <multimediaCaption>Wing box assembly demonstration</multimediaCaption>
</multimedia>

Generated HTML:

<div class="media-embed-container">
  <video controls>
    <source src="../../multimedia/videos/ICN-BWQ1-A-571010-V-001-01.mp4">
  </video>
  <div class="media-caption">
    <div class="caption-title">Wing box assembly demonstration</div>
    <div class="caption-code">Multimedia Code: ICN-BWQ1-A-571010-V-001-01</div>
  </div>
</div>

Screenshots

IETP Index with multimedia support:
IETP Index

Multimedia demo page showing video, audio, interactive images:
Multimedia Demo

File Structure

ietp/
├── assets/
│   ├── css/media-embed.css          (NEW - 411 lines)
│   └── js/media-embed.js             (NEW - 359 lines)
├── build_ietp.py                     (UPDATED - added render_multimedia_object)
└── README.md                         (UPDATED - documented features)

docs/user-guide/
├── User-Guide.md                     (UPDATED - added multimedia section)
└── modules/multimedia-embedding.md   (NEW - 303 lines)

multimedia/
├── graphics/README.md                (NEW - SVG/PNG guidelines)
└── videos/README.md                  (NEW - MP4/WebM standards)

Technical Notes

  • Formats supported: Video (MP4, WebM), Audio (MP3, AAC, WAV), Images (PNG, JPEG, SVG, GIF)
  • Browser compatibility: Modern browsers with HTML5 video/audio support
  • Accessibility: WCAG 2.1 compliant - keyboard nav, ARIA labels, no autoplay default
  • No dependencies: Pure JavaScript, progressive enhancement
  • Security: CodeQL scan passed with zero alerts
Original prompt

Solicitud de cambios: #15

  1. Understanding the Baseline for IETP

IETP typically involves embedding interactive and dynamic content into the UI, such as:

• Dynamic linking between content sections or external resources.

• Embedding multimedia (audio, video, diagrams, etc.).

• Responsive and enriched user interactions like popups, tooltips, and collapsible sections.

To implement and experiment with IETP features in the repository, we need:

• Embedding content dynamically.

• Providing navigation or interaction control for better accessibility and user experience.

  1. Plan of Action for Development

Here’s how you can approach experimenting with IETP features systematically:

a. Embedding Multimedia Content

• For embedding videos/audio directly in the UI, create a dedicated component to render these elements.

• Implement parameterized autoplay (deterministic behavior), user controls, and responsive scaling.

Suggested Steps:

• Build or enhance a React MediaEmbed component if the repository uses React.

• Ensure compatibility with Markdown for descriptions, e.g., Markdown rendering embedded components using HTML-like syntax


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@vercel
Copy link

vercel bot commented Jan 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
v0-gaia-air-schema-format-akru Error Error Jan 14, 2026 8:54am

…udio, and interactive image support

Co-authored-by: AmedeoPelliccia <164860269+AmedeoPelliccia@users.noreply.github.com>
…de with multimedia section

Co-authored-by: AmedeoPelliccia <164860269+AmedeoPelliccia@users.noreply.github.com>
…on notes, enhance accessibility

Co-authored-by: AmedeoPelliccia <164860269+AmedeoPelliccia@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement IETP features for embedding multimedia content Add IETP multimedia embedding with responsive video, audio, and interactive images Jan 14, 2026
Copilot AI requested a review from AmedeoPelliccia January 14, 2026 08:58
@AmedeoPelliccia AmedeoPelliccia marked this pull request as ready for review January 14, 2026 19:37
Copilot AI review requested due to automatic review settings January 14, 2026 19:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements interactive multimedia embedding for the IETP (Interactive Electronic Technical Publication) system, enabling S1000D data modules to render video, audio, and images with responsive controls and accessibility features.

Changes:

  • Added new MediaEmbed JavaScript component for auto-detecting and enhancing multimedia elements
  • Implemented responsive CSS styling with dark theme support and accessibility features
  • Extended build system to render S1000D multimedia object references into HTML
  • Added comprehensive documentation for multimedia features and usage guidelines

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
multimedia/videos/README.md Documentation for video content standards and S1000D naming conventions
multimedia/graphics/README.md Guidelines for technical graphics and diagrams
ietp/build_ietp.py Added render_multimedia_object() function to convert S1000D multimedia elements to HTML
ietp/assets/js/media-embed.js New JavaScript component for multimedia embedding with zoom, play controls, and responsive behavior
ietp/assets/css/media-embed.css Styling for multimedia components with responsive design and accessibility support
ietp/README.md Updated documentation to reference new multimedia features
docs/user-guide/modules/multimedia-embedding.md Comprehensive guide for multimedia embedding features
docs/user-guide/User-Guide.md Added link to multimedia embedding documentation

Comment on lines +280 to +286
modal.innerHTML = `
<div class="modal-backdrop"></div>
<div class="modal-content">
<button class="modal-close" aria-label="Close">&times;</button>
<img src="${img.src}" alt="${img.alt}">
</div>
`;
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

Direct interpolation of img.src and img.alt into HTML template strings creates potential XSS vulnerabilities if these attributes contain malicious content. Use textContent or setAttribute() instead to safely set these values on a created element.

Suggested change
modal.innerHTML = `
<div class="modal-backdrop"></div>
<div class="modal-content">
<button class="modal-close" aria-label="Close">&times;</button>
<img src="${img.src}" alt="${img.alt}">
</div>
`;
// Backdrop
const backdrop = document.createElement('div');
backdrop.className = 'modal-backdrop';
// Content container
const content = document.createElement('div');
content.className = 'modal-content';
// Close button
const closeButton = document.createElement('button');
closeButton.className = 'modal-close';
closeButton.setAttribute('aria-label', 'Close');
closeButton.textContent = '\u00d7';
// Image element with safely set attributes
const zoomedImg = document.createElement('img');
// Use currentSrc if available to reflect the actually displayed resource
zoomedImg.src = img.currentSrc || img.src || '';
zoomedImg.alt = img.alt || '';
// Assemble modal content
content.appendChild(closeButton);
content.appendChild(zoomedImg);
modal.appendChild(backdrop);
modal.appendChild(content);

Copilot uses AI. Check for mistakes.
# Generate HTML based on multimedia type
if mm_type in ["video", "animation"]:
return f'''<div class="media-embed-container">
<div data-s1000d-multimedia="video" data-multimedia-path="{mm_path}" data-multimedia-code="{safe(mm_code)}">
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The mm_path variable is not escaped before being inserted into the HTML attribute. While mm_code uses the safe() function, mm_path should also be escaped to prevent potential attribute injection attacks. Apply safe() or equivalent HTML attribute escaping to mm_path.

Copilot uses AI. Check for mistakes.
</div>'''
elif mm_type == "audio":
return f'''<div class="media-embed-container">
<div data-s1000d-multimedia="audio" data-multimedia-path="{mm_path}" data-multimedia-code="{safe(mm_code)}">
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The mm_path variable is not escaped before being inserted into the HTML attribute. Apply safe() or equivalent HTML attribute escaping to mm_path to prevent attribute injection.

Copilot uses AI. Check for mistakes.
Comment on lines +304 to +305
<div data-s1000d-multimedia="image" data-multimedia-path="{mm_path}" data-multimedia-code="{safe(mm_code)}">
<img src="{mm_path}" alt="{safe(mm_code)}" data-interactive="zoom">
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The mm_path variable is used in both HTML attributes (data-multimedia-path and src) without escaping. Apply safe() to mm_path in both locations to prevent attribute injection and XSS vulnerabilities.

Copilot uses AI. Check for mistakes.
return f'''<div class="media-embed-container">
<div data-s1000d-multimedia="video" data-multimedia-path="{mm_path}" data-multimedia-code="{safe(mm_code)}">
<video controls>
<source src="{mm_path}" type="video/mp4">
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The mm_path variable should be escaped with safe() before being inserted into the src attribute to prevent potential attribute injection attacks.

Copilot uses AI. Check for mistakes.
return f'''<div class="media-embed-container">
<div data-s1000d-multimedia="audio" data-multimedia-path="{mm_path}" data-multimedia-code="{safe(mm_code)}">
<audio controls>
<source src="{mm_path}" type="audio/mpeg">
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The mm_path variable should be escaped with safe() before being inserted into the src attribute to prevent potential attribute injection attacks.

Copilot uses AI. Check for mistakes.
container.innerHTML = '';
container.appendChild(img);

this.enhanceImage(img);
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

When embedImage() is called, it sets data-interactive='zoom' attribute on images via the HTML generation in build_ietp.py, but enhanceImage() is called without that attribute being explicitly set. The enhanceImage() method checks for img.dataset.interactive === 'zoom' at line 134, which will work from the HTML but not when programmatically created. Consider explicitly setting the data-interactive attribute on the img element before calling enhanceImage if zoom functionality is desired for all embedded images.

Copilot uses AI. Check for mistakes.

// Calculate aspect ratio padding
if (type === 'video' || type === 'image') {
const [width, height] = this.options.aspectRatio.split(':').map(Number);
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

If this.options.aspectRatio is not in the expected 'width:height' format (e.g., malformed or missing), the destructuring will fail and width or height could be undefined or NaN, causing incorrect padding calculation. Add validation to ensure the aspect ratio format is valid before processing.

Suggested change
const [width, height] = this.options.aspectRatio.split(':').map(Number);
// Validate aspectRatio format ('width:height') and fall back to 16:9 if invalid
const rawRatio = this.options && typeof this.options.aspectRatio === 'string'
? this.options.aspectRatio
: '';
let width;
let height;
if (rawRatio) {
const parts = rawRatio.split(':');
if (parts.length === 2) {
width = Number(parts[0]);
height = Number(parts[1]);
}
}
// Fallback to default 16:9 if parsing failed or produced invalid values
if (!Number.isFinite(width) || width <= 0 || !Number.isFinite(height) || height <= 0) {
width = 16;
height = 9;
}

Copilot uses AI. Check for mistakes.
Comment on lines +301 to +307
const escHandler = (e) => {
if (e.key === 'Escape') {
close();
document.removeEventListener('keydown', escHandler);
}
};
document.addEventListener('keydown', escHandler);
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The ESC key handler is only removed when the ESC key is pressed. If the modal is closed via the close button or backdrop click, the event listener remains attached, creating a memory leak. Move the removeEventListener call into the close() function to ensure it's always cleaned up.

Copilot uses AI. Check for mistakes.
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.

3 participants