CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-whatwg-url

An implementation of the WHATWG URL Standard's URL API and parsing machinery

Pending
Overview
Eval results
Files

percent-encoding.mddocs/

Percent Encoding

Percent encoding and decoding utilities for handling URL-encoded strings and byte sequences according to the WHATWG URL specification.

Capabilities

percentDecodeString

Decodes percent-encoded sequences in a string, converting them back to their original characters.

/**
 * Percent decode a string
 * @param {string} string - String containing percent-encoded sequences
 * @returns {string} Decoded string with percent sequences converted to characters
 */
function percentDecodeString(string)

Usage Examples:

const { percentDecodeString } = require("whatwg-url");

// Basic percent decoding
const encoded = "Hello%20World%21";
const decoded = percentDecodeString(encoded);
console.log(decoded); // "Hello World!"

// URL component decoding
const path = "/api/users/John%20Doe";
const decodedPath = percentDecodeString(path);
console.log(decodedPath); // "/api/users/John Doe"

// UTF-8 decoding
const utf8Encoded = "caf%C3%A9"; // "café" in UTF-8
const utf8Decoded = percentDecodeString(utf8Encoded);
console.log(utf8Decoded); // "café"

// Mixed encoded/unencoded content
const mixed = "user%40example.com";
const decodedMixed = percentDecodeString(mixed);
console.log(decodedMixed); // "user@example.com"

// Invalid sequences are left as-is
const invalid = "invalid%ZZ%sequence";
const decodedInvalid = percentDecodeString(invalid);
console.log(decodedInvalid); // "invalid%ZZ%sequence"

percentDecodeBytes

Decodes percent-encoded sequences in a byte array (Uint8Array), useful for binary data processing.

/**
 * Percent decode bytes in a Uint8Array
 * @param {Uint8Array} uint8Array - Byte array containing percent-encoded sequences
 * @returns {Uint8Array} Decoded byte array
 */
function percentDecodeBytes(uint8Array)

Usage Examples:

const { percentDecodeBytes } = require("whatwg-url");

// Create a byte array with percent-encoded data
const encoder = new TextEncoder();
const encodedBytes = encoder.encode("Hello%20World");

// Decode the bytes
const decodedBytes = percentDecodeBytes(encodedBytes);

// Convert back to string to verify
const decoder = new TextDecoder();
const result = decoder.decode(decodedBytes);
console.log(result); // "Hello World"

// Binary data with percent encoding
const binaryData = new Uint8Array([
  0x48, 0x65, 0x6C, 0x6C, 0x6F, // "Hello"
  0x25, 0x32, 0x30,             // "%20" 
  0x57, 0x6F, 0x72, 0x6C, 0x64  // "World"
]);

const decodedBinary = percentDecodeBytes(binaryData);
console.log(decoder.decode(decodedBinary)); // "Hello World"

Advanced Usage

Form Data Processing

Handle form-encoded data with percent decoding:

const { percentDecodeString } = require("whatwg-url");

function parseFormData(formString) {
  const pairs = formString.split('&');
  const result = {};
  
  for (const pair of pairs) {
    const [key, value] = pair.split('=');
    const decodedKey = percentDecodeString(key);
    const decodedValue = percentDecodeString(value || '');
    
    if (result[decodedKey]) {
      // Handle multiple values
      if (Array.isArray(result[decodedKey])) {
        result[decodedKey].push(decodedValue);
      } else {
        result[decodedKey] = [result[decodedKey], decodedValue];
      }
    } else {
      result[decodedKey] = decodedValue;
    }
  }
  
  return result;
}

// Usage
const formData = "name=John%20Doe&email=john%40example.com&city=New%20York";
const parsed = parseFormData(formData);
console.log(parsed);
// {
//   name: "John Doe",
//   email: "john@example.com", 
//   city: "New York"
// }

URL Path Decoding

Safely decode URL path components:

const { percentDecodeString } = require("whatwg-url");

function decodePathSegments(path) {
  // Split path and decode each segment
  const segments = path.split('/').map(segment => {
    try {
      return percentDecodeString(segment);
    } catch (error) {
      // Return original segment if decoding fails
      return segment;
    }
  });
  
  return segments.join('/');
}

// Usage
const encodedPath = "/users/John%20Doe/files/My%20Document.pdf";
const decodedPath = decodePathSegments(encodedPath);
console.log(decodedPath); // "/users/John Doe/files/My Document.pdf"

Binary Data Handling

Process binary data with percent encoding:

const { percentDecodeBytes } = require("whatwg-url");

function processBinaryUrl(encodedData) {
  // Convert string to bytes if needed
  const encoder = new TextEncoder();
  const bytes = typeof encodedData === 'string' 
    ? encoder.encode(encodedData)
    : encodedData;
    
  // Decode percent-encoded sequences
  const decoded = percentDecodeBytes(bytes);
  
  // Process the binary data
  return {
    size: decoded.length,
    data: decoded,
    preview: decoded.slice(0, 10) // First 10 bytes
  };
}

// Usage with binary data
const binaryUrl = "data%3Aimage%2Fpng%3Bbase64%2CiVBOR";
const processed = processBinaryUrl(binaryUrl);
console.log(processed.size); // Size of decoded data
console.log(processed.preview); // First 10 bytes

Error Handling

Percent decoding functions handle invalid sequences gracefully:

const { percentDecodeString } = require("whatwg-url");

// Invalid hex sequences are left unchanged
console.log(percentDecodeString("test%GG")); // "test%GG"

// Incomplete sequences are left unchanged  
console.log(percentDecodeString("test%2")); // "test%2"

// Mixed valid/invalid sequences
console.log(percentDecodeString("hello%20world%XX")); // "hello world%XX"

// Empty string handling
console.log(percentDecodeString("")); // ""

// Already decoded content
console.log(percentDecodeString("hello world")); // "hello world"

Integration with URL Parsing

Percent decoding works seamlessly with URL parsing functions:

const { parseURL, percentDecodeString } = require("whatwg-url");

// URL parsing automatically handles percent decoding for most components
const url = parseURL("https://example.com/path%20with%20spaces?name=John%20Doe");

// But you can manually decode if needed
const manuallyDecodedPath = percentDecodeString("/path%20with%20spaces");
console.log(manuallyDecodedPath); // "/path with spaces"

// Query parameters need manual decoding if not using URLSearchParams
if (url.query) {
  const decodedQuery = percentDecodeString(url.query);
  console.log(decodedQuery); // "name=John Doe"
}

Install with Tessl CLI

npx tessl i tessl/npm-whatwg-url

docs

index.md

percent-encoding.md

url-class.md

url-manipulation.md

url-parsing.md

url-search-params.md

tile.json