Skip to content

Commit 8da461f

Browse files
committed
add LocalRemoteCard
1 parent 9896ed4 commit 8da461f

File tree

14 files changed

+206
-20
lines changed

14 files changed

+206
-20
lines changed

src/DemoCards.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ include("compat.jl")
3535
include("types/card.jl")
3636
include("types/section.jl")
3737
include("types/page.jl")
38+
include("remote.jl")
3839

3940
include("utils.jl")
4041
include("show.jl")

src/generate.jl

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ function makedemos(source::String, templates::Union{Dict, Nothing} = nothing;
150150
)
151151
end
152152
else
153+
# For themes that requires an index page
154+
# This will not generate a multi-level structure in the sidebar
153155
out_path = joinpath(relative_root, "index.md")
154156
end
155157

@@ -199,6 +201,9 @@ function makedemos(source::String, templates::Union{Dict, Nothing} = nothing;
199201
@info "Redirect page URL: redirect docs-edit-link for demos in \"$(source)\" directory."
200202
isnothing(templates) || push!(source_files, joinpath(page_root, "index.md"))
201203
foreach(source_files) do source_file
204+
# LocalRemoteCard is a virtual placeholder and does not exist here
205+
isfile(source_file) && return
206+
# only redirect to "real" files
202207
redirect_link(source_file, source, root, src, build, edit_branch)
203208
end
204209

@@ -239,14 +244,14 @@ function generate(page::DemoPage, templates)
239244
Mustache.render(page.template, items)
240245
end
241246

242-
function generate(cards::AbstractVector{<:AbstractDemoCard}, template)
247+
function generate(cards::AbstractVector{<:Union{AbstractDemoCard, LocalRemoteCard}}, template)
243248
# for those hidden cards, only generate the necessary assets and files, but don't add them into
244249
# the index.md page
245-
foreach(filter(x->x.hidden, cards)) do x
250+
foreach(filter(ishidden, cards)) do x
246251
generate(x, template)
247252
end
248253

249-
mapreduce(*, filter(x->!x.hidden, cards); init="") do x
254+
mapreduce(*, filter(x->!ishidden(x), cards); init="") do x
250255
generate(x, template)
251256
end
252257
end
@@ -313,7 +318,7 @@ function save_cover(path::String, sec::DemoSection)
313318
end
314319

315320
"""
316-
save_cover(path::String, card::AbstractDemoCard)
321+
save_cover(path::String, card)
317322
318323
process the cover image and save it.
319324
"""
@@ -348,7 +353,7 @@ function save_cover(path::String, card::AbstractDemoCard)
348353
end
349354
end
350355

351-
function get_covername(card::AbstractDemoCard)
356+
function get_covername(card)
352357
isnothing(card.cover) && return nothing
353358
is_remote_url(card.cover) && return card.cover
354359

src/preview.jl

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ function preview_demos(demo_path::String;
5555

5656
page_dir = generate_or_copy_pagedir(demo_path, build_dir)
5757
copy_assets_and_configs(page_dir, build_dir)
58+
rewrite_localremote_path(page_dir, build_dir)
5859

5960
cd(build_dir) do
6061
page = @suppress_err DemoPage(page_dir)
@@ -208,7 +209,12 @@ function copy_assets_and_configs(src_page_dir, dst_build_dir=pwd())
208209
config = JSON.parsefile(src_config_path)
209210
config_dir = dirname(dst_config_path)
210211
if haskey(config, "order")
211-
order = [x for x in config["order"] if x in readdir(config_dir)]
212+
files = readdir(config_dir)
213+
remote_files = keys(get(config, "remote", Dict()))
214+
order = filter(config["order"]) do x
215+
x in files || x in remote_files
216+
end
217+
212218
if isempty(order)
213219
delete!(config, "order")
214220
else
@@ -226,3 +232,28 @@ function copy_assets_and_configs(src_page_dir, dst_build_dir=pwd())
226232
end
227233
end
228234
end
235+
236+
function rewrite_localremote_path(page_dir, build_dir)
237+
# To support relpath for LocalRemoteCard, we have to
238+
# eagerly rewrite the relpath with abspath so that
239+
# later build can correctly find the remote filepath.
240+
# This only affects LocalRemoteCard with relpath.
241+
242+
page = @suppress_err DemoPage(page_dir)
243+
walkpage(page) do dir, card
244+
if card isa LocalRemoteCard
245+
# find out the corresponding config file, and rewrite the remote entry
246+
# with abspath
247+
build_carddir = joinpath(build_dir, basename(page_dir), relpath(dir, page_dir))
248+
src_config_path = joinpath(build_carddir, config_filename)
249+
250+
config = JSON.parsefile(src_config_path)
251+
config["remote"][card.name] = card.path
252+
253+
open(src_config_path, "w") do io
254+
JSON.print(io, config)
255+
end
256+
end
257+
end
258+
259+
end

src/remote.jl

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
abstract type AbstractRemotePath end
2+
3+
#####
4+
# LocalRemote
5+
#####
6+
struct LocalRemoteCard{T<:AbstractDemoCard} <: AbstractRemotePath
7+
name::String
8+
path::String
9+
item::T
10+
function LocalRemoteCard(name::String, path::String, item::T) where T<:AbstractDemoCard
11+
basename(name) == name || throw(ArgumentError("`name` should not be a path, instead it is: $name"))
12+
isfile(path) || throw(ArgumentError("file $path does not exist."))
13+
new{T}(name, path, item)
14+
end
15+
end
16+
17+
ishidden(card::LocalRemoteCard) = ishidden(card.item)
18+
19+
function Base.basename(card::LocalRemoteCard{T}) where T
20+
name, ext = splitext(card.name)
21+
if isempty(ext)
22+
if T <: MarkdownDemoCard
23+
ext = ".md"
24+
elseif T <: JuliaDemoCard
25+
ext = ".jl"
26+
else
27+
throw(ArgumentError("Unknown card type $T"))
28+
end
29+
end
30+
return name * ext
31+
end
32+
33+
function Base.show(io::IO, card::LocalRemoteCard)
34+
print(io, basename(card), " => ", card.path)
35+
end
36+
37+
function generate(card::LocalRemoteCard, template)
38+
with_tempcard(card) do tempcard
39+
generate(tempcard, template)
40+
end
41+
end
42+
function save_democards(card_dir::String, card::LocalRemoteCard; kwargs...)
43+
dst = joinpath(card_dir, basename(card))
44+
isfile(dst) && throw(ArgumentError("file $dst already exists."))
45+
46+
with_tempcard(card) do tempcard
47+
save_democards(card_dir, tempcard; kwargs...)
48+
end
49+
end
50+
51+
function save_cover(path::String, card::LocalRemoteCard)
52+
with_tempcard(card) do tempcard
53+
save_cover(path, tempcard)
54+
end
55+
end
56+
57+
# TODO: this file copy is not very necessary, and it get called many times
58+
function with_tempcard(f, card)
59+
mktempdir() do dir
60+
# copy and rename file so that generated files are correctly handled
61+
# For example:
62+
# "cardname" => "path/to/sourcefile.jl"
63+
# Later workflow uses "cardname.md" instead of "sourcefile.md"
64+
tmpfile = joinpath(dir, basename(card))
65+
cp(card.path, tmpfile)
66+
f(democard(tmpfile))
67+
end
68+
end

src/types/julia.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,5 @@ function make_badges(card::JuliaDemoCard; src, card_dir, nbviewer_root_url, proj
244244

245245
join(badges, " ")
246246
end
247+
248+
ishidden(x::JuliaDemoCard) = x.hidden

src/types/markdown.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,5 @@ function save_democards(card_dir::String,
133133
footer = credit ? markdown_footer : "\n"
134134
write(markdown_path, header, make_badges(card)*"\n\n", body, footer)
135135
end
136+
137+
ishidden(x::MarkdownDemoCard) = x.hidden

src/types/section.jl

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -97,38 +97,63 @@ function DemoSection(root::String)::DemoSection
9797
# For files that `democard` fails to recognized, dummy
9898
# `UnmatchedCard` will be generated. Currently, we only
9999
# throw warnings for it.
100-
cards = map(democard, card_paths)
100+
cards = Union{AbstractDemoCard, LocalRemoteCard}[democard(x) for x in card_paths]
101101
unmatches = filter(cards) do x
102102
x isa UnmatchedCard
103103
end
104104
if !isempty(unmatches)
105105
msg = join(map(basename, unmatches), "\", \"")
106106
@warn "skip unmatched file: \"$msg\"" section_dir=root
107107
end
108+
108109
cards = filter!(cards) do x
109110
!(x isa UnmatchedCard)
110111
end
111112

112-
section = DemoSection(root,
113-
cards,
114-
map(DemoSection, section_paths),
115-
"",
116-
"")
117-
118-
ordered_paths = joinpath.(root, load_config(section, "order"; config=config))
119-
if !isempty(section.cards)
120-
cards = map(democard, ordered_paths)
121-
subsections = []
122-
else
123-
cards = []
124-
subsections = map(DemoSection, ordered_paths)
113+
if haskey(config, "remote")
114+
remote_cards = LocalRemoteCard[]
115+
for (cardname, cardpath) in config["remote"]
116+
# if possible, store the abspath
117+
cardpath = isabspath(cardpath) ? cardpath : normpath(joinpath(root, cardpath))
118+
push!(remote_cards, LocalRemoteCard(cardname, cardpath, democard(cardpath)))
119+
end
120+
append!(cards, remote_cards)
125121
end
126122

123+
subsections = map(DemoSection, section_paths)
124+
section = DemoSection(root, cards, subsections, "", "")
125+
cards, subsections = sort_by_order(section, config)
126+
127127
title = load_config(section, "title"; config=config)
128128
description = load_config(section, "description"; config=config)
129129
DemoSection(root, cards, subsections, title, description)
130130
end
131131

132+
function sort_by_order(sec::DemoSection, config)
133+
cards = sec.cards
134+
subsections = sec.subsections
135+
136+
ordered_paths = load_config(sec, "order"; config=config)
137+
if !isempty(sec.cards)
138+
indices = map(ordered_paths) do ref
139+
findfirst(cards) do card
140+
basename(card) == ref
141+
end
142+
end
143+
cards = cards[indices]
144+
subsections = []
145+
else
146+
indices = map(ordered_paths) do ref
147+
findfirst(subsections) do sec
148+
basename(sec) == ref
149+
end
150+
end
151+
subsections = subsections[indices]
152+
cards = []
153+
end
154+
155+
return cards, subsections
156+
end
132157

133158
function load_config(sec::DemoSection, key; config=Dict())
134159
if isempty(config)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"remote": {
3+
"julia_card": "../../card/julia/title_1.jl",
4+
"markdown_card": "../../card/markdown/title_3.md"
5+
}
6+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# [Custom Title 2](@id custom_id_2)
2+
3+
This is the content
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"remote": {
3+
"julia_card.jl": "../../card/julia/title_1.jl",
4+
"markdown_card.md": "../../card/markdown/title_3.md"
5+
},
6+
"order": [
7+
"julia_card.jl",
8+
"markdown_card.md",
9+
"title_2.md"
10+
]
11+
}

0 commit comments

Comments
 (0)