@basiclines/rampa 1.1.3 → 1.3.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.
- package/README.md +61 -0
- package/dist/index.js +343 -11
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -140,6 +140,35 @@ Available types:
|
|
|
140
140
|
| `--output` | `-O` | Output format: text, json, css | text |
|
|
141
141
|
| `--preview` | | Show colored squares | true |
|
|
142
142
|
|
|
143
|
+
### Accessibility
|
|
144
|
+
|
|
145
|
+
| Flag | Alias | Description | Default |
|
|
146
|
+
|------|-------|-------------|---------|
|
|
147
|
+
| `--accessibility` | `-A` | APCA contrast report | off |
|
|
148
|
+
|
|
149
|
+
The `-A` flag generates an accessibility report using the [APCA](https://github.com/Myndex/APCA) (Accessible Perceptual Contrast Algorithm) methodology. It analyzes all color pairs across all generated ramps and groups passing pairs by contrast level.
|
|
150
|
+
|
|
151
|
+
**Filter options:**
|
|
152
|
+
|
|
153
|
+
| Syntax | Example | Description |
|
|
154
|
+
|--------|---------|-------------|
|
|
155
|
+
| `-A` | `-A` | Show all passing pairs |
|
|
156
|
+
| `-A=<Lc>` | `-A=60` | Minimum Lc threshold |
|
|
157
|
+
| `-A=<label>` | `-A=body` | Filter by named level |
|
|
158
|
+
| `-A=<min>:<max>` | `-A=15:30` | Lc range filter |
|
|
159
|
+
| `-A=<label>:<label>` | `-A=nontext:bold` | Range using level names |
|
|
160
|
+
|
|
161
|
+
**Level labels:**
|
|
162
|
+
|
|
163
|
+
| Label | Lc Threshold | Use Case |
|
|
164
|
+
|-------|-------------|----------|
|
|
165
|
+
| `preferred` | 90 | Preferred body text |
|
|
166
|
+
| `body` | 75 | Body text |
|
|
167
|
+
| `large` | 60 | Large text |
|
|
168
|
+
| `bold` | 45 | Large/bold text |
|
|
169
|
+
| `minimum` | 30 | Minimum text |
|
|
170
|
+
| `nontext` | 15 | Non-text elements |
|
|
171
|
+
|
|
143
172
|
### Other
|
|
144
173
|
|
|
145
174
|
| Flag | Alias | Description |
|
|
@@ -251,6 +280,28 @@ Output:
|
|
|
251
280
|
rampa -C "#3b82f6" --no-preview | head -5
|
|
252
281
|
```
|
|
253
282
|
|
|
283
|
+
### Accessibility Report
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
# Full APCA contrast report
|
|
287
|
+
rampa -C "#3b82f6" --add=complementary -A
|
|
288
|
+
|
|
289
|
+
# Filter by minimum Lc threshold
|
|
290
|
+
rampa -C "#3b82f6" --add=complementary -A=body
|
|
291
|
+
|
|
292
|
+
# Filter by Lc range
|
|
293
|
+
rampa -C "#3b82f6" --add=complementary -A=15:30
|
|
294
|
+
|
|
295
|
+
# Filter using level labels
|
|
296
|
+
rampa -C "#3b82f6" --add=complementary -A=nontext:bold
|
|
297
|
+
|
|
298
|
+
# Accessibility report in JSON
|
|
299
|
+
rampa -C "#3b82f6" --add=complementary -A -O json
|
|
300
|
+
|
|
301
|
+
# Accessibility report in CSS (appended as comment)
|
|
302
|
+
rampa -C "#3b82f6" --add=complementary -A -O css
|
|
303
|
+
```
|
|
304
|
+
|
|
254
305
|
## Contextual Help
|
|
255
306
|
|
|
256
307
|
Run any flag without a value to see detailed help:
|
|
@@ -280,6 +331,16 @@ bun run build
|
|
|
280
331
|
bun run build:all
|
|
281
332
|
```
|
|
282
333
|
|
|
334
|
+
## AI Evals
|
|
335
|
+
|
|
336
|
+
Compare how different LLM models use the Rampa CLI by sending the same prompt to multiple models in agent mode. Models can discover rampa via `--help`, execute commands, and iterate. Use `--raw` to run without rampa for baseline comparison. See [evals/README.md](evals/README.md) for details.
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
bun run eval # all prompts, all models
|
|
340
|
+
bun run eval --prompt ghostty-matrix-theme --no-judge # single prompt
|
|
341
|
+
bun run eval --prompt ghostty-matrix-theme --raw # without rampa (baseline)
|
|
342
|
+
```
|
|
343
|
+
|
|
283
344
|
## Build Targets
|
|
284
345
|
|
|
285
346
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -9518,8 +9518,8 @@ var calculateHue = (config, position, baseHue, middleIndex, i2) => {
|
|
|
9518
9518
|
};
|
|
9519
9519
|
var calculateSaturation = (config, position, baseSaturation, middleIndex, i2) => {
|
|
9520
9520
|
try {
|
|
9521
|
-
const startSaturation = config.saturationStart / 100;
|
|
9522
|
-
const endSaturation = config.saturationEnd / 100;
|
|
9521
|
+
const startSaturation = config.saturationStart / 100 * baseSaturation;
|
|
9522
|
+
const endSaturation = config.saturationEnd / 100 * baseSaturation;
|
|
9523
9523
|
const newSaturation = startSaturation + (endSaturation - startSaturation) * position;
|
|
9524
9524
|
return clampValue2(newSaturation, 0, 1);
|
|
9525
9525
|
} catch (error) {
|
|
@@ -9943,6 +9943,291 @@ ${dim}For accurate color previews, use a terminal with COLORTERM=truecolor.${res
|
|
|
9943
9943
|
return null;
|
|
9944
9944
|
}
|
|
9945
9945
|
|
|
9946
|
+
// node_modules/apca-w3/src/apca-w3.js
|
|
9947
|
+
var SA98G = {
|
|
9948
|
+
mainTRC: 2.4,
|
|
9949
|
+
get mainTRCencode() {
|
|
9950
|
+
return 1 / this.mainTRC;
|
|
9951
|
+
},
|
|
9952
|
+
sRco: 0.2126729,
|
|
9953
|
+
sGco: 0.7151522,
|
|
9954
|
+
sBco: 0.072175,
|
|
9955
|
+
normBG: 0.56,
|
|
9956
|
+
normTXT: 0.57,
|
|
9957
|
+
revTXT: 0.62,
|
|
9958
|
+
revBG: 0.65,
|
|
9959
|
+
blkThrs: 0.022,
|
|
9960
|
+
blkClmp: 1.414,
|
|
9961
|
+
scaleBoW: 1.14,
|
|
9962
|
+
scaleWoB: 1.14,
|
|
9963
|
+
loBoWoffset: 0.027,
|
|
9964
|
+
loWoBoffset: 0.027,
|
|
9965
|
+
deltaYmin: 0.0005,
|
|
9966
|
+
loClip: 0.1,
|
|
9967
|
+
mFactor: 1.9468554433171,
|
|
9968
|
+
get mFactInv() {
|
|
9969
|
+
return 1 / this.mFactor;
|
|
9970
|
+
},
|
|
9971
|
+
mOffsetIn: 0.0387393816571401,
|
|
9972
|
+
mExpAdj: 0.283343396420869,
|
|
9973
|
+
get mExp() {
|
|
9974
|
+
return this.mExpAdj / this.blkClmp;
|
|
9975
|
+
},
|
|
9976
|
+
mOffsetOut: 0.312865795870758
|
|
9977
|
+
};
|
|
9978
|
+
function APCAcontrast(txtY, bgY, places = -1) {
|
|
9979
|
+
const icp = [0, 1.1];
|
|
9980
|
+
if (isNaN(txtY) || isNaN(bgY) || Math.min(txtY, bgY) < icp[0] || Math.max(txtY, bgY) > icp[1]) {
|
|
9981
|
+
return 0;
|
|
9982
|
+
}
|
|
9983
|
+
let SAPC = 0;
|
|
9984
|
+
let outputContrast = 0;
|
|
9985
|
+
let polCat = "BoW";
|
|
9986
|
+
txtY = txtY > SA98G.blkThrs ? txtY : txtY + Math.pow(SA98G.blkThrs - txtY, SA98G.blkClmp);
|
|
9987
|
+
bgY = bgY > SA98G.blkThrs ? bgY : bgY + Math.pow(SA98G.blkThrs - bgY, SA98G.blkClmp);
|
|
9988
|
+
if (Math.abs(bgY - txtY) < SA98G.deltaYmin) {
|
|
9989
|
+
return 0;
|
|
9990
|
+
}
|
|
9991
|
+
if (bgY > txtY) {
|
|
9992
|
+
SAPC = (Math.pow(bgY, SA98G.normBG) - Math.pow(txtY, SA98G.normTXT)) * SA98G.scaleBoW;
|
|
9993
|
+
outputContrast = SAPC < SA98G.loClip ? 0 : SAPC - SA98G.loBoWoffset;
|
|
9994
|
+
} else {
|
|
9995
|
+
polCat = "WoB";
|
|
9996
|
+
SAPC = (Math.pow(bgY, SA98G.revBG) - Math.pow(txtY, SA98G.revTXT)) * SA98G.scaleWoB;
|
|
9997
|
+
outputContrast = SAPC > -SA98G.loClip ? 0 : SAPC + SA98G.loWoBoffset;
|
|
9998
|
+
}
|
|
9999
|
+
if (places < 0) {
|
|
10000
|
+
return outputContrast * 100;
|
|
10001
|
+
} else if (places == 0) {
|
|
10002
|
+
return Math.round(Math.abs(outputContrast) * 100) + "<sub>" + polCat + "</sub>";
|
|
10003
|
+
} else if (Number.isInteger(places)) {
|
|
10004
|
+
return (outputContrast * 100).toFixed(places);
|
|
10005
|
+
} else {
|
|
10006
|
+
return 0;
|
|
10007
|
+
}
|
|
10008
|
+
}
|
|
10009
|
+
function sRGBtoY(rgb10 = [0, 0, 0]) {
|
|
10010
|
+
function simpleExp(chan) {
|
|
10011
|
+
return Math.pow(chan / 255, SA98G.mainTRC);
|
|
10012
|
+
}
|
|
10013
|
+
return SA98G.sRco * simpleExp(rgb10[0]) + SA98G.sGco * simpleExp(rgb10[1]) + SA98G.sBco * simpleExp(rgb10[2]);
|
|
10014
|
+
}
|
|
10015
|
+
|
|
10016
|
+
// src/accessibility/apca.ts
|
|
10017
|
+
var APCA_LEVELS = [
|
|
10018
|
+
{ id: "preferred-body", name: "Preferred body text", minLc: 90 },
|
|
10019
|
+
{ id: "body", name: "Body text", minLc: 75 },
|
|
10020
|
+
{ id: "large", name: "Large text", minLc: 60 },
|
|
10021
|
+
{ id: "large-bold", name: "Large/bold text", minLc: 45 },
|
|
10022
|
+
{ id: "min-text", name: "Minimum text", minLc: 30 },
|
|
10023
|
+
{ id: "non-text", name: "Non-text", minLc: 15 }
|
|
10024
|
+
];
|
|
10025
|
+
var LEVEL_ALIASES = {
|
|
10026
|
+
preferred: 90,
|
|
10027
|
+
body: 75,
|
|
10028
|
+
large: 60,
|
|
10029
|
+
bold: 45,
|
|
10030
|
+
minimum: 30,
|
|
10031
|
+
nontext: 15
|
|
10032
|
+
};
|
|
10033
|
+
function resolveValue2(val) {
|
|
10034
|
+
const num9 = parseFloat(val);
|
|
10035
|
+
if (!isNaN(num9) && num9 >= 0)
|
|
10036
|
+
return num9;
|
|
10037
|
+
const label = val.toLowerCase().trim();
|
|
10038
|
+
if (label in LEVEL_ALIASES)
|
|
10039
|
+
return LEVEL_ALIASES[label];
|
|
10040
|
+
return null;
|
|
10041
|
+
}
|
|
10042
|
+
function parseAccessibilityFilter(value) {
|
|
10043
|
+
const raw = value ?? "";
|
|
10044
|
+
if (!value || value === "" || value === "true")
|
|
10045
|
+
return { min: 0, max: Infinity, raw };
|
|
10046
|
+
if (value.includes(":")) {
|
|
10047
|
+
const [startStr, endStr] = value.split(":");
|
|
10048
|
+
const start = resolveValue2(startStr);
|
|
10049
|
+
const end = resolveValue2(endStr);
|
|
10050
|
+
if (start === null || end === null) {
|
|
10051
|
+
const validLabels2 = Object.keys(LEVEL_ALIASES).join(", ");
|
|
10052
|
+
console.error(`Error: Invalid accessibility range "${value}". Use Lc numbers or labels: ${validLabels2}`);
|
|
10053
|
+
process.exit(1);
|
|
10054
|
+
}
|
|
10055
|
+
const lo = Math.min(start, end);
|
|
10056
|
+
const hi = Math.max(start, end);
|
|
10057
|
+
return { min: lo, max: hi, raw: value };
|
|
10058
|
+
}
|
|
10059
|
+
const resolved = resolveValue2(value);
|
|
10060
|
+
if (resolved !== null)
|
|
10061
|
+
return { min: resolved, max: Infinity, raw: value };
|
|
10062
|
+
const validLabels = Object.keys(LEVEL_ALIASES).join(", ");
|
|
10063
|
+
console.error(`Error: Invalid accessibility filter "${value}". Use a Lc number, label, or range (e.g. 15:30). Labels: ${validLabels}`);
|
|
10064
|
+
process.exit(1);
|
|
10065
|
+
}
|
|
10066
|
+
function computeApca(fgHex, bgHex) {
|
|
10067
|
+
const [fgR, fgG, fgB] = chroma_js_default(fgHex).rgb();
|
|
10068
|
+
const [bgR, bgG, bgB] = chroma_js_default(bgHex).rgb();
|
|
10069
|
+
return APCAcontrast(sRGBtoY([fgR, fgG, fgB]), sRGBtoY([bgR, bgG, bgB]));
|
|
10070
|
+
}
|
|
10071
|
+
function getPassingLevels(lc) {
|
|
10072
|
+
const absLc = Math.abs(lc);
|
|
10073
|
+
return APCA_LEVELS.filter((level) => absLc >= level.minLc);
|
|
10074
|
+
}
|
|
10075
|
+
|
|
10076
|
+
// src/accessibility/report.ts
|
|
10077
|
+
function collectColors(ramps) {
|
|
10078
|
+
const refs = [];
|
|
10079
|
+
for (const ramp of ramps) {
|
|
10080
|
+
for (let i2 = 0;i2 < ramp.colors.length; i2++) {
|
|
10081
|
+
refs.push({ ramp: ramp.name, index: i2, color: ramp.colors[i2] });
|
|
10082
|
+
}
|
|
10083
|
+
}
|
|
10084
|
+
return refs;
|
|
10085
|
+
}
|
|
10086
|
+
function deduplicateColors(colors2) {
|
|
10087
|
+
if (colors2.length <= 2)
|
|
10088
|
+
return colors2;
|
|
10089
|
+
const keep = new Set;
|
|
10090
|
+
keep.add(0);
|
|
10091
|
+
keep.add(colors2.length - 1);
|
|
10092
|
+
for (let i2 = 1;i2 < colors2.length; i2++) {
|
|
10093
|
+
const prev = colors2[i2 - 1];
|
|
10094
|
+
const curr = colors2[i2];
|
|
10095
|
+
if (curr.ramp !== prev.ramp) {
|
|
10096
|
+
keep.add(i2);
|
|
10097
|
+
keep.add(i2 - 1);
|
|
10098
|
+
continue;
|
|
10099
|
+
}
|
|
10100
|
+
const de = chroma_js_default.deltaE(curr.color, prev.color);
|
|
10101
|
+
if (de >= 3) {
|
|
10102
|
+
keep.add(i2);
|
|
10103
|
+
}
|
|
10104
|
+
}
|
|
10105
|
+
return colors2.filter((_3, i2) => keep.has(i2));
|
|
10106
|
+
}
|
|
10107
|
+
var DEFAULT_FILTER = { min: 0, max: Infinity, raw: "" };
|
|
10108
|
+
function generateAccessibilityReport(ramps, filter = DEFAULT_FILTER) {
|
|
10109
|
+
const allColors = collectColors(ramps);
|
|
10110
|
+
const colors2 = deduplicateColors(allColors);
|
|
10111
|
+
const totalPairs = colors2.length * (colors2.length - 1) / 2;
|
|
10112
|
+
const levelMap = new Map;
|
|
10113
|
+
for (const level of APCA_LEVELS) {
|
|
10114
|
+
levelMap.set(level.id, []);
|
|
10115
|
+
}
|
|
10116
|
+
let passingPairs = 0;
|
|
10117
|
+
for (let i2 = 0;i2 < colors2.length; i2++) {
|
|
10118
|
+
for (let j = i2 + 1;j < colors2.length; j++) {
|
|
10119
|
+
const a2 = colors2[i2];
|
|
10120
|
+
const b2 = colors2[j];
|
|
10121
|
+
const lcAB = computeApca(a2.color, b2.color);
|
|
10122
|
+
const lcBA = computeApca(b2.color, a2.color);
|
|
10123
|
+
const bestAbsLc = Math.max(Math.abs(lcAB), Math.abs(lcBA));
|
|
10124
|
+
const passing = getPassingLevels(bestAbsLc);
|
|
10125
|
+
if (passing.length > 0) {
|
|
10126
|
+
passingPairs++;
|
|
10127
|
+
const pair = {
|
|
10128
|
+
colorA: a2,
|
|
10129
|
+
colorB: b2,
|
|
10130
|
+
lcAB: Math.round(lcAB * 100) / 100,
|
|
10131
|
+
lcBA: Math.round(lcBA * 100) / 100
|
|
10132
|
+
};
|
|
10133
|
+
const highest = passing[0];
|
|
10134
|
+
levelMap.get(highest.id).push(pair);
|
|
10135
|
+
}
|
|
10136
|
+
}
|
|
10137
|
+
}
|
|
10138
|
+
const levels = APCA_LEVELS.filter((level) => level.minLc >= filter.min && level.minLc <= filter.max).map((level) => {
|
|
10139
|
+
const pairs = filter.max < Infinity ? levelMap.get(level.id).filter((p) => {
|
|
10140
|
+
const bestAbsLc = Math.max(Math.abs(p.lcAB), Math.abs(p.lcBA));
|
|
10141
|
+
return bestAbsLc >= filter.min && bestAbsLc <= filter.max;
|
|
10142
|
+
}) : levelMap.get(level.id);
|
|
10143
|
+
return { id: level.id, name: level.name, minLc: level.minLc, pairs };
|
|
10144
|
+
});
|
|
10145
|
+
return {
|
|
10146
|
+
totalPairs,
|
|
10147
|
+
passingPairs,
|
|
10148
|
+
levels,
|
|
10149
|
+
filter
|
|
10150
|
+
};
|
|
10151
|
+
}
|
|
10152
|
+
|
|
10153
|
+
// src/formatters/accessibility-json.ts
|
|
10154
|
+
function formatAccessibilityJson(report) {
|
|
10155
|
+
return {
|
|
10156
|
+
totalPairs: report.totalPairs,
|
|
10157
|
+
passingPairs: report.passingPairs,
|
|
10158
|
+
filter: report.filter.raw ? { value: report.filter.raw, min: report.filter.min, max: report.filter.max === Infinity ? null : report.filter.max } : null,
|
|
10159
|
+
levels: report.levels.map((level) => ({
|
|
10160
|
+
id: level.id,
|
|
10161
|
+
name: level.name,
|
|
10162
|
+
minLc: level.minLc,
|
|
10163
|
+
count: level.pairs.length,
|
|
10164
|
+
pairs: level.pairs.map((pair) => ({
|
|
10165
|
+
colorA: { ramp: pair.colorA.ramp, index: pair.colorA.index, color: pair.colorA.color },
|
|
10166
|
+
colorB: { ramp: pair.colorB.ramp, index: pair.colorB.index, color: pair.colorB.color },
|
|
10167
|
+
lcAB: pair.lcAB,
|
|
10168
|
+
lcBA: pair.lcBA
|
|
10169
|
+
}))
|
|
10170
|
+
}))
|
|
10171
|
+
};
|
|
10172
|
+
}
|
|
10173
|
+
|
|
10174
|
+
// src/formatters/accessibility-text.ts
|
|
10175
|
+
function formatLc(lc) {
|
|
10176
|
+
const str = lc.toString();
|
|
10177
|
+
return lc >= 0 ? ` ${str}` : str;
|
|
10178
|
+
}
|
|
10179
|
+
function pairSquares(pair) {
|
|
10180
|
+
const [rA, gA, bA] = chroma_js_default(pair.colorA.color).rgb();
|
|
10181
|
+
const [rB, gB, bB] = chroma_js_default(pair.colorB.color).rgb();
|
|
10182
|
+
return `${coloredSquare(rA, gA, bA)}${coloredSquare(rB, gB, bB)}`;
|
|
10183
|
+
}
|
|
10184
|
+
function formatAccessibilityText(report, options = {}) {
|
|
10185
|
+
const lines = [];
|
|
10186
|
+
const showPreview = options.preview ?? false;
|
|
10187
|
+
lines.push("");
|
|
10188
|
+
lines.push("# Accessibility Report (APCA)");
|
|
10189
|
+
lines.push(`${report.passingPairs} of ${report.totalPairs} pairs pass at least one level`);
|
|
10190
|
+
lines.push("");
|
|
10191
|
+
const filteredPairCount = report.levels.reduce((sum, l2) => sum + l2.pairs.length, 0);
|
|
10192
|
+
if (filteredPairCount === 0) {
|
|
10193
|
+
const filterDesc = report.filter.raw ? `filter: ${report.filter.raw}` : "current filter";
|
|
10194
|
+
lines.push(`No pairs match the ${filterDesc}`);
|
|
10195
|
+
lines.push("");
|
|
10196
|
+
return lines.join(`
|
|
10197
|
+
`);
|
|
10198
|
+
}
|
|
10199
|
+
for (const level of report.levels) {
|
|
10200
|
+
if (level.pairs.length === 0)
|
|
10201
|
+
continue;
|
|
10202
|
+
lines.push(`## ${level.name} (Lc ≥ ${level.minLc}) — ${level.pairs.length} pairs`);
|
|
10203
|
+
const maxColorA = Math.max(...level.pairs.map((p) => p.colorA.color.length));
|
|
10204
|
+
const maxColorB = Math.max(...level.pairs.map((p) => p.colorB.color.length));
|
|
10205
|
+
const maxLcAB = Math.max(...level.pairs.map((p) => formatLc(p.lcAB).length));
|
|
10206
|
+
const maxLcBA = Math.max(...level.pairs.map((p) => formatLc(p.lcBA).length));
|
|
10207
|
+
const maxRefA = Math.max(...level.pairs.map((p) => `${p.colorA.ramp}[${p.colorA.index}]`.length));
|
|
10208
|
+
const maxRefB = Math.max(...level.pairs.map((p) => `${p.colorB.ramp}[${p.colorB.index}]`.length));
|
|
10209
|
+
for (const pair of level.pairs) {
|
|
10210
|
+
const colA = pair.colorA.color.padEnd(maxColorA);
|
|
10211
|
+
const colB = pair.colorB.color.padEnd(maxColorB);
|
|
10212
|
+
const lcA = formatLc(pair.lcAB).padStart(maxLcAB);
|
|
10213
|
+
const lcB = formatLc(pair.lcBA).padStart(maxLcBA);
|
|
10214
|
+
const refA = `${pair.colorA.ramp}[${pair.colorA.index}]`.padEnd(maxRefA);
|
|
10215
|
+
const refB = `${pair.colorB.ramp}[${pair.colorB.index}]`.padEnd(maxRefB);
|
|
10216
|
+
const preview = showPreview ? `${pairSquares(pair)} ` : "";
|
|
10217
|
+
lines.push(` ${preview}${colA} ↔ ${colB} Lc ${lcA} / ${lcB} ${refA} ↔ ${refB}`);
|
|
10218
|
+
}
|
|
10219
|
+
lines.push("");
|
|
10220
|
+
}
|
|
10221
|
+
return lines.join(`
|
|
10222
|
+
`);
|
|
10223
|
+
}
|
|
10224
|
+
function formatAccessibilityCss(report) {
|
|
10225
|
+
return `
|
|
10226
|
+
/*
|
|
10227
|
+
` + formatAccessibilityText(report) + `*/
|
|
10228
|
+
`;
|
|
10229
|
+
}
|
|
10230
|
+
|
|
9946
10231
|
// src/index.ts
|
|
9947
10232
|
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
9948
10233
|
showHelp();
|
|
@@ -9952,7 +10237,7 @@ function showHelp() {
|
|
|
9952
10237
|
const dim = "\x1B[2m";
|
|
9953
10238
|
const reset = "\x1B[0m";
|
|
9954
10239
|
const help = `
|
|
9955
|
-
rampa v1.
|
|
10240
|
+
rampa v1.2.0
|
|
9956
10241
|
Generate mathematically accurate color palettes from a base color
|
|
9957
10242
|
|
|
9958
10243
|
USAGE
|
|
@@ -9995,6 +10280,10 @@ HARMONIES
|
|
|
9995
10280
|
OUTPUT
|
|
9996
10281
|
${cyan}-O, --output <format>${reset} ${dim}Output format (default: text)${reset}
|
|
9997
10282
|
${cyan}--preview / --no-preview${reset} ${dim}Show colored squares (default: true)${reset}
|
|
10283
|
+
${cyan}-A, --accessibility [filter]${reset} ${dim}Show APCA contrast report${reset}
|
|
10284
|
+
|
|
10285
|
+
${dim}Filters: preferred, body, large, bold, minimum, nontext${reset}
|
|
10286
|
+
${dim}or a custom Lc value (e.g. 60)${reset}
|
|
9998
10287
|
|
|
9999
10288
|
${dim}Formats: text, json, css${reset}
|
|
10000
10289
|
|
|
@@ -10009,6 +10298,8 @@ EXAMPLES
|
|
|
10009
10298
|
${cyan}rampa -C "#3b82f6" --add=shift:45 --add=shift:90${reset}
|
|
10010
10299
|
${cyan}rampa -C "#3b82f6" -O css${reset}
|
|
10011
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}
|
|
10012
10303
|
`;
|
|
10013
10304
|
console.log(help.trim());
|
|
10014
10305
|
process.exit(0);
|
|
@@ -10148,6 +10439,25 @@ Examples:
|
|
|
10148
10439
|
rampa -C "#3b82f6" --output=json
|
|
10149
10440
|
rampa -C "#3b82f6" --output=css
|
|
10150
10441
|
rampa -C "#3b82f6" -O json --add=complementary
|
|
10442
|
+
`,
|
|
10443
|
+
accessibility: `
|
|
10444
|
+
-A, --accessibility [filter] Show APCA contrast report
|
|
10445
|
+
|
|
10446
|
+
Filters (optional):
|
|
10447
|
+
preferred Lc ≥ 90 Preferred body text
|
|
10448
|
+
body Lc ≥ 75 Body text
|
|
10449
|
+
large Lc ≥ 60 Large text
|
|
10450
|
+
bold Lc ≥ 45 Large/bold text
|
|
10451
|
+
minimum Lc ≥ 30 Minimum text
|
|
10452
|
+
nontext Lc ≥ 15 Non-text
|
|
10453
|
+
<number> Custom Lc threshold (e.g. 60)
|
|
10454
|
+
|
|
10455
|
+
Examples:
|
|
10456
|
+
rampa -C "#3b82f6" -A
|
|
10457
|
+
rampa -C "#3b82f6" -A body
|
|
10458
|
+
rampa -C "#3b82f6" -A=large
|
|
10459
|
+
rampa -C "#3b82f6" --accessibility=75
|
|
10460
|
+
rampa -C "#3b82f6" -O json -A preferred
|
|
10151
10461
|
`
|
|
10152
10462
|
};
|
|
10153
10463
|
function showFlagHelp(flag) {
|
|
@@ -10190,13 +10500,13 @@ var validFormats = ["hex", "hsl", "rgb", "oklch"];
|
|
|
10190
10500
|
var main = defineCommand({
|
|
10191
10501
|
meta: {
|
|
10192
10502
|
name: "rampa",
|
|
10193
|
-
version: "1.
|
|
10503
|
+
version: "1.3.0",
|
|
10194
10504
|
description: "Generate mathematically accurate color palettes from a base color"
|
|
10195
10505
|
},
|
|
10196
10506
|
args: {
|
|
10197
10507
|
color: {
|
|
10198
10508
|
type: "string",
|
|
10199
|
-
alias: "C",
|
|
10509
|
+
alias: ["C", "c"],
|
|
10200
10510
|
description: "Base color (hex, hsl, rgb, oklch)",
|
|
10201
10511
|
required: true
|
|
10202
10512
|
},
|
|
@@ -10207,18 +10517,18 @@ var main = defineCommand({
|
|
|
10207
10517
|
},
|
|
10208
10518
|
format: {
|
|
10209
10519
|
type: "string",
|
|
10210
|
-
alias: "F",
|
|
10520
|
+
alias: ["F", "f"],
|
|
10211
10521
|
description: "Output format: hex, hsl, rgb, oklch (default: same as input)"
|
|
10212
10522
|
},
|
|
10213
10523
|
lightness: {
|
|
10214
10524
|
type: "string",
|
|
10215
|
-
alias: "L",
|
|
10525
|
+
alias: ["L", "l"],
|
|
10216
10526
|
description: "Lightness range start:end (0-100, default: 0:100)",
|
|
10217
10527
|
default: "0:100"
|
|
10218
10528
|
},
|
|
10219
10529
|
saturation: {
|
|
10220
10530
|
type: "string",
|
|
10221
|
-
alias: "S",
|
|
10531
|
+
alias: ["S", "s"],
|
|
10222
10532
|
description: "Saturation range start:end (0-100, default: 100:0)",
|
|
10223
10533
|
default: "100:0"
|
|
10224
10534
|
},
|
|
@@ -10268,9 +10578,14 @@ var main = defineCommand({
|
|
|
10268
10578
|
},
|
|
10269
10579
|
output: {
|
|
10270
10580
|
type: "string",
|
|
10271
|
-
alias: "O",
|
|
10581
|
+
alias: ["O", "o"],
|
|
10272
10582
|
description: "Output format: text, json, css (default: text)",
|
|
10273
10583
|
default: "text"
|
|
10584
|
+
},
|
|
10585
|
+
accessibility: {
|
|
10586
|
+
type: "string",
|
|
10587
|
+
alias: ["A", "a"],
|
|
10588
|
+
description: "Show APCA contrast report. Optional: filter by level name or Lc value"
|
|
10274
10589
|
}
|
|
10275
10590
|
},
|
|
10276
10591
|
run({ args }) {
|
|
@@ -10510,10 +10825,23 @@ var main = defineCommand({
|
|
|
10510
10825
|
colors: formattedShiftedColors
|
|
10511
10826
|
});
|
|
10512
10827
|
}
|
|
10828
|
+
const accessibilityEnabled = args.accessibility !== undefined;
|
|
10829
|
+
const accessibilityFilter = accessibilityEnabled ? parseAccessibilityFilter(args.accessibility) : undefined;
|
|
10513
10830
|
if (outputType === "json") {
|
|
10514
|
-
|
|
10831
|
+
if (accessibilityEnabled) {
|
|
10832
|
+
const report = generateAccessibilityReport(ramps, accessibilityFilter);
|
|
10833
|
+
const output = { ramps: JSON.parse(formatJson(ramps)).ramps, accessibility: formatAccessibilityJson(report) };
|
|
10834
|
+
console.log(JSON.stringify(output, null, 2));
|
|
10835
|
+
} else {
|
|
10836
|
+
console.log(formatJson(ramps));
|
|
10837
|
+
}
|
|
10515
10838
|
} else if (outputType === "css") {
|
|
10516
|
-
|
|
10839
|
+
let output = formatCss2(ramps);
|
|
10840
|
+
if (accessibilityEnabled) {
|
|
10841
|
+
const report = generateAccessibilityReport(ramps, accessibilityFilter);
|
|
10842
|
+
output += formatAccessibilityCss(report);
|
|
10843
|
+
}
|
|
10844
|
+
console.log(output);
|
|
10517
10845
|
} else {
|
|
10518
10846
|
const canShowPreview = args.preview && supportsTruecolor();
|
|
10519
10847
|
if (args.preview && !canShowPreview) {
|
|
@@ -10540,6 +10868,10 @@ var main = defineCommand({
|
|
|
10540
10868
|
}
|
|
10541
10869
|
});
|
|
10542
10870
|
});
|
|
10871
|
+
if (accessibilityEnabled) {
|
|
10872
|
+
const report = generateAccessibilityReport(ramps, accessibilityFilter);
|
|
10873
|
+
console.log(formatAccessibilityText(report, { preview: canShowPreview }));
|
|
10874
|
+
}
|
|
10543
10875
|
}
|
|
10544
10876
|
}
|
|
10545
10877
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basiclines/rampa",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Generate mathematically accurate color palettes from a base color",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"build:linux-arm64": "bun build ./src/index.ts --compile --target=bun-linux-arm64 --outfile=./dist/rampa-linux-arm64",
|
|
23
23
|
"build:windows-x64": "bun build ./src/index.ts --compile --target=bun-windows-x64 --outfile=./dist/rampa-windows-x64.exe",
|
|
24
24
|
"build:all": "bun run build:darwin-arm64 && bun run build:darwin-x64 && bun run build:linux-x64 && bun run build:linux-arm64 && bun run build:windows-x64",
|
|
25
|
-
"release": "bun run scripts/release.ts"
|
|
25
|
+
"release": "bun run scripts/release.ts",
|
|
26
|
+
"eval": "bun run evals/src/runner.ts"
|
|
26
27
|
},
|
|
27
28
|
"repository": {
|
|
28
29
|
"type": "git",
|
|
@@ -39,13 +40,16 @@
|
|
|
39
40
|
"author": "ismael.fyi",
|
|
40
41
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
41
42
|
"dependencies": {
|
|
42
|
-
"
|
|
43
|
+
"apca-w3": "^0.1.9",
|
|
43
44
|
"chroma-js": "^3.1.2",
|
|
45
|
+
"citty": "^0.1.6",
|
|
44
46
|
"culori": "^4.0.1"
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
|
49
|
+
"@github/copilot-sdk": "^0.1.23",
|
|
47
50
|
"@types/bun": "^1.2.17",
|
|
48
51
|
"@types/chroma-js": "^3.1.1",
|
|
52
|
+
"picocolors": "^1.1.1",
|
|
49
53
|
"typescript": "^5.5.3"
|
|
50
54
|
}
|
|
51
55
|
}
|