Repository: PumasAI/QuartoNotebookRunner.jl (julia)

Issue:
Consider removing double quotes from strings interpolated into a document
I just tried an example workflow with parameters, and it seems to me this behavior is a bit impractical:

````
---
engine: julia
params:
    title: Title
    text: Text
    image: path to an image
---

# `{julia} title`

This is parametric text: `{julia} text`

And this is an image:

![Some image](`{julia} image`)

````

invoked with some parameters:

```
quarto render params.qmd -P title:"Custom title" -P text:"Some custom text" -P image:"surface.png"
```

Gives the following result:

<img width="654" alt="image" src="https://github.com/PumasAI/QuartoNotebookRunner.jl/assets/22495855/f98257cd-f168-4fa5-b445-fa9e63a43175">

`String`s in Julia have two different printing behaviors, `print` shows them without quotes and `show(io, MIME"text/plain"(), ...` adds them, so they can be entered back in from the copied output. I think this representation is not useful for inline evaluation. We can add `Text` around all values to make it work, but that's an unnecessary workaround:

````
---
engine: julia
params:
    title: Title
    text: Text
    image: path to an image
---

# `{julia} Text(title)`

This is parametric text: `{julia} Text(text)`

And this is an image:

![Some image](`{julia} Text(image)`)
````

<img width="828" alt="image" src="https://github.com/PumasAI/QuartoNotebookRunner.jl/assets/22495855/0bba6fcb-899d-43b0-8b76-a9cdaaecadf7">

Pull request description:
Fixes https://github.com/PumasAI/QuartoNotebookRunner.jl/issues/152

Patch:
diff --git a/src/QuartoNotebookWorker/src/render.jl b/src/QuartoNotebookWorker/src/render.jl
index 76fedef8..8b129c26 100644
--- a/src/QuartoNotebookWorker/src/render.jl
+++ b/src/QuartoNotebookWorker/src/render.jl
@@ -2,7 +2,8 @@ function render(
     code::AbstractString,
     file::AbstractString,
     line::Integer,
-    cell_options::AbstractDict = Dict{String,Any}(),
+    cell_options::AbstractDict = Dict{String,Any}();
+    inline::Bool = false,
 )
     # This records whether the outermost cell is an expandable cell, which we
     # then return to the server so that it can decide whether to treat the cell
