rerun prettier

This commit is contained in:
Eigil Nikolajsen 2023-06-02 16:27:29 +02:00
parent cb3973b1f0
commit 6e5fa43fb1
38 changed files with 6765 additions and 6694 deletions

View File

@ -1,6 +1,5 @@
{
"printWidth": 120,
"tabs": 4,
"useTabs": true,
"semi": false
"printWidth": 120,
"tabWidth": 2,
"semi": false
}

60
calt.js
View File

@ -2,48 +2,48 @@ const fs = require("fs")
const readline = require("readline")
function pbcopy(data) {
var proc = require("child_process").spawn("pbcopy")
proc.stdin.write(data)
proc.stdin.end()
var proc = require("child_process").spawn("pbcopy")
proc.stdin.write(data)
proc.stdin.end()
}
async function featuresToCalt() {
const features = ["ss01_arrows", "ss02_less_equal", "ss03_case", "ss04_ellipsis", "ss05_smartkerning"]
const features = ["ss01_arrows", "ss02_less_equal", "ss03_case", "ss04_ellipsis", "ss05_smartkerning"]
let calt = []
let calt = []
for await (const feature of features) {
const fileStream = fs.createReadStream(`features/${feature}.fea`)
for await (const feature of features) {
const fileStream = fs.createReadStream(`features/${feature}.fea`)
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity,
})
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity,
})
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
const lines = []
const lines = []
lines.push(`### feature ${feature} ###`)
lines.push(`### feature ${feature} ###`)
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
// console.log(`Line from file: ${line}`)
lines.push(line)
}
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
// console.log(`Line from file: ${line}`)
lines.push(line)
}
calt.push(lines)
}
calt.push(lines)
}
calt = calt.flat().filter((ln) => !ln.includes("feature") && !ln.includes("} ss"))
calt = calt.map((ln) => {
if (ln.includes("lookup")) return ln.split("lookup ").join("lookup _")
if (ln.includes("} ")) return ln.split("} ").join("} _")
return ln
})
calt = calt.flat().filter((ln) => !ln.includes("feature") && !ln.includes("} ss"))
calt = calt.map((ln) => {
if (ln.includes("lookup")) return ln.split("lookup ").join("lookup _")
if (ln.includes("} ")) return ln.split("} ").join("} _")
return ln
})
// calt.forEach((ln) => console.log(ln))
pbcopy(`
// calt.forEach((ln) => console.log(ln))
pbcopy(`
feature calt {
# Contextual Alternates
# Contains all 'cxxx' features

View File

@ -1,30 +1,30 @@
<!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" />
<title>Generate Axis Value</title>
</head>
<body>
<br />
<label for="classes">Classes</label>
<br />
<br />
<textarea id="classes" name="classes" rows="20" cols="60"></textarea>
<br />
<br />
<button type="submit" id="submit">Submit</button>
<br />
<br />
<p style="user-select: all" id="result"></p>
<script>
const classes = document.querySelector("#classes")
const result = document.querySelector("#result")
const submit = document.querySelector("#submit")
submit.addEventListener("click", () => {
result.textContent = [...new Set(classes.value.split(" "))].join(" ")
})
</script>
</body>
<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" />
<title>Generate Axis Value</title>
</head>
<body>
<br />
<label for="classes">Classes</label>
<br />
<br />
<textarea id="classes" name="classes" rows="20" cols="60"></textarea>
<br />
<br />
<button type="submit" id="submit">Submit</button>
<br />
<br />
<p style="user-select: all" id="result"></p>
<script>
const classes = document.querySelector("#classes")
const result = document.querySelector("#result")
const submit = document.querySelector("#submit")
submit.addEventListener("click", () => {
result.textContent = [...new Set(classes.value.split(" "))].join(" ")
})
</script>
</body>
</html>

22
f.js
View File

@ -6,10 +6,10 @@
// @c3_3 = [exclam.c3_3 comma.c3_3 period.c3_3 slash.c3_3 colon.c3_3 semicolon.c3_3 question.c3_3 backslash.c3_3 bar.c3_3];
const input =
"exclam exclam.square comma period period.square slash slash.case colon colon.square colon.case colon.case.square semicolon semicolon.square semicolon.case semicolon.case.square question question.square backslash backslash.case bar bar.case less less.case greater greater.case asterisk asterisk.case plus plus.case hyphen hyphen.case equal equal.case asciitilde asciitilde.case"
"exclam exclam.square comma period period.square slash slash.case colon colon.square colon.case colon.case.square semicolon semicolon.square semicolon.case semicolon.case.square question question.square backslash backslash.case bar bar.case less less.case greater greater.case asterisk asterisk.case plus plus.case hyphen hyphen.case equal equal.case asciitilde asciitilde.case"
function c002(input) {
const s = input.split(" ")
return `
const s = input.split(" ")
return `
@dflt = [${input}];
@c2_1 = [${s.join(".c2_1 ")}.c2_1];
@c2_2 = [${s.join(".c2_2 ")}.c2_2];
@ -19,20 +19,20 @@ function c002(input) {
}
function classExcess(c) {
return [...new Set(c.split(" "))].join(" ")
return [...new Set(c.split(" "))].join(" ")
}
function buildGlyphs(g) {
return g
.split(", ")
.map((gl) => gl.split("=")[0])
.join(", ")
return g
.split(", ")
.map((gl) => gl.split("=")[0])
.join(", ")
}
function pbcopy(data) {
var proc = require("child_process").spawn("pbcopy")
proc.stdin.write(data)
proc.stdin.end()
var proc = require("child_process").spawn("pbcopy")
proc.stdin.write(data)
proc.stdin.end()
}
pbcopy(c002(input))

1136
index.html

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +1,53 @@
<!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" />
<title>Generate Axis Value</title>
<style>
#resultButton {
user-select: all;
}
</style>
</head>
<body>
<label for="start">Start value</label>
<input type="text" name="start" id="start" />
<br />
<br />
<label for="end">End value</label>
<input type="text" name="end" id="end" />
<br />
<br />
<label for="precision">Precision</label>
<input type="text" name="precision" id="precision" />
<br />
<br />
<button type="submit" id="submit">Submit</button>
<br />
<br />
<p id="resultButton"></p>
<script>
const submit = document.querySelector("#submit")
const start = document.querySelector("#start")
const end = document.querySelector("#end")
const precision = document.querySelector("#precision")
const resultButton = document.querySelector("#resultButton")
submit.addEventListener("click", () => {
const result = generateAxisValue([+start.value, +end.value], +precision.value)
resultButton.textContent = result
navigator.clipboard.writeText(result)
})
const generateAxisValue = ([start, end], precision) => {
let value = start
let result = ""
while (value <= end) {
result += `"${value}"=${value}, `
value += precision
}
return result.slice(0, -2)
}
</script>
</body>
<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" />
<title>Generate Axis Value</title>
<style>
#resultButton {
user-select: all;
}
</style>
</head>
<body>
<label for="start">Start value</label>
<input type="text" name="start" id="start" />
<br />
<br />
<label for="end">End value</label>
<input type="text" name="end" id="end" />
<br />
<br />
<label for="precision">Precision</label>
<input type="text" name="precision" id="precision" />
<br />
<br />
<button type="submit" id="submit">Submit</button>
<br />
<br />
<p id="resultButton"></p>
<script>
const submit = document.querySelector("#submit")
const start = document.querySelector("#start")
const end = document.querySelector("#end")
const precision = document.querySelector("#precision")
const resultButton = document.querySelector("#resultButton")
submit.addEventListener("click", () => {
const result = generateAxisValue([+start.value, +end.value], +precision.value)
resultButton.textContent = result
navigator.clipboard.writeText(result)
})
const generateAxisValue = ([start, end], precision) => {
let value = start
let result = ""
while (value <= end) {
result += `"${value}"=${value}, `
value += precision
}
return result.slice(0, -2)
}
</script>
</body>
</html>

View File

@ -1,27 +1,27 @@
<!DOCTYPE html>
<html>
<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" />
<style>
@font-face {
font-family: "CommitMono";
src: url("/fonts/CommitMono.woff2");
font-weight: 450;
}
:root {
--grey: #aaa;
}
button#grey::before {
content: "01";
font-style: italic;
font-size: 2rem;
color: var(--grey);
}
</style>
</head>
<body>
<button id="grey">Commit Mono</button>
</body>
<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" />
<style>
@font-face {
font-family: "CommitMono";
src: url("/fonts/CommitMono.woff2");
font-weight: 450;
}
:root {
--grey: #aaa;
}
button#grey::before {
content: "01";
font-style: italic;
font-size: 2rem;
color: var(--grey);
}
</style>
</head>
<body>
<button id="grey">Commit Mono</button>
</body>
</html>

View File

@ -6,53 +6,53 @@
*/
function lcs(arr1, arr2) {
let matrix = [...Array(arr1.length + 1)].fill(0).map(() => Array(arr2.length + 1).fill(0))
let matrix = [...Array(arr1.length + 1)].fill(0).map(() => Array(arr2.length + 1).fill(0))
for (let rowIndex = 1; rowIndex <= arr1.length; rowIndex++) {
for (let columnIndex = 1; columnIndex <= arr2.length; columnIndex++) {
if (arr1[rowIndex - 1] === arr2[columnIndex - 1]) {
matrix[rowIndex][columnIndex] = 1 + matrix[rowIndex - 1][columnIndex - 1]
} else {
matrix[rowIndex][columnIndex] = Math.max(matrix[rowIndex - 1][columnIndex], matrix[rowIndex][columnIndex - 1])
}
}
}
//If there is no match, printing empty string
if (matrix[arr1.length][arr2.index] === 0) {
console.log("")
return
}
for (let rowIndex = 1; rowIndex <= arr1.length; rowIndex++) {
for (let columnIndex = 1; columnIndex <= arr2.length; columnIndex++) {
if (arr1[rowIndex - 1] === arr2[columnIndex - 1]) {
matrix[rowIndex][columnIndex] = 1 + matrix[rowIndex - 1][columnIndex - 1]
} else {
matrix[rowIndex][columnIndex] = Math.max(matrix[rowIndex - 1][columnIndex], matrix[rowIndex][columnIndex - 1])
}
}
}
//If there is no match, printing empty string
if (matrix[arr1.length][arr2.index] === 0) {
console.log("")
return
}
let result = []
let rowIndex = arr1.length
let columnIndex = arr2.length
let result = []
let rowIndex = arr1.length
let columnIndex = arr2.length
while (rowIndex > 0 && columnIndex > 0) {
if (arr1[rowIndex - 1] === arr2[columnIndex - 1]) {
//Prepending everytime a new character is matched in both strings
result.unshift(arr1[rowIndex - 1])
rowIndex--
columnIndex--
} else if (matrix[rowIndex - 1][columnIndex] === matrix[rowIndex][columnIndex]) {
rowIndex--
} else {
columnIndex--
}
}
//Converting the LCS array into a comma separated string
console.log(result.join(", "))
while (rowIndex > 0 && columnIndex > 0) {
if (arr1[rowIndex - 1] === arr2[columnIndex - 1]) {
//Prepending everytime a new character is matched in both strings
result.unshift(arr1[rowIndex - 1])
rowIndex--
columnIndex--
} else if (matrix[rowIndex - 1][columnIndex] === matrix[rowIndex][columnIndex]) {
rowIndex--
} else {
columnIndex--
}
}
//Converting the LCS array into a comma separated string
console.log(result.join(", "))
}
//Usage Text
const usage = 'Usage: please provide two lists in the format "1, 2, 3, 4, 5"'
if (process.argv.length < 4 || process.argv[2] == "" || process.argv[3] == "") {
console.log(usage)
return
console.log(usage)
return
} else {
const input1 = process.argv[2]
const input2 = process.argv[3]
//Parsing into integers after trimming extra blank spaces
const array1 = input1.split(",").map((x) => parseInt(x.trim(), 10))
const array2 = input2.split(",").map((y) => parseInt(y.trim(), 10))
lcs(array1, array2)
const input1 = process.argv[2]
const input2 = process.argv[3]
//Parsing into integers after trimming extra blank spaces
const array1 = input1.split(",").map((x) => parseInt(x.trim(), 10))
const array2 = input2.split(",").map((y) => parseInt(y.trim(), 10))
lcs(array1, array2)
}

View File

@ -1,22 +1,22 @@
function fibonacci(num: number) {
let n = Number(num)
let elementOne: number = 0
let elementTwo: number = 1
let result: number = 0
let n = Number(num)
let elementOne: number = 0
let elementTwo: number = 1
let result: number = 0
for (let i: number = 1; i <= n; i++) {
result = elementOne + elementTwo
elementOne = elementTwo
elementTwo = result
console.log(`${i}: ${elementOne}`)
}
for (let i: number = 1; i <= n; i++) {
result = elementOne + elementTwo
elementOne = elementTwo
elementTwo = result
console.log(`${i}: ${elementOne}`)
}
}
let num_str = process.argv.length >= 3 ? process.argv[2] : ""
let num: number = parseInt(num_str)
if (isNaN(num)) {
console.log("Usage: please input the count of fibonacci numbers to output")
process.exit(0)
console.log("Usage: please input the count of fibonacci numbers to output")
process.exit(0)
}
fibonacci(num)

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"icons": [
{ "src": "/src/favicon/icon-192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/src/favicon/icon-512.png", "type": "image/png", "sizes": "512x512" }
]
"icons": [
{ "src": "/src/favicon/icon-192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/src/favicon/icon-512.png", "type": "image/png", "sizes": "512x512" }
]
}

1776
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,14 @@
{
"name": "commit-webtests",
"private": true,
"version": "0.0.0",
"type": "commonjs",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^4.1.1"
}
"name": "commit-webtests",
"private": true,
"version": "0.0.0",
"type": "commonjs",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^4.1.1"
}
}

View File

@ -1,24 +1,24 @@
@media (max-width: 50rem) {
body {
overflow: visible;
}
#main_scale,
main {
position: relative;
}
header #keyboard_section {
bottom: auto;
top: 0;
visibility: hidden;
}
#mobile {
visibility: visible;
}
#safari,
#navigate_description {
visibility: hidden;
}
header nav {
position: absolute;
}
body {
overflow: visible;
}
#main_scale,
main {
position: relative;
}
header #keyboard_section {
bottom: auto;
top: 0;
visibility: hidden;
}
#mobile {
visibility: visible;
}
#safari,
#navigate_description {
visibility: hidden;
}
header nav {
position: absolute;
}
}

View File

