Merge branch 'master' of github.com:lycheeverse/lychee into quirks

This commit is contained in:
Matthias Endler 2021-03-28 23:59:41 +02:00
commit ddac9a138e
16 changed files with 790 additions and 450 deletions

428
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
[package]
authors = ["Matthias Endler <matthias-endler.de>"]
authors = ["Matthias Endler <matthias@endler.dev>"]
description = "A glorious link checker"
documentation = "https://github.com/lycheeverse/lychee/blob/master/README.md"
edition = "2018"
@ -21,46 +21,51 @@ anyhow = "1.0.38"
futures = "0.3.13"
glob = "0.3.0"
http = "0.2.3"
# Switch back to version on crates.io after 0.6.3+ is released
hubcaps = { git="https://github.com/softprops/hubcaps.git" }
hubcaps = "0.6.2"
linkify = "0.5.0"
regex = "1.4.3"
regex = "1.4.5"
url = "2.2.1"
# Switch back to version on crates.io after
# https://github.com/async-email/async-smtp/pull/36
# is merged and a new version of check-if-email-exists is released
check-if-email-exists = { git="https://github.com/reacherhq/check-if-email-exists.git" }
check-if-email-exists = "0.8.19"
indicatif = "0.15.0"
structopt = "0.3.21"
toml = "0.5.8"
serde = { version = "1.0.123", features = ["derive"] }
serde = { version = "1.0.124", features = ["derive"] }
pulldown-cmark = "0.8.0"
html5ever = "0.25.1"
markup5ever = "0.10.0"
markup5ever_rcdom = "0.1.0"
headers = "0.3.3"
headers = "0.3.4"
derive_builder = "0.9.0"
deadpool = "0.7.0"
shellexpand = "2.1.0"
lazy_static = "1.4.0"
wiremock = "0.5.0"
openssl-sys = "0.9.60"
serde_json = "1.0.62"
wiremock = "0.5.1"
openssl-sys = "0.9.61"
serde_json = "1.0.64"
# Make build work on Apple Silicon.
# See https://github.com/briansmith/ring/issues/1163
# This is necessary for the homebrew build
# https://github.com/Homebrew/homebrew-core/pull/70216
ring = "0.16.19"
ring = "0.16.20"
pad = "0.1.6"
console = "0.14.0"
console = "0.14.1"
fast_chemail = "0.9.6"
[dependencies.reqwest]
features = ["gzip"]
version = "0.11.1"
version = "0.11.2"
[dependencies.tokio]
features = ["full"]
version = "1.2.0"
version = "1.3.0"
[patch.crates-io]
# Switch to version on crates.io after resolving
# https://github.com/async-email/async-smtp/issues/40 and new version of
# check-if-email-exists is released
check-if-email-exists = { git = "https://github.com/reacherhq/check-if-email-exists.git" }
# Switch back to version on crates.io after 0.6.3+ is released
hubcaps = { git="https://github.com/softprops/hubcaps.git" }
[dev-dependencies]
assert_cmd = "1.0.3"

View file

