From 852438d18f879cc84ec3ac14f88d5c31e4ca74a8 Mon Sep 17 00:00:00 2001 From: Andrew Michael McNutt Date: Tue, 12 Mar 2024 14:24:50 -0700 Subject: [PATCH] update the natural language output to be more sql-y --- public/lang-docs.md | 60 +++++++++---------- src/lib/__snapshots__/LintDocs.test.ts.snap | 60 +++++++++---------- src/lib/lint-language/LintLanguage.test.ts | 66 +++++++++++---------- src/lib/lint-language/lint-language.ts | 20 +++++-- src/linting/LintCustomizationTab.svelte | 4 ++ 5 files changed, 114 insertions(+), 96 deletions(-) diff --git a/public/lang-docs.md b/public/lang-docs.md index b9a4058c..d7615f7f 100644 --- a/public/lang-docs.md +++ b/public/lang-docs.md @@ -90,7 +90,7 @@ Maps: Description: Highly saturated light colors are not appropriate for palettes that seek to be serious. See "Affective color in visualization" for more. -Natural Language: ALL c in colors WHERE hsl.l(c) > 70, NOT hsl.s(c) > 70 +Natural Language: ALL c IN colors WHERE hsl.l(c) > 70 SUCH THAT NOT hsl.s(c) > 70 Program: @@ -122,7 +122,7 @@ Program: Description: Highly saturated light colors are not appropriate for palettes that seek to be trustworthy. See "Affective color in visualization" for more. -Natural Language: ALL c in colors WHERE hsl.l(c) > 70, NOT hsl.s(c) > 70 +Natural Language: ALL c IN colors WHERE hsl.l(c) > 70 SUCH THAT NOT hsl.s(c) > 70 Program: @@ -154,7 +154,7 @@ Program: Description: Highly saturated light colors are not appropriate for palettes that seek to be calm. See "Affective color in visualization" for more. -Natural Language: ALL c in colors WHERE hsl.l(c) > 70, NOT hsl.s(c) > 70 +Natural Language: ALL c IN colors WHERE hsl.l(c) > 70 SUCH THAT NOT hsl.s(c) > 70 Program: @@ -186,7 +186,7 @@ Program: Description: Palettes that seek to be playful should have at least one light blue, beige, or gray. See "Affective color in visualization" for more. -Natural Language: EXIST c in colors, (similar(c, lightblue) < 20 or similar(c, beige) < 20 or similar(c, gray) < 20) +Natural Language: EXIST c IN colors SUCH THAT (similar(c, lightblue) < 20 OR similar(c, beige) < 20 OR similar(c, gray) < 20) Program: @@ -217,7 +217,7 @@ Program: Description: Palettes that seek to be positive should not have dark reds or browns. See "Affective color in visualization" for more. -Natural Language: ALL c in colors, NOT (similar(c, darkred) < 20 or similar(c, brown) < 20) +Natural Language: ALL c IN colors SUCH THAT NOT (similar(c, darkred) < 20 OR similar(c, brown) < 20) Program: @@ -249,7 +249,7 @@ Program: Description: Palettes that seek to be negative should not have light colors, particularly greens. See "Affective color in visualization" for more. -Natural Language: ALL c in colors, NOT (similar(c, green) < 20 or lab.l(c) > 70) +Natural Language: ALL c IN colors SUCH THAT NOT (similar(c, green) < 20 OR lab.l(c) > 70) Program: @@ -283,7 +283,7 @@ Program: Description: All colors in a palette should be differentiable by people with deuteranopia (ie can't see green). This is because if they are not, then they will not be differentiable from each other in some contexts. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), NOT similar(cvdSim(a, deuteranopia), cvdSim(b, deuteranopia)) < 9 +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT NOT similar(cvdSim(a, deuteranopia), cvdSim(b, deuteranopia)) < 9 Palettes that will fail this test: @@ -327,7 +327,7 @@ Program: Description: All colors in a palette should be differentiable by people with protanopia (ie can't see red). This is because if they are not, then they will not be differentiable from each other in some contexts. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), NOT similar(cvdSim(a, protanopia), cvdSim(b, protanopia)) < 9 +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT NOT similar(cvdSim(a, protanopia), cvdSim(b, protanopia)) < 9 Palettes that will fail this test: @@ -371,7 +371,7 @@ Program: Description: All colors in a palette should be differentiable by people with tritanopia (ie can't see blue). This is because if they are not, then they will not be differentiable from each other in some contexts. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), NOT similar(cvdSim(a, tritanopia), cvdSim(b, tritanopia)) < 9 +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT NOT similar(cvdSim(a, tritanopia), cvdSim(b, tritanopia)) < 9 Palettes that will fail this test: @@ -415,7 +415,7 @@ Program: Description: All colors in a palette should be differentiable by people with grayscale . This is because if they are not, then they will not be differentiable from each other in some contexts. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), NOT similar(cvdSim(a, grayscale), cvdSim(b, grayscale)) < 9 +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT NOT similar(cvdSim(a, grayscale), cvdSim(b, grayscale)) < 9 Palettes that will fail this test: @@ -459,7 +459,7 @@ Program: Description: Axes should have low contrast with the background. Having it too high can make the axes too distracting. See "Whisper, Don't Scream: Grids and Transparency" for more. -Natural Language: ALL a in colors WHERE isTag(a, axis), contrast(a, background, Lstar) < 20 +Natural Language: ALL a IN colors WHERE isTag(a, axis) SUCH THAT contrast(a, background, Lstar) < 20 Palettes that will fail this test: @@ -500,7 +500,7 @@ Program: Description: Blue should be high probability for the basic color term blue. If it's not, it can be confusing to users. -Natural Language: ALL a in colors WHERE isTag(a, blue), name(a) == blue +Natural Language: ALL a IN colors WHERE isTag(a, blue) SUCH THAT name(a) == blue Palettes that will fail this test: @@ -540,7 +540,7 @@ Program: Description: Do the colors stand out equally? A color palette is described as fair if both chroma and luminance ranges are below a certain threshold and unfair if one of them is above a certain threshold. -Natural Language: (extent(sort(colors, x => lch.l(x))) < 50 and extent(sort(colors, x => lch.c(x))) < 80) +Natural Language: (extent(sort(colors, x => lch.l(x))) < 50 AND extent(sort(colors, x => lch.c(x))) < 80) Palettes that will fail this test: @@ -628,7 +628,7 @@ Program: Description: Background should be sufficiently desaturated. -Natural Language: (((hsl.l(background) > 90 and hsv.s(background) < 8) or hsl.l(background) > 99) or (hsl.l(background) > 10 and hsl.l(background) < 26 and hsv.s(background) < 21)) +Natural Language: (((hsl.l(background) > 90 AND hsv.s(background) < 8) OR hsl.l(background) > 99) OR (hsl.l(background) > 10 AND hsl.l(background) < 26 AND hsv.s(background) < 21)) Palettes that will fail this test: @@ -690,7 +690,7 @@ Program: Description: Tetradic palettes are hard to work with and are not recommended. -Natural Language: NOT EXIST a in colors, (EXIST b in colors, similar(hsl.h(a), hsl.h(b) + 90) < 5 and EXIST b in colors, similar(hsl.h(a), hsl.h(b) + 90) < 5 and EXIST b in colors, similar(hsl.h(a), hsl.h(b) + 90) < 5) +Natural Language: NOT EXIST a IN colors SUCH THAT (EXIST b IN colors SUCH THAT similar(hsl.h(a), hsl.h(b) + 90) < 5 AND EXIST b IN colors SUCH THAT similar(hsl.h(a), hsl.h(b) + 90) < 5 AND EXIST b IN colors SUCH THAT similar(hsl.h(a), hsl.h(b) + 90) < 5) Palettes that will fail this test: @@ -775,7 +775,7 @@ Program: Description: When using green, make it a yellow or blue one. This makes it easier to play nicely with other colors. -Natural Language: ALL a in colors, (hsl.h(a) < 90 or hsl.h(a) > 150) +Natural Language: ALL a IN colors SUCH THAT (hsl.h(a) < 90 OR hsl.h(a) > 150) Palettes that will fail this test: @@ -819,7 +819,7 @@ Program: Description: Don't make your colors too dark and saturated when you're using a bright background. If in doubt, try it out. Make your colors lighter, pull some saturation out of them and see how it feels. -Natural Language: ((hsl.l(background) > 50 and ALL a in colors, contrast(a, background, WCAG21) < 10) or hsl.l(background) < 50) +Natural Language: ((hsl.l(background) > 50 AND ALL a IN colors SUCH THAT contrast(a, background, WCAG21) < 10) OR hsl.l(background) < 50) Palettes that will fail this test: @@ -873,7 +873,7 @@ Program: Description: Use color complements whenever possible -Natural Language: EXIST (a, b) in colors, similar(hsl.h(a), hsl.h(b) + 180) < 5 +Natural Language: EXIST (a, b) IN colors SUCH THAT similar(hsl.h(a), hsl.h(b) + 180) < 5 Program: @@ -906,7 +906,7 @@ Program: Description: Pairs of colors in a palette should be differentiable from each other in Thin marks. -Natural Language: ALL (x, y) in colors WHERE index(x) != index(y), (lab.l(x) absDiff lab.l(y) > 12.58 or lab.a(x) absDiff lab.a(y) > 20.740000000000002 or lab.b(x) absDiff lab.b(y) > 34.05) +Natural Language: ALL (x, y) IN colors WHERE index(x) != index(y) SUCH THAT (absDiff(lab.l(x), lab.l(y)) > 12.58 OR absDiff(lab.a(x), lab.a(y)) > 20.740000000000002 OR absDiff(lab.b(x), lab.b(y)) > 34.05) Palettes that will fail this test: @@ -969,7 +969,7 @@ Program: Description: Pairs of colors in a palette should be differentiable from each other in Medium marks. -Natural Language: ALL (x, y) in colors WHERE index(x) != index(y), (lab.l(x) absDiff lab.l(y) > 6.58 or lab.a(x) absDiff lab.a(y) > 8.42 or lab.b(x) absDiff lab.b(y) > 11.09) +Natural Language: ALL (x, y) IN colors WHERE index(x) != index(y) SUCH THAT (absDiff(lab.l(x), lab.l(y)) > 6.58 OR absDiff(lab.a(x), lab.a(y)) > 8.42 OR absDiff(lab.b(x), lab.b(y)) > 11.09) Palettes that will fail this test: @@ -1032,7 +1032,7 @@ Program: Description: Pairs of colors in a palette should be differentiable from each other in Wide marks. -Natural Language: ALL (x, y) in colors WHERE index(x) != index(y), (lab.l(x) absDiff lab.l(y) > 5.83 or lab.a(x) absDiff lab.a(y) > 6.88 or lab.b(x) absDiff lab.b(y) > 8.219999999999999) +Natural Language: ALL (x, y) IN colors WHERE index(x) != index(y) SUCH THAT (absDiff(lab.l(x), lab.l(y)) > 5.83 OR absDiff(lab.a(x), lab.a(y)) > 6.88 OR absDiff(lab.b(x), lab.b(y)) > 8.219999999999999) Palettes that will fail this test: @@ -1095,7 +1095,7 @@ Program: Description: Colors at either end of the lightness spectrum can be hard to discriminate in some contexts, and are sometimes advised against. See https://blog.datawrapper.de/beautifulcolors/#6 for more. -Natural Language: ALL a in colors, ALL b in ([#000000, #ffffff, #0000ff, #ff0000, #00ff00]), NOT a == b +Natural Language: ALL a IN colors SUCH THAT ALL b IN ([#000000, #ffffff, #0000ff, #ff0000, #00ff00]) SUCH THAT NOT a == b Palettes that will fail this test: @@ -1138,7 +1138,7 @@ Program: Description: All colors in a palette should have a sufficient contrast ratio with the background color. This is because if they are not, then they will not be differentiable from each other in some contexts. Valid algorithms are "APCA", "WCAG21", "Michelson", "Weber", "Lstar", "DeltaPhi". -Natural Language: ALL a in colors, contrast(a, background, WCAG21) > 1.1 +Natural Language: ALL a IN colors SUCH THAT contrast(a, background, WCAG21) > 1.1 Palettes that will fail this test: @@ -1178,7 +1178,7 @@ Program: Description: Opt for colors that are perceptually distinguishable in a logical sequence when designing visual elements like charts or graphs. This ensures that viewers can easily recognize the order or progression of data points. For categorical this means that when only a small number of colors are used, they should be as different as possible. For sequential and diverging, this means that the colors should be as different as possible in order. -Natural Language: ALL (a, b) in colors WHERE index(a) == index(b) - 1, deltaE(a, b, 2000) > 10 +Natural Language: ALL (a, b) IN colors WHERE index(a) == index(b) - 1 SUCH THAT deltaE(a, b, 2000) > 10 Palettes that will fail this test: @@ -1224,7 +1224,7 @@ Program: Description: Categorical values should have an even distribution around the hue circle in LCH color space -Natural Language: (std(speed(sort(colors, x => lch.h(x)), => )) < 10 or std(speed(sort(colors, x => lch.h(x) + 180 % 360), => )) < 10) +Natural Language: (std(speed(sort(colors, x => lch.h(x)))) < 10 OR std(speed(sort(colors, x => lch.h(x) + 180 % 360))) < 10) Palettes that will fail this test: @@ -1289,7 +1289,7 @@ Program: Description: Checks if the colors are in the sRGB gamut. This is important to ensure that the colors are visible and can be displayed on most devices. -Natural Language: ALL a in colors, inGamut(a) == TRUE +Natural Language: ALL a IN colors SUCH THAT inGamut(a) == TRUE Palettes that will fail this test: @@ -1357,7 +1357,7 @@ Program: Description: All colors in a palette should be different from each other. This is because if they are not, then they will not be differentiable from each other in some contexts. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), dist(a, b, lab) > 15 +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT dist(a, b, lab) > 15 Palettes that will fail this test: @@ -1398,7 +1398,7 @@ Program: Description: Being able to identify colors by name is important for usability and for memorability. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), name(a) != name(b) +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT name(a) != name(b) Palettes that will fail this test: @@ -1436,7 +1436,7 @@ Program: Description: Sequential palettes should be ordered by lightness. This is a defining property of a sequential palette and ensures that values are understood as having an increase (or decreasing) value. -Natural Language: (sort(colors, x => lch.l(x)) == map(colors, x => lch.l(x)) or sort(colors, x => lch.l(x)) == reverse(map(colors, x => lch.l(x)), => )) +Natural Language: (sort(colors, x => lch.l(x)) == map(colors, x => lch.l(x)) OR sort(colors, x => lch.l(x)) == reverse(map(colors, x => lch.l(x)))) Palettes that will fail this test: @@ -1482,7 +1482,7 @@ Program: Description: Colors that are close to what are known as ugly colors are sometimes advised against. See https://www.colourlovers.com/palette/1416250/The_Ugliest_Colors for more details. -Natural Language: ALL a in colors, ALL b in ([#56FF00, #0010FF, #6A7E25, #FF00EF, #806E28]), deltaE(a, b, 2000) > 10 +Natural Language: ALL a IN colors SUCH THAT ALL b IN ([#56FF00, #0010FF, #6A7E25, #FF00EF, #806E28]) SUCH THAT deltaE(a, b, 2000) > 10 Palettes that will fail this test: diff --git a/src/lib/__snapshots__/LintDocs.test.ts.snap b/src/lib/__snapshots__/LintDocs.test.ts.snap index da115f0f..fa8d370c 100644 --- a/src/lib/__snapshots__/LintDocs.test.ts.snap +++ b/src/lib/__snapshots__/LintDocs.test.ts.snap @@ -93,7 +93,7 @@ Maps: Description: Highly saturated light colors are not appropriate for palettes that seek to be serious. See "Affective color in visualization" for more. -Natural Language: ALL c in colors WHERE hsl.l(c) > 70, NOT hsl.s(c) > 70 +Natural Language: ALL c IN colors WHERE hsl.l(c) > 70 SUCH THAT NOT hsl.s(c) > 70 Program: @@ -125,7 +125,7 @@ Program: Description: Highly saturated light colors are not appropriate for palettes that seek to be trustworthy. See "Affective color in visualization" for more. -Natural Language: ALL c in colors WHERE hsl.l(c) > 70, NOT hsl.s(c) > 70 +Natural Language: ALL c IN colors WHERE hsl.l(c) > 70 SUCH THAT NOT hsl.s(c) > 70 Program: @@ -157,7 +157,7 @@ Program: Description: Highly saturated light colors are not appropriate for palettes that seek to be calm. See "Affective color in visualization" for more. -Natural Language: ALL c in colors WHERE hsl.l(c) > 70, NOT hsl.s(c) > 70 +Natural Language: ALL c IN colors WHERE hsl.l(c) > 70 SUCH THAT NOT hsl.s(c) > 70 Program: @@ -189,7 +189,7 @@ Program: Description: Palettes that seek to be playful should have at least one light blue, beige, or gray. See "Affective color in visualization" for more. -Natural Language: EXIST c in colors, (similar(c, lightblue) < 20 or similar(c, beige) < 20 or similar(c, gray) < 20) +Natural Language: EXIST c IN colors SUCH THAT (similar(c, lightblue) < 20 OR similar(c, beige) < 20 OR similar(c, gray) < 20) Program: @@ -220,7 +220,7 @@ Program: Description: Palettes that seek to be positive should not have dark reds or browns. See "Affective color in visualization" for more. -Natural Language: ALL c in colors, NOT (similar(c, darkred) < 20 or similar(c, brown) < 20) +Natural Language: ALL c IN colors SUCH THAT NOT (similar(c, darkred) < 20 OR similar(c, brown) < 20) Program: @@ -252,7 +252,7 @@ Program: Description: Palettes that seek to be negative should not have light colors, particularly greens. See "Affective color in visualization" for more. -Natural Language: ALL c in colors, NOT (similar(c, green) < 20 or lab.l(c) > 70) +Natural Language: ALL c IN colors SUCH THAT NOT (similar(c, green) < 20 OR lab.l(c) > 70) Program: @@ -286,7 +286,7 @@ Program: Description: All colors in a palette should be differentiable by people with deuteranopia (ie can't see green). This is because if they are not, then they will not be differentiable from each other in some contexts. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), NOT similar(cvdSim(a, deuteranopia), cvdSim(b, deuteranopia)) < 9 +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT NOT similar(cvdSim(a, deuteranopia), cvdSim(b, deuteranopia)) < 9 Palettes that will fail this test: @@ -330,7 +330,7 @@ Program: Description: All colors in a palette should be differentiable by people with protanopia (ie can't see red). This is because if they are not, then they will not be differentiable from each other in some contexts. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), NOT similar(cvdSim(a, protanopia), cvdSim(b, protanopia)) < 9 +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT NOT similar(cvdSim(a, protanopia), cvdSim(b, protanopia)) < 9 Palettes that will fail this test: @@ -374,7 +374,7 @@ Program: Description: All colors in a palette should be differentiable by people with tritanopia (ie can't see blue). This is because if they are not, then they will not be differentiable from each other in some contexts. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), NOT similar(cvdSim(a, tritanopia), cvdSim(b, tritanopia)) < 9 +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT NOT similar(cvdSim(a, tritanopia), cvdSim(b, tritanopia)) < 9 Palettes that will fail this test: @@ -418,7 +418,7 @@ Program: Description: All colors in a palette should be differentiable by people with grayscale . This is because if they are not, then they will not be differentiable from each other in some contexts. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), NOT similar(cvdSim(a, grayscale), cvdSim(b, grayscale)) < 9 +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT NOT similar(cvdSim(a, grayscale), cvdSim(b, grayscale)) < 9 Palettes that will fail this test: @@ -462,7 +462,7 @@ Program: Description: Axes should have low contrast with the background. Having it too high can make the axes too distracting. See "Whisper, Don't Scream: Grids and Transparency" for more. -Natural Language: ALL a in colors WHERE isTag(a, axis), contrast(a, background, Lstar) < 20 +Natural Language: ALL a IN colors WHERE isTag(a, axis) SUCH THAT contrast(a, background, Lstar) < 20 Palettes that will fail this test: @@ -503,7 +503,7 @@ Program: Description: Blue should be high probability for the basic color term blue. If it's not, it can be confusing to users. -Natural Language: ALL a in colors WHERE isTag(a, blue), name(a) == blue +Natural Language: ALL a IN colors WHERE isTag(a, blue) SUCH THAT name(a) == blue Palettes that will fail this test: @@ -543,7 +543,7 @@ Program: Description: Do the colors stand out equally? A color palette is described as fair if both chroma and luminance ranges are below a certain threshold and unfair if one of them is above a certain threshold. -Natural Language: (extent(sort(colors, x => lch.l(x))) < 50 and extent(sort(colors, x => lch.c(x))) < 80) +Natural Language: (extent(sort(colors, x => lch.l(x))) < 50 AND extent(sort(colors, x => lch.c(x))) < 80) Palettes that will fail this test: @@ -631,7 +631,7 @@ Program: Description: Background should be sufficiently desaturated. -Natural Language: (((hsl.l(background) > 90 and hsv.s(background) < 8) or hsl.l(background) > 99) or (hsl.l(background) > 10 and hsl.l(background) < 26 and hsv.s(background) < 21)) +Natural Language: (((hsl.l(background) > 90 AND hsv.s(background) < 8) OR hsl.l(background) > 99) OR (hsl.l(background) > 10 AND hsl.l(background) < 26 AND hsv.s(background) < 21)) Palettes that will fail this test: @@ -693,7 +693,7 @@ Program: Description: Tetradic palettes are hard to work with and are not recommended. -Natural Language: NOT EXIST a in colors, (EXIST b in colors, similar(hsl.h(a), hsl.h(b) + 90) < 5 and EXIST b in colors, similar(hsl.h(a), hsl.h(b) + 90) < 5 and EXIST b in colors, similar(hsl.h(a), hsl.h(b) + 90) < 5) +Natural Language: NOT EXIST a IN colors SUCH THAT (EXIST b IN colors SUCH THAT similar(hsl.h(a), hsl.h(b) + 90) < 5 AND EXIST b IN colors SUCH THAT similar(hsl.h(a), hsl.h(b) + 90) < 5 AND EXIST b IN colors SUCH THAT similar(hsl.h(a), hsl.h(b) + 90) < 5) Palettes that will fail this test: @@ -778,7 +778,7 @@ Program: Description: When using green, make it a yellow or blue one. This makes it easier to play nicely with other colors. -Natural Language: ALL a in colors, (hsl.h(a) < 90 or hsl.h(a) > 150) +Natural Language: ALL a IN colors SUCH THAT (hsl.h(a) < 90 OR hsl.h(a) > 150) Palettes that will fail this test: @@ -822,7 +822,7 @@ Program: Description: Don't make your colors too dark and saturated when you're using a bright background. If in doubt, try it out. Make your colors lighter, pull some saturation out of them and see how it feels. -Natural Language: ((hsl.l(background) > 50 and ALL a in colors, contrast(a, background, WCAG21) < 10) or hsl.l(background) < 50) +Natural Language: ((hsl.l(background) > 50 AND ALL a IN colors SUCH THAT contrast(a, background, WCAG21) < 10) OR hsl.l(background) < 50) Palettes that will fail this test: @@ -876,7 +876,7 @@ Program: Description: Use color complements whenever possible -Natural Language: EXIST (a, b) in colors, similar(hsl.h(a), hsl.h(b) + 180) < 5 +Natural Language: EXIST (a, b) IN colors SUCH THAT similar(hsl.h(a), hsl.h(b) + 180) < 5 Program: @@ -909,7 +909,7 @@ Program: Description: Pairs of colors in a palette should be differentiable from each other in Thin marks. -Natural Language: ALL (x, y) in colors WHERE index(x) != index(y), (lab.l(x) absDiff lab.l(y) > 12.58 or lab.a(x) absDiff lab.a(y) > 20.740000000000002 or lab.b(x) absDiff lab.b(y) > 34.05) +Natural Language: ALL (x, y) IN colors WHERE index(x) != index(y) SUCH THAT (absDiff(lab.l(x), lab.l(y)) > 12.58 OR absDiff(lab.a(x), lab.a(y)) > 20.740000000000002 OR absDiff(lab.b(x), lab.b(y)) > 34.05) Palettes that will fail this test: @@ -972,7 +972,7 @@ Program: Description: Pairs of colors in a palette should be differentiable from each other in Medium marks. -Natural Language: ALL (x, y) in colors WHERE index(x) != index(y), (lab.l(x) absDiff lab.l(y) > 6.58 or lab.a(x) absDiff lab.a(y) > 8.42 or lab.b(x) absDiff lab.b(y) > 11.09) +Natural Language: ALL (x, y) IN colors WHERE index(x) != index(y) SUCH THAT (absDiff(lab.l(x), lab.l(y)) > 6.58 OR absDiff(lab.a(x), lab.a(y)) > 8.42 OR absDiff(lab.b(x), lab.b(y)) > 11.09) Palettes that will fail this test: @@ -1035,7 +1035,7 @@ Program: Description: Pairs of colors in a palette should be differentiable from each other in Wide marks. -Natural Language: ALL (x, y) in colors WHERE index(x) != index(y), (lab.l(x) absDiff lab.l(y) > 5.83 or lab.a(x) absDiff lab.a(y) > 6.88 or lab.b(x) absDiff lab.b(y) > 8.219999999999999) +Natural Language: ALL (x, y) IN colors WHERE index(x) != index(y) SUCH THAT (absDiff(lab.l(x), lab.l(y)) > 5.83 OR absDiff(lab.a(x), lab.a(y)) > 6.88 OR absDiff(lab.b(x), lab.b(y)) > 8.219999999999999) Palettes that will fail this test: @@ -1098,7 +1098,7 @@ Program: Description: Colors at either end of the lightness spectrum can be hard to discriminate in some contexts, and are sometimes advised against. See https://blog.datawrapper.de/beautifulcolors/#6 for more. -Natural Language: ALL a in colors, ALL b in ([#000000, #ffffff, #0000ff, #ff0000, #00ff00]), NOT a == b +Natural Language: ALL a IN colors SUCH THAT ALL b IN ([#000000, #ffffff, #0000ff, #ff0000, #00ff00]) SUCH THAT NOT a == b Palettes that will fail this test: @@ -1141,7 +1141,7 @@ Program: Description: All colors in a palette should have a sufficient contrast ratio with the background color. This is because if they are not, then they will not be differentiable from each other in some contexts. Valid algorithms are "APCA", "WCAG21", "Michelson", "Weber", "Lstar", "DeltaPhi". -Natural Language: ALL a in colors, contrast(a, background, WCAG21) > 1.1 +Natural Language: ALL a IN colors SUCH THAT contrast(a, background, WCAG21) > 1.1 Palettes that will fail this test: @@ -1181,7 +1181,7 @@ Program: Description: Opt for colors that are perceptually distinguishable in a logical sequence when designing visual elements like charts or graphs. This ensures that viewers can easily recognize the order or progression of data points. For categorical this means that when only a small number of colors are used, they should be as different as possible. For sequential and diverging, this means that the colors should be as different as possible in order. -Natural Language: ALL (a, b) in colors WHERE index(a) == index(b) - 1, deltaE(a, b, 2000) > 10 +Natural Language: ALL (a, b) IN colors WHERE index(a) == index(b) - 1 SUCH THAT deltaE(a, b, 2000) > 10 Palettes that will fail this test: @@ -1227,7 +1227,7 @@ Program: Description: Categorical values should have an even distribution around the hue circle in LCH color space -Natural Language: (std(speed(sort(colors, x => lch.h(x)), => )) < 10 or std(speed(sort(colors, x => lch.h(x) + 180 % 360), => )) < 10) +Natural Language: (std(speed(sort(colors, x => lch.h(x)))) < 10 OR std(speed(sort(colors, x => lch.h(x) + 180 % 360))) < 10) Palettes that will fail this test: @@ -1292,7 +1292,7 @@ Program: Description: Checks if the colors are in the sRGB gamut. This is important to ensure that the colors are visible and can be displayed on most devices. -Natural Language: ALL a in colors, inGamut(a) == TRUE +Natural Language: ALL a IN colors SUCH THAT inGamut(a) == TRUE Palettes that will fail this test: @@ -1360,7 +1360,7 @@ Program: Description: All colors in a palette should be different from each other. This is because if they are not, then they will not be differentiable from each other in some contexts. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), dist(a, b, lab) > 15 +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT dist(a, b, lab) > 15 Palettes that will fail this test: @@ -1401,7 +1401,7 @@ Program: Description: Being able to identify colors by name is important for usability and for memorability. -Natural Language: ALL (a, b) in colors WHERE index(a) != index(b), name(a) != name(b) +Natural Language: ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT name(a) != name(b) Palettes that will fail this test: @@ -1439,7 +1439,7 @@ Program: Description: Sequential palettes should be ordered by lightness. This is a defining property of a sequential palette and ensures that values are understood as having an increase (or decreasing) value. -Natural Language: (sort(colors, x => lch.l(x)) == map(colors, x => lch.l(x)) or sort(colors, x => lch.l(x)) == reverse(map(colors, x => lch.l(x)), => )) +Natural Language: (sort(colors, x => lch.l(x)) == map(colors, x => lch.l(x)) OR sort(colors, x => lch.l(x)) == reverse(map(colors, x => lch.l(x)))) Palettes that will fail this test: @@ -1485,7 +1485,7 @@ Program: Description: Colors that are close to what are known as ugly colors are sometimes advised against. See https://www.colourlovers.com/palette/1416250/The_Ugliest_Colors for more details. -Natural Language: ALL a in colors, ALL b in ([#56FF00, #0010FF, #6A7E25, #FF00EF, #806E28]), deltaE(a, b, 2000) > 10 +Natural Language: ALL a IN colors SUCH THAT ALL b IN ([#56FF00, #0010FF, #6A7E25, #FF00EF, #806E28]) SUCH THAT deltaE(a, b, 2000) > 10 Palettes that will fail this test: diff --git a/src/lib/lint-language/LintLanguage.test.ts b/src/lib/lint-language/LintLanguage.test.ts index a2b26c20..881bd073 100644 --- a/src/lib/lint-language/LintLanguage.test.ts +++ b/src/lib/lint-language/LintLanguage.test.ts @@ -84,7 +84,7 @@ test("LintLanguage conjunctions", () => { }; expect(LLEval(prog1, exampleColors).result).toBe(true); expect(prettyPrintLL(prog1)).toBe( - "(count(colors) < 10 and count(colors) > 2)" + "(count(colors) < 10 AND count(colors) > 2)" ); const prog2 = { @@ -95,7 +95,7 @@ test("LintLanguage conjunctions", () => { }; expect(LLEval(prog2, exampleColors).result).toBe(false); expect(prettyPrintLL(prog2)).toBe( - "(count(colors) < 2 or count(colors) > 10)" + "(count(colors) < 2 OR count(colors) > 10)" ); }); @@ -114,14 +114,14 @@ test("LintLanguage Quantifiers All - Simple", () => { }, }); expect(prettyPrintLL(simpProg(["red"]))).toBe( - "EXIST a in colors, EXIST b in ([#f00]), a == b" + "EXIST a IN colors SUCH THAT EXIST b IN ([#f00]) SUCH THAT a == b" ); const redResult = LLEval(simpProg(["red"]), exampleColors); expect(redResult.result).toBe(false); expect(redResult.blame).toStrictEqual([0, 1, 2]); expect(prettyPrintLL(simpProg(["#7bb9ff"]))).toBe( - "EXIST a in colors, EXIST b in ([#7bb9ff]), a == b" + "EXIST a IN colors SUCH THAT EXIST b IN ([#7bb9ff]) SUCH THAT a == b" ); expect(LLEval(simpProg(["#7bb9ff"]), exampleColors).result).toBe(true); }); @@ -156,14 +156,14 @@ test("LintLanguage permutativeBlame - Quantifiers Simple", () => { }); test("LintLanguage permutativeBlame - Quantifiers deuteranopia", () => { - const prog = allBlindProg("deuteranopia"); + const prog = allCVDProg("deuteranopia"); const pal = toPal(["#d4a8ff", "#7bb9ff", "#008694", "black"]); expect(permutativeBlame(prog, pal, "single")).toStrictEqual([0, 1]); expect(permutativeBlame(prog, pal, "pair")).toStrictEqual([[0, 1]]); }); test("LintLanguage permutativeBlame - Tableau 10", () => { - const prog = allBlindProg("deuteranopia"); + const prog = allCVDProg("deuteranopia"); const pal = toPal([ "#1f77b4", "#ff7f0e", @@ -184,9 +184,9 @@ test("LintLanguage permutativeBlame - Tableau 10", () => { ]); }); -const expectedOutBlind = (type: string) => - `ALL a in colors, ALL b in colors WHERE index(a) != index(b), NOT similar(cvdSim(a, ${type}), cvdSim(b, ${type})) < 9`; -const allBlindProg = (type: string) => ({ +const expectedOutCVD = (type: string) => + `ALL a IN colors SUCH THAT ALL b IN colors WHERE index(a) != index(b) SUCH THAT NOT similar(cvdSim(a, ${type}), cvdSim(b, ${type})) < 9`; +const allCVDProg = (type: string) => ({ all: { in: "colors", varb: "a", @@ -209,23 +209,23 @@ const allBlindProg = (type: string) => ({ }, }); test("LintLanguage Quantifiers All - deuteranopia", () => { - expect(prettyPrintLL(allBlindProg("deuteranopia"))).toBe( - expectedOutBlind("deuteranopia") + expect(prettyPrintLL(allCVDProg("deuteranopia"))).toBe( + expectedOutCVD("deuteranopia") ); - const cbResult = LLEval(allBlindProg("deuteranopia"), exampleColors); + const cbResult = LLEval(allCVDProg("deuteranopia"), exampleColors); expect(cbResult.result).toBe(false); expect(cbResult.blame).toStrictEqual([0, 1]); }); test("LintLanguage Quantifiers All - protanopia", () => { - expect(prettyPrintLL(allBlindProg("protanopia"))).toBe( - expectedOutBlind("protanopia") + expect(prettyPrintLL(allCVDProg("protanopia"))).toBe( + expectedOutCVD("protanopia") ); - const cbResult = LLEval(allBlindProg("protanopia"), exampleColors); + const cbResult = LLEval(allCVDProg("protanopia"), exampleColors); expect(cbResult.result).toBe(false); expect(cbResult.blame).toStrictEqual([0, 1]); }); test("LintLanguage Quantifiers All - tritanopia", () => { - const cbResult = LLEval(allBlindProg("tritanopia"), exampleColors); + const cbResult = LLEval(allCVDProg("tritanopia"), exampleColors); expect(cbResult.result).toBe(true); expect(cbResult.blame).toStrictEqual([]); }); @@ -261,7 +261,7 @@ test("LintLanguage Quantifiers Exist", () => { }, }; expect(prettyPrintLL(colorBlindExists)).toBe( - "NOT EXIST a in colors, EXIST b in colors, cvdSim(a, deuteranopia) != cvdSim(b, deuteranopia)" + "NOT EXIST a IN colors SUCH THAT EXIST b IN colors SUCH THAT cvdSim(a, deuteranopia) != cvdSim(b, deuteranopia)" ); expect(LLEval(colorBlindExists, exampleColors).result).toBe(false); }); @@ -282,7 +282,7 @@ test("LintLanguage Quantifiers Exist - DENSE", () => { }, }; expect(prettyPrintLL(colorBlindExists)).toBe( - "NOT EXIST (a, b) in colors, cvdSim(a, deuteranopia) != cvdSim(b, deuteranopia)" + "NOT EXIST (a, b) IN colors SUCH THAT cvdSim(a, deuteranopia) != cvdSim(b, deuteranopia)" ); expect(LLEval(colorBlindExists, exampleColors).result).toBe(false); }); @@ -304,7 +304,7 @@ test("LintLanguage Quantifiers All - DENSE", () => { }, }; expect(prettyPrintLL(colorBlindExists)).toBe( - "ALL (a, b) in colors, NOT similar(cvdSim(a, deuteranopia), cvdSim(b, deuteranopia)) < 9" + "ALL (a, b) IN colors SUCH THAT NOT similar(cvdSim(a, deuteranopia), cvdSim(b, deuteranopia)) < 9" ); expect(LLEval(colorBlindExists, exampleColors).result).toBe(false); }); @@ -317,7 +317,9 @@ test("LintLanguage Check exists", () => { predicate: { "==": { left: "a", right: "#1fbad6" } }, }, }; - expect(prettyPrintLL(program)).toBe("EXIST a in colors, a == #1fbad6"); + expect(prettyPrintLL(program)).toBe( + "EXIST a IN colors SUCH THAT a == #1fbad6" + ); expect(LLEval(program, exampleColors).result).toBe(false); const program2 = { @@ -327,7 +329,9 @@ test("LintLanguage Check exists", () => { predicate: { "!=": { left: "a", right: "#1fbad6" } }, }, }; - expect(prettyPrintLL(program2)).toBe("EXIST a in colors, a != #1fbad6"); + expect(prettyPrintLL(program2)).toBe( + "EXIST a IN colors SUCH THAT a != #1fbad6" + ); expect(LLEval(program2, exampleColors).result).toBe(true); }); @@ -452,7 +456,7 @@ test("LintLanguage to color rotate", () => { }, }; expect(prettyPrintLL(realisticProgram)).toBe( - "EXIST a in colors, EXIST b in colors, similar(hsl.h(a), hsl.h(b) + 180) < 5" + "EXIST a IN colors SUCH THAT EXIST b IN colors SUCH THAT similar(hsl.h(a), hsl.h(b) + 180) < 5" ); expect(LLEval(realisticProgram, exampleColors).result).toBe(false); }); @@ -472,7 +476,7 @@ test("LintLanguage Name discrimination", () => { }, }; expect(prettyPrintLL(program)).toBe( - "ALL (a, b) in colors WHERE index(a) != index(b), name(a) != name(b)" + "ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT name(a) != name(b)" ); const greenResult = LLEval(program, greens); expect(greenResult.result).toBe(false); @@ -493,7 +497,7 @@ test("LintLanguage Name discrimination - dense notation", () => { }, }; expect(prettyPrintLL(program)).toBe( - "ALL (a, b) in colors WHERE index(a) != index(b), name(a) != name(b)" + "ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT name(a) != name(b)" ); expect(LLEval(program, greens).result).toBe(false); expect(LLEval(program, reds).result).toBe(true); @@ -518,7 +522,7 @@ test("LintLanguage Name discrimination with a single color", () => { }, }; expect(prettyPrintLL(program)).toBe( - "ALL a in colors, ALL b in colors WHERE index(a) != index(b), name(a) != name(b)" + "ALL a IN colors SUCH THAT ALL b IN colors WHERE index(a) != index(b) SUCH THAT name(a) != name(b)" ); const result = LLEval(program, toPal(["#008137"])); expect(result.result).toBe(true); @@ -589,7 +593,7 @@ test("LintLanguage Avoid Extreme Colors", () => { }, }; expect(prettyPrintLL(program)).toBe( - "ALL a in colors, ALL b in ([#000000, #ffffff]), a != b" + "ALL a IN colors SUCH THAT ALL b IN ([#000000, #ffffff]) SUCH THAT a != b" ); const { result, blame } = LLEval(program, greens); expect(result).toBe(true); @@ -617,7 +621,7 @@ test("LintLanguage Avoid Extreme Colors Swapped Predicate Order (blame test)", ( }, }; expect(prettyPrintLL(program)).toBe( - "ALL a in ([#000000, #ffffff]), ALL b in colors, a != b" + "ALL a IN ([#000000, #ffffff]) SUCH THAT ALL b IN colors SUCH THAT a != b" ); const { result, blame } = LLEval(program, greens); expect(result).toBe(true); @@ -674,7 +678,7 @@ test("LintLanguage Sequential Colors", () => { const inOrder = toPal(["#d4a8ff", "#7bb9ff", "#008694"]); expect(LLEval(program, inOrder).result).toBe(true); expect(prettyPrintLL(program)).toBe( - "(ALL (a, b) in colors WHERE index(a) - 1 == index(b), lab.l(a) > lab.l(b) or ALL (a, b) in colors WHERE index(a) - 1 == index(b), lab.l(a) < lab.l(b))" + "(ALL (a, b) IN colors WHERE index(a) - 1 == index(b) SUCH THAT lab.l(a) > lab.l(b) OR ALL (a, b) IN colors WHERE index(a) - 1 == index(b) SUCH THAT lab.l(a) < lab.l(b))" ); }); @@ -762,7 +766,9 @@ test("LintLanguage Background differentiability", () => { }, }; const astString = prettyPrintLL(program); - expect(astString).toBe("ALL a in colors, NOT similar(a, background) < 15"); + expect(astString).toBe( + "ALL a IN colors SUCH THAT NOT similar(a, background) < 15" + ); const result = LLEval(program, toPal(["#fff", "#eee", "#000", "#ddd"])); expect(result.result).toBe(false); expect(result.blame).toStrictEqual([0, 1, 3]); @@ -781,7 +787,7 @@ test("LintLanguage Sequential Similarity", () => { }; const astString = prettyPrintLL(program); expect(astString).toBe( - "ALL (a, b) in colors WHERE index(a) != index(b), NOT similar(a, b) < 10" + "ALL (a, b) IN colors WHERE index(a) != index(b) SUCH THAT NOT similar(a, b) < 10" ); const result = LLEval(program, toPal(["#fff", "#eee", "#000", "#ddd"])); expect(result.result).toBe(false); diff --git a/src/lib/lint-language/lint-language.ts b/src/lib/lint-language/lint-language.ts index 2c26a564..01225343 100644 --- a/src/lib/lint-language/lint-language.ts +++ b/src/lib/lint-language/lint-language.ts @@ -243,7 +243,9 @@ export class LLConjunction extends LLNode { if (this.type === "id") return this.children[0].toString(); if (this.type === "none") return ""; if (this.type === "not") return `NOT ${this.children[0].toString()}`; - return `(${this.children.map((x) => x.toString()).join(` ${this.type} `)})`; + return `(${this.children + .map((x) => x.toString()) + .join(` ${this.type.toUpperCase()} `)})`; } } @@ -395,7 +397,12 @@ export class LLNumberOp extends LLNode { return new LLNumberOp(opType, leftType, rightType); } toString(): string { - return `${this.left.toString()} ${this.type} ${this.right.toString()}`; + const left = this.left.toString(); + const right = this.right.toString(); + if (this.type === "absDiff") { + return `absDiff(${left}, ${right})`; + } + return `${left} ${this.type} ${right}`; } } @@ -896,7 +903,7 @@ export class LLQuantifier extends LLNode { } // const type = this.type === "exist" ? "∃" : "∀"; const type = this.type.toUpperCase(); - return `${type} ${varbs} in ${targ}${where}, ${this.predicate.toString()}`; + return `${type} ${varbs} IN ${targ}${where} SUCH THAT ${this.predicate.toString()}`; } } @@ -1087,9 +1094,10 @@ export class LLMap extends LLNode { } toString(): string { const type = this.type; - return `${type}(${this.children.toString()}, ${ - this.varb - } => ${this.func.toString()})`; + const funcStr = this.func.toString(); + const func = + this.varb != " " && funcStr != " " ? `, ${this.varb} => ${funcStr}` : ""; + return `${type}(${this.children.toString()}${func})`; } } diff --git a/src/linting/LintCustomizationTab.svelte b/src/linting/LintCustomizationTab.svelte index 164a7795..41b4018e 100644 --- a/src/linting/LintCustomizationTab.svelte +++ b/src/linting/LintCustomizationTab.svelte @@ -311,6 +311,10 @@ }} /> +
+
Lint Self Description (from the program):
+
{lintRun?.naturalLanguageProgram}
+
Show Compare Debug In Terminal