@ -6,193 +6,193 @@
} */
button {
vertical-align: top;
border: none;
background: transparent;
font-family: inherit;
font-size: 0.75rem;
font-variation-settings: inherit;
line-height: 1rem;
width: max-content;
white-space: nowrap;
text-align: left;
position: relative;
vertical-align: top;
border: none;
background: transparent;
font-family: inherit;
font-size: 0.75rem;
font-variation-settings: inherit;
line-height: 1rem;
width: max-content;
white-space: nowrap;
text-align: left;
position: relative;
}
button:active {
background: repeating-conic-gradient(transparent 0% 25%, var(--text) 0% 50%, var(--text) 0% 100%) 50% / 2px 2px;
background: repeating-conic-gradient(transparent 0% 25%, var(--text) 0% 50%, var(--text) 0% 100%) 50% / 2px 2px;
}
#app_root.no_focus {
opacity: 0.5;
opacity: 0.5;
}
:focus,
input:focus + label {
animation: flicker 60ms 2;
animation: flicker 60ms 2;
}
[contenteditable="true"]:focus {
animation: flicker 200ms 2;
animation: flicker 200ms 2;
}
@keyframes flicker {
0%,
49% {
opacity: 0;
}
50%,
100% {
opacity: 1;
}
0%,
49% {
opacity: 0;
}
50%,
100% {
opacity: 1;
}
}
@keyframes flicker_reverse {
0%,
49% {
opacity: 1;
}
50%,
100% {
opacity: 0;
}
0%,
49% {
opacity: 1;
}
50%,
100% {
opacity: 0;
}
}
.top_container p {
white-space: pre-wrap;
white-space: pre-wrap;
}
.line-through {
text-decoration: line-through;
text-decoration: line-through;
}
h2 {
font-size: 0.75rem;
line-height: 1rem;
font-weight: normal;
width: fit-content;
font-size: 0.75rem;
line-height: 1rem;
font-weight: normal;
width: fit-content;
}
ul {
list-style-type: none;
width: max-content;
list-style-type: none;
width: max-content;
}
ol li::before {
display: none;
display: none;
}
ul li::before {
content: "• ";
position: absolute;
margin-left: -2ch;
content: "• ";
position: absolute;
margin-left: -2ch;
}
ul li:focus::before {
background-color: transparent;
color: var(--text);
background-color: transparent;
color: var(--text);
}
a,
a:visited {
color: var(--text);
color: var(--text);
}
a:focus {
text-decoration: none;
background-color: var(--text);
color: var(--bg);
text-decoration: none;
text-decoration: none;
background-color: var(--text);
color: var(--bg);
text-decoration: none;
}
#safari:focus p:first-of-type {
background-color: var(--text);
color: var(--bg);
background-color: var(--text);
color: var(--bg);
}
#safari {
background-color: var(--bg);
color: var(--text);
width: max-content;
background-color: var(--bg);
color: var(--text);
width: max-content;
}
#safari:focus p,
#safari:focus ul {
opacity: 1;
opacity: 1;
}
#safari:focus a,
#safari a:focus {
opacity: 1;
opacity: 1;
}
#safari:has(*:focus) * {
opacity: 1;
opacity: 1;
}
#safari #safari_not_working:focus {
background-color: var(--text);
color: var(--bg);
opacity: 1;
background-color: var(--text);
color: var(--bg);
opacity: 1;
}
#safari #safari_not_working {
opacity: 0;
opacity: 0;
}
#safari a:focus + #safari_not_working {
visibility: hidden;
visibility: hidden;
}
#nav_form input:checked + label::before {
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
}
#nav_form input:checked + label {
color: var(--text);
color: var(--text);
}
.span_key.pressed_key {
position: relative;
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
position: relative;
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
}
ul:focus .span_key.pressed_key {
background: repeating-conic-gradient(var(--bg) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
background: repeating-conic-gradient(var(--bg) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
}
.span_key.pressed_key::after {
content: " ✓";
position: absolute;
right: -1ch;
top: -0.5rem;
content: " ✓";
position: absolute;
right: -1ch;
top: -0.5rem;
}
#page_animation {
width: 100vw;
height: 100vh;
height: 100dvh;
position: fixed;
top: 0;
left: 0;
z-index: 99;
background-color: var(--bg);
pointer-events: none;
width: 100vw;
height: 100vh;
height: 100dvh;
position: fixed;
top: 0;
left: 0;
z-index: 99;
background-color: var(--bg);
pointer-events: none;
}
#page_animation.page_animation {
animation: 220ms steps(5, jump-start) forwards page_animation;
animation: 220ms steps(5, jump-start) forwards page_animation;
}
@keyframes page_animation {
0% {
transform: translateY(0vh);
}
99.9% {
visibility: visible;
}
100% {
visibility: hidden;
transform: translateY(100vh);
}
0% {
transform: translateY(0vh);
}
99.9% {
visibility: visible;
}
100% {
visibility: hidden;
transform: translateY(100vh);
}
}

View File

@ -1,88 +1,88 @@
#keyboard_container {
font-size: 0.75rem;
display: flex;
width: max-content;
gap: 4ch;
align-items: end;
font-size: 0.75rem;
display: flex;
width: max-content;
gap: 4ch;
align-items: end;
}
.key_group {
display: flex;
flex-direction: column;
display: flex;
flex-direction: column;
}
.keys {
font-size: 0.75rem;
display: flex;
gap: 0.375ch;
margin-bottom: 0.125rem;
font-size: 0.75rem;
display: flex;
gap: 0.375ch;
margin-bottom: 0.125rem;
}
.key {
font-size: 0.75rem;
height: 1.2rem;
border: 0.0625rem solid var(--text);
border-bottom: 0.125rem solid var(--text);
display: grid;
place-content: center;
padding: 0 0.25rem;
user-select: none;
font-size: 0.75rem;
height: 1.2rem;
border: 0.0625rem solid var(--text);
border-bottom: 0.125rem solid var(--text);
display: grid;
place-content: center;
padding: 0 0.25rem;
user-select: none;
}
.key:hover {
cursor: pointer;
cursor: pointer;
}
.key[data-noclick="true"]:hover {
cursor: not-allowed;
cursor: not-allowed;
}
.key.active_key,
.key:active {
background: var(--text);
color: var(--bg);
height: 1.1rem;
margin-top: 0.1rem;
background: var(--text);
color: var(--bg);
height: 1.1rem;
margin-top: 0.1rem;
}
#select_element .key:nth-child(1) {
width: 5rem;
width: 5rem;
}
#escape_textfield .key:nth-child(2) {
letter-spacing: -0.1rem;
text-indent: -0.1rem;
padding: 0.25rem;
letter-spacing: -0.1rem;
text-indent: -0.1rem;
padding: 0.25rem;
}
#safari p,
#safari ul {
background-color: var(--bg);
color: var(--text);
opacity: 0;
background-color: var(--bg);
color: var(--text);
opacity: 0;
}
#safari a {
opacity: 0;
opacity: 0;
}
#safari p:first-of-type {
opacity: 1;
opacity: 1;
}
#tutorial li {
margin-top: 0.3rem;
margin-top: 0.3rem;
}
.span_key {
display: inline;
border: 0.0625rem solid var(--text);
border-bottom: 0.125rem solid var(--text);
padding: 0 calc(0.5ch - 0.0625rem);
margin: 0;
display: inline;
border: 0.0625rem solid var(--text);
border-bottom: 0.125rem solid var(--text);
padding: 0 calc(0.5ch - 0.0625rem);
margin: 0;
}
ul:focus .span_key {
border: 0.0625rem solid var(--bg);
border-bottom: 0.125rem solid var(--bg);
border: 0.0625rem solid var(--bg);
border-bottom: 0.125rem solid var(--bg);
}

View File

@ -1,74 +1,74 @@
table {
margin: 4rem 0 2rem 0;
border-collapse: collapse;
margin: 4rem 0 2rem 0;
border-collapse: collapse;
}
th > div > p,
td > div > p {
/* width: 6rem; */
font-size: 0.5rem;
font-weight: normal;
text-align: center;
/* width: 6rem; */
font-size: 0.5rem;
font-weight: normal;
text-align: center;
}
th > div,
td > div {
width: 6rem;
aspect-ratio: 1 / 1;
display: grid;
justify-content: center;
width: 6rem;
aspect-ratio: 1 / 1;
display: grid;
justify-content: center;
}
tr:first-of-type th > div {
width: 6rem;
aspect-ratio: 3 / 1;
width: 6rem;
aspect-ratio: 3 / 1;
}
td > div > input,
td > div > label,
td > div > p {
grid-row: 1;
grid-column: 1;
display: inline-block;
margin: auto;
white-space: pre;
text-align: center;
line-height: 1.1;
grid-row: 1;
grid-column: 1;
display: inline-block;
margin: auto;
white-space: pre;
text-align: center;
line-height: 1.1;
}
tr th:first-of-type > div {
font-size: 0.5rem;
width: 2rem;
justify-content: start;
font-size: 0.5rem;
width: 2rem;
justify-content: start;
}
tr th:first-of-type > div > p {
font-size: 0.5rem;
text-align: start;
font-size: 0.5rem;
text-align: start;
}
td > div > label {
font-size: 4rem;
font-size: 4rem;
}
#section_2 fieldset {
border: none;
display: block;
border: none;
display: block;
}
#section_2 input {
width: 0;
height: 0;
opacity: 0;
width: 0;
height: 0;
opacity: 0;
}
#section_2 input:focus:checked + label {
background-color: var(--text);
color: var(--bg);
transform: scale(4);
z-index: 2;
background-color: var(--text);
color: var(--bg);
transform: scale(4);
z-index: 2;
}
#section_2 input:checked + label::before {
display: none;
display: none;
}

View File

@ -1,92 +1,92 @@
#familiar_form fieldset {
border: none;
display: flex;
gap: 1rem;
position: relative;
width: fit-content;
border: none;
display: flex;
gap: 1rem;
position: relative;
width: fit-content;
}
#familiar_form fieldset::before {
content: "";
position: absolute;
height: 0.0625rem;
bottom: 0.125rem;
left: 1rem;
right: 1rem;
background-color: var(--text);
content: "";
position: absolute;
height: 0.0625rem;
bottom: 0.125rem;
left: 1rem;
right: 1rem;
background-color: var(--text);
}
#familiar_form fieldset div {
display: flex;
flex-direction: column-reverse;
align-items: center;
gap: 0.5rem;
display: flex;
flex-direction: column-reverse;
align-items: center;
gap: 0.5rem;
}
#familiar_form input[type="radio"] {
-webkit-appearance: none;
appearance: none;
background-color: var(--text);
margin: 0;
-webkit-appearance: none;
appearance: none;
background-color: var(--text);
margin: 0;
color: var(--text);
width: 0.375rem;
height: 0.375rem;
color: var(--text);
width: 0.375rem;
height: 0.375rem;
display: grid;
place-content: center;
display: grid;
place-content: center;
}
#familiar_form input[type="radio"]:checked {
transform: scale(1.5);
transform: scale(1.5);
}
#familiar_form input[type="radio"]:focus {
transform: scale(2);
transform: scale(2);
}
#familiar_form fieldset > div:nth-child(2) {
margin-left: 16rem;
margin-left: 16rem;
}
#familiar_form fieldset > div:nth-child(3) {
margin-left: 15rem;
margin-left: 15rem;
}
#familiar_form fieldset > div:nth-child(5) {
margin-left: 1rem;
margin-left: 1rem;
}
#familiar_container p {
max-width: none;
max-width: none;
}
figure {
width: max-content;
width: max-content;
}
blockquote,
blockquote ~ * {
font-size: 0.75rem;
padding-left: 2ch;
position: relative;
border-left: 0.0625rem solid var(--text);
max-width: var(--max-width);
font-size: 0.75rem;
padding-left: 2ch;
position: relative;
border-left: 0.0625rem solid var(--text);
max-width: var(--max-width);
}
blockquote::before {
content: "“";
left: -0.5ch;
top: 0;
font-size: 1.5rem;
line-height: 2rem;
content: "“";
left: -0.5ch;
top: 0;
font-size: 1.5rem;
line-height: 2rem;
}
#familiar_container svg {
width: 100rem;
height: 20rem;
width: 100rem;
height: 20rem;
}
#familiar_container svg path {
fill: var(--text);
fill: var(--text);
}

View File

@ -1,122 +1,122 @@
#original figure > div,
#smart_kerning figure > div {
display: flex;
display: flex;
}
#original p,
#smart_kerning p {
font-size: 24rem;
line-height: 1;
position: relative;
border-right: 0.0625rem solid var(--text);
border-left: 0.0625rem solid var(--text);
margin-left: -0.0625rem;
font-size: 24rem;
line-height: 1;
position: relative;
border-right: 0.0625rem solid var(--text);
border-left: 0.0625rem solid var(--text);
margin-left: -0.0625rem;
}
#original p::after,
#smart_kerning p::after {
font-size: 0.75rem;
text-align: center;
display: block;
width: 100%;
font-size: 0.75rem;
text-align: center;
display: block;
width: 100%;
}
#original p:nth-child(1)::after,
#smart_kerning p:nth-child(1)::after {
content: "Wide letter";
content: "Wide letter";
}
#original p:nth-child(2)::after {
content: "Smart kerning OFF";
content: "Smart kerning OFF";
}
#smart_kerning p:nth-child(2)::after {
content: "Smart kerning ON";
content: "Smart kerning ON";
}
#original p:nth-child(3)::after,
#smart_kerning p:nth-child(3)::after {
content: "Narrow letter";
content: "Narrow letter";
}
#smart_kerning p:nth-child(2)::before {
content: "o";
position: absolute;
transform: translateX(calc(24rem / 1000 * 40));
color: var(--middle);
z-index: -1;
content: "o";
position: absolute;
transform: translateX(calc(24rem / 1000 * 40));
color: var(--middle);
z-index: -1;
}
#before p,
#after p {
font-size: 8rem;
line-height: 1;
max-width: none;
white-space: nowrap;
font-size: 8rem;
line-height: 1;
max-width: none;
white-space: nowrap;
}
#before p {
font-feature-settings: "calt" 0;
font-feature-settings: "calt" 0;
}
#intelligent_form fieldset {
border: none;
display: flex;
gap: 2rem;
font-size: 0.75rem;
line-height: 1rem;
background-color: var(--bg);
width: max-content;
border: none;
display: flex;
gap: 2rem;
font-size: 0.75rem;
line-height: 1rem;
background-color: var(--bg);
width: max-content;
}
#intelligent_form > div {
position: relative;
position: relative;
}
#intelligent_form input {
-webkit-appearance: none;
appearance: none;
background-color: var(--text);
margin: 0;
padding: 0;
border: none;
-webkit-appearance: none;
appearance: none;
background-color: var(--text);
margin: 0;
padding: 0;
border: none;
color: var(--text);
width: 0;
height: 0;
position: relative;
opacity: 1;
display: block;
color: var(--text);
width: 0;
height: 0;
position: relative;
opacity: 1;
display: block;
}
#intelligent_form input + label {
position: relative;
z-index: 1;
position: relative;
z-index: 1;
}
#intelligent_form input + label::before {
z-index: -1;
content: "";
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: var(--bg);
z-index: -1;
content: "";
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: var(--bg);
}
#intelligent_form input:focus:checked + label::before {
background-color: var(--text);
background-color: var(--text);
}
#intelligent_form input:focus:checked + label {
color: var(--bg);
color: var(--bg);
}
#intelligent_form input:checked + label::before {
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
}
#intelligent_form input:checked + label {
color: var(--text);
color: var(--text);
}

View File

@ -1,71 +1,71 @@
#code_form fieldset {
font-size: 1.5rem;
gap: 1ch;
font-size: 1.5rem;
gap: 1ch;
}
form fieldset {
border: none;
display: flex;
gap: 4ch;
font-size: 0.75rem;
line-height: 1rem;
background-color: var(--bg);
width: max-content;
border: none;
display: flex;
gap: 4ch;
font-size: 0.75rem;
line-height: 1rem;
background-color: var(--bg);
width: max-content;
}
form > div {
position: relative;
position: relative;
}
form input {
-webkit-appearance: none;
appearance: none;
background-color: var(--text);
margin: 0;
padding: 0;
border: none;
-webkit-appearance: none;
appearance: none;
background-color: var(--text);
margin: 0;
padding: 0;
border: none;
color: var(--text);
width: 0;
height: 0;
position: relative;
opacity: 1;
display: block;
color: var(--text);
width: 0;
height: 0;
position: relative;
opacity: 1;
display: block;
}
form input + label {
position: relative;
z-index: 1;
cursor: pointer;
position: relative;
z-index: 1;
cursor: pointer;
}
form input + label::before {
z-index: -1;
content: "";
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: var(--bg);
z-index: -1;
content: "";
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: var(--bg);
}
form input:focus:checked + label::before {
background-color: var(--text);
background-color: var(--text);
}
form input:focus:checked + label {
color: var(--bg);
color: var(--bg);
}
form input:checked + label::before {
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
}
form input:checked + label {
color: var(--text);
color: var(--text);
}
#canvas {
transform-origin: top left;
transform-origin: top left;
}

View File

@ -1,126 +1,126 @@
#waterfall {
display: flex;
width: min-content;
gap: 2rem;
display: flex;
width: min-content;
gap: 2rem;
}
.waterfall_texts_container {
display: flex;
flex-direction: column;
justify-content: end;
height: 10rem;
display: flex;
flex-direction: column;
justify-content: end;
height: 10rem;
}
.waterfall_texts_container > div {
height: 2.5rem;
display: flex;
align-items: end;
height: 2.5rem;
display: flex;
align-items: end;
}
.waterfall_text {
line-height: 0.6;
white-space: pre;
line-height: 0.6;
white-space: pre;
}
.waterfall_desc {
width: max-content;
white-space: pre;
width: max-content;
white-space: pre;
}
.question_container {
display: flex;
align-items: center;
font-size: 0.75rem;
gap: 2ch;
position: relative;
display: flex;
align-items: center;
font-size: 0.75rem;
gap: 2ch;
position: relative;
}
.question_character.hide_character {
opacity: 1;
animation: 0ms 0s 3 forwards flicker_reverse;
opacity: 1;
animation: 0ms 0s 3 forwards flicker_reverse;
}
.question_character.show_character {
opacity: 0;
animation: 100ms 0s 3 forwards flicker;
opacity: 0;
animation: 100ms 0s 3 forwards flicker;
}
.button_container button {
display: block;
display: block;
}
:root {
--question-character-size: 6rem;
--question-character-size: 6rem;
}
.question_character {
font-size: var(--question-character-size);
line-height: var(--question-character-size);
border: 0.0625rem solid var(--text);
position: relative;
font-size: var(--question-character-size);
line-height: var(--question-character-size);
border: 0.0625rem solid var(--text);
position: relative;
}
.question_character::after {
content: "";
position: absolute;
left: 0;
right: 0;
bottom: 15%;
/* height: 0.0625rem; */
background-color: var(--text);
content: "";
position: absolute;
left: 0;
right: 0;
bottom: 15%;
/* height: 0.0625rem; */
background-color: var(--text);
}
#score_points {
display: none;
display: none;
}
#score_points.view_score {
display: block;
display: block;
}
.question_button:focus::before {
content: "<-";
position: absolute;
left: -2ch;
color: var(--text);
content: "<-";
position: absolute;
left: -2ch;
color: var(--text);
}
.question_button.right_button::before {
content: "<-";
position: absolute;
left: -2ch;
color: var(--text);
content: "<-";
position: absolute;
left: -2ch;
color: var(--text);
}
.question_button.wrong_button::before {
content: "->";
position: absolute;
left: auto;
right: -2ch;
color: var(--text);
content: "->";
position: absolute;
left: auto;
right: -2ch;
color: var(--text);
}
.question_button.button_choice {
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
color: var(--text);
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
color: var(--text);
}
.question_button.button_choice:focus {
background: repeating-conic-gradient(transparent 0% 25%, var(--text) 0% 50%, var(--text) 0% 100%) 50% / 2px 2px;
color: var(--bg);
background: repeating-conic-gradient(transparent 0% 25%, var(--text) 0% 50%, var(--text) 0% 100%) 50% / 2px 2px;
color: var(--bg);
}
.answer_feedback {
position: relative;
font-size: 0.75rem;
top: calc(var(--question-character-size) * 0.5);
top: 40%;
width: 0;
margin-left: -2ch;
left: 0;
position: relative;
font-size: 0.75rem;
top: calc(var(--question-character-size) * 0.5);
top: 40%;
width: 0;
margin-left: -2ch;
left: 0;
}
.question_container.active_question ~ .question_container.active_question {
opacity: 1;
pointer-events: auto;
opacity: 1;
pointer-events: auto;
}
.question_container.active_question ~ .question_container {
opacity: 0;
pointer-events: none;
opacity: 0;
pointer-events: none;
}

