Skip to content

Latest commit

 

History

History
84 lines (65 loc) · 3.64 KB

File metadata and controls

84 lines (65 loc) · 3.64 KB

DOM Polyfill Improvements

Overview

This improved DOM polyfill provides the minimal DOM functionality required by @observablehq/notebook-kit/dist/src/lib/serialize.js to work in a Node.js environment.

Key Improvements Made

1. Enhanced Element Property Management

  • Modular approach: Created enhanceElement() function to handle property setup for any element type
  • Property-attribute synchronization: Properties like id and type automatically sync with attributes
  • Better textContent handling: Improved getter/setter with proper child node management
  • HTML escaping: innerHTML now properly escapes text content for HTML serialization

2. Robust CSS Selector Support

  • Improved adapter: Enhanced the xmldomAdapter with better error handling and type checking
  • NodeList compatibility: Created proper NodeList-like objects with item() and forEach() methods
  • Better element filtering: Only element nodes are considered in selector operations
  • Fallback handling: Graceful error handling for malformed selectors

3. Enhanced Document Global

  • Complete document setup: Added querySelector and querySelectorAll to the global document
  • Improved createTextNode: Better handling of empty/null text content
  • Better element creation: All created elements are enhanced with modern DOM properties

4. TypeScript Compatibility

  • Proper typing: Fixed TypeScript errors while maintaining functionality
  • Type-safe casts: Used appropriate type assertions where needed
  • Better error handling: Comprehensive error catching and logging

What the Polyfill Supports

Based on analysis of serialize.js, the polyfill provides:

Document Methods

  • document.createElement(tagName) - Creates enhanced elements
  • document.createTextNode(data) - Creates text nodes
  • document.querySelector(selector) - Finds first matching element
  • document.querySelectorAll(selector) - Finds all matching elements

Element Properties & Methods

  • element.id - Syncs with id attribute
  • element.type - Syncs with type attribute (for script elements)
  • element.textContent - Text content getter/setter
  • element.innerHTML - HTML content getter (read-only)
  • element.outerHTML - Full element HTML (read-only)
  • element.setAttribute(name, value) - Set attributes
  • element.hasAttribute(name) - Check for attributes
  • element.appendChild(child) - Add child nodes

DOMParser

  • new DOMParser().parseFromString(html, contentType) - Parse HTML strings
  • Parsed documents have querySelector and querySelectorAll methods

Usage Example

import './dom-polyfill'; // Polyfills global document and DOMParser

// Now you can use DOM operations like serialize.js does:
const notebook = document.createElement('notebook');
notebook.setAttribute('theme', 'air');

const script = document.createElement('script');
script.id = '1';
script.type = 'module';
script.textContent = 'console.log("Hello");';

notebook.appendChild(script);

console.log(notebook.outerHTML);
// Output: <notebook theme="air"><script id="1" type="module">console.log("Hello");</script></notebook>

Performance Considerations

  • Minimal overhead: Only polyfills what's actually needed
  • Lazy property setup: Properties are defined only when elements are created
  • Efficient selectors: Uses css-select library for fast CSS selector matching
  • Memory efficient: No unnecessary polyfills or globals

Compatibility

  • Works with xmldom for XML/HTML parsing
  • Compatible with css-select for selector queries
  • TypeScript friendly with proper type definitions
  • Node.js environment focused (doesn't interfere with browser globals)