or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

css-rules.mdcss-values.mdindex.mdlists-collections.mdparsing.mdstyle-declarations.mdstylesheet-management.md
tile.json

lists-collections.mddocs/

Lists and Collections

Array-like collection management for media queries and document matchers with automatic deduplication and proper serialization.

Capabilities

MediaList Class

Manages collections of media types and media queries with array-like behavior and automatic deduplication.

/**
 * Collection of media types and queries for @media rules and @import conditions
 */
class MediaList {
  constructor();
  
  /** Number of media items in the list */
  length: number;
  
  /** Comma-separated string representation of all media items */
  mediaText: string;
  
  /**
   * Add a media type/query if not already present
   * @param {string} medium - Media type or query to add
   */
  appendMedium(medium): void;
  
  /**
   * Remove a media type/query if present
   * @param {string} medium - Media type or query to remove
   */
  deleteMedium(medium): void;
  
  // Array-like indexed access: [0], [1], etc.
}

Usage Examples:

const { MediaList, parse } = require("cssom");

// Create new media list
const mediaList = new MediaList();

// Add media types
mediaList.appendMedium("screen");
mediaList.appendMedium("print");
mediaList.appendMedium("(max-width: 768px)");

console.log(mediaList.length); // 3
console.log(mediaList.mediaText); // "screen, print, (max-width: 768px)"

// Array-like access
console.log(mediaList[0]); // "screen"
console.log(mediaList[1]); // "print"
console.log(mediaList[2]); // "(max-width: 768px)"

// Remove media type
mediaList.deleteMedium("print");
console.log(mediaList.length); // 2
console.log(mediaList.mediaText); // "screen, (max-width: 768px)"

// Access from parsed CSS
const sheet = parse(`
  @media screen and (max-width: 768px), print {
    body { font-size: 14px; }
  }
`);

const mediaRule = sheet.cssRules[0];
console.log(mediaRule.media.length); // 2
console.log(mediaRule.media.mediaText); // "screen and (max-width: 768px), print"

MediaList with @import Rules

MediaList integration with CSS @import rules:

const { parse } = require("cssom");

const sheet = parse(`
  @import "base.css";
  @import "responsive.css" screen and (min-width: 768px);
  @import url("print.css") print;
`);

// Access media list from import rules
const importRule1 = sheet.cssRules[0];
const importRule2 = sheet.cssRules[1];
const importRule3 = sheet.cssRules[2];

console.log(importRule1.media.length); // 0 (no media specified)
console.log(importRule2.media.mediaText); // "screen and (min-width: 768px)"
console.log(importRule3.media.mediaText); // "print"

MatcherList Class

Manages collections of document matchers for @-moz-document rules with similar array-like behavior.

/**
 * Collection of document matchers for @-moz-document rules
 */
class MatcherList {
  constructor();
  
  /** Number of matcher items in the list */
  length: number;
  
  /** Comma-separated string representation of all matchers */
  matcherText: string;
  
  /**
   * Add a document matcher if not already present
   * @param {string} matcher - Document matcher to add
   */
  appendMatcher(matcher): void;
  
  /**
   * Remove a document matcher if present
   * @param {string} matcher - Document matcher to remove
   */
  deleteMatcher(matcher): void;
  
  // Array-like indexed access: [0], [1], etc.
}

Usage Examples:

const { MatcherList, parse } = require("cssom");

// Create new matcher list
const matcherList = new MatcherList();

// Add document matchers
matcherList.appendMatcher("url(http://example.com/)");
matcherList.appendMatcher("url-prefix(https://secure.example.com/)");
matcherList.appendMatcher("domain(example.org)");

console.log(matcherList.length); // 3
console.log(matcherList.matcherText); 
// "url(http://example.com/), url-prefix(https://secure.example.com/), domain(example.org)"

// Array-like access
console.log(matcherList[0]); // "url(http://example.com/)"
console.log(matcherList[1]); // "url-prefix(https://secure.example.com/)"

// Remove matcher
matcherList.deleteMatcher("domain(example.org)");
console.log(matcherList.length); // 2

// Access from parsed CSS (Firefox-specific)
const sheet = parse(`
  @-moz-document url-prefix(http://example.com/), domain(example.org) {
    body { background: red; }
  }
`);