View File

@ -1,152 +1,152 @@
#section_7 #alternates_container fieldset,
#section_7 #features_container fieldset {
display: grid;
grid-template-columns: 21ch 3ch 3ch;
gap: 2ch;
display: grid;
grid-template-columns: 21ch 3ch 3ch;
gap: 2ch;
}
#section_7 #examplesettings_form fieldset p {
white-space: pre;
font-variant-ligatures: none;
white-space: pre;
font-variant-ligatures: none;
}
fieldset.alternates > div {
width: 4ch;
width: 4ch;
}
#section_7 form > div {
position: relative;
position: relative;
}
#section_7 form input[type="radio"] + label {
position: relative;
z-index: 1;
position: relative;
z-index: 1;
}
#section_7 form input[type="radio"] + label::before {
z-index: -1;
content: "";
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: var(--bg);
z-index: -1;
content: "";
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: var(--bg);
}
#section_7 form input[type="radio"]:focus:checked + label::before {
background-color: var(--text);
background-color: var(--text);
}
#section_7 form input[type="radio"]:focus:checked + label {
color: var(--bg);
color: var(--bg);
}
#section_7 form input[type="radio"]:checked + label::before {
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
background: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, transparent 0% 100%) 50% / 2px 2px;
}
#section_7 form input[type="radio"]:checked + label {
color: var(--text);
color: var(--text);
}
#examples_container {
width: fit-content;
max-height: 20.6rem;
margin-bottom: 0.4rem;
overflow-y: scroll;
-ms-overflow-style: none; /* Internet Explorer 10+ */
scrollbar-width: none; /* Firefox */
width: fit-content;
max-height: 20.6rem;
margin-bottom: 0.4rem;
overflow-y: scroll;
-ms-overflow-style: none; /* Internet Explorer 10+ */
scrollbar-width: none; /* Firefox */
}
#examples_container::-webkit-scrollbar {
display: none; /* Safari and Chrome */
display: none; /* Safari and Chrome */
}
p#code_example {
white-space: pre;
max-width: none;
min-width: 102ch;
padding-left: 5ch;
position: relative;
font-variant-ligatures: none;
white-space: pre;
max-width: none;
min-width: 102ch;
padding-left: 5ch;
position: relative;
font-variant-ligatures: none;
}
p#code_example::before {
content: attr(data-before);
position: absolute;
white-space: pre;
left: 0;
top: 0;
height: 100%;
overflow: hidden;
content: attr(data-before);
position: absolute;
white-space: pre;
left: 0;
top: 0;
height: 100%;
overflow: hidden;
}
#section_7 form input[type="checkbox"] {
opacity: 1;
width: 0.5rem;
height: 0.5rem;
display: inline-block;
background-color: transparent;
border: 0.0625rem solid var(--text);
opacity: 1;
width: 0.5rem;
height: 0.5rem;
display: inline-block;
background-color: transparent;
border: 0.0625rem solid var(--text);
}
#section_7 form input[type="checkbox"]:checked {
background-color: var(--text);
background-color: var(--text);
}
#section_7 form input[type="checkbox"]:focus + label {
background-color: var(--text);
color: var(--bg);
background-color: var(--text);
color: var(--bg);
}
button:focus a {
color: var(--bg);
text-decoration: none;
color: var(--bg);
text-decoration: none;
}
.download_button {
display: block;
width: max-content;
display: block;
width: max-content;
}
.download_button.line-through:focus {
text-decoration: line-through;
text-decoration: line-through;
}
.download_button.line-through:focus::after {
content: "Not possible at the moment.";
text-decoration: none;
position: absolute;
background-color: var(--bg);
color: var(--text);
content: "Not possible at the moment.";
text-decoration: none;
position: absolute;
background-color: var(--bg);
color: var(--text);
}
.download_button.loading::after {
content: ".";
position: absolute;
color: var(--text);
right: -2ch;
animation: 800ms 0ms steps(4, jump-none) infinite loading;
content: ".";
position: absolute;
color: var(--text);
right: -2ch;
animation: 800ms 0ms steps(4, jump-none) infinite loading;
}
.download_button.loaded::after {
content: "✓";
position: absolute;
color: var(--text);
right: -2ch;
animation: none;
content: "✓";
position: absolute;
color: var(--text);
right: -2ch;
animation: none;
}
.download_button.error::after {
content: "✕";
position: absolute;
color: var(--text);
right: -2ch;
animation: none;
content: "✕";
position: absolute;
color: var(--text);
right: -2ch;
animation: none;
}
@keyframes loading {
0% {
transform: translateX(0);
}
100% {
transform: translateX(2ch);
}
0% {
transform: translateX(0);
}
100% {
transform: translateX(2ch);
}
}

View File

@ -1,64 +1,64 @@
ol {
font-size: 0.75rem;
margin-left: 0;
width: max-content;
font-size: 0.75rem;
margin-left: 0;
width: max-content;
}
ol li {
margin-left: 3ch;
max-width: calc(var(--max-width) - 3ch);
margin-left: 3ch;
max-width: calc(var(--max-width) - 3ch);
}
ol li p {
max-width: calc(var(--max-width) - 6ch);
max-width: calc(var(--max-width) - 6ch);
}
ol:focus li p {
color: var(--bg);
color: var(--bg);
}
ol li ul li p {
position: relative;
position: relative;
}
ol li ul li p::before {
content: "•";
position: absolute;
left: -2ch;
content: "•";
position: absolute;
left: -2ch;
}
.accordion_header {
margin-left: 2ch;
position: relative;
max-width: calc(var(--max-width) - 2ch);
margin-left: 2ch;
position: relative;
max-width: calc(var(--max-width) - 2ch);
}
.accordion_header::before {
content: "+";
position: absolute;
left: -2ch;
content: "+";
position: absolute;
left: -2ch;
}
.accordion_point {
margin-left: 2ch;
margin-bottom: 1rem;
max-width: calc(var(--max-width) - 2ch);
margin-left: 2ch;
margin-bottom: 1rem;
max-width: calc(var(--max-width) - 2ch);
}
ol.accordion_point {
margin-top: 0;
margin-left: 3ch;
margin-top: 0;
margin-left: 3ch;
}
.accordion_header + .accordion_point {
display: none;
display: none;
}
.accordion_header:focus:has(+ .accordion_point)::before {
content: "-";
color: var(--text);
content: "-";
color: var(--text);
}
.accordion_header:focus + .accordion_point {
display: block;
display: block;
}

View File

@ -1,163 +1,163 @@
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--text: #111;
--middle: #555;
--bg: #aaa;
--max-width: 54ch;
font-size: 16px;
--text: #111;
--middle: #555;
--bg: #aaa;
--max-width: 54ch;
font-size: 16px;
}
::selection {
color: var(--text);
background-color: var(--middle);
color: var(--text);
background-color: var(--middle);
}
#block_tab_start,
#block_tab_end {
position: absolute;
top: 0;
position: absolute;
top: 0;
}
#main_scale {
inset: 0;
position: fixed;
inset: 0;
position: fixed;
}
main {
min-width: 100vw;
padding: 4rem 0 0 4ch;
min-width: 100vw;
padding: 4rem 0 0 4ch;
}
header nav {
width: max-content;
padding: 1rem 4ch 0 4ch;
background-color: var(--bg);
z-index: 100;
position: fixed;
top: 0;
width: max-content;
padding: 1rem 4ch 0 4ch;
background-color: var(--bg);
z-index: 100;
position: fixed;
top: 0;
}
header #keyboard_section {
width: 100%;
padding: 0.25rem 0 1rem 4ch;
background-color: var(--bg);
z-index: 100;
position: fixed;
bottom: 0;
width: 100%;
padding: 0.25rem 0 1rem 4ch;
background-color: var(--bg);
z-index: 100;
position: fixed;
bottom: 0;
}
#keyboard_section.hidden {
display: none;
display: none;
}
#nav_form {
display: flex;
gap: 4ch;
font-size: 0.75rem;
line-height: 1rem;
display: flex;
gap: 4ch;
font-size: 0.75rem;
line-height: 1rem;
}
#nav_form input {
-webkit-appearance: none;
appearance: none;
width: 0;
height: 0;
opacity: 0;
-webkit-appearance: none;
appearance: none;
width: 0;
height: 0;
opacity: 0;
}
#nav_form input + label {
position: relative;
z-index: 1;
position: relative;
z-index: 1;
}
#nav_form input + label::before {
z-index: -1;
content: "";
position: absolute;
inset: 0;
background-color: var(--bg);
z-index: -1;
content: "";
position: absolute;
inset: 0;
background-color: var(--bg);
}
#nav_form input:focus:checked + label::before {
background-color: var(--text);
background-color: var(--text);
}
#nav_form input:focus:checked + label {
color: var(--bg);
color: var(--bg);
}
#section_container {
inset: 1rem 2rem;
inset: 1rem 2rem;
}
p,
a,
figcaption,
button {
font-size: 0.75rem;
line-height: 1rem;
max-width: var(--max-width);
width: fit-content;
vertical-align: top;
color: inherit;
font-size: 0.75rem;
line-height: 1rem;
max-width: var(--max-width);
width: fit-content;
vertical-align: top;
color: inherit;
}
a,
.download_button {
text-decoration: underline;
text-decoration-skip-ink: none;
text-underline-offset: 0.24ch;
cursor: pointer;
text-decoration: underline;
text-decoration-skip-ink: none;
text-underline-offset: 0.24ch;
cursor: pointer;
}
a:focus,
.download_button:focus {
text-decoration: none;
text-decoration: none;
}
h1 {
font-size: 1.5rem;
line-height: 2rem;
font-weight: normal;
width: fit-content;
font-size: 1.5rem;
line-height: 2rem;
font-weight: normal;
width: fit-content;
}
#click_focus,
#change_setting {
inset: 0;
position: fixed;
z-index: 999;
display: grid;
place-content: center;
visibility: hidden;
pointer-events: none;
inset: 0;
position: fixed;
z-index: 999;
display: grid;
place-content: center;
visibility: hidden;
pointer-events: none;
}
#content_root.faded {
opacity: 0.33;
opacity: 0.33;
}
#mobile {
visibility: hidden;
visibility: hidden;
}
:focus {
text-decoration: none;
color: var(--bg);
background-color: var(--text);
outline: none;
text-decoration: none;
color: var(--bg);
background-color: var(--text);
outline: none;
}
ul li,
ol li {
font-size: 0.75rem;
line-height: 1rem;
margin-left: 2ch;
max-width: 54ch;
width: fit-content;
font-size: 0.75rem;
line-height: 1rem;
margin-left: 2ch;
max-width: 54ch;
width: fit-content;
}

View File

