import { Injectable } from "@angular/core"; import { DocumentData } from "../symbols/DocumentData"; import { HttpClient } from "@angular/common/http"; import { take } from "rxjs/operators"; @Injectable({ providedIn: "root" }) export class DocumentFetchService { private language: string; private readonly replacements: {tag: string, replacement: string, single?: boolean}[] = [ {tag: "warning", replacement: "$1"}, {tag: "inverted", replacement: "$1"}, {tag: "u", replacement: "$1"}, {tag: "br", replacement: "
", single: true} ]; constructor(private http: HttpClient) { this.language = document.body.parentElement.lang; } public async fetch(unsafeId: string): Promise { const encodedId = this.encodeId(unsafeId); try { return await this.fetchWithLanguage(encodedId, this.language); } catch (e) { try { return await this.fetchWithLanguage(encodedId, "en"); } catch (e) { return { found: false, id: encodedId, content: await this.fetchErrorContent(404) }; } } } private async fetchWithLanguage(unsafeId: string, language: string): Promise { const encodedId = this.encodeId(unsafeId); const response: string = await this.http.get("/documents/" + encodedId + "." + language + ".md", { responseType: "text" }) .pipe(take(1)).toPromise(); return { found: true, id: encodedId, content: this.format(await response) }; } public async fetchErrorContent(errorCode: number): Promise { if (errorCode > 0 && errorCode <= 700) { try { const response: string = await this.http.get("/documents/" + errorCode + "." + this.language + ".md", { responseType: "text" }) .pipe(take(1)).toPromise(); return this.format(await response); } catch (e) { } } return "Error " + errorCode + "."; } private encodeId(id: string): string { const encoded = id.split("/").map(encodeURIComponent).filter((part) => part.length > 0 && !/[^a-zA-Z0-9_-àùéèì]/.test(part)).join("/"); if (encoded.length > 0) { return encoded; } else { return "index"; } } private format(rawDocument: string): string { let count: number; do { count = 0; this.replacements.forEach(replacement => { const replacementResult = this.replaceTagWith(rawDocument, replacement.tag, replacement.replacement,replacement.single); count += replacementResult.count; rawDocument = replacementResult.document; }); } while (count > 0); return rawDocument; } private replaceTagWith(document: string, tagName: string, tagResult: string, single?: boolean): {document: string, count: number} { const newDocument = single === true ? document.replace(new RegExp("\\[" + tagName + "\\]", "g"), tagResult) : document.replace(new RegExp("\\[" + tagName + "\\]([^[]+)\\[\\/" + tagName + "\\]", "g"), tagResult); return {document: newDocument, count: newDocument !== document ? 1 : 0}; } }