fix: resolve all ESLint errors across the codebase

- Remove unused imports (getIconIds, setIcon, exp, arrayMoveMutable, etc.)
- Add missing explicit return types on functions and arrow functions
- Add public accessibility modifier to PageHeaderManager.buttons
- Fix mixed spaces/tabs in constants.ts and commandComponent.tsx
- Wrap case block declaration in MacroBuilder.tsx to fix no-case-declarations
- Add eslint-disable comments for false-positive no-unused-vars on
  function type annotation parameter names and TypeScript enum members
- Remove dead forceUpdate reference in MacroBuilder.tsx (was referencing
  this in a function component)

Reduces from 64 errors + 2 warnings to 0 errors + 2 warnings (the remaining
warnings are intentional non-null assertions).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
John Morabito 2026-06-13 20:55:23 -04:00
parent 092d6a534e
commit 31ea9c9c45
15 changed files with 60 additions and 52 deletions

View file

@ -625,4 +625,4 @@ export const ICON_LIST = requireApiVersion("1.7.3")
"zoom-in",
"zoom-out",
"search-large",
];
];

View file

@ -5,7 +5,7 @@ import {
updateStyles,
} from "src/util";
import { updateSpacing } from "src/util";
import { Command, getIconIds, Plugin } from "obsidian";
import { Command, Plugin } from "obsidian";
import { DEFAULT_SETTINGS } from "./constants";
import t from "./l10n";
import {

View file

@ -1,4 +1,3 @@
import exp from "constants";
import { Menu, setIcon, WorkspaceLeaf } from "obsidian";
import t from "src/l10n";
import CommanderPlugin from "src/main";
@ -81,7 +80,7 @@ export default class ExplorerManager extends CommandManagerBase {
await this.plugin.saveSettings();
}
private buttonExists(leaf: WorkspaceLeaf, action: CommandIconPair) {
private buttonExists(leaf: WorkspaceLeaf, action: CommandIconPair): boolean {
return [
...leaf.view.containerEl.querySelectorAll(
"div.nav-buttons-container > .cmdr.clickable-icon"

View file

@ -32,15 +32,16 @@ abstract class Base extends CommandManagerBase {
// eslint-disable-next-line @typescript-eslint/no-empty-function
public reorder(): void {}
// eslint-disable-next-line no-unused-vars
protected addRemovableCommand(
this: (item: MenuItem) => void,
// eslint-disable-next-line no-unused-vars
this: (_item: MenuItem) => void,
command: Command,
cmdPair: CommandIconPair,
plugin: CommanderPlugin,
menu: Menu,
commandList: CommandIconPair[]
): (item: MenuItem) => void {
// eslint-disable-next-line no-unused-vars
): (_item: MenuItem) => void {
return (item: MenuItem) => {
item.dom.addClass("cmdr");
item.dom.style.color =

View file

@ -1,4 +1,4 @@
import { ItemView, Menu, setIcon, WorkspaceLeaf } from "obsidian";
import { ItemView, Menu, WorkspaceLeaf } from "obsidian";
import t from "src/l10n";
import CommanderPlugin from "src/main";
import { CommandIconPair } from "src/types";
@ -9,7 +9,7 @@ import { chooseNewCommand, isModeActive } from "src/util";
import CommandManagerBase from "./commandManager";
export default class PageHeaderManager extends CommandManagerBase {
buttons = new WeakMap<ItemView, Map<string, HTMLElement>>();
public buttons = new WeakMap<ItemView, Map<string, HTMLElement>>();
public constructor(plugin: CommanderPlugin, pairArray: CommandIconPair[]) {
super(plugin, pairArray);
@ -112,7 +112,7 @@ export default class PageHeaderManager extends CommandManagerBase {
);
}
private addAdderButton(leaf: WorkspaceLeaf) {
private addAdderButton(leaf: WorkspaceLeaf): void {
const { view } = leaf;
const id = "cmdr-adder";
if (!(view instanceof ItemView)) return;
@ -141,7 +141,7 @@ export default class PageHeaderManager extends CommandManagerBase {
);
}
private buttonsFor(leaf: WorkspaceLeaf, create = false) {
private buttonsFor(leaf: WorkspaceLeaf, create = false): Map<string, HTMLElement> | undefined {
if (!(leaf.view instanceof ItemView)) return;
if (create && !this.buttons.has(leaf.view))
this.buttons.set(leaf.view, new Map());
@ -164,7 +164,7 @@ export default class PageHeaderManager extends CommandManagerBase {
if (this.plugin.settings.showAddCommand) this.addAdderButton(leaf);
}
private removeButtonsFromLeaf(leaf: WorkspaceLeaf) {
private removeButtonsFromLeaf(leaf: WorkspaceLeaf): void {
const buttons = this.buttonsFor(leaf);
if (buttons) {
for (const button of buttons.values()) button.detach();

View file

@ -3,7 +3,8 @@ import { CommandIconPair } from "src/types";
import CommandManagerBase from "./commandManager";
interface TextToolbarAPI {
setCommands(cmds: { id: string; icon: string; name: string }[]): void;
// eslint-disable-next-line no-unused-vars
setCommands(_cmds: { id: string; icon: string; name: string }[]): void;
}
function getTextToolbarAPI(plugin: CommanderPlugin): TextToolbarAPI | undefined {

View file

@ -1,11 +1,13 @@
import { h } from "preact";
/* eslint-disable no-unused-vars */
export enum Action {
COMMAND,
DELAY,
EDITOR,
LOOP,
}
/* eslint-enable no-unused-vars */
export type MacroItem =
| { action: Action.COMMAND; commandId: string }

View file

@ -3,10 +3,10 @@ import t from "src/l10n";
import CommanderPlugin from "src/main";
export default class ChooseCustomNameModal extends SuggestModal<string> {
// This is used in onOpen, not sure why eslint doesn't recognize it
// eslint-disable-next-line no-unused-vars
public constructor(
// eslint-disable-next-line no-unused-vars
private defaultName: string,
// eslint-disable-next-line no-unused-vars
private plugin: CommanderPlugin
) {
super(plugin.app);
@ -62,9 +62,10 @@ export default class ChooseCustomNameModal extends SuggestModal<string> {
public renderSuggestion(value: string, el: HTMLElement): void {}
// This will be overriden anyway, but typescript complains if it's not declared
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-empty-function
/* eslint-disable no-unused-vars, @typescript-eslint/no-empty-function */
public onChooseSuggestion(
item: string,
evt: MouseEvent | KeyboardEvent
): void {}
/* eslint-enable no-unused-vars, @typescript-eslint/no-empty-function */
}

View file

@ -5,7 +5,7 @@ import CommanderPlugin from "src/main";
import { injectIcons, ObsidianIcon, updateStyles } from "src/util";
import ChooseIconModal from "../chooseIconModal";
function render(containerEl: HTMLElement, plugin: CommanderPlugin) {
function render(containerEl: HTMLElement, plugin: CommanderPlugin): void {
containerEl.empty();
new Setting(containerEl)

View file

@ -4,7 +4,8 @@ import { useEffect, useRef } from "preact/hooks";
interface ColorPickerProps {
initialColor: string;
onChange: (color: string) => void;
// eslint-disable-next-line no-unused-vars
onChange: (_color: string) => void;
}
export const ColorPicker = ({

View file

@ -10,6 +10,7 @@ import { SliderComponent } from "./settingComponent";
interface MacroBuilderProps {
plugin: CommanderPlugin;
macro: Macro;
// eslint-disable-next-line no-unused-vars
onSave: (macro: Macro) => void;
onCancel: () => void;
}
@ -26,9 +27,7 @@ export default function ({
JSON.parse(JSON.stringify(macro.macro)) || []
);
const forceUpdate = this.forceUpdate.bind(this);
const handleAddCommand = async () => {
const handleAddCommand = async (): Promise<void> => {
const command = await new AddCommandModal(plugin).awaitSelection();
if (command) {
setMacroCommands([
@ -38,7 +37,7 @@ export default function ({
}
};
const handleAddDelay = async () => {
const handleAddDelay = async (): Promise<void> => {
setMacroCommands([
...macroCommands,
{ action: Action.DELAY, delay: 250 },
@ -54,14 +53,14 @@ export default function ({
type="text"
placeholder="Macro Name"
value={name}
onChange={(e) => setName(e.currentTarget.value)}
onChange={(e): void => setName(e.currentTarget.value)}
width="100%"
/>
</div>
<div>
<span>Icon</span>
<button
onClick={async () =>
onClick={async (): Promise<void> =>
setIcon(
await new ChooseIconModal(
plugin
@ -76,7 +75,7 @@ export default function ({
{macroCommands.map((item, idx) => {
switch (item.action) {
case Action.COMMAND:
case Action.COMMAND: {
const command = getCommandFromId(
item.commandId,
plugin
@ -111,7 +110,7 @@ export default function ({
<ObsidianIcon
class="clickable-icon"
icon="arrow-down"
onClick={() => {
onClick={(): void => {
if (
idx ===
macroCommands.length - 1
@ -130,7 +129,7 @@ export default function ({
<ObsidianIcon
class="clickable-icon"
icon="arrow-up"
onClick={() => {
onClick={(): void => {
if (idx === 0) return;
const newCommands = [
...macroCommands,
@ -145,7 +144,7 @@ export default function ({
<ObsidianIcon
class="clickable-icon"
icon="cross"
onClick={() => {
onClick={(): void => {
setMacroCommands(
macroCommands.filter(
(_, i) => i !== idx
@ -157,6 +156,7 @@ export default function ({
</div>
</div>
);
}
case Action.DELAY:
return (
<div class="setting-item cmdr-mm-item">
@ -168,7 +168,7 @@ export default function ({
step={50}
description="Delay in milliseconds"
value={item.delay}
changeHandler={(value) =>
changeHandler={(value): void =>
(item.delay = value)
}
/>
@ -178,7 +178,7 @@ export default function ({
<ObsidianIcon
class="clickable-icon"
icon="arrow-down"
onClick={() => {
onClick={(): void => {
if (
idx ===
macroCommands.length - 1
@ -197,7 +197,7 @@ export default function ({
<ObsidianIcon
class="clickable-icon"
icon="arrow-up"
onClick={() => {
onClick={(): void => {
if (idx === 0) return;
const newCommands = [
...macroCommands,
@ -212,7 +212,7 @@ export default function ({
<ObsidianIcon
class="clickable-icon"
icon="cross"
onClick={() => {
onClick={(): void => {
setMacroCommands(
macroCommands.filter(
(_, i) => i !== idx
@ -237,7 +237,7 @@ export default function ({
type="checkbox"
id="checkbox"
checked={startup}
onChange={({ target }) => {
onChange={({ target }): void => {
//@ts-expect-error
setStartup(target?.checked ?? false);
}}
@ -256,7 +256,7 @@ export default function ({
<button
class={macroCommands.length === 0 ? "disabled" : "mod-cta"}
disabled={macroCommands.length === 0}
onClick={() =>
onClick={(): boolean | void =>
macroCommands.length &&
onSave({ macro: macroCommands, name, icon, startup })
}

View file

@ -7,12 +7,15 @@ import MacroBuilderComponent from "./MacroBuilder";
export default class MacroBuilderModal extends Modal {
private plugin: CommanderPlugin;
private macro: Macro;
private onSave: (macro: Macro) => void;
// eslint-disable-next-line no-unused-vars
private onSave: (_macro: Macro) => void;
public constructor(
plugin: CommanderPlugin,
// eslint-disable-next-line no-unused-vars
macro: Macro,
onSave: (macro: Macro) => void
// eslint-disable-next-line no-unused-vars
onSave: (_macro: Macro) => void
) {
super(plugin.app);
this.macro = macro;

View file

@ -1,13 +1,10 @@
import { arrayMoveMutable } from "array-move";
import { Platform } from "obsidian";
import { Fragment, h } from "preact";
import t from "src/l10n";
import CommanderPlugin from "src/main";
import { Macro } from "src/types";
import { isModeActive, ObsidianIcon, updateMacroCommands } from "src/util";
import ChooseIconModal from "../chooseIconModal";
import { ObsidianIcon, updateMacroCommands } from "src/util";
import ConfirmDeleteModal from "../confirmDeleteModal";
import CommandComponent from "./commandComponent";
import Logo from "./Logo";
import MacroBuilderModal from "./MacroBuilderModal";
@ -19,8 +16,8 @@ export default function MacroViewer({
plugin,
macros,
}: MacroBuilderProps): h.JSX.Element {
const handleBuilder = (macro: Macro, idx?: number) => {
const onClose = (updatedMacro: Macro) => {
const handleBuilder = (macro: Macro, idx?: number): void => {
const onClose = (updatedMacro: Macro): void => {
macros.splice(
idx !== undefined ? idx : macros.length,
idx !== undefined ? 1 : 0,
@ -36,7 +33,7 @@ export default function MacroViewer({
modal.open();
};
const handleDelete = (idx: number) => {
const handleDelete = (idx: number): void => {
macros.splice(idx, 1);
plugin.saveSettings();
this.forceUpdate();
@ -57,7 +54,7 @@ export default function MacroViewer({
<div className="setting-item-control">
<button
aria-label="Edit Macro"
onClick={() => handleBuilder(item, idx)}
onClick={(): void => handleBuilder(item, idx)}
>
<ObsidianIcon icon="lucide-pencil" />
</button>
@ -96,7 +93,7 @@ export default function MacroViewer({
<div className="cmdr-add-new-wrapper">
<button
class="mod-cta"
onClick={() =>
onClick={(): void =>
handleBuilder({ name: "", macro: [], icon: "star" })
}
>

View file

@ -15,9 +15,12 @@ interface CommandViewerProps {
handleUp: () => void;
handleDown: () => void;
handleNewIcon: () => void;
handleRename: (name: string) => void;
handleModeChange: (mode?: string) => void;
handleColorChange: (color?: string) => void;
// eslint-disable-next-line no-unused-vars
handleRename: (_name: string) => void;
// eslint-disable-next-line no-unused-vars
handleModeChange: (_mode?: string) => void;
// eslint-disable-next-line no-unused-vars
handleColorChange: (_color?: string) => void;
sortable?: boolean;
}
@ -146,7 +149,7 @@ export default function CommandComponent({
{isChecked
? t(
"Warning: This is a checked Command, meaning it might not run under every circumstance."
)
)
: ""}
</div>
</div>

View file

@ -160,7 +160,7 @@ export function updateMacroCommands(plugin: CommanderPlugin): void {
}
}
export function updateStyles(settings: AdvancedToolbarSettings) {
export function updateStyles(settings: AdvancedToolbarSettings): void {
const { classList: c, style: s } = document.body;
s.setProperty("--at-button-height", (settings.rowHeight ?? 48) + "px");
s.setProperty("--at-button-width", (settings.buttonWidth ?? 48) + "px");
@ -173,7 +173,7 @@ export function updateStyles(settings: AdvancedToolbarSettings) {
c.toggle("AT-no-toolbar", settings.rowCount === 0);
}
export function removeStyles() {
export function removeStyles(): void {
const { classList: c, style: s } = document.body;
s.removeProperty("--at-button-height");
s.removeProperty("--at-button-width");
@ -190,7 +190,7 @@ export function removeStyles() {
export function injectIcons(
settings: AdvancedToolbarSettings,
plugin: CommanderPlugin
) {
): void {
settings.mappedIcons.forEach((mapped) => {
const command = plugin.app.commands.commands[mapped.commandID];
if (command) {