Skip to content

Commit a9fa0d5

Browse files
committed
Refactor
1 parent b57d60e commit a9fa0d5

File tree

3 files changed

+153
-116
lines changed

3 files changed

+153
-116
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
defmodule ComponentsGuide.Research.Source do
2+
@cache_name :research_spec_cache
3+
4+
defp read_cache(key) do
5+
tuple = {:ok, value} = Cachex.get(@cache_name, key)
6+
IO.puts("reading #{if value == nil, do: "nil", else: "present"}")
7+
IO.inspect(key)
8+
tuple
9+
# {:ok, nil}
10+
end
11+
12+
defp write_cache(key, value) do
13+
Cachex.put(@cache_name, key, value)
14+
end
15+
16+
defmodule Fetch do
17+
defstruct done: false, request_ref: nil, body_list: [], status: nil, headers: []
18+
19+
defp apply_response({:status, _request_ref, status_code}, state = %Fetch{}) do
20+
%{state | status: status_code}
21+
end
22+
23+
defp apply_response({:headers, _request_ref, headers}, state = %Fetch{}) do
24+
%{state | headers: headers}
25+
end
26+
27+
defp apply_response({:data, _request_ref, chunk}, state = %Fetch{body_list: body_list}) do
28+
%{state | body_list: [body_list | [chunk]]}
29+
end
30+
31+
defp apply_response({:done, _request_ref}, state = %Fetch{}) do
32+
%{state | done: true}
33+
end
34+
35+
defp receive_mint_response(state = %Fetch{}, conn, request_ref) do
36+
receive do
37+
message ->
38+
case Mint.HTTP.stream(conn, message) do
39+
:unknown ->
40+
receive_mint_response(state, conn, request_ref)
41+
42+
{:error, _, e, _} ->
43+
{:error, e}
44+
45+
{:ok, conn, responses} ->
46+
state = Enum.reduce(responses, state, &apply_response/2)
47+
48+
if state.done do
49+
{:ok, IO.iodata_to_binary(state.body_list)}
50+
else
51+
receive_mint_response(state, conn, request_ref)
52+
end
53+
end
54+
end
55+
end
56+
57+
def get(url) do
58+
uri = URI.parse(url)
59+
60+
IO.puts("fetching URL #{uri} #{uri.host} #{uri.path}")
61+
{:ok, conn} = Mint.HTTP.connect(:https, uri.host, 443)
62+
{:ok, conn, request_ref} = Mint.HTTP.request(conn, "GET", uri.path, [], nil)
63+
64+
receive_mint_response(%Fetch{}, conn, request_ref)
65+
end
66+
end
67+
68+
defp body({:fetch, url}) do
69+
IO.puts("fetching URL #{url}")
70+
# with {:ok, response} <- HTTPClient.get(url) do
71+
# html = response.body
72+
# {:ok, html}
73+
# end
74+
75+
Fetch.get(url)
76+
77+
# {:ok, response} = Mojito.request(method: :get, url: url, timeout: 50000)
78+
# {:ok, response.body}
79+
end
80+
81+
defp body({:html_document, url}) do
82+
{:ok, html} = read({:fetch, url})
83+
tuple = {:ok, _document} = Floki.parse_document(html)
84+
tuple
85+
end
86+
87+
defp body({:fetch_json, url}) do
88+
{:ok, encoded} = read({:fetch, url})
89+
tuple = {:ok, data} = Jason.decode(encoded)
90+
tuple
91+
end
92+
93+
defp run(key) do
94+
tuple = {:ok, value} = body(key)
95+
write_cache(key, value)
96+
tuple
97+
end
98+
99+
defp read(key) do
100+
case read_cache(key) do
101+
{:ok, nil} ->
102+
run(key)
103+
104+
{:ok, value} ->
105+
{:ok, value}
106+
107+
other ->
108+
other
109+
end
110+
end
111+
112+
def html_document_at(url), do: read({:html_document, url})
113+
def json_at(url), do: read({:fetch_json, url})
114+
115+
def clear_cache() do
116+
Cachex.clear(@cache_name)
117+
end
118+
end
Lines changed: 20 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,27 @@
11
defmodule ComponentsGuide.Research.Spec do
2-
alias ComponentsGuide.HTTPClient
3-
4-
@cache_name :research_spec_cache
5-
6-
defp read_cache(key) do
7-
tuple = {:ok, value} = Cachex.get(@cache_name, key)
8-
IO.puts("reading #{if value == nil, do: "nil", else: "present"}")
9-
IO.inspect(key)
10-
tuple
11-
# {:ok, nil}
12-
end
13-
14-
defp write_cache(key, value) do
15-
Cachex.put(@cache_name, key, value)
16-
end
17-
18-
defmodule Fetch do
19-
defstruct done: false, request_ref: nil, body_list: [], status: nil, headers: []
20-
21-
defp apply_response({:status, _request_ref, status_code}, state = %Fetch{}) do
22-
%{state | status: status_code}
2+
alias ComponentsGuide.Research.Source
3+
4+
def search_for(:caniuse, query) when is_binary(query) do
5+
url = "https://cdn.jsdelivr.net/npm/caniuse-db@1.0.30001042/data.json"
6+
{:ok, data} = Source.json_at(url)
7+
table = data["data"]
8+
if false do
9+
keys = Map.keys(table)
10+
inspect(keys)
11+
else
12+
table["documenthead"] |> inspect()
2313
end
24-
25-
defp apply_response({:headers, _request_ref, headers}, state = %Fetch{}) do
26-
%{state | headers: headers}
27-
end
28-
29-
defp apply_response({:data, _request_ref, chunk}, state = %Fetch{body_list: body_list}) do
30-
%{state | body_list: [body_list | [chunk]]}
31-
end
32-
33-
defp apply_response({:done, _request_ref}, state = %Fetch{}) do
34-
%{state | done: true}
35-
end
36-
37-
defp receive_mint_response(state = %Fetch{}, conn, request_ref) do
38-
receive do
39-
message ->
40-
case Mint.HTTP.stream(conn, message) do
41-
:unknown ->
42-
receive_mint_response(state, conn, request_ref)
43-
44-
{:error, _, e, _} ->
45-
{:error, e}
46-
47-
{:ok, conn, responses} ->
48-
state = Enum.reduce(responses, state, &apply_response/2)
49-
50-
if state.done do
51-
{:ok, IO.iodata_to_binary(state.body_list)}
52-
else
53-
receive_mint_response(state, conn, request_ref)
54-
end
55-
end
56-
end
57-
end
58-
59-
def get(url) do
60-
uri = URI.parse(url)
61-
62-
IO.puts("fetching URL #{uri} #{uri.host} #{uri.path}")
63-
{:ok, conn} = Mint.HTTP.connect(:https, uri.host, 443)
64-
{:ok, conn, request_ref} = Mint.HTTP.request(conn, "GET", uri.path, [], nil)
65-
66-
receive_mint_response(%Fetch{}, conn, request_ref)
67-
end
68-
end
69-
70-
defp body({:fetch, url}) do
71-
IO.puts("fetching URL #{url}")
72-
# with {:ok, response} <- HTTPClient.get(url) do
73-
# html = response.body
74-
# {:ok, html}
75-
# end
76-
77-
Fetch.get(url)
78-
79-
# {:ok, response} = Mojito.request(method: :get, url: url, timeout: 50000)
80-
# {:ok, response.body}
81-
end
82-
83-
defp body({:html_document, url}) do
84-
{:ok, html} = read({:fetch, url})
85-
IO.puts("html length #{length(html)}")
86-
tuple = {:ok, _document} = Floki.parse_document(html)
87-
tuple
88-
end
89-
90-
defp run(key) do
91-
tuple = {:ok, value} = body(key)
92-
write_cache(key, value)
93-
tuple
94-
end
95-
96-
defp read(key) do
97-
case read_cache(key) do
98-
{:ok, nil} ->
99-
run(key)
100-
101-
{:ok, value} ->
102-
{:ok, value}
103-
104-
other ->
105-
other
106-
end
107-
end
108-
109-
def clear_search_cache() do
110-
Cachex.clear(@cache_name)
11114
end
11215

