Improved Linting

This commit is contained in:
4Source 2025-08-12 22:07:41 +02:00
parent 5cf63fca6f
commit afd4e38c3a
9 changed files with 141 additions and 34 deletions

View file

@ -44,6 +44,13 @@
"error",
"always-multiline"
],
"comma-spacing": [
"error",
{
"before": false,
"after": true
}
],
"@stylistic/dot-location": [
"error",
"property"
@ -55,7 +62,25 @@
"@stylistic/function-call-spacing": "error",
"@stylistic/implicit-arrow-linebreak": "error",
"@stylistic/key-spacing": "error",
"@stylistic/lines-around-comment": "error",
"@stylistic/lines-around-comment": [
"error",
{
"beforeBlockComment": true,
"afterBlockComment": false,
"beforeLineComment": true,
"afterLineComment": false,
"allowBlockStart": true,
"allowBlockEnd": false,
"allowClassStart": true,
"allowClassEnd": false,
"allowObjectStart": true,
"allowObjectEnd": false,
"allowArrayStart": true,
"allowArrayEnd": false,
"ignorePattern": "TODO|HACK|BUG|TEST",
"applyDefaultIgnorePatterns": false
}
],
"@stylistic/new-parens": "error",
"@stylistic/no-confusing-arrow": "error",
"@stylistic/no-extra-semi": "error",
@ -74,7 +99,8 @@
"@stylistic/no-trailing-spaces": [
"error",
{
"skipBlankLines": true
"skipBlankLines": false,
"ignoreComments": false
}
],
"@stylistic/nonblock-statement-body-position": "error",
@ -91,7 +117,14 @@
"@stylistic/semi-spacing": "error",
"@stylistic/semi-style": "error",
"@stylistic/space-before-blocks": "error",
"@stylistic/space-before-function-paren": "error",
"@stylistic/space-before-function-paren": [
"error",
{
"anonymous": "always",
"named": "never",
"asyncArrow": "always"
}
],
"@stylistic/arrow-spacing": "error",
"@stylistic/space-in-parens": "error",
"@stylistic/space-infix-ops": "error",
@ -110,6 +143,13 @@
"allowEmptyCase": true
}
],
"no-console": ["error", {"allow": ["warn", "error", "debug"]}]
"line-comment-position": [
"error",
{
"position": "above",
"ignorePattern": "TODO|HACK|BUG|TEST",
"applyDefaultIgnorePatterns": false
}
]
}
}

8
.eslintrc.dev Normal file
View file

@ -0,0 +1,8 @@
{
"extends": [
"./.eslintrc"
],
"rules": {
"no-console": "off",
}
}

21
.eslintrc.release Normal file
View file

@ -0,0 +1,21 @@
{
"extends": [
"./.eslintrc"
],
"rules": {
"no-console": [
"error",
{
"allow": [
"warn",
"error",
"debug"
]
}
],
"multiline-comment-style": [
"error",
"starred-block"
]
}
}

View file

