Class: Unmagic::Icon::Web
- Inherits:
-
Object
- Object
- Unmagic::Icon::Web
- Defined in:
- lib/unmagic/icon/web.rb
Constant Summary collapse
- ALL_LIBRARIES =
The library param value that means “show icons from every library”.
"all"- PAGE_SIZE =
How many icons to send per page (initial render and each “load more”).
100
Class Method Summary collapse
Instance Method Summary collapse
-
#asset_url(path) ⇒ Object
Build a static asset URL, honouring any SCRIPT_NAME mount prefix.
- #call(env) ⇒ Object
- #escape(text) ⇒ Object
-
#filter_icons(icons, query) ⇒ Object
Case-insensitive substring match on the icon name.
- #fragment_request? ⇒ Boolean
-
#fragment_response ⇒ Object
The page of icons as a rendered HTML fragment, which the browser appends (“load more”) or swaps in (live search).
-
#library_url(library_name) ⇒ Object
Build a URL to the gallery selecting the given library, carrying the current search query along.
-
#render_icons(icons) ⇒ Object
Render the shared icons partial for a list of icons.
Class Method Details
.app ⇒ Object
17 18 19 20 21 22 23 |
# File 'lib/unmagic/icon/web.rb', line 17 def self.app @app ||= Rack::Builder.new do public_path = File.("web/public", __dir__) use Rack::Static, urls: [ "/public" ], root: File.dirname(public_path) run Unmagic::Icon::Web.new end.to_app end |
.call(env) ⇒ Object
13 14 15 |
# File 'lib/unmagic/icon/web.rb', line 13 def self.call(env) app.call(env) end |
Instance Method Details
#asset_url(path) ⇒ Object
Build a static asset URL, honouring any SCRIPT_NAME mount prefix.
118 119 120 |
# File 'lib/unmagic/icon/web.rb', line 118 def asset_url(path) [ @request.env["SCRIPT_NAME"], path ].join.gsub(%r{/+}, "/") end |
#call(env) ⇒ Object
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 |
# File 'lib/unmagic/icon/web.rb', line 31 def call(env) @request = Rack::Request.new(env) @libraries = Unmagic::Icon::Library::Registry.all @search_query = @request.params["search"].to_s @offset = @request.params["offset"].to_i @offset = 0 if @offset.negative? library_param = @request.params["library"].to_s # No `library` param (a fresh page load) defaults to "All". if library_param.empty? || library_param == ALL_LIBRARIES @selected_library = nil @selected_param = ALL_LIBRARIES candidates = @libraries.flat_map(&:icons) else begin @selected_library = Unmagic::Icon::Library::Registry.find(library_param) rescue Unmagic::Icon::LibraryNotFoundError return [ 404, { "content-type" => "text/plain" }, [ "Library not found: #{library_param}" ] ] end @selected_param = @selected_library.name candidates = @selected_library.icons end # Search and paginate on the server; only the page's icons get their svg # read+serialized, so we never inline the whole (possibly huge) set. filtered = filter_icons(candidates, @search_query) @total = filtered.length @page_icons = filtered[@offset, PAGE_SIZE] || [] return fragment_response if fragment_request? template_path = File.("web/views/layout.html.erb", __dir__) template = ERB.new(File.read(template_path)) html = template.result(binding) [ 200, { "content-type" => "text/html; charset=utf-8" }, [ html ] ] end |
#escape(text) ⇒ Object
70 71 72 |
# File 'lib/unmagic/icon/web.rb', line 70 def escape(text) CGI.escapeHTML(text.to_s) end |
#filter_icons(icons, query) ⇒ Object
Case-insensitive substring match on the icon name.
75 76 77 78 79 80 |
# File 'lib/unmagic/icon/web.rb', line 75 def filter_icons(icons, query) return icons if query.empty? needle = query.downcase icons.select { |icon| icon.name.downcase.include?(needle) } end |
#fragment_request? ⇒ Boolean
82 83 84 |
# File 'lib/unmagic/icon/web.rb', line 82 def fragment_request? @request.params["format"] == "fragment" end |
#fragment_response ⇒ Object
The page of icons as a rendered HTML fragment, which the browser appends (“load more”) or swaps in (live search). Counts ride along as headers so the body stays pure markup. Icons are rendered in exactly one place —the ‘icons` partial, shared with the full page.
90 91 92 93 94 95 96 97 98 99 |
# File 'lib/unmagic/icon/web.rb', line 90 def fragment_response headers = { "content-type" => "text/html; charset=utf-8", "x-total-count" => @total.to_s, "x-offset" => @offset.to_s, "x-page-size" => PAGE_SIZE.to_s } [ 200, headers, [ render_icons(@page_icons) ] ] end |
#library_url(library_name) ⇒ Object
Build a URL to the gallery selecting the given library, carrying the current search query along. ‘library_name` of nil selects “All”.
111 112 113 114 115 |
# File 'lib/unmagic/icon/web.rb', line 111 def library_url(library_name) params = { "library" => library_name || ALL_LIBRARIES } params["search"] = @search_query unless @search_query.empty? url(params) end |
#render_icons(icons) ⇒ Object
Render the shared icons partial for a list of icons. ‘-%>` trim keeps the output empty (not whitespace) when there are no icons, so the browser can detect “no results”.
104 105 106 107 |
# File 'lib/unmagic/icon/web.rb', line 104 def render_icons(icons) template_path = File.("web/views/icons.html.erb", __dir__) ERB.new(File.read(template_path), trim_mode: "-").result(binding) end |