@ -2,332 +2,332 @@ const codeForm = document.querySelector("#code_form")
const codeFieldset = document.querySelector("#code_form fieldset")
websiteData.sections.forEach((section) => {
if (section.name == "code") {
section.content.characters.forEach((character, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "code"
input.id = character.name
input.classList.add("code_character")
input.value = character.name
if (index == 0) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = character.value
label.setAttribute("for", character.name)
div.append(input, label)
codeFieldset.append(div)
})
}
if (section.name == "code") {
section.content.characters.forEach((character, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "code"
input.id = character.name
input.classList.add("code_character")
input.value = character.name
if (index == 0) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = character.value
label.setAttribute("for", character.name)
div.append(input, label)
codeFieldset.append(div)
})
}
})
function updateCode(event, form) {
console.log("update code")
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
console.log("update code")
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
let displayCharacter = ""
let displayName = ""
websiteData.sections.forEach((section) => {
if (section.name == "code") {
section.content.characters.forEach((character, index) => {
if (character.name == output) {
displayCharacter = character.value
displayName = character.name
}
})
}
})
let displayCharacter = ""
let displayName = ""
websiteData.sections.forEach((section) => {
if (section.name == "code") {
section.content.characters.forEach((character, index) => {
if (character.name == output) {
displayCharacter = character.value
displayName = character.name
}
})
}
})
let selectedGlyphData
if (commitMonoFont) {
Object.values(commitMonoFont.glyphs.glyphs).forEach((glyph) => {
if (glyph.name == output) selectedGlyphData = glyph
})
updateCanvas(selectedGlyphData, commitMonoFont, displayCharacter, displayName)
}
let selectedGlyphData
if (commitMonoFont) {
Object.values(commitMonoFont.glyphs.glyphs).forEach((glyph) => {
if (glyph.name == output) selectedGlyphData = glyph
})
updateCanvas(selectedGlyphData, commitMonoFont, displayCharacter, displayName)
}
if (event) event.preventDefault()
if (event) event.preventDefault()
}
const canvasScale = 16
const drawFontLine = (GLYPH_SCALE, ctx, upem, width, name, value, yOffset) => {
let scaledValue = mapRange(value, 0, upem, 0, width * GLYPH_SCALE)
scaledValue = width - scaledValue + (yOffset * GLYPH_SCALE * width) / upem
let scaledValue = mapRange(value, 0, upem, 0, width * GLYPH_SCALE)
scaledValue = width - scaledValue + (yOffset * GLYPH_SCALE * width) / upem
ctx.strokeStyle = getCssVar("--text")
ctx.beginPath()
ctx.moveTo(7 * canvasScale, scaledValue)
ctx.lineTo(width - 7 * canvasScale, scaledValue)
ctx.closePath()
ctx.stroke()
ctx.strokeStyle = getCssVar("--text")
ctx.beginPath()
ctx.moveTo(7 * canvasScale, scaledValue)
ctx.lineTo(width - 7 * canvasScale, scaledValue)
ctx.closePath()
ctx.stroke()
ctx.fillStyle = getCssVar("--text")
ctx.font = `${0.75 * canvasScale}px "Commit Mono"`
ctx.textAlign = "left"
ctx.fillText(name, 0, scaledValue + 0.25 * canvasScale)
ctx.textAlign = "left"
ctx.fillText(value, width - 4 * canvasScale, scaledValue + 0.25 * canvasScale)
ctx.fillStyle = getCssVar("--text")
ctx.font = `${0.75 * canvasScale}px "Commit Mono"`
ctx.textAlign = "left"
ctx.fillText(name, 0, scaledValue + 0.25 * canvasScale)
ctx.textAlign = "left"
ctx.fillText(value, width - 4 * canvasScale, scaledValue + 0.25 * canvasScale)
}
const drawFontLineVertical = (GLYPH_SCALE, ctx, upem, width, value, yOffset, ascender, descender) => {
let scaledValue1 = mapRange(ascender, 0, upem, 0, width * GLYPH_SCALE)
scaledValue1 = width - scaledValue1 + (yOffset * GLYPH_SCALE * width) / upem
let scaledValue2 = mapRange(descender, 0, upem, 0, width * GLYPH_SCALE)
scaledValue2 = width - scaledValue2 + (yOffset * GLYPH_SCALE * width) / upem
let scaledValue1 = mapRange(ascender, 0, upem, 0, width * GLYPH_SCALE)
scaledValue1 = width - scaledValue1 + (yOffset * GLYPH_SCALE * width) / upem
let scaledValue2 = mapRange(descender, 0, upem, 0, width * GLYPH_SCALE)
scaledValue2 = width - scaledValue2 + (yOffset * GLYPH_SCALE * width) / upem
ctx.strokeStyle = getCssVar("--text")
ctx.beginPath()
ctx.moveTo(value, scaledValue1)
ctx.lineTo(value, scaledValue2)
ctx.closePath()
ctx.stroke()
ctx.strokeStyle = getCssVar("--text")
ctx.beginPath()
ctx.moveTo(value, scaledValue1)
ctx.lineTo(value, scaledValue2)
ctx.closePath()
ctx.stroke()
}
function updateCanvas(selectedGlyphData, selectedFont, displayCharacter, displayName) {
// initialize canvas
let CANVAS_SCALE = window.devicePixelRatio
const canvas = document.querySelector("#canvas")
let canvasWidth = 60 * canvasScale
let canvasHeight = 42 * canvasScale
canvas.style.width = `${canvasWidth}px`
canvas.style.height = `${canvasHeight}px`
canvas.width = canvasWidth * CANVAS_SCALE
canvas.height = canvasHeight * CANVAS_SCALE
const ctx = canvas.getContext("2d")
ctx.scale(CANVAS_SCALE, CANVAS_SCALE)
// initialize canvas
let CANVAS_SCALE = window.devicePixelRatio
const canvas = document.querySelector("#canvas")
let canvasWidth = 60 * canvasScale
let canvasHeight = 42 * canvasScale
canvas.style.width = `${canvasWidth}px`
canvas.style.height = `${canvasHeight}px`
canvas.width = canvasWidth * CANVAS_SCALE
canvas.height = canvasHeight * CANVAS_SCALE
const ctx = canvas.getContext("2d")
ctx.scale(CANVAS_SCALE, CANVAS_SCALE)
let GLYPH_SCALE = 0.6
ctx.clearRect(0, 0, canvasWidth, canvasHeight)
let GLYPH_SCALE = 0.6
ctx.clearRect(0, 0, canvasWidth, canvasHeight)
if (selectedGlyphData.path) {
const CANVAS_GLYPH_COMPOSITION_FILL = [
{
type: "outline",
fill: true,
color: getCssVar("--text"),
pointSize: undefined,
},
]
const CANVAS_GLYPH_COMPOSITION_BEZIER = [
// {
// type: "outline",
// fill: true,
// color: "rgba(0, 0, 0, 0.1)",
// pointSize: undefined,
// },
{
type: "handles",
fill: false,
color: getCssVar("--middle"),
pointSize: undefined,
},
{
type: "outline",
fill: false,
color: getCssVar("--text"),
pointSize: undefined,
},
{
type: "points",
fill: true,
color: getCssVar("--text"),
pointSize: 10, // size of point on bezier glyph
},
{
type: "handle points",
fill: true,
color: getCssVar("--middle"),
pointSize: 10, // size of handles on bezier glyph
},
]
if (selectedGlyphData.path) {
const CANVAS_GLYPH_COMPOSITION_FILL = [
{
type: "outline",
fill: true,
color: getCssVar("--text"),
pointSize: undefined,
},
]
const CANVAS_GLYPH_COMPOSITION_BEZIER = [
// {
// type: "outline",
// fill: true,
// color: "rgba(0, 0, 0, 0.1)",
// pointSize: undefined,
// },
{
type: "handles",
fill: false,
color: getCssVar("--middle"),
pointSize: undefined,
},
{
type: "outline",
fill: false,
color: getCssVar("--text"),
pointSize: undefined,
},
{
type: "points",
fill: true,
color: getCssVar("--text"),
pointSize: 10, // size of point on bezier glyph
},
{
type: "handle points",
fill: true,
color: getCssVar("--middle"),
pointSize: 10, // size of handles on bezier glyph
},
]
const upem = selectedFont?.unitsPerEm || 1000
const width = 60 * canvasScale
const upem = selectedFont?.unitsPerEm || 1000
const width = 60 * canvasScale
const yOffset = -45 * canvasScale
const xOffset = 20 * canvasScale
const ascender = selectedFont?.tables.os2?.sTypoAscender || 750
const capHeight = selectedFont?.tables.os2?.sCapHeight || 700
const xHeight = selectedFont?.tables.os2?.sxHeight
const baseline = 0
const descender = selectedFont?.tables.os2?.sTypoDescender || -200
drawFontLine(GLYPH_SCALE, ctx, upem, width, "Ascender", ascender, yOffset)
drawFontLine(GLYPH_SCALE, ctx, upem, width, "Cap Height", capHeight, yOffset)
drawFontLine(GLYPH_SCALE, ctx, upem, width, "X-height", xHeight || 500, yOffset)
drawFontLine(GLYPH_SCALE, ctx, upem, width, "Baseline", baseline, yOffset)
drawFontLine(GLYPH_SCALE, ctx, upem, width, "Descender", descender, yOffset)
drawFontLineVertical(GLYPH_SCALE, ctx, upem, width, 7 * canvasScale, yOffset, ascender, descender)
drawFontLineVertical(GLYPH_SCALE, ctx, upem, width, 30 * canvasScale, yOffset, ascender, descender)
drawFontLineVertical(GLYPH_SCALE, ctx, upem, width, 53 * canvasScale, yOffset, ascender, descender)
const yOffset = -45 * canvasScale
const xOffset = 20 * canvasScale
const ascender = selectedFont?.tables.os2?.sTypoAscender || 750
const capHeight = selectedFont?.tables.os2?.sCapHeight || 700
const xHeight = selectedFont?.tables.os2?.sxHeight
const baseline = 0
const descender = selectedFont?.tables.os2?.sTypoDescender || -200
drawFontLine(GLYPH_SCALE, ctx, upem, width, "Ascender", ascender, yOffset)
drawFontLine(GLYPH_SCALE, ctx, upem, width, "Cap Height", capHeight, yOffset)
drawFontLine(GLYPH_SCALE, ctx, upem, width, "X-height", xHeight || 500, yOffset)
drawFontLine(GLYPH_SCALE, ctx, upem, width, "Baseline", baseline, yOffset)
drawFontLine(GLYPH_SCALE, ctx, upem, width, "Descender", descender, yOffset)
drawFontLineVertical(GLYPH_SCALE, ctx, upem, width, 7 * canvasScale, yOffset, ascender, descender)
drawFontLineVertical(GLYPH_SCALE, ctx, upem, width, 30 * canvasScale, yOffset, ascender, descender)
drawFontLineVertical(GLYPH_SCALE, ctx, upem, width, 53 * canvasScale, yOffset, ascender, descender)
ctx.fillStyle = getCssVar("--text")
ctx.font = `${0.75 * canvasScale}px "Commit Mono"`
ctx.textAlign = "center"
ctx.fillText(displayName, (30 - 11.5) * canvasScale, 2.75 * canvasScale)
ctx.fillText(displayName, (30 + 11.5) * canvasScale, 2.75 * canvasScale)
ctx.fillStyle = getCssVar("--text")
ctx.font = `${0.75 * canvasScale}px "Commit Mono"`
ctx.textAlign = "center"
ctx.fillText(displayName, (30 - 11.5) * canvasScale, 2.75 * canvasScale)
ctx.fillText(displayName, (30 + 11.5) * canvasScale, 2.75 * canvasScale)
// make ready transformation matrixes for manipulating paths
let firstMatrix = new DOMMatrix()
firstMatrix = firstMatrix.scaleSelf(width / upem)
let secondMatrix = new DOMMatrix()
secondMatrix = secondMatrix.scaleSelf(GLYPH_SCALE)
secondMatrix = secondMatrix.translateSelf(-width * 0.5, -width) // translate to left edge, top
secondMatrix = secondMatrix.translateSelf((width * 0.5) / GLYPH_SCALE, width / GLYPH_SCALE) // translate to center, baseline
secondMatrix = secondMatrix.translateSelf(0, (yOffset * width) / upem) // translate yOffset
secondMatrix = secondMatrix.translateSelf((xOffset * width) / upem, 0) // translate xOffset
// make ready transformation matrixes for manipulating paths
let firstMatrix = new DOMMatrix()
firstMatrix = firstMatrix.scaleSelf(width / upem)
let secondMatrix = new DOMMatrix()
secondMatrix = secondMatrix.scaleSelf(GLYPH_SCALE)
secondMatrix = secondMatrix.translateSelf(-width * 0.5, -width) // translate to left edge, top
secondMatrix = secondMatrix.translateSelf((width * 0.5) / GLYPH_SCALE, width / GLYPH_SCALE) // translate to center, baseline
secondMatrix = secondMatrix.translateSelf(0, (yOffset * width) / upem) // translate yOffset
secondMatrix = secondMatrix.translateSelf((xOffset * width) / upem, 0) // translate xOffset
// set initial value for glyph composition based on if bezier is switched on or off
// let canvasGlyphComposition = bezier ? CANVAS_GLYPH_COMPOSITION_BEZIER : CANVAS_GLYPH_COMPOSITION_FILL
// set initial value for glyph composition based on if bezier is switched on or off
// let canvasGlyphComposition = bezier ? CANVAS_GLYPH_COMPOSITION_BEZIER : CANVAS_GLYPH_COMPOSITION_FILL
CANVAS_GLYPH_COMPOSITION_BEZIER.forEach((composite) => {
const calcPointsize = composite.pointSize * (upem / 1000)
const firstPath2d = glyphBezier(selectedGlyphData, upem, composite.type, calcPointsize)
const secondPath2d = new Path2D()
secondPath2d.addPath(firstPath2d, firstMatrix)
const finalPath2d = new Path2D()
finalPath2d.addPath(secondPath2d, secondMatrix)
CANVAS_GLYPH_COMPOSITION_BEZIER.forEach((composite) => {
const calcPointsize = composite.pointSize * (upem / 1000)
const firstPath2d = glyphBezier(selectedGlyphData, upem, composite.type, calcPointsize)
const secondPath2d = new Path2D()
secondPath2d.addPath(firstPath2d, firstMatrix)
const finalPath2d = new Path2D()
finalPath2d.addPath(secondPath2d, secondMatrix)
if (composite.fill) {
ctx.fillStyle = composite.color
ctx.fill(finalPath2d)
} else {
ctx.strokeStyle = composite.color
ctx.stroke(finalPath2d)
}
})
CANVAS_GLYPH_COMPOSITION_FILL.forEach((composite) => {
secondMatrix = secondMatrix.translateSelf((-2 * xOffset * width) / upem, 0) // translate xOffset
if (composite.fill) {
ctx.fillStyle = composite.color
ctx.fill(finalPath2d)
} else {
ctx.strokeStyle = composite.color
ctx.stroke(finalPath2d)
}
})
CANVAS_GLYPH_COMPOSITION_FILL.forEach((composite) => {
secondMatrix = secondMatrix.translateSelf((-2 * xOffset * width) / upem, 0) // translate xOffset
const calcPointsize = composite.pointSize * (upem / 1000)
const firstPath2d = glyphBezier(selectedGlyphData, upem, composite.type, calcPointsize)
const secondPath2d = new Path2D()
secondPath2d.addPath(firstPath2d, firstMatrix)
const finalPath2d = new Path2D()
finalPath2d.addPath(secondPath2d, secondMatrix)
const calcPointsize = composite.pointSize * (upem / 1000)
const firstPath2d = glyphBezier(selectedGlyphData, upem, composite.type, calcPointsize)
const secondPath2d = new Path2D()
secondPath2d.addPath(firstPath2d, firstMatrix)
const finalPath2d = new Path2D()
finalPath2d.addPath(secondPath2d, secondMatrix)
if (composite.fill) {
ctx.fillStyle = composite.color
ctx.fill(finalPath2d)
} else {
ctx.strokeStyle = composite.color
ctx.stroke(finalPath2d)
}
})
}
if (composite.fill) {
ctx.fillStyle = composite.color
ctx.fill(finalPath2d)
} else {
ctx.strokeStyle = composite.color
ctx.stroke(finalPath2d)
}
})
}
}
function glyphBezier(glyph, upem, typeOfOutline, pointSize) {
let ps = pointSize
let offsetX = (upem - glyph.advanceWidth) * 0.5
let path2d = new Path2D()
let ps = pointSize
let offsetX = (upem - glyph.advanceWidth) * 0.5
let path2d = new Path2D()
if (typeOfOutline == "outline") {
let commandString = ""
glyph.path.commands.forEach((command) => {
switch (command.type) {
case "M":
commandString += `${command.type} `
commandString += `${command.x + offsetX} ${upem - command.y} `
break
case "L":
commandString += `${command.type} `
commandString += `${command.x + offsetX} ${upem - command.y} `
break
case "C":
commandString += `${command.type} `
commandString += `${command.x1 + offsetX} ${upem - command.y1}, `
commandString += `${command.x2 + offsetX} ${upem - command.y2}, `
commandString += `${command.x + offsetX} ${upem - command.y} `
break
case "Q":
commandString += `${command.type} `
commandString += `${command.x1 + offsetX} ${upem - command.y1}, `
commandString += `${command.x + offsetX} ${upem - command.y} `
break
case "Z":
commandString += `${command.type} `
break
}
})
path2d.addPath(new Path2D(commandString))
}
if (typeOfOutline == "outline") {
let commandString = ""
glyph.path.commands.forEach((command) => {
switch (command.type) {
case "M":
commandString += `${command.type} `
commandString += `${command.x + offsetX} ${upem - command.y} `
break
case "L":
commandString += `${command.type} `
commandString += `${command.x + offsetX} ${upem - command.y} `
break
case "C":
commandString += `${command.type} `
commandString += `${command.x1 + offsetX} ${upem - command.y1}, `
commandString += `${command.x2 + offsetX} ${upem - command.y2}, `
commandString += `${command.x + offsetX} ${upem - command.y} `
break
case "Q":
commandString += `${command.type} `
commandString += `${command.x1 + offsetX} ${upem - command.y1}, `
commandString += `${command.x + offsetX} ${upem - command.y} `
break
case "Z":
commandString += `${command.type} `
break
}
})
path2d.addPath(new Path2D(commandString))
}
if (typeOfOutline == "points") {
glyph.path.commands.forEach((command) => {
let p = new Path2D()
const x = command.x + offsetX
const y = upem - command.y
switch (command.type) {
case "M":
p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
break
case "L":
p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
break
case "C":
p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
break
case "Q":
p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
break
}
path2d.addPath(p)
})
}
if (typeOfOutline == "points") {
glyph.path.commands.forEach((command) => {
let p = new Path2D()
const x = command.x + offsetX
const y = upem - command.y
switch (command.type) {
case "M":
p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
break
case "L":
p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
break
case "C":
p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
break
case "Q":
p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
break
}
path2d.addPath(p)
})
}
if (typeOfOutline == "handles") {
let p = new Path2D()
glyph.path.commands.forEach((command) => {
switch (command.type) {
case "M":
p.moveTo(command.x + offsetX, upem - command.y)
break
case "L":
p.moveTo(command.x + offsetX, upem - command.y)
break
case "C":
p.lineTo(command.x1 + offsetX, upem - command.y1)
p.moveTo(command.x + offsetX, upem - command.y)
p.lineTo(command.x2 + offsetX, upem - command.y2)
p.moveTo(command.x + offsetX, upem - command.y)
break
case "Q":
p.lineTo(command.x1 + offsetX, upem - command.y1)
p.moveTo(command.x1 + offsetX, upem - command.y1)
p.lineTo(command.x + offsetX, upem - command.y)
break
case "Z":
p.moveTo(command.x + offsetX, upem - command.y)
break
}
})
path2d.addPath(p)
}
if (typeOfOutline == "handles") {
let p = new Path2D()
glyph.path.commands.forEach((command) => {
switch (command.type) {
case "M":
p.moveTo(command.x + offsetX, upem - command.y)
break
case "L":
p.moveTo(command.x + offsetX, upem - command.y)
break
case "C":
p.lineTo(command.x1 + offsetX, upem - command.y1)
p.moveTo(command.x + offsetX, upem - command.y)
p.lineTo(command.x2 + offsetX, upem - command.y2)
p.moveTo(command.x + offsetX, upem - command.y)
break
case "Q":
p.lineTo(command.x1 + offsetX, upem - command.y1)
p.moveTo(command.x1 + offsetX, upem - command.y1)
p.lineTo(command.x + offsetX, upem - command.y)
break
case "Z":
p.moveTo(command.x + offsetX, upem - command.y)
break
}
})
path2d.addPath(p)
}
if (typeOfOutline == "handle points") {
glyph.path.commands.forEach((command) => {
let p = new Path2D()
const x1 = command.x1 + offsetX
const x2 = command.x2 + offsetX
const y1 = upem - command.y1
const y2 = upem - command.y2
switch (command.type) {
case "C":
p.rect(x1 - ps * 0.5, y1 - ps * 0.5, ps, ps)
p.rect(x2 - ps * 0.5, y2 - ps * 0.5, ps, ps)
break
case "Q":
p.rect(x1 - ps * 0.5, y1 - ps * 0.5, ps, ps)
break
}
path2d.addPath(p)
})
}
if (typeOfOutline == "handle points") {
glyph.path.commands.forEach((command) => {
let p = new Path2D()
const x1 = command.x1 + offsetX
const x2 = command.x2 + offsetX
const y1 = upem - command.y1
const y2 = upem - command.y2
switch (command.type) {
case "C":
p.rect(x1 - ps * 0.5, y1 - ps * 0.5, ps, ps)
p.rect(x2 - ps * 0.5, y2 - ps * 0.5, ps, ps)
break
case "Q":
p.rect(x1 - ps * 0.5, y1 - ps * 0.5, ps, ps)
break
}
path2d.addPath(p)
})
}
return path2d
return path2d
}

