castle-web-cli 0.4.166 → 0.4.167
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/dist/agent.d.ts +1 -2
- package/dist/agent.js +22 -13
- package/dist/api.js +16 -1
- package/dist/imports.js +19 -4
- package/dist/localPaths.d.ts +2 -0
- package/dist/localPaths.js +6 -0
- package/dist/serve.js +5 -1
- package/dist/serveSecurity.d.ts +12 -0
- package/dist/serveSecurity.js +42 -0
- package/dist/shell/assets/{index-CG9TrvCm.js → index-C8M-p00y.js} +36 -36
- package/dist/shell/index.html +1 -1
- package/kits/base/castle.json +64 -2
- package/kits/base/editors/ImageViewer.js +259 -0
- package/kits/base/editors/MediaPlayer.js +90 -0
- package/kits/base/editors/imageViewer.css +95 -0
- package/kits/base/editors/mediaPlayer.css +58 -0
- package/kits/multiplayer-2d/castle.json +1 -1
- package/kits/multiplayer-2d/package-lock.json +4 -1
- package/kits/multiplayer-3d/castle.json +1 -1
- package/kits/multiplayer-3d/package-lock.json +1 -1
- package/kits/physics-2d/behaviors/Joints.jsx +11 -5
- package/kits/physics-2d/behaviors/Sprite.jsx +6 -21
- package/kits/physics-2d/castle.json +1 -61
- package/kits/physics-2d/editors/BlueprintLibrary.jsx +8 -68
- package/kits/physics-2d/editors/SingleEditor.jsx +3 -10
- package/kits/physics-2d/editors/editorRegistry.jsx +36 -2
- package/kits/physics-2d/engine/art.js +25 -1
- package/kits/physics-2d/engine/artThumbnail.jsx +92 -0
- package/kits/physics-2d/engine/files.js +4 -15
- package/kits/physics-2d/engine/spriteField.jsx +176 -0
- package/kits/physics-2d/engine/ui.module.css +136 -0
- package/kits/physics-2d/package-lock.json +5 -0
- package/kits/physics-2d/pnpm-lock.yaml +96 -3
- package/kits/physics-3d/castle.json +1 -1
- package/kits/physics-3d/package-lock.json +1 -1
- package/kits/physics-3d/pnpm-lock.yaml +88 -3
- package/kits/real-time/castle.json +1 -1
- package/kits/real-time/package.json +3 -0
- package/kits/turn-based/castle.json +1 -1
- package/kits/turn-based/package-lock.json +1 -1
- package/package.json +1 -1
- package/kits/base/node_modules/.package-lock.json +0 -28
- package/kits/base/node_modules/castle-web-fonts/README.md +0 -114
- package/kits/base/node_modules/castle-web-fonts/dist/catalog.d.ts +0 -18
- package/kits/base/node_modules/castle-web-fonts/dist/catalog.js +0 -142
- package/kits/base/node_modules/castle-web-fonts/dist/face.d.ts +0 -1
- package/kits/base/node_modules/castle-web-fonts/dist/face.js +0 -52
- package/kits/base/node_modules/castle-web-fonts/dist/faces/Bore.d.ts +0 -3
- package/kits/base/node_modules/castle-web-fonts/dist/faces/Bore.js +0 -10
- package/kits/base/node_modules/castle-web-fonts/dist/faces/CourierPrime.d.ts +0 -3
- package/kits/base/node_modules/castle-web-fonts/dist/faces/CourierPrime.js +0 -10
- package/kits/base/node_modules/castle-web-fonts/dist/faces/DMSans.d.ts +0 -3
- package/kits/base/node_modules/castle-web-fonts/dist/faces/DMSans.js +0 -10
- package/kits/base/node_modules/castle-web-fonts/dist/faces/Glacier.d.ts +0 -3
- package/kits/base/node_modules/castle-web-fonts/dist/faces/Glacier.js +0 -10
- package/kits/base/node_modules/castle-web-fonts/dist/faces/HelicoCentrica.d.ts +0 -3
- package/kits/base/node_modules/castle-web-fonts/dist/faces/HelicoCentrica.js +0 -10
- package/kits/base/node_modules/castle-web-fonts/dist/faces/Piazzolla.d.ts +0 -3
- package/kits/base/node_modules/castle-web-fonts/dist/faces/Piazzolla.js +0 -10
- package/kits/base/node_modules/castle-web-fonts/dist/faces/Synco.d.ts +0 -3
- package/kits/base/node_modules/castle-web-fonts/dist/faces/Synco.js +0 -10
- package/kits/base/node_modules/castle-web-fonts/dist/faces/Tektur.d.ts +0 -3
- package/kits/base/node_modules/castle-web-fonts/dist/faces/Tektur.js +0 -10
- package/kits/base/node_modules/castle-web-fonts/dist/faces/YatraOne.d.ts +0 -3
- package/kits/base/node_modules/castle-web-fonts/dist/faces/YatraOne.js +0 -10
- package/kits/base/node_modules/castle-web-fonts/dist/index.d.ts +0 -16
- package/kits/base/node_modules/castle-web-fonts/dist/index.js +0 -15
- package/kits/base/node_modules/castle-web-fonts/licenses/CC-BY-ND-4.0.txt +0 -393
- package/kits/base/node_modules/castle-web-fonts/licenses/FONTS.md +0 -64
- package/kits/base/node_modules/castle-web-fonts/licenses/OFL-1.1.txt +0 -95
- package/kits/base/node_modules/castle-web-fonts/package.json +0 -47
- package/kits/base/node_modules/castle-web-fonts/woff2/Bore.woff2 +0 -0
- package/kits/base/node_modules/castle-web-fonts/woff2/CourierPrime.woff2 +0 -0
- package/kits/base/node_modules/castle-web-fonts/woff2/DMSans.woff2 +0 -0
- package/kits/base/node_modules/castle-web-fonts/woff2/Glacier.woff2 +0 -0
- package/kits/base/node_modules/castle-web-fonts/woff2/HelicoCentrica.woff2 +0 -0
- package/kits/base/node_modules/castle-web-fonts/woff2/Piazzolla.woff2 +0 -0
- package/kits/base/node_modules/castle-web-fonts/woff2/SOURCE.txt +0 -2
- package/kits/base/node_modules/castle-web-fonts/woff2/Synco.woff2 +0 -0
- package/kits/base/node_modules/castle-web-fonts/woff2/Tektur.woff2 +0 -0
- package/kits/base/node_modules/castle-web-fonts/woff2/YatraOne.woff2 +0 -0
- package/kits/physics-2d/editors/ImageViewer.jsx +0 -206
- package/kits/physics-2d/editors/MediaPlayer.jsx +0 -57
- package/kits/physics-2d/editors/mediaFile.js +0 -31
- package/kits/physics-2d/editors/mediaViewer.module.css +0 -128
|
@@ -26,15 +26,27 @@ importers:
|
|
|
26
26
|
'@dimforge/rapier3d-compat':
|
|
27
27
|
specifier: ^0.19.2
|
|
28
28
|
version: 0.19.3
|
|
29
|
+
'@dnd-kit/core':
|
|
30
|
+
specifier: ^6.3.1
|
|
31
|
+
version: 6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
|
32
|
+
'@dnd-kit/modifiers':
|
|
33
|
+
specifier: ^9.0.0
|
|
34
|
+
version: 9.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
|
|
35
|
+
'@dnd-kit/sortable':
|
|
36
|
+
specifier: ^10.0.0
|
|
37
|
+
version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
|
|
38
|
+
'@dnd-kit/utilities':
|
|
39
|
+
specifier: ^3.2.2
|
|
40
|
+
version: 3.2.2(react@19.2.8)
|
|
29
41
|
'@fortawesome/free-solid-svg-icons':
|
|
30
42
|
specifier: ^5.15.4
|
|
31
43
|
version: 5.15.4
|
|
32
44
|
'@lezer/highlight':
|
|
33
45
|
specifier: ^1.2.3
|
|
34
46
|
version: 1.2.3
|
|
35
|
-
castle-web-
|
|
36
|
-
specifier:
|
|
37
|
-
version:
|
|
47
|
+
castle-web-fonts:
|
|
48
|
+
specifier: ^1.0.0
|
|
49
|
+
version: 1.0.0
|
|
38
50
|
codemirror:
|
|
39
51
|
specifier: ^6.0.2
|
|
40
52
|
version: 6.0.2
|
|
@@ -51,6 +63,9 @@ importers:
|
|
|
51
63
|
specifier: ^0.180.0
|
|
52
64
|
version: 0.180.0
|
|
53
65
|
devDependencies:
|
|
66
|
+
castle-web-sdk:
|
|
67
|
+
specifier: file:../../sdk
|
|
68
|
+
version: file:../../sdk
|
|
54
69
|
eslint:
|
|
55
70
|
specifier: ^9.0.0
|
|
56
71
|
version: 9.39.5
|
|
@@ -114,6 +129,34 @@ packages:
|
|
|
114
129
|
'@dimforge/rapier3d-compat@0.19.3':
|
|
115
130
|
resolution: {integrity: sha512-mMVdSj1PRTT108s9Swbu2GQOmHbn8kbJANRV5xfczL3s0T4vkgZAuoMRgvBzQcHanpKusbC0ZJj6z3mC3aj3vg==}
|
|
116
131
|
|
|
132
|
+
'@dnd-kit/accessibility@3.1.1':
|
|
133
|
+
resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==}
|
|
134
|
+
peerDependencies:
|
|
135
|
+
react: '>=16.8.0'
|
|
136
|
+
|
|
137
|
+
'@dnd-kit/core@6.3.1':
|
|
138
|
+
resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==}
|
|
139
|
+
peerDependencies:
|
|
140
|
+
react: '>=16.8.0'
|
|
141
|
+
react-dom: '>=16.8.0'
|
|
142
|
+
|
|
143
|
+
'@dnd-kit/modifiers@9.0.0':
|
|
144
|
+
resolution: {integrity: sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==}
|
|
145
|
+
peerDependencies:
|
|
146
|
+
'@dnd-kit/core': ^6.3.0
|
|
147
|
+
react: '>=16.8.0'
|
|
148
|
+
|
|
149
|
+
'@dnd-kit/sortable@10.0.0':
|
|
150
|
+
resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==}
|
|
151
|
+
peerDependencies:
|
|
152
|
+
'@dnd-kit/core': ^6.3.0
|
|
153
|
+
react: '>=16.8.0'
|
|
154
|
+
|
|
155
|
+
'@dnd-kit/utilities@3.2.2':
|
|
156
|
+
resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
|
|
157
|
+
peerDependencies:
|
|
158
|
+
react: '>=16.8.0'
|
|
159
|
+
|
|
117
160
|
'@eslint-community/eslint-utils@4.10.1':
|
|
118
161
|
resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==}
|
|
119
162
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
|
@@ -303,6 +346,9 @@ packages:
|
|
|
303
346
|
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
|
304
347
|
engines: {node: '>=6'}
|
|
305
348
|
|
|
349
|
+
castle-web-fonts@1.0.0:
|
|
350
|
+
resolution: {integrity: sha512-amFts4vVJjaXKNQkh2DMMmxYHafCYczAOvme70n+0WX8fsTqJACh6r6MzND94l89Q6LFoIyrCm+cLh3S1Usy0w==}
|
|
351
|
+
|
|
306
352
|
castle-web-sdk@file:../../sdk:
|
|
307
353
|
resolution: {directory: ../../sdk, type: directory}
|
|
308
354
|
|
|
@@ -855,6 +901,9 @@ packages:
|
|
|
855
901
|
token-stream@1.0.0:
|
|
856
902
|
resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==}
|
|
857
903
|
|
|
904
|
+
tslib@2.8.1:
|
|
905
|
+
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
|
906
|
+
|
|
858
907
|
type-check@0.4.0:
|
|
859
908
|
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
|
860
909
|
engines: {node: '>= 0.8.0'}
|
|
@@ -969,6 +1018,38 @@ snapshots:
|
|
|
969
1018
|
|
|
970
1019
|
'@dimforge/rapier3d-compat@0.19.3': {}
|
|
971
1020
|
|
|
1021
|
+
'@dnd-kit/accessibility@3.1.1(react@19.2.8)':
|
|
1022
|
+
dependencies:
|
|
1023
|
+
react: 19.2.8
|
|
1024
|
+
tslib: 2.8.1
|
|
1025
|
+
|
|
1026
|
+
'@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
|
|
1027
|
+
dependencies:
|
|
1028
|
+
'@dnd-kit/accessibility': 3.1.1(react@19.2.8)
|
|
1029
|
+
'@dnd-kit/utilities': 3.2.2(react@19.2.8)
|
|
1030
|
+
react: 19.2.8
|
|
1031
|
+
react-dom: 19.2.8(react@19.2.8)
|
|
1032
|
+
tslib: 2.8.1
|
|
1033
|
+
|
|
1034
|
+
'@dnd-kit/modifiers@9.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
|
|
1035
|
+
dependencies:
|
|
1036
|
+
'@dnd-kit/core': 6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
|
1037
|
+
'@dnd-kit/utilities': 3.2.2(react@19.2.8)
|
|
1038
|
+
react: 19.2.8
|
|
1039
|
+
tslib: 2.8.1
|
|
1040
|
+
|
|
1041
|
+
'@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
|
|
1042
|
+
dependencies:
|
|
1043
|
+
'@dnd-kit/core': 6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
|
1044
|
+
'@dnd-kit/utilities': 3.2.2(react@19.2.8)
|
|
1045
|
+
react: 19.2.8
|
|
1046
|
+
tslib: 2.8.1
|
|
1047
|
+
|
|
1048
|
+
'@dnd-kit/utilities@3.2.2(react@19.2.8)':
|
|
1049
|
+
dependencies:
|
|
1050
|
+
react: 19.2.8
|
|
1051
|
+
tslib: 2.8.1
|
|
1052
|
+
|
|
972
1053
|
'@eslint-community/eslint-utils@4.10.1(eslint@9.39.5)':
|
|
973
1054
|
dependencies:
|
|
974
1055
|
eslint: 9.39.5
|
|
@@ -1170,6 +1251,8 @@ snapshots:
|
|
|
1170
1251
|
|
|
1171
1252
|
callsites@3.1.0: {}
|
|
1172
1253
|
|
|
1254
|
+
castle-web-fonts@1.0.0: {}
|
|
1255
|
+
|
|
1173
1256
|
castle-web-sdk@file:../../sdk: {}
|
|
1174
1257
|
|
|
1175
1258
|
chalk@4.1.2:
|
|
@@ -1754,6 +1837,8 @@ snapshots:
|
|
|
1754
1837
|
|
|
1755
1838
|
token-stream@1.0.0: {}
|
|
1756
1839
|
|
|
1840
|
+
tslib@2.8.1: {}
|
|
1841
|
+
|
|
1757
1842
|
type-check@0.4.0:
|
|
1758
1843
|
dependencies:
|
|
1759
1844
|
prelude-ls: 1.2.1
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"autoUpdateWhenImported": true,
|
|
29
29
|
"deckId": "K6-Xs7dCoMVi",
|
|
30
30
|
"cardId": "Kh_08IYATpC3",
|
|
31
|
-
"publishedVersion": "2026-09-
|
|
31
|
+
"publishedVersion": "2026-09-05T00:07:41.510Z",
|
|
32
32
|
"server": {
|
|
33
33
|
"main": "code/server/index.js",
|
|
34
34
|
"maxPlayers": 8,
|
package/package.json
CHANGED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "base",
|
|
3
|
-
"lockfileVersion": 3,
|
|
4
|
-
"requires": true,
|
|
5
|
-
"packages": {
|
|
6
|
-
"../../sdk": {
|
|
7
|
-
"name": "castle-web-sdk",
|
|
8
|
-
"version": "0.4.22",
|
|
9
|
-
"dev": true,
|
|
10
|
-
"devDependencies": {
|
|
11
|
-
"eslint": "^9.0.0",
|
|
12
|
-
"jscpd": "^4.0.5",
|
|
13
|
-
"typescript": "^5.0.0",
|
|
14
|
-
"typescript-eslint": "^8.0.0"
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
"node_modules/castle-web-fonts": {
|
|
18
|
-
"version": "1.0.0",
|
|
19
|
-
"resolved": "https://registry.npmjs.org/castle-web-fonts/-/castle-web-fonts-1.0.0.tgz",
|
|
20
|
-
"integrity": "sha512-amFts4vVJjaXKNQkh2DMMmxYHafCYczAOvme70n+0WX8fsTqJACh6r6MzND94l89Q6LFoIyrCm+cLh3S1Usy0w==",
|
|
21
|
-
"license": "SEE LICENSE IN licenses/FONTS.md"
|
|
22
|
-
},
|
|
23
|
-
"node_modules/castle-web-sdk": {
|
|
24
|
-
"resolved": "../../sdk",
|
|
25
|
-
"link": true
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# castle-web-fonts
|
|
2
|
-
|
|
3
|
-
The nine typefaces the Castle Classic engine gives its text tool, as web fonts
|
|
4
|
-
a Castle deck can use. Same faces, same names: a deck asking for `Piazzolla`
|
|
5
|
-
here gets what a Classic card asking for `Piazzolla` gets.
|
|
6
|
-
|
|
7
|
-
```js
|
|
8
|
-
import { installTektur } from 'castle-web-fonts';
|
|
9
|
-
|
|
10
|
-
installTektur(); // now: font-family: 'Tektur'
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Install what you name, then use the family name in CSS. Two or three faces is
|
|
14
|
-
normal — one for body and UI, one display face for titles.
|
|
15
|
-
|
|
16
|
-
## The faces
|
|
17
|
-
|
|
18
|
-
| face | character | good for | woff2 |
|
|
19
|
-
|---|---|---|---:|
|
|
20
|
-
| `DMSans` | clean geometric sans, low contrast | body, UI, HUD | 27 KB |
|
|
21
|
-
| `Piazzolla` | sturdy text serif, readable at length | body text, narrative, prose-heavy decks | 81 KB |
|
|
22
|
-
| `CourierPrime` | monospace typewriter serif | code, terminals, typewriter effects | 28 KB |
|
|
23
|
-
| `Tektur` | condensed squarish techno | sci-fi, arcade, HUD numerals | 31 KB |
|
|
24
|
-
| `Bore` | very heavy wide grotesque | impact headlines, scores, big titles | 12 KB |
|
|
25
|
-
| `Synco` | light wide geometric, unusual joins | retro-modernist titles | 12 KB |
|
|
26
|
-
| `Glacier` | slanted condensed hand-cut italic | informal, energetic display | 13 KB |
|
|
27
|
-
| `HelicoCentrica` | blackletter-flavored roman, pointed serifs | medieval, fantasy, ornate | 78 KB |
|
|
28
|
-
| `YatraOne` | high-contrast brushy display (also Devanagari) | bold headlines, South Asian text | 89 KB |
|
|
29
|
-
|
|
30
|
-
Each has one weight and one style, as in Classic. Ask for bold or italic and the
|
|
31
|
-
browser synthesizes it.
|
|
32
|
-
|
|
33
|
-
## `install<Face>(): Promise<string>`
|
|
34
|
-
|
|
35
|
-
Registers the face and resolves with its CSS family name. Idempotent — repeat
|
|
36
|
-
calls return the first call's promise, so calling it from several modules is
|
|
37
|
-
fine.
|
|
38
|
-
|
|
39
|
-
The bytes are a `data:` URI inside the module, so there is no network fetch: no
|
|
40
|
-
CORS, no round trip, nothing to go wrong offline, and the face is available on
|
|
41
|
-
the first frame. That matters because a published deck is a single HTML file
|
|
42
|
-
served from an origin that is never castle.xyz — `castle-deck://` in the iOS
|
|
43
|
-
app, `*.decks.castle.games` on Android.
|
|
44
|
-
|
|
45
|
-
**Awaiting it matters before drawing to a canvas.** Canvas 2D does not trigger a
|
|
46
|
-
font load, so `ctx.font = '20px Piazzolla'` before the face is ready silently
|
|
47
|
-
falls back to the default and never repaints when the font arrives:
|
|
48
|
-
|
|
49
|
-
```js
|
|
50
|
-
import { installPiazzolla } from 'castle-web-fonts';
|
|
51
|
-
|
|
52
|
-
const family = await installPiazzolla();
|
|
53
|
-
ctx.font = `20px ${family}`;
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
In CSS it matters less — the browser reflows when the face lands.
|
|
57
|
-
|
|
58
|
-
## `FACES`, `FACE_NAMES`, `faceInfo(name)`
|
|
59
|
-
|
|
60
|
-
The catalog: each face's `name`, `label`, `character`, `goodFor`, `credit`,
|
|
61
|
-
`copyright`, `url`, and `license`. **Metadata only — no font bytes**, so a font
|
|
62
|
-
picker can list every face without pulling any of them into the bundle.
|
|
63
|
-
|
|
64
|
-
## One named export per face, never a lookup
|
|
65
|
-
|
|
66
|
-
A deck pays for exactly the faces it names, because each face is a named export
|
|
67
|
-
backed by its own module and there is no other way to reach the bytes. Adding a
|
|
68
|
-
tenth face, or a fiftieth, costs every existing deck zero.
|
|
69
|
-
|
|
70
|
-
That property is fragile and worth stating plainly:
|
|
71
|
-
|
|
72
|
-
```js
|
|
73
|
-
// Fine. Inlines Tektur, 41 KB.
|
|
74
|
-
import { installTektur } from 'castle-web-fonts';
|
|
75
|
-
|
|
76
|
-
// NOT fine. Inlines all nine, 495 KB, in every deck that does this.
|
|
77
|
-
const FONTS = { Tektur: installTektur, Bore: installBore, /* ... */ };
|
|
78
|
-
FONTS[themeName]();
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
No bundler can prove which key a lookup reads, so it keeps every face. Declaring
|
|
82
|
-
`"sideEffects": false` does not rescue it. `npm run check` builds a real
|
|
83
|
-
single-file bundle and counts the inlined faces, so a regression fails there
|
|
84
|
-
rather than in someone's deck.
|
|
85
|
-
|
|
86
|
-
If a font name has to come from data — a theme file, a saved setting — resolve
|
|
87
|
-
that name to an `install` call at build time, not at runtime. The physics-2d kit
|
|
88
|
-
does this by generating a one-line module when the deck's font is picked.
|
|
89
|
-
|
|
90
|
-
## Licensing
|
|
91
|
-
|
|
92
|
-
Eight faces are [OFL 1.1](licenses/OFL-1.1.txt), which permits woff2 conversion
|
|
93
|
-
and redistribution. Bore is [CC BY-ND 4.0](licenses/CC-BY-ND-4.0.txt), where
|
|
94
|
-
conversion is a permitted technical modification under §2(a)(4) — but
|
|
95
|
-
**subsetting Bore is not**, since dropping glyphs makes a derivative work. It is
|
|
96
|
-
12 KB whole.
|
|
97
|
-
|
|
98
|
-
Per-face notices, verbatim from each font's own name table, are in
|
|
99
|
-
[licenses/FONTS.md](licenses/FONTS.md).
|
|
100
|
-
|
|
101
|
-
## Development
|
|
102
|
-
|
|
103
|
-
`woff2/*.woff2` are converted from the TrueType files in a `ghost` checkout
|
|
104
|
-
(`core/assets/`), which is where the C++ engine bakes them in from — those are
|
|
105
|
-
the source of truth for which faces exist:
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
npm run convert -- --ghost ../../ghost # ttf -> woff2/
|
|
109
|
-
npm run build # woff2/ -> dist/
|
|
110
|
-
npm run check # lint + build + bundle-size invariant
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
`convert` is deliberately not part of the build: a ghost checkout is not
|
|
114
|
-
something a `castle-web-fonts` build may assume.
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export interface CastleFace {
|
|
2
|
-
/** CSS family name, e.g. 'Piazzolla'. Also the `install<Name>` suffix and the `woff2/<Name>.woff2` stem. */
|
|
3
|
-
name: string;
|
|
4
|
-
/** Human name, e.g. 'Courier Prime'. */
|
|
5
|
-
label: string;
|
|
6
|
-
/** Source filename in a ghost checkout's core/assets/. */
|
|
7
|
-
ttf: string;
|
|
8
|
-
/** What the face looks like, in a phrase. */
|
|
9
|
-
character: string;
|
|
10
|
-
/** What it suits. */
|
|
11
|
-
goodFor: string;
|
|
12
|
-
/** Designer / foundry attribution. */
|
|
13
|
-
credit: string;
|
|
14
|
-
license: 'OFL-1.1' | 'CC-BY-ND-4.0';
|
|
15
|
-
}
|
|
16
|
-
export declare const FACES: CastleFace[];
|
|
17
|
-
export declare const FACE_NAMES: string[];
|
|
18
|
-
export declare function faceInfo(name: string): CastleFace | undefined;
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
// The nine faces the Castle Classic engine offers its text tool, as web fonts.
|
|
2
|
-
//
|
|
3
|
-
// This list is the package: everything else -- the per-face modules, the woff2
|
|
4
|
-
// conversion, the docs table -- is generated from or checked against it. The
|
|
5
|
-
// `name` of a face is three things at once, deliberately: its CSS family, the
|
|
6
|
-
// suffix of its `install<Name>` export, and the stem of its `woff2/<Name>.woff2`
|
|
7
|
-
// file. They match Classic's own registry names (ghost/core/src/behaviors/
|
|
8
|
-
// text_fonts.cpp), so a deck asking for `Piazzolla` here gets the same face a
|
|
9
|
-
// Classic card asking for `Piazzolla` gets.
|
|
10
|
-
//
|
|
11
|
-
// `character` and `goodFor` are what an agent picking a face reads instead of
|
|
12
|
-
// seeing a specimen, and what the physics-2d picker prints on its cards. Keep
|
|
13
|
-
// them one short phrase each.
|
|
14
|
-
//
|
|
15
|
-
// This module carries NO font bytes, so importing it costs a deck nothing --
|
|
16
|
-
// the picker UI and the docs generator both want the metadata alone.
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @typedef {object} CastleFace
|
|
20
|
-
* @property {string} name CSS family name, e.g. 'Piazzolla'.
|
|
21
|
-
* @property {string} label Human name, e.g. 'Courier Prime'.
|
|
22
|
-
* @property {string} ttf Source filename in a ghost checkout's core/assets/.
|
|
23
|
-
* @property {string} character What the face looks like, in a phrase.
|
|
24
|
-
* @property {string} goodFor What it suits.
|
|
25
|
-
* @property {string} credit Designer / foundry attribution.
|
|
26
|
-
* @property {'OFL-1.1' | 'CC-BY-ND-4.0'} license
|
|
27
|
-
* @property {string} copyright The notice embedded in the font's own name table, verbatim.
|
|
28
|
-
* @property {string} url Where the face is published.
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
/** @type {CastleFace[]} */
|
|
32
|
-
export const FACES = [
|
|
33
|
-
{
|
|
34
|
-
name: 'DMSans',
|
|
35
|
-
label: 'DM Sans',
|
|
36
|
-
ttf: 'DMSans-Medium.ttf',
|
|
37
|
-
character: 'clean geometric sans, low contrast',
|
|
38
|
-
goodFor: 'body, UI, HUD',
|
|
39
|
-
credit: 'Colophon Foundry',
|
|
40
|
-
license: 'OFL-1.1',
|
|
41
|
-
copyright: "Copyright 2014-2017 Indian Type Foundry (info@indiantypefoundry.com) with Reserved Font Name 'Poppins'. Copyright 2019 Google LLC.",
|
|
42
|
-
url: 'https://github.com/googlefonts/dm-fonts',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
name: 'Piazzolla',
|
|
46
|
-
label: 'Piazzolla',
|
|
47
|
-
ttf: 'Piazzolla.ttf',
|
|
48
|
-
character: 'sturdy text serif, readable at length',
|
|
49
|
-
goodFor: 'body text, narrative, prose-heavy decks',
|
|
50
|
-
credit: 'Juan Pablo del Peral for Huerta Tipográfica',
|
|
51
|
-
license: 'OFL-1.1',
|
|
52
|
-
copyright: 'Copyright 2018 The Piazzolla Project Authors (https://github.com/huertatipografica/piazzolla)',
|
|
53
|
-
url: 'https://github.com/huertatipografica/piazzolla',
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: 'CourierPrime',
|
|
57
|
-
label: 'Courier Prime',
|
|
58
|
-
ttf: 'CourierPrime-Regular.ttf',
|
|
59
|
-
character: 'monospace typewriter serif',
|
|
60
|
-
goodFor: 'code, terminals, typewriter effects',
|
|
61
|
-
credit: 'Alan Dague-Greene for John August',
|
|
62
|
-
license: 'OFL-1.1',
|
|
63
|
-
copyright: 'Copyright (c) 2013, Quote-Unquote Apps (http://quoteunquoteapps.com), with Reserved Font Name Courier Prime.',
|
|
64
|
-
url: 'https://quoteunquoteapps.com/courierprime/',
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
name: 'Tektur',
|
|
68
|
-
label: 'Tektur',
|
|
69
|
-
ttf: 'Tektur.ttf',
|
|
70
|
-
character: 'condensed squarish techno',
|
|
71
|
-
goodFor: 'sci-fi, arcade, HUD numerals',
|
|
72
|
-
credit: 'Adam Jagosz',
|
|
73
|
-
license: 'OFL-1.1',
|
|
74
|
-
copyright: 'Copyright 2020 The Tektur Project Authors (https://www.github.com/hyvyys/Tektur)',
|
|
75
|
-
url: 'https://github.com/hyvyys/Tektur',
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
name: 'Bore',
|
|
79
|
-
label: 'Bore',
|
|
80
|
-
ttf: 'Bore.ttf',
|
|
81
|
-
character: 'very heavy wide grotesque',
|
|
82
|
-
goodFor: 'impact headlines, scores, big titles',
|
|
83
|
-
credit: 'Austin Stahl',
|
|
84
|
-
license: 'CC-BY-ND-4.0',
|
|
85
|
-
copyright: 'Copyright © 2021 by Austin Stahl. All rights reserved.',
|
|
86
|
-
url: 'https://www.austinstahl.com/bore-download',
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
name: 'Synco',
|
|
90
|
-
label: 'Synco',
|
|
91
|
-
ttf: 'Synco.ttf',
|
|
92
|
-
character: 'light wide geometric, unusual joins',
|
|
93
|
-
goodFor: 'retro-modernist titles',
|
|
94
|
-
credit: 'Ariel Martín Pérez for Altiplano',
|
|
95
|
-
license: 'OFL-1.1',
|
|
96
|
-
copyright: 'Copyright © 2020 by Raphaël Verona | Altiplano Typefaces. All rights reserved.',
|
|
97
|
-
url: 'https://fontesk.com/synco-font/',
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
name: 'Glacier',
|
|
101
|
-
label: 'Glacier',
|
|
102
|
-
ttf: 'Glacier.ttf',
|
|
103
|
-
character: 'slanted condensed hand-cut italic',
|
|
104
|
-
goodFor: 'informal, energetic display',
|
|
105
|
-
credit: 'Quentin Juhel',
|
|
106
|
-
license: 'OFL-1.1',
|
|
107
|
-
copyright: 'Copyright (c) 2020, Quentin Juhel (https://juhel-quentin.fr), with Reserved Font Name Glacier.',
|
|
108
|
-
url: 'https://fontesk.com/glacier-typeface/',
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
name: 'HelicoCentrica',
|
|
112
|
-
label: 'Helico Centrica',
|
|
113
|
-
ttf: 'HelicoCentrica.ttf',
|
|
114
|
-
character: 'blackletter-flavored roman, pointed serifs',
|
|
115
|
-
goodFor: 'medieval, fantasy, ornate',
|
|
116
|
-
credit: 'Toby Le Rhone',
|
|
117
|
-
license: 'OFL-1.1',
|
|
118
|
-
copyright: 'Copyright (c) Toby le Rhone, 2015. No rights reserved.',
|
|
119
|
-
url: 'https://fontesk.com/helico-centrica-roman-font/',
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
name: 'YatraOne',
|
|
123
|
-
label: 'Yatra One',
|
|
124
|
-
ttf: 'YatraOne.ttf',
|
|
125
|
-
character: 'high-contrast brushy display (also Devanagari)',
|
|
126
|
-
goodFor: 'bold headlines, South Asian text',
|
|
127
|
-
credit: 'Catherine Leigh Schmidt',
|
|
128
|
-
license: 'OFL-1.1',
|
|
129
|
-
copyright: 'Copyright 2014 The Yatra Project Authors.',
|
|
130
|
-
url: 'https://github.com/cathschmidt/yatra-one',
|
|
131
|
-
},
|
|
132
|
-
];
|
|
133
|
-
|
|
134
|
-
/** Every face's CSS family name, in catalog order. */
|
|
135
|
-
export const FACE_NAMES = FACES.map((face) => face.name);
|
|
136
|
-
|
|
137
|
-
/** One face's metadata by CSS family name, or undefined. Metadata only -- this
|
|
138
|
-
* cannot install anything, precisely because a name-keyed install would pull
|
|
139
|
-
* every face into the bundle (see the README). */
|
|
140
|
-
export function faceInfo(name) {
|
|
141
|
-
return FACES.find((face) => face.name === name);
|
|
142
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function installFace(family: string, source: string): Promise<string>;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// Registering one face with the document.
|
|
2
|
-
//
|
|
3
|
-
// The bytes arrive as a `data:` URI baked into the calling face module, so this
|
|
4
|
-
// never touches the network: no CORS, no round trip, and the face is usable on
|
|
5
|
-
// the first frame. That matters because a Castle deck is published as a single
|
|
6
|
-
// HTML file and runs from origins that are never castle.xyz -- `castle-deck://`
|
|
7
|
-
// in the iOS app, `*.decks.castle.games` on Android.
|
|
8
|
-
|
|
9
|
-
const installs = new Map();
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Register `family` from a woff2 `data:` URI and resolve with the family name
|
|
13
|
-
* once it is ready to draw with. Idempotent: repeat calls for the same family
|
|
14
|
-
* return the first call's promise.
|
|
15
|
-
*
|
|
16
|
-
* Awaiting matters for canvas: `ctx.font` does not trigger a font load, so
|
|
17
|
-
* drawing before the face is ready silently falls back to the default and never
|
|
18
|
-
* repaints. In CSS it matters less -- the browser reflows when the face lands.
|
|
19
|
-
*
|
|
20
|
-
* @param {string} family
|
|
21
|
-
* @param {string} source A `data:font/woff2;base64,...` URI.
|
|
22
|
-
* @returns {Promise<string>}
|
|
23
|
-
*/
|
|
24
|
-
export function installFace(family, source) {
|
|
25
|
-
const existing = installs.get(family);
|
|
26
|
-
if (existing) return existing;
|
|
27
|
-
const install = load(family, source);
|
|
28
|
-
// Fire-and-forget is the documented common case (`installTektur()` with no
|
|
29
|
-
// await), so mark the promise handled here. Awaiting callers still see the
|
|
30
|
-
// rejection -- this is the same promise object, not a swallowing wrapper.
|
|
31
|
-
install.catch(() => {});
|
|
32
|
-
installs.set(family, install);
|
|
33
|
-
return install;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function load(family, source) {
|
|
37
|
-
// Server-side rendering, a worker, a test runner: nothing to register the
|
|
38
|
-
// face with, and no text to draw either. Resolve rather than throw so a
|
|
39
|
-
// deck's top-level `installX()` doesn't take the module down with it.
|
|
40
|
-
if (typeof document === 'undefined' || typeof FontFace === 'undefined') return family;
|
|
41
|
-
// `swap`, so the block period never applies: a face still loading renders in
|
|
42
|
-
// the fallback rather than as nothing. With a data: URI that window is
|
|
43
|
-
// sub-frame anyway, but invisible text is the worse way to lose the race.
|
|
44
|
-
const face = new FontFace(family, `url("${source}") format("woff2")`, { display: 'swap' });
|
|
45
|
-
// ADDED BEFORE LOADED, and the order carries weight: `document.fonts.ready`
|
|
46
|
-
// only waits for faces the set already holds, so adding after the load would
|
|
47
|
-
// leave it resolving early -- and that promise is how a host waits for every
|
|
48
|
-
// face a deck registered, including ones it can't know the names of.
|
|
49
|
-
document.fonts.add(face);
|
|
50
|
-
await face.load();
|
|
51
|
-
return family;
|
|
52
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Bore -- Austin Stahl, CC-BY-ND-4.0. Generated by scripts/build.mjs.
|
|
2
|
-
import { installFace } from '../face.js';
|
|
3
|
-
|
|
4
|
-
const SOURCE =
|
|
5
|
-
'data:font/woff2;base64,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';
|
|
6
|
-
|
|
7
|
-
/** Install Bore and resolve with its CSS family name, 'Bore'. */
|
|
8
|
-
export function installBore() {
|
|
9
|
-
return installFace('Bore', SOURCE);
|
|
10
|
-
}
|