All files / libs/tools/plugin/src/executors/intl-update potFileGenerator.stream.ts

0% Statements 0/67
0% Branches 0/1
0% Functions 0/1
0% Lines 0/67

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68                                                                                                                                       
import { Readable } from 'node:stream';

import { type ExtractedMessageDescriptor } from '@formatjs/cli-lib/src/extract';

const POT_BLOCK_SPACING = '\n\n';

export class PotFileGeneratorStream extends Readable {
  private readonly keys = Object.keys(this.messages).sort((idA, idB) => {
    const msgA = this.messages[idA].defaultMessage ?? '';
    const msgB = this.messages[idB].defaultMessage ?? '';
    return msgA.localeCompare(msgB, this.locale, { numeric: true });
  });

  private current = 0;

  public constructor(
    private readonly messages: Record<string, ExtractedMessageDescriptor>,
    private readonly locale?: string,
  ) {
    super();
  }

  public override _read() {
    if (this.current >= this.keys.length) {
      // signals that the stream ended
      this.push(null);
      return;
    }

    if (this.current === 0) {
      this.push(this.formatPotHeader(this.locale));
      this.push(POT_BLOCK_SPACING);
    }

    const id = this.keys[this.current];
    const msg = this.messages[id];

    this.current += 1;
    this.push(this.formatPoMsg(id, msg));
    this.push(POT_BLOCK_SPACING);
  }

  public formatPotHeader(locale?: string) {
    return [
      'msgid ""',
      'msgstr ""',
      String.raw`"Content-Type: text/plain; charset=UTF-8\n"`,
      String.raw`"Content-Transfer-Encoding: 8bit\n"`,
      String.raw`"MIME-Version: 1.0\n"`,
      locale && String.raw`"Language: ${locale}\n"`,
    ]
      .filter(Boolean)
      .join('\n');
  }

  public formatPoMsg(id: string, msg: ExtractedMessageDescriptor) {
    return [
      typeof msg.description === 'string' && `#. ${msg.description}`,
      msg.file && `#: ${msg.file}:${msg.line}`,
      `msgctxt "${id.replaceAll('"', String.raw`\"`)}"`,
      `msgid "${(msg.defaultMessage ?? '').replaceAll('"', String.raw`\"`).replaceAll(String.raw`\\"`, String.raw`\"`)}"`, // Escape double quotes, but avoid double escaping (breaks the POT file format).
      'msgstr ""',
    ]
      .filter(Boolean)
      .join('\n');
  }
}