-
Notifications
You must be signed in to change notification settings - Fork 14
/
card.jl
124 lines (104 loc) · 3.61 KB
/
card.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
abstract type AbstractDemoCard end
struct UnmatchedCard <: AbstractDemoCard
path::String
end
"""
democard(path::String)::T
Constructs a concrete AbstractDemoCard instance.
The return type `T` is determined by the extension of the path
to your demofile. Currently supported types are:
* [`MarkdownDemoCard`](@ref) for markdown files
* [`JuliaDemoCard`](@ref) for julia files
* [`UnmatchedCard`](@ref) for unmatched files
"""
function democard(path::String)::AbstractDemoCard
validate_file(path)
_, ext = splitext(path)
if ext in markdown_exts
return MarkdownDemoCard(path)
elseif ext in julia_exts
return JuliaDemoCard(path)
else
return UnmatchedCard(path)
end
end
basename(x::AbstractDemoCard) = basename(x.path)
function get_default_id(card::AbstractDemoCard)
# drop leading coutning numbers such as 1. 1_ 1-
m = match(r"\d*(?<name>.*)", card.title)
id = replace(strip(m["name"]), ' ' => '-')
end
function validate_id(id::AbstractString, card::AbstractDemoCard)
if occursin(' ', id)
throw(ArgumentError("invalid id in $(card.path), it should not contain spaces."))
end
end
function is_democard(file)
try
@suppress_err democard(file)
return true
catch err
@debug err
return false
end
end
function load_config(card::T, key; config=Dict()) where T <: AbstractDemoCard
isempty(config) && (config = parse(card))
if key == "cover"
haskey(config, key) || return nothing
cover_path = config[key]
if !is_remote_url(cover_path)
cover_path = replace(cover_path, r"[/\\]" => Base.Filesystem.path_separator) # windows compatibility
end
return cover_path
elseif key == "id"
haskey(config, key) || return get_default_id(card)
id = config[key]
validate_id(id, card)
return id
elseif key == "title"
return get(config, key, get_default_title(card))
elseif key == "description"
return get(config, key, card.title)
elseif key == "hidden"
return get(config, key, false)
elseif key == "author"
return get(config, key, "")
elseif key == "date"
return DateTime(get(config, key, DateTime(0)))
elseif key == "julia"
version = get(config, key, JULIA_COMPAT)
return version isa VersionNumber ? version : VersionNumber(string(version))
else
throw(ArgumentError("Unrecognized key $(key) for $(T)"))
end
end
function make_badges(card::AbstractDemoCard)
badges = []
if !isempty(card.author)
for author in split(card.author, ';')
# TODO: also split on "and"
isempty(author) && continue
m = match(regex_md_url, author)
if isnothing(m)
author_str = HTTP.escapeuri(strip(author))
push!(badges, "![Author](https://img.shields.io/badge/Author-$(author_str)-blue)")
else
# when markdown url is detected, create a link for it
# author: [Johnny Chen](https://github.com/johnnychen94)
name, url = strip.(m.captures)
name = HTTP.escapeuri(name)
badge_str = "[![Author](https://img.shields.io/badge/Author-$(name)-blue)]($url)"
push!(badges, badge_str)
end
end
end
if card.date != DateTime(0)
date_str = string(round(Int, datetime2unix(card.date)))
push!(badges, "![Update time](https://img.shields.io/date/$(date_str))")
end
isempty(badges) ? "" : join(badges, " ")
end
### load concrete implementations
include("markdown.jl")
include("julia.jl")