ink-sdl 0.3.2 → 0.4.0

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.
@@ -4,9 +4,18 @@ import { pickBy, isDefined } from "remeda";
4
4
 
5
5
  // src/Sdl2/index.ts
6
6
  import koffi from "koffi";
7
- import { platform } from "os";
7
+
8
+ // src/utils/findLibrary/index.ts
8
9
  import { existsSync } from "fs";
10
+ import { platform } from "os";
9
11
  import { find, last } from "remeda";
12
+ var isSystemPath = (p) => !p.includes("/") && !p.includes("\\");
13
+ var findLibrary = (pathMap) => {
14
+ const plat = platform();
15
+ const paths = pathMap[plat] ?? [];
16
+ const foundPath = find(paths, (p) => isSystemPath(p) || existsSync(p));
17
+ return foundPath ?? last(paths) ?? null;
18
+ };
10
19
 
11
20
  // src/Sdl2/consts.ts
12
21
  var SDL_INIT_VIDEO = 32;
@@ -94,13 +103,6 @@ var SDL_LIB_PATHS = {
94
103
  ],
95
104
  win32: ["SDL2.dll", "C:\\Windows\\System32\\SDL2.dll"]
96
105
  };
97
- var isSystemPath = (p) => !p.includes("/") && !p.includes("\\");
98
- var findLibrary = (pathMap) => {
99
- const plat = platform();
100
- const paths = pathMap[plat] ?? [];
101
- const foundPath = find(paths, (p) => isSystemPath(p) || existsSync(p));
102
- return foundPath ?? last(paths) ?? null;
103
- };
104
106
  var findSDLLibrary = () => {
105
107
  return findLibrary(SDL_LIB_PATHS);
106
108
  };
