├── .gitignore
├── .prettierrc
├── 404.html
├── README.md
├── apple-touch-icon.png
├── bun.lockb
├── favicon.ico
├── index.html
├── manifest.webmanifest
├── package-lock.json
├── package.json
└── src
├── css
├── loading.css
├── mobile.css
├── non_essential.css
├── section_1.css
├── section_10.css
├── section_2.css
├── section_3.css
├── section_4.css
├── section_5.css
├── section_6.css
├── section_7.css
├── section_8.css
├── section_9.css
└── style.css
├── favicon
├── icon-192.png
├── icon-512.png
└── icon-512.svg
├── features
├── aalt.fea
├── balance.fea
├── barhyphen.fea
├── colon.fea
├── cv04.fea
├── frac.fea
├── kern_smartkerning.fea
├── liga.fea
├── none.fea
├── pipe.fea
├── posa.fea
├── progress.fea
├── ss01_less_equal-copy.fea
├── ss01_less_equal.fea
├── ss02_arrows.fea
├── ss03_case.fea
├── ss03_case_inter.fea
├── ss04_ellipsis.fea
├── ss05_smartkerning copy 2.fea
├── ss05_smartkerning copy.fea
├── ss05_smartkerning.fea
├── ss06_smartkerning.fea
├── test.fea
└── zero.fea
├── fonts
├── CommitMono-1.143.zip
├── fontlab
│ ├── CommitMonoV143-200Italic.otf
│ ├── CommitMonoV143-200Regular.otf
│ ├── CommitMonoV143-225Italic.otf
│ ├── CommitMonoV143-225Regular.otf
│ ├── CommitMonoV143-250Italic.otf
│ ├── CommitMonoV143-250Regular.otf
│ ├── CommitMonoV143-275Italic.otf
│ ├── CommitMonoV143-275Regular.otf
│ ├── CommitMonoV143-300Italic.otf
│ ├── CommitMonoV143-300Regular.otf
│ ├── CommitMonoV143-325Italic.otf
│ ├── CommitMonoV143-325Regular.otf
│ ├── CommitMonoV143-350Italic.otf
│ ├── CommitMonoV143-350Regular.otf
│ ├── CommitMonoV143-375Italic.otf
│ ├── CommitMonoV143-375Regular.otf
│ ├── CommitMonoV143-400Italic.otf
│ ├── CommitMonoV143-400Regular.otf
│ ├── CommitMonoV143-425Italic.otf
│ ├── CommitMonoV143-425Regular.otf
│ ├── CommitMonoV143-450Italic.otf
│ ├── CommitMonoV143-450Regular.otf
│ ├── CommitMonoV143-475Italic.otf
│ ├── CommitMonoV143-475Regular.otf
│ ├── CommitMonoV143-500Italic.otf
│ ├── CommitMonoV143-500Regular.otf
│ ├── CommitMonoV143-525Italic.otf
│ ├── CommitMonoV143-525Regular.otf
│ ├── CommitMonoV143-550Italic.otf
│ ├── CommitMonoV143-550Regular.otf
│ ├── CommitMonoV143-575Italic.otf
│ ├── CommitMonoV143-575Regular.otf
│ ├── CommitMonoV143-600Italic.otf
│ ├── CommitMonoV143-600Regular.otf
│ ├── CommitMonoV143-625Italic.otf
│ ├── CommitMonoV143-625Regular.otf
│ ├── CommitMonoV143-650Italic.otf
│ ├── CommitMonoV143-650Regular.otf
│ ├── CommitMonoV143-675Italic.otf
│ ├── CommitMonoV143-675Regular.otf
│ ├── CommitMonoV143-700Italic.otf
│ ├── CommitMonoV143-700Regular.otf
│ ├── CommitMonoV143-VF.ttf
│ └── CommitMonoV143-VF.woff2
└── other
│ ├── CascadiaCode.woff2
│ ├── Consolas.woff2
│ ├── FiraCode.woff2
│ ├── JetBrainsMono.woff2
│ ├── Menlo.woff2
│ └── SourceCodePro.woff2
├── img
├── commitmono.png
└── familiar
│ ├── commit_mono.svg
│ ├── fira_mono.svg
│ ├── franklin_gothic.svg
│ ├── letter_gothic.svg
│ └── untitled_sans.svg
├── js
├── code_section.js
├── distinct_section.js
├── docs_section.js
├── download_wizard.js
├── dynamic_favicon.js
├── example_section.js
├── familiar_section.js
├── intelligent_section.js
├── nav.js
├── opentype.min.js
├── section.js
├── start_functions.js
├── table_section.js
├── utility_functions.js
├── website_data.js
└── zip.min.js
├── language_examples
├── brainfuck.bf
├── c++.cpp
├── fortran.f
├── html.html
├── java.java
├── javascript.js
├── kotlin.kts
├── php.php
├── python.py
├── ruby_example.rb
├── rust.rs
└── typescript.ts
├── tests
├── braille.html
├── braille.js
├── calt.js
├── classes.html
├── f.js
├── instances.html
├── letter_group_test.js
└── tables.html
└── txt
├── featuretest.txt
├── installation.txt
├── license.txt
├── todo.txt
├── ttfautohint.txt
└── woff2_conversion_guide.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 | bun.lockb
15 |
16 | # Editor directories and files
17 | .vscode/*
18 | !.vscode/extensions.json
19 | .idea
20 | .DS_Store
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw?
26 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "tabWidth": 4,
4 | "semi": false
5 | }
6 |
--------------------------------------------------------------------------------
/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Commit Mono. Neutral programming typeface.
17 |
18 |
19 |
50 |
51 |
52 | 404
53 | page not found
54 |
55 | Press ENTER to go to home page.
56 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Commit Mono
2 |
3 | Commit Mono is an anonymous and neutral programming typeface focused on creating a better reading experience.
4 |
5 | [**Customize download, explore the font**](https://commitmono.com/)
6 |
7 | [**Download latest default version**](https://github.com/eigilnikolajsen/commit-mono/releases/latest/)
8 |
9 |
10 |
11 | If you wish to support this project directly [**buy me a coffee**](https://www.buymeacoffee.com/eigilnikolajsen).
12 |
13 | 
14 |
--------------------------------------------------------------------------------
/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/apple-touch-icon.png
--------------------------------------------------------------------------------
/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/bun.lockb
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/favicon.ico
--------------------------------------------------------------------------------
/manifest.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "icons": [
3 | { "src": "/src/favicon/icon-192.png", "type": "image/png", "sizes": "192x192" },
4 | { "src": "/src/favicon/icon-512.png", "type": "image/png", "sizes": "512x512" }
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "commit-webtests",
3 | "version": "0.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "commit-webtests",
9 | "version": "0.0.0",
10 | "devDependencies": {
11 | "vite": "^5.0.12"
12 | }
13 | },
14 | "node_modules/@esbuild/darwin-x64": {
15 | "version": "0.19.11",
16 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz",
17 | "integrity": "sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==",
18 | "cpu": [
19 | "x64"
20 | ],
21 | "dev": true,
22 | "optional": true,
23 | "os": [
24 | "darwin"
25 | ],
26 | "engines": {
27 | "node": ">=12"
28 | }
29 | },
30 | "node_modules/@rollup/rollup-darwin-x64": {
31 | "version": "4.9.6",
32 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz",
33 | "integrity": "sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==",
34 | "cpu": [
35 | "x64"
36 | ],
37 | "dev": true,
38 | "optional": true,
39 | "os": [
40 | "darwin"
41 | ]
42 | },
43 | "node_modules/@types/estree": {
44 | "version": "1.0.5",
45 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
46 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
47 | "dev": true
48 | },
49 | "node_modules/esbuild": {
50 | "version": "0.19.11",
51 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz",
52 | "integrity": "sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==",
53 | "dev": true,
54 | "hasInstallScript": true,
55 | "bin": {
56 | "esbuild": "bin/esbuild"
57 | },
58 | "engines": {
59 | "node": ">=12"
60 | },
61 | "optionalDependencies": {
62 | "@esbuild/aix-ppc64": "0.19.11",
63 | "@esbuild/android-arm": "0.19.11",
64 | "@esbuild/android-arm64": "0.19.11",
65 | "@esbuild/android-x64": "0.19.11",
66 | "@esbuild/darwin-arm64": "0.19.11",
67 | "@esbuild/darwin-x64": "0.19.11",
68 | "@esbuild/freebsd-arm64": "0.19.11",
69 | "@esbuild/freebsd-x64": "0.19.11",
70 | "@esbuild/linux-arm": "0.19.11",
71 | "@esbuild/linux-arm64": "0.19.11",
72 | "@esbuild/linux-ia32": "0.19.11",
73 | "@esbuild/linux-loong64": "0.19.11",
74 | "@esbuild/linux-mips64el": "0.19.11",
75 | "@esbuild/linux-ppc64": "0.19.11",
76 | "@esbuild/linux-riscv64": "0.19.11",
77 | "@esbuild/linux-s390x": "0.19.11",
78 | "@esbuild/linux-x64": "0.19.11",
79 | "@esbuild/netbsd-x64": "0.19.11",
80 | "@esbuild/openbsd-x64": "0.19.11",
81 | "@esbuild/sunos-x64": "0.19.11",
82 | "@esbuild/win32-arm64": "0.19.11",
83 | "@esbuild/win32-ia32": "0.19.11",
84 | "@esbuild/win32-x64": "0.19.11"
85 | }
86 | },
87 | "node_modules/fsevents": {
88 | "version": "2.3.3",
89 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
90 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
91 | "dev": true,
92 | "hasInstallScript": true,
93 | "optional": true,
94 | "os": [
95 | "darwin"
96 | ],
97 | "engines": {
98 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
99 | }
100 | },
101 | "node_modules/nanoid": {
102 | "version": "3.3.7",
103 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
104 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
105 | "dev": true,
106 | "funding": [
107 | {
108 | "type": "github",
109 | "url": "https://github.com/sponsors/ai"
110 | }
111 | ],
112 | "bin": {
113 | "nanoid": "bin/nanoid.cjs"
114 | },
115 | "engines": {
116 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
117 | }
118 | },
119 | "node_modules/picocolors": {
120 | "version": "1.0.0",
121 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
122 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
123 | "dev": true
124 | },
125 | "node_modules/postcss": {
126 | "version": "8.4.33",
127 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz",
128 | "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==",
129 | "dev": true,
130 | "funding": [
131 | {
132 | "type": "opencollective",
133 | "url": "https://opencollective.com/postcss/"
134 | },
135 | {
136 | "type": "tidelift",
137 | "url": "https://tidelift.com/funding/github/npm/postcss"
138 | },
139 | {
140 | "type": "github",
141 | "url": "https://github.com/sponsors/ai"
142 | }
143 | ],
144 | "dependencies": {
145 | "nanoid": "^3.3.7",
146 | "picocolors": "^1.0.0",
147 | "source-map-js": "^1.0.2"
148 | },
149 | "engines": {
150 | "node": "^10 || ^12 || >=14"
151 | }
152 | },
153 | "node_modules/rollup": {
154 | "version": "4.9.6",
155 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz",
156 | "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==",
157 | "dev": true,
158 | "dependencies": {
159 | "@types/estree": "1.0.5"
160 | },
161 | "bin": {
162 | "rollup": "dist/bin/rollup"
163 | },
164 | "engines": {
165 | "node": ">=18.0.0",
166 | "npm": ">=8.0.0"
167 | },
168 | "optionalDependencies": {
169 | "@rollup/rollup-android-arm-eabi": "4.9.6",
170 | "@rollup/rollup-android-arm64": "4.9.6",
171 | "@rollup/rollup-darwin-arm64": "4.9.6",
172 | "@rollup/rollup-darwin-x64": "4.9.6",
173 | "@rollup/rollup-linux-arm-gnueabihf": "4.9.6",
174 | "@rollup/rollup-linux-arm64-gnu": "4.9.6",
175 | "@rollup/rollup-linux-arm64-musl": "4.9.6",
176 | "@rollup/rollup-linux-riscv64-gnu": "4.9.6",
177 | "@rollup/rollup-linux-x64-gnu": "4.9.6",
178 | "@rollup/rollup-linux-x64-musl": "4.9.6",
179 | "@rollup/rollup-win32-arm64-msvc": "4.9.6",
180 | "@rollup/rollup-win32-ia32-msvc": "4.9.6",
181 | "@rollup/rollup-win32-x64-msvc": "4.9.6",
182 | "fsevents": "~2.3.2"
183 | }
184 | },
185 | "node_modules/source-map-js": {
186 | "version": "1.0.2",
187 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
188 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
189 | "dev": true,
190 | "engines": {
191 | "node": ">=0.10.0"
192 | }
193 | },
194 | "node_modules/vite": {
195 | "version": "5.0.12",
196 | "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz",
197 | "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==",
198 | "dev": true,
199 | "dependencies": {
200 | "esbuild": "^0.19.3",
201 | "postcss": "^8.4.32",
202 | "rollup": "^4.2.0"
203 | },
204 | "bin": {
205 | "vite": "bin/vite.js"
206 | },
207 | "engines": {
208 | "node": "^18.0.0 || >=20.0.0"
209 | },
210 | "funding": {
211 | "url": "https://github.com/vitejs/vite?sponsor=1"
212 | },
213 | "optionalDependencies": {
214 | "fsevents": "~2.3.3"
215 | },
216 | "peerDependencies": {
217 | "@types/node": "^18.0.0 || >=20.0.0",
218 | "less": "*",
219 | "lightningcss": "^1.21.0",
220 | "sass": "*",
221 | "stylus": "*",
222 | "sugarss": "*",
223 | "terser": "^5.4.0"
224 | },
225 | "peerDependenciesMeta": {
226 | "@types/node": {
227 | "optional": true
228 | },
229 | "less": {
230 | "optional": true
231 | },
232 | "lightningcss": {
233 | "optional": true
234 | },
235 | "sass": {
236 | "optional": true
237 | },
238 | "stylus": {
239 | "optional": true
240 | },
241 | "sugarss": {
242 | "optional": true
243 | },
244 | "terser": {
245 | "optional": true
246 | }
247 | }
248 | }
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "commit-webtests",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "commonjs",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "devDependencies": {
12 | "vite": "^5.0.12"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/css/loading.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "CommitMonoLoading";
3 | src: url("data:font/woff2;charset=url-8;base64,d09GMk9UVE8AAAVoAAoAAAAACRAAAAUgAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAADYcqGhYGYACCcgE2AiQDIgQGBYQhByAbVAgRZJPTIvuRkLnpo1niWFGcZNnEK1FCUU4/x8PT2u/PnZ3dh6g3CJGQRBORpJVGg67f6q9Ns3ed4+/dNQeGD6Q1Nv+/r3HXBE48osgCyvt7NvUTYnINZZJwUNelEzGpqkxUH92fDB0zXaUP82xFMJQsXXOHVdpANttEIhM32xM/y6P+MHZhAh4hJxTKBbrhm89nfEyZeMKSimREp600nifplvNJJ34a/VkBz5F8L+EFZeCFSvKWUsig+NR/R0ZgyZDGIvDSwGSjyt9iLXIEIdUwnqN2Eiag0Go3YpZ2uyOTcHUKJe4KKRInfhZA3BH3KPTa1jUwMjW34E8oZC3tOm14RybSiV8CM8EswZ2BYK7G3WoT1eM4OBCww4CQ/0grvTR5bXZ2cnJ2ztqkpUvXrlvCqo+2rtrF72jXPnwM5x5SebwLrKI9x4/tO2lFSnl5RkqXP9vhF3Ul/HqgT++reCFN7bm85urm6zukd8WH8k80PNbBHMnbfi1Ygsk+Ewyn2MfivKuFiQ361vzVM1du3zn/BDf0iAjL9o2Z7Kaj8lzaxn2+WZ1am9An5uYS0pab2kJMyaNISGuk3cc/AwUa3/jsxbNaA1Zj1eQ+7hzYJknff3H9xQ2X10rviU83nGku0fFVXjj3lKRp3YzUkXqsdcIK7MlRebjPGywHbWdlRmsSq8ar2qD/nYftsKFtQpe269bK+0M6YduD7Q+pd0egDK7T4xblNzXn5TU15i0a6//gheO5RryXpn4MaUzfumjq+JV2jhNSy3PSk4u5wcn0rF1rF8/Uub+bADqw+Nr59fHICkywWC+mvh7ZsjskJtw/ONybOxYRfSpWD8SDuz8zjqTsjuUeteER4r7GX9u189IOPSYHDDabGjkvYx1XZeXVe3auX6lbE7Q5dh+rPn+TZ25+ASst7DVeZPWQegNkD97hJjbwq/CJoeD2h8EGMfUF5N3G9PKkdZlZiUm69/rEZcvXrV+2kBPb+W83Cdj1iIR6GEvzleUvdf2zV4KN6saCJDP1ekAs2yY5sGnDiY364WsyHnLqsB33IgA9hIPie6f1gCbJx/L2Ow0ZC4aw+PcjnpAAOfam9ahZa6dsYk8/GvQnTaw+eot3ukU0PYKqxySUHaWB+QwyMKhka5BhRmuDLakBSj/BFsBwt4SuEx+DCnLUP375st6AVedNNLhy6qPe3VO8n5zHhd5ivMo7ylty1Js/4w3T4gopc6PsthzOKW7fViozCyOr7ihV/Adj6KaLIAu6KMJTL+80vZKGuIJqm/Gc4ARBye4ep2gcIxAk2uHOt6z2oeI+AnMMHrwKfRBX1Yn/XgiqV+jDEvAAaUpQVMbhQqVPiQYFmGITYUPjK626Tk2Kq04ULit/PgOKGsEbWgtt27SjQ6fsHBgRZstv321OjERlQLEZl0IalH5zlJ/leblVov5H/A/7H/o/GFkrVe6Hj7cN3r2/07C4d8BPVfUG4UvYu0B7XoTTKBQvTgILkkKgWl1ZeII95O98bdJy+6Y6fmDlb51Xaocv2hU3QDqOGmDnfJm6PNe1hP6x6pJWSEiBbFwE1Lptypq0/jU2kWUoLNhDkPS4AZUzL5Bt+YHaRHDSBhKjb+N2c7H+U0jpsxD/Imn8NZKvzdrGzuo09DDFCJvgDVwXEcOKxvB0IrnZ0UzDHZbzF5JiEhhaTrOlQlHaWpaS0GVp19ozUcDlJtuojBhThsdj6sLDGy/MoCNODT2409BVrVsWGh9kAA==");
4 | font-style: normal;
5 | font-weight: 400;
6 | font-display: swap;
7 | }
8 | *,
9 | *::before,
10 | *::after {
11 | box-sizing: border-box;
12 | margin: 0;
13 | padding: 0;
14 | }
15 | :root {
16 | --text: #111;
17 | --middle: #555;
18 | --bg: #aaa;
19 | --max-width: 54ch;
20 | font-size: 16px;
21 | }
22 | body {
23 | background: var(--bg);
24 | color: var(--text);
25 | font-family: "CommitMono", monospace;
26 | -webkit-font-smoothing: antialiased;
27 | -moz-osx-font-smoothing: grayscale;
28 | font-size: 0.75rem;
29 | line-height: 1rem;
30 | font-feature-settings: "ss01", "ss03", "ss04", "ss05";
31 | overflow: hidden;
32 | }
33 |
34 | #loading {
35 | position: fixed;
36 | inset: 0;
37 | display: grid;
38 | place-content: center;
39 | background-color: var(--bg);
40 | z-index: 200;
41 | }
42 |
43 | #loading p {
44 | width: 10ch;
45 | font-family: "CommitMonoLoading";
46 | }
47 |
48 | #loading p::after {
49 | content: "...";
50 | animation: 500ms forwards infinite loading_animation;
51 | }
52 |
53 | @keyframes loading_animation {
54 | 0% {
55 | content: "";
56 | }
57 | 25% {
58 | content: ".";
59 | }
60 | 50% {
61 | content: "..";
62 | }
63 | 75% {
64 | content: "...";
65 | }
66 | 100% {
67 | content: "";
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/css/mobile.css:
--------------------------------------------------------------------------------
1 | @media (pointer: coarse) and (max-width: 1000px) {
2 | body {
3 | overflow: visible;
4 | }
5 | #main_scale,
6 | main {
7 | position: relative;
8 | }
9 | header #keyboard_section {
10 | visibility: hidden;
11 | }
12 | #footer_hint {
13 | display: none;
14 | }
15 | #footer_hint_mobile {
16 | display: block;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/css/non_essential.css:
--------------------------------------------------------------------------------
1 | button {
2 | vertical-align: top;
3 | border: none;
4 | background: transparent;
5 | font-family: inherit;
6 | font-size: 0.75rem;
7 | font-variation-settings: inherit;
8 | line-height: 1rem;
9 | width: max-content;
10 | white-space: nowrap;
11 | text-align: left;
12 | position: relative;
13 | font-feature-settings: inherit;
14 | }
15 |
16 | button:active {
17 | background: var(--bg75);
18 | }
19 |
20 | #app_root.no_focus {
21 | opacity: 0.5;
22 | }
23 |
24 | :focus,
25 | input:focus + label {
26 | animation: flicker 50ms 2;
27 | }
28 |
29 | @keyframes flicker {
30 | 0%,
31 | 49% {
32 | opacity: 0;
33 | }
34 | 50%,
35 | 100% {
36 | opacity: 1;
37 | }
38 | }
39 |
40 | @keyframes flicker_reverse {
41 | 0%,
42 | 49% {
43 | opacity: 1;
44 | }
45 | 50%,
46 | 100% {
47 | opacity: 0;
48 | }
49 | }
50 |
51 | .top_container p {
52 | white-space: pre-wrap;
53 | }
54 |
55 | .line-through {
56 | text-decoration: line-through;
57 | }
58 |
59 | h2 {
60 | font-size: 0.75rem;
61 | line-height: 1rem;
62 | font-weight: normal;
63 | width: fit-content;
64 | font-variation-settings: "wght" 700;
65 | }
66 |
67 | a,
68 | a:visited {
69 | color: var(--text);
70 | }
71 |
72 | p:focus a,
73 | a:focus {
74 | text-decoration: none;
75 | background-color: var(--text);
76 | color: var(--bg);
77 | text-decoration: none;
78 | }
79 |
80 | #click_focus,
81 | #change_setting {
82 | inset: 0;
83 | position: fixed;
84 | z-index: 999;
85 | display: grid;
86 | place-content: center;
87 | visibility: hidden;
88 | pointer-events: none;
89 | }
90 |
91 | .span_key.pressed_key {
92 | position: relative;
93 | background: var(--bg25);
94 | }
95 |
96 | ul:focus .span_key.pressed_key {
97 | background: var(--bg25-i);
98 | }
99 |
100 | .span_key.pressed_key::after {
101 | content: " ✓";
102 | position: absolute;
103 | right: -1ch;
104 | top: -0.5rem;
105 | }
106 |
107 | #keyboard_container.use_keyboard_animation {
108 | animation: flicker 140ms 8;
109 | }
110 |
--------------------------------------------------------------------------------
/src/css/section_1.css:
--------------------------------------------------------------------------------
1 | #keyboard_container {
2 | font-size: 0.75rem;
3 | display: flex;
4 | width: max-content;
5 | gap: 4ch;
6 | align-items: end;
7 | }
8 |
9 | .key_group {
10 | display: flex;
11 | flex-direction: column;
12 | }
13 |
14 | .keys {
15 | display: flex;
16 | gap: 0.5ch;
17 | margin-bottom: 0.125rem;
18 | }
19 |
20 | .key {
21 | line-height: 0.85rem;
22 | display: inline;
23 | border: 0.0625rem solid var(--text);
24 | border-bottom: 0.125rem solid var(--text);
25 | padding: 0 calc(0.5ch - 0.0625rem);
26 | user-select: none;
27 | }
28 |
29 | .key:hover {
30 | cursor: pointer;
31 | }
32 |
33 | .key[data-noclick="true"]:hover {
34 | cursor: not-allowed;
35 | }
36 |
37 | .key.active_key,
38 | .key:active {
39 | background: var(--text);
40 | color: var(--bg);
41 | line-height: 0.75rem;
42 | margin-top: 0.1rem;
43 | }
44 |
45 | #tutorial li {
46 | margin-top: 0.3rem;
47 | }
48 |
49 | .span_key {
50 | display: inline;
51 | border: 0.0625rem solid var(--text);
52 | border-bottom: 0.125rem solid var(--text);
53 | padding: 0 calc(0.5ch - 0.0625rem);
54 | }
55 |
56 | *:focus .span_key {
57 | border: 0.0625rem solid var(--bg);
58 | border-bottom: 0.125rem solid var(--bg);
59 | }
60 |
--------------------------------------------------------------------------------
/src/css/section_10.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/css/section_10.css
--------------------------------------------------------------------------------
/src/css/section_2.css:
--------------------------------------------------------------------------------
1 | table {
2 | margin: 4rem 0 2rem 0;
3 | border-collapse: collapse;
4 | }
5 |
6 | th > div > p,
7 | td > div > p {
8 | font-size: 0.5rem;
9 | font-weight: normal;
10 | text-align: center;
11 | }
12 |
13 | th > div,
14 | td > div {
15 | width: 6rem;
16 | aspect-ratio: 1 / 1;
17 | display: grid;
18 | justify-content: center;
19 | }
20 |
21 | tr:first-of-type th > div {
22 | width: 6rem;
23 | aspect-ratio: 3 / 1;
24 | }
25 |
26 | td > div > input,
27 | td > div > label,
28 | td > div > p {
29 | grid-row: 1;
30 | grid-column: 1;
31 | display: inline-block;
32 | margin: auto;
33 | white-space: pre;
34 | text-align: center;
35 | line-height: 1.1;
36 | }
37 |
38 | tr th:first-of-type > div {
39 | font-size: 0.5rem;
40 | width: 2rem;
41 | justify-content: start;
42 | }
43 |
44 | tr th:first-of-type > div > p {
45 | font-size: 0.5rem;
46 | text-align: start;
47 | }
48 |
49 | td > div > input + label {
50 | font-size: 4rem;
51 | height: auto;
52 | }
53 |
54 | #section_2 fieldset {
55 | border: none;
56 | display: block;
57 | }
58 |
59 | #section_2 input[type="radio"] {
60 | width: 0;
61 | height: 0;
62 | opacity: 0;
63 | -webkit-user-modify: read-only;
64 | }
65 | #section_2 input[type="radio"]:focus:checked + label {
66 | background: var(--text);
67 | color: var(--bg);
68 | scale: 4;
69 | z-index: 2;
70 | }
71 | #section_2 input[type="radio"]:checked + label {
72 | scale: 1;
73 | background: var(--bg);
74 | color: var(--text);
75 | }
76 |
--------------------------------------------------------------------------------
/src/css/section_3.css:
--------------------------------------------------------------------------------
1 | #familiar_form fieldset {
2 | border: none;
3 | display: flex;
4 | gap: 1rem;
5 | position: relative;
6 | width: fit-content;
7 | }
8 |
9 | #familiar_form fieldset::before {
10 | content: "";
11 | position: absolute;
12 | height: 0.0625rem;
13 | bottom: 0.125rem;
14 | left: 1rem;
15 | right: 1rem;
16 | background-color: var(--text);
17 | }
18 |
19 | #familiar_form fieldset div {
20 | display: flex;
21 | flex-direction: column-reverse;
22 | align-items: center;
23 | gap: 0.5rem;
24 | }
25 |
26 | #familiar_form input[type="radio"] {
27 | -webkit-appearance: none;
28 | appearance: none;
29 | background-color: var(--text);
30 |
31 | display: block;
32 | width: 0.375rem;
33 | height: 0.375rem;
34 |
35 | opacity: 1;
36 |
37 | /* display: grid; */
38 | /* place-content: center; */
39 | }
40 |
41 | #familiar_form label {
42 | display: inline;
43 | height: auto;
44 | }
45 |
46 | #familiar_form input[type="radio"]:checked {
47 | transform: scale(1.5);
48 | }
49 |
50 | #familiar_form input[type="radio"]:focus {
51 | transform: scale(2);
52 | }
53 |
54 | #familiar_form fieldset > div:nth-child(2) {
55 | margin-left: 16rem;
56 | }
57 |
58 | #familiar_form fieldset > div:nth-child(3) {
59 | margin-left: 15rem;
60 | }
61 |
62 | #familiar_form fieldset > div:nth-child(5) {
63 | margin-left: 1rem;
64 | }
65 |
66 | cite {
67 | font-style: normal;
68 | }
69 |
70 | figure {
71 | width: max-content;
72 | }
73 |
74 | blockquote,
75 | cite {
76 | font-variation-settings: "ital" 1;
77 | }
78 |
79 | blockquote,
80 | blockquote ~ * {
81 | font-size: 0.75rem;
82 | padding-left: 2ch;
83 | position: relative;
84 | border-left: 0.0625rem solid var(--text);
85 | max-width: var(--max-width);
86 | }
87 |
88 | blockquote::before {
89 | content: "“";
90 | left: -0.5ch;
91 | top: 0;
92 | font-size: 1.5rem;
93 | line-height: 2rem;
94 | }
95 |
96 | #familiar_container svg {
97 | width: 100rem;
98 | height: 20rem;
99 | }
100 |
101 | #familiar_container svg {
102 | width: 100rem;
103 | height: 20rem;
104 | }
105 |
106 | .svg_container {
107 | width: 100rem;
108 | height: 20rem;
109 | }
110 |
111 | #familiar_container svg path {
112 | fill: var(--text);
113 | }
114 |
115 | #familiar_container .svg_container:focus svg path {
116 | fill: var(--bg);
117 | }
118 |
--------------------------------------------------------------------------------
/src/css/section_4.css:
--------------------------------------------------------------------------------
1 | #original figure > div,
2 | #smart_kerning figure > div {
3 | display: flex;
4 | }
5 |
6 | #original p,
7 | #smart_kerning p {
8 | font-size: 24rem;
9 | line-height: 1;
10 | position: relative;
11 | border-right: 0.0625rem solid var(--text);
12 | border-left: 0.0625rem solid var(--text);
13 | margin-left: -0.0625rem;
14 | }
15 |
16 | #original p::after,
17 | #smart_kerning p::after {
18 | font-size: 0.75rem;
19 | text-align: center;
20 | display: block;
21 | width: 100%;
22 | }
23 |
24 | #original p:nth-child(1)::after,
25 | #smart_kerning p:nth-child(1)::after {
26 | content: "Wide letter";
27 | }
28 |
29 | #original p:nth-child(2)::after {
30 | content: "Smart kerning OFF";
31 | }
32 |
33 | #smart_kerning p:nth-child(2)::after {
34 | content: "Smart kerning ON";
35 | }
36 |
37 | #original p:nth-child(3)::after,
38 | #smart_kerning p:nth-child(3)::after {
39 | content: "Narrow letter";
40 | }
41 |
42 | #smart_kerning p:nth-child(2) {
43 | transform: translateX(calc(24rem / 1000 * 44));
44 | border-right: 0.0625rem solid transparent;
45 | border-left: 0.0625rem solid transparent;
46 | }
47 |
48 | #intelligent_container figure > div:focus p {
49 | border-right: 0.0625rem solid var(--bg);
50 | border-left: 0.0625rem solid var(--bg);
51 | }
52 |
53 | #intelligent_container figure > div:focus p:nth-child(2) {
54 | border-right: 0.0625rem solid transparent;
55 | border-left: 0.0625rem solid transparent;
56 | }
57 |
58 | #before p,
59 | #after p {
60 | font-size: 8rem;
61 | line-height: 1;
62 | max-width: none;
63 | white-space: nowrap;
64 | }
65 |
66 | #before p {
67 | font-feature-settings: "ss05" 0;
68 | font-variant-ligatures: none;
69 | }
70 |
71 | #after p {
72 | font-feature-settings: "ss05" 1;
73 | }
74 |
--------------------------------------------------------------------------------
/src/css/section_5.css:
--------------------------------------------------------------------------------
1 | #code_form fieldset {
2 | font-size: 1.5rem;
3 | line-height: 1.65rem;
4 | gap: 1ch;
5 | }
6 |
7 | form fieldset {
8 | border: none;
9 | display: flex;
10 | gap: 4ch;
11 | font-size: 0.75rem;
12 | line-height: 1rem;
13 | background-color: var(--bg);
14 | width: max-content;
15 | }
16 |
17 | form > div {
18 | position: relative;
19 | }
20 |
21 | #canvas {
22 | transform-origin: top left;
23 | }
24 |
25 | #code_description {
26 | height: 4rem;
27 | }
28 |
--------------------------------------------------------------------------------
/src/css/section_6.css:
--------------------------------------------------------------------------------
1 | #waterfall {
2 | display: flex;
3 | width: min-content;
4 | gap: 2rem;
5 | }
6 |
7 | .waterfall_texts_container {
8 | display: flex;
9 | flex-direction: column;
10 | justify-content: end;
11 | height: 10rem;
12 | }
13 |
14 | .waterfall_texts_container > div {
15 | height: 2.5rem;
16 | display: flex;
17 | align-items: end;
18 | }
19 |
20 | .waterfall_text {
21 | line-height: 0.6;
22 | white-space: pre;
23 | }
24 |
25 | .waterfall_desc {
26 | width: max-content;
27 | white-space: pre;
28 | }
29 |
30 | .question_container {
31 | display: flex;
32 | align-items: center;
33 | font-size: 0.75rem;
34 | gap: 2ch;
35 | position: relative;
36 | margin-top: 1rem;
37 | }
38 |
39 | .question_character.hide_character {
40 | opacity: 1;
41 | animation: 0ms 0s 3 forwards flicker_reverse;
42 | }
43 |
44 | .question_character.show_character {
45 | opacity: 0;
46 | animation: 100ms 0s 3 forwards flicker;
47 | }
48 |
49 | .button_container button {
50 | display: block;
51 | }
52 |
53 | :root {
54 | --question-character-size: 2rem;
55 | }
56 |
57 | .question_character {
58 | font-size: var(--question-character-size);
59 | line-height: var(--question-character-size);
60 | border: 0.0625rem solid var(--text);
61 | position: relative;
62 | }
63 | .question_character::after {
64 | content: "";
65 | position: absolute;
66 | left: 0;
67 | right: 0;
68 | bottom: 15%;
69 | /* height: 0.0625rem; */
70 | background-color: var(--text);
71 | }
72 |
73 | #score_points {
74 | display: none;
75 | }
76 | #score_points.view_score {
77 | display: block;
78 | }
79 |
80 | .question_button:focus::before,
81 | .question_button:hover::before {
82 | content: "<-";
83 | position: absolute;
84 | left: -2ch;
85 | color: var(--text);
86 | }
87 | .question_button:hover {
88 | background: var(--bg50);
89 | color: var(--bg);
90 | cursor: pointer;
91 | text-decoration: none;
92 | }
93 | .question_button.right_button::before {
94 | content: "<-";
95 | position: absolute;
96 | left: -2ch;
97 | color: var(--text);
98 | }
99 | .question_button.wrong_button::before {
100 | content: "->";
101 | position: absolute;
102 | left: auto;
103 | right: -2ch;
104 | color: var(--text);
105 | }
106 |
107 | .question_button.button_choice {
108 | background: var(--bg25);
109 | color: var(--text);
110 | text-decoration: none;
111 | }
112 | .question_button.button_choice:focus {
113 | background: var(--bg75);
114 | color: var(--bg);
115 | text-decoration: none;
116 | }
117 | .question_button.button_choicent {
118 | text-decoration: none;
119 | }
120 |
121 | .answer_feedback {
122 | position: relative;
123 | font-size: 1.5rem;
124 | top: calc(var(--question-character-size) * 0.5);
125 | top: 40%;
126 | width: 0;
127 | margin-left: -1.5ch;
128 | margin-right: 0.5ch;
129 | left: 0;
130 | font-variation-settings: "wght" 350;
131 | }
132 |
133 | .question_container {
134 | pointer-events: none;
135 | }
136 |
137 | .question_container.active_question {
138 | pointer-events: auto;
139 | }
140 |
141 | .question_container.active_question:has(+ .active_question) {
142 | pointer-events: none;
143 | }
144 |
145 | .question_container.active_question ~ .question_container.active_question {
146 | pointer-events: auto;
147 | display: flex;
148 | }
149 |
150 | .question_container.active_question ~ .question_container {
151 | pointer-events: none;
152 | display: none;
153 | }
154 |
155 | #play_again {
156 | opacity: 0;
157 | }
158 |
159 | #score_tally:focus + #play_again,
160 | #play_again:focus {
161 | opacity: 1;
162 | }
163 |
--------------------------------------------------------------------------------
/src/css/section_7.css:
--------------------------------------------------------------------------------
1 | #section_7 #alternates_container fieldset,
2 | #section_7 #features_container fieldset {
3 | display: grid;
4 | grid-template-columns: 28ch 3ch 3ch;
5 | gap: 2ch;
6 | }
7 |
8 | #section_7 #examplesettings_form fieldset p {
9 | white-space: pre;
10 | font-variant-ligatures: none;
11 | }
12 |
13 | fieldset.alternates > div {
14 | width: 4ch;
15 | }
16 |
17 | #section_7 form > div {
18 | position: relative;
19 | }
20 |
21 | #examples_container {
22 | width: fit-content;
23 | max-height: 20.6rem;
24 | margin-bottom: 0.4rem;
25 | overflow-y: scroll;
26 | -ms-overflow-style: none; /* Internet Explorer 10+ */
27 | scrollbar-width: none; /* Firefox */
28 | }
29 | #examples_container::-webkit-scrollbar {
30 | display: none;
31 | }
32 |
33 | p#code_example {
34 | white-space: pre;
35 | max-width: none;
36 | min-width: 102ch;
37 | padding-left: 5ch;
38 | position: relative;
39 | line-height: 1;
40 | }
41 | p#code_example::before {
42 | content: attr(data-before);
43 | position: absolute;
44 | white-space: pre;
45 | left: 0;
46 | top: 0;
47 | height: 100%;
48 | overflow: hidden;
49 | }
50 |
51 | button:focus a {
52 | color: var(--bg);
53 | text-decoration: none;
54 | }
55 |
56 | .button_link {
57 | width: max-content;
58 | position: relative;
59 | }
60 | .button_link:hover {
61 | background: var(--bg75);
62 | color: var(--bg);
63 | text-decoration: none;
64 | }
65 | .button_link:focus:active,
66 | .button_link:active {
67 | background: var(--bg50);
68 | color: var(--bg);
69 | text-decoration: none;
70 | }
71 | .button_link:focus {
72 | background-color: var(--text);
73 | color: var(--bg);
74 | text-decoration: none;
75 | }
76 | .button_link::after {
77 | position: absolute;
78 | color: var(--text);
79 | right: -2ch;
80 | top: 0;
81 | }
82 | .button_link.loading::after {
83 | content: ".";
84 | animation: 800ms 0ms steps(4, jump-none) infinite loading;
85 | }
86 | .button_link.loaded::after {
87 | content: "✓";
88 | animation: none;
89 | }
90 | .button_link.error::after {
91 | content: "✕";
92 | animation: none;
93 | }
94 | .button_link.safari::after {
95 | content: "Safari download not working. Try Chrome or Firefox.";
96 | font-variation-settings: "ital" 1;
97 | right: auto;
98 | left: calc(100% + 1ch);
99 | animation: none;
100 | }
101 |
102 | @keyframes loading {
103 | 0% {
104 | transform: translateX(0);
105 | }
106 | 100% {
107 | transform: translateX(2ch);
108 | }
109 | }
110 |
111 | input.loading_font + label {
112 | animation: flicker 200ms infinite;
113 | }
114 |
115 | input[type="text"] {
116 | width: 10ch;
117 | height: 1rem;
118 | border: 1px solid var(--text);
119 | background-color: var(--bg);
120 | font-family: inherit;
121 | font-size: inherit;
122 | line-height: inherit;
123 | display: inline-block;
124 | }
125 |
126 | input[type="text"][contenteditable="true"] {
127 | animation: none;
128 | }
129 |
130 | input[type="text"]:focus {
131 | color: var(--text);
132 | }
133 |
134 | input[type="text"]:-webkit-autofill,
135 | input[type="text"]:-webkit-autofill:hover,
136 | input[type="text"]:-webkit-autofill:focus,
137 | input[type="text"]:auto-fill,
138 | input[type="text"]:auto-fill:hover,
139 | input[type="text"]:auto-fill:focus {
140 | -webkit-text-fill-color: var(--text);
141 | -webkit-box-shadow: 0 0 0px 40rem var(--bg) inset;
142 | }
143 |
144 | input[type="text"] + p {
145 | display: inline-block;
146 | margin-left: 0ch;
147 | }
148 |
149 | .file_label {
150 | height: 1rem;
151 | border: 1px solid var(--text);
152 | background-color: var(--bg);
153 | font-family: inherit;
154 | font-size: inherit;
155 | line-height: inherit;
156 | display: inline-block;
157 | padding: 0 0.5ch;
158 | }
159 |
160 | input[type="file"]:focus + label {
161 | background-color: var(--text);
162 | color: var(--bg);
163 | text-decoration: none;
164 | }
165 |
166 | #custom-settings-input {
167 | border: none;
168 | width: 17ch;
169 | font-variation-settings: inherit;
170 | opacity: 0.75;
171 | }
172 |
173 | /* #custom-settings-input, */
174 | #custom-settings-input::placeholder {
175 | opacity: 0.5;
176 | color: var(--text);
177 | font-feature-settings: inherit;
178 | font-variation-settings: inherit;
179 | }
180 | #custom-settings-input:focus::placeholder {
181 | opacity: 0.75;
182 | }
183 |
--------------------------------------------------------------------------------
/src/css/section_8.css:
--------------------------------------------------------------------------------
1 | ol {
2 | font-size: 0.75rem;
3 | margin-left: 0;
4 | max-width: max-content;
5 | counter-reset: install;
6 | list-style: none;
7 | }
8 |
9 | ol > li {
10 | margin-left: 3ch;
11 | max-width: calc(var(--max-width) - 3ch);
12 | counter-increment: install;
13 | position: relative;
14 | }
15 |
16 | ol > li > *:first-child:before {
17 | content: "#" counter(install) " ";
18 | position: absolute;
19 | left: -3ch;
20 | }
21 |
22 | ol li p {
23 | max-width: calc(var(--max-width) - 6ch);
24 | }
25 |
26 | ol:focus li p {
27 | color: var(--bg);
28 | }
29 |
30 | ol li ul li p {
31 | position: relative;
32 | }
33 |
34 | ol li ul li p::before {
35 | content: "•";
36 | position: absolute;
37 | left: -2ch;
38 | }
39 |
40 | details > summary {
41 | cursor: pointer;
42 | list-style: none;
43 | width: fit-content;
44 | max-width: calc(var(--max-width) - 4ch);
45 | position: relative;
46 | margin: 1rem 0 0 4ch;
47 | }
48 | details[open] > summary {
49 | background: var(--bg25);
50 | color: var(--text);
51 | }
52 | details > summary:focus {
53 | background: var(--text);
54 | color: var(--bg);
55 | }
56 | details > p {
57 | max-width: calc(var(--max-width) - 4ch);
58 | margin: 0 0 1rem 4ch;
59 | }
60 | details > ol {
61 | max-width: calc(var(--max-width) - 4ch);
62 | margin: 0 0 1rem 4ch;
63 | counter-reset: reinstall;
64 | }
65 | details > ol li::before {
66 | display: block;
67 | counter-increment: reinstall;
68 | content: "#" counter(reinstall) " ";
69 | position: absolute;
70 | left: -3ch;
71 | }
72 | details > ol li {
73 | position: relative;
74 | }
75 | details > summary::before {
76 | content: "[+]";
77 | position: absolute;
78 | left: -4ch;
79 | }
80 | details[open] > summary::before {
81 | content: "[-]";
82 | }
83 | details > summary:focus::before {
84 | color: var(--text);
85 | }
86 |
--------------------------------------------------------------------------------
/src/css/section_9.css:
--------------------------------------------------------------------------------
1 | .docs_example {
2 | width: max-content;
3 | font-variant-ligatures: none;
4 | white-space: pre;
5 | font-feature-settings: normal;
6 | }
7 |
8 | .span_off,
9 | .span_on {
10 | cursor: pointer;
11 | }
12 |
13 | .active_feature {
14 | cursor: pointer;
15 | background: var(--bg25);
16 | height: 100%;
17 | display: inline-block;
18 | }
19 |
20 | h2:focus .active_feature {
21 | background: var(--bg25-i);
22 | }
23 |
24 | #section_9 h2 {
25 | max-width: var(--max-width);
26 | }
27 |
28 | .docs_alternate {
29 | margin-right: 2rem;
30 | display: inline-block;
31 | vertical-align: baseline;
32 | }
33 |
34 | #features_docu > div {
35 | width: max-content;
36 | }
37 |
38 | #charset {
39 | width: var(--max-width);
40 | width: 32ch;
41 | font-variant-ligatures: none;
42 | white-space: pre-wrap;
43 | font-size: 5rem;
44 | line-height: 5rem;
45 | display: grid;
46 | grid-template-columns: repeat(10, 1ch);
47 | gap: 1ch;
48 | }
49 |
50 | #charset .charset_letter {
51 | /* background-color: blue; */
52 | font-size: inherit;
53 | width: fit-content;
54 | line-height: inherit;
55 | }
56 |
57 | .new_label {
58 | position: relative;
59 | }
60 |
61 | .new_label::before {
62 | content: "NEW";
63 | font-size: 0.66rem;
64 | background: var(--text);
65 | color: var(--bg);
66 | position: relative;
67 | padding: 0 0.5ch;
68 | }
69 |
70 | #language_support {
71 | display: grid;
72 | grid-auto-flow: column;
73 | grid-template-rows: repeat(12, 1fr);
74 | width: max-content;
75 | gap: 0 4ch;
76 | }
77 |
78 | #language_support > p {
79 | /* width: 22ch; */
80 | }
81 |
--------------------------------------------------------------------------------
/src/css/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --bg25: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 100%) 1px 0.5px / 2px 2px;
3 | --bg50: repeating-conic-gradient(var(--text) 0% 25%, transparent 0% 50%, var(--text) 0% 75%, transparent 0% 100%)
4 | 1px 0.5px / 2px 2px;
5 | --bg75: repeating-conic-gradient(transparent 0% 25%, var(--text) 0% 100%) 1px 0.5px / 2px 2px;
6 | --bg25-i: repeating-conic-gradient(var(--bg) 0% 25%, transparent 0% 100%) 1px 0.5px / 2px 2px;
7 | --bg50-i: repeating-conic-gradient(var(--bg) 0% 25%, transparent 0% 50%, var(--bg) 0% 75%, transparent 0% 100%) 1px
8 | 0.5px / 2px 2px;
9 | --bg75-i: repeating-conic-gradient(transparent 0% 25%, var(--bg) 0% 100%) 1px 0.5px / 2px 2px;
10 | }
11 |
12 | ::selection {
13 | color: var(--text);
14 | background-color: var(--middle);
15 | }
16 |
17 | #block_tab_start,
18 | #block_tab_end {
19 | position: absolute;
20 | top: 0;
21 | }
22 |
23 | #main_scale {
24 | inset: 0;
25 | overflow: scroll;
26 | scrollbar-width: none;
27 | -ms-overflow-style: none;
28 | height: 100vh;
29 | height: 100dvh;
30 | padding-bottom: 10rem;
31 | }
32 | #main_scale::-webkit-scrollbar {
33 | display: none;
34 | }
35 |
36 | main {
37 | min-width: 100vw;
38 | width: fit-content;
39 | padding: 4rem 4ch 0 4ch;
40 | }
41 |
42 | header nav {
43 | width: 100vw;
44 | padding: 1rem 4ch 0 4ch;
45 | background-color: var(--bg);
46 | z-index: 100;
47 | position: fixed;
48 | top: 0;
49 | }
50 |
51 | header #keyboard_section {
52 | width: 100%;
53 | padding: 0.25rem 4ch 1rem 4ch;
54 | background-color: var(--bg);
55 | z-index: 100;
56 | position: fixed;
57 | bottom: 0;
58 | }
59 |
60 | @media (max-width: 1000px) {
61 | main {
62 | padding: 4rem 2ch 0 2ch;
63 | }
64 | header nav {
65 | padding: 1rem 2ch 0 2ch;
66 | }
67 | header #keyboard_section {
68 | padding: 0.25rem 2ch 1rem 2ch;
69 | }
70 | }
71 |
72 | header #keyboard_section,
73 | header nav {
74 | overflow-y: scroll;
75 | -ms-overflow-style: none; /* Internet Explorer 10+ */
76 | scrollbar-width: none; /* Firefox */
77 | }
78 | header #keyboard_section::-webkit-scrollbar,
79 | header nav::-webkit-scrollbar {
80 | display: none;
81 | }
82 |
83 | #keyboard_section.hidden {
84 | display: none;
85 | }
86 |
87 | #nav_form {
88 | display: flex;
89 | gap: 4ch;
90 | font-size: 0.75rem;
91 | line-height: 1rem;
92 | width: max-content;
93 | }
94 |
95 | #section_container {
96 | inset: 1rem 2rem;
97 | }
98 |
99 | p,
100 | a,
101 | figcaption,
102 | button {
103 | font-size: 0.75rem;
104 | line-height: 1rem;
105 | max-width: var(--max-width);
106 | width: fit-content;
107 | vertical-align: top;
108 | color: inherit;
109 | }
110 |
111 | a,
112 | .button_link,
113 | button {
114 | text-decoration: underline;
115 | text-decoration-skip-ink: none;
116 | text-underline-offset: 0.24ch;
117 | cursor: pointer;
118 | }
119 | a:focus,
120 | .button_link:focus {
121 | text-decoration: none;
122 | }
123 |
124 | i {
125 | font-style: normal;
126 | font-variation-settings:
127 | "wght" 400,
128 | "ital" 1;
129 | }
130 |
131 | h1 {
132 | font-size: 1.5rem;
133 | line-height: 2rem;
134 | font-weight: normal;
135 | width: fit-content;
136 | }
137 |
138 | #change_setting p {
139 | padding: 0 1ch;
140 | background-color: var(--bg);
141 | }
142 |
143 | .faded {
144 | opacity: 0.33;
145 | }
146 |
147 | #mobile {
148 | visibility: hidden;
149 | }
150 |
151 | :focus {
152 | text-decoration: none;
153 | color: var(--bg);
154 | background-color: var(--text);
155 | outline: none;
156 | }
157 |
158 | form input[type="radio"],
159 | input[type="file"] {
160 | -webkit-appearance: none;
161 | appearance: none;
162 | background-color: var(--text);
163 | color: var(--text);
164 | border: none;
165 | width: 0;
166 | height: 0;
167 | opacity: 0;
168 | display: block;
169 | }
170 | form input[type="radio"] + label {
171 | cursor: pointer;
172 | display: inline-block;
173 | }
174 | form input[type="radio"]:focus:checked + label {
175 | background-color: var(--text);
176 | color: var(--bg);
177 | }
178 | form input[type="radio"]:checked + label {
179 | background: var(--bg25);
180 | }
181 | form input[type="radio"]:hover + label,
182 | form input[type="radio"]:checked:hover + label {
183 | background: var(--bg75);
184 | color: var(--bg);
185 | }
186 | form input[type="radio"]:focus:hover + label {
187 | background: var(--text);
188 | }
189 | form input[type="radio"]:focus + label:active,
190 | form input[type="radio"]:checked + label:active,
191 | form input[type="radio"] + label:active {
192 | background: var(--bg50);
193 | color: var(--bg);
194 | }
195 |
196 | ul li,
197 | ol li {
198 | font-size: 0.75rem;
199 | line-height: 1rem;
200 | margin-left: 2ch;
201 | max-width: 54ch;
202 | width: fit-content;
203 | }
204 |
205 | ul {
206 | list-style-type: none;
207 | max-width: max-content;
208 | }
209 |
210 | ol li::before {
211 | display: none;
212 | }
213 |
214 | ul li::before {
215 | content: "• ";
216 | position: absolute;
217 | margin-left: -2ch;
218 | }
219 |
220 | ul li:focus::before {
221 | background-color: transparent;
222 | color: var(--text);
223 | }
224 |
225 | #page_animation {
226 | width: 200vw;
227 | height: 200vh;
228 | height: 200dvh;
229 | position: fixed;
230 | top: 0;
231 | left: 0;
232 | z-index: 99;
233 | background-color: var(--bg);
234 | pointer-events: none;
235 | }
236 |
237 | #page_animation.page_animation {
238 | animation: 440ms steps(10, jump-start) forwards page_animation;
239 | }
240 |
241 | @keyframes page_animation {
242 | 0% {
243 | transform: translateY(0vh);
244 | }
245 | 99.9% {
246 | visibility: visible;
247 | }
248 | 100% {
249 | visibility: hidden;
250 | transform: translateY(200vh);
251 | }
252 | }
253 |
254 | #focus_check {
255 | position: absolute;
256 | }
257 |
258 | #footer_hint_mobile {
259 | display: none;
260 | }
261 |
262 | #section_container section {
263 | display: none;
264 | }
265 | #section_container section.visible {
266 | display: block;
267 | }
268 |
269 | .shake:focus,
270 | .shake,
271 | input:focus + .shake {
272 | animation: 200ms steps(1, jump-start) shake;
273 | }
274 | .shake_left:focus,
275 | .shake_left,
276 | input:focus + .shake_left {
277 | animation: 125ms steps(1, jump-start) shake_left;
278 | }
279 | .shake_right:focus,
280 | .shake_right,
281 | input:focus + .shake_right {
282 | animation: 125ms steps(1, jump-start) shake_right;
283 | }
284 | .shake_up:focus,
285 | .shake_up,
286 | input:focus + .shake_up {
287 | animation: 125ms steps(1, jump-start) shake_up;
288 | }
289 | .shake_down:focus,
290 | .shake_down,
291 | input:focus + .shake_down {
292 | animation: 125ms steps(1, jump-start) shake_down;
293 | }
294 |
295 | @keyframes shake {
296 | 0% {
297 | transform: translate(0);
298 | }
299 | 33% {
300 | transform: translate(0.125rem, 0.125rem);
301 | }
302 | 67% {
303 | transform: translate(-0.125rem, -0.125rem);
304 | }
305 | 100% {
306 | transform: translate(0);
307 | }
308 | }
309 | @keyframes shake_left {
310 | 0% {
311 | transform: translateX(0);
312 | }
313 | 50% {
314 | transform: translateX(-0.25rem);
315 | }
316 | 100% {
317 | transform: translateX(0);
318 | }
319 | }
320 | @keyframes shake_right {
321 | 0% {
322 | transform: translateX(0);
323 | }
324 | 50% {
325 | transform: translateX(0.25rem);
326 | }
327 | 100% {
328 | transform: translateX(0);
329 | }
330 | }
331 | @keyframes shake_up {
332 | 0% {
333 | transform: translateY(0);
334 | }
335 | 50% {
336 | transform: translateY(-0.25rem);
337 | }
338 | 100% {
339 | transform: translateY(0);
340 | }
341 | }
342 | @keyframes shake_down {
343 | 0% {
344 | transform: translateY(0);
345 | }
346 | 50% {
347 | transform: translateY(0.25rem);
348 | }
349 | 100% {
350 | transform: translateY(0);
351 | }
352 | }
353 |
354 | .nav_button {
355 | text-decoration: underline;
356 | }
357 | .nav_button:focus {
358 | text-decoration: none;
359 | }
360 |
--------------------------------------------------------------------------------
/src/favicon/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/favicon/icon-192.png
--------------------------------------------------------------------------------
/src/favicon/icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/favicon/icon-512.png
--------------------------------------------------------------------------------
/src/favicon/icon-512.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/features/aalt.fea:
--------------------------------------------------------------------------------
1 | feature aalt {
2 | # Access All Alternates
3 |
4 | #> featur
5 | feature c001;
6 | feature c002;
7 | feature c003;
8 | feature c004;
9 | feature c005;
10 | feature c006;
11 | #< feature
12 |
13 | } aalt;
14 |
--------------------------------------------------------------------------------
/src/features/balance.fea:
--------------------------------------------------------------------------------
1 | feature c007 {
2 | # Coding Ligature 001—999
3 | # Letter balancing
4 |
5 | # feature
6 | pos @width_narrow @width_narrow' @width_wide <-30 0 0 0>;
7 | pos @width_wide @width_narrow' @width_narrow <30 0 0 0>;
8 | pos @width_narrow @width_regular' @width_wide <-30 0 0 0>;
9 | pos @width_wide @width_regular' @width_narrow <30 0 0 0>;
10 | pos @width_narrow @width_wide' @width_wide <-30 0 0 0>;
11 | pos @width_wide @width_wide' @width_narrow <30 0 0 0>;
12 | pos @width_regular @width_narrow' @width_wide <-20 0 0 0>;
13 | pos @width_wide @width_narrow' @width_regular <20 0 0 0>;
14 | pos @width_regular @width_regular' @width_wide <-20 0 0 0>;
15 | pos @width_wide @width_regular' @width_regular <20 0 0 0>;
16 | pos @width_regular @width_wide' @width_wide <-20 0 0 0>;
17 | pos @width_wide @width_wide' @width_regular <20 0 0 0>;
18 | pos @width_narrow @width_narrow' @width_regular <-10 0 0 0>;
19 | pos @width_regular @width_narrow' @width_narrow <10 0 0 0>;
20 | pos @width_narrow @width_regular' @width_regular <-10 0 0 0>;
21 | pos @width_regular @width_regular' @width_narrow <10 0 0 0>;
22 | pos @width_narrow @width_wide' @width_regular <-10 0 0 0>;
23 | pos @width_regular @width_wide' @width_narrow <10 0 0 0>;
24 |
25 | } c007;
26 |
--------------------------------------------------------------------------------
/src/features/barhyphen.fea:
--------------------------------------------------------------------------------
1 | feature c005 {
2 | # Coding Ligature 001—999
3 | # Bar hyphen, bar equal, bar underscore substitution
4 |
5 | # classes
6 | @b_hyphen = [hyphen hyphen.arrow];
7 | @b_equal = [equal equal.arrow];
8 |
9 | # feature
10 | sub @b_hyphen bar' @b_hyphen by bar.hy_start_hy_end;
11 | sub @b_hyphen bar' by bar.hy_start;
12 | sub bar' @b_hyphen by bar.hy_end;
13 |
14 | sub @b_equal bar' @b_equal by bar.eq_start_eq_end;
15 | sub @b_equal bar' by bar.eq_start;
16 | sub bar' @b_equal by bar.eq_end;
17 |
18 | sub underscore bar' underscore by bar.un_start_un_end;
19 | sub underscore bar' by bar.un_start;
20 | sub bar' underscore by bar.un_end;
21 |
22 | } c005;
--------------------------------------------------------------------------------
/src/features/colon.fea:
--------------------------------------------------------------------------------
1 | feature c004 {
2 | # Coding Ligature 001—999
3 | # Colon equal/hash substitution
4 |
5 | # classes
6 | @colon_ = [colon colon.c2_1 colon.c2_2 colon.c3_1 colon.c3_3];
7 | @colon_case = [colon.case colon.case.c2_1 colon.case.c2_2 colon.case.c3_1 colon.case.c3_3];
8 | @colon_square = [colon.square colon.square.c2_1 colon.square.c2_2 colon.square.c3_1 colon.square.c3_3];
9 | @colon_case_square = [colon.case.square colon.case.square.c2_1 colon.case.square.c2_2 colon.case.square.c3_1 colon.case.square.c3_3];
10 | @colon_squashed = [colon.squash colon.squash.case colon.squash.square colon.squash.case.square];
11 | @squashers = [equal equal.case numbersign less less.case less.c2_1 less.c2_2 less.c3_1 less.c3_3 less.case.c2_1 less.case.c2_2 less.case.c3_1 less.case.c3_3 greater greater.case greater.c2_1 greater.c2_2 greater.c3_1 greater.c3_3 greater.case.c2_1 greater.case.c2_2 greater.case.c3_1 greater.case.c3_3];
12 |
13 |
14 | # feature
15 | lookup Squash_1 {
16 | sub @colon_' @squashers by colon.squash;
17 | sub @colon_case' @squashers by colon.squash.case;
18 | sub @colon_square' @squashers by colon.squash.square;
19 | sub @colon_case_square' @squashers by colon.squash.case.square;
20 | sub @squashers @colon' by colon.squash;
21 | sub @squashers @colon_case' by colon.squash.case;
22 | sub @squashers @colon_square' by colon.squash.square;
23 | sub @squashers @colon_case_square' by colon.squash.case.square;
24 | } Squash_1;
25 |
26 | lookup Squash_2 {
27 | sub @colon_' @colon_squashed by colon.squash;
28 | sub @colon_case' @colon_squashed by colon.squash.case;
29 | sub @colon_square' @colon_squashed by colon.squash.square;
30 | sub @colon_case_square' @colon_squashed by colon.squash.case.square;
31 | sub @colon_squashed @colon_' by colon.squash;
32 | sub @colon_squashed @colon_case' by colon.squash.case;
33 | sub @colon_squashed @colon_square' by colon.squash.square;
34 | sub @colon_squashed @colon_case_square' by colon.squash.case.square;
35 | } Squash_2;
36 |
37 | } c004;
38 |
39 |
--------------------------------------------------------------------------------
/src/features/cv04.fea:
--------------------------------------------------------------------------------
1 | feature cv04 {
2 | # Character Variant 01—99
3 |
4 | #> featur
5 |
6 | @four = [four four.dnom four.numr uni2084 uni2074];
7 | @four_cv04 = [four.cv04 four.dnom.cv04 four.numr.cv04 uni2084.cv04 uni2074.cv04];
8 |
9 | sub @four by @four_cv04;
10 |
11 | #< feature
12 | } cv04;
13 |
--------------------------------------------------------------------------------
/src/features/frac.fea:
--------------------------------------------------------------------------------
1 | feature frac {
2 | # Fractions
3 |
4 | #> featur
5 |
6 | # Arbitrary fractions (based on opentypecookbook.com)
7 |
8 | lookup frac_bar {
9 | ignore sub slash @figs @figs @figs @figs @figs @figs @figs @figs @figs @figs slash';
10 | ignore sub slash' @figs @figs @figs @figs @figs @figs @figs @figs @figs @figs slash;
11 | ignore sub slash @figs @figs @figs @figs @figs @figs @figs @figs @figs slash';
12 | ignore sub slash' @figs @figs @figs @figs @figs @figs @figs @figs @figs slash;
13 | ignore sub slash @figs @figs @figs @figs @figs @figs @figs @figs slash';
14 | ignore sub slash' @figs @figs @figs @figs @figs @figs @figs @figs slash;
15 | ignore sub slash @figs @figs @figs @figs @figs @figs @figs slash';
16 | ignore sub slash' @figs @figs @figs @figs @figs @figs @figs slash;
17 | ignore sub slash @figs @figs @figs @figs @figs @figs slash';
18 | ignore sub slash' @figs @figs @figs @figs @figs @figs slash;
19 | ignore sub slash @figs @figs @figs @figs @figs slash';
20 | ignore sub slash' @figs @figs @figs @figs @figs slash;
21 | ignore sub slash @figs @figs @figs @figs slash';
22 | ignore sub slash' @figs @figs @figs @figs slash;
23 | ignore sub slash @figs @figs @figs slash';
24 | ignore sub slash' @figs @figs @figs slash;
25 | ignore sub slash @figs @figs slash';
26 | ignore sub slash' @figs @figs slash;
27 | ignore sub slash @figs slash';
28 | ignore sub slash' @figs slash;
29 | ignore sub slash slash';
30 | ignore sub slash' slash;
31 | sub @figs slash' @figs by fraction;
32 | } frac_bar;
33 |
34 | lookup numr1 {
35 | sub @figs' fraction by @numr;
36 | } numr1;
37 |
38 | lookup numr2 {
39 | sub @figs' @numr fraction by @numr;
40 | } numr2;
41 |
42 | lookup numr3 {
43 | sub @figs' @numr @numr fraction by @numr;
44 | } numr3;
45 |
46 | lookup numr4 {
47 | sub @figs' @numr @numr @numr fraction by @numr;
48 | } numr4;
49 |
50 | lookup numr5 {
51 | sub @figs' @numr @numr @numr @numr fraction by @numr;
52 | } numr5;
53 |
54 | lookup numr6 {
55 | sub @figs' @numr @numr @numr @numr @numr fraction by @numr;
56 | } numr6;
57 |
58 | lookup numr7 {
59 | sub @figs' @numr @numr @numr @numr @numr @numr fraction by @numr;
60 | } numr7;
61 |
62 | lookup numr8 {
63 | sub @figs' @numr @numr @numr @numr @numr @numr @numr fraction by @numr;
64 | } numr8;
65 |
66 | lookup numr9 {
67 | sub @figs' @numr @numr @numr @numr @numr @numr @numr @numr fraction by @numr;
68 | } numr9;
69 |
70 | lookup numr10 {
71 | sub @figs' @numr @numr @numr @numr @numr @numr @numr @numr @numr fraction by @numr;
72 | } numr10;
73 |
74 | lookup dnom {
75 | sub [fraction @dnom] @figs' by @dnom;
76 | } dnom;
77 |
78 | #< feature
79 |
80 | } frac;
81 |
--------------------------------------------------------------------------------
/src/features/kern_smartkerning.fea:
--------------------------------------------------------------------------------
1 | feature kern {
2 | # GPOS feature: Kerning
3 | # Lookups: 1
4 |
5 | # Smart kerning with pos
6 |
7 |
8 | # classes
9 | @narrow_letter = [I L f i j l r t];
10 | @normal_letter = [F J P T Y a b c d e g h k n o p q s u v x y z space comma hyphen period colon semicolon underscore];
11 | @larger_letter = [A B C D E G H K O Q R S U V X Z];
12 | @widest_letter = [M N W m w];
13 | @origin = [A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z];
14 |
15 |
16 | # feature
17 | lookup kern {
18 |
19 | pos @narrow_letter @origin' @widest_letter <-44 0 0 0>;
20 | pos @narrow_letter @origin' @larger_letter <-30 0 0 0>;
21 | pos @normal_letter @origin' @widest_letter <-30 0 0 0>;
22 | pos @narrow_letter @origin' @normal_letter <-18 0 0 0>;
23 | pos @normal_letter @origin' @larger_letter <-18 0 0 0>;
24 | pos @larger_letter @origin' @widest_letter <-18 0 0 0>;
25 |
26 | pos @widest_letter @origin' @narrow_letter <44 0 0 0>;
27 | pos @larger_letter @origin' @narrow_letter <30 0 0 0>;
28 | pos @normal_letter @origin' @narrow_letter <30 0 0 0>;
29 | pos @widest_letter @origin' @normal_letter <18 0 0 0>;
30 | pos @larger_letter @origin' @normal_letter <18 0 0 0>;
31 | pos @widest_letter @origin' @larger_letter <18 0 0 0>;
32 |
33 | } kern;
34 |
35 | } kern;
36 |
--------------------------------------------------------------------------------
/src/features/liga.fea:
--------------------------------------------------------------------------------
1 | feature liga {
2 | # Standard Ligatures
3 |
4 | # feature
5 | lookup CloseUp_1_ {
6 | ignore sub @case_default' @lowercase_actor;
7 | ignore sub @case_default' @case_default @lowercase_actor;
8 | ignore sub @case_default @case_default' @lowercase_actor;
9 | ignore sub @case_default' @case_default @case_default @lowercase_actor;
10 | ignore sub @case_default @case_default' @case_default @lowercase_actor;
11 | ignore sub @case_default @case_default @case_default' @lowercase_actor;
12 | ignore sub @case_default' @case_default @case_default @case_default @lowercase_actor;
13 | ignore sub @case_default @case_default' @case_default @case_default @lowercase_actor;
14 | ignore sub @case_default @case_default @case_default' @case_default @lowercase_actor;
15 | ignore sub @case_default @case_default @case_default @case_default' @lowercase_actor;
16 | ignore sub @case_default' @case_default @case_default @case_default @case_default @lowercase_actor;
17 | ignore sub @case_default @case_default' @case_default @case_default @case_default @lowercase_actor;
18 | ignore sub @case_default @case_default @case_default' @case_default @case_default @lowercase_actor;
19 | ignore sub @case_default @case_default @case_default @case_default' @case_default @lowercase_actor;
20 | ignore sub @case_default @case_default @case_default @case_default @case_default' @lowercase_actor;
21 | sub @uppercase_actor @case_default' by @case_top;
22 | } CloseUp_1_;
23 |
24 | lookup CloseUp_2_ {
25 | ignore sub @lowercase_actor @case_default';
26 | ignore sub @lowercase_actor @case_default @case_default';
27 | ignore sub @lowercase_actor @case_default @case_default @case_default';
28 | ignore sub @lowercase_actor @case_default @case_default @case_default @case_default';
29 | ignore sub @lowercase_actor @case_default @case_default @case_default @case_default @case_default';
30 | sub @case_default' @uppercase_actor by @case_top;
31 | sub @case_default' @case_default @uppercase_actor by @case_top;
32 | sub @case_default' @case_default @case_default @uppercase_actor by @case_top;
33 | sub @case_default' @case_default @case_default @case_default @uppercase_actor by @case_top;
34 | sub @case_default' @case_default @case_default @case_default @case_default @uppercase_actor by @case_top;
35 | } CloseUp_2_;
36 |
37 | lookup StartEndSpace_ {
38 | sub @uppercase_actor @space_actor @case_default' @space_actor @uppercase_actor by @case_top;
39 | sub @uppercase_actor @space_actor @case_default' @case_default @space_actor @uppercase_actor by @case_top;
40 | sub @uppercase_actor @space_actor @case_default' @case_default @case_default @space_actor @uppercase_actor by @case_top;
41 | sub @uppercase_actor @space_actor @case_default' @case_default @case_default @case_default @space_actor @uppercase_actor by @case_top;
42 | sub @uppercase_actor @space_actor @case_default' @case_default @case_default @case_default @case_default @space_actor @uppercase_actor by @case_top;
43 | } StartEndSpace_;
44 |
45 | lookup InBetween_ {
46 | sub @case_top @case_default' by @case_top;
47 | } InBetween_;
48 |
49 | lookup Fix_ {
50 | sub @case_default @case_top' by @case_default;
51 | } Fix_;
52 |
53 |
54 |
55 | # classes
56 |
57 | @dflt = [exclam exclam.square period period.square slash slash.case colon colon.square colon.case colon.case.square semicolon semicolon.square question question.square backslash backslash.case bar bar.case less less.case greater greater.case];
58 | @c2_1 = [exclam.c2_1 exclam.square.c2_1 period.c2_1 period.square.c2_1 slash.c2_1 slash.case.c2_1 colon.c2_1 colon.square.c2_1 colon.case.c2_1 colon.case.square.c2_1 semicolon.c2_1 semicolon.square.c2_1 question.c2_1 question.square.c2_1 backslash.c2_1 backslash.case.c2_1 bar.c2_1 bar.case.c2_1 less.c2_1 less.case.c2_1 greater.c2_1 greater.case.c2_1];
59 | @c2_2 = [exclam.c2_2 exclam.square.c2_2 period.c2_2 period.square.c2_2 slash.c2_2 slash.case.c2_2 colon.c2_2 colon.square.c2_2 colon.case.c2_2 colon.case.square.c2_2 semicolon.c2_2 semicolon.square.c2_2 question.c2_2 question.square.c2_2 backslash.c2_2 backslash.case.c2_2 bar.c2_2 bar.case.c2_2 less.c2_2 less.case.c2_2 greater.c2_2 greater.case.c2_2];
60 | @c3_1 = [exclam.c3_1 exclam.square.c3_1 period.c3_1 period.square.c3_1 slash.c3_1 slash.case.c3_1 colon.c3_1 colon.square.c3_1 colon.case.c3_1 colon.case.square.c3_1 semicolon.c3_1 semicolon.square.c3_1 question.c3_1 question.square.c3_1 backslash.c3_1 backslash.case.c3_1 bar.c3_1 bar.case.c3_1 less.c3_1 less.case.c3_1 greater.c3_1 greater.case.c3_1];
61 | @c3_3 = [exclam.c3_3 exclam.square.c3_3 period.c3_3 period.square.c3_3 slash.c3_3 slash.case.c3_3 colon.c3_3 colon.square.c3_3 colon.case.c3_3 colon.case.square.c3_3 semicolon.c3_3 semicolon.square.c3_3 question.c3_3 question.square.c3_3 backslash.c3_3 backslash.case.c3_3 bar.c3_3 bar.case.c3_3 less.c3_3 less.case.c3_3 greater.c3_3 greater.case.c3_3];
62 | @exceptions = [numbersign];
63 |
64 | # exceptions
65 | ignore sub @exceptions @dflt';
66 | ignore sub @exceptions @dflt @dflt';
67 | ignore sub @dflt' @exceptions;
68 | ignore sub @dflt' @dflt @exceptions;
69 |
70 | ignore sub @greater' @less @slash;
71 | ignore sub @colon' @slash @slash;
72 | ignore sub @colon @slash' @slash;
73 |
74 | # feature
75 | ignore sub @dflt' @dflt @dflt @dflt;
76 | ignore sub @dflt @dflt' @dflt @dflt;
77 | ignore sub @dflt @dflt @dflt' @dflt;
78 | ignore sub @dflt @dflt @dflt @dflt';
79 |
80 | sub @dflt' @dflt @dflt by @c3_1;
81 | sub @c3_1 @dflt @dflt' by @c3_3;
82 |
83 | ignore sub @c3_1 @dflt' @dflt;
84 |
85 | sub @dflt' @dflt by @c2_1;
86 | sub @c2_1 @dflt' by @c2_2;
87 |
88 |
89 |
90 | # feature
91 | sub @narrow_letter @origin' @widest_letter by @leftL;
92 | sub @narrow_letter @origin' @larger_letter by @leftM;
93 | sub @normal_letter @origin' @widest_letter by @leftM;
94 | sub @narrow_letter @origin' @normal_letter by @leftS;
95 | sub @normal_letter @origin' @larger_letter by @leftS;
96 | sub @larger_letter @origin' @widest_letter by @leftS;
97 |
98 | sub @widest_letter @origin' @narrow_letter by @rightL;
99 | sub @larger_letter @origin' @narrow_letter by @rightM;
100 | sub @normal_letter @origin' @narrow_letter by @rightS;
101 | sub @widest_letter @origin' @normal_letter by @rightM;
102 | sub @larger_letter @origin' @normal_letter by @rightS;
103 | sub @widest_letter @origin' @larger_letter by @rightS;
104 |
105 | } liga;
106 |
107 |
--------------------------------------------------------------------------------
/src/features/none.fea:
--------------------------------------------------------------------------------
1 | feature none {
2 | # Character Variant 01—99
3 |
4 | #> featur
5 | sub nbspace by space;
6 | #< feature
7 |
8 | } none;
9 |
--------------------------------------------------------------------------------
/src/features/pipe.fea:
--------------------------------------------------------------------------------
1 | feature c003 {
2 | # Coding Ligature 001—999
3 | # Pipe substitution
4 |
5 | # classes
6 | @less_ = [less less.c2_1 less.c2_2 less.c3_1 less.c3_3];
7 | @less_case = [less.case less.case.c2_1 less.case.c2_2 less.case.c3_1 less.case.c3_3];
8 | @greater_ = [greater greater.c2_1 greater.c2_2 greater.c3_1 greater.c3_3];
9 | @greater_case = [greater.case greater.case.c2_1 greater.case.c2_2 greater.case.c3_1 greater.case.c3_3];
10 | @bar_pipe = [bar.pipe bar.case.pipe];
11 | @bar_c = [bar.c2_1 bar.c2_2 bar bar.c3_1 bar.c3_3 bar.pipe];
12 | @bar_c_case = [bar.case.c2_1 bar.case.c2_2 bar.case bar.case.c3_1 bar.case.c3_3 bar.case.pipe];
13 |
14 | # feature
15 | lookup BarFix {
16 | sub @less_ @bar_c' by bar.pipe;
17 | sub @bar_c' @bar_c @bar_c @greater_ by bar.pipe;
18 | sub @bar_c' @bar_c @greater_ by bar.pipe;
19 | sub @bar_c' @greater_ by bar.pipe;
20 |
21 | sub @less_ @bar_c_case' by bar.case.pipe;
22 | sub @bar_c_case' @bar_c_case @bar_c_case @greater_ by bar.case.pipe;
23 | sub @bar_c_case' @bar_c_case @greater_ by bar.case.pipe;
24 | sub @bar_c_case' @greater_ by bar.case.pipe;
25 | } BarFix;
26 |
27 | lookup BarToBarPipe {
28 | sub @bar_pipe @bar_c' by bar.pipe;
29 | sub @bar_pipe @bar_c_case' by bar.case.pipe;
30 | } BarToBarPipe;
31 |
32 | lookup Start {
33 | sub @less_' @bar_pipe by less.pipe;
34 | sub @less_case' @bar_pipe by less.pipe.case;
35 | } Start;
36 |
37 | lookup End {
38 | sub @bar_pipe @greater_' by greater.pipe;
39 | sub @bar_pipe @greater_case' by greater.pipe.case;
40 | } End;
41 |
42 | } c003;
43 |
44 |
--------------------------------------------------------------------------------
/src/features/posa.fea:
--------------------------------------------------------------------------------
1 | feature c002 {
2 | # Coding Ligature 001—999
3 | # Adjust punctuation
4 |
5 | #> feature
6 |
7 | pos @uppercase_actor @adjust_punctuation' @adjust_punctuation @uppercase_actor <40 0 0 0>;
8 | pos @uppercase_actor @adjust_punctuation @adjust_punctuation' @uppercase_actor <-40 0 0 0>;
9 | pos @uppercase_actor @adjust_punctuation' @adjust_punctuation @adjust_punctuation @uppercase_actor <80 0 0 0>;
10 | pos @uppercase_actor @adjust_punctuation @adjust_punctuation' @adjust_punctuation @uppercase_actor <0 0 0 0>;
11 | pos @uppercase_actor @adjust_punctuation @adjust_punctuation @adjust_punctuation' @uppercase_actor <-80 0 0 0>;
12 |
13 | pos @space_actor @adjust_punctuation' @adjust_punctuation @space_actor <40 0 0 0>;
14 | pos @space_actor @adjust_punctuation @adjust_punctuation' @space_actor <-40 0 0 0>;
15 | pos @space_actor @adjust_punctuation' @adjust_punctuation @adjust_punctuation @space_actor <80 0 0 0>;
16 | pos @space_actor @adjust_punctuation @adjust_punctuation' @adjust_punctuation @space_actor <0 0 0 0>;
17 | pos @space_actor @adjust_punctuation @adjust_punctuation @adjust_punctuation' @space_actor <-80 0 0 0>;
18 |
19 | #< feature
20 |
21 | } c002;
22 |
--------------------------------------------------------------------------------
/src/features/progress.fea:
--------------------------------------------------------------------------------
1 | feature c006 {
2 | # Coding Ligature 001—999
3 | # Progress bar substitution
4 |
5 | # classes
6 | @empty = [period period.c2_1 period.c2_2 period.c3_1 period.c3_3 period.square period.square.c2_1 period.square.c2_2 period.square.c3_1 period.square.c3_3 @space_actor];
7 | @fills = [numbersign equal equal.case equal.arrow equal.arrow.case];
8 | @indic = [greater greater.case greater.arrow_start_equal greater.arrow_start_equal.case];
9 | @l_bracket = [bracketleft bracketleft.case parenleft parenleft.case];
10 | @r_bracket = [bracketright bracketright.case parenright parenright.case];
11 |
12 | # feature
13 | lookup Progress_start {
14 | sub @l_bracket' @empty @empty @empty @empty @empty by uniEE00;
15 | sub @l_bracket' @fills @empty @empty @empty @empty by uniEE03;
16 | sub @l_bracket' @fills @fills @empty @empty @empty by uniEE03;
17 | sub @l_bracket' @fills @fills @fills @empty @empty by uniEE03;
18 | sub @l_bracket' @fills @fills @fills @fills @empty by uniEE03;
19 | sub @l_bracket' @fills @fills @fills @fills @fills by uniEE03;
20 | sub @l_bracket' @indic @empty @empty @empty @empty by uniEE03;
21 | } Progress_start;
22 |
23 | lookup Progress_middle {
24 | sub uniEE00 @empty' by uniEE01;
25 | sub uniEE01 @empty' by uniEE01;
26 | sub uniEE03 @fills' by uniEE04;
27 | sub uniEE04 @fills' by uniEE04;
28 | sub uniEE04 @empty' by uniEE01;
29 | sub uniEE03 @indic' by uniEE04;
30 | sub uniEE04 @indic' by uniEE04;
31 | } Progress_middle;
32 |
33 | lookup Progress_end {
34 | sub uniEE04 @r_bracket' by uniEE05;
35 | sub uniEE01 @r_bracket' by uniEE02;
36 | } Progress_end;
37 |
38 | lookup Spinner {
39 | sub uniEE02 @space_actor hyphen' by uniEE06;
40 | sub uniEE02 @space_actor backslash' by uniEE07;
41 | sub uniEE02 @space_actor bar' by uniEE08;
42 | sub uniEE02 @space_actor slash' by uniEE09;
43 | sub uniEE02 hyphen' by uniEE06;
44 | sub uniEE02 backslash' by uniEE07;
45 | sub uniEE02 bar' by uniEE08;
46 | sub uniEE02 slash' by uniEE09;
47 |
48 | sub uniEE05 @space_actor hyphen' by uniEE06;
49 | sub uniEE05 @space_actor backslash' by uniEE07;
50 | sub uniEE05 @space_actor bar' by uniEE08;
51 | sub uniEE05 @space_actor slash' by uniEE09;
52 | sub uniEE05 hyphen' by uniEE06;
53 | sub uniEE05 backslash' by uniEE07;
54 | sub uniEE05 bar' by uniEE08;
55 | sub uniEE05 slash' by uniEE09;
56 |
57 | sub hyphen' @space_actor uniEE00 by uniEE06;
58 | sub backslash' @space_actor uniEE00 by uniEE07;
59 | sub bar' @space_actor uniEE00 by uniEE08;
60 | sub slash' @space_actor uniEE00 by uniEE09;
61 | sub hyphen' uniEE00 by uniEE06;
62 | sub backslash' uniEE00 by uniEE07;
63 | sub bar' uniEE00 by uniEE08;
64 | sub slash' uniEE00 by uniEE09;
65 |
66 | sub hyphen' @space_actor uniEE03 by uniEE06;
67 | sub backslash' @space_actor uniEE03 by uniEE07;
68 | sub bar' @space_actor uniEE03 by uniEE08;
69 | sub slash' @space_actor uniEE03 by uniEE09;
70 | sub hyphen' uniEE03 by uniEE06;
71 | sub backslash' uniEE03 by uniEE07;
72 | sub bar' uniEE03 by uniEE08;
73 | sub slash' uniEE03 by uniEE09;
74 | } Spinner;
75 |
76 | } c006;
77 |
--------------------------------------------------------------------------------
/src/features/ss01_less_equal-copy.fea:
--------------------------------------------------------------------------------
1 | feature ss01 {
2 | # Coding Feature 00-99
3 | # less_equal, exclam_equal substitution
4 |
5 | # feature
6 | sub @space_actor equal' equal @space_actor by equal_equal.liga;
7 | sub @space_actor equal_equal.liga equal' @space_actor by space;
8 |
9 | sub @space_actor equal' equal equal @space_actor by equal_equal_equal.liga;
10 | sub @space_actor equal_equal_equal.liga equal' equal @space_actor by space;
11 | sub @space_actor equal_equal_equal.liga space equal' @space_actor by space;
12 |
13 | sub @space_actor less' equal @space_actor by less_equal.liga;
14 | sub @space_actor less_equal.liga equal' @space_actor by space;
15 | sub @space_actor [less.arrow_start_equal less.arrow_start_equal.case]' [equal.arrow equal.arrow.case] @space_actor by less_equal.liga;
16 | sub @space_actor less_equal.liga [equal.arrow equal.arrow.case]' @space_actor by space;
17 |
18 | sub @space_actor greater' equal @space_actor by greater_equal.liga;
19 | sub @space_actor greater_equal.liga equal' @space_actor by space;
20 |
21 | sub @space_actor exclam' equal @space_actor by exclam_equal.liga;
22 | sub @space_actor exclam_equal.liga equal' @space_actor by space;
23 |
24 | sub @space_actor exclam' equal equal @space_actor by exclam_equal_equal.liga;
25 | sub @space_actor exclam_equal_equal.liga equal' equal @space_actor by space;
26 | sub @space_actor exclam_equal_equal.liga space equal' @space_actor by space;
27 |
28 | } ss01;
29 |
--------------------------------------------------------------------------------
/src/features/ss01_less_equal.fea:
--------------------------------------------------------------------------------
1 | feature ss01 {
2 | # Coding Feature 00-99
3 | # less_equal, exclam_equal substitution
4 |
5 | # feature
6 | ignore sub [exclam exclam.square]' equal' equal' equal;
7 | sub [exclam exclam.square]' equal' equal' by exclam_equal_equal.liga;
8 | sub exclam_equal_equal.liga by exclam_equal_equal.liga space space;
9 |
10 | ignore sub [exclam exclam.square]' equal' equal;
11 | sub [exclam exclam.square]' equal' by exclam_equal.liga;
12 | sub exclam_equal.liga by exclam_equal.liga space;
13 |
14 | ignore sub less' equal' equal;
15 | sub less' equal' by less_equal.liga;
16 | sub less_equal.liga by less_equal.liga space;
17 |
18 | ignore sub greater' equal' equal;
19 | sub greater' equal' by greater_equal.liga;
20 | sub greater_equal.liga by greater_equal.liga space;
21 |
22 | ignore sub less equal' equal' equal';
23 | ignore sub greater equal' equal' equal';
24 | ignore sub equal' equal' equal' less;
25 | ignore sub equal' equal' equal' greater;
26 | ignore sub equal' equal' equal' equal;
27 | ignore sub equal equal' equal' equal';
28 | sub equal' equal' equal' by equal_equal_equal.liga;
29 | sub equal_equal_equal.liga by equal_equal_equal.liga space space;
30 |
31 | ignore sub less equal' equal';
32 | ignore sub greater equal' equal';
33 | ignore sub equal' equal' less;
34 | ignore sub equal' equal' greater;
35 | ignore sub equal' equal' equal;
36 | ignore sub equal equal' equal';
37 | sub equal' equal' by equal_equal.liga;
38 | sub equal_equal.liga by equal_equal.liga space;
39 |
40 | } ss01;
41 |
--------------------------------------------------------------------------------
/src/features/ss02_arrows.fea:
--------------------------------------------------------------------------------
1 | feature ss02 {
2 | # Coding Feature 00-99
3 | # Arrows
4 |
5 | # classes
6 | @hyphen = [hyphen hyphen.case];
7 | @hyphen_arrow = [hyphen.arrow hyphen.arrow.case];
8 | @equal = [equal equal.case];
9 | @equal_arrow = [equal.arrow equal.arrow.case];
10 | @less_arrow_end = [less.arrow_end less.arrow_end.case];
11 | @less_arrow_start = [less.arrow_start less.arrow_start.case];
12 | @less_arrow_start_hyphen = [less.arrow_start_hyphen less.arrow_start_hyphen.case];
13 | @less_arrow_start_equal = [less.arrow_start_equal less.arrow_start_equal.case];
14 | @greater_arrow_end = [greater.arrow_end greater.arrow_end.case];
15 | @greater_arrow_start = [greater.arrow_start greater.arrow_start.case];
16 | @greater_arrow_start_hyphen = [greater.arrow_start_hyphen greater.arrow_start_hyphen.case];
17 | @greater_arrow_start_equal = [greater.arrow_start_equal greater.arrow_start_equal.case];
18 | @exclam = [exclam exclam.square];
19 |
20 | # feature
21 | lookup TipStart_1 {
22 | ignore sub @space_actor @less' @equal @space_actor;
23 | ignore sub @space_actor @greater' @equal @space_actor;
24 | sub @less' @hyphen by @less_arrow_start_hyphen;
25 | sub @less' @equal by @less_arrow_start_equal;
26 | sub @greater' @hyphen by @greater_arrow_end;
27 | sub @greater' @equal by @greater_arrow_end;
28 | } TipStart_1;
29 |
30 | lookup TipStart_2 {
31 | sub @less' @less_arrow_start_hyphen by @less_arrow_start;
32 | sub @less' @less_arrow_start_equal by @less_arrow_start;
33 | sub @greater' @greater_arrow_end by @greater_arrow_end;
34 | } TipStart_2;
35 |
36 | lookup TipStart_3 {
37 | sub @less' @less_arrow_start by @less_arrow_start;
38 | sub @greater' @greater_arrow_end by @greater_arrow_end;
39 | } TipStart_3;
40 |
41 |
42 |
43 | lookup BodyStartA {
44 | sub @less_arrow_start_hyphen @hyphen' by @hyphen_arrow;
45 | sub @less_arrow_start_equal @equal' by @equal_arrow;
46 | sub @greater_arrow_end @hyphen' by @hyphen_arrow;
47 | sub @greater_arrow_end @equal' by @equal_arrow;
48 | } BodyStartA;
49 |
50 |
51 |
52 | lookup BodyStartB_1 {
53 | sub @hyphen' @less by @hyphen_arrow;
54 | sub @equal' @less by @equal_arrow;
55 | sub @hyphen' @greater by @hyphen_arrow;
56 | sub @equal' @greater by @equal_arrow;
57 | } BodyStartB_1;
58 |
59 | lookup BodyStartB_2 {
60 | sub @hyphen' @hyphen_arrow by @hyphen_arrow;
61 | sub @equal' @equal_arrow by @equal_arrow;
62 | } BodyStartB_2;
63 |
64 | lookup BodyStartB_3 {
65 | sub @hyphen' @hyphen_arrow by @hyphen_arrow;
66 | sub @equal' @equal_arrow by @equal_arrow;
67 | } BodyStartB_3;
68 |
69 | lookup BodyStartB_4 {
70 | sub @hyphen' @hyphen_arrow by @hyphen_arrow;
71 | sub @equal' @equal_arrow by @equal_arrow;
72 | } BodyStartB_4;
73 |
74 | lookup BodyStartB_5 {
75 | sub @hyphen' @hyphen_arrow by @hyphen_arrow;
76 | sub @equal' @equal_arrow by @equal_arrow;
77 | } BodyStartB_5;
78 |
79 |
80 |
81 | lookup BodyEnd {
82 | sub @hyphen_arrow @hyphen' by @hyphen_arrow;
83 | sub @equal_arrow @equal' by @equal_arrow;
84 | } BodyEnd;
85 |
86 |
87 |
88 | lookup TipEnd_1 {
89 | sub @hyphen_arrow @less' by @less_arrow_end;
90 | sub @equal_arrow @less' by @less_arrow_end;
91 | sub @hyphen_arrow @greater' by @greater_arrow_start_hyphen;
92 | sub @equal_arrow @greater' by @greater_arrow_start_equal;
93 | } TipEnd_1;
94 |
95 | lookup TipEnd_2 {
96 | sub @greater_arrow_start_hyphen @greater' by @greater_arrow_start;
97 | sub @greater_arrow_start_equal @greater' by @greater_arrow_start;
98 | } TipEnd_2;
99 |
100 | lookup TipEnd_3 {
101 | sub @less_arrow_end @less' by @less_arrow_end;
102 | sub @greater_arrow_start @greater' by @greater_arrow_start;
103 | } TipEnd_3;
104 |
105 |
106 |
107 | lookup HTMLcomment {
108 | sub @less' @exclam @hyphen @hyphen by @less_arrow_start_hyphen;
109 | sub @less_arrow_start_hyphen @exclam @hyphen' @hyphen by @hyphen_arrow;
110 | sub @less_arrow_start_hyphen @exclam @hyphen_arrow @hyphen' by @hyphen_arrow;
111 | } HTMLcomment;
112 |
113 | } ss02;
114 |
--------------------------------------------------------------------------------
/src/features/ss03_case.fea:
--------------------------------------------------------------------------------
1 | feature ss03 {
2 | # Coding Feature 00-99
3 | # Case sensitive punctuation
4 |
5 | # feature
6 | lookup CloseUp_1 {
7 | ignore sub @case_default' @lowercase_actor;
8 | ignore sub @case_default' @case_default @lowercase_actor;
9 | ignore sub @case_default @case_default' @lowercase_actor;
10 | ignore sub @case_default' @case_default @case_default @lowercase_actor;
11 | ignore sub @case_default @case_default' @case_default @lowercase_actor;
12 | ignore sub @case_default @case_default @case_default' @lowercase_actor;
13 | ignore sub @case_default' @case_default @case_default @case_default @lowercase_actor;
14 | ignore sub @case_default @case_default' @case_default @case_default @lowercase_actor;
15 | ignore sub @case_default @case_default @case_default' @case_default @lowercase_actor;
16 | ignore sub @case_default @case_default @case_default @case_default' @lowercase_actor;
17 | ignore sub @case_default' @case_default @case_default @case_default @case_default @lowercase_actor;
18 | ignore sub @case_default @case_default' @case_default @case_default @case_default @lowercase_actor;
19 | ignore sub @case_default @case_default @case_default' @case_default @case_default @lowercase_actor;
20 | ignore sub @case_default @case_default @case_default @case_default' @case_default @lowercase_actor;
21 | ignore sub @case_default @case_default @case_default @case_default @case_default' @lowercase_actor;
22 | ignore sub @case_default @uppercase_actor @case_default';
23 | ignore sub @case_default @case_default @uppercase_actor @case_default';
24 | sub @uppercase_actor @case_default' by @case_top;
25 | } CloseUp_1;
26 |
27 | lookup CloseUp_2 {
28 | ignore sub @lowercase_actor @case_default';
29 | ignore sub @lowercase_actor @case_default @case_default';
30 | ignore sub @lowercase_actor @case_default @case_default @case_default';
31 | ignore sub @lowercase_actor @case_default @case_default @case_default @case_default';
32 | ignore sub @lowercase_actor @case_default @case_default @case_default @case_default @case_default';
33 | ignore sub @case_default' @uppercase_actor @case_default;
34 | ignore sub @case_default' @uppercase_actor @case_default @case_default;
35 | sub @case_default' @uppercase_actor by @case_top;
36 | sub @case_default' @case_default @uppercase_actor by @case_top;
37 | sub @case_default' @case_default @case_default @uppercase_actor by @case_top;
38 | sub @case_default' @case_default @case_default @case_default @uppercase_actor by @case_top;
39 | sub @case_default' @case_default @case_default @case_default @case_default @uppercase_actor by @case_top;
40 | } CloseUp_2;
41 |
42 | lookup StartEndSpace {
43 | sub @uppercase_actor @space_actor @case_default' @space_actor @uppercase_actor by @case_top;
44 | sub @uppercase_actor @space_actor @case_default' @case_default @space_actor @uppercase_actor by @case_top;
45 | sub @uppercase_actor @space_actor @case_default' @case_default @case_default @space_actor @uppercase_actor by @case_top;
46 | sub @uppercase_actor @space_actor @case_default' @case_default @case_default @case_default @space_actor @uppercase_actor by @case_top;
47 | sub @uppercase_actor @space_actor @case_default' @case_default @case_default @case_default @case_default @space_actor @uppercase_actor by @case_top;
48 | } StartEndSpace;
49 |
50 | lookup InBetween {
51 | sub @case_top @case_default' by @case_top;
52 | } InBetween;
53 |
54 | lookup Fix {
55 | sub @case_default @case_top' by @case_default;
56 | } Fix;
57 |
58 | } ss03;
59 |
--------------------------------------------------------------------------------
/src/features/ss03_case_inter.fea:
--------------------------------------------------------------------------------
1 | feature ss03 {
2 | # Coding Feature 00-99
3 | # Case sensitive punctuation
4 |
5 | # -------------------------------------------------------------------------------------
6 | # BEGIN glyph class definitions
7 |
8 | @DASH = [hyphen endash emdash];
9 | @DASH_CASE = [hyphen.case endash.case emdash.case];
10 | @DASH_ANY = [@DASH @DASH_CASE];
11 |
12 | # cap-height tall glyphs
13 | @UC = [
14 | @Uppercase
15 | @Numeral
16 |
17 | # punctuation
18 | ampersand exclam exclamdbl exclamdown uni2049 question uni2047 uni2048
19 | questiondown interrobang invertedinterrobang bar paragraph
20 |
21 | # currency
22 | dollar cent yen sterling florin uni20BA uni20BD euro uni20B9 tenge peseta
23 | peso kip won lira austral hryvnia naira guarani coloncurrency cedi cruzeiro
24 | tugrik uni20AF mill afii57636 manat rupee lari franc
25 |
26 | # cap-tall symbols
27 | numero triagrt triagdn triagup warningSign blackleftpointingtriangle
28 | circleblack circlewhite
29 | diamondblack diamondblack_x diamondwhite diamondwhite_x
30 | sunWithRays blackSunWithRays
31 | heartWhiteSuit heartBlackSuit heavyBlackHeart
32 | upBlackArrow upWhiteArrow
33 | capslock placeofinterestsign control projective option alternativekeysymbol
34 | brokenCircleNorthWestArrow anticlockwiseOpenCircleArrow
35 | clockwiseOpenCircleArrow
36 | deleteleft deleteright clear ejectsymbol
37 |
38 | # percent and fractions
39 | onehalf onethird onequarter threequarters fivesixths onefraction seveneighths
40 | oneeighth fiveeighths threeeighths percent perthousand pertenthousand uni214D
41 | cadauna careof accountof addresssubject
42 | ];
43 |
44 | # x-height tall glyphs
45 | @LC = [
46 | @Lowercase
47 | ];
48 |
49 | @CASE_DELIM_L = [
50 | braceleft braceright
51 | bracketleft bracketright
52 | parenleft parenright
53 | ];
54 | @CASE_NONDELIM_L = [
55 | at
56 | multiply
57 | minus
58 | plus
59 | plusminus
60 | divide
61 | equal
62 | notequal
63 | endash
64 | figuredash
65 | emdash
66 | hyphen
67 | bullet
68 | openbullet
69 | hyphenbullet
70 | trianglebullet
71 | blackleftbullet
72 | blackrightbullet
73 | blackSmallSquare
74 | leftArrow
75 | leftLongArrow
76 | leftLongArrow2
77 | leftDoubleArrow
78 | leftLongDoubleArrow
79 | rightArrow
80 | rightLongArrow
81 | rightLongArrow2
82 | rightDoubleArrow
83 | rightLongDoubleArrow
84 | leftRightArrow
85 | leftRightLongArrow
86 | leftRightDoubleArrow
87 | leftRightLongDoubleArrow
88 | northEastArrow
89 | southEastArrow
90 | southWestArrow
91 | northWestArrow
92 | colon
93 | approxequal
94 | asciitilde
95 | less
96 | greater
97 | lessequal
98 | greaterequal
99 | ];
100 | @CASE_L = [
101 | @CASE_DELIM_L
102 | @CASE_NONDELIM_L
103 | ];
104 |
105 | @CASE_DELIM_R = [
106 | braceleft.case braceright.case
107 | bracketleft.case bracketright.case
108 | parenleft.case parenright.case
109 | ];
110 | @CASE_NONDELIM_R = [
111 | at.case
112 | multiply.case
113 | minus.case
114 | plus.case
115 | plusminus.case
116 | divide.case
117 | equal.case
118 | notequal.case
119 | endash.case
120 | figuredash.case
121 | emdash.case
122 | hyphen.case
123 | bullet.case
124 | openbullet.case
125 | hyphenbullet.case
126 | trianglebullet.case
127 | blackleftbullet.case
128 | blackrightbullet.case
129 | blackSmallSquare.case
130 | leftArrow.case
131 | leftLongArrow.case
132 | leftLongArrow2.case
133 | leftDoubleArrow.case
134 | leftLongDoubleArrow.case
135 | rightArrow.case
136 | rightLongArrow.case
137 | rightLongArrow2.case
138 | rightDoubleArrow.case
139 | rightLongDoubleArrow.case
140 | leftRightArrow.case
141 | leftRightLongArrow.case
142 | leftRightDoubleArrow.case
143 | leftRightLongDoubleArrow.case
144 | northEastArrow.case
145 | southEastArrow.case
146 | southWestArrow.case
147 | northWestArrow.case
148 | colon.case
149 | approxequal.case
150 | asciitilde.case
151 | less.case
152 | greater.case
153 | lessequal.case
154 | greaterequal.case
155 | ];
156 | @CASE_R = [
157 | @CASE_DELIM_R
158 | @CASE_NONDELIM_R
159 | ];
160 |
161 | @Punctuation = [
162 | slash bar quoteleft quoteright quotesingle quotedbl
163 | quotedblleft quotedblright quotedblbase quotesinglbase prime doubleprime
164 | tripleprime quadrupleprime primerev doubleprimerev tripleprimerev primemod
165 | doubleprimemod comma period ellipsis twodotleader semicolon underscore
166 | asciicircum circumflex
167 | asterisk
168 | ];
169 |
170 | # END glyph class definitions
171 | # -------------------------------------------------------------------------------------
172 | # BEGIN case
173 |
174 | # A foo' -> A foo.case
175 | #
176 | # ignore subs adjacent to lower case
177 | #
178 | # h[1,3]
179 | ignore sub @LC @CASE_DELIM_L @All @CASE_DELIM_L'; # h[X]
180 | ignore sub @LC @CASE_DELIM_L @All @All @CASE_DELIM_L'; # h[XX]
181 | ignore sub @LC @CASE_DELIM_L @All @All @All @CASE_DELIM_L'; # h[XXX]
182 | ignore sub @LC @CASE_DELIM_L @All @All @All @All @CASE_DELIM_L'; # h[XXXX]
183 | # x[]X
184 | ignore sub @LC @CASE_DELIM_L @CASE_DELIM_L' @UC; # x[]X
185 | ignore sub @LC @CASE_DELIM_L' @Whitespace @UC; # x[ X
186 | ignore sub @LC @CASE_DELIM_L' @Whitespace @Whitespace @UC; # x[ X
187 | ignore sub @LC @CASE_DELIM_L @CASE_DELIM_L' @Whitespace @UC; # x[] X
188 | ignore sub @LC @CASE_DELIM_L @CASE_DELIM_L' @Whitespace @Whitespace @UC; # x[] X
189 | ignore sub @LC @CASE_DELIM_L' @UC; # x[X
190 |
191 | # short runs of uc-lc, e.g "(Xx)", "[xxX]"
192 | ignore sub @CASE_DELIM_L' @UC @LC @CASE_DELIM_L; # (Xx)
193 | ignore sub @CASE_DELIM_L' @UC @All @LC @CASE_DELIM_L; # (X.x)
194 | ignore sub @CASE_DELIM_L @LC @UC @CASE_DELIM_L'; # (xX)
195 | ignore sub @CASE_DELIM_L @LC @All @UC @CASE_DELIM_L'; # (x.X)
196 |
197 | #
198 | # e.g. "x-M"
199 | ignore sub @LC @CASE_L'; # x-
200 | ignore sub @LC @CASE_L @CASE_L'; # x--
201 | ignore sub @LC @CASE_L @CASE_L @CASE_L'; # x---
202 | # ignore sub @LC [@CASE_L @Whitespace] @CASE_L'; # x--, x -
203 | # ignore sub @LC [@CASE_L @Whitespace] [@CASE_L @Whitespace] @CASE_L'; # x---, x --, x -, x- -
204 | # ignore sub @LC
205 | # [@CASE_L @Whitespace]
206 | # [@CASE_L @Whitespace]
207 | # [@CASE_L @Whitespace]
208 | # @CASE_L'; # x----, x ---, x --, x -, x- --, x- -, x-- -
209 | # ignore sub @LC
210 | # [@CASE_L @Whitespace]
211 | # [@CASE_L @Whitespace]
212 | # [@CASE_L @Whitespace]
213 | # [@CASE_L @Whitespace]
214 | # @CASE_L'; # x----- ...
215 | #
216 | # e.g. "x- "
217 | # ignore sub @LC @CASE_L' @Whitespace; # "x- "
218 | # ignore sub @LC @CASE_L' @Whitespace @Whitespace; # "x- "
219 | #
220 | # e.g. "-x"
221 | ignore sub @CASE_L' @LC; # -x
222 | ignore sub @CASE_L' @CASE_L @LC; # --x
223 | ignore sub @CASE_L' @CASE_L @CASE_L @LC; # ---x
224 | # ignore sub @CASE_L @CASE_L @CASE_L @CASE_L @LC; # ----x
225 | # ignore sub @CASE_L @CASE_L @CASE_L @CASE_L @CASE_L @LC; # -----x
226 |
227 | #
228 | # pairs with space, e.g. "( ) M" since we don't support subbing
229 | # all on the left side.
230 | ignore sub @CASE_DELIM_L @Whitespace @CASE_DELIM_L' @Whitespace [ @UC @CASE_R ];
231 | #
232 | # e.g. "A-", "A -", "A -"
233 | sub [@UC @CASE_R] @CASE_L' by @CASE_R;
234 | sub [@UC @CASE_R] @Whitespace @CASE_L' by @CASE_R;
235 | sub [@UC @CASE_R] @Whitespace @Whitespace @CASE_L' by @CASE_R;
236 |
237 | # foo' foo foo foo foo A -> foo.case foo foo foo foo A
238 | # foo' foo foo foo A -> foo.case foo foo foo A
239 | # foo' foo foo A -> foo.case foo foo A
240 | # foo' foo A -> foo.case foo A
241 | # foo' A -> foo.case A
242 | # Note: since we look quite far back, sequences like x{}[]M will case both
243 | # the square brackets next to M _and_ the curly braces to become .case
244 | #
245 | # e.g. "-A", "--A", "---A", "----A", "-----A"
246 | sub @CASE_L' [@UC @CASE_R] by @CASE_R;
247 | sub @CASE_L' @CASE_L [@CASE_R @UC] by @CASE_R;
248 | sub @CASE_L' @CASE_L @CASE_L [@CASE_R @UC] by @CASE_R;
249 | sub @CASE_L' @CASE_L @CASE_L @CASE_L [@CASE_R @UC] by @CASE_R;
250 | sub @CASE_L' @CASE_L @CASE_L @CASE_L @CASE_L [@CASE_R @UC] by @CASE_R;
251 | #
252 | # e.g. "- A", "-- A", "--- A", "---- A", "----- A"
253 | sub @CASE_L' @Whitespace [@UC @CASE_R] by @CASE_R;
254 | sub @CASE_L' @CASE_L @Whitespace [@CASE_R @UC] by @CASE_R;
255 | sub @CASE_L' @CASE_L @CASE_L @Whitespace [@CASE_R @UC] by @CASE_R;
256 | sub @CASE_L' @CASE_L @CASE_L @CASE_L @Whitespace [@CASE_R @UC] by @CASE_R;
257 | sub @CASE_L' @CASE_L @CASE_L @CASE_L @CASE_L @Whitespace [@CASE_R @UC] by @CASE_R;
258 | #
259 | # e.g. "- A", "-- A", "--- A", "---- A", "----- A"
260 | sub @CASE_L' @Whitespace @Whitespace [@UC @CASE_R] by @CASE_R;
261 | sub @CASE_L' @CASE_L @Whitespace @Whitespace [@CASE_R @UC] by @CASE_R;
262 | sub @CASE_L' @CASE_L @CASE_L @Whitespace @Whitespace [@CASE_R @UC] by @CASE_R;
263 | sub @CASE_L' @CASE_L @CASE_L @CASE_L @Whitespace @Whitespace [@CASE_R @UC] by @CASE_R;
264 | sub @CASE_L' @CASE_L @CASE_L @CASE_L @CASE_L @Whitespace @Whitespace [@CASE_R @UC] by @CASE_R;
265 |
266 | # X(_)
267 | sub @CASE_DELIM_R @Punctuation @CASE_DELIM_L' by @CASE_DELIM_R;
268 |
269 | # in between number position adjustment, e.g. 3 /multiply 4 -> 3 multiply.case 4
270 | @between_num_L = [multiply asterisk];
271 | @between_num_R = [multiply.case asterisk.case];
272 | sub @Numeral @between_num_L' @Numeral by @between_num_R; # 3*9
273 | sub @Numeral @Whitespace @between_num_L' @Numeral by @between_num_R; # 3 *9
274 | sub @Numeral @Whitespace @Whitespace @between_num_L' @Numeral by @between_num_R; # 3 *9
275 | sub @Numeral @between_num_L' @Whitespace @Numeral by @between_num_R; # 3* 9
276 | sub @Numeral @Whitespace @between_num_L' @Whitespace @Numeral by @between_num_R; # 3 * 9
277 | sub @Numeral @Whitespace @Whitespace @between_num_L' @Whitespace @Numeral by @between_num_R; # 3 * 9
278 | sub @Numeral @between_num_L' @Whitespace @Whitespace @Numeral by @between_num_R; # 3* 9
279 | sub @Numeral @Whitespace @between_num_L' @Whitespace @Whitespace @Numeral by @between_num_R; # 3 * 9
280 | sub @Numeral @Whitespace @Whitespace @between_num_L' @Whitespace @Whitespace @Numeral by @between_num_R; # 3 * 9
281 |
282 | # END case
283 | # -------------------------------------------------------------------------------------
284 |
285 | } ss03;
286 |
--------------------------------------------------------------------------------
/src/features/ss04_ellipsis.fea:
--------------------------------------------------------------------------------
1 | feature ss04 {
2 | # Coding Feature 00-99
3 | # Adjust punctuation horizontally
4 |
5 | # classes
6 |
7 | @dflt = [exclam exclam.square period period.square slash slash.case colon colon.square colon.case colon.case.square semicolon semicolon.square question question.square backslash backslash.case bar bar.case less less.case greater greater.case];
8 | @c2_1 = [exclam.c2_1 exclam.square.c2_1 period.c2_1 period.square.c2_1 slash.c2_1 slash.case.c2_1 colon.c2_1 colon.square.c2_1 colon.case.c2_1 colon.case.square.c2_1 semicolon.c2_1 semicolon.square.c2_1 question.c2_1 question.square.c2_1 backslash.c2_1 backslash.case.c2_1 bar.c2_1 bar.case.c2_1 less.c2_1 less.case.c2_1 greater.c2_1 greater.case.c2_1];
9 | @c2_2 = [exclam.c2_2 exclam.square.c2_2 period.c2_2 period.square.c2_2 slash.c2_2 slash.case.c2_2 colon.c2_2 colon.square.c2_2 colon.case.c2_2 colon.case.square.c2_2 semicolon.c2_2 semicolon.square.c2_2 question.c2_2 question.square.c2_2 backslash.c2_2 backslash.case.c2_2 bar.c2_2 bar.case.c2_2 less.c2_2 less.case.c2_2 greater.c2_2 greater.case.c2_2];
10 | @c3_1 = [exclam.c3_1 exclam.square.c3_1 period.c3_1 period.square.c3_1 slash.c3_1 slash.case.c3_1 colon.c3_1 colon.square.c3_1 colon.case.c3_1 colon.case.square.c3_1 semicolon.c3_1 semicolon.square.c3_1 question.c3_1 question.square.c3_1 backslash.c3_1 backslash.case.c3_1 bar.c3_1 bar.case.c3_1 less.c3_1 less.case.c3_1 greater.c3_1 greater.case.c3_1];
11 | @c3_3 = [exclam.c3_3 exclam.square.c3_3 period.c3_3 period.square.c3_3 slash.c3_3 slash.case.c3_3 colon.c3_3 colon.square.c3_3 colon.case.c3_3 colon.case.square.c3_3 semicolon.c3_3 semicolon.square.c3_3 question.c3_3 question.square.c3_3 backslash.c3_3 backslash.case.c3_3 bar.c3_3 bar.case.c3_3 less.c3_3 less.case.c3_3 greater.c3_3 greater.case.c3_3];
12 | @exceptions = [numbersign];
13 |
14 | # exceptions
15 | ignore sub @exceptions @dflt';
16 | ignore sub @exceptions @dflt @dflt';
17 | ignore sub @dflt' @exceptions;
18 | ignore sub @dflt' @dflt @exceptions;
19 |
20 | ignore sub @greater' @less @slash;
21 | ignore sub @colon' @slash @slash;
22 | ignore sub @colon @slash' @slash;
23 |
24 | # feature
25 | ignore sub @dflt' @dflt @dflt @dflt;
26 | ignore sub @dflt @dflt' @dflt @dflt;
27 | ignore sub @dflt @dflt @dflt' @dflt;
28 | ignore sub @dflt @dflt @dflt @dflt';
29 |
30 | sub @dflt' @dflt @dflt by @c3_1;
31 | sub @c3_1 @dflt @dflt' by @c3_3;
32 |
33 | ignore sub @c3_1 @dflt' @dflt;
34 |
35 | sub @dflt' @dflt by @c2_1;
36 | sub @c2_1 @dflt' by @c2_2;
37 |
38 | } ss04;
--------------------------------------------------------------------------------
/src/features/ss05_smartkerning copy 2.fea:
--------------------------------------------------------------------------------
1 | feature ss05 {
2 | # Coding Feature 00-99
3 | # Smart kerning
4 |
5 | # feature
6 | # lookup sk_left {
7 | sub @narrow_letter @origin' @widest_letter by @leftL;
8 | sub @narrow_letter @origin' @larger_letter by @leftM;
9 | sub @normal_letter @origin' @widest_letter by @leftM;
10 | sub @narrow_letter @origin' @normal_letter by @leftS;
11 | sub @normal_letter @origin' @larger_letter by @leftS;
12 | # sub @larger_letter @origin' @widest_letter by @leftS;
13 | # } sk_left;
14 |
15 | # lookup sk_right {
16 | sub @widest_letter @origin' @narrow_letter by @rightL;
17 | sub @larger_letter @origin' @narrow_letter by @rightM;
18 | sub @normal_letter @origin' @narrow_letter by @rightS;
19 | sub @widest_letter @origin' @normal_letter by @rightM;
20 | sub @larger_letter @origin' @normal_letter by @rightS;
21 | # sub @widest_letter @origin' @larger_letter by @rightS;
22 | # } sk_right;
23 |
24 |
25 |
26 | } ss05;
27 |
--------------------------------------------------------------------------------
/src/features/ss05_smartkerning copy.fea:
--------------------------------------------------------------------------------
1 | feature ss05 {
2 | # Coding Feature 00-99
3 | # Smart kerning
4 |
5 | # feature
6 | # lookup sk_left {
7 | sub @narrow_letter @origin' @widest_letter by @leftL;
8 | sub @narrow_letter @origin' @larger_letter by @leftM;
9 | sub @normal_letter @origin' @widest_letter by @leftM;
10 | sub @narrow_letter @origin' @normal_letter by @leftS;
11 | sub @normal_letter @origin' @larger_letter by @leftS;
12 | sub @larger_letter @origin' @widest_letter by @leftS;
13 | # } sk_left;
14 |
15 | # lookup sk_right {
16 | sub @widest_letter @origin' @narrow_letter by @rightL;
17 | sub @larger_letter @origin' @narrow_letter by @rightM;
18 | sub @normal_letter @origin' @narrow_letter by @rightS;
19 | sub @widest_letter @origin' @normal_letter by @rightM;
20 | sub @larger_letter @origin' @normal_letter by @rightS;
21 | sub @widest_letter @origin' @larger_letter by @rightS;
22 | # } sk_right;
23 |
24 |
25 |
26 | } ss05;
27 |
--------------------------------------------------------------------------------
/src/features/ss05_smartkerning.fea:
--------------------------------------------------------------------------------
1 | feature ss05 {
2 | # Coding Feature 00-99
3 | # Smart kerning
4 |
5 | # feature
6 |
7 | sub @narrow_letter @origin' @widest_letter by @leftL;
8 | sub @narrow_letter @origin' @larger_letter by @leftM;
9 | sub @normal_letter @origin' @widest_letter by @leftM;
10 | sub @narrow_letter @origin' @normal_letter by @leftS;
11 | sub @normal_letter @origin' @larger_letter by @leftS;
12 | sub @larger_letter @origin' @widest_letter by @leftS;
13 |
14 | sub @widest_letter @origin' @narrow_letter by @rightL;
15 | sub @larger_letter @origin' @narrow_letter by @rightM;
16 | sub @normal_letter @origin' @narrow_letter by @rightS;
17 | sub @widest_letter @origin' @normal_letter by @rightM;
18 | sub @larger_letter @origin' @normal_letter by @rightS;
19 | sub @widest_letter @origin' @larger_letter by @rightS;
20 |
21 |
22 | ignore sub @narrow_letter @origin' @widest_letter;
23 | ignore sub @narrow_letter @origin' @larger_letter;
24 | ignore sub @narrow_letter @origin' @normal_letter;
25 | ignore sub @narrow_letter @origin' @narrow_letter;
26 |
27 | ignore sub @normal_letter @origin' @widest_letter;
28 | ignore sub @normal_letter @origin' @larger_letter;
29 | ignore sub @normal_letter @origin' @normal_letter;
30 | ignore sub @normal_letter @origin' @narrow_letter;
31 |
32 | ignore sub @larger_letter @origin' @widest_letter;
33 | ignore sub @larger_letter @origin' @larger_letter;
34 | ignore sub @larger_letter @origin' @normal_letter;
35 | ignore sub @larger_letter @origin' @narrow_letter;
36 |
37 | ignore sub @widest_letter @origin' @widest_letter;
38 | ignore sub @widest_letter @origin' @larger_letter;
39 | ignore sub @widest_letter @origin' @normal_letter;
40 | ignore sub @widest_letter @origin' @narrow_letter;
41 |
42 | sub @origin' @widest_letter by @leftL;
43 | sub @origin' @larger_letter by @leftM;
44 | sub @origin' @normal_letter by @leftS;
45 |
46 | sub @widest_letter @origin' by @rightL;
47 | sub @larger_letter @origin' by @rightM;
48 | sub @normal_letter @origin' by @rightS;
49 |
50 | } ss05;
51 |
--------------------------------------------------------------------------------
/src/features/ss06_smartkerning.fea:
--------------------------------------------------------------------------------
1 | feature ss06 {
2 | # Coding Feature 00-99
3 | # Smart kerning
4 |
5 | # feature
6 |
7 | lookup nr {
8 | sub @normal_letter @origin' @narrow_letter by @rightS;
9 | sub @larger_letter @origin' @narrow_letter by @rightS;
10 | } nr;
11 |
12 | lookup rl {
13 | sub @narrow_letter @origin' @normal_letter by @leftS;
14 | sub @narrow_letter @origin' @larger_letter by @leftS;
15 | } rl;
16 |
17 | lookup lw {
18 | sub @larger_letter @origin' @widest_letter by @leftS;
19 | sub @widest_letter @origin' @larger_letter by @rightS;
20 | } lw;
21 |
22 |
23 |
24 | } ss06;
25 |
--------------------------------------------------------------------------------
/src/features/zero.fea:
--------------------------------------------------------------------------------
1 | feature zero {
2 | # Slashed Zero
3 |
4 | #> featur
5 |
6 | sub [zero zero.square] by zero.zero;
7 | sub [zero.dnom zero.dnom.square] by zero.dnom.zero;
8 | sub [zero.numr zero.numr.square] by zero.numr.zero;
9 | sub [uni2080 uni2080.square] by uni2080.zero;
10 | sub [uni2070 uni2070.square] by uni2070.zero;
11 |
12 | #< feature
13 |
14 | } zero;
15 |
--------------------------------------------------------------------------------
/src/fonts/CommitMono-1.143.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/CommitMono-1.143.zip
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-200Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-200Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-200Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-200Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-225Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-225Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-225Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-225Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-250Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-250Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-250Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-250Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-275Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-275Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-275Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-275Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-300Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-300Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-300Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-300Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-325Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-325Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-325Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-325Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-350Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-350Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-350Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-350Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-375Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-375Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-375Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-375Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-400Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-400Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-400Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-400Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-425Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-425Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-425Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-425Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-450Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-450Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-450Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-450Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-475Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-475Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-475Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-475Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-500Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-500Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-500Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-500Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-525Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-525Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-525Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-525Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-550Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-550Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-550Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-550Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-575Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-575Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-575Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-575Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-600Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-600Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-600Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-600Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-625Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-625Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-625Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-625Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-650Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-650Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-650Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-650Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-675Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-675Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-675Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-675Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-700Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-700Italic.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-700Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-700Regular.otf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-VF.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-VF.ttf
--------------------------------------------------------------------------------
/src/fonts/fontlab/CommitMonoV143-VF.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/fontlab/CommitMonoV143-VF.woff2
--------------------------------------------------------------------------------
/src/fonts/other/CascadiaCode.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/other/CascadiaCode.woff2
--------------------------------------------------------------------------------
/src/fonts/other/Consolas.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/other/Consolas.woff2
--------------------------------------------------------------------------------
/src/fonts/other/FiraCode.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/other/FiraCode.woff2
--------------------------------------------------------------------------------
/src/fonts/other/JetBrainsMono.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/other/JetBrainsMono.woff2
--------------------------------------------------------------------------------
/src/fonts/other/Menlo.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/other/Menlo.woff2
--------------------------------------------------------------------------------
/src/fonts/other/SourceCodePro.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/fonts/other/SourceCodePro.woff2
--------------------------------------------------------------------------------
/src/img/commitmono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eigilnikolajsen/commit-mono/ff532ce10d0107bd3e82a9ea004b4c98f7215ae7/src/img/commitmono.png
--------------------------------------------------------------------------------
/src/js/code_section.js:
--------------------------------------------------------------------------------
1 | const codeForm = document.querySelector("#code_form")
2 | const codeFieldset = document.querySelector("#code_form fieldset")
3 | const codeDescription = document.querySelector("#code_description")
4 |
5 | function buildCode() {
6 | // console.log("buildCode")
7 | websiteData.sections.forEach((section) => {
8 | if (section.name == "code") {
9 | section.content.characters.forEach((character, index) => {
10 | const div = document.createElement("div")
11 | const input = document.createElement("input")
12 | input.type = "radio"
13 | input.name = "code"
14 | input.id = character.name
15 | input.classList.add("code_character")
16 | input.value = character.name
17 | input.dataset.forform = "code_form"
18 | // input.tabIndex = 0
19 | if (index == 0) {
20 | input.setAttribute("checked", "true")
21 | }
22 | const label = document.createElement("label")
23 | label.textContent = character.value
24 | label.setAttribute("for", character.name)
25 | div.append(input, label)
26 | codeFieldset.append(div)
27 |
28 | const p = document.createElement("p")
29 | p.tabIndex = 0
30 | p.dataset.edit = "true"
31 | p.classList.add("code_char")
32 | p.dataset.char = character.name
33 | p.textContent = character.description
34 | p.style.display = "none"
35 | codeDescription.append(p)
36 | })
37 | }
38 | })
39 | }
40 |
41 | let commitMonoFont
42 | async function updateCodeFont() {
43 | // console.log("updateCodeFont")
44 | opentype
45 | .load(
46 | `/src/fonts/fontlab/CommitMono${versionOfCommitMono}-${websiteData.weight}${
47 | websiteData.italic ? "Italic" : "Regular"
48 | }.otf`
49 | )
50 | .then((font) => {
51 | // // console.log(font)
52 | commitMonoFont = font
53 | updateCode(null, codeForm)
54 | })
55 | .catch((err) => console.log(err))
56 |
57 | // Promise.all([
58 | // opentype.load("src/fonts/other/CascadiaCode-Regular.otf"),
59 | // opentype.load("src/fonts/other/CascadiaCode-Italic.otf"),
60 | // opentype.load("src/fonts/other/CascadiaCode-Bold.otf"),
61 | // opentype.load("src/fonts/other/CascadiaCode-BoldItalic.otf"),
62 | // opentype.load("src/fonts/other/CommitMono-400-Regular.otf"),
63 | // opentype.load("src/fonts/other/CommitMono-400-Italic.otf"),
64 | // opentype.load("src/fonts/other/CommitMono-700-Regular.otf"),
65 | // opentype.load("src/fonts/other/CommitMono-700-Italic.otf"),
66 | // ]).then((res) => {
67 | // res.forEach((font) => {
68 | // const { fontFamily, fontSubfamily, fullName, postScriptName } = font.names.windows
69 | // console.log(`
70 | // fontFamily: ${fontFamily?.en}
71 | // fontSubfamily: ${fontSubfamily?.en}
72 | // fullName: ${fullName?.en}
73 | // postScriptName: ${postScriptName?.en}`)
74 | // })
75 | // })
76 | }
77 |
78 | function updateCode(event, form) {
79 | // console.log("updateCode")
80 | const data = new FormData(form)
81 | let output = ""
82 | for (const entry of data) {
83 | output = `${entry[1]}`
84 | }
85 |
86 | let displayCharacter = ""
87 | let displayName = ""
88 | websiteData.sections.forEach((section) => {
89 | if (section.name == "code") {
90 | section.content.characters.forEach((character, index) => {
91 | if (character.name == output) {
92 | displayCharacter = character.value
93 | displayName = character.name
94 | const ps = document.querySelectorAll(".code_char")
95 | ps.forEach((p) =>
96 | p.dataset.char == character.name ? (p.style.display = "block") : (p.style.display = "none")
97 | )
98 | }
99 | })
100 | }
101 | })
102 |
103 | let selectedGlyphData
104 | if (commitMonoFont) {
105 | Object.values(commitMonoFont.glyphs.glyphs).forEach((glyph) => {
106 | if (glyph.name == output) selectedGlyphData = glyph
107 | })
108 | updateCanvas(selectedGlyphData, commitMonoFont, displayCharacter, displayName)
109 | }
110 |
111 | if (event) event.preventDefault()
112 | }
113 |
114 | const canvasScale = 16
115 |
116 | const drawFontLine = (GLYPH_SCALE, ctx, upem, width, name, value, yOffset) => {
117 | let scaledValue = mapRange(value, 0, upem, 0, width * GLYPH_SCALE)
118 | scaledValue = width - scaledValue + (yOffset * GLYPH_SCALE * width) / upem
119 |
120 | ctx.strokeStyle = getCssVar("--text")
121 | ctx.beginPath()
122 | ctx.moveTo(7 * canvasScale, scaledValue)
123 | ctx.lineTo(width - 7 * canvasScale, scaledValue)
124 | ctx.closePath()
125 | ctx.stroke()
126 |
127 | ctx.fillStyle = getCssVar("--text")
128 | ctx.font = `${0.75 * canvasScale}px "CommitMono"`
129 | ctx.textAlign = "left"
130 | ctx.fillText(name, 0, scaledValue + 0.25 * canvasScale)
131 | ctx.textAlign = "left"
132 | ctx.fillText(value, width - 4 * canvasScale, scaledValue + 0.25 * canvasScale)
133 | }
134 | const drawFontLineVertical = (GLYPH_SCALE, ctx, upem, width, value, yOffset, ascender, descender) => {
135 | let scaledValue1 = mapRange(ascender, 0, upem, 0, width * GLYPH_SCALE)
136 | scaledValue1 = width - scaledValue1 + (yOffset * GLYPH_SCALE * width) / upem
137 | let scaledValue2 = mapRange(descender, 0, upem, 0, width * GLYPH_SCALE)
138 | scaledValue2 = width - scaledValue2 + (yOffset * GLYPH_SCALE * width) / upem
139 |
140 | ctx.strokeStyle = getCssVar("--text")
141 | ctx.beginPath()
142 | ctx.moveTo(value, scaledValue1)
143 | ctx.lineTo(value, scaledValue2)
144 | ctx.closePath()
145 | ctx.stroke()
146 | }
147 |
148 | function updateCanvas(selectedGlyphData, selectedFont, displayCharacter, displayName) {
149 | // initialize canvas
150 | let CANVAS_SCALE = window.devicePixelRatio
151 | const canvas = document.querySelector("#canvas")
152 | let canvasWidth = 60 * canvasScale
153 | let canvasHeight = 42 * canvasScale
154 | canvas.style.width = `${canvasWidth}px`
155 | canvas.style.height = `${canvasHeight}px`
156 | canvas.width = canvasWidth * CANVAS_SCALE
157 | canvas.height = canvasHeight * CANVAS_SCALE
158 | const ctx = canvas.getContext("2d")
159 | ctx.scale(CANVAS_SCALE, CANVAS_SCALE)
160 |
161 | let GLYPH_SCALE = 0.6
162 | ctx.clearRect(0, 0, canvasWidth, canvasHeight)
163 |
164 | if (selectedGlyphData.path) {
165 | const CANVAS_GLYPH_COMPOSITION_FILL = [
166 | {
167 | type: "outline",
168 | fill: true,
169 | color: getCssVar("--text"),
170 | pointSize: undefined,
171 | },
172 | ]
173 | const CANVAS_GLYPH_COMPOSITION_BEZIER = [
174 | // {
175 | // type: "outline",
176 | // fill: true,
177 | // color: "rgba(0, 0, 0, 0.1)",
178 | // pointSize: undefined,
179 | // },
180 | {
181 | type: "handles",
182 | fill: false,
183 | color: getCssVar("--middle"),
184 | pointSize: undefined,
185 | },
186 | {
187 | type: "outline",
188 | fill: false,
189 | color: getCssVar("--text"),
190 | pointSize: undefined,
191 | },
192 | {
193 | type: "points",
194 | fill: true,
195 | color: getCssVar("--text"),
196 | pointSize: 10, // size of point on bezier glyph
197 | },
198 | {
199 | type: "handle points",
200 | fill: true,
201 | color: getCssVar("--middle"),
202 | pointSize: 10, // size of handles on bezier glyph
203 | },
204 | ]
205 |
206 | const upem = selectedFont?.unitsPerEm || 1000
207 | const width = 60 * canvasScale
208 |
209 | const yOffset = -45 * canvasScale
210 | const xOffset = 20 * canvasScale
211 | const ascender = selectedFont?.tables.os2?.sTypoAscender || 750
212 | const capHeight = selectedFont?.tables.os2?.sCapHeight || 700
213 | const xHeight = selectedFont?.tables.os2?.sxHeight
214 | const baseline = 0
215 | const descender = selectedFont?.tables.os2?.sTypoDescender || -200
216 | drawFontLine(GLYPH_SCALE, ctx, upem, width, "Ascender", ascender, yOffset)
217 | drawFontLine(GLYPH_SCALE, ctx, upem, width, "Cap Height", capHeight, yOffset)
218 | drawFontLine(GLYPH_SCALE, ctx, upem, width, "X-height", xHeight || 500, yOffset)
219 | drawFontLine(GLYPH_SCALE, ctx, upem, width, "Baseline", baseline, yOffset)
220 | drawFontLine(GLYPH_SCALE, ctx, upem, width, "Descender", descender, yOffset)
221 | drawFontLineVertical(GLYPH_SCALE, ctx, upem, width, 7 * canvasScale, yOffset, ascender, descender)
222 | drawFontLineVertical(GLYPH_SCALE, ctx, upem, width, 30 * canvasScale, yOffset, ascender, descender)
223 | drawFontLineVertical(GLYPH_SCALE, ctx, upem, width, 53 * canvasScale, yOffset, ascender, descender)
224 |
225 | ctx.fillStyle = getCssVar("--text")
226 | ctx.font = `${0.75 * canvasScale}px "CommitMono"`
227 | ctx.textAlign = "center"
228 | ctx.fillText(displayName, (30 - 11.5) * canvasScale, 2.75 * canvasScale)
229 | ctx.fillText(displayName, (30 + 11.5) * canvasScale, 2.75 * canvasScale)
230 |
231 | // make ready transformation matrixes for manipulating paths
232 | let firstMatrix = new DOMMatrix()
233 | firstMatrix = firstMatrix.scaleSelf(width / upem)
234 | let secondMatrix = new DOMMatrix()
235 | secondMatrix = secondMatrix.scaleSelf(GLYPH_SCALE)
236 | secondMatrix = secondMatrix.translateSelf(-width * 0.5, -width) // translate to left edge, top
237 | secondMatrix = secondMatrix.translateSelf((width * 0.5) / GLYPH_SCALE, width / GLYPH_SCALE) // translate to center, baseline
238 | secondMatrix = secondMatrix.translateSelf(0, (yOffset * width) / upem) // translate yOffset
239 | secondMatrix = secondMatrix.translateSelf((xOffset * width) / upem, 0) // translate xOffset
240 |
241 | // set initial value for glyph composition based on if bezier is switched on or off
242 | // let canvasGlyphComposition = bezier ? CANVAS_GLYPH_COMPOSITION_BEZIER : CANVAS_GLYPH_COMPOSITION_FILL
243 |
244 | CANVAS_GLYPH_COMPOSITION_BEZIER.forEach((composite) => {
245 | const calcPointsize = composite.pointSize * (upem / 1000)
246 | const firstPath2d = glyphBezier(selectedGlyphData, upem, composite.type, calcPointsize)
247 | const secondPath2d = new Path2D()
248 | secondPath2d.addPath(firstPath2d, firstMatrix)
249 | const finalPath2d = new Path2D()
250 | finalPath2d.addPath(secondPath2d, secondMatrix)
251 |
252 | if (composite.fill) {
253 | ctx.fillStyle = composite.color
254 | ctx.fill(finalPath2d)
255 | } else {
256 | ctx.strokeStyle = composite.color
257 | ctx.stroke(finalPath2d)
258 | }
259 | })
260 | CANVAS_GLYPH_COMPOSITION_FILL.forEach((composite) => {
261 | secondMatrix = secondMatrix.translateSelf((-2 * xOffset * width) / upem, 0) // translate xOffset
262 |
263 | const calcPointsize = composite.pointSize * (upem / 1000)
264 | const firstPath2d = glyphBezier(selectedGlyphData, upem, composite.type, calcPointsize)
265 | const secondPath2d = new Path2D()
266 | secondPath2d.addPath(firstPath2d, firstMatrix)
267 | const finalPath2d = new Path2D()
268 | finalPath2d.addPath(secondPath2d, secondMatrix)
269 |
270 | if (composite.fill) {
271 | ctx.fillStyle = composite.color
272 | ctx.fill(finalPath2d)
273 | } else {
274 | ctx.strokeStyle = composite.color
275 | ctx.stroke(finalPath2d)
276 | }
277 | })
278 | }
279 | }
280 |
281 | function glyphBezier(glyph, upem, typeOfOutline, pointSize) {
282 | let ps = pointSize
283 | let offsetX = (upem - glyph.advanceWidth) * 0.5
284 | let path2d = new Path2D()
285 |
286 | if (typeOfOutline == "outline") {
287 | let commandString = ""
288 | glyph.path.commands.forEach((command) => {
289 | switch (command.type) {
290 | case "M":
291 | commandString += `${command.type} `
292 | commandString += `${command.x + offsetX} ${upem - command.y} `
293 | break
294 | case "L":
295 | commandString += `${command.type} `
296 | commandString += `${command.x + offsetX} ${upem - command.y} `
297 | break
298 | case "C":
299 | commandString += `${command.type} `
300 | commandString += `${command.x1 + offsetX} ${upem - command.y1}, `
301 | commandString += `${command.x2 + offsetX} ${upem - command.y2}, `
302 | commandString += `${command.x + offsetX} ${upem - command.y} `
303 | break
304 | case "Q":
305 | commandString += `${command.type} `
306 | commandString += `${command.x1 + offsetX} ${upem - command.y1}, `
307 | commandString += `${command.x + offsetX} ${upem - command.y} `
308 | break
309 | case "Z":
310 | commandString += `${command.type} `
311 | break
312 | }
313 | })
314 | path2d.addPath(new Path2D(commandString))
315 | }
316 |
317 | if (typeOfOutline == "points") {
318 | glyph.path.commands.forEach((command) => {
319 | let p = new Path2D()
320 | const x = command.x + offsetX
321 | const y = upem - command.y
322 | switch (command.type) {
323 | case "M":
324 | p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
325 | break
326 | case "L":
327 | p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
328 | break
329 | case "C":
330 | p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
331 | break
332 | case "Q":
333 | p.rect(x - ps * 0.5, y - ps * 0.5, ps, ps)
334 | break
335 | }
336 | path2d.addPath(p)
337 | })
338 | }
339 |
340 | if (typeOfOutline == "handles") {
341 | let p = new Path2D()
342 | glyph.path.commands.forEach((command) => {
343 | switch (command.type) {
344 | case "M":
345 | p.moveTo(command.x + offsetX, upem - command.y)
346 | break
347 | case "L":
348 | p.moveTo(command.x + offsetX, upem - command.y)
349 | break
350 | case "C":
351 | p.lineTo(command.x1 + offsetX, upem - command.y1)
352 | p.moveTo(command.x + offsetX, upem - command.y)
353 | p.lineTo(command.x2 + offsetX, upem - command.y2)
354 | p.moveTo(command.x + offsetX, upem - command.y)
355 | break
356 | case "Q":
357 | p.lineTo(command.x1 + offsetX, upem - command.y1)
358 | p.moveTo(command.x1 + offsetX, upem - command.y1)
359 | p.lineTo(command.x + offsetX, upem - command.y)
360 | break
361 | case "Z":
362 | p.moveTo(command.x + offsetX, upem - command.y)
363 | break
364 | }
365 | })
366 | path2d.addPath(p)
367 | }
368 |
369 | if (typeOfOutline == "handle points") {
370 | glyph.path.commands.forEach((command) => {
371 | let p = new Path2D()
372 | const x1 = command.x1 + offsetX
373 | const x2 = command.x2 + offsetX
374 | const y1 = upem - command.y1
375 | const y2 = upem - command.y2
376 | switch (command.type) {
377 | case "C":
378 | p.rect(x1 - ps * 0.5, y1 - ps * 0.5, ps, ps)
379 | p.rect(x2 - ps * 0.5, y2 - ps * 0.5, ps, ps)
380 | break
381 | case "Q":
382 | p.rect(x1 - ps * 0.5, y1 - ps * 0.5, ps, ps)
383 | break
384 | }
385 | path2d.addPath(p)
386 | })
387 | }
388 |
389 | return path2d
390 | }
391 |
--------------------------------------------------------------------------------
/src/js/distinct_section.js:
--------------------------------------------------------------------------------
1 | let waterfall, gtc
2 | websiteData.sections.forEach((section) => {
3 | if (section.name == "distinct") {
4 | waterfall = section.content.waterfall
5 | gtc = section.content.gtc.Easy
6 | }
7 | })
8 |
9 | function updateWaterfall() {
10 | // console.log("updateWaterfall")
11 | const waterfallContainer = document.querySelector("#waterfall")
12 | waterfallContainer.innerHTML = ""
13 | waterfall.sizes.forEach((size) => {
14 | const div = document.createElement("div")
15 | div.id = `size_${size}`
16 |
17 | const desc = document.createElement("p")
18 | desc.classList.add("waterfall_desc")
19 | desc.textContent = `${size}rem\n${Math.round(size * rem * 100) / 100}px`
20 |
21 | const textsContainer = document.createElement("div")
22 | textsContainer.classList.add("waterfall_texts_container")
23 | waterfall.texts.forEach((text) => {
24 | const div2 = document.createElement("div")
25 | const p = document.createElement("p")
26 | p.classList.add("waterfall_text")
27 | p.style.fontSize = `${Math.round(size * rem * 100) / 100}px`
28 | p.textContent = text
29 | div2.append(p)
30 | textsContainer.append(div2)
31 | })
32 | div.append(desc, textsContainer)
33 |
34 | waterfallContainer.append(div)
35 | })
36 | }
37 |
38 | const gtcForm = document.querySelector("#gtc_form")
39 | const gtcFieldset = document.querySelector("#gtc_form fieldset")
40 |
41 | function buildDistinction() {
42 | // console.log("buildDistinction")
43 | gtcFieldset.innerHTML = ""
44 | websiteData.sections.forEach((section) => {
45 | if (section.name == "distinct") {
46 | section.content.gtcDifficulties.forEach((difficulty, index) => {
47 | const div = document.createElement("div")
48 | const input = document.createElement("input")
49 | input.type = "radio"
50 | input.name = "difficulty"
51 | input.id = `difficulty_${difficulty.name}`
52 | input.classList.add("gtc_difficulty")
53 | input.value = difficulty.name
54 | input.dataset.forform = "gtc_form"
55 | // input.tabIndex = 0
56 | if (index == 0) {
57 | input.setAttribute("checked", "true")
58 | }
59 | const label = document.createElement("label")
60 | label.textContent = difficulty.name
61 | label.setAttribute("for", `difficulty_${difficulty.name}`)
62 | div.append(input, label)
63 | gtcFieldset.append(div)
64 | })
65 | }
66 | })
67 | }
68 |
69 | function updateGTC(event, form) {
70 | // console.log("updateGTC")
71 | const data = new FormData(form)
72 | let output = ""
73 | for (const entry of data) {
74 | output = `${entry[1]}`
75 | }
76 | websiteData.sections.forEach((section) => {
77 | if (section.name == "distinct") {
78 | section.content.gtcDifficulties.forEach((difficulty) => {
79 | if (difficulty.name == output) {
80 | gtc = section.content.gtc[output]
81 | setCssVar(["--question-character-size", `${difficulty.size}rem`])
82 | buildGTC()
83 | }
84 | })
85 | }
86 | })
87 |
88 | if (event) event.preventDefault()
89 | }
90 |
91 | let answers = []
92 | let score = -1
93 | let currentQuestion = -1
94 | let firstButtons = []
95 | function buildGTC() {
96 | // console.log("buildGTC")
97 | const gtcContainer = document.querySelector("#gtc_questions_container")
98 | gtcContainer.innerHTML = ""
99 | answers = []
100 | score = -1
101 | currentQuestion = -1
102 | firstButtons = []
103 | gtc.forEach((question, index) => {
104 | const div = document.createElement("div")
105 | div.classList.add("question_container")
106 | div.dataset.index = index
107 |
108 | const answer = Math.round(Math.random())
109 | const wrongAnswer = (answer + 1) % 2
110 | answers.push(answer)
111 |
112 | const p = document.createElement("p")
113 | p.classList.add("question_character")
114 | p.textContent = question.value[answer]
115 | const pWrong = document.createElement("p")
116 | pWrong.classList.add("question_character", "wrong_character", "hide_character")
117 | pWrong.textContent = question.value[wrongAnswer]
118 | const buttonContainer = document.createElement("div")
119 | buttonContainer.classList.add("button_container")
120 | const option0 = document.createElement("button")
121 | option0.classList.add("question_button")
122 | option0.textContent = question.options[0]
123 | option0.dataset.questionIndex = index
124 | option0.tabIndex = -1
125 | firstButtons.push(option0)
126 | const option1 = document.createElement("button")
127 | option1.classList.add("question_button")
128 | option1.textContent = question.options[1]
129 | option1.dataset.questionIndex = index
130 | option1.tabIndex = -1
131 |
132 | const options = [option0, option1]
133 | options[answer].addEventListener("click", (e) => nextQuestion(true, answer, wrongAnswer, e.pointerType))
134 | options[wrongAnswer].addEventListener("click", (e) => nextQuestion(false, answer, wrongAnswer, e.pointerType))
135 |
136 | const answerFeedback = document.createElement("p")
137 | answerFeedback.classList.add("answer_feedback")
138 |
139 | buttonContainer.append(option0, option1)
140 | const br = document.createElement("br")
141 | div.append(answerFeedback, p, buttonContainer, pWrong)
142 | gtcContainer.append(div)
143 | })
144 | nextQuestion(true, 0, 1)
145 | }
146 |
147 | function nextQuestion(correct, answer, wrongAnswer, pointerType) {
148 | // console.log(pointerType)
149 | const scoreTally = document.querySelector("#score_tally")
150 | const allQuestions = document.querySelectorAll(".question_container")
151 | let answerFeedback
152 |
153 | if (correct) score++
154 |
155 | allQuestions.forEach((question, index) => {
156 | const wrongCharacter = question.querySelector(".wrong_character")
157 |
158 | if (index == currentQuestion) {
159 | question.classList.add("active_question")
160 | const rightButton = question.querySelector(`.button_container .question_button:nth-child(${answer + 1})`)
161 | const wrongButton = question.querySelector(
162 | `.button_container .question_button:nth-child(${wrongAnswer + 1})`,
163 | )
164 | correct ? rightButton.classList.add("button_choice") : wrongButton.classList.add("button_choice")
165 | !correct ? rightButton.classList.add("button_choicent") : wrongButton.classList.add("button_choicent")
166 | rightButton.classList.add("right_button")
167 | rightButton.tabIndex = -1
168 | wrongButton.classList.add("wrong_button")
169 | wrongButton.tabIndex = -1
170 |
171 | answerFeedback = question.querySelector(".answer_feedback")
172 | answerFeedback.textContent = correct ? "✓" : "✕"
173 |
174 | wrongCharacter.classList.remove("hide_character")
175 | wrongCharacter.classList.add("show_character")
176 | } else if (index == currentQuestion + 1) {
177 | question.classList.add("active_question")
178 | } else {
179 | question.classList.remove("active_question")
180 | }
181 | })
182 |
183 | currentQuestion++
184 |
185 | allQuestions.forEach((question, index) => {
186 | if (index == currentQuestion) {
187 | question.querySelectorAll(".question_button").forEach((button) => (button.tabIndex = 0))
188 | }
189 | })
190 | scoreTally.textContent = `Score: ${score}/${gtc.length}`
191 |
192 | if (currentQuestion < gtc.length) {
193 | if (!isMobile && pointerType === "") setTimeout(() => firstButtons[currentQuestion]?.focus(), 10)
194 | } else {
195 | scoreTally.tabIndex = 0
196 | setTimeout(() => scoreTally.focus(), 10)
197 | }
198 | }
199 |
200 | function onPlayAgain(button) {
201 | button.classList.remove("shake")
202 | const gtc = document.querySelector("#gtc")
203 | gtc.style.opacity = 0
204 | buildGTC()
205 | setTimeout(() => {
206 | document.querySelector("#gtc_form input:checked").focus()
207 | gtc.style.opacity = 1
208 | }, 100)
209 | }
210 |
--------------------------------------------------------------------------------
/src/js/docs_section.js:
--------------------------------------------------------------------------------
1 | const docsForm = document.querySelector("#docs_form")
2 | const faqContainerDocs = document.querySelector("#faq_container_docs")
3 | const featuresContainerDocs = document.querySelector("#features_container_docs")
4 | const alternatesContainerDocs = document.querySelector("#alternates_container_docs")
5 | const charsetContainerDocs = document.querySelector("#charset_container_docs")
6 | const languageContainerDocs = document.querySelector("#language_container_docs")
7 |
8 | let customizeContent
9 | let docsContent
10 | websiteData.sections.forEach((section) => {
11 | if (section.name == "customize") customizeContent = section.content
12 | if (section.name == "docs") docsContent = section.content
13 | })
14 |
15 | function buildDocs() {
16 | // console.log("buildDocs")
17 | customizeContent.features.forEach((feature) => {
18 | const sizes = [
19 | [3, 4],
20 | [1.5, 2],
21 | [0.5, 1],
22 | ]
23 | const container = document.createElement("div")
24 | const h2 = document.createElement("h2")
25 | const featureDescriptionWithSpan = feature.description
26 | .split("|")
27 | .map((l) =>
28 | l == "OFF" || l == "DEF"
29 | ? `[${l}] `
32 | : l == "ON" || l == "ALT"
33 | ? `[${l}] `
36 | : l,
37 | )
38 | .join("")
39 | h2.innerHTML = featureDescriptionWithSpan
40 | h2.tabIndex = 0
41 | h2.dataset.edit = "true"
42 | const p = document.createElement("p")
43 | p.textContent = `Default: ${feature.on ? "ON" : "OFF"}. Feature in variable font: "${feature.feature}".`
44 | container.append(h2, p)
45 | sizes.forEach((size) => {
46 | const exampleText = document.createElement("p")
47 | exampleText.textContent = feature.docsExample
48 | exampleText.classList.add("docs_example", `docs_${feature.type}`)
49 | exampleText.dataset.feature = feature.feature
50 | exampleText.style.fontSize = `${size[0]}rem`
51 | exampleText.style.lineHeight = `${size[1]}rem`
52 | container.append(exampleText)
53 | })
54 | const br1 = document.createElement("br")
55 | const br2 = document.createElement("br")
56 | container.append(br1, br2)
57 | if (feature.type == "feature") {
58 | featuresContainerDocs.append(container)
59 | }
60 | if (feature.type == "alternate") {
61 | alternatesContainerDocs.append(container)
62 | }
63 | })
64 | const charset = document.querySelector("#charset")
65 | const tunedCharset = docsContent.charset.split("").join(" ")
66 | docsContent.charset.split("").forEach((char) => {
67 | const span = document.createElement("p")
68 | span.classList.add("charset_letter")
69 | span.textContent = char
70 | charset.append(span)
71 | })
72 | // charset.textContent = tunedCharset
73 |
74 | const languageSupport = document.querySelector("#language_support")
75 | docsContent.supportedLanguages.forEach((language) => {
76 | const p = document.createElement("p")
77 | p.classList.add("language_support")
78 | p.textContent = language
79 | languageSupport.append(p)
80 | })
81 |
82 | updateDocs(null, docsForm)
83 | }
84 |
85 | function changeFeatureDocs(enable) {
86 | // console.log("changeFeatureDocs")
87 | if (enable == "enable") {
88 | websiteData.enableFeaturesInDocs = true
89 | } else if (enable == "disable") {
90 | websiteData.enableFeaturesInDocs = false
91 | } else if (enable == "switch") {
92 | websiteData.enableFeaturesInDocs = !websiteData.enableFeaturesInDocs
93 | }
94 | const enabled = websiteData.enableFeaturesInDocs
95 | const allExampleTexts = document.querySelectorAll(".docs_example")
96 | allExampleTexts.forEach((text) => {
97 | text.style.fontFeatureSettings = `"${text.dataset.feature}" ${enabled ? 1 : 0}`
98 | })
99 | const allSpanOff = document.querySelectorAll(".span_off")
100 | const allSpanOn = document.querySelectorAll(".span_on")
101 | if (enabled) {
102 | allSpanOff.forEach((span) => span.classList.remove("active_feature"))
103 | allSpanOn.forEach((span) => span.classList.add("active_feature"))
104 | } else {
105 | allSpanOff.forEach((span) => span.classList.add("active_feature"))
106 | allSpanOn.forEach((span) => span.classList.remove("active_feature"))
107 | }
108 | }
109 |
110 | function updateDocs(event, form) {
111 | // console.log("updateDocs")
112 | const data = new FormData(form)
113 | let output = ""
114 | for (const entry of data) {
115 | output = entry[1]
116 | }
117 | const docsContainers = document.querySelectorAll(".docs_container")
118 | docsContainers.forEach((topic) => {
119 | // console.log(topic.id)
120 | topic.style.display = "none"
121 | if (`${output}_container_docs` == topic.id) {
122 | topic.style.display = "block"
123 | }
124 | })
125 | if (event) event.preventDefault()
126 | }
127 |
--------------------------------------------------------------------------------
/src/js/dynamic_favicon.js:
--------------------------------------------------------------------------------
1 | document.onvisibilitychange = () => {
2 | // dynamicFavicon()
3 | if (document.visibilityState === "visible") changeFavicon(true)
4 | else changeFavicon(false)
5 | }
6 |
7 | let faviconIntervalID
8 | let faviconCounter = 0
9 |
10 | // function dynamicFavicon() {
11 | // if (document.visibilityState === "visible") {
12 | // faviconIntervalID = setInterval(changeFav, 500)
13 | // } else {
14 | // clearInterval(faviconIntervalID)
15 | // faviconIntervalID = null
16 | // if (faviconCounter % 2 == 1) changeFav()
17 | // }
18 |
19 | // function changeFav() {
20 | // const link = document.createElement("link"),
21 | // oldLink = document.getElementById("dynamic-favicon")
22 |
23 | // link.id = "dynamic-favicon"
24 | // link.rel = "icon"
25 | // link.href = faviconCounter % 2 == 0 ? "src/favicon/icon-off.svg" : "src/favicon/icon.svg"
26 | // if (oldLink) {
27 | // document.head.removeChild(oldLink)
28 | // }
29 | // document.head.appendChild(link)
30 | // faviconCounter++
31 | // }
32 | // }
33 |
34 | function changeFavicon(hasFocus) {
35 | // console.log("changeFavicon")
36 | const link = document.createElement("link"),
37 | oldLink = document.getElementById("dynamic-favicon")
38 |
39 | link.id = "dynamic-favicon"
40 | link.rel = "icon"
41 | link.href = hasFocus ? "src/favicon/icon-512.svg" : "src/favicon/icon-512.svg"
42 | if (oldLink) {
43 | document.head.removeChild(oldLink)
44 | }
45 | document.head.appendChild(link)
46 | }
47 |
--------------------------------------------------------------------------------
/src/js/example_section.js:
--------------------------------------------------------------------------------
1 | const exampleForm = document.querySelector("#examples_form")
2 | const exampleSettingsForm = document.querySelector("#examplesettings_form")
3 | const weightForm = document.querySelector("#weight_form")
4 | const letterSpacingForm = document.querySelector("#letter_spacing_form")
5 | const lineHeightForm = document.querySelector("#line_height_form")
6 | const fontNameForm = document.querySelector("#font_name_form")
7 | const exampleFieldset = document.querySelector("#examples_form fieldset")
8 | const fontsFieldset = document.querySelector("#fonts_form fieldset")
9 | const weightFieldset = document.querySelector("#weight_form fieldset")
10 | const letterSpacingFieldset = document.querySelector("#letter_spacing_form fieldset")
11 | const lineHeightFieldset = document.querySelector("#line_height_form fieldset")
12 | const alternatesContainer = document.querySelector("#alternates_container")
13 | const featuresContainer = document.querySelector("#features_container")
14 |
15 | function buildExample() {
16 | // console.log("buildExample")
17 | websiteData.sections.forEach((section) => {
18 | if (section.name == "customize") {
19 | fontsFieldset.innerHTML = ""
20 | section.content.fonts.forEach((font, index) => {
21 | const div = document.createElement("div")
22 | const input = document.createElement("input")
23 | input.type = "radio"
24 | input.name = "font"
25 | input.id = font.id
26 | input.classList.add("example_font")
27 | input.value = font.cssName
28 | input.dataset.forform = "fonts_form"
29 | // input.tabIndex = 0
30 | if (index == 0) {
31 | input.setAttribute("checked", "true")
32 | }
33 | const label = document.createElement("label")
34 | label.textContent = font.name
35 | label.setAttribute("for", font.id)
36 | div.append(input, label)
37 | fontsFieldset.append(div)
38 | })
39 |
40 | exampleFieldset.innerHTML = ""
41 | section.content.languages.forEach((language, index) => {
42 | const div = document.createElement("div")
43 | const input = document.createElement("input")
44 | input.type = "radio"
45 | input.name = "language"
46 | input.id = language.languageName
47 | input.classList.add("example_language")
48 | input.value = language.languageName
49 | input.dataset.forform = "examples_form"
50 | // input.tabIndex = 0
51 | if (index == 0) {
52 | input.setAttribute("checked", "true")
53 | }
54 | const label = document.createElement("label")
55 | label.textContent = language.languageName
56 | label.setAttribute("for", language.languageName)
57 | div.append(input, label)
58 | exampleFieldset.append(div)
59 | })
60 |
61 | weightFieldset.innerHTML = ""
62 | section.content.weights.forEach((weight, index) => {
63 | const div = document.createElement("div")
64 | const input = document.createElement("input")
65 | input.type = "radio"
66 | input.name = "weight"
67 | input.id = `weight_${weight}`
68 | input.classList.add("example_weight")
69 | input.value = weight
70 | input.dataset.forform = "weight_form"
71 | if (weight == 400) {
72 | input.setAttribute("checked", "true")
73 | }
74 | const label = document.createElement("label")
75 | label.textContent = weight
76 | label.setAttribute("for", `weight_${weight}`)
77 | div.append(input, label)
78 | weightFieldset.append(div)
79 | })
80 |
81 | letterSpacingFieldset.innerHTML = ""
82 | const ls = section.content.letterSpacings
83 | for (let value = ls.min; value <= ls.max; value += ls.step) {
84 | const div = document.createElement("div")
85 | const input = document.createElement("input")
86 | input.type = "radio"
87 | input.name = "letterSpacing"
88 | input.id = `letter_spacing_${value}`
89 | input.classList.add("example_letter_spacing")
90 | input.value = value
91 | input.dataset.forform = "letter_spacing_form"
92 | if (value == ls.value) input.setAttribute("checked", "true")
93 | const label = document.createElement("label")
94 | label.textContent = `${value}%`
95 | label.setAttribute("for", `letter_spacing_${value}`)
96 | div.append(input, label)
97 | letterSpacingFieldset.append(div)
98 | }
99 |
100 | lineHeightFieldset.innerHTML = ""
101 | const lh = section.content.lineHeights
102 | for (let val = lh.min; val <= lh.max + 0.01; val += lh.step) {
103 | const value = Math.round(val * 1000) / 1000
104 | const div = document.createElement("div")
105 | const input = document.createElement("input")
106 | input.type = "radio"
107 | input.name = "lineHeight"
108 | input.id = `line_height_${value}`
109 | input.classList.add("example_line_height")
110 | input.value = value
111 | input.dataset.forform = "line_height_form"
112 | if (value == lh.value) input.setAttribute("checked", "true")
113 | const label = document.createElement("label")
114 | label.textContent = value
115 | label.setAttribute("for", `line_height_${value}`)
116 | div.append(input, label)
117 | lineHeightFieldset.append(div)
118 | }
119 |
120 | featuresContainer.innerHTML = ""
121 | alternatesContainer.innerHTML = ""
122 | section.content.features.forEach((feature, index) => {
123 | const fieldset = document.createElement("fieldset")
124 | const duo = [0, 0]
125 | const p = document.createElement("p")
126 | p.textContent = `${feature.feature}: ${feature.label}`
127 | p.id = `alt_${feature.name}`
128 | fieldset.append(p)
129 | duo.forEach((_, index) => {
130 | const div = document.createElement("div")
131 | const input = document.createElement("input")
132 | input.type = "radio"
133 | input.name = feature.name
134 | input.id = `${feature.feature}_${!!index}`
135 | input.value = `'${feature.feature}' ${index == 0 ? "off" : "on"}`
136 | input.dataset.forform = "examplesettings_form"
137 | if (!feature.on && index == 0) input.setAttribute("checked", "true")
138 | if (feature.on && index == 1) input.setAttribute("checked", "true")
139 | const label = document.createElement("label")
140 | if (feature.type == "feature") label.textContent = index == 0 ? "OFF" : "ON"
141 | if (feature.type == "alternate") label.textContent = index == 0 ? "DEF" : "ALT"
142 | label.setAttribute("for", `${feature.feature}_${!!index}`)
143 | div.append(input, label)
144 | fieldset.append(div)
145 | })
146 | if (feature.type == "feature") featuresContainer.append(fieldset)
147 | else alternatesContainer.append(fieldset)
148 | })
149 | }
150 | })
151 |
152 | updateExamples(null, exampleForm)
153 | updateExampleSettings(null, exampleSettingsForm, true)
154 | }
155 |
156 | const codeExample = document.querySelector("#code_example")
157 | function updateExamples(event, form) {
158 | // console.log("updateExamples")
159 | const data = new FormData(form)
160 | let output = ""
161 | for (const entry of data) {
162 | output = `${entry[1]}`
163 | }
164 |
165 | websiteData.sections.forEach((section) => {
166 | if (section.name == "customize") {
167 | section.content.languages.forEach((language, index) => {
168 | if (language.languageName == output) {
169 | codeExample.textContent = language.codeExample
170 | let nums = Array.from(new Array(1000), (x, i) => i + 1).join("\n")
171 | codeExample.setAttribute("data-before", nums)
172 | }
173 | })
174 | }
175 | })
176 |
177 | if (event) event.preventDefault()
178 | }
179 |
180 | function updateFont(event, form) {
181 | // console.log("updateFont")
182 | const data = new FormData(form)
183 | let output = ""
184 | for (const entry of data) {
185 | output = `${entry[1]}`
186 | }
187 |
188 | if (output !== "CommitMono") codeExample.style.fontFeatureSettings = "normal"
189 | else codeExample.style.fontFeatureSettings = [...new FormData(exampleSettingsForm).values()].join(", ")
190 |
191 | let fontInDocument = false
192 | document.fonts.forEach((font) => (font.family == output ? (fontInDocument = true) : null))
193 |
194 | if (!fontInDocument) {
195 | const input = document.querySelector(`input[value="${output}"]`)
196 | input.classList.add("loading_font")
197 | const outputFont = new FontFace(output, `url(/src/fonts/other/${output}.woff2)`, {
198 | style: "normal",
199 | weight: "400",
200 | })
201 | document.fonts.add(outputFont)
202 | outputFont.load()
203 | document.fonts.ready.then(() => {
204 | codeExample.style.fontFamily = output
205 | input.classList.remove("loading_font")
206 | })
207 | } else {
208 | codeExample.style.fontFamily = output
209 | }
210 |
211 | if (event) event.preventDefault()
212 | }
213 |
214 | function updateWeight(event, form) {
215 | // console.log("updateWeight")
216 | const data = new FormData(form)
217 | let output = ""
218 | for (const entry of data) {
219 | output = +entry[1]
220 | }
221 |
222 | downloadSettingsCustom.weight = output
223 | websiteData.weight = output
224 | document.querySelector("body").style.fontVariationSettings = `"wght" ${websiteData.weight}, "ital" ${
225 | websiteData.italic ? "1" : "0"
226 | }`
227 |
228 | console.log(downloadSettingsCustom)
229 |
230 | if (event) event.preventDefault()
231 | }
232 |
233 | function updateLetterSpacing(event, form) {
234 | // console.log("updateWeight")
235 | const data = new FormData(form)
236 | let output = ""
237 | for (const entry of data) {
238 | output = +entry[1]
239 | }
240 | downloadSettingsCustom.letterSpacing = output
241 | websiteData.letterSpacing = output
242 | codeExample.style.letterSpacing = `${output / 100}em`
243 |
244 | if (event) event.preventDefault()
245 | }
246 |
247 | function updateLineHeight(event, form) {
248 | // console.log("updateWeight")
249 | const data = new FormData(form)
250 | let output = ""
251 | for (const entry of data) {
252 | output = +entry[1]
253 | }
254 | downloadSettingsCustom.lineHeight = output
255 | websiteData.lineHeight = output
256 | codeExample.style.lineHeight = output
257 |
258 | if (event) event.preventDefault()
259 | }
260 |
261 | function updateFontName(event, form) {
262 | const data = new FormData(form)
263 | let output = ""
264 | for (const entry of data) {
265 | output = entry[1]
266 | }
267 | const customName = document.querySelector("#custom_name")
268 | const suffix = output ? output : ""
269 | const regex = /^[\w-_]*$/
270 | const label = document.querySelector("#font_name + p")
271 | if (output.match(regex)) {
272 | downloadSettingsCustom.fontName = output
273 | label.textContent = "✓ Valid name."
274 | customName.textContent = `CommitMono${suffix}`
275 | websiteData.fontName = `CommitMono${suffix}`
276 | } else {
277 | downloadSettingsCustom.fontName = ""
278 | label.textContent = "✕ Invalid name, use: A-z 0-9 _ -"
279 | customName.textContent = `CommitMonoYourName`
280 | websiteData.fontName = `CommitMono`
281 | }
282 |
283 | if (event) event.preventDefault()
284 | }
285 |
286 | function updateExampleSettings(event, form, isDefault) {
287 | // console.log("updateExampleSettings")
288 | const data = new FormData(form)
289 | let output = ""
290 | function updateDownloadSettings(type, feature) {
291 | const key = feature.split("' ")[0].slice(1)
292 | const value = feature.split("' ")[1] == "on"
293 | downloadSettingsCustom[type][key] = value
294 | if (isDefault) downloadSettingsDefault[type][key] = value
295 | }
296 | for (const entry of data) {
297 | output += `${entry[1]}, `
298 | if (entry[1].includes("cv")) updateDownloadSettings("alternates", entry[1])
299 | if (entry[1].includes("ss")) updateDownloadSettings("features", entry[1])
300 |
301 | const label = document.querySelector(`#alt_${entry[0]}`)
302 | if (label) label.style.fontFeatureSettings = entry[1]
303 | }
304 | output = output.slice(0, -2)
305 |
306 | const currentFont = [...new FormData(document.forms["fonts_form"]).values()][0]
307 | if (currentFont === "CommitMono") codeExample.style.fontFeatureSettings = output
308 | else codeExample.style.fontFeatureSettings = "normal"
309 |
310 | const customFeatureCode = document.querySelector("#custom_feature_code")
311 | const shortFeatureCode = output
312 | .split(", ")
313 | .filter((f) => f.includes("on"))
314 | .join(", ")
315 | customFeatureCode.textContent = `"${shortFeatureCode}"`
316 |
317 | if (event) event.preventDefault()
318 | }
319 |
320 | function areObjectsIdentical(obj1, obj2) {
321 | return JSON.stringify(obj1) === JSON.stringify(obj2)
322 | }
323 |
324 | async function uploadCustomSettings(event, fileInput) {
325 | event.stopPropagation()
326 | event.preventDefault()
327 |
328 | const file = fileInput.files[0]
329 | const fileType = file?.name.split(".").pop()
330 |
331 | if (fileType == "json") {
332 | const fileText = await file.text()
333 | const uploadedSettings = JSON.parse(fileText)
334 | updateCustomSettings(uploadedSettings)
335 | }
336 | }
337 |
338 | function updateCustomSettings(settings) {
339 | if (settings.weight) {
340 | document.forms["weight_form"][`weight_${settings.weight}`].checked = true
341 | updateWeight(null, weightForm)
342 | }
343 | if (settings.letterSpacing) {
344 | document.forms["letter_spacing_form"][`letter_spacing_${settings.letterSpacing}`].checked = true
345 | updateLetterSpacing(null, letterSpacingForm)
346 | }
347 | if (settings.lineHeight) {
348 | document.forms["line_height_form"][`line_height_${settings.lineHeight}`].checked = true
349 | updateLineHeight(null, lineHeightForm)
350 | }
351 | if (settings.alternates) {
352 | Object.entries(settings.alternates).forEach(([feature, enabled]) => {
353 | document.forms["examplesettings_form"][`${feature}_${enabled}`].checked = true
354 | })
355 | updateExampleSettings(null, exampleSettingsForm, false)
356 | }
357 | }
358 |
359 | const customSettingsInput = document.querySelector("#custom-settings-input")
360 | customSettingsInput.addEventListener("click", () => {
361 | enterTextField()
362 | customSettingsInput.value = ""
363 | })
364 | customSettingsInput.addEventListener("blur", exitTextField)
365 | customSettingsInput.addEventListener("input", (e) => {
366 | enterTextField()
367 | try {
368 | const pastedText = JSON.parse(e.target.value)
369 | updateCustomSettings(pastedText)
370 | customSettingsInput.value = "[Imported ✓]"
371 | setTimeout(() => (customSettingsInput.value = ""), 1500)
372 | } catch (error) {
373 | if (customSettingsInput.value.includes("[Error ✕")) customSettingsInput.value = ""
374 | else if (!customSettingsInput.value.includes("[Imported ✓]")) {
375 | customSettingsInput.value = "[Error ✕]"
376 | setTimeout(() => (customSettingsInput.value = ""), 1500)
377 | }
378 | }
379 | })
380 |
381 | const copyCustomSettings = document.querySelector("#copy-custom-settings")
382 | copyCustomSettings.addEventListener("click", () => {
383 | if (navigator.clipboard) navigator.clipboard.writeText(JSON.stringify(downloadSettingsCustom))
384 | const text = copyCustomSettings.textContent
385 | copyCustomSettings.textContent = "[Copied ✓]"
386 | setTimeout(() => (copyCustomSettings.textContent = text), 1500)
387 | })
388 |
--------------------------------------------------------------------------------
/src/js/familiar_section.js:
--------------------------------------------------------------------------------
1 | const familiarContainer = document.querySelector("#familiar_container")
2 |
3 | function buildFamiliar() {
4 | // console.log("buildFamiliar")
5 | websiteData.sections.forEach((section) => {
6 | if (section.name == "familiar") {
7 | familiarContainer.innerHTML = ""
8 | section.content.timeline.forEach((example, index) => {
9 | const div = document.createElement("div")
10 | div.style.display = example.name == "commit_mono_example" ? "block" : "none"
11 | div.id = example.name
12 | div.dataset.name = example.name
13 | const svgContainer = document.createElement("div")
14 | svgContainer.innerHTML = section.content.svgs[example.name]
15 | svgContainer.tabIndex = 0
16 | svgContainer.classList.add("svg_container")
17 | const img = document.createElement("img")
18 | img.src = `/src/img/familiar/${example.src}`
19 | const p = document.createElement("p")
20 | p.tabIndex = 0
21 | p.dataset.edit = "true"
22 | example.description.forEach((description) => (p.textContent += description + " "))
23 | div.append(p)
24 | const br = document.createElement("br")
25 | div.append(br, svgContainer)
26 | familiarContainer.append(div)
27 | })
28 | }
29 | })
30 | }
31 |
32 | function updateFamiliar(event, form) {
33 | // console.log("updateFamiliar")
34 | buildFamiliar()
35 | const data = new FormData(form)
36 | let output = ""
37 | for (const entry of data) {
38 | output = entry[1]
39 | }
40 | websiteData.sections.forEach((section) => {
41 | if (section.name == "familiar") {
42 | section.content.timeline.forEach((example) => {
43 | const exampleContainer = familiarContainer.querySelector(`#${example.name}`)
44 | if (exampleContainer.dataset.name == output) {
45 | exampleContainer.style.display = "block"
46 | } else {
47 | exampleContainer.style.display = "none"
48 | }
49 | })
50 | }
51 | })
52 | event.preventDefault()
53 | }
54 |
--------------------------------------------------------------------------------
/src/js/intelligent_section.js:
--------------------------------------------------------------------------------
1 | function updateIntelligent(event, form) {
2 | // console.log("updateIntelligent")
3 | const data = new FormData(form)
4 | let output = ""
5 | for (const entry of data) {
6 | output = `${entry[1]}`
7 | }
8 | const examples = ["original", "smart_kerning", "before", "after"]
9 | examples.forEach((example) => {
10 | const exampleContainer = document.querySelector(`#${example}`)
11 | if (exampleContainer.id == output) {
12 | exampleContainer.style.display = "block"
13 | } else {
14 | exampleContainer.style.display = "none"
15 | }
16 | })
17 | event.preventDefault()
18 | }
19 |
--------------------------------------------------------------------------------
/src/js/section.js:
--------------------------------------------------------------------------------
1 | function fillSectionData() {
2 | // console.log("fillSectionData")
3 | websiteData.sections.forEach((section, index) => {
4 | const topContainer = document.querySelector(`#section_${index + 1} .top_container`)
5 | if (topContainer) {
6 | const h1 = document.createElement("h1")
7 | h1.textContent = `${index + 1 < 10 ? `0${index + 1}` : index + 1} ${capitalize(section.name)}`
8 | h1.tabIndex = 0
9 | h1.dataset.edit = "true"
10 | const br = document.createElement("br")
11 | const p = document.createElement("p")
12 | p.innerHTML = section.description
13 | p.tabIndex = 0
14 | p.dataset.edit = "true"
15 | topContainer.append(h1, br, p)
16 | }
17 | })
18 | }
19 |
--------------------------------------------------------------------------------
/src/js/start_functions.js:
--------------------------------------------------------------------------------
1 | let waitingForLoadIntervalID = null
2 | let allCssLoaded = false
3 | function startAll() {
4 | // console.log("startAll")
5 |
6 | // websiteData.invert = isDarkMode
7 |
8 | appendStyleSheets()
9 |
10 | waitingForLoadIntervalID = setInterval(() => {
11 | if (allCssLoaded) {
12 | document.querySelector("#navigate_description").focus()
13 | document.querySelector("#loading").style.display = "none"
14 | clearInterval(waitingForLoadIntervalID)
15 | waitingForLoadIntervalID = null
16 | }
17 | }, 100)
18 |
19 | fillSectionData()
20 |
21 | buildNav()
22 |
23 | buildTable()
24 |
25 | buildFamiliar()
26 |
27 | buildCode()
28 |
29 | buildDistinction()
30 |
31 | buildGTC()
32 |
33 | buildExample()
34 |
35 | buildDocs()
36 |
37 | updateCodeFont()
38 |
39 | updateWaterfall()
40 |
41 | changeFavicon(true)
42 |
43 | sectionNavigation(0)
44 |
45 | setInterval(checkDocumentFocus, 100)
46 | }
47 |
48 | if (fontsLoaded) {
49 | // console.log("fontsLoaded startAll()")
50 | startAll()
51 | }
52 |
--------------------------------------------------------------------------------
/src/js/table_section.js:
--------------------------------------------------------------------------------
1 | function buildTable() {
2 | // console.log("buildTable")
3 | const table = document.querySelector("#section_2 .content_container table")
4 |
5 | for (let i = 0; i <= 6; i++) {
6 | const tr = document.createElement("tr")
7 | const fieldset = document.createElement("fieldset")
8 | tr.append(fieldset)
9 | for (let j = 0; j <= 16; j++) {
10 | if (i == 0 || j == 0) {
11 | const th = document.createElement("th")
12 | const div = document.createElement("div")
13 | const p = document.createElement("p")
14 | if (i != 0 && j == 0) {
15 | p.textContent = createBinaryString(i + 1, 3)
16 | } else if (i == 0 && j != 0) {
17 | p.textContent = createBinaryString(j - 1, 4)
18 | } else {
19 | p.textContent = ""
20 | }
21 | div.append(p)
22 | th.append(div)
23 | fieldset.append(th)
24 | } else {
25 | const charCode = (i - 1) * 16 + j + 31
26 |
27 | const td = document.createElement("td")
28 | td.id = `td_${charCode}`
29 | const div = document.createElement("div")
30 | const input = document.createElement("input")
31 | input.type = "radio"
32 | input.id = `char_${charCode}`
33 | input.name = `row_${i}`
34 | input.value = charCode
35 | // input.tabIndex = 0
36 | input.dataset.forform = "table_form"
37 | // input.tabIndex = 0
38 | if (j == 2) input.setAttribute("checked", "true")
39 | const label = document.createElement("label")
40 | label.textContent = i == 6 && j == 16 ? "" : String.fromCharCode(charCode)
41 | label.setAttribute("for", `char_${charCode}`)
42 | // label.dataset.edit = "true"
43 | div.append(input, label)
44 | td.append(div)
45 | fieldset.append(td)
46 | }
47 | }
48 | table.append(tr)
49 | }
50 | }
51 | const createBinaryString = (number, length) => parseInt(number, 10).toString(2).padStart(length, "0")
52 |
53 | let previousOutput = [33, 49, 65, 81, 97, 113]
54 | function updateTable(event, form) {
55 | // console.log("updateTable")
56 | const data = new FormData(form)
57 | let output = []
58 | for (const entry of data) output.push(+entry[1])
59 | let indexOfChange = 0
60 | let offset = 0
61 | output.forEach((row, index) => (row != previousOutput[index] ? (indexOfChange = index) : null))
62 | output.forEach((row, index) => (index == indexOfChange ? (offset = row - previousOutput[index]) : null))
63 | output.forEach((row, index) => {
64 | if (index != indexOfChange) {
65 | document.forms["table_form"][`char_${row + offset}`].checked = true
66 | output[index] += offset
67 | }
68 | })
69 | previousOutput = [...output]
70 | event.preventDefault()
71 | }
72 |
--------------------------------------------------------------------------------
/src/js/utility_functions.js:
--------------------------------------------------------------------------------
1 | // takes a string and returns a string, where the first letter is uppercase
2 | function capitalize(string) {
3 | const stringArray = string.split("")
4 | return stringArray.shift().toUpperCase() + stringArray.join("")
5 | }
6 |
7 | const mapRange = (value, x1, y1, x2, y2) => ((value - x1) * (y2 - x2)) / (y1 - x1) + x2
8 |
9 | const getCssVar = (property) => getComputedStyle(document.documentElement).getPropertyValue(property)
10 | const setCssVar = ([property, value]) => document.documentElement.style.setProperty(property, value)
11 |
12 | const isMobileTest = () => {
13 | if (window.matchMedia("(pointer: coarse) and (max-width: 1000px").matches) {
14 | // console.log("(pointer: coarse) and (max-width: 1000px)")
15 | return true
16 | } else return false
17 | }
18 |
19 | const mobileMediaQuery = "(pointer: coarse) and (max-width: 1000px)"
20 | const mqlMobile = window.matchMedia(mobileMediaQuery)
21 | let isMobile = mqlMobile.matches
22 | mqlMobile.addEventListener("change", (e) => {
23 | isMobile = e.matches
24 | changedFocus(true)
25 | })
26 |
27 | // const darkModeMediaQuery = "(prefers-color-scheme: dark)"
28 | // const mqlDarkMode = window.matchMedia(darkModeMediaQuery)
29 | // let isDarkMode = mqlDarkMode.matches
30 | // mqlDarkMode.addEventListener("change", changeMode)
31 | function changeMode(isDarkMode, isHighContrast) {
32 | // console.log("CHANGE THEME")
33 | websiteData.invert = isDarkMode
34 | websiteData.highContrast = isHighContrast
35 | if (isHighContrast) {
36 | if (websiteData.invert) {
37 | setCssVar(["--bg", "#000"])
38 | setCssVar(["--text", "#fff"])
39 | } else {
40 | setCssVar(["--bg", "#fff"])
41 | setCssVar(["--text", "#000"])
42 | }
43 | } else {
44 | if (websiteData.invert) {
45 | setCssVar(["--bg", "#111"])
46 | setCssVar(["--text", "#aaa"])
47 | } else {
48 | setCssVar(["--bg", "#aaa"])
49 | setCssVar(["--text", "#111"])
50 | }
51 | }
52 | updateCode(null, codeForm)
53 | }
54 |
55 | function wait(milliseconds) {
56 | return new Promise((resolve) => {
57 | setTimeout(resolve, milliseconds)
58 | })
59 | }
60 |
61 | let checkCssLoadIntervalIDs = []
62 | function appendStyleSheets() {
63 | // console.log("appendStyleSheets")
64 | const stylesheetIndexes = [
65 | "style",
66 | "mobile",
67 | "non_essential",
68 | "section_1",
69 | "section_2",
70 | "section_3",
71 | "section_4",
72 | "section_5",
73 | "section_6",
74 | "section_7",
75 | "section_8",
76 | "section_9",
77 | "section_10",
78 | ]
79 | const head = document.querySelector("head")
80 | stylesheetIndexes.forEach((stylesheet, index) => {
81 | const link = document.createElement("link")
82 | link.setAttribute("rel", "stylesheet")
83 | link.setAttribute("href", `src/css/${stylesheet}.css`)
84 | head.append(link)
85 | checkCssLoadIntervalIDs[index] = setInterval(() => {
86 | const cssLoaded = Boolean(link.sheet)
87 | if (cssLoaded) {
88 | // console.log(`${stylesheet} CSS loaded`)
89 | clearInterval(checkCssLoadIntervalIDs[index])
90 | checkCssLoadIntervalIDs[index] = null
91 | if (index == 3) {
92 | allCssLoaded = true
93 | // console.log("ALL CSS LOADED")
94 | }
95 | }
96 | }, 100)
97 | })
98 | }
99 |
100 | function showHideChangeSettings(text, ms, dim) {
101 | const changeSetting = document.querySelector("#change_setting p")
102 | changeSetting.textContent = text
103 | changeSetting.style.visibility = "visible"
104 | if (dim) {
105 | document.querySelector("#nav_form").classList.add("faded")
106 | document.querySelector("#main_scale").classList.add("faded")
107 | }
108 | clearTimeout(changeSettingTimeoutID)
109 | changeSettingTimeoutID = setTimeout(() => {
110 | changeSetting.style.visibility = "hidden"
111 | if (dim) {
112 | document.querySelector("#nav_form").classList.remove("faded")
113 | document.querySelector("#main_scale").classList.remove("faded")
114 | }
115 | }, ms ?? 1000)
116 | }
117 |
118 | const consol = {
119 | log: function (message) {
120 | // console.log(message)
121 | },
122 | }
123 |
--------------------------------------------------------------------------------
/src/language_examples/brainfuck.bf:
--------------------------------------------------------------------------------
1 | ++++++++++>>++++++++++[<++++++++++>-]<[>>+>>+++>>>>+>+>+<<<<<<<<[>+>->+<[>]>[<+>
2 | -]<<[<]>-]>>>[>>>-<<<[-]][-]<[-]+++++<[<+>-]<[>+>->+<[>]>[<+>-]<<[<]>-]>>>[>>>>-
3 | <<<<[-]]>>>[>>>-[------->+<]>---.[-->+++<]>.-[--->+<]>++..[-]<<<<[-]<<[-]]>[>>++
4 | ++[++++>---<]>-.++[----->+<]>+.+++++..[-]<<<[-]<[-]]>[<<<<<<<[>>>>>>>>+>>>>>>>>+
5 | <<<<<<<<<<<<<<<<-]>>>>>>>>>>>>>>>>[<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>-]<<<<<<++++
6 | ++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>
7 | +>>]<<<<<]>[-]>>[>++++++[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->++++++++<]>.[
8 | -]]<<++++++[-<++++++++>]<.[-]<<[-<+>]<[-]<[-]]<<<<<[-]<[-]<[<+>-]<<<<.>-]
--------------------------------------------------------------------------------
/src/language_examples/c++.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | using namespace std;
6 |
7 | int main(int argc, char **argv)
8 | {
9 | if (argc == 1)
10 | {
11 | cout << "Usage: please input a non-negative integer\n";
12 | return 1;
13 | }
14 | string tmp = argv[1];
15 | if (argc == 1 || argv[1][0] == '\0' || (atoi(argv[1]) == 0 && strcmp(argv[1], "0") != 0) || atoi(argv[1]) < 0 || tmp.find(".") != string::npos)
16 | {
17 | cout << "Usage: please input a non-negative integer\n";
18 | }
19 | else
20 | {
21 | int input = atoi(argv[1]);
22 | if (input == 0 || input == 1)
23 | {
24 | cout << "composite\n";
25 | return 0;
26 | }
27 | for (int i = 2; i < input; ++i)
28 | {
29 | if (input % i == 0)
30 | {
31 | cout << "composite\n";
32 | return 0;
33 | }
34 | }
35 | cout << "Prime\n";
36 | }
37 |
38 | return 0;
39 | }
--------------------------------------------------------------------------------
/src/language_examples/fortran.f:
--------------------------------------------------------------------------------
1 | ! upcase and to_upper didn't work,
2 | ! had to resort to check ASCII value of first letter & then
3 | ! subtract 32 from it, ...
4 | program capitalize
5 | character(len=100) :: cmd
6 | character(len=1) :: firstletter
7 | character(len=:), allocatable :: printoutput
8 |
9 | ! Anything not equal to single argument, Print Error
10 | IF(COMMAND_ARGUMENT_COUNT().NE.1)THEN
11 | write(*,'(g0.8)')"Usage: please provide a string"
12 | STOP
13 | ENDIF
14 |
15 | CALL GET_COMMAND_ARGUMENT(1,cmd)
16 | if (cmd == "") then
17 | write(*,'(g0.8)')"Usage: please provide a string"
18 | STOP
19 | endif
20 | ! Get first letter
21 | firstletter = cmd(1:1)
22 | ! Check if first letter is between ASCII Value of a and z
23 | if (iachar(firstletter)>= iachar("a") .and. iachar(firstletter)<=iachar("z") ) then
24 | ! Subtract 32 from ASCII Value, to convert it to respective capital letter
25 | firstletter = achar(iachar(firstletter)-32)
26 | ! Overwrite the first letter
27 | cmd(1:1) = firstletter
28 | end if
29 | printoutput = adjustl(trim(cmd))
30 | write(*,'(g0.8)')printoutput
31 | end program capitalize
--------------------------------------------------------------------------------
/src/language_examples/html.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
23 |
24 |
25 | Commit Mono
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/language_examples/java.java:
--------------------------------------------------------------------------------
1 | class PrimeNumberException extends Exception {
2 | }
3 |
4 | public class PrimeNumber {
5 |
6 | public static boolean isPrime(int number) {
7 | if ((number % 2 == 0 && number != 2) || number == 1) {
8 | return false;
9 | }
10 |
11 | boolean foundFactor = false;
12 | for (int n = 3; n <= (int) Math.ceil(Math.sqrt(number)); ++n) {
13 | if ((number % n) == 0) {
14 | foundFactor = true;
15 | break;
16 | }
17 | }
18 | return !foundFactor;
19 | }
20 |
21 | public static void main(String[] args) {
22 | try {
23 |
24 | if (args.length < 1 || args[0].indexOf('-') != -1) {
25 | throw new PrimeNumberException();
26 | }
27 |
28 | if (isPrime(Integer.valueOf(args[0]))) {
29 | System.out.println("Prime");
30 |
31 | } else {
32 | System.out.println("Composite");
33 | }
34 |
35 | } catch (NumberFormatException | PrimeNumberException e) {
36 | System.err.println("Usage: please input a non-negative integer");
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/src/language_examples/javascript.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Main Code for Longest Commmon Subsequence
3 | *
4 | * @param {Integer[]} arr1
5 | * @param {Integer[]} arr2
6 | */
7 |
8 | function lcs(arr1, arr2) {
9 | let matrix = [...Array(arr1.length + 1)].fill(0).map(() => Array(arr2.length + 1).fill(0))
10 |
11 | for (let rowIndex = 1; rowIndex <= arr1.length; rowIndex++) {
12 | for (let columnIndex = 1; columnIndex <= arr2.length; columnIndex++) {
13 | if (arr1[rowIndex - 1] === arr2[columnIndex - 1]) {
14 | matrix[rowIndex][columnIndex] = 1 + matrix[rowIndex - 1][columnIndex - 1]
15 | } else {
16 | matrix[rowIndex][columnIndex] = Math.max(
17 | matrix[rowIndex - 1][columnIndex],
18 | matrix[rowIndex][columnIndex - 1],
19 | )
20 | }
21 | }
22 | }
23 | //If there is no match, printing empty string
24 | if (matrix[arr1.length][arr2.index] === 0) {
25 | console.log("")
26 | return
27 | }
28 |
29 | let result = []
30 | let rowIndex = arr1.length
31 | let columnIndex = arr2.length
32 |
33 | while (rowIndex > 0 && columnIndex > 0) {
34 | if (arr1[rowIndex - 1] === arr2[columnIndex - 1]) {
35 | //Prepending everytime a new character is matched in both strings
36 | result.unshift(arr1[rowIndex - 1])
37 | rowIndex--
38 | columnIndex--
39 | } else if (matrix[rowIndex - 1][columnIndex] === matrix[rowIndex][columnIndex]) {
40 | rowIndex--
41 | } else {
42 | columnIndex--
43 | }
44 | }
45 | //Converting the LCS array into a comma separated string
46 | console.log(result.join(", "))
47 | }
48 |
49 | //Usage Text
50 | const usage = 'Usage: please provide two lists in the format "1, 2, 3, 4, 5"'
51 | if (process.argv.length < 4 || process.argv[2] == "" || process.argv[3] == "") {
52 | console.log(usage)
53 | return
54 | } else {
55 | const input1 = process.argv[2]
56 | const input2 = process.argv[3]
57 | //Parsing into integers after trimming extra blank spaces
58 | const array1 = input1.split(",").map((x) => parseInt(x.trim(), 10))
59 | const array2 = input2.split(",").map((y) => parseInt(y.trim(), 10))
60 | lcs(array1, array2)
61 | }
62 |
--------------------------------------------------------------------------------
/src/language_examples/kotlin.kts:
--------------------------------------------------------------------------------
1 | fun main(args: Array)
2 | {
3 | if (args.isNullOrEmpty() || args[0].isBlank() || args[0].toIntOrNull()?.takeIf { it >= 0 } == null) {
4 | println("Usage: please input a non-negative integer")
5 | return
6 | }
7 |
8 | val num = args[0].toInt()
9 | if(num>1)
10 | {
11 | for(i in 2 until num)
12 | {
13 | if(num%i == 0)
14 | {
15 | println("Composite")
16 | return
17 | }
18 | }
19 | println("Prime")
20 | }
21 | else
22 | {
23 | println("Composite")
24 | }
25 | }
--------------------------------------------------------------------------------
/src/language_examples/php.php:
--------------------------------------------------------------------------------
1 | 4
10 | end
11 |
12 | counter_numbers.reject { |k| k == 'M' }.all? { |(_, counter)| counter <= 3 }
13 | end
14 |
15 | def roman_to_decimal(full_roman_number)
16 | return 'Usage: please provide a string of roman numerals' if full_roman_number.nil?
17 | return 0 if full_roman_number.empty?
18 |
19 | roman_numbers = full_roman_number.upcase.split('')
20 | return 'Error: invalid string of roman numerals' unless roman_valid?(roman_numbers)
21 |
22 | total = 0
23 |
24 | roman_numbers.each_with_index do |roman_number, index|
25 | current_value = ROMAN_VALUES[roman_number.to_sym]
26 | next_value = ROMAN_VALUES[roman_numbers[index+1]&.to_sym] || 0
27 |
28 | if (current_value >= next_value)
29 | total += current_value
30 | else
31 | total -= current_value
32 | end
33 | end
34 |
35 | total
36 | end
37 |
38 | print(roman_to_decimal(ARGV[0]))
--------------------------------------------------------------------------------
/src/language_examples/rust.rs:
--------------------------------------------------------------------------------
1 | // Requirement https://sample-programs.therenegadecoder.com/projects/prime-number/
2 | // Accept a number on command line and print if it is Composite or Prime
3 | // Works till 39 digits, ...
4 |
5 | use std::env::args;
6 | use std::process::exit;
7 | use std::str::FromStr;
8 |
9 | fn usage() -> ! {
10 | println!("Usage: please input a non-negative integer");
11 | exit(0);
12 | }
13 |
14 | fn parse_int(s: &str) -> Result::Err> {
15 | s.trim().parse::()
16 | }
17 |
18 | fn main() {
19 | let mut args = args().skip(1);
20 |
21 | // Exit if 1st command-line argument not an positive integer
22 | let input_num: u128 = args
23 | .next()
24 | .and_then(|s| parse_int(&s).ok())
25 | .unwrap_or_else(|| usage());
26 |
27 | if input_num < 2 || (input_num != 2 && input_num % 2 == 0) {
28 | println!("Composite");
29 | exit(0);
30 | }
31 |
32 | let mut n = 3u128;
33 | while n * n <= input_num {
34 | if input_num % n == 0 {
35 | println!("Composite");
36 | exit(0);
37 | }
38 | n += 2;
39 | }
40 | println!("Prime");
41 | }
--------------------------------------------------------------------------------
/src/language_examples/typescript.ts:
--------------------------------------------------------------------------------
1 | function fibonacci(num: number) {
2 | let n = Number(num)
3 | let elementOne: number = 0
4 | let elementTwo: number = 1
5 | let result: number = 0
6 |
7 | for (let i: number = 1; i <= n; i++) {
8 | result = elementOne + elementTwo
9 | elementOne = elementTwo
10 | elementTwo = result
11 | console.log(`${i}: ${elementOne}`)
12 | }
13 | }
14 |
15 | let num_str = process.argv.length >= 3 ? process.argv[2] : ""
16 | let num: number = parseInt(num_str)
17 | if (isNaN(num)) {
18 | console.log("Usage: please input the count of fibonacci numbers to output")
19 | process.exit(0)
20 | }
21 |
22 | fibonacci(num)
23 |
--------------------------------------------------------------------------------
/src/tests/braille.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Braille Glyph Recipes
8 |
50 |
51 |
52 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/tests/braille.js:
--------------------------------------------------------------------------------
1 | function brailleRecipes() {
2 | // 1 4
3 | // 2 5
4 | // 3 6
5 | // 7 8
6 | const positionOf1 = [190, 570]
7 | const offset = 220
8 | const positions = {
9 | 1: [0, 0],
10 | 2: [0, "bd1"],
11 | 3: [0, "bd2"],
12 | 4: ["bd1", 0],
13 | 5: ["bd1", "bd1"],
14 | 6: ["bd1", "bd2"],
15 | 7: [0, "bd3"],
16 | 8: ["bd1", "bd3"],
17 | }
18 | const container = document.querySelector("#container")
19 |
20 | const blank = document.createElement("div")
21 | blank.innerHTML = `brblank
${String.fromCharCode(10240)}
`
22 | container.append(blank)
23 | for (let i = 1; i < 256; i++) {
24 | const name =
25 | "dots" +
26 | i
27 | .toString(2)
28 | .split("")
29 | .reverse()
30 | .map((n, i) => (n == 1 ? i + 1 : null))
31 | .filter(Boolean)
32 | .join("")
33 | const recipe =
34 | "=" +
35 | i
36 | .toString(2)
37 | .split("")
38 | .reverse()
39 | .map((n, i) => (n == 1 ? i + 1 : null))
40 | .filter(Boolean)
41 | .map((dotNumber) => positions[dotNumber])
42 | .map(([x, y]) => `_bdot@${x ? "`origin+" + x + "`" : "origin"},${y ? "`origin-" + y + "`" : "origin"}`)
43 | .join("+")
44 | const div = document.createElement("div")
45 | div.innerHTML = `${name}
${String.fromCharCode(10240 + i)}
`
46 | div.addEventListener("click", () => {
47 | div.classList.toggle("clicked")
48 | navigator.clipboard.writeText(recipe)
49 | })
50 | container.append(div)
51 | // console.log(name, recipe)
52 | }
53 | // console.log(positions)
54 | }
55 | brailleRecipes()
56 |
--------------------------------------------------------------------------------
/src/tests/calt.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs")
2 | const readline = require("readline")
3 |
4 | function pbcopy(data) {
5 | var proc = require("child_process").spawn("pbcopy")
6 | proc.stdin.write(data)
7 | proc.stdin.end()
8 | }
9 |
10 | async function featuresToCalt() {
11 | // const features = ["ss01_arrows", "ss02_less_equal", "ss03_case", "ss04_ellipsis", "ss05_smartkerning"]
12 | const features = ["ss03_case", "ss04_ellipsis", "ss05_smartkerning"]
13 |
14 | let calt = []
15 |
16 | for await (const feature of features) {
17 | const fileStream = fs.createReadStream(`../features/${feature}.fea`)
18 |
19 | const rl = readline.createInterface({
20 | input: fileStream,
21 | crlfDelay: Infinity,
22 | })
23 | // Note: we use the crlfDelay option to recognize all instances of CR LF
24 | // ('\r\n') in input.txt as a single line break.
25 |
26 | const lines = []
27 |
28 | lines.push(`### feature ${feature} ###`)
29 |
30 | for await (const line of rl) {
31 | // Each line in input.txt will be successively available here as `line`.
32 | // console.log(`Line from file: ${line}`)
33 | lines.push(line)
34 | }
35 |
36 | calt.push(lines)
37 | }
38 |
39 | calt = calt.flat().filter((ln) => !ln.includes("feature") && !ln.includes("} ss"))
40 | calt = calt.map((ln) => {
41 | if (ln.includes("lookup")) return ln.split("lookup ").join("lookup _")
42 | if (ln.includes("} ")) return ln.split("} ").join("} _")
43 | return ln
44 | })
45 |
46 | // calt.forEach((ln) => console.log(ln))
47 | pbcopy(`
48 | feature calt {
49 | # Contextual Alternates
50 | # Contains all 'cxxx' features
51 |
52 | ${calt.join("\n")}
53 |
54 | } calt;`)
55 | }
56 |
57 | featuresToCalt()
58 |
--------------------------------------------------------------------------------
/src/tests/classes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Generate Axis Value
8 |
9 |
10 |
11 | Classes
12 |
13 |
14 |
15 |
16 |
17 | Submit
18 |
19 |
20 |
21 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/tests/f.js:
--------------------------------------------------------------------------------
1 | // @dflt = [exclam comma period slash colon semicolon question backslash bar];
2 | // @c2_1 = [exclam.c2_1 comma.c2_1 period.c2_1 slash.c2_1 colon.c2_1 semicolon.c2_1 question.c2_1 backslash.c2_1 bar.c2_1];
3 | // @c2_2 = [exclam.c2_2 comma.c2_2 period.c2_2 slash.c2_2 colon.c2_2 semicolon.c2_2 question.c2_2 backslash.c2_2 bar.c2_2];
4 | // @c3_1 = [exclam.c3_1 comma.c3_1 period.c3_1 slash.c3_1 colon.c3_1 semicolon.c3_1 question.c3_1 backslash.c3_1 bar.c3_1];
5 | // @c3_2 = [exclam comma period slash colon semicolon question backslash bar];
6 | // @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];
7 |
8 | const input =
9 | "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"
10 | function c002(input) {
11 | const s = input.split(" ")
12 | return `
13 | @dflt = [${input}];
14 | @c2_1 = [${s.join(".c2_1 ")}.c2_1];
15 | @c2_2 = [${s.join(".c2_2 ")}.c2_2];
16 | @c3_1 = [${s.join(".c3_1 ")}.c3_1];
17 | @c3_3 = [${s.join(".c3_3 ")}.c3_3];
18 | `
19 | }
20 |
21 | function classExcess(c) {
22 | return [...new Set(c.split(" "))].join(" ")
23 | }
24 |
25 | function buildGlyphs(g) {
26 | return g
27 | .split(", ")
28 | .map((gl) => gl.split("=")[0])
29 | .join(", ")
30 | }
31 |
32 | function pbcopy(data) {
33 | var proc = require("child_process").spawn("pbcopy")
34 | proc.stdin.write(data)
35 | proc.stdin.end()
36 | }
37 |
38 | pbcopy(c002(input))
39 | console.log(c002(input))
40 |
41 | // pbcopy(classExcess(classContent))
42 | // console.log(classExcess(classContent))
43 |
44 | // pbcopy(buildGlyphs(input))
45 | // console.log(buildGlyphs(input))
46 |
--------------------------------------------------------------------------------
/src/tests/instances.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Generate Axis Value
8 |
13 |
14 |
15 | Start value
16 |
17 |
18 |
19 | End value
20 |
21 |
22 |
23 | Precision
24 |
25 |
26 |
27 | Submit
28 |
29 |
30 |
31 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/tests/tables.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | School timetable
7 |
33 |
34 |
35 | School timetable
36 |
37 |
38 |
39 |
40 | Mon
41 | Tues
42 | Wed
43 | Thurs
44 | Fri
45 | Sat
46 | Sun
47 |
48 |
49 | 1st period
50 | English
51 |
52 |
53 | German
54 | Dutch
55 |
56 |
57 |
58 |
59 | 2nd period
60 | English
61 | English
62 |
63 | German
64 | Dutch
65 |
66 |
67 |
68 |
69 | 3rd period
70 |
71 | German
72 |
73 | German
74 | Dutch
75 |
76 |
77 |
78 |
79 | 4th period
80 |
81 | English
82 |
83 | English
84 | Dutch
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/src/txt/featuretest.txt:
--------------------------------------------------------------------------------
1 | Commit Mono: Normal
2 | programming typeface
3 |
4 |
5 | FEATURES
6 | => <= H:H ... immi
7 |
8 |
9 | ALTERNATES
10 | a g . i @ 6 0 y *
11 |
12 |
13 | SMART KERNING
14 | iom oom Hom moH
15 | ioH ooH Hoo moo
16 | ioo ooi Hoi moi
17 |
18 | tmmt tCCt toot gttg CttC mttm
19 | gmmg gCCg CggC mggm
20 | CmmC mCCm
21 |
22 |
23 | ARROWS
24 | <- <------
25 | <= <======
26 | -> ------>
27 | => ======>
28 | <<-----<<
29 | >>----->>
30 | <<----->>
31 | >>-----<<
32 | <<=====<<
33 | >>=====>>
34 | <<=====>>
35 | >>=====<<
36 |
37 |
38 | CASE
39 | H: H :
40 | e: H:o
41 | H : H H: o H : o
42 | H :::::H ::::::H
43 | H ::::: H :::::: H
44 | H-----H H------H
45 | H-----n H------n
46 | n-----H n------H
47 | n-----n n------n
48 | H----- n H------ n
49 | n -----H n ------H
50 |
51 |
52 | LIGATURES
53 | x <= x >= x == x === x != x !== x
54 | x <= X >= x == X === x != X !== x
55 | X <= X >= X == X === X != X !== X
56 |
--------------------------------------------------------------------------------
/src/txt/installation.txt:
--------------------------------------------------------------------------------
1 | A short guide for how to install and enable your shiny new version of Commit Mono.
2 | This is taken from section 08 Install from https://commitmono.com/
3 |
4 | #1 (Download the fonts)
5 | #2 Unzip the fonts. You'll see 4 font files. These 4 fonts make up a 'Style Group':
6 | * CommitMono-Regular: Base version with settings and weight of your choice.
7 | * CommitMono-Italic: An italic version, same weight as regular.
8 | * CommitMono-Bold: A bold version, weight 700.
9 | * CommitMono-BoldItalic: A bold version, weight 700, that is also italic.
10 | #3 Install all 4 fonts on your system:
11 | * Windows: Right click the font in the folder and click "Install".
12 | * Mac: Open fonts with Font Book from the folder and click "Install".
13 | * Linux: Unpack fonts to ~/.local/share/fonts (or /usr/share/fonts to install
14 | fonts system-wide) then fc-cache -f -v
15 | #4 Restart your editor/IDE.
16 | #5 Activate Commit Mono in your editor.
17 | Settings/Preferences → Editor → Font: Pick ‘CommitMono’ from the list (notice:
18 | there is no space). If you’re using VS Code, simply add these two lines to the
19 | settings.json file:
20 | "editor.fontFamily": "CommitMono",
21 | "editor.fontLigatures": true,
22 |
23 | For a comprehensive guide on how to enable features/ligatures in your specific
24 | editor/IDE, refer to Fira Code wiki:
25 | https://github.com/tonsky/FiraCode/wiki#enabling-ligatures
--------------------------------------------------------------------------------
/src/txt/license.txt:
--------------------------------------------------------------------------------
1 | This Font Software is licensed under the SIL Open Font License, Version 1.1.
2 | This license is copied below, and is also available with a FAQ at:
3 | http://scripts.sil.org/OFL
4 |
5 | -----------------------------------------------------------
6 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
7 | -----------------------------------------------------------
8 |
9 | PREAMBLE
10 | The goals of the Open Font License (OFL) are to stimulate worldwide
11 | development of collaborative font projects, to support the font creation
12 | efforts of academic and linguistic communities, and to provide a free and
13 | open framework in which fonts may be shared and improved in partnership
14 | with others.
15 |
16 | The OFL allows the licensed fonts to be used, studied, modified and
17 | redistributed freely as long as they are not sold by themselves. The
18 | fonts, including any derivative works, can be bundled, embedded,
19 | redistributed and/or sold with any software provided that any reserved
20 | names are not used by derivative works. The fonts and derivatives,
21 | however, cannot be released under any other type of license. The
22 | requirement for fonts to remain under this license does not apply
23 | to any document created using the fonts or their derivatives.
24 |
25 | DEFINITIONS
26 | "Font Software" refers to the set of files released by the Copyright
27 | Holder(s) under this license and clearly marked as such. This may
28 | include source files, build scripts and documentation.
29 |
30 | "Reserved Font Name" refers to any names specified as such after the
31 | copyright statement(s).
32 |
33 | "Original Version" refers to the collection of Font Software components as
34 | distributed by the Copyright Holder(s).
35 |
36 | "Modified Version" refers to any derivative made by adding to, deleting,
37 | or substituting -- in part or in whole -- any of the components of the
38 | Original Version, by changing formats or by porting the Font Software to a
39 | new environment.
40 |
41 | "Author" refers to any designer, engineer, programmer, technical
42 | writer or other person who contributed to the Font Software.
43 |
44 | PERMISSION & CONDITIONS
45 | Permission is hereby granted, free of charge, to any person obtaining
46 | a copy of the Font Software, to use, study, copy, merge, embed, modify,
47 | redistribute, and sell modified and unmodified copies of the Font
48 | Software, subject to the following conditions:
49 |
50 | 1) Neither the Font Software nor any of its individual components,
51 | in Original or Modified Versions, may be sold by itself.
52 |
53 | 2) Original or Modified Versions of the Font Software may be bundled,
54 | redistributed and/or sold with any software, provided that each copy
55 | contains the above copyright notice and this license. These can be
56 | included either as stand-alone text files, human-readable headers or
57 | in the appropriate machine-readable metadata fields within text or
58 | binary files as long as those fields can be easily viewed by the user.
59 |
60 | 3) No Modified Version of the Font Software may use the Reserved Font
61 | Name(s) unless explicit written permission is granted by the corresponding
62 | Copyright Holder. This restriction only applies to the primary font name as
63 | presented to the users.
64 |
65 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
66 | Software shall not be used to promote, endorse or advertise any
67 | Modified Version, except to acknowledge the contribution(s) of the
68 | Copyright Holder(s) and the Author(s) or with their explicit written
69 | permission.
70 |
71 | 5) The Font Software, modified or unmodified, in part or in whole,
72 | must be distributed entirely under this license, and must not be
73 | distributed under any other license. The requirement for fonts to
74 | remain under this license does not apply to any document created
75 | using the Font Software.
76 |
77 | TERMINATION
78 | This license becomes null and void if any of the above conditions are
79 | not met.
80 |
81 | DISCLAIMER
82 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
83 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
84 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
85 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
86 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
87 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
88 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
89 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
90 | OTHER DEALINGS IN THE FONT SOFTWARE.
--------------------------------------------------------------------------------
/src/txt/todo.txt:
--------------------------------------------------------------------------------
1 | High priority
2 | [x] Make instances available
3 | [x] Make variable font available
4 | [x] Include license in download
5 | [x] Add links to Mads Brodt
6 | [x] Bold & space out FAQ
7 | [x] Fix != ligature
8 | [ ] Fix download in Safari
9 | [x] Update 08 Install to include "editor.fontLigatures": true, somewhere
10 |
11 | Medium priority
12 | [ ] Make open source and add good README.md file
13 | [ ] Improve drawing quality of italic version
14 | [ ] ?? Delete other features in code version
15 | [ ] Make Cyrillic and Greek characterset
16 | [ ] Update 08 Install with bold text
17 | [ ] Spread the word
18 | [ ] Submit website to FWA and Awwwards
19 |
20 | Low priority
21 | [ ] Make changes made in 07 Customize site wide
22 | [ ] Update GTC with more games
23 | [ ] ?? distinquish code version from web version
24 | [ ] Add support to type your own character in code section
25 | [ ] Write article to publish in some typography magazine
26 | [ ] Make Commit Sans
--------------------------------------------------------------------------------
/src/txt/ttfautohint.txt:
--------------------------------------------------------------------------------
1 | # step 1: export default from website an place in src/fonts/website-export/CommitMono.zip
2 | # step 2: make sure fontforge and ttfautohint is installed
3 | # step 3: run this from the root directory
4 |
5 | rm src/fonts/*.zip
6 | mkdir src/fonts/CommitMono-1.143
7 | mv src/fonts/website-export/CommitMono.zip src/fonts/CommitMono-1.143/CommitMono.zip
8 | cd src/fonts/CommitMono-1.143
9 | unzip CommitMono.zip
10 | rm CommitMono.zip
11 | mkdir ttfautohint
12 | fontforge -lang ff -c 'Open("CommitMono-400-Regular.otf"); Generate("CommitMono-400-Regular-unhinted.ttf")'
13 | fontforge -lang ff -c 'Open("CommitMono-400-Italic.otf"); Generate("CommitMono-400-Italic-unhinted.ttf")'
14 | fontforge -lang ff -c 'Open("CommitMono-700-Regular.otf"); Generate("CommitMono-700-Regular-unhinted.ttf")'
15 | fontforge -lang ff -c 'Open("CommitMono-700-Italic.otf"); Generate("CommitMono-700-Italic-unhinted.ttf")'
16 | ttfautohint -R CommitMono-400-Regular-unhinted.ttf -a sss CommitMono-400-Regular-unhinted.ttf ttfautohint/CommitMono-400-Regular.ttf
17 | ttfautohint -R CommitMono-400-Regular-unhinted.ttf -a sss CommitMono-400-Italic-unhinted.ttf ttfautohint/CommitMono-400-Italic.ttf
18 | ttfautohint -R CommitMono-400-Regular-unhinted.ttf -a sss CommitMono-700-Regular-unhinted.ttf ttfautohint/CommitMono-700-Regular.ttf
19 | ttfautohint -R CommitMono-400-Regular-unhinted.ttf -a sss CommitMono-700-Italic-unhinted.ttf ttfautohint/CommitMono-700-Italic.ttf
20 | rm CommitMono-400-Regular-unhinted.ttf
21 | rm CommitMono-400-Italic-unhinted.ttf
22 | rm CommitMono-700-Regular-unhinted.ttf
23 | rm CommitMono-700-Italic-unhinted.ttf
24 | cd ..
25 | zip -vr CommitMono-1.143.zip CommitMono-1.143/ -x "*.DS_Store"
26 | rm -R CommitMono-1.143
27 | cd ..
28 | cd ..
29 |
30 | # step 4: upload src/fonts/CommitMono.zip to GitHub
--------------------------------------------------------------------------------
/src/txt/woff2_conversion_guide.txt:
--------------------------------------------------------------------------------
1 | #1 Rename variable font to "CommitMonoV143-VF.ttf"
2 | #2 Navigate to /Developer/woff2
3 | #3
4 | ~/Developer/woff2/woff2_compress ~/Library/CloudStorage/Dropbox/Privat/Eigils\ ting/projects/typography/Font\ Projects/code-mono-font/commit-mono/export/CommitMonoV143/CommitMonoV143-VF.ttf
--------------------------------------------------------------------------------