@chrtco/sdk 0.10.46 → 0.10.47

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.
@@ -1,5 +1,5 @@
1
1
  import maplibregl from 'maplibre-gl';
2
- import { C as ColorTableName, f as SymbolFamily } from '../symbol-families-D2Kx20HJ.cjs';
2
+ import { C as ColorTableName, j as SymbolFamily } from '../symbol-families-De7sN-p5.cjs';
3
3
 
4
4
  /**
5
5
  * Every style image a chart registers for one palette and symbol family, as
@@ -1,5 +1,5 @@
1
1
  import maplibregl from 'maplibre-gl';
2
- import { C as ColorTableName, f as SymbolFamily } from '../symbol-families-D2Kx20HJ.js';
2
+ import { C as ColorTableName, j as SymbolFamily } from '../symbol-families-De7sN-p5.js';
3
3
 
4
4
  /**
5
5
  * Every style image a chart registers for one palette and symbol family, as
@@ -1,4 +1,10 @@
1
1
  // src/atlas/s52-colors.ts
2
+ var EINK_MONO_GREYS = {
3
+ INK: "#000000",
4
+ DARK: "#555555",
5
+ MID: "#aaaaaa",
6
+ PAPER: "#ffffff"
7
+ };
2
8
  var S52_DAY = {
3
9
  // Depth
4
10
  NODTA: "#a4a4a4",
@@ -279,10 +285,234 @@ var S52_NIGHT = {
279
285
  RES02: "#383028",
280
286
  RES03: "#383028"
281
287
  };
288
+ var S52_EINK_COLOR = {
289
+ NODTA: "#b4b4b4",
290
+ DEPIT: "#4f8f3a",
291
+ DEPVS: "#74ade0",
292
+ DEPMS: "#bad6ef",
293
+ DEPMD: "#ffffff",
294
+ DEPDW: "#ffffff",
295
+ LANDA: "#f2e2b0",
296
+ LANDF: "#c49a4a",
297
+ CHBRN: "#8b5a2b",
298
+ CHGRF: "#9a9a9a",
299
+ CHGRD: "#444444",
300
+ CHBLK: "#000000",
301
+ CSTLN: "#000000",
302
+ OUTLW: "#000000",
303
+ BKAJ1: "#333333",
304
+ TRFCD: "#c800c8",
305
+ TRFCF: "#c800c8",
306
+ RESBL: "#0050c8",
307
+ APTS1: "#c800c8",
308
+ DNGHL: "#e00000",
309
+ ISHDG: "#e00000",
310
+ LITRD: "#e00000",
311
+ LITGN: "#00a000",
312
+ LITYW: "#f0c000",
313
+ LITWT: "#ffffff",
314
+ LITBL: "#0050c8",
315
+ LITOR: "#f07000",
316
+ RADHI: "#00a000",
317
+ RADLO: "#006000",
318
+ PLRTE: "#e00000",
319
+ ARPAT: "#008040",
320
+ ISDNG: "#c800c8",
321
+ CHRED: "#e00000",
322
+ CHGRN: "#00a000",
323
+ CHYLW: "#f0c000",
324
+ CHMGD: "#c800c8",
325
+ CHMGF: "#c800c8",
326
+ CHWHT: "#ffffff",
327
+ CHCOR: "#f07000",
328
+ // Deeper-than-safety soundings: dark grey, the one secondary ink. Shoal
329
+ // soundings are black — the louder numeral, as in every other table.
330
+ SNDG1: "#555555",
331
+ SNDG2: "#000000",
332
+ DEPSC: "#000000",
333
+ DEPCN: "#555555",
334
+ UINFD: "#000000",
335
+ UINFF: "#555555",
336
+ UINFR: "#e00000",
337
+ UINFG: "#00a000",
338
+ UINFO: "#f07000",
339
+ UINFB: "#0050c8",
340
+ UINFM: "#c800c8",
341
+ UIBCK: "#ffffff",
342
+ UIBDR: "#555555",
343
+ UIAFD: "#74ade0",
344
+ UIAFF: "#c49a4a",
345
+ PIPLN: "#008000",
346
+ OUTLL: "#c49a4a",
347
+ SCLBR: "#f07000",
348
+ NINFO: "#f07000",
349
+ ADINF: "#b08800",
350
+ RESGR: "#555555",
351
+ SHIPS: "#000000",
352
+ PSTRK: "#000000",
353
+ SYTRK: "#555555",
354
+ APLRT: "#f07000",
355
+ CURSR: "#f07000",
356
+ BKAJ2: "#000000",
357
+ RES01: "#808080",
358
+ RES02: "#808080",
359
+ RES03: "#808080"
360
+ };
361
+ var M = EINK_MONO_GREYS;
362
+ var S52_EINK_MONO = {
363
+ // No data is DARK, never the land tone: a no-data edge in the land tone
364
+ // reads as a coastline (seen on the Boston render, 2026-10-05).
365
+ NODTA: M.DARK,
366
+ DEPIT: M.PAPER,
367
+ DEPVS: M.PAPER,
368
+ DEPMS: M.PAPER,
369
+ DEPMD: M.PAPER,
370
+ DEPDW: M.PAPER,
371
+ LANDA: M.MID,
372
+ LANDF: M.DARK,
373
+ CHBRN: M.DARK,
374
+ CHGRF: M.MID,
375
+ CHGRD: M.DARK,
376
+ CHBLK: M.INK,
377
+ CSTLN: M.INK,
378
+ OUTLW: M.INK,
379
+ BKAJ1: M.DARK,
380
+ TRFCD: M.INK,
381
+ TRFCF: M.INK,
382
+ RESBL: M.INK,
383
+ APTS1: M.INK,
384
+ DNGHL: M.INK,
385
+ ISHDG: M.INK,
386
+ LITRD: M.INK,
387
+ LITGN: M.INK,
388
+ LITYW: M.INK,
389
+ LITWT: M.PAPER,
390
+ LITBL: M.INK,
391
+ LITOR: M.INK,
392
+ RADHI: M.INK,
393
+ RADLO: M.DARK,
394
+ PLRTE: M.INK,
395
+ ARPAT: M.INK,
396
+ ISDNG: M.INK,
397
+ CHRED: M.DARK,
398
+ CHGRN: M.MID,
399
+ CHYLW: M.MID,
400
+ CHMGD: M.INK,
401
+ CHMGF: M.INK,
402
+ CHWHT: M.PAPER,
403
+ CHCOR: M.MID,
404
+ SNDG1: M.DARK,
405
+ SNDG2: M.INK,
406
+ DEPSC: M.INK,
407
+ DEPCN: M.DARK,
408
+ UINFD: M.INK,
409
+ UINFF: M.DARK,
410
+ UINFR: M.INK,
411
+ UINFG: M.INK,
412
+ UINFO: M.INK,
413
+ UINFB: M.INK,
414
+ UINFM: M.INK,
415
+ UIBCK: M.PAPER,
416
+ UIBDR: M.DARK,
417
+ UIAFD: M.MID,
418
+ UIAFF: M.MID,
419
+ PIPLN: M.INK,
420
+ OUTLL: M.DARK,
421
+ SCLBR: M.INK,
422
+ NINFO: M.INK,
423
+ ADINF: M.DARK,
424
+ RESGR: M.DARK,
425
+ SHIPS: M.INK,
426
+ PSTRK: M.INK,
427
+ SYTRK: M.DARK,
428
+ APLRT: M.INK,
429
+ CURSR: M.INK,
430
+ BKAJ2: M.INK,
431
+ RES01: M.DARK,
432
+ RES02: M.DARK,
433
+ RES03: M.DARK
434
+ };
435
+ var N = { GROUND: M.INK, DIM: M.DARK, LINE: M.MID, BRIGHT: M.PAPER };
436
+ var S52_EINK_NIGHT = {
437
+ NODTA: N.GROUND,
438
+ DEPIT: N.GROUND,
439
+ DEPVS: N.GROUND,
440
+ DEPMS: N.GROUND,
441
+ DEPMD: N.GROUND,
442
+ DEPDW: N.GROUND,
443
+ LANDA: N.DIM,
444
+ LANDF: N.LINE,
445
+ CHBRN: N.LINE,
446
+ CHGRF: N.DIM,
447
+ CHGRD: N.LINE,
448
+ CHBLK: N.LINE,
449
+ CSTLN: N.LINE,
450
+ OUTLW: N.LINE,
451
+ BKAJ1: N.DIM,
452
+ TRFCD: N.LINE,
453
+ TRFCF: N.LINE,
454
+ RESBL: N.LINE,
455
+ APTS1: N.LINE,
456
+ DNGHL: N.BRIGHT,
457
+ ISHDG: N.BRIGHT,
458
+ LITRD: N.BRIGHT,
459
+ LITGN: N.BRIGHT,
460
+ LITYW: N.BRIGHT,
461
+ LITWT: N.BRIGHT,
462
+ LITBL: N.BRIGHT,
463
+ LITOR: N.BRIGHT,
464
+ RADHI: N.LINE,
465
+ RADLO: N.DIM,
466
+ PLRTE: N.LINE,
467
+ ARPAT: N.LINE,
468
+ ISDNG: N.BRIGHT,
469
+ // Mark bodies by tone, as in mono, so they stay apart from each other and
470
+ // from the black water; shape still says which side.
471
+ CHRED: N.DIM,
472
+ CHGRN: N.LINE,
473
+ CHYLW: N.LINE,
474
+ CHMGD: N.LINE,
475
+ CHMGF: N.LINE,
476
+ CHWHT: N.BRIGHT,
477
+ CHCOR: N.LINE,
478
+ SNDG1: N.LINE,
479
+ SNDG2: N.BRIGHT,
480
+ DEPSC: N.BRIGHT,
481
+ DEPCN: N.LINE,
482
+ UINFD: N.LINE,
483
+ UINFF: N.DIM,
484
+ UINFR: N.BRIGHT,
485
+ UINFG: N.LINE,
486
+ UINFO: N.LINE,
487
+ UINFB: N.LINE,
488
+ UINFM: N.LINE,
489
+ UIBCK: N.GROUND,
490
+ UIBDR: N.DIM,
491
+ UIAFD: N.DIM,
492
+ UIAFF: N.DIM,
493
+ PIPLN: N.LINE,
494
+ OUTLL: N.DIM,
495
+ SCLBR: N.LINE,
496
+ NINFO: N.LINE,
497
+ ADINF: N.DIM,
498
+ RESGR: N.DIM,
499
+ SHIPS: N.BRIGHT,
500
+ PSTRK: N.LINE,
501
+ SYTRK: N.DIM,
502
+ APLRT: N.BRIGHT,
503
+ CURSR: N.BRIGHT,
504
+ BKAJ2: N.GROUND,
505
+ RES01: N.DIM,
506
+ RES02: N.DIM,
507
+ RES03: N.DIM
508
+ };
282
509
  var COLOR_TABLES = {
283
510
  DAY: S52_DAY,
284
511
  DUSK: S52_DUSK,
285
- NIGHT: S52_NIGHT
512
+ NIGHT: S52_NIGHT,
513
+ EINK_COLOR: S52_EINK_COLOR,
514
+ EINK_MONO: S52_EINK_MONO,
515
+ EINK_NIGHT: S52_EINK_NIGHT
286
516
  };
287
517
  function resolveColor(token, table = "DAY") {
288
518
  const t = COLOR_TABLES[table];
@@ -15617,6 +15847,9 @@ var CHRT_GLYPH_SVGS = {
15617
15847
  "cardinal-w": '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M16 6 12 1.5h8Z" fill="#101418"/><path d="M16 6.5 20 11h-8Z" fill="#101418"/><path d="M13 12h6l1 13H12Z" fill="#FFC805"/><path d="M6 28h20" stroke="#101418" stroke-width="2.4" stroke-linecap="round"/></svg>',
15618
15848
  "daymark-square": '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect x="6" y="6" width="20" height="20" rx="1.5" fill="#fff"/></svg>',
15619
15849
  "daymark-triangle": '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M16 5 28 26H4Z" fill="#fff"/></svg>',
15850
+ "eink-danger": '<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8"><path d="M-2 2 L2 -2 M0 8 L8 0 M6 10 L10 6" stroke="#000000" stroke-width="1" fill="none"/><path d="M-2 6 L2 10 M0 0 L8 8 M6 -2 L10 2" stroke="#000000" stroke-width="1" fill="none"/></svg>',
15851
+ "eink-dots": '<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10"><circle cx="2.5" cy="2.5" r="0.9" fill="#000000"/><circle cx="7.5" cy="7.5" r="0.9" fill="#000000"/></svg>',
15852
+ "eink-hatch": '<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8"><path d="M-2 2 L2 -2 M0 8 L8 0 M6 10 L10 6" stroke="#000000" stroke-width="0.9" fill="none"/></svg>',
15620
15853
  "hatch-nocoverage": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M-3 9 L9 -3 M-3 21 L21 -3 M3 27 L27 3 M15 27 L27 15" stroke="#8A97A0" stroke-width="0.8" fill="none"/><path d="M-3 15 L15 33 M-3 3 L21 27 M3 -3 L27 21 M15 -3 L27 9" stroke="#8A97A0" stroke-width="0.8" fill="none"/></svg>',
15621
15854
  "hatch-uncharted": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M-3 9 L9 -3 M-3 21 L21 -3 M3 27 L27 3 M15 27 L27 15" stroke="#5B7383" stroke-width="0.65" fill="none"/></svg>',
15622
15855
  "isolated-danger": '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><circle cx="16" cy="3.5" r="2.4" fill="#101418"/><circle cx="16" cy="9.5" r="2.4" fill="#101418"/><path d="M13 13h6l1 12H12Z" fill="#101418"/><rect x="12.4" y="17.5" width="7.2" height="3.4" fill="#E5484D"/><path d="M6 28h20" stroke="#101418" stroke-width="2.4" stroke-linecap="round"/></svg>',
@@ -15659,6 +15892,22 @@ function capLuminance(hex, ceiling) {
15659
15892
  }
15660
15893
  var NIGHT_INK = S52_NIGHT.CHBLK;
15661
15894
  var NIGHT_MUTED_INK = scaleLinearLight(S52_NIGHT.CHBLK, 0.43);
15895
+ function einkMonoGrey(hex) {
15896
+ const l = relativeLuminance(hex);
15897
+ const g = EINK_MONO_GREYS;
15898
+ const steps = [g.INK, g.DARK, g.MID, g.PAPER].map((c) => [c, relativeLuminance(c)]);
15899
+ let best = steps[0];
15900
+ for (const step of steps) if (Math.abs(step[1] - l) < Math.abs(best[1] - l)) best = step;
15901
+ return best[0];
15902
+ }
15903
+ function einkNightGrey(hex) {
15904
+ const l = relativeLuminance(hex);
15905
+ const g = EINK_MONO_GREYS;
15906
+ const steps = [g.DARK, g.MID, g.PAPER].map((c) => [c, relativeLuminance(c)]);
15907
+ let best = steps[0];
15908
+ for (const step of steps) if (Math.abs(step[1] - l) < Math.abs(best[1] - l)) best = step;
15909
+ return best[0];
15910
+ }
15662
15911
 
15663
15912
  // src/atlas/chrt-style.ts
15664
15913
  var CHRT_ICON_PREFIX = "chrt:";
@@ -15683,7 +15932,9 @@ var CHRT_SDF_GLYPHS = /* @__PURE__ */ new Set([
15683
15932
  var CHRT_GLYPH_NAMES = new Set(Object.keys(CHRT_GLYPH_SVGS));
15684
15933
  var HOUSE_BLACK = "#101418";
15685
15934
  function chrtHouseColor(dayHex, palette = "DAY") {
15686
- if (palette === "DAY") return dayHex;
15935
+ if (palette === "DAY" || palette === "EINK_COLOR") return dayHex;
15936
+ if (palette === "EINK_MONO") return einkMonoGrey(dayHex);
15937
+ if (palette === "EINK_NIGHT") return dayHex.toLowerCase() === HOUSE_BLACK.toLowerCase() || dayHex.toLowerCase() === "#000000" ? "#aaaaaa" : einkNightGrey(dayHex);
15687
15938
  const isBlack = dayHex.toLowerCase() === HOUSE_BLACK.toLowerCase();
15688
15939
  if (palette === "DUSK") {
15689
15940
  return isBlack ? dayHex : capLuminance(dayHex, relativeLuminance(resolveColor("CHBLK", "DUSK")));
@@ -15691,7 +15942,7 @@ function chrtHouseColor(dayHex, palette = "DAY") {
15691
15942
  return isBlack ? NIGHT_INK : capLuminance(dayHex, relativeLuminance(NIGHT_MUTED_INK));
15692
15943
  }
15693
15944
  function themeChrtGlyph(svg2, palette = "DAY") {
15694
- if (palette === "DAY") return svg2;
15945
+ if (palette === "DAY" || palette === "EINK_COLOR") return svg2;
15695
15946
  return svg2.replace(
15696
15947
  /(fill|stroke)="(#[0-9a-fA-F]{3}|#[0-9a-fA-F]{6})"/g,
15697
15948
  (_m, attr, hex) => {
@@ -15702,6 +15953,7 @@ function themeChrtGlyph(svg2, palette = "DAY") {
15702
15953
  }
15703
15954
 
15704
15955
  // src/atlas/base-layers.ts
15956
+ var NOCOVERAGE_PATTERN = "chrt:hatch-nocoverage";
15705
15957
  var UNCHARTED_PATTERN = "chrt:hatch-uncharted";
15706
15958
  function inlandHatchColor(palette) {
15707
15959
  return (BASE_THEMES[palette] ?? BASE_THEMES.DAY).inlandHatch;
@@ -15712,6 +15964,9 @@ function basePatternSvg(name, palette) {
15712
15964
  if (`${CHRT_ICON_PREFIX}${name}` === UNCHARTED_PATTERN) {
15713
15965
  return raw.replace(/stroke="#[0-9a-fA-F]{3,6}"/g, `stroke="${inlandHatchColor(palette)}"`);
15714
15966
  }
15967
+ if (palette === "EINK_NIGHT" && `${CHRT_ICON_PREFIX}${name}` === NOCOVERAGE_PATTERN) {
15968
+ return raw.replace(/stroke="#[0-9a-fA-F]{3,6}"/g, `stroke="#555555"`);
15969
+ }
15715
15970
  return themeChrtGlyph(raw, palette);
15716
15971
  }
15717
15972
  var BASE_THEMES = {
@@ -15818,6 +16073,65 @@ var BASE_THEMES = {
15818
16073
  inlandShore: "#1C2227",
15819
16074
  inlandLabel: "#617484",
15820
16075
  inlandHalo: "#232A30"
16076
+ },
16077
+ // ── E-ink: uncharted is DARK, never paper ─────────────────────────────
16078
+ // On an e-ink chart, charted safe water is paper. Water outside coverage
16079
+ // must never read as that, so it is the darkest fill on the page — the
16080
+ // e-ink twin of DAY's dark carto — with the no-coverage crosshatch over it
16081
+ // (invariant 5: the coverage portrayal survives). Land outside coverage
16082
+ // keeps the chart's own land tone.
16083
+ EINK_COLOR: {
16084
+ earth: "#d8ccb0",
16085
+ water: "#4f5a62",
16086
+ river: "#4f5a62",
16087
+ boundary: "#000000",
16088
+ jurisdiction: "#f2e2b0",
16089
+ inlandWater: "#c8d6e0",
16090
+ // The house stripe, 3.4:1 on this rough water — strong enough for the
16091
+ // 150 ppi colour layer.
16092
+ inlandHatch: "#5B7383",
16093
+ stateLine: "#555555",
16094
+ stateLabel: "#000000",
16095
+ stateHalo: "#ffffff",
16096
+ inlandShore: "#555555",
16097
+ inlandLabel: "#000000",
16098
+ inlandHalo: "#ffffff"
16099
+ },
16100
+ // Mono: the same rule in the four greys. Uncharted water DARK under a MID
16101
+ // crosshatch; land MID; rough inland water PAPER under the uncharted hatch.
16102
+ EINK_MONO: {
16103
+ earth: "#aaaaaa",
16104
+ water: "#555555",
16105
+ river: "#555555",
16106
+ boundary: "#000000",
16107
+ jurisdiction: "#aaaaaa",
16108
+ inlandWater: "#ffffff",
16109
+ inlandHatch: "#555555",
16110
+ stateLine: "#555555",
16111
+ stateLabel: "#000000",
16112
+ stateHalo: "#ffffff",
16113
+ inlandShore: "#555555",
16114
+ inlandLabel: "#000000",
16115
+ inlandHalo: "#ffffff"
16116
+ },
16117
+ // Night: the inverse. Water outside coverage is the black ground UNDER the
16118
+ // light crosshatch — charted safe water is plain black, so the hatch is what
16119
+ // tells them apart, here as everywhere. Land the DIM grey; labels the line
16120
+ // grey on black.
16121
+ EINK_NIGHT: {
16122
+ earth: "#555555",
16123
+ water: "#000000",
16124
+ river: "#000000",
16125
+ boundary: "#aaaaaa",
16126
+ jurisdiction: "#555555",
16127
+ inlandWater: "#000000",
16128
+ inlandHatch: "#aaaaaa",
16129
+ stateLine: "#aaaaaa",
16130
+ stateLabel: "#aaaaaa",
16131
+ stateHalo: "#000000",
16132
+ inlandShore: "#aaaaaa",
16133
+ inlandLabel: "#aaaaaa",
16134
+ inlandHalo: "#000000"
15821
16135
  }
15822
16136
  };
15823
16137
 
@@ -16378,10 +16692,20 @@ var S101_NIGHT = {
16378
16692
  // src/atlas/s101-style.ts
16379
16693
  var S101_ICON_PREFIX = "s101:";
16380
16694
  var S101_SYMBOL_NAMES = new Set(Object.keys(S101_POINT_SVGS));
16695
+ function s101EinkTable(einkS52, fallback) {
16696
+ const out = {};
16697
+ for (const [token, dayHex] of Object.entries(S101_DAY)) {
16698
+ out[token] = einkS52[token] ?? fallback(dayHex);
16699
+ }
16700
+ return out;
16701
+ }
16381
16702
  var S101_TABLES = {
16382
16703
  DAY: S101_DAY,
16383
16704
  DUSK: S101_DUSK,
16384
- NIGHT: S101_NIGHT
16705
+ NIGHT: S101_NIGHT,
16706
+ EINK_COLOR: s101EinkTable(S52_EINK_COLOR, (hex) => hex),
16707
+ EINK_MONO: s101EinkTable(S52_EINK_MONO, einkMonoGrey),
16708
+ EINK_NIGHT: s101EinkTable(S52_EINK_NIGHT, einkNightGrey)
16385
16709
  };
16386
16710
  var warnedTokens = /* @__PURE__ */ new Set();
16387
16711
  function reportUnresolvedToken(token, table) {
@@ -16406,7 +16730,17 @@ function getThemedS101Svg(symbolName, table = "DAY") {
16406
16730
 
16407
16731
  // src/atlas/symbol-image-specs.ts
16408
16732
  var SUPERSAMPLE = 2;
16409
- var BASE_PATTERN_GLYPHS = ["hatch-nocoverage", "hatch-uncharted"];
16733
+ var BASE_PATTERN_GLYPHS = [
16734
+ "hatch-nocoverage",
16735
+ "hatch-uncharted",
16736
+ // The e-ink fill patterns (`eink-portrayal.ts`). Only the e-ink palettes
16737
+ // reference them, but they are registered with the hatches in every palette
16738
+ // so a client switching INTO e-ink never draws a pattern-less fill while a
16739
+ // late image load catches up. Three 8 px tiles.
16740
+ "eink-dots",
16741
+ "eink-hatch",
16742
+ "eink-danger"
16743
+ ];
16410
16744
  function upsample(svg2) {
16411
16745
  return svg2.replace(
16412
16746
  /width="(\d+)" height="(\d+)"/,