From 56db1014cb2c0b35840bebf057a10fcd93526985 Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Fri, 11 Oct 2024 09:51:01 -0500 Subject: [PATCH 01/12] Add annotation size cookie static class --- src/cookies.ts | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/cookies.ts b/src/cookies.ts index 7cfe6170..62b76a51 100644 --- a/src/cookies.ts +++ b/src/cookies.ts @@ -2,6 +2,8 @@ * ULabel cookie utilities. */ +import { ULabelSubtask } from "./subtask"; + export abstract class NightModeCookie { /** * The name of the cookie that stores the night mode preference. @@ -43,3 +45,57 @@ export abstract class NightModeCookie { ].join(";"); } } + +/** + * Cookie utilities for tracking annotation display size. + */ +export abstract class AnnotationSizeCookie { + /** + * Produce the name of the cookie for a given subtask. + * Swaps spaces for underscores and lowercases the name. + * + * @param subtask ULabelSubtask to generate the cookie name for. + */ + private static cooke_name(subtask: ULabelSubtask): string { + const subtask_name = subtask.display_name.replaceLowerConcat(" ", "_"); + return `${subtask_name}_size`; + } + + /** + * Set the annotation size cookie for a given subtask. + * + * @param cookie_value Cookie value to set. + * @param subtask Subtask to set the cookie for. + */ + public static set_size_cookie( + cookie_value: number, + subtask: ULabelSubtask, + ) { + const cookie_name = AnnotationSizeCookie.cooke_name(subtask); + const d = new Date(); + d.setTime(d.getTime() + (10000 * 24 * 60 * 60 * 1000)); + + document.cookie = `${cookie_name}=${cookie_value};${d.toUTCString()};path=/`; + } + + /** + * Retrieve the annotation size cookie for a given subtask, if it exists. + * + * @param subtask Subtask to read the cookie for. + * @returns The cookie value if it exists, otherwise null. + */ + public static read_size_cookie(subtask: ULabelSubtask): number | null { + const cookie_name = AnnotationSizeCookie.cooke_name(subtask); + const cookie_array = document.cookie.split(";"); + + cookie_array.forEach((cookie) => { + // Trim whitespace at the beginning + cookie = cookie.trim(); + if (cookie.startsWith(cookie_name)) { + return parseInt(cookie.split("=")[1]); + } + }); + + return null; + } +} From 86ee4d4aeb6a833acdb6662aa1830a7260c4c4c8 Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Fri, 11 Oct 2024 10:13:55 -0500 Subject: [PATCH 02/12] Use new cookie class, also fix expiration --- src/cookies.ts | 20 +++++++++++++------- src/toolbox.ts | 40 +++++----------------------------------- 2 files changed, 18 insertions(+), 42 deletions(-) diff --git a/src/cookies.ts b/src/cookies.ts index 62b76a51..4ad13658 100644 --- a/src/cookies.ts +++ b/src/cookies.ts @@ -56,7 +56,7 @@ export abstract class AnnotationSizeCookie { * * @param subtask ULabelSubtask to generate the cookie name for. */ - private static cooke_name(subtask: ULabelSubtask): string { + private static cookie_name(subtask: ULabelSubtask): string { const subtask_name = subtask.display_name.replaceLowerConcat(" ", "_"); return `${subtask_name}_size`; } @@ -71,30 +71,36 @@ export abstract class AnnotationSizeCookie { cookie_value: number, subtask: ULabelSubtask, ) { - const cookie_name = AnnotationSizeCookie.cooke_name(subtask); + const cookie_name = AnnotationSizeCookie.cookie_name(subtask); const d = new Date(); d.setTime(d.getTime() + (10000 * 24 * 60 * 60 * 1000)); - document.cookie = `${cookie_name}=${cookie_value};${d.toUTCString()};path=/`; + document.cookie = `${cookie_name}=${cookie_value};expires=${d.toUTCString()};path=/`; } /** * Retrieve the annotation size cookie for a given subtask, if it exists. + * Resolves NaN to null. * * @param subtask Subtask to read the cookie for. * @returns The cookie value if it exists, otherwise null. */ public static read_size_cookie(subtask: ULabelSubtask): number | null { - const cookie_name = AnnotationSizeCookie.cooke_name(subtask); + const cookie_name = AnnotationSizeCookie.cookie_name(subtask); + console.log(cookie_name); const cookie_array = document.cookie.split(";"); - cookie_array.forEach((cookie) => { + for (let cookie of cookie_array) { // Trim whitespace at the beginning cookie = cookie.trim(); if (cookie.startsWith(cookie_name)) { - return parseInt(cookie.split("=")[1]); + let cookie_value = parseInt(cookie.split("=")[1]); + if (cookie_value === undefined || isNaN(cookie_value)) { + cookie_value = null; + } + return cookie_value; } - }); + }; return null; } diff --git a/src/toolbox.ts b/src/toolbox.ts index 2c55e63e..15a8101a 100644 --- a/src/toolbox.ts +++ b/src/toolbox.ts @@ -24,6 +24,7 @@ import { get_local_storage_item, set_local_storage_item, } from "./utilities"; +import { AnnotationSizeCookie } from "./cookies"; // For ResizeToolboxItem enum ValidResizeValues { @@ -1171,8 +1172,8 @@ export class AnnotationResizeItem extends ToolboxItem { // that the annotation was saved as. for (const subtask in ulabel.subtasks) { const cached_size_property = ulabel.subtasks[subtask].display_name.replaceLowerConcat(" ", "-", "-cached-size"); - const size_cookie = this.read_size_cookie(ulabel.subtasks[subtask]); - if ((size_cookie != null) && size_cookie != "NaN") { + const size_cookie = AnnotationSizeCookie.read_size_cookie(ulabel.subtasks[subtask]); + if (size_cookie != null) { this.update_annotation_size(ulabel, ulabel.subtasks[subtask], Number(size_cookie)); this[cached_size_property] = Number(size_cookie); } else if (ulabel.config.default_annotation_size != undefined) { @@ -1420,7 +1421,8 @@ export class AnnotationResizeItem extends ToolboxItem { } if (subtask.annotations.ordering.length > 0) { - this.set_size_cookie(subtask.annotations.access[subtask.annotations.ordering[0]].line_size, subtask); + const cst_line_size = subtask.annotations.access[subtask.annotations.ordering[0]].line_size; + AnnotationSizeCookie.set_size_cookie(cst_line_size, subtask); } } @@ -1431,38 +1433,6 @@ export class AnnotationResizeItem extends ToolboxItem { } } - private set_size_cookie(cookie_value, subtask) { - const d = new Date(); - d.setTime(d.getTime() + (10000 * 24 * 60 * 60 * 1000)); - - const subtask_name = subtask.display_name.replaceLowerConcat(" ", "_"); - - document.cookie = subtask_name + "_size=" + cookie_value + ";" + d.toUTCString() + ";path=/"; - } - - private read_size_cookie(subtask) { - const subtask_name = subtask.display_name.replaceLowerConcat(" ", "_"); - - const cookie_name = subtask_name + "_size="; - - const cookie_array = document.cookie.split(";"); - - for (let i = 0; i < cookie_array.length; i++) { - let current_cookie = cookie_array[i]; - - // while there's whitespace at the front of the cookie, loop through and remove it - while (current_cookie.charAt(0) == " ") { - current_cookie = current_cookie.substring(1); - } - - if (current_cookie.indexOf(cookie_name) == 0) { - return current_cookie.substring(cookie_name.length, current_cookie.length); - } - } - - return null; - } - public get_html() { return `
From 447f4bd222bca03c1e1b99b2f8b7a0b1355cebb7 Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Fri, 11 Oct 2024 10:21:13 -0500 Subject: [PATCH 03/12] A few nullish coalescing ops --- src/toolbox.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/toolbox.ts b/src/toolbox.ts index 15a8101a..f741b00c 100644 --- a/src/toolbox.ts +++ b/src/toolbox.ts @@ -2027,13 +2027,13 @@ export class FilterPointDistanceFromRow extends ToolboxItem { // Check if localStorage has a value for showing the overlay const show_overlay = get_local_storage_item("filterDistanceShowOverlay"); // Guard against null values - this.show_overlay = show_overlay !== null ? show_overlay : this.show_overlay; + this.show_overlay = show_overlay ?? this.show_overlay; this.overlay.update_display_overlay(this.show_overlay); // Check if localStorage has a value for filtering during polyline move const filter_during_polyline_move = get_local_storage_item("filterDistanceFilterDuringPolylineMove"); // Guard against null values - this.filter_during_polyline_move = filter_during_polyline_move !== null ? filter_during_polyline_move : this.filter_during_polyline_move; + this.filter_during_polyline_move = filter_during_polyline_move ?? this.filter_during_polyline_move; this.add_styles(); @@ -2489,7 +2489,7 @@ export class SubmitButtons extends ToolboxItem { const submit_buttons_by_row: ULabelSubmitButton[][] = []; // First, get all the unique row numbers. // If a button doesn't have a row number, it will be placed in row 0. - const row_numbers: Set = new Set(this.submit_buttons.map((button) => button.row_number ? button.row_number : 0)); + const row_numbers: Set = new Set(this.submit_buttons.map((button) => button.row_number ?? 0)); // Sort the row numbers const sorted_row_numbers: number[] = Array.from(row_numbers).sort((a, b) => a - b); // Group the buttons by row number in ascending order From 87c31acb8b1ad0cd3fef0a51b95d208a2b2bc96a Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Fri, 11 Oct 2024 10:23:22 -0500 Subject: [PATCH 04/12] Update deprecated argument comments --- src/index.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/index.js b/src/index.js index 480869e0..8d704e99 100644 --- a/src/index.js +++ b/src/index.js @@ -481,18 +481,20 @@ export class ULabel { `); return { - container_id: arguments[0], // Required - image_data: arguments[1], // Required - username: arguments[2], // Required - submit_buttons: arguments[3], // Required - subtasks: arguments[4], // Required - task_meta: arguments[5] ?? null, // Use default if optional argument is undefined - annotation_meta: arguments[6] ?? null, // Use default if optional argument is undefined - px_per_px: arguments[7] ?? 1, // Use default if optional argument is undefined - initial_crop: arguments[8] ?? null, // Use default if optional argument is undefined - initial_line_size: arguments[9] ?? null, // Use default if optional argument is undefined - config_data: arguments[10] ?? null, // Use default if optional argument is undefined - toolbox_order: arguments[11] ?? null, // Use default if optional argument is undefined + // Required arguments + container_id: arguments[0], + image_data: arguments[1], + username: arguments[2], + submit_buttons: arguments[3], + subtasks: arguments[4], + // Optional arguments + task_meta: arguments[5] ?? null, + annotation_meta: arguments[6] ?? null, + px_per_px: arguments[7] ?? 1, + initial_crop: arguments[8] ?? null, + initial_line_size: arguments[9] ?? null, + config_data: arguments[10] ?? null, + toolbox_order: arguments[11] ?? null, }; } From b9039bf5221f0ff004ff3d41a39a488fed216d1e Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Fri, 11 Oct 2024 10:58:31 -0500 Subject: [PATCH 05/12] Simplify drag state construction --- src/index.js | 51 ++++++++++++++++----------------------------------- 1 file changed, 16 insertions(+), 35 deletions(-) diff --git a/src/index.js b/src/index.js index 8d704e99..e2a3452f 100644 --- a/src/index.js +++ b/src/index.js @@ -572,6 +572,15 @@ export class ULabel { this.color_info = {}; ULabel.initialize_subtasks(this); + // Build entry for `this.drag_state` + const build_drag_state_entry = () => { + return { + mouse_start: null, // Screen coordinates where the current mouse drag started + offset_start: null, // Scroll values where the current mouse drag started + zoom_val_start: null, // zoom_val when the dragging interaction started + }; + }; + // Create object for dragging interaction state // TODO(v1) // There can only be one drag, yes? Maybe pare this down... @@ -579,41 +588,13 @@ export class ULabel { this.drag_state = { active_key: null, release_button: null, - annotation: { - mouse_start: null, // Screen coordinates where the current mouse drag started - offset_start: null, // Scroll values where the current mouse drag started - zoom_val_start: null, // zoom_val when the dragging interaction started - }, - brush: { - mouse_start: null, // Screen coordinates where the current mouse drag started - offset_start: null, // Scroll values where the current mouse drag started - zoom_val_start: null, // zoom_val when the dragging interaction started - }, - edit: { - mouse_start: null, // Screen coordinates where the current mouse drag started - offset_start: null, // Scroll values where the current mouse drag started - zoom_val_start: null, // zoom_val when the dragging interaction started - }, - pan: { - mouse_start: null, // Screen coordinates where the current mouse drag started - offset_start: null, // Scroll values where the current mouse drag started - zoom_val_start: null, // zoom_val when the dragging interaction started - }, - zoom: { - mouse_start: null, // Screen coordinates where the current mouse drag started - offset_start: null, // Scroll values where the current mouse drag started - zoom_val_start: null, // zoom_val when the dragging interaction started - }, - move: { - mouse_start: null, // Screen coordinates where the current mouse drag started - offset_start: null, // Scroll values where the current mouse drag started - zoom_val_start: null, // zoom_val when the dragging interaction started - }, - right: { - mouse_start: null, // Screen coordinates where the current mouse drag started - offset_start: null, // Scroll values where the current mouse drag started - zoom_val_start: null, // zoom_val when the dragging interaction started - }, + annotation: build_drag_state_entry(), + brush: build_drag_state_entry(), + edit: build_drag_state_entry(), + pan: build_drag_state_entry(), + zoom: build_drag_state_entry(), + move: build_drag_state_entry(), + right: build_drag_state_entry(), }; for (const st in this.subtasks) { From 8cb8782baf0604b644c340a7ed9c1e25a3f5d6d7 Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Sun, 18 Oct 2026 21:10:46 -0500 Subject: [PATCH 06/12] Use nullish coalescing for remaining #189 quirks Co-authored-by: joshua-dean Co-Authored-By: Claude Opus 5.5 --- src/toolbox.ts | 4 ++-- src/toolbox_items/submit_buttons.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/toolbox.ts b/src/toolbox.ts index cbb344d8..98ca295b 100644 --- a/src/toolbox.ts +++ b/src/toolbox.ts @@ -1943,13 +1943,13 @@ export class FilterPointDistanceFromRow extends ToolboxItem { // Check if localStorage has a value for showing the overlay const show_overlay = get_local_storage_item("filterDistanceShowOverlay"); // Guard against null values - this.show_overlay = show_overlay !== null ? show_overlay : this.show_overlay; + this.show_overlay = show_overlay ?? this.show_overlay; this.overlay.update_display_overlay(this.show_overlay); // Check if localStorage has a value for filtering during polyline move const filter_during_polyline_move = get_local_storage_item("filterDistanceFilterDuringPolylineMove"); // Guard against null values - this.filter_during_polyline_move = filter_during_polyline_move !== null ? filter_during_polyline_move : this.filter_during_polyline_move; + this.filter_during_polyline_move = filter_during_polyline_move ?? this.filter_during_polyline_move; this.add_styles(); diff --git a/src/toolbox_items/submit_buttons.ts b/src/toolbox_items/submit_buttons.ts index fee29fca..2152b3c7 100644 --- a/src/toolbox_items/submit_buttons.ts +++ b/src/toolbox_items/submit_buttons.ts @@ -205,7 +205,7 @@ export class SubmitButtons extends ToolboxItem { const submit_buttons_by_row: ULabelSubmitButton[][] = []; // First, get all the unique row numbers. // If a button doesn't have a row number, it will be placed in row 0. - const row_numbers: Set = new Set(this.submit_buttons.map((button) => button.row_number ? button.row_number : 0)); + const row_numbers: Set = new Set(this.submit_buttons.map((button) => button.row_number ?? 0)); // Sort the row numbers const sorted_row_numbers: number[] = Array.from(row_numbers).sort((a, b) => a - b); // Group the buttons by row number in ascending order From ae6b21f1a225ddb460ac9aaee7d3e6b578fff3ef Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Thu, 22 Oct 2026 15:49:35 -0500 Subject: [PATCH 07/12] More nullish coalescing --- src/annotation.ts | 6 +++--- src/html_builder.ts | 2 +- src/toolbox_items/keybinds.ts | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/annotation.ts b/src/annotation.ts index bbc2cb5c..1f736e97 100644 --- a/src/annotation.ts +++ b/src/annotation.ts @@ -286,9 +286,9 @@ export class ULabelAnnotation { // Return the data, initializing the arrays if they are undefined const ret: PolygonSpatialData = { spatial_payload: annotation.spatial_payload, - containing_box: annotation.containing_box ? annotation.containing_box : null, - spatial_payload_holes: annotation.spatial_payload_holes ? annotation.spatial_payload_holes : [false], - spatial_payload_child_indices: annotation.spatial_payload_child_indices ? annotation.spatial_payload_child_indices : [[]], + containing_box: annotation.containing_box ?? null, + spatial_payload_holes: annotation.spatial_payload_holes ?? [false], + spatial_payload_child_indices: annotation.spatial_payload_child_indices ?? [[]], }; if (deep_copy) { return JSON.parse(JSON.stringify(ret)); diff --git a/src/html_builder.ts b/src/html_builder.ts index c987b2b6..b65b42bc 100644 --- a/src/html_builder.ts +++ b/src/html_builder.ts @@ -726,7 +726,7 @@ export class SliderHandler { value="${this.default_value}" />
` : ""; keybinds_html += ` @@ -829,7 +829,7 @@ export class KeybindsToolboxItem extends ToolboxItem { const is_customized = this.is_class_keybind_customized(keybind.class_id!); const collision_class = has_collision ? " collision" : ""; const customized_class = is_customized ? " customized" : ""; - const display_key = keybind.key != null ? keybind.key : "none"; + const display_key = keybind.key ?? "none"; const reset_button = is_customized ? `` : ""; keybinds_html += ` @@ -860,7 +860,7 @@ export class KeybindsToolboxItem extends ToolboxItem { for (const keybind of other) { const has_collision = this.has_collision(keybind.key, all_keybinds); const collision_class = has_collision ? " collision" : ""; - const display_key = keybind.key !== null && keybind.key !== undefined ? keybind.key : "none"; + const display_key = keybind.key ?? "none"; keybinds_html += `
${keybind.label} From 698b0bf9f9eef9b587d2a391cf521472fa493843 Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Thu, 22 Oct 2026 16:03:27 -0500 Subject: [PATCH 08/12] Ignore .claude and load .gitignore into ESLint ESLint's flat config doesn't read .gitignore, so `eslint .` walked into nested Claude Code worktrees under .claude/worktrees and linted their build output. Load .gitignore via @eslint/compat's includeIgnoreFile and ignore .claude. Co-authored-by: joshua-dean Co-Authored-By: Claude Opus 5.5 --- .gitignore | 3 ++- eslint.config.mjs | 3 +++ package-lock.json | 35 +++++++++++++++++++++++++++++++++++ package.json | 1 + 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ee23a3dc..cc2a3ca8 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ output.txt test-results/ playwright-report/ dist -*.log \ No newline at end of file +*.log +.claude diff --git a/eslint.config.mjs b/eslint.config.mjs index 5ee3af48..9f4d61b1 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -2,8 +2,11 @@ import globals from "globals"; import eslint from "@eslint/js"; import stylistic from "@stylistic/eslint-plugin"; import tseslint from "typescript-eslint"; +import { includeIgnoreFile } from "@eslint/compat"; +import { fileURLToPath } from "node:url"; export default [ + includeIgnoreFile(fileURLToPath(new URL(".gitignore", import.meta.url)), "Imported .gitignore patterns"), { // Global ignores // https://eslint.org/docs/latest/use/configure/configuration-files#configuration-objects diff --git a/package-lock.json b/package-lock.json index 6234e231..a7c5767f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.31.0", "license": "MIT", "devDependencies": { + "@eslint/compat": "^2.1.1", "@eslint/config-inspector": "^1.3.0", "@eslint/js": "^9.11.1", "@playwright/test": "^1.56.0", @@ -1035,6 +1036,40 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/compat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-2.1.1.tgz", + "integrity": "sha512-rMcy8GSrwNzcISX/BlTDY/GLB4eCopEuy9woIls3To+15OLxykZrxxq+WUcylCPCQ6F4MujjBM1DX5V1aqI3Vw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "peerDependencies": { + "eslint": "^8.40 || 9 || 10" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/compat/node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, "node_modules/@eslint/config-helpers": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz", diff --git a/package.json b/package.json index a9a47ba6..af69dca9 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "homepage": "https://github.com/SenteraLLC/ulabel", "unpkg": "dist/ulabel.min.js", "devDependencies": { + "@eslint/compat": "^2.1.1", "@eslint/config-inspector": "^1.3.0", "@eslint/js": "^9.11.1", "@playwright/test": "^1.56.0", From 670c938ca5ab915b8d5bd72adb00dd8b724db708 Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Thu, 22 Oct 2026 16:05:48 -0500 Subject: [PATCH 09/12] Use includeIgnoreFile from @eslint/config-helpers The @eslint/compat export is deprecated. eslint/config only re-exports it from ESLint 10 onward, so depend on @eslint/config-helpers directly. Co-authored-by: joshua-dean Co-Authored-By: Claude Opus 5.5 --- eslint.config.mjs | 2 +- package-lock.json | 59 +++++++++++++++++++++++++---------------------- package.json | 2 +- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 9f4d61b1..ce24ac7d 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -2,7 +2,7 @@ import globals from "globals"; import eslint from "@eslint/js"; import stylistic from "@stylistic/eslint-plugin"; import tseslint from "typescript-eslint"; -import { includeIgnoreFile } from "@eslint/compat"; +import { includeIgnoreFile } from "@eslint/config-helpers"; import { fileURLToPath } from "node:url"; export default [ diff --git a/package-lock.json b/package-lock.json index a7c5767f..cbc50981 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.31.0", "license": "MIT", "devDependencies": { - "@eslint/compat": "^2.1.1", + "@eslint/config-helpers": "^0.7.0", "@eslint/config-inspector": "^1.3.0", "@eslint/js": "^9.11.1", "@playwright/test": "^1.56.0", @@ -1036,10 +1036,10 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@eslint/compat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-2.1.1.tgz", - "integrity": "sha512-rMcy8GSrwNzcISX/BlTDY/GLB4eCopEuy9woIls3To+15OLxykZrxxq+WUcylCPCQ6F4MujjBM1DX5V1aqI3Vw==", + "node_modules/@eslint/config-helpers": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1047,17 +1047,9 @@ }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "peerDependencies": { - "eslint": "^8.40 || 9 || 10" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } } }, - "node_modules/@eslint/compat/node_modules/@eslint/core": { + "node_modules/@eslint/config-helpers/node_modules/@eslint/core": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", @@ -1070,19 +1062,6 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz", - "integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.16.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@eslint/config-inspector": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@eslint/config-inspector/-/config-inspector-1.3.0.tgz", @@ -6188,6 +6167,32 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/eslint/node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint/node_modules/@eslint/config-helpers/node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/eslint/node_modules/eslint-scope": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", diff --git a/package.json b/package.json index af69dca9..93ccd07a 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "homepage": "https://github.com/SenteraLLC/ulabel", "unpkg": "dist/ulabel.min.js", "devDependencies": { - "@eslint/compat": "^2.1.1", + "@eslint/config-helpers": "^0.7.0", "@eslint/config-inspector": "^1.3.0", "@eslint/js": "^9.11.1", "@playwright/test": "^1.56.0", From 95701350f9ba47603454288933a1219c47b4e58e Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Thu, 22 Oct 2026 16:06:24 -0500 Subject: [PATCH 10/12] 0.31.1 and update CHANGELOG --- CHANGELOG.md | 5 ++++- package.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 080779ed..b99eb102 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,10 @@ All notable changes to this project will be documented here. -## [Unreleased] +## [0.31.1] - Oct 22nd, 2026 +#### Changed +- Simplified ternary syntax into nullish coalescing in several locations +- Added `@eslint/config-helpers` so ESLint can load `.gitignore` ## [0.31.0] - Oct 21st, 2026 #### Added diff --git a/package.json b/package.json index 93ccd07a..fb99a90f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ulabel", "description": "An image annotation tool.", - "version": "0.31.0", + "version": "0.31.1", "main": "dist/ulabel.min.js", "module": "dist/ulabel.min.js", "types": "dist/index.d.ts", From 899c617d2b3730149ac437235ea8a707270e3df6 Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Thu, 22 Oct 2026 16:08:38 -0500 Subject: [PATCH 11/12] Bump in version.js --- src/version.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.js b/src/version.js index 8754155b..4a332776 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -export const ULABEL_VERSION = "0.31.0"; +export const ULABEL_VERSION = "0.31.1"; From df223ec193f832036b5953751830cd97752ae03e Mon Sep 17 00:00:00 2001 From: joshua-dean Date: Thu, 22 Oct 2026 16:09:51 -0500 Subject: [PATCH 12/12] Update PR template --- CHANGELOG.md | 1 + pull_request_template.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b99eb102..b86ba2ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented here. #### Changed - Simplified ternary syntax into nullish coalescing in several locations - Added `@eslint/config-helpers` so ESLint can load `.gitignore` +- Update CHANGELOG capitalization in PR template ## [0.31.0] - Oct 21st, 2026 #### Added diff --git a/pull_request_template.md b/pull_request_template.md index 0d4554a4..d465a529 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -10,7 +10,7 @@ - [ ] Version number in `package.json` has been bumped since last release - [ ] Version numbers match between package `package.json` and `src/version.js` - [ ] Updated documentation if necessary (currently just in `api_spec.md`) -- [ ] Added changes to `changelog.md` +- [ ] Added changes to `CHANGELOG.md` ## Breaking API Changes