@@ -13,7 +14,7 @@ function render(
     is_expansion_ref = Ref(false)
     result = Base.@invokelatest(
         collect(
-            _render_thunk(code, cell_options, is_expansion_ref) do
+            _render_thunk(code, cell_options, is_expansion_ref; inline) do
                 Base.@invokelatest include_str(
                     NotebookState.notebook_module(),
                     code;
@@ -35,7 +36,8 @@ function _render_thunk(
     thunk::Base.Callable,
     code::AbstractString,
     cell_options::AbstractDict = Dict{String,Any}(),
-    is_expansion_ref::Ref{Bool} = Ref(false),
+    is_expansion_ref::Ref{Bool} = Ref(false);
+    inline::Bool,
 )
     captured, display_results = with_inline_display(thunk, cell_options)
 
@@ -81,12 +83,18 @@ function _render_thunk(
                 )
             end
             # **The recursive call:**
-            return Base.@invokelatest _render_thunk(wrapped, cell.code, cell.options)
+            return Base.@invokelatest _render_thunk(
+                wrapped,
+                cell.code,
+                cell.options;
+                inline,
+            )
         end
     else
         results = Base.@invokelatest render_mimetypes(
             REPL.ends_with_semicolon(code) ? nothing : captured.value,
-            cell_options,
+            cell_options;
+            inline,
         )
         # Wrap the `NamedTuple` in a `Tuple` to avoid the `NamedTuple`
         # being flattened into just it's values when passed into
@@ -290,7 +298,9 @@ Base.show(io::IO, m::MIME"text/plain", w::WrapperType) = Base.show(io, m, w.valu
 Base.showable(mime::MIME, w::WrapperType) = Base.showable(mime, w.value)
 
 
-function render_mimetypes(value, cell_options)
+# for inline code chunks, `inline` should be set to `true` which causes "text/plain" output like
+# what you'd get from `print` (Strings without quotes) and not from `show("text/plain", ...)`
+function render_mimetypes(value, cell_options; inline::Bool = false)
     # Intercept objects prior to rendering so that we can wrap specific
     # types in our own `WrapperType` to customised rendering instead of
     # what the package defines itself.
@@ -329,23 +339,31 @@ function render_mimetypes(value, cell_options)
             "image/png",
         ],
     )
-    mimes = get(mime_groups, to_format) do
-        [
-            "text/plain",
-            "text/markdown",
-            "text/html",
-            "text/latex",
-            "image/svg+xml",
-            "image/png",
-            "application/pdf",
-            "application/json",
-        ]
+    mimes = if inline
+        ["text/plain", "text/markdown"]
+    else
+        get(mime_groups, to_format) do
+            [
+                "text/plain",
+                "text/markdown",
+                "text/html",
+                "text/latex",
+                "image/svg+xml",
+                "image/png",
+                "application/pdf",
+                "application/json",
+            ]
+        end
     end
     for mime in mimes
         if showable(mime, value)
             buffer = IOBuffer()
             try
-                Base.@invokelatest show(with_context(buffer, cell_options), mime, value)
+                if inline && mime == "text/plain"
+                    Base.@invokelatest print(with_context(buffer, cell_options), value)
+                else
+                    Base.@invokelatest show(with_context(buffer, cell_options), mime, value)
+                end
             catch error
                 backtrace = catch_backtrace()
                 result[mime] = (;
@@ -377,7 +395,7 @@ function render_mimetypes(value, cell_options)
     end
     return result
 end
-render_mimetypes(value::Nothing, cell_options) =
+render_mimetypes(value::Nothing, cell_options; inline::Bool = false) =
     Dict{String,@NamedTuple{error::Bool, data::Vector{UInt8}}}()
 
 
diff --git a/src/server.jl b/src/server.jl
index 4b771bd6..3ac86472 100644
--- a/src/server.jl
+++ b/src/server.jl
@@ -810,7 +810,12 @@ function evaluate_raw_cells!(
                             if startswith(node.literal, "{r}")
                                 source_code = wrap_with_r_boilerplate(source_code)
                             end
-                            expr = :(render($(source_code), $(chunk.file), $(chunk.line)))
+                            expr = :(render(
+                                $(source_code),
+                                $(chunk.file),
+                                $(chunk.line);
+                                inline = true,
+                            ))
                             # There should only ever be a single result from an
                             # inline evaluation since you can't pass cell
                             # options and so `expand` will always be `false`.
diff --git a/src/worker.jl b/src/worker.jl
index 73220290..c047a606 100644
--- a/src/worker.jl
+++ b/src/worker.jl
@@ -11,7 +11,7 @@ function worker_init(f::File, options::Dict)
                     ),
                 )
                 global refresh!(args...) = QNW.refresh!($(f.path), $(options), args...)
-                global render(args...) = QNW.render(args...)
+                global render(args...; kwargs...) = QNW.render(args...; kwargs...)
             end
 
             nothing


Test patch:
diff --git a/test/testsets/inline_code.jl b/test/testsets/inline_code.jl
index 7b7d9fcb..f9ead090 100644
--- a/test/testsets/inline_code.jl
+++ b/test/testsets/inline_code.jl
@@ -59,7 +59,7 @@ include("../utilities/prelude.jl")
         @test any(contains("Some `Text` objects *\\*placeholder\\**."), cell.source)
 
         cell = cells[9]
-        @test any(contains("Some plain `String`s \"\\*placeholder\\*\"."), cell.source)
+        @test any(contains("Some plain `String`s \\*placeholder\\*."), cell.source)
         @test any(contains("A more complex expression 2."), cell.source)
     end
 end