RSS Git Download  Clone
Raw Blame History 3kB 84 lines
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { Layout } from '../layout/cory-layout';
import { constructMarkdown } from '../../worker/markdown-core';
import nextId from '../utils/next-id.js';

@Injectable()
export class MarkdownService {

    public context: any;
    layout: Layout;

    private worker: Worker | null = null;

    constructor(@Inject(PLATFORM_ID) private platformId: Object) {
        if (isPlatformBrowser(this.platformId)) {
            this.worker = new Worker(
                new URL('../../worker/markdown.worker', import.meta.url),
                { type: 'module' },
            );
        }
    }

    public async render(md: string, layout: Layout, path: string): Promise<string> {
        this.layout = layout;

        if (this.layout.packages === undefined) {
            await new Promise<void>((resolve) => {
                const wait = () => {
                    if (this.layout.packages === undefined) {
                        setTimeout(wait, 100);
                    } else {
                        resolve();
                    }
                };
                wait();
            });
        }

        const locationSnapshot = isPlatformBrowser(this.platformId)
            ? JSON.parse(JSON.stringify(window.location))
            : {
                origin: 'https://corifeus.com',
                pathname: '/' + (this.layout.currentRepo || 'matrix'),
                href: 'https://corifeus.com/' + (this.layout.currentRepo || 'matrix'),
                hostname: 'corifeus.com',
            };

        const payload = {
            md,
            settings: this.context.settings.data,
            currentRepo: this.layout.currentRepo,
            packages: this.layout.packages,
            path,
            location: locationSnapshot,
        };

        if (!this.worker) {
            return constructMarkdown(payload);
        }

        return this.renderInWorker(payload);
    }

    private renderInWorker(payload: any): Promise<string> {
        return new Promise((resolve, reject) => {
            const requestId = nextId();
            const onMessage = (event: MessageEvent) => {
                if (event.data.requestId === requestId) {
                    this.worker!.removeEventListener('message', onMessage);
                    if (event.data.success === true) {
                        resolve(event.data.html);
                    } else {
                        reject(new Error(event.data.errorMessage));
                    }
                }
            };

            this.worker!.addEventListener('message', onMessage);
            this.worker!.postMessage({ ...payload, requestId });
        });
    }
}