Skip to content
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

WIP: inserting tables with \tableinput command #197

Merged
merged 10 commits into from
Sep 2, 2019
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.2.0"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
JuDocTemplates = "6793090a-55ae-11e9-0511-73b91164f4ea"
LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589"
Expand Down
47 changes: 47 additions & 0 deletions docs/src/man/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,53 @@ This is the index then some **markdown** in a side file.

**Note**: if you don't specify a file extension, `.md` is appended to the specified path.

### Inserting a table

You can insert tables directly from CSV files with the `\tableinput{header}{path}` command.
If you generate the file on-the-fly, you should follow this example:
`````judoc
```julia:./tableinput/gen
testcsv = "h1,h2,h3
152,some string, 1.5f0
0,another string,2.87"
write("assets/pages/tableinput/testcsv.csv", testcsv)
```
`````
Then you can insert the table with:
`````judoc
\tableinput{}{./tableinput/testcsv.csv}
`````
Which will result in:

| h1 | h2 | h3 |
| --- | -------------- | ----- |
| 152 | some string | 1.5f0 |
| 0 | another string | 2.87 |
In this case given no header was specified in the call, a header was generated from the first line in the CSV (here: h1, h2).
cserteGT3 marked this conversation as resolved.
Show resolved Hide resolved
If you want, you can specify the header:
`````judoc
\tableinput{custom h1, custom h2, custom h3}{./tableinput/testcsv.csv}
`````

| custom h1 | custom h2 | custom h3 |
| --------- | -------------- | --------- |
| 152 | some string | 1.5f0 |
| 0 | another string | 2.87 |

Or you can include an existing CSV file (`assets/test2.csv`):
`````judoc
\tableinput{}{/assets/test2.csv}
`````

!!! note

The look of the table will be defined by your CSS stylesheet.

There's a couple of rules that you have to keep in mind when using the `\tableinput{}{}` command:
* The CSV file must have a header line.
cserteGT3 marked this conversation as resolved.
Show resolved Hide resolved
* Columns must be separated with comma (`,`).
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with -> by a

* If a header is specified, its length must match the number of columns of the file.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of the file -> in the file


## Page variables

Page variables are a way to interact with the HTML templating.
Expand Down
1 change: 1 addition & 0 deletions src/JuDoc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ using JuDocTemplates

using Markdown
using Dates # see jd_vars
using DelimitedFiles: readdlm

import LiveServer

Expand Down
63 changes: 63 additions & 0 deletions src/converter/lx_simple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,68 @@ function resolve_lx_figalt(lxc::LxCom)::String
end


"""
$SIGNATURES

Internal function to resolve a `\\tableinput{header}{rpath}` (finds a csv and includes it with header).
"""
function resolve_lx_tableinput(lxc::LxCom)::String
rpath = strip(content(lxc.braces[2]))
header = strip(content(lxc.braces[1]))
path = resolve_assets_rpath(rpath; canonical=false)
fdir, fext = splitext(path)
# copy-paste from resolve_lx_figalt()
# A. a path with extension --> use that
# there can be a relative path set but the user may mean
# that it's in the subfolder /output/ (if generated by code) so should look
# both in the relpath and if not found and if /output/ not already the last subdir
syspath = joinpath(PATHS[:folder], split(path, '/')...)
if isfile(syspath)
return csv2html(syspath, header)
end
# now try in the output dir just in case (provided we weren't already looking there)
p1, p2 = splitdir(fdir)
if splitdir(p1)[2] != "output"
candpath = joinpath(p1, "output", p2 * fext)
syspath = joinpath(PATHS[:folder], split(candpath, '/')...)
isfile(syspath) && return csv2html(syspath, header)
end
return html_err("table matching '$path' not found")
end


