💾 Archived View for iich.space › src › modules › mission-control › template-builder.ts captured on 2022-03-01 at 16:05:00.

View Raw

More Information

⬅️ Previous capture (2021-12-03)

-=-=-=-=-=-=-

import { URL } from 'url';

import { I18n, TranslateFunction, getLocaleFromUrl } from './i18n';

export type Template<Props = Record<string, unknown>> = (
  tb: TemplateBuilder,
  props: Props,
) => string;

export class TemplateBuilder {
  url: URL;
  i18n: I18n | null;
  t: TranslateFunction;

  constructor(url: URL, i18n: I18n | null) {
    this.url = url;
    this.i18n = i18n;
    this.each = this.each.bind(this);
    this.include = this.include.bind(this);
    this.when = this.when.bind(this);
    this.link = this.link.bind(this);

    if (this.i18n !== null) {
      const locale = getLocaleFromUrl(this.url);
      this.t = this.i18n.createT(locale);
    } else {
      this.t = () => '';
    }
  }

  include<Props extends Record<string, unknown>, T extends Template<Props>>(
    template: T,
    props?: Props,
  ): string {
    return template(this, (props || {}) as Props)
      .replace(/\n?[\b]/gm, '')
      .replace(/^\n/, '')
      .replace(/\n$/, '');
  }

  when(
    condition: boolean | undefined | null,
    ifFn: () => string,
    elseFn?: () => string,
  ): string {
    let result = '';

    if (condition) {
      result = ifFn();
    } else if (elseFn) {
      result = elseFn();
    }

    result = result.replace(/^\n/, '').replace(/\n$/, '');

    if (result.length > 0) {
      return result;
    }

    return '\b';
  }

  each<T>(items: Array<T>, fn: (item: T) => string, space = 1): string {
    return items
      .map((item) => fn(item))
      .join(
        Array.from(Array(space).keys())
          .map(() => '\n')
          .join(''),
      );
  }

  link(path: string, label?: string): string {
    const processedPath = [['{HOST}', this.url.host]].reduce(
      (acc, [search, replace]) => acc.replaceAll(search, replace),
      path,
    );
    return `=> ${processedPath}${label ? ' ' + label : ''}`;
  }
}