Compare commits

...

9 commits

13 changed files with 2435 additions and 3794 deletions

2
.gitignore vendored
View file

@ -3,3 +3,5 @@ node_modules
public
resources
.hugo_build.lock
sec
tmp/

13
.woodpecker.yml Normal file
View file

@ -0,0 +1,13 @@
pipeline:
build:
image: python
when:
event: [ push, pull_request, tag, deployment ]
branch: master
commands:
- curl -fsSL https://deb.nodesource.com/setup_16.x | bash - &&\
- apt update && apt-get -y --no-install-recommends install nodejs tar gpg curl wget
- make env
- make
- make ci-deploy
secrets: [ FORGEJO_WRITE_DEPLOY_KEY, LIBREPAGES_DEPLOY_SECRET ]

27
Makefile Normal file
View file

@ -0,0 +1,27 @@
default:
./scripts/hugo.sh build
ci-deploy: ## Deploy from CI/CD. Only call from within CI
@if [ "${CI}" != "woodpecker" ]; \
then echo "Only call from within CI. Will re-write your local Git configuration. To override, set export CI=woodpecker"; \
exit 1; \
fi
git config --global user.email "${CI_COMMIT_AUTHOR_EMAIL}"
git config --global user.name "${CI_COMMIT_AUTHOR}"
./scripts/hugo.sh deploy librepages public "${CI_COMMIT_AUTHOR} <${CI_COMMIT_AUTHOR_EMAIL}>"
./scripts/ci.sh --init "$$FORGEJO_WRITE_DEPLOY_KEY"
cat /tmp/ci-ssh-id
./scripts/ci.sh --deploy ${LIBREPAGES_DEPLOY_SECRET} librepages
./scripts/ci.sh --clean
env: ## Download build dependencies and setup dev environment
./scripts/hugo.sh install
npm ci
npm run clean
npm run build
help: ## Prints help for targets with comments
@cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
serve:
./scripts/hugo.sh hugo server

View file

