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: 34f25d1dcf2409c807016000b18943617c1c16311b69e93ca1270cdf7ea64ef4
4
- data.tar.gz: 60bc0906be8a455f57c82ed82b18ff5173c506c10ff6cf6e774a492d11b37e92
3
+ metadata.gz: 989e78f7e6995bb095549eb94361934f40c944b45c207f24820d91c518006280
4
+ data.tar.gz: ae7e2b72145732bcdcfc52cabb325eae06c1910a5de7fe2781b958184f93e318
5
5
  SHA512:
6
- metadata.gz: 0a4c3978c495d6c9d8c4236c086d0d8edc101ccf206ace362d129aadeaafe15756285a07cbfc8df7ca19afbb8cbafe43805c1e9316563acb1f19f3047da3f09a
7
- data.tar.gz: 88a77667e160b4049b564c63f95f24393b5332aa531395dd5fbefffb0808a7dbe3ec082e9206c6d7c2646f1fa90be4aa3104ff15f97858553ea3846b824d90a4
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
- def initialize(tagName, content, tokens)
8
- super
9
- @content = content
10
- load_tools
11
- load_instances
12
- end
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
- 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
- }
17
+ def load_tools
18
+ @tools = YAML.load(File.read(TOOLS_PATH))
52
19
  end
53
- end
54
20
 
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"
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
- # 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
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
- 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
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
- 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
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
- 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"
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
- instances = @instances_by_tool[tool["id"]]
122
- tags << instances_dropdown(instances, site, tool["id"]) if instances && !instances.empty?
123
- tags
124
- end
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
- 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
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
- def instances_dropdown(instances, site, tool_id)
131
- dd_id = "instances-dd-#{tool_id}-#{object_id}"
132
-
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
140
-
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
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
- # 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
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
- # --- escaping helpers ---
178
+ # --- escaping helpers ---
168
179
 
169
- def html_escape(s)
170
- (s || "").to_s.gsub("&","&amp;").gsub("<","&lt;").gsub(">","&gt;").gsub('"',"&quot;")
171
- end
180
+ def html_escape(s)
181
+ (s || "").to_s.gsub("&","&amp;").gsub("<","&lt;").gsub(">","&gt;").gsub('"',"&quot;")
182
+ end
172
183
 
173
- def html_attr(s)
174
- html_escape(s).gsub("'","&#39;")
175
- end
184
+ def html_attr(s)
185
+ html_escape(s).gsub("'","&#39;")
186
+ end
176
187
  end
177
188
  end
178
189
  Liquid::Template.register_tag("tool", Jekyll::Ett::ToolTag)
@@ -1,5 +1,5 @@
1
1
  module Jekyll
2
2
  class Ett
3
- VERSION = '1.0.0'
3
+ VERSION = '1.1.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elixir-toolkit-theme-plugins
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - bedroesb