@basiclines/rampa 1.3.0 → 1.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.
Files changed (2) hide show
  1. package/dist/index.js +177 -58
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -9869,8 +9869,32 @@ function isValidOutputFormat(format) {
9869
9869
  }
9870
9870
 
9871
9871
  // src/formatters/json.ts
9872
- function formatJson(ramps) {
9873
- return JSON.stringify({ ramps }, null, 2);
9872
+ function structuredColor(hex6, format) {
9873
+ const c4 = chroma_js_default(hex6);
9874
+ const [r4, g3, b2] = c4.rgb();
9875
+ const [hh, ss, ll] = c4.hsl();
9876
+ const [ol, oc, oh] = c4.oklch();
9877
+ const all = {
9878
+ hex: c4.hex(),
9879
+ rgb: { r: r4, g: g3, b: b2 },
9880
+ hsl: { h: Math.round(hh || 0), s: Math.round(ss * 100), l: Math.round(ll * 100) },
9881
+ oklch: { l: parseFloat((ol * 100).toFixed(1)), c: parseFloat(oc.toFixed(3)), h: Math.round(oh || 0) }
9882
+ };
9883
+ if (format) {
9884
+ return { [format]: all[format] };
9885
+ }
9886
+ return all;
9887
+ }
9888
+ function formatJson(ramps, format) {
9889
+ const output = {
9890
+ ramps: ramps.map((ramp) => ({
9891
+ name: ramp.name,
9892
+ baseColor: ramp.baseColor,
9893
+ config: ramp.config,
9894
+ colors: (ramp.rawColors || ramp.colors).map((c4) => structuredColor(c4, format))
9895
+ }))
9896
+ };
9897
+ return JSON.stringify(output, null, 2);
9874
9898
  }
9875
9899
 
9876
9900
  // src/formatters/css.ts
@@ -10229,7 +10253,8 @@ function formatAccessibilityCss(report) {
10229
10253
  }
10230
10254
 
10231
10255
  // src/index.ts
10232
- if (process.argv.includes("--help") || process.argv.includes("-h")) {
10256
+ var args = process.argv.slice(2);
10257
+ if (args.includes("--help") || args.includes("-h") || args.includes("help") || args.length === 0) {
10233
10258
  showHelp();
10234
10259
  }
10235
10260
  function showHelp() {
@@ -10237,7 +10262,7 @@ function showHelp() {
10237
10262
  const dim = "\x1B[2m";
10238
10263
  const reset = "\x1B[0m";
10239
10264
  const help = `
10240
- rampa v1.2.0
10265
+ rampa v1.4.0
10241
10266
  Generate mathematically accurate color palettes from a base color
10242
10267
 
10243
10268
  USAGE
@@ -10246,7 +10271,11 @@ USAGE
10246
10271
  BASE
10247
10272
  ${cyan}-C, --color <color>${reset} ${dim}Base color (required)${reset}
10248
10273
  ${cyan}--size <number>${reset} ${dim}Number of colors in palette (2-100, default: 10)${reset}
10249
- ${cyan}-F, --format <type>${reset} ${dim}Color format: hex, hsl, rgb, oklch (default: auto)${reset}
10274
+
10275
+ FORMAT
10276
+ ${cyan}-F, --format <type>${reset} ${dim}Color format for output values (default: same as input)${reset}
10277
+
10278
+ ${dim}Types: hex, hsl, rgb, oklch${reset}
10250
10279
 
10251
10280
  RANGES
10252
10281
  ${cyan}-L, --lightness <start:end>${reset} ${dim}Lightness range 0-100 (default: 0:100)${reset}
@@ -10279,27 +10308,44 @@ HARMONIES
10279
10308
 
10280
10309
  OUTPUT
10281
10310
  ${cyan}-O, --output <format>${reset} ${dim}Output format (default: text)${reset}
10311
+
10312
+ ${dim}Formats: text, json, css${reset}
10313
+
10282
10314
  ${cyan}--preview / --no-preview${reset} ${dim}Show colored squares (default: true)${reset}
10283
- ${cyan}-A, --accessibility [filter]${reset} ${dim}Show APCA contrast report${reset}
10315
+
10316
+ ACCESSIBILITY
10317
+ ${cyan}-A, --accessibility [filter]${reset} ${dim}Show APCA contrast report${reset}
10284
10318
 
10285
10319
  ${dim}Filters: preferred, body, large, bold, minimum, nontext${reset}
10286
10320
  ${dim}or a custom Lc value (e.g. 60)${reset}
10287
10321
 
10288
- ${dim}Formats: text, json, css${reset}
10322
+ COLOR CONVERSION
10323
+ ${cyan}--read-only${reset} ${dim}Output the input color without generating a ramp${reset}
10324
+
10325
+ ${dim}Use with --color to specify the input color.${reset}
10326
+ ${dim}Use with --format to convert to a specific format.${reset}
10327
+ ${dim}Use with --output to choose text, json, or css.${reset}
10328
+
10329
+ ${dim}Without --format: outputs all formats (hex, hsl, rgb, oklch)${reset}
10330
+ ${dim}With --format: outputs only the specified format${reset}
10331
+ ${dim}JSON output returns structured values, not strings${reset}
10289
10332
 
10290
10333
  OTHER
10291
10334
  ${cyan}-h, --help${reset} ${dim}Show this help${reset}
10292
10335
  ${cyan}-v, --version${reset} ${dim}Show version${reset}
10293
10336
 
10294
10337
  EXAMPLES
10295
- ${cyan}rampa -C "#3b82f6"${reset}
10296
- ${cyan}rampa -C "#3b82f6" --size=5 -L 10:90${reset}
10297
- ${cyan}rampa -C "#3b82f6" --add=complementary --add=triadic${reset}
10298
- ${cyan}rampa -C "#3b82f6" --add=shift:45 --add=shift:90${reset}
10299
- ${cyan}rampa -C "#3b82f6" -O css${reset}
10300
- ${cyan}rampa -C "#3b82f6" --tint-color="#FF0000" --tint-opacity=15${reset}
10301
- ${cyan}rampa -C "#3b82f6" -A${reset}
10302
- ${cyan}rampa -C "#3b82f6" --add=complementary -O json -A${reset}
10338
+ ${cyan}rampa --color "#3b82f6"${reset}
10339
+ ${cyan}rampa --color "#3b82f6" --size=5 --lightness 10:90${reset}
10340
+ ${cyan}rampa --color "#3b82f6" --add=complementary --add=triadic${reset}
10341
+ ${cyan}rampa --color "#3b82f6" --add=shift:45 --add=shift:90${reset}
10342
+ ${cyan}rampa --color "#3b82f6" --output css${reset}
10343
+ ${cyan}rampa --color "#3b82f6" --tint-color="#FF0000" --tint-opacity=15${reset}
10344
+ ${cyan}rampa --color "#3b82f6" --accessibility${reset}
10345
+ ${cyan}rampa --color "#3b82f6" --add=complementary --output json --accessibility${reset}
10346
+ ${cyan}rampa --color "#fe0000" --read-only${reset}
10347
+ ${cyan}rampa --color "#fe0000" --read-only --format hsl${reset}
10348
+ ${cyan}rampa --color "#fe0000" --read-only --format hsl --output json${reset}
10303
10349
  `;
10304
10350
  console.log(help.trim());
10305
10351
  process.exit(0);
@@ -10458,6 +10504,19 @@ Examples:
10458
10504
  rampa -C "#3b82f6" -A=large
10459
10505
  rampa -C "#3b82f6" --accessibility=75
10460
10506
  rampa -C "#3b82f6" -O json -A preferred
10507
+ `,
10508
+ "read-only": `
10509
+ --read-only Output the input color converted to the target format (no ramp)
10510
+
10511
+ When --format is specified, outputs the color in that format.
10512
+ When --format is omitted, outputs all formats (hex, hsl, rgb, oklch).
10513
+
10514
+ Examples:
10515
+ rampa -C "#fe0000" --read-only
10516
+ rampa -C "#fe0000" --read-only -F hsl
10517
+ rampa -C "#fe0000" --read-only -O json
10518
+ rampa -C "#fe0000" --read-only -O json -F hsl
10519
+ rampa -C "#fe0000" --read-only -O css -F rgb
10461
10520
  `
10462
10521
  };
10463
10522
  function showFlagHelp(flag) {
@@ -10496,11 +10555,23 @@ function formatColor2(color, format) {
10496
10555
  return c4.hex();
10497
10556
  }
10498
10557
  }
10558
+ function formatColorStructured(color) {
10559
+ const c4 = chroma_js_default(color);
10560
+ const [r4, g3, b2] = c4.rgb();
10561
+ const [hh, ss, ll] = c4.hsl();
10562
+ const [ol, oc, oh] = c4.oklch();
10563
+ return {
10564
+ hex: c4.hex(),
10565
+ rgb: { r: r4, g: g3, b: b2 },
10566
+ hsl: { h: Math.round(hh || 0), s: Math.round(ss * 100), l: Math.round(ll * 100) },
10567
+ oklch: { l: parseFloat((ol * 100).toFixed(1)), c: parseFloat(oc.toFixed(3)), h: Math.round(oh || 0) }
10568
+ };
10569
+ }
10499
10570
  var validFormats = ["hex", "hsl", "rgb", "oklch"];
10500
10571
  var main = defineCommand({
10501
10572
  meta: {
10502
10573
  name: "rampa",
10503
- version: "1.3.0",
10574
+ version: "1.4.0",
10504
10575
  description: "Generate mathematically accurate color palettes from a base color"
10505
10576
  },
10506
10577
  args: {
@@ -10586,79 +10657,123 @@ var main = defineCommand({
10586
10657
  type: "string",
10587
10658
  alias: ["A", "a"],
10588
10659
  description: "Show APCA contrast report. Optional: filter by level name or Lc value"
10660
+ },
10661
+ "read-only": {
10662
+ type: "boolean",
10663
+ description: "Output the input color converted to the target format without generating a ramp",
10664
+ default: false
10589
10665
  }
10590
10666
  },
10591
- run({ args }) {
10592
- if (needsHelp(args.size) && args.size !== "10")
10667
+ run({ args: args2 }) {
10668
+ if (needsHelp(args2.size) && args2.size !== "10")
10593
10669
  showFlagHelp("size");
10594
- if (args.format !== undefined && needsHelp(args.format))
10670
+ if (args2.format !== undefined && needsHelp(args2.format))
10595
10671
  showFlagHelp("format");
10596
- if (needsHelp(args.lightness) && args.lightness !== "0:100")
10672
+ if (needsHelp(args2.lightness) && args2.lightness !== "0:100")
10597
10673
  showFlagHelp("lightness");
10598
- if (needsHelp(args.saturation) && args.saturation !== "100:0")
10674
+ if (needsHelp(args2.saturation) && args2.saturation !== "100:0")
10599
10675
  showFlagHelp("saturation");
10600
- if (needsHelp(args.hue) && args.hue !== "-10:10")
10676
+ if (needsHelp(args2.hue) && args2.hue !== "-10:10")
10601
10677
  showFlagHelp("hue");
10602
- if (needsHelp(args["lightness-scale"]) && args["lightness-scale"] !== "linear")
10678
+ if (needsHelp(args2["lightness-scale"]) && args2["lightness-scale"] !== "linear")
10603
10679
  showFlagHelp("lightness-scale");
10604
- if (needsHelp(args["saturation-scale"]) && args["saturation-scale"] !== "linear")
10680
+ if (needsHelp(args2["saturation-scale"]) && args2["saturation-scale"] !== "linear")
10605
10681
  showFlagHelp("saturation-scale");
10606
- if (needsHelp(args["hue-scale"]) && args["hue-scale"] !== "linear")
10682
+ if (needsHelp(args2["hue-scale"]) && args2["hue-scale"] !== "linear")
10607
10683
  showFlagHelp("hue-scale");
10608
- if (args["tint-color"] !== undefined && needsHelp(args["tint-color"]))
10684
+ if (args2["tint-color"] !== undefined && needsHelp(args2["tint-color"]))
10609
10685
  showFlagHelp("tint-color");
10610
- if (needsHelp(args["tint-opacity"]) && args["tint-opacity"] !== "0")
10686
+ if (needsHelp(args2["tint-opacity"]) && args2["tint-opacity"] !== "0")
10611
10687
  showFlagHelp("tint-opacity");
10612
- if (needsHelp(args["tint-blend"]) && args["tint-blend"] !== "normal")
10688
+ if (needsHelp(args2["tint-blend"]) && args2["tint-blend"] !== "normal")
10613
10689
  showFlagHelp("tint-blend");
10614
- if (args.add !== undefined && needsHelp(args.add))
10690
+ if (args2.add !== undefined && needsHelp(args2.add))
10615
10691
  showFlagHelp("add");
10616
- if (needsHelp(args.output) && args.output !== "text")
10692
+ if (needsHelp(args2.output) && args2.output !== "text")
10617
10693
  showFlagHelp("output");
10618
- const detectedFormat = detectColorFormat(args.color);
10694
+ const detectedFormat = detectColorFormat(args2.color);
10619
10695
  let validatedColor;
10620
10696
  try {
10621
- validatedColor = chroma_js_default(args.color).hex();
10697
+ validatedColor = chroma_js_default(args2.color).hex();
10622
10698
  } catch {
10623
10699
  showFlagHelp("color");
10624
10700
  }
10625
- const size = parseInt(args.size, 10);
10701
+ const size = parseInt(args2.size, 10);
10626
10702
  if (isNaN(size) || size < 2 || size > 100) {
10627
- console.error(`Error: Size must be a number between 2 and 100, got "${args.size}"
10703
+ console.error(`Error: Size must be a number between 2 and 100, got "${args2.size}"
10628
10704
  `);
10629
10705
  showFlagHelp("size");
10630
10706
  }
10631
- const outputFormat = args.format?.toLowerCase() || detectedFormat;
10632
- if (!validFormats.includes(outputFormat)) {
10633
- console.error(`Error: Invalid format "${args.format}"
10707
+ const outputFormat = args2.format?.toLowerCase() || detectedFormat;
10708
+ if (args2.format && !validFormats.includes(outputFormat)) {
10709
+ console.error(`Error: Invalid format "${args2.format}"
10634
10710
  `);
10635
10711
  showFlagHelp("format");
10636
10712
  }
10713
+ if (args2["read-only"]) {
10714
+ const outputType2 = args2.output;
10715
+ if (!isValidOutputFormat(outputType2)) {
10716
+ console.error(`Error: Invalid output format "${outputType2}"
10717
+ `);
10718
+ showFlagHelp("output");
10719
+ }
10720
+ const hasExplicitFormat = !!args2.format;
10721
+ if (hasExplicitFormat) {
10722
+ const converted = formatColor2(validatedColor, outputFormat);
10723
+ if (outputType2 === "json") {
10724
+ const structured = formatColorStructured(validatedColor);
10725
+ console.log(JSON.stringify({ color: { value: converted, [outputFormat]: structured[outputFormat] } }, null, 2));
10726
+ } else if (outputType2 === "css") {
10727
+ console.log(`:root {
10728
+ --color: ${converted};
10729
+ }`);
10730
+ } else {
10731
+ console.log(converted);
10732
+ }
10733
+ } else {
10734
+ if (outputType2 === "json") {
10735
+ console.log(JSON.stringify({ color: formatColorStructured(validatedColor) }, null, 2));
10736
+ } else if (outputType2 === "css") {
10737
+ const lines = [":root {"];
10738
+ for (const fmt of validFormats) {
10739
+ lines.push(` --color-${fmt}: ${formatColor2(validatedColor, fmt)};`);
10740
+ }
10741
+ lines.push("}");
10742
+ console.log(lines.join(`
10743
+ `));
10744
+ } else {
10745
+ for (const fmt of validFormats) {
10746
+ console.log(`${fmt}: ${formatColor2(validatedColor, fmt)}`);
10747
+ }
10748
+ }
10749
+ }
10750
+ return;
10751
+ }
10637
10752
  let lightness, saturation, hue3;
10638
10753
  try {
10639
- lightness = parsePercentRange(args.lightness, "lightness");
10754
+ lightness = parsePercentRange(args2.lightness, "lightness");
10640
10755
  } catch (e4) {
10641
10756
  console.error(`Error: ${e4.message}
10642
10757
  `);
10643
10758
  showFlagHelp("lightness");
10644
10759
  }
10645
10760
  try {
10646
- saturation = parsePercentRange(args.saturation, "saturation");
10761
+ saturation = parsePercentRange(args2.saturation, "saturation");
10647
10762
  } catch (e4) {
10648
10763
  console.error(`Error: ${e4.message}
10649
10764
  `);
10650
10765
  showFlagHelp("saturation");
10651
10766
  }
10652
10767
  try {
10653
- hue3 = parseHueRange(args.hue);
10768
+ hue3 = parseHueRange(args2.hue);
10654
10769
  } catch (e4) {
10655
10770
  console.error(`Error: ${e4.message}
10656
10771
  `);
10657
10772
  showFlagHelp("hue");
10658
10773
  }
10659
- const lightnessScale = args["lightness-scale"];
10660
- const saturationScale = args["saturation-scale"];
10661
- const hueScale = args["hue-scale"];
10774
+ const lightnessScale = args2["lightness-scale"];
10775
+ const saturationScale = args2["saturation-scale"];
10776
+ const hueScale = args2["hue-scale"];
10662
10777
  if (!isValidScaleType(lightnessScale)) {
10663
10778
  console.error(`Error: Invalid lightness-scale "${lightnessScale}"
10664
10779
  `);
@@ -10674,9 +10789,9 @@ var main = defineCommand({
10674
10789
  `);
10675
10790
  showFlagHelp("hue-scale");
10676
10791
  }
10677
- const tintColor = args["tint-color"];
10678
- const tintOpacity = parseInt(args["tint-opacity"], 10);
10679
- const tintBlend = args["tint-blend"];
10792
+ const tintColor = args2["tint-color"];
10793
+ const tintOpacity = parseInt(args2["tint-opacity"], 10);
10794
+ const tintBlend = args2["tint-blend"];
10680
10795
  let validatedTintColor;
10681
10796
  if (tintColor) {
10682
10797
  try {
@@ -10688,7 +10803,7 @@ var main = defineCommand({
10688
10803
  }
10689
10804
  }
10690
10805
  if (isNaN(tintOpacity) || tintOpacity < 0 || tintOpacity > 100) {
10691
- console.error(`Error: tint-opacity must be between 0 and 100, got "${args["tint-opacity"]}"
10806
+ console.error(`Error: tint-opacity must be between 0 and 100, got "${args2["tint-opacity"]}"
10692
10807
  `);
10693
10808
  showFlagHelp("tint-opacity");
10694
10809
  }
@@ -10697,7 +10812,7 @@ var main = defineCommand({
10697
10812
  `);
10698
10813
  showFlagHelp("tint-blend");
10699
10814
  }
10700
- const addValues = args.add ? Array.isArray(args.add) ? args.add : [args.add] : [];
10815
+ const addValues = args2.add ? Array.isArray(args2.add) ? args2.add : [args2.add] : [];
10701
10816
  const harmonies = [];
10702
10817
  const hueShifts = [];
10703
10818
  for (const value of addValues) {
@@ -10730,7 +10845,7 @@ var main = defineCommand({
10730
10845
  if (!tintColor && tintBlend !== "normal") {
10731
10846
  console.error("Warning: --tint-blend has no effect without --tint-color");
10732
10847
  }
10733
- const outputType = args.output;
10848
+ const outputType = args2.output;
10734
10849
  if (!isValidOutputFormat(outputType)) {
10735
10850
  console.error(`Error: Invalid output format "${outputType}"
10736
10851
  `);
@@ -10795,7 +10910,8 @@ var main = defineCommand({
10795
10910
  name: "base",
10796
10911
  baseColor: formatColor2(validatedColor, outputFormat),
10797
10912
  config: buildRampConfig(),
10798
- colors: formattedBaseColors
10913
+ colors: formattedBaseColors,
10914
+ rawColors: baseColors
10799
10915
  });
10800
10916
  for (const harmony of harmonies) {
10801
10917
  const harmonyColors = getHarmonyColors(harmony, validatedColor);
@@ -10807,7 +10923,8 @@ var main = defineCommand({
10807
10923
  name: `${harmony}${suffix}`,
10808
10924
  baseColor: formatColor2(harmonyBaseColor, outputFormat),
10809
10925
  config: buildRampConfig(),
10810
- colors: formattedHarmonyColors
10926
+ colors: formattedHarmonyColors,
10927
+ rawColors: harmonyRampColors
10811
10928
  });
10812
10929
  });
10813
10930
  }
@@ -10822,18 +10939,20 @@ var main = defineCommand({
10822
10939
  name: `shift-${Math.round(shift)}`,
10823
10940
  baseColor: formatColor2(shiftedBaseColor, outputFormat),
10824
10941
  config: buildRampConfig(),
10825
- colors: formattedShiftedColors
10942
+ colors: formattedShiftedColors,
10943
+ rawColors: shiftedRampColors
10826
10944
  });
10827
10945
  }
10828
- const accessibilityEnabled = args.accessibility !== undefined;
10829
- const accessibilityFilter = accessibilityEnabled ? parseAccessibilityFilter(args.accessibility) : undefined;
10946
+ const accessibilityEnabled = args2.accessibility !== undefined;
10947
+ const accessibilityFilter = accessibilityEnabled ? parseAccessibilityFilter(args2.accessibility) : undefined;
10948
+ const jsonFormat = args2.format ? outputFormat : undefined;
10830
10949
  if (outputType === "json") {
10831
10950
  if (accessibilityEnabled) {
10832
10951
  const report = generateAccessibilityReport(ramps, accessibilityFilter);
10833
- const output = { ramps: JSON.parse(formatJson(ramps)).ramps, accessibility: formatAccessibilityJson(report) };
10952
+ const output = { ramps: JSON.parse(formatJson(ramps, jsonFormat)).ramps, accessibility: formatAccessibilityJson(report) };
10834
10953
  console.log(JSON.stringify(output, null, 2));
10835
10954
  } else {
10836
- console.log(formatJson(ramps));
10955
+ console.log(formatJson(ramps, jsonFormat));
10837
10956
  }
10838
10957
  } else if (outputType === "css") {
10839
10958
  let output = formatCss2(ramps);
@@ -10843,8 +10962,8 @@ var main = defineCommand({
10843
10962
  }
10844
10963
  console.log(output);
10845
10964
  } else {
10846
- const canShowPreview = args.preview && supportsTruecolor();
10847
- if (args.preview && !canShowPreview) {
10965
+ const canShowPreview = args2.preview && supportsTruecolor();
10966
+ if (args2.preview && !canShowPreview) {
10848
10967
  const limitationNote = getColorLimitationNote();
10849
10968
  if (limitationNote) {
10850
10969
  console.log(limitationNote);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basiclines/rampa",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Generate mathematically accurate color palettes from a base color",
5
5
  "type": "module",
6
6
  "bin": {