From 63d0e62adf949c38e85ef5dc24893cf49721ff6d Mon Sep 17 00:00:00 2001 From: Lazaro Alonso Date: Sat, 3 Feb 2024 16:54:49 +0100 Subject: [PATCH] adds ANSIBlocks --- Project.toml | 4 ++- README.md | 6 +--- docs/src/code_example.md | 14 +++++--- src/ANSIBlocks.jl | 73 ++++++++++++++++++++++++++++++++++++++ src/DocumenterVitepress.jl | 1 + 5 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 src/ANSIBlocks.jl diff --git a/Project.toml b/Project.toml index 3c9e80ee..492d2bd3 100644 --- a/Project.toml +++ b/Project.toml @@ -7,7 +7,9 @@ version = "0.1.0" ANSIColoredPrinters = "a4c015fc-c6ff-483c-b24f-f7ea428134e9" Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +IOCapture = "b5f81e59-6552-4d32-b1f0-c071b021bf89" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" +REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [compat] -Documenter = "0.27" \ No newline at end of file +Documenter = "0.27" diff --git a/README.md b/README.md index 30fb4e91..d80c231a 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,7 @@ Visit at https://luxdl.github.io/DocumenterVitepress.jl/ ## npm dependencies ```shell -npm add -D vitepress -``` - -```shell -npm install -D vitest +npm i ``` ## run docs locally diff --git a/docs/src/code_example.md b/docs/src/code_example.md index 065ea86b..5cf40777 100644 --- a/docs/src/code_example.md +++ b/docs/src/code_example.md @@ -2,13 +2,19 @@ The `Julia` code used here is done using the following packages versions: -```@example version +````@example version using Pkg Pkg.status() -``` +```` And a simple task: -```@example simple_sum +````@example simple_sum 2 + 2 -``` \ No newline at end of file +```` + +## ANSI example + +````@ansi +printstyled("this is my color"; color = :red) +```` \ No newline at end of file diff --git a/src/ANSIBlocks.jl b/src/ANSIBlocks.jl new file mode 100644 index 00000000..9a5e2363 --- /dev/null +++ b/src/ANSIBlocks.jl @@ -0,0 +1,73 @@ +import Documenter: Anchors, Builder, Documents, Expanders, Documenter, Utilities +import Documenter.Utilities: Selectors +import Markdown, REPL +import Base64: stringmime +import IOCapture +import Documenter.Expanders: iscode, droplines, prepend_prompt, remove_sandbox_from_output + +abstract type ANSIBlocks <: Expanders.ExpanderPipeline end + +Selectors.order(::Type{ANSIBlocks}) = 12.0 +Selectors.matcher(::Type{ANSIBlocks}, node, page, doc) = iscode(node, r"^@ansi") + +function Selectors.runner(::Type{ANSIBlocks}, x, page, doc) + matched = match(r"^@ansi(?:\s+([^\s;]+))?\s*(;.*)?$", x.language) + matched === nothing && error("invalid '@ansi' syntax: $(x.language)") + name, kwargs = matched.captures + + # Bail early if in draft mode + if Utilities.is_draft(doc, page) + @debug "Skipping evaluation of @ansi block in draft mode:\n$(x.code)" + page.mapping[x] = create_draft_result(x; blocktype="@ansi") + return + end + + # The sandboxed module -- either a new one or a cached one from this page. + mod = Utilities.get_sandbox_module!(page.globals.meta, "atexample", name) + + # "parse" keyword arguments to repl + ansicolor = true + + multicodeblock = Markdown.Code[] + linenumbernode = LineNumberNode(0, "REPL") # line unused, set to 0 + @debug "Evaluating @ansi block:\n$(x.code)" + for (ex, str) in Utilities.parseblock(x.code, doc, page; keywords = false, + linenumbernode = linenumbernode) + input = droplines(str) + if VERSION >= v"1.5.0-DEV.178" + # Use the REPL softscope for REPLBlocks, + # see https://github.com/JuliaLang/julia/pull/33864 + ex = REPL.softscope!(ex) + end + c = IOCapture.capture(rethrow = InterruptException, color = ansicolor) do + cd(page.workdir) do + Core.eval(mod, ex) + end + end + Core.eval(mod, Expr(:global, Expr(:(=), :ans, QuoteNode(c.value)))) + result = c.value + buf = IOContext(IOBuffer(), :color=>ansicolor) + output = if !c.error + hide = REPL.ends_with_semicolon(input) + Documenter.DocTests.result_to_string(buf, hide ? nothing : c.value) + else + Documenter.DocTests.error_to_string(buf, c.value, []) + end + if !isempty(input) + push!(multicodeblock, Markdown.Code("ansi", prepend_prompt(input))) + end + out = IOBuffer() + print(out, c.output) # c.output is std(out|err) + if isempty(input) || isempty(output) + println(out) + else + println(out, output, "\n") + end + + outstr = String(take!(out)) + # Replace references to gensym'd module with Main + outstr = remove_sandbox_from_output(outstr, mod) + push!(multicodeblock, Markdown.Code("documenter-ansi", rstrip(outstr))) + end + page.mapping[x] = Documents.MultiCodeBlock("ansi", multicodeblock) +end \ No newline at end of file diff --git a/src/DocumenterVitepress.jl b/src/DocumenterVitepress.jl index 06bed6f2..cf2bfddb 100644 --- a/src/DocumenterVitepress.jl +++ b/src/DocumenterVitepress.jl @@ -12,6 +12,7 @@ using Documenter.Utilities: Selectors const ASSETS = normpath(joinpath(@__DIR__, "..", "assets")) include("writer.jl") +include("ANSIBlocks.jl") export MarkdownVitepress