Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Copy link
Member

Choose a reason for hiding this comment

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

Pkg can be removed then?

Copy link
Author

Choose a reason for hiding this comment

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

haven't fully removed p7zip_jll usage yet, just the minimum to make the tests pass.

Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
XMLDict = "228000da-037f-5747-90a9-8195ccbf91a5"
ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"

[compat]
DataStructures = "0.18"
Expand Down
1 change: 1 addition & 0 deletions src/PPTX.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module PPTX

using XMLDict
using EzXML
using ZipFile
using DataStructures

import Tables
Copy link
Member

Choose a reason for hiding this comment

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

At line 11, we can remove import Pkg.PlatformEngines: exe7z ?

Copy link
Author

Choose a reason for hiding this comment

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

haven't fully removed p7zip_jll usage yet, just the minimum to make the tests pass.

Copy link
Author

Choose a reason for hiding this comment

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

with ZipFile though, you don't need to write files to disk, but would need to rethink a bit more of the structure of the code.

Copy link
Member

Choose a reason for hiding this comment

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

let's leave this idea for another version. We could leave this PR open for now, or open an issue instead.

Expand Down
60 changes: 33 additions & 27 deletions src/write.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@

function write_presentation!(p::Presentation)
rm("./presentation.xml")
isfile("./presentation.xml") && rm("./presentation.xml")
xml = make_presentation(p)
doc = xml_document(xml)
return write("./presentation.xml", doc)
end

