├── .github
└── FUNDING.yml
├── LICENSE
├── README.md
├── fonts.css
├── index.html
├── parameters.json
├── styles.css
└── tc.js
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: letterror
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Erik van Blokland
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TypeCooker
2 |
3 | A small web tool for creating recipes for sketching and exploring type.
4 |
5 | This is the code running with very nice fonts on http://typecooker.com.
6 | A local copy is here: http://letterror.github.io/TypeCooker
7 | Follow @TypeCooker
8 |
--------------------------------------------------------------------------------
/fonts.css:
--------------------------------------------------------------------------------
1 |
2 | /* font-face declarations */
3 |
4 | /*@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:600,300);
5 | */
6 |
7 | @font-face {
8 | font-family: 'lighterSans';
9 | font-style: normal;
10 | font-weight: 300;
11 | src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(https://fonts.gstatic.com/s/sourcesanspro/v9/toadOcfmlt9b38dHJxOBGPS42wKzre0cxmO5m5GyTsY.ttf) format('truetype');
12 | }
13 | @font-face {
14 | font-family: 'heavierSans';
15 | font-style: normal;
16 | font-weight: 600;
17 | src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url(https://fonts.gstatic.com/s/sourcesanspro/v9/toadOcfmlt9b38dHJxOBGBRq_IsDXucKYMk4-diqPEc.ttf) format('truetype');
18 | }
19 |
20 | body{
21 | line-height: 120%;
22 | font-size: 6vw;
23 | }
24 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | TypeCooker
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "application":[
3 | {
4 | "url":"parameters.html#intendedapplication",
5 | "level":3,
6 | "name":"unknown",
7 | "weight":2,
8 | "description":"It is not clear how this typeface is to be used."
9 | },
10 | {
11 | "url":"parameters.html#intendedapplication",
12 | "level":3,
13 | "name":"multi-purpose",
14 | "weight":10,
15 | "description":"This typeface must do well in all sorts of sizes and media."
16 | },
17 | {
18 | "url":"parameters.html#intendedapplication",
19 | "level":3,
20 | "name":"newsprint",
21 | "weight":10,
22 | "description":"This typeface must work well on rough paper."
23 | },
24 | {
25 | "url":"parameters.html#intendedapplication",
26 | "level":3,
27 | "name":"smooth offset printing",
28 | "weight":10,
29 | "description":"This typeface must work well on smooth paper."
30 | },
31 | {
32 | "url":"parameters.html#intendedapplication",
33 | "level":4,
34 | "name":"engraving",
35 | "weight":5,
36 | "description":"This typeface needs to be engraved into something."
37 | },
38 | {
39 | "url":"parameters.html#intendedapplication",
40 | "level":3,
41 | "name":"signage",
42 | "weight":10,
43 | "description":"This typeface will be used on signage."
44 | },
45 | {
46 | "url":"parameters.html#intendedapplication",
47 | "level":4,
48 | "name":"packaging",
49 | "weight":5,
50 | "description":"This typeface will be used on packaging."
51 | },
52 | {
53 | "url":"parameters.html#intendedapplication",
54 | "level":5,
55 | "name":"subtitles on television",
56 | "weight":2,
57 | "description":"This typeface will be used on television."
58 | },
59 | {
60 | "url":"parameters.html#intendedapplication",
61 | "level":5,
62 | "name":"antialiased bitmaps",
63 | "weight":2,
64 | "description":"This typeface will be used as antialiased bitmaps."
65 | },
66 | {
67 | "url":"parameters.html#intendedapplication",
68 | "level":5,
69 | "name":"rubber stamps",
70 | "weight":2,
71 | "description":"This typeface will be used on rubber stamps."
72 | }
73 | ],
74 | "weight":[
75 | {
76 | "url":"parameters.html#strokeweight",
77 | "level":4,
78 | "name":"hairline",
79 | "weight":2,
80 | "description":"All strokes are as thin as possible."
81 | },
82 | {
83 | "url":"parameters.html#strokeweight",
84 | "level":4,
85 | "name":"very thin",
86 | "weight":3,
87 | "description":"All strokes are very thin."
88 | },
89 | {
90 | "url":"parameters.html#strokeweight",
91 | "level":3,
92 | "name":"thin",
93 | "weight":4,
94 | "description":"All strokes are thin."
95 | },
96 | {
97 | "url":"parameters.html#strokeweight",
98 | "level":3,
99 | "name":"extra light",
100 | "weight":5,
101 | "description":"All strokes are light, but not extremely."
102 | },
103 | {
104 | "url":"parameters.html#strokeweight",
105 | "level":1,
106 | "name":"light",
107 | "weight":5,
108 | "description":"All strokes are light, but not extremely."
109 | },
110 | {
111 | "url":"parameters.html#strokeweight",
112 | "level":2,
113 | "name":"book",
114 | "weight":6,
115 | "description":"All strokes are such that they're readable at arms' length."
116 | },
117 | {
118 | "url":"parameters.html#strokeweight",
119 | "level":1,
120 | "name":"plain",
121 | "weight":7,
122 | "description":"All strokes are plain. Not too light, not too heavy."
123 | },
124 | {
125 | "url":"parameters.html#strokeweight",
126 | "level":3,
127 | "name":"medium",
128 | "weight":6,
129 | "description":"All strokes are heavier than normal, not bold."
130 | },
131 | {
132 | "url":"parameters.html#strokeweight",
133 | "level":3,
134 | "name":"semi bold",
135 | "weight":5,
136 | "description":"All strokes are heavier than normal, not bold."
137 | },
138 | {
139 | "url":"parameters.html#strokeweight",
140 | "level":1,
141 | "name":"bold",
142 | "weight":4,
143 | "description":"All strokes are heavy."
144 | },
145 | {
146 | "url":"parameters.html#strokeweight",
147 | "description":"All strokes are heavier than bold.",
148 | "name":"extra bold",
149 | "weight":3,
150 | "level":3
151 | },
152 | {
153 | "url":"parameters.html#strokeweight",
154 | "level":4,
155 | "name":"black",
156 | "weight":2,
157 | "description":"All strokes are as heavy as they can be."
158 | }
159 | ],
160 | "keys":[
161 | "width",
162 | "weight",
163 | "construction",
164 | "stroke endings",
165 | "ascender",
166 | "descender",
167 | "contrast type",
168 | "contrast amount",
169 | "stems",
170 | "application",
171 | "size",
172 | "special",
173 | "also"
174 | ],
175 | "stroke endings":[
176 | {
177 | "url":"parameters.html#strokeendings",
178 | "level":1,
179 | "name":"straight, no serif",
180 | "weight":10,
181 | "description":"The strokes do not end in serifs."
182 | },
183 | {
184 | "url":"parameters.html#strokeendings",
185 | "level":1,
186 | "name":"serifs",
187 | "weight":10,
188 | "description":"The strokes end in serifs."
189 | },
190 | {
191 | "url":"parameters.html#strokeendings",
192 | "level":3,
193 | "name":"rounded, no serif",
194 | "weight":5,
195 | "description":"The strokes are rounded at the end."
196 | },
197 | {
198 | "url":"parameters.html#strokeendings",
199 | "level":3,
200 | "name":"bracketed serif",
201 | "weight":5,
202 | "description":"The strokes end in bracketed serifs."
203 | },
204 | {
205 | "url":"parameters.html#strokeendings",
206 | "level":4,
207 | "name":"asymmetric serif",
208 | "weight":5,
209 | "description":"The strokes end in asymmetric serifs."
210 | },
211 | {
212 | "url":"parameters.html#strokeendings",
213 | "level":4,
214 | "name":"wedge serif",
215 | "weight":10,
216 | "description":"The strokes end in triangular serifs."
217 | },
218 | {
219 | "url":"parameters.html#strokeendings",
220 | "level":3,
221 | "name":"slab serif",
222 | "weight":5,
223 | "description":"The strokes end in rectangular serifs."
224 | }
225 | ],
226 | "ascender":[
227 | {
228 | "url":"parameters.html#ascender",
229 | "level":3,
230 | "name":"longer than normal",
231 | "weight":5,
232 | "description":"The ascenders should be longer than normal. But what is normal?"
233 | },
234 | {
235 | "url":"parameters.html#ascender",
236 | "level":3,
237 | "name":"shorter than normal",
238 | "weight":5,
239 | "description":"The ascenders should be shorter than normal. But what is normal?"
240 | },
241 | {
242 | "url":"parameters.html#ascender",
243 | "level":4,
244 | "name":"much shorter than normal",
245 | "weight":2,
246 | "description":"The ascenders should be much shorter than normal. But what is normal?"
247 | },
248 | {
249 | "url":"parameters.html#ascender",
250 | "level":4,
251 | "name":"much longer than normal",
252 | "weight":2,
253 | "description":"The ascenders should be much longer than normal. But what is normal?"
254 | },
255 | {
256 | "url":"parameters.html#ascender",
257 | "level":5,
258 | "name":"none at all",
259 | "weight":1,
260 | "description":"There is no room for ascenders."
261 | }
262 | ],
263 | "construction":[
264 | {
265 | "url":"parameters.html#construction",
266 | "level":1,
267 | "name":"roman",
268 | "weight":10,
269 | "description":"Construct the letters as lowercase romans."
270 | },
271 | {
272 | "url":"parameters.html#construction",
273 | "level":1,
274 | "name":"capitals",
275 | "weight":10,
276 | "description":"Construct the letters as capitals."
277 | },
278 | {
279 | "url":"parameters.html#construction",
280 | "level":2,
281 | "name":"italic",
282 | "weight":10,
283 | "description":"Construct the letters as cursive italics."
284 | },
285 | {
286 | "url":"parameters.html#construction",
287 | "level":4,
288 | "name":"caps and smallcaps",
289 | "weight":2,
290 | "description":"Construct the letters with an initial capital, then followed by smallcaps."
291 | },
292 | {
293 | "url":"parameters.html#construction",
294 | "level":3,
295 | "name":"roman + capitals",
296 | "weight":5,
297 | "description":"Construct the letters with an initial capital, then followed by lowercase roman."
298 | },
299 | {
300 | "url":"parameters.html#construction",
301 | "level":3,
302 | "name":"italic + capitals",
303 | "weight":5,
304 | "description":"Construct the letters with an initial capital, then followed by lowercase italic."
305 | },
306 | {
307 | "url":"parameters.html#construction",
308 | "level":3,
309 | "name":"proportional oldstyle figures",
310 | "weight":2,
311 | "description":"Old style (non-lining) figures with proportional widths."
312 | },
313 | {
314 | "url":"parameters.html#construction",
315 | "level":3,
316 | "name":"tabular oldstyle figures",
317 | "weight":2,
318 | "description":"Old style (non-lining) figures with tabular widths."
319 | },
320 | {
321 | "url":"parameters.html#construction",
322 | "level":3,
323 | "name":"proportional lining figures",
324 | "weight":2,
325 | "description":"Lining figures with proportional widths."
326 | },
327 | {
328 | "url":"parameters.html#construction",
329 | "level":3,
330 | "name":"tabular lining figures",
331 | "weight":2,
332 | "description":"Lining figures with tabular widths."
333 | },
334 | {
335 | "url":"parameters.html#construction",
336 | "level":3,
337 | "name":"smallcaps figures",
338 | "weight":2,
339 | "description":"Figures fitting to smallcap size. Add a regular capital to get a sense of the proportions."
340 | }
341 | ],
342 | "stems":[
343 | {
344 | "url":"parameters.html#stems",
345 | "level":3,
346 | "name":"straight",
347 | "weight":10,
348 | "description":"The stems are perfectly straight."
349 | },
350 | {
351 | "url":"parameters.html#stems",
352 | "level":3,
353 | "name":"slightly concave",
354 | "weight":4,
355 | "description":"The stems are slightly curved inward. Reversed entasis."
356 | },
357 | {
358 | "url":"parameters.html#stems",
359 | "level":4,
360 | "name":"visibly concave",
361 | "weight":4,
362 | "description":"The stems are visibly curved inward. Reversed entasis."
363 | },
364 | {
365 | "url":"parameters.html#stems",
366 | "level":4,
367 | "name":"flaring",
368 | "weight":4,
369 | "description":"The stems are very much curved inward. Might involve serifs."
370 | },
371 | {
372 | "url":"parameters.html#stems",
373 | "level":5,
374 | "name":"convex",
375 | "weight":2,
376 | "description":"The stems are very much curved outward. Entasis."
377 | }
378 | ],
379 | "special":[
380 | {
381 | "url":"parameters.html#special",
382 | "level":4,
383 | "name":"only straight lines",
384 | "weight":5,
385 | "description":"Use no curves. Curves are overrated."
386 | },
387 | {
388 | "url":"parameters.html#special",
389 | "level":4,
390 | "name":"curves as octagonals",
391 | "weight":5,
392 | "description":"Eight segments to make an oval."
393 | },
394 | {
395 | "url":"parameters.html#special",
396 | "level":4,
397 | "name":"rough contours",
398 | "weight":2,
399 | "description":"The contours are rought. Should not be that difficult."
400 | },
401 | {
402 | "url":"parameters.html#special",
403 | "level":4,
404 | "name":"casual",
405 | "weight":2,
406 | "description":"Displays a casual approach to construction and finish."
407 | },
408 | {
409 | "url":"parameters.html#special",
410 | "level":4,
411 | "name":"sketchy",
412 | "weight":2,
413 | "description":"Letters appear sketchy."
414 | },
415 | {
416 | "url":"parameters.html#special",
417 | "level":4,
418 | "name":"cut as a stencil",
419 | "weight":5,
420 | "description":"Make sure the contours do not drop out."
421 | },
422 | {
423 | "url":"parameters.html#special",
424 | "level":4,
425 | "name":"at least 1 ligature",
426 | "weight":8,
427 | "description":"Two letters must form a ligature."
428 | },
429 | {
430 | "url":"parameters.html#special",
431 | "level":4,
432 | "name":"at least 2 ligatures",
433 | "weight":8,
434 | "description":"Two pairs of letters must form a ligature."
435 | },
436 | {
437 | "url":"parameters.html#special",
438 | "level":4,
439 | "name":"inktraps for white corners",
440 | "weight":4,
441 | "description":"Open sharp white corners a bit."
442 | },
443 | {
444 | "url":"parameters.html#special",
445 | "level":4,
446 | "name":"inktraps for black corners",
447 | "weight":4,
448 | "description":"Prevent sharp black corners from rounding."
449 | },
450 | {
451 | "url":"parameters.html#special",
452 | "level":4,
453 | "name":"initial and final swashes",
454 | "weight":5,
455 | "description":"Add unnecessary but pretty frivolities to first and last letters."
456 | }
457 | ],
458 | "contrast type":[
459 | {
460 | "url":"parameters.html#contrasttype",
461 | "level":2,
462 | "name":"translation",
463 | "weight":5,
464 | "description":"The contrast produced by a broad nib pen."
465 | },
466 | {
467 | "url":"parameters.html#contrasttype",
468 | "level":2,
469 | "name":"expansion",
470 | "weight":5,
471 | "description":"The contrast produced by a flexible or pointed nib pen."
472 | },
473 | {
474 | "url":"parameters.html#contrasttype",
475 | "level":4,
476 | "name":"transitional",
477 | "weight":5,
478 | "description":"A historical mix of broad nib and pointed nib influences."
479 | },
480 | {
481 | "url":"parameters.html#contrasttype",
482 | "level":4,
483 | "name":"between translation and transitional",
484 | "weight":5,
485 | "description":"A historical mix of broad nib and pointed nib influences."
486 | },
487 | {
488 | "url":"parameters.html#contrasttype",
489 | "level":4,
490 | "name":"between expansion and transitional",
491 | "weight":5,
492 | "description":"A historical mix of broad nib and pointed nib influences."
493 | },
494 | {
495 | "url":"parameters.html#contrasttype",
496 | "level":4,
497 | "name":"speedball",
498 | "weight":2,
499 | "description":"Very low contrast as produced by the Speedball pen."
500 | },
501 | {
502 | "url":"parameters.html#contrasttype",
503 | "level":4,
504 | "name":"brush",
505 | "weight":2,
506 | "description":"Largely translation, but incorporating rotation and pressure."
507 | },
508 | {
509 | "url":"parameters.html#contrasttype",
510 | "level":5,
511 | "name":"can't be determined",
512 | "weight":2,
513 | "description":"The contrast is rather difficult to identify. That does not mean is has no contrast!"
514 | }
515 | ],
516 | "also":[
517 | {
518 | "url":"parameters.html#special",
519 | "level":4,
520 | "name":"as a bold",
521 | "weight":2,
522 | "description":"As defined by the other parameters, but then also some letters as a bold."
523 | },
524 | {
525 | "url":"parameters.html#special",
526 | "level":4,
527 | "name":"as a hairline",
528 | "weight":2,
529 | "description":"As defined by the other parameters, but then also some letters as a hairline."
530 | },
531 | {
532 | "url":"parameters.html#special",
533 | "level":4,
534 | "name":"as a black",
535 | "weight":2,
536 | "description":"As defined by the other parameters, but then also some letters as a black."
537 | },
538 | {
539 | "url":"parameters.html#special",
540 | "level":4,
541 | "name":"as reversed contrast",
542 | "weight":1,
543 | "description":"As defined by the other parameters, but then also some letters with reversed contrast."
544 | },
545 | {
546 | "url":"parameters.html#special",
547 | "level":4,
548 | "name":"as an italic",
549 | "weight":1,
550 | "description":"As defined by the other parameters, but then also some italic letters."
551 | },
552 | {
553 | "url":"parameters.html#special",
554 | "level":4,
555 | "name":"with some smallcaps",
556 | "weight":1,
557 | "description":"As defined by the other parameters, but then also some smallcaps."
558 | }
559 | ],
560 | "descender":[
561 | {
562 | "url":"parameters.html#descender",
563 | "level":3,
564 | "name":"longer than normal",
565 | "weight":5,
566 | "description":"The descenders should be longer than normal. But what is normal?"
567 | },
568 | {
569 | "url":"parameters.html#descender",
570 | "level":3,
571 | "name":"shorter than normal",
572 | "weight":5,
573 | "description":"The descenders should be shorter than normal. But what is normal?"
574 | },
575 | {
576 | "url":"parameters.html#descender",
577 | "level":4,
578 | "name":"much shorter than normal",
579 | "weight":2,
580 | "description":"The descenders should be much shorter than normal. But what is normal?"
581 | },
582 | {
583 | "url":"parameters.html#descender",
584 | "level":5,
585 | "name":"none",
586 | "weight":1,
587 | "description":"There is no room for descenders."
588 | }
589 | ],
590 | "contrast amount":[
591 | {
592 | "url":"parameters.html#contrastamount",
593 | "level":5,
594 | "name":"inverted",
595 | "weight":10,
596 | "description":"Thicks are thins and thins are thick."
597 | },
598 | {
599 | "url":"parameters.html#contrastamount",
600 | "level":5,
601 | "name":"slightly inverted",
602 | "weight":10,
603 | "description":"Thicks are thins and thins are thick. But try to be subtle."
604 | },
605 | {
606 | "url":"parameters.html#contrastamount",
607 | "level":4,
608 | "name":"no contrast at all",
609 | "weight":10,
610 | "description":"Thick equals thin. There is no contrast, even when you really need it."
611 | },
612 | {
613 | "url":"parameters.html#contrastamount",
614 | "level":3,
615 | "name":"not visible",
616 | "weight":10,
617 | "description":"Thick looks like thin. There appears to be no contrast."
618 | },
619 | {
620 | "url":"parameters.html#contrastamount",
621 | "level":3,
622 | "name":"very low",
623 | "weight":10,
624 | "description":"Thicks are similar to thins."
625 | },
626 | {
627 | "url":"parameters.html#contrastamount",
628 | "level":1,
629 | "name":"low",
630 | "weight":10,
631 | "description":"Thicks are similar to thins."
632 | },
633 | {
634 | "url":"parameters.html#contrastamount",
635 | "level":1,
636 | "name":"some",
637 | "weight":10,
638 | "description":"Thicks are similar to thins but you can tell the difference."
639 | },
640 | {
641 | "url":"parameters.html#contrastamount",
642 | "level":2,
643 | "name":"visible",
644 | "weight":10,
645 | "description":"Thicks are visibly thicker than the thins."
646 | },
647 | {
648 | "url":"parameters.html#contrastamount",
649 | "level":2,
650 | "name":"quite some contrast",
651 | "weight":10,
652 | "description":"Thicks are visibly thicker than the thins."
653 | },
654 | {
655 | "url":"parameters.html#contrastamount",
656 | "level":1,
657 | "name":"a lot",
658 | "weight":10,
659 | "description":"Thicks are a lot thicker than the thins."
660 | },
661 | {
662 | "url":"parameters.html#contrastamount",
663 | "level":2,
664 | "name":"high",
665 | "weight":10,
666 | "description":"A lot of difference between the thicks and the thins."
667 | },
668 | {
669 | "url":"parameters.html#contrastamount",
670 | "level":4,
671 | "name":"very high",
672 | "weight":10,
673 | "description":"A lot of difference between the thicks and the thins."
674 | },
675 | {
676 | "url":"parameters.html#contrastamount",
677 | "level":5,
678 | "name":"extreme",
679 | "weight":10,
680 | "description":"The thicks and thins are as different as you can make them."
681 | }
682 | ],
683 | "width":[
684 | {
685 | "url":"parameters.html#width",
686 | "level":4,
687 | "name":"compressed",
688 | "weight":2,
689 | "description":"The overall width is as small as possible."
690 | },
691 | {
692 | "url":"parameters.html#width",
693 | "level":3,
694 | "name":"extra condensed",
695 | "weight":3,
696 | "description":"The overall width is really small, almost no room for counters."
697 | },
698 | {
699 | "level":2,
700 | "name":"condensed",
701 | "weight":3,
702 | "description":"The overall width is small, but not uncomfortably so."
703 | },
704 | {
705 | "url":"parameters.html#width",
706 | "level":1,
707 | "name":"narrow",
708 | "weight":4,
709 | "description":"Not much overall width."
710 | },
711 | {
712 | "url":"parameters.html#width",
713 | "level":1,
714 | "name":"normal",
715 | "weight":5,
716 | "description":"A normal width."
717 | },
718 | {
719 | "url":"parameters.html#width",
720 | "level":1,
721 | "name":"extended",
722 | "weight":4,
723 | "description":"The overall width is larger than normal. (But what is normal)"
724 | },
725 | {
726 | "url":"parameters.html#width",
727 | "level":2,
728 | "name":"wide",
729 | "weight":3,
730 | "description":"The overall width is definitely wide."
731 | },
732 | {
733 | "url":"parameters.html#width",
734 | "level":2,
735 | "name":"very wide",
736 | "weight":2,
737 | "description":"The overall width is very large."
738 | },
739 | {
740 | "url":"parameters.html#width",
741 | "level":3,
742 | "name":"extremely wide",
743 | "weight":1,
744 | "description":"Draw something really wide. Then make it twice as wide again."
745 | },
746 | {
747 | "url":"parameters.html#width",
748 | "level":4,
749 | "name":"monospaced",
750 | "weight":2,
751 | "description":"All letters have the same width"
752 | },
753 | {
754 | "url":"parameters.html#width",
755 | "level":4,
756 | "name":"monospaced condensed",
757 | "weight":2,
758 | "description":"All letters have the same, narrow, width"
759 | }
760 | ],
761 | "size":[
762 | {
763 | "url":"parameters.html#intendedsize",
764 | "level":4,
765 | "name":"agate",
766 | "weight":2,
767 | "description":"Really small, really legible."
768 | },
769 | {
770 | "url":"parameters.html#intendedsize",
771 | "level":4,
772 | "name":"reading",
773 | "weight":4,
774 | "description":"Really legible at arms length."
775 | },
776 | {
777 | "url":"parameters.html#intendedsize",
778 | "level":4,
779 | "name":"phone reading",
780 | "weight":8,
781 | "description":"Anticipating contemporary web design, the type will be too small. Can the font help?"
782 | },
783 | {
784 | "url":"parameters.html#intendedsize",
785 | "level":4,
786 | "name":"laptop reading",
787 | "weight":8,
788 | "description":"Reading continuous text on a laptop screen."
789 | },
790 | {
791 | "url":"parameters.html#intendedsize",
792 | "level":4,
793 | "name":"wall television reading",
794 | "weight":8,
795 | "description":"Reading text on a wall mounted television."
796 | },
797 | {
798 | "url":"parameters.html#intendedsize",
799 | "level":4,
800 | "name":"very large sizes",
801 | "weight":4,
802 | "description":"Huge text on a wall."
803 | },
804 | {
805 | "url":"parameters.html#intendedsize",
806 | "level":4,
807 | "name":"most sizes",
808 | "weight":4,
809 | "description":"Can't be too specialised, it has to work well on a range of sizes."
810 | }
811 | ],
812 | "variable":[
813 | {
814 | "url":"parameters.html#variable",
815 | "level":4,
816 | "name":"make width axis variations",
817 | "weight":2,
818 | "description":"Draw wider and narrower variations."
819 | },
820 | {
821 | "url":"parameters.html#variable",
822 | "level":4,
823 | "name":"make weight axis variations",
824 | "weight":2,
825 | "description":"Draw lighter and heavier variations."
826 | },
827 | {
828 | "url":"parameters.html#variable",
829 | "level":4,
830 | "name":"make optical axis variations",
831 | "weight":2,
832 | "description":"Draw variations for normal and smaller sizes."
833 | },
834 | {
835 | "url":"parameters.html#variable",
836 | "level":5,
837 | "name":"make optical axis variations",
838 | "weight":2,
839 | "description":"Draw variations for normal and larger sizes."
840 | },
841 | {
842 | "url":"parameters.html#variable",
843 | "level":5,
844 | "name":"make optical axis variations",
845 | "weight":2,
846 | "description":"Draw variations for smaller and larger sizes."
847 | }
848 | ]
849 | }
850 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | body{
2 | background-color:rgba(197, 206, 225, 0.7);
3 | margin: 0;
4 | }
5 | #twitter{
6 | background-color: #4099ff;
7 | width: 100%;
8 | color: white;
9 | margin:0;
10 | padding-left: 0.1em;
11 | padding-right: 0.1em;
12 | }
13 | #tc{
14 | color: white;
15 | font-family: "heavierSans";
16 | padding-left: 0.1em;
17 | background-color: #ff001b;
18 | font-style: normal;
19 | font-weight: normal;
20 | }
21 | .explainparameter{
22 | display: none;
23 | background-color: blue;
24 | color: white;
25 | font-family: "heavierSans";
26 | }
27 | #recipe{
28 | width: 100vw;
29 | margin:0;
30 | }
31 | .selected{
32 | color: white;
33 | font-family: "heavierSans";
34 | padding-left: 0.1em;
35 | background-color: #ff001b;
36 | font-style: normal;
37 | font-weight: normal;
38 | }
39 | a{
40 | cursor: pointer; /* force displaying pointer curser for a tags missing a href attribute */
41 | text-decoration: none;
42 | color: white;
43 | padding-left: 0.05em;
44 | padding-right: 0.05em;
45 | }
46 | a:hover{
47 | font-family: "heavierSans";
48 | color: white;
49 | }
50 | .container{
51 | background-color: rgba(255, 255, 255, 0.52);
52 | }
53 | .entry, .choice, .explain{
54 | display: inline-block;
55 | font-family: "lighterSans";
56 | font-style: normal;
57 | font-weight: normal;
58 | text-align: left;
59 | text-transform: capitalize;
60 | color: rgba(32, 31, 27, 0.95);
61 | padding: 0;
62 | }
63 | .entry{
64 | background-color: #ffc400;
65 | color: white;
66 | }
67 | .entry:hover, .explaining{
68 | /* background-color: #ffc400;
69 | color: white;
70 | */
71 | color: #ffc400;
72 | }
73 | div.explaining{
74 | background-color: #ffc400;
75 | color: red;
76 | }
77 | .choice{
78 | display: inline-block;
79 | margin-right: 0.125em;
80 | padding-left: 0.125em;
81 | padding-right: 0.125em;
82 | }
83 | .explain{
84 | display: none;
85 | background-color: black;
86 | color: white;
87 | text-transform: none;
88 | font-family: "lighterSans";
89 |
90 | }
91 | #title, #explain{
92 | font-family: "lighterSans";
93 | text-align: left;
94 | color: white;
95 | padding-left: 0.1em;
96 | background-color: #ff001b;
97 | }
98 | #title{
99 | text-transform: uppercase;
100 | }
101 | em{
102 | font-style: normal;
103 | font-family: "lighterSans";
104 | color: rgba(0, 0, 0, 0.4);
105 | text-transform: capitalize;
106 | padding-left: 0.1em;
107 | padding-right: 0.1em;
108 | background-color: #ffc400;
109 | }
110 | #footer{
111 | font-family: "lighterSans";
112 | color: white;
113 | }
114 |
--------------------------------------------------------------------------------
/tc.js:
--------------------------------------------------------------------------------
1 |
2 | // The previous implementations relied on external frameworks to do the work.
3 | // It seems TypeCooker tends to outlive these frameworks. This makes maintenance
4 | // a bit more difficult. So instead, for this implementation, let's use only
5 | // canonical javascript. http://youmightnotneedjquery.com
6 |
7 | //Copyright (c) 2015, Erik van Blokland
8 | //All rights reserved.
9 |
10 | // Redistribution and use in source and binary forms, with or without
11 | // modification, are permitted provided that the following conditions are met:
12 |
13 | // 1. Redistributions of source code must retain the above copyright notice, this
14 | // list of conditions and the following disclaimer.
15 | // 2. Redistributions in binary form must reproduce the above copyright notice,
16 | // this list of conditions and the following disclaimer in the documentation
17 | // and/or other materials provided with the distribution.
18 |
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 | // The views and conclusions contained in the software and documentation are those
31 | // of the authors and should not be interpreted as representing official policies,
32 | // either expressed or implied, of the FreeBSD Project.
33 |
34 | // stuff
35 | var parametersURL = "parameters.json";
36 | var selectionLevel = 1;
37 | var currentExplained = null;
38 | var data = {};
39 | var current = {}; // holds the generated parameter - value pairs
40 |
41 | // explain text
42 | var explainText = "Hi! If you don’t know what kind of letters to draw, TypeCooker can give you some ideas. Try to match as many parameters as you can. ";
43 | var explainOpen = false;
44 |
45 | // load the parameters
46 | var request = new XMLHttpRequest();
47 | request.open('GET', parametersURL, true);
48 | var parameterData = {};
49 | var selectionLevel = 2;
50 | var titleYellow = "#ffc400";
51 |
52 | request.onload = function() {
53 | if (request.status >= 200 && request.status < 400) {
54 | // Success!
55 | parameterData = JSON.parse(request.responseText);
56 | console.log('succes!', parameterData);
57 | selectionLevel = getParameterByName('level');
58 | console.log('selectionLevel', selectionLevel);
59 | if(selectionLevel==null){
60 | selectionLevel=2;
61 | }
62 | el = document.getElementById("level"+selectionLevel);
63 | if (el.classList) {
64 | el.classList.add('selected');
65 | } else {
66 | el.className += ' ' + 'selected';
67 | }
68 |
69 | // if there is a hash fragment present in the url, rebuild the interface state
70 | // to match the options provided
71 | // else generate a new ranomd set of options
72 | if (window.location.hash) {
73 | console.log("rebuild");
74 | var options = buildObjFromHash(window.location.hash);
75 | // "update" share link in the footer to match the current options
76 | var shareLink = window.location.href + window.location.hash;
77 | document.getElementById("share-link").setAttribute("href", shareLink);
78 | makeFromObject(options, parameterData);
79 |
80 | // then remove the hash form the url, so that a user that came via
81 | // a set link can still generate new sets
82 | window.location.hash = "";
83 | } else {
84 | console.log("generate");
85 | makeSelection(selectionLevel, parameterData);
86 | }
87 | } else {
88 | // We reached our target server, but it returned an error
89 | console.log("error loading", parametersURL);
90 | }
91 | };
92 | request.onerror = function() {
93 | // There was a connection error of some sort
94 | console.log("can't load", parametersURL);
95 | };
96 |
97 | // send the request
98 | request.send();
99 |
100 | // http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
101 | function shuffle(array) {
102 | var currentIndex = array.length, temporaryValue, randomIndex ;
103 |
104 | // While there remain elements to shuffle...
105 | while (0 !== currentIndex) {
106 |
107 | // Pick a remaining element...
108 | randomIndex = Math.floor(Math.random() * currentIndex);
109 | currentIndex -= 1;
110 |
111 | // And swap it with the current element.
112 | temporaryValue = array[currentIndex];
113 | array[currentIndex] = array[randomIndex];
114 | array[randomIndex] = temporaryValue;
115 | }
116 | return array;
117 | }
118 |
119 | //http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
120 | function getParameterByName(name) {
121 | name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
122 | var regex = new RegExp("[\\?&]" + name + "=([^]*)"),
123 | results = regex.exec(location.search);
124 | return results === null ? 2 : decodeURIComponent(results[1].replace(/\+/g, " "));
125 | }
126 |
127 | function buildObjFromHash(hash) {
128 | // replace any possible starting # sign
129 | hash = hash.replace(/^#/, "");
130 |
131 | // iterate though all & seperated paramater - value pairs
132 | var parts = hash.split("&");
133 | var obj = {};
134 | for (part in parts) {
135 | var components = parts[part].split("=");
136 | obj[decodeURIComponent(components[0])] = decodeURIComponent(components[1]);
137 | }
138 | return obj;
139 | }
140 |
141 | function buildHashFromObj(obj) {
142 | var hash = "";
143 | for (property in obj) {
144 | hash += "&" + encodeURIComponent(property) + "=" + encodeURIComponent(obj[property])
145 | }
146 | hash = hash.substring(1); // remove that first &
147 | return hash;
148 | }
149 |
150 | // build parameter unit
151 | var buildParameter = function(parameterName){
152 | // build the structure for the parameter, but without any contents.
153 | var t = "";
154 | var parameterNameAsClass = parameterName.replace(/\s+/g, '');
155 | var parameterExplainAsClass = parameterNameAsClass+"explain";
156 | var parameterChoiceAsClass = parameterNameAsClass+"choice";
157 | t += "";
158 | t += "
"+"
";
159 | t += "
"+"
";
160 | t += "
";
161 | t += ""+"
";
162 | //console.log("t", t);
163 | return t;
164 | }
165 |
166 | // show
167 | var explainParameter = function(parameterName){
168 | console.log('--> explain', parameterName);
169 | if(currentExplained){
170 | // we have a previous choice
171 | document.getElementById(currentExplained+"explain").style.display = "none";
172 | document.getElementById(currentExplained).style.backgroundColor = titleYellow;
173 | document.getElementById(currentExplained+"choice").style.backgroundColor = "inherit";
174 | document.getElementById(currentExplained+"choice").style.color = "black";
175 | if(currentExplained==parameterName){
176 | currentExplained = null;
177 | return;
178 | }
179 | }
180 | document.getElementById(parameterName+"explain").style.display = "block";
181 | document.getElementById(parameterName+"explain").style.backgroundColor = "black";
182 | document.getElementById(parameterName+"choice").style.backgroundColor = "black";
183 | document.getElementById(parameterName+"choice").style.color = titleYellow;
184 | document.getElementById(parameterName).style.backgroundColor = "black";
185 | currentExplained = parameterName;
186 | console.log("done with", currentExplained);
187 | }
188 |
189 | // show explanation
190 | var showExplain = function(){
191 | if(explainOpen){
192 | document.getElementById("explain").innerHTML = "";
193 | explainOpen = false;
194 | } else {
195 | document.getElementById("explain").innerHTML = explainText;
196 | explainOpen = true;
197 | }
198 | }
199 |
200 |
201 | // build the "recipe" html for all parameterNames
202 | var buildRecipe = function (parameterNames) {
203 | for(var i=0;i"+thisName+"";
219 | el.innerHTML = thisNameLink+el.innerHTML;
220 | document.getElementById(parameterNameAsClass+"choice").innerHTML = selection.name;
221 | document.getElementById(parameterNameAsClass+"explain").innerHTML = d;
222 | }
223 |
224 | // got passed a hash on load, build the selection from an object and the passed
225 | // in json data
226 | var makeFromObject = function (obj, data) {
227 | var parameterNames = [];
228 | for(var key in data){
229 | parameterNames.push(key);
230 | }
231 | buildRecipe(parameterNames);
232 |
233 | // remove the "keys" array form the json data to avoid having it
234 | // included as a new parameter listed as selected
235 | data.keys = undefined;
236 |
237 | // since the obj only contains the "name" value of the actual data
238 | // let's make an object that has all the data from the json
239 | var objectFromJson = obj;
240 | for (param in data) {
241 | for (index in data[param]) {
242 | if (data[param][index]["name"] == obj[param]) {
243 | objectFromJson[param] = data[param][index];
244 | }
245 | }
246 | }
247 |
248 | // build the actual html for each parameter
249 | for (parameter in objectFromJson) {
250 | buildSelection(objectFromJson[parameter], parameter);
251 | }
252 | }
253 |
254 | // json loaded and no url has provided, make a new randomized selection
255 | var makeSelection = function(level, data){
256 | var selectedItems = [];
257 | var parameterNames = [];
258 | for(var key in data){
259 | parameterNames.push(key);
260 | }
261 |
262 | parameterNames = shuffle(parameterNames);
263 | buildRecipe(parameterNames);
264 |
265 | for(var i=0;ilevel){
273 | // above our pay grade, skip.
274 | continue;
275 | }
276 | for(var t=0;t<=b.weight;t++){
277 | // add this option according to weight
278 | optionsForThisName.push(b);
279 | }
280 | }
281 | if(optionsForThisName.length>0){
282 | var selection = optionsForThisName[Math.floor(Math.random()*optionsForThisName.length)];
283 | buildSelection(selection, thisName);
284 | current[thisName] = selection.name;
285 | }
286 | }
287 | }
288 |
289 | // Copy to clipboard as discussed here
290 | // http://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript
291 | function shareRecipe() {
292 | // Create footer share link to match the current options
293 | // remove and hash that might or might not have been in the location
294 | var shareLink = window.location.href.replace(/#$/, "") + "#" + buildHashFromObj(current);
295 | window.prompt("Save link to this recipe: Ctrl+C, Enter", shareLink);
296 | }
297 |
298 | // thank you for your attention. Now go draw something.
--------------------------------------------------------------------------------