Initial commit. ♥

main
Bauke 3 years ago
commit 8d94dd95c6
Signed by: Bauke
GPG Key ID: C1C0F29952BCF558

108
.gitignore vendored

@ -0,0 +1,108 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Output directories.
build/
public/

@ -0,0 +1,26 @@
.common:
image: node:12
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
before_script:
- node --version
- yarn --version
- yarn
test:
extends: .common
stage: test
script:
- yarn test
pages:
extends: .common
stage: deploy
script:
- yarn build
- cp 'public/index.html' 'public/404.html'
artifacts:
paths:
- public

@ -0,0 +1,7 @@
Copyright 2020 Holllo <helllo@holllo.cc>
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.

@ -0,0 +1,17 @@
# Love
> A color scheme for you to love. ♡ https://love.holllo.cc
## Get
### File Formats
* [JSON](https://love.holllo.cc/love.json)
### Software
* Firefox Color [Dark](https://color.firefox.com/?theme=XQAAAAIYAQAAAAAAAABBqYhm849SCia2CaaEGccwS-xNKlhSXT3Vtt2XDAs6h7gdL5pcAb7xqXopx66Ln4wY2B4_apm1Xo1m-kSLNybjC15LIb4OXWhGfyPJrZA2e0IeJeWC0yox2SBMD04SrZBvZwoC8QX9EBbJd69TMCmh7d-g0Wc_msdR2nzvnbFECN4_c5VKI9Btzbzvdvjw1-KH_nfezJDCoRea7HASdSJBgMVdHiWfmWiLujatKOWmCJfGaFyV_75SjmA)/[Light](https://color.firefox.com/?theme=XQAAAAIqAQAAAAAAAABBqYhm849SCia2CaaEGccwS-xNKliFvSp4LiFpmRcA5AwYsIABKiGtHcakOiV8NSmxjnVR9H4TYg2VNxSp6iDrgcvBoo3NoFSZSndEX6ZHCH8h1ahP78I4dZXjJD8ZzlOxqC6HrDKQmTBAEm09iix8uVI5_QcbhtDjDxpYbPP5WGvXu84Za9H0s1VXwrgKdxIgKTJraGh0P5bPsWJ_YY-lPSsAB62ABnbOV7SJEIMsWMC9a01QhpCubrrA-f_WNVAA)
## License
Open-sourced with [the MIT License](License).

@ -0,0 +1,52 @@
{
"name": "love",
"version": "0.1.0",
"license": "MIT",
"author": "Holllo <helllo@holllo.cc>",
"homepage": "https://love.holllo.cc",
"repository": "https://gitlab.com/holllo/love",
"scripts": {
"build": "yarn ts-node source/scripts/pages.ts && yarn build:images",
"build:images": "cpy 'source/pages/images/**' 'public/images/'"
},
"dependencies": {
"modern-normalize": "^0.6.0"
},
"devDependencies": {
"@types/nunjucks": "^3.1.3",
"@types/sass": "^1.16.0",
"@types/tar": "^4.0.3",
"cpy-cli": "^3.1.0",
"hsluv": "^0.1.0",
"hsluv-sass": "^1.0.0",
"htmlclean": "^3.0.8",
"mathsass": "^0.11.0",
"nunjucks": "^3.2.1",
"sass": "^1.26.3",
"stylelint": "^13.2.1",
"stylelint-config-xo-scss": "^0.12.0",
"stylelint-config-xo-space": "^0.14.0",
"tar": "^6.0.1",
"ts-node": "^8.7.0",
"typescript": "^3.8.3",
"xo": "^0.28.0"
},
"stylelint": {
"extends": [
"stylelint-config-xo-scss",
"stylelint-config-xo-space"
],
"ignoreFiles": [
"public/css/**"
],
"rules": {
"at-rule-empty-line-before": null,
"at-rule-no-unknown": null,
"no-descending-specificity": null
}
},
"xo": {
"prettier": true,
"space": true
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="224" height="31">
<rect id="back" fill="#f6c915" width="224" height="31"/>
<svg viewBox="0 0 80 80" height="21" width="21" x="4" y="5">
<g transform="translate(-78.37-208.06)" fill="#1a171b">
<path d="m104.28 271.1c-3.571 0-6.373-.466-8.41-1.396-2.037-.93-3.495-2.199-4.375-3.809-.88-1.609-1.308-3.457-1.282-5.544.025-2.086.313-4.311.868-6.675l9.579-40.05 11.69-1.81-10.484 43.44c-.202.905-.314 1.735-.339 2.489-.026.754.113 1.421.415 1.999.302.579.817 1.044 1.546 1.395.729.353 1.747.579 3.055.679l-2.263 9.278"/>
<path d="m146.52 246.14c0 3.671-.604 7.03-1.811 10.07-1.207 3.043-2.879 5.669-5.01 7.881-2.138 2.213-4.702 3.935-7.693 5.167-2.992 1.231-6.248 1.848-9.767 1.848-1.71 0-3.42-.151-5.129-.453l-3.394 13.651h-11.162l12.52-52.19c2.01-.603 4.311-1.143 6.901-1.622 2.589-.477 5.393-.716 8.41-.716 2.815 0 5.242.428 7.278 1.282 2.037.855 3.708 2.024 5.02 3.507 1.307 1.484 2.274 3.219 2.904 5.205.627 1.987.942 4.11.942 6.373m-27.378 15.461c.854.202 1.91.302 3.167.302 1.961 0 3.746-.364 5.355-1.094 1.609-.728 2.979-1.747 4.111-3.055 1.131-1.307 2.01-2.877 2.64-4.714.628-1.835.943-3.858.943-6.071 0-2.161-.479-3.998-1.433-5.506-.956-1.508-2.615-2.263-4.978-2.263-1.61 0-3.118.151-4.525.453l-5.28 21.948"/>
</g>
</svg>
<text fill="#1a171b" font-family="Iosevka,Inter,sans-serif" font-weight="700" font-size="14" x="27" y="20">
Support Holllo via LiberaPay
</text>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,220 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The Love Color Scheme</title>
<link href="css/style.css" rel="stylesheet">
</head>
<body>
<div id="wrapper">
<h1>Love</h1>
<section class="goals">
<h2 class="light">Goals</h2>
<div class="goal">
<h3 class="goal-title">
<a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast">
Minimum AAA color contrast ratio.
</a>
</h3>
<p>
Don't worry about picking colors that pair well and are legible. Any combination
as used on this page have a contrast ratio of 7 to 1 or better.
</p>
</div>
<div class="goal light">
<h3 class="goal-title">
<a href="#variants">Dark and light variants.</a>
</h3>
<p>
Only you see the world through your eyes, decide for yourself whether you like
it dark or light. Or both.
</p>
</div>
<div class="goal">
<h3 class="goal-title">
<a href="https://gitlab.com/holllo/love">Free and open-source.</a>
</h3>
<p>
Open-sourced with the MIT License, because everyone deserves love.
</p>
</div>
<div class="goal light">
<h3 class="goal-title">
<a href="#get">Broad integration.</a>
</h3>
<p>
Get Love wherever you like.
</p>
</div>
</section>
<div class="divider"></div>
<section id="samples" class="cupcake-ipsum">
<h2 class="light">Samples</h2>
<p class="border">
Cupcake ipsum dolor sit amet powder. Chocolate jujubes cookie chocolate cake I
love cake. Jujubes I love chocolate bar dessert cake candy canes macaroon. Wafer
oat cake dessert donut. Ice cream wafer lollipop cake. Chocolate jelly-o caramels
dragée gummies powder donut chocolate cake I love. Caramels cake chocolate cake
dessert liquorice I love gummi bears. I love pudding lemon drops icing liquorice.
Gummies cookie cake bonbon marshmallow lollipop lemon drops.
</p>
<p class="light">
Caramels dragée apple pie topping. Apple pie jelly beans I love chupa chups
cheesecake I love jelly beans. Gummies marzipan sesame snaps wafer brownie pie
dragée cake. Macaroon fruitcake dragée sugar plum muffin caramels. Jelly beans
gingerbread jelly beans dessert sugar plum candy sweet roll. Biscuit tiramisu I
love gummi bears chocolate bar chocolate. Powder chocolate cake toffee bear claw
danish lemon drops cake.
</p>
</section>
<div class="spacer"></div>
{% for variant in love %}
<section class="{{ variant.name }}-labels">
{% for accent in variant.colors.accents %}
<span title="{{ accent.toUpperCase() }}">LOVE</span>
{% endfor %}
</section>
{% endfor %}
<div class="spacer"></div>
{% for variant in love %}
<section class="{{ variant.name }}-outline-labels">
{% for accent in variant.colors.accents %}
<span title="{{ accent.toUpperCase() }}">LOVE</span>
{% endfor %}
</section>
{% endfor %}
<div class="spacer"></div>
{% for variant in love %}
<section class="{{ variant.name }}-rainbow {{ 'light' if variant.name == 'light' else 'border' }}">
<p></p>
</section>
{% endfor %}
<div class="divider"></div>
<section id="variants">
<h2 class="light">Variants</h2>
{% for variant in love %}
<div id="{{ variant.name }}">
<h3>{{ variant.name|capitalize }}</h3>
<p class="foreground-primary">
Foreground Primary <span class="color">{{ variant.colors.foreground1 }}</span>
</p>
<p class="foreground-secondary">
Foreground Secondary <span class="color">{{ variant.colors.foreground2 }}</span>
</p>
<p class="background-primary">
Background Primary <span class="color">{{ variant.colors.background1 }}</span>
</p>
<p class="background-secondary">
Background Secondary <span class="color">{{ variant.colors.background2 }}</span>
</p>
{% for accent in variant.colors.accents %}
<p class="accent-{{ loop.index }}">
Accent {{ loop.index }} <span class="color">{{ accent }}</span>
</p>
{% endfor %}
{% for gray in variant.colors.grays %}
<p class="gray-{{ loop.index }}">
Gray {{ loop.index }} <span class="color">{{ gray }}</span>
</p>
{% endfor %}
</div>
{% endfor %}
</section>
<div class="divider"></div>
<section id="get">
<h2 class="light">
Integrations
</h2>
<div class="border">
<p>
Love isn't widely available yet, but you can help change that.
Suggest file formats, software, websites and anything else you know of where
color customization is possible, and we'll spread the love together.
</p>
<p>
Your suggestions are welcome at Love's
<a href="https://gitlab.com/holllo/love/issues">issue tracker</a>
and through email at
<a href="mailto:love@holllo.cc">love@holllo.cc</a>.
</p>
</div>
<div class="light">
<h3>
File Formats
</h3>
<ul>
<li>
<a href="love.json">JSON</a>
</li>
</ul>
</div>
<div class="border">
<h3>
Software
</h3>
<ul>
<li>
Atom<sup>*</sup>
</li>
<li>
Firefox Color
<a href="https://color.firefox.com/?theme=XQAAAAIYAQAAAAAAAABBqYhm849SCia2CaaEGccwS-xNKlhSXT3Vtt2XDAs6h7gdL5pcAb7xqXopx66Ln4wY2B4_apm1Xo1m-kSLNybjC15LIb4OXWhGfyPJrZA2e0IeJeWC0yox2SBMD04SrZBvZwoC8QX9EBbJd69TMCmh7d-g0Wc_msdR2nzvnbFECN4_c5VKI9Btzbzvdvjw1-KH_nfezJDCoRea7HASdSJBgMVdHiWfmWiLujatKOWmCJfGaFyV_75SjmA">Dark</a>
{{- '/' -}}
<a href="https://color.firefox.com/?theme=XQAAAAIqAQAAAAAAAABBqYhm849SCia2CaaEGccwS-xNKliFvSp4LiFpmRcA5AwYsIABKiGtHcakOiV8NSmxjnVR9H4TYg2VNxSp6iDrgcvBoo3NoFSZSndEX6ZHCH8h1ahP78I4dZXjJD8ZzlOxqC6HrDKQmTBAEm09iix8uVI5_QcbhtDjDxpYbPP5WGvXu84Za9H0s1VXwrgKdxIgKTJraGh0P5bPsWJ_YY-lPSsAB62ABnbOV7SJEIMsWMC9a01QhpCubrrA-f_WNVAA">Light</a>
</li>
<li>
Sublime Text<sup>*</sup>
</li>
<li>
Visual Studio Code<sup>*</sup>
</li>
</ul>
</div>
<div class="light">
<p>
<small>* indicates planned but not yet available.</small>
</p>
</div>
</section>
<div class="divider"></div>
<section id="attributions">
<h2 class="light">Attributions</h2>
<div class="border">
<h3>
<a href="https://rsms.me/inter/">Inter</a>
</h3>
<p>Excellent OFL 1.1 licensed sans-serif font.</p>
</div>
<div class="light monospace">
<h3>
<a href="https://github.com/i-tu/Hasklig/">Hasklig</a>
</h3>
<p>OFL 1.1 licensed monospace font with ligatures.</p>
</div>
<div class="border">
<h3>
<a href="https://www.hsluv.org/">HSLuv</a>
</h3>
<p>Human-friendly HSL alternative, without it Love wouldn't exist.</p>
</div>
</section>
<div class="spacer"></div>
<footer>
<div>
<a class="hide-external" href="https://holllo.cc">
<img src="images/holllo-mark.png" alt="Made by Holllo">
</a>
</div>
<div>
<a id="liberapay-button" class="hide-external" href="https://liberapay.com/Holllo/donate">
<img src="images/liberapay-button.svg" alt="Support Holllo via LiberaPay">
</a>
</div>
</footer>
</div>
</body>
</html>

@ -0,0 +1,263 @@
// Inter
@font-face {
font-family: Inter;
font-style: normal;
font-weight: 100;
font-display: swap;
src:
url('../fonts/Inter/Inter-Thin-BETA.woff2') format('woff2'),
url('../fonts/Inter/Inter-Thin-BETA.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: italic;
font-weight: 100;
font-display: swap;
src:
url('../fonts/Inter/Inter-ThinItalic-BETA.woff2') format('woff2'),
url('../fonts/Inter/Inter-ThinItalic-BETA.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: normal;
font-weight: 200;
font-display: swap;
src:
url('../fonts/Inter/Inter-ExtraLight-BETA.woff2') format('woff2'),
url('../fonts/Inter/Inter-ExtraLight-BETA.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: italic;
font-weight: 200;
font-display: swap;
src:
url('../fonts/Inter/Inter-ExtraLightItalic-BETA.woff2') format('woff2'),
url('../fonts/Inter/Inter-ExtraLightItalic-BETA.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: normal;
font-weight: 300;
font-display: swap;
src:
url('../fonts/Inter/Inter-Light-BETA.woff2') format('woff2'),
url('../fonts/Inter/Inter-Light-BETA.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: italic;
font-weight: 300;
font-display: swap;
src:
url('../fonts/Inter/Inter-LightItalic-BETA.woff2') format('woff2'),
url('../fonts/Inter/Inter-LightItalic-BETA.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: normal;
font-weight: normal;
font-display: swap;
src:
url('../fonts/Inter/Inter-Regular.woff2') format('woff2'),
url('../fonts/Inter/Inter-Regular.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: italic;
font-weight: normal;
font-display: swap;
src:
url('../fonts/Inter/Inter-Italic.woff2') format('woff2'),
url('../fonts/Inter/Inter-Italic.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: normal;
font-weight: 500;
font-display: swap;
src:
url('../fonts/Inter/Inter-Medium.woff2') format('woff2'),
url('../fonts/Inter/Inter-Medium.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: italic;
font-weight: 500;
font-display: swap;
src:
url('../fonts/Inter/Inter-MediumItalic.woff2') format('woff2'),
url('../fonts/Inter/Inter-MediumItalic.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: normal;
font-weight: 600;
font-display: swap;
src:
url('../fonts/Inter/Inter-SemiBold.woff2') format('woff2'),
url('../fonts/Inter/Inter-SemiBold.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: italic;
font-weight: 600;
font-display: swap;
src:
url('../fonts/Inter/Inter-SemiBoldItalic.woff2') format('woff2'),
url('../fonts/Inter/Inter-SemiBoldItalic.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: normal;
font-weight: bold;
font-display: swap;
src:
url('../fonts/Inter/Inter-Bold.woff2') format('woff2'),
url('../fonts/Inter/Inter-Bold.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: italic;
font-weight: bold;
font-display: swap;
src:
url('../fonts/Inter/Inter-BoldItalic.woff2') format('woff2'),
url('../fonts/Inter/Inter-BoldItalic.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: normal;
font-weight: 800;
font-display: swap;
src:
url('../fonts/Inter/Inter-ExtraBold.woff2') format('woff2'),
url('../fonts/Inter/Inter-ExtraBold.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: italic;
font-weight: 800;
font-display: swap;
src:
url('../fonts/Inter/Inter-ExtraBoldItalic.woff2') format('woff2'),
url('../fonts/Inter/Inter-ExtraBoldItalic.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: normal;
font-weight: 900;
font-display: swap;
src:
url('../fonts/Inter/Inter-Black.woff2') format('woff2'),
url('../fonts/Inter/Inter-Black.woff') format('woff');
}
@font-face {
font-family: Inter;
font-style: italic;
font-weight: 900;
font-display: swap;
src:
url('../fonts/Inter/Inter-BlackItalic.woff2') format('woff2'),
url('../fonts/Inter/Inter-BlackItalic.woff') format('woff');
}
// Hasklig
@font-face {
font-family: Hasklig;
font-style: normal;
font-weight: 200;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-ExtraLight.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: italic;
font-weight: 200;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-ExtraLightIt.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: normal;
font-weight: 300;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-Light.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: italic;
font-weight: 300;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-LightIt.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: normal;
font-weight: normal;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-Regular.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: italic;
font-weight: normal;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-It.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: normal;
font-weight: 500;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-Medium.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: italic;
font-weight: 500;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-MediumIt.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: normal;
font-weight: 600;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-SemiBold.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: italic;
font-weight: 600;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-SemiBoldIt.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: normal;
font-weight: bold;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-Bold.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: italic;
font-weight: bold;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-BoldIt.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: normal;
font-weight: 900;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-Black.otf') format('opentype');
}
@font-face {
font-family: Hasklig;
font-style: italic;
font-weight: 900;
font-display: swap;
src: url('../fonts/Hasklig/Hasklig-BlackIt.otf') format('opentype');
}

@ -0,0 +1,413 @@
@import '../../../node_modules/modern-normalize/modern-normalize';
@import '../../../node_modules/hsluv-sass/src/hsluv';
@import 'fonts';
/* :root-insert */
$small-breakpoint: 600px;
$medium-breakpoint: 900px;
$large-breakpoint: 1200px;
$extra-large-breakpoint: 1800px;
html {
font-size: 62.5%;
}
body {
background-color: var(--background-1);
color: var(--foreground-1);
font-family: Inter, sans-serif;
font-size: 2rem;
}
a,
a:visited {
color: var(--dark-accent-7);
&:hover {
color: var(--dark-accent-4);
}
&[href^='http']:not(.hide-external) {
margin-right: 12px;
&::after {
content: '';
font-size: 1.5rem;
position: absolute;
}
}
}
h1 {
padding: 16px;
}
h1,
h2,
h3,
p {
margin: 0;
}
ol,
ul {
margin: 0;
padding-left: 32px;
}
section {
background-color: var(--background-1);
}
ul {
list-style-type: symbols(cyclic '' '');
}
#wrapper {
margin: 0 16px;
}
@media (min-width: $medium-breakpoint) {
#wrapper {
margin: 0 auto;
width: $medium-breakpoint;
}
}
.light {
background-color: var(--foreground-1);
color: var(--background-1);
a,
a:visited {
color: var(--light-accent-8);
&:hover {
color: var(--light-accent-10);
}
}
}
.border {
border: 2px solid var(--foreground-1);
}
.divider {
border-top: 2px solid var(--foreground-1);
margin: 32px 0;
}
.monospace {
font-family: Hasklig, monospace;
}
.spacer {
margin-bottom: 32px;
}
.goals {
border: 2px solid;
h2 {
padding: 16px;
}
}
.goal {
padding: 16px;
&:nth-child(even) {
background-color: var(--background-1);
color: var(--foreground-1);
}
&:nth-child(odd) {
background-color: var(--foreground-1);
color: var(--background-1);
}
}
.goal-title {
display: block;
padding-bottom: 8px;
}
.cupcake-ipsum {
h2 {
background-color: var(--foreground-1);
color: var(--background-1);
padding: 16px;
}
p {
padding: 16px;
}
}
.dark-labels,
.light-labels,
.dark-outline-labels,
.light-outline-labels {
display: flex;
justify-content: space-between;
padding: 16px;
overflow-x: auto;
span {
font-family: Hasklig, monospace;
font-weight: bold;
margin-right: 8px;
padding: 8px;
text-align: center;
width: 100px;
&:last-child {
margin-right: 0;
}
}
}
.dark-labels {
border: 2px solid var(--foreground-1);
color: var(--background-1);
@for $index from 1 through 10 {
span:nth-child(#{$index}) {
background-color: var(--dark-accent-#{$index});
}
}
}
.light-labels {
background-color: var(--foreground-1);
@for $index from 1 through 10 {
span:nth-child(#{$index}) {
background-color: var(--light-accent-#{$index});
}
}
}
.dark-outline-labels {
border: 2px solid;
@for $index from 1 through 10 {
span:nth-child(#{$index}) {
$color: var(--dark-accent-#{$index});
border: 2px solid $color;
box-shadow: 0 0 2px $color, inset 0 0 2px $color;
color: $color;
text-shadow: 0 0 2px $color;
}
}
}
.light-outline-labels {
background-color: var(--foreground-1);
@for $index from 1 through 10 {
span:nth-child(#{$index}) {
$color: var(--light-accent-#{$index});
border: 2px solid $color;
box-shadow: 0 0 2px $color, inset 0 0 2px $color;
color: $color;
text-shadow: 0 0 2px $color;
}
}
}
.color {
font-family: Hasklig, monospace;
font-weight: bold;
}
.dark-rainbow,
.light-rainbow {
padding: 16px;
text-align: center;
p {
padding: 16px 0;
}
}
.dark-rainbow p {
background: linear-gradient(to right, var(--dark-accent-1), var(--dark-accent-2), var(--dark-accent-3), var(--dark-accent-4), var(--dark-accent-5), var(--dark-accent-6), var(--dark-accent-7), var(--dark-accent-8), var(--dark-accent-9), var(--dark-accent-10));
color: var(--background-1);
}
.light-rainbow p {
background: linear-gradient(to right, var(--light-accent-1), var(--light-accent-2), var(--light-accent-3), var(--light-accent-4), var(--light-accent-5), var(--light-accent-6), var(--light-accent-7), var(--light-accent-8), var(--light-accent-9), var(--light-accent-10));
color: var(--foreground-1);
}
#variants {
h2 {
padding: 16px;
}
}
#dark,
#light {
padding: 16px;
h3 {
margin-bottom: 16px;
}
p {
display: flex;
margin-bottom: 2px;
padding: 8px;
&:last-child {
margin-bottom: 0;
}
.color {
margin-left: auto;
}
}
}
#dark {
border: 2px solid var(--foreground-1);
.foreground-primary {
background-color: var(--foreground-1);
color: var(--background-1);
}
.foreground-secondary {
background-color: var(--foreground-2);
color: var(--background-1);
}
.background-primary {
background-color: var(--background-1);
color: var(--foreground-1);
}
.background-secondary {
background-color: var(--background-2);
color: var(--foreground-1);
}
@for $index from 1 through 10 {
.accent-#{$index} {
background-color: var(--dark-accent-#{$index});
color: var(--background-1);
}
}
@for $index from 1 through 3 {
.gray-#{$index} {
background-color: var(--dark-gray-#{$index});
color: var(--background-1);
}
}
}
#light {
background-color: var(--foreground-1);
color: var(--background-1);
.foreground-primary {
background-color: var(--background-1);
color: var(--foreground-1);
}
.foreground-secondary {
background-color: var(--background-2);
color: var(--foreground-1);
}
.background-primary {
background-color: var(--foreground-1);
color: var(--background-1);
}
.background-secondary {
background-color: var(--foreground-2);
color: var(--background-1);
}
@for $index from 1 through 10 {
.accent-#{$index} {
background-color: var(--light-accent-#{$index});
color: var(--foreground-1);
}
}
@for $index from 1 through 4 {
.gray-#{$index} {
background-color: var(--light-gray-#{$index});
color: var(--foreground-1);
}
}
}
footer {
display: flex;
flex-direction: column;
margin-bottom: 32px;
> div {
display: flex;
justify-content: center;
&:first-of-type {
align-items: center;
margin-bottom: 8px;
a {
align-items: center;
color: var(--foreground-1);
display: flex;
text-decoration: none;
&:hover {
color: var(--foreground-1);
}
}
img {
height: 29px;
}
}
}
}
#get {
h2 {
padding: 16px;
}
h3 {
margin-bottom: 16px;
}
> div {
padding: 16px;
}
}
#attributions {
h2 {
padding: 16px;
}
h3 {
margin-bottom: 8px;
}
> div {
padding: 16px;
}
}
#liberapay-button {
display: flex;
line-height: 0;
}

@ -0,0 +1,68 @@
import {hsluvToHex as hsluv} from 'hsluv';
export interface LoveVariant {
name: string;
colors: {
foreground1: string;
foreground2: string;
background1: string;
background2: string;
accents: string[];
grays: string[];
};
}
export function generateLove(): LoveVariant[] {
// Create Love with its 2 variants.
const love: LoveVariant[] = [
{
name: 'dark',
colors: {
foreground1: hsluv([275, 100, 95]).toUpperCase(),
foreground2: hsluv([275, 100, 90]).toUpperCase(),
background1: hsluv([275, 40, 10]).toUpperCase(),
background2: hsluv([275, 40, 15]).toUpperCase(),
accents: [],
grays: []
}
},
{
name: 'light',
colors: {
foreground1: hsluv([275, 40, 10]).toUpperCase(),
foreground2: hsluv([275, 40, 15]).toUpperCase(),
background1: hsluv([275, 100, 95]).toUpperCase(),
background2: hsluv([275, 100, 90]).toUpperCase(),
accents: [],
grays: []
}
}
];
// Generate the accent and gray colors.
const accentCount = 10;
const grayCount = 3;
for (let index = 0; index < accentCount; index++) {
// Dark accents.
love[0].colors.accents.push(
hsluv([index * (360 / accentCount), 90, 75]).toUpperCase()
);
// Light accents.
love[1].colors.accents.push(
hsluv([index * (360 / accentCount), 90, 30]).toUpperCase()
);
if (index < grayCount) {
// Dark grays.
love[0].colors.grays.push(
hsluv([0, 0, 100 - (index + 1) * 10]).toUpperCase()
);
// Light grays.
love[1].colors.grays.push(hsluv([0, 0, (index + 1) * 10]).toUpperCase());
}
}
return love;
}

@ -0,0 +1,88 @@
import {promises as fsp} from 'fs';
import {join} from 'path';
// @ts-ignore
import htmlclean from 'htmlclean';
import nunjucks from 'nunjucks';
import sass from 'sass';
import tar from 'tar';
import {generateLove, LoveVariant} from './love';
export async function entry(): Promise<void> {
// Create all required directories for the website.
await fsp.mkdir(join(__dirname, '../../public/css/'), {recursive: true});
await fsp.mkdir(join(__dirname, '../../public/fonts/'), {recursive: true});
await fsp.mkdir(join(__dirname, '../../public/images/'), {recursive: true});
// Configure Nunjucks to use the templates for `source/pages/`.
nunjucks.configure(join(__dirname, '../pages/'), {
lstripBlocks: true,
trimBlocks: true,
throwOnUndefined: true
});
const love: LoveVariant[] = generateLove();
// Write the colors to file.
await writeJSON(join(__dirname, '../../public/love.json'), love);
// Render the Sass to CSS.
let css: string = sass
.renderSync({
file: join(__dirname, '../pages/scss/style.scss'),
sourceMap: false
})
.css.toString();
// Generate the CSS custom properties.
const cssProperties = `:root {
--foreground-1: ${love[0].colors.foreground1};
--foreground-2: ${love[0].colors.foreground2};
--background-1: ${love[0].colors.background1};
--background-2: ${love[0].colors.background2};
${love[0].colors.accents
.map((value, index) => ` --dark-accent-${index + 1}: ${value};`)
.join('\n')}
${love[0].colors.grays
.map((value, index) => ` --dark-gray-${index + 1}: ${value};`)
.join('\n')}
${love[1].colors.accents
.map((value, index) => ` --light-accent-${index + 1}: ${value};`)
.join('\n')}
${love[1].colors.grays
.map((value, index) => ` --light-gray-${index + 1}: ${value};`)
.join('\n')}
}\n`;
// Replace the predefined `:root` location with our properties.
css = css.replace(/\/\* :root-insert \*\//, cssProperties);
// Write the CSS to file.
await fsp.writeFile(join(__dirname, '../../public/css/style.css'), css);
// Render and write the `index.html` file.
await fsp.writeFile(
join(__dirname, '../../public/index.html'),
htmlclean(nunjucks.render('index.html', {love}))
);
// Extract the fonts to file.
await tar.extract({
file: join(__dirname, '../pages/assets/Inter.tar'),
cwd: join(__dirname, '../../public/fonts/')
});
await tar.extract({
file: join(__dirname, '../pages/assets/Hasklig.tar'),
cwd: join(__dirname, '../../public/fonts/')
});
console.log('Lovely!');
}
// Utility helper function to write some data to file as JSON.
export async function writeJSON(path: string, data: unknown): Promise<void> {
await fsp.writeFile(path, JSON.stringify(data, null, 2));
}
if (require.main === module) {
entry();
}

@ -0,0 +1,16 @@
{
"compilerOptions": {
"declaration": true,
"esModuleInterop": true,
"module": "commonjs",
"outDir": "build/",
"strict": true,
"target": "es6"
},
"include": [
"source/**/*.ts"
],
"exclude": [
"node_modules"
]
}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save