function write_relationships!(p::Presentation)
rm("./_rels/presentation.xml.rels")
isfile("./_rels/presentation.xml.rels") && rm("./_rels/presentation.xml.rels")
xml = make_relationships(p)
doc = xml_document(xml)
return write("./_rels/presentation.xml.rels", doc)
Expand Down Expand Up @@ -36,7 +36,7 @@ function add_title_shape!(doc::EzXML.Document, slide::Slide, unzipped_ppt_dir::S
title_shape_node = PPTX.get_title_shape_node(slide, unzipped_ppt_dir)
if !isnothing(title_shape_node)
PPTX.update_xml_title!(title_shape_node, slide.title)
new_id = maximum(get_shape_ids(doc))+1
new_id = maximum(get_shape_ids(doc)) + 1
update_shape_id!(title_shape_node, new_id)
unlink!(title_shape_node)
link!(spTree, title_shape_node)
Expand Down Expand Up @@ -106,16 +106,13 @@ function Base.write(
open_ppt::Bool=true,
template_path::String=joinpath(TEMPLATE_DIR, "no-slides"),
)

template_path = abspath(template_path)
template_name = splitpath(template_path)[end]
template_isdir = isdir(template_path)
template_isfile = isfile(template_path)

if !template_isdir && !template_isfile
error(
"No file found at template path: $template_path",
)
error("No file found at template path: $template_path")
end

if !endswith(filepath, ".pptx")
Expand All @@ -125,9 +122,7 @@ function Base.write(
filepath = abspath(filepath)
filedir, filename = splitdir(filepath)

if !isdir(filedir)
mkdir(filedir)
end
isdir(filedir) || mkdir(filedir)

if isfile(filepath)
if overwrite
Expand All @@ -139,33 +134,29 @@ function Base.write(
end
end

origin = pwd()
try
mktempdir() do tmpdir
cd(tmpdir)
tmpdir = mktempdir()
cd(tmpdir) do
Copy link
Member

Choose a reason for hiding this comment

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

oh nice :)

cp(template_path, template_name)
unzipped_dir = template_name
if template_isfile
unzip(template_name)
unzipped_dir = first(splitext(template_name)) # remove .pptx
end
ppt_dir = joinpath(unzipped_dir, "ppt")
cd(ppt_dir)
write_relationships!(p)
write_presentation!(p)
write_slides!(p)
write_shapes!(p)
update_table_style!()
cd(tmpdir)
cd(ppt_dir) do
write_relationships!(p)
write_presentation!(p)
write_slides!(p)
write_shapes!(p)
update_table_style!()
end
zip(unzipped_dir, filename)
cp(filename, filepath)
# need to cd out of folder, else mktempdir cannot cleanup
cd(origin)
end
catch e
rethrow(e)
finally
cd(origin)
end
if open_ppt
run(`cmd /C start powerpnt.exe /C $filepath`)
Expand All @@ -175,8 +166,23 @@ end

# unzips file as folder into current folder
function unzip(path::String)
output = split(path, ".pptx")[begin]
run_silent_pipeline(`$(exe7z()) x $path -o$output`)
output = first(split(path, ".pptx"))
fullpath = isabspath(path) ? path : joinpath(pwd(), path)
outputpath = isabspath(output) ? output : joinpath(pwd(), output)
isdir(outputpath) || mkdir(outputpath)

open(fullpath) do io
zip_content = ZipFile.Reader(io)
for f in zip_content.files
fullfilepath = joinpath(outputpath, f.name)
if (endswith(f.name, "/") || endswith(f.name, "\\"))
mkdir(fullfilepath)
else
isdir(dirname(fullfilepath)) || mkpath(dirname(fullfilepath))
write(fullfilepath, read(f))
end
end
end
end

# Turns folder into zipped file
Expand All @@ -195,9 +201,9 @@ end
function run_silent_pipeline(command)
standard_output = Pipe() # capture output, so it doesn't pollute the REPL
try
run(pipeline(command, stdout=standard_output))
run(pipeline(command; stdout=standard_output))
catch e
println(standard_output)
rethrow(e)
end
end
end
88 changes: 56 additions & 32 deletions test/testWriting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,84 @@ function bincompare(path::String, ref::String)
bin2 = read(ref)
same = true
i = 1
for (b1,b2) in zip(bin1,bin2)
for (b1, b2) in zip(bin1, bin2)
same = same & (b1 == b2)
if !same
println("$b1 is not $b2 at byte $i")
break
end
i+=1
i += 1
end
return same
end

function write_and_remove(fname::String, p::Presentation)
PPTX.write(fname, p, overwrite = true, open_ppt = false)
PPTX.write(fname, p; overwrite=true, open_ppt=false)
rm(fname)
return true
end

@testset "zipping/unzipping" begin
origin = @__DIR__

# simple zip/unzip test
mktempdir() do tmpdir
cd(tmpdir)
a_folder = abspath(joinpath(PPTX.TEMPLATE_DIR,"no-slides"))
cp(a_folder, abspath(joinpath(".","no-slides")))
tmpdir = mktempdir(; prefix="pptx_")
cd(tmpdir) do
a_folder = abspath(joinpath(PPTX.TEMPLATE_DIR, "no-slides"))
cp(a_folder, abspath(joinpath(".", "no-slides")))
PPTX.zip("no-slides", "zipfile.pptx")
@test isfile("zipfile.pptx")
PPTX.unzip("zipfile.pptx")
@test isdir("zipfile")
cd(origin)
end
end

@testset "writing" begin
@testset "push same picture" begin
picture_path = joinpath(PPTX.ASSETS_DIR, "cauliflower.jpg")
p = Presentation([Slide([Picture(picture_path)]), Slide([Picture(picture_path)])])
@test write_and_remove("test.pptx", p)
no_slides_template = abspath(joinpath(PPTX.TEMPLATE_DIR, "no-slides.pptx"))
tmpdir = mktempdir(; prefix="pptx_")
cd(tmpdir) do
cp(no_slides_template, abspath(joinpath(".", "no-slides-cp.pptx")))
PPTX.unzip("no-slides-cp.pptx")
dir_contents = readdir("no-slides-cp")
@test "[Content_Types].xml" ∈ dir_contents
@test "_rels" ∈ dir_contents
@test "docProps" ∈ dir_contents
@test "ppt" ∈ dir_contents
end

@testset "pushing same picture twice" begin
pres = Presentation()
s1 = Slide()
julia_logo = Picture(joinpath(PPTX.ASSETS_DIR,"julia_logo.png"), top = 110, left = 110)
push!(s1, julia_logo)
push!(pres, s1)
s2 = Slide()
push!(s2, julia_logo)
push!(pres, s2)
target = abspath(joinpath(PPTX.TESTDATA_DIR, "rezipped.pptx"))
if isfile(target)
rm(target)
end
tmpdir = mktempdir(; prefix="pptx_")
cd(tmpdir) do
cp(no_slides_template, abspath(joinpath(".", "no-slides.pptx")))
PPTX.unzip("no-slides.pptx")
PPTX.zip("no-slides", "rezipped.pptx")
# cp("rezipped.pptx", target)
end
# @test bincompare(no_slides_template, target)

@test write_and_remove("test.pptx", pres)
@testset "special cases" begin
@testset "push same picture" begin
picture_path = joinpath(PPTX.ASSETS_DIR, "cauliflower.jpg")
p = Presentation([
Slide([Picture(picture_path)]), Slide([Picture(picture_path)])
])
@test write_and_remove("test.pptx", p)
end

@testset "pushing same picture twice" begin
pres = Presentation()
s1 = Slide()
julia_logo = Picture(
joinpath(PPTX.ASSETS_DIR, "julia_logo.png"); top=110, left=110
)
push!(s1, julia_logo)
push!(pres, s1)
s2 = Slide()
push!(s2, julia_logo)
push!(pres, s2)

@test write_and_remove("test.pptx", pres)
end
end
end

Expand All @@ -63,22 +90,19 @@ end
@testset "custom template" begin
dark_template_name = "no-slides-dark"
dark_template_path = joinpath(PPTX.TEMPLATE_DIR, dark_template_name)
pres = Presentation(;title="My Presentation")
pres = Presentation(; title="My Presentation")
s = Slide()
push!(pres, s)

# error testing
wrong_path = abspath(joinpath(".", "wrong_path"))
err_msg = "No file found at template path: $wrong_path"
@test_throws ErrorException(err_msg) PPTX.write(
"anywhere.pptx",
pres;
overwrite=true,
open_ppt=false,
template_path=wrong_path,
"anywhere.pptx", pres; overwrite=true, open_ppt=false, template_path=wrong_path
)

mktempdir() do tmpdir
tmpdir = mktempdir(; prefix="pptx_")
cd(tmpdir) do
filename = "testfile-dark"
output_pptx = abspath(joinpath(tmpdir, "$filename.pptx"))
PPTX.write(
Expand Down