mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Ban the null literal via ESLint and replace existing usages with undefined or truthiness checks (#4401)
This commit is contained in:
committed by
Dennis Kobert
parent
4f318bbdae
commit
6cb4490137
@@ -73,6 +73,13 @@ export default defineConfig([
|
||||
],
|
||||
},
|
||||
],
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
selector: "Literal[raw='null']",
|
||||
message: "Use `undefined` instead of `null`.",
|
||||
},
|
||||
],
|
||||
|
||||
// TypeScript plugin config (for TS-specific linting)
|
||||
"@typescript-eslint/indent": "off",
|
||||
@@ -96,7 +103,7 @@ export default defineConfig([
|
||||
"@typescript-eslint/consistent-type-assertions": ["error", { assertionStyle: "never" }],
|
||||
"@typescript-eslint/consistent-indexed-object-style": ["error", "record"],
|
||||
"@typescript-eslint/consistent-generic-constructors": ["error", "constructor"],
|
||||
"@typescript-eslint/no-restricted-types": ["error", { types: { null: "Use `undefined` instead." } }],
|
||||
"@typescript-eslint/no-restricted-types": ["error", { types: { null: "Use `undefined` instead of `null`." } }],
|
||||
|
||||
// Prettier plugin config (for validating and fixing formatting)
|
||||
"prettier/prettier": "error",
|
||||
|
||||
@@ -28,7 +28,7 @@ export function createSRgba8FromHsva(h: number, s: number, v: number, a: number)
|
||||
// COLOR UTILITY FUNCTIONS
|
||||
|
||||
export function isSRgba8(value: unknown): value is SRGBA8 {
|
||||
return typeof value === "object" && value !== null && "red" in value;
|
||||
return !!value && typeof value === "object" && "red" in value;
|
||||
}
|
||||
|
||||
// Parse a CSS color string into an `SRGBA8`. Uses a canvas to delegate parsing to the browser.
|
||||
@@ -183,11 +183,11 @@ export function contrastingOutlineFactor(value: FillChoice<SRGBA8>, proximityCol
|
||||
// GRADIENT UTILITY FUNCTIONS
|
||||
|
||||
export function isGradientStops(value: unknown): value is GradientStops<SRGBA8> {
|
||||
return typeof value === "object" && value !== null && "color" in value && Array.isArray(value.color);
|
||||
return !!value && typeof value === "object" && "color" in value && Array.isArray(value.color);
|
||||
}
|
||||
|
||||
export function isGradientRamp(value: unknown): value is GradientRamp<SRGBA8> {
|
||||
return typeof value === "object" && value !== null && "stops" in value && isGradientStops(value.stops);
|
||||
return !!value && typeof value === "object" && "stops" in value && isGradientStops(value.stops);
|
||||
}
|
||||
|
||||
// FILL CHOICE UTILITY FUNCTIONS
|
||||
@@ -203,8 +203,7 @@ export function fillChoiceGradient(value: FillChoice<SRGBA8>): GradientStops<SRG
|
||||
}
|
||||
|
||||
export function parseFillChoice(value: unknown): FillChoice<SRGBA8> {
|
||||
if (value === "None" || value === undefined || value === null) return "None";
|
||||
if (typeof value === "object" && value !== null && "Solid" in value && isSRgba8(value.Solid)) return { Solid: value.Solid };
|
||||
if (typeof value === "object" && value !== null && "Gradient" in value && isGradientRamp(value.Gradient)) return { Gradient: value.Gradient };
|
||||
if (value && typeof value === "object" && "Solid" in value && isSRgba8(value.Solid)) return { Solid: value.Solid };
|
||||
if (value && typeof value === "object" && "Gradient" in value && isGradientRamp(value.Gradient)) return { Gradient: value.Gradient };
|
||||
return "None";
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ function targetIsTextField(target: EventTarget | HTMLElement | undefined): boole
|
||||
|
||||
function potentiallyRestoreCanvasFocus(e: Event) {
|
||||
const appElement = window.document.querySelector("[data-app-container]");
|
||||
const app = appElement instanceof HTMLElement ? appElement : null;
|
||||
const app = appElement instanceof HTMLElement ? appElement : undefined;
|
||||
|
||||
const newInCanvasArea =
|
||||
(e.target instanceof Element && e.target.closest("[data-viewport], [data-viewport-container], [data-graph]")) instanceof Element &&
|
||||
|
||||
@@ -147,7 +147,7 @@ async function migrateToNewFormat() {
|
||||
if (oldDocuments) {
|
||||
Object.values(oldDocuments).forEach((value) => {
|
||||
const oldEntry: unknown = value;
|
||||
if (typeof oldEntry !== "object" || oldEntry === null) return;
|
||||
if (!oldEntry || typeof oldEntry !== "object") return;
|
||||
if (!("documentId" in oldEntry) || !("document" in oldEntry) || !("details" in oldEntry)) return;
|
||||
|
||||
// Extract the document ID, handling bigint, number, and string formats
|
||||
@@ -168,7 +168,7 @@ async function migrateToNewFormat() {
|
||||
|
||||
// Extract document details, handling camelCase from the old shipped format
|
||||
const details: unknown = oldEntry.details;
|
||||
if (typeof details !== "object" || details === null) return;
|
||||
if (!details || typeof details !== "object") return;
|
||||
|
||||
let name = "";
|
||||
if ("name" in details && typeof details.name === "string") name = details.name;
|
||||
@@ -193,7 +193,7 @@ async function migrateToNewFormat() {
|
||||
|
||||
// TODO: Eventually remove this document upgrade code
|
||||
function extractIsSavedFromUnknown(details: unknown): boolean {
|
||||
if (typeof details !== "object" || details === null) return false;
|
||||
if (!details || typeof details !== "object") return false;
|
||||
|
||||
// Old camelCase format
|
||||
if ("isSaved" in details) return Boolean(details.isSaved);
|
||||
|
||||
Reference in New Issue
Block a user