@ -0,0 +1,51 @@
---
title: "February, 2023: Monthly Report"
description: "Gusted and I secured funding from NLnet to work on mCaptcha in 2023, we suffered an outage from 15 January to February 6, polyfill benchmarking support in mCaptcha"
lead: "We are mCaptcha. We build kickass CAPTCHA systems that give (DDoS) attackers a run for their money. And we do all of this without tracking your users. Oh and did I mention our UX is great?"
date: 2023-03-08
lastmod: 2023-03-08
draft: false
weight: 50
images: ["icon.png"]
contributors: ["Aravinth Manivannan"]
---
Hello and welcome to the (August 2022 to) February, 2023 monthly report!
## TL;DR
_[Gusted](https://gusted.xyz) and I secured funding from NLnet to work
on mCaptcha in 2023, we suffered an outage from 15 January to February
6, polyfill benchmarking support in mCaptcha_
## We have funding!
[Gusted](https://gusted.xyz) and I applied and secured funding through
2023 development is funded through the [NGI0
Entrust](https://nlnet.nl/entrust) Fund, via [NLnet](https://nlnet.nl).
The full list of tasks that we'll be working on in the period is is
available
[here](https://git.batsense.net/mCaptcha/2023-NLnet/projects/6).
## Infrastructure outage: 15 January, 2023 to February 6, 2023
A hard disk on of the servers hosting mCaptcha infrastructure failed,
which caused the outage. Fixing the hard disk lead to additional
problems, the fan on that server was failing and we couldn't get spares
sooner.
We had current backups, so there was no data loss.
Going forward, we are planning to create Infrastructure-as-Code to fully
restore all mCaptcha infrastructure, so that in the even of an outage,
we could restore our infrastructure in much shorter duration.
## mCaptcha/survey now includes polyfill benchmarking
mCaptcha/survey runs benchmarks with mCaptcha's PoW algorithm to collect
statistics on how mCaptcha performs on various browsers and devices. So
far, we've only been running benchmarks with the WebAssembly
implementation. This [pull request](https://github.com/mCaptcha/survey/pull/14) added support for running benchmarks
with the JavaScript polyfill implementation on browsers without
WebAssembly support.

View file

@ -1,6 +1,6 @@
---
title: "July, 2022: Monthly Report"
description: "Codeberg is trying you mCaptcha, Gitea is getting mCaptcha support, mCaptcha supports MariaDB, I've applied for NLnet and Open Tech Fund, documentation is updated: tutorials and glossary is added and glue libraries have new releases."
description: "Codeberg is trying out mCaptcha, Gitea is getting mCaptcha support, mCaptcha supports MariaDB, I've applied for NLnet and Open Tech Fund, documentation is updated: tutorials and glossary is added and glue libraries have new releases."
lead: "We are mCaptcha. We build kickass CAPTCHA systems that give (DDoS) attackers a run for their money. And we do all of this without tracking your users. Oh and did I mention our UX is great?"
date: 2022-08-04
lastmod: 2022-08-04
@ -14,7 +14,7 @@ Hello and welcome to the July, 2022 monthly report!
## TL;DR
_Codeberg is trying you mCaptcha, Gitea is getting mCaptcha support,
_Codeberg is trying out mCaptcha, Gitea is getting mCaptcha support,
mCaptcha supports MariaDB, I've applied for NLnet and Open Tech Fund,
documentation is updated: tutorials and glossary is added and glue libraries
have new releases._

View file

@ -7,6 +7,25 @@ draft: false
images: []
---
## Funding
### NLnet
<div align="center">
<img
height="150px"
alt="NLnet NGIZero logo"
src="/third-party/NGIZero-green.hex.svg"
/>
</div>
<br />
2023 development is funded through the [NGI0 Entrust
Fund](https://nlnet.nl/entrust), via [NLnet](https://nlnet.nl/). Please
see [here](https://nlnet.nl/project/mCaptcha/) for more details.
## Free software libraries and tools
mCaptcha is built entirely using free software libraries tools. We are

4368
package-lock.json generated

File diff suppressed because it is too large Load diff

119
scripts/ci.sh Executable file
View file

@ -0,0 +1,119 @@
#!/bin/bash
# ci.sh: Helper script to automate deployment operations on CI/CD
# Copyright © 2022 Aravinth Manivannan <realaravinth@batsense.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
set -xEeuo pipefail
#source $(pwd)/scripts/lib.sh
readonly SSH_ID_FILE=/tmp/ci-ssh-id
readonly SSH_REMOTE_NAME=origin-ssh
match_arg() {
if [ $1 == $2 ] || [ $1 == $3 ]
then
return 0
else
return 1
fi
}
help() {
cat << EOF
USAGE: ci.sh [SUBCOMMAND]
Helper script to automate deployment operations on CI/CD
Subcommands
-c --clean cleanup secrets, SSH key and other runtime data
-i --init <SSH_PRIVATE_KEY> initialize environment, write SSH private to file
-d --deploy <PAGES-SECRET> <TARGET BRANCH> push branch to Gitea and call Pages server
-h --help print this help menu
EOF
}
# $1: SSH private key
write_ssh(){
truncate --size 0 $SSH_ID_FILE
echo "$1" > $SSH_ID_FILE
chmod 600 $SSH_ID_FILE
}
set_ssh_remote() {
http_remote_url=$(git remote get-url origin)
remote_hostname=$(echo $http_remote_url | cut -d '/' -f 3)
repository_owner=$(echo $http_remote_url | cut -d '/' -f 4)
repository_name=$(echo $http_remote_url | cut -d '/' -f 5)
ssh_remote="git@git.batsense.net:mcaptcha/website.git"
git remote add $SSH_REMOTE_NAME $ssh_remote
}
clean() {
if [ -f $SSH_ID_FILE ]
then
shred $SSH_ID_FILE
rm $SSH_ID_FILE
fi
}
# $1: Pages API secret
# $2: Deployment target branch
deploy() {
if (( "$#" < 2 ))
then
help
else
git -c core.sshCommand="/usr/bin/ssh -oStrictHostKeyChecking=no -i $SSH_ID_FILE"\
push --force $SSH_REMOTE_NAME $2
curl -vv --location --request \
POST "https://deploy.batsense.net/api/v1/update"\
--header 'Content-Type: application/json' \
--data-raw "{ \"secret\": \"$1\", \"branch\": \"$2\" }"
fi
}
if (( "$#" < 1 ))
then
help
exit -1
fi
if match_arg $1 '-i' '--init'
then
if (( "$#" < 2 ))
then
help
exit -1
fi
set_ssh_remote
write_ssh "$2"
elif match_arg $1 '-c' '--clean'
then
clean
elif match_arg $1 '-d' '--deploy'
then
if (( "$#" < 3 ))
then
help
exit -1
fi
deploy $2 $3
elif match_arg $1 '-h' '--help'
then
help
else
help
fi

155
scripts/hugo.sh Executable file
View file

@ -0,0 +1,155 @@
#!/bin/bash
# Used in CI workflow: install hugo binary from GitHub
# Copyright © 2021 Aravinth Manivannan <realaravinth@batsense.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
set -euo pipefail
readonly PROJECT_ROOT=$(pwd)
readonly TARBALL=hugo.tar.gz
readonly SOURCE="https://github.com/gohugoio/hugo/releases/download/v0.110.0/hugo_extended_0.110.0_linux-amd64.tar.gz"
readonly BIN_PATH=tmp/bin
readonly BIN=$BIN_PATH/hugo
readonly DIST=public
source $(pwd)/scripts/lib.sh
help() {
cat << EOF
hugo.sh: hugo build script
USAGE:
hugo.sh <options>
OPTIONS:
b build build website
c clean clean dependencies and build artifacts
d deploy deploy build to branch
h help print this help menu
i install install build dependencies
u url make urls relative
z hugo invoke hugo
EOF
}
download() {
if [ ! -e $BIN_PATH ];
then
mkdir -p $BIN_PATH
cd $BIN_PATH
echo "[*] Downloading Hugo"
wget --quiet --output-document=$TARBALL $SOURCE
tar -xvzf $TARBALL > /dev/null
rm $TARBALL
echo "[*] Downloaded hugo into $BIN"
cd $PROJECT_ROOT
fi
}
init() {
if [ ! -d $BIN_PATH ]
then
mkdir $BIN_PATH
fi
if [ ! -f $BIN ]
then
cd $BIN_PATH
download
fi
}
run() {
$BIN "${@:1}"
}
build() {
run
}
no_absolute_url() {
sed -i 's/https:\/\/mcaptcha.org//g' $(find public -type f | grep html)
}
clean() {
rm -rf $BIN_PATH || true
rm -rf $DIST || true
echo "[*] Workspace cleaned"
}
# $1: branch name
# $2: directory containing build assets
# $3: Author in <author-name author@example.com> format
deploy() {
cd $PROJECT_ROOT
original_branch=$(git branch --show-current)
tmp_dir=$(mktemp -d)
cp -r $2/* $tmp_dir
if [[ -z $(git ls-remote --heads origin ${1}) ]]
then
echo "[*] Creating deployment branch $1"
git checkout --orphan $1
else
echo "[*] Deployment branch $1 exists, pulling changes from remote"
git fetch origin $1
git switch $1
fi
git rm -rf .
/bin/rm -rf *
cp -r $tmp_dir/* .
git add --all
if [ $(git status --porcelain | xargs | sed '/^$/d' | wc -l) -gt 0 ];
then
echo "[*] Repository has changed, committing changes"
git commit \
--author="$3" \
--message="new deploy: $(date --iso-8601=seconds)"
fi
git checkout $original_branch
}
check_arg $1
download
if match_arg $1 'c' 'clean'
then
clean
elif match_arg $1 'i' 'install'
then
init
elif match_arg $1 'd' 'deploy'
then
check_arg $2
check_arg $3
check_arg $4
deploy $2 $3 $4
elif match_arg $1 'b' 'build'
then
build
elif match_arg $1 'h' 'help'
then
help
elif match_arg $1 'z' 'hugo'
then
hugo "${@:3}"
else
echo "Error: $1 is not an option"
help
exit 1
fi
exit 0

32
scripts/lib.sh Executable file
View file

@ -0,0 +1,32 @@
#!/bin/bash
# Copyright © 2021 Aravinth Manivannan <realaravinth@batsense.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
check_arg(){
if [ -z $1 ]
then
help
exit 1
fi
}
match_arg() {
if [ $1 == $2 ] || [ $1 == $3 ]
then
return 0
else
return 1
fi
}

98
scripts/spellcheck.sh Executable file
View file

@ -0,0 +1,98 @@
#!/bin/bash
# Used in CI workflow: install and check for spelling errors
# Copyright © 2021 Aravinth Manivannan <realaravinth@batsense.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
readonly MISSPELL_DOWNLOAD="https://github.com/client9/misspell/releases/download/v0.3.4/misspell_0.3.4_linux_64bit.tar.gz"
readonly TMP_DIR=$(pwd)/tmp
readonly PROJECT_ROOT=$(pwd)
readonly MISSPELL_TARBALL="$TMP_DIR/misspell.tar.bz2"
readonly MISSPELL="$TMP_DIR/misspell"
set -Eeuo pipefail
source $(pwd)/scripts/lib.sh
FLAGS=""
help() {
cat << EOF
spellcheck.sh: Check for spelling errors
USAGE:
spellcheck.sh <options>
OPTIONS:
c --check check for spelling erros
h --help print this help menu
w --write check and fix spelling errors
EOF
}
download() {
if [ ! -e $MISSPELL ];
then
echo "[*] Downloading misspell"
wget --quiet --output-doc=$MISSPELL_TARBALL $MISSPELL_DOWNLOAD;
cd $TMP_DIR
tar -xf $MISSPELL_TARBALL;
cd $PROJECT_ROOT
pip install codespell
else
echo "[*] Found misspell"
fi
}
spell_check_codespell() {
_check(){
codespell $FLAGS $PROJECT_ROOT/$1 #|| true
}
_check README.md
_check contents
}
spell_check_misspell() {
mkdir $TMP_DIR || true
download
_check(){
$MISSPELL $FLAGS $PROJECT_ROOT/$1
}
_check contents
_check README.md
}
check_arg $1
if match_arg $1 'w' '--write'
then
echo "[*] checking and correcting spellings"
FLAGS="-w"
spell_check_misspell
spell_check_codespell
elif match_arg $1 'c' '--check'
then
echo "[*] checking spellings"
spell_check_misspell
spell_check_codespell
elif match_arg $1 'h' '--help'
then
help
else
echo "undefined option"
help
exit 1
fi

103
static/third-party/NGIZero-green.hex.svg vendored Normal file
View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<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"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
width="165.92125"
height="191.45087"
viewBox="0 0 165.92125 191.45086"
enable-background="new 0 0 198.425 198.425"
xml:space="preserve"
sodipodi:docname="NGIZero-green.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
id="metadata4142"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs4140" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1007"
id="namedview4138"
showgrid="false"
inkscape:zoom="1.6820179"
inkscape:cx="-191.39267"
inkscape:cy="54.855534"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Ebene_1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<polygon
points="36.911,63.104 36.911,66.116 36.911,132.309 36.911,135.321 39.346,136.825 96.715,169.921 99.273,171.419 101.853,169.921 159.319,136.825 161.938,135.321 161.938,132.309 161.938,66.116 161.938,63.104 159.308,61.6 101.841,28.504 99.234,27.006 96.629,28.504 39.347,61.6 "
id="polygon4013"
style="fill:#96c00a;fill-opacity:1"
transform="matrix(1.3249745,0,0,1.3249745,-48.642464,-35.674938)" />
<polygon
points="161.712,62.925 161.712,131.589 99.212,167.589 36.712,131.589 36.712,62.925 99.212,26.925 "
id="polygon4015"
style="fill:#97bf00;fill-opacity:0.91764706"
transform="matrix(1.3249745,0,0,1.3249745,-48.642464,-35.674938)" />
<polygon
stroke-miterlimit="10"
points="157.712,65.379 157.712,133.046 99.212,166.88 40.712,133.046 40.712,65.379 99.212,31.546 "
id="Outerline"
transform="matrix(1.3249745,0,0,1.3249745,-48.642464,-35.674938)"
style="fill:none;stroke:#ffffff;stroke-width:2;stroke-miterlimit:10"
inkscape:label="#outerline" />
<g
id="g4281"
transform="matrix(1.3249745,0,0,1.3249745,-47.067006,-23.859001)"><path
inkscape:connector-curvature="0"
id="path42"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.55783975"
d="m 133.45691,60.461638 v 0 c 2.27263,0 4.11462,1.841988 4.11462,4.114628 v 27.330241 c 0,2.27264 -1.84199,4.114628 -4.11462,4.114628 -2.27264,0 -4.11463,-1.841988 -4.11463,-4.114628 V 64.576266 c 0,-2.27264 1.84199,-4.114628 4.11463,-4.114628" /><g
transform="matrix(0.55783976,0,0,-0.55783976,120.13631,77.682765)"
id="g44"><path
inkscape:connector-curvature="0"
id="path46"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 0,0 H -0.506 C -0.57,0 -0.633,-0.008 -0.698,-0.01 -0.762,-0.008 -0.825,0 -0.89,0 h -7.283 c -3.929,0 -7.359,-2.965 -7.613,-6.885 -0.278,-4.296 3.124,-7.867 7.361,-7.867 0.776,0 1.343,-0.754 1.111,-1.494 -0.658,-2.088 -2.341,-3.751 -4.547,-4.333 -2.074,-0.547 -4.276,-0.821 -6.605,-0.821 -4.007,0 -7.574,0.865 -10.7,2.595 -3.127,1.73 -5.57,4.144 -7.331,7.24 -1.761,3.096 -2.641,6.617 -2.641,10.564 0,4.006 0.88,7.558 2.641,10.654 1.761,3.097 4.219,5.493 7.377,7.195 3.156,1.698 6.768,2.549 10.836,2.549 4.681,0 8.865,-1.269 12.55,-3.807 2.341,-1.612 5.524,-1.588 7.757,0.171 3.48,2.741 3.289,8.045 -0.315,10.452 -1.7,1.136 -3.538,2.112 -5.512,2.928 -4.553,1.881 -9.623,2.823 -15.208,2.823 -6.679,0 -12.69,-1.412 -18.03,-4.235 -5.344,-2.822 -9.517,-6.738 -12.522,-11.747 -3.005,-5.008 -4.508,-10.67 -4.508,-16.983 0,-6.315 1.503,-11.975 4.508,-16.984 3.005,-5.009 7.148,-8.924 12.43,-11.747 5.282,-2.824 11.231,-4.235 17.849,-4.235 4.613,0 9.197,0.699 13.751,2.095 0.045,0.014 0.091,0.028 0.136,0.042 7.104,2.202 11.884,8.86 11.884,16.297 v 9.047 C 6.486,-2.904 3.583,0 0,0" /></g><g
transform="matrix(0.55783976,0,0,-0.55783976,85.80763,64.525332)"
id="g48"><path
inkscape:connector-curvature="0"
id="path50"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v -49.176 c 0,-4.023 -3.262,-7.285 -7.286,-7.285 h -1.381 c -2.181,0 -4.247,0.977 -5.631,2.662 l -24.229,29.505 c -1.804,2.197 -5.368,0.921 -5.368,-1.922 v -22.96 c 0,-4.023 -3.261,-7.285 -7.285,-7.285 -4.023,0 -7.285,3.262 -7.285,7.285 V 0 c 0,4.024 3.262,7.285 7.285,7.285 h 1.468 c 2.184,0 4.253,-0.979 5.636,-2.669 l 24.135,-29.475 c 1.802,-2.202 5.37,-0.927 5.37,1.918 V 0 c 0,4.024 3.261,7.285 7.285,7.285 C -3.262,7.285 0,4.024 0,0" /></g></g><g
aria-label="Z E R O"
transform="matrix(0.94681934,0,0,0.94681934,-209.97267,182.03385)"
style="font-variant:normal;font-weight:600;font-stretch:normal;font-size:31.76000023px;font-family:'Montserrat SemiBold';-inkscape-font-specification:Montserrat-SemiBold;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:0.7171717;fill-rule:nonzero;stroke:none"
id="text56"><path
inkscape:connector-curvature="0"
d="m 243.58117,-73.015206 h 19.46231 v 3.613321 l -12.42176,15.02707 h 12.77844 v 4.512774 h -20.17567 v -3.613321 l 12.42176,-15.02707 h -12.06508 z"
id="path2325" /><path
inkscape:connector-curvature="0"
d="m 278.7684,-73.015206 h 16.11262 v 4.512774 h -10.14211 v 4.311172 h 9.5373 v 4.512773 h -9.5373 v 5.303672 h 10.48328 v 4.512774 H 278.7684 Z"
id="path2327" /><path
inkscape:connector-curvature="0"
d="m 320.00367,-62.749034 q 1.87645,0 2.68285,-0.697851 0.82192,-0.697852 0.82192,-2.295157 0,-1.581796 -0.82192,-2.26414 -0.8064,-0.682344 -2.68285,-0.682344 h -2.51226 v 5.939492 z m -2.51226,4.125078 v 8.761915 h -5.97051 v -23.153165 h 9.11859 q 4.57481,0 6.69938,1.535274 2.14008,1.535273 2.14008,4.853945 0,2.295156 -1.11657,3.768399 -1.10105,1.473242 -3.33418,2.171093 1.22512,0.279141 2.18661,1.271641 0.97699,0.976992 1.96949,2.9775 l 3.24113,6.575313 h -6.3582 l -2.82242,-5.753399 q -0.85293,-1.736875 -1.73688,-2.372695 -0.86844,-0.635821 -2.32617,-0.635821 z"
id="path2329" /><path
inkscape:connector-curvature="0"
d="m 357.57911,-69.107237 q -2.72938,0 -4.23364,2.016016 -1.50425,2.016015 -1.50425,5.675859 0,3.644336 1.50425,5.660352 1.50426,2.016015 4.23364,2.016015 2.74488,0 4.24914,-2.016015 1.50426,-2.016016 1.50426,-5.660352 0,-3.659844 -1.50426,-5.675859 -1.50426,-2.016016 -4.24914,-2.016016 z m 0,-4.32668 q 5.58281,0 8.7464,3.19461 3.1636,3.194609 3.1636,8.823945 0,5.613828 -3.1636,8.808438 -3.16359,3.194609 -8.7464,3.194609 -5.56731,0 -8.74641,-3.194609 -3.16359,-3.19461 -3.16359,-8.808438 0,-5.629336 3.16359,-8.823945 3.1791,-3.19461 8.74641,-3.19461 z"
id="path2331" /></g></svg>

After

Width:  |  Height:  |  Size: 7.3 KiB

1238
yarn.lock

File diff suppressed because it is too large Load diff