Practical Example

/**
 * The interface for elements.
 */
export interface Elements {
  /**
   * A root element.
   */
  root: HTMLElement;

  /**
   * A container element that contains code.
   */
  code: HTMLElement;
}

/**
 * The class for highlighting code via provided tokens.
 *
 * @since 0.0.1
 */
export class Highlighter {
  /**
   * Holds elements.
   */
  protected elements: Elements;

  /**
   * Holds options.
   */
  protected readonly options: Options;

  /**
   * Holds the EventBus instance.
   */
  protected readonly event: EventBus = new EventBus();

  /**
   * The Highlighter constructor.
   *
   * @param elm     - An element to highlight.
   * @param options - Optional. Options.
   */
  constructor( elm: HTMLElement, options: Options ) {
    this.elements = {
      root: elm,
      code: create( 'div', { class: `${ PROJECT_CODE }__code` } ),
    }

    this.options = options;
    this.init();
  }

  /**
   * Initializes the instance.
   */
  protected init(): void {
    forOwn( Components, Component => {
      Component( this.elements, this.event, this.options );
    } );

    this.event.emit( 'mounted', this );
  }

  /**
   * Creates a div element for each line.
   *
   * @return A created div element.
   */
  protected createLine(): HTMLDivElement {
    return create( 'div', { class: `${ PROJECT_CODE }__line` } );
  }

  /**
   * Creates a span element for each token.
   *
   * @param category - A category name.
   * @param value    - A text value.
   *
   * @return A created span element.
   */
  protected createSpan( category: string, value: string ): HTMLSpanElement {
    const className = `${ PROJECT_CODE_SHORT }__token ${ PROJECT_CODE_SHORT }__${ category }`;
    const span      = create( 'span', { class: className } );
    text( span, value );
    return span;
  }

  /**
   * Append tokens to the provided element with creating div elements for each line.
   *
   * @param elm    - An element to append tokens to.
   * @param tokens - An array with tokens.
   */
  protected append( elm: HTMLElement, tokens: Token[] ): void {
    let line = this.createLine();
    const lines = [ line ];

    tokens.forEach( ( token ) => {
      if ( token[ 0 ] === 'eol' ) {
        line = this.createLine();
        lines.push( line );
      } else {
        append( line, this.createSpan( token[ 0 ], token[ 1 ] ) );
      }
    } );

    append( elm, ...lines );
  }

  /**
   * Render tokens as HTML elements.
   *
   * @param tokens - Tokens to render.
   */
  render( tokens: Token[] ): void {
    const { root, code } = this.elements;
    this.append( code, tokens );

    text( root, '' );
    append( root, code );
    root.classList.add( PROJECT_CODE );

    this.event.emit( 'rendered', this );
  }

  /**
   * Destroys the instance.
   */
  destroy(): void {
    this.event.emit( 'destroy' );
    this.elements = null;
  }
}
  

Comments/Strings

/**
 * Multiline comment
 * 'Should not be a string'
 * "Should not be a string"
 */
/* Multiline comment in a single line */

// Single line comment
// 'Should not be a string'
// "Should not be a string"

'Single quote'
'Single \'quote\' with escape'
'Single 'quote' with single quote'
'Single "quote" with double quote'
'Single `quote` with back quote'

"Double quote"
"Double \"quote\" with escape"
"Double "quote" with double quote"
"Double 'quote' with single quote"
"Double `quote` with back quote"

`Back quote`
'Back \`quote\` with escape'
'Back `quote` with back quote'
'Back 'quote' with single quote'
'Back "quote" with double quote'

'/* Should not be a comment */'
'// Should not be a comment'

"/* Should not be a comment */"
"// Should not be a comment"

`/* Should not be a comment */`
`// Should not be a comment`
  

RegExp

/^.*?[\n\s]/gmsi
  

Template Literal

`Multiline
    template
      literal`

`The result will be ${ ( a + b ) * 3 }`

// Nested template literal
`container ${
  isMobile()
  // ${ comment }
  // `
  ? 'is-mobile'
  : `container--${ page.isFront() ? 'front' : 'page' }`
}`;
  

Functions/Generics

// Function
function apply<T extends object>( value: T ) {}

// Anonymous function
const a = function <T extends object>( value: T ) {}

// Arrow function
<T extends object> ( value: T ) => {}

// Method
{
  apply<T extends object>( value: T ) {}
}

type Assign<T, U> = Omit<T, keyof U> & U;

export function assign<T extends object, U extends object[]>( object: T, ...sources: U ): Assign<T, U> {
    const keys: Array<string | symbol> = getKeys( source );

    if ( a < 1 && b > d ) {
      console.log( a );
    }

    for ( let i = 0; i < keys.length; i++ ) {
    }
  }

  return object;
}
  

Typing

declare var process: any;

type Token = [ string, number, ...RegExp[] ];

interface CustomDivElement extends HTMLDivElement {
  selectionStart: number,
  selectionEnd: number,
  setSelection( number, number ): void;
}

namespace Lexer {
  export interface Grammar {
    main: Tokenizers[];
    [ key: string ]: Tokenizers[];
  }
}

function isArray<T>( subject: T[] ): subject is T[] {
  return Array.isArray( subject );
}
  

Keywords

declare, keyof, namespace, readonly, type, string,
number, boolean, bigint, symbol, any, never, unknown
  

Classes

Object.keys( object );

class Component {
  constructor() {
  }
}

const component = new Component();
  

Booleans

true, false
  

Numbers

0 1 1.23 .23 +1.23 -1.23
1e10 1e+10 1e-10 1E10 1E+10 1E-10
1.2e10 1.2e+10 1.2e-10 1.2E10 1.2E+10 1.2E-10
  

Operators

+ - ~ ! / * % ** < > <= >= == != === !==
<< >> >>> & | ^ && || ?? ?
= *= **= /= %= += -= <<= >>= >>>= &= ^= |= &&= ||= ??= :
  

Brackets

{} () []
  

Delimiters

; . ,
;;;; .... ,,,,