View File

@ -1,37 +1,37 @@
let waterfall, gtc
websiteData.sections.forEach((section) => {
if (section.name == "distinction") {
waterfall = section.content.waterfall
gtc = section.content.gtc
}
if (section.name == "distinction") {
waterfall = section.content.waterfall
gtc = section.content.gtc
}
})
function updateWaterfall() {
const waterfallContainer = document.querySelector("#waterfall")
waterfallContainer.innerHTML = ""
waterfall.sizes.forEach((size) => {
const div = document.createElement("div")
div.id = `size_${size}`
const waterfallContainer = document.querySelector("#waterfall")
waterfallContainer.innerHTML = ""
waterfall.sizes.forEach((size) => {
const div = document.createElement("div")
div.id = `size_${size}`
const desc = document.createElement("p")
desc.classList.add("waterfall_desc")
desc.textContent = `${size}rem\n${size * rem}px`
const desc = document.createElement("p")
desc.classList.add("waterfall_desc")
desc.textContent = `${size}rem\n${size * rem}px`
const textsContainer = document.createElement("div")
textsContainer.classList.add("waterfall_texts_container")
waterfall.texts.forEach((text) => {
const div2 = document.createElement("div")
const p = document.createElement("p")
p.classList.add("waterfall_text")
p.style.fontSize = `${size * rem}px`
p.textContent = text
div2.append(p)
textsContainer.append(div2)
})
div.append(desc, textsContainer)
const textsContainer = document.createElement("div")
textsContainer.classList.add("waterfall_texts_container")
waterfall.texts.forEach((text) => {
const div2 = document.createElement("div")
const p = document.createElement("p")
p.classList.add("waterfall_text")
p.style.fontSize = `${size * rem}px`
p.textContent = text
div2.append(p)
textsContainer.append(div2)
})
div.append(desc, textsContainer)
waterfallContainer.append(div)
})
waterfallContainer.append(div)
})
}
updateWaterfall()
@ -40,42 +40,42 @@ const gtcForm = document.querySelector("#gtc_form")
const gtcFieldset = document.querySelector("#gtc_form fieldset")
websiteData.sections.forEach((section) => {
if (section.name == "distinction") {
section.content.gtcDifficulties.forEach((difficulty, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "difficulty"
input.id = `difficulty_${difficulty.name}`
input.classList.add("gtc_difficulty")
input.value = difficulty.name
if (index == 0) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = difficulty.name
label.setAttribute("for", `difficulty_${difficulty.name}`)
div.append(input, label)
gtcFieldset.append(div)
})
}
if (section.name == "distinction") {
section.content.gtcDifficulties.forEach((difficulty, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "difficulty"
input.id = `difficulty_${difficulty.name}`
input.classList.add("gtc_difficulty")
input.value = difficulty.name
if (index == 0) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = difficulty.name
label.setAttribute("for", `difficulty_${difficulty.name}`)
div.append(input, label)
gtcFieldset.append(div)
})
}
})
function updateGTC(event, form) {
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
websiteData.sections.forEach((section) => {
if (section.name == "distinction") {
section.content.gtcDifficulties.forEach((difficulty) => {
if (difficulty.name == output) {
setCssVar(["--question-character-size", `${difficulty.size}rem`])
}
})
}
})
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
websiteData.sections.forEach((section) => {
if (section.name == "distinction") {
section.content.gtcDifficulties.forEach((difficulty) => {
if (difficulty.name == output) {
setCssVar(["--question-character-size", `${difficulty.size}rem`])
}
})
}
})
if (event) event.preventDefault()
if (event) event.preventDefault()
}
let answers = []
@ -83,103 +83,103 @@ let score = -1
let currentQuestion = -1
let firstButtons = []
function createGTC() {
const gtcContainer = document.querySelector("#gtc_questions_container")
gtcContainer.innerHTML = ""
answers = []
firstButtons = []
gtc.forEach((question, index) => {
const div = document.createElement("div")
div.classList.add("question_container")
div.dataset.index = index
const gtcContainer = document.querySelector("#gtc_questions_container")
gtcContainer.innerHTML = ""
answers = []
firstButtons = []
gtc.forEach((question, index) => {
const div = document.createElement("div")
div.classList.add("question_container")
div.dataset.index = index
const answer = Math.round(Math.random())
const wrongAnswer = (answer + 1) % 2
answers.push(answer)
const answer = Math.round(Math.random())
const wrongAnswer = (answer + 1) % 2
answers.push(answer)
const p = document.createElement("p")
p.classList.add("question_character")
p.textContent = question.value[answer]
const pWrong = document.createElement("p")
pWrong.classList.add("question_character", "wrong_character", "hide_character")
pWrong.textContent = question.value[wrongAnswer]
const buttonContainer = document.createElement("div")
buttonContainer.classList.add("button_container")
const option0 = document.createElement("button")
option0.classList.add("question_button")
option0.textContent = question.options[0]
option0.dataset.questionIndex = index
option0.tabIndex = -1
firstButtons.push(option0)
const option1 = document.createElement("button")
option1.classList.add("question_button")
option1.textContent = question.options[1]
option1.dataset.questionIndex = index
option1.tabIndex = -1
const p = document.createElement("p")
p.classList.add("question_character")
p.textContent = question.value[answer]
const pWrong = document.createElement("p")
pWrong.classList.add("question_character", "wrong_character", "hide_character")
pWrong.textContent = question.value[wrongAnswer]
const buttonContainer = document.createElement("div")
buttonContainer.classList.add("button_container")
const option0 = document.createElement("button")
option0.classList.add("question_button")
option0.textContent = question.options[0]
option0.dataset.questionIndex = index
option0.tabIndex = -1
firstButtons.push(option0)
const option1 = document.createElement("button")
option1.classList.add("question_button")
option1.textContent = question.options[1]
option1.dataset.questionIndex = index
option1.tabIndex = -1
const options = [option0, option1]
options[answer].addEventListener("click", () => nextQuestion(true, answer, wrongAnswer))
options[wrongAnswer].addEventListener("click", () => nextQuestion(false, answer, wrongAnswer))
const options = [option0, option1]
options[answer].addEventListener("click", () => nextQuestion(true, answer, wrongAnswer))
options[wrongAnswer].addEventListener("click", () => nextQuestion(false, answer, wrongAnswer))
const answerFeedback = document.createElement("p")
answerFeedback.classList.add("answer_feedback")
const answerFeedback = document.createElement("p")
answerFeedback.classList.add("answer_feedback")
buttonContainer.append(option0, option1)
const br = document.createElement("br")
div.append(answerFeedback, p, buttonContainer, pWrong)
gtcContainer.append(br, div)
})
const scorePoints = document.createElement("p")
scorePoints.id = "score_points"
scorePoints.textContent = `You scored ${score} out of ${gtc.length}`
gtcContainer.append(scorePoints)
nextQuestion(true, 0, 1)
buttonContainer.append(option0, option1)
const br = document.createElement("br")
div.append(answerFeedback, p, buttonContainer, pWrong)
gtcContainer.append(br, div)
})
const scorePoints = document.createElement("p")
scorePoints.id = "score_points"
scorePoints.textContent = `You scored ${score} out of ${gtc.length}`
gtcContainer.append(scorePoints)
nextQuestion(true, 0, 1)
}
function nextQuestion(correct, answer, wrongAnswer) {
const scoreTally = document.querySelector("#score_tally")
const allQuestions = document.querySelectorAll(".question_container")
let answerFeedback
const scoreTally = document.querySelector("#score_tally")
const allQuestions = document.querySelectorAll(".question_container")
let answerFeedback
if (correct) score++
if (correct) score++
allQuestions.forEach((question, index) => {
const wrongCharacter = question.querySelector(".wrong_character")
allQuestions.forEach((question, index) => {
const wrongCharacter = question.querySelector(".wrong_character")
if (index == currentQuestion) {
question.classList.add("active_question")
const rightButton = question.querySelector(`.button_container .question_button:nth-child(${answer + 1})`)
const wrongButton = question.querySelector(`.button_container .question_button:nth-child(${wrongAnswer + 1})`)
correct ? rightButton.classList.add("button_choice") : wrongButton.classList.add("button_choice")
rightButton.classList.add("right_button")
wrongButton.classList.add("wrong_button")
if (index == currentQuestion) {
question.classList.add("active_question")
const rightButton = question.querySelector(`.button_container .question_button:nth-child(${answer + 1})`)
const wrongButton = question.querySelector(`.button_container .question_button:nth-child(${wrongAnswer + 1})`)
correct ? rightButton.classList.add("button_choice") : wrongButton.classList.add("button_choice")
rightButton.classList.add("right_button")
wrongButton.classList.add("wrong_button")
answerFeedback = question.querySelector(".answer_feedback")
answerFeedback.textContent = correct ? "✓" : "✕"
answerFeedback = question.querySelector(".answer_feedback")
answerFeedback.textContent = correct ? "✓" : "✕"
wrongCharacter.classList.remove("hide_character")
wrongCharacter.classList.add("show_character")
} else if (index == currentQuestion + 1) {
question.classList.add("active_question")
} else {
question.classList.remove("active_question")
}
})
wrongCharacter.classList.remove("hide_character")
wrongCharacter.classList.add("show_character")
} else if (index == currentQuestion + 1) {
question.classList.add("active_question")
} else {
question.classList.remove("active_question")
}
})
currentQuestion++
currentQuestion++
allQuestions.forEach((question, index) => {
if (index == currentQuestion) {
question.querySelectorAll(".question_button").forEach((button) => (button.tabIndex = 0))
}
})
scoreTally.textContent = `Score: ${score}/${gtc.length}`
allQuestions.forEach((question, index) => {
if (index == currentQuestion) {
question.querySelectorAll(".question_button").forEach((button) => (button.tabIndex = 0))
}
})
scoreTally.textContent = `Score: ${score}/${gtc.length}`
if (currentQuestion < gtc.length) {
if (!isMobile) setTimeout(() => firstButtons[currentQuestion]?.focus(), 10)
} else {
scoreTally.tabIndex = 0
setTimeout(() => scoreTally.focus(), 10)
}
if (currentQuestion < gtc.length) {
if (!isMobile) setTimeout(() => firstButtons[currentQuestion]?.focus(), 10)
} else {
scoreTally.tabIndex = 0
setTimeout(() => scoreTally.focus(), 10)
}
}
createGTC()

View File

@ -1,47 +1,47 @@
document.onvisibilitychange = () => {
// dynamicFavicon()
if (document.visibilityState === "visible") changeFavicon(true)
else changeFavicon(false)
// dynamicFavicon()
if (document.visibilityState === "visible") changeFavicon(true)
else changeFavicon(false)
}
let faviconIntervalID
let faviconCounter = 0
function dynamicFavicon() {
if (document.visibilityState === "visible") {
faviconIntervalID = setInterval(changeFav, 500)
} else {
clearInterval(faviconIntervalID)
faviconIntervalID = null
if (faviconCounter % 2 == 1) changeFav()
}
if (document.visibilityState === "visible") {
faviconIntervalID = setInterval(changeFav, 500)
} else {
clearInterval(faviconIntervalID)
faviconIntervalID = null
if (faviconCounter % 2 == 1) changeFav()
}
function changeFav() {
const link = document.createElement("link"),
oldLink = document.getElementById("dynamic-favicon")
function changeFav() {
const link = document.createElement("link"),
oldLink = document.getElementById("dynamic-favicon")
link.id = "dynamic-favicon"
link.rel = "icon"
link.href = faviconCounter % 2 == 0 ? "src/favicon/icon-off.svg" : "src/favicon/icon.svg"
if (oldLink) {
document.head.removeChild(oldLink)
}
document.head.appendChild(link)
faviconCounter++
}
link.id = "dynamic-favicon"
link.rel = "icon"
link.href = faviconCounter % 2 == 0 ? "src/favicon/icon-off.svg" : "src/favicon/icon.svg"
if (oldLink) {
document.head.removeChild(oldLink)
}
document.head.appendChild(link)
faviconCounter++
}
}
function changeFavicon(hasFocus) {
const link = document.createElement("link"),
oldLink = document.getElementById("dynamic-favicon")
const link = document.createElement("link"),
oldLink = document.getElementById("dynamic-favicon")
link.id = "dynamic-favicon"
link.rel = "icon"
link.href = hasFocus ? "src/favicon/icon-off.svg" : "src/favicon/icon.svg"
if (oldLink) {
document.head.removeChild(oldLink)
}
document.head.appendChild(link)
link.id = "dynamic-favicon"
link.rel = "icon"
link.href = hasFocus ? "src/favicon/icon-off.svg" : "src/favicon/icon.svg"
if (oldLink) {
document.head.removeChild(oldLink)
}
document.head.appendChild(link)
}
changeFavicon(true)

View File

