From 75d2f063a2d2d9b5a779359c5da58d27b0c323aa Mon Sep 17 00:00:00 2001
From: LB Johnston <mail@lb.ee>
Date: Thu, 23 Jun 2022 20:58:56 +1000
Subject: [PATCH] eslint - update lines-between-class-members & format

- allow single line members to be compact
---
 .eslintrc.js                                         |  7 ++++++-
 client/src/components/ChooserWidget/index.js         |  6 ++++++
 client/src/components/CommentApp/main.tsx            | 12 ++++++++++++
 .../Draftail/CommentableEditor/CommentableEditor.tsx |  7 +++++++
 .../StreamField/blocks/BaseSequenceBlock.js          |  8 ++++++++
 .../src/components/StreamField/blocks/StreamBlock.js |  2 ++
 client/src/entrypoints/admin/telepath/widgets.js     | 12 ++++++++++++
 .../contrib/typed_table_block/typed_table_block.js   |  4 ++++
 8 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/.eslintrc.js b/.eslintrc.js
index 651d353820..ef0fe1e333 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -10,7 +10,6 @@ const legacyCode = {
   'jsx-a11y/interactive-supports-focus': 'off',
   'jsx-a11y/no-noninteractive-element-interactions': 'off',
   'jsx-a11y/role-supports-aria-props': 'off',
-  'lines-between-class-members': 'off',
   'max-classes-per-file': 'off',
   'no-await-in-loop': 'off',
   'no-continue': 'off',
@@ -73,6 +72,12 @@ module.exports = {
     ],
     // does not align with the majority of legacy and newer code, some use named others use default exports
     'import/prefer-default-export': 'off',
+    // allow no lines between single line members (e.g. static declarations)
+    'lines-between-class-members': [
+      'error',
+      'always',
+      { exceptAfterSingleLine: true },
+    ],
     // note you must disable the base rule as it can report incorrect errors
     'no-use-before-define': 'off',
     'react/jsx-filename-extension': ['error', { extensions: ['.js', '.tsx'] }],
diff --git a/client/src/components/ChooserWidget/index.js b/client/src/components/ChooserWidget/index.js
index 573afd1399..a07c6de83c 100644
--- a/client/src/components/ChooserWidget/index.js
+++ b/client/src/components/ChooserWidget/index.js
@@ -47,9 +47,11 @@ export class Chooser {
   getState() {
     return this.state;
   }
+
   getValue() {
     return this.state && this.state.id;
   }
+
   setState(newState) {
     this.state = newState;
     if (newState) {
@@ -58,13 +60,16 @@ export class Chooser {
       this.renderEmptyState();
     }
   }
+
   clear() {
     this.setState(null);
   }
+
   renderEmptyState() {
     this.input.setAttribute('value', '');
     this.chooserElement.classList.add('blank');
   }
+
   renderState(newState) {
     this.input.setAttribute('value', newState.id);
     this.titleElement.innerText = newState.title;
@@ -80,6 +85,7 @@ export class Chooser {
     }
     return result;
   }
+
   focus() {
     this.chooserElement.querySelector('.action-choose').focus();
   }
diff --git a/client/src/components/CommentApp/main.tsx b/client/src/components/CommentApp/main.tsx
index 5d9b6073cf..60d5dc9861 100644
--- a/client/src/components/CommentApp/main.tsx
+++ b/client/src/components/CommentApp/main.tsx
@@ -105,11 +105,14 @@ function renderCommentsUi(
 
 export class CommentApp {
   store: Store;
+
   layout: LayoutController;
+
   utils = {
     selectCommentsForContentPathFactory,
     selectCommentFactory,
   };
+
   selectors = {
     selectComments,
     selectEnabled,
@@ -117,6 +120,7 @@ export class CommentApp {
     selectIsDirty,
     selectCommentCount,
   };
+
   actions = commentActionFunctions;
 
   constructor() {
@@ -136,19 +140,23 @@ export class CommentApp {
       }),
     );
   }
+
   updateAnnotation(annotation: Annotation, commentId: number) {
     this.attachAnnotationLayout(annotation, commentId);
     this.store.dispatch(updateComment(commentId, { annotation: annotation }));
   }
+
   attachAnnotationLayout(annotation: Annotation, commentId: number) {
     // Attach an annotation to an existing comment in the layout
 
     // const layout engine know the annotation so it would position the comment correctly
     this.layout.setCommentAnnotation(commentId, annotation);
   }
+
   setCurrentTab(tab: string | null) {
     this.store.dispatch(updateGlobalSettings({ currentTab: tab }));
   }
+
   makeComment(annotation: Annotation, contentpath: string, position = '') {
     const commentId = getNextCommentId();
 
@@ -180,6 +188,7 @@ export class CommentApp {
     );
     return commentId;
   }
+
   setVisible(visible: boolean) {
     this.store.dispatch(
       updateGlobalSettings({
@@ -187,15 +196,18 @@ export class CommentApp {
       }),
     );
   }
+
   invalidateContentPath(contentPath: string) {
     // Called when a given content path on the form is no longer valid (eg, a block has been deleted)
     this.store.dispatch(invalidateContentPath(contentPath));
   }
+
   updateContentPath(commentId: number, newContentPath: string) {
     this.store.dispatch(
       updateComment(commentId, { contentpath: newContentPath }),
     );
   }
+
   renderApp(
     element: HTMLElement,
     outputElement: HTMLElement,
diff --git a/client/src/components/Draftail/CommentableEditor/CommentableEditor.tsx b/client/src/components/Draftail/CommentableEditor/CommentableEditor.tsx
index 4fb451bfb9..9c174b957a 100644
--- a/client/src/components/Draftail/CommentableEditor/CommentableEditor.tsx
+++ b/client/src/components/Draftail/CommentableEditor/CommentableEditor.tsx
@@ -75,27 +75,32 @@ export class DraftailInlineAnnotation implements Annotation {
     this.focusedBlockKey = '';
     this.cachedMedianRef = null;
   }
+
   addDecoratorRef(ref: DecoratorRef, blockKey: BlockKey) {
     this.decoratorRefs.set(ref, blockKey);
 
     // We're adding a ref, so remove the cached median refs - this needs to be recalculated
     this.cachedMedianRef = null;
   }
+
   removeDecoratorRef(ref: DecoratorRef) {
     this.decoratorRefs.delete(ref);
 
     // We're deleting a ref, so remove the cached median refs - this needs to be recalculated
     this.cachedMedianRef = null;
   }
+
   setFocusedBlockKey(blockKey: BlockKey) {
     this.focusedBlockKey = blockKey;
   }
+
   static getHeightForRef(ref: DecoratorRef) {
     if (ref.current) {
       return ref.current.getBoundingClientRect().top;
     }
     return 0;
   }
+
   static getMedianRef(refArray: Array<DecoratorRef>) {
     const refs = refArray.sort(
       (firstRef, secondRef) =>
@@ -107,9 +112,11 @@ export class DraftailInlineAnnotation implements Annotation {
     }
     return null;
   }
+
   getTab() {
     return this.field.closest('[role="tabpanel"]')?.getAttribute('id');
   }
+
   getAnchorNode(focused = false) {
     // The comment should always aim to float by an annotation, rather than between them
     // so calculate which annotation is the median one by height and float the comment by that
diff --git a/client/src/components/StreamField/blocks/BaseSequenceBlock.js b/client/src/components/StreamField/blocks/BaseSequenceBlock.js
index 49fecc58bd..b976a38a1c 100644
--- a/client/src/components/StreamField/blocks/BaseSequenceBlock.js
+++ b/client/src/components/StreamField/blocks/BaseSequenceBlock.js
@@ -51,6 +51,7 @@ class ActionButton {
   enable() {
     this.dom.removeAttr('disabled');
   }
+
   disable() {
     this.dom.attr('disabled', 'true');
   }
@@ -258,31 +259,38 @@ export class BaseSequenceChild extends EventEmitter {
       this.block.setCapabilityOptions('duplicate', { enabled: true });
     }
   }
+
   disableDuplication() {
     this.emit('disableDuplication');
     if (this.block && this.block.setCapabilityOptions) {
       this.block.setCapabilityOptions('duplicate', { enabled: false });
     }
   }
+
   enableSplit() {
     if (this.block && this.block.setCapabilityOptions) {
       this.block.setCapabilityOptions('split', { enabled: true });
     }
   }
+
   disableSplit() {
     if (this.block && this.block.setCapabilityOptions) {
       this.block.setCapabilityOptions('split', { enabled: false });
     }
   }
+
   enableMoveUp() {
     this.emit('enableMoveUp');
   }
+
   disableMoveUp() {
     this.emit('disableMoveUp');
   }
+
   enableMoveDown() {
     this.emit('enableMoveDown');
   }
+
   disableMoveDown() {
     this.emit('disableMoveDown');
   }
diff --git a/client/src/components/StreamField/blocks/StreamBlock.js b/client/src/components/StreamField/blocks/StreamBlock.js
index 949a9ea69f..b3273a7521 100644
--- a/client/src/components/StreamField/blocks/StreamBlock.js
+++ b/client/src/components/StreamField/blocks/StreamBlock.js
@@ -173,6 +173,7 @@ class StreamBlockMenu extends BaseInsertionControl {
       this.open({ animate: true });
     }
   }
+
   open(opts) {
     if (!this.canAddBlock) {
       return;
@@ -188,6 +189,7 @@ class StreamBlockMenu extends BaseInsertionControl {
     this.outerContainer.attr('aria-hidden', 'false');
     this.isOpen = true;
   }
+
   close(opts) {
     if (opts && opts.animate) {
       this.outerContainer.slideUp();
diff --git a/client/src/entrypoints/admin/telepath/widgets.js b/client/src/entrypoints/admin/telepath/widgets.js
index c1eb331d50..b5f06c3e07 100644
--- a/client/src/entrypoints/admin/telepath/widgets.js
+++ b/client/src/entrypoints/admin/telepath/widgets.js
@@ -8,15 +8,19 @@ class BoundWidget {
     this.setState(initialState);
     this.parentCapabilities = parentCapabilities || new Map();
   }
+
   getValue() {
     return this.input.val();
   }
+
   getState() {
     return this.input.val();
   }
+
   setState(state) {
     this.input.val(state);
   }
+
   getTextLabel(opts) {
     const val = this.getValue();
     if (typeof val !== 'string') return null;
@@ -26,9 +30,11 @@ class BoundWidget {
     }
     return val;
   }
+
   focus() {
     this.input.focus();
   }
+
   setCapabilityOptions(capability, options) {
     Object.assign(this.parentCapabilities.get(capability), options);
   }
@@ -63,9 +69,11 @@ class BoundCheckboxInput extends BoundWidget {
   getValue() {
     return this.input.is(':checked');
   }
+
   getState() {
     return this.input.is(':checked');
   }
+
   setState(state) {
     // if false, set attribute value to null to remove it
     this.input.attr('checked', state || null);
@@ -85,15 +93,19 @@ class BoundRadioSelect {
     this.selector = 'input[name="' + name + '"]:checked';
     this.setState(initialState);
   }
+
   getValue() {
     return this.element.find(this.selector).val();
   }
+
   getState() {
     return this.element.find(this.selector).val();
   }
+
   setState(state) {
     this.element.find('input[name="' + this.name + '"]').val([state]);
   }
+
   focus() {
     this.element.find('input[name="' + this.name + '"]').focus();
   }
diff --git a/client/src/entrypoints/contrib/typed_table_block/typed_table_block.js b/client/src/entrypoints/contrib/typed_table_block/typed_table_block.js
index fe188c3dd1..c13f75dbd5 100644
--- a/client/src/entrypoints/contrib/typed_table_block/typed_table_block.js
+++ b/client/src/entrypoints/contrib/typed_table_block/typed_table_block.js
@@ -153,10 +153,12 @@ export class TypedTableBlock {
     this.addColumnMenu.show();
     this.addColumnCallback = callback;
   }
+
   hideAddColumnMenu() {
     this.addColumnMenu.hide();
     this.addColumnMenuBaseElement = null;
   }
+
   toggleAddColumnMenu(baseElement, callback) {
     if (this.addColumnMenuBaseElement === baseElement) {
       this.hideAddColumnMenu();
@@ -164,6 +166,7 @@ export class TypedTableBlock {
       this.showAddColumnMenu(baseElement, callback);
     }
   }
+
   clear() {
     // reset to initial empty state with no rows or columns
     this.columns = [];
@@ -192,6 +195,7 @@ export class TypedTableBlock {
     this.tbody.replaceChildren();
     this.addRowButton.hide();
   }
+
   insertColumn(index, blockDef, opts) {
     const column = {
       blockDef,