public void RenderLatex()
        {
            // Seems to be some sort of problem running this in Rider - it just hangs

            var katexJsLatexProcessor = new KatexJsLatexProcessor();

            string html1 = katexJsLatexProcessor.RenderToString("c = \\pm\\sqrt{a^2 + b^2}");

            string html2 = katexJsLatexProcessor.RenderToString("c = \\pm\\sqrt{a^2 + b^2}");

            Assert.NotNull(html1);
            Assert.NotNull(html2);
        }
        public void RenderToStringSpeedTestMultiThreaded()
        {
            // Seems to be some sort of problem running this in Rider - it just hangs

            var stopwatch = new Stopwatch();

            stopwatch.Start();

            int renders = 1000;

            // Optimal jintEngine count seems to be 4 on Surface Book 2

            var katexJsLatexProcessor = new KatexJsLatexProcessor(4, 2000);

            long initialisationMilliseconds = stopwatch.ElapsedMilliseconds;

            // initialisationMilliseconds tests out at about 500 ms - significant overhead

            _testOutputHelper.WriteLine($"{nameof(initialisationMilliseconds)}: {initialisationMilliseconds}");

            stopwatch.Restart();

            var options = new ParallelOptions {
                MaxDegreeOfParallelism = 10
            };

            Parallel.For(0, renders, options, async i =>
            {
                _ = katexJsLatexProcessor.RenderToString("c = \\pm\\sqrt{a^2 + b^2}");
            });

            stopwatch.Stop();

            long elapsedMilliseconds = stopwatch.ElapsedMilliseconds;

            double millisecondsPerRender = elapsedMilliseconds / (double)renders;

            _testOutputHelper.WriteLine($"{nameof(millisecondsPerRender)}: {millisecondsPerRender}");
            _testOutputHelper.WriteLine($"{stopwatch.ElapsedMilliseconds}: {elapsedMilliseconds}");

            Assert.True(millisecondsPerRender < 100);
        }
        public void RenderLatexSpeedTest()
        {
            // Seems to be some sort of problem running this in Rider - it just hangs

            var stopwatch = new Stopwatch();

            stopwatch.Start();

            int renders = 1000;

            var katexJsLatexProcessor = new KatexJsLatexProcessor();

            long initialisationMilliseconds = stopwatch.ElapsedMilliseconds;

            // katexScriptInitMilliseconds tests out at about 0.5 seconds - significant overhead

            _testOutputHelper.WriteLine($"{nameof(initialisationMilliseconds)}: {initialisationMilliseconds}");

            stopwatch.Restart();

            for (int i = 0; i < renders; i++)
            {
                _ = katexJsLatexProcessor.RenderToString("c = \\pm\\sqrt{a^2 + b^2}");
            }

            stopwatch.Stop();

            long elapsedMilliseconds = stopwatch.ElapsedMilliseconds;

            double millisecondsPerRender = elapsedMilliseconds / (double)renders;

            _testOutputHelper.WriteLine($"{nameof(millisecondsPerRender)}: {millisecondsPerRender}");

            // 0.281 seconds if creating new KatexScript per render but only 0.025 if reusing over tested over 10000 iterations.
            // So there is capacity for 40 renders / second on test hardware (Surface Book 2). With caching for server side rendering
            // this should be performant enough per server.

            Assert.True(millisecondsPerRender < 100);
        }
        public void RenderToStringSpeedTestMultiThreadedFlooded()
        {
            int renders = 1000;

            // Optimal jintEngine count seems to be 4 on Surface Book 2

            var katexJsLatexProcessor = new KatexJsLatexProcessor(1, 500);

            var options = new ParallelOptions {
                MaxDegreeOfParallelism = 100
            };

            // Aggregate exception made up of timeouts

            Assert.Throws <AggregateException>(() =>
            {
                Parallel.For(0, renders, options, i =>
                {
                    _ = katexJsLatexProcessor.RenderToString("c = \\pm\\sqrt{a^2 + b^2}");
                });
            });
        }
        // Docs:    Note processing timings
        //          Note required package refs
        //          Note js equivalent library

        static void Main(string[] args)
        {
            // Instantiate KatexJsLatexProcessor. ILatexProcessor provides parsing for raw LaTeX strings.
            // ILatexProcessor can be used standalone or within IMarkdownLatexPreprocessor

            // The argument jintEngineCount causes KatexJsLatexProcessor
            // to create 4 Jint JavaScript Interpreter engine instances and load the KaTeX JS library into
            // each. This is because Jint is not thread safe so KatexJsLatexProcessor manages thread safety
            // locking during function calls. Multiple instances allows for concurrent processing using a
            // round robin algorithm to distribute requests to each Jint engine.

            // Argument jintEngineLockTimeout specifies a timeout in milliseconds after which an exception will be thrown
            // if a lock cannot be obtained on an instance of the underlying Jint engine if the load on KatexJsLatexProcessor
            // is too high. You can set this value as high as needed.

            var latexProcessor = new KatexJsLatexProcessor(jintEngineCount: 4, jintEngineLockTimeout: 2000);

            // Instantiate MarkdownLatexPreprocessor. IMarkdownLatexPreprocessor provides parsing for LaTeX strings in markdown text.

            var markdownLatexPreprocessor = new MarkdownLatexPreprocessor(latexProcessor);

            // Services can be instantiated via DI as follows

            // services.AddSingleton<ILatexProcessor>(new KatexJsLatexProcessor(4, 2000));
            // services.AddSingleton<IMarkdownLatexPreprocessor, MarkdownLatexPreprocessor>();

            // Render a raw LaTeX expression.

            string latexHtml = latexProcessor.RenderToStringAsync("f(a,b,c) = (a^2+b^2+c^2)^3").Result;

            Console.WriteLine("Latex expression output:");
            Console.WriteLine(latexHtml);

            string markdown = @"

## Example Markdown

This is an example markdown document

This is an expression in inline delmiters ...

$f(a,b,c) = (a^2+b^2+c^2)^3$

... and this one with block delimiters

$$

\sum_{i=1}^\infty\frac{1}{n^2}=\frac{\pi^2}{6}

$$

";

            // ... or use MarkdownLatexPreprocessor to process LaTeX expressions within
            // markdown text.

            var markdownHtml = markdownLatexPreprocessor.ProcessLatex(markdown);

            Console.WriteLine("Markdown output:");
            Console.WriteLine(markdownHtml);
            Console.ReadLine();
        }