@ -7,189 +7,189 @@ const alternatesContainer = document.querySelector("#alternates_container")
const featuresContainer = document.querySelector("#features_container")
function createCodeSection() {
websiteData.sections.forEach((section) => {
if (section.name == "customize") {
fontsFieldset.innerHTML = ""
section.content.fonts.forEach((font, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "font"
input.id = font.id
input.classList.add("example_font")
input.value = font.name
if (index == 0) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = font.name
label.setAttribute("for", font.id)
div.append(input, label)
fontsFieldset.append(div)
})
websiteData.sections.forEach((section) => {
if (section.name == "customize") {
fontsFieldset.innerHTML = ""
section.content.fonts.forEach((font, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "font"
input.id = font.id
input.classList.add("example_font")
input.value = font.name
if (index == 0) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = font.name
label.setAttribute("for", font.id)
div.append(input, label)
fontsFieldset.append(div)
})
exampleFieldset.innerHTML = ""
section.content.languages.forEach((language, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "language"
input.id = language.languageName
input.classList.add("example_language")
input.value = language.languageName
if (index == 0) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = language.languageName
label.setAttribute("for", language.languageName)
div.append(input, label)
exampleFieldset.append(div)
})
exampleFieldset.innerHTML = ""
section.content.languages.forEach((language, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "language"
input.id = language.languageName
input.classList.add("example_language")
input.value = language.languageName
if (index == 0) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = language.languageName
label.setAttribute("for", language.languageName)
div.append(input, label)
exampleFieldset.append(div)
})
weightFieldset.innerHTML = ""
section.content.weights.forEach((weight, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "weight"
input.id = `weight_${weight}`
input.classList.add("example_weight")
input.value = weight
if (index == 6) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = weight
label.setAttribute("for", `weight_${weight}`)
div.append(input, label)
weightFieldset.append(div)
})
weightFieldset.innerHTML = ""
section.content.weights.forEach((weight, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "weight"
input.id = `weight_${weight}`
input.classList.add("example_weight")
input.value = weight
if (index == 6) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = weight
label.setAttribute("for", `weight_${weight}`)
div.append(input, label)
weightFieldset.append(div)
})
featuresContainer.innerHTML = ""
alternatesContainer.innerHTML = ""
section.content.features.forEach((feature, index) => {
const fieldset = document.createElement("fieldset")
const duo = [0, 0]
const p = document.createElement("p")
p.textContent = feature.label
p.id = `alt_${feature.name}`
fieldset.append(p)
duo.forEach((d, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = feature.name
input.id = `${feature.name}${index}`
input.value = `'${feature.feature}' ${index == 0 ? "off" : "on"}`
if (!feature.on && index == 0) input.setAttribute("checked", "true")
if (feature.on && index == 1) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = index == 0 ? "OFF" : "ON"
label.setAttribute("for", `${feature.name}${index}`)
div.append(input, label)
fieldset.append(div)
})
if (feature.type == "feature") featuresContainer.append(fieldset)
else alternatesContainer.append(fieldset)
})
}
})
featuresContainer.innerHTML = ""
alternatesContainer.innerHTML = ""
section.content.features.forEach((feature, index) => {
const fieldset = document.createElement("fieldset")
const duo = [0, 0]
const p = document.createElement("p")
p.textContent = feature.label
p.id = `alt_${feature.name}`
fieldset.append(p)
duo.forEach((d, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = feature.name
input.id = `${feature.name}${index}`
input.value = `'${feature.feature}' ${index == 0 ? "off" : "on"}`
if (!feature.on && index == 0) input.setAttribute("checked", "true")
if (feature.on && index == 1) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = index == 0 ? "OFF" : "ON"
label.setAttribute("for", `${feature.name}${index}`)
div.append(input, label)
fieldset.append(div)
})
if (feature.type == "feature") featuresContainer.append(fieldset)
else alternatesContainer.append(fieldset)
})
}
})
updateExamples(null, exampleForm)
updateExampleSettings(null, exampleSettingsForm)
updateExamples(null, exampleForm)
updateExampleSettings(null, exampleSettingsForm)
}
const codeExample = document.querySelector("#code_example")
function updateExamples(event, form) {
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
websiteData.sections.forEach((section) => {
if (section.name == "customize") {
section.content.languages.forEach((language, index) => {
if (language.languageName == output) {
codeExample.textContent = language.codeExample
let nums = Array.from(new Array(1000), (x, i) => i + 1).join("\n")
codeExample.setAttribute("data-before", nums)
}
})
}
})
websiteData.sections.forEach((section) => {
if (section.name == "customize") {
section.content.languages.forEach((language, index) => {
if (language.languageName == output) {
codeExample.textContent = language.codeExample
let nums = Array.from(new Array(1000), (x, i) => i + 1).join("\n")
codeExample.setAttribute("data-before", nums)
}
})
}
})
if (event) event.preventDefault()
if (event) event.preventDefault()
}
function updateFont(event, form) {
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
codeExample.style.fontFamily = output
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
codeExample.style.fontFamily = output
if (event) event.preventDefault()
if (event) event.preventDefault()
}
function updateWeight(event, form) {
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = +entry[1]
}
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = +entry[1]
}
fontDownloadSettings.weight = output
websiteData.weight = output
document.querySelector("body").style.fontVariationSettings = `"wght" ${websiteData.weight}`
document.querySelector("#download").textContent = `Download CommitMono-${websiteData.weight} with current settings`
fontDownloadSettings.weight = output
websiteData.weight = output
document.querySelector("body").style.fontVariationSettings = `"wght" ${websiteData.weight}`
document.querySelector("#download").textContent = `Download CommitMono-${websiteData.weight} with current settings`
console.log(fontDownloadSettings)
console.log(fontDownloadSettings)
if (event) event.preventDefault()
if (event) event.preventDefault()
}
let fontDownloadSettings = { weight: 450, alternates: {}, features: {} }
let fontDownloadSettingsDefault = {
weight: 450,
alternates: {
cv01: false,
cv02: false,
cv03: false,
cv04: false,
cv05: false,
cv06: false,
cv07: false,
},
features: {
ss01: false,
ss02: false,
ss03: true,
ss04: true,
ss05: true,
},
weight: 450,
alternates: {
cv01: false,
cv02: false,
cv03: false,
cv04: false,
cv05: false,
cv06: false,
cv07: false,
},
features: {
ss01: false,
ss02: false,
ss03: true,
ss04: true,
ss05: true,
},
}
function updateExampleSettings(event, form) {
const data = new FormData(form)
let output = ""
let font = ""
function updateDownloadSettings(type, feature) {
const key = feature.split("' ")[0].slice(1)
const value = feature.split("' ")[1] == "on"
fontDownloadSettings[type][key] = value
}
for (const entry of data) {
if (entry[0] != "font") {
output += `${entry[1]}, `
if (entry[1].includes("cv")) updateDownloadSettings("alternates", entry[1])
if (entry[1].includes("ss")) updateDownloadSettings("features", entry[1])
} else font = entry[1]
const label = document.querySelector(`#alt_${entry[0]}`)
if (label) label.style.fontFeatureSettings = entry[1]
}
const data = new FormData(form)
let output = ""
let font = ""
function updateDownloadSettings(type, feature) {
const key = feature.split("' ")[0].slice(1)
const value = feature.split("' ")[1] == "on"
fontDownloadSettings[type][key] = value
}
for (const entry of data) {
if (entry[0] != "font") {
output += `${entry[1]}, `
if (entry[1].includes("cv")) updateDownloadSettings("alternates", entry[1])
if (entry[1].includes("ss")) updateDownloadSettings("features", entry[1])
} else font = entry[1]
const label = document.querySelector(`#alt_${entry[0]}`)
if (label) label.style.fontFeatureSettings = entry[1]
}
console.log(fontDownloadSettings)
console.log(fontDownloadSettings)
const codeExample = document.querySelector("#code_example")
codeExample.style.fontFeatureSettings = output.slice(0, -2)
const codeExample = document.querySelector("#code_example")
codeExample.style.fontFeatureSettings = output.slice(0, -2)
if (event) event.preventDefault()
if (event) event.preventDefault()
}
createCodeSection()

View File

@ -2,50 +2,50 @@ const familiarContainer = document.querySelector("#familiar_container")
let familiarContent
websiteData.sections.forEach((section) => {
if (section.name == "familiar") familiarContent = section.content
if (section.name == "familiar") familiarContent = section.content
})
function buildFamiliar() {
familiarContainer.innerHTML = ""
familiarContent.timeline.forEach((example, index) => {
const div = document.createElement("div")
div.style.display = index != 0 ? "none" : "block"
div.id = example.name
div.dataset.name = example.name
const svgContainer = document.createElement("div")
svgContainer.innerHTML = familiarContent.svgs[example.name]
const img = document.createElement("img")
img.src = `/src/img/familiar/${example.src}`
example.description.forEach((description) => {
const p = document.createElement("p")
p.textContent = description
p.tabIndex = 0
p.dataset.edit = "true"
div.append(p)
})
const br = document.createElement("br")
div.append(br, svgContainer)
familiarContainer.append(div)
})
familiarContainer.innerHTML = ""
familiarContent.timeline.forEach((example, index) => {
const div = document.createElement("div")
div.style.display = index != 0 ? "none" : "block"
div.id = example.name
div.dataset.name = example.name
const svgContainer = document.createElement("div")
svgContainer.innerHTML = familiarContent.svgs[example.name]
const img = document.createElement("img")
img.src = `/src/img/familiar/${example.src}`
example.description.forEach((description) => {
const p = document.createElement("p")
p.textContent = description
p.tabIndex = 0
p.dataset.edit = "true"
div.append(p)
})
const br = document.createElement("br")
div.append(br, svgContainer)
familiarContainer.append(div)
})
}
buildFamiliar()
function updateFamiliar(event, form) {
buildFamiliar()
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = entry[1]
}
familiarContent.timeline.forEach((example) => {
const exampleContainer = familiarContainer.querySelector(`#${example.name}`)
if (exampleContainer.dataset.name == output) {
exampleContainer.style.display = "block"
} else {
exampleContainer.style.display = "none"
}
})
event.preventDefault()
buildFamiliar()
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = entry[1]
}
familiarContent.timeline.forEach((example) => {
const exampleContainer = familiarContainer.querySelector(`#${example.name}`)
if (exampleContainer.dataset.name == output) {
exampleContainer.style.display = "block"
} else {
exampleContainer.style.display = "none"
}
})
event.preventDefault()
}
// const svgs = {

View File

View File

@ -1,17 +1,17 @@
function updateIntelligent(event, form) {
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
const examples = ["original", "smart_kerning", "before", "after"]
examples.forEach((example) => {
const exampleContainer = document.querySelector(`#${example}`)
if (exampleContainer.id == output) {
exampleContainer.style.display = "block"
} else {
exampleContainer.style.display = "none"
}
})
event.preventDefault()
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
const examples = ["original", "smart_kerning", "before", "after"]
examples.forEach((example) => {
const exampleContainer = document.querySelector(`#${example}`)
if (exampleContainer.id == output) {
exampleContainer.style.display = "block"
} else {
exampleContainer.style.display = "none"
}
})
event.preventDefault()
}

View File

