analytics/lib/plausible_web/components/generic.ex
hq1 c81cb16933
Snippet integration verification (#4106)
* Allow running browserless.io locally

* Compile tailwind classes based on extra/ too

* Add browserless runtime configuration

* Ignore verification events on ingestion

* Improve extracting HTML text in tests

* Update dependencies

- Floki will be used on production to parse site contents
- Req will be used to handle redundant stuff like retrying etc.

* Add shuttle SVG to generic components

Later on we'll use it to indicate verification errors

* Connect live socket & allow skipping awaiting the first pageview

* Connect live socket in general settings

* Implement verification checks & diagnostics

* Stub remote services with Req for testing

* Change snippet screen copy

* Update tracker script, so that:

1. headless browsers aren't ignored if `window.__plausible` is defined
2. callback optionally supplies the event response HTTP status

This will be later used to check whether the server acknowledged
the verification event.

* Implement LiveView verification UI

* Embed the verification UIs into settings and onboarding

* Implement browserless puppeteer verification script

It:
 - tries to visit the site
 - defines window.__plausible, so the tracker doesn't ignore test events
 - sends a verification event and instruments the callback
 - awaits the callback to fire and returns the result

* Improve diagnostics for CSP

Only report CSP error if the snippet is already found

* Put verification behind a feature flag/env setting

* Contact Us hint only for Enterprise Edition

* For headless code, use JS context instead of EEx interpolation

* Update diagnostics test with WordPress scenarios

* Shorten exception/throw interception

* Rename test

* Tidy up

* Bust URL always on headless check

* Update moduledoc

* Detect official Plausible WordPress Plugin

and act accordingly on diagnostics interoperation

* Stop using 'rating' in favour of 'interpretation'

* Only report CSP error if no proxy is likely

* Update CHANGELOG

* Allow event-* attributes on snippet elements

* Improve naive GTM detection, not to confuse it with GA4

* Update lib/plausible/verification.ex

Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>

* Update test/plausible/site/verification/checks_test.exs

Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>

* s/perform_wrapped/perform_safe

* Update lib/plausible/verification/checks/installation.ex

Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>

* Remove garbage

---------

Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
2024-05-23 15:00:50 +02:00

393 lines
28 KiB
Elixir

defmodule PlausibleWeb.Components.Generic do
@moduledoc """
Generic reusable components
"""
use Phoenix.Component, global_prefixes: ~w(x-)
@notice_themes %{
yellow: %{
bg: "bg-yellow-50 dark:bg-yellow-100",
icon: "text-yellow-400",
title_text: "text-yellow-800 dark:text-yellow-900",
body_text: "text-yellow-700 dark:text-yellow-800"
},
red: %{
bg: "bg-red-100",
icon: "text-red-700",
title_text: "text-red-800 dark:text-red-900",
body_text: "text-red-700 dark:text-red-800"
}
}
@button_themes %{
"primary" => "bg-indigo-600 text-white hover:bg-indigo-700 focus-visible:outline-indigo-600",
"bright" =>
"border border-gray-200 bg-gray-100 dark:bg-gray-300 text-gray-800 hover:bg-gray-200 focus-visible:outline-gray-100",
"danger" =>
"border border-gray-300 dark:border-gray-500 text-red-700 bg-white dark:bg-gray-800 hover:text-red-500 dark:hover:text-red-400 focus:border-blue-300 active:text-red-800"
}
@button_base_class "inline-flex items-center justify-center gap-x-2 rounded-md px-3.5 py-2.5 text-sm font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 disabled:bg-gray-400 dark:disabled:text-white dark:disabled:text-gray-400 dark:disabled:bg-gray-700"
attr(:type, :string, default: "button")
attr(:theme, :string, default: "primary")
attr(:class, :string, default: "")
attr(:disabled, :boolean, default: false)
attr(:rest, :global)
slot(:inner_block)
def button(assigns) do
assigns =
assign(assigns,
button_base_class: @button_base_class,
theme_class: @button_themes[assigns.theme]
)
~H"""
<button
type={@type}
disabled={@disabled}
class={[
@button_base_class,
@theme_class,
@class
]}
{@rest}
>
<%= render_slot(@inner_block) %>
</button>
"""
end
attr(:href, :string, required: true)
attr(:class, :string, default: "")
attr(:theme, :string, default: "primary")
attr(:disabled, :boolean, default: false)
attr(:rest, :global)
slot(:inner_block)
def button_link(assigns) do
theme_class =
if assigns.disabled do
"bg-gray-400 text-white dark:text-white dark:text-gray-400 dark:bg-gray-700 cursor-not-allowed"
else
@button_themes[assigns.theme]
end
onclick =
if assigns.disabled do
"return false;"
else
assigns[:onclick]
end
assigns =
assign(assigns,
onclick: onclick,
button_base_class: @button_base_class,
theme_class: theme_class
)
~H"""
<.link
href={@href}
onclick={@onclick}
class={[
@button_base_class,
@theme_class,
@class
]}
{@rest}
>
<%= render_slot(@inner_block) %>
</.link>
"""
end
attr(:slug, :string, required: true)
def docs_info(assigns) do
~H"""
<a href={"https://plausible.io/docs/#{@slug}"} rel="noreferrer" target="_blank">
<Heroicons.information_circle class="text-gray-400 w-6 h-6 absolute top-0 right-0" />
</a>
"""
end
attr(:title, :any, default: nil)
attr(:size, :atom, default: :sm)
attr(:theme, :atom, default: :yellow)
attr(:dismissable_id, :any, default: nil)
attr(:class, :string, default: "")
attr(:rest, :global)
slot(:inner_block)
def notice(assigns) do
assigns = assign(assigns, :theme, Map.fetch!(@notice_themes, assigns.theme))
~H"""
<div id={@dismissable_id} class={@dismissable_id && "hidden"}>
<div class={["rounded-md p-4 relative", @theme.bg, @class]} {@rest}>
<button
:if={@dismissable_id}
class={"absolute right-0 top-0 m-2 #{@theme.title_text}"}
onclick={"localStorage['notice_dismissed__#{@dismissable_id}'] = 'true'; document.getElementById('#{@dismissable_id}').classList.add('hidden')"}
>
<Heroicons.x_mark class="h-4 w-4 hover:stroke-2" />
</button>
<div class="flex">
<div :if={@title} class="flex-shrink-0">
<svg
class={"h-5 w-5 #{@theme.icon}"}
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class={["w-full", @title && "ml-3"]}>
<h3 :if={@title} class={"text-#{@size} font-medium #{@theme.title_text} mb-2"}>
<%= @title %>
</h3>
<div class={"text-#{@size} #{@theme.body_text}"}>
<p>
<%= render_slot(@inner_block) %>
</p>
</div>
</div>
</div>
</div>
</div>
<script :if={@dismissable_id} data-key={@dismissable_id}>
const dismissId = document.currentScript.dataset.key
const localStorageKey = `notice_dismissed__${dismissId}`
if (localStorage[localStorageKey] !== 'true') {
document.getElementById(dismissId).classList.remove('hidden')
}
</script>
"""
end
attr :id, :any, default: nil
attr :href, :string, default: "#"
attr :new_tab, :boolean, default: false
attr :class, :string, default: ""
attr :rest, :global
slot :inner_block
def styled_link(assigns) do
~H"""
<.unstyled_link
new_tab={@new_tab}
href={@href}
class={"text-indigo-600 hover:text-indigo-700 dark:text-indigo-500 dark:hover:text-indigo-600 " <> @class}
{@rest}
>
<%= render_slot(@inner_block) %>
</.unstyled_link>
"""
end
slot :button, required: true do
attr :class, :string
end
slot :panel, required: true do
attr :class, :string
end
def dropdown(assigns) do
~H"""
<div
x-data="dropdown"
x-on:keydown.escape.prevent.stop="close($refs.button)"
x-on:focusin.window="! $refs.panel.contains($event.target) && close()"
>
<button x-ref="button" x-on:click="toggle()" type="button" class={List.first(@button).class}>
<%= render_slot(List.first(@button)) %>
</button>
<div
x-ref="panel"
x-show="open"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
x-on:click.outside="close($refs.button)"
style="display: none;"
class={List.first(@panel).class}
>
<%= render_slot(List.first(@panel)) %>
</div>
</div>
"""
end
attr :href, :string, required: true
attr :new_tab, :boolean, default: false
attr :rest, :global
slot :inner_block, required: true
def dropdown_link(assigns) do
class =
"w-full inline-flex text-gray-700 dark:text-gray-300 px-3.5 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-900 dark:hover:text-gray-100"
class =
if assigns.new_tab do
"#{class} justify-between"
else
class
end
assigns = assign(assigns, :class, class)
~H"""
<.unstyled_link new_tab={@new_tab} href={@href} x-on:click="close()" class={@class} {@rest}>
<%= render_slot(@inner_block) %>
</.unstyled_link>
"""
end
attr :href, :string, required: true
attr :new_tab, :boolean, default: false
attr :class, :string, default: ""
attr :id, :any, default: nil
attr :rest, :global
slot :inner_block
def unstyled_link(assigns) do
if assigns[:new_tab] do
assigns = assign(assigns, :icon_class, icon_class(assigns))
~H"""
<.link
id={@id}
class={[
"inline-flex items-center gap-x-0.5",
@class
]}
href={@href}
target="_blank"
rel="noopener noreferrer"
{@rest}
>
<%= render_slot(@inner_block) %>
<Heroicons.arrow_top_right_on_square class={["opacity-60", @icon_class]} />
</.link>
"""
else
~H"""
<.link class={@class} href={@href} {@rest}>
<%= render_slot(@inner_block) %>
</.link>
"""
end
end
attr :class, :any, default: ""
attr :rest, :global
def spinner(assigns) do
~H"""
<svg
class={["animate-spin h-4 w-4 text-indigo-500", @class]}
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
{@rest}
>
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4">
</circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
>
</path>
</svg>
"""
end
attr :wrapper_class, :any, default: ""
attr :class, :any, default: ""
slot :inner_block, required: true
slot :tooltip_content, required: true
def tooltip(assigns) do
~H"""
<div x-data="{sticky: false, hovered: false}" class={["tooltip-wrapper relative", @wrapper_class]}>
<p
x-on:click="sticky = true; hovered = true"
x-on:click.outside="sticky = false; hovered = false"
x-on:mouseover="hovered = true"
x-on:mouseout="hovered = false"
class={["cursor-pointer flex align-items-center", @class]}
>
<%= render_slot(@inner_block) %>
<Heroicons.information_circle class="w-5 h-5 ml-2" />
</p>
<span
x-show="hovered || sticky"
class="bg-gray-900 pointer-events-none absolute bottom-10 margin-x-auto left-10 right-10 transition-opacity p-4 rounded text-sm text-white"
>
<%= render_slot(List.first(@tooltip_content)) %>
</span>
</div>
"""
end
attr :rest, :global, include: ~w(fill stroke stroke-width)
attr :name, :atom, required: true
attr :outline, :boolean, default: true
attr :solid, :boolean, default: false
attr :mini, :boolean, default: false
def dynamic_icon(assigns) do
apply(Heroicons, assigns.name, [assigns])
end
attr :width, :integer, default: 100
attr :height, :integer, default: 100
attr :id, :string, default: "shuttle"
def shuttle(assigns) do
~H"""
<svg
id={@id}
class="inline fill-current text-gray-800 dark:text-white"
xmlns="http://www.w3.org/2000/svg"
width={@width}
height={@height}
version="1.1"
x="0px"
y="0px"
viewBox="0 0 100 100"
xmlSpace="preserve"
>
<g>
<path d="M35.6830368,38.7263184c2.7299805,0,4.9511719-2.2211914,4.9511719-4.9511719s-2.2211914-4.9511719-4.9511719-4.9511719 c-2.7304688,0-4.9516602,2.2211914-4.9516602,4.9511719S32.9525681,38.7263184,35.6830368,38.7263184z M35.6830368,30.8239746 c1.6274414,0,2.9511719,1.3237305,2.9511719,2.9511719s-1.3237305,2.9511719-2.9511719,2.9511719 s-2.9516602-1.3237305-2.9516602-2.9511719S34.0555954,30.8239746,35.6830368,30.8239746z" /><path d="M43.4540329,27.4133301c2.1630859,0,3.9228516-1.7597656,3.9228516-3.9228516s-1.7597656-3.9228516-3.9228516-3.9228516 c-2.1625977,0-3.9223633,1.7597656-3.9223633,3.9228516S41.2914352,27.4133301,43.4540329,27.4133301z M43.4540329,21.567627 c1.0600586,0,1.9228516,0.862793,1.9228516,1.9228516s-0.862793,1.9228516-1.9228516,1.9228516 s-1.9223633-0.862793-1.9223633-1.9228516S42.3939743,21.567627,43.4540329,21.567627z" /><path d="M80.2762985,41.4973145c3.6635742,0,6.6445313-2.980957,6.6445313-6.6445313s-2.980957-6.6445313-6.6445313-6.6445313 c-3.6640625,0-6.6450195,2.980957-6.6450195,6.6445313S76.612236,41.4973145,80.2762985,41.4973145z M80.2762985,30.208252 c2.5610352,0,4.6445313,2.0834961,4.6445313,4.6445313s-2.0834961,4.6445313-4.6445313,4.6445313 s-4.6450195-2.0834961-4.6450195-4.6445313S77.7152634,30.208252,80.2762985,30.208252z" /><path d="M86.4340134,28.1555176c1.9663086,0,3.565918-1.5996094,3.565918-3.565918s-1.5996094-3.565918-3.565918-3.565918 c-1.9658203,0-3.5654297,1.5996094-3.5654297,3.565918S84.4681931,28.1555176,86.4340134,28.1555176z M86.4340134,23.0236816 c0.8632813,0,1.565918,0.7026367,1.565918,1.565918s-0.7026367,1.565918-1.565918,1.565918 s-1.5654297-0.7026367-1.5654297-1.565918S85.5707321,23.0236816,86.4340134,23.0236816z" /><path d="M79.9183884,48.1384277l-0.5896606,0.1737061c0.1333618-0.4435425,0.2112427-0.9072266,0.2112427-1.3841553 c0-0.4707031-0.0678711-0.9375-0.2045898-1.3950195c-0.78125-2.5327148-3.4887695-3.9741211-6.0366211-3.2119141 l-1.7001953,0.5170898c-0.3798828,0.1108398-0.7299805,0.1855469-1.0664063,0.2265625 c-0.003479,0.0004272-0.006897,0.000061-0.010376,0.0004883c-0.0266113,0.0028076-0.0534058-0.0014648-0.0794678,0.00354 c-0.6416626,0.0675659-1.277771,0.0505981-1.8896484-0.0645752l-4.8505859-0.8999023 c-3.8491211-0.7124023-7.8662109-0.4970703-11.6201172,0.6259766l-11.3138428,3.4025879 c-0.0564575-0.0429077-0.1116943-0.0877075-0.1778564-0.1184082l-13.7036133-6.3583984 c-0.230957-0.1069336-0.4951172-0.121582-0.7353516-0.0419922l-8.2226563,2.7250977 c-0.309082,0.1025391-0.5488281,0.3486328-0.6425781,0.6601563c-0.0942383,0.3110352-0.03125,0.6489258,0.1694336,0.9052734 l5.8516235,7.4795532l-2.1152954,0.6361694c-0.2539063,0.0761719-0.4672852,0.2504883-0.5927734,0.4838867 c-0.1254883,0.2338867-0.1533203,0.5078125-0.0766602,0.7617188l0.3309326,1.0892944 c-0.2720337,0.0733643-0.5426636,0.1504517-0.8016357,0.250061c-4.4667969,1.7197266-6.3505859,7.1894531-6.4287109,7.4213867 c-0.1542969,0.4580078,0.0415039,0.9609375,0.4648438,1.1943359c0.1640625,0.0908203,3.1762695,1.7246094,6.574707,1.7246094 c1.0532227,0,2.144043-0.1572266,3.1977539-0.5654297c0.0115356-0.0044556,0.022644-0.010437,0.0341797-0.0149536 l0.0750732,0.2472534l-1.4403076,0.4239502c-0.2548828,0.0751953-0.4692383,0.2485352-0.5961914,0.4819336 s-0.1557617,0.5073242-0.0800781,0.762207l0.2781982,0.9320679c-1.5239868-0.0391846-2.9415283,0.1781616-4.2181396,0.6724243 c-5.4560547,2.1005859-7.7651367,8.8061523-7.8608398,9.090332c-0.1176758,0.3505859-0.0327148,0.7373047,0.2211914,1.0058594 c0.2539063,0.269043,0.6376953,0.3745117,0.9916992,0.2773438c1.5864258-0.4365234,3.1904297-0.6772461,4.7919922-0.7211914 l-1.0683594,1.046875c-0.269043,0.2631836-0.3671875,0.6552734-0.2543945,1.0141602s0.4174805,0.6240234,0.7880859,0.6865234 c0.0708008,0.0117188,0.9082031,0.1474609,2.121582,0.1474609c1.3310547,0,3.1152344-0.1635742,4.8369141-0.8339844 c0.9935913-0.385376,1.942627-0.9547729,2.8378296-1.6859131l0.4258423,1.4300537 c0.1289063,0.434082,0.5268555,0.715332,0.9580078,0.715332c0.09375,0,0.1889648-0.0136719,0.2832031-0.0415039l3.6088257-1.064209 c0.5294189,0.4693604,1.2138062,0.7355957,1.9185181,0.7355957c0.2729492,0,0.5488281-0.0395508,0.8183594-0.1206055 l2.612793-0.7680664c0.6903687-0.1968994,1.2542114-0.6436157,1.6234131-1.2183228 c0.3770752,0.1716309,0.7831421,0.2798462,1.2032471,0.2798462c0.2666016,0,0.5361328-0.0366211,0.8007813-0.1132813 l2.6342773-0.7744141c0.6880493-0.2131348,1.241272-0.6553345,1.6037598-1.2210083 c0.3721924,0.1687622,0.7717285,0.2756958,1.1843262,0.2756958c0.2724609,0,0.5478516-0.0395508,0.8178711-0.1206055 l2.612793-0.7675781c0.980957-0.2804565,1.713623-1.0597534,1.9748535-2.0108032l33.9655762-10.0023804 c3.3706055-1.003418,5.6347656-4.0170898,5.6347656-7.4985352c0-0.7524414-0.1083984-1.4975586-0.3222656-2.2167969 C88.4432907,49.2814941,84.0643845,46.9157715,79.9183884,48.1384277z M26.4042282,41.6369629l10.9301758,5.0717773 l-12.3256836,3.6044922l-5.1030273-6.5224609L26.4042282,41.6369629z M63.3373337,44.0710449l2.6757202,0.4962769 l-6.4960327,2.1526489c-0.3745117,0.121582-0.7783203-0.0761719-0.9013672-0.4448242l-0.8479614-2.5335693 C59.6291428,43.6253662,61.5039597,43.730957,63.3373337,44.0710449z M52.6566696,44.645752 c1.0076294-0.3015137,2.0372925-0.5230713,3.0765381-0.6818237l0.9859619,2.9459839 c0.3779297,1.1303711,1.4384766,1.847168,2.5737305,1.8466797c0.2832031,0,0.5708008-0.0444336,0.8535156-0.1381836 l10.8579102-3.5981445c0.0090942-0.0029907,0.0158081-0.0096436,0.0247192-0.0128784 c0.3674316-0.0574341,0.7401123-0.1351929,1.1417847-0.2532349l1.7055664-0.5185547 c1.4975586-0.4467773,3.0883789,0.3989258,3.5454102,1.878418c0.078125,0.2631836,0.1181641,0.5371094,0.1181641,0.8139648 c0,0.8886719-0.4160156,1.7143555-1.1201172,2.2368164l-28.8650513,8.5059814l-0.8562622,0.2522583 c-0.2514038-0.196106-0.5341187-0.3519897-0.8377686-0.4598999c-0.0093384-0.0098267-0.0202637-0.0175781-0.0297241-0.0272827 c-0.038208-0.0392456-0.079895-0.0735474-0.1200562-0.1102905c-0.0634155-0.0580444-0.1269531-0.1153564-0.1948242-0.1671143 c-0.0471191-0.0359497-0.0963745-0.067749-0.1453857-0.1005859c-0.0665283-0.0444946-0.1335449-0.0876465-0.2033081-0.1263428 c-0.0535278-0.0297241-0.1080322-0.0564575-0.163269-0.0827026c-0.0698853-0.0332031-0.1405029-0.0636597-0.2127686-0.0911255 c-0.0580444-0.0220947-0.1160889-0.0426025-0.1754761-0.0609131c-0.0736694-0.0227051-0.1481323-0.0411987-0.2234497-0.0580444 c-0.0602417-0.0134888-0.1199341-0.0269775-0.1810303-0.0365601c-0.0789795-0.0123901-0.1585693-0.0187988-0.2385254-0.0245972 c-0.0588379-0.0043335-0.1170044-0.0105591-0.1762085-0.0112305c-0.0892334-0.0009766-0.1785889,0.0061035-0.2682495,0.0134888 c-0.0505371,0.0042114-0.1008911,0.0043335-0.1514893,0.0112305c-0.1401367,0.019043-0.2800293,0.0469971-0.4185791,0.0874023 l-2.6254883,0.7714844c-0.1715088,0.0514526-0.335022,0.1169434-0.4894409,0.1948242 c-0.1483154,0.0748291-0.2871094,0.1623535-0.4178467,0.258667c-0.0053711,0.0039673-0.0119019,0.0066528-0.0172729,0.0106812 c-0.1115723,0.083374-0.2116089,0.1785278-0.3088379,0.2757568c-0.020752,0.020752-0.0458374,0.0375366-0.0658569,0.0588379 c-0.0830688,0.0883789-0.1534424,0.1865234-0.2243042,0.2841187c-0.0264282,0.036377-0.0588379,0.0684204-0.0834961,0.105957 c-0.0002441,0.0003662-0.0006104,0.0007324-0.0008545,0.0010986c-0.008728-0.0039673-0.0183105-0.0056763-0.0270996-0.0095215 c-0.0830688-0.0366821-0.1703491-0.0613403-0.2565308-0.0900269c-0.0712891-0.0236816-0.1404419-0.0530396-0.213501-0.0710449 c-0.0961914-0.0238037-0.1952515-0.0338135-0.2938232-0.0474854c-0.0670166-0.0093384-0.1325073-0.0254517-0.2003174-0.0299683 c-0.1109619-0.0073853-0.2233276,0.0008545-0.3355103,0.0066528c-0.0574341,0.0029907-0.1143188-0.0018921-0.171875,0.0046387 c-0.1697998,0.0193481-0.3398438,0.0536499-0.5081787,0.1049194l-2.6225586,0.7709961 c-0.1702271,0.0504761-0.3327026,0.1159668-0.4865723,0.194458c-0.0361938,0.0184937-0.0670166,0.0443115-0.1022339,0.064209 c-0.114624,0.0647583-0.2285767,0.1306152-0.3320923,0.2097778c-0.0396729,0.0302734-0.0722656,0.0681152-0.1102295,0.1004028 c-0.0912476,0.0775757-0.1833496,0.1543579-0.263916,0.2424927c-0.0459595,0.0502319-0.0822754,0.1082764-0.1245728,0.1616211 c-0.0603638,0.0762329-0.1253662,0.1488647-0.1779175,0.230957c-0.4283447-0.1953125-0.90625-0.2789307-1.394104-0.2468872 c-0.0344849,0.0022583-0.0682373-0.0021362-0.1028442,0.0013428c-0.1741333,0.0176392-0.3493042,0.0509033-0.5236816,0.100708 l-2.6259766,0.7719727c-0.1636353,0.0493164-0.3181763,0.1143799-0.4664307,0.1885986 c-0.0487671,0.0244141-0.0928955,0.0542603-0.1398315,0.0811157c-0.0963745,0.0551758-0.1904907,0.1124878-0.2788086,0.1773682 c-0.0499268,0.0366821-0.0962524,0.0762939-0.1435547,0.1159058c-0.0778809,0.0652466-0.1521606,0.1329956-0.2223511,0.2055054 c-0.0435181,0.0449219-0.0854492,0.09021-0.1258545,0.1376343c-0.0662231,0.0778198-0.1264648,0.1592407-0.18396,0.2432251 c-0.03302,0.0482788-0.0672607,0.0950928-0.09729,0.1452026c-0.0593262,0.098999-0.1095581,0.2024536-0.1566162,0.3079224 c-0.0180054,0.0402222-0.0400391,0.078186-0.0561523,0.1193237c-0.0580444,0.1479492-0.1044922,0.300354-0.137207,0.4569702 c-0.007019,0.0336914-0.0078735,0.0687256-0.0136719,0.1027222c-0.0180664,0.1057129-0.0368042,0.2113647-0.0427246,0.3195801 l-0.2138062-0.7027588c0.012085-0.1270142,0.0072021-0.2562256-0.0317993-0.3841553l-1.1140137-3.6674194l-0.322998-1.0791626 c-0.0026855-0.0089111-0.0092773-0.015564-0.012207-0.024353l-0.9248047-3.0444946 c-0.0401001-0.1308594-0.1096802-0.2437134-0.1931763-0.3440552l-0.2487183-0.8175659L52.6566696,44.645752z M22.3425827,59.2571411l0.0478516,0.1574097c-0.1259155,0.0722656-0.2521362,0.1400757-0.3763428,0.1901855 c-0.253418,0.0957031-0.5390625,0.1601563-0.8525391,0.1923828c0.2495117-0.1816406,0.5009766-0.3227539,0.7504883-0.4189453 C22.0441818,59.3267212,22.1913376,59.2897949,22.3425827,59.2571411z M23.1390915,62.5144043 c-2.6728516,1.0361328-5.8369141-0.0449219-7.2880859-0.668457c0.6430664-1.4326172,2.2358398-4.3408203,4.9189453-5.3740234 c0.213562-0.0823975,0.4368286-0.1488037,0.6634521-0.2074585l0.3309937,1.0894775 c-0.1945801,0.0488892-0.3952637,0.0895996-0.5745239,0.1589966c-1.090332,0.421875-2.1020508,1.2758789-3.0068359,2.5380859 c-0.1958008,0.2734375-0.2412109,0.6269531-0.1206055,0.940918s0.3911133,0.5463867,0.7197266,0.6186523 c0.6391602,0.1396484,1.2744141,0.2109375,1.8881836,0.2109375c0.7543945,0,1.4448242-0.1166992,2.0698242-0.3535156 c0.0811157-0.0325317,0.1576538-0.0828857,0.2376709-0.1199341l0.3328857,1.0957642 C23.2537155,62.4679565,23.1967697,62.4923706,23.1390915,62.5144043z M23.5314255,72.725647l0.0012207,0.0040894 c-0.5898438,0.7407227-1.1948242,1.3237305-1.8076172,1.7416992c-0.5957031-0.9111328-1.5537109-1.5366211-2.6308594-1.7211914 c0.199707-0.1118164,0.4003906-0.2060547,0.6015625-0.2827148c1.0146484-0.387207,2.3012695-0.4477539,3.6938477-0.2143555 L23.5314255,72.725647z M21.756279,77.7346191c-1.2910156,0.5024414-2.6557617,0.6630859-3.7475586,0.6904297l1.1201172-1.0976563 c0.2788086-0.2729492,0.3730469-0.6831055,0.2421875-1.050293s-0.4633789-0.625-0.8515625-0.6601563 c-0.6420898-0.0581055-1.2861328-0.0869141-1.9301758-0.0869141c-1.2963867,0-2.5947266,0.1171875-3.8862305,0.3515625 c0.9746094-1.9414063,2.9125977-4.96875,5.9301758-6.1308594c1.1391602-0.440918,2.434082-0.6181641,3.8476563-0.5322266 l0.2842407,0.9488525c-1.3863525-0.1206055-2.680603,0.0112915-3.7837524,0.4320068 c-1.2207031,0.4672852-2.3857422,1.3544922-3.4614258,2.6357422c-0.2607422,0.3105469-0.3085938,0.7480469-0.1201172,1.1069336 c0.1879883,0.3588867,0.5737305,0.5717773,0.9785156,0.5317383l1.8959961-0.1762695 c0.0302734-0.003418,0.0610352-0.0043945,0.0913086-0.0043945c0.784668,0.0019531,1.4975586,0.4169922,1.831543,1.1416016 c0.0463867,0.0922852,0.0771484,0.1743164,0.097168,0.2583008c0.0678711,0.2875977,0.2592773,0.5307617,0.5229492,0.6635742 c0.1416016,0.0712891,0.2958984,0.1069336,0.4501953,0.1069336c0.1342773,0,0.2685547-0.0268555,0.3945313-0.0810547 c0.8795776-0.3776855,1.7250366-1.0009155,2.534668-1.8171997l0.3041992,1.0198364 C23.6381149,76.7746582,22.7172165,77.3615723,21.756279,77.7346191z M25.7430954,72.3293457 c-0.0053711-0.0239258-0.0117188-0.0478516-0.0185547-0.0712891l-1.6694336-5.5859375l0.6426392-0.1890869 c0.1815186,0.1630859,0.4124756,0.2652588,0.6615601,0.2652588c0.0947266,0,0.190918-0.0136719,0.2866211-0.0424805 l0.7924194-0.2364502l2.1046753,7.0847168l1.0675659,3.6032104l-2.2332153,0.6588745L25.7430954,72.3293457z M35.3881149,76.8781738l-2.6269531,0.7719727c-0.3734741,0.1134644-0.7839355-0.0386963-0.998291-0.3710938 c-0.0044556-0.0070801-0.0038452-0.0159912-0.0085449-0.0229492c-0.0307617-0.0463867-0.0595703-0.1108398-0.0820313-0.1914063 l-1.4168701-4.7697754l-2.2486572-7.5876465l-0.2172852-0.7382813c-0.0527344-0.4150391,0.2158203-0.8164063,0.6328125-0.9418945 l2.6118164-0.7680664c0.4311523-0.1245117,0.8818359,0.0771484,1.0400391,0.4121094l3.5966187,12.0499268l0.3242798,1.0936279 c0.0015259,0.0049438,0.0045166,0.0084229,0.0061035,0.0133667l0.0114746,0.0383911 c0.0001221,0.0003052,0.0003662,0.001709,0.0004883,0.0020752c0.0063477,0.031189,0.0131836,0.0750122,0.0131836,0.145874 c0,0.0057373,0.0036621,0.0105591,0.0037842,0.0162964C36.0345993,76.4204712,35.773613,76.7678833,35.3881149,76.8781738z M41.6283493,75.0583496l-2.6157227,0.7685547c-0.3842773,0.1107788-0.7797852-0.0397949-1.0014038-0.3787842 c-0.0003052-0.0004883-0.0002441-0.0010986-0.0005493-0.0015869c-0.0240479-0.0377808-0.0378418-0.0718384-0.053833-0.1066895 c-0.0119019-0.026001-0.0247803-0.0489502-0.0344238-0.0758057c-0.0065308-0.0221558-0.0131226-0.0442505-0.0206299-0.06604 c-0.001709-0.005127-0.0059204-0.0084839-0.0077515-0.0136108l-3.7139282-12.5259399l-0.1210938-0.4052734 c-0.0109863-0.0336914-0.0181274-0.0585327-0.0230103-0.0740356c-0.0022583-0.0072632-0.005188-0.0172729-0.0057983-0.0172729 c-0.0004883,0-0.0004883,0.0014648-0.0004883,0.0048828c-0.0610352-0.4277344,0.2119141-0.8452148,0.6318359-0.9697266 l2.6289063-0.7724609c0.40625-0.125,0.8422852,0.0654297,1.034668,0.4501953 c0.0029297,0.0058594,0.0058594,0.0112305,0.0087891,0.0170898c0.0043945,0.0102539,0.0087891,0.0205078,0.0131836,0.0302734 c0.015625,0.034668,0.0341797,0.0708008,0.0463867,0.1069336l3.8374023,12.9326172 c0.0012207,0.0040894,0.0032349,0.0079956,0.0044556,0.012085l0.0062866,0.0211182 c0.0129395,0.0390625,0.0126953,0.0739746,0.0166626,0.107666c0.0024414,0.0253906,0.0077515,0.0415649,0.0077515,0.0773926 c0,0.0050049,0.0032349,0.0092163,0.0032959,0.0142212C42.2725143,74.5970459,42.0161667,74.9381714,41.6283493,75.0583496z M48.509697,72.3605957c0.0048828,0.3955078-0.2558594,0.7475586-0.6416016,0.8579102l-2.6264648,0.7714844 c-0.3828125,0.1132813-0.7822266-0.0351563-0.9838867-0.3564453c-0.0009155-0.0015259-0.0010376-0.0028076-0.0019531-0.0043335 c-0.003479-0.0057983-0.0027466-0.0128784-0.0063477-0.0186157c-0.0113525-0.0181274-0.015686-0.0336304-0.0253296-0.0511475 c-0.026001-0.0504761-0.0529175-0.1010132-0.0684204-0.1506348c-0.0031128-0.0101929-0.0059204-0.0204468-0.0092773-0.0306396 c-0.0010376-0.0032349-0.0037231-0.0053711-0.0047607-0.008606l-3.7252197-12.5631714l-0.1323242-0.456543 c-0.0039063-0.0375977-0.0102539-0.074707-0.0185547-0.1113281c-0.0249023-0.3901367,0.2368164-0.7514648,0.6362305-0.8710938 l2.6176758-0.7695313c0.3603516-0.1015625,0.7441406,0.0283203,0.9614258,0.3271484 c0.0151367,0.0214844,0.0566406,0.078125,0.0737305,0.0981445c0.0341797,0.0678711,0.0683594,0.1425781,0.0791016,0.1674805 l3.8598633,13.0180664c0.0068359,0.0180664,0.0161133,0.0527344,0.0161133,0.1391602 C48.509697,72.3522949,48.509697,72.3562012,48.509697,72.3605957z M83.7972946,61.208252L50.2455368,71.088623 L46.943779,59.935791l33.5390625-9.8789063c3.0947266-0.909668,6.3588867,0.8496094,7.2783203,3.9257813 c0.1582031,0.5327148,0.2387695,1.0859375,0.2387695,1.6450195C87.9999313,58.2175293,86.3099899,60.4602051,83.7972946,61.208252z " /><path d="M82.1522751,50.5427246c-0.4902344,0-0.9799805,0.0712891-1.456543,0.2124023 c-0.5292969,0.1572266-0.831543,0.7133789-0.6748047,1.2431641c0.1572266,0.5292969,0.7143555,0.8310547,1.2431641,0.6748047 c1.6289063-0.4804688,3.3920898,0.496582,3.8676758,2.0874023c0.1293945,0.4335938,0.5273438,0.7138672,0.9575195,0.7138672 c0.0952148,0,0.1914063-0.0136719,0.2871094-0.0424805c0.5288086-0.1582031,0.8295898-0.715332,0.6713867-1.2446289 C86.4061813,52.0412598,84.3929977,50.5427246,82.1522751,50.5427246z" /><path d="M78.2572556,51.4729004l-2.8793945,0.847168c-0.5297852,0.15625-0.8330078,0.7119141-0.6772461,1.2416992 c0.128418,0.4355469,0.5268555,0.7182617,0.9589844,0.7182617c0.09375,0,0.1884766-0.0136719,0.2827148-0.0410156 l2.8793945-0.847168c0.5297852-0.15625,0.8330078-0.7119141,0.6772461-1.2416992 C79.3427048,51.6203613,78.784111,51.3190918,78.2572556,51.4729004z" /><path d="M72.7758102,53.0856934l-23.9584961,7.0512695c-0.5297852,0.15625-0.8330078,0.7119141-0.6772461,1.2416992 c0.128418,0.4355469,0.5268555,0.7182617,0.9589844,0.7182617c0.09375,0,0.1884766-0.0136719,0.2827148-0.0410156 l23.9584961-7.0512695c0.5297852-0.15625,0.8330078-0.7119141,0.6772461-1.2416992 C73.8607712,53.232666,73.303154,52.932373,72.7758102,53.0856934z" />
</g>
</svg>
"""
end
defp icon_class(link_assigns) do
if String.contains?(link_assigns[:class], "text-sm") or
String.contains?(link_assigns[:class], "text-xs") do
["w-3 h-3"]
else
["w-4 h-4"]
end
end
end