11316
def search_for(:whatwg_html_spec, query) when is_binary(query) do
11417
IO.puts("searching whatwg html spec")
11518

116-
url = "https://html.spec.whatwg.org/"
19+
# url = "https://html.spec.whatwg.org/"
11720
url = "https://html.spec.whatwg.org/dev/"
11821

119-
{:ok, html} = body({:fetch, url})
120-
# {:ok, document} = read({:html_document, "https://html.spec.whatwg.org/"})
22+
# {:ok, html} = body({:fetch, url})
23+
# {:ok, html} = read({:fetch, url})
24+
{:ok, document} = Source.html_document_at(url)
12125

12226
# IO.puts("document size #{:erts_debug.flat_size(document)}")
12327

@@ -126,10 +30,11 @@ defmodule ComponentsGuide.Research.Spec do
12630
# result = Meeseeks.one(document, selector)
12731
# Meeseeks.html(result)
12832

129-
# document
130-
# |> Floki.find("#contents")
131-
# |> Floki.raw_html()
33+
document
34+
|> Floki.find("body")
35+
|> Floki.find("a:fl-contains('form')")
36+
|> Floki.raw_html()
13237

133-
html
38+
# html
13439
end
13540
end

apps/components_guide_web/lib/components_guide_web/controllers/research_controller.ex

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
defmodule ComponentsGuideWeb.ResearchController do
22
use ComponentsGuideWeb, :controller
3+
use Phoenix.HTML
34

45
alias ComponentsGuide.Research.Spec
56

@@ -20,8 +21,21 @@ defmodule ComponentsGuideWeb.ResearchController do
2021
index(conn, %{"q" => ""})
2122
end
2223

24+
defp h2(text) do
25+
content_tag(:h2, text, class: "font-bold")
26+
end
27+
2328
defp load_results(query) when is_binary(query) do
2429
# Spec.clear_search_cache()
25-
Spec.search_for(:whatwg_html_spec, query)
30+
[
31+
content_tag(:article, [
32+
h2("HTML spec"),
33+
Spec.search_for(:whatwg_html_spec, query)
34+
]),
35+
content_tag(:article, [
36+
h2("Can I Use"),
37+
Spec.search_for(:caniuse, query)
38+
])
39+
]
2640
end
2741
end

0 commit comments

Comments
 (0)