-
Notifications
You must be signed in to change notification settings - Fork 367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding support for rich display of Markdown cells #2346
Changes from 4 commits
273bbb3
e72d033
a1d9619
57a3b58
531e089
ea571e6
c53598e
5df96a6
a391912
5f5f121
73a9010
3a85fbf
8928695
1a0fd3b
c1e38d4
be35852
7d4e5d0
2f5c2d3
c05e3ea
b90696d
606f3eb
174d632
5414031
17b6e1b
7a8c0de
c112ef4
8a04964
9fbe264
43a047c
8ff0ff0
e67308e
ab4209c
4993be3
feb0f5d
bbd5143
088c894
6a2ed0d
b3866e5
0f6fb38
1342b4b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -142,6 +142,10 @@ function _show(io::IO, ::MIME"text/html", df::AbstractDataFrame; | |||||
cell_val = df[row, column_name] | ||||||
if ismissing(cell_val) | ||||||
write(io, "<td><em>missing</em></td>") | ||||||
elseif cell_val isa Markdown.MD | ||||||
write(io, "<td>") | ||||||
show(io, "text/html", cell_val) | ||||||
write(io, "</td>") | ||||||
elseif cell_val isa SHOW_TABULAR_TYPES | ||||||
write(io, "<td><em>") | ||||||
cell = sprint(ourshow, cell_val) | ||||||
|
@@ -303,6 +307,8 @@ function _show(io::IO, ::MIME"text/latex", df::AbstractDataFrame; | |||||
cell = df[row,col] | ||||||
if ismissing(cell) | ||||||
print(io, "\\emph{missing}") | ||||||
elseif cell isa Markdown.MD | ||||||
show(io, "text/latex", cell) | ||||||
elseif cell isa SHOW_TABULAR_TYPES | ||||||
print(io, "\\emph{") | ||||||
print(io, latex_escape(sprint(ourshow, cell, context=io))) | ||||||
|
@@ -417,7 +423,12 @@ function printtable(io::IO, | |||||
elseif isnothing(df[i, j]) | ||||||
print(io, nothingstring) | ||||||
else | ||||||
if ! (etypes[j] <: Real) | ||||||
if df[i,j] isa Markdown.MD | ||||||
print(io, quotemark) | ||||||
r=repr(df[i,j]) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||
escapedprint(io, first(r,max(0,length(r)-1)), quotestr) | ||||||
NicholasWMRitchie marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
print(io, quotemark) | ||||||
elseif ! (etypes[j] <: Real) | ||||||
print(io, quotemark) | ||||||
escapedprint(io, df[i, j], quotestr) | ||||||
print(io, quotemark) | ||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -54,6 +54,11 @@ ourshow(io::IO, x::Symbol) = ourshow(io, string(x)) | |||||
ourshow(io::IO, x::Nothing; styled::Bool=false) = ourshow(io, "", styled=styled) | ||||||
ourshow(io::IO, x::SHOW_TABULAR_TYPES; styled::Bool=false) = | ||||||
ourshow(io, summary(x), styled=styled) | ||||||
function ourshow(io::IO, x::Markdown.MD) | ||||||
r = repr(x) | ||||||
len = min(length(r, 1, something(findfirst(c->c=='\n', r), lastindex(r)+1)-1), 50) | ||||||
bkamins marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
return print(io, len < length(r) - 1 ? first(r, len)*"…" : first(r, len)) | ||||||
bkamins marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using chars should give a slightly more efficient code:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||
end | ||||||
|
||||||
# AbstractChar: https://github.com/JuliaLang/julia/pull/34730 (1.5.0-DEV.261) | ||||||
# Irrational: https://github.com/JuliaLang/julia/pull/34741 (1.5.0-DEV.266) | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
module TestIO | ||
|
||
using Test, DataFrames, CategoricalArrays, Dates | ||
using Test, DataFrames, CategoricalArrays, Dates, Markdown | ||
|
||
# Test LaTeX export | ||
@testset "LaTeX export" begin | ||
|
@@ -9,20 +9,21 @@ using Test, DataFrames, CategoricalArrays, Dates | |
C = ["A", "B", "C", "S"], | ||
D = [1.0, 2.0, missing, 3.0], | ||
E = CategoricalArray(["a", missing, "c", "d"]), | ||
F = Vector{String}(undef, 4) | ||
F = Vector{String}(undef, 4), | ||
G = [ md"[DataFrames.jl](http://juliadata.github.io/DataFrames.jl)", md"###A", md"``\frac{A}{B}``", md"*A*b**A**"] | ||
) | ||
str = """ | ||
\\begin{tabular}{r|cccccc} | ||
\t& A & B & C & D & E & F\\\\ | ||
\t\\hline | ||
\t& $(Int) & String & String & Float64? & Cat…? & String\\\\ | ||
\t\\hline | ||
\t1 & 1 & \\\$10.0 & A & 1.0 & a & \\emph{\\#undef} \\\\ | ||
\t2 & 2 & M\\&F & B & 2.0 & \\emph{missing} & \\emph{\\#undef} \\\\ | ||
\t3 & 3 & A\\textasciitilde{}B & C & \\emph{missing} & c & \\emph{\\#undef} \\\\ | ||
\t4 & 4 & \\textbackslash{}\\textbackslash{}alpha & S & 3.0 & d & \\emph{\\#undef} \\\\ | ||
\\end{tabular} | ||
""" | ||
str = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you keep the triple quoted form? It's more readable. Same below. |
||
"\\begin{tabular}{r|ccccccc}\n" * | ||
"\t& A & B & C & D & E & F & G\\\\\n" * | ||
"\t\\hline\n\t& "*repr(Int)*" & String & String & Float64? & Cat…? & String & MD…\\\\\n" * | ||
"\t\\hline\n" * | ||
"\t1 & 1 & \\\$10.0 & A & 1.0 & a & \\emph{\\#undef} & \\href{http://juliadata.github.io/DataFrames.jl}{DataFrames.jl}\n\n \\\\\n" * | ||
"\t2 & 2 & M\\&F & B & 2.0 & \\emph{missing} & \\emph{\\#undef} & \\#\\#\\#A\n\n \\\\\n" * | ||
"\t3 & 3 & A\\textasciitilde{}B & C & \\emph{missing} & c & \\emph{\\#undef} & \$\\frac{A}{B}\$\n\n \\\\\n" * | ||
"\t4 & 4 & \\textbackslash{}\\textbackslash{}alpha & S & 3.0 & d & \\emph{\\#undef} & \\emph{A}b\\textbf{A}\n\n \\\\\n" * | ||
"\\end{tabular}\n" | ||
|
||
|
||
@test repr(MIME("text/latex"), df) == str | ||
@test repr(MIME("text/latex"), eachcol(df)) == str | ||
@test repr(MIME("text/latex"), eachrow(df)) == str | ||
|
@@ -130,6 +131,27 @@ end | |
|
||
@test_throws ArgumentError DataFrames._show(stdout, MIME("text/html"), | ||
DataFrame(ones(2,2)), rowid=10) | ||
|
||
df = DataFrame( | ||
A=Int64[1,4,9,16], | ||
B = [ | ||
md"[DataFrames.jl](http://juliadata.github.io/DataFrames.jl)", | ||
md"###A", | ||
md"``\frac{A}{B}``", | ||
md"*A*b**A**" ] | ||
) | ||
|
||
@test repr(MIME("text/html"), df) == | ||
NicholasWMRitchie marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"<table class=\"data-frame\"><thead><tr><th></th><th>A</th><th>B</th></tr><tr><th></th>" * | ||
"<th>Int64</th><th>MD…</th></tr></thead><tbody><p>4 rows × 2 columns</p><tr><th>1</th>" * | ||
"<td>1</td><td><div class=\"markdown\">" * | ||
"<p><a href=\"http://juliadata.github.io/DataFrames.jl\">DataFrames.jl</a>" * | ||
"</p>\n</div></td></tr><tr><th>2</th><td>4</td><td><div class=\"markdown\">" * | ||
"<p>###A</p>\n</div></td></tr><tr><th>3</th><td>9</td><td><div class=\"markdown\">" * | ||
"<p>$\\frac{A}{B}$</p>\n</div></td></tr><tr><th>4</th>" * | ||
"<td>16</td><td><div class=\"markdown\"><p><em>A</em>b<strong>A</strong></p>"* | ||
"\n</div></td></tr></tbody></table>" | ||
|
||
end | ||
|
||
# test limit attribute of IOContext is used | ||
|
@@ -180,6 +202,101 @@ end | |
end | ||
end | ||
|
||
@testset "Markdown as text/plain and as text/csv" begin | ||
df = DataFrame( | ||
A=Int64[1,4,9,16,25,36,49,64], | ||
B = [ | ||
md"[DataFrames.jl](http://juliadata.github.io/DataFrames.jl)", | ||
md"``\frac{x^2}{x^2+y^2}``", | ||
md"# Header", | ||
md"This is *very*, **very**, very, very, very, very, very, very, very long line" , | ||
md"", | ||
Markdown.parse("∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0" * | ||
"∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0"), | ||
Markdown.parse("∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ\n"* | ||
" * ∞7∫αγ\n"* | ||
" * ∞8∫αγ\n"* | ||
" * ∞9∫αγ∞0∫α\nγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0"), | ||
Markdown.parse("∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0∫α\n"* | ||
" * γ∞1∫α\n"* | ||
" * γ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0"), | ||
] | ||
) | ||
@test sprint(show, "text/plain", df) == """ | ||
8×2 DataFrame | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add 8-characters indentation. Same below. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one still applies. |
||
│ Row │ A │ B │ | ||
│ │ Int64 │ Markdown.MD │ | ||
├─────┼───────┼─────────────────────────────────────────────────────┤ | ||
│ 1 │ 1 │ [DataFrames.jl](http://juliadata.github.io/DataFra… │ | ||
│ 2 │ 4 │ \$\\frac{x^2}{x^2+y^2}\$ │ | ||
│ 3 │ 9 │ # Header │ | ||
│ 4 │ 16 │ This is *very*, **very**, very, very, very, very, … │ | ||
│ 5 │ 25 │ │ | ||
│ 6 │ 36 │ ∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0… │ | ||
│ 7 │ 49 │ ∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ… │ | ||
│ 8 │ 64 │ ∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0… │""" | ||
|
||
@test sprint(show, "text/csv", df) == """ | ||
\"A\",\"B\" | ||
1,\"[DataFrames.jl](http://juliadata.github.io/DataFrames.jl)\" | ||
4,\"\$\\\\frac{x^2}{x^2+y^2}\$\" | ||
9,\"# Header\" | ||
16,\"This is *very*, **very**, very, very, very, very, very, very, very long line\" | ||
25,\"\" | ||
36,\"∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0\" | ||
49,\"∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ\\n\\n * ∞7∫αγ\\n * ∞8∫αγ\\n * ∞9∫αγ∞0∫α\\n\\nγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0\" | ||
64,\"∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0∫α\\n\\n * γ∞1∫α\\n * γ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0\" | ||
""" | ||
end | ||
|
||
@testset "Markdown as HTML" begin | ||
df = DataFrame( | ||
A=Int64[1,4,9,16,25,36,49,64], | ||
B = [ | ||
md"[DataFrames.jl](http://juliadata.github.io/DataFrames.jl)", | ||
md"``\frac{x^2}{x^2+y^2}``", | ||
md"# Header", | ||
md"This is *very*, **very**, very, very, very, very, very, very, very long line" , | ||
md"", | ||
Markdown.parse("∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0" * | ||
"∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0"), | ||
Markdown.parse("∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ\n"* | ||
" * ∞7∫αγ\n"* | ||
" * ∞8∫αγ\n"* | ||
" * ∞9∫αγ∞0∫α\nγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0"), | ||
Markdown.parse("∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0∫α\n"* | ||
" * γ∞1∫α\n"* | ||
" * γ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0"), | ||
] | ||
) | ||
@test sprint(show,"text/html",df) == | ||
"<table class=\"data-frame\"><thead>" * | ||
"<tr><th></th><th>A</th><th>B</th></tr>" * | ||
"<tr><th></th><th>Int64</th><th>MD…</th></tr>" * | ||
"</thead>" * | ||
"<tbody>" * "<p>8 rows × 2 columns</p>" * | ||
"<tr><th>1</th><td>1</td><td><div class=\"markdown\">" * | ||
"<p><a href=\"http://juliadata.github.io/DataFrames.jl\">DataFrames.jl</a></p>\n</div></td></tr>" * | ||
"<tr><th>2</th><td>4</td><td><div class=\"markdown\"><p>$\\frac{x^2}{x^2+y^2}$</p>\n</div></td></tr>" * | ||
"<tr><th>3</th><td>9</td><td><div class=\"markdown\"><h1>Header</h1>\n</div></td></tr>" * | ||
"<tr><th>4</th><td>16</td><td><div class=\"markdown\">" * | ||
"<p>This is <em>very</em>, <strong>very</strong>, very, very, very, very, very, very, very long line</p>\n" * | ||
"</div></td></tr>" * | ||
"<tr><th>5</th><td>25</td><td><div class=\"markdown\"></div></td></tr>" * | ||
"<tr><th>6</th><td>36</td><td><div class=\"markdown\">" * | ||
"<p>∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0</p>\n" * | ||
"</div></td></tr>" * | ||
"<tr><th>7</th><td>49</td><td><div class=\"markdown\">" * | ||
"<p>∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ</p>\n<ul>\n<li><p>∞7∫αγ</p>\n</li>\n<li><p>∞8∫αγ</p>\n</li>\n<li><p>∞9∫αγ∞0∫α</p>\n</li>\n</ul>\n<p>γ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0</p>\n" * | ||
"</div></td></tr>" * | ||
"<tr><th>8</th><td>64</td><td><div class=\"markdown\">" * | ||
"<p>∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0∫α</p>" * | ||
"\n<ul>\n" * | ||
"<li><p>γ∞1∫α</p>\n</li>\n" * | ||
"<li><p>γ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0</p>\n</li>\n" * | ||
"</ul>\n" * "</div></td></tr></tbody></table>" | ||
end | ||
|
||
@testset "empty data frame and DataFrameRow" begin | ||
df = DataFrame(a = [1,2], b = [1.0, 2.0]) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since accessing
df[i, j]
is relatively slow, better store it incell = df[i, j]
and use that afterwards as in the HTML method (not sure why we didn't do this here).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see it, nor the other changes you mention below. :-)