branding-engine 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +428 -73
- package/bin/cli.mjs +8 -5
- package/examples/severino-labs/README.md +95 -0
- package/examples/severino-labs/brand.json +30 -0
- package/examples/severino-labs/generated/cards/social-card.png +0 -0
- package/examples/severino-labs/generated/severino-labs/README.md +49 -0
- package/examples/severino-labs/generated/severino-labs/icons/apple-touch-icon.png +0 -0
- package/examples/severino-labs/generated/severino-labs/icons/favicon-192.png +0 -0
- package/examples/severino-labs/generated/severino-labs/icons/favicon-32.png +0 -0
- package/examples/severino-labs/generated/severino-labs/icons/favicon.ico +0 -0
- package/examples/severino-labs/generated/severino-labs/icons/favicon.svg +1 -0
- package/examples/severino-labs/generated/severino-labs/mark/mark-1024.png +0 -0
- package/examples/severino-labs/generated/severino-labs/mark/mark-512.png +0 -0
- package/examples/severino-labs/generated/severino-labs/mark/mark-transparent-dark.png +0 -0
- package/examples/severino-labs/generated/severino-labs/mark/mark-transparent-light.png +0 -0
- package/examples/severino-labs/generated/severino-labs/mark/mark.svg +1 -0
- package/examples/severino-labs/generated/severino-labs/sheet/overview.png +0 -0
- package/examples/severino-labs/generated/severino-labs/sheet/palette.png +0 -0
- package/examples/severino-labs/generated/severino-labs/sheet/sheet-mark.png +0 -0
- package/examples/severino-labs/generated/severino-labs/sheet/type-specimen.png +0 -0
- package/examples/severino-labs/generated/severino-labs/web/head.html +6 -0
- package/examples/severino-labs/generated/severino-labs/web/site.webmanifest +19 -0
- package/examples/severino-labs/generated/severino-labs/web/tokens.css +7 -0
- package/examples/severino-labs/generated/severino-labs/wordmark/wordmark-caps-dark.png +0 -0
- package/examples/severino-labs/generated/severino-labs/wordmark/wordmark-caps-light.png +0 -0
- package/examples/severino-labs/generated/severino-labs/wordmark/wordmark-caps.svg +1 -0
- package/examples/severino-labs/generated/severino-labs/wordmark/wordmark-dark.png +0 -0
- package/examples/severino-labs/generated/severino-labs/wordmark/wordmark-light.png +0 -0
- package/examples/severino-labs/generated/severino-labs/wordmark/wordmark.svg +1 -0
- package/examples/severino-labs/studio.jpg +0 -0
- package/index.mjs +1 -0
- package/package.json +13 -6
- package/src/build.mjs +8 -6
- package/src/lib/extract-glyphs.mjs +65 -0
- package/src/lib/glyphs.mjs +6 -19
- package/src/lib/identity.mjs +11 -0
- package/src/lib/mark.mjs +28 -8
- package/src/lib/render.mjs +11 -2
- package/src/lib/wordmark.mjs +6 -1
- package/src/make-mark.mjs +2 -0
- package/src/make-sheet.mjs +2 -0
- package/src/make-web.mjs +2 -0
- package/src/make-wordmark.mjs +3 -1
- package/src/site.mjs +3 -1
- package/requirements.txt +0 -3
- package/src/lib/extract-glyphs.py +0 -75
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Severino Labs",
|
|
3
|
+
"identity": {
|
|
4
|
+
"slug": "severino-labs",
|
|
5
|
+
"color": "#6D5EF7",
|
|
6
|
+
"deep": "#352A8A",
|
|
7
|
+
"onColor": "#FFFFFF",
|
|
8
|
+
"glyph": "SL",
|
|
9
|
+
"wordmark": "Severino Labs"
|
|
10
|
+
},
|
|
11
|
+
"portrait": "./studio.jpg",
|
|
12
|
+
"cardPalette": {
|
|
13
|
+
"accent": "#9B8CFF",
|
|
14
|
+
"textSoft": "#E3DEFF",
|
|
15
|
+
"textMuted": "#B7AFE8"
|
|
16
|
+
},
|
|
17
|
+
"cards": [
|
|
18
|
+
{
|
|
19
|
+
"file": "social-card.png",
|
|
20
|
+
"width": 1200,
|
|
21
|
+
"height": 630,
|
|
22
|
+
"photoWidth": 420,
|
|
23
|
+
"eyebrow": "Severino Labs",
|
|
24
|
+
"name": "Brand systems, generated.",
|
|
25
|
+
"tagline": "Marks, wordmarks, sheets, web assets, and social cards from one config.",
|
|
26
|
+
"meta": "Illustrative branding-engine example",
|
|
27
|
+
"url": "github.com/jseverino/branding-engine"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Severino Labs Brand Kit
|
|
2
|
+
|
|
3
|
+
The full kit: the poster up top, each section's own image below, then the files,
|
|
4
|
+
all generated from the brand's mark, color, and font.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Mark
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
Rounded accent tile with a white glyph (default); accent glyph and white glyph on
|
|
13
|
+
transparent for light and dark surfaces. In `mark/`: `mark.svg`,
|
|
14
|
+
`mark-512/1024.png`, `mark-transparent-light/dark.png`.
|
|
15
|
+
|
|
16
|
+
## Color
|
|
17
|
+
|
|
18
|
+

|
|
19
|
+
|
|
20
|
+
| Role | Hex |
|
|
21
|
+
|---|---|
|
|
22
|
+
| Accent | `#6D5EF7` |
|
|
23
|
+
| Deep | `#352A8A` |
|
|
24
|
+
| Ink | `#0b0620` |
|
|
25
|
+
| Paper | `#ffffff` |
|
|
26
|
+
|
|
27
|
+
CSS custom properties in `web/tokens.css`.
|
|
28
|
+
|
|
29
|
+
## Type
|
|
30
|
+
|
|
31
|
+

|
|
32
|
+
|
|
33
|
+
Inter (`inter-variable-latin.woff2`).
|
|
34
|
+
|
|
35
|
+
## Wordmark
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
Vector-first: `wordmark.svg` (text in `currentColor`) is the source; the `-light/-dark` PNGs rasterize from it. Title case and all-caps both ship.
|
|
42
|
+
|
|
43
|
+
## Folders
|
|
44
|
+
|
|
45
|
+
- `icons/` favicons + apple-touch
|
|
46
|
+
- `mark/` the mark: vector, raster, transparent light/dark
|
|
47
|
+
- `wordmark/` horizontal lockups: `wordmark.svg` + light/dark PNGs, title + caps
|
|
48
|
+
- `sheet/` this overview and its section images
|
|
49
|
+
- `web/` `tokens.css`, `site.webmanifest`, `head.html` (drop-in wiring)
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><rect width="64" height="64" rx="14.08" fill="#6D5EF7"/><g fill="#ffffff" transform="translate(32 32) scale(0.01727 -0.01727) translate(-1234.12 -745.00)"><path transform="translate(0.00 0)" d="M691.19921875 -24Q491.9996337890625 -24 352.39984130859375 36.300018310546875Q212.800048828125 96.60003662109375 139.80010986328125 212.39999389648438Q66.8001708984375 328.199951171875 66.8001708984375 492.7998046875H417.99761962890625Q420.3975830078125 423.5992431640625 454.49774169921875 373.8988342285156Q488.597900390625 324.19842529296875 549.9982604980469 297.6982116699219Q611.3986206054688 271.197998046875 695.1991577148438 271.197998046875Q769.7996826171875 271.197998046875 825.1000671386719 290.7981872558594Q880.4004516601562 310.39837646484375 911.4006652832031 345.7987365722656Q942.40087890625 381.1990966796875 942.40087890625 428.39959716796875Q942.40087890625 469.59991455078125 915.8008422851562 500.400146484375Q889.2008056640625 531.2003784179688 833.1006774902344 554.1005554199219Q777.0005493164062 577.000732421875 688.2002563476562 595.0008544921875L536.4000244140625 625.6010131835938Q317.9998779296875 669.6011962890625 206.60003662109375 777.2009887695312Q95.2001953125 884.80078125 95.2001953125 1048.0006103515625Q95.2001953125 1187.4004516601562 169.50003051757812 1292.1003112792969Q243.79986572265625 1396.8001708984375 376.599609375 1455.4000854492188Q509.39935302734375 1514 685.1990356445312 1514Q864.9986572265625 1514 995.0984191894531 1455.5000305175781Q1125.1981811523438 1397.0000610351562 1197.1980590820312 1287.400146484375Q1269.1979370117188 1177.8002319335938 1273.9979248046875 1024.400390625H932.8004150390625Q925.6004028320312 1114.8011474609375 860.3999938964844 1166.7015686035156Q795.1995849609375 1218.6019897460938 690.3988647460938 1218.6019897460938Q624.7984008789062 1218.6019897460938 573.8980407714844 1199.0018005371094Q522.9976806640625 1179.401611328125 494.09747314453125 1145.2012634277344Q465.197265625 1111.0009155273438 465.197265625 1065.8004760742188Q465.197265625 1025.4002075195312 489.59735107421875 996.7999877929688Q513.9974365234375 968.1997680664062 566.6976318359375 946.7995910644531Q619.3978271484375 925.3994140625 702.5982055664062 908.7992553710938L832.3988037109375 882.7990112304688Q956.5985717773438 858.198974609375 1046.5984191894531 820.9989624023438Q1136.5982666015625 783.7989501953125 1194.2981872558594 731.3989868164062Q1251.9981079101562 678.9990234375 1279.5980834960938 610.2991027832031Q1307.1980590820312 541.5991821289062 1307.1980590820312 454.79931640625Q1307.1980590820312 304.19964599609375 1234.09814453125 196.99978637695312Q1160.9982299804688 89.7999267578125 1023.0984802246094 32.89996337890625Q885.19873046875 -24 691.19921875 -24Z"/><path transform="translate(1281.84 0)" d="M93.600830078125 0V1490H462.39794921875V313.59765625H1119.598876953125V0Z"/></g></svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><rect width="512" height="512" rx="112.64" fill="#6D5EF7"/><g fill="#ffffff" transform="translate(256 256) scale(0.13816 -0.13816) translate(-1234.12 -745.00)"><path transform="translate(0.00 0)" d="M691.19921875 -24Q491.9996337890625 -24 352.39984130859375 36.300018310546875Q212.800048828125 96.60003662109375 139.80010986328125 212.39999389648438Q66.8001708984375 328.199951171875 66.8001708984375 492.7998046875H417.99761962890625Q420.3975830078125 423.5992431640625 454.49774169921875 373.8988342285156Q488.597900390625 324.19842529296875 549.9982604980469 297.6982116699219Q611.3986206054688 271.197998046875 695.1991577148438 271.197998046875Q769.7996826171875 271.197998046875 825.1000671386719 290.7981872558594Q880.4004516601562 310.39837646484375 911.4006652832031 345.7987365722656Q942.40087890625 381.1990966796875 942.40087890625 428.39959716796875Q942.40087890625 469.59991455078125 915.8008422851562 500.400146484375Q889.2008056640625 531.2003784179688 833.1006774902344 554.1005554199219Q777.0005493164062 577.000732421875 688.2002563476562 595.0008544921875L536.4000244140625 625.6010131835938Q317.9998779296875 669.6011962890625 206.60003662109375 777.2009887695312Q95.2001953125 884.80078125 95.2001953125 1048.0006103515625Q95.2001953125 1187.4004516601562 169.50003051757812 1292.1003112792969Q243.79986572265625 1396.8001708984375 376.599609375 1455.4000854492188Q509.39935302734375 1514 685.1990356445312 1514Q864.9986572265625 1514 995.0984191894531 1455.5000305175781Q1125.1981811523438 1397.0000610351562 1197.1980590820312 1287.400146484375Q1269.1979370117188 1177.8002319335938 1273.9979248046875 1024.400390625H932.8004150390625Q925.6004028320312 1114.8011474609375 860.3999938964844 1166.7015686035156Q795.1995849609375 1218.6019897460938 690.3988647460938 1218.6019897460938Q624.7984008789062 1218.6019897460938 573.8980407714844 1199.0018005371094Q522.9976806640625 1179.401611328125 494.09747314453125 1145.2012634277344Q465.197265625 1111.0009155273438 465.197265625 1065.8004760742188Q465.197265625 1025.4002075195312 489.59735107421875 996.7999877929688Q513.9974365234375 968.1997680664062 566.6976318359375 946.7995910644531Q619.3978271484375 925.3994140625 702.5982055664062 908.7992553710938L832.3988037109375 882.7990112304688Q956.5985717773438 858.198974609375 1046.5984191894531 820.9989624023438Q1136.5982666015625 783.7989501953125 1194.2981872558594 731.3989868164062Q1251.9981079101562 678.9990234375 1279.5980834960938 610.2991027832031Q1307.1980590820312 541.5991821289062 1307.1980590820312 454.79931640625Q1307.1980590820312 304.19964599609375 1234.09814453125 196.99978637695312Q1160.9982299804688 89.7999267578125 1023.0984802246094 32.89996337890625Q885.19873046875 -24 691.19921875 -24Z"/><path transform="translate(1281.84 0)" d="M93.600830078125 0V1490H462.39794921875V313.59765625H1119.598876953125V0Z"/></g></svg>
|
|
Binary file
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<!-- Adjust the paths to wherever you deploy the icons. -->
|
|
2
|
+
<link rel="icon" href="/favicon.ico" sizes="any">
|
|
3
|
+
<link rel="icon" type="image/svg+xml" href="/icons/favicon.svg">
|
|
4
|
+
<link rel="apple-touch-icon" href="/icons/apple-touch-icon.png">
|
|
5
|
+
<link rel="manifest" href="/site.webmanifest">
|
|
6
|
+
<meta name="theme-color" content="#6D5EF7">
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Severino Labs",
|
|
3
|
+
"short_name": "SL",
|
|
4
|
+
"icons": [
|
|
5
|
+
{
|
|
6
|
+
"src": "/icons/favicon-192.png",
|
|
7
|
+
"sizes": "192x192",
|
|
8
|
+
"type": "image/png"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"src": "/icons/apple-touch-icon.png",
|
|
12
|
+
"sizes": "180x180",
|
|
13
|
+
"type": "image/png"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"theme_color": "#6D5EF7",
|
|
17
|
+
"background_color": "#ffffff",
|
|
18
|
+
"display": "standalone"
|
|
19
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="1856.43" height="352" viewBox="0 0 1856.43 352" xmlns="http://www.w3.org/2000/svg"><g transform="translate(48 48)"><rect width="256" height="256" rx="56.32" fill="#6D5EF7"/><g fill="#ffffff" transform="translate(128 128) scale(0.06908 -0.06908) translate(-1234.12 -745.00)"><path transform="translate(0.00 0)" d="M691.19921875 -24Q491.9996337890625 -24 352.39984130859375 36.300018310546875Q212.800048828125 96.60003662109375 139.80010986328125 212.39999389648438Q66.8001708984375 328.199951171875 66.8001708984375 492.7998046875H417.99761962890625Q420.3975830078125 423.5992431640625 454.49774169921875 373.8988342285156Q488.597900390625 324.19842529296875 549.9982604980469 297.6982116699219Q611.3986206054688 271.197998046875 695.1991577148438 271.197998046875Q769.7996826171875 271.197998046875 825.1000671386719 290.7981872558594Q880.4004516601562 310.39837646484375 911.4006652832031 345.7987365722656Q942.40087890625 381.1990966796875 942.40087890625 428.39959716796875Q942.40087890625 469.59991455078125 915.8008422851562 500.400146484375Q889.2008056640625 531.2003784179688 833.1006774902344 554.1005554199219Q777.0005493164062 577.000732421875 688.2002563476562 595.0008544921875L536.4000244140625 625.6010131835938Q317.9998779296875 669.6011962890625 206.60003662109375 777.2009887695312Q95.2001953125 884.80078125 95.2001953125 1048.0006103515625Q95.2001953125 1187.4004516601562 169.50003051757812 1292.1003112792969Q243.79986572265625 1396.8001708984375 376.599609375 1455.4000854492188Q509.39935302734375 1514 685.1990356445312 1514Q864.9986572265625 1514 995.0984191894531 1455.5000305175781Q1125.1981811523438 1397.0000610351562 1197.1980590820312 1287.400146484375Q1269.1979370117188 1177.8002319335938 1273.9979248046875 1024.400390625H932.8004150390625Q925.6004028320312 1114.8011474609375 860.3999938964844 1166.7015686035156Q795.1995849609375 1218.6019897460938 690.3988647460938 1218.6019897460938Q624.7984008789062 1218.6019897460938 573.8980407714844 1199.0018005371094Q522.9976806640625 1179.401611328125 494.09747314453125 1145.2012634277344Q465.197265625 1111.0009155273438 465.197265625 1065.8004760742188Q465.197265625 1025.4002075195312 489.59735107421875 996.7999877929688Q513.9974365234375 968.1997680664062 566.6976318359375 946.7995910644531Q619.3978271484375 925.3994140625 702.5982055664062 908.7992553710938L832.3988037109375 882.7990112304688Q956.5985717773438 858.198974609375 1046.5984191894531 820.9989624023438Q1136.5982666015625 783.7989501953125 1194.2981872558594 731.3989868164062Q1251.9981079101562 678.9990234375 1279.5980834960938 610.2991027832031Q1307.1980590820312 541.5991821289062 1307.1980590820312 454.79931640625Q1307.1980590820312 304.19964599609375 1234.09814453125 196.99978637695312Q1160.9982299804688 89.7999267578125 1023.0984802246094 32.89996337890625Q885.19873046875 -24 691.19921875 -24Z"/><path transform="translate(1281.84 0)" d="M93.600830078125 0V1490H462.39794921875V313.59765625H1119.598876953125V0Z"/></g></g><g fill="currentColor" transform="translate(376 176) scale(0.09375 -0.09375) translate(-69.60 -745.00)"><path transform="translate(0.00 0)" d="M678.3984375 -24Q485.999267578125 -24 349.7996826171875 36.60003662109375Q213.60009765625 97.2000732421875 141.6002197265625 212.29998779296875Q69.600341796875 327.39990234375 69.600341796875 489.599609375H378.9952392578125Q380.795166015625 411.198486328125 417.4954833984375 354.79766845703125Q454.19580078125 298.3968505859375 521.4965209960938 268.39642333984375Q588.7972412109375 238.39599609375 681.3983154296875 238.39599609375Q764.599365234375 238.39599609375 826.2001342773438 261.09637451171875Q887.8009033203125 283.7967529296875 922.3013305664062 325.09747314453125Q956.8017578125 366.398193359375 956.8017578125 421.7991943359375Q956.8017578125 468.1998291015625 929.6016845703125 502.80029296875Q902.401611328125 537.4007568359375 844.2013549804688 563.2011108398438Q786.0010986328125 589.00146484375 692.4005126953125 609.001708984375L536.800048828125 642.2020263671875Q315.999755859375 689.202392578125 207.2000732421875 793.4019775390625Q98.400390625 897.6015625 98.400390625 1058.001220703125Q98.400390625 1194.8009033203125 170.00006103515625 1297.2006225585938Q241.5997314453125 1399.600341796875 370.19921875 1456.8001708984375Q498.7987060546875 1514 669.3980712890625 1514Q842.997314453125 1514 969.1968383789062 1456.0000610351562Q1095.3963623046875 1398.0001220703125 1165.3961181640625 1289.80029296875Q1235.3958740234375 1181.6004638671875 1239.995849609375 1030.80078125H939.600830078125Q932.2008056640625 1133.602294921875 860.2999877929688 1192.4031372070312Q788.399169921875 1251.2039794921875 671.7977294921875 1251.2039794921875Q598.5968017578125 1251.2039794921875 541.7960815429688 1228.5036010742188Q484.995361328125 1205.80322265625 452.6949462890625 1165.9025268554688Q420.39453125 1126.0018310546875 420.39453125 1073.6009521484375Q420.39453125 1028.8004150390625 446.1947021484375 996.5999755859375Q471.994873046875 964.3995361328125 527.895263671875 940.0991821289062Q583.795654296875 915.798828125 673.1964111328125 896.5985107421875L812.797607421875 866.5980224609375Q933.1971435546875 841.39794921875 1020.6968383789062 803.9979248046875Q1108.196533203125 766.597900390625 1164.5963745117188 714.7979736328125Q1220.9962158203125 662.998046875 1248.1961669921875 595.5982055664062Q1275.3961181640625 528.1983642578125 1275.3961181640625 443.5986328125Q1275.3961181640625 298.3992919921875 1203.6962890625 193.49957275390625Q1131.9964599609375 88.599853515625 998.1969604492188 32.2999267578125Q864.3974609375 -24 678.3984375 -24Z"/><path transform="translate(1304.04 0)" d="M107.20166015625 0V1490H1187.1971435546875V1214.8046875H428.7958984375V885.5982666015625H1129.797119140625V617.6026611328125H428.7958984375V275.1953125H1187.1971435546875V0Z"/><path transform="translate(2514.08 0)" d="M528.001708984375 0 8.00048828125 1490H358.7939453125L591.3975830078125 783.9921875Q635.3968505859375 641.9949951171875 682.7965698242188 479.8966064453125Q730.1962890625 317.7982177734375 784.5965576171875 130.5982666015625H691.3983154296875Q743.798583984375 317.7982177734375 789.598388671875 479.8966064453125Q835.398193359375 641.9949951171875 877.7974853515625 783.9921875L1102.401123046875 1490H1448.794677734375L940.793212890625 0Z"/><path transform="translate(3930.12 0)" d="M107.20166015625 0V1490H1187.1971435546875V1214.8046875H428.7958984375V885.5982666015625H1129.797119140625V617.6026611328125H428.7958984375V275.1953125H1187.1971435546875V0Z"/><path transform="translate(5140.16 0)" d="M107.20166015625 0V1490H708.19970703125Q877.399169921875 1490 1000.7987670898438 1429.9002075195312Q1124.1983642578125 1369.8004150390625 1191.09814453125 1259.30078125Q1257.9979248046875 1148.8011474609375 1257.9979248046875 997.20166015625Q1257.9979248046875 848.60205078125 1187.6981201171875 740.0023193359375Q1117.3983154296875 631.402587890625 989.8987426757812 572.5027465820312Q862.399169921875 513.6029052734375 689.39990234375 513.6029052734375H300.7978515625V770.7989501953125H688.0003662109375Q767.0013427734375 770.7989501953125 824.10205078125 798.7992553710938Q881.2027587890625 826.799560546875 912.203125 877.8001708984375Q943.2034912109375 928.80078125 943.2034912109375 997.20166015625Q943.2034912109375 1066.6025390625 912.0031127929688 1116.9031372070312Q880.802734375 1167.2037353515625 823.7020263671875 1195.2040405273438Q766.601318359375 1223.204345703125 687.2003173828125 1223.204345703125H428.7958984375V0ZM949.002685546875 0 610.601806640625 673.599853515625H947.1964111328125L1292.7972412109375 0Z"/><path transform="translate(6435.20 0)" d="M428.7958984375 1490V0H107.20166015625V1490Z"/><path transform="translate(6930.24 0)" d="M107.20166015625 0V1490H444.3963623046875L907.802490234375 750.9906005859375Q930.202392578125 715.790771484375 964.30224609375 656.0911254882812Q998.402099609375 596.3914794921875 1036.7019653320312 527.5918579101562Q1075.0018310546875 458.792236328125 1108.8017578125 395.992431640625L1072.0025634765625 311.994384765625Q1068.20263671875 381.793701171875 1065.4026489257812 472.29290771484375Q1062.6026611328125 562.7921142578125 1061.3026733398438 646.2913208007812Q1060.002685546875 729.79052734375 1060.002685546875 777.58984375V1490H1381.596923828125V0H1043.6021728515625L621.797119140625 671.207763671875Q594.997314453125 714.607421875 553.2974853515625 784.9070434570312Q511.59765625 855.2066650390625 461.29766845703125 944.806396484375Q410.9976806640625 1034.4061279296875 356.7974853515625 1132.80615234375L414.39599609375 1166.40673828125Q421.1959228515625 1057.0064697265625 424.2958984375 959.8067016601562Q427.3958740234375 862.60693359375 428.09588623046875 788.4072875976562Q428.7958984375 714.2076416015625 428.7958984375 672.0078125V0Z"/><path transform="translate(8378.28 0)" d="M765.2000732421875 -24Q564.6002197265625 -24 404.70050048828125 69.000244140625Q244.80078125 162.00048828125 152.4010009765625 334.300537109375Q60.001220703125 506.6005859375 60.001220703125 744Q60.001220703125 983.3994140625 152.4010009765625 1155.9994506835938Q244.80078125 1328.5994873046875 404.70050048828125 1421.2997436523438Q564.6002197265625 1514 765.2000732421875 1514Q966.199951171875 1514 1125.5996704101562 1421.2997436523438Q1284.9993896484375 1328.5994873046875 1377.6991577148438 1155.9994506835938Q1470.39892578125 983.3994140625 1470.39892578125 744Q1470.39892578125 506.0006103515625 1377.6991577148438 333.7005615234375Q1284.9993896484375 161.4005126953125 1125.5996704101562 68.70025634765625Q966.199951171875 -24 765.2000732421875 -24ZM765.2000732421875 259.1953125Q878.0009765625 259.1953125 964.0020751953125 316.0958251953125Q1050.003173828125 372.996337890625 1098.2039794921875 481.49737548828125Q1146.40478515625 589.9984130859375 1146.40478515625 744Q1146.40478515625 899.0015869140625 1098.2039794921875 1008.0026245117188Q1050.003173828125 1117.003662109375 964.0020751953125 1173.9041748046875Q878.0009765625 1230.8046875 765.2000732421875 1230.8046875Q652.9991455078125 1230.8046875 566.998046875 1173.9041748046875Q480.9969482421875 1117.003662109375 432.49615478515625 1008.0026245117188Q383.995361328125 899.0015869140625 383.995361328125 744Q383.995361328125 589.9984130859375 432.49615478515625 481.49737548828125Q480.9969482421875 372.996337890625 566.998046875 316.0958251953125Q652.9991455078125 259.1953125 765.2000732421875 259.1953125Z"/><path transform="translate(10256.36 0)" d="M107.20166015625 0V1490H428.7958984375V275.1953125H1101.19775390625V0Z"/><path transform="translate(11360.40 0)" d="M8.00048828125 0 528.001708984375 1490H945.593017578125L1466.1939697265625 0H1108.6007080078125L883.1971435546875 706.0078125Q838.397705078125 854.4053955078125 792.3980102539062 1010.3037109375Q746.3983154296875 1166.2020263671875 693.998046875 1359.4017333984375H781.99658203125Q728.3963623046875 1166.2020263671875 681.7966918945312 1010.3037109375Q635.197021484375 854.4053955078125 588.797607421875 706.0078125L356.1939697265625 0ZM345.3983154296875 314.2042236328125V570.2003173828125H1129.3961181640625V314.2042236328125Z"/><path transform="translate(12793.44 0)" d="M107.20166015625 0V1490H709.9990234375Q871.99853515625 1490 984.5983276367188 1441.7999877929688Q1097.1981201171875 1393.5999755859375 1155.5980834960938 1308.099853515625Q1213.998046875 1222.5997314453125 1213.998046875 1108.3994140625Q1213.998046875 1022.7994384765625 1180.7982177734375 955.8995971679688Q1147.598388671875 888.999755859375 1087.2986450195312 844.6998291015625Q1026.9989013671875 800.39990234375 944.399169921875 779.7996826171875V777.7996826171875Q1035.9989013671875 770.3994140625 1109.2987060546875 725.49951171875Q1182.5985107421875 680.599609375 1225.4984130859375 603.3997802734375Q1268.3983154296875 526.199951171875 1268.3983154296875 420.39990234375Q1268.3983154296875 296.3997802734375 1208.3983764648438 201.49981689453125Q1148.3984375 106.599853515625 1031.9983520507812 53.2999267578125Q915.5982666015625 0 746.7978515625 0ZM421.59619140625 251.1962890625H699.999755859375Q813.2020263671875 251.1962890625 876.4031372070312 300.59686279296875Q939.604248046875 349.9974365234375 939.604248046875 439.798828125Q939.604248046875 499.999755859375 911.5037841796875 543.6004028320312Q883.4033203125 587.2010498046875 830.8023681640625 611.0014038085938Q778.201416015625 634.8017578125 704 634.8017578125H421.59619140625ZM421.59619140625 874.3984375H684.600341796875Q749.4014892578125 874.3984375 796.2022705078125 896.5987548828125Q843.0030517578125 918.799072265625 868.1034545898438 959.899658203125Q893.203857421875 1001.000244140625 893.203857421875 1056.60107421875Q893.203857421875 1140.0023193359375 837.4029541015625 1189.4030151367188Q781.60205078125 1238.8037109375 684.600341796875 1238.8037109375H421.59619140625Z"/><path transform="translate(14073.48 0)" d="M678.3984375 -24Q485.999267578125 -24 349.7996826171875 36.60003662109375Q213.60009765625 97.2000732421875 141.6002197265625 212.29998779296875Q69.600341796875 327.39990234375 69.600341796875 489.599609375H378.9952392578125Q380.795166015625 411.198486328125 417.4954833984375 354.79766845703125Q454.19580078125 298.3968505859375 521.4965209960938 268.39642333984375Q588.7972412109375 238.39599609375 681.3983154296875 238.39599609375Q764.599365234375 238.39599609375 826.2001342773438 261.09637451171875Q887.8009033203125 283.7967529296875 922.3013305664062 325.09747314453125Q956.8017578125 366.398193359375 956.8017578125 421.7991943359375Q956.8017578125 468.1998291015625 929.6016845703125 502.80029296875Q902.401611328125 537.4007568359375 844.2013549804688 563.2011108398438Q786.0010986328125 589.00146484375 692.4005126953125 609.001708984375L536.800048828125 642.2020263671875Q315.999755859375 689.202392578125 207.2000732421875 793.4019775390625Q98.400390625 897.6015625 98.400390625 1058.001220703125Q98.400390625 1194.8009033203125 170.00006103515625 1297.2006225585938Q241.5997314453125 1399.600341796875 370.19921875 1456.8001708984375Q498.7987060546875 1514 669.3980712890625 1514Q842.997314453125 1514 969.1968383789062 1456.0000610351562Q1095.3963623046875 1398.0001220703125 1165.3961181640625 1289.80029296875Q1235.3958740234375 1181.6004638671875 1239.995849609375 1030.80078125H939.600830078125Q932.2008056640625 1133.602294921875 860.2999877929688 1192.4031372070312Q788.399169921875 1251.2039794921875 671.7977294921875 1251.2039794921875Q598.5968017578125 1251.2039794921875 541.7960815429688 1228.5036010742188Q484.995361328125 1205.80322265625 452.6949462890625 1165.9025268554688Q420.39453125 1126.0018310546875 420.39453125 1073.6009521484375Q420.39453125 1028.8004150390625 446.1947021484375 996.5999755859375Q471.994873046875 964.3995361328125 527.895263671875 940.0991821289062Q583.795654296875 915.798828125 673.1964111328125 896.5985107421875L812.797607421875 866.5980224609375Q933.1971435546875 841.39794921875 1020.6968383789062 803.9979248046875Q1108.196533203125 766.597900390625 1164.5963745117188 714.7979736328125Q1220.9962158203125 662.998046875 1248.1961669921875 595.5982055664062Q1275.3961181640625 528.1983642578125 1275.3961181640625 443.5986328125Q1275.3961181640625 298.3992919921875 1203.6962890625 193.49957275390625Q1131.9964599609375 88.599853515625 998.1969604492188 32.2999267578125Q864.3974609375 -24 678.3984375 -24Z"/></g></svg>
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="1607.54" height="352" viewBox="0 0 1607.54 352" xmlns="http://www.w3.org/2000/svg"><g transform="translate(48 48)"><rect width="256" height="256" rx="56.32" fill="#6D5EF7"/><g fill="#ffffff" transform="translate(128 128) scale(0.06908 -0.06908) translate(-1234.12 -745.00)"><path transform="translate(0.00 0)" d="M691.19921875 -24Q491.9996337890625 -24 352.39984130859375 36.300018310546875Q212.800048828125 96.60003662109375 139.80010986328125 212.39999389648438Q66.8001708984375 328.199951171875 66.8001708984375 492.7998046875H417.99761962890625Q420.3975830078125 423.5992431640625 454.49774169921875 373.8988342285156Q488.597900390625 324.19842529296875 549.9982604980469 297.6982116699219Q611.3986206054688 271.197998046875 695.1991577148438 271.197998046875Q769.7996826171875 271.197998046875 825.1000671386719 290.7981872558594Q880.4004516601562 310.39837646484375 911.4006652832031 345.7987365722656Q942.40087890625 381.1990966796875 942.40087890625 428.39959716796875Q942.40087890625 469.59991455078125 915.8008422851562 500.400146484375Q889.2008056640625 531.2003784179688 833.1006774902344 554.1005554199219Q777.0005493164062 577.000732421875 688.2002563476562 595.0008544921875L536.4000244140625 625.6010131835938Q317.9998779296875 669.6011962890625 206.60003662109375 777.2009887695312Q95.2001953125 884.80078125 95.2001953125 1048.0006103515625Q95.2001953125 1187.4004516601562 169.50003051757812 1292.1003112792969Q243.79986572265625 1396.8001708984375 376.599609375 1455.4000854492188Q509.39935302734375 1514 685.1990356445312 1514Q864.9986572265625 1514 995.0984191894531 1455.5000305175781Q1125.1981811523438 1397.0000610351562 1197.1980590820312 1287.400146484375Q1269.1979370117188 1177.8002319335938 1273.9979248046875 1024.400390625H932.8004150390625Q925.6004028320312 1114.8011474609375 860.3999938964844 1166.7015686035156Q795.1995849609375 1218.6019897460938 690.3988647460938 1218.6019897460938Q624.7984008789062 1218.6019897460938 573.8980407714844 1199.0018005371094Q522.9976806640625 1179.401611328125 494.09747314453125 1145.2012634277344Q465.197265625 1111.0009155273438 465.197265625 1065.8004760742188Q465.197265625 1025.4002075195312 489.59735107421875 996.7999877929688Q513.9974365234375 968.1997680664062 566.6976318359375 946.7995910644531Q619.3978271484375 925.3994140625 702.5982055664062 908.7992553710938L832.3988037109375 882.7990112304688Q956.5985717773438 858.198974609375 1046.5984191894531 820.9989624023438Q1136.5982666015625 783.7989501953125 1194.2981872558594 731.3989868164062Q1251.9981079101562 678.9990234375 1279.5980834960938 610.2991027832031Q1307.1980590820312 541.5991821289062 1307.1980590820312 454.79931640625Q1307.1980590820312 304.19964599609375 1234.09814453125 196.99978637695312Q1160.9982299804688 89.7999267578125 1023.0984802246094 32.89996337890625Q885.19873046875 -24 691.19921875 -24Z"/><path transform="translate(1281.84 0)" d="M93.600830078125 0V1490H462.39794921875V313.59765625H1119.598876953125V0Z"/></g></g><g fill="currentColor" transform="translate(376 176) scale(0.09375 -0.09375) translate(-69.60 -745.80)"><path transform="translate(0.00 0)" d="M678.3984375 -24Q485.999267578125 -24 349.7996826171875 36.60003662109375Q213.60009765625 97.2000732421875 141.6002197265625 212.29998779296875Q69.600341796875 327.39990234375 69.600341796875 489.599609375H378.9952392578125Q380.795166015625 411.198486328125 417.4954833984375 354.79766845703125Q454.19580078125 298.3968505859375 521.4965209960938 268.39642333984375Q588.7972412109375 238.39599609375 681.3983154296875 238.39599609375Q764.599365234375 238.39599609375 826.2001342773438 261.09637451171875Q887.8009033203125 283.7967529296875 922.3013305664062 325.09747314453125Q956.8017578125 366.398193359375 956.8017578125 421.7991943359375Q956.8017578125 468.1998291015625 929.6016845703125 502.80029296875Q902.401611328125 537.4007568359375 844.2013549804688 563.2011108398438Q786.0010986328125 589.00146484375 692.4005126953125 609.001708984375L536.800048828125 642.2020263671875Q315.999755859375 689.202392578125 207.2000732421875 793.4019775390625Q98.400390625 897.6015625 98.400390625 1058.001220703125Q98.400390625 1194.8009033203125 170.00006103515625 1297.2006225585938Q241.5997314453125 1399.600341796875 370.19921875 1456.8001708984375Q498.7987060546875 1514 669.3980712890625 1514Q842.997314453125 1514 969.1968383789062 1456.0000610351562Q1095.3963623046875 1398.0001220703125 1165.3961181640625 1289.80029296875Q1235.3958740234375 1181.6004638671875 1239.995849609375 1030.80078125H939.600830078125Q932.2008056640625 1133.602294921875 860.2999877929688 1192.4031372070312Q788.399169921875 1251.2039794921875 671.7977294921875 1251.2039794921875Q598.5968017578125 1251.2039794921875 541.7960815429688 1228.5036010742188Q484.995361328125 1205.80322265625 452.6949462890625 1165.9025268554688Q420.39453125 1126.0018310546875 420.39453125 1073.6009521484375Q420.39453125 1028.8004150390625 446.1947021484375 996.5999755859375Q471.994873046875 964.3995361328125 527.895263671875 940.0991821289062Q583.795654296875 915.798828125 673.1964111328125 896.5985107421875L812.797607421875 866.5980224609375Q933.1971435546875 841.39794921875 1020.6968383789062 803.9979248046875Q1108.196533203125 766.597900390625 1164.5963745117188 714.7979736328125Q1220.9962158203125 662.998046875 1248.1961669921875 595.5982055664062Q1275.3961181640625 528.1983642578125 1275.3961181640625 443.5986328125Q1275.3961181640625 298.3992919921875 1203.6962890625 193.49957275390625Q1131.9964599609375 88.599853515625 998.1969604492188 32.2999267578125Q864.3974609375 -24 678.3984375 -24Z"/><path transform="translate(1281.00 0)" d="M588.9989013671875 -24Q428.59912109375 -24 308.59954833984375 46.70001220703125Q188.5999755859375 117.4000244140625 122.50030517578125 242.20001220703125Q56.400634765625 367 56.400634765625 527.199951171875Q56.400634765625 688.7999267578125 123.400390625 813.4999389648438Q190.400146484375 938.199951171875 308.29974365234375 1009.0999755859375Q426.1993408203125 1080 579.3988037109375 1080Q696.5985107421875 1080 792.5982055664062 1040.2999877929688Q888.597900390625 1000.5999755859375 958.1976318359375 927.4999389648438Q1027.79736328125 854.39990234375 1065.4971923828125 754.3998413085938Q1103.197021484375 654.3997802734375 1103.197021484375 533.7996826171875V450.8011474609375H163.199951171875V643.5992431640625H955.9991455078125L816.40185546875 599.7989501953125Q816.40185546875 676.6002197265625 788.4014282226562 732.1011962890625Q760.4010009765625 787.6021728515625 709.000244140625 817.6027221679688Q657.5994873046875 847.603271484375 585.99853515625 847.603271484375Q515.3975830078125 847.603271484375 463.8968505859375 817.6027221679688Q412.3961181640625 787.6021728515625 384.39569091796875 732.1011962890625Q356.395263671875 676.6002197265625 356.395263671875 599.7989501953125V464.801513671875Q356.395263671875 386.4002685546875 384.8956298828125 327.5992431640625Q413.39599609375 268.7982177734375 467.69671630859375 236.59759521484375Q521.9974365234375 204.39697265625 598.5985107421875 204.39697265625Q654.3992919921875 204.39697265625 697.8998413085938 220.39727783203125Q741.400390625 236.3975830078125 770.8007202148438 265.49810791015625Q800.2010498046875 294.5986328125 813.201171875 333.3992919921875H1093.5966796875Q1074.1966552734375 228.199462890625 1003.39697265625 147.79962158203125Q932.5972900390625 67.3997802734375 825.497802734375 21.69989013671875Q718.3983154296875 -24 588.9989013671875 -24Z"/><path transform="translate(2373.00 0)" d="M399.6015625 0 9.600830078125 1056H332.795166015625L501.3975830078125 543.99609375Q531.5975341796875 448.796875 559.0974731445312 353.59765625Q586.597412109375 258.3984375 613.3973388671875 163.19921875H539.9986572265625Q566.5986328125 258.3984375 593.298583984375 353.59765625Q619.99853515625 448.796875 649.198486328125 543.99609375L814.8009033203125 1056H1134.395263671875L744.39453125 0Z"/><path transform="translate(3453.00 0)" d="M588.9989013671875 -24Q428.59912109375 -24 308.59954833984375 46.70001220703125Q188.5999755859375 117.4000244140625 122.50030517578125 242.20001220703125Q56.400634765625 367 56.400634765625 527.199951171875Q56.400634765625 688.7999267578125 123.400390625 813.4999389648438Q190.400146484375 938.199951171875 308.29974365234375 1009.0999755859375Q426.1993408203125 1080 579.3988037109375 1080Q696.5985107421875 1080 792.5982055664062 1040.2999877929688Q888.597900390625 1000.5999755859375 958.1976318359375 927.4999389648438Q1027.79736328125 854.39990234375 1065.4971923828125 754.3998413085938Q1103.197021484375 654.3997802734375 1103.197021484375 533.7996826171875V450.8011474609375H163.199951171875V643.5992431640625H955.9991455078125L816.40185546875 599.7989501953125Q816.40185546875 676.6002197265625 788.4014282226562 732.1011962890625Q760.4010009765625 787.6021728515625 709.000244140625 817.6027221679688Q657.5994873046875 847.603271484375 585.99853515625 847.603271484375Q515.3975830078125 847.603271484375 463.8968505859375 817.6027221679688Q412.3961181640625 787.6021728515625 384.39569091796875 732.1011962890625Q356.395263671875 676.6002197265625 356.395263671875 599.7989501953125V464.801513671875Q356.395263671875 386.4002685546875 384.8956298828125 327.5992431640625Q413.39599609375 268.7982177734375 467.69671630859375 236.59759521484375Q521.9974365234375 204.39697265625 598.5985107421875 204.39697265625Q654.3992919921875 204.39697265625 697.8998413085938 220.39727783203125Q741.400390625 236.3975830078125 770.8007202148438 265.49810791015625Q800.2010498046875 294.5986328125 813.201171875 333.3992919921875H1093.5966796875Q1074.1966552734375 228.199462890625 1003.39697265625 147.79962158203125Q932.5972900390625 67.3997802734375 825.497802734375 21.69989013671875Q718.3983154296875 -24 588.9989013671875 -24Z"/><path transform="translate(4545.00 0)" d="M102.0009765625 0V1056H399.595458984375V874.400634765625H402.3955078125Q431.3955078125 971.4000244140625 493.195556640625 1016.9002075195312Q554.99560546875 1062.400390625 659.995361328125 1062.400390625Q686.59521484375 1062.400390625 708.4951171875 1061.600341796875Q730.39501953125 1060.80029296875 748.794677734375 1060.000244140625V800.00390625Q732.1949462890625 801.2039794921875 694.6953125 803.0040893554688Q657.1956787109375 804.80419921875 619.595703125 804.80419921875Q559.19580078125 804.80419921875 511.595703125 777.2042236328125Q463.99560546875 749.604248046875 436.9954833984375 695.9041137695312Q409.995361328125 642.2039794921875 409.995361328125 563.603515625V0Z"/><path transform="translate(5256.00 0)" d="M102.0009765625 0V1056H409.995361328125V0ZM255.398193359375 1190.6029052734375Q184.59912109375 1190.6029052734375 135.29974365234375 1238.1023559570312Q86.0003662109375 1285.601806640625 86.0003662109375 1354.0009765625Q86.0003662109375 1422.400146484375 135.29974365234375 1469.8995971679688Q184.59912109375 1517.3990478515625 255.398193359375 1517.3990478515625Q326.197265625 1517.3990478515625 375.49664306640625 1469.8995971679688Q424.7960205078125 1422.400146484375 424.7960205078125 1354.0009765625Q424.7960205078125 1285.601806640625 375.49664306640625 1238.1023559570312Q326.197265625 1190.6029052734375 255.398193359375 1190.6029052734375Z"/><path transform="translate(5704.00 0)" d="M409.995361328125 583.201416015625V0H102.0009765625V1056H405.3953857421875V779.0008544921875H354.9954833984375Q405.195556640625 919.0009765625 497.99554443359375 998.700439453125Q590.7955322265625 1078.39990234375 736.794677734375 1078.39990234375Q850.3944091796875 1078.39990234375 932.99462890625 1029.5Q1015.5948486328125 980.60009765625 1060.5951538085938 887.60009765625Q1105.595458984375 794.60009765625 1105.595458984375 661.999755859375V0H797.60107421875V603.20166015625Q797.60107421875 706.0030517578125 748.6004028320312 759.6036987304688Q699.5997314453125 813.204345703125 609.3985595703125 813.204345703125Q550.3978271484375 813.204345703125 505.3970947265625 788.8040771484375Q460.3963623046875 764.40380859375 435.19586181640625 713.503173828125Q409.995361328125 662.6025390625 409.995361328125 583.201416015625Z"/><path transform="translate(6848.00 0)" d="M597.99853515625 -24Q436.9991455078125 -24 314.79962158203125 44.7000732421875Q192.60009765625 113.400146484375 124.5003662109375 237.400146484375Q56.400634765625 361.400146484375 56.400634765625 527.199951171875Q56.400634765625 693.3997802734375 124.5003662109375 817.4998168945312Q192.60009765625 941.599853515625 314.79962158203125 1010.7999267578125Q436.9991455078125 1080 597.99853515625 1080Q759.9979248046875 1080 881.6974487304688 1010.7999267578125Q1003.39697265625 941.599853515625 1071.4967041015625 817.4998168945312Q1139.596435546875 693.3997802734375 1139.596435546875 527.199951171875Q1139.596435546875 361.400146484375 1071.4967041015625 237.400146484375Q1003.39697265625 113.400146484375 881.6974487304688 44.7000732421875Q759.9979248046875 -24 597.99853515625 -24ZM597.99853515625 224.796142578125Q666.7998046875 224.796142578125 718.6005859375 260.5966796875Q770.4013671875 296.397216796875 799.4017333984375 364.298095703125Q828.402099609375 432.198974609375 828.402099609375 527.199951171875Q828.402099609375 623.6009521484375 799.4017333984375 691.2018432617188Q770.4013671875 758.802734375 718.6005859375 795.0032958984375Q666.7998046875 831.203857421875 597.99853515625 831.203857421875Q530.197265625 831.203857421875 477.896484375 795.2033081054688Q425.595703125 759.2027587890625 396.5953369140625 691.40185546875Q367.594970703125 623.6009521484375 367.594970703125 527.199951171875Q367.594970703125 431.7989501953125 396.5953369140625 364.09808349609375Q425.595703125 296.397216796875 477.69647216796875 260.5966796875Q529.7972412109375 224.796142578125 597.99853515625 224.796142578125Z"/><path transform="translate(8346.00 0)" d="M107.20166015625 0V1490H428.7958984375V275.1953125H1101.19775390625V0Z"/><path transform="translate(9427.00 0)" d="M425.200927734375 -17.7999267578125Q319.6009521484375 -17.7999267578125 237.8009033203125 17.0001220703125Q156.0008544921875 51.8001708984375 109.00079345703125 121.80023193359375Q62.000732421875 191.80029296875 62.000732421875 296.80029296875Q62.000732421875 386.600341796875 94.80084228515625 446.30023193359375Q127.6009521484375 506.0001220703125 184.7010498046875 542.699951171875Q241.8011474609375 579.3997802734375 316.40118408203125 598.4996948242188Q391.001220703125 617.599609375 473.60107421875 625.19970703125Q569.80126953125 634.39990234375 626.9013061523438 643.4998168945312Q684.0013427734375 652.5997314453125 708.8013305664062 669.7996826171875Q733.601318359375 686.9996337890625 733.601318359375 720.39990234375V726.800048828125Q733.601318359375 763.8009033203125 713.6010131835938 791.8015747070312Q693.6007080078125 819.80224609375 656.7000732421875 835.70263671875Q619.7994384765625 851.60302734375 567.99853515625 851.60302734375Q515.397705078125 851.60302734375 475.697021484375 835.2026977539062Q435.996337890625 818.8023681640625 412.99591064453125 789.1018676757812Q389.9954833984375 759.4013671875 385.9954833984375 719.600830078125H97.2001953125Q104.60009765625 830.4002685546875 162.5999755859375 910.7000732421875Q220.599853515625 990.9998779296875 325.49945068359375 1034.6998901367188Q430.3990478515625 1078.39990234375 577.59814453125 1078.39990234375Q687.597412109375 1078.39990234375 773.4969482421875 1053.6998901367188Q859.396484375 1028.9998779296875 918.4962158203125 981.7999267578125Q977.595947265625 934.5999755859375 1007.995849609375 867.3001098632812Q1038.395751953125 800.000244140625 1038.395751953125 714.800537109375V0H737.201171875V148.800048828125H733.201171875Q704.6015625 95.8006591796875 662.8017578125 58.5006103515625Q621.001953125 21.2005615234375 562.7017822265625 1.7003173828125Q504.401611328125 -17.7999267578125 425.200927734375 -17.7999267578125ZM512.79833984375 192.397705078125Q580.1998291015625 192.397705078125 630.5004272460938 217.2982177734375Q680.801025390625 242.19873046875 708.401123046875 285.3994140625Q736.001220703125 328.60009765625 736.001220703125 384.400634765625V487.601806640625Q723.0013427734375 481.001708984375 702.5010986328125 474.8016357421875Q682.0008544921875 468.6015625 655.2003784179688 462.9014892578125Q628.39990234375 457.201416015625 596.7993774414062 451.70135498046875Q565.1988525390625 446.2012939453125 530.3984375 440.80126953125Q481.39794921875 433.4012451171875 441.8973388671875 417.20111083984375Q402.396728515625 401.0009765625 379.1962890625 374.20062255859375Q355.995849609375 347.4002685546875 355.995849609375 307.199462890625Q355.995849609375 271.39892578125 375.59613037109375 245.49853515625Q395.1964111328125 219.59814453125 430.39697265625 205.9979248046875Q465.5975341796875 192.397705078125 512.79833984375 192.397705078125Z"/><path transform="translate(10503.00 0)" d="M717.996337890625 -22.39990234375Q648.79638671875 -22.39990234375 589.1962890625 -1.99993896484375Q529.59619140625 18.4000244140625 483.29595947265625 59.5999755859375Q436.9957275390625 100.7999267578125 407.3953857421875 162.39990234375H405.995361328125V0H102.0009765625V1490H409.995361328125V910.799560546875H411.3953857421875Q445.3953857421875 967.9996337890625 490.99560546875 1004.8997192382812Q536.5958251953125 1041.7998046875 594.4960327148438 1060.099853515625Q652.396240234375 1078.39990234375 720.396240234375 1078.39990234375Q855.3963623046875 1078.39990234375 957.4963989257812 1008.7999267578125Q1059.596435546875 939.199951171875 1117.1964111328125 815.3999633789062Q1174.79638671875 691.5999755859375 1174.79638671875 529.199951171875Q1174.79638671875 363.60009765625 1118.0963745117188 239.5001220703125Q1061.3963623046875 115.400146484375 958.996337890625 46.5001220703125Q856.5963134765625 -22.39990234375 717.996337890625 -22.39990234375ZM636.1986083984375 227.1961669921875Q705.99951171875 227.1961669921875 756.80029296875 262.89654541015625Q807.60107421875 298.596923828125 835.6015625 366.19775390625Q863.60205078125 433.798583984375 863.60205078125 529.199951171875Q863.60205078125 625.0013427734375 835.6015625 692.002197265625Q807.60107421875 759.0030517578125 756.80029296875 794.7034301757812Q705.99951171875 830.40380859375 636.1986083984375 830.40380859375Q564.5975341796875 830.40380859375 510.29681396484375 793.1033325195312Q455.99609375 755.8028564453125 425.9957275390625 688.4019775390625Q395.995361328125 621.0010986328125 395.995361328125 529.199951171875Q395.995361328125 437.798828125 425.9957275390625 369.7979736328125Q455.99609375 301.797119140625 510.29681396484375 264.49664306640625Q564.5975341796875 227.1961669921875 636.1986083984375 227.1961669921875Z"/><path transform="translate(11670.00 0)" d="M547.997802734375 -25.7999267578125Q408.598876953125 -25.7999267578125 300.09954833984375 16.89984130859375Q191.6002197265625 59.599609375 126.50054931640625 140.19940185546875Q61.40087890625 220.7991943359375 52.0009765625 333.3992919921875H355.595458984375Q363.3955078125 267.59814453125 411.69610595703125 229.89764404296875Q459.9967041015625 192.1971435546875 542.7978515625 192.1971435546875Q622.1990966796875 192.1971435546875 667.099853515625 221.69781494140625Q712.0006103515625 251.198486328125 712.0006103515625 297.7994384765625Q712.0006103515625 337.4002685546875 677.000244140625 362.000732421875Q641.9998779296875 386.6011962890625 577.599609375 399.0013427734375L390.80029296875 434.2015380859375Q236.6005859375 463.8017578125 156.30078125 541.8016357421875Q76.0009765625 619.801513671875 76.0009765625 742.6011962890625Q76.0009765625 844.000732421875 131.1007080078125 919.50048828125Q186.200439453125 995.000244140625 288.2998046875 1036.6001586914062Q390.399169921875 1078.2000732421875 530.3980712890625 1078.2000732421875Q670.3968505859375 1078.2000732421875 774.09619140625 1034.3001708984375Q877.7955322265625 990.4002685546875 936.1952514648438 910.200439453125Q994.594970703125 830.0006103515625 997.594970703125 719.0008544921875H712.7998046875Q711.7998046875 780.2017822265625 663.6992797851562 820.8023681640625Q615.5987548828125 861.4029541015625 539.9976806640625 861.4029541015625Q466.396728515625 861.4029541015625 424.5960693359375 830.9022827148438Q382.79541015625 800.401611328125 382.79541015625 755.8006591796875Q382.79541015625 716.7998046875 415.69586181640625 691.6993408203125Q448.5963134765625 666.598876953125 507.197021484375 654.5986328125L710.795654296875 615.798583984375Q871.7952880859375 584.598388671875 947.8950805664062 514.29833984375Q1023.994873046875 443.998291015625 1023.994873046875 326.9984130859375Q1023.994873046875 220.5987548828125 963.795166015625 141.29913330078125Q903.595458984375 61.99951171875 796.1961059570312 18.09979248046875Q688.7967529296875 -25.7999267578125 547.997802734375 -25.7999267578125Z"/></g></svg>
|
|
Binary file
|
package/index.mjs
CHANGED
|
@@ -9,6 +9,7 @@ export { makeWeb } from './src/make-web.mjs';
|
|
|
9
9
|
export { makeCards } from './src/make-cards.mjs';
|
|
10
10
|
export { markSvg } from './src/lib/mark.mjs';
|
|
11
11
|
export { wordmarkSvg } from './src/lib/wordmark.mjs';
|
|
12
|
+
export { normalizeGlyph } from './src/lib/identity.mjs';
|
|
12
13
|
// Lower-level primitives for embedding the renderers in a custom pipeline (e.g.
|
|
13
14
|
// a site that writes brand assets to its own paths).
|
|
14
15
|
export { renderCard } from './src/lib/card.mjs';
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "branding-engine",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "Generate
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Generate favicons, marks, wordmarks, social cards, brand sheets, and web tokens from one color and a 1-3 character glyph.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
7
|
+
"check": "npm test && npm run check:package",
|
|
8
|
+
"check:package": "npm pack --dry-run",
|
|
9
|
+
"test": "node --test",
|
|
10
|
+
"test:core": "node --test test/smoke.test.mjs"
|
|
8
11
|
},
|
|
9
12
|
"bin": {
|
|
10
13
|
"branding-engine": "bin/cli.mjs"
|
|
@@ -16,8 +19,8 @@
|
|
|
16
19
|
"bin",
|
|
17
20
|
"src",
|
|
18
21
|
"assets",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
22
|
+
"examples",
|
|
23
|
+
"index.mjs"
|
|
21
24
|
],
|
|
22
25
|
"engines": {
|
|
23
26
|
"node": ">=18"
|
|
@@ -33,7 +36,9 @@
|
|
|
33
36
|
"keywords": [
|
|
34
37
|
"branding",
|
|
35
38
|
"favicon",
|
|
39
|
+
"brand-kit",
|
|
36
40
|
"logo",
|
|
41
|
+
"monogram",
|
|
37
42
|
"svg",
|
|
38
43
|
"social-cards"
|
|
39
44
|
],
|
|
@@ -41,7 +46,9 @@
|
|
|
41
46
|
"access": "public"
|
|
42
47
|
},
|
|
43
48
|
"dependencies": {
|
|
44
|
-
"
|
|
49
|
+
"opentype.js": "^2.0.0",
|
|
50
|
+
"sharp": "0.34.5",
|
|
51
|
+
"wawoff2": "^2.0.1"
|
|
45
52
|
},
|
|
46
53
|
"optionalDependencies": {
|
|
47
54
|
"@playwright/test": "^1.60.0"
|
package/src/build.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { DEFAULT_FONT } from './lib/font.mjs';
|
|
11
11
|
import { WORDMARK_CHARS, ensureGlyphs } from './lib/glyphs.mjs';
|
|
12
|
+
import { normalizeGlyph } from './lib/identity.mjs';
|
|
12
13
|
import { darken } from './lib/color.mjs';
|
|
13
14
|
import { launchBrowser } from './lib/render.mjs';
|
|
14
15
|
import { makeMark } from './make-mark.mjs';
|
|
@@ -65,7 +66,7 @@ export async function buildBrand({ config, outDir, only } = {}) {
|
|
|
65
66
|
...Object.entries(surfaces).map(([slug, s]) => ({
|
|
66
67
|
slug, color: s.color, glyph: s.glyph || id.glyph, wordmark: s.wordmark, deep: s.deep, onColor: s.onColor,
|
|
67
68
|
})),
|
|
68
|
-
];
|
|
69
|
+
].map((kit) => ({ ...kit, glyph: normalizeGlyph(kit.glyph) }));
|
|
69
70
|
const markChars = [...new Set([...BASE_CHARS, ...kits.flatMap((k) => [...k.glyph])])].join('');
|
|
70
71
|
|
|
71
72
|
process.env.BRAND_FONT = font;
|
|
@@ -73,10 +74,10 @@ export async function buildBrand({ config, outDir, only } = {}) {
|
|
|
73
74
|
process.env.BRAND_WORDMARK_GLYPHS = 'wordmark-glyphs.json';
|
|
74
75
|
|
|
75
76
|
if (stages.has('mark') || stages.has('sheet')) {
|
|
76
|
-
ensureGlyphs({ file: 'brand-glyphs.json', font, weight, chars: markChars, label: 'mark glyphs' });
|
|
77
|
+
await ensureGlyphs({ file: 'brand-glyphs.json', font, weight, chars: markChars, label: 'mark glyphs' });
|
|
77
78
|
}
|
|
78
79
|
if (stages.has('wordmark')) {
|
|
79
|
-
ensureGlyphs({ file: 'wordmark-glyphs.json', font, weight: wordmarkWeight, chars: WORDMARK_CHARS, label: 'wordmark glyphs' });
|
|
80
|
+
await ensureGlyphs({ file: 'wordmark-glyphs.json', font, weight: wordmarkWeight, chars: WORDMARK_CHARS, label: 'wordmark glyphs' });
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
const browser = stages.has('sheet') || (stages.has('cards') && brand.cards) ? await launchBrowser() : null;
|
|
@@ -113,10 +114,11 @@ export async function buildKit({
|
|
|
113
114
|
} = {}) {
|
|
114
115
|
outDir = outDir ? path.resolve(outDir) : path.join(process.cwd(), 'kits');
|
|
115
116
|
const stages = stageSet(only);
|
|
117
|
+
glyph = normalizeGlyph(glyph);
|
|
116
118
|
|
|
117
119
|
// A custom font points the caches at font-specific files and pre-extracts the
|
|
118
|
-
// mark glyphs for
|
|
119
|
-
//
|
|
120
|
+
// Cache mark glyphs for this identity. The default font uses bundled caches;
|
|
121
|
+
// custom fonts are extracted in Node. makeWordmark manages its own cache.
|
|
120
122
|
if (font) {
|
|
121
123
|
const abs = path.isAbsolute(font) ? font : path.resolve(process.cwd(), font);
|
|
122
124
|
const stem = path.basename(abs).replace(/\.[^.]+$/, '');
|
|
@@ -124,7 +126,7 @@ export async function buildKit({
|
|
|
124
126
|
process.env.BRAND_GLYPHS = `${stem}-glyphs.json`;
|
|
125
127
|
process.env.BRAND_WORDMARK_GLYPHS = `${stem}-wordmark-glyphs.json`;
|
|
126
128
|
if (stages.has('mark') || stages.has('sheet')) {
|
|
127
|
-
ensureGlyphs({ file: process.env.BRAND_GLYPHS, font: abs, weight, chars: glyph, label: 'mark glyphs' });
|
|
129
|
+
await ensureGlyphs({ file: process.env.BRAND_GLYPHS, font: abs, weight, chars: glyph, label: 'mark glyphs' });
|
|
128
130
|
}
|
|
129
131
|
} else {
|
|
130
132
|
delete process.env.BRAND_FONT;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Extract font glyphs into the compact JSON cache consumed by the SVG renderers.
|
|
2
|
+
// OpenType.js plus a WebAssembly WOFF2 decoder keeps this path entirely in
|
|
3
|
+
// Node. Variable fonts are transformed at the requested weight.
|
|
4
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import opentype from 'opentype.js';
|
|
7
|
+
import wawoff2 from 'wawoff2';
|
|
8
|
+
|
|
9
|
+
async function loadFont(fontPath) {
|
|
10
|
+
let bytes = readFileSync(fontPath);
|
|
11
|
+
if (path.extname(fontPath).toLowerCase() === '.woff2') {
|
|
12
|
+
bytes = Buffer.from(await wawoff2.decompress(bytes));
|
|
13
|
+
}
|
|
14
|
+
const buffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
15
|
+
return opentype.parse(buffer);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function glyphAtWeight(font, glyph, weight) {
|
|
19
|
+
if (!font.tables.fvar || !font.variation) return glyph;
|
|
20
|
+
const coords = font.variation.getDefaultCoordinates();
|
|
21
|
+
if (font.tables.fvar.axes.some((axis) => axis.tag === 'wght')) {
|
|
22
|
+
coords.wght = Number(weight);
|
|
23
|
+
}
|
|
24
|
+
return font.variation.process.getTransform(glyph, coords);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function extractGlyphs({ chars, weight, fontPath, outPath }) {
|
|
28
|
+
const font = await loadFont(fontPath);
|
|
29
|
+
const glyphs = {};
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
for (const ch of [...new Set([...chars])]) {
|
|
33
|
+
const index = font.charToGlyphIndex(ch);
|
|
34
|
+
if (index === 0 && ch !== '\0') {
|
|
35
|
+
throw new Error(`Font ${path.basename(fontPath)} has no glyph for "${ch}".`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const glyph = glyphAtWeight(font, font.glyphs.get(index), weight);
|
|
39
|
+
const box = glyph.getBoundingBox();
|
|
40
|
+
glyphs[ch] = {
|
|
41
|
+
path: glyph.path.toPathData({ decimalPlaces: 2, flipY: false }),
|
|
42
|
+
advance: glyph.advanceWidth,
|
|
43
|
+
bounds: {
|
|
44
|
+
xMin: Number.isFinite(box.x1) ? box.x1 : 0,
|
|
45
|
+
yMin: Number.isFinite(box.y1) ? box.y1 : 0,
|
|
46
|
+
xMax: Number.isFinite(box.x2) ? box.x2 : 0,
|
|
47
|
+
yMax: Number.isFinite(box.y2) ? box.y2 : 0,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Could not extract glyphs from ${path.basename(fontPath)} in Node: ${error.message}`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const data = {
|
|
58
|
+
font: path.basename(fontPath),
|
|
59
|
+
unitsPerEm: Number(font.unitsPerEm),
|
|
60
|
+
weight: Number(weight),
|
|
61
|
+
glyphs,
|
|
62
|
+
};
|
|
63
|
+
writeFileSync(outPath, JSON.stringify(data, null, 2));
|
|
64
|
+
return data;
|
|
65
|
+
}
|
package/src/lib/glyphs.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
// Shared glyph-outline cache management. A cache is the JSON that
|
|
2
|
-
// extract-glyphs.
|
|
2
|
+
// extract-glyphs.mjs writes: { font, unitsPerEm, weight, glyphs }. Both the mark
|
|
3
3
|
// (uppercase monogram at the brand weight) and the wordmark (mixed case at the
|
|
4
4
|
// lighter wordmark weight) sit on this, so extraction logic lives in one place.
|
|
5
5
|
//
|
|
6
6
|
// Two cache locations: the read-only set BUNDLED with this package (the default
|
|
7
|
-
// Inter, full alphabet: so the common case
|
|
7
|
+
// Inter, full alphabet: so the common case never writes),
|
|
8
8
|
// and a writable directory (BRAND_CACHE_DIR, else <cwd>/.brand-cache) used when a
|
|
9
9
|
// custom font or a missing glyph forces a fresh extraction. The package install
|
|
10
10
|
// itself is never written to.
|
|
11
|
-
import { execFileSync } from 'node:child_process';
|
|
12
11
|
import { existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
13
12
|
import path from 'node:path';
|
|
14
13
|
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { extractGlyphs } from './extract-glyphs.mjs';
|
|
15
15
|
import { DEFAULT_FONT, fontPath } from './font.mjs';
|
|
16
16
|
|
|
17
17
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -51,28 +51,15 @@ export function cacheCovers({ file, font, weight, chars }) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// Extract `chars` from `font` at `weight` into the writable cache unless a
|
|
54
|
-
// readable cache already covers them.
|
|
55
|
-
|
|
56
|
-
export function ensureGlyphs({ file, font = fontPath(), weight, chars, label = file }) {
|
|
54
|
+
// readable cache already covers them.
|
|
55
|
+
export async function ensureGlyphs({ file, font = fontPath(), weight, chars, label = file }) {
|
|
57
56
|
if (cacheCovers({ file, font, weight, chars })) return;
|
|
58
57
|
const dir = cacheDir();
|
|
59
58
|
const out = path.join(dir, file);
|
|
60
59
|
const charset = [...new Set([...chars])].join('');
|
|
61
60
|
mkdirSync(dir, { recursive: true });
|
|
62
61
|
console.log(`Extracting ${label} "${charset}" @ ${weight} from ${path.basename(font)}`);
|
|
63
|
-
|
|
64
|
-
execFileSync(
|
|
65
|
-
'python3',
|
|
66
|
-
[path.resolve(here, 'extract-glyphs.py'), charset, String(weight), font, out],
|
|
67
|
-
{ stdio: 'inherit' },
|
|
68
|
-
);
|
|
69
|
-
} catch {
|
|
70
|
-
throw new Error(
|
|
71
|
-
`Could not extract glyphs into ${out}. A custom font or new glyph needs ` +
|
|
72
|
-
`python3 + fonttools (pip install -r requirements.txt). The bundled Inter ` +
|
|
73
|
-
`needs none of this.`,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
62
|
+
await extractGlyphs({ chars: charset, weight, fontPath: font, outPath: out });
|
|
76
63
|
}
|
|
77
64
|
|
|
78
65
|
export function loadGlyphs(file) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Normalize the compact mark shown inside favicon and logo tiles.
|
|
2
|
+
// The bundled glyph cache covers uppercase A-Z and digits 0-9.
|
|
3
|
+
export function normalizeGlyph(glyph = 'JS') {
|
|
4
|
+
const value = String(glyph).trim().toUpperCase();
|
|
5
|
+
if (!/^[A-Z0-9]{1,3}$/.test(value)) {
|
|
6
|
+
throw new Error(
|
|
7
|
+
`Invalid glyph: "${glyph}". Expected 1-3 letters or digits, e.g. A, AC, or A3X.`,
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
package/src/lib/mark.mjs
CHANGED
|
@@ -4,18 +4,29 @@
|
|
|
4
4
|
//
|
|
5
5
|
// Outlines come from brand-glyphs.json (A-Z and 0-9 are bundled by default).
|
|
6
6
|
import { loadGlyphs } from './glyphs.mjs';
|
|
7
|
+
import { normalizeGlyph } from './identity.mjs';
|
|
7
8
|
|
|
8
9
|
// Read glyphs lazily so a BRAND_GLYPHS set in-process (by the build) is honored.
|
|
9
10
|
// Defaults to brand-glyphs.json; point at another extracted set with BRAND_GLYPHS.
|
|
10
11
|
let _glyphData;
|
|
12
|
+
let _glyphFile;
|
|
11
13
|
function glyphData() {
|
|
12
|
-
|
|
14
|
+
const file = process.env.BRAND_GLYPHS || 'brand-glyphs.json';
|
|
15
|
+
if (!_glyphData || _glyphFile !== file) {
|
|
16
|
+
_glyphData = loadGlyphs(file);
|
|
17
|
+
_glyphFile = file;
|
|
18
|
+
}
|
|
13
19
|
return _glyphData;
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
const RENDER = {
|
|
17
23
|
letterSpacing: -0.045, // em
|
|
18
|
-
widthRatio:
|
|
24
|
+
widthRatio: {
|
|
25
|
+
1: 0.46,
|
|
26
|
+
2: 0.63,
|
|
27
|
+
3: 0.76,
|
|
28
|
+
},
|
|
29
|
+
heightRatio: 0.56, // cap narrow glyphs such as "I" by height
|
|
19
30
|
radiusRatio: 0.22, // rounded-square corner radius (0 = square)
|
|
20
31
|
};
|
|
21
32
|
|
|
@@ -31,8 +42,7 @@ function layout(glyph) {
|
|
|
31
42
|
if (!g) {
|
|
32
43
|
throw new Error(
|
|
33
44
|
`No outline for glyph "${ch}". Available: ${Object.keys(glyphs).join(', ')}. ` +
|
|
34
|
-
`
|
|
35
|
-
`font, ensure python3 + fonttools are installed.`,
|
|
45
|
+
`Re-run through buildKit or buildBrand so the Node extractor can cache it.`,
|
|
36
46
|
);
|
|
37
47
|
}
|
|
38
48
|
placed.push({ x: penX, g });
|
|
@@ -45,7 +55,14 @@ function layout(glyph) {
|
|
|
45
55
|
yMin = Math.min(yMin, g.bounds.yMin);
|
|
46
56
|
yMax = Math.max(yMax, g.bounds.yMax);
|
|
47
57
|
}
|
|
48
|
-
return {
|
|
58
|
+
return {
|
|
59
|
+
placed,
|
|
60
|
+
count: chars.length,
|
|
61
|
+
cx: (xMin + xMax) / 2,
|
|
62
|
+
cy: (yMin + yMax) / 2,
|
|
63
|
+
gw: xMax - xMin,
|
|
64
|
+
gh: yMax - yMin,
|
|
65
|
+
};
|
|
49
66
|
}
|
|
50
67
|
|
|
51
68
|
/**
|
|
@@ -55,11 +72,14 @@ function layout(glyph) {
|
|
|
55
72
|
* @param {boolean} [opts.rounded=true] rounded-square (false = full square)
|
|
56
73
|
* @param {string|null} [opts.bg] tile fill, or null for transparent
|
|
57
74
|
* @param {string} [opts.fg='#ffffff'] glyph fill
|
|
58
|
-
* @param {string} [opts.glyph='JS']
|
|
75
|
+
* @param {string} [opts.glyph='JS'] 1-3 alphanumeric mark characters
|
|
59
76
|
*/
|
|
60
77
|
export function markSvg({ size = 512, rounded = true, bg, fg = '#ffffff', glyph = 'JS' } = {}) {
|
|
61
|
-
const
|
|
62
|
-
const
|
|
78
|
+
const normalizedGlyph = normalizeGlyph(glyph);
|
|
79
|
+
const { placed, count, cx, cy, gw, gh } = layout(normalizedGlyph);
|
|
80
|
+
const widthScale = (RENDER.widthRatio[count] * size) / gw;
|
|
81
|
+
const heightScale = (RENDER.heightRatio * size) / gh;
|
|
82
|
+
const s = Math.min(widthScale, heightScale);
|
|
63
83
|
const rx = rounded ? +(size * RENDER.radiusRatio).toFixed(2) : 0;
|
|
64
84
|
const bgRect = bg ? `<rect width="${size}" height="${size}" rx="${rx}" fill="${bg}"/>` : '';
|
|
65
85
|
const paths = placed
|
package/src/lib/render.mjs
CHANGED
|
@@ -8,9 +8,18 @@ import { fontPath } from './font.mjs';
|
|
|
8
8
|
|
|
9
9
|
// The bundled font embedded as a data URI, as an @font-face for `family`.
|
|
10
10
|
export function fontFaceCss(family) {
|
|
11
|
-
const
|
|
11
|
+
const font = fontPath();
|
|
12
|
+
const ext = font.split('.').pop().toLowerCase();
|
|
13
|
+
const formats = {
|
|
14
|
+
otf: ['font/otf', 'opentype'],
|
|
15
|
+
ttf: ['font/ttf', 'truetype'],
|
|
16
|
+
woff: ['font/woff', 'woff'],
|
|
17
|
+
woff2: ['font/woff2', 'woff2'],
|
|
18
|
+
};
|
|
19
|
+
const [mime, format] = formats[ext] || ['application/octet-stream', ext];
|
|
20
|
+
const b64 = readFileSync(font).toString('base64');
|
|
12
21
|
return `@font-face{font-family:${family};font-weight:200 900;font-display:block;` +
|
|
13
|
-
`src:url(data
|
|
22
|
+
`src:url(data:${mime};base64,${b64}) format('${format}')}`;
|
|
14
23
|
}
|
|
15
24
|
|
|
16
25
|
// Playwright is an optional dependency: only the sheet and social-card renderers
|
package/src/lib/wordmark.mjs
CHANGED
|
@@ -21,8 +21,13 @@ const LETTER_SPACING = { title: -0.03125, caps: -0.02 }; // em
|
|
|
21
21
|
// Read glyphs lazily so a cache (re)written earlier in the same process, or a
|
|
22
22
|
// BRAND_WORDMARK_GLYPHS set by build.mjs, is honored on first render.
|
|
23
23
|
let _glyphData;
|
|
24
|
+
let _glyphFile;
|
|
24
25
|
function glyphData() {
|
|
25
|
-
|
|
26
|
+
const file = wordmarkGlyphFile();
|
|
27
|
+
if (!_glyphData || _glyphFile !== file) {
|
|
28
|
+
_glyphData = loadGlyphs(file);
|
|
29
|
+
_glyphFile = file;
|
|
30
|
+
}
|
|
26
31
|
return _glyphData;
|
|
27
32
|
}
|
|
28
33
|
|