const docRule = sheet.cssRules[0];
console.log(docRule.matcher.length); // 2
console.log(docRule.matcher.matcherText); // "url-prefix(http://example.com/), domain(example.org)"

Advanced Collection Operations

Complex operations and manipulations with media and matcher lists:

const { MediaList, MatcherList } = require("cssom");

// Media list manipulation
const media = new MediaList();

// Bulk operations
const mediaTypes = ["screen", "print", "(max-width: 768px)", "handheld"];
mediaTypes.forEach(type => media.appendMedium(type));

console.log(media.mediaText);

// Conditional modifications
if (media.length > 2) {
  media.deleteMedium("handheld"); // Remove outdated media type
}

// Check for specific media types
for (let i = 0; i < media.length; i++) {
  if (media[i].includes("max-width")) {
    console.log("Found responsive media query:", media[i]);
  }
}

// Matcher list manipulation
const matchers = new MatcherList();

// Common document matcher patterns
const patterns = [
  "url(http://example.com/)",
  "url-prefix(https://secure.)",
  "domain(trusted.example.org)",
  "regexp(\"https://.*\\.example\\.com/.*\")"
];

patterns.forEach(pattern => matchers.appendMatcher(pattern));
console.log(matchers.matcherText);

Deduplication Behavior

Both MediaList and MatcherList automatically handle duplicates:

const { MediaList } = require("cssom");

const media = new MediaList();

// Add same media type multiple times
media.appendMedium("screen");
media.appendMedium("print");
media.appendMedium("screen"); // Duplicate - won't be added again

console.log(media.length); // 2 (not 3)
console.log(media.mediaText); // "screen, print"

// Verify deduplication
console.log(media[0]); // "screen"
console.log(media[1]); // "print"
console.log(media[2]); // undefined

Serialization and Parsing

How lists serialize to and parse from CSS text:

const { parse, MediaList } = require("cssom");

// Parse complex media queries
const complexCSS = `
  @media screen and (min-width: 768px) and (max-width: 1024px), 
         print and (orientation: landscape),
         (prefers-color-scheme: dark) {
    .content { padding: 20px; }
  }
`;

const sheet = parse(complexCSS);
const mediaRule = sheet.cssRules[0];

console.log("Parsed media count:", mediaRule.media.length);
console.log("Full media text:", mediaRule.media.mediaText);

// Individual media queries
for (let i = 0; i < mediaRule.media.length; i++) {
  console.log(`Media ${i + 1}:`, mediaRule.media[i]);
}

// Modify and re-serialize
mediaRule.media.appendMedium("(min-resolution: 2dppx)");
console.log("Updated media text:", mediaRule.media.mediaText);

Implementation Limitations

Important considerations when working with lists:

const { MatcherList } = require("cssom");

// Current limitation: URLs with commas may not parse correctly
const matchers = new MatcherList();

// This works fine
matchers.appendMatcher("url(http://example.com/path)");

// This might have issues if the URL contains commas
// matchers.appendMatcher("url(http://example.com/path?param=a,b,c)");

// Workaround: Use URL encoding or avoid commas in matcher URLs
console.log("Matcher count:", matchers.length);
console.log("Matcher text:", matchers.matcherText);

// MediaList handles complex queries better
const media = new MediaList();
media.appendMedium("screen and (min-width: 768px)");
media.appendMedium("print and (color)");

console.log("Media handling is more robust:", media.mediaText);

Collection Utilities

Utility patterns for working with CSS collections:

const { parse } = require("cssom");

// Helper function to extract all media queries from a stylesheet
function extractMediaQueries(stylesheet) {
  const mediaQueries = [];
  
  for (let i = 0; i < stylesheet.cssRules.length; i++) {
    const rule = stylesheet.cssRules[i];
    
    if (rule.type === 4) { // MEDIA_RULE
      for (let j = 0; j < rule.media.length; j++) {
        mediaQueries.push(rule.media[j]);
      }
    }
    
    if (rule.type === 3) { // IMPORT_RULE
      for (let j = 0; j < rule.media.length; j++) {
        mediaQueries.push(rule.media[j]);
      }
    }
  }
  
  return mediaQueries;
}

// Usage
const sheet = parse(`
  @import "base.css" screen;
  @media (max-width: 768px) { body { font-size: 14px; } }
  @media print { body { color: black; } }
`);

const allMediaQueries = extractMediaQueries(sheet);
console.log("All media queries found:", allMediaQueries);