All files / app/services/paragraphdecoder paragraph-decoder.service.ts

100% Statements 29/29
100% Branches 4/4
100% Functions 7/7
100% Lines 27/27

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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122                                              1x               192x                 20x                   32x 32x 32x                   20x 20x 20x                         268x 193x   75x 75x 21x   54x 33x   21x                     139x 139x 139x 271x   139x                   50x 50x 50x 139x   50x      
import { Injectable } from '@angular/core';
import { Paragraph } from 'src/app/components/classes/paragraph/paragraph';
import { SubParagraph } from 'src/app/components/classes/subparagraph/subParagraph';
import { SubParagraphRoot } from 'src/app/enums/subParagraphRoot';
 
/**
 * Paragraph decoder service, used to convert a string to an array of
 * {@link Paragraph}.
 *
 * In the text, use `[[]]` to create new paragraph, use `[[br]]` to create a
 * `<br>` element, use `[[a_asset, link/to/asset.jpg]]` to create an `<a>` with
 * href to assets/link/to/asset.jpg (see {@link TextSubParagraphComponent}), use
 * `[[, some text]]` to create `<strong><em>some text</em></strong>`
 *
 * Do note that those elements are designed with the existence of code injection
 * in mind and/or malicious content in mind. For instance, `<a\>` links are
 * designed to be always prefixed by the asset folder path and hence avoid any
 * kind of attacks and injection of link to another domain (or even the same
 * domain but with an unexpected path).
 */
@Injectable({
  providedIn: 'root',
})
export class ParagraphDecoderService {
  /**
   * Creates a `<span></span>` {@link SubParagraph}
   *
   * @param input The text
   * @returns The {@link SubParagraph}
   */
  private decodeSubParagraphSpan(input: string): SubParagraph {
    return new SubParagraph(SubParagraphRoot.SPAN, input);
  }
 
  /**
   * Creates a `<br>` {@link SubParagraph}
   *
   * @returns The {@link SubParagraph}
   */
  private decodeSubParagraphBr(): SubParagraph {
    return new SubParagraph(SubParagraphRoot.BR, '');
  }
 
  /**
   * Creates a `<a></a>` {@link SubParagraph}
   *
   * @param input The text
   * @returns The {@link SubParagraph}
   */
  private decodeSubParagraphAasset(input: string): SubParagraph {
    const split = input.split(',');
    split.splice(0, 1);
    return new SubParagraph(SubParagraphRoot.A_ASSET, split.join(','));
  }
 
  /**
   * Creates a `<strong><em></em></strong>` {@link SubParagraph}
   *
   * @param input The text
   * @returns The {@link SubParagraph}
   */
  private decodeSubParagraphStrongEm(input: string): SubParagraph {
    const split = input.split(',');
    split.splice(0, 1);
    return new SubParagraph(SubParagraphRoot.STRONG_EM, split.join(','));
  }
 
  /**
   * Decodes a {@link SubParagraph}. Since it is based on a split of `[[X,Y]]`,
   * even positions always are `<span></span>` {@link SubParagraph}. Odd position
   * nature depends on the value of `X`
   *
   * @param position The {@link SubParagraph} position in the split
   * @param input The text
   * @returns The {@link SubParagraph}
   */
  private decodeSubParagraph(position: number, input: string): SubParagraph {
    if (position % 2 == 0) {
      return this.decodeSubParagraphSpan(input);
    }
    const ref = input.split(',')[0];
    if (ref == 'br') {
      return this.decodeSubParagraphBr();
    }
    if (ref == 'a_asset') {
      return this.decodeSubParagraphAasset(input);
    }
    return this.decodeSubParagraphStrongEm(input);
  }
 
  /**
   * Dcodes a {@link Paragraph}. It is based on a split of `[[]]`. It is composed
   * of {@link SubParagraph} defined by `[[X,Y]]`.
   *
   * @param input The string
   * @returns The {@link Paragraph}
   */
  private decodeParagraph(input: string): Paragraph {
    const split = input.split(/\[\[|\]\]/);
    const p = new Paragraph([]);
    for (let i = 0; i < split.length; i++) {
      if (split[i]) p.els.push(this.decodeSubParagraph(i, split[i]));
    }
    return p;
  }
 
  /**
   * Decodes a set string into an array of paragraphs.
   *
   * @param input The string
   * @returns The array of {@link Paragraph}
   */
  decode(input: string): Paragraph[] {
    const res = [];
    const paragraphs = input.split(/\[\[\]\]/);
    for (const paragraph of paragraphs) {
      res.push(this.decodeParagraph(paragraph));
    }
    return res;
  }
}