"""
$SIGNATURES

Internal function to process an array of strings to markdown table (in one single string).
If header is empty, the first row of the file will be used for header.
"""
function csv2html(path, header)::String
csvcontent = readdlm(path, ',', String, header=false)
nrows, ncols = size(csvcontent)
# replacing header
if ! isempty(header)
newheader = split(header, ",")
hs = size(newheader,1)
hs != ncols && return html_err("header size ($hs) and number of columns ($ncols) do not match")
csvcontent[1,:] = newheader
end
io = IOBuffer()
# writing the header
write(io, prod("| " * csvcontent[1, i] * " " for i in 1:ncols))
# writing end of header & header separator
write(io, "|\n|", repeat( " ----- |", ncols), "\n")
# writing content
for i in 2:nrows
for j in 1:ncols
write(io, "| ", csvcontent[i,j], " ")
end
write(io, "|\n")
end
return md2html(String(take!(io)))
end


"""
$SIGNATURES

Expand All @@ -94,6 +156,7 @@ const LXCOM_SIMPLE = Dict{String, Function}(
"\\output" => resolve_lx_output, # include plain output generated by code
"\\figalt" => resolve_lx_figalt, # include a figure (may or may not have been generated)
"\\file" => resolve_lx_file, # include a file
"\\tableinput" => resolve_lx_tableinput, # include table from a csv file
cserteGT3 marked this conversation as resolved.
Show resolved Hide resolved
)


Expand Down
1 change: 1 addition & 0 deletions src/jd_vars.jl
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ the site. See [`resolve_lxcom`](@ref).
GLOBAL_LXDEFS["\\figalt"] = LxDef("\\figalt", 2, EMPTY_SS)
GLOBAL_LXDEFS["\\fig"] = LxDef("\\fig", 1, subs("\\figalt{}{#1}"))
GLOBAL_LXDEFS["\\file"] = LxDef("\\file", 2, subs("[#1]()"))
GLOBAL_LXDEFS["\\tableinput"] = LxDef("\\tableinput", 2, EMPTY_SS)
# text formatting
GLOBAL_LXDEFS["\\underline"] = LxDef("\\underline", 1,
subs("~~~<span style=\"text-decoration:underline;\">!#1</span>~~~"))
Expand Down
38 changes: 38 additions & 0 deletions test/converter/lx_simple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,41 @@ end
<p>View $(J.html_err("file matching '/assets/blih.pdf' not found")) here.</p>
""")
end

@testset "table" begin
testcsv = "h1,h2,h3\nstring1, 1.567, 0\n,,\n l i n e ,.158,99999999"
write(joinpath(J.PATHS[:assets], "testcsv.csv"), testcsv)
# no header specified
h = raw"""
A table:
\tableinput{}{/assets/testcsv.csv}
Done.
""" |> seval
shouldbe = """<p>A table: <table><tr><th>h1</th><th>h2</th><th>h3</th></tr>
<tr><td>string1</td><td>1.567</td><td>0</td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td>l i n e</td><td>.158</td><td>99999999</td></tr></table>
Done.</p>"""
@test isapproxstr(h, shouldbe)
# header specified
h = raw"""
A table:
\tableinput{A,B,C}{/assets/testcsv.csv}
Done.
""" |> seval
shouldbe = """<p>A table: <table><tr><th>A</th><th>B</th><th>C</th></tr>
<tr><td>string1</td><td>1.567</td><td>0</td></tr>
cserteGT3 marked this conversation as resolved.
Show resolved Hide resolved
<tr><td></td><td></td><td></td></tr>
<tr><td>l i n e</td><td>.158</td><td>99999999</td></tr></table>
Done.</p>"""
@test isapproxstr(h, shouldbe)
# wrong header
h = raw"""
A table:
\tableinput{,}{/assets/testcsv.csv}
Done.
""" |> seval
shouldbe = """<p>A table: <p><span style=\"color:red;\">// header size (2) and number of columns (3) do not match //</span></p>
Done.</p>"""
@test isapproxstr(h, shouldbe)
end