@ -7,169 +7,169 @@ const navForm = document.querySelector("#nav_form")
const changeSetting = document.querySelector("#change_setting p")
websiteData.sections.forEach((section, index) => {
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "nav"
input.id = section.name
input.classList.add("nav_section_input")
input.value = `section_${index + 1}`
if (index == 0) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.for = section.name
label.textContent = `${index + 1 < 10 ? `0${index + 1}` : index + 1} ${capitalize(section.name)}`
label.classList.add("nav_element")
label.dataset.sectionIndex = index + 1
label.setAttribute("for", section.name)
div.append(input, label)
navForm.append(div)
if (index == 0) {
setTimeout(() => {
input.focus()
}, 1)
}
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.name = "nav"
input.id = section.name
input.classList.add("nav_section_input")
input.value = `section_${index + 1}`
if (index == 0) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.for = section.name
label.textContent = `${index + 1 < 10 ? `0${index + 1}` : index + 1} ${capitalize(section.name)}`
label.classList.add("nav_element")
label.dataset.sectionIndex = index + 1
label.setAttribute("for", section.name)
div.append(input, label)
navForm.append(div)
if (index == 0) {
setTimeout(() => {
input.focus()
}, 1)
}
})
function updateNav(event, form) {
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
pageAnimation()
websiteData.sections.forEach((section, index) => {
const sectionContainer = document.querySelector(`#section_${index + 1}`)
if (sectionContainer.id == output) {
sectionContainer.style.display = "block"
} else {
sectionContainer.style.display = "none"
}
})
// pushPage("KeyR")
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${entry[1]}`
}
pageAnimation()
websiteData.sections.forEach((section, index) => {
const sectionContainer = document.querySelector(`#section_${index + 1}`)
if (sectionContainer.id == output) {
sectionContainer.style.display = "block"
} else {
sectionContainer.style.display = "none"
}
})
// pushPage("KeyR")
if (event) event.preventDefault()
if (event) event.preventDefault()
}
function pageAnimation() {
const element = document.querySelector("#page_animation")
element.classList.remove("page_animation")
setTimeout(() => element.classList.add("page_animation"), 10)
const element = document.querySelector("#page_animation")
element.classList.remove("page_animation")
setTimeout(() => element.classList.add("page_animation"), 10)
}
let currentSection = 1
let insideTextField = false
function enterTextField() {
active = document.activeElement
setTimeout(() => {
active.setAttribute("contenteditable", "true")
active.blur()
active.focus()
}, 40)
insideTextField = true
active = document.activeElement
setTimeout(() => {
active.setAttribute("contenteditable", "true")
active.blur()
active.focus()
}, 40)
insideTextField = true
}
function exitTextField() {
document.activeElement.setAttribute("contenteditable", "false")
insideTextField = false
document.activeElement.setAttribute("contenteditable", "false")
insideTextField = false
}
const keys = document.querySelectorAll(".key")
keys.forEach((key) => {
key.addEventListener("click", () => {
if (key.dataset.noclick != "true") {
key.dataset.keyCode.includes("Shift")
? keyDown({ code: key.dataset.keyCode, key: key.dataset.key, shiftKey: true })
: keyDown({ code: key.dataset.keyCode, key: key.dataset.key, shiftKey: false })
key.dataset.keyCode.includes("Shift")
? keyUp({ code: key.dataset.keyCode, key: key.dataset.key, shiftKey: true })
: keyUp({ code: key.dataset.keyCode, key: key.dataset.key, shiftKey: false })
}
})
key.addEventListener("click", () => {
if (key.dataset.noclick != "true") {
key.dataset.keyCode.includes("Shift")
? keyDown({ code: key.dataset.keyCode, key: key.dataset.key, shiftKey: true })
: keyDown({ code: key.dataset.keyCode, key: key.dataset.key, shiftKey: false })
key.dataset.keyCode.includes("Shift")
? keyUp({ code: key.dataset.keyCode, key: key.dataset.key, shiftKey: true })
: keyUp({ code: key.dataset.keyCode, key: key.dataset.key, shiftKey: false })
}
})
})
let changeSettingTimeoutID
function keyDown(e) {
console.log(e.code)
console.log(e.code)
websiteData.tutorial.forEach((key) => {
if (e.code == key) {
const keyNode = document.querySelector(`.key_code_${key}`)
keyNode.classList.add("pressed_key")
}
if (key == "ShiftTab" && e.code == "Tab" && e.shiftKey) {
const keyNode = document.querySelector(".key_code_ShiftTab")
keyNode.classList.add("pressed_key")
}
})
websiteData.tutorial.forEach((key) => {
if (e.code == key) {
const keyNode = document.querySelector(`.key_code_${key}`)
keyNode.classList.add("pressed_key")
}
if (key == "ShiftTab" && e.code == "Tab" && e.shiftKey) {
const keyNode = document.querySelector(".key_code_ShiftTab")
keyNode.classList.add("pressed_key")
}
})
if (e.code == "KeyE" && document.activeElement.dataset.edit == "true" && !insideTextField) enterTextField()
if (e.code == "KeyE" && document.activeElement.dataset.edit == "true" && !insideTextField) enterTextField()
if (e.code == "Escape") exitTextField()
if (e.code == "Escape") exitTextField()
if (!insideTextField) {
// show keypress on frontpage
const activeKey = !e.shiftKey
? document.querySelector(`.key[data-key-code="${e.code}"]`)
: document.querySelector(`.key[data-key-code="Shift${e.code}"]`)
activeKey?.classList.add("active_key")
if (!insideTextField) {
// show keypress on frontpage
const activeKey = !e.shiftKey
? document.querySelector(`.key[data-key-code="${e.code}"]`)
: document.querySelector(`.key[data-key-code="Shift${e.code}"]`)
activeKey?.classList.add("active_key")
if (e.code.includes("Digit")) {
goToSection(e.code)
}
if (e.code.includes("Digit")) {
goToSection(e.code)
}
// push page
if (
e.code == "KeyW" ||
e.code == "KeyA" ||
e.code == "KeyS" ||
e.code == "KeyD" ||
e.code == "KeyR" ||
e.code == "Minus" ||
e.code == "Slash"
) {
pushPage(e.code)
}
// push page
if (
e.code == "KeyW" ||
e.code == "KeyA" ||
e.code == "KeyS" ||
e.code == "KeyD" ||
e.code == "KeyR" ||
e.code == "Minus" ||
e.code == "Slash"
) {
pushPage(e.code)
}
if (e.code == "KeyH") {
document.querySelector("#keyboard_section").classList.toggle("hidden")
}
if (e.code == "KeyH") {
document.querySelector("#keyboard_section").classList.toggle("hidden")
}
if (e.code == "KeyB" || e.code == "KeyL") {
if (e.code == "KeyB") websiteData.weight = websiteData.weight == 700 ? 700 : websiteData.weight + 25
if (e.code == "KeyL") websiteData.weight = websiteData.weight == 300 ? 300 : websiteData.weight - 25
updateCodeFont()
document.querySelector("body").style.fontVariationSettings = `"wght" ${websiteData.weight}`
changeSetting.textContent = `Weight: ${websiteData.weight}. Def: 450, Min: 300, Max: 700.`
changeSetting.style.visibility = "visible"
clearTimeout(changeSettingTimeoutID)
changeSettingTimeoutID = setTimeout(() => (changeSetting.style.visibility = "hidden"), 500)
document.querySelector(
"#download"
).textContent = `Download CommitMono-${websiteData.weight} with current settings`
document.forms["weight_form"][`weight_${websiteData.weight}`].checked = true
}
if (e.code == "KeyB" || e.code == "KeyL") {
if (e.code == "KeyB") websiteData.weight = websiteData.weight == 700 ? 700 : websiteData.weight + 25
if (e.code == "KeyL") websiteData.weight = websiteData.weight == 300 ? 300 : websiteData.weight - 25
updateCodeFont()
document.querySelector("body").style.fontVariationSettings = `"wght" ${websiteData.weight}`
changeSetting.textContent = `Weight: ${websiteData.weight}. Def: 450, Min: 300, Max: 700.`
changeSetting.style.visibility = "visible"
clearTimeout(changeSettingTimeoutID)
changeSettingTimeoutID = setTimeout(() => (changeSetting.style.visibility = "hidden"), 500)
document.querySelector(
"#download"
).textContent = `Download CommitMono-${websiteData.weight} with current settings`
document.forms["weight_form"][`weight_${websiteData.weight}`].checked = true
}
if (e.code == "KeyM") {
if (websiteData.invert) {
setCssVar(["--bg", "#aaa"])
setCssVar(["--text", "#111"])
} else {
setCssVar(["--bg", "#111"])
setCssVar(["--text", "#aaa"])
}
updateCode(null, codeForm)
websiteData.invert = !websiteData.invert
}
}
if (e.code == "KeyM") {
if (websiteData.invert) {
setCssVar(["--bg", "#aaa"])
setCssVar(["--text", "#111"])
} else {
setCssVar(["--bg", "#111"])
setCssVar(["--text", "#aaa"])
}
updateCode(null, codeForm)
websiteData.invert = !websiteData.invert
}
}
}
function keyUp(e) {
const activeKey = document.querySelectorAll(".active_key")
activeKey?.forEach((key) => key.classList.remove("active_key"))
const activeKey = document.querySelectorAll(".active_key")
activeKey?.forEach((key) => key.classList.remove("active_key"))
if (e.code == "Tab" && document.activeElement.id.includes("block_tab")) {
console.log("active nav section then tab")
const checkedMenuInput = document.querySelector("#nav_form input:checked")
checkedMenuInput.focus()
}
if (e.code == "Tab" && document.activeElement.id.includes("block_tab")) {
console.log("active nav section then tab")
const checkedMenuInput = document.querySelector("#nav_form input:checked")
checkedMenuInput.focus()
}
}
window.addEventListener("keydown", keyDown)
@ -181,179 +181,179 @@ const keySection = document.querySelector("#keyboard_section")
let rem = +document.documentElement.style.fontSize.split("px")[0]
function pushPage(keyCode) {
console.log("push page", keyCode)
const x = websiteData.pushPage.coordinates.x
const y = websiteData.pushPage.coordinates.y
const scale = websiteData.pushPage.scale
const dist = websiteData.pushPage.distance
console.log("push page", keyCode)
const x = websiteData.pushPage.coordinates.x
const y = websiteData.pushPage.coordinates.y
const scale = websiteData.pushPage.scale
const dist = websiteData.pushPage.distance
// move left
if (keyCode == "KeyW") {
main.style.transform = `translate(${x}px, ${y + dist}px)`
navForm.style.transform = `translate(${x}px, 0)`
keySection.style.transform = `translate(${x}px, 0)`
websiteData.pushPage.coordinates.y += dist
}
// move left
if (keyCode == "KeyW") {
main.style.transform = `translate(${x}px, ${y + dist}px)`
navForm.style.transform = `translate(${x}px, 0)`
keySection.style.transform = `translate(${x}px, 0)`
websiteData.pushPage.coordinates.y += dist
}
// move left
else if (keyCode == "KeyA") {
main.style.transform = `translate(${x + dist}px, ${y}px)`
navForm.style.transform = `translate(${x + dist}px, 0)`
keySection.style.transform = `translate(${x + dist}px, 0)`
websiteData.pushPage.coordinates.x += dist
}
// move left
else if (keyCode == "KeyA") {
main.style.transform = `translate(${x + dist}px, ${y}px)`
navForm.style.transform = `translate(${x + dist}px, 0)`
keySection.style.transform = `translate(${x + dist}px, 0)`
websiteData.pushPage.coordinates.x += dist
}
// move down
else if (keyCode == "KeyS") {
main.style.transform = `translate(${x}px, ${y - dist}px)`
navForm.style.transform = `translate(${x}px, 0)`
keySection.style.transform = `translate(${x}px, 0)`
websiteData.pushPage.coordinates.y -= dist
}
// move down
else if (keyCode == "KeyS") {
main.style.transform = `translate(${x}px, ${y - dist}px)`
navForm.style.transform = `translate(${x}px, 0)`
keySection.style.transform = `translate(${x}px, 0)`
websiteData.pushPage.coordinates.y -= dist
}
// move right
else if (keyCode == "KeyD") {
main.style.transform = `translate(${x - dist}px, ${y}px)`
navForm.style.transform = `translate(${x - dist}px, 0)`
keySection.style.transform = `translate(${x - dist}px, 0)`
websiteData.pushPage.coordinates.x -= dist
}
// move right
else if (keyCode == "KeyD") {
main.style.transform = `translate(${x - dist}px, ${y}px)`
navForm.style.transform = `translate(${x - dist}px, 0)`
keySection.style.transform = `translate(${x - dist}px, 0)`
websiteData.pushPage.coordinates.x -= dist
}
// zoom in ("Minus" is the plus key, very confusing)
else if (keyCode == "Minus") {
rem = +rem + 2
document.documentElement.style.fontSize = `${rem}px`
updateWaterfall()
document.querySelector("#canvas").style.transform = `scale(${rem / 16})`
changeSetting.textContent = `Base font size: ${rem}px`
changeSetting.style.visibility = "visible"
clearTimeout(changeSettingTimeoutID)
changeSettingTimeoutID = setTimeout(() => (changeSetting.style.visibility = "hidden"), 500)
}
// zoom in ("Minus" is the plus key, very confusing)
else if (keyCode == "Minus") {
rem = +rem + 2
document.documentElement.style.fontSize = `${rem}px`
updateWaterfall()
document.querySelector("#canvas").style.transform = `scale(${rem / 16})`
changeSetting.textContent = `Base font size: ${rem}px`
changeSetting.style.visibility = "visible"
clearTimeout(changeSettingTimeoutID)
changeSettingTimeoutID = setTimeout(() => (changeSetting.style.visibility = "hidden"), 500)
}
// zoom out
else if (keyCode == "Slash") {
rem = +rem - 2
document.documentElement.style.fontSize = `${rem}px`
updateWaterfall()
document.querySelector("#canvas").style.transform = `scale(${rem / 16})`
changeSetting.textContent = `Base font size: ${rem}px`
changeSetting.style.visibility = "visible"
clearTimeout(changeSettingTimeoutID)
changeSettingTimeoutID = setTimeout(() => (changeSetting.style.visibility = "hidden"), 500)
}
// zoom out
else if (keyCode == "Slash") {
rem = +rem - 2
document.documentElement.style.fontSize = `${rem}px`
updateWaterfall()
document.querySelector("#canvas").style.transform = `scale(${rem / 16})`
changeSetting.textContent = `Base font size: ${rem}px`
changeSetting.style.visibility = "visible"
clearTimeout(changeSettingTimeoutID)
changeSettingTimeoutID = setTimeout(() => (changeSetting.style.visibility = "hidden"), 500)
}
// reset transforms
else if (keyCode == "KeyR") {
main.style.transform = `translate(0)`
navForm.style.transform = `translate(0)`
keySection.style.transform = `translate(0)`
mainScale.style.transform = `scale(1)`
websiteData.pushPage.coordinates.x = 0
websiteData.pushPage.coordinates.y = 0
websiteData.pushPage.scale = 1
rem = 16
document.documentElement.style.fontSize = "16px"
document.querySelector("#canvas").style.transform = "scale(1)"
websiteData.weight = 450
document.querySelector("body").style.fontVariationSettings = `"wght" 450`
if (typeof updateCodeFont === "function") updateCodeFont()
if (typeof updateWaterfall === "function") updateWaterfall()
if (typeof createCodeSection === "function") createCodeSection()
}
// reset transforms
else if (keyCode == "KeyR") {
main.style.transform = `translate(0)`
navForm.style.transform = `translate(0)`
keySection.style.transform = `translate(0)`
mainScale.style.transform = `scale(1)`
websiteData.pushPage.coordinates.x = 0
websiteData.pushPage.coordinates.y = 0
websiteData.pushPage.scale = 1
rem = 16
document.documentElement.style.fontSize = "16px"
document.querySelector("#canvas").style.transform = "scale(1)"
websiteData.weight = 450
document.querySelector("body").style.fontVariationSettings = `"wght" 450`
if (typeof updateCodeFont === "function") updateCodeFont()
if (typeof updateWaterfall === "function") updateWaterfall()
if (typeof createCodeSection === "function") createCodeSection()
}
}
let active // saves what DOM element is currently active
let focusTimeOutID // to be able to use clearTimeout()
document.addEventListener("focusin", (e) => {
// console.log("focusin", document.activeElement)
// console.log("focusin", document.activeElement)
// new focus: exit text field
if (document.activeElement != active) exitTextField()
// new focus: exit text field
if (document.activeElement != active) exitTextField()
const prevActive = active
const prevActive = active
// save current focused element
active = document.activeElement
// save current focused element
active = document.activeElement
// // when current focused element is blurred, start a timer of 100ms.
// active.addEventListener("blur", onBlurIn)
// // when current focused element is blurred, start a timer of 100ms.
// active.addEventListener("blur", onBlurIn)
// // clear timeout when a new element is focused
// clearTimeout(focusTimeOutID)
// focusTimeOutID = null
// // clear timeout when a new element is focused
// clearTimeout(focusTimeOutID)
// focusTimeOutID = null
if (active.id.includes("block_tab")) {
console.log("BLOCK TAB")
if (prevActive.className.includes("question_button")) {
prevActive.parentElement.querySelector(".question_button").focus()
} else {
const checkedMenuInput = document.querySelector("#nav_form input:checked")
checkedMenuInput.focus()
}
}
if (active.id.includes("block_tab")) {
console.log("BLOCK TAB")
if (prevActive.className.includes("question_button")) {
prevActive.parentElement.querySelector(".question_button").focus()
} else {
const checkedMenuInput = document.querySelector("#nav_form input:checked")
checkedMenuInput.focus()
}
}
// scroll page, if focus reaches bottom or top
const bounds = active.getBoundingClientRect()
const paddingOffsetBottom = 200
if (bounds.top > window.innerHeight - paddingOffsetBottom) {
const numberOfMoves = Math.floor(
(bounds.top - (window.innerHeight - paddingOffsetBottom)) / websiteData.pushPage.distance
)
for (let i = 0; i < numberOfMoves; i++) {
pushPage("KeyS")
}
}
const paddingOffsetTop = 16
if (bounds.top < paddingOffsetTop) {
const numberOfMoves = Math.ceil(Math.abs(bounds.top - paddingOffsetTop - 32) / websiteData.pushPage.distance)
console.log("num of moves:", numberOfMoves, "bounds.top:", bounds.top)
for (let i = 0; i < numberOfMoves; i++) {
pushPage("KeyW")
}
}
// scroll page, if focus reaches bottom or top
const bounds = active.getBoundingClientRect()
const paddingOffsetBottom = 200
if (bounds.top > window.innerHeight - paddingOffsetBottom) {
const numberOfMoves = Math.floor(
(bounds.top - (window.innerHeight - paddingOffsetBottom)) / websiteData.pushPage.distance
)
for (let i = 0; i < numberOfMoves; i++) {
pushPage("KeyS")
}
}
const paddingOffsetTop = 16
if (bounds.top < paddingOffsetTop) {
const numberOfMoves = Math.ceil(Math.abs(bounds.top - paddingOffsetTop - 32) / websiteData.pushPage.distance)
console.log("num of moves:", numberOfMoves, "bounds.top:", bounds.top)
for (let i = 0; i < numberOfMoves; i++) {
pushPage("KeyW")
}
}
})
let prevHasFocus = true
function checkDocumentFocus() {
if (!isMobile) {
if (prevHasFocus != document.hasFocus()) {
changedFocus(document.hasFocus())
}
prevHasFocus = document.hasFocus()
}
if (!isMobile) {
if (prevHasFocus != document.hasFocus()) {
changedFocus(document.hasFocus())
}
prevHasFocus = document.hasFocus()
}
}
function changedFocus(hasFocus) {
if (hasFocus) active.focus()
changeFavicon(hasFocus)
hasFocus ? contentRoot.classList.remove("faded") : contentRoot.classList.add("faded")
clickFocus.style.visibility = hasFocus ? "hidden" : "visible"
updateCode(null, codeForm)
if (hasFocus) active.focus()
changeFavicon(hasFocus)
hasFocus ? contentRoot.classList.remove("faded") : contentRoot.classList.add("faded")
clickFocus.style.visibility = hasFocus ? "hidden" : "visible"
updateCode(null, codeForm)
}
function onBlurIn(e) {
// remove event listener from so they don't stack
e.target.removeEventListener("blur", onBlurIn)
// remove event listener from so they don't stack
e.target.removeEventListener("blur", onBlurIn)
// if this timer runs out before a new element is focused, refocus same element
if (!isMobile)
focusTimeOutID = setTimeout(() => {
active.focus()
}, 100)
// if this timer runs out before a new element is focused, refocus same element
if (!isMobile)
focusTimeOutID = setTimeout(() => {
active.focus()
}, 100)
}
function goToSection(keyCode) {
pageAnimation()
const section = +keyCode.split("Digit")[1]
const sectionName = websiteData.sections[section - 1]?.name
const attemptedSection = document.querySelector(`[value="section_${section}"]`)
if (attemptedSection && sectionName) {
attemptedSection.focus()
document.forms["nav_form"][sectionName].checked = true
updateNav(null, navForm)
console.log(section, sectionName, attemptedSection)
}
pageAnimation()
const section = +keyCode.split("Digit")[1]
const sectionName = websiteData.sections[section - 1]?.name
const attemptedSection = document.querySelector(`[value="section_${section}"]`)
if (attemptedSection && sectionName) {
attemptedSection.focus()
document.forms["nav_form"][sectionName].checked = true
updateNav(null, navForm)
console.log(section, sectionName, attemptedSection)
}
}
setInterval(checkDocumentFocus, 100)

View File

