elixir-toolkit-theme-plugins 0.1.9 → 1.0.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 +4 -4
- data/.github/workflows/release.yml +6 -4
- data/elixir-toolkit-theme-plugins.gemspec +1 -1
- data/lib/elixir-toolkit-theme-plugins/tool_table_filter.rb +19 -11
- data/lib/elixir-toolkit-theme-plugins/tool_tag.rb +155 -53
- data/lib/elixir-toolkit-theme-plugins/version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 34f25d1dcf2409c807016000b18943617c1c16311b69e93ca1270cdf7ea64ef4
|
|
4
|
+
data.tar.gz: 60bc0906be8a455f57c82ed82b18ff5173c506c10ff6cf6e774a492d11b37e92
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0a4c3978c495d6c9d8c4236c086d0d8edc101ccf206ace362d129aadeaafe15756285a07cbfc8df7ca19afbb8cbafe43805c1e9316563acb1f19f3047da3f09a
|
|
7
|
+
data.tar.gz: 88a77667e160b4049b564c63f95f24393b5332aa531395dd5fbefffb0808a7dbe3ec082e9206c6d7c2646f1fa90be4aa3104ff15f97858553ea3846b824d90a4
|
|
@@ -11,11 +11,13 @@ jobs:
|
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
|
|
13
13
|
steps:
|
|
14
|
-
- uses: actions/checkout@
|
|
15
|
-
- name: Set up Ruby 3.
|
|
16
|
-
uses:
|
|
14
|
+
- uses: actions/checkout@v5
|
|
15
|
+
- name: Set up Ruby 3.3
|
|
16
|
+
uses: ruby/setup-ruby@v1.204.0
|
|
17
17
|
with:
|
|
18
|
-
ruby-version: 3.
|
|
18
|
+
ruby-version: '3.3'
|
|
19
|
+
bundler-cache: true
|
|
20
|
+
cache-version: 0
|
|
19
21
|
|
|
20
22
|
- name: Publish to GPR
|
|
21
23
|
run: |
|
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.name = "elixir-toolkit-theme-plugins"
|
|
10
10
|
spec.version = Jekyll::Ett::VERSION.dup
|
|
11
11
|
spec.authors = ["bedroesb", "janslifka", "MarekSuchanek"]
|
|
12
|
-
spec.email = ["
|
|
12
|
+
spec.email = ["bert.droesbeke@vib.be\n"]
|
|
13
13
|
|
|
14
14
|
spec.summary = "Plugins to work together with ELIXIR Toolkit theme"
|
|
15
15
|
spec.homepage = "https://elixir-belgium.github.io/elixir-toolkit-theme-plugins/"
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
require "jekyll"
|
|
2
|
-
|
|
2
|
+
require "set"
|
|
3
3
|
|
|
4
4
|
module Jekyll
|
|
5
5
|
class Ett
|
|
6
6
|
module ToolTableFilter
|
|
7
7
|
def add_related_pages(data)
|
|
8
|
+
return [] if data.nil?
|
|
9
|
+
return data unless data.is_a?(Array)
|
|
10
|
+
|
|
8
11
|
load_page_data
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
data.each do |tool|
|
|
14
|
+
next unless tool.is_a?(Hash)
|
|
15
|
+
|
|
16
|
+
if tool["id"] && @related_pages[tool["id"]]
|
|
17
|
+
tool["related_pages"] = @related_pages[tool["id"]].to_a
|
|
13
18
|
end
|
|
14
19
|
end
|
|
15
20
|
|
|
@@ -21,20 +26,23 @@ module Jekyll
|
|
|
21
26
|
def load_page_data
|
|
22
27
|
@related_pages = {}
|
|
23
28
|
pages_path = File.join(Dir.pwd, "**", "*.md")
|
|
29
|
+
|
|
24
30
|
Dir.glob(pages_path).each do |f|
|
|
25
31
|
file = File.read(f)
|
|
26
32
|
page_id_matches = file.match(/page_id:\s*(\w+)/)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
next unless page_id_matches
|
|
35
|
+
|
|
36
|
+
page_id = page_id_matches[1]
|
|
37
|
+
|
|
38
|
+
file.scan(/\{%\s*tool\s*"([^"]+)"\s*%}/).flatten.each do |m|
|
|
39
|
+
@related_pages[m] ||= Set.new
|
|
40
|
+
@related_pages[m].add(page_id)
|
|
34
41
|
end
|
|
35
42
|
end
|
|
36
43
|
end
|
|
37
44
|
end
|
|
38
45
|
end
|
|
46
|
+
|
|
39
47
|
Liquid::Template.register_filter(Jekyll::Ett::ToolTableFilter)
|
|
40
48
|
end
|
|
@@ -1,76 +1,178 @@
|
|
|
1
1
|
require "jekyll"
|
|
2
|
-
|
|
2
|
+
require "yaml"
|
|
3
3
|
|
|
4
4
|
module Jekyll
|
|
5
5
|
class Ett
|
|
6
6
|
class ToolTag < Liquid::Tag
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
def initialize(tagName, content, tokens)
|
|
8
|
+
super
|
|
9
|
+
@content = content
|
|
10
|
+
load_tools
|
|
11
|
+
load_instances
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def load_tools
|
|
15
|
+
tools_path = File.join(Dir.pwd, "_data", "tool_and_resource_list.yml")
|
|
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
|
+
}
|
|
11
52
|
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# --- 2) instances from tool_and_resource_list.yml itself ---
|
|
56
|
+
(@tools || []).each do |tool|
|
|
57
|
+
parent_id = tool["instance_of"]
|
|
58
|
+
next if parent_id.nil? || parent_id == "NA"
|
|
12
59
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
+
}
|
|
16
69
|
end
|
|
70
|
+
end
|
|
71
|
+
|
|
17
72
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
data-bs-toggle="popover"
|
|
26
|
-
data-bs-placement="bottom"
|
|
27
|
-
data-bs-trigger="focus"
|
|
28
|
-
data-bs-content="<h5>#{tool["name"]}</h5><div class='mb-2'>#{tool["description"]}</div>#{tags}"
|
|
29
|
-
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>"
|
|
30
|
-
data-bs-html="true"
|
|
31
|
-
><i class="fa-solid fa-wrench fa-sm me-2"></i>#{ tool["name"] }</a>}
|
|
73
|
+
# Accepts a file string, returns parsed YAML front matter hash or nil
|
|
74
|
+
def extract_front_matter(file_string)
|
|
75
|
+
if file_string =~ /\A---\s*\n(.*?)\n---\s*\n/m
|
|
76
|
+
yaml = Regexp.last_match(1)
|
|
77
|
+
YAML.safe_load(yaml, permitted_classes: [Date, Time], aliases: true)
|
|
78
|
+
else
|
|
79
|
+
nil
|
|
32
80
|
end
|
|
81
|
+
rescue
|
|
82
|
+
nil
|
|
83
|
+
end
|
|
33
84
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
85
|
+
def render(context)
|
|
86
|
+
site = context.registers[:site]
|
|
87
|
+
tool_id_from_liquid = context[@content.strip]
|
|
88
|
+
tool = find_tool(tool_id_from_liquid)
|
|
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
|
|
102
|
+
|
|
103
|
+
def find_tool(tool_id)
|
|
104
|
+
tool = @tools.find { |t| t["id"] == tool_id.strip }
|
|
105
|
+
return tool if tool
|
|
106
|
+
raise Exception.new "Undefined tool ID: #{tool_id}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def create_tags(tool, site)
|
|
110
|
+
tags = ""
|
|
111
|
+
tags << create_tag("#{tool["url"]}", "fa-link", "Website")
|
|
112
|
+
if tool["registry"]
|
|
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"
|
|
39
119
|
end
|
|
40
120
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
registry = tool["registry"]
|
|
121
|
+
instances = @instances_by_tool[tool["id"]]
|
|
122
|
+
tags << instances_dropdown(instances, site, tool["id"]) if instances && !instances.empty?
|
|
123
|
+
tags
|
|
124
|
+
end
|
|
46
125
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
126
|
+
def create_tag(url, icon, label)
|
|
127
|
+
"<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>"
|
|
128
|
+
end
|
|
50
129
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
end
|
|
130
|
+
def instances_dropdown(instances, site, tool_id)
|
|
131
|
+
dd_id = "instances-dd-#{tool_id}-#{object_id}"
|
|
54
132
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
133
|
+
items = instances.map do |inst|
|
|
134
|
+
href = inst["url"] || resolve_page_url(inst["page_path"], site) || "#"
|
|
135
|
+
flag = inst["country_code"].to_s.strip.empty? ? "" : "<span class='flag-icon ms-2 shadow-sm flag-icon-#{inst["country_code"].downcase}'></span>"
|
|
136
|
+
name = html_escape(inst["name"])
|
|
137
|
+
url = html_attr(href)
|
|
138
|
+
"<li><a class='dropdown-item' href='#{url}' target='_blank' rel='noopener'>#{name} #{flag}</a></li>"
|
|
139
|
+
end.join
|
|
58
140
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
141
|
+
%Q{
|
|
142
|
+
<div class='dropdown d-inline-block'>
|
|
143
|
+
<button class='btn btn-badge btn-outline-primary dropdown-toggle'
|
|
144
|
+
type='button'
|
|
145
|
+
id='#{dd_id}'
|
|
146
|
+
data-bs-toggle='dropdown'
|
|
147
|
+
aria-expanded='false'>
|
|
148
|
+
<i class='fa-solid fa-globe me-2'></i>Instances
|
|
149
|
+
</button>
|
|
150
|
+
<ul class='dropdown-menu' aria-labelledby='#{dd_id}'>
|
|
151
|
+
#{items}
|
|
152
|
+
</ul>
|
|
153
|
+
</div>
|
|
154
|
+
}
|
|
155
|
+
end
|
|
62
156
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
157
|
+
# Resolve a site-relative URL from an absolute file path stored in page_path
|
|
158
|
+
def resolve_page_url(abs_path, site)
|
|
159
|
+
return nil unless abs_path && site
|
|
160
|
+
rel = abs_path.sub(%r{\A#{Regexp.escape(Dir.pwd)}/?}, "")
|
|
161
|
+
doc = (site.pages + site.collections.values.flat_map(&:docs)).find { |p| p.path == rel }
|
|
162
|
+
doc&.url
|
|
163
|
+
rescue
|
|
164
|
+
nil
|
|
165
|
+
end
|
|
66
166
|
|
|
67
|
-
|
|
68
|
-
tags
|
|
69
|
-
end
|
|
167
|
+
# --- escaping helpers ---
|
|
70
168
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
169
|
+
def html_escape(s)
|
|
170
|
+
(s || "").to_s.gsub("&","&").gsub("<","<").gsub(">",">").gsub('"',""")
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def html_attr(s)
|
|
174
|
+
html_escape(s).gsub("'","'")
|
|
175
|
+
end
|
|
74
176
|
end
|
|
75
177
|
end
|
|
76
178
|
Liquid::Template.register_tag("tool", Jekyll::Ett::ToolTag)
|
metadata
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: elixir-toolkit-theme-plugins
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- bedroesb
|
|
8
8
|
- janslifka
|
|
9
9
|
- MarekSuchanek
|
|
10
|
-
autorequire:
|
|
10
|
+
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date:
|
|
13
|
+
date: 2025-12-07 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: jekyll
|
|
@@ -46,9 +46,9 @@ dependencies:
|
|
|
46
46
|
- - "~>"
|
|
47
47
|
- !ruby/object:Gem::Version
|
|
48
48
|
version: '12.0'
|
|
49
|
-
description:
|
|
49
|
+
description:
|
|
50
50
|
email:
|
|
51
|
-
- '
|
|
51
|
+
- 'bert.droesbeke@vib.be
|
|
52
52
|
|
|
53
53
|
'
|
|
54
54
|
executables: []
|
|
@@ -69,7 +69,7 @@ homepage: https://elixir-belgium.github.io/elixir-toolkit-theme-plugins/
|
|
|
69
69
|
licenses:
|
|
70
70
|
- MIT
|
|
71
71
|
metadata: {}
|
|
72
|
-
post_install_message:
|
|
72
|
+
post_install_message:
|
|
73
73
|
rdoc_options: []
|
|
74
74
|
require_paths:
|
|
75
75
|
- lib
|
|
@@ -84,8 +84,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
84
84
|
- !ruby/object:Gem::Version
|
|
85
85
|
version: '0'
|
|
86
86
|
requirements: []
|
|
87
|
-
rubygems_version: 3.
|
|
88
|
-
signing_key:
|
|
87
|
+
rubygems_version: 3.5.22
|
|
88
|
+
signing_key:
|
|
89
89
|
specification_version: 4
|
|
90
90
|
summary: Plugins to work together with ELIXIR Toolkit theme
|
|
91
91
|
test_files: []
|