mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +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
360321e0ce
commit
6480de274e
@@ -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 plugin config (for TS-specific linting)
|
||||||
"@typescript-eslint/indent": "off",
|
"@typescript-eslint/indent": "off",
|
||||||
@@ -96,7 +103,7 @@ export default defineConfig([
|
|||||||
"@typescript-eslint/consistent-type-assertions": ["error", { assertionStyle: "never" }],
|
"@typescript-eslint/consistent-type-assertions": ["error", { assertionStyle: "never" }],
|
||||||
"@typescript-eslint/consistent-indexed-object-style": ["error", "record"],
|
"@typescript-eslint/consistent-indexed-object-style": ["error", "record"],
|
||||||
"@typescript-eslint/consistent-generic-constructors": ["error", "constructor"],
|
"@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 plugin config (for validating and fixing formatting)
|
||||||
"prettier/prettier": "error",
|
"prettier/prettier": "error",
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export function createSRgba8FromHsva(h: number, s: number, v: number, a: number)
|
|||||||
// COLOR UTILITY FUNCTIONS
|
// COLOR UTILITY FUNCTIONS
|
||||||
|
|
||||||
export function isSRgba8(value: unknown): value is SRGBA8 {
|
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.
|
// 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
|
// GRADIENT UTILITY FUNCTIONS
|
||||||
|
|
||||||
export function isGradientStops(value: unknown): value is GradientStops<SRGBA8> {
|
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> {
|
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
|
// FILL CHOICE UTILITY FUNCTIONS
|
||||||
@@ -203,8 +203,7 @@ export function fillChoiceGradient(value: FillChoice<SRGBA8>): GradientStops<SRG
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function parseFillChoice(value: unknown): FillChoice<SRGBA8> {
|
export function parseFillChoice(value: unknown): FillChoice<SRGBA8> {
|
||||||
if (value === "None" || value === undefined || value === null) return "None";
|
if (value && typeof value === "object" && "Solid" in value && isSRgba8(value.Solid)) return { Solid: value.Solid };
|
||||||
if (typeof value === "object" && value !== null && "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 };
|
||||||
if (typeof value === "object" && value !== null && "Gradient" in value && isGradientRamp(value.Gradient)) return { Gradient: value.Gradient };
|
|
||||||
return "None";
|
return "None";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ function targetIsTextField(target: EventTarget | HTMLElement | undefined): boole
|
|||||||
|
|
||||||
function potentiallyRestoreCanvasFocus(e: Event) {
|
function potentiallyRestoreCanvasFocus(e: Event) {
|
||||||
const appElement = window.document.querySelector("[data-app-container]");
|
const appElement = window.document.querySelector("[data-app-container]");
|
||||||
const app = appElement instanceof HTMLElement ? appElement : null;
|
const app = appElement instanceof HTMLElement ? appElement : undefined;
|
||||||
|
|
||||||
const newInCanvasArea =
|
const newInCanvasArea =
|
||||||
(e.target instanceof Element && e.target.closest("[data-viewport], [data-viewport-container], [data-graph]")) instanceof Element &&
|
(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) {
|
if (oldDocuments) {
|
||||||
Object.values(oldDocuments).forEach((value) => {
|
Object.values(oldDocuments).forEach((value) => {
|
||||||
const oldEntry: unknown = 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;
|
if (!("documentId" in oldEntry) || !("document" in oldEntry) || !("details" in oldEntry)) return;
|
||||||
|
|
||||||
// Extract the document ID, handling bigint, number, and string formats
|
// 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
|
// Extract document details, handling camelCase from the old shipped format
|
||||||
const details: unknown = oldEntry.details;
|
const details: unknown = oldEntry.details;
|
||||||
if (typeof details !== "object" || details === null) return;
|
if (!details || typeof details !== "object") return;
|
||||||
|
|
||||||
let name = "";
|
let name = "";
|
||||||
if ("name" in details && typeof details.name === "string") name = details.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
|
// TODO: Eventually remove this document upgrade code
|
||||||
function extractIsSavedFromUnknown(details: unknown): boolean {
|
function extractIsSavedFromUnknown(details: unknown): boolean {
|
||||||
if (typeof details !== "object" || details === null) return false;
|
if (!details || typeof details !== "object") return false;
|
||||||
|
|
||||||
// Old camelCase format
|
// Old camelCase format
|
||||||
if ("isSaved" in details) return Boolean(details.isSaved);
|
if ("isSaved" in details) return Boolean(details.isSaved);
|
||||||
|
|||||||
Reference in New Issue
Block a user