<commit_before>import template = require("es6-template-string");
import format = require("string-template");
import { parse, relative, resolve } from "upath";
import { Progress, TextDocument } from "vscode";
import { ConversionType } from "../../Conversion/ConversionType";
import { Resources } from "../../Properties/Resources";
import { IProgressState } from "../Tasks/IProgressState";
import { IPatternContext } from "./IPatternContext";

/**
 * Provides the functionality to resolve path-patterns.
 */
export class PatternResolver
{
    /**
     * The pattern to resolve.
     */
    private pattern: string;

    /**
     * A component for reporting progress.
     */
    private reporter: Progress<IProgressState>;

    /**
     * The variables inside the pattern.
     */
    private variables: Array<string | number | symbol>;

    /**
     * Initializes a new instance of the `PatternResolver` class.
     *
     * @param pattern
     * The pattern to resolve.
     *
     * @param reporter
     * A component for reporting progress.
     */
    public constructor(pattern: string, reporter?: Progress<IProgressState>)
    {
        let variables: Array<string | number | symbol> = [];
        this.pattern = pattern;
        this.reporter = reporter;

        let context: IPatternContext = {
            basename: "",
            extension: "",
            filename: "",
            dirname: "",
            workspaceFolder: ""
        };

        template(pattern, context);

        for (let key of Object.keys(context))
        {
            delete context[key as keyof IPatternContext];

            try
            {
                template(pattern, context);
            }
            catch
            {
                variables.push(key);
            }

            context[key as keyof IPatternContext] = "";
        }

        this.variables = variables;
    }

    /**
     * Gets the pattern to resolve.
     */
    public get Pattern(): string
    {
        return this.pattern;
    }

    /**
     * Gets the variables inside the pattern.
     */
    public get Variables(): ReadonlyArray<string | number | symbol>
    {
        return [...this.variables];
    }

    /**
     * Gets a component for reporting progress.
     */
    protected get Reporter(): Progress<IProgressState>
    {
        return this.reporter;
    }

    /**
     * Resolves the pattern.
     *
     * @param documentRoot
     * The path to the folder containing the document.
     *
     * @param document
     * The document to create the destination-path for.
     *
     * @param type
     * The type of the file to create the filename for.
     *
     * @param destinationRoot
     * The path to the folder to resolve the pattern to.
     *
     * @returns
     */
    public Resolve(documentRoot: string, document: TextDocument, type: ConversionType, destinationRoot?: string): string
    {
        let extension: string;
        let context: IPatternContext;
        let parsedPath = parse(document.fileName);

        this.Reporter?.report(
            {
                message: format(Resources.Resources.Get("Progress.ConversionStarting"), ConversionType[type])
            });

        switch (type)
        {
            case ConversionType.SelfContainedHTML:
            case ConversionType.HTML:
                extension = "html";
                break;
            case ConversionType.JPEG:
                extension = "jpg";
                break;
            case ConversionType.PNG:
                extension = "png";
                break;
            case ConversionType.PDF:
                extension = "pdf";
                break;
        }

        context = {
            filename: parsedPath.base,
            basename: parsedPath.name,
            extension,
            dirname: (destinationRoot !== null) ? relative(destinationRoot, documentRoot) : ".",
            workspaceFolder: destinationRoot
        };

        this.Reporter?.report(
            {
                message: Resources.Resources.Get("Progress.ResolveFileName")
            });<commit_msg>Fix pattern-resolver<commit_after>import template = require("es6-template-string");
import format = require("string-template");
import { parse, relative, resolve } from "upath";
import { Progress, TextDocument } from "vscode";
import { ConversionType } from "../../Conversion/ConversionType";
import { Resources } from "../../Properties/Resources";
import { IProgressState } from "../Tasks/IProgressState";
import { IPatternContext } from "./IPatternContext";

/**
 * Provides the functionality to resolve path-patterns.
 */
export class PatternResolver
{
    /**
     * The pattern to resolve.
     */
    private pattern: string;

    /**
     * A component for reporting progress.
     */
    private reporter: Progress<IProgressState>;

    /**
     * The variables inside the pattern.
     */
    private variables: Array<string | number | symbol>;

    /**
     * Initializes a new instance of the `PatternResolver` class.
     *
     * @param pattern
     * The pattern to resolve.
     *
     * @param reporter
     * A component for reporting progress.
     */
    public constructor(pattern: string, reporter?: Progress<IProgressState>)
    {
        let variables: Array<string | number | symbol> = [];
        this.pattern = pattern;
        this.reporter = reporter;

        let context: IPatternContext = {
            basename: "",
            extension: "",
            filename: "",
            dirname: "",
            workspaceFolder: ""
        };

        template(pattern, context);

        for (let key of Object.keys(context))
        {
            delete context[key as keyof IPatternContext];

            try
            {
                template(pattern, context);
            }
            catch
            {
                variables.push(key);
            }

            context[key as keyof IPatternContext] = "";
        }

        this.variables = variables;
    }

    /**
     * Gets the pattern to resolve.
     */
    public get Pattern(): string
    {
        return this.pattern;
    }

    /**
     * Gets the variables inside the pattern.
     */
    public get Variables(): ReadonlyArray<string | number | symbol>
    {
        return [...this.variables];
    }

    /**
     * Gets a component for reporting progress.
     */
    protected get Reporter(): Progress<IProgressState>
    {
        return this.reporter;
    }

    /**
     * Resolves the pattern.
     *
     * @param documentRoot
     * The path to the folder containing the document.
     *
     * @param document
     * The document to create the destination-path for.
     *
     * @param type
     * The type of the file to create the filename for.
     *
     * @param destinationRoot
     * The path to the folder to resolve the pattern to.
     *
     * @returns
     */
    public Resolve(documentRoot: string, document: TextDocument, type: ConversionType, destinationRoot?: string): string
    {
        let extension: string;
        let context: IPatternContext;
        let parsedPath = parse(document.fileName);

        this.Reporter?.report(
            {
                message: format(Resources.Resources.Get("Progress.ConversionStarting"), ConversionType[type])
            });

        switch (type)
        {
            case ConversionType.SelfContainedHTML:
            case ConversionType.HTML:
                extension = "html";
                break;
            case ConversionType.JPEG:
                extension = "jpg";
                break;
            case ConversionType.PNG:
                extension = "png";
                break;
            case ConversionType.PDF:
                extension = "pdf";
                break;
        }

        context = {
            filename: parsedPath.base,
            basename: parsedPath.name,
            extension,
            dirname: ((destinationRoot ?? null) !== null) ? relative(destinationRoot, documentRoot) : ".",
            workspaceFolder: destinationRoot
        };

        this.Reporter?.report(
            {
                message: Resources.Resources.Get("Progress.ResolveFileName")
            });
{'fraction_non_alphanumeric': 0.1027672802633183, 'fraction_numerical': 0.0002438132390588809, 'mean_word_length': 1.7613598115112756, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, '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': '7036931', 'n_tokens_mistral': 2070, 'n_tokens_neox': 2015, 'n_words': 562}