@ -2,20 +2,20 @@ console.log("opentype test")
const versionOfCommitMono = "V109"
const updateLabel = (input) => {
console.log(input)
input.parentNode.querySelector("output").textContent = input.value
console.log(input)
input.parentNode.querySelector("output").textContent = input.value
}
const updateOptions = (event, form) => {
console.log(event)
console.log(event)
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${output}${entry[0]}=${entry[1]}\n`
}
console.log(output)
event.preventDefault()
const data = new FormData(form)
let output = ""
for (const entry of data) {
output = `${output}${entry[0]}=${entry[1]}\n`
}
console.log(output)
event.preventDefault()
}
let commitMonoFont
@ -37,172 +37,172 @@ let commitMonoFont
// }
async function updateCodeFont() {
opentype
.load(`/src/fonts/instances/CommitMono${versionOfCommitMono}-${websiteData.weight}.otf`)
.then((font) => {
commitMonoFont = font
updateCode(null, codeForm)
})
.catch((err) => console.log(err))
opentype
.load(`/src/fonts/instances/CommitMono${versionOfCommitMono}-${websiteData.weight}.otf`)
.then((font) => {
commitMonoFont = font
updateCode(null, codeForm)
})
.catch((err) => console.log(err))
}
updateCodeFont()
let downloadStarted = false
async function downloadFont(button) {
if (!downloadStarted) {
downloadStarted = true
let downloadableFont
if (button.dataset.type === "staticDefault") {
downloadWithSettings(fontDownloadSettingsDefault, button)
}
if (button.dataset.type === "staticCurrent") {
downloadWithSettings(fontDownloadSettings, button)
console.log(button.dataset.type)
}
if (button.dataset.type === "variableDefault") {
downloadWithSettings(fontDownloadSettingsDefault, button)
console.log(button.dataset.type)
}
}
if (!downloadStarted) {
downloadStarted = true
let downloadableFont
if (button.dataset.type === "staticDefault") {
downloadWithSettings(fontDownloadSettingsDefault, button)
}
if (button.dataset.type === "staticCurrent") {
downloadWithSettings(fontDownloadSettings, button)
console.log(button.dataset.type)
}
if (button.dataset.type === "variableDefault") {
downloadWithSettings(fontDownloadSettingsDefault, button)
console.log(button.dataset.type)
}
}
}
async function downloadWithSettings(settings, button) {
console.log(settings)
button.classList.add("loading")
console.log(settings)
button.classList.add("loading")
const fontFilePath = `/src/fonts/instances/CommitMono${versionOfCommitMono}-${settings.weight}.otf`
const fontFilePath = `/src/fonts/instances/CommitMono${versionOfCommitMono}-${settings.weight}.otf`
opentype
.load(fontFilePath)
.then(async (font) => {
//
// #1 change alternates by switching their paths
// the below loop does this
opentype
.load(fontFilePath)
.then(async (font) => {
//
// #1 change alternates by switching their paths
// the below loop does this
// loop through the alternate settings
Object.entries(settings.alternates).forEach(([alternate, active]) => {
//
// filter for only the active ones
if (!active) return
console.log("alternate", alternate, "active", active)
// loop through the alternate settings
Object.entries(settings.alternates).forEach(([alternate, active]) => {
//
// filter for only the active ones
if (!active) return
console.log("alternate", alternate, "active", active)
// look at all the fonts features
font.tables.gsub.features.forEach((feature) => {
//
// if the feature matches the alternate we're currently on
if (feature.tag == alternate) {
console.log("feature", feature)
// look at all the fonts features
font.tables.gsub.features.forEach((feature) => {
//
// if the feature matches the alternate we're currently on
if (feature.tag == alternate) {
console.log("feature", feature)
// then loop through the list of lookup indexes of that feature
feature.feature.lookupListIndexes.forEach((lookupIndex) => {
console.log("lookupIndex", lookupIndex)
// then loop through the list of lookup indexes of that feature
feature.feature.lookupListIndexes.forEach((lookupIndex) => {
console.log("lookupIndex", lookupIndex)
// loop through the subtable of each lookup at the lookup index
font.tables.gsub.lookups[lookupIndex].subtables.forEach((subtable) => {
console.log("subtable", subtable)
// loop through the subtable of each lookup at the lookup index
font.tables.gsub.lookups[lookupIndex].subtables.forEach((subtable) => {
console.log("subtable", subtable)
// loop through the glyphs of the subtable
subtable.coverage.glyphs.forEach((glyphIndexOriginal, index) => {
//
// glyphIndexOriginal is the index of the original glyph
// glyphIndexSubstitute is the index of the glyph to substitute the original with
const glyphIndexSubstitute = subtable.substitute[index]
console.log("glyphIndexOriginal", glyphIndexOriginal, "glyphIndexSubstitute", glyphIndexSubstitute)
// loop through the glyphs of the subtable
subtable.coverage.glyphs.forEach((glyphIndexOriginal, index) => {
//
// glyphIndexOriginal is the index of the original glyph
// glyphIndexSubstitute is the index of the glyph to substitute the original with
const glyphIndexSubstitute = subtable.substitute[index]
console.log("glyphIndexOriginal", glyphIndexOriginal, "glyphIndexSubstitute", glyphIndexSubstitute)
// get the paths for the original and the substitute glyph
const glyphPathOriginal = font.glyphs.glyphs[glyphIndexOriginal].path
const glyphPathSubstitute = font.glyphs.glyphs[glyphIndexSubstitute].path
// get the paths for the original and the substitute glyph
const glyphPathOriginal = font.glyphs.glyphs[glyphIndexOriginal].path
const glyphPathSubstitute = font.glyphs.glyphs[glyphIndexSubstitute].path
// swap the paths, so the original glyph gets the path of the substitute and vice versa
font.glyphs.glyphs[glyphIndexOriginal].path = glyphPathSubstitute
font.glyphs.glyphs[glyphIndexSubstitute].path = glyphPathOriginal
})
})
})
}
})
})
// swap the paths, so the original glyph gets the path of the substitute and vice versa
font.glyphs.glyphs[glyphIndexOriginal].path = glyphPathSubstitute
font.glyphs.glyphs[glyphIndexSubstitute].path = glyphPathOriginal
})
})
})
}
})
})
//
// "2 put active features into calt
// create empty "calt" feature to store the feature
const emptyCalt = { tag: "calt", feature: { featureParams: 0, lookupListIndexes: [] } }
font.tables.gsub.features.push(emptyCalt)
//
// "2 put active features into calt
// create empty "calt" feature to store the feature
const emptyCalt = { tag: "calt", feature: { featureParams: 0, lookupListIndexes: [] } }
font.tables.gsub.features.push(emptyCalt)
// garbage code that adds a single number to a specific array in the gsub table
// like this [0, 1, 2, 3, 4] => [0, 1, 2, 3, 4, 5]
font.tables.gsub.scripts.forEach((script) =>
script.script.defaultLangSys.featureIndexes.push(script.script.defaultLangSys.featureIndexes.length)
)
// garbage code that adds a single number to a specific array in the gsub table
// like this [0, 1, 2, 3, 4] => [0, 1, 2, 3, 4, 5]
font.tables.gsub.scripts.forEach((script) =>
script.script.defaultLangSys.featureIndexes.push(script.script.defaultLangSys.featureIndexes.length)
)
// create the empty array that is to be the lookup indexes for the calt feature
const caltLookupIndexes = []
// create the empty array that is to be the lookup indexes for the calt feature
const caltLookupIndexes = []
// once again, loop through the alternate settings (feature settings)
Object.entries(settings.features).forEach(([alternate, active]) => {
//
// filter for only the active ones
if (!active) return
console.log("alternate", alternate, "active", active)
// once again, loop through the alternate settings (feature settings)
Object.entries(settings.features).forEach(([alternate, active]) => {
//
// filter for only the active ones
if (!active) return
console.log("alternate", alternate, "active", active)
// then loop through all features
font.tables.gsub.features.forEach((feature) => {
//
// and find the ones that match the active tags
if (feature.tag == alternate) {
console.log("feature", feature)
// then loop through all features
font.tables.gsub.features.forEach((feature) => {
//
// and find the ones that match the active tags
if (feature.tag == alternate) {
console.log("feature", feature)
// push the lookup indexes into the empty caltLookupIndexes variable
feature.feature.lookupListIndexes.forEach((lookupIndex) => caltLookupIndexes.push(lookupIndex))
}
})
// push the lookup indexes into the empty caltLookupIndexes variable
feature.feature.lookupListIndexes.forEach((lookupIndex) => caltLookupIndexes.push(lookupIndex))
}
})
// once more loop through all features
font.tables.gsub.features.forEach((feature) => {
//
// when the calt feature is reached (it's the last one)
if (feature.tag === "calt") {
//
// set its lookup indexes to the variable
feature.feature.lookupListIndexes = caltLookupIndexes
console.log("caltLookupIndexes", caltLookupIndexes)
}
})
})
// once more loop through all features
font.tables.gsub.features.forEach((feature) => {
//
// when the calt feature is reached (it's the last one)
if (feature.tag === "calt") {
//
// set its lookup indexes to the variable
feature.feature.lookupListIndexes = caltLookupIndexes
console.log("caltLookupIndexes", caltLookupIndexes)
}
})
})
//
// #3 change the names
Object.entries(font.names).forEach(([nameKey, nameValue]) => {
const oldName = `CommitMono${versionOfCommitMono}`
const newName = "CommitMono"
if (nameValue.en.includes(oldName)) {
nameValue.en = nameValue.en
.split(oldName)
.map((str, i) => (i == 0 ? newName : str))
.join("")
}
console.log(nameKey)
if (nameKey == "fullName") {
font.names[nameKey].en = nameValue.en.split(" ").join("-")
}
})
font.tables.name = font.names
//
// #3 change the names
Object.entries(font.names).forEach(([nameKey, nameValue]) => {
const oldName = `CommitMono${versionOfCommitMono}`
const newName = "CommitMono"
if (nameValue.en.includes(oldName)) {
nameValue.en = nameValue.en
.split(oldName)
.map((str, i) => (i == 0 ? newName : str))
.join("")
}
console.log(nameKey)
if (nameKey == "fullName") {
font.names[nameKey].en = nameValue.en.split(" ").join("-")
}
})
font.tables.name = font.names
// await wait(1000)
await font.download()
downloadStarted = false
button.classList.remove("loading")
button.classList.add("loaded")
// await wait(1000)
await font.download()
downloadStarted = false
button.classList.remove("loading")
button.classList.add("loaded")
console.log(font)
})
.catch(async (err) => {
await wait(1000)
button.classList.remove("loading")
button.classList.add("error")
console.log(font)
})
.catch(async (err) => {
await wait(1000)
button.classList.remove("loading")
button.classList.add("error")
downloadStarted = false
console.log(err)
})
downloadStarted = false
console.log(err)
})
}

View File

@ -1,15 +1,15 @@
websiteData.sections.forEach((section, index) => {
const topContainer = document.querySelector(`#section_${index + 1} .top_container`)
if (topContainer) {
const h1 = document.createElement("h1")
h1.textContent = `${index + 1 < 10 ? `0${index + 1}` : index + 1} ${capitalize(section.name)}`
h1.tabIndex = 0
h1.dataset.edit = "true"
const br = document.createElement("br")
const p = document.createElement("p")
p.textContent = section.description
p.tabIndex = 0
p.dataset.edit = "true"
topContainer.append(h1, br, p)
}
const topContainer = document.querySelector(`#section_${index + 1} .top_container`)
if (topContainer) {
const h1 = document.createElement("h1")
h1.textContent = `${index + 1 < 10 ? `0${index + 1}` : index + 1} ${capitalize(section.name)}`
h1.tabIndex = 0
h1.dataset.edit = "true"
const br = document.createElement("br")
const p = document.createElement("p")
p.textContent = section.description
p.tabIndex = 0
p.dataset.edit = "true"
topContainer.append(h1, br, p)
}
})

View File

@ -1,68 +1,68 @@
function createTable() {
const table = document.querySelector("#section_2 .content_container table")
const table = document.querySelector("#section_2 .content_container table")
for (let i = 0; i <= 6; i++) {
const tr = document.createElement("tr")
const fieldset = document.createElement("fieldset")
tr.append(fieldset)
for (let j = 0; j <= 16; j++) {
if (i == 0 || j == 0) {
const th = document.createElement("th")
const div = document.createElement("div")
const p = document.createElement("p")
if (i != 0 && j == 0) {
p.textContent = createBinaryString(i + 1, 3)
} else if (i == 0 && j != 0) {
p.textContent = createBinaryString(j - 1, 4)
} else {
p.textContent = ""
}
div.append(p)
th.append(div)
fieldset.append(th)
} else {
const charCode = (i - 1) * 16 + j + 31
for (let i = 0; i <= 6; i++) {
const tr = document.createElement("tr")
const fieldset = document.createElement("fieldset")
tr.append(fieldset)
for (let j = 0; j <= 16; j++) {
if (i == 0 || j == 0) {
const th = document.createElement("th")
const div = document.createElement("div")
const p = document.createElement("p")
if (i != 0 && j == 0) {
p.textContent = createBinaryString(i + 1, 3)
} else if (i == 0 && j != 0) {
p.textContent = createBinaryString(j - 1, 4)
} else {
p.textContent = ""
}
div.append(p)
th.append(div)
fieldset.append(th)
} else {
const charCode = (i - 1) * 16 + j + 31
const td = document.createElement("td")
td.id = `td_${charCode}`
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.id = `char_${charCode}`
input.name = `row_${i}`
input.value = charCode
// input.tabIndex = 1
if (j == 2) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = i == 6 && j == 16 ? "" : String.fromCharCode(charCode)
label.setAttribute("for", `char_${charCode}`)
label.dataset.edit = "true"
div.append(input, label)
td.append(div)
fieldset.append(td)
}
}
table.append(tr)
}
const td = document.createElement("td")
td.id = `td_${charCode}`
const div = document.createElement("div")
const input = document.createElement("input")
input.type = "radio"
input.id = `char_${charCode}`
input.name = `row_${i}`
input.value = charCode
// input.tabIndex = 1
if (j == 2) input.setAttribute("checked", "true")
const label = document.createElement("label")
label.textContent = i == 6 && j == 16 ? "" : String.fromCharCode(charCode)
label.setAttribute("for", `char_${charCode}`)
label.dataset.edit = "true"
div.append(input, label)
td.append(div)
fieldset.append(td)
}
}
table.append(tr)
}
}
const createBinaryString = (number, length) => parseInt(number, 10).toString(2).padStart(length, "0")
createTable()
let previousOutput = [33, 49, 65, 81, 97, 113]
function updateTable(event, form) {
const data = new FormData(form)
let output = []
for (const entry of data) output.push(+entry[1])
let indexOfChange = 0
let offset = 0
output.forEach((row, index) => (row != previousOutput[index] ? (indexOfChange = index) : null))
output.forEach((row, index) => (index == indexOfChange ? (offset = row - previousOutput[index]) : null))
output.forEach((row, index) => {
if (index != indexOfChange) {
document.forms["table_form"][`char_${row + offset}`].checked = true
output[index] += offset
}
})
previousOutput = [...output]
event.preventDefault()
const data = new FormData(form)
let output = []
for (const entry of data) output.push(+entry[1])
let indexOfChange = 0
let offset = 0
output.forEach((row, index) => (row != previousOutput[index] ? (indexOfChange = index) : null))
output.forEach((row, index) => (index == indexOfChange ? (offset = row - previousOutput[index]) : null))
output.forEach((row, index) => {
if (index != indexOfChange) {
document.forms["table_form"][`char_${row + offset}`].checked = true
output[index] += offset
}
})
previousOutput = [...output]
event.preventDefault()
}

View File

@ -1,7 +1,7 @@
// takes a string and returns a string, where the first letter is uppercase
function capitalize(string) {
const stringArray = string.split("")
return stringArray.shift().toUpperCase() + stringArray.join("")
const stringArray = string.split("")
return stringArray.shift().toUpperCase() + stringArray.join("")
}
const mapRange = (value, x1, y1, x2, y2) => ((value - x1) * (y2 - x2)) / (y1 - x1) + x2
@ -10,44 +10,44 @@ const getCssVar = (property) => getComputedStyle(document.documentElement).getPr
const setCssVar = ([property, value]) => document.documentElement.style.setProperty(property, value)
const isMobileTest = () => {
if (window.matchMedia("(pointer: coarse) and (max-width: 1000px").matches) {
console.log("(pointer: coarse) and (max-width: 1000px)")
return true
} else return false
if (window.matchMedia("(pointer: coarse) and (max-width: 1000px").matches) {
console.log("(pointer: coarse) and (max-width: 1000px)")
return true
} else return false
}
const mobileMediaQuery = "(pointer: coarse) and (max-width: 1000px)"
const mql = window.matchMedia(mobileMediaQuery)
let isMobile = mql.matches
mql.addEventListener("change", (e) => {
isMobile = e.matches
changedFocus(true)
isMobile = e.matches
changedFocus(true)
})
function wait(milliseconds) {
return new Promise((resolve) => {
setTimeout(resolve, milliseconds)
})
return new Promise((resolve) => {
setTimeout(resolve, milliseconds)
})
}
function appendStyleSheets() {
const stylesheetIndexes = [
"non_essential",
"section_2",
"section_3",
"section_4",
"section_5",
"section_6",
"section_7",
"section_8",
"section_9",
]
const head = document.querySelector("head")
stylesheetIndexes.forEach((stylesheet) => {
const link = document.createElement("link")
link.setAttribute("rel", "stylesheet")
link.setAttribute("href", `src/css/${stylesheet}.css`)
head.append(link)
})
const stylesheetIndexes = [
"non_essential",
"section_2",
"section_3",
"section_4",
"section_5",
"section_6",
"section_7",
"section_8",
"section_9",
]
const head = document.querySelector("head")
stylesheetIndexes.forEach((stylesheet) => {
const link = document.createElement("link")
link.setAttribute("rel", "stylesheet")
link.setAttribute("href", `src/css/${stylesheet}.css`)
head.append(link)
})
}
appendStyleSheets()

File diff suppressed because one or more lines are too long

View File

@ -1,90 +1,90 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>School timetable</title>
<style>
html {
font-family: sans-serif;
}
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>School timetable</title>
<style>
html {
font-family: sans-serif;
}
table {
border-collapse: collapse;
border: 0.125rem solid rgb(200, 200, 200);
letter-spacing: 0.0625rem;
font-size: 0.8rem;
}
table {
border-collapse: collapse;
border: 0.125rem solid rgb(200, 200, 200);
letter-spacing: 0.0625rem;
font-size: 0.8rem;
}
td,
th {
border: 0.0625rem solid rgb(190, 190, 190);
padding: 10px 20px;
}
td,
th {
border: 0.0625rem solid rgb(190, 190, 190);
padding: 10px 20px;
}
td {
text-align: center;
}
td {
text-align: center;
}
caption {
padding: 10px;
}
</style>
</head>
<body>
<h1>School timetable</h1>
caption {
padding: 10px;
}
</style>
</head>
<body>
<h1>School timetable</h1>
<table>
<tr>
<td>&nbsp;</td>
<th>Mon</th>
<th>Tues</th>
<th>Wed</th>
<th>Thurs</th>
<th>Fri</th>
<th>Sat</th>
<th>Sun</th>
</tr>
<tr>
<th>1st period</th>
<td>English</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>German</td>
<td>Dutch</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<th>2nd period</th>
<td>English</td>
<td>English</td>
<td>&nbsp;</td>
<td>German</td>
<td>Dutch</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<th>3rd period</th>
<td>&nbsp;</td>
<td>German</td>
<td>&nbsp;</td>
<td>German</td>
<td>Dutch</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<th>4th period</th>
<td>&nbsp;</td>
<td>English</td>
<td>&nbsp;</td>
<td>English</td>
<td>Dutch</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</body>
<table>
<tr>
<td>&nbsp;</td>
<th>Mon</th>
<th>Tues</th>
<th>Wed</th>
<th>Thurs</th>
<th>Fri</th>
<th>Sat</th>
<th>Sun</th>
</tr>
<tr>
<th>1st period</th>
<td>English</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>German</td>
<td>Dutch</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<th>2nd period</th>
<td>English</td>
<td>English</td>
<td>&nbsp;</td>
<td>German</td>
<td>Dutch</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<th>3rd period</th>
<td>&nbsp;</td>
<td>German</td>
<td>&nbsp;</td>
<td>German</td>
<td>Dutch</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<th>4th period</th>
<td>&nbsp;</td>
<td>English</td>
<td>&nbsp;</td>
<td>English</td>
<td>Dutch</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</body>
</html>