<commit_before>import marked from 'marked';
import VueRouter from '@js/Helper/router';
import ThemeManager from '@js/Manager/ThemeManager';
import Localisation from '@/js/Classes/Localisation';
import SettingsManager from '@js/Manager/SettingsManager';

/**
 *
 */
class HandbookRenderer {

    constructor() {
        this.handbookUrl = SettingsManager.get('server.handbook.url');
        this.pages = [];
        this.imageCounter = 0;
        this.imageCaption = null;
    }

    /**
     *
     * @param page
     * @returns {Promise<*>}
     */
    async fetchPage(page) {
        if(this.pages.hasOwnProperty(page)) return this.pages[page];

        try {
            let url      = this.handbookUrl + page,
                response = await fetch(new Request(`${url}.md`)),
                baseUrl = url.substr(url, url.lastIndexOf('/')+1);

            if(response.ok) {
                let html = this.render(await response.text(), baseUrl, url);
                this.pages[page] = html;
                return html;
            }
            return Localisation.translate('Unable to fetch page: {message}.', {message: Localisation.translate(response.statusText)});
        } catch(e) {
            if(process.env.NODE_ENV === 'development') console.error('Request failed', e);
            throw e;
        }
    }

    /**
     *
     * @param markdown
     * @param baseUrl
     * @param documentUrl
     * @returns {*}
     */
    render(markdown, baseUrl, documentUrl) {
        this.imageCounter = 0;

        let renderer = new marked.Renderer();
        renderer.link = (href, title, text, wrap) => { return this._renderLink(href, title, text, wrap, baseUrl, documentUrl);};
        renderer.image = (href, title, text, nowrap) => { return this._renderImage(href, title, text, nowrap, baseUrl);};
        renderer.heading = HandbookRenderer._renderHeader;
        HandbookRenderer._extendMarkedLexer();

        return marked(markdown, {renderer});
    }

    /**
     *
     * @private
     */
    static _extendMarkedLexer() {
        marked.InlineLexer.prototype.outputLink = function(cap, link) {
            function escape(html) {
                return html
                    .replace(/&/g, '&amp;')
                    .replace(/</g, '&lt;')
                    .replace(/>/g, '&gt;');
            }

            let href  = escape(link.href),
                title = link.title ? escape(link.title):null;

            this.isRenderingImage = false;
            if(cap[0].charAt(0) !== '!') {
                this.isRenderingLink = true;
                let value = this.renderer.link(href, title, this.output(cap[1]), this.isRenderingImage);
                this.isRenderingImage = false;
                this.isRenderingLink = false;
                return value;
            }

            this.isRenderingImage = true;
            return this.renderer.image(href, title, escape(cap[1]), this.isRenderingLink);
        };
    }

    /**
     *
     * @param href
     * @param title
     * @param text
     * @param wrap
     * @param baseUrl
     * @param documentUrl
     * @returns {string}
     * @private
     */
    _renderLink(href, title, text, wrap, baseUrl, documentUrl) {
        let target = '_blank',
            url    = new URL(href, href.substr(0, 1) === '#' ? documentUrl:baseUrl);

        href = url.href;
        if(url.href.indexOf(documentUrl) !== -1 && url.hash.length) {
            [href, title, target] = HandbookRenderer._processAnchorLink(url.hash, title);
        } else if(url.href.indexOf(this.handbookUrl) !== -1) {
            let mime = url.href.substr(url.href.lastIndexOf('.') + 1);
            if(['png', 'jpg', 'jpeg', 'gif', 'mp4', 'm4v', 'ogg', 'webm', 'txt', 'html', 'json', 'js'].indexOf(mime) === -1) {<commit_msg>Fix Handbook internal link processing error<commit_after>import marked from 'marked';
import VueRouter from '@js/Helper/router';
import ThemeManager from '@js/Manager/ThemeManager';
import Localisation from '@/js/Classes/Localisation';
import SettingsManager from '@js/Manager/SettingsManager';

/**
 *
 */
class HandbookRenderer {

    constructor() {
        this.handbookUrl = SettingsManager.get('server.handbook.url');
        this.pages = [];
        this.imageCounter = 0;
        this.imageCaption = null;
    }

    /**
     *
     * @param page
     * @returns {Promise<*>}
     */
    async fetchPage(page) {
        if(this.pages.hasOwnProperty(page)) return this.pages[page];

        try {
            let url      = this.handbookUrl + page,
                response = await fetch(new Request(`${url}.md`)),
                baseUrl = url.substr(url, url.lastIndexOf('/')+1);

            if(response.ok) {
                let html = this.render(await response.text(), baseUrl, url);
                this.pages[page] = html;
                return html;
            }
            return Localisation.translate('Unable to fetch page: {message}.', {message: Localisation.translate(response.statusText)});
        } catch(e) {
            if(process.env.NODE_ENV === 'development') console.error('Request failed', e);
            throw e;
        }
    }

    /**
     *
     * @param markdown
     * @param baseUrl
     * @param documentUrl
     * @returns {*}
     */
    render(markdown, baseUrl, documentUrl) {
        this.imageCounter = 0;

        let renderer = new marked.Renderer();
        renderer.link = (href, title, text, wrap) => { return this._renderLink(href, title, text, wrap, baseUrl, documentUrl);};
        renderer.image = (href, title, text, nowrap) => { return this._renderImage(href, title, text, nowrap, baseUrl);};
        renderer.heading = HandbookRenderer._renderHeader;
        HandbookRenderer._extendMarkedLexer();

        return marked(markdown, {renderer});
    }

    /**
     *
     * @private
     */
    static _extendMarkedLexer() {
        marked.InlineLexer.prototype.outputLink = function(cap, link) {
            function escape(html) {
                return html
                    .replace(/&/g, '&amp;')
                    .replace(/</g, '&lt;')
                    .replace(/>/g, '&gt;');
            }

            let href  = escape(link.href),
                title = link.title ? escape(link.title):null;

            this.isRenderingImage = false;
            if(cap[0].charAt(0) !== '!') {
                this.isRenderingLink = true;
                let value = this.renderer.link(href, title, this.output(cap[1]), this.isRenderingImage);
                this.isRenderingImage = false;
                this.isRenderingLink = false;
                return value;
            }

            this.isRenderingImage = true;
            return this.renderer.image(href, title, escape(cap[1]), this.isRenderingLink);
        };
    }

    /**
     *
     * @param href
     * @param title
     * @param text
     * @param wrap
     * @param baseUrl
     * @param documentUrl
     * @returns {string}
     * @private
     */
    _renderLink(href, title, text, wrap, baseUrl, documentUrl) {
        let target = '_blank',
            url    = new URL(href, href.substr(0, 1) === '#' ? documentUrl:baseUrl);

        href = url.href;
        if(url.hash.length && url.href.indexOf(`${documentUrl}#`) !== -1) {
            [href, title, target] = HandbookRenderer._processAnchorLink(url.hash, title);
        } else if(url.href.indexOf(this.handbookUrl) !== -1) {
            let mime = url.href.substr(url.href.lastIndexOf('.') + 1);
            if(['png', 'jpg', 'jpeg', 'gif', 'mp4', 'm4v', 'ogg', 'webm', 'txt', 'html', 'json', 'js'].indexOf(mime) === -1) {
{'fraction_non_alphanumeric': 0.14725216933999474, 'fraction_numerical': 0.003944254535892716, 'mean_word_length': 2.0090981012658227, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3377882', 'n_tokens_mistral': 2266, 'n_tokens_neox': 2204, 'n_words': 463}