├── .formatter.exs
├── .gitignore
├── LICENSE.md
├── README.md
├── config
└── config.exs
├── lib
└── open_graph.ex
├── mix.exs
├── mix.lock
└── test
├── fixtures
├── github.html
└── nature.html
├── open_graph_test.exs
└── test_helper.exs
/.formatter.exs:
--------------------------------------------------------------------------------
1 | # Used by "mix format"
2 | [
3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
4 | ]
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # The directory Mix will write compiled artifacts to.
2 | /_build/
3 |
4 | # If you run "mix test --cover", coverage assets end up here.
5 | /cover/
6 |
7 | # The directory Mix downloads your dependencies sources to.
8 | /deps/
9 |
10 | # Where third-party dependencies like ExDoc output generated docs.
11 | /doc/
12 |
13 | # Ignore .fetch files in case you like to edit your project deps locally.
14 | /.fetch
15 |
16 | # If the VM crashes, it generates a dump, let's ignore it too.
17 | erl_crash.dump
18 |
19 | # Also ignore archive artifacts (built via "mix archive.build").
20 | *.ez
21 |
22 | # Ignore package tarball (built via "mix hex.build").
23 | open_graph-*.tar
24 |
25 | # Temporary files, for example, from tests.
26 | /tmp/
27 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # The MIT License
2 |
3 | Copyright (c) 2016 Andriel Nuernberg
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenGraph
2 |
3 | [](https://hex.pm/packages/open_graph)
4 | [](https://hexdocs.pm/open_graph/)
5 | [](https://hex.pm/packages/open_graph)
6 | [](https://github.com/andrielfn/open_graph/blob/master/LICENSE.md)
7 | [](https://github.com/andrielfn/open_graph/commits/master)
8 |
9 | A Elixir wrapper for the [Open Graph protocol](http://ogp.me).
10 |
11 | ## Installation
12 |
13 | The package can be installed as:
14 |
15 | Add `:open_graph` to your list of dependencies in `mix.exs`:
16 |
17 | ```elixir
18 | def deps do
19 | [
20 | {:open_graph, "~> 0.0.5"}
21 | ]
22 | end
23 | ```
24 |
25 | Ensure `:open_graph` is started before your application:
26 |
27 | ```elixir
28 | def application do
29 | [applications: [:open_graph]]
30 | end
31 | ```
32 |
33 | ## Usage
34 |
35 | ```elixir
36 | iex> OpenGraph.fetch("https://github.com")
37 |
38 | {:ok,
39 | %OpenGraph{description: "GitHub is where people build software. More than 15 million...",
40 | image: "https://assets-cdn.github.com/images/modules/open_graph/github-octocat.png",
41 | site_name: "GitHub", title: "Build software better, together", type: nil,
42 | url: "https://github.com"}}
43 | ```
44 |
45 | You can also parse raw HTML:
46 |
47 | ```elixir
48 | iex> OpenGraph.parse(" ")
49 |
50 | %OpenGraph{description: nil, image: nil, site_name: nil, title: "Some title",
51 | type: nil, url: nil}
52 | ```
53 |
54 | ## Copyright and License
55 |
56 | Copyright (c) 2016 Andriel Nuernberg
57 |
58 | This work is free. You can redistribute it and/or modify it under the
59 | terms of the MIT License. See the [LICENSE.md](./LICENSE.md) file for more details.
60 |
--------------------------------------------------------------------------------
/config/config.exs:
--------------------------------------------------------------------------------
1 | # This file is responsible for configuring your application
2 | # and its dependencies with the aid of the Mix.Config module.
3 | import Config
4 |
5 | # This configuration is loaded before any dependency and is restricted
6 | # to this project. If another project depends on this project, this
7 | # file won't be loaded nor affect the parent project. For this reason,
8 | # if you want to provide default values for your application for
9 | # 3rd-party users, it should be done in your "mix.exs" file.
10 |
11 | # You can configure for your application as:
12 | #
13 | # config :open_graph, key: :value
14 | #
15 | # And access this configuration in your application as:
16 | #
17 | # Application.get_env(:open_graph, :key)
18 | #
19 | # Or configure a 3rd-party app:
20 | #
21 | # config :logger, level: :info
22 | #
23 |
24 | # It is also possible to import configuration files, relative to this
25 | # directory. For example, you can emulate configuration per environment
26 | # by uncommenting the line below and defining dev.exs, test.exs and such.
27 | # Configuration from the imported file will override the ones defined
28 | # here (which is why it is important to import them last).
29 | #
30 | # import_config "#{Mix.env}.exs"
31 |
--------------------------------------------------------------------------------
/lib/open_graph.ex:
--------------------------------------------------------------------------------
1 | defmodule OpenGraph do
2 | @moduledoc """
3 | Fetch and parse websites to extract Open Graph meta tags.
4 |
5 | The example above shows how to fetch the GitHub Open Graph rich objects.
6 |
7 | iex> OpenGraph.fetch("https://github.com")
8 | {:ok, %OpenGraph{description: "GitHub is where people build software. More than 15 million...",
9 | image: "https://assets-cdn.github.com/images/modules/open_graph/github-octocat.png",
10 | site_name: "GitHub", title: "Build software better, together", type: nil,
11 | url: "https://github.com"}}
12 | """
13 |
14 | @metatag_regex ~r/<\s*meta\s(?=[^>]*?\bproperty\s*=\s*(?|"\s*([^"]*?)\s*"|'\s*([^']*?)\s*'|([^"'>]*?)(?=\s*\/?\s*>|\s\w+\s*=)))[^>]*?\bcontent\s*=\s*(?|"\s*([^"]*?)\s*"|'\s*([^']*?)\s*'|([^"'>]*?)(?=\s*\/?\s*>|\s\w+\s*=))[^>]*>/
15 |
16 | defstruct [:title, :type, :image, :url, :description, :site_name]
17 |
18 | @doc """
19 | Fetches the raw HTML for the given website URL.
20 |
21 | Args:
22 | * `url` - target URL as a binary string or char list
23 |
24 | This functions returns `{:ok, %OpenGraph{...}}` if the request is successful,
25 | `{:error, reason}` otherwise.
26 | """
27 | def fetch(url) do
28 | case HTTPoison.get(url, [],
29 | ssl: [{:versions, [:"tlsv1.2"]}],
30 | follow_redirect: true,
31 | hackney: [{:force_redirect, true}]
32 | ) do
33 | {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
34 | {:ok, OpenGraph.parse(body)}
35 |
36 | {:ok, %HTTPoison.Response{status_code: 502}} ->
37 | {:error, "Bad Gateway"}
38 |
39 | {:ok, %HTTPoison.Response{status_code: 404}} ->
40 | {:error, "Not found :("}
41 |
42 | {:ok, %HTTPoison.Response{status_code: 505}} ->
43 | {:error, "Error from HTTPoison, status code: 505"}
44 |
45 | {:ok, %HTTPoison.Response{status_code: status_code}} ->
46 | {:error, "Error from HTTPoison, status code: #{status_code}"}
47 |
48 | {:error, %HTTPoison.Error{reason: reason}} ->
49 | {:error, reason}
50 | end
51 | end
52 |
53 | @doc """
54 | Parses the given HTML to extract the Open Graph objects.
55 |
56 | Args:
57 | * `html` - raw HTML as a binary string or char list
58 |
59 | This functions returns an OpenGraph struct.
60 | """
61 | def parse(html) do
62 | map =
63 | @metatag_regex
64 | |> Regex.scan(html, capture: :all_but_first)
65 | |> Enum.filter(&filter_og_metatags(&1))
66 | |> Enum.map(&drop_og_prefix(&1))
67 | |> Enum.into(%{}, fn [k, v] -> {k, v} end)
68 | |> Enum.map(fn {key, value} -> {String.to_atom(key), value} end)
69 |
70 | struct(OpenGraph, map)
71 | end
72 |
73 | defp filter_og_metatags(["og:" <> _property, _content]), do: true
74 | defp filter_og_metatags(_), do: false
75 |
76 | defp drop_og_prefix(["og:" <> property, content]) do
77 | [property, content]
78 | end
79 | end
80 |
--------------------------------------------------------------------------------
/mix.exs:
--------------------------------------------------------------------------------
1 | defmodule OpenGraph.Mixfile do
2 | use Mix.Project
3 |
4 | @source_url "https://github.com/andrielfn/open_graph"
5 | @version "0.0.6"
6 |
7 | def project do
8 | [
9 | app: :open_graph,
10 | version: @version,
11 | elixir: "~> 1.14",
12 | start_permanent: Mix.env() == :prod,
13 | deps: deps(),
14 | docs: docs(),
15 | package: package()
16 | ]
17 | end
18 |
19 | def application do
20 | [extra_applications: [:httpoison, :logger]]
21 | end
22 |
23 | defp deps do
24 | [
25 | {:httpoison, "~> 2.0"},
26 | {:ex_doc, ">= 0.0.0", only: :dev, runtime: false},
27 | {:credo, "~> 1.6.0", only: [:dev, :test], runtime: false}
28 | ]
29 | end
30 |
31 | defp package do
32 | [
33 | description: "A Elixir wrapper for the Open Graph protocol.",
34 | maintainers: ["Andriel Nuernberg"],
35 | licenses: ["MIT"],
36 | links: %{"GitHub" => "https://github.com/andrielfn/open_graph"},
37 | files: ~w(lib mix.exs README.md LICENSE.md)
38 | ]
39 | end
40 |
41 | defp docs do
42 | [
43 | extras: [
44 | "LICENSE.md": [title: "License"],
45 | "README.md": [title: "Overview"]
46 | ],
47 | main: "readme",
48 | source_url: @source_url,
49 | source_ref: "#{@version}",
50 | formatters: ["html"]
51 | ]
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/mix.lock:
--------------------------------------------------------------------------------
1 | %{
2 | "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
3 | "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
4 | "credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"},
5 | "earmark": {:hex, :earmark, "1.2.6", "b6da42b3831458d3ecc57314dff3051b080b9b2be88c2e5aa41cd642a5b044ed", [:mix], [], "hexpm", "b42a23e9bd92d65d16db2f75553982e58519054095356a418bb8320bbacb58b1"},
6 | "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"},
7 | "ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"},
8 | "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
9 | "floki": {:hex, :floki, "0.10.1", "1e36c04264396699f02640e4f88ee92c3459a9286795f54c860aec9204bfcbf2", [:mix], [{:mochiweb_html, "~> 2.15", [hex: :mochiweb_html, optional: false]}]},
10 | "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
11 | "httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"},
12 | "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
13 | "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
14 | "makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"},
15 | "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
16 | "makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
17 | "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
18 | "mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
19 | "mochiweb_html": {:hex, :mochiweb_html, "2.15.0", "d7402e967d7f9f2912f8befa813c37be62d5eeeddbbcb6fe986c44e01460d497", [:rebar3], []},
20 | "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
21 | "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
22 | "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
23 | "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
24 | }
25 |
--------------------------------------------------------------------------------
/test/fixtures/github.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | How people build software · GitHub
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
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 | I am GitHub.
60 |
61 |
62 |
--------------------------------------------------------------------------------
/test/fixtures/nature.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Nature
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
30 |
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 |
71 |
72 |
73 |
74 |
96 |
102 |
103 |
104 |
105 |
247 |
248 |
249 |
250 |
251 |
252 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
Skip to main content
321 |
322 |
323 |
324 |
325 |
326 |
327 |
Thank you for visiting nature.com. You are using a browser version with limited support for CSS. To obtain
328 | the best experience, we recommend you use a more up to date browser (or turn off compatibility mode in
329 | Internet Explorer). In the meantime, to ensure continued support, we are displaying the site without styles
330 | and JavaScript.
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
Advertisement
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
697 |
698 |
699 |
700 |
701 |
704 |
705 |
Massive UK study of
706 | COVID-19 cases shows that people who are jabbed have good immunity at
707 | first, but quickly become more vulnerable to the fast-spreading Delta
708 | variant.
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 | Featured Content
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
749 |
750 |
751 |
752 |
Repeated vocalizations could help young bats to practise the sounds they will need as adults.
753 |
754 |
755 |
756 |
757 |
758 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 | News
772 |
773 |
774 |
775 | 19 Aug 2021
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
812 |
813 |
814 |
815 |
Dramatic antibody production in people
816 | infected during the 2002–04 outbreak furthers hopes of a vaccine against
817 | many coronaviruses.
818 |
819 |
820 |
821 |
822 |
823 |
824 | Smriti Mallapaty
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 | News
837 |
838 |
839 |
840 | 18 Aug 2021
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 |
860 |
861 |
862 |
863 |
867 |
868 |
869 |
870 |
871 |
872 |
873 |
874 |
877 |
878 |
879 |
880 |
Modelling suggests that the Montreal
881 | Protocol may be mitigating climate change by protecting the land carbon
882 | sink, as well as by protecting the ozone layer and reducing greenhouse
883 | gas emissions.
884 |
885 |
886 |
887 |
888 |
889 |
890 | Paul J. Young Anna B. Harper Rolando R. Garcia
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 | Article
903 |
904 |
905 |
906 | 18 Aug 2021
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
943 |
944 |
945 |
946 |
Survey finds that government-funded
947 | trials sometimes face efforts to suppress results. Plus, hopeful signs
948 | for a ‘pan-coronavirus’ vaccine and a rare pair of all-white orca
949 | whales.
950 |
951 |
952 |
953 |
954 |
955 |
958 |
959 |
960 |
961 |
962 |
963 |
964 |
965 |
966 |
967 |
968 | Nature Briefing
969 |
970 |
971 |
972 | 19 Aug 2021
973 |
974 |
975 |
976 |
977 |
978 |
979 |
980 |
981 |
982 |
983 |
984 |
985 |
986 |
987 |
988 |
989 |
990 |
991 |
992 |
993 |
994 |
995 |
996 |
997 |
998 |
1006 |
1007 |
1008 |
1009 |
1010 | Current Issue
1011 |
1012 | 19 Aug 2021
1013 |
1014 |
1015 |
1016 |
1017 |
1018 |
1019 |
1020 |
1021 |
1022 |
1023 |
1024 | Advertisement
1025 |
1026 |
1037 |
1038 |
1039 |
1040 |
1041 |
1042 |
1492 |
1493 |
1494 |
1495 |
1496 |
1497 |
1498 |
1499 |
1509 |
1510 |
1511 |
1512 |
1513 |
1514 |
1515 |
1516 |
1517 |
1518 |
1519 |
1520 |
1521 |
1522 |
1523 |
1524 |
1525 |
1529 |
1530 |
1531 |
1532 |
1533 |
1534 |
1535 |
1536 |
1539 |
1540 |
1541 |
1542 |
Feeding mice high-fructose corn syrup, a
1543 | widely used sweetener in human diets, has been found to drive an
1544 | increase in the surface area of the gut that is associated with enhanced
1545 | absorption of dietary nutrients and weight gain.
1546 |
1547 |
1548 |
1549 |
1550 |
1551 |
1552 |
1569 |
1570 |
1571 |
1572 |
1573 |
1574 |
1575 |
1576 |
1577 |
1578 |
1579 |
1580 |
1581 |
1582 |
1583 |
1584 |
1585 |
1586 |
1587 |
1588 |
1589 |
1590 |
1591 |
1592 |
1593 |
1597 |
1598 |
1599 |
1600 |
1601 |
1602 |
1603 |
1604 |
1607 |
1608 |
1609 |
1610 |
Supersolids are exotic materials whose
1611 | constituent particles can simultaneously form a crystal and flow without
1612 | friction. The first 2D supersolid has been produced using ultracold
1613 | gases of highly magnetic atoms.
1614 |
1615 |
1616 |
1617 |
1618 |
1619 |
1620 |
1621 |
1622 |
1623 |
1640 |
1641 |
1642 |
1643 |
1644 |
1645 |
1646 |
1647 |
1648 |
1649 |
1650 |
1651 |
1652 |
1653 |
1654 |
1655 |
1656 |
1657 |
1658 |
1659 |
1660 |
1661 |
1665 |
1666 |
1667 |
1668 |
1669 |
1670 |
1671 |
1672 |
1675 |
1676 |
1677 |
1678 |
The fruit fly Drosophila melanogaster
1679 | is a social animal. Flies kept in chronic social isolation have now
1680 | been found to show dysregulated sleep and feeding patterns, casting
1681 | light on how prolonged absence of social contact affects health.
1682 |
1683 |
1684 |
1685 |
1686 |
1687 |
1688 |
1689 |
1690 |
1691 |
1708 |
1709 |
1710 |
1711 |
1712 |
1713 |
1714 |
1715 |
1716 |
1717 |
1718 |
1719 |
1720 |
1721 |
1722 |
1723 |
1724 |
1725 |
1726 |
1727 |
1728 |
1729 |
1733 |
1734 |
1735 |
1736 |
1737 |
1738 |
1739 |
1740 |
1743 |
1744 |
1745 |
1746 |
Nature ’s pages feature a 1921 look at the origin of some English place-names, and an 1871 report of a polar expedition.
1747 |
1748 |
1749 |
1750 |
1751 |
1752 |
1753 |
1754 |
1755 |
1756 |
1757 |
1758 |
1759 |
1760 |
1761 | News & Views
1762 |
1763 |
1764 |
1765 | 17 Aug 2021
1766 |
1767 |
1768 |
1769 |
1770 |
1771 |
1772 |
1773 |
1774 |
1775 |
1776 |
1777 |
1778 |
1779 |
1780 |
1781 |
1782 |
1783 |
1784 |
1785 |
1786 |
1787 |
1788 |
1789 |
1790 |
1794 |
1795 |
1796 |
1797 |
1798 |
1799 |
1800 |
1801 |
1804 |
1805 |
1806 |
1807 |
To meet climate targets, technologies
1808 | that remove atmospheric carbon dioxide will probably be needed. An
1809 | analysis shows how their development and use could be accelerated if
1810 | carbon emitters are obliged to remove their own CO2 .
1811 |
1812 |
1813 |
1814 |
1815 |
1816 |
1817 |
1818 |
1819 |
1820 |
1837 |
1838 |
1839 |
1840 |
1841 |
1842 |
1843 |
1844 |
1845 |
1846 |
1847 |
1848 |
1849 |
1850 |
1851 |
1852 |
1853 |
1854 |
1855 |
1856 |
1857 |
1858 |
1859 |
1860 |
1863 |
1864 |
1865 |
1866 |
1867 |
1868 |
1869 |
1870 |
1887 |
1888 |
1889 |
1890 |
1891 |
1892 |
1893 |
1894 |
1895 |
1896 |
1897 |
1898 |
1899 |
1900 |
1901 |
1902 |
1903 |
1906 |
1907 |
1908 |
1909 |
1910 |
1911 |
1912 |
1913 |
1930 |
1931 |
1932 |
1933 |
1934 |
1935 |
1936 |
1937 |
1938 |
1939 |
1940 |
1941 |
1942 |
1943 |
1944 |
1945 |
1946 |
1949 |
1950 |
1951 |
1952 |
1953 |
1954 |
1955 |
1956 |
1973 |
1974 |
1975 |
1976 |
1977 |
1978 |
1979 |
1980 |
1981 |
1982 |
1983 |
1984 |
1985 |
1986 |
1987 |
1988 |
1989 |
1992 |
1993 |
1994 |
1995 |
1996 |
1997 |
1998 |
1999 |
2016 |
2017 |
2018 |
2019 |
2020 |
2021 |
2022 |
2023 |
2024 |
2025 |
2026 |
2027 |
2028 |
2029 |
2030 |
2031 |
2032 |
2033 |
2034 |
2035 |
2036 |
2037 |
2038 |
2039 |
2040 |
2041 |
2045 |
2046 |
2047 |
2048 |
2049 |
2050 |
2051 |
2052 |
2053 |
2054 |
2055 |
2056 |
2066 |
2067 |
2068 |
2069 |
2070 |
2071 |
2072 |
2073 |
2074 |
2075 |
2076 |
2077 |
2078 |
2079 |
2080 |
2084 |
2085 |
2086 |
2087 |
2088 |
2089 |
2090 |
2091 |
2094 |
2095 |
2096 |
2097 |
Surface enhancements in
2098 | glass mobility are complicated in polymers by the
2099 | interplay of the surface mobile layer thickness with a second
2100 | length scale (the size of the polymer chains), giving rise to a
2101 | transient rubbery surface even in polymers with short chains.
2102 |
2103 |
2104 |
2105 |
2106 |
2107 |
2108 | Zhiwei Hao Asieh Ghanekarade Biao Zuo
2109 |
2110 |
2111 |
2112 |
2113 |
2114 |
2115 |
2116 |
2117 |
2118 |
2119 |
2120 | Article
2121 |
2122 |
2123 |
2124 | 18 Aug 2021
2125 |
2126 |
2127 |
2128 |
2129 |
2130 |
2131 |
2132 |
2133 |
2134 |
2135 |
2136 |
2137 |
2138 |
2139 |
2140 |
2141 |
2142 |
2143 |
2144 |
2145 |
2146 |
2147 |
2151 |
2152 |
2153 |
2154 |
2155 |
2156 |
2157 |
2158 |
2161 |
2162 |
2163 |
2164 |
Signals from the sympathetic nervous
2165 | system act via mesenchymal stromal cells to regulate the function of
2166 | group 2 innate lymphoid cells and control adipocyte metabolism.
2167 |
2168 |
2169 |
2170 |
2171 |
2172 |
2173 | Filipa Cardoso Roel G. J. Klein Wolterink Henrique Veiga-Fernandes
2174 |
2175 |
2176 |
2177 |
2178 |
2179 |
2180 |
2181 |
2182 |
2183 |
2184 |
2185 | Article
2186 |
2187 |
2188 |
2189 | 18 Aug 2021
2190 |
2191 |
2192 |
2193 |
2194 |
2195 |
2196 |
2197 |
2198 |
2199 |
2200 |
2201 |
2202 |
2203 |
2204 |
2205 |
2206 |
2207 |
2208 |
2209 |
2210 |
2211 |
2212 |
2216 |
2217 |
2218 |
2219 |
2220 |
2221 |
2222 |
2223 |
2226 |
2227 |
2228 |
2229 |
Modelling suggests that the Montreal
2230 | Protocol may be mitigating climate change by protecting the land carbon
2231 | sink, as well as by protecting the ozone layer and reducing greenhouse
2232 | gas emissions.
2233 |
2234 |
2235 |
2236 |
2237 |
2238 |
2239 | Paul J. Young Anna B. Harper Rolando R. Garcia
2240 |
2241 |
2242 |
2243 |
2244 |
2245 |
2246 |
2247 |
2248 |
2249 |
2250 |
2251 | Article
2252 |
2253 |
2254 |
2255 | 18 Aug 2021
2256 |
2257 |
2258 |
2259 |
2260 |
2261 |
2262 |
2263 |
2264 |
2265 |
2266 |
2267 |
2268 |
2269 |
2270 |
2271 |
2272 |
2273 |
2274 |
2275 |
2276 |
2277 |
2278 |
2282 |
2283 |
2284 |
2285 |
2286 |
2287 |
2288 |
2289 |
2292 |
2293 |
2294 |
2295 |
A protein chaperone system is identified
2296 | that consists of proteins with poly-Asp/Glu sequence, and may have an
2297 | important role in diseases characterized by protein aggregation.
2298 |
2299 |
2300 |
2301 |
2302 |
2303 |
2304 | Liangqian Huang Trisha Agrawal Xiaolu Yang
2305 |
2306 |
2307 |
2308 |
2309 |
2310 |
2311 |
2312 |
2313 |
2314 |
2315 |
2316 | Article
2317 |
2318 |
2319 |
2320 | 18 Aug 2021
2321 |
2322 |
2323 |
2324 |
2325 |
2326 |
2327 |
2328 |
2329 |
2330 |
2331 |
2332 |
2333 |
2334 |
2335 |
2336 |
2337 |
2338 |
2339 |
2340 |
2341 |
2342 |
2343 |
2347 |
2348 |
2349 |
2350 |
2351 |
2352 |
2353 |
2354 |
2357 |
2358 |
2359 |
2360 |
Two-dimensional supersolidity is demonstrated using highly magnetic, ultracold dysprosium atoms.
2361 |
2362 |
2363 |
2364 |
2365 |
2366 |
2367 | Matthew A. Norcia Claudia Politi Francesca Ferlaino
2368 |
2369 |
2370 |
2371 |
2372 |
2373 |
2374 |
2375 |
2376 |
2377 |
2378 |
2379 | Article
2380 |
2381 |
2382 |
2383 | 18 Aug 2021
2384 |
2385 |
2386 |
2387 |
2388 |
2389 |
2390 |
2391 |
2392 |
2393 |
2394 |
2395 |
2396 |
2397 |
2398 |
2399 |
2400 |
2401 |
2402 |
2403 |
2404 |
2405 |
2406 |
2407 |
2408 |
2416 |
2417 |
2418 |
2419 |
2420 |
2421 |
2422 |
2423 |
2424 |
2425 |
2426 |
2427 |
2430 |
2431 |
2432 | Researchers are rethinking
2433 | the nature and potential of matter. From new metal mixes that form more
2434 | efficient catalysts to bio-inspired super-black products, their work is
2435 | driving advances in manufacturing, drug discovery and product design.
2436 |
2437 |
2438 |
2439 |
2440 |
2441 | Nature Index
2442 |
2443 |
2444 | 30 Jun 2021
2445 |
2446 |
2447 |
2448 |
2449 |
2450 |
2451 |
2452 |
2453 |
2454 |
2465 |
2466 |
2467 |
2468 |
2469 |
2470 |
2471 |
2472 |
2473 |
2474 |
2475 |
2476 |
2477 |
2478 |
Trending - Altmetric
2479 |
2480 |
2527 |
2528 |
2529 |
2530 |
2531 |
2532 |
2533 |
2534 |
2535 |
2536 |
2537 |
2538 |
2539 |
2540 |
2541 |
2542 |
2543 |
2544 |
2545 |
2551 |
2552 |
2553 |
2554 |
2555 |
2560 |
2569 |
2570 |
2571 |
2572 |
2577 |
2586 |
2587 |
2588 |
2589 |
2595 |
2604 |
2605 |
2606 |
2607 |
2614 |
2623 |
2624 |
2625 |
2626 |
2631 |
2640 |
2641 |
2642 |
2643 |
2644 |
2645 |
2646 |
2647 |
2648 |
2649 |
2655 |
2656 |
2657 |
2658 |
2659 |
2664 |
2669 |
2670 |
2671 |
2672 |
2677 |
2682 |
2683 |
2684 |
2685 |
2690 |
2695 |
2696 |
2697 |
2698 |
2703 |
2708 |
2709 |
2710 |
2711 |
2718 |
2723 |
2724 |
2725 |
2726 |
2727 |
2728 |
2729 |
2730 |
2731 |
2732 |
2733 |
2744 |
2745 |
2746 |
2747 |
2748 |
2749 |
2750 |
2751 |
2752 |
2753 |
2754 |
2755 |
2756 |
2757 |
2758 |
2759 |
2760 |
2761 |
2762 |
2763 |
2764 |
2765 | Close banner
2766 |
2767 |
2768 |
2769 |
2770 |
2771 |
2772 | Close
2773 |
2774 |
2775 |
2776 |
2777 |
2804 |
2805 |
2806 |
2807 |
2808 |
2809 |
2810 |
2811 |
2812 |
2813 |
2814 |
2815 | Close banner
2816 |
2817 |
2818 |
2819 |
2820 |
2821 |
2822 | Close
2823 |
2824 |
2825 |
2826 |
2827 |
2828 |
Get the most important science stories of the day, free in your inbox.
2829 |
Sign up for Nature Briefing
2830 |
2831 |
2832 |
2833 |
2834 |
2835 |
2836 |
2837 |
2838 |
2839 |
2840 |
2841 |
2842 |
2843 |
2844 |
2845 |
2846 |
2847 |
2848 |
2849 |
2850 |
2851 |
2852 |
2853 |
2854 |
2855 |
2856 |
2857 |
2858 |
2859 |
2860 |
2861 |
2862 |
2863 | Top headline image: Credit: Ian Forsyth/Getty
2864 |
2865 |
2866 |
2867 |
2868 |
2869 |
2870 |
2871 |
2872 |
2873 |
2874 |
2875 |
2876 |
2877 |
2878 | Issue cover: Cover image: KL Murphy
2879 |
2880 |
2881 |
2882 |
2883 |
2884 |
2885 |
2886 | Nature (Nature )
2887 |
2888 |
2889 |
2890 |
2891 | ISSN 1476-4687 (online)
2892 |
2893 |
2894 |
2895 |
2896 |
2897 |
2898 |
2899 | ISSN 0028-0836 (print)
2900 |
2901 |
2902 |
2903 |
2904 |
2905 |
2906 |
2907 |
2908 |
2909 |
2910 |
2911 |
3036 |
3037 |
3038 |
3044 |
3045 |
3046 |
3047 |
3048 |
3049 |
3050 |
3051 |
3052 |
3053 |
3054 |
3055 |
3056 |
3057 |
3058 |
3059 |
3060 |
3061 |
3062 |
3063 |
3064 |
3065 |
3066 |
3067 |
3068 |
3069 |
3070 |
3071 |
3072 |
3073 |
3074 |
3075 |
3076 |
3077 |
3078 |
3115 |
3116 |
3117 |
3118 |
3119 |
3120 |
3121 |
3122 |
3123 |
3124 |
3125 |
3126 |
3127 |
--------------------------------------------------------------------------------
/test/open_graph_test.exs:
--------------------------------------------------------------------------------
1 | defmodule OpenGraphTest do
2 | use ExUnit.Case
3 |
4 | setup do
5 | github = File.read!("#{File.cwd!()}/test/fixtures/github.html")
6 | nature = File.read!("#{File.cwd!()}/test/fixtures/nature.html")
7 | {:ok, github: github, nature: nature}
8 | end
9 |
10 | test "parses with valid OpenGraph metatags in the given HTML", %{github: html} do
11 | og = OpenGraph.parse(html)
12 |
13 | assert og.title == "Build software better, together"
14 | assert og.url == "https://github.com"
15 | assert og.site_name == "GitHub"
16 |
17 | assert og.description ==
18 | "GitHub is where people build software. More than 15 million people use GitHub to discover, fork, and contribute to over 38 million projects."
19 |
20 | assert og.image ==
21 | "https://assets-cdn.github.com/images/modules/open_graph/github-octocat.png"
22 | end
23 |
24 | test "parses with empty given HTML" do
25 | og = OpenGraph.parse("")
26 |
27 | assert og.title == nil
28 | assert og.url == nil
29 | assert og.site_name == nil
30 | assert og.description == nil
31 | assert og.image == nil
32 | end
33 |
34 | test "fetch despite 303 redirections", %{nature: html} do
35 | og = OpenGraph.parse(html)
36 |
37 | assert og.description ==
38 | "Nature is the foremost international weekly scientific journal in the world and is the flagship journal for Nature Portfolio. It publishes the finest ..."
39 |
40 | assert og.image ==
41 | "http://media.springernature.com/lw630/nature-cms/uploads/cms/pages/2913/top_item_image/d41586-021-02261-8_19578828-705d6691a7215ead2ffecb4e0cfae7bc.jpg"
42 |
43 | assert og.site_name == "Nature"
44 | assert og.title == "Nature"
45 | assert og.type == "website"
46 | assert og.url == "https://www.nature.com/nature"
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/test/test_helper.exs:
--------------------------------------------------------------------------------
1 | ExUnit.start()
2 |
--------------------------------------------------------------------------------