Skip to content

doga/IRI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Internationalized Resource Identifier

A parser for IRIs.

How this works

Parsing an IRI produces either an IRL or an URN. IRL is a non-standard representation of a URL that this library introduces, as it is very useful. An IRL object:

  • keeps the URL in its original Unicode form (i.e. https://çağlayan.info/user/çağlayan/), without projecting the URL string into ASCII space as the URL specification requires.
  • nevertheless makes the standards-compliant representation of the URL available through its url property (i.e. https://xn--alayan-vua36b.info/user/%C3%A7a%C4%9Flayan/).

This library provides a tagged template parser named iri, which is generally all that is needed to parse an IRI:

import { iri } from 'https://esm.sh/gh/doga/[email protected]/mod.mjs';

const
host  = 'localhost',
anIri = iri`http://${host}`; // an IRL instance

This library provides other classes and tagged template parsers as well, as shown in the detailed usage example below.

Usage examples

Tip: Run the examples below by typing this in your terminal (requires Deno 2+):

deno run --allow-net --allow-run --allow-env --allow-read jsr:@andrewbrey/[email protected] --dax=false --mode=isolated 'https://raw.githubusercontent.com/doga/IRI/master/README.md'
Parse IRIs using tagged templates.
description = '''
Running this example is safe, it will not read or write anything to your filesystem.
'''
import { IriParser, IRL, URN, iri, irl, url, urn } from 'https://esm.sh/gh/doga/[email protected]/mod.mjs';

const
iris = [
  iri`https://çağlayan.info/user/çağlayan/?çağlayan#çağlayan`, // IRL
  IriParser.parse('https://çağlayan.info/user/çağlayan/?çağlayan#çağlayan'), // IRL
  iri``, // null

  irl`https://çağlayan.info/user/çağlayan/`, // IRL
  irl`https://xn--alayan-vua36b.info/user/%C3%A7a%C4%9Flayan/`, // IRL
  new IRL('https://çağlayan.info/user/çağlayan/'), // IRL

  url`https://xn--alayan-vua36b.info/user/%C3%A7a%C4%9Flayan/`, // URL
  IriParser.parse('https://xn--alayan-vua36b.info/user/%C3%A7a%C4%9Flayan/'), // IRL

  urn`urn:ietf:rfc:2648`, // URN
  IriParser.parse('urn:ietf:rfc:2648'), // URN
];

for (const iri1 of iris){
  if(!iri1)continue;
  if (iri1 instanceof URN) {
    console.group(`URN: ${iri1}`);
    console.info(`
      namespace         👉 ${iri1.namespace}
      namespaceSpecific 👉 ${iri1.namespaceSpecific}
      resolver          👉 ${iri1.resolver}
      query             👉 ${iri1.query}
      fragment          👉 ${iri1.fragment}
    `);
    console.groupEnd();
  } else if (iri1 instanceof URL) {
    console.group(`URL: ${iri1}`);
    console.info(`
    URL:
      origin   👉 ${iri1.origin}
      hostname 👉 ${iri1.hostname}
      host     👉 ${iri1.host}
      pathname 👉 ${iri1.pathname}
      hash     👉 ${iri1.hash}
      search   👉 ${iri1.search}
    `);
    console.groupEnd();
  } else if (iri1 instanceof IRL) { // URL with Unicode characters
    console.group(`IRL: ${iri1}`);
    console.info(`
    IRL:
      origin   👉 ${iri1.origin}
      hostname 👉 ${iri1.hostname}
      host     👉 ${iri1.host}
      pathname 👉 ${iri1.pathname}
      hash     👉 ${iri1.hash}
      search   👉 ${iri1.search}

    URL:
      origin   👉 ${iri1.url.origin}
      hostname 👉 ${iri1.url.hostname}
      host     👉 ${iri1.url.host}
      pathname 👉 ${iri1.url.pathname}
      hash     👉 ${iri1.url.hash}
      search   👉 ${iri1.url.search}
    `);
    console.groupEnd();
  }
}

Sample output for the code above:

step 1 of 1 // Parse IRIs using tagged templates.

IRL: https://çağlayan.info/user/çağlayan/?çağlayan#çağlayan
    
        IRL:
          origin   👉 https://çağlayan.info
          hostname 👉 çağlayan.info
          host     👉 çağlayan.info
          pathname 👉 /user/çağlayan/
          hash     👉 #çağlayan
          search   👉 ?çağlayan
    
        URL:
          origin   👉 https://xn--alayan-vua36b.info
          hostname 👉 xn--alayan-vua36b.info
          host     👉 xn--alayan-vua36b.info
          pathname 👉 /user/%C3%A7a%C4%9Flayan/
          hash     👉 #%C3%A7a%C4%9Flayan
          search   👉 ?%C3%A7a%C4%9Flayan
        
IRL: https://çağlayan.info/user/çağlayan/?çağlayan#çağlayan
    
        IRL:
          origin   👉 https://çağlayan.info
          hostname 👉 çağlayan.info
          host     👉 çağlayan.info
          pathname 👉 /user/çağlayan/
          hash     👉 #çağlayan
          search   👉 ?çağlayan
    
        URL:
          origin   👉 https://xn--alayan-vua36b.info
          hostname 👉 xn--alayan-vua36b.info
          host     👉 xn--alayan-vua36b.info
          pathname 👉 /user/%C3%A7a%C4%9Flayan/
          hash     👉 #%C3%A7a%C4%9Flayan
          search   👉 ?%C3%A7a%C4%9Flayan
        
IRL: https://çağlayan.info/user/çağlayan/
    
        IRL:
          origin   👉 https://çağlayan.info
          hostname 👉 çağlayan.info
          host     👉 çağlayan.info
          pathname 👉 /user/çağlayan/
          hash     👉 
          search   👉 
    
        URL:
          origin   👉 https://xn--alayan-vua36b.info
          hostname 👉 xn--alayan-vua36b.info
          host     👉 xn--alayan-vua36b.info
          pathname 👉 /user/%C3%A7a%C4%9Flayan/
          hash     👉 
          search   👉 
        
IRL: https://çağlayan.info/user/çağlayan/
    
        IRL:
          origin   👉 https://çağlayan.info
          hostname 👉 çağlayan.info
          host     👉 çağlayan.info
          pathname 👉 /user/çağlayan/
          hash     👉 
          search   👉 
    
        URL:
          origin   👉 https://xn--alayan-vua36b.info
          hostname 👉 xn--alayan-vua36b.info
          host     👉 xn--alayan-vua36b.info
          pathname 👉 /user/%C3%A7a%C4%9Flayan/
          hash     👉 
          search   👉 
        
IRL: https://çağlayan.info/user/çağlayan/
    
        IRL:
          origin   👉 https://çağlayan.info
          hostname 👉 çağlayan.info
          host     👉 çağlayan.info
          pathname 👉 /user/çağlayan/
          hash     👉 
          search   👉 
    
        URL:
          origin   👉 https://xn--alayan-vua36b.info
          hostname 👉 xn--alayan-vua36b.info
          host     👉 xn--alayan-vua36b.info
          pathname 👉 /user/%C3%A7a%C4%9Flayan/
          hash     👉 
          search   👉 
        
URL: https://xn--alayan-vua36b.info/user/%C3%A7a%C4%9Flayan/
    
        URL:
          origin   👉 https://xn--alayan-vua36b.info
          hostname 👉 xn--alayan-vua36b.info
          host     👉 xn--alayan-vua36b.info
          pathname 👉 /user/%C3%A7a%C4%9Flayan/
          hash     👉 
          search   👉 
        
IRL: https://çağlayan.info/user/çağlayan/
    
        IRL:
          origin   👉 https://çağlayan.info
          hostname 👉 çağlayan.info
          host     👉 çağlayan.info
          pathname 👉 /user/çağlayan/
          hash     👉 
          search   👉 
    
        URL:
          origin   👉 https://xn--alayan-vua36b.info
          hostname 👉 xn--alayan-vua36b.info
          host     👉 xn--alayan-vua36b.info
          pathname 👉 /user/%C3%A7a%C4%9Flayan/
          hash     👉 
          search   👉 
        
URN: urn:ietf:rfc:2648
    
          namespace         👉 ietf
          namespaceSpecific 👉 rfc:2648
          resolver          👉 undefined
          query             👉 undefined
          fragment          👉 undefined
        
URN: urn:ietf:rfc:2648
    
          namespace         👉 ietf
          namespaceSpecific 👉 rfc:2648
          resolver          👉 undefined
          query             👉 undefined
          fragment          👉 undefined
        

Class diagram

---
title: Class diagram
---

classDiagram
  URL: string host
  URL: string pathname
  URL: toString()
  URL: ...

  IRL: URL url
  IRL: string host
  IRL: string pathname
  IRL: toString()
  IRL: ...
  IRL *-- URL : has property
  note for IRL "𝘜𝘯𝘪𝘤𝘰𝘥𝘦 𝘳𝘦𝘱𝘳𝘦𝘴𝘦𝘯𝘵𝘢𝘵𝘪𝘰𝘯 𝘰𝘧 𝘢 𝘜𝘙𝘓."

  URN: string namespace
  URN: string namespaceSpecific
  URN: ...
  URN: toString()

  IriParser: parse()
  IriParser ..> IRL : depends on
  IriParser ..> URN : depends on
Loading