From 672e357070ddaf11ab0e799678f087327446c0c4 Mon Sep 17 00:00:00 2001
From: Andrew McNutt <mcnutt.andrew@gmail.com>
Date: Sun, 15 Sep 2024 15:59:57 -0700
Subject: [PATCH] Ignore specific colors (#114)

* Ignore specific colors

* clean up

* presentation tweaks
---
 .../src/linting/EvalResponse.svelte           | 28 +++++++++++++++++++
 .../src/linting/LintDisplay.svelte            | 26 +++++++++++++++++
 apps/color-buddy/src/stores/config-store.ts   |  1 -
 packages/palette-lint/src/linter.ts           |  8 +++++-
 4 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/apps/color-buddy/src/linting/EvalResponse.svelte b/apps/color-buddy/src/linting/EvalResponse.svelte
index 4ad8811e..8528afd9 100644
--- a/apps/color-buddy/src/linting/EvalResponse.svelte
+++ b/apps/color-buddy/src/linting/EvalResponse.svelte
@@ -84,6 +84,9 @@
     (x) => lintProgram.description.toLowerCase().includes(x) && x !== colorSpace
   ) as any;
   $: ignored = !!evalConfig[lintProgram.name]?.ignore;
+  $: blameData = (
+    lintResult.kind === "success" ? lintResult.blameData : []
+  ).flat();
 </script>
 
 <Tooltip {positionAlongRightEdge}>
@@ -172,6 +175,31 @@
       </button>
     {/if}
 
+    <div>For just this lint</div>
+    {#each blameData as index}
+      <button
+        class={buttonStyle
+          .split(" ")
+          .filter((x) => x !== "opacity-50")
+          .join(" ")}
+        on:click={() => {
+          colorStore.setCurrentPalEvalConfig({
+            ...evalConfig,
+            [`${palette.colors[index].toHex()}-?-${lintProgram.id}`]: {
+              ignore: true,
+            },
+          });
+        }}
+      >
+        <span class="opacity-50">ignore ({palette.colors[index].toHex()})</span>
+
+        <div
+          class="rounded-full w-3 h-3 ml-1 inline-block opacity-100"
+          style={`background: ${palette.colors[index].toHex()}`}
+        />
+      </button>
+    {/each}
+
     {#if requestState === "loading"}
       <div>Loading...</div>
     {:else if requestState === "failed"}
diff --git a/apps/color-buddy/src/linting/LintDisplay.svelte b/apps/color-buddy/src/linting/LintDisplay.svelte
index 0cf08b2d..6ccba9e9 100644
--- a/apps/color-buddy/src/linting/LintDisplay.svelte
+++ b/apps/color-buddy/src/linting/LintDisplay.svelte
@@ -14,6 +14,12 @@
   $: evalConfig = currentPal.evalConfig;
   $: lintProgram = lintResult.lintProgram;
   $: isCompact = $configStore.evalDisplayMode === "compact";
+  $: ignoredColors = Object.entries(evalConfig)
+    .filter(
+      ([name, config]) =>
+        (name.split("-?-")[1] || "").trim() === lintProgram.id && config.ignore
+    )
+    .map(([name]) => name.split("-?-")[0]);
 </script>
 
 {#if lintResult.kind === "ignored"}
@@ -61,6 +67,26 @@
         </div>
         <EvalResponse {lintResult} />
       </div>
+      {#if ignoredColors.length > 0 && !isCompact}
+        <div class="text-sm italic">
+          Ignored colors for this lint:
+          {#each ignoredColors as color}
+            <div class="inline-block relative w-3 h-3 mx-1">
+              <button
+                on:click={() => {
+                  colorStore.setCurrentPalEvalConfig({
+                    ...evalConfig,
+                    [`${color}-?-${lintProgram.id}`]: { ignore: false },
+                  });
+                }}
+                class="rounded-full w-3 h-3 bottom-0 absolute inline-block opacity-100"
+                style={`background: ${color}`}
+              />
+            </div>
+          {/each}
+          (click to re-enable)
+        </div>
+      {/if}
       {#if lintResult.kind === "success" && !lintResult.passes && !isCompact}
         <ExplanationViewer {lintResult} />
       {/if}
diff --git a/apps/color-buddy/src/stores/config-store.ts b/apps/color-buddy/src/stores/config-store.ts
index 7021a308..6f2991b0 100644
--- a/apps/color-buddy/src/stores/config-store.ts
+++ b/apps/color-buddy/src/stores/config-store.ts
@@ -95,7 +95,6 @@ function hydrateStore(): StoreData {
   if (str === "undefined") {
     str = JSON.stringify(InitialStore);
   }
-  console.log(str, localStorage.getItem(storeName));
   const store = addDefaults(JSON.parse(str));
   if (store.tempPal) {
     store.tempPal = stringPalToColorPal(store.tempPal as any);
diff --git a/packages/palette-lint/src/linter.ts b/packages/palette-lint/src/linter.ts
index ea959a96..ad8edfeb 100644
--- a/packages/palette-lint/src/linter.ts
+++ b/packages/palette-lint/src/linter.ts
@@ -77,6 +77,12 @@ function processLint(
   if (!ignored) {
     return { kind: "ignored", lintProgram: lint };
   }
+  // ignored colors
+  let pal = { ...palette };
+  pal.colors = palette.colors.filter((color) => {
+    const key = `${color.toHex()}-?-${lint.id}`;
+    return palette.evalConfig[key]?.ignore !== true;
+  });
 
   // run the lint
   if (prebuiltIdToCustomFunc[lint.id]) {
@@ -84,7 +90,7 @@ function processLint(
   }
   let result: LintResult;
   try {
-    result = RunLint(lint, palette, options);
+    result = RunLint(lint, pal, options);
   } catch (e) {
     console.error(e);
     result = { kind: "invalid", lintProgram: lint };