Initial commit

This commit is contained in:
Niko Reunanen 2025-04-09 11:12:51 +03:00
commit 1fe72d15c7
Signed by: nreunane
GPG key ID: D192625387DB0F16
102 changed files with 5246 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.DS_Store
*.swp
public

6
archetypes/default.md Normal file
View file

@ -0,0 +1,6 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

80
config.yaml Normal file
View file

@ -0,0 +1,80 @@
baseURL: https://nikoreunanen.com
languageCode: en-us
defaultContentLanguage: en
title: Cognitive Digressions
theme: cupper-hugo-theme
# enableGitInfo: true
googleAnalytics: true
taxonomies:
tag: tags
permalinks:
post: /:filename/
imaging:
quality: 99
params:
description: Inner monologue or just hearing voices?
homeMetaContent: Cognitive Digressions is a repository of half-digested ideas
footer: All expressed views on this site are my own and do not represent the opinions of any entity whatsoever with which I have been, am now, or will be affiliated.
dateFormat: Jan 2, 2006
katex: true
hideHeaderLinks: false
search: true
showThemeSwitcher: true
moveFooterToHeader: false
customCss:
- css/basic_highlight.css
customJs:
- js/basic_highlight.js
menu:
nav:
- name: About
url: /
weight: 1
- name: Posts
url: /post/
weight: 2
- name: LinkedIn
url: https://www.linkedin.com/in/nikoreunanen/
weight: 3
- name: Contracting
url: https://ntsol.io
weight: 4
- name: RSS
url: /index.xml
weight: 5
markup:
defaultMarkdownHandler: goldmark
goldmark:
extensions:
definitionList: true
footnote: true
linkify: true
strikethrough: true
table: true
taskList: true
typographer: true
parser:
attribute: true
autoHeadingID: true
renderer:
hardWraps: false
unsafe: true
xHTML: false
highlight:
codeFences: false
hl_lines: ""
lineNoStart: 1
lineNos: false
lineNumbersInTable: true
noClasses: true
style: monokai
tabWidth: 4
tableOfContents:
endLevel: 6
startLevel: 2

11
content/_index.md Normal file
View file