@ -1,11 +1,10 @@
![lychee](assets/banner.png)
![lychee](assets/banner.svg)
![Rust](https://github.com/hello-rust/lychee/workflows/Rust/badge.svg)
[![docs.rs](https://docs.rs/lychee/badge.svg)](https://docs.rs/lychee)
A fast, async, resource-friendly link checker written in Rust. \
For GitHub links, it can optionally use a [`GITHUB_TOKEN`](#github-token)
to avoid getting blocked by GitHub's rate limiter.
⚡ A fast, async, resource-friendly link checker written in Rust.
Finds broken hyperlinks and mail addresses inside Markdown, HTML, reStructuredText, or any other text file or website!
Available as a CLI utility and as a GitHub Action: [lycheeverse/lychee-action](https://github.com/lycheeverse/lychee-action).
@ -149,7 +148,7 @@ token with no extra permissions is enough to be able to check public repos links
There is an extensive list of commandline parameters to customize the behavior,
see below for a full list.
```sh
```ignore
USAGE:
lychee [FLAGS] [OPTIONS] [--] [inputs]...
@ -164,7 +163,7 @@ FLAGS:
--help Prints help information
-i, --insecure Proceed for server connections considered insecure (invalid TLS)
-n, --no-progress Do not show progress bar. This is recommended for non-interactive shells (e.g. for
continuos integration)
continuous integration)
--skip-missing Skip missing input files (default is to error if they don't exist)
-V, --version Prints version information
-v, --verbose Verbose program output

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 94 KiB

View file

@ -1,48 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="banner.svg"
inkscape:version="1.0 (4035a4f, 2020-05-01)"
id="svg8"
version="1.1"
viewBox="0 0 586.12097 199.90691"
height="199.90691mm"
width="586.12097mm"
inkscape:export-filename="/Users/mendler/Code/private/hello-rust/lychee/assets/banner.png"
inkscape:export-xdpi="44.380001"
inkscape:export-ydpi="44.380001">
height="199.90691mm"
viewBox="0 0 586.12097 199.90691"
version="1.1"
id="svg8"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs2" />
<sodipodi:namedview
inkscape:window-maximized="0"
inkscape:window-y="77"
inkscape:window-x="176"
inkscape:window-height="855"
inkscape:window-width="1440"
inkscape:snap-global="false"
showgrid="false"
inkscape:document-rotation="0"
inkscape:current-layer="layer1"
inkscape:document-units="mm"
inkscape:cy="545.66352"
inkscape:cx="1147.7503"
inkscape:zoom="0.24115867"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata5">
<rdf:RDF>
@ -51,84 +20,197 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<rect
style="fill:#ffe0ee;fill-opacity:1;stroke-width:4.28731"
id="rect883"
width="587.20996"
height="199.90691"
x="5.5053711e-08"
y="4.5117185e-06" />
<path
id="path871"
style="fill:#ff1999;fill-opacity:1;stroke:none;stroke-width:0.25551px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 159.59066,103.82924 c 14.99116,0.64148 12.92677,17.69491 2.96101,19.20702 16.93678,2.36528 9.15018,21.4697 1.70316,21.06358 10.64644,11.65275 0.0968,26.02163 -12.70168,19.21259 2.90666,10.61599 -13.74135,16.18912 -17.34781,5.58646 -5.9185,17.7452 -21.96429,11.1921 -21.85763,2.91495 -5.40706,9.44335 -17.811467,3.55048 -17.760227,-3.82699 -9.48579,5.41893 -21.331274,-6.09625 -14.69728,-14.86733 -12.918854,-0.31192 -12.613544,-16.263 -2.94088,-18.52235 2.24638,0.91287 -0.91387,4.11833 -0.0264,-0.16724 -13.374104,-4.32888 -11.146094,-18.82497 -1.69642,-18.68607 -4.509104,-6.34808 2.8269,-15.13412 10.7949,-14.23361" />
<path
id="path862"
style="fill:#ffb7df;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 152.76938,101.54098 c 3.8703,0.44388 3.85972,1.63203 3.54074,5.598 -23.42417,29.83859 -83.659371,13.46178 -69.824277,-1.96893" />
<path
id="path833"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 152.51767,103.85791 C 151.75029,81.0197 138.01643,62.17493 120.09727,62.12108 94.720993,62.04478 82.401383,95.31936 88.545293,111.45584 c 17.672797,13.96638 58.792787,5.47239 63.972377,-7.59793 z" />
<circle
style="fill:#676767;fill-opacity:1;stroke:none;stroke-width:3.43958;stroke-opacity:1"
id="path885"
cx="111.76191"
cy="89.683678"
r="2.5224922" />
<circle
style="fill:#676767;fill-opacity:1;stroke:none;stroke-width:3.43958;stroke-opacity:1"
id="path887"
cx="137.11961"
cy="90.613029"
r="2.9207804" />
<path
id="path889"
style="fill:none;stroke:#676767;stroke-width:0.948181;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 120.21103,91.51671 c -0.25275,1.95289 0.36798,3.81019 2.1354,4.17244 2.62743,0.53852 3.65985,-1.30863 4.57608,-3.44058" />
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1"
aria-label="lychee"
id="text850"
style="font-size:108.204px;line-height:1.25;font-family:'Fresh Lychee';-inkscape-font-specification:'Fresh Lychee, Normal';fill:#e7008e;stroke-width:2.7051"
transform="translate(-25.769247,274.09113)">
<rect
y="-274.09113"
x="25.769247"
height="199.90691"
width="586.12097"
id="rect883"
style="fill:#ffcedc;fill-opacity:1;stroke-width:4.28334" />
<path
sodipodi:nodetypes="ccccccccccccccccccccc"
d="m 205.41812,-170.26189 c 5.73968,-1.83633 10.71807,2.94825 10.44183,8.98808 1.16945,5.44306 -5.56249,8.32534 -7.48082,10.21894 4.38191,0.65883 6.22515,5.7598 10.07669,8.41713 2.08774,5.72791 -6.30945,14.93346 -8.37353,12.64645 2.28456,4.78512 7.95572,10.33398 3.8041,15.81469 -3.35976,6.3567 -10.98205,6.50278 -16.50578,3.3979 -3.4087,-1.6627 0.4162,6.83776 -4.23743,8.23177 -4.55515,5.445409 -11.49904,2.773004 -13.11038,-2.64531 -4.47286,4.56198 -11.11975,8.519 -17.50605,5.809323 -1.03647,-3.197403 -1.48276,-7.939493 -4.35158,-2.894373 -3.70749,2.822947 -10.23638,7.642151 -14.19895,3.593554 -2.11646,-3.193094 -0.43558,-9.545184 -3.56128,-7.420544 -4.98464,-0.49777 -12.51164,2.30275 -15.11011,-3.87225 0.011,-3.08783 -1.02336,-10.22734 0.41283,-10.99508 4.08047,5.14589 -8.65383,0.22106 -8.24895,-4.02694 0.20614,-5.02569 0.74749,-11.58877 5.30807,-14.49541 2.24638,0.91287 -0.91387,4.11833 -0.0264,-0.16724 -12.68708,-9.82502 0.87671,-17.45094 -1.69642,-18.68607 -2.36408,-5.96578 1.92064,-11.13165 7.09498,-13.37919 1.11126,-0.67221 2.4178,-1.01865 3.69992,-0.85442"
style="fill:#ff1999;fill-opacity:1;stroke:none;stroke-width:0.25551px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path871" />
d="m 240.25481,-129.1122 c -5.19379,-5.62661 -1.51485,-45.01287 -1.19024,-53.77739 0,-1.19024 -0.10821,-2.27228 -0.21641,-3.46253 -0.86563,-5.19379 -7.46608,-6.60044 -10.06297,-1.51485 -6.16763,12.11884 -13.3091,53.01996 -1.29845,64.16497 2.92151,2.48869 7.24967,3.46253 10.7122,2.16408 3.13791,-1.40665 4.76097,-5.4102 2.05587,-7.57428 z"
id="path5637" />
<path
d="m 199.12601,-174.13765 c 3.8703,0.44388 7.10914,3.93435 6.79016,7.90032 -0.23033,6.09786 -5.17987,12.28447 -11.53633,12.48063 -13.01153,4.47015 -26.6342,8.99312 -40.58802,7.51302 -3.06238,-0.14386 -5.71371,-1.8906 -8.68653,-2.50943 -6.35416,-1.80648 -13.30378,-3.17853 -18.19729,-7.97424 -1.82929,-3.41057 -1.5228,-8.78266 2.16174,-10.82836 0.8996,-0.42085 1.92878,-0.49394 2.90005,-0.33485"
style="fill:#ffb7df;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path862" />
d="m 246.45794,-142.96231 c 2.92151,11.57782 15.90599,15.14856 23.04746,3.89534 1.51485,-2.27228 2.8133,-4.86918 4.00354,-7.24967 0.21641,4.43637 0.10821,12.44346 -2.05587,18.17827 -1.51486,4.00355 -5.73481,9.08914 -7.89889,2.4887 -0.54102,-1.73127 -1.73127,-2.81331 -3.46253,-3.02972 -2.05588,-0.1082 -3.46253,0.64923 -4.32816,2.05588 -1.40665,2.8133 -0.75743,6.05942 0.1082,9.08914 3.78714,12.76807 21.42439,11.68603 27.051,-0.97384 4.65278,-10.60399 1.08204,-28.24124 -0.86563,-37.43858 -1.73126,-7.35788 -7.89889,-6.70865 -9.95477,-0.86564 -1.51485,3.57074 -3.13791,6.60045 -4.43636,8.87273 -12.33526,21.5326 -8.0071,-8.87273 -1.94767,-17.31264 2.9215,-4.32816 -3.13792,-8.33171 -9.41375,-5.08559 -8.1153,3.89535 -12.55167,17.09624 -9.84657,27.37562 z"
id="path5639" />
<path
d="m 198.34513,-170.23322 c -0.36573,-13.08432 -3.59266,-27.038 -13.13134,-36.57849 -6.85312,-7.34588 -18.33298,-9.50341 -27.49036,-5.51492 -11.96233,4.59013 -20.23806,16.29278 -22.25798,28.74033 -1.76308,7.33178 -4.42543,15.28949 -1.43621,22.66855 1.80765,3.80438 6.46465,4.69343 10.27841,4.71683 7.81569,1.55095 15.77211,2.7791 23.76125,2.10384 8.99133,-0.59516 18.07387,-2.42539 26.17569,-6.45589 2.62857,-1.77642 6.01594,-4.60956 4.96884,-8.17829 -0.19337,-0.549 -0.5008,-1.05273 -0.8683,-1.50196 z"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path833" />
<circle
r="2.5224922"
cy="-184.40746"
cx="157.58937"
id="path885"
style="fill:#676767;fill-opacity:1;stroke:none;stroke-width:3.43958;stroke-opacity:1" />
<circle
r="2.9207804"
cy="-183.4781"
cx="182.94707"
id="path887"
style="fill:#676767;fill-opacity:1;stroke:none;stroke-width:3.43958;stroke-opacity:1" />
d="m 310.31014,-164.2785 c 1.40666,-3.02971 5.51841,-8.22351 5.84302,-5.19379 0.75743,6.81685 8.65632,7.03326 9.30554,-2.27229 0.21641,-2.8133 -0.2164,-4.97738 -1.29844,-6.70865 -2.92151,-4.65277 -8.54812,-5.73481 -13.85012,-4.54456 -7.79068,1.73126 -13.41729,8.87272 -16.2306,16.447 -3.78714,9.95477 -3.35432,22.18182 1.40665,31.37916 6.81686,12.98448 21.4244,12.33526 26.29358,-2.59689 1.08204,-3.35433 1.73126,-6.81685 2.05587,-9.73836 0.43282,-5.302 -5.08558,-6.92506 -6.38403,-1.08204 -1.94767,20.55876 -8.76453,14.28293 -10.06297,2.27228 -0.64923,-6.70865 -0.43282,-10.8204 2.9215,-17.96186 z"
id="path5641" />
<path
d="m 166.03849,-182.57442 c -0.42159,1.67148 0.62783,3.44936 2.1354,4.17244 0.76566,0.3718 1.73119,0.61263 2.51272,0.14886 0.97558,-0.50957 1.38766,-1.59754 1.69489,-2.58738 0.11095,-0.33816 0.22305,-0.6768 0.36847,-1.00206"
style="fill:none;stroke:#676767;stroke-width:0.948181;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path889" />
d="m 349.39207,-129.97783 c 0.86564,-2.16408 3.24612,-22.50644 8.22351,-19.26032 5.19379,3.46253 2.59689,14.28293 4.54457,19.69313 2.27228,6.16763 10.8204,5.302 9.84656,-0.43281 -1.29845,-7.46608 -0.54102,-15.25677 -3.78714,-22.50644 -3.57073,-7.89889 -12.55166,-8.43991 -17.63725,-2.27228 -4.11175,4.97738 -4.21996,5.302 -4.32816,0.97384 0,-9.84657 0.21641,-19.47672 1.08204,-29.86431 0,-9.08914 -8.0071,-9.30554 -11.46963,-1.51485 -3.24612,7.46607 -7.46607,35.3827 -2.9215,51.3969 1.29844,4.32816 3.57073,10.38758 9.30554,9.73836 2.92151,-0.21641 5.84302,-2.38049 7.14146,-5.95122 z"
id="path5643" />
<path
d="m 116.13536,-201.43298 c -6.07872,-5.52471 -14.04203,-9.06105 -19.746769,-14.93996 -1.478172,-1.94696 -3.526762,-4.36574 -6.476167,-3.9045"
style="fill:none;fill-opacity:1;stroke:#fff554;stroke-width:5.01895;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path939" />
<path
d="m 131.70064,-206.04778 c -6.75239,-4.75454 -5.80151,-14.22359 -10.79083,-20.29921 -3.76452,-6.02587 -8.297,-11.57407 -11.51331,-17.93646"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#fff554;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path943" />
<path
d="m 119.34415,-185.29021 c -11.32811,3.30421 -22.738879,8.18098 -34.179824,8.53942 -3.411169,0.77919 -6.678853,3.08383 -10.14384,3.05053"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#fff554;stroke-width:7.98358;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path951" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:108.204px;line-height:1.25;font-family:sans-serif;fill:#010001;fill-opacity:1;stroke:none;stroke-width:2.7051"
x="247.01997"
y="-133.84195"
id="text850"><tspan
sodipodi:role="line"
id="tspan848"
x="247.01997"
y="-133.84195"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.204px;font-family:'sweet purple';-inkscape-font-specification:'sweet purple, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#010001;fill-opacity:1;stroke-width:2.7051">lychee</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:34.4503px;line-height:1.25;font-family:'Signatra DEMO';-inkscape-font-specification:'Signatra DEMO, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.861259"
x="240.99301"
y="-211.8911"
id="text854"><tspan
sodipodi:role="line"
id="tspan852"
x="240.99301"
y="-211.8911"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:34.4503px;font-family:'Signatra DEMO';-inkscape-font-specification:'Signatra DEMO, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.861259">Introducing the glorious</tspan></text>
d="m 391.5426,-144.47717 c 6.92505,2.38049 14.49933,-3.78714 15.68958,-10.8204 3.89534,-20.77517 -20.66697,-19.36852 -26.9428,-2.48869 -3.13792,8.54811 -2.5969,18.17827 1.29845,24.99512 6.70865,11.79424 18.61109,9.84657 25.64435,-2.7051 2.48869,-4.32816 -1.08204,-10.38758 -4.76098,-3.35432 -4.54457,7.89889 -13.95831,11.03681 -10.9286,-5.62661 z m 1.08204,-6.38404 c 0.54102,-5.4102 4.76097,-14.06652 7.89889,-13.20088 4.32816,4.65277 -0.21641,12.55166 -7.89889,13.20088 z m 31.92018,6.16763 c 8.65632,0.43282 13.6337,-8.43991 11.79423,-16.77162 -0.86563,-3.89534 -3.57073,-8.43991 -8.87272,-8.33171 -4.97739,0.32462 -9.41375,4.00355 -11.46963,8.87273 -3.46253,7.79069 -4.65277,20.88337 -0.32461,28.78227 4.86918,9.08913 16.98803,9.08913 20.55876,-2.27229 0.75743,-2.48869 1.19024,-5.30199 1.40665,-7.79069 0.64923,-4.11175 -4.54457,-4.32816 -5.4102,-0.75742 -0.75743,2.9215 -1.19024,4.65277 -1.94767,7.24966 -2.8133,6.81686 -6.81685,-1.94767 -5.73481,-8.98093 z m 0.54102,-6.70865 c 1.08204,-4.11175 2.59689,-7.79068 4.65277,-10.9286 3.67894,2.92151 1.94767,10.9286 -4.65277,10.9286 z"
id="path5645" />
</g>
<g
aria-label="Introducing the glorious"
id="text854"
style="font-size:34.4503px;line-height:1.25;font-family:Authentic;-inkscape-font-specification:'Authentic, Normal';fill:#a40b73;stroke-width:0.861259"
transform="translate(-25.769247,274.09113)">
<path
d="m 227.44083,-206.70145 h -0.0336 l -0.0336,0.0168 q -0.42054,0 -0.80743,-0.50464 -0.16822,-0.21868 -0.16822,-0.37007 0.0336,-0.13458 0.16822,-0.16822 0,0 0.18503,-0.0336 2.65779,-0.38689 4.77729,-0.63922 0.471,-3.78482 7.065,-19.56332 0.63922,-1.53076 1.22797,-2.91011 -0.62239,0.0841 -1.27843,0.16821 -0.65604,0.0841 -1.16068,0.16822 -0.48782,0.0673 -0.89154,0.13457 -0.40371,0.0505 -0.62239,0.0841 l -0.21868,0.0336 h -0.0673 q -0.42054,0 -0.82425,-0.50465 -0.1514,-0.21867 -0.16822,-0.37007 0.0336,-0.13457 0.16822,-0.16821 0,0 0.13457,-0.0168 3.04468,-0.471 5.43332,-0.74015 0.21868,-0.45418 0.43736,-0.471 0.2355,0.0168 0.60557,0.37007 1.85036,-0.18503 2.89329,-0.18503 0.5551,0 0.77378,0.0336 0.84107,0.10093 1.22797,0.68968 0.11775,0.18504 0.11775,0.30279 -0.0336,0.15139 -0.1514,0.18503 h -0.0336 q -0.0505,0 -0.18503,-0.0336 -0.52147,-0.13457 -1.02611,-0.13457 h -0.0505 q -1.39617,0.0336 -3.51568,0.26914 -6.07253,14.18047 -8.02382,20.57262 -0.35325,1.14385 -0.52146,1.91764 2.00175,-0.21868 3.19607,-0.21868 0.42053,0 0.85789,0.0673 0.72332,0.11775 1.11022,0.7906 0.11775,0.18504 0.11775,0.30279 -0.0168,0.0673 -0.0505,0.0841 -0.0336,-0.0168 -0.0673,-0.0336 -0.31961,-0.15139 -1.29525,-0.15139 -1.11022,0 -4.03715,0.31961 -0.0336,0.40371 -0.26914,0.42053 -0.26914,-0.0168 -0.60557,-0.3196 -0.63922,0.0841 -1.3289,0.16821 -0.68968,0.10093 -1.21114,0.16822 -0.52146,0.0673 -0.95882,0.13457 -0.42054,0.0673 -0.65604,0.10093 z"
id="path5765" />
<path
d="m 242.24369,-220.47821 q 0.0673,-0.0841 0.18504,-0.10093 0.37007,0 0.79061,0.45418 0.20186,0.2355 0.21868,0.40372 0,0.0505 -0.0336,0.10093 -0.0168,0.0336 -1.74943,3.43157 3.24654,-3.14561 4.40722,-3.63343 0.13457,-0.0505 0.2355,-0.0841 0.21868,-0.0505 0.38689,-0.0505 0.79061,0.0168 1.3289,0.65603 0.43735,0.52147 0.43735,1.74943 0,0.3869 -0.18503,2.08586 -0.0168,0.18504 -0.0168,0.26914 0,0.10093 0.0336,0.13458 0.0336,0.0168 0.0505,0.0168 0.58875,0 4.1549,-2.67461 0.471,-0.35325 0.60557,-0.471 0.0505,-0.0336 0.11775,-0.0336 0.30279,0 0.63921,0.53828 0.16822,0.28597 0.16822,0.48782 -0.0168,0.11775 -0.0841,0.20186 -1.68214,1.37936 -2.355,1.81672 -1.56439,1.00928 -2.60732,1.00928 -0.60557,-0.0168 -1.05975,-0.33643 -0.79061,-0.63921 -0.79061,-1.98493 0,-0.38689 0.0673,-1.16068 0.0673,-0.72332 0.0673,-1.04292 v -0.18504 q -0.99246,0.25232 -3.91939,3.07832 -2.28772,2.20361 -2.64097,2.5064 -0.57193,0.471 -0.77378,0.48782 -0.95883,-0.0841 -1.00929,-0.90836 0,-0.35325 3.33064,-6.76222 z"
id="path5767" />
<path
d="m 257.70259,-232.11864 q 0.10093,-0.26914 0.60558,0.0168 0.0673,0.0336 0.10092,0.0505 0.471,0.3196 0.48783,0.65603 -0.0168,0.0505 -0.0168,0.0841 0,0 -0.16821,0.48782 -0.97564,2.80918 -1.78307,5.26511 9.62186,-0.95882 13.38986,0.75696 0.48782,0.21868 0.63921,0.63922 0.0168,0.0505 0.0337,0.0841 0.0505,0.25232 -0.21868,0.25232 -0.13457,-0.0168 -0.28597,-0.0841 -3.68389,-1.68214 -13.92814,-0.48782 -0.3869,1.19432 -1.27843,3.81846 -3.14561,9.42001 -3.90258,12.6329 -0.471,2.0354 -0.40371,2.87647 0.0168,0.28596 -0.35325,0.20185 -0.11775,-0.0336 -0.21868,-0.0841 -0.48782,-0.2355 -0.62239,-0.63922 -0.0168,-0.0673 -0.0168,-0.10093 -0.1514,-1.884 2.69143,-10.66478 0.43735,-1.3289 1.32889,-4.02033 0.87471,-2.62414 1.26161,-3.83528 -1.37936,0.18503 -2.80918,0.42053 -1.42982,0.21868 -2.48958,0.42054 -1.07657,0.18503 -1.93446,0.35325 -0.85789,0.16821 -1.32889,0.26914 l -0.45418,0.0841 q -0.33643,0.0841 -0.77379,-0.35325 -0.0505,-0.0505 -0.0841,-0.0841 -0.0336,-0.0505 -0.0673,-0.0841 -0.0505,-0.0505 -0.0673,-0.10093 -0.0336,-0.0505 -0.0505,-0.0841 -0.0168,-0.0336 -0.0168,-0.0673 -0.0168,-0.0505 -0.0168,-0.0841 0,-0.0336 0.0168,-0.0505 0,-0.0336 0.0336,-0.0505 0.0168,-0.0336 0.0505,-0.0505 0.0168,-0.0168 0.0505,-0.0168 0,0 0.16821,-0.0336 5.23147,-1.07658 10.16015,-1.66533 0.55511,-1.69896 1.12704,-3.3811 0.57192,-1.69897 0.85789,-2.52322 z"
id="path5769" />
<path
d="m 266.24788,-218.10638 q 0.2355,-0.21868 0.67286,0.2355 0.43736,0.45417 0.26914,0.7065 -0.0336,0.0168 -0.0336,0.0336 -0.13457,0.11775 -2.25407,2.45593 -3.70072,4.05396 -5.11372,4.44086 -0.3196,0.0673 -0.53828,0 -0.55511,-0.20186 -0.90836,-0.7065 -0.63922,-0.95882 1.42982,-4.72683 0.15139,-0.28596 0.471,-0.84107 0.42054,-0.75696 0.55511,-1.02611 -2.06904,0.6224 -3.19607,-0.15139 -1.05975,-0.72332 -0.80743,-2.08586 0.18503,-1.05975 0.95882,-1.63168 0.25232,-0.18503 0.50464,-0.25232 0.68968,-0.20185 1.3289,0.471 0.35325,0.3869 0.45417,0.80743 0.13458,0.75697 -0.40371,1.884 0.13457,-0.0336 0.48782,-0.16821 0.84107,-0.30279 1.07657,-0.30279 0.79061,0.0673 1.11022,0.82425 0.18503,0.50465 -1.1775,3.02786 -1.39618,2.60732 -1.6485,3.22972 -0.13457,0.37007 -0.18504,0.60557 1.12704,-0.52147 4.44086,-4.12125 2.16996,-2.37183 2.50639,-2.70825 z m -8.34343,-0.2355 q 0.79061,-1.21115 0.942,-2.08586 -0.38689,0.31961 -0.67286,0.942 -0.18503,0.37007 -0.28596,0.90836 -0.0168,0.18503 0.0168,0.2355 z"
id="path5771" />
<path
d="m 268.11506,-218.79606 q 0.3869,0.33643 0.40372,0.52146 0,0.11775 -0.31961,0.26914 -0.18504,0.0841 -0.25232,0.13458 0.26914,0.89153 1.54757,1.1775 0.67286,-1.21115 0.67286,-2.1195 0,-0.35325 -0.11775,-0.55511 -0.0505,-0.0505 -0.20186,-0.0505 -0.75696,0 -1.413,0.35325 -0.21868,0.13458 -0.31961,0.26915 z m -1.39618,0.11775 q 0,-0.0336 -0.0168,-0.10093 0,-0.0505 0,-0.0841 0,-1.00928 1.11022,-1.39618 0.45418,-0.16821 0.97564,-0.16821 1.21114,0.0168 1.86718,0.65603 0.68968,0.67286 0.68968,1.74943 0,0.63922 -0.28597,1.31207 1.91765,-0.37007 3.34747,-1.53075 0.0673,-0.0505 0.15139,-0.0505 0.35325,0 0.7065,0.471 0.16822,0.21868 0.18504,0.38689 -0.0168,0.10093 -0.0841,0.1514 -2.08586,1.68214 -4.37357,1.68214 -0.31961,0 -0.471,-0.0168 -1.51393,2.45593 -3.54933,2.45593 -0.87471,0 -1.39617,-0.37007 -0.0337,-0.0505 -0.0505,-0.0673 -0.85789,-0.62239 -0.85789,-1.59804 0,-1.32889 1.37936,-2.84282 0.33642,-0.37007 0.67285,-0.63921 z m 0.6224,1.37935 q -1.16068,1.24479 -1.44665,2.37183 -0.0336,0.18503 -0.0505,0.33643 -0.0168,0.30278 0,0.38689 0.2355,0.10093 0.48782,0.10093 1.04293,0 2.27089,-1.36254 0.2355,-0.26914 0.43736,-0.53828 -1.04293,-0.48783 -1.69896,-1.29526 z"
id="path5773" />
<path
d="m 280.63021,-219.53621 q -0.0168,-0.0168 -0.0673,-0.0505 -0.0336,-0.0168 -0.0505,-0.0336 -0.0673,0.13457 -0.26914,0.50464 -1.91765,3.54932 -3.24654,4.69318 -0.77379,0.65604 -1.413,0.65604 -0.43736,-0.0168 -0.77379,-0.25233 -0.942,-0.75696 -0.95882,-2.28771 0,-0.79061 0.31961,-1.66532 0.79061,-2.08586 2.355,-2.87647 0.74014,-0.37007 1.54757,-0.37007 0.74014,0 1.51393,0.31961 2.47275,-4.45768 5.14736,-10.42929 l 0.0336,-0.0505 q 0.0673,-0.10092 0.20186,-0.11775 0.37007,0 0.79061,0.40372 0.26914,0.26914 0.20185,0.45418 -2.5905,6.45943 -4.89503,13.45714 -2.35501,7.18276 -2.35501,9.3359 0,0.10093 0.0337,0.25232 0.0168,0.13457 0.0168,0.20186 -0.0336,0.15139 -0.20186,0.16821 -0.38689,0 -0.79061,-0.40371 -0.18503,-0.20186 -0.21867,-0.38689 -0.0337,-0.16822 -0.0337,-0.53829 0,-2.27089 2.72508,-9.92465 0.18503,-0.50464 0.38689,-1.05975 z m -1.46347,-0.60557 q -0.20185,-0.0336 -0.30278,-0.0336 -1.46347,0 -2.72507,1.69896 -1.04293,1.413 -1.19433,2.80918 -0.0168,0.16822 -0.0168,0.30279 0,0.35325 0.10093,0.60557 1.27843,-0.38689 4.13807,-5.38286 z"
id="path5775" />
<path
d="m 286.33268,-220.79781 q 0.0673,-0.0841 0.18503,-0.0841 0.37007,0 0.77379,0.43736 0.20186,0.25232 0.21868,0.42053 0,0.0673 -0.0336,0.11775 -1.34571,1.90082 -1.90082,3.58297 -0.2355,0.7065 -0.2355,1.21114 0,0.11775 0.0336,0.30279 1.36254,-0.471 4.07079,-4.0035 0.57193,-0.74015 0.99247,-1.34572 0.13457,-0.16821 0.3196,-0.18504 0.40372,0 0.74015,0.50465 0.15139,0.2355 0.15139,0.38689 -0.0168,0.0841 -0.0505,0.13457 -0.45418,1.37936 -0.70651,2.99422 -0.0841,0.53828 -0.0841,0.89153 0.0168,0.48783 0.16821,0.58875 0.13457,0.0841 0.3869,0.0841 1.14385,0 3.65025,-1.85036 1.32889,-0.99246 1.79989,-1.56439 0.10093,-0.0841 0.16821,-0.0841 0.35325,0 0.72333,0.45418 0.16821,0.2355 0.18503,0.38689 -0.0168,0.0841 -0.0505,0.13458 -0.99247,1.21114 -2.65779,2.28771 -1.83354,1.1775 -3.17925,1.1775 -0.7065,-0.0168 -1.21114,-0.33643 -1.14386,-0.77378 -1.14386,-2.355 v -0.2355 q -2.08586,2.5064 -3.297,2.96057 -0.0336,0 -0.0673,0.0168 -0.15139,0.0505 -0.31961,0.0505 -0.67285,-0.0168 -1.2616,-0.65604 -0.50465,-0.58875 -0.50465,-1.44664 0,-1.93446 2.13633,-4.97914 z"
id="path5777" />
<path
d="m 301.74111,-218.19049 q -0.0841,0.16821 -0.2355,0.18503 -0.37007,0 -0.77379,-0.50464 -0.2355,-0.30278 -0.18503,-0.48782 l 0.2355,-0.68968 q -0.95882,0.18504 -2.23725,1.59804 -1.44665,1.58121 -1.69897,2.96057 -0.0505,0.2355 -0.0505,0.43736 0.0168,0.42053 0.20186,0.72332 0.21867,0.0505 0.42053,0.0505 1.63168,0 5.66883,-2.65778 0.35325,-0.21868 1.0261,-0.67286 1.0934,-0.74014 1.49711,-0.97564 0.0841,-0.0505 0.13457,-0.0505 0.3869,0 0.80743,0.48782 0.16822,0.2355 0.18504,0.3869 -0.0168,0.11775 -0.0841,0.15139 -0.43736,0.26914 -1.56439,1.02611 -3.22972,2.15314 -4.82776,2.826 -1.2616,0.52146 -2.15314,0.52146 -0.16821,0 -0.42054,-0.0336 -1.09339,-0.18504 -1.69896,-1.1775 -0.28596,-0.471 -0.35325,-0.99247 -0.0168,-0.10092 -0.0168,-0.25232 0,-1.413 1.32889,-3.14561 1.27843,-1.63167 2.69143,-2.15314 0.45418,-0.15139 0.84107,-0.15139 0.90836,0.0168 1.42982,0.80743 0.16822,0.26914 0.16822,0.57193 0,0.25232 -0.28597,1.07657 -0.0336,0.0841 -0.0505,0.13457 z"
id="path5779" />
<path
d="m 306.70343,-220.52867 q 0.0673,-0.10093 0.18504,-0.11775 0.37007,0 0.79061,0.45418 0.20185,0.2355 0.21867,0.40371 0,0.0505 -0.0336,0.10093 -1.46346,3.09514 -1.61486,4.81093 -0.0168,0.15139 -0.0168,0.28597 0,0.2355 0.0673,0.48782 h 0.0336 q 1.39618,0 4.13807,-2.80918 0.7065,-0.74015 1.21115,-1.34572 0.0505,-0.0673 0.13457,-0.0673 0.28596,0 0.60557,0.50464 0.16821,0.26914 0.16821,0.471 -0.0168,0.0841 -0.0673,0.18504 -3.39793,4.03714 -5.46697,4.10443 -0.18503,0 -0.471,-0.0673 -0.80743,-0.2355 -1.24478,-0.95882 -0.28597,-0.471 -0.28597,-1.21114 0,-1.78308 1.6485,-5.23147 z m 1.86718,-0.75697 q -0.0673,0.0841 -0.18503,0.10093 -0.37008,0 -0.77379,-0.43735 -0.20186,-0.25233 -0.21868,-0.42054 0,-0.0505 0.0336,-0.11775 l 1.39618,-2.23725 q 0.0673,-0.0841 0.20186,-0.0841 0.38689,0 0.79061,0.45418 0.18503,0.21868 0.20185,0.38689 0,0.0505 -0.0336,0.11775 z"
id="path5781" />
<path
d="m 312.69186,-220.47821 q 0.0673,-0.0841 0.18504,-0.10093 0.37007,0 0.7906,0.45418 0.20186,0.2355 0.21868,0.40372 0,0.0505 -0.0336,0.10093 -0.0168,0.0336 -1.74943,3.43157 3.24654,-3.14561 4.40722,-3.63343 0.13457,-0.0505 0.2355,-0.0841 0.21867,-0.0505 0.38689,-0.0505 0.79061,0.0168 1.32889,0.65603 0.43736,0.52147 0.43736,1.74943 0,0.3869 -0.18504,2.08586 -0.0168,0.18504 -0.0168,0.26914 0,0.10093 0.0336,0.13458 0.0336,0.0168 0.0505,0.0168 0.58875,0 4.15489,-2.67461 0.471,-0.35325 0.60558,-0.471 0.0505,-0.0336 0.11775,-0.0336 0.30278,0 0.63921,0.53828 0.16821,0.28597 0.16821,0.48782 -0.0168,0.11775 -0.0841,0.20186 -1.68215,1.37936 -2.355,1.81672 -1.5644,1.00928 -2.60733,1.00928 -0.60557,-0.0168 -1.05975,-0.33643 -0.7906,-0.63921 -0.7906,-1.98493 0,-0.38689 0.0673,-1.16068 0.0673,-0.72332 0.0673,-1.04292 v -0.18504 q -0.99247,0.25232 -3.9194,3.07832 -2.28771,2.20361 -2.64096,2.5064 -0.57193,0.471 -0.77379,0.48782 -0.95882,-0.0841 -1.00928,-0.90836 0,-0.35325 3.33064,-6.76222 z"
id="path5783" />
<path
d="m 328.18441,-220.37728 q 0.26914,0.0673 0.57193,0.30279 0.2355,-0.31961 0.53828,-0.79061 0.33643,-0.50464 1.04293,0.15139 0.20186,0.20186 0.31961,0.37007 0.42053,0.65604 -0.53829,4.18854 -0.0673,0.2355 -0.13457,0.45418 1.54757,-0.95882 3.12879,-1.884 0.72332,-0.42054 1.02611,-0.60557 0.25232,-0.15139 0.74014,0.21868 0.0505,0.0505 0.0841,0.0841 0.42053,0.40372 0.28596,0.63922 -0.0336,0.0336 -0.0505,0.0505 -0.37008,0.2355 -1.02611,0.60557 -3.02786,1.78308 -4.82775,2.96058 -1.98493,5.98843 -4.239,9.52093 -0.75697,1.21114 -1.48029,1.96811 -1.85036,1.91764 -3.5325,0.37007 -4.87822,-4.239 7.50236,-12.3974 0.18503,-0.13457 0.60557,-0.40371 0.82425,-2.45593 1.1775,-3.90258 -2.27089,3.02786 -3.78482,3.54933 -1.49711,0.50464 -2.13633,-0.74015 -0.13457,-0.30278 -0.21867,-0.65603 -0.37008,-1.61486 1.0261,-2.87647 1.22797,-1.11021 2.94375,-1.22796 0.52147,-0.0168 0.97565,0.0505 z m 0.0841,0.97565 q -1.36254,-0.0673 -2.60733,0.89153 -1.27843,1.00929 -1.27843,2.2709 0,0.2355 0.0505,0.45417 0.11775,0.471 3.16243,-2.85964 0.57193,-0.63921 0.67286,-0.75696 z m -5.75294,16.33361 q 2.16997,-2.28772 4.64272,-8.61258 0.13457,-0.33642 0.25232,-0.65603 -5.73611,4.03714 -7.16593,6.93043 -0.97564,2.01857 0.37007,3.19607 l 0.0673,0.0673 q 0.52146,0.25232 1.42982,-0.53829 0.20186,-0.18503 0.40371,-0.38689 z"
id="path5785" />
<path
d="m 358.29477,-218.15685 q 0.28597,-0.18503 0.80743,0.28597 0.48783,0.43735 0.28597,0.65603 -0.0168,0.0336 -0.0336,0.0336 -0.16822,0.10093 -0.57193,0.37008 -2.32136,1.56439 -3.58297,1.93446 -1.63168,0.48782 -2.52321,-0.40371 -0.77379,-0.77379 -0.87472,-2.67461 -0.0168,-0.11775 -0.0336,-0.63922 -1.19432,0.74015 -3.22972,3.6839 -1.73261,2.52321 -1.93446,2.77554 -0.21868,0.28596 -0.40372,0.48782 -0.42053,0.30278 -0.97564,-0.18504 -0.43736,-0.42053 -0.42054,-0.87471 0.10093,-1.6485 4.74365,-14.01226 -1.34572,0.77379 -3.11197,1.46347 -6.07253,17.35972 -5.82021,20.47168 0.0168,0.28597 -0.37007,0.18504 -0.10093,-0.0336 -0.20186,-0.0841 -0.48782,-0.2355 -0.6224,-0.63921 -0.0168,-0.0673 -0.0168,-0.10093 -0.2355,-3.09515 5.34922,-19.2269 -4.42404,1.48028 -9.31908,2.23725 -0.21867,0.0336 -0.25232,0.0336 -0.35325,0.0505 -0.7906,-0.38689 -0.0337,-0.0505 -0.0673,-0.0841 -0.0505,-0.0673 -0.0841,-0.13457 -0.0505,-0.0673 -0.0673,-0.13457 -0.0337,-0.0673 -0.0337,-0.11775 0,-0.0505 0.0168,-0.0841 0.0168,-0.0336 0.0673,-0.0673 0.0336,-0.0337 0.0841,-0.0337 0.38689,0 2.99421,-0.53828 4.59226,-0.92518 7.99019,-2.23725 0.50464,-1.44665 1.00928,-2.85965 0.52147,-1.42982 0.77379,-2.10268 l 0.25232,-0.68968 q 0.10093,-0.26914 0.58875,0.0168 0.0673,0.0336 0.11775,0.0673 0.471,0.31961 0.48782,0.65604 -0.0168,0.0505 -0.0168,0.0841 -0.0168,-0.0168 -1.48029,4.10443 2.10268,-0.97564 3.39793,-2.1195 0.21868,-0.57193 0.3869,-1.00928 0.16821,-0.45418 0.28596,-0.79061 0.13457,-0.33643 0.20186,-0.52146 l 0.0673,-0.16822 q 0.11775,-0.30278 0.68968,0.0673 0.18504,0.13457 0.31961,0.26914 0.11775,0.0505 0.30279,0.16821 0.52146,0.3869 0.48782,0.7065 -0.0168,0.0168 -0.0168,0.0336 -0.40372,1.05975 -1.5644,2.1195 -3.41475,9.01629 -4.89504,13.59172 0.20186,-0.26915 0.65604,-0.942 2.01857,-2.91011 2.96057,-3.73436 0.1514,-0.13457 0.28597,-0.2355 0.58875,-0.42054 1.16068,-0.10093 1.00928,0.57193 1.19432,1.81671 0.0336,0.21868 0.0505,0.67286 0.0841,0.97565 0.26915,1.39618 1.14385,0.0673 5.0296,-2.45593 z"
id="path5787" />
<path
d="m 358.56392,-215.49906 q -0.26914,0.13457 -0.26914,0.75696 0.0168,0.58875 0.33643,0.7065 0.3196,0.10093 0.68967,0.10093 2.11951,0 5.95479,-2.80918 0.99247,-0.72332 1.74943,-1.39618 0.0673,-0.0505 0.13457,-0.0505 0.33643,0 0.68968,0.50464 0.18504,0.26914 0.18504,0.45418 -0.0168,0.10093 -0.0673,0.16821 -0.40371,0.40372 -1.78307,1.39618 -3.81847,2.7419 -6.15665,2.75872 -0.30278,0 -0.43735,-0.0168 -2.13632,-0.28597 -2.37182,-1.95129 -0.0337,-0.18503 -0.0337,-0.37007 0,-1.53075 1.31207,-3.24654 1.19433,-1.56439 2.48958,-1.98493 0.28596,-0.0841 0.53828,-0.10093 h 0.0673 q 0.79061,0 1.34571,0.68968 0.35325,0.45418 0.35325,0.92518 -0.0168,0.33643 -0.16821,0.6224 -0.16822,0.30278 -0.52147,0.62239 -0.33642,0.31961 -0.75696,0.58875 -0.40371,0.26914 -0.87471,0.52146 -0.45418,0.25233 -0.87472,0.45418 -0.42054,0.20186 -0.77379,0.35325 -0.33642,0.1514 -0.53828,0.21868 z m 0.942,-1.86718 q 2.27089,-1.16068 2.55686,-2.1195 -0.99247,0.30278 -2.22043,1.71578 -0.18504,0.20186 -0.33643,0.40372 z"
id="path5789" />
<path
d="m 380.12899,-220.37728 q 0.26914,0.0673 0.57193,0.30279 0.2355,-0.31961 0.53828,-0.79061 0.33643,-0.50464 1.04293,0.15139 0.20186,0.20186 0.31961,0.37007 0.42053,0.65604 -0.53829,4.18854 -0.0673,0.2355 -0.13457,0.45418 1.54757,-0.95882 3.12879,-1.884 0.72332,-0.42054 1.02611,-0.60557 0.25232,-0.15139 0.74014,0.21868 0.0505,0.0505 0.0841,0.0841 0.42053,0.40372 0.28596,0.63922 -0.0336,0.0336 -0.0505,0.0505 -0.37008,0.2355 -1.02611,0.60557 -3.02786,1.78308 -4.82775,2.96058 -1.98493,5.98843 -4.239,9.52093 -0.75697,1.21114 -1.48029,1.96811 -1.85036,1.91764 -3.5325,0.37007 -4.87822,-4.239 7.50236,-12.3974 0.18503,-0.13457 0.60557,-0.40371 0.82425,-2.45593 1.1775,-3.90258 -2.27089,3.02786 -3.78482,3.54933 -1.49711,0.50464 -2.13632,-0.74015 -0.13458,-0.30278 -0.21868,-0.65603 -0.37008,-1.61486 1.0261,-2.87647 1.22797,-1.11021 2.94375,-1.22796 0.52147,-0.0168 0.97565,0.0505 z m 0.0841,0.97565 q -1.36254,-0.0673 -2.60733,0.89153 -1.27843,1.00929 -1.27843,2.2709 0,0.2355 0.0505,0.45417 0.11775,0.471 3.16243,-2.85964 0.57193,-0.63921 0.67286,-0.75696 z m -5.75294,16.33361 q 2.16997,-2.28772 4.64272,-8.61258 0.13457,-0.33642 0.25232,-0.65603 -5.73611,4.03714 -7.16593,6.93043 -0.97564,2.01857 0.37007,3.19607 l 0.0673,0.0673 q 0.52146,0.25232 1.42982,-0.53829 0.20186,-0.18503 0.40371,-0.38689 z"
id="path5791" />
<path
d="m 392.9301,-218.20731 q 0.0841,-0.0505 0.16822,-0.0505 0.35325,0 0.7065,0.48782 0.18503,0.2355 0.18503,0.40372 -0.0168,0.13457 -0.0505,0.16821 -0.82425,0.60557 -3.63343,3.78483 -2.91011,3.31382 -3.83529,4.0876 -0.57193,0.48783 -0.84107,0.50465 h -0.11775 q -1.44664,-0.0336 -1.46346,-1.83354 0,-3.12879 5.652,-16.78779 0.16821,-0.43736 0.42053,-1.02611 1.11022,-2.65778 1.26161,-3.11196 0.0673,-0.11775 0.18504,-0.11775 0.38689,0 0.7906,0.42053 0.20186,0.2355 0.21868,0.42054 0,0.35325 -0.79061,2.13632 -0.30278,0.67286 -0.48782,1.09339 -4.239,10.29472 -5.43332,14.44962 -0.58875,2.08585 -0.60557,3.12878 1.16068,-0.77378 3.73436,-3.768 2.65778,-3.09514 3.39793,-3.85211 0.28596,-0.30278 0.53828,-0.53828 z"
id="path5793" />
<path
d="m 394.74683,-218.79606 q 0.38689,0.33643 0.40371,0.52146 0,0.11775 -0.31961,0.26914 -0.18503,0.0841 -0.25232,0.13458 0.26914,0.89153 1.54757,1.1775 0.67286,-1.21115 0.67286,-2.1195 0,-0.35325 -0.11775,-0.55511 -0.0505,-0.0505 -0.20186,-0.0505 -0.75696,0 -1.413,0.35325 -0.21868,0.13458 -0.3196,0.26915 z m -1.39618,0.11775 q 0,-0.0336 -0.0168,-0.10093 0,-0.0505 0,-0.0841 0,-1.00928 1.11021,-1.39618 0.45418,-0.16821 0.97564,-0.16821 1.21115,0.0168 1.86718,0.65603 0.68968,0.67286 0.68968,1.74943 0,0.63922 -0.28596,1.31207 1.91764,-0.37007 3.34746,-1.53075 0.0673,-0.0505 0.1514,-0.0505 0.35325,0 0.7065,0.471 0.16821,0.21868 0.18503,0.38689 -0.0168,0.10093 -0.0841,0.1514 -2.08585,1.68214 -4.37357,1.68214 -0.31961,0 -0.471,-0.0168 -1.51393,2.45593 -3.54932,2.45593 -0.87472,0 -1.39618,-0.37007 -0.0336,-0.0505 -0.0505,-0.0673 -0.85789,-0.62239 -0.85789,-1.59804 0,-1.32889 1.37936,-2.84282 0.33643,-0.37007 0.67286,-0.63921 z m 0.62239,1.37935 q -1.16068,1.24479 -1.44664,2.37183 -0.0337,0.18503 -0.0505,0.33643 -0.0168,0.30278 0,0.38689 0.2355,0.10093 0.48782,0.10093 1.04293,0 2.2709,-1.36254 0.2355,-0.26914 0.43735,-0.53828 -1.04292,-0.48783 -1.69896,-1.29526 z"
id="path5795" />
<path
d="m 409.36464,-218.10638 q 0.2355,-0.21868 0.67286,0.2355 0.43736,0.45417 0.26914,0.7065 -0.0336,0.0168 -0.0336,0.0336 -0.13457,0.11775 -2.25407,2.45593 -3.70072,4.05396 -5.11372,4.44086 -0.3196,0.0673 -0.53828,0 -0.55511,-0.20186 -0.90836,-0.7065 -0.63922,-0.95882 1.42982,-4.72683 0.15139,-0.28596 0.471,-0.84107 0.42054,-0.75696 0.55511,-1.02611 -2.06904,0.6224 -3.19607,-0.15139 -1.05975,-0.72332 -0.80743,-2.08586 0.18503,-1.05975 0.95882,-1.63168 0.25232,-0.18503 0.50464,-0.25232 0.68968,-0.20185 1.3289,0.471 0.35325,0.3869 0.45417,0.80743 0.13458,0.75697 -0.40371,1.884 0.13457,-0.0336 0.48782,-0.16821 0.84107,-0.30279 1.07657,-0.30279 0.79061,0.0673 1.11022,0.82425 0.18503,0.50465 -1.1775,3.02786 -1.39618,2.60732 -1.6485,3.22972 -0.13457,0.37007 -0.18504,0.60557 1.12704,-0.52147 4.44086,-4.12125 2.16996,-2.37183 2.50639,-2.70825 z m -8.34343,-0.2355 q 0.79061,-1.21115 0.942,-2.08586 -0.38689,0.31961 -0.67285,0.942 -0.18504,0.37007 -0.28597,0.90836 -0.0168,0.18503 0.0168,0.2355 z"
id="path5797" />
<path
d="m 410.45804,-220.52867 q 0.0673,-0.10093 0.18504,-0.11775 0.37007,0 0.7906,0.45418 0.20186,0.2355 0.21868,0.40371 0,0.0505 -0.0336,0.10093 -1.46347,3.09514 -1.61486,4.81093 -0.0168,0.15139 -0.0168,0.28597 0,0.2355 0.0673,0.48782 h 0.0336 q 1.39618,0 4.13807,-2.80918 0.7065,-0.74015 1.21115,-1.34572 0.0505,-0.0673 0.13457,-0.0673 0.28596,0 0.60557,0.50464 0.16821,0.26914 0.16821,0.471 -0.0168,0.0841 -0.0673,0.18504 -3.39793,4.03714 -5.46697,4.10443 -0.18504,0 -0.471,-0.0673 -0.80743,-0.2355 -1.24479,-0.95882 -0.28596,-0.471 -0.28596,-1.21114 0,-1.78308 1.6485,-5.23147 z m 1.86718,-0.75697 q -0.0673,0.0841 -0.18504,0.10093 -0.37007,0 -0.77378,-0.43735 -0.20186,-0.25233 -0.21868,-0.42054 0,-0.0505 0.0336,-0.11775 l 1.39618,-2.23725 q 0.0673,-0.0841 0.20186,-0.0841 0.38689,0 0.79061,0.45418 0.18503,0.21868 0.20185,0.38689 0,0.0505 -0.0336,0.11775 z"
id="path5799" />
<path
d="m 417.15297,-218.79606 q 0.38689,0.33643 0.40371,0.52146 0,0.11775 -0.3196,0.26914 -0.18504,0.0841 -0.25233,0.13458 0.26915,0.89153 1.54758,1.1775 0.67285,-1.21115 0.67285,-2.1195 0,-0.35325 -0.11775,-0.55511 -0.0505,-0.0505 -0.20185,-0.0505 -0.75697,0 -1.413,0.35325 -0.21868,0.13458 -0.31961,0.26915 z m -1.39618,0.11775 q 0,-0.0336 -0.0168,-0.10093 0,-0.0505 0,-0.0841 0,-1.00928 1.11021,-1.39618 0.45418,-0.16821 0.97565,-0.16821 1.21114,0.0168 1.86718,0.65603 0.68967,0.67286 0.68967,1.74943 0,0.63922 -0.28596,1.31207 1.91764,-0.37007 3.34747,-1.53075 0.0673,-0.0505 0.15139,-0.0505 0.35325,0 0.7065,0.471 0.16821,0.21868 0.18503,0.38689 -0.0168,0.10093 -0.0841,0.1514 -2.08586,1.68214 -4.37358,1.68214 -0.3196,0 -0.471,-0.0168 -1.51392,2.45593 -3.54932,2.45593 -0.87471,0 -1.39618,-0.37007 -0.0336,-0.0505 -0.0505,-0.0673 -0.8579,-0.62239 -0.8579,-1.59804 0,-1.32889 1.37936,-2.84282 0.33643,-0.37007 0.67286,-0.63921 z m 0.62239,1.37935 q -1.16068,1.24479 -1.44664,2.37183 -0.0336,0.18503 -0.0505,0.33643 -0.0168,0.30278 0,0.38689 0.2355,0.10093 0.48782,0.10093 1.04293,0 2.27089,-1.36254 0.2355,-0.26914 0.43736,-0.53828 -1.04293,-0.48783 -1.69897,-1.29526 z"
id="path5801" />
<path
d="m 424.9413,-220.79781 q 0.0673,-0.0841 0.18504,-0.0841 0.37007,0 0.77378,0.43736 0.20186,0.25232 0.21868,0.42053 0,0.0673 -0.0336,0.11775 -1.34572,1.90082 -1.90082,3.58297 -0.23551,0.7065 -0.23551,1.21114 0,0.11775 0.0337,0.30279 1.36253,-0.471 4.07079,-4.0035 0.57192,-0.74015 0.99246,-1.34572 0.13457,-0.16821 0.31961,-0.18504 0.40371,0 0.74014,0.50465 0.15139,0.2355 0.15139,0.38689 -0.0168,0.0841 -0.0505,0.13457 -0.45418,1.37936 -0.7065,2.99422 -0.0841,0.53828 -0.0841,0.89153 0.0168,0.48783 0.16822,0.58875 0.13457,0.0841 0.38689,0.0841 1.14386,0 3.65025,-1.85036 1.32889,-0.99246 1.79989,-1.56439 0.10093,-0.0841 0.16822,-0.0841 0.35325,0 0.72332,0.45418 0.16821,0.2355 0.18504,0.38689 -0.0168,0.0841 -0.0505,0.13458 -0.99246,1.21114 -2.65779,2.28771 -1.83353,1.1775 -3.17925,1.1775 -0.7065,-0.0168 -1.21114,-0.33643 -1.14386,-0.77378 -1.14386,-2.355 v -0.2355 q -2.08586,2.5064 -3.297,2.96057 -0.0336,0 -0.0673,0.0168 -0.1514,0.0505 -0.31961,0.0505 -0.67286,-0.0168 -1.26161,-0.65604 -0.50464,-0.58875 -0.50464,-1.44664 0,-1.93446 2.13632,-4.97914 z"
id="path5803" />
<path
d="m 437.50691,-222.02578 q 0.0673,-0.0336 0.13457,-0.0336 0.38689,0 0.80743,0.471 0.16821,0.2355 0.18503,0.38689 -0.0168,0.11775 -0.0841,0.15139 -1.66533,0.97565 -1.96811,1.86718 -0.10093,0.28597 -0.10093,0.58875 0.0168,0.74015 0.63921,1.98493 2.40547,-1.0261 5.02961,-1.63168 h 0.0841 q 0.42054,0 0.82425,0.50465 0.15139,0.21868 0.16822,0.37007 -0.0337,0.13457 -0.1514,0.16821 -3.07832,0.7065 -5.45014,1.7999 0.0841,0.3196 0.0841,0.5551 0,1.24479 -2.08585,2.20361 -0.0168,0.0168 -0.0336,0.0168 -0.75696,0.33643 -1.09339,0.33643 -0.67286,-0.0336 -1.14386,-0.84107 -0.11775,-0.21868 -0.11775,-0.45418 0.0168,-1.19432 3.09515,-2.67461 -0.82425,-1.58121 -0.95882,-1.9681 -0.18504,-0.53829 -0.18504,-0.95883 0.0336,-1.4971 2.32136,-2.84282 z m -2.43911,8.17522 q 0.67286,-0.37007 1.02611,-0.74014 -0.55511,0.35325 -1.02611,0.74014 z"
id="path5805" />
</g>
<path
id="path1174"
d="M 73.946849,72.08789 44.732883,51.93914"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:3.83013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1077"
d="M 69.772509,83.12209 35.166886,75.25578"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1079"
d="M 89.043673,63.40752 59.482109,34.04175"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:7.07425;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1651"
style="fill:#ff6fbf;fill-opacity:1;stroke:none;stroke-width:0.809318px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 301.60352 449.5 C 271.08862 449.06845 263.89238 494.10524 307.08008 507.55469 C 307.03435 507.76672 307.0194 507.92281 306.98047 508.12305 C 275.9299 515.29905 275.03043 564.6559 316.66406 565.62305 C 295.24159 592.87401 333.49149 628.65062 364.12305 611.81445 C 363.9575 634.73562 404.0141 653.04277 421.47461 623.70312 C 421.15211 647.79013 466.58711 667.17735 488.05078 624.23438 C 467.54672 631.87551 445.0549 618.65164 445.2793 603.28125 C 428.26016 629.51457 389.21557 613.14281 389.37695 592.64844 C 359.51948 607.70211 322.23409 575.71351 343.11523 551.34766 C 302.53307 550.48293 303.41238 506.35071 333.67969 499.93555 C 333.71768 499.75721 333.73112 499.61837 333.77539 499.42969 C 300.53113 489.93294 297.91892 462.82529 312.9375 452.0332 C 309.14662 451.18394 305.41715 450.36435 301.60352 449.5 z M 514.07812 595.18359 C 513.94565 595.53415 513.80559 595.86914 513.66992 596.21289 C 513.87521 596.01753 514.06266 595.82753 514.26562 595.63281 C 514.20426 595.48176 514.13728 595.33708 514.07812 595.18359 z "
transform="scale(0.26458333)" />
<g
id="g1528"
transform="rotate(-20.515124,1219.7167,136.35224)">
<path
id="path1501"
d="m 493.03438,-169.83117 35.23341,4.24673"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:3.83013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1503"
d="m 491.59684,-181.54066 34.29284,-9.13399"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1505"
d="m 483.70816,-155.12455 39.82857,12.24415"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:7.07425;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 211.86761,150.54834 c -15.21065,1.27975 -15.55477,-18.79894 -14.97346,-32.55099 2.81561,22.2787 5.94096,24.46342 14.97346,32.55099 z"
id="path1842" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 225.86453,110.67337 c -6.3793,10.97618 -5.78028,31.91508 10.90459,28.80763 -15.01871,-8.73873 -11.69774,-18.58362 -10.90459,-28.80763 z"
id="path2493" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 230.78809,149.20539 c 0.29846,11.70617 5.25091,14.35061 13.50866,15.13622 -7.10705,-3.21463 -11.60401,-8.45341 -13.50866,-15.13622 z"
id="path2661" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 288.85071,144.36365 c -16.64632,7.11608 -26.42811,-20.22647 -19.20509,-29.45865 0.81406,-1.0405 3.60606,-0.0115 3.74335,1.30204 1.26663,12.11918 1.62757,28.15661 15.46174,28.15661 z"
id="path2791" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 323.02924,140.78304 c -12.4618,24.2735 -21.59292,-26.37688 -13.18316,-24.08773 2.3655,0.77157 1.95306,30.76068 13.18316,24.08773 z"
id="path3514" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 343.86187,145.34018 c -8.00178,3.57283 -6.84011,-6.73626 -7.81222,-14.15968 1.99742,7.4239 3.89552,13.70584 7.81222,14.15968 z"
id="path3943" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 357.85882,115.39326 c -0.66846,10.70133 0.61461,23.39575 5.37089,31.57447 -11.32261,-9.13143 -9.2694,-32.0618 -5.37089,-31.57447 z"
id="path4035" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 390.66716,121.74326 c 0.46105,11.05567 1.08599,16.24192 6.42922,25.22447 -9.58258,-5.24896 -9.6471,-23.1254 -6.42922,-25.22447 z"
id="path4364" />
</svg>

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 36 KiB

205
assets/banner_raw.svg Normal file
View file

@ -0,0 +1,205 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
inkscape:export-ydpi="44.380001"
inkscape:export-xdpi="44.380001"
inkscape:export-filename="/Users/mendler/Code/private/hello-rust/lychee/assets/banner.png"
width="586.12097mm"
height="199.90691mm"
viewBox="0 0 586.12097 199.90691"
version="1.1"
id="svg8"
inkscape:version="1.1-alpha (d4b03b3, 2021-03-04)"
sodipodi:docname="banner_raw.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs2" />
<sodipodi:namedview
fit-margin-bottom="0"
fit-margin-right="0"
fit-margin-left="0"
fit-margin-top="0"
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.24295786"
inkscape:cx="981.6517"
inkscape:cy="347.79693"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:snap-global="false"
inkscape:window-width="1440"
inkscape:window-height="855"
inkscape:window-x="0"
inkscape:window-y="23"
inkscape:window-maximized="1"
objecttolerance="10.0"
gridtolerance="10.0"
guidetolerance="10.0"
inkscape:pagecheckerboard="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-25.769247,274.09113)"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#ffe0ee;fill-opacity:1;stroke-width:4.28731"
id="rect883"
width="587.20996"
height="199.90691"
x="25.769247"
y="-274.09113" />
<g
id="g5486"
transform="translate(-20.058214)">
<path
id="path871"
style="fill:#ff1999;fill-opacity:1;stroke:none;stroke-width:0.25551px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 205.41812,-170.26189 c 14.99116,0.64148 12.92677,17.69491 2.96101,19.20702 16.93678,2.36528 9.15018,21.4697 1.70316,21.06358 10.64644,11.65275 0.0968,26.02163 -12.70168,19.21259 2.90666,10.61599 -13.74135,16.18912 -17.34781,5.58646 -5.9185,17.745197 -21.96429,11.192101 -21.85763,2.91495 -5.40706,9.443351 -17.81147,3.55048 -17.76023,-3.82699 -9.48579,5.41893 -21.33127,-6.09625 -14.69728,-14.86733 -12.91885,-0.31192 -12.61354,-16.263 -2.94088,-18.52235 2.24638,0.91287 -0.91387,4.11833 -0.0264,-0.16724 -13.3741,-4.32888 -11.14609,-18.82497 -1.69642,-18.68607 -4.5091,-6.34808 2.8269,-15.13412 10.7949,-14.23361"
sodipodi:nodetypes="cccccccccccc" />
<path
id="path862"
style="fill:#ffb7df;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 198.59684,-172.55015 c 3.8703,0.44388 3.85972,1.63203 3.54074,5.598 -23.42417,29.83859 -83.65937,13.46178 -69.82428,-1.96893"
sodipodi:nodetypes="ccc" />
<path
id="path833"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 198.34513,-170.23322 c -0.76738,-22.83821 -21.38462,-45.28001 -40.6217,-42.09341 -18.0554,2.99086 -29.49459,33.55486 -23.35068,49.69134 17.6728,13.96638 58.79279,5.47239 63.97238,-7.59793 z"
sodipodi:nodetypes="cacc" />
<circle
style="fill:#676767;fill-opacity:1;stroke:none;stroke-width:3.43958;stroke-opacity:1"
id="path885"
cx="157.58937"
cy="-184.40746"
r="2.5224922" />
<circle
style="fill:#676767;fill-opacity:1;stroke:none;stroke-width:3.43958;stroke-opacity:1"
id="path887"
cx="182.94707"
cy="-183.4781"
r="2.9207804" />
<path
id="path889"
style="fill:none;stroke:#676767;stroke-width:0.948181;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 166.03849,-182.57442 c -0.25275,1.95289 0.36798,3.81019 2.1354,4.17244 2.62743,0.53852 3.65985,-1.30863 4.57608,-3.44058"
sodipodi:nodetypes="csc" />
<text
id="text850"
y="-114.72107"
x="237.91479"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.204px;line-height:1.25;font-family:'Fresh Lychee';-inkscape-font-specification:'Fresh Lychee, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#e7008e;fill-opacity:1;stroke:none;stroke-width:2.7051"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.204px;font-family:'Fresh Lychee';-inkscape-font-specification:'Fresh Lychee, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#e7008e;fill-opacity:1;stroke-width:2.7051"
y="-114.72107"
x="237.91479"
id="tspan848"
sodipodi:role="line">lychee</tspan></text>
<text
id="text854"
y="-208.24902"
x="246.45612"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:34.4503px;line-height:1.25;font-family:Authentic;-inkscape-font-specification:'Authentic, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#a40b73;fill-opacity:1;stroke:none;stroke-width:0.861259"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:34.4503px;font-family:Authentic;-inkscape-font-specification:'Authentic, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#a40b73;fill-opacity:1;stroke-width:0.861259"
y="-208.24902"
x="246.45612"
id="tspan852"
sodipodi:role="line">Introducing the glorious</tspan></text>
<path
id="path1174"
d="M 119.77431,-202.00324 90.560344,-222.15199"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:3.83013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1077"
d="m 115.59997,-190.96904 -34.605623,-7.86631"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1079"
d="m 134.87113,-210.68361 -29.56156,-29.36577"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:7.07425;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1651"
style="fill:#ff6fbf;fill-opacity:1;stroke:none;stroke-width:0.214132px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 125.62647,-155.16092 c -8.07373,-0.11418 -9.97773,11.8018 1.44901,15.3603 -0.0121,0.0561 -0.016,0.0974 -0.0263,0.15038 -8.21546,1.89865 -8.45345,14.95765 2.56211,15.21354 -5.66803,7.21015 4.45226,16.67604 12.55686,12.22147 -0.0438,6.06456 10.55451,10.90833 15.17427,3.14555 -0.0911,6.80412 13.61862,12.19149 18.67535,-2.39572 -33.46018,-10.5289 -47.46418,-29.90715 -50.39125,-43.69552 z"
sodipodi:nodetypes="cccccccc" />
<g
id="g1528"
transform="rotate(-20.515124,485.3293,-127.31247)">
<path
id="path1501"
d="m 493.03438,-169.83117 35.23341,4.24673"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:3.83013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1503"
d="m 491.59684,-181.54066 34.29284,-9.13399"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1505"
d="m 483.70816,-155.12455 39.82857,12.24415"
style="fill:#fff554;fill-opacity:1;stroke:#fff554;stroke-width:7.07425;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 257.69507,-123.54279 c -15.21065,1.27975 -15.55477,-18.79894 -14.97346,-32.55099 2.81561,22.2787 5.94096,24.46342 14.97346,32.55099 z"
id="path1842"
sodipodi:nodetypes="ccc" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 271.69199,-163.41776 c -6.3793,10.97618 -5.78028,31.91508 10.90459,28.80763 -15.01871,-8.73873 -11.69774,-18.58362 -10.90459,-28.80763 z"
id="path2493"
sodipodi:nodetypes="ccc" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 276.61555,-124.88574 c 0.29846,11.70617 5.25091,14.35061 13.50866,15.13622 -7.10705,-3.21463 -11.60401,-8.45341 -13.50866,-15.13622 z"
id="path2661"
sodipodi:nodetypes="ccc" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 334.67817,-129.72748 c -16.64632,7.11608 -26.42811,-20.22647 -19.20509,-29.45865 0.81406,-1.0405 3.60606,-0.0115 3.74335,1.30204 1.26663,12.11918 1.62757,28.15661 15.46174,28.15661 z"
id="path2791"
sodipodi:nodetypes="casc" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 368.8567,-133.30809 c -12.4618,24.2735 -21.59292,-26.37688 -13.18316,-24.08773 2.3655,0.77157 1.95306,30.76068 13.18316,24.08773 z"
id="path3514"
sodipodi:nodetypes="ccc" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 389.68933,-128.75095 c -8.00178,3.57283 -6.84011,-6.73626 -7.81222,-14.15968 1.99742,7.4239 3.89552,13.70584 7.81222,14.15968 z"
id="path3943"
sodipodi:nodetypes="ccc" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 403.68628,-158.69787 c -0.66846,10.70133 0.61461,23.39575 5.37089,31.57447 -11.32261,-9.13143 -9.2694,-32.0618 -5.37089,-31.57447 z"
id="path4035"
sodipodi:nodetypes="ccc" />
<path
style="opacity:0.466667;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 436.49462,-152.34787 c 0.46105,11.05567 1.08599,16.24192 6.42922,25.22447 -9.58258,-5.24896 -9.6471,-23.1254 -6.42922,-25.22447 z"
id="path4364"
sodipodi:nodetypes="ccc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -175,7 +175,12 @@ async fn run(cfg: &Config, inputs: Vec<Input>) -> Result<i32> {
if let Some(output) = &cfg.output {
fs::write(output, stats_formatted).context("Cannot write status output to file")?;
} else {
println!("\n{}", stats_formatted);
if cfg.verbose && !stats.is_empty() {
// separate summary from the verbose list of links above
println!();
}
// we assume that the formatted stats don't have a final newline
println!("{}", stats_formatted);
}
match stats.is_success() {

View file

@ -117,7 +117,7 @@ pub struct Config {
pub verbose: bool,
/// Do not show progress bar.
/// This is recommended for non-interactive shells (e.g. for continuos
/// This is recommended for non-interactive shells (e.g. for continuous
/// integration)
#[structopt(short, long)]
#[serde(default)]

View file

@ -17,9 +17,8 @@ pub fn color_response(response: &Response) -> String {
Status::Ok(_) => style(response).green().bright(),
Status::Redirected(_) => style(response),
Status::Excluded => style(response).dim(),
Status::Error(_) => style(response).yellow().bright(),
Status::Timeout(_) => style(response).yellow().bright(),
Status::Failed(_) => style(response).red().bright(),
Status::Error(_, _) => style(response).red().bright(),
};
out.to_string()
}
@ -54,17 +53,16 @@ impl ResponseStats {
pub fn add(&mut self, response: Response) {
self.total += 1;
match response.status {
Status::Failed(_) => self.failures += 1,
Status::Error(_, _) => self.failures += 1,
Status::Timeout(_) => self.timeouts += 1,
Status::Redirected(_) => self.redirects += 1,
Status::Excluded => self.excludes += 1,
Status::Error(_) => self.errors += 1,
_ => self.successful += 1,
}
if matches!(
response.status,
Status::Failed(_) | Status::Timeout(_) | Status::Redirected(_) | Status::Error(_)
Status::Error(_, _) | Status::Timeout(_) | Status::Redirected(_)
) {
let fail = self.fail_map.entry(response.source.clone()).or_default();
fail.insert(response);
@ -74,9 +72,13 @@ impl ResponseStats {
pub fn is_success(&self) -> bool {
self.total == self.successful + self.excludes
}
pub fn is_empty(&self) -> bool {
self.total == 0
}
}
fn write_stat(f: &mut fmt::Formatter, title: &str, stat: usize) -> fmt::Result {
fn write_stat(f: &mut fmt::Formatter, title: &str, stat: usize, newline: bool) -> fmt::Result {
let fill = title.chars().count();
f.write_str(title)?;
f.write_str(
@ -84,7 +86,12 @@ fn write_stat(f: &mut fmt::Formatter, title: &str, stat: usize) -> fmt::Result {
.to_string()
.pad(MAX_PADDING - fill, '.', Alignment::Right, false),
)?;
f.write_str("\n")
if newline {
f.write_str("\n")?;
}
Ok(())
}
impl Display for ResponseStats {
@ -93,24 +100,23 @@ impl Display for ResponseStats {
writeln!(f, "📝 Summary")?;
writeln!(f, "{}", separator)?;
write_stat(f, "🔍 Total", self.total)?;
write_stat(f, "✅ Successful", self.successful)?;
write_stat(f, "⏳ Timeouts", self.timeouts)?;
write_stat(f, "🔀 Redirected", self.redirects)?;
write_stat(f, "👻 Excluded", self.excludes)?;
write_stat(f, "🚫 Errors", self.errors + self.failures)?;
write_stat(f, "🔍 Total", self.total, true)?;
write_stat(f, "✅ Successful", self.successful, true)?;
write_stat(f, "⏳ Timeouts", self.timeouts, true)?;
write_stat(f, "🔀 Redirected", self.redirects, true)?;
write_stat(f, "👻 Excluded", self.excludes, true)?;
write_stat(f, "🚫 Errors", self.errors + self.failures, false)?;
if !&self.fail_map.is_empty() {
writeln!(f)?;
}
for (input, responses) in &self.fail_map {
writeln!(f, "Errors in {}", input)?;
// Using leading newlines over trailing ones (e.g. `writeln!`)
// lets us avoid extra newlines without any additional logic.
write!(f, "\n\nErrors in {}", input)?;
for response in responses {
writeln!(f, "{}", color_response(response))?
write!(f, "\n{}", color_response(response))?
}
writeln!(f)?;
}
writeln!(f)
Ok(())
}
}
@ -120,6 +126,20 @@ mod test_super {
use super::*;
#[test]
fn test_stats_is_empty() {
let mut stats = ResponseStats::new();
assert!(stats.is_empty());
stats.add(Response {
uri: website("http://example.org/ok"),
status: Status::Ok(http::StatusCode::OK),
source: Input::Stdin,
});
assert!(!stats.is_empty());
}
#[test]
fn test_stats() {
let mut stats = ResponseStats::new();
@ -130,7 +150,7 @@ mod test_super {
});
stats.add(Response {
uri: website("http://example.org/failed"),
status: Status::Failed(http::StatusCode::BAD_GATEWAY),
status: Status::Error("".to_string(), Some(http::StatusCode::BAD_GATEWAY)),
source: Input::Stdin,
});
stats.add(Response {
@ -144,7 +164,7 @@ mod test_super {
vec![
Response {
uri: website("http://example.org/failed"),
status: Status::Failed(http::StatusCode::BAD_GATEWAY),
status: Status::Error("".to_string(), Some(http::StatusCode::BAD_GATEWAY)),
source: Input::Stdin,
},
Response {

View file

@ -194,7 +194,7 @@ impl Client {
// TODO: We should not be using a HTTP status code for mail
match self.check_mail(&address).await {
true => Status::Ok(http::StatusCode::OK),
false => Status::Error(format!("Invalid mail address: {}", address)),
false => Status::Error(format!("Invalid mail address: {}", address), None),
}
}
})
@ -232,7 +232,7 @@ impl Client {
Some(github) => {
let repo = github.repo(owner, repo).get().await;
match repo {
Err(e) => Status::Error(format!("{}", e)),
Err(e) => Status::Error(e.to_string(), None),
Ok(_) => Status::Ok(http::StatusCode::OK),
}
}
@ -240,6 +240,7 @@ impl Client {
"GitHub token not specified. To check GitHub links reliably, \
use `--github-token` flag / `GITHUB_TOKEN` env var."
.to_string(),
None,
),
}
}
@ -297,7 +298,6 @@ pub async fn check<T: TryInto<Request>>(request: T) -> Result<Response> {
#[cfg(test)]
mod test {
use super::*;
use http::StatusCode;
use std::time::{Duration, Instant};
use wiremock::matchers::method;
use wiremock::{Mock, MockServer, ResponseTemplate};
@ -317,7 +317,18 @@ mod test {
.check(mock_server.uri())
.await
.unwrap();
assert!(matches!(res.status, Status::Failed(_)));
assert!(res.status.is_failure());
}
#[tokio::test]
async fn test_nonexistent_with_path() {
let res = ClientBuilder::default()
.build()
.unwrap()
.check("http://127.0.0.1/invalid")
.await
.unwrap();
assert!(res.status.is_failure());
}
#[tokio::test]
@ -338,7 +349,7 @@ mod test {
.unwrap();
let end = start.elapsed();
assert!(matches!(res.status, Status::Failed(_)));
assert!(matches!(res.status, Status::Error(_, _)));
// on slow connections, this might take a bit longer than nominal backed-off timeout (7 secs)
assert!(end.as_secs() >= 7);
@ -358,16 +369,14 @@ mod test {
}
#[tokio::test]
async fn test_github() {
assert!(matches!(
ClientBuilder::default()
.build()
.unwrap()
.check("https://github.com/lycheeverse/lychee")
.await
.unwrap()
.status,
Status::Ok(_)
));
assert!(ClientBuilder::default()
.build()
.unwrap()
.check("https://github.com/lycheeverse/lychee")
.await
.unwrap()
.status
.is_success());
}
#[tokio::test]
@ -379,7 +388,7 @@ mod test {
.await
.unwrap()
.status;
assert!(matches!(res, Status::Error(_)));
assert!(res.is_failure());
}
#[tokio::test]
@ -398,7 +407,7 @@ mod test {
.await
.unwrap()
.status;
assert!(matches!(res, Status::Ok(_)));
assert!(res.is_success());
}
#[tokio::test]
@ -409,7 +418,7 @@ mod test {
.check("https://expired.badssl.com/")
.await
.unwrap();
assert!(matches!(res.status, Status::Error(_)));
assert!(res.status.is_failure());
// Same, but ignore certificate error
let res = ClientBuilder::default()
@ -419,7 +428,7 @@ mod test {
.check("https://expired.badssl.com/")
.await
.unwrap();
assert!(matches!(res.status, Status::Ok(_)));
assert!(res.status.is_success());
}
#[tokio::test]
@ -430,7 +439,7 @@ mod test {
.check("https://crates.io/crates/lychee")
.await
.unwrap();
assert!(matches!(res.status, Status::Failed(StatusCode::NOT_FOUND)));
assert!(res.status.is_failure());
// Try again, but with a custom header.
// For example, crates.io requires a custom accept header.
@ -444,7 +453,7 @@ mod test {
.check("https://crates.io/crates/lychee")
.await
.unwrap();
assert!(matches!(res.status, Status::Ok(_)));
assert!(res.status.is_success());
}
#[tokio::test]

View file

@ -498,4 +498,27 @@ mod test {
assert_eq!(links, expected_links);
}
#[test]
fn test_extract_urls_with_at_sign_properly() {
// note that these used to parse as emails
let input = "https://example.com/@test/test http://otherdomain.com/test/@test".to_string();
let links: HashSet<Uri> = extract_links(
&InputContent::from_string(&input, FileType::Plaintext),
None,
)
.into_iter()
.map(|r| r.uri)
.collect();
let expected_links = [
website("https://example.com/@test/test"),
website("http://otherdomain.com/test/@test"),
]
.iter()
.cloned()
.collect();
assert_eq!(links, expected_links);
}
}

View file

@ -1,18 +1,23 @@
use lazy_static::lazy_static;
use regex::RegexSet;
use std::net::IpAddr;
use crate::Uri;
/// Pre-defined exclusions for known false-positives
static FALSE_POSITIVE_REGEX: &[&str] = &[r"http://www.w3.org/1999/xhtml"];
/// Exclude configuration for the link checker.
/// You can ignore links based on regex patterns or pre-defined IP ranges.
#[derive(Clone, Debug)]
pub struct Excludes {
/// User-defined set of excluded regex patterns
pub regex: Option<RegexSet>,
/// Example: 192.168.0.1
pub private_ips: bool,
/// Example: 169.254.0.0
pub link_local_ips: bool,
/// For IPv4: 127.0. 0.1/8
/// For IPv4: 127.0.0.1/8
/// For IPv6: ::1/128
pub loopback_ips: bool,
/// Example: octocat@github.com
@ -41,6 +46,13 @@ impl Excludes {
false
}
pub fn false_positive(&self, input: &str) -> bool {
lazy_static! {
static ref FALSE_POSITIVES: RegexSet = RegexSet::new(FALSE_POSITIVE_REGEX).unwrap();
}
FALSE_POSITIVES.is_match(input)
}
pub fn ip(&self, uri: &Uri) -> bool {
if let Some(ipaddr) = uri.host_ip() {
if self.loopback_ips && ipaddr.is_loopback() {

View file

@ -39,7 +39,7 @@ impl Filter {
pub fn excluded(&self, request: &Request) -> bool {
// Skip mail?
if matches!(request.uri, Uri::Mail(_)) && self.excludes.is_mail_excluded() {
if self.excludes.is_mail_excluded() && matches!(request.uri, Uri::Mail(_)) {
return true;
}
// Skip specific IP address?
@ -48,23 +48,29 @@ impl Filter {
}
// No regex includes/excludes at all?
if self.includes.is_empty() && self.excludes.is_empty() {
// Not excluded unless it's a known false positive
return self.excludes.false_positive(request.uri.as_str());
}
// Includes take precedence over excludes
if self.includes.regex(request.uri.as_str()) {
return false;
}
if self.includes.regex(request.uri.as_str()) {
// Includes take precedence over excludes
return false;
// Exclude well-known false-positives.
// This is done after checking includes to allow for user overwrites.
if self.excludes.false_positive(request.uri.as_str()) {
return true;
}
// In case we have includes and no excludes,
// skip everything that was not included
if !self.includes.is_empty() && self.excludes.is_empty() {
return true;
}
// We have no includes. Check regex excludes
// We have no includes. Check regex excludes.
// This includes well-known false positives.
if self.excludes.regex(request.uri.as_str()) {
return true;
}
// URI scheme excluded?
if self.scheme.is_none() {
return false;
}
@ -144,6 +150,31 @@ mod test {
assert_eq!(filter.excluded(&request("https://example.org")), false);
}
#[test]
fn test_false_positives() {
let includes = Some(Includes::default());
let excludes = Some(Excludes::default());
let filter = Filter::new(includes, excludes, None);
assert_eq!(
filter.excluded(&request("http://www.w3.org/1999/xhtml")),
true
);
assert_eq!(filter.excluded(&request("https://example.org")), false);
}
#[test]
fn test_overwrite_false_positives() {
let includes = Some(Includes {
regex: Some(RegexSet::new(&[r"http://www.w3.org/1999/xhtml"]).unwrap()),
});
let excludes = Some(Excludes::default());
let filter = Filter::new(includes, excludes, None);
assert_eq!(
filter.excluded(&request("http://www.w3.org/1999/xhtml")),
false
);
}
#[test]
fn test_include_regex() {
let includes = Some(Includes {

View file

@ -78,11 +78,17 @@ impl Response {
impl Display for Response {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let metadata = match &self.status {
Status::Ok(code) | Status::Redirected(code) | Status::Failed(code) => {
Status::Ok(code) | Status::Redirected(code) => {
format!(" [{}]", code)
}
Status::Timeout(code) if code.is_some() => format!(" [{}]", code.unwrap()),
Status::Error(e) => format!(" ({})", e),
Status::Error(e, code) => {
if let Some(code) = code {
format!(" ({})", code)
} else {
format!(" ({})", e)
}
}
_ => "".to_string(),
};
write!(f, "{} {}{}", self.status.icon(), self.uri, metadata)
@ -95,15 +101,13 @@ pub enum Status {
/// Request was successful
Ok(http::StatusCode),
/// Request failed with HTTP error code
Failed(http::StatusCode),
Error(String, Option<http::StatusCode>),
/// Request timed out
Timeout(Option<http::StatusCode>),
/// Got redirected to different resource
Redirected(http::StatusCode),
/// Resource was excluded from checking
Excluded,
/// Low-level error while loading resource
Error(String),
}
impl Display for Status {
@ -112,8 +116,13 @@ impl Display for Status {
Status::Ok(c) => format!("OK ({})", c),
Status::Redirected(c) => format!("Redirect ({})", c),
Status::Excluded => "Excluded".to_string(),
Status::Failed(c) => format!("Failed ({})", c),
Status::Error(e) => format!("Runtime error ({})", e),
Status::Error(err, code) => {
if let Some(code) = code {
format!("Failed: {} ({})", err, code)
} else {
format!("Failed: {}", err)
}
}
Status::Timeout(Some(c)) => format!("Timeout ({})", c),
Status::Timeout(None) => "Timeout".to_string(),
};
@ -139,7 +148,7 @@ impl Status {
} else if statuscode.is_redirection() {
Status::Redirected(statuscode)
} else {
Status::Failed(statuscode)
Status::Error("".into(), Some(statuscode))
}
}
@ -147,6 +156,10 @@ impl Status {
matches!(self, Status::Ok(_))
}
pub fn is_failure(&self) -> bool {
matches!(self, Status::Error(_, _))
}
pub fn is_excluded(&self) -> bool {
matches!(self, Status::Excluded)
}
@ -156,8 +169,7 @@ impl Status {
Status::Ok(_) => "",
Status::Redirected(_) => "⇄️",
Status::Excluded => "?",
Status::Failed(_) => "",
Status::Error(_) => "",
Status::Error(_, _) => "",
Status::Timeout(_) => "",
}
}
@ -168,7 +180,7 @@ impl From<reqwest::Error> for Status {
if e.is_timeout() {
Status::Timeout(e.status())
} else {
Status::Error(e.to_string())
Status::Error(e.to_string(), e.status())
}
}
}

View file

@ -1,4 +1,5 @@
use anyhow::{bail, Result};
use fast_chemail::is_valid_email;
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
use std::{convert::TryFrom, fmt::Display};
@ -56,12 +57,12 @@ impl TryFrom<&str> for Uri {
// Remove the `mailto` scheme if it exists
// to avoid parsing it as a website URL.
let s = s.trim_start_matches("mailto:");
if s.contains('@') & !is_link_internal {
return Ok(Uri::Mail(s.to_string()));
}
if let Ok(uri) = Url::parse(s) {
return Ok(Uri::Website(uri));
};
} else if !is_link_internal && is_valid_email(&s) {
return Ok(Uri::Mail(s.to_string()));
}
bail!("Cannot convert to Uri")
}
}
@ -86,6 +87,10 @@ mod test {
Uri::try_from("http://example.org").unwrap(),
website("http://example.org")
);
assert_eq!(
Uri::try_from("http://example.org/@test/testing").unwrap(),
website("http://example.org/@test/testing")
);
assert_eq!(
Uri::try_from("mail@example.org").unwrap(),
Uri::Mail("mail@example.org".to_string())

View file

@ -41,13 +41,13 @@ mod readme {
.expect("Invalid utf8 output for `--help`");
let readme = load_readme_text();
const BACKTICKS_OFFSET: usize = 5; // marker: ```sh
const BACKTICKS_OFFSET: usize = 9; // marker: ```ignore
const NEWLINE_OFFSET: usize = 1;
let usage_start = BACKTICKS_OFFSET
+ NEWLINE_OFFSET
+ readme
.find("```sh\nUSAGE:\n")
.find("```ignore\nUSAGE:\n")
.expect("Couldn't find USAGE section in README.md");
let usage_end = readme[usage_start..]