elixir-toolkit-theme-plugins 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 989e78f7e6995bb095549eb94361934f40c944b45c207f24820d91c518006280
|
|
4
|
+
data.tar.gz: ae7e2b72145732bcdcfc52cabb325eae06c1910a5de7fe2781b958184f93e318
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2869b8b726d00bb4c58e105c97563e61836f122b449decfa13851d8f7a09d1c489b96121f41af6c0a97c6fbc9f34809b2c64ffb0907943fe2f3041e8a82150f9
|
|
7
|
+
data.tar.gz: 07eea18abf4bbe4bb3bcca9303bc4a21c121a1d5d6c98309c8d8df3a3383dc468f9fcb2e1be910b6b289e7dc827e7cd939b67b510bd97c72fd5e8cc663a27fb6
|
|
@@ -9,6 +9,7 @@ module Jekyll
|
|
|
9
9
|
return data unless data.is_a?(Array)
|
|
10
10
|
|
|
11
11
|
load_page_data
|
|
12
|
+
instances_index = Jekyll::Ett::ToolTag.instances_index
|
|
12
13
|
|
|
13
14
|
data.each do |tool|
|
|
14
15
|
next unless tool.is_a?(Hash)
|
|
@@ -16,6 +17,10 @@ module Jekyll
|
|
|
16
17
|
if tool["id"] && @related_pages[tool["id"]]
|
|
17
18
|
tool["related_pages"] = @related_pages[tool["id"]].to_a
|
|
18
19
|
end
|
|
20
|
+
|
|
21
|
+
if tool["id"] && instances_index[tool["id"]]
|
|
22
|
+
tool["instances"] = instances_index[tool["id"]]
|
|
23
|
+
end
|
|
19
24
|
end
|
|
20
25
|
|
|
21
26
|
data
|
|
@@ -30,7 +35,6 @@ module Jekyll
|
|
|
30
35
|
Dir.glob(pages_path).each do |f|
|
|
31
36
|
file = File.read(f)
|
|
32
37
|
page_id_matches = file.match(/page_id:\s*(\w+)/)
|
|
33
|
-
|
|
34
38
|
next unless page_id_matches
|
|
35
39
|
|
|
36
40
|
page_id = page_id_matches[1]
|
|
@@ -4,175 +4,186 @@ require "yaml"
|
|
|
4
4
|
module Jekyll
|
|
5
5
|
class Ett
|
|
6
6
|
class ToolTag < Liquid::Tag
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
@@instances_by_tool = nil
|
|
8
|
+
TOOLS_PATH = File.join(Dir.pwd, "_data", "tool_and_resource_list.yml")
|
|
9
|
+
|
|
10
|
+
def initialize(tagName, content, tokens)
|
|
11
|
+
super
|
|
12
|
+
@content = content
|
|
13
|
+
load_tools
|
|
14
|
+
load_instances
|
|
15
|
+
end
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@tools = YAML.load(File.read(tools_path))
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Scan Markdown pages for front matter declaring national_resources
|
|
20
|
-
# and index instances by their "instance_of" tool id
|
|
21
|
-
def load_instances
|
|
22
|
-
# Single combined index for *all* instances
|
|
23
|
-
@instances_by_tool = Hash.new { |h, k| h[k] = [] }
|
|
24
|
-
|
|
25
|
-
# --- 1) instances from national_resources in page front matter ---
|
|
26
|
-
pages_path = File.join(Dir.pwd, "**", "*.md")
|
|
27
|
-
files = Dir.glob(pages_path)
|
|
28
|
-
|
|
29
|
-
files.each do |f|
|
|
30
|
-
raw = File.read(f)
|
|
31
|
-
fm = extract_front_matter(raw)
|
|
32
|
-
next unless fm.is_a?(Hash)
|
|
33
|
-
|
|
34
|
-
country_code = (fm["country_code"] || "").to_s
|
|
35
|
-
country_name = (fm["title"] || "").to_s
|
|
36
|
-
resources = fm["national_resources"] || []
|
|
37
|
-
next unless resources.is_a?(Array)
|
|
38
|
-
|
|
39
|
-
resources.each do |res|
|
|
40
|
-
next unless res.is_a?(Hash)
|
|
41
|
-
inst_of = res["instance_of"]
|
|
42
|
-
next if inst_of.nil? || inst_of == "NA"
|
|
43
|
-
|
|
44
|
-
@instances_by_tool[inst_of] << {
|
|
45
|
-
"name" => (res["name"] || res["id"] || "Instance"),
|
|
46
|
-
"url" => res["url"],
|
|
47
|
-
"id" => res["id"],
|
|
48
|
-
"country_code" => country_code,
|
|
49
|
-
"country_name" => country_name,
|
|
50
|
-
"page_path" => f
|
|
51
|
-
}
|
|
17
|
+
def load_tools
|
|
18
|
+
@tools = YAML.load(File.read(TOOLS_PATH))
|
|
52
19
|
end
|
|
53
|
-
end
|
|
54
20
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
next if parent_id.nil? || parent_id == "NA"
|
|
59
|
-
|
|
60
|
-
@instances_by_tool[parent_id] << {
|
|
61
|
-
"name" => (tool["name"] || tool["id"] || "Instance"),
|
|
62
|
-
"url" => tool["url"], # normally defined for tools
|
|
63
|
-
"id" => tool["id"],
|
|
64
|
-
# YAML entries often don’t have country information; leave blank so no flag
|
|
65
|
-
"country_code" => "",
|
|
66
|
-
"country_name" => "",
|
|
67
|
-
"page_path" => nil # no page file to resolve
|
|
68
|
-
}
|
|
21
|
+
# --- class-level accessor used by both tag and filters ---
|
|
22
|
+
def self.instances_index
|
|
23
|
+
@@instances_by_tool ||= build_instances_index
|
|
69
24
|
end
|
|
70
|
-
end
|
|
71
25
|
|
|
26
|
+
def self.build_instances_index
|
|
27
|
+
instances_by_tool = Hash.new { |h, k| h[k] = [] }
|
|
28
|
+
|
|
29
|
+
tools = YAML.load(File.read(TOOLS_PATH))
|
|
30
|
+
|
|
31
|
+
# 1) instances from national_resources in page front matter
|
|
32
|
+
pages_path = File.join(Dir.pwd, "**", "*.md")
|
|
33
|
+
files = Dir.glob(pages_path)
|
|
34
|
+
|
|
35
|
+
files.each do |f|
|
|
36
|
+
raw = File.read(f)
|
|
37
|
+
fm = extract_front_matter(raw)
|
|
38
|
+
next unless fm.is_a?(Hash)
|
|
39
|
+
|
|
40
|
+
country_code = (fm["country_code"] || "").to_s
|
|
41
|
+
country_name = (fm["title"] || "").to_s
|
|
42
|
+
resources = fm["national_resources"] || []
|
|
43
|
+
next unless resources.is_a?(Array)
|
|
44
|
+
|
|
45
|
+
resources.each do |res|
|
|
46
|
+
next unless res.is_a?(Hash)
|
|
47
|
+
inst_of = res["instance_of"]
|
|
48
|
+
next if inst_of.nil? || inst_of == "NA"
|
|
49
|
+
|
|
50
|
+
instances_by_tool[inst_of] << {
|
|
51
|
+
"name" => (res["name"] || res["id"] || "Instance"),
|
|
52
|
+
"url" => res["url"],
|
|
53
|
+
"id" => res["id"],
|
|
54
|
+
"country_code" => country_code,
|
|
55
|
+
"country_name" => country_name,
|
|
56
|
+
"page_path" => f
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# 2) instances from tool_and_resource_list.yml itself
|
|
62
|
+
(tools || []).each do |tool|
|
|
63
|
+
parent_id = tool["instance_of"]
|
|
64
|
+
next if parent_id.nil? || parent_id == "NA"
|
|
65
|
+
|
|
66
|
+
instances_by_tool[parent_id] << {
|
|
67
|
+
"name" => (tool["name"] || tool["id"] || "Instance"),
|
|
68
|
+
"url" => tool["url"],
|
|
69
|
+
"id" => tool["id"],
|
|
70
|
+
"country_code" => "",
|
|
71
|
+
"country_name" => "",
|
|
72
|
+
"page_path" => nil
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
instances_by_tool
|
|
77
|
+
end
|
|
72
78
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
# shared front-matter parser (class-level)
|
|
80
|
+
def self.extract_front_matter(file_string)
|
|
81
|
+
if file_string =~ /\A---\s*\n(.*?)\n---\s*\n/m
|
|
82
|
+
yaml = Regexp.last_match(1)
|
|
83
|
+
YAML.safe_load(yaml, permitted_classes: [Date, Time], aliases: true)
|
|
84
|
+
else
|
|
85
|
+
nil
|
|
86
|
+
end
|
|
87
|
+
rescue
|
|
88
|
+
nil
|
|
80
89
|
end
|
|
81
|
-
rescue
|
|
82
|
-
nil
|
|
83
|
-
end
|
|
84
90
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
tags = create_tags(tool, site)
|
|
90
|
-
%Q{<a
|
|
91
|
-
tabindex="0"
|
|
92
|
-
class="tool"
|
|
93
|
-
aria-description="#{html_escape(tool["description"])}"
|
|
94
|
-
data-bs-toggle="popover"
|
|
95
|
-
data-bs-placement="bottom"
|
|
96
|
-
data-bs-trigger="focus"
|
|
97
|
-
data-bs-content="<h5>#{html_escape(tool["name"])}</h5><div class='mb-2'>#{html_escape(tool["description"])}</div><div class='d-flex flex-wrap gap-1'>#{tags}</div>"
|
|
98
|
-
data-bs-template="<div class='popover popover-tool' role='tooltip'><div class='popover-arrow'></div><h3 class='popover-header'></h3><div class='popover-body'></div></div>"
|
|
99
|
-
data-bs-html="true"
|
|
100
|
-
><i class="fa-solid fa-wrench fa-sm me-2"></i>#{ html_escape(tool["name"]) }</a>}
|
|
101
|
-
end
|
|
91
|
+
# instance-level wrapper uses the shared index
|
|
92
|
+
def load_instances
|
|
93
|
+
@instances_by_tool = self.class.instances_index
|
|
94
|
+
end
|
|
102
95
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
96
|
+
def render(context)
|
|
97
|
+
site = context.registers[:site]
|
|
98
|
+
tool_id_from_liquid = context[@content.strip]
|
|
99
|
+
tool = find_tool(tool_id_from_liquid)
|
|
100
|
+
tags = create_tags(tool, site)
|
|
101
|
+
%Q{<a
|
|
102
|
+
tabindex="0"
|
|
103
|
+
class="tool"
|
|
104
|
+
aria-description="#{html_escape(tool["description"])}"
|
|
105
|
+
data-bs-toggle="popover"
|
|
106
|
+
data-bs-placement="bottom"
|
|
107
|
+
data-bs-trigger="focus"
|
|
108
|
+
data-bs-content="<h5>#{html_escape(tool["name"])}</h5><div class='mb-2'>#{html_escape(tool["description"])}</div><div class='d-flex flex-wrap gap-1'>#{tags}</div>"
|
|
109
|
+
data-bs-template="<div class='popover popover-tool' role='tooltip'><div class='popover-arrow'></div><h3 class='popover-header'></h3><div class='popover-body'></div></div>"
|
|
110
|
+
data-bs-html="true"
|
|
111
|
+
><i class="fa-solid fa-wrench fa-sm me-2"></i>#{ html_escape(tool["name"]) }</a>}
|
|
112
|
+
end
|
|
108
113
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
registry = tool["registry"]
|
|
114
|
-
tags << create_tag("https://bio.tools/#{registry["biotools"]}", "fa-info", "Tool info") if registry["biotools"] && registry["biotools"] != "NA"
|
|
115
|
-
tags << create_tag("https://fairsharing.org/FAIRsharing.#{registry["fairsharing"]}", "fa-database", "Standards/Databases") if registry["fairsharing"] && registry["fairsharing"] != "NA"
|
|
116
|
-
tags << create_tag("https://fairsharing.org/#{registry["fairsharing-coll"]}", "fa-database", "Standards/Databases") if registry["fairsharing-coll"] && registry["fairsharing-coll"] != "NA"
|
|
117
|
-
tags << create_tag("https://tess.elixir-europe.org/search?q=#{registry["tess"]}", "fa-graduation-cap", "Training") if registry["tess"] && registry["tess"] != "NA"
|
|
118
|
-
tags << create_tag("https://europepmc.org/article/MED/#{registry["europmc"]}", "fa-book", "Publication") if registry["europmc"] && registry["europmc"] != "NA"
|
|
114
|
+
def find_tool(tool_id)
|
|
115
|
+
tool = @tools.find { |t| t["id"] == tool_id.strip }
|
|
116
|
+
return tool if tool
|
|
117
|
+
raise Exception.new "Undefined tool ID: #{tool_id}"
|
|
119
118
|
end
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
def create_tags(tool, site)
|
|
121
|
+
tags = ""
|
|
122
|
+
tags << create_tag("#{tool["url"]}", "fa-link", "Website")
|
|
123
|
+
if tool["registry"]
|
|
124
|
+
registry = tool["registry"]
|
|
125
|
+
tags << create_tag("https://bio.tools/#{registry["biotools"]}", "fa-info", "Tool info") if registry["biotools"] && registry["biotools"] != "NA"
|
|
126
|
+
tags << create_tag("https://fairsharing.org/FAIRsharing.#{registry["fairsharing"]}", "fa-database", "Standards/Databases") if registry["fairsharing"] && registry["fairsharing"] != "NA"
|
|
127
|
+
tags << create_tag("https://fairsharing.org/#{registry["fairsharing-coll"]}", "fa-database", "Standards/Databases") if registry["fairsharing-coll"] && registry["fairsharing-coll"] != "NA"
|
|
128
|
+
tags << create_tag("https://tess.elixir-europe.org/search?q=#{registry["tess"]}", "fa-graduation-cap", "Training") if registry["tess"] && registry["tess"] != "NA"
|
|
129
|
+
tags << create_tag("https://europepmc.org/article/MED/#{registry["europmc"]}", "fa-book", "Publication") if registry["europmc"] && registry["europmc"] != "NA"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
instances = @instances_by_tool[tool["id"]]
|
|
133
|
+
tags << instances_dropdown(instances, site, tool["id"]) if instances && !instances.empty?
|
|
134
|
+
tags
|
|
135
|
+
end
|
|
125
136
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
137
|
+
def create_tag(url, icon, label)
|
|
138
|
+
"<a href='#{html_attr(url)}' target='_blank' rel='noopener'><span class='badge bg-dark text-white hover-primary'><i class='fa-solid #{icon} me-2'></i>#{html_escape(label)}</span></a>"
|
|
139
|
+
end
|
|
129
140
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
141
|
+
def instances_dropdown(instances, site, tool_id)
|
|
142
|
+
dd_id = "instances-dd-#{tool_id}-#{object_id}"
|
|
143
|
+
|
|
144
|
+
items = instances.map do |inst|
|
|
145
|
+
href = inst["url"] || resolve_page_url(inst["page_path"], site) || "#"
|
|
146
|
+
flag = inst["country_code"].to_s.strip.empty? ? "" : "<span class='flag-icon ms-2 shadow-sm flag-icon-#{inst["country_code"].downcase}'></span>"
|
|
147
|
+
name = html_escape(inst["name"])
|
|
148
|
+
url = html_attr(href)
|
|
149
|
+
"<li><a class='dropdown-item' href='#{url}' target='_blank' rel='noopener'>#{name} #{flag}</a></li>"
|
|
150
|
+
end.join
|
|
151
|
+
|
|
152
|
+
%Q{
|
|
153
|
+
<div class='dropdown d-inline-block'>
|
|
154
|
+
<button class='btn btn-badge btn-outline-primary dropdown-toggle'
|
|
155
|
+
type='button'
|
|
156
|
+
id='#{dd_id}'
|
|
157
|
+
data-bs-toggle='dropdown'
|
|
158
|
+
aria-expanded='false'>
|
|
159
|
+
<i class='fa-solid fa-globe me-2'></i>Instances
|
|
160
|
+
</button>
|
|
161
|
+
<ul class='dropdown-menu' aria-labelledby='#{dd_id}'>
|
|
162
|
+
#{items}
|
|
163
|
+
</ul>
|
|
164
|
+
</div>
|
|
165
|
+
}
|
|
166
|
+
end
|
|
156
167
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
168
|
+
# Resolve a site-relative URL from an absolute file path stored in page_path
|
|
169
|
+
def resolve_page_url(abs_path, site)
|
|
170
|
+
return nil unless abs_path && site
|
|
171
|
+
rel = abs_path.sub(%r{\A#{Regexp.escape(Dir.pwd)}/?}, "")
|
|
172
|
+
doc = (site.pages + site.collections.values.flat_map(&:docs)).find { |p| p.path == rel }
|
|
173
|
+
doc&.url
|
|
174
|
+
rescue
|
|
175
|
+
nil
|
|
176
|
+
end
|
|
166
177
|
|
|
167
|
-
|
|
178
|
+
# --- escaping helpers ---
|
|
168
179
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
180
|
+
def html_escape(s)
|
|
181
|
+
(s || "").to_s.gsub("&","&").gsub("<","<").gsub(">",">").gsub('"',""")
|
|
182
|
+
end
|
|
172
183
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
184
|
+
def html_attr(s)
|
|
185
|
+
html_escape(s).gsub("'","'")
|
|
186
|
+
end
|
|
176
187
|
end
|
|
177
188
|
end
|
|
178
189
|
Liquid::Template.register_tag("tool", Jekyll::Ett::ToolTag)
|