@ -0,0 +1,11 @@
---
title: "Cognitive Digressions"
date: 2021-01-21
draft: false
---
Welcome to a repository of half-digested ideas, partially explored thoughts and other cognitive digressions. A mental scratchpad of sorts.
Personal views: [absurdism](https://en.wikipedia.org/wiki/Absurdism), cats are awesome, coding is creative, anything can be interesting, boring kills businesses, music creates the feelings in a movie, it is not good to spend time with copies of yourself, the division between qualitative and quantitative research is artificial.
Don't swallow information without chewing it. Especially online. All expressed views on this site are my own and do not represent the opinions of any entity whatsoever with which I have been, am now, or will be affiliated.

View file

@ -0,0 +1,7 @@
---
title: "Augmenting Humans With Machine Learning"
date: 2021-01-19T01:58:16+02:00
draft: true
---
Why to replace them? Why to fight windmills?

View file

@ -0,0 +1,6 @@
---
title: "Cell Division as Objective"
date: 2021-01-23T22:09:39+02:00
draft: true
---

View file

@ -0,0 +1,373 @@
---
title: "Combine Django, Vue.js, Vuetify and TypeScript"
date: 2021-06-27T09:18:41+03:00
draft: false
---
Let's combine Django, Vue.js, Vuetify and TypeScript into a complete toolchain for your next web project 🚀🚀
Benefits:
* Automatic reloading of front-end (TypeScript, Vue.js, Vuetify) and back-end (Python, Django) during development for quick code iterations
* [Django](https://www.djangoproject.com/) got you covered for web development, from excellent database tools to user authentication, and everything between
* [Vue.js](https://vuejs.org/) makes it easy to write interactive user interfaces
* [Vuetify](https://vuetifyjs.com/en/) gives you a toolbox of graphical user interface components that follow the Material Design-framework
* [TypeScript](https://www.typescriptlang.org/) extends JavaScript with typing to catch JavaScript errors before running the code
* You'll have a self-contained application to deploy in production with static assets. No separate front-end project.
Notes:
* You need to have Python ≥ 3.6 and Node.js installed
* We'll use Vue.js 2.x since Vue.js 3 is still in alpha
* You can use [Flask](https://flask.palletsprojects.com/en/2.0.x/) or other Python web frameworks instead of Django. Actually, you could use any web framework, including [Actix Web](https://actix.rs/) for Rust, since the same principles apply for connecting the front-end with the back-end.
* This tutorial uses [whitenoise](http://whitenoise.evans.io/en/stable/) with Django to serve static assets in production builds. You might want to switch to a [CDN](https://en.wikipedia.org/wiki/Content_delivery_network) if you have a high-traffic system. You just need to configure the *DEPLOYMENT_PATH* variable in *vue.config.js* to match your CDN URL addresses.
Alright, let's go. First we need the official Vue.js standard tooling and to create a tutorial project folder.
```bash
# Install the official Vue.js command line tool
npm install -g @vue/cli
# Create a project folder
mkdir tutorial
```
## Create Vue.js front-end
Create a new Vue.js 2.x project.
```bash
# current directory: tutorial
# Create a new Vue.js 2.x project in tutorial/client
vue create client
# Choose "Manually select features"
# Select TypeScript with spacebar
# Press enter
# Choose Vue version 2.x
# Use class-style component syntax?: n
# Use Babel alongside TypeScript...: Y
# Linter: ESLint with error prevention only
# Pick additional lint features: Lint on save
# Where do you prefer...: In dedicated config files
# Save this as a preset for future projects?: N
# Install Vuetify
cd client
vue add vuetify # Choose the default option on prompt
# Tracker to connect Django and webpack bundles
npm install -D webpack-bundle-tracker
```
Replace the existing content in `tutorial/client/vue.config.js` with the following:
```js
const BundleTracker = require("webpack-bundle-tracker");
const DEPLOYMENT_PATH = '/static/'
module.exports = {
runtimeCompiler: true,
pages: {
index: {
entry: "./src/main.ts",
chunks: ["chunk-vendors"]
}
},
publicPath: process.env.PROJECT_MODE === 'production' ? DEPLOYMENT_PATH : 'http://localhost:8080/',
outputDir: "../server/example/static/",
chainWebpack: config => {
config.optimization.splitChunks(false)
config.plugin('BundleTracker').use(BundleTracker, [{filename: '../server/webpack-stats.json'}])
config.resolve.alias.set('__STATIC__', 'static')
config.devServer
.public('http://0.0.0.0:8080')
.host('0.0.0.0')
.port(8080)
.hotOnly(true)
.watchOptions({poll: 1000})
.https(false)
.headers({"Access-Control-Allow-Origin": ["*"]})
},
transpileDependencies: ["vuetify"]
}
```
We will create the server Django project and the example app very soon. The above `vue.config.js` does the following:
* The front-end is served from http://localhost:8080 during development (PROJECT\_MODE=development)
* Production version (PROJECT\_MODE=production) of the front-end is written into `tutorial/server/example/static` as a static build (`outputDir`). We'll create a Django app called example, which finds these static files with default configuration.
* `webpack-stats.json` informs Django how to access the front-end assets during development and production
* The front-end reloads automatically after changes
* The resulting bundle is named *index*. Notice that you could output multiple bundles with different TypeScript entry scripts.
## Create Django back-end
Install Django for back-end.
```bash
# current directory: tutorial
# Python virtual environment at tutorial/local/venv
python3 -m venv local/venv
source local/venv/bin/activate
# Upgrade the installation tools
pip install --upgrade setuptools pip wheel
# Install Django, whitenoise is for serving static assets
pip install Django whitenoise
# Create a Django project in tutorial/server
django-admin startproject server
# Create a new Django app for your project
cd server
python manage.py startapp example
```
Now let's register the new Django app by modifying the existing Django project settings `tutorial/server/server/settings.py`:
```python
# Add the following at the beginning of the file:
import os
# Add the following at the end of the file:
STATS_FILE = os.path.join(BASE_DIR, 'webpack-stats.json')
# Add the following in the INSTALLED_APPS list:
'example.apps.ExampleConfig'
# Add the following in the MIDDLEWARE list
# below 'django.middleware.security.SecurityMiddleware'
# see http://whitenoise.evans.io/en/stable/
'whitenoise.middleware.WhiteNoiseMiddleware'
```
Now let's route the views from the example app in the root project. Replace the existing content in `tutorial/server/server/urls.py` with the following:
```python
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('example.urls')),
path('admin/', admin.site.urls)
]
```
We'll create register an index page in the example app. It will serve the automatically generated Vue.js and Vuetify example page through Django. Write the following in a new file `tutorial/server/example/urls.py`
```python
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index')
]
```
Finally it's time to create the actual view that we already registered previously.
Replace the existing content in `tutorial/server/example/views.py` with the following:
```python
import json
import pathlib
from django.shortcuts import render
from django.http import HttpResponse
from django.conf import settings
class WebpackStatsProcessing:
def __init__(self):
self.data = json.loads(pathlib.Path(settings.STATS_FILE).read_text('utf-8'))
def get_tags(self, bundle: str) -> str:
include_tags = []
for asset in self.data['chunks'][bundle]:
if asset.endswith('.map'):
continue
location = self.data['assets'][asset]['publicPath']
if asset.endswith(('.js', 'js.gz')):
include_tags.append(f'<link href="{location}" rel="preload" as="script" />')
include_tags.append(f'<script type="text/javascript" src="{location}"></script>')
if asset.endswith(('.css', '.css.gz')):
include_tags.append(f'<link href="{location}" rel="stylesheet preload" as="style" />')
return '\n'.join(include_tags)
webpack_stats_tracker = WebpackStatsProcessing()
def index(request):
return HttpResponse(render(request, 'example/vuetify_bundle.html', context={
'bundle': webpack_stats_tracker.get_tags('index'),
'title': 'Index page from Example Django app'
}))
```
The class *WebpackStatsProcessing* is an example on how to parse *webpack-stats.json* to load a webpack bundle (Vue.js, Vuetify, ...) and output the required script and style tags for Django HTML templates. As you see in the *index* view, the *bundle* context parameter contains the required tags. The file *webpack-stats.json* routes the assets through the development front-end server during development and a static asset build in a production.
The only thing missing anymore is the actual Django HTML template that is rendered by the *index* view. First, create a new folder `tutorial/server/example/templates/example` and then write the following content in a new file `tutorial/server/example/templates/example/vuetify_bundle.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css">
<title>{{ title }}</title>
</head>
<body>
<noscript>
<strong>We're sorry but frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
{{ bundle|safe }}
</body>
</html>
```
## Run development environment
Now we are ready to run the development environment. You need two terminals at the same time:
Terminal 1 (front-end):
```bash
# current directory: tutorial/client
npm run serve
# Wait for the code compilation to finish because
# it will write the webpack-stats.json
```
Terminal 2 (back-end):
```bash
# current directory: tutorial
source local/venv/bin/activate
cd server
python manage.py runserver
# You can ignore any database migration errors since
# this tutorial doesn't use database models
```
Open [http://localhost:8000](http://localhost:8000) and hopefully you'll see the front-end being served through Django with automatic reloads for front-end and back-end. For example, edit `tutorial/client/src/components/HelloWorld.vue`, save changes and the front-end should update automatically. Cool. Check the page source and you should see that the assets are requested from http://localhost:8080, which is the address configured in `vue.config.js`. This is possible because `webpack-stats.json` instructs Django to use the http://localhost:8080 during development.
Your tutorial file structure should look something like this:
```
tutorial
├── client
│   ├── README.md
│   ├── babel.config.js
│   ├── node_modules
│   ├── package-lock.json
│   ├── package.json
│   ├── public
│   │   ├── favicon.ico
│   │   └── index.html
│   ├── src
│   │   ├── App.vue
│   │   ├── assets
│   │   │   ├── logo.png
│   │   │   └── logo.svg
│   │   ├── components
│   │   │   └── HelloWorld.vue
│   │   ├── main.ts
│   │   ├── plugins
│   │   │   └── vuetify.ts
│   │   ├── shims-tsx.d.ts
│   │   ├── shims-vue.d.ts
│   │   └── shims-vuetify.d.ts
│   ├── tsconfig.json
│   └── vue.config.js
├── local
│   └── venv
└── server
├── db.sqlite3
├── example
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── templates
│   │   └── example
│   │   └── vuetify_bundle.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── server
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── webpack-stats.json
```
If you use Git for version control, then remember to put the following folders and files in .gitignore:
* node\_modules
* local
* static
* webpack-stats.json
## Build a production version
You might want to build a production version without the front-end development server so that only Django is used. Luckily it is very easy now:
```bash
# current directory: tutorial/client
PROJECT_MODE=production npm run build
```
Launch the Django development server again:
```bash
python manage.py runserver
````
Check the page source. You should see that the assets are Django static assets instead of the earlier origin http://localhost:8080. You could deploy the Django project this way if you don't mind the package *whitenoise* serving the static assets through Django and not an external CDN.
One option is to use gunicorn to serve the Django WSGI app. You can build it as a Docker image and deploy the image in production (e.g. Cloud Run in Google Cloud Platform):
```docker
FROM python:3.9.5-slim
ENV DEBIAN_FRONTEND noninteractive
ENV PYTHONUNBUFFERED True
# No need to use a root account
RUN groupadd -g 61000 docker
RUN useradd -g 61000 -l -m -s /bin/false -u 61000 docker
USER docker
COPY ./server /app
WORKDIR /app
RUN pip install --upgrade --no-cache-dir pip wheel setuptools
RUN pip install --no-cache-dir Django whitenoise gunicorn
# Add gunicorn to PATH
ENV PATH="/home/docker/.local/bin/:${PATH}"
ENV MODE="production"
CMD ["bash", "launch.sh"]
```
Write the following line in tutorial/server/launch.sh:
```bash
gunicorn server.wsgi:application --bind ":${PORT:-8000}" --workers 2 --threads 8 --timeout 0
```
Done.
## Conclusion
There is still a lot of space for optimization, cleaning, configuration, making build sizes smaller and so on. However, this should get you started. Now you have Django, Vue.js, Vuetify and TypeScript living together. Happy coding!

View file

@ -0,0 +1,65 @@
---
title: "Data Science Tips And Life Hacks"
date: 2021-01-30
draft: false
---
Here are some tips and life hacks on how to survive data science. As they say, work smart, not hard. As a matter of fact, my favorite tasks are the tasks that I don't have to do. It is possible that task, as a word, is defined in some forgotten dictionary as something to avoid. Like, has anyone in the history of humankind used the word task in a positive context? Anyway, going off on a tangent. Let's get started.
### Learn the domain where you work
It is easy to acquire a pile of numbers and compute something. Just calculate the average value or apply a statistical model. However, to be useful, connect your work with the domain. What do your results mean? What is the actual insight within your results? What kind of actions can be taken based on the results? Are the results valid? Are the results significant? Is there anything fishy about the results? Are your statistical assumptions valid? How to define and measure success? Are [type I errors](https://en.wikipedia.org/wiki/Type_I_and_type_II_errors) more serious than [type II errors](https://en.wikipedia.org/wiki/Type_I_and_type_II_errors)? Do you need to explain the logic behind the results or is a black box sufficient? It is hard to make impact and be relevant inside a vacuum.
### Are you solving the correct problem?
Make sure that you are solving a valuable problem in the first place. Otherwise you are fighting against windmills, competing in a race that you can't win. The "why" is at least as important as the "how".
{{< blockquote author="The author of this post" >}}
The value of the best solution for a wrong problem is a big number times zero
{{< /blockquote >}}
Some people will have a hard time communicating with you or even understanding what you do. Your world can be very abstract to others. However, you still need to interact with them and figure out what they need. For example, you can create mockups of deliverables, from documents to user interfaces. This will help people to latch on something concrete and have a real, grounded basis for discussion. They can relatively easily tell if you are moving towards a good direction, and to help find one. The quality of feedback, interaction, requirements and extracted domain knowledge will skyrocket.
### Understand people
Humans are irrational and implicitly anthropomorphize everything. Like, "this restaurant makes excellent pasta" or "did you hear about the artificial intelligence that detects cats in images." However, organizations, businesses and companies are not living creatures. They consists of humans. Clients and customers are humans, even in business-to-business context. You operate in a sandbox filled to the brim with Homo sapientes. There is no escape. Soft skills are very important and required for efficient collaboration. Before you point your finger at me, I acknowledge that many people together form a system that exhibits its own behavior patterns, like how birds fly together or how atoms form solid matter together.
Find your supporters in your organization, possibly the people who decided to hire you. Try to stay in friendly terms with them, remember their birthdays and so on. Supporters are your hedge against problems. Let's say that your employer experiences financial challenges. If decision makers in the organization like you, and they understand your value for the business, then you might not be the first one to let go.
Try to get along with people, try to be like-able. Smile. Don't make your work life harder than it has to be. It sucks when you build an awesome, provenly beneficial system and no-one wants to use it. You effectively end up doing nothing. Zero impact and no business value. Therefore, it is of a paramount importance to obtain supporters, testers, collaborators, feedback givers, users and internal buy-in for your work.
Data science is an abstract, hazy concept for many people. Just remember that they are not stupid or less intelligent than you. They are professionals in their own field. Who knows, maybe they are just not interested in data science. It is on you to help them understand your value. Never grow a unhealthy ego, no-one wants to feel stupid. The universe does not owe success and fame to you because you can implement the latest tricks in machine learning. Teach the intuition of relevant concepts in data science to your work buddies. Do not mind repeating the same things over and over again. Data science is a complex area and you can provide an easy, abstracted interface to utilize the power of data science.
Empathy is not only for hippies. Empathy is seriously important and gives you tools to build a personal connection with the person in front of you. Step in her shoes. Understand her and think from her perspective. What motivates her? What makes her tick? What are her hobbies? What are her values? Now you can use familiar vocabulary, build analogies, frame impact into relevant outcomes and become interesting. You can help her to understand you, what you do and why your work is important.
### Data? Evaluation metrics?
You need to define what you are doing before acquiring data. If you have to produce insight or create something that works, practice designing experiments and to apply the scientific method. Put science in data science. For example, define hypotheses and how to measure effect sizes to reject or accept the hypotheses.
Be careful about the measures of effect size, which are typically some evaluation metrics in machine learning context. For example, accuracy metric is a bad choice for data with class imbalance. Let's say that you are building a system to diagnose a disease where 0.1% of population has the disease. You get an expected accuracy of 99.9% simply by diagnosing everyone to not have the disease. You provide accurate diagnoses while denying treatment from a lot of people.
Now you need to define the required data. You need to understand the business context and domain to figure out if the data exist, can be bought or if you have to collect it. Take the following dimensions into account: cost, time, effort, legislation and availability.
### Dont tune parameters forever
Create a baseline result using a simple model that is easy to implement, understand and deploy in production. The baseline result is a measure stick to determine progress, and sometimes you'll end up noticing that the simple model is all you need. For example, use [Logistic Regression](/logistic-regression-is-worth-learning/). Set a time limit for experiments and be systematic with tracking your experiments. Sometimes you tilt, go into a parameter frenzy and will eventually repeat existing experiments. Don't tweak model parameters or hyperparameters for months if the incremental improvement is not justified by its business potential. Sometimes significant improvements are acquired by paradigm changes in model structure and using more accurate statistical assumptions through better understanding of the domain.
### Feeling of loneliness and organizational maturity
One of the common reasons for a data science person to quit is the feeling of loneliness. If you are looking for a new job, find out if the potential work places have peers and mentors available. Businesses that are not mature in data science might not be easy on your mental health unless you have a very entrepreneurial personality. Ask questions during the recruitment process to assess the maturity. For example, by probing how they approach model deployment. Remember that you can also find mentors and data friends outside your work environment.
### Prepare for help requests and to turn down some of them
If people find you useful, then they are likely to want your input and effort on many things. You might have to start turning some of them down to get your own work done. A data science manager can be helpful to have around since she can gate the incoming tickets on your behalf. She is someone who guards your time. A data science manager is probably found in organizations that are more mature in data science.
### Never stop learning
Learn to learn, and never stop, it will keep rewarding you. You will become much more productive if you have a wide skill set. Maybe even a tenfold increase in productivity. I personally like the idea of a T-shaped skill set where a person knows a lot about some topics and a bit about many topics. It is very empowering to be able to create a concrete prototype of any idea: app, website, machine learning algorithm and so on.
Do not overfit your machine learning skills by being an expert in using only one specific method. Your favorite algorithm is not a hammer and not every problem is a nail. Have knowledge of many different methods, understand underlying theories and form mathematical connections between machine learning topics. Then you can design a suitable solution for a problem, and not the other way around.
Learn basics of software development, deployment and some best practices. Write unit tests and integration tests, especially for feature extraction pipelines. Implement active learning for speeding up the model training and data annotation. Learn the basics of containers and cloud platforms. You'll learn to structure your software in a deployment-friendly manner, especially if someone else deploys it. This person will quickly understand how your software is used, she will save a lot of time and have a longer, happier life.
### Math bugs are different than code bugs
A compiler or an interpreter can catch problems in source code but you are on your own with problems in mathematics and logic. Your neural network will happily keep training using random, shuffled labels, even though it's not what you want. Code defensibly and do not trust the data that come in. Depending on the domain and context, it is sometimes better to just crash the program after a failed logic assertion. Review your code carefully.

View file

@ -0,0 +1,10 @@
---
title: "[PDF] Distance Metrics Refresher"
date: 2021-01-21
draft: false
---
[Here is a distance metric refresher for you as a PDF document](/pdf/distance_metrics_refresher.pdf). I wrote it in 2014 but the related mathematics have not changed over the years. Surprise. Enjoy.
Peace and harmony.

View file

@ -0,0 +1,307 @@
---
title: "Logistic Regression is Worth Learning"
date: 2021-01-21
draft: false
---
Logistic Regression (LR) is not a divine truth that exists as a [Platonic ideal](https://en.wikipedia.org/wiki/Platonic_idealism). It is possible to design LR from first principles. LR is a great gateway to learn a variety of topics in mathematics, statistics and machine learning. And as a bonus, LR is useful in practice. Let's talk about LR.
## Corporate roleplay
It is Tuesday. You are enjoying a cup of coffee and your manager calls you. She says that we need to predict if a customer goes away (churns) in one month. You listen to her until you agree to do it, probably because your coffee is getting cold. Eventually you start to think about the problem and come up with a very short specification:
* Churn happens or doesn't. It is a binary outcome per customer.
* Your manager wants to prioritize her time with customers that are the most likely to churn. She needs the estimated probability of churn per customer.
* Your manager will be interested to understand how the predictions are made, especially if they are accurate. She might learn useful insights on how different factors affect customer churn.
* The probability estimates should not fluctuate heavily all the time.
## Start simple
Time to define the churn prediction task. We need a model that outputs the estimated probability of churn \\(\hat{p}\\):
$$ \hat{p}=P(churn | \vec{x}) \in [0,1] $$
The symbol \\(\vec{x}\\) denotes a \\(d\\)-dimensional vector \\(\vec{x}=\\{x_1,x_2,...x_d\\}\\) of \\(d\\) numbers. Let's call them data vectors. Also known as [feature](https://en.wikipedia.org/wiki/Feature_(machine_learning)) values in machine learning lingo. If a specific customer has a corresponding data vector \\(\vec{x}\\), then this customer has an estimated churn probability of \\(P(churn | \vec{x})\\). A math person might write \\(\vec{x} \in \mathbb{R}^d\\) meaning that the data vectors are contained in \\(d\\)-dimensional [Euclidean space](https://en.wikipedia.org/wiki/Euclidean_space). Relevant data vectors for churn prediction might be available in your Customer Relationship Managemen (CRM) system database.
We need to define a statistical model for \\(\hat{p}\\). Like, explicitly tell how \\(\hat{p}\\) is manifested in our world. Let's define a simple model for easy computation, inference and implementation. You are also more likely to see consistent results. Not so much with large neural networks where random initialization can give you a different winning [lottery ticket](https://arxiv.org/abs/1803.03635) every time, even if the data do not change. Machine learning is probably the only field where winning the lottery means that you have to work and grind even harder.
{{< blockquote author="The author of this post" >}}
You learn to expect that training a large neural network over and over again using the same data gives you different results.
{{< /blockquote >}}
However.
{{< blockquote author="Someone, not Einstein" >}}
The definition of insanity is doing the same thing over and over again and expecting different results.
{{< /blockquote >}}
Deep learning, not even once. Makes you crazy by definition... You can stop throwing tomatoes at me. I understand that if you fix every initial condition, you will get identical results over repetitions. And that there are techniques making the results more stable.
Can you imagine how unhappy your manager might become, and how hard her job would be, if "nothing changes" and the estimates change significantly? Of course we are assuming that you get acceptable results using a simple model. You can always test if a simple model is accurate enough in your business context. Anyway, I believe it is always a good idea to start with a simple model when it makes sense. Tip: you might need a complex model for speech recognition.
Ok, sorry for that digression, let's get back to designing a simple model for \\(\hat{p}\\). How about the following linear [functional form](https://www.encyclopedia.com/social-sciences/applied-and-social-sciences-magazines/functional-form) using a [dot product](https://en.wikipedia.org/wiki/Dot_product)?
$$ \hat{p}(\vec{x},\vec{w}) = \vec{x} \cdot \vec{w} = \sum\nolimits_i^d{\vec{x}_i\vec{w}_i} = \vec{x}_1\vec{w}_1 + ... + \vec{x}_d\vec{w}_d $$
How is the dot product useful for our purposes? It matches and activates to patterns that are exhibited by customers with a high probability of churn. It maps a customer-specific \\(\vec{x}\\) to a large value if \\(\vec{x}\\) contains patterns that indicate churn. Notice that you can only tweak the parameter vector \\(\vec{w}\\) because \\(\vec{x}\\) is already fixed and given. This is the reason why \\(\vec{w}\\) contains the model's knowledge, why it is called a parameter vector and why finding the values of \\(\vec{w}\\) is called training the model.
Unfortunately, the functional form that we designed sucks:
1. The [range](https://www.sydney.edu.au/content/dam/students/documents/mathematics-learning-centre/functions-domain-and-range.pdf) of the dot product \\(\vec{x} \cdot \vec{w}\\) is \\((-\infty,\infty)\\), which is not great if we want \\(\hat{p}\\) to represent a probability. Our earlier definition of \\(P\\), and the definition of a probability in general, says that a probability takes values within \\([0,1]\\). How about using the dot product as a unnormalized probability? No thanks, it's an ad hoc hack. How large values are considered to be large enough to indicate churn? It is a nightmare to find a reliable magic threshold.
2. If the [norms](https://en.wikipedia.org/wiki/Norm_(mathematics)) of \\(\vec{x}\\) or \\(\vec{w}\\) are large, then large changes are required for significant change in \\(\hat{p}\\). It is a gateway to [overfitting](https://en.wikipedia.org/wiki/Overfitting) your models to noise or having some variables dominate others just because they are measured in larger absolute units.
Time for a new iteration.
## Responsive math design
How to make \\(\hat{p}\\) more sensitive to smaller changes in \\(\vec{x}\\) or \\(\vec{w}\\)? Exponents. Those have some serious firepower. Let's use the natural exponential function as follows:
$$ \hat{p}(\vec{x},\vec{w}) = e^{\vec{x} \cdot \vec{w}} $$
Now changes in \\(\vec{x}\\) or \\(\vec{w}\\) result in multiplicative change in \\(\hat{p}\\).
The previously mentioned problem of \\(\hat{p}\\) not being a probability is still here. The value of \\(\hat{p}\\) is between zero and positive infinity: \\(e^{\vec{x} \cdot \vec{w}} \in (0,\infty)\\). Therefore, \\(\hat{p}\\) is not a valid probability unless we use duck tape and define \\(\hat{p}=min(1,e^{\vec{x} \cdot \vec{w}})\\). Just... no. Let's come up with something better.
## Houston, we have a probability
What is a suitable function that maps \\((0,\infty)\\) to \\((0,1)\\)?
Time passes, the head scratching is audible and nothing comes up. Time to quit? No. We should try something different. So far we have been focusing on the right side of the equation.
Let's define a function called odds to map a probability \\(p \in \[0,1)\\) to \\(\[0,\infty)\\):
$$
odds(p) = \frac{p}{1-p}
$$
The inverse function of odds maps \\(\[0,\infty)\\) back to a probability \\(\[0,1)\\):
$$
p(odds) = \frac{odds}{1+odds}
$$
Ok. So we have the following functions available:
| Function | Domain (from) | Range (to) |
| ------------- |:-------------:| -----:|
| \\(odds(p) = \frac{p}{1-p}\\) | \\(\[0,1)\\) | \\(\[0,\infty)\\) |
| \\(p(\vec{x},\vec{w})=e^{\vec{x} \cdot \vec{w}}\\) | \\((-\infty,\infty)\\) | \\((0,\infty)\\) |
Interesting. Two equations with matching legos. It is possible to model the \\(odds\\) function as a dot product since they have compatible ranges:
$$
odds(p) = p(\vec{x},\vec{w})
$$
Now throw the inverse odds function into the mix:
$$
p(odds(\vec{x},\vec{w})) = \frac{e^{\vec{x} \cdot \vec{w}}}{1+e^{\vec{x} \cdot \vec{w}}} = \frac{1}{1+e^{-\vec{x} \cdot \vec{w}}}
$$
You'll get the last form by multiplying \\(\frac{e^{\vec{x} \cdot \vec{w}}}{1+e^{\vec{x} \cdot \vec{w}}}\\) with \\(\frac{e^{-\vec{x} \cdot \vec{w}}}{e^{-\vec{x} \cdot \vec{w}}}\\). Since \\(p\\) behaves like a probability, and we want a probability, let's redefine \\(\hat{p}\\) using \\(p\\) like a coder who re-assigns a variable value:
$$
\hat{p} = P(churn | \vec{x}) = p(odds(\vec{x},\vec{w})) = \frac{1}{1+e^{-\vec{x} \cdot \vec{w}}}
$$
Well, well, look who's here. Our good friend Logistic Regression. The model outputs a valid probability estimate and its decision boundary is linear. We have a model that fulfills our short specification for churn prediction. We might be wrong but at least we are not guaranteed to be wrong.
Please wait. Do not deploy your model in production yet. Your manager is not going to be happy with the results. Why? The model spews out noise, it makes random guesses, no intelligence involved. Why? There is zero knowledge in the model since \\(\vec{w}\\) is unchanged. The model needs to be trained and the parameters adjusted using training data.
## Why the name?
Why LR is called Logistic and Regression? Let's take some shortcuts instead of repeating all the previous steps. The following function is called [logit](https://en.wikipedia.org/wiki/Logit) and it is the logarithm of our previously defined odds function:
$$
logit(p) = ln(\frac{p}{1-p}) \in (-\infty,\infty)
$$
Let's build a model where the logit defined as the previously used dot product. It is fine since \\(\vec{x} \cdot \vec{w} \in (-\infty,\infty)\\):
$$
ln(\frac{p}{1-p}) = \vec{x} \cdot \vec{w}
$$
Solve for \\(p\\) and you'll get:
$$
p = \frac{e^{\vec{x} \cdot \vec{w}}}{1+e^{\vec{x} \cdot \vec{w}}} = \frac{1}{1+e^{-\vec{x} \cdot \vec{w}}} = \sigma(\vec{x} \cdot \vec{w})
$$
We find LR again. The function \\(\sigma\\) is called a [sigmoid function](https://en.wikipedia.org/wiki/Sigmoid_function) and it is a special case of [logistic function](https://en.wikipedia.org/wiki/Logistic_function). Sigmoid function is actually the inverse function of the logit function.
Regression comes from the linear regression model that we throw in the sigmoid function, which is a special case of logistic function. That's Logistic and Regression in Logistic Regression.
## Learning in machine learning
We have defined the model, which turned out to be LR. The next step is to put learning in machine learning. For our LR, learning means finding a parameter vector \\(\vec{w}\\) that outputs a large value of \\(\vec{x} \cdot \vec{w}\\) when \\(\vec{x}\\) corresponds to a customer with a high probability of churn, and vice versa.
What is a principled basis for tweaking the parameter vector? First of all, it is mathematically impossible to create information from nothing. We need to continue injecting knowledge and assumptions into the system, which we already started by defining the functional form or our LR model. How about observations of what has happened so far? Well, at least they might reflect the real world whereas our own guesses might not. Luckily your CRM system maintains a database of past and current customer behavior. We can extract \\(n\\) pairs of data vectors \\(\vec{x}\_i\\) and churn outcomes \\(y\_i \in \\{0,1\\}\\). This set of actual, historical behavior is called a dataset:
$$
\mathbf{X}=\\{(\\vec{x}\_1,y\_1),...,(\\vec{x}\_n,y\_n)\\} \subset \mathbf{R}^d \times \\{0,1\\}
$$
Okay. How to get started in figuring out a suitable \\(\vec{w}\\)? How do we even know what is a good \\(\vec{w}\\)? Well, it is impossible to define what is good if there is no reference of bad.
{{< blockquote author="Antoine-Augustin Cournot, 1847" >}}
If you can not measure it, you can not improve it.
{{< /blockquote >}}
Thanks Antoine-Augustin. Indeed, it is a fundamental necessity to have a function \\(L(\vec{w} | \mathbf{X})\\) that tells us how good fit a given parameter vector is for the available dataset. Let's call it a [likelihood function](https://en.wikipedia.org/wiki/Likelihood_function). This formulation let's us to find a parameter vector \\(\vec{w}\_\*\\) that is consistent with the dataset by maximising the likelihood function value:
$$
\vec{w}\_\*=argmax_{\vec{w}}L(\vec{w} | \mathbf{X})
$$
Therefore, \\(\vec{w}\_\*\\) gives us LR that is aligned with the dataset. The implicit assumption for making predictions using previously unseen data vectors is that the patterns in past behavior are indicative and predictive of the future behavior. If this assumption does not hold for churn prediction, then you'll get incorrect predictions. Therefore, we will continue by assuming that many customers share similar reasons for churn. Let's call \\(\vec{w}\_\*\\) a solution since it is the parameter vector of the highest likelihood for the given data.
Notice that if we had a dataset of infinite size (\\(n=\infty\\)), then we wouldn't need LR at all. We could calculate the churn probability as the ratio between the number of churn positives and total observations for a data vector. It would be a database query. However, since obviously we don't have an infinite amount of data, let alone a computer that runs for an infinite time, we have to make assumptions and find patterns. And hope that the customers now and in the future exhibit the same patterns.
Ok. What next? We need to define the functional form of the likelihood function that computes the compatibility of a parameter vector with a given dataset. Let's start by defining the likelihood function for a single pair of a data vector and outcome. Notice that it is a dataset of size \\(n=1\\). How about the following definition?
$$
L(\vec{w} | \vec{x},y) = \begin{cases}
\hat{p}(\vec{x},\vec{w}) & \text{if } y=1 \\\\
1-\hat{p}(\vec{x},\vec{w}) & \text{if } y=0
\end{cases}
$$
If a customer did actually churn (\\(y=1\\)), then the likelihood is the estimated probability of churn. If the customer didn't churn (\\(y=0\\)), then the likelihood is the estimated probability of not churning. No matter what is the outcome, if we maximize the value of \\(L(\vec{w} | \vec{x},y)\\), then we maximize the fit of our LR model to the data. It is exactly what we want. In other words, maximizing the likelihood function maximizes the amount of correctly assigned probability. Let's do what coders do and refactor it into a single expression for mathematical convenience:
$$
L(\vec{w} | \vec{x},y) = \hat{p}(\vec{x},\vec{w})^{y}(1-\hat{p}(\vec{x},\vec{w}))^{1-y}
$$
Done. The definition has not changed. Let's assume that the pairs of \\(\vec{x}\_i,y\_i\\) are [independent and identically distributed](https://en.wikipedia.org/wiki/Independent_and_identically_distributed_random_variables). Now we can generalize the definition of the likelihood function for datasets of size \\(n \ge 1\\) by defining a joint probability:
$$
L(\vec{w} | \mathbf{X}) = \prod\nolimits_i^n \hat{p}(\vec{x_i},\vec{w})^{y_i}(1-\hat{p}(\vec{x_i},\vec{w}))^{1-y_i}
$$
Phew! There it is. Maximize \\(L(\vec{w} | \mathbf{X})\\) to get a solution and call it a day. However, aren't we missing something quite essential here? We have to maximize the likelihood function and it's not going to happen by wishful thinking alone.
## Learning to learn continues
The situation is as follows. We have a dataset and we have a likelihood function. The next step is to find a parameter vector to maximize the likelihood function. It smells like an optimization task. Where and how to get started? Maybe you could gamble and sample random parameter vectors from a [uniform distribution](https://en.wikipedia.org/wiki/Continuous_uniform_distribution) for ten minutes, and save the \\(\vec{w}\\) with the highest likelihood function value. Well... you might get lucky and get reasonable results. Or not. It is not deterministic, there are no guarantees of optimality even if you throw dice for the rest of your life.
Do you happen to remember calculus? Derivatives, integrals, rate of change. The stuff that was butchered by a boring teacher. The stuff that you never used? Good news. You did not study for nothing. We have a real use case for calculus. Let's start.
[Calculus](https://en.wikipedia.org/wiki/Calculus) is the mathematics of change where [derivatives](https://en.wikipedia.org/wiki/Derivative) measure the rate of change of a function at a given point. Like, how stable the particular location of a function is. Or how sensitive the function is to a given input. We can use derivatives to define the change in our likelihood function given a parameter vector as an input. Sounds promising. Actually, we can calculate the direction where we need to move the parameter vector to increase the value of the likelihood function. That's exactly what we need, a tool served for us on a silver platter. To use this mighty tool, we need to define the derivatives of the likelihood function with respect to the individual elements of a parameter vector. They are called [partial derivatives](https://en.wikipedia.org/wiki/Derivative#Partial_derivatives). When we collect the partial derivatives into a vector, then it is called a [gradient](https://en.wikipedia.org/wiki/Gradient). Now, the gradient gives us the direction from \\(\vec{w}\\) that increases the \\(L(\vec{w} | \mathbf{X})\\) the fastest.
We have already spelled out the algorithm for maximizing the likelihood function. Push the parameter vector towards the direction defined by the gradient of the likelihood function with respect to the parameter vector. If we take repeated turns between calculating the gradient and updating the parameter vector, we arrive to an optimization algorithm called gradient ascend. Hopefully math people are not offended by our abuse of notation when we define the following assignment using the equality sign:
$$
\vec{w} = \vec{w} + \alpha\nabla_wL
$$
The alpha is a parameter of the gradient descend, and it is not a parameter of the LR model. In machine learning lingo, the alpha is a hyperparameter and it is called a learning rate in this gradient ascend context. The alpha is utilized to stabilize the gradient ascend by not taking too large or small steps towards the gradient. You can try \\(\alpha=\frac{0.05}{n}\\) as a starting point. The meaning behind the name of the gradient ascend is hopefully clear. The parameter vector ascends towards the direction of increased likelihood.
Now, to train the LR model, we can repeat the gradient ascend step until the likelihood function does not increase anymore. Done, lights out, time to go home now. Or not. We haven't derived the gradient yet. I promise that this is as deep as the recursion gets. Light is visible at the end of the tunnel already.
## Gradient without colors
The parameter vector has \\(d\\) elements. However, without loss of generality, we can derive the partial derivative of the \\(j\\):th element with respect to the likelihood function, and just copy it for the remaining elements to form the gradient. As a refresher, the following was the definition of the likelihood function:
$$
L(\vec{w} | \mathbf{X}) = \prod\nolimits_i^n \hat{p}(\vec{x_i},\vec{w})^{y_i}(1-\hat{p}(\vec{x_i},\vec{w}))^{1-y_i}
$$
The product is quite hairy and feels troublesome. Like, the equation is a giant multiplication. Have fun deriving monster sized equations. No thanks.
Let's use a transformation that doesn't change the solution \\(\vec{w}\_\*\\) while it makes the derivation easier. One such a function is the natural logarithm, which is a [monotonic function](https://en.wikipedia.org/wiki/Monotonic_function). It has the awesome property of converting products into sums:
$$
ln(L(\vec{w} | \mathbf{X})) = l(\vec{w} | \mathbf{X}) = \sum\nolimits_i^n y_iln(\hat{p}(\vec{x_i},\vec{w})) + (1-y_i)ln(1-\hat{p}(\vec{x_i},\vec{w}))
$$
The partial derivative of \\(l(\vec{w} | \mathbf{X})\\) with respect to the \\(j\\):th element of \\(\vec{w}\\) is denoted as \\(\frac{\partial l(\vec{w} | \mathbf{X})}{\partial w_j}\\). Time to wear a calculus hat and start deriving the derivative. Let's temporarily use a shorter notation \\(\hat{p}(\vec{x},\vec{w})=\sigma(z)=\hat{p}\\) where \\(z=\vec{x} \cdot \vec{w}\\) to make the equations shorter.
$$
\begin{aligned}
\frac{l(\vec{w} | \mathbf{X})}{\partial w_j} &= \frac{\partial}{\partial w_j}[\sum\nolimits_i^n y_iln(\hat{p}) + (1-y_i)ln(1-\hat{p})] \cr
&= \sum\nolimits_i^n \frac{\partial}{\partial w_j}[y_iln(\hat{p}) + (1-y_i)ln(1-\hat{p})] \cr
&= \sum\nolimits_i^n \frac{\partial}{\partial w_j}[y_iln(\hat{p})] + \frac{\partial}{\partial w_j}[(1-y_i)ln(1-\hat{p})] \cr
&= \sum\nolimits_i^n y_i\frac{\partial}{\partial \hat{p}}\frac{\partial \hat{p}}{\partial w_j}[ln(\hat{p})] + (1-y_i)\frac{\partial}{\partial \hat{p}}\frac{\partial \hat{p}}{\partial w_j}[ln(1-\hat{p})] \cr
&= \sum\nolimits_i^n y_i\frac{1}{\hat{p}}\frac{\partial}{\partial z}\frac{\partial \hat{z}}{\partial w_j}[\hat{p}] + (1-y_i)\frac{1}{1-\hat{p}}(-1)\frac{\partial}{\partial \hat{z}}\frac{\partial \hat{z}}{\partial w_j}[\hat{p}] \cr
&= \sum\nolimits_i^n \frac{y_i}{\hat{p}}\frac{\partial}{\partial z}\frac{\partial \hat{z}}{\partial w_j}[\hat{p}] + \frac{y_i-1}{1-\hat{p}}\frac{\partial}{\partial \hat{z}}\frac{\partial \hat{z}}{\partial w_j}[\hat{p}] \cr
\end{aligned}
$$
Okay... let's have a pause here and derive \\(\frac{\partial \hat{p}}{\partial z}\\) separately so that we can have a break from the previous monster.
$$
\begin{aligned}
\frac{\partial \hat{p}}{\partial z} &= \frac{\partial}{\partial z}\frac{1}{1+e^{-z}} \cr
&= \frac{\partial}{\partial z}(1+e^{-z})^{-1} \cr
&= -(1+e^{-z})^{-2}\frac{\partial}{\partial z}(1+e^{-z}) \cr
&= -(1+e^{-z})^{-2}e^{-z}\frac{\partial}{\partial z}[-z] \cr
&= (1+e^{-z})^{-2}e^{-z} \cr
&= \frac{e^{-z}}{(1+e^{-z})^2} \cr
&= \frac{1}{1+e^{-z}}\frac{e^{-z}}{1+e^{-z}} \cr
&= \hat{p}(1-\hat{p}) \cr
\end{aligned}
$$
Back to the likelihood business:
$$
\begin{aligned}
\frac{l(\vec{w} | \mathbf{X})}{\partial w_j} &= \sum\nolimits_i^n \frac{y_i}{\hat{p}}\frac{\partial}{\partial z}\frac{\partial \hat{z}}{\partial w_j}[\hat{p}] + \frac{y_i-1}{1-\hat{p}}\frac{\partial}{\partial \hat{z}}\frac{\partial \hat{z}}{\partial w_j}[\hat{p}] \cr
&= \sum\nolimits_i^n \frac{y_i}{\hat{p}}\hat{p}(1-\hat{p})\frac{\partial \hat{z}}{\partial w_j}[z] + \frac{y_i-1}{1-\hat{p}}\hat{p}(1-\hat{p})\frac{\partial \hat{z}}{\partial w_j}[z] \cr
&= \sum\nolimits_i^n \frac{y_i}{\hat{p}}\hat{p}(1-\hat{p})x_i^j + \frac{y_i-1}{1-\hat{p}}\hat{p}(1-\hat{p})x_i^j \cr
&= \sum\nolimits_i^n y_i(1-\hat{p})x_i^j + (y_i-1)\hat{p}x_i^j \cr
&= \sum\nolimits_i^n y_ix_i^j-y_i\hat{p}x_i^j+y_i\hat{p}x_i^j-\hat{p}x_i^j \cr
&= \sum\nolimits_i^n y_ix_i^j-\hat{p}x_i^j \cr
&= \sum\nolimits_i^n (y_i-\hat{p})x_i^j \cr
\end{aligned}
$$
There it is! The partial derivative that can save us. Let's say it aloud once more:
$$
\frac{\partial l(\vec{w} | \mathbf{X})}{\partial w_j} = \sum\nolimits_i^n (y_i - \hat{p}(\vec{x_i},\vec{w}))x_i^j
$$
The symbol \\(x_i^j\\) means the \\(j\\):th element of the \\(i\\):th data vector in the dataset. Now, the gradient is as follows:
$$
\nabla_wl(\vec{w} | \mathbf{X}) = \\{\frac{\partial l(\vec{w} | \mathbf{X})}{\partial w_1},...,\frac{\partial l(\vec{w} | \mathbf{X})}{\partial w_d}\\}
$$
Now you are ready to train your LR for churn prediction:
1. Get a dataset
2. Initialize \\(\vec{w}\\) with random values
3. Train the LR:
1. Calculate \\(\nabla_wl(\vec{w} | \mathbf{X})\\)
2. Update \\(\vec{w} = \vec{w} + \alpha\nabla_wl(\vec{w} | \mathbf{X})\\).
3. If the likelihood function \\(L(\vec{w} | \mathbf{x})\\) increased, then go to 3a. If not, then \\(\vec{w}\_\*=\vec{w}\\) and go to 4.
4. Use your LR to make churn predictions as \\(\hat{p}(\vec{x},\vec{w}\_\*) = \sigma(\vec{x} \cdot \vec{w}\_\*)\\)
## Conclusion
LR is worth learning since it covers multiple topics. LR is also relevant and useful in practice. I skipped some topics that might be helpful to know. Nevertheless, you are ready to implement the first version of the LR for churn prediction.
A coder can import scikit-learn in Python and use the provided LR without any knowledge of the previously explained stuff. That's fine until its not. For example, the gradient ascend of the likelihood function might not converge properly. If you understand the concepts behind LR, then you might have an intuition of how to fix the problem. Otherwise, you have to guess what to ask at Stack Overflow.
LR has some direct connections to more complex models:
* If you [Kaggle](https://www.kaggle.com/), then you might be aware that [sigmoid function is available](https://xgboost.readthedocs.io/en/latest/parameter.html#learning-task-parameters) in [XGboost](https://github.com/dmlc/xgboost/) for binary classification.
* If you think in neural networks, then LR is a neural network with one sigmoid-activated unit. LR is also often the last transformation in deep neural networks for binary classification. The deep neural network tries to unfold the data before it arrives to the LR, which throws a linear decision boundary at the data. The transformations find a data representation that is [linearly separable](https://en.wikipedia.org/wiki/Linear_separability) for the LR. Therefore, the purpose of the millions and billions of parameters is to serve the LR by finding a data transformation that the mighty LR can comprehend, also known as feature learning. I find it funny, it's like trying to build a simple joystick with one button to fly a massive passenger airplane. Anyway.
Further topics, exercises and tasks for you:
* How would you measure the accuracy of your LR as a churn predictor for unseen data vectors? What is overfitting? What is cross-validation?
* What is regularization? What is the difference of \\(l_1\\) and \\(l_2\\) regularization? Derive the gradient \\(\nabla_wl(\vec{w} | \mathbf{X})\\)
when the likelihood function is re-defined as \\(l(\vec{w} | \mathbf{X}) - l_2(\vec{w})\\).
* Check out softmax function for generalizing LR to have a categorical output. Derive the gradient for this softmax multiclass LR. What is the intuition behind naming softmax as softmax?
* There are arguably more efficient algorithms available for the gradient ascend. Find some of them.
* What is the difference when a parameter vector is at a global optimum or at a local optimum?
* What is a greedy algorithm? Why is the gradient ascend a greedy algorithm?
* Why not to worry about ending up at a local optimum with LR, even when using the gradient ascend that is a greedy algorithm?
* Implement the LR evaluation and training from scratch in Python. Utilize some public dataset. Use NumPy for vectorizing the computations.
* What is entropy in information theory? How is \\(l(\vec{w} | \mathbf{X})\\) related to entropy and what is the intuition? Why is the negative of \\(l(\vec{w} | \mathbf{X})\\) often called binary cross-entropy loss?
* What is the connection of \\(L(\vec{w} | \mathbf{X})\\) and Bernoulli distribution?
Peace and harmony.

View file

@ -0,0 +1,6 @@
---
title: "[PDF] How To Measure Customer Experience"
date: 2021-01-19T02:02:47+02:00
draft: true
---

View file

@ -0,0 +1,6 @@
---
title: "Singular Value Decomposition Is Worth Learning"
date: 2021-01-19T02:24:02+02:00
draft: true
---

View file

@ -0,0 +1,15 @@
---
title: "Teach Context"
date: 2021-01-19T02:53:07+02:00
draft: true
---
A math equation is a pinnacle of sweat, tears and exploration. There is a human story.
A slight analog with show and tell in literature.
It is your responsibility to make people interested and sell your ideas.
Like the cliche says that there are no boring topics, just bored minds.
Give context to your listeners. Help them to think and understand.

View file

@ -0,0 +1,145 @@
/* PrismJS 1.23.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+docker+python */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
color: black;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
color: black;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: white;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.token.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
/* This background color was intended by the author of this theme. */
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View file

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

2
themes/cupper-hugo-theme/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
exampleSite/public/
resources/

View file

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2017 Heydon Pickering
Copyright (c) 2019 Zachary Betz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,109 @@
# Cupper
[![Netlify Status](https://api.netlify.com/api/v1/badges/bc8c4e51-37ee-419d-ad4f-b378010ee546/deploy-status)](https://app.netlify.com/sites/cupper-hugo-theme/deploys)
An accessibility-friendly Hugo theme, ported from the [original Cupper](https://github.com/ThePacielloGroup/cupper) project.
## Table of contents
- [Demo](#demo)
- [Minimum Hugo version](#minimum-hugo-version)
- [Installation](#installation)
- [Updating](#updating)
- [Run example site](#run-example-site)
- [Configuration](#configuration)
- [Logo](#logo)
- [Favicons](#favicons)
- [Shortcodes](#shortcodes)
- [Syntax highlighting](#syntax-highlighting)
- [Disable toc for a blog post](#disable-toc-for-a-blog-post)
- [Localization](#localization)
- [Custom CSS and JS](#custom-css-and-js)
- [Getting help](#getting-help)
- [Credits](#credits)
## Demo
https://cupper-hugo-theme.netlify.com/
## Minimum Hugo version
Hugo version `0.60.1` or higher is required. View the [Hugo releases](https://github.com/gohugoio/hugo/releases) and download the binary for your OS.
## Installation
From the root of your site:
```
git submodule add https://github.com/zwbetz-gh/cupper-hugo-theme.git themes/cupper-hugo-theme
```
## Updating
From the root of your site:
```
git submodule update --remote --merge
```
## Run example site
From the root of `themes/cupper-hugo-theme/exampleSite`:
```
hugo server --themesDir ../..
```
## Configuration
Copy `config.yaml` from the [`exampleSite`](https://github.com/zwbetz-gh/cupper-hugo-theme/tree/master/exampleSite), then edit as desired.
## Logo
Place your SVG logo at `static/images/logo.svg`. If you don't provide a logo, then the default theme logo will be used.
## Favicons
Upload your image to [RealFaviconGenerator](https://realfavicongenerator.net/) then copy-paste the generated favicon files under `static`.
## Shortcodes
See the [full list of supported shortcodes](https://cupper-hugo-theme.netlify.com/cupper-shortcodes/).
## Syntax highlighting
Syntax highlighting is provided by [Prism](https://prismjs.com/). See this [markdown code fences example](https://cupper-hugo-theme.netlify.com/cupper-shortcodes/#syntax-highlighting).
## Disable toc for a blog post
Blog posts that have two or more subheadings (`<h2>`s) automatically get a table of contents. To disable this set `toc` to `false`. For example:
```
---
title: "My page with a few headings"
toc: false
---
```
## Localization
The strings in the templates of this theme can be localized. Make a copy of `<THEME_BASE_FOLDER>/i18n/en.yaml` to `<YOUR_SITE_FOLDER>/i18n/<YOUR_SITE_LANGUAGE>.yaml`, and translate one by one, changing the `translation` field.
[Here is a tutorial that goes more in depth about this.](https://regisphilibert.com/blog/2018/08/hugo-multilingual-part-2-i18n-string-localization/)
## Custom CSS and JS
You can provide an optional list of custom CSS files, which must be placed inside the `static` dir. These will load after the theme CSS loads. So, `static/css/custom_01.css` translates to `css/custom_01.css`.
You can provide an optional list of custom JS files, which must be placed inside the `static` dir. These will load after the theme JS loads. So, `static/js/custom_01.js` translates to `js/custom_01.js`.
See the [example site config file](https://github.com/zwbetz-gh/cupper-hugo-theme/blob/master/exampleSite/config.yaml) for sample usage.
## Getting help
If you run into an issue that isn't answered by this documentation or the [`exampleSite`](https://github.com/zwbetz-gh/cupper-hugo-theme/tree/master/exampleSite), then visit the [Hugo forum](https://discourse.gohugo.io/). The folks there are helpful and friendly. **Before** asking your question, be sure to read the [requesting help guidelines](https://discourse.gohugo.io/t/requesting-help/9132).
## Credits
Thank you to [Heydon Pickering](http://www.heydonworks.com) and [The Paciello Group](https://www.paciellogroup.com/) for creating the original Cupper project.

View file

@ -0,0 +1,6 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
tags: []
---

View file

@ -0,0 +1,8 @@
#search {
height: 50px;
width: 100%;
padding: 8px;
border: 2px solid;
line-height: 1.6;
font-size: 1.25rem;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,21 @@
(function () {
function onEvent() {
var filter = search.value.toUpperCase();
var list = document.getElementById("list");
var listItems = list.getElementsByTagName("li");
for (i = 0; i < listItems.length; i++) {
var item = listItems[i];
var text = item.innerText.toUpperCase();
if (text.indexOf(filter) > -1) {
item.style.display = "";
} else {
item.style.display = "none";
}
}
}
var search = document.getElementById("search");
if (search) {
search.addEventListener("keyup", onEvent);
}
})();

View file

@ -0,0 +1,150 @@
/* Expandable sections */
(function () {
function toggle (button, target) {
var expanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', !expanded);
target.hidden = !target.hidden;
}
var expanders = document.querySelectorAll('[data-expands]');
Array.prototype.forEach.call(expanders, function (expander) {
var target = document.getElementById(expander.getAttribute('data-expands'));
expander.addEventListener('click', function () {
toggle(expander, target);
})
})
}());
/* Menu button */
(function () {
var button = document.getElementById('menu-button');
if (button) {
var menu = document.getElementById('patterns-list');
button.addEventListener('click', function() {
var expanded = this.getAttribute('aria-expanded') === 'true';
this.setAttribute('aria-expanded', !expanded);
})
}
}());
/* Persist navigation scroll point */
(function () {
window.onbeforeunload = function () {
var patternsNav = document.getElementById('patterns-nav');
if (patternsNav) {
var scrollPoint = patternsNav.scrollTop;
localStorage.setItem('scrollPoint', scrollPoint);
}
}
window.addEventListener('DOMContentLoaded', function () {
if (document.getElementById('patterns-nav')) {
if (window.location.href.indexOf('patterns/') !== -1) {
document.getElementById('patterns-nav').scrollTop = parseInt(localStorage.getItem('scrollPoint'));
} else {
document.getElementById('patterns-nav').scrollTop = 0;
}
}
})
}());
{{ if not .Site.Params.hideHeaderLinks }}
/* Add "link here" links to <h2> headings */
(function () {
var headings = document.querySelectorAll('main > h2');
Array.prototype.forEach.call(headings, function (heading) {
var id = heading.getAttribute('id');
if (id) {
var newHeading = heading.cloneNode(true);
newHeading.setAttribute('tabindex', '-1');
var container = document.createElement('div');
container.setAttribute('class', 'h2-container');
container.appendChild(newHeading);
heading.parentNode.insertBefore(container, heading);
var link = document.createElement('a');
link.setAttribute('href', '#' + id);
link.innerHTML = '<svg aria-hidden="true" class="link-icon" viewBox="0 0 50 50" focusable="false"> <use xlink:href="#link"></use> </svg>';
container.appendChild(link);
heading.parentNode.removeChild(heading);
}
})
}());
{{ end }}
/* Enable scrolling by keyboard of code samples */
(function () {
var codeBlocks = document.querySelectorAll('pre, .code-annotated');
Array.prototype.forEach.call(codeBlocks, function (block) {
if (block.querySelector('code')) {
block.setAttribute('role', 'region');
block.setAttribute('aria-label', 'code sample');
if (block.scrollWidth > block.clientWidth) {
block.setAttribute('tabindex', '0');
}
}
});
}());
/* Switch and persist theme */
(function () {
var checkbox = document.getElementById('themer');
function persistTheme(val) {
localStorage.setItem('darkTheme', val);
}
function applyDarkTheme() {
var rules = [
'.intro-and-nav, .main-and-footer { filter: invert(100%); }',
'* { background-color: inherit; }',
'img:not([src*=".svg"]), .colors, iframe, .demo-container { filter: invert(100%); }'
];
rules.forEach(function(rule) {
document.styleSheets[0].insertRule(rule);
})
}
function clearDarkTheme() {
for (let i = 0; i < document.styleSheets[0].cssRules.length; i++) {
document.styleSheets[0].deleteRule(i);
}
}
checkbox.addEventListener('change', function () {
if (this.checked) {
applyDarkTheme();
persistTheme('true');
} else {
clearDarkTheme();
persistTheme('false');
}
});
function showTheme() {
if (localStorage.getItem('darkTheme') === 'true') {
applyDarkTheme();
checkbox.checked = true;
}
}
function showContent() {
document.body.style.visibility = 'visible';
document.body.style.opacity = 1;
}
window.addEventListener('DOMContentLoaded', function () {
showTheme();
showContent();
});
}());

View file

@ -0,0 +1,149 @@
{
"title": "Inclusive Design Principles",
"description": "<p>These Inclusive Design Principles are about putting people first. It's about designing for the needs of people with permanent, temporary, situational, or changing disabilities — all of us really.</p><p>They are intended to give anyone involved in the design and development of websites and applications - designers, user experience professionals, developers, product owners, idea makers, innovators, artists and thinkers - a broad approach to inclusive design.</p><p>For more background, read about the <a href=\"https://www.paciellogroup.com/blog/2017/06/inclusive-design-principles/\">Inclusive Design Principles</a> on the TPG blog.</p>",
"authors": [
"Léonie Watson",
"Henny Swan",
"Ian Pouncey",
"Heydon Pickering"
],
"principles": [
{
"title": "Provide comparable experience",
"strapline": "Ensure your interface provides a comparable experience for all so people can accomplish tasks in a way that suits their needs without undermining the quality of the content.",
"description": "Whether out of circumstance, choice, or context people are diverse. As people use different approaches and tools to read and operate interfaces, what the interface offers each user should be comparable in value, quality, and efficiency.",
"examples": [
{
"title": "Content for alternatives",
"description": "Having a basic alternative, whether it's alt text, a transcript, audio description, or sign language, makes the content accessible but to be equivalent it needs to capture the essence of the original."
},
{
"title": "Ergonomic features",
"description": "Providing synchronized closed captions makes your video accessible. But making them customizable, color coded, and repositionable provides a more comparable experience."
},
{
"title": "Notifications",
"description": "Notifications that appear in an interface are visually obvious but require proactive discovery by screen reader users. A comparable experience for blind users, can be achieved by using a live region. The notification then requires no explicit action on the part of the user."
}
]
},
{
"title": "Consider situation",
"strapline": "People use your interface in different situations. Make sure your interface delivers a valuable experience to people regardless of their circumstances.",
"description": "People are first time users, established users, users at work, users at home, users on the move, and users under pressure. All of these situations can have an impact. For those who already find interaction challenging, such as those with disabilities, this impact may make usage particularly difficult.",
"examples": [
{
"title": "Colour contrast",
"description": "When using an interface outdoors, good contrast lessens the impact of bright sunshine."
},
{
"title": "Context sensitive help",
"description": "Users may need help when they first encounter a complex form or interaction. This help may become redundant, even distracting, as a user becomes more familiar with the form or interaction. Context sensitive help provides the user with choice as to when they access help and better control over the page."
},
{
"title": "Captions on the go",
"description": "You're aware that the video content you are providing will be consumed on mobile devices, which may be in public spaces where people might prefer to consume the content without being antisocial. For smaller viewports, sound is switched off and captions activated by default."
}
]
},
{
"title": "Be consistent",
"strapline": "Use familiar conventions and apply them consistently.",
"description": "Familiar interfaces borrow from well-established patterns. These should be used consistently within the interface to reinforce their meaning and purpose. This should be applied to functionality, behavior, editorial, and presentation. You should say the same things in the same way and users should be able to do the same things in the same way.",
"examples": [
{
"title": "Consistent design patterns",
"description": "Use consistent web and platform design patterns to help build familiarity and understanding."
},
{
"title": "Consistent editorial",
"description": "Use plain language consistently across platforms including editorial that is relied on by screen reader users such as text alternatives, headings, labels for buttons and so on. Keeping editorial style consistent is also important e.g. making sure the top of the article always has a clearly marked summary paragraph, making sure bullets always start with a bolded definition."
},
{
"title": "Consistent page architecture",
"description": "Use consistent page architecture across templates to help people scan and navigate key content."
}
]
},
{
"title": "Give control",
"strapline": "Ensure people are in control. People should be able to access and interact with content in their preferred way.",
"description": "Do not suppress or disable the ability to change standard browser and platform settings such as orientation, font size, zoom, and contrast. In addition, avoid content changes that have not been initiated by the user unless there is a way to control it.",
"examples": [
{
"title": "Scrolling control",
"description": "'Infinite scrolling' can be problematic, especially for users navigating by keyboard because they can't get past the stream of refreshing content. Give the option to turn off this feature and replace it with a 'load more' button."
},
{
"title": "Make it stop",
"description": "Some users find that animations or parallax scrolling cause nausea, and others find them plain distracting. Where they play automatically, they should at least be easy to stop, by providing prominent playback controls."
},
{
"title": "Allow zoom",
"description": "There are many reasons why a user may want to operate the pinch-to-zoom gesture on their touch device. Make sure it is not suppressed, and that the content does not get obscured when it is put to use."
}
]
},
{
"title": "Offer choice",
"strapline": "Consider providing different ways for people to complete tasks, especially those that are complex or non standard.",
"description": "There is often more than one way to complete a task. You cannot assume what someone's preferred way might be. By providing alternatives for layout and task completion, you offer people choices that suit them and their circumstances at the time.",
"examples": [
{
"title" : "Multiple ways to complete an action",
"description": "Where appropriate, provide multiple ways to complete an action. On mobile swipe to delete an item can be supported together with an edit button that allows you to select items then delete. An example of this is in iOS mail."
},
{
"title": "Layout",
"description": "Where there are long lists of content consider offering a grid or list layout option. This supports people who may want larger images on screen or smaller rows."
},
{
"title": "Accessible alternatives",
"description": "Alternative ways of presenting data, such as data tables for info graphics, should be available to all users, as an option rather than a hidden link just for screen reader users. Accessible alternatives can benefit not just a specific target group but all users as long as we offer the choice."
}
]
},
{
"title": "Prioritise content",
"strapline": "Help users focus on core tasks, features, and information by prioritising them within the content and layout.",
"description": "Interfaces can be difficult to understand when core features are not clearly exposed and prioritised. A site or application may provide lots of information and functionality, but people should be able to focus on one thing at a time. Identify the core purpose of the interface, and then the content and features needed to fulfill that purpose.",
"examples": [
{
"title": "Keep task focused",
"description": "Progressively reveal features and content when needed, not all in one go."
},
{
"title": "Prioritising tasks",
"description": "An email application is principally for writing and reading email. The 'compose' button is, therefore, present on all screens, and early in the focus order. The inbox is prioritised over other lists of email, such as 'sent' and 'spam' messages. Less used features such as tagging or organizing email into folders appear later in the focus order, as they will generally only be used when the primary task of reading the email is complete."
},
{
"title": "Prioritising content",
"description": "The primary content on a news article page is the story, therefore it should come before other content, both visually and in the source order. Related content, such as similar articles, should follow it, and unrelated content after that."
},
{
"title": "Prioritising editorial",
"description": "Editorial for links, headings and buttons should use plain language and put the primary text first. This applies to both visible and hidden text. This makes the text easy to scan both visually and audibly for screen reader users. Plain language also benefits non native speakers and is easier to translate."
}
]
},
{
"title": "Add value",
"strapline": "Consider the value of features and how they improve the experience for different users.",
"description": "Features should add value to the user experience by providing efficient and diverse ways to find and interact with content. Consider device features such as voice, geolocation, camera and vibration API's, and how integration with connected devices or a second screen could provide choice.",
"examples": [
{
"title": "Integration with connected devices or second screen",
"description": "Using voice interfaces to control multimedia, search for content, output from music or TV adds value for people who struggle to use other interfaces."
},
{
"title": "Integration with platform APIs",
"description": "Enhance functionality using platform features. The vibration API makes notifications more usable by deaf and hard of hearing people while the geolocation API makes it easier for people with mobility impairments to use location based services."
},
{
"title": "Make task completion easier",
"description": "Add a 'Show password' button to input fields so users can verify they have correctly inputted text, or add touch identification for password protected areas."
}
]
}
]
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
- id: skip_to_content
translation: skip to content
- id: nav_main_navigation
translation: Main navigation
- id: nav_button_menu
translation: Menu
- id: discuss_show_comments_button
translation: Show comments
- id: discuss_comments_disabled
translation: Disqus comments are disabled.
- id: discuss_js_disabled
translation: Enable JavaScript to view Disqus comments.
- id: dark_theme
translation: "dark theme:"
- id: table_of_contents
translation: Table of contents
- id: publish_date
translation: "Publish date:"
- id: last_updated
translation: "Last updated:"
- id: tags
translation: "Tags:"
- id: aria_label_tags
translation: tags
- id: search_placeholder
translation: Search by title...
- id: search_aria_label
translation: Search by title

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="{{ .Site.Language.Lang }}">
{{ partial "head.html" . }}
<body>
<a href="#main">{{ T "skip_to_content" }}</a>
{{ partial "noscript.html" . }}
{{ partial "svg.html" . }}
<div class="wrapper">
{{ partial "header.html" . }}
<div class="main-and-footer">
<div>
{{ block "main" . }}{{ end }}
{{ if ne .Site.Params.moveFooterToHeader true }}
{{ partial "footer.html" . }}
{{ end }}
</div>
</div>
</div>
{{ partial "script.html" . }}
{{ partial "katex.html" . }}
</body>
</html>

View file

@ -0,0 +1,32 @@
{{ define "main" }}
<main id="main">
<h1>{{ .Title }}</h1>
{{ if site.Params.search }}
<input
id="search"
type="text"
placeholder="{{ T "search_placeholder" }}"
aria-label="{{ T "search_aria_label" }}"
/>
{{ end }}
<ul class="patterns-list" id="list">
{{ range .Pages.ByPublishDate.Reverse }}
<li>
<h2>
<a href="{{ .RelPermalink }}">
<svg
class="bookmark"
aria-hidden="true"
viewBox="0 0 40 50"
focusable="false"
>
<use xlink:href="#bookmark"></use>
</svg>
{{ .Title }}
</a>
</h2>
</li>
{{ end }}
</ul>
</main>
{{ end }}

View file

@ -0,0 +1,6 @@
{{ define "main" }}
<main id="main">
<h1>{{ .Title }}</h1>
{{ .Content }}
</main>
{{ end }}

View file

@ -0,0 +1,19 @@
{{ define "main" }}
<main id="main">
<h1>{{ .Title }}</h1>
<ul class="patterns-list">
{{ range .Data.Terms.Alphabetical }}
<li>
<h2>
<a href="{{ .Page.RelPermalink }}">
<svg class="tag-icon" aria-hidden="true" viewBox="0 0 177.16535 177.16535" focusable="false">
<use xlink:href="#tag"></use>
</svg>
{{ printf "(%d) %s" .Count .Page.Title }}
</a>
</h2>
</li>
{{ end }}
</ul>
</main>
{{ end }}

View file

@ -0,0 +1,6 @@
{{ define "main" }}
<main id="main">
<h1>{{ .Title }}</h1>
{{ .Content }}
</main>
{{ end }}

View file

@ -0,0 +1,6 @@
// Remove button
var disqusButton = document.getElementById('disqus-button');
disqusButton.parentNode.removeChild(disqusButton);
// Un-hide comments
var disqusComments = document.getElementById('disqus-comments');
disqusComments.style.display = 'block';

View file

@ -0,0 +1,10 @@
// Config
var disqus_config = function () {
};
// Build and append comments
var d = document;
var s = d.createElement('script');
s.async = true;
s.src = '//' + "{{ . }}" + '.disqus.com/embed.js';
s.setAttribute('data-timestamp', + new Date());
(d.head || d.body).appendChild(s);

View file

@ -0,0 +1,27 @@
<div id="disqus-container">
{{ with .Site.DisqusShortname }}
<button id="disqus-button" onclick="showComments()">{{ T "discuss_show_comments_button" }}</button>
<div id="disqus-comments">
{{ $isDummyName := eq . "yourdiscussshortname" }}
{{ $isServer := $.Site.IsServer }}
{{ if or $isDummyName $isServer }}
<p><em>{{ T "discuss_comments_disabled" }}</em></p>
<script type="application/javascript">
function showComments() {
{{ partial "disqus-js-common.js" . | safeJS }}
}
</script>
{{ else }}
<div id="disqus_thread">
</div>
<script type="application/javascript">
function showComments() {
{{ partial "disqus-js-main.js" . | safeJS }}
{{ partial "disqus-js-common.js" . | safeJS }}
}
</script>
{{ end }}
<noscript>{{ T "discuss_js_disabled" }}</noscript>
</div>
{{ end }}
</div>

View file

@ -0,0 +1,14 @@
<footer role="contentinfo">
<div
{{ if eq .Site.Params.showThemeSwitcher false }}style="display: none;"{{ end }}
>
<label for="themer">
{{ T "dark_theme" }} <input type="checkbox" id="themer" class="vh">
<!-- Shows "on" or "off" -->
<span aria-hidden="true"></span>
</label>
</div>
{{ with .Site.Params.footer }}
{{ . | markdownify }}
{{ end }}
</footer>

View file

@ -0,0 +1,10 @@
{{ if not .Site.IsServer }}
{{ with .Site.GoogleAnalytics }}
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', '{{ . }}', 'auto');
ga('send', 'pageview');
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
{{ end }}
{{ end }}

View file

@ -0,0 +1,58 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
{{ hugo.Generator }}
<link rel="canonical" href="{{ .RelPermalink }}">
{{ if .IsHome }}
{{ with .Site.Params.homeMetaContent }}
<meta name="description" content="{{ . | plainify }}">
{{ end }}
{{ end }}
{{ if not .Site.IsServer }}
{{ with .Site.GoogleAnalytics }}
<script async src="https://www.googletagmanager.com/gtag/js?id=G-85ZKKXCG56"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-85ZKKXCG56');
</script>
{{ end }}
{{ end }}
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#000000">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="theme-color" content="#ffffff">
<style>
body {
visibility: hidden;
opacity: 0;
}
</style>
<link rel="stylesheet" href="{{ "css/prism.css" | relURL }}" media="none" onload="this.media='all';">
{{ $templateStyles := resources.Get "css/template-styles.css" }}
{{ $styles := $templateStyles | resources.ExecuteAsTemplate "css/styles.css" . }}
<link rel="stylesheet" type="text/css" href="{{ $styles.RelPermalink }}">
{{ range .Site.Params.customCss }}
<link rel="stylesheet" href="{{ . | relURL }}">
{{ end }}
{{ $title := print .Title " | " .Site.Title }}
{{ if .IsHome }}
{{ $title = .Site.Title }}
{{ end }}
<title>{{ $title }}</title>
</head>

View file

@ -0,0 +1,20 @@
<header class="intro-and-nav" role="banner">
<div>
<div class="intro">
<a
class="logo"
href="{{ .Site.BaseURL }}"
aria-label="{{ .Site.Title }} home page"
>
<img src="{{ "images/logo.svg" | relURL }}" alt="">
</a>
<p class="library-desc">
{{ with .Site.Params.description }} {{ . | markdownify }} {{ end }}
</p>
</div>
{{ partial "nav.html" . }}
{{ if eq .Site.Params.moveFooterToHeader true }}
{{ partial "footer.html" . }}
{{ end }}
</div>
</header>

View file

@ -0,0 +1,5 @@
{{ if eq $.Site.Params.katex true }}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.css" integrity="sha384-dbVIfZGuN1Yq7/1Ocstc1lUEm+AT+/rCkibIcC/OmWo5f0EA48Vf8CytHzGrSwbQ" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.js" integrity="sha384-2BKqo+exmr9su6dir+qCw08N2ZKRucY4PrGQPPWU1A7FtlCGjmEGFqXCv5nyM5Ij" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous" onload="renderMathInElement(document.body);"></script>
{{ end }}

View file

@ -0,0 +1,26 @@
<nav id="patterns-nav" class="patterns" role="navigation">
<h2 class="vh">{{ T "nav_main_navigation" }}</h2>
<button id="menu-button" aria-expanded="false">
<svg viewBox="0 0 50 50" aria-hidden="true" focusable="false">
<use xlink:href="#menu"></use>
</svg>
{{ T "nav_button_menu" }}
</button>
{{ $current := . }}
<ul id="patterns-list">
{{ range .Site.Menus.nav }}
<li class="pattern">
{{ $active := or ($current.IsMenuCurrent "nav" .) ($current.HasMenuCurrent "nav" .) }}
{{ $active = or $active (eq .Name $current.Title) }}
{{ $active = or $active (and (eq .Name "Blog") (eq $current.Section "post")) }}
{{ $active = or $active (and (eq .Name "Tags") (eq $current.Section "tags")) }}
<a href="{{ .URL }}" {{ if $active }}aria-current="page"{{ end }}>
<svg class="bookmark-icon" aria-hidden="true" focusable="false" viewBox="0 0 40 50">
<use xlink:href="#bookmark"></use>
</svg>
<span class="text">{{ .Name }}</span>
</a>
</li>
{{ end }}
</ul>
</nav>

View file

@ -0,0 +1,8 @@
<noscript>
<style>
body {
visibility: visible;
opacity: 1;
}
</style>
</noscript>

View file

@ -0,0 +1,16 @@
{{ $templateDomScripts := resources.Get "js/template-dom-scripts.js" }}
{{ $domScripts := $templateDomScripts | resources.ExecuteAsTemplate "js/dom-scripts.js" . }}
<script src="{{ $domScripts.RelPermalink }}"></script>
<script src="{{ "js/prism.js" | relURL }}"></script>
{{ if site.Params.search }}
{{ $searchJs := resources.Get "js/search.js" | fingerprint }}
<script src="{{ $searchJs.RelPermalink }}"></script>
{{ $searchCss := resources.Get "css/search.css" | fingerprint }}
<link rel="stylesheet" href="{{ $searchCss.RelPermalink }}"></link>
{{ end }}
{{ range .Site.Params.customJs }}
<script src="{{ . | relURL }}"></script>
{{ end }}

View file

@ -0,0 +1,88 @@
<svg style="display: none">
<symbol id="bookmark" viewBox="0 0 40 50">
<g transform="translate(2266 3206.2)">
<path style="stroke:currentColor;stroke-width:3.2637;fill:none" d="m-2262.2-3203.4-.2331 42.195 16.319-16.318 16.318 16.318.2331-42.428z"/>
</g>
</symbol>
<symbol id="w3c" viewBox="0 0 127.09899 67.763">
<text font-size="83" style="font-size:83px;font-family:Trebuchet;letter-spacing:-12;fill-opacity:0" letter-spacing="-12" y="67.609352" x="-26.782778">W3C</text>
<text font-size="83" style="font-size:83px;font-weight:bold;font-family:Trebuchet;fill-opacity:0" y="67.609352" x="153.21722" font-weight="bold">SVG</text>
<path style="fill:currentColor;image-rendering:optimizeQuality;shape-rendering:geometricPrecision" d="m33.695.377 12.062 41.016 12.067-41.016h8.731l-19.968 67.386h-.831l-12.48-41.759-12.479 41.759h-.832l-19.965-67.386h8.736l12.061 41.016 8.154-27.618-3.993-13.397h8.737z"/>
<path style="fill:currentColor;image-rendering:optimizeQuality;shape-rendering:geometricPrecision" d="m91.355 46.132c0 6.104-1.624 11.234-4.862 15.394-3.248 4.158-7.45 6.237-12.607 6.237-3.882 0-7.263-1.238-10.148-3.702-2.885-2.47-5.02-5.812-6.406-10.022l6.82-2.829c1.001 2.552 2.317 4.562 3.953 6.028 1.636 1.469 3.56 2.207 5.781 2.207 2.329 0 4.3-1.306 5.909-3.911 1.609-2.606 2.411-5.738 2.411-9.401 0-4.049-.861-7.179-2.582-9.399-1.995-2.604-5.129-3.912-9.397-3.912h-3.327v-3.991l11.646-20.133h-14.062l-3.911 6.655h-2.493v-14.976h32.441v4.075l-12.31 21.217c4.324 1.385 7.596 3.911 9.815 7.571 2.22 3.659 3.329 7.953 3.329 12.892z"/>
<path style="fill:currentColor;image-rendering:optimizeQuality;shape-rendering:geometricPrecision" d="m125.21 0 1.414 8.6-5.008 9.583s-1.924-4.064-5.117-6.314c-2.693-1.899-4.447-2.309-7.186-1.746-3.527.73-7.516 4.938-9.258 10.13-2.084 6.21-2.104 9.218-2.178 11.978-.115 4.428.58 7.043.58 7.043s-3.04-5.626-3.011-13.866c.018-5.882.947-11.218 3.666-16.479 2.404-4.627 5.954-7.404 9.114-7.728 3.264-.343 5.848 1.229 7.841 2.938 2.089 1.788 4.213 5.698 4.213 5.698l4.94-9.837z"/>
<path style="fill:currentColor;image-rendering:optimizeQuality;shape-rendering:geometricPrecision" d="m125.82 48.674s-2.208 3.957-3.589 5.48c-1.379 1.524-3.849 4.209-6.896 5.555-3.049 1.343-4.646 1.598-7.661 1.306-3.01-.29-5.807-2.032-6.786-2.764-.979-.722-3.486-2.864-4.897-4.854-1.42-2-3.634-5.995-3.634-5.995s1.233 4.001 2.007 5.699c.442.977 1.81 3.965 3.749 6.572 1.805 2.425 5.315 6.604 10.652 7.545 5.336.945 9.002-1.449 9.907-2.031.907-.578 2.819-2.178 4.032-3.475 1.264-1.351 2.459-3.079 3.116-4.108.487-.758 1.276-2.286 1.276-2.286l-1.276-6.644z"/>
</symbol>
<symbol id="tag" viewBox="0 0 177.16535 177.16535">
<g transform="translate(0 -875.2)">
<path style="fill-rule:evenodd;stroke-width:0;fill:currentColor" d="m159.9 894.3-68.79 8.5872-75.42 77.336 61.931 60.397 75.429-76.565 6.8495-69.755zm-31.412 31.835a10.813 10.813 0 0 1 1.8443 2.247 10.813 10.813 0 0 1 -3.5174 14.872l-.0445.0275a10.813 10.813 0 0 1 -14.86 -3.5714 10.813 10.813 0 0 1 3.5563 -14.863 10.813 10.813 0 0 1 13.022 1.2884z"/>
</g>
</symbol>
<symbol id="balloon" viewBox="0 0 141.73228 177.16535">
<g transform="translate(0 -875.2)">
<g>
<path style="fill:currentColor" d="m68.156 882.83-.88753 1.4269c-4.9564 7.9666-6.3764 17.321-5.6731 37.378.36584 10.437 1.1246 23.51 1.6874 29.062.38895 3.8372 3.8278 32.454 4.6105 38.459 4.6694-.24176 9.2946.2879 14.377 1.481 1.2359-3.2937 5.2496-13.088 8.886-21.623 6.249-14.668 8.4128-21.264 10.253-31.252 1.2464-6.7626 1.6341-12.156 1.4204-19.764-.36325-12.93-2.1234-19.487-6.9377-25.843-2.0833-2.7507-6.9865-7.6112-7.9127-7.8436-.79716-.20019-6.6946-1.0922-6.7755-1.0248-.02213.0182-5.0006-.41858-7.5248-.22808l-2.149-.22808h-3.3738z"/>
<path style="fill:currentColor" d="m61.915 883.28-3.2484.4497c-1.7863.24724-3.5182.53481-3.8494.63994-2.4751.33811-4.7267.86957-6.7777 1.5696-.28598 0-1.0254.20146-2.3695.58589-5.0418 1.4418-6.6374 2.2604-8.2567 4.2364-6.281 7.6657-11.457 18.43-12.932 26.891-1.4667 8.4111.71353 22.583 5.0764 32.996 3.8064 9.0852 13.569 25.149 22.801 37.517 1.3741 1.841 2.1708 2.9286 2.4712 3.5792 3.5437-1.1699 6.8496-1.9336 10.082-2.3263-1.3569-5.7831-4.6968-21.86-6.8361-33.002-.92884-4.8368-2.4692-14.322-3.2452-19.991-.68557-5.0083-.77707-6.9534-.74159-15.791.04316-10.803.41822-16.162 1.5026-21.503 1.4593-5.9026 3.3494-11.077 6.3247-15.852z"/>
<path style="fill:currentColor" d="m94.499 885.78c-.10214-.0109-.13691 0-.0907.0409.16033.13489 1.329 1.0675 2.5976 2.0723 6.7003 5.307 11.273 14.568 12.658 25.638.52519 4.1949.24765 14.361-.5059 18.523-2.4775 13.684-9.7807 32.345-20.944 53.519l-3.0559 5.7971c2.8082.76579 5.7915 1.727 8.9926 2.8441 11.562-11.691 18.349-19.678 24.129-28.394 7.8992-11.913 11.132-20.234 12.24-31.518.98442-10.02-1.5579-20.876-6.7799-28.959-.2758-.4269-.57803-.86856-.89617-1.3166-3.247-6.13-9.752-12.053-21.264-16.131-2.3687-.86369-6.3657-2.0433-7.0802-2.1166z"/>
<path style="fill:currentColor" d="m32.52 892.22c-.20090-.13016-1.4606.81389-3.9132 2.7457-11.486 9.0476-17.632 24.186-16.078 39.61.79699 7.9138 2.4066 13.505 5.9184 20.562 5.8577 11.77 14.749 23.219 30.087 38.74.05838.059.12188.1244.18052.1838 1.3166-.5556 2.5965-1.0618 3.8429-1.5199-.66408-.32448-1.4608-1.3297-3.8116-4.4602-5.0951-6.785-8.7512-11.962-13.051-18.486-5.1379-7.7948-5.0097-7.5894-8.0586-13.054-6.2097-11.13-8.2674-17.725-8.6014-27.563-.21552-6.3494.13041-9.2733 1.775-14.987 2.1832-7.5849 3.9273-10.986 9.2693-18.07 1.7839-2.3656 2.6418-3.57 2.4409-3.7003z"/>
<path style="fill:currentColor" d="m69.133 992.37c-6.2405.0309-12.635.76718-19.554 2.5706 4.6956 4.7759 9.935 10.258 12.05 12.625l4.1272 4.6202h11.493l3.964-4.4516c2.0962-2.3541 7.4804-7.9845 12.201-12.768-8.378-1.4975-16.207-2.6353-24.281-2.5955z"/>
<rect style="stroke-width:0;fill:currentColor" ry="2.0328" height="27.746" width="22.766" y="1017.7" x="60.201"/>
</g>
</g>
</symbol>
<symbol id="info" viewBox="0 0 41.667 41.667">
<g transform="translate(-37.035 -1004.6)">
<path style="stroke-linejoin:round;stroke:currentColor;stroke-linecap:round;stroke-width:3.728;fill:none" d="m76.25 1030.2a18.968 18.968 0 0 1 -23.037 13.709 18.968 18.968 0 0 1 -13.738 -23.019 18.968 18.968 0 0 1 23.001 -13.768 18.968 18.968 0 0 1 13.798 22.984"/>
<g transform="matrix(1.1146 0 0 1.1146 -26.276 -124.92)">
<path style="stroke:currentColor;stroke-linecap:round;stroke-width:3.728;fill:none" d="m75.491 1039.5v-8.7472"/>
<path style="stroke-width:0;fill:currentColor" transform="scale(-1)" d="m-73.193-1024.5a2.3719 2.3719 0 0 1 -2.8807 1.7142 2.3719 2.3719 0 0 1 -1.718 -2.8785 2.3719 2.3719 0 0 1 2.8763 -1.7217 2.3719 2.3719 0 0 1 1.7254 2.8741"/>
</g>
</g>
</symbol>
<symbol id="warning" viewBox="0 0 48.430474 41.646302">
<g transform="translate(-1.1273 -1010.2)">
<path style="stroke-linejoin:round;stroke:currentColor;stroke-linecap:round;stroke-width:4.151;fill:none" d="m25.343 1012.3-22.14 37.496h44.28z"/>
<path style="stroke:currentColor;stroke-linecap:round;stroke-width:4.1512;fill:none" d="m25.54 1027.7v8.7472"/>
<path style="stroke-width:0;fill:currentColor" d="m27.839 1042.8a2.3719 2.3719 0 0 1 -2.8807 1.7143 2.3719 2.3719 0 0 1 -1.718 -2.8785 2.3719 2.3719 0 0 1 2.8763 -1.7217 2.3719 2.3719 0 0 1 1.7254 2.8741"/>
</g>
</symbol>
<symbol id="menu" viewBox="0 0 50 50">
<rect style="stroke-width:0;fill:currentColor" height="10" width="50" y="0" x="0"/>
<rect style="stroke-width:0;fill:currentColor" height="10" width="50" y="20" x="0"/>
<rect style="stroke-width:0;fill:currentColor" height="10" width="50" y="40" x="0"/>
</symbol>
<symbol id="link" viewBox="0 0 50 50">
<g transform="translate(0 -1002.4)">
<g transform="matrix(.095670 0 0 .095670 2.3233 1004.9)">
<g>
<path style="stroke-width:0;fill:currentColor" d="m452.84 192.9-128.65 128.65c-35.535 35.54-93.108 35.54-128.65 0l-42.881-42.886 42.881-42.876 42.884 42.876c11.845 11.822 31.064 11.846 42.886 0l128.64-128.64c11.816-11.831 11.816-31.066 0-42.9l-42.881-42.881c-11.822-11.814-31.064-11.814-42.887 0l-45.928 45.936c-21.292-12.531-45.491-17.905-69.449-16.291l72.501-72.526c35.535-35.521 93.136-35.521 128.64 0l42.886 42.881c35.535 35.523 35.535 93.141-.001 128.66zm-254.28 168.51-45.903 45.9c-11.845 11.846-31.064 11.817-42.881 0l-42.884-42.881c-11.845-11.821-11.845-31.041 0-42.886l128.65-128.65c11.819-11.814 31.069-11.814 42.884 0l42.886 42.886 42.876-42.886-42.876-42.881c-35.54-35.521-93.113-35.521-128.65 0l-128.65 128.64c-35.538 35.545-35.538 93.146 0 128.65l42.883 42.882c35.51 35.54 93.11 35.54 128.65 0l72.496-72.499c-23.956 1.597-48.092-3.784-69.474-16.283z"/>
</g>
</g>
</g>
</symbol>
<symbol id="doc" viewBox="0 0 35 45">
<g transform="translate(-147.53 -539.83)">
<path style="stroke:currentColor;stroke-width:2.4501;fill:none" d="m149.38 542.67v39.194h31.354v-39.194z"/>
<g style="stroke-width:25" transform="matrix(.098003 0 0 .098003 133.69 525.96)">
<path d="m220 252.36h200" style="stroke:currentColor;stroke-width:25;fill:none"/>
<path style="stroke:currentColor;stroke-width:25;fill:none" d="m220 409.95h200"/>
<path d="m220 488.74h200" style="stroke:currentColor;stroke-width:25;fill:none"/>
<path d="m220 331.15h200" style="stroke:currentColor;stroke-width:25;fill:none"/>
</g>
</g>
</symbol>
<symbol id="tick" viewBox="0 0 177.16535 177.16535">
<g transform="translate(0 -875.2)">
<rect style="stroke-width:0;fill:currentColor" transform="rotate(30)" height="155" width="40" y="702.99" x="556.82"/>
<rect style="stroke-width:0;fill:currentColor" transform="rotate(30)" height="40" width="90.404" y="817.99" x="506.42"/>
</g>
</symbol>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

View file

@ -0,0 +1,19 @@
{{ $headings := findRE "<h2.*?>(.|\n])+?</h2>" .Content }}
{{ if ge (len $headings) 2 }}
<nav class="toc" aria-labelledby="toc-heading">
<h2 id="toc-heading">{{ T "table_of_contents" }}</h2>
<ol>
{{ range $headings }}
<li>
{{ $id := findRE "id=\".*\"" . }}
{{ $id = index $id 0 }}
{{ $id = strings.TrimPrefix "id=\"" $id }}
{{ $id = strings.TrimSuffix "\"" $id }}
<a href="#{{ $id }}">
{{ . | htmlUnescape | plainify }}
</a>
</li>
{{ end }}
</ol>
</nav>
{{ end }}

View file

@ -0,0 +1,46 @@
{{ define "main" }}
<main id="main">
<h1>
<svg class="bookmark-icon" aria-hidden="true" viewBox="0 0 40 50" focusable="false">
<use xlink:href="#bookmark"></use>
</svg>
{{ .Title }}
</h1>
<div class="date">
{{ $dateFormat := $.Site.Params.dateFormat | default "Jan 2, 2006" }}
{{ $publishDate := .PublishDate }}
<strong>{{ T "publish_date" }} </strong>{{ $publishDate.Format $dateFormat }}
{{ with .Lastmod }}
{{ if gt . $publishDate }}
<br>
<strong>{{ T "last_updated" }} </strong>{{ .Format $dateFormat }}
{{ end }}
{{ end }}
</div>
{{ with .Params.tags }}
<div class="tags">
<strong>{{ T "tags" }} </strong>
<ul aria-label="{{ T "aria_label_tags" }}">
{{ range . }}
<li>
<svg class="tag-icon" aria-hidden="true" viewBox="0 0 177.16535 177.16535" focusable="false">
<use xlink:href="#tag"></use>
</svg>
{{ $href := print ("tags/" | relLangURL) (. | urlize) "/" }}
<a href="{{ $href }}">{{ . }}</a>
</li>
{{ end }}
</ul>
</div>
{{ end }}
{{ if ne .Params.toc false }}
{{ partial "toc" . }}
{{ end }}
{{ .Content }}
</main>
{{ partial "disqus.html" . }}
{{ end }}

View file

@ -0,0 +1,11 @@
{{ $quote := .Inner }}
<blockquote class="blockquote">
<p>
{{ $quote | markdownify }}
{{ with (.Get "author") }}
<br>
<span class="author">&mdash; {{ . }}</span>
{{ end }}
</p>
</blockquote>

View file

@ -0,0 +1,7 @@
{{ $trimmed := (trim .Inner "\n") }}
{{ $lines := split $trimmed "\n" }}
<pre class="cmd">
{{ range $lines }}
<code>{{ . }}</code>
{{ end }}
</pre>

View file

@ -0,0 +1,5 @@
{{ $code := .Inner | htmlEscape }}
{{ $code := replace $code "[[[" "<span class='highlight'>" }}
{{ $code := replace $code "]]]" "</span>" }}
{{ $numbered := .Get "numbered" }}
<div class="code-annotated {{ if and ($numbered) (ne $numbered "false") }}numbered{{ end }}"><code>{{ $code | safeHTML }}</code></div>

View file

@ -0,0 +1,10 @@
{{ $pen := .Get 0 }}
{{ with .Site.Params.codePenUser }}
<iframe height="300" scrolling="no" title="code demonstration with codePen" src="//codepen.io/{{ . | lower }}/embed/{{ $pen }}/?height=265&theme-id=dark&default-tab=result,result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">
<div>
<a href="//codepen.io/{{ . | lower }}/pen/{{ $pen }}">See the demo on codePen</a>
</div>
</iframe>
{{ else }}
<p class="site-error"><strong>Site error:</strong> The <code>codePenUser</code> param has not been set in <code>config.toml</code></p>
{{ end }}

View file

@ -0,0 +1,11 @@
{{ $colorString := replace (.Get 0) " " "" | upper }}
{{ $colors := split $colorString "," }}
<div class="colors-container">
<ul class="colors">
{{ range $colors }}
<li style="background-color: {{ . }};{{ if or (eq . "#FFFFFF") (eq . "#FFF")}} border: 1px solid #111{{ end }}">
<span>{{ . }}</span>
</li>
{{ end }}
</ul>
</div>

View file

@ -0,0 +1,25 @@
<div class="expandable-section">
{{ if .Get "level" }}
<h{{ .Get "level" }}>
{{ end }}
{{/* 1. Get the md5 hash of the expandable inner text */}}
{{/* 2. Split the hash string into an array */}}
{{/* 3. Shuffle the array */}}
{{/* 4. Convert the array back into a string */}}
{{ $random := delimit (shuffle (split (md5 .Inner) "" )) "" }}
<button aria-expanded="{{ with .Get "open" }}true{{ else }}false{{ end }}" data-expands="js-expandable-{{ $random }}">
<span class="expandable-label">{{ .Get "label" | default "More info" }}</span>
<svg aria-hidden="true" focusable="false" viewBox="0 0 70.866142 70.866141">
<g transform="translate(0 -981.5)">
<rect style="stroke-width:0;fill:currentColor" ry="5" height="60" width="9.8985" y="987.36" x="30.051" class="up-strut" />
<rect style="stroke-width:0;fill:currentColor" ry="5" height="10" width="60" y="1012.4" x="5"/>
</g>
</svg>
</button>
{{ if .Get "level" }}
</h{{ .Get "level"}}>
{{ end }}
<div id="js-expandable-{{ $random }}" {{ with .Get "open" | not }}hidden{{ end }}>
{{ .Inner | markdownify }}
</div>
</div>

View file

@ -0,0 +1,28 @@
{{ $img := .Get "img" }}
{{ $caption := .Get "caption" }}
{{ $command := .Get "command" }}
{{ $options := .Get "options" }}
{{ $original := .Page.Resources.GetMatch (printf "*%s*" $img) }}
{{ $new := "" }}
{{ if eq $command "Fit" }}
{{ $new = $original.Fit $options }}
{{ else if eq $command "Fill" }}
{{ $new = $original.Fill $options }}
{{ else if eq $command "Resize" }}
{{ $new = $original.Resize $options }}
{{ else if eq $command "Original" }}
{{ $new = $original }}
{{ else }}
{{ errorf "Invalid image processing command: Must be one of Fit, Fill, Resize, Original." }}
{{ end }}
<figure role="group" aria-describedby="caption-{{ $caption | md5 }}">
<a href="{{ $original.RelPermalink }}" class="img-link">
<img src="{{ $new.RelPermalink }}">
</a>
<figcaption id="caption-{{ $caption | md5 }}">
{{ $caption | markdownify }}
</figcaption>
</figure>

View file

@ -0,0 +1,3 @@
<div class="file-tree">
{{ .Inner | markdownify }}
</div>

View file

@ -0,0 +1,29 @@
{{ $command := .Get "command" }}
{{ $options := .Get "options" }}
{{ with .Page.Resources.ByType "image" }}
{{ range . }}
{{ $original := . }}
{{ $new := "" }}
{{ if eq $command "Fit" }}
{{ $new = $original.Fit $options }}
{{ else if eq $command "Fill" }}
{{ $new = $original.Fill $options }}
{{ else if eq $command "Resize" }}
{{ $new = $original.Resize $options }}
{{ else if eq $command "Original" }}
{{ $new = $original }}
{{ else }}
{{ errorf "Invalid image processing command: Must be one of Fit, Fill, Resize, Original." }}
{{ end }}
<div class="gallery">
<a href="{{ $original.RelPermalink }}" class="img-link">
<img src="{{ $new.RelPermalink }}">
</a>
</div>
{{ end }}
{{ end }}

View file

@ -0,0 +1,8 @@
<aside aria-label="note" class="note">
<div>
<svg class="sign" aria-hidden="true" viewBox="0 0 41.667306 41.66729" focusable="false">
<use xlink:href="#info"></use>
</svg>
{{ .Inner }}
</div>
</aside>

View file

@ -0,0 +1,24 @@
{{ $JSON := $.Site.Data.principles }}
{{ $included := replace (.Get "include") ", " "," }}
{{ $included := apply (split $included ",") "lower" "." }}
{{ $descriptions := .Get "descriptions" }}
<ul class="principles {{ if and ($descriptions) (ne $descriptions "false") }}with-desc{{ end }}">
{{ range $JSON.principles }}
{{ if in $included (lower .title) }}
<li>
<strong>
<a href="https://inclusivedesignprinciples.org#{{ .title | urlize }}">
<svg class="balloon-icon" viewBox="0 0 141.73228 177.16535" aria-hidden="true" focusable="false">
<use xlink:href="#balloon"></use>
</svg>
{{ .title }}
</a>:
</strong>
<em>{{ .strapline }}</em>
{{ if and ($descriptions) (ne $descriptions "false") }}
<p>{{ .description }}</p>
{{ end }}
</li>
{{ end }}
{{ end }}
</ul>

View file

@ -0,0 +1,28 @@
{{ $tested := replace (.Get "using") ", " "," }}
{{ $tested := replace $tested " + " "+" }}
{{ $tested := split $tested "," }}
<table class="tested">
<tr>
<th scope="row">
<svg viewBox="0 0 177.16535 177.16535" focusable="false" aria-hidden="true">
<use xlink:href="#tick"></use>
</svg>
Tested using
</th>
{{ range $tested }}
<td>
{{ $browser := findRE "^[a-zA-Z ]+" . }}
{{ $browser := index $browser 0 }}
{{ $version := findRE "[0-9]+$" . }}
{{ $slug := replace $browser " " "-" | lower }}
<img src="{{ (printf "images/browser-%s" $slug) | relURL }}.svg" alt="">
<span><strong>{{ $browser }} {{ index $version 0 }}</strong></span>
{{ if in . "+" }}
{{ $parts := split . "+" }}
{{ $additional := index $parts 1 }}
<span class="additional">with <strong>{{ $additional }}</strong></span>
{{ end }}
</td>
{{ end }}
</tr>
</table>

View file

@ -0,0 +1,3 @@
<div class="ticks">
{{ .Inner | markdownify }}
</div>

View file

@ -0,0 +1,8 @@
<aside aria-label="warning" class="note warning">
<div>
<svg class="sign" aria-hidden="true" viewBox="0 0 48.430474 41.646302" focusable="false">
<use xlink:href="#warning"></use>
</svg>
{{ .Inner }}
</div>
</aside>

View file

@ -0,0 +1,30 @@
{{ $JSON := $.Site.Data.wcag }}
{{ $included := replace (.Get "include") ", " "," }}
{{ $included := split $included "," }}
{{ $descriptions := .Get "descriptions" }}
<ul class="wcag {{ if and ($descriptions) (ne $descriptions "false") }}with-desc{{ end }}">
{{ range $JSON }}
{{ if in $included .ref_id }}
<li>
<strong><a href="{{ .url }}">
<svg class="wcag-icon" viewBox="0 0 127.09899 67.763" aria-hidden="true" focusable="false">
<use xlink:href="#w3c"></use>
</svg>
{{ .ref_id }} {{ .title }}</a> (level {{ .level }}){{ if $descriptions }}:{{ end }}
</strong>
{{ if and ($descriptions) (ne $descriptions "false") }}
{{ .description }}
{{ if .special_cases }}
<ul>
{{ range .special_cases }}
<li><strong>{{ .title }}:</strong>
{{ .description }}
</li>
{{ end }}
</ul>
{{ end }}
{{ end }}
</li>
{{ end }}
{{ end }}
</ul>

View file

@ -0,0 +1,6 @@
#!/usr/bin/env bash
git config --local user.name "zwbetz-gh"
git config --local user.email "zwbetz@gmail.com"
git config --local --list

View file

@ -0,0 +1,13 @@
[build]
publish = "exampleSite/public"
command = "cd exampleSite && hugo --themesDir ../.."
[build.environment]
HUGO_VERSION = "0.72.0"
HUGO_THEME = "repo"
HUGO_BASEURL = "https://cupper-hugo-theme.netlify.app"
[[headers]]
for = "/*"
[headers.values]
Access-Control-Allow-Origin = "*"

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

View file

@ -0,0 +1,6 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="50" width="24.999" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 24.998724 50.000001">
<g transform="translate(-25.001 -1002.4)">
<path style="fill-rule:evenodd;fill:#ffffff" d="m25.001 1002.4 24.999 25v-25z"/>
<path style="fill-rule:evenodd;fill:#ffffff" d="m50 1027.4-24.999 25h24.999z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 480 B

View file

@ -0,0 +1,6 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="50mm" width="50mm" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 177.16535 177.16535">
<g transform="translate(0 -875.2)">
<rect style="stroke-width:0;fill:#111" transform="rotate(30)" height="155" width="40" y="702.99" x="556.82"/>
<rect style="stroke-width:0;fill:#111" transform="rotate(30)" height="40" width="90.404" y="817.99" x="506.42"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 535 B

View file

@ -0,0 +1,5 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="22.578mm" width="11.289mm" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 40.00001 80.000027">
<g transform="translate(-200 -563.49)">
<path style="fill-rule:evenodd;stroke-width:0;fill:#000000" d="m240 563.49-40 40v40l40-40z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 415 B

View file

@ -0,0 +1,183 @@
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript&plugins=line-numbers */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
pre[class*="language-"].line-numbers {
position: relative;
padding-left: 3.8em;
counter-reset: linenumber;
}
pre[class*="language-"].line-numbers > code {
position: relative;
white-space: inherit;
}
.line-numbers .line-numbers-rows {
position: absolute;
pointer-events: none;
top: 0;
font-size: 100%;
left: -3.8em;
width: 3em; /* works for line-numbers below 1000 lines */
letter-spacing: -1px;
border-right: 1px solid #999;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.line-numbers-rows > span {
pointer-events: none;
display: block;
counter-increment: linenumber;
}
.line-numbers-rows > span:before {
content: counter(linenumber);
color: #999;
display: block;
padding-right: 0.8em;
text-align: right;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,13 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 100 100">
<g transform="translate(0 -952.36)">
<g transform="matrix(.094248 0 0 .094248 2.8805 955.24)"></g>
<g transform="matrix(.18832 0 0 .18832 4.2017 956.56)"></g>
<g transform="matrix(.059920 0 0 .059920 64.099 1012.5)">
<g>
<g id="android">
<path d="m152.68 458.36c0 15.3 10.2 25.5 25.5 25.5h25.5v89.25c0 20.4 17.85 38.25 38.25 38.25s38.25-17.85 38.25-38.25v-89.25h51v89.25c0 20.4 17.85 38.25 38.25 38.25s38.25-17.85 38.25-38.25v-89.25h25.5c15.3 0 25.5-10.2 25.5-25.5v-255h-306v255zm-63.75-255c-20.4 0-38.25 17.851-38.25 38.25v178.5c0 20.4 17.85 38.25 38.25 38.25s38.25-17.85 38.25-38.25v-178.5c0-20.4-17.85-38.25-38.25-38.25zm433.5 0c-20.4 0-38.25 17.851-38.25 38.25v178.5c0 20.4 17.85 38.25 38.25 38.25s38.25-17.85 38.25-38.25v-178.5c0-20.4-17.85-38.25-38.25-38.25zm-127.5-147.9 33.15-33.15c5.1-5.1 5.1-12.75 0-17.85-5.101-5.101-12.75-5.101-17.851 0l-38.25 38.25c-17.85-12.75-40.8-17.851-66.3-17.851s-48.45 5.101-68.85 15.3l-35.7-38.25c-5.1-2.55-15.3-2.55-20.4 0-2.55 5.101-2.55 15.301 0 20.4l33.15 33.15c-35.7 28.05-61.2 71.399-61.2 122.4h306c0-51-25.5-96.897-63.75-122.4zm-140.25 71.4h-25.5v-25.5h25.5v25.5zm127.5 0h-25.5v-25.5h25.5v25.5zm-315.17-295.94a296.37 296.37 0 0 1 -296.37 296.37 296.37 296.37 0 0 1 -296.37 -296.37 296.37 296.37 0 0 1 296.37 -296.37 296.37 296.37 0 0 1 296.37 296.37zm-104.26-296.4c96.933 62.959 161.06 172.16 161.06 296.36 0 61.07-15.514 118.54-42.798 168.65l.22814.13017-363.47 626.27c17.485 1.1449 35.126 1.7928 52.903 1.7928 143.13 0 277.31-37.916 393.4-103.98.012-.31092.02-.63485.0334-.94527-17.736-4.0482-33.875-15.396-43.092-31.162-39.38 18.48-92.101-3.73-105.87-45.11-8.2326-57.3-3.506-115.34-4.109-172.98-2.4526-23.22-2.1755-48.13 9.485-69.07 16.194-32.792 57.849-48.918 92.213-37.387 3.0695-40.159 17.93-79.632 43.548-110.86-7.7581-10.996-15.806-22.506-17.83-36.149-6.0082-29.885 19.952-62.746 51.175-60.335 23.886-.42474 44.235 15.691 58.412 33.476 37.546-10.929 78.773-12.322 115.85 1.2387 8.8519-9.3168 17.44-19.247 28.521-26.011 25.787-17.584 64.503-3.2156 75.883 24.936 9.2404 20.832.0935 45.21-14.864 60.856 24.881 28.78 39.738 65.45 44.102 103.13 44.834-99.661 69.983-210.11 69.983-326.48 0-104.75-20.275-204.75-57.01-296.36h-547.74zm-854.06-147.32c-85.186 126.81-134.88 279.48-134.88 443.73 0 401.08 296.34 732.91 682.03 788.56l274.92-473.69c-48.07 24.49-102.46 38.3-160.11 38.3l-.0317-.0317c-152.83 0-282.96-97.085-332.15-232.93l-329.78-563.95zm661.92-353.11c-253.59 0-479.45 118.48-625.38 303.08l273.22 467.26c13.519-182.06 165.09-325.68 350.4-326.64v-.0317h716.19c-130.18-262.88-401.19-443.67-714.42-443.67z"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,8 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 100 100">
<g transform="translate(0 -952.36)">
<g transform="matrix(.19488 0 0 .19488 .30580 952.28)">
<circle cx="255" cy="257" r="91.125"/>
<path d="m254.45 148.42v-.007h220.21c-40.03-80.827-123.35-136.41-219.66-136.41-77.97 0-147.42 36.424-192.29 93.18l84.011 143.67c4.157-55.982 50.757-100.14 107.74-100.43zm.55 217.16c-46.99 0-87.004-29.849-102.13-71.617l-101.39-173.39c-26.192 38.99-41.48 85.93-41.48 136.43 0 123.32 91.121 225.35 209.71 242.46l84.529-145.65c-14.78 7.53-31.51 11.778-49.235 11.778zm227.48-199.71h-168.41c29.804 19.358 49.519 52.938 49.519 91.125 0 18.777-4.768 36.443-13.157 51.851l.062.037-111.75 192.56c5.376.352 10.795.55 16.261.55 135.31 0 245-109.69 245-245 0-32.206-6.226-62.956-17.521-91.125z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 964 B

View file

@ -0,0 +1,9 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 100 100">
<g transform="translate(0 -952.36)">
<g transform="matrix(.094248 0 0 .094248 2.8805 955.24)">
<g>
<path d="m48.1 445c28.7-226.6 183.3-432.1 460.4-435 167.2 3.3 304.8 79 386.7 223.5 41.1 75.4 54 154.6 56.6 242.1v102.8h-614.7c2.9 253.5 373.1 244.9 532.5 133.2v206.4c-93.4 56.1-305.2 106.2-469.2 41.7-139.7-52.4-239.2-198.6-238.6-339.3-4.6-182.4 90.7-303.1 238.6-371.8-31.4 38.8-55.3 81.7-67.7 156h347.1s20.3-207.4-196.5-207.4c-204.4 7-351.8 125.9-435.2 247.8z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 719 B

View file

@ -0,0 +1,11 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 100 100">
<g transform="translate(0 -952.36)">
<g transform="matrix(.059920 0 0 .059920 63.622 1011.8)">
<g>
<g id="android">
<path d="m152.68 458.36c0 15.3 10.2 25.5 25.5 25.5h25.5v89.25c0 20.4 17.85 38.25 38.25 38.25s38.25-17.85 38.25-38.25v-89.25h51v89.25c0 20.4 17.85 38.25 38.25 38.25s38.25-17.85 38.25-38.25v-89.25h25.5c15.3 0 25.5-10.2 25.5-25.5v-255h-306v255zm-63.75-255c-20.4 0-38.25 17.851-38.25 38.25v178.5c0 20.4 17.85 38.25 38.25 38.25s38.25-17.85 38.25-38.25v-178.5c0-20.4-17.85-38.25-38.25-38.25zm433.5 0c-20.4 0-38.25 17.851-38.25 38.25v178.5c0 20.4 17.85 38.25 38.25 38.25s38.25-17.85 38.25-38.25v-178.5c0-20.4-17.85-38.25-38.25-38.25zm-127.5-147.9 33.15-33.15c5.1-5.1 5.1-12.75 0-17.85-5.101-5.101-12.75-5.101-17.851 0l-38.25 38.25c-17.85-12.75-40.8-17.851-66.3-17.851s-48.45 5.101-68.85 15.3l-35.7-38.25c-5.1-2.55-15.3-2.55-20.4 0-2.55 5.101-2.55 15.301 0 20.4l33.15 33.15c-35.7 28.05-61.2 71.399-61.2 122.4h306c0-51-25.5-96.897-63.75-122.4zm-140.25 71.4h-25.5v-25.5h25.5v25.5zm127.5 0h-25.5v-25.5h25.5v25.5zm-648.47-1052.2c-153.2 3.6312-304.31 56.616-426.52 149.39-18.198 25.776-95.427 53.771-75.003 84.13 9.915 16.563 16.376 8.3085 28.098-2.5751 164.29-163 410.41-231.13 636.37-186.77 92.023 25.701 185.78 47.562 275.11 81.522-109.16-73.972-240.18-119.24-372.34-124.19-21.892-1.5227-43.827-2.0181-65.713-1.4994zm298.77 104.11c76.659 48.615 145.81 109.53 198.61 183.74 61.419 79.922-35.193-17.684-72.428-19.394-88.432-28.428 16.633 33.427 26.337 66.104 60.034 74.183 88.79 168.13 85.434 263.15 11.41 74.947-20.783-6.5197-51.958-25.131-26.927 16.205 9.4167 113.18 3.1944 158.15-2.001 35.591-8.6324 182.4-41.69 91.464-3.8949 21.877-8.0142 44.695-13.038 67.506 6.9144-3.442 14.6-5.2532 22.687-4.6286 23.886-.42475 44.235 15.691 58.412 33.476 37.546-10.929 78.773-12.322 115.85 1.2386 8.8519-9.3168 17.44-19.247 28.521-26.011 25.787-17.584 64.503-3.2156 75.883 24.936 9.2405 20.832.0935 45.21-14.864 60.856 6.8594 7.9343 12.945 16.469 18.286 25.457 1.0056-39.357 8.0123-77.518 30.966-112.78 53.847-99.934 51.155-220.2 19.003-326.41-8.2394 28.596-33.964 85.038-26.37 17.928 10.813-131.53-37.639-269.01-140.16-354.58-22.49 23.997-92.919-108.34-105.48-52.023 58.36 70.768 130.06 135.32 165.16 222.86-17.994-32.268-82.372-117.57-130.58-156.49-65.555-73.849-157.79-115.62-251.77-139.41zm-865.39 45.699c-50.598 52.066-69.113 127.82-74.97 198.35h.0326v12.973c36.168-35.923 74.584-71.088 121.65-92.083 18.348-21.886-58.779-74.369-46.71-119.24zm437.44 50.784c-75.56 3.3882-142.96 57.617-187.23 116.53-27.292 57.073-24.079 9.047-14.831-24.61-49.193-38.29-146.9-8.65-203.07 22.393-125.63 73.098-172.17 220.3-202.84 353.5 46.722-83.328 1.3199 41.211 7.6926 75.133-.0883 29.606-14.711 183.82 8.4097 91.17 19.997-17.796 15.603 95.292 34.486 121.84 60.197 232.76 250.23 410.71 466.84 502.11 25.064 12.981 176.11 63.077 91.04 15.809 21.545-4.9454 94.604 32.129 135.7 31.813 14.254-4.9045 111.13 24.012 52.349-12.386 87.718-10.482 179.32-14.973 265.66-40.549 25.455-4.5994 49.455-12.983 72.004-23.99-3.6951-3.749-7.0469-7.8251-9.7135-12.386-39.4 18.47-92.121-3.75-105.89-45.13-8.2333-57.3-3.507-115.34-4.11-172.98-2.4524-23.22-2.1752-48.13 9.486-69.07 16.194-32.792 57.849-48.918 92.213-37.387 3.0695-40.159 17.93-79.632 43.548-110.86-3.8428-5.4464-7.7335-11.025-10.952-16.917-17.786 46.326-44.452 87.656-88.465 114.48-20.397-56.905-69.067 56.024-98.081 43.646-19.503-24.663-105.87 20.648-151.77 15.059-29.333 13.051-163.69-36.48-81.522-34.845 30.162-11.267-81.324-26.471-110.21-35.921-66.003-36.299-124.97-97.226-144.63-171.75-6.0631-72.002-14.554-159.04 39.962-215.69-36.095-40.357-131.34-18.073-163.4 32.498-65.468 83.028-32.742 203.3 36.149 273.64-22.962-18.109-63.338-67.843-74.449-107.4-43.518-104.6 30.036-246.52 149.06-246.75 56.519-24.428 141.17 122.1 126.28 12.256 8.0825-45.987-40.037-74.328-50.035-116.53-47.135-116.39 15.69-245.94 103.17-324.95-11.083-1.7248-22.062-2.2768-32.857-1.7928zm-46.71 188.34c-17.752 59.498-4.1945 125.22 32.009 175.17 4.7202.58411 8.9614 22.512 16.852 9.9417 48.679-44.867 154.38-54.475 140.68-141.01-50.281-41.86-139.62 7.2935-189.54-44.102zm-60.954 408.62c-5.2671 74.276 14.421 156.02 79.012 200.56 16.369 17.781 32.353 17.455 54.891 16.07 80.845 8.0341 153.29-31.634 213.44-81.555 19.296-35.347 87.94 8.0109 83.999-41.592-24.259-68.562-118.59-77.127-177.94-53.033-80.692 57.747-186.74 21.228-253.4-40.451z"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -0,0 +1,5 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 100 100">
<g transform="translate(0 -952.36)">
<path style="fill:#000000" d="m48.212 1047.3c-2.4619.02-6.8405-2.2013-8.1318-1.9049 5.0976 2.8323-3.9517-.1694-5.4535-.9472-12.979-5.4764-24.366-16.139-27.973-30.086-1.1315-1.5909-.8693-8.3687-2.0675-7.3024-1.3854 5.5516-.50865-3.6884-.50336-5.4624-.38185-2.0326 2.3388-9.4953-.46079-4.5023 1.8379-7.9816 4.6266-16.8 12.154-21.18 3.3659-1.8601 9.2204-3.6361 12.168-1.3418-.55412 2.0167-.74594 4.8931.88940 1.4733 3.0318-4.0343 7.8741-7.7006 13.187-6.8738-5.2415 4.734-9.0067 12.495-6.1824 19.469.59907 2.5287 3.4842 4.2277 2.9999 6.9832.89239 6.5818-4.1802-2.1975-7.5668-.73381-7.1319.014-11.539 8.5177-8.9314 14.785.66574 2.3704 3.084 5.35 4.4599 6.4351-4.1279-4.2151-6.089-11.422-2.1662-16.397 1.9214-3.0302 7.6289-4.3642 9.7917-1.946-3.2666 3.394-2.7576 8.6087-2.3943 12.923 1.1778 4.4653 4.7112 8.117 8.6661 10.292 1.7306.5662 8.4095 1.4758 6.6022 2.1509-4.9236-.098 3.1271 2.871 4.8847 2.089 2.7503.3349 7.9265-2.3797 9.0951-.9019 1.7385.7417 4.6534-6.026 5.8756-2.6163 5.2366-3.191 6.3838-9.8086 7.3784-15.395 1.9808 5.4491 2.3774-3.3468 2.4973-5.4794.37284-2.6946-1.8045-8.5058-.19106-9.4768 1.868 1.1152 3.7972 5.997 3.1135 1.5062.20110-5.6935-1.5215-11.324-5.1187-15.769-.58148-1.958-6.8783-5.6625-1.5795-3.9591 2.2311.10252 8.0208 5.9503 4.3406 1.1614-3.1635-4.4467-7.3076-8.096-11.901-11.009 5.6314 1.4258 11.159 3.928 15.087 8.353 2.8885 2.3325 6.7461 7.4432 7.8243 9.3767-2.1033-5.2453-6.4004-9.1126-9.8973-13.353.75267-3.3744 4.9719 4.5534 6.3195 3.1155 6.1431 5.1271 9.0478 13.367 8.3999 21.248-.45504 4.0212 1.0863.63813 1.58-1.0753 1.9265 6.3645 2.0874 13.571-1.1391 19.559-2.0733 3.1852-1.9952 6.76-1.747 10.39-.28526 2.7302-2.3678 5.0662-3.9091 7.2654-2.5671 3.2593-5.9016 5.7954-9.4254 7.921-2.5621 4.2065-6.66 7.1655-11.521 8.0438-5.1734 1.5325-10.662 1.8031-15.918 2.4312 3.5236 2.182-2.2877.4449-3.1376.7408zm-9.8762-30.448c-3.8703-2.6692-5.0516-7.5674-4.736-12.018 3.9942 3.6958 10.35 5.8829 15.185 2.4227 3.5565-1.4437 9.2074-.9303 10.661 3.1779.23613 2.9722-3.8772.3751-5.0334 2.4931-3.6039 2.9912-7.9438 5.3678-12.788 4.8864-1.3505.083-2.3077.1036-3.2885-.9618zm.83582-26.006c-2.1693-2.9927-2.9816-6.9309-1.9179-10.496 2.9917 3.0796 8.3442.13308 11.357 2.6413.82094 5.1851-5.5128 5.7608-8.4296 8.4492-.47280.75321-.72707-.55934-1.0099-.59434zm-29.822-12.94c.35096-4.2257 1.4603-8.7642 4.4921-11.884-.72317 2.6884 3.8972 5.8318 2.7978 7.1432-2.82 1.258-5.1226 3.3666-7.2898 5.5191v-.77858zm8.3923-6.87c-1.2238-1.8191 3.4023-3.4964 4.4927-5.0409 8.3684-6.3529 19.001-9.5905 29.495-8.8606 7.9193.29674 15.77 3.0082 22.311 7.4406-5.3527-2.0349-10.971-3.3439-16.485-4.8839-13.539-2.6576-28.287 1.4241-38.131 11.191-.70238.65214-1.0888 1.1464-1.6829.15394z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1,10 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 100 100">
<g transform="translate(0 -952.36)">
<g transform="matrix(.094248 0 0 .094248 2.8805 955.24)"></g>
<g transform="matrix(.18832 0 0 .18832 4.2017 956.56)">
<g>
<path d="m367.1 280.8h118.02c.909-8.185 1.273-16.549 1.273-25.099 0-40.111-10.768-77.733-29.562-110.13 19.45-51.66 18.75-95.5-7.27-121.7-24.75-24.64-91.15-20.64-166.21 12.599-5.552-.42-11.158-.636-16.817-.636-103.02 0-189.46 70.897-213.35 166.42 32.318-41.377 66.318-71.377 111.74-93.224-4.13 3.87-28.227 27.826-32.28 31.882-119.77 119.74-157.54 276.16-116.9 316.81 30.893 30.887 86.879 25.671 151.19-5.824 29.903 15.229 63.75 23.815 99.61 23.815 96.565 0 178.4-62.158 208.04-148.72h-118.93c-16.366 30.19-48.373 50.739-85.107 50.739s-68.743-20.549-85.108-50.739c-7.275-13.638-11.457-29.276-11.457-45.828v-.36h193.13zm-192.95-58.02c2.728-48.555 43.1-87.292 92.384-87.292 49.282 0 89.655 38.736 92.382 87.292h-184.77zm274.33-174.5c16.763 16.94 16.344 48.107 2.006 87.011-24.57-37.458-60.26-66.972-102.4-83.824 45.06-19.319 81.71-21.878 100.39-3.191zm-401.74 401.72c-21.391-21.4-14.943-66.31 12.614-120.42 17.154 48.136 50.578 88.545 93.668 114.58-47.714 21.66-86.768 25.337-106.28 5.839z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,7 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 100 100">
<g transform="translate(0 -952.36)">
<g transform="matrix(.094248 0 0 .094248 2.8805 955.24)"></g>
<g transform="matrix(.18832 0 0 .18832 4.2017 956.56)"></g>
<path style="fill:#000000" d="m41.401 1047.9c-15.184-3.4313-27.055-14.514-32.097-29.968-1.8896-5.7912-2.2419-8.3552-2.2419-16.315 0-7.7133.34205-10.428 1.9973-15.851 4.3432-14.23 14.797-24.477 28.855-28.282 3.1637-.85642 4.4999-1.004 10.407-1.1488 7.5416-.18488 10.196.16319 16.09 2.1095 13.258 4.3784 23.204 15.449 26.86 29.898 5.55 21.931-3.0849 44.309-21.234 55.029-2.6091 1.5413-6.3812 3.0931-9.7867 4.0263-3.6468.9992-15.279 1.3093-18.85.5024zm13.609-11.258c5.0503-2.4708 8.4981-9.4275 9.9833-20.143.76151-5.4946.67497-24.895-.13378-29.989-1.7607-11.09-5.0434-17.485-10.15-19.773-2.7736-1.2429-7.3443-1.2343-9.8983.0188-3.9487 1.937-7.0286 6.5962-8.6902 13.147-1.6506 6.5069-1.8367 8.7982-1.8225 22.442.01131 10.842.11812 13.461.67338 16.515 1.9995 10.997 5.6512 16.945 11.401 18.571 2.5076.7089 6.2822.3649 8.637-.7872z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -0,0 +1,5 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 100 100">
<g transform="translate(0 -952.36)">
<path d="m52.788 1002.2q0 1.3678-.86801 2.3674-.86801.9995-2.1832.9995-1.3678 0-2.3673-.8681-.99953-.8679-.99953-2.1832 0-1.3676.89432-2.3673.89432-.99943 2.2095-.99943t2.3147.86803q.99953.868.99953 2.1831zm.78910 3.0513 18.412-30.565q-.47346.42084-3.551 3.2879t-6.6022 6.1287-7.1808 6.6811q-3.6562 3.4194-6.155 5.8131-2.4988 2.3936-2.6566 2.7093l-18.36 30.512q.36825-.3681 3.5247-3.2615 3.1564-2.8935 6.6285-6.1287 3.4721-3.2353 7.1545-6.6811 3.6825-3.4458 6.155-5.8394t2.6303-2.6566zm34.037-2.8934q0 10.574-5.4711 19.517-.15782-.1053-.89432-.5787-.73650-.4733-1.3941-.8679-.65758-.3945-.86801-.3945-.68389 0-.68389.6839 0 .526 3.1038 2.3146-3.8929 5.8919-9.706 10.022-5.8131 4.1297-12.705 5.8131l-.84171-3.5247q-.0526-.5261-.78910-.5261-.26304 0-.42086.2894-.15782.2893-.10522.4997l.84171 3.5773q-3.7877.7891-7.6806.7891-10.469 0-19.57-5.5237.0526-.1054.68389-1.0785.63128-.9731 1.131-1.7622.49976-.7891.49976-.9997 0-.6837-.68389-.6837-.31564 0-.89432.7627-.57868.7628-1.1837 1.815-.60498 1.052-.71019 1.2099-5.9446-3.9455-10.101-9.8638-4.1559-5.9183-5.7868-12.862l3.6299-.7891q.52607-.1579.52607-.7891 0-.2631-.28934-.4208-.28934-.1579-.55237-.1054l-3.5773.7891q-.73650-3.7877-.73650-7.3123 0-10.837 5.7341-19.938.10522.0527.97323.63128.86801.57867 1.5782.99953.71019.42087.92062.42087.68389 0 .68389-.63129 0-.31564-.65759-.81541-.65758-.49976-1.7097-1.131l-1.0521-.6313q4.0507-5.892 9.9427-9.9427t12.836-5.6289l.78910 3.5247q.10522.52607.78910.52607.26303 0 .42085-.28934.15782-.28933.10522-.55237l-.78910-3.4721q3.7351-.68389 7.0493-.68389 10.732 0 19.938 5.7342-2.0517 2.946-2.0517 3.4194 0 .68389.63128.68389.57868 0 2.5251-3.3668 5.8394 3.9455 9.8638 9.7849t5.6552 12.678l-2.946.63128q-.52607.10521-.52607.84171 0 .26303.28934.42085t.49976.10521l2.9986-.68389q.73650 3.7877.73650 7.365zm4.4716 0q0-8.5749-3.3405-16.361-3.3405-7.7858-8.9695-13.415-5.6289-5.6289-13.415-8.9695-7.786-3.37-16.361-3.37-8.5749 0-16.361 3.3405-7.7858 3.3405-13.415 8.9695-5.6289 5.6289-8.9695 13.415-3.3405 7.7858-3.3405 16.361 0 8.5748 3.3405 16.361 3.3405 7.7859 8.9695 13.415 5.6289 5.629 13.415 8.9695 7.7858 3.3405 16.361 3.3405 8.5749 0 16.361-3.3405 7.7858-3.3405 13.415-8.9695 5.6289-5.6289 8.9695-13.415 3.3405-7.7859 3.3405-16.361zm5.0503 0q0 9.5744-3.7351 18.307-3.7351 8.7327-10.048 15.046-6.3128 6.3128-15.046 10.048-8.7327 3.735-18.307 3.735-9.5744 0-18.307-3.735-8.7327-3.7351-15.046-10.048-6.3128-6.3129-10.048-15.046-3.7351-8.7328-3.7351-18.307 0-9.5745 3.7351-18.307 3.7351-8.7327 10.048-15.046 6.3128-6.3128 15.046-10.048 8.7327-3.7351 18.307-3.7351 9.5744 0 18.307 3.7351 8.7327 3.7351 15.046 10.048 6.3128 6.3128 10.048 15.046 3.7351 8.7328 3.7351 18.307z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1,9 @@
<svg height="41.667" width="41.667" viewBox="0 0 41.667306 41.66729">
<g transform="translate(-37.035 -1004.6)">
<path style="stroke-linejoin:round;stroke:currentColor;stroke-linecap:round;stroke-width:3.728;fill:none" d="m76.25 1030.2a18.968 18.968 0 0 1 -23.037 13.709 18.968 18.968 0 0 1 -13.738 -23.019 18.968 18.968 0 0 1 23.001 -13.768 18.968 18.968 0 0 1 13.798 22.984"/>
<g transform="matrix(1.1146 0 0 1.1146 -26.276 -124.92)">
<path style="stroke:currentColor;stroke-linecap:round;stroke-width:3.728;fill:none" d="m75.491 1039.5v-8.7472"/>
<path style="stroke-width:0;fill:currentColor" transform="scale(-1)" d="m-73.193-1024.5a2.3719 2.3719 0 0 1 -2.8807 1.7142 2.3719 2.3719 0 0 1 -1.718 -2.8785 2.3719 2.3719 0 0 1 2.8763 -1.7217 2.3719 2.3719 0 0 1 1.7254 2.8741"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 811 B

View file

@ -0,0 +1,5 @@
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="50mm" width="50mm" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 177.16535 177.16535">
<g transform="translate(0 -875.2)">
<path style="fill-rule:evenodd;stroke-width:0;fill:#111111" d="m159.9 894.3-68.79 8.5872-75.42 77.336 61.931 60.397 75.429-76.565 6.8495-69.755zm-31.412 31.835a10.813 10.813 0 0 1 1.8443 2.247 10.813 10.813 0 0 1 -3.5174 14.872l-.0445.0275a10.813 10.813 0 0 1 -14.86 -3.5714 10.813 10.813 0 0 1 3.5563 -14.863 10.813 10.813 0 0 1 13.022 1.2884z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 658 B

View file

@ -0,0 +1,7 @@
<svg height="41.646" width="48.43" viewBox="0 0 48.430474 41.646302">
<g transform="translate(-1.1273 -1010.2)">
<path style="stroke-linejoin:round;stroke:currentColor;stroke-linecap:round;stroke-width:4.151;fill:none" d="m25.343 1012.3-22.14 37.496h44.28z"/>
<path style="stroke:currentColor;stroke-linecap:round;stroke-width:4.1512;fill:none" d="m25.54 1027.7v8.7472"/>
<path style="stroke-width:0;fill:currentColor" d="m27.839 1042.8a2.3719 2.3719 0 0 1 -2.8807 1.7143 2.3719 2.3719 0 0 1 -1.718 -2.8785 2.3719 2.3719 0 0 1 2.8763 -1.7217 2.3719 2.3719 0 0 1 1.7254 2.8741"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 599 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 152.7 100.69"><path d="M1.96 0C.88 0 0 .85 0 1.88v88.3c0 1 .88 1.86 1.94 1.86h26.1v-1.65H1.96c-.15 0-.25-.1-.25-.23V1.87c0-.14.1-.22.24-.22h148.8c.15 0 .24.08.24.23v88.3c0 .13-.1.22-.24.22h-27.4v1.64h27.4c1.07 0 1.95-.86 1.95-1.88V1.87c0-1.02-.88-1.87-1.94-1.87H1.96z" white-space="normal" style="text-decoration-color:#000000;isolation:auto;mix-blend-mode:normal;text-indent:0;block-progression:tb;text-decoration-line:none;text-transform:none;text-decoration-style:solid" color="#000" solid-color="#000000"/><path d="M72.43 75.45c-3.22-.35-4.48-.54-6.43-.97-4.5-1-8.23-2.75-11.48-5.4-8.24-6.7-13-19.6-14.36-38.8-.32-4.66-.4-7.98-.23-8.34.25-.5.93-1.27 1.48-1.7 4.06-3.24 14-5.02 30.3-5.44 7.44-.18 16.9.22 23.04.98 5.87.73 9.62 1.64 12.4 3 1.04.52 1.3.7 1.95 1.34 1.12 1.1 1.14 1.2 1.27 4.88.05 1.65.1 3 .12 3.02 0 0 .25-.07.54-.18 1.34-.52 3.74-1.3 5.06-1.63 2.38-.6 3.17-.72 5.18-.72 2.04 0 2.84.15 4.15.8 1.93.95 4.3 3.56 5.42 5.96.97 2.14 1.3 3.56 1.28 5.85 0 1.9-.16 2.8-.75 4.58-2.3 6.9-10.07 14.34-20.6 19.8-4.68 2.4-9.83 4.25-13.62 4.86l-1.05.16-.82.67c-4.08 3.3-9.88 5.82-15.56 6.73-2.63.42-6 .66-7.3.53zm34.03-19.1c3.4-.8 6.9-2.25 9.45-3.93 4.18-2.75 7-6.07 8.3-9.84.46-1.34.64-2.35.64-3.64-.02-2-.5-3.4-1.58-4.45-1.07-1.06-2.34-1.5-4.08-1.38-2.25.13-4.6 1.07-7.45 2.98-2.05 1.36-1.87 1.1-2.14 3.02-.86 6.16-2.45 11.7-4.7 16.46l-.55 1.2.46-.07c.26-.04 1-.2 1.64-.35zm-27.14-7.77c1.38-2.07 2.65-3.9 2.82-4.03.58-.5 1.44-.46 2 .06.16.17 1.45 2.02 2.85 4.12l2.55 3.82.02-12.5V27.5c-.02 0-.74.08-1.62.2-2.67.4-4.73.55-8.16.6l-3.3.06.03 7.1c.04 9.5.13 17.06.22 16.96.04-.04 1.2-1.77 2.6-3.85zm-6.06-21.57c.04-.75.07-.9.3-1.2.5-.66.47-.65 4.97-.66 5.52 0 7.38-.14 11-.82 1.87-.35 2.17-.34 2.63.04.47.4.6.78.6 1.68 0 1-.2.94 1.98.6 4.34-.7 6.84-1.46 7.82-2.4.45-.45.47-.8.06-1.26-.35-.4-.9-.72-1.78-1.05-4.46-1.68-14.23-2.7-25.75-2.7-11.48.02-21.44 1.06-25.65 2.7-.84.33-1.65.9-1.87 1.28-.55 1 1.2 2 4.94 2.84 4.5 1 12.1 1.7 19.08 1.78h1.66l.03-.84zM43.42 96.62q-1.468 0-2.71-.723-1.22-.723-1.943-1.965-.723-1.243-.723-2.71v-2.734q0-1.47.723-2.71t1.942-1.966q1.24-.723 2.71-.723 1.13 0 2.17.47 1.03.45 1.78 1.29.16.16.16.36 0 .25-.21.45l-.97.97q-.16.16-.37.16t-.39-.21q-.88-.88-2.19-.88-1.11 0-1.9.79-.77.76-.77 1.87v2.96q0 1.1.77 1.89.79.77 1.89.77 1.31 0 2.19-.88.18-.21.38-.21t.36.16l.97.97q.2.2.2.45 0 .2-.16.36-.75.83-1.79 1.31-1.04.45-2.17.45zm11.26 0q-1.288 0-2.327-.61-1.016-.61-1.604-1.694-.59-1.084-.59-2.44v-8.02q0-.203.13-.338t.34-.136h1.76q.2 0 .34.136t.13.34v7.68q0 1.197.61 1.852.61.632 1.71.632 1.33 0 2.1-.858.79-.88.79-2.395v-6.92q0-.21.13-.34t.34-.14h1.76q.2 0 .34.13t.13.34v12q0 .2-.14.34t-.34.13h-1.76q-.21 0-.34-.14t-.14-.34v-1.06q-.63.86-1.52 1.35-.86.47-1.9.47zm10.17 4.07q-.203 0-.34-.136t-.134-.338V83.86q0-.203.135-.338t.34-.136h1.47q.21 0 .34.136t.14.34v1.015q.59-.88 1.45-1.333.88-.45 1.88-.45 1.33 0 2.49.72 1.18.702 1.86 1.9.7 1.196.7 2.574v3.14q0 1.378-.67 2.576t-1.83 1.92q-1.15.7-2.53.7-.83 0-1.62-.34-.762-.36-1.4-1.015v4.94q0 .2-.13.34t-.34.13h-1.77zm4.925-6.664q1.107 0 1.875-.768.79-.79.79-1.898v-3.004q0-1.107-.79-1.875-.768-.79-1.875-.79t-1.898.79q-.79.77-.79 1.88v3.01q0 1.11.79 1.9.79.77 1.898.77zm8.935 6.664q-.203 0-.34-.136t-.134-.338V83.86q0-.203.135-.338t.34-.136h1.47q.21 0 .34.136t.14.34v1.015q.59-.88 1.45-1.333.88-.45 1.88-.45 1.33 0 2.49.72 1.18.702 1.86 1.9.7 1.196.7 2.574v3.14q0 1.378-.67 2.576t-1.83 1.92q-1.15.7-2.53.7-.83 0-1.62-.34-.762-.36-1.4-1.015v4.94q0 .2-.13.34t-.34.13h-1.77zm4.925-6.664q1.107 0 1.875-.768.79-.79.79-1.898v-3.004q0-1.107-.79-1.875-.768-.79-1.875-.79t-1.898.79q-.79.77-.79 1.88v3.01q0 1.11.79 1.9.79.77 1.898.77zM97.12 96.33q-1.468 0-2.71-.723-1.22-.723-1.943-1.965-.723-1.243-.723-2.71v-2.44q0-1.47.722-2.71t1.943-1.967q1.24-.723 2.71-.723t2.68.723q1.24.723 1.96 1.966.72 1.25.72 2.71v1.52q0 .41-.3.7-.27.27-.68.27h-7.07v.12q0 1.11.76 1.9.79.77 1.9.77h3.59q.2 0 .34.14t.13.34v1.63q0 .21-.14.34t-.338.14H97.1zm2.666-7.794v-.203q0-1.107-.79-1.875-.77-.79-1.876-.79t-1.898.79q-.768.768-.768 1.875v.203h5.33zm5.424 7.794q-.203 0-.34-.136t-.134-.338v-1.672q0-.203.135-.34t.34-.134h1.72v-7.77h-1.94q-.2 0-.34-.137t-.13-.34V83.86q0-.203.14-.34t.34-.134h3.5q.41 0 .68.294.3.27.3.677v.813l1.22-.97q.68-.543 1.18-.746.5-.226 1.18-.226h.7q.21 0 .34.135t.14.34v1.738q0 .21-.13.34t-.34.14h-.58q-.59 0-1.02.21-.43.21-1.31.91l-1.24 1v5.7h2.238q.21 0 .34.14t.14.34v1.67q0 .21-.132.34t-.34.14h-6.59z"/></svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,62 @@
/**
* Copyright 2015 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-env browser */
'use strict';
if ('serviceWorker' in navigator) {
// Delay registration until after the page has loaded, to ensure that our
// precaching requests don't degrade the first visit experience.
// See https://developers.google.com/web/fundamentals/instant-and-offline/service-worker/registration
window.addEventListener('load', function() {
// Your service-worker.js *must* be located at the top-level directory relative to your site.
// It won't be able to control pages unless it's located at the same level or higher than them.
// *Don't* register service worker file in, e.g., a scripts/ sub-directory!
// See https://github.com/slightlyoff/ServiceWorker/issues/468
navigator.serviceWorker.register('service-worker.js').then(function(reg) {
// updatefound is fired if service-worker.js changes.
reg.onupdatefound = function() {
// The updatefound event implies that reg.installing is set; see
// https://w3c.github.io/ServiceWorker/#service-worker-registration-updatefound-event
var installingWorker = reg.installing;
installingWorker.onstatechange = function() {
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and the fresh content will
// have been added to the cache.
// It's the perfect time to display a "New content is available; please refresh."
// message in the page's interface.
console.log('New or updated content is available.');
} else {
// At this point, everything has been precached.
// It's the perfect time to display a "Content is cached for offline use." message.
console.log('Content is now available offline!');
}
break;
case 'redundant':
console.error('The installing service worker became redundant.');
break;
}
};
};
}).catch(function(e) {
console.error('Error during service worker registration:', e);
});
});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -0,0 +1,78 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1224.000000pt" height="1224.000000pt" viewBox="0 0 1224.000000 1224.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,1224.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M95 10136 c-35 -15 -83 -67 -90 -99 -3 -12 -4 -1629 -3 -3594 l3
-3572 21 -28 c12 -15 36 -37 55 -48 33 -20 52 -20 1099 -20 l1065 0 0 65 0 65
-1053 3 -1052 2 2 3553 3 3552 5975 0 5975 0 3 -3552 2 -3553 -1102 -2 -1103
-3 -3 -68 -3 -67 1118 2 c1098 3 1119 3 1152 23 19 11 43 33 55 48 l21 28 3
3583 2 3583 -22 33 c-13 18 -36 43 -51 54 l-28 21 -6007 2 c-4979 2 -6012 0
-6037 -11z"/>
<path d="M5590 8959 c-606 -22 -1123 -71 -1480 -140 -456 -88 -752 -216 -873
-376 l-42 -57 2 -170 c8 -636 107 -1425 248 -1961 222 -848 581 -1425 1100
-1768 175 -116 456 -236 680 -291 110 -27 268 -54 449 -77 166 -20 191 -21
354 -10 340 23 568 67 849 165 272 95 553 247 756 409 63 51 73 56 160 71 635
115 1451 523 2011 1007 56 47 160 147 231 220 283 290 439 542 527 854 20 69
23 104 23 260 0 155 -3 191 -22 260 -66 242 -206 460 -389 605 -124 99 -221
135 -389 146 -198 13 -425 -30 -753 -142 -90 -31 -166 -53 -169 -50 -4 3 -10
86 -14 184 -15 342 -16 348 -100 433 -205 208 -809 348 -1739 404 -538 32
-979 40 -1420 24z m1220 -374 c823 -50 1373 -166 1429 -304 11 -26 11 -34 -3
-55 -31 -49 -151 -104 -317 -146 -107 -28 -327 -68 -410 -76 l-66 -7 -8 69
c-9 83 -25 119 -65 139 -39 20 -51 20 -251 -14 -236 -40 -363 -50 -791 -57
-233 -5 -376 -11 -389 -18 -40 -20 -59 -58 -66 -129 l-6 -67 -141 0 c-306 0
-840 37 -1161 81 -477 65 -755 160 -755 258 0 165 706 303 1740 341 301 11
957 3 1260 -15z m370 -1640 c0 -547 -2 -995 -4 -995 -3 0 -84 118 -182 263
-97 144 -195 286 -217 315 -75 102 -152 105 -224 9 -22 -28 -120 -171 -219
-317 l-179 -265 -6 70 c-4 39 -10 472 -14 963 l-7 892 158 0 c217 0 512 17
674 39 74 10 154 19 178 20 l42 1 0 -995z m2501 545 c262 -50 386 -332 297
-675 -129 -495 -621 -933 -1273 -1134 -105 -32 -326 -84 -332 -77 -2 2 23 64
55 137 169 382 277 761 347 1214 17 107 33 179 44 195 24 35 226 169 346 229
195 99 376 137 516 111z"/>
<path d="M3377 3479 c-106 -25 -226 -121 -276 -221 -45 -89 -53 -149 -49 -347
3 -167 5 -179 31 -235 60 -130 146 -209 266 -247 119 -36 254 -18 361 51 50
32 100 83 100 101 0 6 -23 35 -51 65 -56 58 -84 67 -113 35 -10 -11 -40 -29
-69 -41 -112 -49 -233 -9 -286 94 -23 44 -26 64 -29 181 -7 212 21 290 121
340 66 33 134 33 203 1 28 -13 55 -29 58 -35 4 -6 16 -16 27 -21 17 -9 28 -3
79 46 33 31 60 65 60 74 0 22 -76 92 -129 119 -88 46 -212 62 -304 40z"/>
<path d="M5530 3477 c-52 -15 -135 -68 -150 -97 -17 -33 -30 -23 -30 23 0 24
-5 48 -12 55 -15 15 -132 16 -159 2 -18 -10 -19 -29 -19 -683 0 -510 3 -676
12 -685 16 -16 180 -16 196 0 9 9 12 70 12 215 l0 202 55 -38 c70 -49 125 -64
217 -60 182 10 336 156 367 349 13 80 14 283 1 369 -27 191 -189 346 -371 357
-44 2 -93 -1 -119 -9z m174 -227 c45 -31 85 -87 97 -137 12 -53 11 -272 -2
-331 -38 -180 -277 -225 -384 -74 l-30 44 -3 171 c-2 108 1 186 8 210 14 49
65 105 115 129 57 27 150 21 199 -12z"/>
<path d="M6655 3481 c-54 -14 -104 -42 -145 -82 l-40 -39 0 33 c0 18 -7 43
-16 55 -13 19 -24 22 -84 22 -49 0 -73 -4 -84 -16 -14 -14 -16 -89 -16 -683 0
-505 3 -670 12 -679 16 -16 180 -16 196 0 9 9 12 71 12 216 l0 204 49 -37 c71
-52 127 -68 219 -63 184 8 341 153 372 343 13 79 13 303 0 384 -31 187 -191
337 -371 346 -41 2 -87 1 -104 -4z m163 -234 c23 -14 54 -48 69 -74 27 -46 28
-55 32 -199 4 -189 -9 -243 -69 -298 -52 -46 -81 -58 -151 -59 -71 0 -137 35
-177 95 -26 40 -27 46 -30 212 -2 107 1 185 8 209 14 49 65 105 115 129 59 27
150 21 203 -15z"/>
<path d="M7670 3474 c-163 -44 -284 -184 -311 -364 -15 -95 -6 -308 15 -377
37 -117 140 -229 256 -275 49 -19 78 -22 253 -26 145 -3 202 -1 212 8 19 16
21 160 3 178 -8 8 -57 12 -154 12 -166 0 -234 11 -287 46 -42 28 -87 108 -87
157 l0 27 298 0 299 0 22 24 c22 24 23 30 19 158 -4 125 -6 137 -37 201 -91
189 -299 285 -501 231z m206 -213 c51 -23 98 -80 114 -137 22 -77 27 -75 -207
-72 -233 3 -224 0 -203 77 13 49 59 105 109 131 47 25 133 25 187 1z"/>
<path d="M8970 3459 c-25 -11 -77 -44 -116 -74 l-72 -54 -6 48 c-11 80 -23 85
-201 89 -99 2 -161 -1 -174 -8 -19 -9 -21 -20 -21 -93 0 -51 5 -88 12 -95 7
-7 44 -12 95 -12 l83 0 0 -310 0 -310 -72 0 c-40 0 -80 -4 -88 -10 -18 -11
-26 -133 -11 -173 l11 -27 292 2 293 3 3 88 c2 57 -1 94 -9 103 -8 10 -37 14
-105 14 l-94 0 0 229 0 228 75 59 c105 83 148 104 211 104 74 0 84 13 84 106
0 105 -6 114 -83 114 -41 0 -77 -7 -107 -21z"/>
<path d="M4038 3459 c-17 -9 -18 -37 -18 -359 0 -220 4 -369 11 -402 25 -116
89 -202 187 -250 60 -30 75 -33 157 -33 104 0 151 18 229 86 l46 41 0 -40 c0
-61 17 -72 114 -72 50 0 87 5 94 12 17 17 17 999 0 1016 -14 14 -166 16 -188
2 -13 -8 -16 -62 -20 -347 -3 -221 -9 -347 -17 -364 -37 -83 -111 -129 -208
-129 -70 0 -107 13 -141 52 -41 45 -44 77 -44 429 0 294 -2 340 -16 353 -18
19 -157 22 -186 5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5 KiB

View file

@ -0,0 +1,19 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

Some files were not shown because too many files have changed in this diff Show more