diff --git a/LintLanguageDocs.md b/LintLanguageDocs.md index f40dd923..a696cd1d 100644 --- a/LintLanguageDocs.md +++ b/LintLanguageDocs.md @@ -1,50 +1,54 @@ Expressions -EXPR = Conjunction | Quantifier | Comparison | Boolean +Conjunction | Quantifier | Comparison | Boolean + +Value = Variable | Number | Color | Boolean Conjunctions: -AND: {and: [EXPR, EXPR, ...]} -OR: {or: [EXPR, EXPR, EXPR]} -NOT: {not: EXPR} +{and: [EXPR, EXPR, ...]} +{or: [EXPR, EXPR, EXPR]} +{not: EXPR} Quantifiers: -FORALL: {all: {varbs: Variable[], predicate: EXPR, where?: EXPR, in: Variable | Value[]}} -EXISTS: {exists: {varbs: Variable[], predicate: EXPR, where?: EXPR, in: Variable | Value[]}} +{all: {varbs: Variable[], predicate: EXPR, where?: EXPR, in: Variable | Value[]}} +{exists: {varbs: Variable[], predicate: EXPR, where?: EXPR, in: Variable | Value[]}} -Comparisons (value) => expression -similar: {"similar": {left: Value, right: Value, threshold: Number}} -equal: {"==": {left: Value, right: Value}} -not equal: {"!=": {left: Value, right: Value}} -less than: {"<": {left: Value, right: Value}} -greater than: {">": {left: Value, right: Value}} - -Value = Variable | Number | Color | Boolean +Comparisons: +{"similar": {left: Value, right: Value, threshold: Number}} +{"==": {left: Value, right: Value}} +{"!=": {left: Value, right: Value}} +{"<": {left: Value, right: Value}} +{">": {left: Value, right: Value}} -Operations: +Math Operations: \*: {left: Number | Variable, right: Number | Variable} +: {left: Number | Variable, right: Number | Variable} /: {left: Number | Variable, right: Number | Variable} -: {left: Number | Variable, right: Number | Variable} -dist: {left: Color | Variable, right: Color | Variable, space: COLOR_SPACE } -deltaE: {left: Color | Variable, right: Color | Variable, algorithm: '2000' | etc } -contrast: {left: Color | Variable, right: Color | Variable, algorithm: | "APCA" | "WCAG21" | "Michelson" | "Weber" | "Lstar" | "DeltaPhi"} - -count: {count: Variable | Number[] | Color[]} -sum: {sum: Variable | Number[]} -min: {min: Variable | Number[]} -max: {max: Variable | Number[]} -mean: {mean: Variable | Number[]} -first: {first: Variable | Number[]} -last: {last: Variable | Number[]} -extent: {extent: Variable | Number[]} - -toColor: {toColor: variableName, space: 'lab' | 'hsl' | etc, channel: 'a' | 'b' | 'l' | etc} -cvdSim: {cvdSim: variableName, type: 'protanomaly' | 'deuteranomaly' | 'tritanopia' | 'grayscale'} -name: {name: variableName} - -map: {map: Variable | Value[], func: Operation, varb: Variable} -sort: {sort: Variable | Value[], func: Operation, varb: Variable} -filter: {filter: Variable | Value[], func: EXPR, varb: Variable} +Value Comparisons: +{dist: {left: Color | Variable, right: Color | Variable}, space: COLOR_SPACE } +{deltaE: {left: Color | Variable, right: Color | Variable}, algorithm: '2000' | etc } +{contrast: {left: Color | Variable, right: Color | Variable}, algorithm: | "APCA" | "WCAG21" | "Michelson" | "Weber" | "Lstar" | "DeltaPhi"} + +Aggregates +{count: Variable | Number[] | Color[]} +{sum: Variable | Number[]} +{min: Variable | Number[]} +{max: Variable | Number[]} +{mean: Variable | Number[]} +{first: Variable | Number[]} +{last: Variable | Number[]} +{extent: Variable | Number[]} + +Color Manipulations: +{toColor: variableName, space: 'lab' | 'hsl' | etc, channel: 'a' | 'b' | 'l' | etc} +{cvdSim: variableName, type: 'protanomaly' | 'deuteranomaly' | 'tritanopia' | 'grayscale'} +{name: variableName} + +Maps: +{map: Variable | Value[], func: Operation, varb: Variable} +{sort: Variable | Value[], func: Operation, varb: Variable} +{filter: Variable | Value[], func: EXPR, varb: Variable} ```yaml --- diff --git a/README.md b/README.md index 6b626961..84572279 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,11 @@ Macros story # Language todos - [ ] Add more blame robustness, may pay to try to reason across all of the operator families (insight: keep a list of the blamable variables in the environment to support tracing) -- [ ] Add background, roles, palette level semantics -- [ ] Categorical mutually distinct +- [ ] roles, palette level semantics +- [ ] per cols 4 all: color blindness metric should maybe be sensitive to task? +- [ ] Sequential check fix is incorrect for things with equi-ligthness +- [x] Add background, +- [x] Categorical mutually distinct - [x] Integration into main app - [x] "Blame" for colors - [x] JSON Schema (for validation) (if parser is not used), get a sustainable way to use it @@ -31,20 +34,21 @@ Macros story # Todo bankruptcy -- [ ] Search paletes by lint screen +- [ ] Search palettes-by-lint screen - [ ] off by one persistance error in undo/redo -- [ ] Gamut algorithm broken again - [ ] Add HCT/CAM, add explainers to each of the color spaces, blocked by colorjs release -- [ ] Allow no palettes, allows renaming of non-current palettes +- [ ] Allow no palettes, allows renaming of non-current palettes, which would be enable by: +- [ ] Parameterize the scatter column completely, allow edits to the compare stuff - [ ] Colors from String should save on enter? - [ ] Changing spaces is pretty bad on lab <-> oklab, cf ("#35ffbf", "#87b995", "#e84f82") - [ ] "Easy on ramp" progressive disclosure -- [ ] per cols 4 all: color blindness metric should maybe be sensitive to task? - [ ] Labels, tooltips, etc - [ ] Bug: Color channel usage slightly cursed (doesn't update positions correctly) - [ ] Bug: rotate in polar coordinates doesn't work right - [ ] Directional subtile for aligns, they do not work in polar also -- [ ] Sequential check fix is incorrect for things with equi-ligthness +- [ ] Performance stuff for linter (separate message generation into something very throttled, maybe move to web workers? Cache as hard as possible) +- [ ] Hover broken on compare +- [x] Gamut algorithm broken again - [x] Add up/down manipulation to palettes # Nice to have diff --git a/netlify/functions/suggest-lint.ts b/netlify/functions/suggest-lint.ts index 67ee9aa5..d24bfb73 100644 --- a/netlify/functions/suggest-lint.ts +++ b/netlify/functions/suggest-lint.ts @@ -10,40 +10,56 @@ You are a color expert and domain-specific language programmer. You take in a li # Task and output format Given a lint prompt, suggest a lint using the color check linting language Your response should be a JSON object written in the following JSON DSL. You must be explicit in your response and include all necessary information. If a list of colors is suggest you should guess what those colors are and give explicit values -Expressions -EXPR = Conjunction | Quantifier | Comparison | Boolean +Conjunction | Quantifier | Comparison | Boolean + +Value = Variable | Number | Color | Boolean Conjunctions: -AND: {and: [EXPR, EXPR, ...]} -OR: {or: [EXPR, EXPR, EXPR]} -NOT: {not: EXPR} +{and: [EXPR, EXPR, ...]} +{or: [EXPR, EXPR, EXPR]} +{not: EXPR} Quantifiers: -FORALL: {all: {varbs: Variable[], predicate: EXPR, where?: EXPR, in: Variable | Value[]}} -EXISTS: {exist: {varbs: Variable[], predicate: EXPR, where?: EXPR, in: Variable | Value[]}} +{all: {varbs: Variable[], predicate: EXPR, where?: EXPR, in: Variable | Value[]}} +{exists: {varbs: Variable[], predicate: EXPR, where?: EXPR, in: Variable | Value[]}} -Comparisons (value) => expression -similar: {"similar": {left: Value, right: Value, threshold: Number}} -equal: {"==": {left: Value, right: Value}} -not equal: {"!=": {left: Value, right: Value}} -less than: {"<": {left: Value, right: Value}} -greater than: {">": {left: Value, right: Value}} +Comparisons: +{"similar": {left: Value, right: Value, threshold: Number}} +{"==": {left: Value, right: Value}} +{"!=": {left: Value, right: Value}} +{"<": {left: Value, right: Value}} +{">": {left: Value, right: Value}} -Value = Variable | Number | Color | Boolean -Variable = string | colors | background - -Operations: -*|+|/|-: {left: Number | Variable, right: Number | Variable} -dist: {left: Color | Variable, right: Color | Variable, space: COLOR_SPACE } -deltaE: {left: Color | Variable, right: Color | Variable, algorithm: '2000' | etc } -contrast: {left: Color | Variable, right: Color | Variable, algorithm: | "APCA" | "WCAG21" | "Michelson" | "Weber" | "Lstar" | "DeltaPhi"} -count: {count: Variable | Number[] | Color[]} -sum|min|max|mean|first|last|extent: {sum: Variable | Number[]} -toColor: {toColor: variableName, space: 'lab' | 'hsl' | etc, channel: 'a' | 'b' | 'l' | etc} -cvdSim: {cvdSim: variableName, type: 'protanomaly' | 'deuteranomaly' | 'tritanopia' | 'grayscale'} -name: {name: variableName} -map|sort: {map: Variable | Value[], func: Operation} -filter: {filter: Variable | Value[], func: EXPR} +Math Operations: +\*: {left: Number | Variable, right: Number | Variable} ++: {left: Number | Variable, right: Number | Variable} +/: {left: Number | Variable, right: Number | Variable} +-: {left: Number | Variable, right: Number | Variable} + +Value Comparisons: +{dist: {left: Color | Variable, right: Color | Variable}, space: COLOR_SPACE } +{deltaE: {left: Color | Variable, right: Color | Variable}, algorithm: '2000' | etc } +{contrast: {left: Color | Variable, right: Color | Variable}, algorithm: | "APCA" | "WCAG21" | "Michelson" | "Weber" | "Lstar" | "DeltaPhi"} + +Aggregates +{count: Variable | Number[] | Color[]} +{sum: Variable | Number[]} +{min: Variable | Number[]} +{max: Variable | Number[]} +{mean: Variable | Number[]} +{first: Variable | Number[]} +{last: Variable | Number[]} +{extent: Variable | Number[]} + +Color Manipulations: +{toColor: variableName, space: 'lab' | 'hsl' | etc, channel: 'a' | 'b' | 'l' | etc} +{cvdSim: variableName, type: 'protanomaly' | 'deuteranomaly' | 'tritanopia' | 'grayscale'} +{name: variableName} + +Maps: +{map: Variable | Value[], func: Operation, varb: Variable} +{sort: Variable | Value[], func: Operation, varb: Variable} +{filter: Variable | Value[], func: EXPR, varb: Variable} Example prompt: All colors should be color blind friendly for deuteranopia Example Result: diff --git a/src/lib/lint-language/lint-type.ts b/src/lib/lint-language/lint-type.ts index 9994ca8c..724afd4c 100644 --- a/src/lib/lint-language/lint-type.ts +++ b/src/lib/lint-language/lint-type.ts @@ -43,20 +43,20 @@ type LintComparison = type MathOperations = "+" | "-" | "*" | "/"; type LintMathOps = Record; type LintPairOps = - | { dist: { left: LintRef; right: LintRef; space: "lab" | "hsl" } } - | { deltaE: { left: LintRef; right: LintRef; algorithm: "2000" | "76" } } + | { dist: { left: LintRef; right: LintRef }; space: "lab" | "hsl" } + | { deltaE: { left: LintRef; right: LintRef }; algorithm: "2000" | "76" } | { contrast: { left: LintRef; right: LintRef; - algorithm: - | "APCA" - | "WCAG21" - | "Michelson" - | "Weber" - | "Lstar" - | "DeltaPhi"; }; + algorithm: + | "APCA" + | "WCAG21" + | "Michelson" + | "Weber" + | "Lstar" + | "DeltaPhi"; }; type LintMap = // | { map: LintVariable | LintValue[]; func: LintColorFunction | LintPairOps } diff --git a/src/linting/Eval.svelte b/src/linting/Eval.svelte index 0a0a9724..6f9e3f1b 100644 --- a/src/linting/Eval.svelte +++ b/src/linting/Eval.svelte @@ -18,9 +18,12 @@ $: evalConfig = currentPal.evalConfig; $: customLints = $lintStore.lints; // $: checks = runLintChecks(currentPal, palType, customLints, evalConfig); - let checks = [] as ColorLint[]; - let updateSearchDebounced = debounce(100, (pal: any) => { - checks = runLintChecks(pal, palType, customLints, evalConfig); + $: checks = [] as ColorLint[]; + $: selectedLint = $lintStore.focusedLint; + $: updateSearchDebounced = debounce(100, (pal: any) => { + if (!selectedLint) { + checks = runLintChecks(pal, palType, customLints, evalConfig); + } }); $: updateSearchDebounced(currentPal); diff --git a/src/scatterplot/ColorScatterPlot.svelte b/src/scatterplot/ColorScatterPlot.svelte index a34b9d0e..438ffd90 100644 --- a/src/scatterplot/ColorScatterPlot.svelte +++ b/src/scatterplot/ColorScatterPlot.svelte @@ -588,6 +588,11 @@   {/if} +{#if $configStore.showGamutMarkers} +
+ X indicates value that is out of gamut +
+{/if}