@ -5,6 +5,7 @@ import { TreeItem } from './TreeItem';
export class OpenEditorsView extends View {
// Array of top-level tree items representing open editor windows
windows: TreeItem[];
// The root container element for the tree structure
treeEl: HTMLDivElement;
@ -12,22 +13,22 @@ export class OpenEditorsView extends View {
* Initializes the OpenEditorsView with a given workspace leaf.
* @param leaf - The workspace leaf where this view will be rendered.
*/
constructor (leaf: WorkspaceLeaf) {
constructor(leaf: WorkspaceLeaf) {
super(leaf);
this.windows = [];
this.icon = ICON_OPEN_EDITORS;
}
getViewType (): string {
getViewType(): string {
return VIEW_TYPE_OPEN_EDITORS;
}
getDisplayText (): string {
getDisplayText(): string {
return VIEW_DISPLAY_OPEN_EDITORS;
}
async onOpen () {
async onOpen() {
// Create the main container for the view
this.containerEl.empty();
const container = this.containerEl.createEl('div', { cls: (VIEW_TYPE_OPEN_EDITORS + '-container') });
@ -37,6 +38,7 @@ export class OpenEditorsView extends View {
this.registerEvent(this.app.workspace.on('layout-change', async () => {
// Clear the current tree structure
this.clearTree();
// Rebuild the tree based on the updated layout
this.createTree();
}));
@ -45,7 +47,7 @@ export class OpenEditorsView extends View {
/**
* Creates the tree structure representing the current workspace layout.
*/
createTree () {
createTree() {
// Get the current workspace layout
const layout = this.app.workspace.getLayout();
@ -66,6 +68,7 @@ export class OpenEditorsView extends View {
}]);
},
}]);
// Add the tree item to the list of windows
this.windows.push(tree);
@ -94,7 +97,7 @@ export class OpenEditorsView extends View {
* @param layout - The current layout node being processed.
* @param parent - The parent TreeItem to attach new child TreeItems to.
*/
TreeWalker (layout: { id: string, type: string, children: object[], state: { title: string, type: string } }, parent: TreeItem | undefined) {
TreeWalker(layout: { id: string, type: string, children: object[], state: { title: string, type: string } }, parent: TreeItem | undefined) {
// Counter for labeling groups and tabs
let count = 1;
switch (layout.type) {
@ -114,11 +117,13 @@ export class OpenEditorsView extends View {
}]);
},
}]);
// Add the tree item to the list of windows
this.windows.push(parent);
if (layout.children.length > 1) {
let groupCount = 1;
// Recursively build the tree structure for all child elements
layout.children.forEach((element: { id: string, type: string, children: object[], state: { title: string, type: string } }) => {
const group = parent?.addChild((containerEl) => new TreeItem(containerEl, `Group ${groupCount}`, element.id, element.type, undefined, [{
@ -146,6 +151,7 @@ export class OpenEditorsView extends View {
}
break;
// Handle split layouts
case 'split':
layout.children.forEach((element: { id: string, type: string, children: object[], state: { title: string, type: string } }) => {
@ -208,17 +214,20 @@ export class OpenEditorsView extends View {
}
},
}]));
// Recursively process tabs as children
this.TreeWalker(element, group);
count++;
});
break;
// Handle tabs layouts
case 'tabs':
layout.children.forEach((element: { id: string, type: string, children: object[], state: { title: string, type: string } }) => {
this.TreeWalker(element, parent);
});
break;
// Handle individual leaves
case 'leaf':
parent?.addChild((container) => new TreeItem(container, layout.state.title, layout.id, layout.type, {
@ -249,9 +258,10 @@ export class OpenEditorsView extends View {
/**
* Clears the current tree structure and resets the windows array.
*/
clearTree () {
clearTree() {
// Delete all tree items and their children
this.windows.forEach(window => window.deleteTree());
// Reset the windows array
this.windows = [];

View file

@ -3,16 +3,22 @@ import { IconName, setIcon } from 'obsidian';
export class TreeItem {
// The ID of the tree item
id: string;
// The type of the workspace item behind this tree item
type: string;
// Tree items inside this tree item
children: TreeItem[];
// Main container element for the tree item
treeItemEl: HTMLDivElement;
// Represents the tree item
selfEl: HTMLDivElement;
// Container for child elements
childrenEl: HTMLDivElement;
// Element for displaying collapsible icons
iconEl: HTMLDivElement;
@ -24,7 +30,7 @@ export class TreeItem {
* @param handler - Optional event handlers
* @param actions - Optional actions (clickable icons with callbacks)
*/
constructor (
constructor(
conteinerEl: HTMLDivElement,
title: string,
id: string,
@ -60,6 +66,7 @@ export class TreeItem {
this.childrenEl.setCssProps({ 'display': 'none' });
}
}
// Invoke custom click handler if provided
if (handler?.onClickCallback) {
handler.onClickCallback(ev);
@ -91,10 +98,12 @@ export class TreeItem {
if (action.ariaLabel) {
button.ariaLabel = action.ariaLabel;
}
// Add a click listener to invoke the action callback
button.onClickEvent((ev) => {
// Prevent click from bubbling up
ev.stopPropagation();
// Call provided onClick Callback function
action.onClickCallback(ev);
});
@ -106,7 +115,7 @@ export class TreeItem {
* Recursively apply a callback function to the current tree item and its children.
* @param callback - The function to call for each tree item.
*/
rekursiveCall (callback: (tree: TreeItem) => void) {
rekursiveCall(callback: (tree: TreeItem) => void) {
this.children.forEach((child) => {
child.rekursiveCall(callback);
});
@ -118,7 +127,7 @@ export class TreeItem {
* @param callback - The function to call for each tree item.
* @param type - The type TreeItem needs to have
*/
rekursiveCallForType (actions: { callback: (tree: TreeItem) => void, type: string }[]) {
rekursiveCallForType(actions: { callback: (tree: TreeItem) => void, type: string }[]) {
this.children.forEach((child) => {
child.rekursiveCallForType(actions);
});
@ -137,7 +146,7 @@ export class TreeItem {
* @example
* parent.addChild((containerEl) => new TreeItem(containerEl, "Title", "ID"))
*/
addChild (treeCreateCallback: (containerEl: HTMLDivElement) => TreeItem): TreeItem {
addChild(treeCreateCallback: (containerEl: HTMLDivElement) => TreeItem): TreeItem {
if (!this.selfEl.hasClass('mod-collapsible')) {
// Make this tree item collapsible if it isn't already
this.selfEl.addClass('mod-collapsible');
@ -146,7 +155,9 @@ export class TreeItem {
}
const child = treeCreateCallback(this.childrenEl);
this.children.push(child); // Add the child to the children array
// Add the child to the children array
this.children.push(child);
return child;
}
@ -154,15 +165,18 @@ export class TreeItem {
* Remove a child TreeItem by its ID.
* @param id - The unique identifier of the child to remove.
*/
removeChild (id: string) {
removeChild(id: string) {
const child = this.children.find((value) => value.id == id);
if (child) {
this.children.remove(child);
// Recursively remove all children
child.removeAllChildren();
// Remove the DOM elements for this child
child.removeDom();
}
// If there are no more children, remove collapsible functionality
if (this.children.length <= 0 && this.selfEl.hasClass('mod-collapsible')) {
this.selfEl.removeClass('mod-collapsible');
@ -173,16 +187,18 @@ export class TreeItem {
/**
* Remove all child TreeItems from this tree item.
*/
removeAllChildren () {
removeAllChildren() {
while (this.children.length > 0) {
const child = this.children.pop();
if (child) {
// Recursively remove all children
child.removeAllChildren();
// Remove the DOM elements for this child
child.removeDom();
}
}
// If there are no more children, remove collapsible functionality
if (this.children.length <= 0 && this.selfEl.hasClass('mod-collapsible')) {
this.selfEl.removeClass('mod-collapsible');
@ -193,7 +209,7 @@ export class TreeItem {
/**
* Completely delete this tree and all of its children.
*/
deleteTree () {
deleteTree() {
this.removeAllChildren();
this.removeDom();
}
@ -201,7 +217,7 @@ export class TreeItem {
/**
* Private helper to remove DOM elements associated with this tree item.
*/
private removeDom () {
private removeDom() {
this.treeItemEl?.remove();
this.selfEl?.remove();
this.childrenEl?.remove();

View file

@ -2,9 +2,9 @@ export const VIEW_TYPE_OPEN_EDITORS = 'open-editors';
export const ICON_OPEN_EDITORS = 'layers';
export const VIEW_DISPLAY_OPEN_EDITORS = 'Open editors';
export const ICON_CLOSE = 'x-square'; // x
export const ICON_CLOSE_GROUP = 'copy-x'; // folder-x
export const ICON_CLOSE_WINDOW = 'copy-x'; // monitor-x
export const ICON_CLOSE = 'x-square';
export const ICON_CLOSE_GROUP = 'copy-x';
export const ICON_CLOSE_WINDOW = 'copy-x';
export const ICON_MOVE_TO_NEW_WINDOW = 'picture-in-picture';
export const ICON_OPEN_IN_NEW_WINDOW = 'picture-in-picture-2';
export const ICON_SPLIT_RIGHT = 'separator-vertical';

View file

@ -6,11 +6,13 @@ import { OpenEditorsView } from './OpenEditorsView';
export default class OpenEditorsPlugin extends Plugin {
settings: Settings;
async onload () {
async onload() {
await this.loadSettings();
// This adds a settings tab so the user can configure various aspects of the plugin
// this.addSettingTab(new OpenEditorsSettingTab(this.app, this));
/*
* This adds a settings tab so the user can configure various aspects of the plugin
* this.addSettingTab(new OpenEditorsSettingTab(this.app, this));
*/
// Register the view
this.registerView(VIEW_TYPE_OPEN_EDITORS, (leaf) => new OpenEditorsView(leaf));
@ -30,19 +32,19 @@ export default class OpenEditorsPlugin extends Plugin {
});
}
onunload () {
onunload() {
}
async loadSettings () {
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings () {
async saveSettings() {
await this.saveData(this.settings);
}
async activateView (viewType: string) {
async activateView(viewType: string) {
const { workspace } = this.app;
let leaf: WorkspaceLeaf | null = null;
@ -53,8 +55,10 @@ export default class OpenEditorsPlugin extends Plugin {
leaf = leaves[0];
}
else {
// Our view could not be found in the workspace, create a new leaf
// in the right sidebar for it
/*
* Our view could not be found in the workspace, create a new leaf
* in the right sidebar for it
*/
leaf = workspace.getRightLeaf(false);
if (leaf) {
await leaf.setViewState({ type: viewType, active: true });

View file

@ -4,7 +4,7 @@ import OpenEditorsPlugin from 'src/main';
export class OpenEditorsSettingTab extends PluginSettingTab {
plugin: OpenEditorsPlugin;
constructor (
constructor(
app: App,
plugin: OpenEditorsPlugin
) {
@ -12,7 +12,7 @@ export class OpenEditorsSettingTab extends PluginSettingTab {
this.plugin = plugin;
}
display (): void {
display(): void {
const { containerEl } = this;
containerEl.empty();

8
src/types.d.ts vendored Normal file
View file

@ -0,0 +1,8 @@
import { } from 'obsidian';
declare module 'obsidian' {
interface WorkspaceLeaf {
id: string,
parent: WorkspaceTabs | WorkspaceMobileDrawer;
}
}