@@ -962,15 +964,12 @@ var AnsiParser = class {
962
964
  // src/TextRenderer/index.ts
963
965
  import { resolve, dirname, join } from "path";
964
966
  import { fileURLToPath } from "url";
965
- import { existsSync as existsSync3 } from "fs";
966
- import { platform as platform3, homedir } from "os";
967
- import { sortBy, take } from "remeda";
967
+ import { existsSync as existsSync2 } from "fs";
968
+ import { platform as platform2, homedir } from "os";
969
+ import { flatMap, sortBy, take } from "remeda";
968
970
 
969
971
  // src/SdlTtf/index.ts
970
972
  import koffi2 from "koffi";
971
- import { platform as platform2 } from "os";
972
- import { existsSync as existsSync2 } from "fs";
973
- import { find as find2, last as last2 } from "remeda";
974
973
  var SDL_TTF_LIB_PATHS = {
975
974
  darwin: [
976
975
  "/opt/homebrew/lib/libSDL2_ttf.dylib",
@@ -996,15 +995,8 @@ var SDL_TTF_LIB_PATHS = {
996
995
  ],
997
996
  win32: ["SDL2_ttf.dll", "C:\\Windows\\System32\\SDL2_ttf.dll"]
998
997
  };
999
- var isSystemPath2 = (p) => !p.includes("/") && !p.includes("\\");
1000
- var findLibrary2 = (pathMap) => {
1001
- const plat = platform2();
1002
- const paths = pathMap[plat] ?? [];
1003
- const foundPath = find2(paths, (p) => isSystemPath2(p) || existsSync2(p));
1004
- return foundPath ?? last2(paths) ?? null;
1005
- };
1006
998
  var findSDLTtfLibrary = () => {
1007
- return findLibrary2(SDL_TTF_LIB_PATHS);
999
+ return findLibrary(SDL_TTF_LIB_PATHS);
1008
1000
  };
1009
1001
  var SdlTtf = class {
1010
1002
  lib;
@@ -1214,6 +1206,21 @@ var EMOJI_FONTS = {
1214
1206
  var EMOJI_FONT_SCALE = 0.75;
1215
1207
 
1216
1208
  // src/TextRenderer/index.ts
1209
+ var findFirstExisting = (paths) => {
1210
+ for (const p of paths) {
1211
+ try {
1212
+ if (existsSync2(p)) {
1213
+ return p;
1214
+ }
1215
+ } catch {
1216
+ }
1217
+ }
1218
+ return null;
1219
+ };
1220
+ var getPlatformPaths = (pathMap) => {
1221
+ const plat = platform2();
1222
+ return [...pathMap[plat] ?? []];
1223
+ };
1217
1224
  var TextRenderer = class {
1218
1225
  sdl = getSdl2();
1219
1226
  ttf = getSdlTtf();
@@ -1252,7 +1259,7 @@ var TextRenderer = class {
1252
1259
  */
1253
1260
  getSystemFontDirectories() {
1254
1261
  const home = homedir();
1255
- const plat = platform3();
1262
+ const plat = platform2();
1256
1263
  if (plat === "darwin") {
1257
1264
  return [
1258
1265
  join(home, "Library/Fonts"),
@@ -1291,16 +1298,13 @@ var TextRenderer = class {
1291
1298
  findFontByName(fontName) {
1292
1299
  const extensions = [".ttf", ".ttc", ".otf", ".TTC", ".TTF", ".OTF"];
1293
1300
  const directories = this.getSystemFontDirectories();
1294
- for (const dir of directories) {
1295
- for (const ext of extensions) {
1296
- const fontPath = join(dir, `${fontName}${ext}`);
1297
- try {
1298
- if (existsSync3(fontPath)) {
1299
- return fontPath;
1300
- }
1301
- } catch {
1302
- }
1303
- }
1301
+ const paths = flatMap(
1302
+ directories,
1303
+ (dir) => extensions.map((ext) => join(dir, `${fontName}${ext}`))
1304
+ );
1305
+ const fontPath = findFirstExisting(paths);
1306
+ if (fontPath) {
1307
+ return fontPath;
1304
1308
  }
1305
1309
  throw new Error(
1306
1310
  `Font "${fontName}" not found in system font directories.
@@ -1313,13 +1317,9 @@ Tried extensions: ${extensions.join(", ")}`
1313
1317
  * Get the path to the Cozette font (system or bundled)
1314
1318
  */
1315
1319
  getDefaultFontPath() {
1316
- for (const p of this.getSystemFontPaths()) {
1317
- try {
1318
- if (existsSync3(p)) {
1319
- return p;
1320
- }
1321
- } catch {
1322
- }
1320
+ const systemPath = findFirstExisting(this.getSystemFontPaths());
1321
+ if (systemPath) {
1322
+ return systemPath;
1323
1323
  }
1324
1324
  const currentFilename = fileURLToPath(import.meta.url);
1325
1325
  const currentDirname = dirname(currentFilename);
@@ -1331,96 +1331,38 @@ Tried extensions: ${extensions.join(", ")}`
1331
1331
  resolve(currentDirname, "../fonts", DEFAULT_FONT_FILENAME)
1332
1332
  // Alternate
1333
1333
  ];
1334
- for (const p of bundledPaths) {
1335
- try {
1336
- if (existsSync3(p)) {
1337
- return p;
1338
- }
1339
- } catch {
1340
- }
1341
- }
1342
- return bundledPaths[0];
1334
+ return findFirstExisting(bundledPaths) ?? bundledPaths[0];
1343
1335
  }
1344
1336
  /**
1345
1337
  * Get fallback fonts for the current platform
1346
1338
  */
1347
1339
  getFallbackFontPaths() {
1348
- const plat = platform3();
1349
- if (plat === "darwin") {
1350
- return [...FALLBACK_FONTS.darwin];
1351
- }
1352
- if (plat === "linux") {
1353
- return [...FALLBACK_FONTS.linux];
1354
- }
1355
- if (plat === "win32") {
1356
- return [...FALLBACK_FONTS.win32];
1357
- }
1358
- return [];
1340
+ return getPlatformPaths(FALLBACK_FONTS);
1359
1341
  }
1360
1342
  /**
1361
1343
  * Find an available font, trying default first then fallbacks
1362
1344
  */
1363
1345
  findAvailableFont() {
1364
1346
  const defaultPath = this.getDefaultFontPath();
1365
- try {
1366
- if (existsSync3(defaultPath)) {
1367
- return defaultPath;
1368
- }
1369
- } catch {
1370
- }
1371
- for (const fallbackPath of this.getFallbackFontPaths()) {
1372
- try {
1373
- if (existsSync3(fallbackPath)) {
1374
- return fallbackPath;
1375
- }
1376
- } catch {
1377
- }
1378
- }
1379
- return defaultPath;
1347
+ return findFirstExisting([defaultPath, ...this.getFallbackFontPaths()]) ?? defaultPath;
1380
1348
  }
1381
1349
  /**
1382
1350
  * Find a system font, skipping the default bundled font
1383
1351
  */
1384
1352
  findSystemFont() {
1385
- for (const fallbackPath of this.getFallbackFontPaths()) {
1386
- try {
1387
- if (existsSync3(fallbackPath)) {
1388
- return fallbackPath;
1389
- }
1390
- } catch {
1391
- }
1392
- }
1393
- return this.getDefaultFontPath();
1353
+ return findFirstExisting(this.getFallbackFontPaths()) ?? this.getDefaultFontPath();
1394
1354
  }
1395
1355
  /**
1396
1356
  * Get emoji font paths for the current platform
1397
1357
  */
1398
1358
  getEmojiFontPaths() {
1399
- const plat = platform3();
1400
- if (plat === "darwin") {
1401
- return [...EMOJI_FONTS.darwin];
1402
- }
1403
- if (plat === "linux") {
1404
- return [...EMOJI_FONTS.linux];
1405
- }
1406
- if (plat === "win32") {
1407
- return [...EMOJI_FONTS.win32];
1408
- }
1409
- return [];
1359
+ return getPlatformPaths(EMOJI_FONTS);
1410
1360
  }
1411
1361
  /**
1412
1362
  * Find an available emoji font
1413
1363
  */
1414
1364
  findEmojiFont() {
1415
- for (const fontPath of this.getEmojiFontPaths()) {
1416
- try {
1417
- if (existsSync3(fontPath)) {
1418
- return fontPath;
1419
- }
1420
- } catch {
1421
- }
1422
- }
1423
- return null;
1365
+ return findFirstExisting(this.getEmojiFontPaths());
1424
1366
  }
1425
1367
  /**
1426
1368
  * Load the fallback emoji font if available
@@ -1912,6 +1854,11 @@ var TEXT_DECORATION_THICKNESS = 0.08;
1912
1854
  var DEFAULT_BG2 = { r: 0, g: 0, b: 0 };
1913
1855
  var DEFAULT_FG2 = { r: 255, g: 255, b: 255 };
1914
1856
  var MIN_BRIGHTNESS = 100;
1857
+ var adjustBrightness = (color, multiplier, clamp = true) => ({
1858
+ r: clamp ? Math.min(COLOR_CHANNEL_MAX, Math.floor(color.r * multiplier)) : Math.floor(color.r * multiplier),
1859
+ g: clamp ? Math.min(COLOR_CHANNEL_MAX, Math.floor(color.g * multiplier)) : Math.floor(color.g * multiplier),
1860
+ b: clamp ? Math.min(COLOR_CHANNEL_MAX, Math.floor(color.b * multiplier)) : Math.floor(color.b * multiplier)
1861
+ });
1915
1862
  var HEX_COLOR_LENGTH = 6;
1916
1863
  var HEX_R_END = 2;
1917
1864
  var HEX_G_END = 4;
@@ -2026,13 +1973,7 @@ var SdlUiRenderer = class {
2026
1973
  this.charHeight = charDims.height;
2027
1974
  this.updateTerminalDimensions();
2028
1975
  this.createRenderTarget();
2029
- this.sdl.setRenderDrawColor(
2030
- this.renderer,
2031
- this.defaultBgColor.r,
2032
- this.defaultBgColor.g,
2033
- this.defaultBgColor.b,
2034
- COLOR_CHANNEL_MAX
2035
- );
1976
+ this.setDrawColor(this.defaultBgColor);
2036
1977
  this.sdl.setRenderTarget(this.renderer, this.renderTarget);
2037
1978
  this.sdl.renderClear(this.renderer);
2038
1979
  this.sdl.setRenderTarget(this.renderer, null);
@@ -2130,13 +2071,7 @@ var SdlUiRenderer = class {
2130
2071
  this.renderText(cmd);
2131
2072
  break;
2132
2073
  case "clear_screen":
2133
- this.sdl.setRenderDrawColor(
2134
- this.renderer,
2135
- this.defaultBgColor.r,
2136
- this.defaultBgColor.g,
2137
- this.defaultBgColor.b,
2138
- COLOR_CHANNEL_MAX
2139
- );
2074
+ this.setDrawColor(this.defaultBgColor);
2140
2075
  this.sdl.renderClear(this.renderer);
2141
2076
  this.ansiParser.reset();
2142
2077
  break;
@@ -2200,50 +2135,22 @@ var SdlUiRenderer = class {
2200
2135
  let fg = this.reverse ? this.bgColor : this.fgColor;
2201
2136
  const bg = this.reverse ? this.fgColor : this.bgColor;
2202
2137
  if (this.bold) {
2203
- fg = {
2204
- r: Math.min(
2205
- COLOR_CHANNEL_MAX,
2206
- Math.floor(fg.r * BOLD_BRIGHTNESS_MULTIPLIER)
2207
- ),
2208
- g: Math.min(
2209
- COLOR_CHANNEL_MAX,
2210
- Math.floor(fg.g * BOLD_BRIGHTNESS_MULTIPLIER)
2211
- ),
2212
- b: Math.min(
2213
- COLOR_CHANNEL_MAX,
2214
- Math.floor(fg.b * BOLD_BRIGHTNESS_MULTIPLIER)
2215
- )
2216
- };
2138
+ fg = adjustBrightness(fg, BOLD_BRIGHTNESS_MULTIPLIER);
2217
2139
  }
2218
2140
  if (this.dim) {
2219
- fg = {
2220
- r: Math.floor(fg.r * DIM_BRIGHTNESS_MULTIPLIER),
2221
- g: Math.floor(fg.g * DIM_BRIGHTNESS_MULTIPLIER),
2222
- b: Math.floor(fg.b * DIM_BRIGHTNESS_MULTIPLIER)
2223
- };
2141
+ fg = adjustBrightness(fg, DIM_BRIGHTNESS_MULTIPLIER, false);
2224
2142
  }
2225
2143
  const brightness = Math.max(fg.r, fg.g, fg.b);
2226
2144
  if (brightness < MIN_BRIGHTNESS) {
2227
2145
  if (brightness === 0) {
2228
2146
  fg = { r: MIN_BRIGHTNESS, g: MIN_BRIGHTNESS, b: MIN_BRIGHTNESS };
2229
2147
  } else {
2230
- const scale = MIN_BRIGHTNESS / brightness;
2231
- fg = {
2232
- r: Math.min(COLOR_CHANNEL_MAX, Math.floor(fg.r * scale)),
2233
- g: Math.min(COLOR_CHANNEL_MAX, Math.floor(fg.g * scale)),
2234
- b: Math.min(COLOR_CHANNEL_MAX, Math.floor(fg.b * scale))
2235
- };
2148
+ fg = adjustBrightness(fg, MIN_BRIGHTNESS / brightness);
2236
2149
  }
2237
2150
  }
2238
2151
  const textWidth = text.length * this.charWidth;
2239
2152
  const bgRect = createSDLRect(x, y, textWidth, this.charHeight);
2240
- this.sdl.setRenderDrawColor(
2241
- this.renderer,
2242
- bg.r,
2243
- bg.g,
2244
- bg.b,
2245
- COLOR_CHANNEL_MAX
2246
- );
2153
+ this.setDrawColor(bg);
2247
2154
  this.sdl.renderFillRect(this.renderer, bgRect);
2248
2155
  this.textRenderer.renderText(text, x, y, fg, this.italic);
2249
2156
  if (this.underline || this.strikethrough) {
@@ -2251,13 +2158,7 @@ var SdlUiRenderer = class {
2251
2158
  1,
2252
2159
  Math.round(this.charHeight * TEXT_DECORATION_THICKNESS)
2253
2160
  );
2254
- this.sdl.setRenderDrawColor(
2255
- this.renderer,
2256
- fg.r,
2257
- fg.g,
2258
- fg.b,
2259
- COLOR_CHANNEL_MAX
2260
- );
2161
+ this.setDrawColor(fg);
2261
2162
  if (this.underline) {
2262
2163
  const underlineY = y + Math.round(this.charHeight * UNDERLINE_POSITION);
2263
2164
  const underlineRect = createSDLRect(
@@ -2283,16 +2184,22 @@ var SdlUiRenderer = class {
2283
2184
  return;
2284
2185
  }
2285
2186
  this.sdl.setRenderTarget(this.renderer, this.renderTarget);
2187
+ this.setDrawColor(this.defaultBgColor);
2188
+ this.sdl.renderClear(this.renderer);
2189
+ this.sdl.setRenderTarget(this.renderer, null);
2190
+ this.ansiParser.reset();
2191
+ }
2192
+ /**
2193
+ * Set the SDL render draw color
2194
+ */
2195
+ setDrawColor(color) {
2286
2196
  this.sdl.setRenderDrawColor(
2287
2197
  this.renderer,
2288
- this.defaultBgColor.r,
2289
- this.defaultBgColor.g,
2290
- this.defaultBgColor.b,
2198
+ color.r,
2199
+ color.g,
2200
+ color.b,
2291
2201
  COLOR_CHANNEL_MAX
2292
2202
  );
2293
- this.sdl.renderClear(this.renderer);
2294
- this.sdl.setRenderTarget(this.renderer, null);
2295
- this.ansiParser.reset();
2296
2203
  }
2297
2204
  /**
2298
2205
  * Clear a line from a specific position
@@ -2306,13 +2213,7 @@ var SdlUiRenderer = class {
2306
2213
  const drawable = this.sdl.getDrawableSize(this.window);
2307
2214
  const clearWidth = drawable.width - x;
2308
2215
  const rect = createSDLRect(x, y, clearWidth, this.charHeight);
2309
- this.sdl.setRenderDrawColor(
2310
- this.renderer,
2311
- this.bgColor.r,
2312
- this.bgColor.g,
2313
- this.bgColor.b,
2314
- COLOR_CHANNEL_MAX
2315
- );
2216
+ this.setDrawColor(this.bgColor);
2316
2217
  this.sdl.renderFillRect(this.renderer, rect);
2317
2218
  }
2318
2219
  /**
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createSdlStreams
4
- } from "./chunk-BOQYTA3S.js";
4
+ } from "./chunk-YE6CUIKT.js";
5
5
 
6
6
  // src/cli.tsx
7
7
  import { parseArgs } from "util";
package/dist/index.d.ts CHANGED
@@ -334,6 +334,10 @@ declare class SdlUiRenderer {
334
334
  * Clear the entire screen
335
335
  */
336
336
  clear(): void;
337
+ /**
338
+ * Set the SDL render draw color
339
+ */
340
+ private setDrawColor;
337
341
  /**
338
342
  * Clear a line from a specific position
339
343
  */
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  isSdl2Available,
16
16
  isSdlAvailable,
17
17
  isSdlTtfAvailable
18
- } from "./chunk-BOQYTA3S.js";
18
+ } from "./chunk-YE6CUIKT.js";
19
19
  export {
20
20
  AnsiParser,
21
21
  InputBridge,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ink-sdl",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Render Ink terminal apps in native SDL windows",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",