Browse Source

Initial commit. ♥

tags/0.1.0
Bauke 8 months ago
commit
8d94dd95c6
Signed by: Bauke <me@bauke.xyz> GPG Key ID: C1C0F29952BCF558
16 changed files with 6680 additions and 0 deletions
  1. +108
    -0
      .gitignore
  2. +26
    -0
      .gitlab-ci.yml
  3. +7
    -0
      License
  4. +17
    -0
      ReadMe.md
  5. +52
    -0
      package.json
  6. BIN
      source/pages/assets/Hasklig.tar
  7. BIN
      source/pages/assets/Inter.tar
  8. BIN
      source/pages/images/holllo-mark.png
  9. +12
    -0
      source/pages/images/liberapay-button.svg
  10. +220
    -0
      source/pages/index.html
  11. +263
    -0
      source/pages/scss/_fonts.scss
  12. +413
    -0
      source/pages/scss/style.scss
  13. +68
    -0
      source/scripts/love.ts
  14. +88
    -0
      source/scripts/pages.ts
  15. +16
    -0
      tsconfig.json
  16. +5390
    -0
      yarn.lock

+ 108
- 0
.gitignore View File

@@ -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/

+ 26
- 0
.gitlab-ci.yml View File

@@ -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

+ 7
- 0
License View File

@@ -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.

+ 17
- 0
ReadMe.md View File

@@ -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).

+ 52
- 0
package.json View File

@@ -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
}
}

BIN
source/pages/assets/Hasklig.tar View File


BIN
source/pages/assets/Inter.tar View File


BIN
source/pages/images/holllo-mark.png View File

Before After
Width: 590  |  Height: 344  |  Size: 2.0 KiB

+ 12
- 0
source/pages/images/liberapay-button.svg View File

@@ -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>

+ 220
- 0
source/pages/index.html View File

@@ -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>

+ 263
- 0
source/pages/scss/_fonts.scss View File

@@ -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');
}

+ 413
- 0
source/pages/scss/style.scss View File

@@ -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;
}

+ 68
- 0
source/scripts/love.ts View File

@@ -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;
}

+ 88
- 0
source/scripts/pages.ts View File

@@ -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();
}

+ 16
- 0
tsconfig.json View File

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

+ 5390
- 0
yarn.lock
File diff suppressed because it is too large
View File


Loading…
Cancel
Save