Преглед изворни кода

Merge pull request #3470 from overleaf/eslint

Upgrade and configure ESLint

GitOrigin-RevId: ad5aeaf85e72c847a125ff3a9db99a12855e38aa
Alf Eaton пре 5 година
родитељ
комит
2ff1cf43d6
100 измењених фајлова са 390 додато и 513 уклоњено
  1. 38 7
      services/web/.eslintrc
  2. 6 1
      services/web/.prettierrc
  3. 20 19
      services/web/Makefile
  4. 1 1
      services/web/app/src/Features/BrandVariations/BrandVariationsHandler.js
  5. 9 25
      services/web/app/src/Features/Chat/ChatApiHandler.js
  6. 1 1
      services/web/app/src/Features/Chat/ChatController.js
  7. 2 4
      services/web/app/src/Features/Collaborators/CollaboratorsEmailHandler.js
  8. 1 1
      services/web/app/src/Features/Collaborators/CollaboratorsInviteController.js
  9. 1 1
      services/web/app/src/Features/Collaborators/CollaboratorsInviteHandler.js
  10. 1 1
      services/web/app/src/Features/Compile/ClsiCookieManager.js
  11. 2 6
      services/web/app/src/Features/Compile/ClsiManager.js
  12. 1 1
      services/web/app/src/Features/Compile/ClsiStateManager.js
  13. 1 1
      services/web/app/src/Features/Compile/CompileController.js
  14. 1 1
      services/web/app/src/Features/Compile/CompileManager.js
  15. 1 1
      services/web/app/src/Features/Contacts/ContactManager.js
  16. 1 1
      services/web/app/src/Features/Cooldown/CooldownManager.js
  17. 4 10
      services/web/app/src/Features/Docstore/DocstoreManager.js
  18. 1 3
      services/web/app/src/Features/DocumentUpdater/DocumentUpdaterHandler.js
  19. 1 1
      services/web/app/src/Features/Documents/DocumentController.js
  20. 1 1
      services/web/app/src/Features/Downloads/ProjectZipStreamManager.js
  21. 1 1
      services/web/app/src/Features/Editor/EditorController.js
  22. 10 30
      services/web/app/src/Features/Email/EmailBuilder.js
  23. 1 3
      services/web/app/src/Features/Errors/Errors.js
  24. 4 11
      services/web/app/src/Features/Exports/ExportsHandler.js
  25. 1 1
      services/web/app/src/Features/FileStore/FileHashManager.js
  26. 1 3
      services/web/app/src/Features/FileStore/FileStoreHandler.js
  27. 3 9
      services/web/app/src/Features/History/HistoryController.js
  28. 2 2
      services/web/app/src/Features/History/HistoryManager.js
  29. 1 1
      services/web/app/src/Features/History/RestoreManager.js
  30. 1 3
      services/web/app/src/Features/Institutions/InstitutionsAPI.js
  31. 2 6
      services/web/app/src/Features/LinkedFiles/LinkedFilesController.js
  32. 1 1
      services/web/app/src/Features/LinkedFiles/LinkedFilesHandler.js
  33. 1 1
      services/web/app/src/Features/LinkedFiles/ProjectFileAgent.js
  34. 3 7
      services/web/app/src/Features/LinkedFiles/ProjectOutputFileAgent.js
  35. 1 1
      services/web/app/src/Features/LinkedFiles/UrlAgent.js
  36. 1 1
      services/web/app/src/Features/Metadata/MetaHandler.js
  37. 1 1
      services/web/app/src/Features/Notifications/NotificationsController.js
  38. 1 1
      services/web/app/src/Features/Project/ProjectCollabratecDetailsHandler.js
  39. 1 2
      services/web/app/src/Features/Project/ProjectController.js
  40. 1 1
      services/web/app/src/Features/Project/ProjectCreationHandler.js
  41. 2 2
      services/web/app/src/Features/Project/ProjectDeleter.js
  42. 1 1
      services/web/app/src/Features/Project/ProjectGetter.js
  43. 1 1
      services/web/app/src/Features/Project/ProjectHistoryHandler.js
  44. 2 8
      services/web/app/src/Features/Project/ProjectLocator.js
  45. 1 1
      services/web/app/src/Features/Project/ProjectRootDocManager.js
  46. 2 4
      services/web/app/src/Features/Project/ProjectTokenGenerator.js
  47. 1 1
      services/web/app/src/Features/Project/ProjectUpdateHandler.js
  48. 1 1
      services/web/app/src/Features/Publishers/PublishersGetter.js
  49. 2 4
      services/web/app/src/Features/References/ReferencesHandler.js
  50. 1 1
      services/web/app/src/Features/Security/OneTimeTokenHandler.js
  51. 1 1
      services/web/app/src/Features/ServerAdmin/AdminController.js
  52. 1 1
      services/web/app/src/Features/StaticPages/HomeController.js
  53. 1 2
      services/web/app/src/Features/Subscription/LimitationsManager.js
  54. 1 2
      services/web/app/src/Features/Subscription/RecurlyWrapper.js
  55. 1 1
      services/web/app/src/Features/Subscription/SubscriptionController.js
  56. 1 1
      services/web/app/src/Features/Subscription/SubscriptionGroupHandler.js
  57. 1 1
      services/web/app/src/Features/Subscription/SubscriptionLocator.js
  58. 2 4
      services/web/app/src/Features/Subscription/SubscriptionViewModelBuilder.js
  59. 2 6
      services/web/app/src/Features/Subscription/TeamInvitesHandler.js
  60. 1 1
      services/web/app/src/Features/Subscription/V1SubscriptionManager.js
  61. 1 1
      services/web/app/src/Features/SystemMessages/SystemMessageManager.js
  62. 1 3
      services/web/app/src/Features/Templates/TemplatesManager.js
  63. 1 1
      services/web/app/src/Features/ThirdPartyDataStore/TpdsController.js
  64. 1 1
      services/web/app/src/Features/ThirdPartyDataStore/TpdsUpdateHandler.js
  65. 1 1
      services/web/app/src/Features/ThirdPartyDataStore/UpdateMerger.js
  66. 1 1
      services/web/app/src/Features/Uploads/ArchiveManager.js
  67. 1 3
      services/web/app/src/Features/User/SAMLIdentityManager.js
  68. 2 6
      services/web/app/src/Features/User/UserController.js
  69. 1 3
      services/web/app/src/Features/User/UserEmailsConfirmationHandler.js
  70. 1 3
      services/web/app/src/Features/User/UserEmailsController.js
  71. 1 3
      services/web/app/src/Features/User/UserRegistrationHandler.js
  72. 27 26
      services/web/app/src/Features/User/UserSessionsManager.js
  73. 1 2
      services/web/app/src/Features/UserMembership/UserMembershipHandler.js
  74. 1 1
      services/web/app/src/Features/UserMembership/UserMembershipViewModel.js
  75. 1 1
      services/web/app/src/Features/UserMembership/UserMembershipsHandler.js
  76. 2 6
      services/web/app/src/Features/V1/V1Api.js
  77. 2 4
      services/web/app/src/Features/V1/V1Handler.js
  78. 0 1
      services/web/app/src/infrastructure/Csrf.js
  79. 1 1
      services/web/app/src/infrastructure/FileWriter.js
  80. 4 1
      services/web/frontend/js/base.js
  81. 1 3
      services/web/frontend/js/directives/complexPassword.js
  82. 2 2
      services/web/frontend/js/directives/equals.js
  83. 2 2
      services/web/frontend/js/directives/expandableTextArea.js
  84. 7 7
      services/web/frontend/js/directives/fineUpload.js
  85. 2 2
      services/web/frontend/js/directives/maxHeight.js
  86. 2 2
      services/web/frontend/js/directives/onEnter.js
  87. 2 2
      services/web/frontend/js/directives/rightClick.js
  88. 10 9
      services/web/frontend/js/directives/videoPlayState.js
  89. 13 16
      services/web/frontend/js/features/chat/components/message-content.js
  90. 10 13
      services/web/frontend/js/features/chat/store/chat-store-effect.js
  91. 7 10
      services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-inner.js
  92. 4 6
      services/web/frontend/js/features/file-tree/components/file-tree-root.js
  93. 3 6
      services/web/frontend/js/features/file-tree/contexts/file-tree-draggable.js
  94. 7 9
      services/web/frontend/js/features/file-tree/contexts/file-tree-selectable.js
  95. 3 1
      services/web/frontend/js/features/file-tree/controllers/file-tree-controller.js
  96. 24 30
      services/web/frontend/js/features/file-tree/hooks/file-tree-angular-listener.js
  97. 58 78
      services/web/frontend/js/features/file-tree/hooks/file-tree-socket-listener.js
  98. 11 14
      services/web/frontend/js/features/outline/components/outline-item.js
  99. 4 6
      services/web/frontend/js/features/outline/components/outline-pane.js
  100. 9 9
      services/web/frontend/js/features/preview/components/preview-logs-pane.js

+ 38 - 7
services/web/.eslintrc

@@ -1,24 +1,36 @@
 {
 {
+  "root": true,
   "extends": [
   "extends": [
+    "eslint:recommended",
+    "plugin:react/recommended",
+    "plugin:react-hooks/recommended",
+    "plugin:jsx-a11y/recommended",
     "standard",
     "standard",
     "standard-jsx",
     "standard-jsx",
     "standard-react",
     "standard-react",
-    "prettier",
+    "plugin:prettier/recommended",
+    "prettier/prettier",
     "prettier/react",
     "prettier/react",
-    "prettier/standard",
-    "plugin:react-hooks/recommended",
-    "plugin:jsx-a11y/recommended"
+    "prettier/standard"
   ],
   ],
   "plugins": [
   "plugins": [
+    "prettier",
     "jsx-a11y",
     "jsx-a11y",
     "mocha",
     "mocha",
     "chai-expect",
     "chai-expect",
     "chai-friendly"
     "chai-friendly"
   ],
   ],
-  "parser": "babel-eslint",
   "env": {
   "env": {
     "browser": true,
     "browser": true,
-    "mocha": true
+    "mocha": true,
+    "node": true,
+    "es2020": true
+  },
+  "parserOptions": {
+    "sourceType": "module",
+    "ecmaFeatures": {
+      "jsx": true
+    }
   },
   },
   "settings": {
   "settings": {
     // Tell eslint-plugin-react to detect which version of React we are using
     // Tell eslint-plugin-react to detect which version of React we are using
@@ -27,12 +39,31 @@
     }
     }
   },
   },
   "rules": {
   "rules": {
+    "dot-notation": "off",
+    "node/no-callback-literal": "off",
+    "node/no-deprecated-api": "off",
+    "node/handle-callback-err": "off",
+    "node/no-path-concat": "off",
+    "no-prototype-builtins": "off",
     // Swap the no-unused-expressions rule with a more chai-friendly one
     // Swap the no-unused-expressions rule with a more chai-friendly one
-    "no-unused-expressions": 0,
+    "no-unused-expressions": "off",
+    "no-unused-vars": "off",
+    "no-var": "off",
+    "prefer-const": "off",
+    "prefer-regex-literals": "off",
     "react/jsx-curly-brace-presence": ["error", {
     "react/jsx-curly-brace-presence": ["error", {
       "props": "never",
       "props": "never",
       "children": "never"
       "children": "never"
     }],
     }],
+    "react/display-name": "off",
+    "react/no-unescaped-entities": "off",
+    "react/no-unused-prop-types": "off",
+    "react/jsx-no-target-blank": "off",
+    "react/jsx-handler-names": "off",
+    "array-callback-return": "off",
+    "no-empty": "off",
+    "no-unreachable-loop": "off",
+    "no-loss-of-precision": "off",
     "chai-friendly/no-unused-expressions": "error"
     "chai-friendly/no-unused-expressions": "error"
   },
   },
   "overrides": [
   "overrides": [

+ 6 - 1
services/web/.prettierrc

@@ -1,4 +1,9 @@
 {
 {
+  "arrowParens": "avoid",
+  "jsxSingleQuote": false,
   "semi": false,
   "semi": false,
-  "singleQuote": true
+  "singleQuote": true,
+  "trailingComma": "none",
+  "tabWidth": 2,
+  "useTabs": false
 }
 }

+ 20 - 19
services/web/Makefile

@@ -161,6 +161,7 @@ WITH_NODE_MODULES_PATH = \
 	format_backend \
 	format_backend \
 	format_frontend \
 	format_frontend \
 	format_misc \
 	format_misc \
+	format_styles \
 	format_test \
 	format_test \
 	$(TEST_SUITES) \
 	$(TEST_SUITES) \
 
 
@@ -168,41 +169,47 @@ $(WITH_NODE_MODULES_PATH): export PATH=$(NODE_MODULES_PATH)
 
 
 format: format_backend
 format: format_backend
 format_backend:
 format_backend:
-	prettier-eslint \
+	eslint \
 		app.js \
 		app.js \
 		'app/**/*.js' \
 		'app/**/*.js' \
 		'modules/*/index.js' \
 		'modules/*/index.js' \
 		'modules/*/app/**/*.js' \
 		'modules/*/app/**/*.js' \
-	 	--list-different
+		--max-warnings=0
 
 
 format: format_frontend
 format: format_frontend
 format_frontend:
 format_frontend:
-	prettier-eslint \
-		'frontend/**/*.{js,less}' \
-		'modules/*/frontend/**/*.{js,less}' \
+	eslint \
+		'frontend/**/*.js' \
+		'modules/*/frontend/**/*.js' \
+		--max-warnings=0
+
+format: format_styles
+format_styles:
+	prettier \
+		'frontend/**/*.less' \
+		'modules/*/frontend/**/*.less' \
 		--list-different
 		--list-different
 
 
 format: format_test
 format: format_test
 format_test:
 format_test:
-	prettier-eslint \
+	eslint \
 		'test/**/*.js' \
 		'test/**/*.js' \
 		'modules/*/test/**/*.js' \
 		'modules/*/test/**/*.js' \
-		--list-different
+		--max-warnings=0
 
 
 format: format_misc
 format: format_misc
 # migrations, scripts, webpack config, karma config
 # migrations, scripts, webpack config, karma config
 format_misc:
 format_misc:
-	prettier-eslint \
-		'**/*.{js,less}' \
+	eslint . \
 		--ignore app.js \
 		--ignore app.js \
 		--ignore 'app/**/*.js' \
 		--ignore 'app/**/*.js' \
 		--ignore 'modules/*/app/**/*.js' \
 		--ignore 'modules/*/app/**/*.js' \
 		--ignore 'modules/*/index.js' \
 		--ignore 'modules/*/index.js' \
-		--ignore 'frontend/**/*.{js,less}' \
-		--ignore 'modules/*/frontend/**/*.{js,less}' \
+		--ignore 'frontend/**/*.js' \
+		--ignore 'modules/*/frontend/**/*.js' \
 		--ignore 'test/**/*.js' \
 		--ignore 'test/**/*.js' \
 		--ignore 'modules/*/test/**/*.js' \
 		--ignore 'modules/*/test/**/*.js' \
-		--list-different
+		--max-warnings=0
 
 
 format_in_docker:
 format_in_docker:
 	$(RUN_LINT_FORMAT) make format -j --output-sync
 	$(RUN_LINT_FORMAT) make format -j --output-sync
@@ -210,12 +217,6 @@ format_in_docker:
 format_fix:
 format_fix:
 	npm run --silent format:fix
 	npm run --silent format:fix
 
 
-lint:
-	npm run --silent lint
-
-lint_in_docker:
-	$(RUN_LINT_FORMAT) make lint
-
 #
 #
 # Build & publish
 # Build & publish
 #
 #
@@ -291,5 +292,5 @@ $(MODULE_TARGETS):
 	test test_module test_unit test_unit_app \
 	test test_module test_unit test_unit_app \
 	test_unit_modules test_unit_module test_karma test_karma_run \
 	test_unit_modules test_unit_module test_karma test_karma_run \
 	test_karma_build_run test_frontend test_acceptance test_acceptance_app \
 	test_karma_build_run test_frontend test_acceptance test_acceptance_app \
-	test_acceptance_modules test_acceptance_module ci format format_fix lint \
+	test_acceptance_modules test_acceptance_module ci format format_fix \
 	build build_test_karma publish tar
 	build build_test_karma publish tar

+ 1 - 1
services/web/app/src/Features/BrandVariations/BrandVariationsHandler.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-return-assign,
     no-return-assign,
     no-unused-vars,
     no-unused-vars,

+ 9 - 25
services/web/app/src/Features/Chat/ChatApiHandler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
@@ -41,9 +41,7 @@ module.exports = ChatApiHandler = {
   sendGlobalMessage(project_id, user_id, content, callback) {
   sendGlobalMessage(project_id, user_id, content, callback) {
     return ChatApiHandler._apiRequest(
     return ChatApiHandler._apiRequest(
       {
       {
-        url: `${
-          settings.apis.chat.internal_url
-        }/project/${project_id}/messages`,
+        url: `${settings.apis.chat.internal_url}/project/${project_id}/messages`,
         method: 'POST',
         method: 'POST',
         json: { user_id, content }
         json: { user_id, content }
       },
       },
@@ -62,9 +60,7 @@ module.exports = ChatApiHandler = {
 
 
     return ChatApiHandler._apiRequest(
     return ChatApiHandler._apiRequest(
       {
       {
-        url: `${
-          settings.apis.chat.internal_url
-        }/project/${project_id}/messages`,
+        url: `${settings.apis.chat.internal_url}/project/${project_id}/messages`,
         method: 'GET',
         method: 'GET',
         qs,
         qs,
         json: true
         json: true
@@ -79,9 +75,7 @@ module.exports = ChatApiHandler = {
     }
     }
     return ChatApiHandler._apiRequest(
     return ChatApiHandler._apiRequest(
       {
       {
-        url: `${
-          settings.apis.chat.internal_url
-        }/project/${project_id}/thread/${thread_id}/messages`,
+        url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}/messages`,
         method: 'POST',
         method: 'POST',
         json: { user_id, content }
         json: { user_id, content }
       },
       },
@@ -109,9 +103,7 @@ module.exports = ChatApiHandler = {
     }
     }
     return ChatApiHandler._apiRequest(
     return ChatApiHandler._apiRequest(
       {
       {
-        url: `${
-          settings.apis.chat.internal_url
-        }/project/${project_id}/thread/${thread_id}/resolve`,
+        url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}/resolve`,
         method: 'POST',
         method: 'POST',
         json: { user_id }
         json: { user_id }
       },
       },
@@ -125,9 +117,7 @@ module.exports = ChatApiHandler = {
     }
     }
     return ChatApiHandler._apiRequest(
     return ChatApiHandler._apiRequest(
       {
       {
-        url: `${
-          settings.apis.chat.internal_url
-        }/project/${project_id}/thread/${thread_id}/reopen`,
+        url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}/reopen`,
         method: 'POST'
         method: 'POST'
       },
       },
       callback
       callback
@@ -140,9 +130,7 @@ module.exports = ChatApiHandler = {
     }
     }
     return ChatApiHandler._apiRequest(
     return ChatApiHandler._apiRequest(
       {
       {
-        url: `${
-          settings.apis.chat.internal_url
-        }/project/${project_id}/thread/${thread_id}`,
+        url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}`,
         method: 'DELETE'
         method: 'DELETE'
       },
       },
       callback
       callback
@@ -155,9 +143,7 @@ module.exports = ChatApiHandler = {
     }
     }
     return ChatApiHandler._apiRequest(
     return ChatApiHandler._apiRequest(
       {
       {
-        url: `${
-          settings.apis.chat.internal_url
-        }/project/${project_id}/thread/${thread_id}/messages/${message_id}/edit`,
+        url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}/messages/${message_id}/edit`,
         method: 'POST',
         method: 'POST',
         json: {
         json: {
           content
           content
@@ -173,9 +159,7 @@ module.exports = ChatApiHandler = {
     }
     }
     return ChatApiHandler._apiRequest(
     return ChatApiHandler._apiRequest(
       {
       {
-        url: `${
-          settings.apis.chat.internal_url
-        }/project/${project_id}/thread/${thread_id}/messages/${message_id}`,
+        url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}/messages/${message_id}`,
         method: 'DELETE'
         method: 'DELETE'
       },
       },
       callback
       callback

+ 1 - 1
services/web/app/src/Features/Chat/ChatController.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-undef,
     no-undef,
     no-unused-vars,
     no-unused-vars,

+ 2 - 4
services/web/app/src/Features/Collaborators/CollaboratorsEmailHandler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
@@ -18,9 +18,7 @@ const Settings = require('settings-sharelatex')
 module.exports = CollaboratorsEmailHandler = {
 module.exports = CollaboratorsEmailHandler = {
   _buildInviteUrl(project, invite) {
   _buildInviteUrl(project, invite) {
     return (
     return (
-      `${Settings.siteUrl}/project/${project._id}/invite/token/${
-        invite.token
-      }?` +
+      `${Settings.siteUrl}/project/${project._id}/invite/token/${invite.token}?` +
       [
       [
         `project_name=${encodeURIComponent(project.name)}`,
         `project_name=${encodeURIComponent(project.name)}`,
         `user_first_name=${encodeURIComponent(project.owner_ref.first_name)}`
         `user_first_name=${encodeURIComponent(project.owner_ref.first_name)}`

+ 1 - 1
services/web/app/src/Features/Collaborators/CollaboratorsInviteController.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 1
services/web/app/src/Features/Collaborators/CollaboratorsInviteHandler.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 1
services/web/app/src/Features/Compile/ClsiCookieManager.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 2 - 6
services/web/app/src/Features/Compile/ClsiManager.js

@@ -584,9 +584,7 @@ const ClsiManager = {
   },
   },
 
 
   getOutputFileStream(projectId, userId, buildId, outputFilePath, callback) {
   getOutputFileStream(projectId, userId, buildId, outputFilePath, callback) {
-    const url = `${
-      Settings.apis.clsi.url
-    }/project/${projectId}/user/${userId}/build/${buildId}/output/${outputFilePath}`
+    const url = `${Settings.apis.clsi.url}/project/${projectId}/user/${userId}/build/${buildId}/output/${outputFilePath}`
     ClsiCookieManager.getCookieJar(projectId, (err, jar) => {
     ClsiCookieManager.getCookieJar(projectId, (err, jar) => {
       if (err != null) {
       if (err != null) {
         return callback(
         return callback(
@@ -766,9 +764,7 @@ const ClsiManager = {
       path = path.replace(/^\//, '') // Remove leading /
       path = path.replace(/^\//, '') // Remove leading /
       resources.push({
       resources.push({
         path,
         path,
-        url: `${Settings.apis.filestore.url}/project/${project._id}/file/${
-          file._id
-        }`,
+        url: `${Settings.apis.filestore.url}/project/${project._id}/file/${file._id}`,
         modified: file.created != null ? file.created.getTime() : undefined
         modified: file.created != null ? file.created.getTime() : undefined
       })
       })
     }
     }

+ 1 - 1
services/web/app/src/Features/Compile/ClsiStateManager.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 1
services/web/app/src/Features/Compile/CompileController.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-undef,
     no-undef,
     no-unused-vars,
     no-unused-vars,

+ 1 - 1
services/web/app/src/Features/Compile/CompileManager.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 1 - 1
services/web/app/src/Features/Contacts/ContactManager.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 1
services/web/app/src/Features/Cooldown/CooldownManager.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 4 - 10
services/web/app/src/Features/Docstore/DocstoreManager.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */
@@ -26,9 +26,7 @@ const DocstoreManager = {
     if (callback == null) {
     if (callback == null) {
       callback = function(error) {}
       callback = function(error) {}
     }
     }
-    const url = `${
-      settings.apis.docstore.url
-    }/project/${project_id}/doc/${doc_id}`
+    const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}`
     return request.del({ url: url, timeout: TIMEOUT }, function(
     return request.del({ url: url, timeout: TIMEOUT }, function(
       error,
       error,
       res,
       res,
@@ -128,9 +126,7 @@ const DocstoreManager = {
       callback = options
       callback = options
       options = {}
       options = {}
     }
     }
-    let url = `${
-      settings.apis.docstore.url
-    }/project/${project_id}/doc/${doc_id}`
+    let url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}`
     if (options.include_deleted) {
     if (options.include_deleted) {
       url += '?include_deleted=true'
       url += '?include_deleted=true'
     }
     }
@@ -177,9 +173,7 @@ const DocstoreManager = {
     if (callback == null) {
     if (callback == null) {
       callback = function(error, modified, rev) {}
       callback = function(error, modified, rev) {}
     }
     }
-    const url = `${
-      settings.apis.docstore.url
-    }/project/${project_id}/doc/${doc_id}`
+    const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}`
     return request.post(
     return request.post(
       {
       {
         url,
         url,

+ 1 - 3
services/web/app/src/Features/DocumentUpdater/DocumentUpdaterHandler.js

@@ -132,9 +132,7 @@ function getProjectDocsIfMatch(projectId, projectStateHash, callback) {
   // docs from redis via the docupdater. Otherwise we will need to
   // docs from redis via the docupdater. Otherwise we will need to
   // fall back to getting them from mongo.
   // fall back to getting them from mongo.
   const timer = new metrics.Timer('get-project-docs')
   const timer = new metrics.Timer('get-project-docs')
-  const url = `${
-    settings.apis.documentupdater.url
-  }/project/${projectId}/get_and_flush_if_old?state=${projectStateHash}`
+  const url = `${settings.apis.documentupdater.url}/project/${projectId}/get_and_flush_if_old?state=${projectStateHash}`
   request.post(url, function(error, res, body) {
   request.post(url, function(error, res, body) {
     timer.done()
     timer.done()
     if (error) {
     if (error) {

+ 1 - 1
services/web/app/src/Features/Documents/DocumentController.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 1 - 1
services/web/app/src/Features/Downloads/ProjectZipStreamManager.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-undef,
     no-undef,
 */
 */

+ 1 - 1
services/web/app/src/Features/Editor/EditorController.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-dupe-keys,
     no-dupe-keys,
     no-unused-vars,
     no-unused-vars,

+ 10 - 30
services/web/app/src/Features/Email/EmailBuilder.js

@@ -146,9 +146,7 @@ templates.registered = ctaTemplate({
   },
   },
   secondaryMessage() {
   secondaryMessage() {
     return [
     return [
-      `If you have any questions or problems, please contact ${
-        settings.adminEmail
-      }`
+      `If you have any questions or problems, please contact ${settings.adminEmail}`
     ]
     ]
   },
   },
   ctaText() {
   ctaText() {
@@ -165,9 +163,7 @@ templates.canceledSubscription = ctaTemplate({
   },
   },
   message() {
   message() {
     return [
     return [
-      `We are sorry to see you cancelled your ${
-        settings.appName
-      } premium subscription. Would you mind giving us some feedback on what the site is lacking at the moment via this quick survey?`
+      `We are sorry to see you cancelled your ${settings.appName} premium subscription. Would you mind giving us some feedback on what the site is lacking at the moment via this quick survey?`
     ]
     ]
   },
   },
   secondaryMessage() {
   secondaryMessage() {
@@ -292,9 +288,7 @@ templates.verifyEmailToJoinTeam = ctaTemplate({
   },
   },
   message(opts) {
   message(opts) {
     return [
     return [
-      `Please click the button below to join the team and enjoy the benefits of an upgraded ${
-        settings.appName
-      } account.`
+      `Please click the button below to join the team and enjoy the benefits of an upgraded ${settings.appName} account.`
     ]
     ]
   },
   },
   ctaText(opts) {
   ctaText(opts) {
@@ -348,9 +342,7 @@ templates.ownershipTransferConfirmationPreviousOwner = NoCTAEmailTemplate({
       : `<b>${projectName}</b>`
       : `<b>${projectName}</b>`
     return [
     return [
       `As per your request, we have made ${nameAndEmail} the owner of ${projectNameDisplay}.`,
       `As per your request, we have made ${nameAndEmail} the owner of ${projectNameDisplay}.`,
-      `If you haven't asked to change the owner of ${projectNameDisplay}, please get in touch with us via ${
-        settings.adminEmail
-      }.`
+      `If you haven't asked to change the owner of ${projectNameDisplay}, please get in touch with us via ${settings.adminEmail}.`
     ]
     ]
   }
   }
 })
 })
@@ -403,23 +395,17 @@ templates.userOnboardingEmail = NoCTAEmailTemplate({
   message(opts, isPlainText) {
   message(opts, isPlainText) {
     const learnLatexLink = EmailMessageHelper.displayLink(
     const learnLatexLink = EmailMessageHelper.displayLink(
       'Learn LaTeX in 30 minutes',
       'Learn LaTeX in 30 minutes',
-      `${
-        settings.siteUrl
-      }/learn/latex/Learn_LaTeX_in_30_minutes?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
+      `${settings.siteUrl}/learn/latex/Learn_LaTeX_in_30_minutes?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
       isPlainText
       isPlainText
     )
     )
     const templatesLinks = EmailMessageHelper.displayLink(
     const templatesLinks = EmailMessageHelper.displayLink(
       'Find a beautiful template',
       'Find a beautiful template',
-      `${
-        settings.siteUrl
-      }/latex/templates?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
+      `${settings.siteUrl}/latex/templates?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
       isPlainText
       isPlainText
     )
     )
     const collaboratorsLink = EmailMessageHelper.displayLink(
     const collaboratorsLink = EmailMessageHelper.displayLink(
       'Work with your collaborators',
       'Work with your collaborators',
-      `${
-        settings.siteUrl
-      }/learn/how-to/Sharing_a_project?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
+      `${settings.siteUrl}/learn/how-to/Sharing_a_project?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
       isPlainText
       isPlainText
     )
     )
     const siteLink = EmailMessageHelper.displayLink(
     const siteLink = EmailMessageHelper.displayLink(
@@ -438,9 +424,7 @@ templates.userOnboardingEmail = NoCTAEmailTemplate({
       isPlainText
       isPlainText
     )
     )
     return [
     return [
-      `Thanks for signing up for ${
-        settings.appName
-      } recently. We hope you've been finding it useful! Here are some key features to help you get the most out of the service:`,
+      `Thanks for signing up for ${settings.appName} recently. We hope you've been finding it useful! Here are some key features to help you get the most out of the service:`,
       `${learnLatexLink}: In this tutorial we provide a quick and easy first introduction to LaTeX with no prior knowledge required. By the time you are finished, you will have written your first LaTeX document!`,
       `${learnLatexLink}: In this tutorial we provide a quick and easy first introduction to LaTeX with no prior knowledge required. By the time you are finished, you will have written your first LaTeX document!`,
       `${templatesLinks}: If you're looking for a template or example to get started, we've a large selection available in our template gallery, including CVs, project reports, journal articles and more.`,
       `${templatesLinks}: If you're looking for a template or example to get started, we've a large selection available in our template gallery, including CVs, project reports, journal articles and more.`,
       `${collaboratorsLink}: One of the key features of Overleaf is the ability to share projects and collaborate on them with other users. Find out how to share your projecs with your colleagues in this quick how-to guide.`,
       `${collaboratorsLink}: One of the key features of Overleaf is the ability to share projects and collaborate on them with other users. Find out how to share your projecs with your colleagues in this quick how-to guide.`,
@@ -485,12 +469,8 @@ templates.securityAlert = NoCTAEmailTemplate({
       `We are writing to let you know that ${actionDescribed} on ${dateFormatted} at ${timeFormatted} GMT.`,
       `We are writing to let you know that ${actionDescribed} on ${dateFormatted} at ${timeFormatted} GMT.`,
       ...message,
       ...message,
       `If this was you, you can ignore this email.`,
       `If this was you, you can ignore this email.`,
-      `If this was not you, we recommend getting in touch with our support team at ${
-        settings.adminEmail
-      } to report this as potentially suspicious activity on your account.`,
-      `We also encourage you to read our ${helpLink} to keeping your ${
-        settings.appName
-      } account safe.`
+      `If this was not you, we recommend getting in touch with our support team at ${settings.adminEmail} to report this as potentially suspicious activity on your account.`,
+      `We also encourage you to read our ${helpLink} to keeping your ${settings.appName} account safe.`
     ]
     ]
   }
   }
 })
 })

+ 1 - 3
services/web/app/src/Features/Errors/Errors.js

@@ -105,9 +105,7 @@ class SAMLSessionDataMissing extends BackwardCompatibleError {
       samlSession.userEmailAttributeUnreliable
       samlSession.userEmailAttributeUnreliable
     ) {
     ) {
       this.tryAgain = false
       this.tryAgain = false
-      this.message = `Your account settings at your institution prevent us from accessing your email address. You will need to make your email address public at your institution in order to link with ${
-        settings.appName
-      }. Please contact your IT department if you have any questions.`
+      this.message = `Your account settings at your institution prevent us from accessing your email address. You will need to make your email address public at your institution in order to link with ${settings.appName}. Please contact your IT department if you have any questions.`
     } else if (!institutionEmail) {
     } else if (!institutionEmail) {
       this.message =
       this.message =
         'Unable to confirm your institutional email address. The institutional identity provider did not provide an email address in the expected attribute. Please contact us if this keeps happening.'
         'Unable to confirm your institutional email address. The institutional identity provider did not provide an email address in the expected attribute. Please contact us if this keeps happening.'

+ 4 - 11
services/web/app/src/Features/Exports/ExportsHandler.js

@@ -1,9 +1,8 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
-    standard/no-callback-literal,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.
@@ -202,9 +201,7 @@ module.exports = ExportsHandler = self = {
     }
     }
     return request.get(
     return request.get(
       {
       {
-        url: `${
-          settings.apis.project_history.url
-        }/project/${project_id}/version`,
+        url: `${settings.apis.project_history.url}/project/${project_id}/version`,
         json: true
         json: true
       },
       },
       function(err, res, body) {
       function(err, res, body) {
@@ -217,9 +214,7 @@ module.exports = ExportsHandler = self = {
           return callback(null, body.version)
           return callback(null, body.version)
         } else {
         } else {
           err = new OError(
           err = new OError(
-            `project history version returned a failure status code: ${
-              res.statusCode
-            }`,
+            `project history version returned a failure status code: ${res.statusCode}`,
             { project_id }
             { project_id }
           )
           )
           return callback(err)
           return callback(err)
@@ -262,9 +257,7 @@ module.exports = ExportsHandler = self = {
     }
     }
     return request.get(
     return request.get(
       {
       {
-        url: `${
-          settings.apis.v1.url
-        }/api/v1/sharelatex/exports/${export_id}/${type}_url`,
+        url: `${settings.apis.v1.url}/api/v1/sharelatex/exports/${export_id}/${type}_url`,
         auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass }
         auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass }
       },
       },
       function(err, res, body) {
       function(err, res, body) {

+ 1 - 1
services/web/app/src/Features/FileStore/FileHashManager.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 3
services/web/app/src/Features/FileStore/FileStoreHandler.js

@@ -97,9 +97,7 @@ const FileStoreHandler = {
         writeStream.on('response', function(response) {
         writeStream.on('response', function(response) {
           if (![200, 201].includes(response.statusCode)) {
           if (![200, 201].includes(response.statusCode)) {
             err = new OError(
             err = new OError(
-              `non-ok response from filestore for upload: ${
-                response.statusCode
-              }`,
+              `non-ok response from filestore for upload: ${response.statusCode}`,
               { statusCode: response.statusCode }
               { statusCode: response.statusCode }
             )
             )
             return callbackOnce(err)
             return callbackOnce(err)

+ 3 - 9
services/web/app/src/Features/History/HistoryController.js

@@ -179,9 +179,7 @@ module.exports = HistoryController = {
     HistoryController._makeRequest(
     HistoryController._makeRequest(
       {
       {
         method: 'POST',
         method: 'POST',
-        url: `${
-          settings.apis.project_history.url
-        }/project/${projectId}/user/${userId}/labels`,
+        url: `${settings.apis.project_history.url}/project/${projectId}/user/${userId}/labels`,
         json: { comment, version }
         json: { comment, version }
       },
       },
       function(err, label) {
       function(err, label) {
@@ -274,9 +272,7 @@ module.exports = HistoryController = {
     HistoryController._makeRequest(
     HistoryController._makeRequest(
       {
       {
         method: 'DELETE',
         method: 'DELETE',
-        url: `${
-          settings.apis.project_history.url
-        }/project/${projectId}/user/${userId}/labels/${labelId}`
+        url: `${settings.apis.project_history.url}/project/${projectId}/user/${userId}/labels/${labelId}`
       },
       },
       function(err) {
       function(err) {
         if (err) {
         if (err) {
@@ -338,9 +334,7 @@ module.exports = HistoryController = {
     }
     }
     // increase timeout to 6 minutes
     // increase timeout to 6 minutes
     res.setTimeout(6 * 60 * 1000)
     res.setTimeout(6 * 60 * 1000)
-    const url = `${
-      settings.apis.v1_history.url
-    }/projects/${v1ProjectId}/version/${version}/zip`
+    const url = `${settings.apis.v1_history.url}/projects/${v1ProjectId}/version/${version}/zip`
     const options = {
     const options = {
       auth: {
       auth: {
         user: settings.apis.v1_history.user,
         user: settings.apis.v1_history.user,

+ 2 - 2
services/web/app/src/Features/History/HistoryManager.js

@@ -106,8 +106,8 @@ async function injectUserDetails(data) {
   const entries = Array.isArray(data.diff)
   const entries = Array.isArray(data.diff)
     ? data.diff
     ? data.diff
     : Array.isArray(data.updates)
     : Array.isArray(data.updates)
-      ? data.updates
-      : []
+    ? data.updates
+    : []
   for (const entry of entries) {
   for (const entry of entries) {
     for (const user of (entry.meta && entry.meta.users) || []) {
     for (const user of (entry.meta && entry.meta.users) || []) {
       if (typeof user === 'string') {
       if (typeof user === 'string') {

+ 1 - 1
services/web/app/src/Features/History/RestoreManager.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 3
services/web/app/src/Features/Institutions/InstitutionsAPI.js

@@ -207,9 +207,7 @@ var makeAffiliationRequest = function(requestOptions, callback) {
         if (body && body.errors) {
         if (body && body.errors) {
           errorMessage = `${response.statusCode}: ${body.errors}`
           errorMessage = `${response.statusCode}: ${body.errors}`
         } else {
         } else {
-          errorMessage = `${requestOptions.defaultErrorMessage}: ${
-            response.statusCode
-          }`
+          errorMessage = `${requestOptions.defaultErrorMessage}: ${response.statusCode}`
         }
         }
 
 
         logger.warn(
         logger.warn(

+ 2 - 6
services/web/app/src/Features/LinkedFiles/LinkedFilesController.js

@@ -132,9 +132,7 @@ module.exports = LinkedFilesController = {
   },
   },
 
 
   handleError(error, req, res, next) {
   handleError(error, req, res, next) {
-    if (error instanceof BadDataError) {
-      return res.status(400).send('The submitted data is not valid')
-    } else if (error instanceof AccessDeniedError) {
+    if (error instanceof AccessDeniedError) {
       return res.status(403).send('You do not have access to this project')
       return res.status(403).send('You do not have access to this project')
     } else if (error instanceof BadDataError) {
     } else if (error instanceof BadDataError) {
       return res.status(400).send('The submitted data is not valid')
       return res.status(400).send('The submitted data is not valid')
@@ -156,9 +154,7 @@ module.exports = LinkedFilesController = {
       return res
       return res
         .status(422)
         .status(422)
         .send(
         .send(
-          `Your URL could not be reached (${
-            error.statusCode
-          } status code). Please check it and try again.`
+          `Your URL could not be reached (${error.statusCode} status code). Please check it and try again.`
         )
         )
     } else if (error instanceof InvalidUrlError) {
     } else if (error instanceof InvalidUrlError) {
       return res
       return res

+ 1 - 1
services/web/app/src/Features/LinkedFiles/LinkedFilesHandler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 1
services/web/app/src/Features/LinkedFiles/ProjectFileAgent.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 3 - 7
services/web/app/src/Features/LinkedFiles/ProjectOutputFileAgent.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */
@@ -100,9 +100,7 @@ module.exports = ProjectOutputFileAgent = {
                 ) // Created
                 ) // Created
               } else {
               } else {
                 err = new OutputFileFetchFailedError(
                 err = new OutputFileFetchFailedError(
-                  `Output file fetch failed: ${linkedFileData.build_id}, ${
-                    linkedFileData.source_output_file_path
-                  }`
+                  `Output file fetch failed: ${linkedFileData.build_id}, ${linkedFileData.source_output_file_path}`
                 )
                 )
                 err.statusCode = response.statusCode
                 err.statusCode = response.statusCode
                 return callback(err)
                 return callback(err)
@@ -158,9 +156,7 @@ module.exports = ProjectOutputFileAgent = {
                 ) // Created
                 ) // Created
               } else {
               } else {
                 err = new OutputFileFetchFailedError(
                 err = new OutputFileFetchFailedError(
-                  `Output file fetch failed: ${linkedFileData.build_id}, ${
-                    linkedFileData.source_output_file_path
-                  }`
+                  `Output file fetch failed: ${linkedFileData.build_id}, ${linkedFileData.source_output_file_path}`
                 )
                 )
                 err.statusCode = response.statusCode
                 err.statusCode = response.statusCode
                 return callback(err)
                 return callback(err)

+ 1 - 1
services/web/app/src/Features/LinkedFiles/UrlAgent.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 1
services/web/app/src/Features/Metadata/MetaHandler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-cond-assign,
     no-cond-assign,
 */
 */

+ 1 - 1
services/web/app/src/Features/Notifications/NotificationsController.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 1 - 1
services/web/app/src/Features/Project/ProjectCollabratecDetailsHandler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 1 - 2
services/web/app/src/Features/Project/ProjectController.js

@@ -751,8 +751,7 @@ const ProjectController = {
             } else if (
             } else if (
               Settings.wsUrlV2 &&
               Settings.wsUrlV2 &&
               Settings.wsUrlV2Percentage > 0 &&
               Settings.wsUrlV2Percentage > 0 &&
-              (ObjectId(projectId).getTimestamp() / 1000) %
-                100 <
+              (ObjectId(projectId).getTimestamp() / 1000) % 100 <
                 Settings.wsUrlV2Percentage
                 Settings.wsUrlV2Percentage
             ) {
             ) {
               wsUrl = Settings.wsUrlV2
               wsUrl = Settings.wsUrlV2

+ 1 - 1
services/web/app/src/Features/Project/ProjectCreationHandler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-path-concat,
     no-path-concat,
 */
 */

+ 2 - 2
services/web/app/src/Features/Project/ProjectDeleter.js

@@ -226,8 +226,8 @@ async function deleteProject(projectId, options = {}) {
       deletedProjectLastUpdatedAt: project.lastUpdated
       deletedProjectLastUpdatedAt: project.lastUpdated
     }
     }
 
 
-    Object.keys(deleterData).forEach(
-      key => (deleterData[key] === undefined ? delete deleterData[key] : '')
+    Object.keys(deleterData).forEach(key =>
+      deleterData[key] === undefined ? delete deleterData[key] : ''
     )
     )
 
 
     await DeletedProject.updateOne(
     await DeletedProject.updateOne(

+ 1 - 1
services/web/app/src/Features/Project/ProjectGetter.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 1
services/web/app/src/Features/Project/ProjectHistoryHandler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 2 - 8
services/web/app/src/Features/Project/ProjectLocator.js

@@ -198,11 +198,7 @@ const ProjectLocator = {
       if (!found) {
       if (!found) {
         cb(
         cb(
           new Error(
           new Error(
-            `not found project: ${
-              project._id
-            } search path: ${needlePath}, folder ${
-              foldersList[level]
-            } could not be found`
+            `not found project: ${project._id} search path: ${needlePath}, folder ${foldersList[level]} could not be found`
           )
           )
         )
         )
       }
       }
@@ -242,9 +238,7 @@ const ProjectLocator = {
       } else {
       } else {
         cb(
         cb(
           new Error(
           new Error(
-            `not found project: ${
-              project._id
-            } search path: ${needlePath}, entity ${entityName} could not be found`
+            `not found project: ${project._id} search path: ${needlePath}, entity ${entityName} could not be found`
           )
           )
         )
         )
       }
       }

+ 1 - 1
services/web/app/src/Features/Project/ProjectRootDocManager.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
     no-useless-escape,
     no-useless-escape,

+ 2 - 4
services/web/app/src/Features/Project/ProjectTokenGenerator.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
@@ -87,9 +87,7 @@ const ProjectTokenGenerator = {
             if (response.statusCode !== 200) {
             if (response.statusCode !== 200) {
               return cb(
               return cb(
                 new Error(
                 new Error(
-                  `non-200 response from v1 read-token-exists api: ${
-                    response.statusCode
-                  }`
+                  `non-200 response from v1 read-token-exists api: ${response.statusCode}`
                 )
                 )
               )
               )
             }
             }

+ 1 - 1
services/web/app/src/Features/Project/ProjectUpdateHandler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     no-unused-vars,
     no-unused-vars,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 1 - 1
services/web/app/src/Features/Publishers/PublishersGetter.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 2 - 4
services/web/app/src/Features/References/ReferencesHandler.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */
@@ -204,9 +204,7 @@ module.exports = ReferencesHandler = {
                 return callback(null, data)
                 return callback(null, data)
               } else {
               } else {
                 err = new Error(
                 err = new Error(
-                  `references api responded with non-success code: ${
-                    res.statusCode
-                  }`
+                  `references api responded with non-success code: ${res.statusCode}`
                 )
                 )
                 return callback(err)
                 return callback(err)
               }
               }

+ 1 - 1
services/web/app/src/Features/Security/OneTimeTokenHandler.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 1
services/web/app/src/Features/ServerAdmin/AdminController.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len
     max-len
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 1 - 1
services/web/app/src/Features/StaticPages/HomeController.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-path-concat,
     no-path-concat,
     no-unused-vars,
     no-unused-vars,

+ 1 - 2
services/web/app/src/Features/Subscription/LimitationsManager.js

@@ -1,8 +1,7 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
-    standard/no-callback-literal,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.

+ 1 - 2
services/web/app/src/Features/Subscription/RecurlyWrapper.js

@@ -1,10 +1,9 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
     node/no-deprecated-api,
     node/no-deprecated-api,
-    standard/no-callback-literal,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.

+ 1 - 1
services/web/app/src/Features/Subscription/SubscriptionController.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-return-assign,
     no-return-assign,
     no-unused-vars,
     no-unused-vars,

+ 1 - 1
services/web/app/src/Features/Subscription/SubscriptionGroupHandler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 1
services/web/app/src/Features/Subscription/SubscriptionLocator.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 2 - 4
services/web/app/src/Features/Subscription/SubscriptionViewModelBuilder.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-return-assign,
     no-return-assign,
     no-unused-vars,
     no-unused-vars,
@@ -98,9 +98,7 @@ module.exports = {
             if (plan == null) {
             if (plan == null) {
               return cb(
               return cb(
                 new Error(
                 new Error(
-                  `No plan found for planCode '${
-                    personalSubscription.planCode
-                  }'`
+                  `No plan found for planCode '${personalSubscription.planCode}'`
                 )
                 )
               )
               )
             }
             }

+ 2 - 6
services/web/app/src/Features/Subscription/TeamInvitesHandler.js

@@ -190,9 +190,7 @@ var createInvite = function(subscription, email, inviter, callback) {
       const opts = {
       const opts = {
         to: email,
         to: email,
         inviter,
         inviter,
-        acceptInviteUrl: `${settings.siteUrl}/subscription/invites/${
-          invite.token
-        }/`,
+        acceptInviteUrl: `${settings.siteUrl}/subscription/invites/${invite.token}/`,
         appName: settings.appName
         appName: settings.appName
       }
       }
       EmailHandler.sendEmail('verifyEmailToJoinTeam', opts, error => {
       EmailHandler.sendEmail('verifyEmailToJoinTeam', opts, error => {
@@ -273,9 +271,7 @@ var checkIfInviteIsPossible = function(subscription, email, callback) {
 var getInviterName = function(inviter) {
 var getInviterName = function(inviter) {
   let inviterName
   let inviterName
   if (inviter.first_name && inviter.last_name) {
   if (inviter.first_name && inviter.last_name) {
-    inviterName = `${inviter.first_name} ${inviter.last_name} (${
-      inviter.email
-    })`
+    inviterName = `${inviter.first_name} ${inviter.last_name} (${inviter.email})`
   } else {
   } else {
     inviterName = inviter.email
     inviterName = inviter.email
   }
   }

+ 1 - 1
services/web/app/src/Features/Subscription/V1SubscriptionManager.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 1 - 1
services/web/app/src/Features/SystemMessages/SystemMessageManager.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.

+ 1 - 3
services/web/app/src/Features/Templates/TemplatesManager.js

@@ -41,9 +41,7 @@ const TemplatesManager = {
     _callback
     _callback
   ) {
   ) {
     const callback = _.once(_callback)
     const callback = _.once(_callback)
-    const zipUrl = `${
-      settings.apis.v1.url
-    }/api/v1/sharelatex/templates/${templateVersionId}`
+    const zipUrl = `${settings.apis.v1.url}/api/v1/sharelatex/templates/${templateVersionId}`
     const zipReq = request(zipUrl, {
     const zipReq = request(zipUrl, {
       auth: {
       auth: {
         user: settings.apis.v1.user,
         user: settings.apis.v1.user,

+ 1 - 1
services/web/app/src/Features/ThirdPartyDataStore/TpdsController.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
    camelcase,
    camelcase,
-   handle-callback-err,
+   node/handle-callback-err,
    max-len,
    max-len,
  */
  */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 1 - 1
services/web/app/src/Features/ThirdPartyDataStore/TpdsUpdateHandler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */

+ 1 - 1
services/web/app/src/Features/ThirdPartyDataStore/UpdateMerger.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 1 - 1
services/web/app/src/Features/Uploads/ArchiveManager.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-return-assign,
     no-return-assign,
 */
 */

+ 1 - 3
services/web/app/src/Features/User/SAMLIdentityManager.js

@@ -132,9 +132,7 @@ async function _sendLinkedEmail(userId, providerName, institutionEmail) {
   const user = await UserGetter.promises.getUser(userId, { email: 1 })
   const user = await UserGetter.promises.getUser(userId, { email: 1 })
   const emailOptions = {
   const emailOptions = {
     to: user.email,
     to: user.email,
-    actionDescribed: `an Institutional SSO account at ${providerName} was linked to your account ${
-      user.email
-    }`,
+    actionDescribed: `an Institutional SSO account at ${providerName} was linked to your account ${user.email}`,
     action: 'institutional SSO account linked',
     action: 'institutional SSO account linked',
     message: [
     message: [
       `<span style="display:inline-block;padding: 0 20px;width:100%;">Linked: <br/><b>${institutionEmail}</b></span>`
       `<span style="display:inline-block;padding: 0 20px;width:100%;">Linked: <br/><b>${institutionEmail}</b></span>`

+ 2 - 6
services/web/app/src/Features/User/UserController.js

@@ -23,9 +23,7 @@ const { expressify } = require('../../util/promises')
 async function _sendSecurityAlertClearedSessions(user) {
 async function _sendSecurityAlertClearedSessions(user) {
   const emailOptions = {
   const emailOptions = {
     to: user.email,
     to: user.email,
-    actionDescribed: `active sessions were cleared on your account ${
-      user.email
-    }`,
+    actionDescribed: `active sessions were cleared on your account ${user.email}`,
     action: 'active sessions cleared'
     action: 'active sessions cleared'
   }
   }
   try {
   try {
@@ -42,9 +40,7 @@ async function _sendSecurityAlertClearedSessions(user) {
 function _sendSecurityAlertPasswordChanged(user) {
 function _sendSecurityAlertPasswordChanged(user) {
   const emailOptions = {
   const emailOptions = {
     to: user.email,
     to: user.email,
-    actionDescribed: `your password has been changed on your account ${
-      user.email
-    }`,
+    actionDescribed: `your password has been changed on your account ${user.email}`,
     action: 'password changed'
     action: 'password changed'
   }
   }
   EmailHandler.sendEmail('securityAlert', emailOptions, error => {
   EmailHandler.sendEmail('securityAlert', emailOptions, error => {

+ 1 - 3
services/web/app/src/Features/User/UserEmailsConfirmationHandler.js

@@ -36,9 +36,7 @@ function sendConfirmationEmail(userId, email, emailTemplate, callback) {
       }
       }
       const emailOptions = {
       const emailOptions = {
         to: email,
         to: email,
-        confirmEmailUrl: `${
-          settings.siteUrl
-        }/user/emails/confirm?token=${token}`,
+        confirmEmailUrl: `${settings.siteUrl}/user/emails/confirm?token=${token}`,
         sendingUser_id: userId
         sendingUser_id: userId
       }
       }
       EmailHandler.sendEmail(emailTemplate, emailOptions, callback)
       EmailHandler.sendEmail(emailTemplate, emailOptions, callback)

+ 1 - 3
services/web/app/src/Features/User/UserEmailsController.js

@@ -14,9 +14,7 @@ const { expressify } = require('../../util/promises')
 async function _sendSecurityAlertEmail(user, email) {
 async function _sendSecurityAlertEmail(user, email) {
   const emailOptions = {
   const emailOptions = {
     to: user.email,
     to: user.email,
-    actionDescribed: `a secondary email address has been added to your account ${
-      user.email
-    }`,
+    actionDescribed: `a secondary email address has been added to your account ${user.email}`,
     message: [
     message: [
       `<span style="display:inline-block;padding: 0 20px;width:100%;">Added: <br/><b>${email}</b></span>`
       `<span style="display:inline-block;padding: 0 20px;width:100%;">Added: <br/><b>${email}</b></span>`
     ],
     ],

+ 1 - 3
services/web/app/src/Features/User/UserRegistrationHandler.js

@@ -129,9 +129,7 @@ const UserRegistrationHandler = {
               return callback(err)
               return callback(err)
             }
             }
 
 
-            const setNewPasswordUrl = `${
-              settings.siteUrl
-            }/user/activate?token=${token}&user_id=${user._id}`
+            const setNewPasswordUrl = `${settings.siteUrl}/user/activate?token=${token}&user_id=${user._id}`
 
 
             EmailHandler.sendEmail(
             EmailHandler.sendEmail(
               'registered',
               'registered',

+ 27 - 26
services/web/app/src/Features/User/UserSessionsManager.js

@@ -93,36 +93,37 @@ UserSessionsManager = {
         return callback(null, [])
         return callback(null, [])
       }
       }
 
 
-      Async.mapSeries(sessionKeys, (k, cb) => rclient.get(k, cb), function(
-        err,
-        sessions
-      ) {
-        if (err) {
-          OError.tag(err, 'error getting all sessions for user from redis', {
-            user_id: user._id
-          })
-          return callback(err)
-        }
-
-        const result = []
-        for (let session of Array.from(sessions)) {
-          if (!session) {
-            continue
+      Async.mapSeries(
+        sessionKeys,
+        (k, cb) => rclient.get(k, cb),
+        function(err, sessions) {
+          if (err) {
+            OError.tag(err, 'error getting all sessions for user from redis', {
+              user_id: user._id
+            })
+            return callback(err)
           }
           }
-          session = JSON.parse(session)
-          let sessionUser = session.passport && session.passport.user
-          if (!sessionUser) {
-            sessionUser = session.user
+
+          const result = []
+          for (let session of Array.from(sessions)) {
+            if (!session) {
+              continue
+            }
+            session = JSON.parse(session)
+            let sessionUser = session.passport && session.passport.user
+            if (!sessionUser) {
+              sessionUser = session.user
+            }
+
+            result.push({
+              ip_address: sessionUser.ip_address,
+              session_created: sessionUser.session_created
+            })
           }
           }
 
 
-          result.push({
-            ip_address: sessionUser.ip_address,
-            session_created: sessionUser.session_created
-          })
+          callback(null, result)
         }
         }
-
-        callback(null, result)
-      })
+      )
     })
     })
   },
   },
 
 

+ 1 - 2
services/web/app/src/Features/UserMembership/UserMembershipHandler.js

@@ -1,8 +1,7 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
-    standard/no-callback-literal,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.

+ 1 - 1
services/web/app/src/Features/UserMembership/UserMembershipViewModel.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 1 - 1
services/web/app/src/Features/UserMembership/UserMembershipsHandler.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 2 - 6
services/web/app/src/Features/V1/V1Api.js

@@ -86,17 +86,13 @@ const V1Api = {
       return callback(error)
       return callback(error)
     } else if (response.statusCode === 404) {
     } else if (response.statusCode === 404) {
       error = new Errors.NotFoundError(
       error = new Errors.NotFoundError(
-        `overleaf v1 returned non-success code: ${response.statusCode} ${
-          options.method
-        } ${options.uri}`
+        `overleaf v1 returned non-success code: ${response.statusCode} ${options.method} ${options.uri}`
       )
       )
       error.statusCode = response.statusCode
       error.statusCode = response.statusCode
       return callback(error)
       return callback(error)
     } else {
     } else {
       error = new Error(
       error = new Error(
-        `overleaf v1 returned non-success code: ${response.statusCode} ${
-          options.method
-        } ${options.uri}`
+        `overleaf v1 returned non-success code: ${response.statusCode} ${options.method} ${options.uri}`
       )
       )
       error.statusCode = response.statusCode
       error.statusCode = response.statusCode
       return callback(error)
       return callback(error)

+ 2 - 4
services/web/app/src/Features/V1/V1Handler.js

@@ -1,6 +1,6 @@
 /* eslint-disable
 /* eslint-disable
     camelcase,
     camelcase,
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
     no-unused-vars,
     no-unused-vars,
 */
 */
@@ -93,9 +93,7 @@ module.exports = V1Handler = {
           return callback(null, true)
           return callback(null, true)
         } else {
         } else {
           err = new Error(
           err = new Error(
-            `Unexpected status from v1 password reset api: ${
-              response.statusCode
-            }`
+            `Unexpected status from v1 password reset api: ${response.statusCode}`
           )
           )
           return callback(err, false)
           return callback(err, false)
         }
         }

+ 0 - 1
services/web/app/src/infrastructure/Csrf.js

@@ -2,7 +2,6 @@
     max-len,
     max-len,
     no-return-assign,
     no-return-assign,
     no-unused-vars,
     no-unused-vars,
-    standard/no-callback-literal,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.

+ 1 - 1
services/web/app/src/infrastructure/FileWriter.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-    handle-callback-err,
+    node/handle-callback-err,
     max-len,
     max-len,
 */
 */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.

+ 4 - 1
services/web/frontend/js/base.js

@@ -66,7 +66,10 @@ const App = angular
             processEscapes: true,
             processEscapes: true,
             // Dollar delimiters are added by the mathjax directive
             // Dollar delimiters are added by the mathjax directive
             inlineMath: [['\\(', '\\)']],
             inlineMath: [['\\(', '\\)']],
-            displayMath: [['$$', '$$'], ['\\[', '\\]']]
+            displayMath: [
+              ['$$', '$$'],
+              ['\\[', '\\]']
+            ]
           }
           }
         })
         })
     )
     )

+ 1 - 3
services/web/frontend/js/directives/complexPassword.js

@@ -80,9 +80,7 @@ App.directive('complexPassword', () => ({
       }
       }
       if (opts.length.min != null && modelValue.length < opts.length.min) {
       if (opts.length.min != null && modelValue.length < opts.length.min) {
         isValid = false
         isValid = false
-        scope.complexPasswordErrorMessage = `Password too short, minimum ${
-          opts.length.min
-        }`
+        scope.complexPasswordErrorMessage = `Password too short, minimum ${opts.length.min}`
       }
       }
       ngModelCtrl.$setValidity('complexPassword', isValid)
       ngModelCtrl.$setValidity('complexPassword', isValid)
       return modelValue
       return modelValue

+ 2 - 2
services/web/frontend/js/directives/equals.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-*/
+ */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.
 /*
 /*
@@ -14,7 +14,7 @@ export default App.directive('equals', () => ({
   link(scope, elem, attrs, ctrl) {
   link(scope, elem, attrs, ctrl) {
     const firstField = `#${attrs.equals}`
     const firstField = `#${attrs.equals}`
     return elem.add(firstField).on('keyup', () =>
     return elem.add(firstField).on('keyup', () =>
-      scope.$apply(function() {
+      scope.$apply(function () {
         const equal = elem.val() === $(firstField).val()
         const equal = elem.val() === $(firstField).val()
         return ctrl.$setValidity('areEqual', equal)
         return ctrl.$setValidity('areEqual', equal)
       })
       })

+ 2 - 2
services/web/frontend/js/directives/expandableTextArea.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-*/
+ */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.
 /*
 /*
@@ -12,7 +12,7 @@ import App from '../base'
 export default App.directive('expandableTextArea', () => ({
 export default App.directive('expandableTextArea', () => ({
   restrict: 'A',
   restrict: 'A',
   link(scope, el) {
   link(scope, el) {
-    const resetHeight = function() {
+    const resetHeight = function () {
       const curHeight = el.outerHeight()
       const curHeight = el.outerHeight()
       const fitHeight = el.prop('scrollHeight')
       const fitHeight = el.prop('scrollHeight')
       // clear height if text area is empty
       // clear height if text area is empty

+ 7 - 7
services/web/frontend/js/directives/fineUpload.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-*/
+ */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.
 /*
 /*
@@ -42,12 +42,12 @@ export default App.directive('fineUpload', $timeout => ({
       validation.sizeLimit = scope.sizeLimit
       validation.sizeLimit = scope.sizeLimit
     }
     }
     const maxConnections = scope.maxConnections || 1
     const maxConnections = scope.maxConnections || 1
-    const onComplete = scope.onCompleteCallback || function() {}
-    const onUpload = scope.onUploadCallback || function() {}
-    const onError = scope.onErrorCallback || function() {}
-    const onValidateBatch = scope.onValidateBatch || function() {}
-    const onSubmit = scope.onSubmitCallback || function() {}
-    const onCancel = scope.onCancelCallback || function() {}
+    const onComplete = scope.onCompleteCallback || function () {}
+    const onUpload = scope.onUploadCallback || function () {}
+    const onError = scope.onErrorCallback || function () {}
+    const onValidateBatch = scope.onValidateBatch || function () {}
+    const onSubmit = scope.onSubmitCallback || function () {}
+    const onCancel = scope.onCancelCallback || function () {}
     if (scope.autoUpload == null) {
     if (scope.autoUpload == null) {
       autoUpload = true
       autoUpload = true
     } else {
     } else {

+ 2 - 2
services/web/frontend/js/directives/maxHeight.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-*/
+ */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.
 /*
 /*
@@ -13,7 +13,7 @@ import App from '../base'
 export default App.directive('maxHeight', () => ({
 export default App.directive('maxHeight', () => ({
   restrict: 'A',
   restrict: 'A',
   link(scope, element, attrs) {
   link(scope, element, attrs) {
-    return scope.$watch(attrs.maxHeight, function(value) {
+    return scope.$watch(attrs.maxHeight, function (value) {
       if (value != null) {
       if (value != null) {
         return element.css({ 'max-height': value })
         return element.css({ 'max-height': value })
       }
       }

+ 2 - 2
services/web/frontend/js/directives/onEnter.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-*/
+ */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.
 /*
 /*
@@ -10,7 +10,7 @@
 import App from '../base'
 import App from '../base'
 
 
 export default App.directive('onEnter', () => (scope, element, attrs) =>
 export default App.directive('onEnter', () => (scope, element, attrs) =>
-  element.bind('keydown keypress', function(event) {
+  element.bind('keydown keypress', function (event) {
     if (event.which === 13) {
     if (event.which === 13) {
       scope.$apply(() => scope.$eval(attrs.onEnter, { event }))
       scope.$apply(() => scope.$eval(attrs.onEnter, { event }))
       return event.preventDefault()
       return event.preventDefault()

+ 2 - 2
services/web/frontend/js/directives/rightClick.js

@@ -1,5 +1,5 @@
 /* eslint-disable
 /* eslint-disable
-*/
+ */
 // TODO: This file was created by bulk-decaffeinate.
 // TODO: This file was created by bulk-decaffeinate.
 // Fix any style issues and re-enable lint.
 // Fix any style issues and re-enable lint.
 /*
 /*
@@ -12,7 +12,7 @@ import App from '../base'
 export default App.directive('rightClick', () => ({
 export default App.directive('rightClick', () => ({
   restrict: 'A',
   restrict: 'A',
   link(scope, element, attrs) {
   link(scope, element, attrs) {
-    return element.bind('contextmenu', function(e) {
+    return element.bind('contextmenu', function (e) {
       e.preventDefault()
       e.preventDefault()
       e.stopPropagation()
       e.stopPropagation()
       return scope.$eval(attrs.rightClick)
       return scope.$eval(attrs.rightClick)

+ 10 - 9
services/web/frontend/js/directives/videoPlayState.js

@@ -14,15 +14,16 @@ export default App.directive('videoPlayState', $parse => ({
   restrict: 'A',
   restrict: 'A',
   link(scope, element, attrs) {
   link(scope, element, attrs) {
     const videoDOMEl = element[0]
     const videoDOMEl = element[0]
-    return scope.$watch(() => $parse(attrs.videoPlayState)(scope), function(
-      shouldPlay
-    ) {
-      if (shouldPlay) {
-        videoDOMEl.currentTime = 0
-        return videoDOMEl.play()
-      } else {
-        return videoDOMEl.pause()
+    return scope.$watch(
+      () => $parse(attrs.videoPlayState)(scope),
+      function(shouldPlay) {
+        if (shouldPlay) {
+          videoDOMEl.currentTime = 0
+          return videoDOMEl.play()
+        } else {
+          return videoDOMEl.pause()
+        }
       }
       }
-    })
+    )
   }
   }
 }))
 }))

+ 13 - 16
services/web/frontend/js/features/chat/components/message-content.js

@@ -20,23 +20,20 @@ function MessageContent({ content }) {
     }
     }
   }, [])
   }, [])
 
 
-  useEffect(
-    () => {
-      // adds attributes to all the links generated by <Linkify/>, required due to https://github.com/tasti/react-linkify/issues/99
-      for (let a of root.current.getElementsByTagName('a')) {
-        a.setAttribute('target', '_blank')
-        a.setAttribute('rel', 'noreferrer noopener')
-      }
+  useEffect(() => {
+    // adds attributes to all the links generated by <Linkify/>, required due to https://github.com/tasti/react-linkify/issues/99
+    for (let a of root.current.getElementsByTagName('a')) {
+      a.setAttribute('target', '_blank')
+      a.setAttribute('rel', 'noreferrer noopener')
+    }
 
 
-      // MathJax typesetting
-      const MJHub = window.MathJax.Hub
-      const timeoutHandler = setTimeout(() => {
-        MJHub.Queue(['Typeset', MJHub, root.current])
-      }, 0)
-      return () => clearTimeout(timeoutHandler)
-    },
-    [content]
-  )
+    // MathJax typesetting
+    const MJHub = window.MathJax.Hub
+    const timeoutHandler = setTimeout(() => {
+      MJHub.Queue(['Typeset', MJHub, root.current])
+    }, 0)
+    return () => clearTimeout(timeoutHandler)
+  }, [content])
 
 
   return (
   return (
     <p ref={root}>
     <p ref={root}>

+ 10 - 13
services/web/frontend/js/features/chat/store/chat-store-effect.js

@@ -13,19 +13,16 @@ export function useChatStore() {
   const [loading, setLoading] = useState(chatStoreRef.current.loading)
   const [loading, setLoading] = useState(chatStoreRef.current.loading)
   const [messages, setMessages] = useState(chatStoreRef.current.messages)
   const [messages, setMessages] = useState(chatStoreRef.current.messages)
 
 
-  useEffect(
-    () => {
-      const chatStore = chatStoreRef.current
-      function handleStoreUpdated() {
-        setAtEnd(chatStore.atEnd)
-        setLoading(chatStore.loading)
-        setMessages(chatStore.messages)
-      }
-      chatStore.on('updated', handleStoreUpdated)
-      return () => chatStore.destroy()
-    },
-    [chatStoreRef]
-  )
+  useEffect(() => {
+    const chatStore = chatStoreRef.current
+    function handleStoreUpdated() {
+      setAtEnd(chatStore.atEnd)
+      setLoading(chatStore.loading)
+      setMessages(chatStore.messages)
+    }
+    chatStore.on('updated', handleStoreUpdated)
+    return () => chatStore.destroy()
+  }, [chatStoreRef])
 
 
   return {
   return {
     userId: user.id,
     userId: user.id,

+ 7 - 10
services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-inner.js

@@ -20,16 +20,13 @@ function FileTreeItemInner({ id, name, isSelected, icons }) {
 
 
   const itemRef = createRef()
   const itemRef = createRef()
 
 
-  useEffect(
-    () => {
-      if (isSelected && itemRef.current) {
-        scrollIntoViewIfNeeded(itemRef.current, {
-          scrollMode: 'if-needed'
-        })
-      }
-    },
-    [isSelected, itemRef]
-  )
+  useEffect(() => {
+    if (isSelected && itemRef.current) {
+      scrollIntoViewIfNeeded(itemRef.current, {
+        scrollMode: 'if-needed'
+      })
+    }
+  }, [isSelected, itemRef])
 
 
   function handleContextMenu(ev) {
   function handleContextMenu(ev) {
     ev.preventDefault()
     ev.preventDefault()

+ 4 - 6
services/web/frontend/js/features/file-tree/components/file-tree-root.js

@@ -28,12 +28,10 @@ function FileTreeRoot({
 }) {
 }) {
   const isReady = projectId && rootFolder
   const isReady = projectId && rootFolder
 
 
-  useEffect(
-    () => {
-      if (isReady) onInit()
-    },
-    [isReady]
-  )
+  useEffect(() => {
+    if (isReady) onInit()
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [isReady])
   if (!isReady) return null
   if (!isReady) return null
 
 
   return (
   return (

+ 3 - 6
services/web/frontend/js/features/file-tree/contexts/file-tree-draggable.js

@@ -61,12 +61,9 @@ export function useDraggable(draggedEntityId) {
 
 
   // remove the automatic preview as we're using a custom preview via
   // remove the automatic preview as we're using a custom preview via
   // FileTreeDraggablePreviewLayer
   // FileTreeDraggablePreviewLayer
-  useEffect(
-    () => {
-      preview(getEmptyImage())
-    },
-    [preview]
-  )
+  useEffect(() => {
+    preview(getEmptyImage())
+  }, [preview])
 
 
   return {
   return {
     dragRef,
     dragRef,

+ 7 - 9
services/web/frontend/js/features/file-tree/contexts/file-tree-selectable.js

@@ -76,15 +76,13 @@ export function FileTreeSelectableProvider({
   const { fileTreeData } = useFileTreeMutable()
   const { fileTreeData } = useFileTreeMutable()
 
 
   // calls `onSelect` on entities selection
   // calls `onSelect` on entities selection
-  useEffect(
-    () => {
-      const selectedEntities = Array.from(selectedEntityIds).map(id =>
-        findInTree(fileTreeData, id)
-      )
-      onSelect(selectedEntities)
-    },
-    [fileTreeData, selectedEntityIds]
-  )
+  useEffect(() => {
+    const selectedEntities = Array.from(selectedEntityIds).map(id =>
+      findInTree(fileTreeData, id)
+    )
+    onSelect(selectedEntities)
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [fileTreeData, selectedEntityIds])
 
 
   useEffect(() => {
   useEffect(() => {
     // listen for `editor.openDoc` and selected that doc
     // listen for `editor.openDoc` and selected that doc

+ 3 - 1
services/web/frontend/js/features/file-tree/controllers/file-tree-controller.js

@@ -55,7 +55,9 @@ App.controller('ReactFileTreeController', function(
       // multi-selected entity" so here we pass a count of 0
       // multi-selected entity" so here we pass a count of 0
       $scope.$emit('entities:multiSelected', { count: 0 })
       $scope.$emit('entities:multiSelected', { count: 0 })
     } else if (selectedEntities.length > 1) {
     } else if (selectedEntities.length > 1) {
-      $scope.$emit('entities:multiSelected', { count: selectedEntities.length })
+      $scope.$emit('entities:multiSelected', {
+        count: selectedEntities.length
+      })
     }
     }
   }
   }
 })
 })

+ 24 - 30
services/web/frontend/js/features/file-tree/hooks/file-tree-angular-listener.js

@@ -10,41 +10,35 @@ export function useFileTreeAngularListener() {
     finishCreatingLinkedFile
     finishCreatingLinkedFile
   } = useFileTreeActionable()
   } = useFileTreeActionable()
 
 
-  useEffect(
-    () => {
-      function handleDispatchCreateDoc(ev) {
-        const { ...doc } = ev.detail
-        finishCreatingDoc(doc)
-      }
-      window.addEventListener(
+  useEffect(() => {
+    function handleDispatchCreateDoc(ev) {
+      const { ...doc } = ev.detail
+      finishCreatingDoc(doc)
+    }
+    window.addEventListener(
+      'FileTreeReactBridge.createDoc',
+      handleDispatchCreateDoc
+    )
+    return () =>
+      window.removeEventListener(
         'FileTreeReactBridge.createDoc',
         'FileTreeReactBridge.createDoc',
         handleDispatchCreateDoc
         handleDispatchCreateDoc
       )
       )
-      return () =>
-        window.removeEventListener(
-          'FileTreeReactBridge.createDoc',
-          handleDispatchCreateDoc
-        )
-    },
-    [finishCreatingDoc]
-  )
+  }, [finishCreatingDoc])
 
 
-  useEffect(
-    () => {
-      function handleDispatchCreateLinkedFile(ev) {
-        const { ...file } = ev.detail
-        finishCreatingLinkedFile(file)
-      }
-      window.addEventListener(
+  useEffect(() => {
+    function handleDispatchCreateLinkedFile(ev) {
+      const { ...file } = ev.detail
+      finishCreatingLinkedFile(file)
+    }
+    window.addEventListener(
+      'FileTreeReactBridge.createLinkedFile',
+      handleDispatchCreateLinkedFile
+    )
+    return () =>
+      window.removeEventListener(
         'FileTreeReactBridge.createLinkedFile',
         'FileTreeReactBridge.createLinkedFile',
         handleDispatchCreateLinkedFile
         handleDispatchCreateLinkedFile
       )
       )
-      return () =>
-        window.removeEventListener(
-          'FileTreeReactBridge.createLinkedFile',
-          handleDispatchCreateLinkedFile
-        )
-    },
-    [finishCreatingLinkedFile]
-  )
+  }, [finishCreatingLinkedFile])
 }
 }

+ 58 - 78
services/web/frontend/js/features/file-tree/hooks/file-tree-socket-listener.js

@@ -15,87 +15,67 @@ export function useFileTreeSocketListener() {
   const { unselect } = useFileTreeSelectable()
   const { unselect } = useFileTreeSelectable()
   const socket = window._ide && window._ide.socket
   const socket = window._ide && window._ide.socket
 
 
-  useEffect(
-    () => {
-      function handleDispatchRename(entityId, name) {
-        dispatchRename(entityId, name)
-      }
-      if (socket) socket.on('reciveEntityRename', handleDispatchRename)
-      return () => {
-        if (socket)
-          socket.removeListener('reciveEntityRename', handleDispatchRename)
-      }
-    },
-    [socket, dispatchRename]
-  )
+  useEffect(() => {
+    function handleDispatchRename(entityId, name) {
+      dispatchRename(entityId, name)
+    }
+    if (socket) socket.on('reciveEntityRename', handleDispatchRename)
+    return () => {
+      if (socket)
+        socket.removeListener('reciveEntityRename', handleDispatchRename)
+    }
+  }, [socket, dispatchRename])
 
 
-  useEffect(
-    () => {
-      function handleDispatchDelete(entityId) {
-        unselect(entityId)
-        dispatchDelete(entityId)
-      }
-      if (socket) socket.on('removeEntity', handleDispatchDelete)
-      return () => {
-        if (socket) socket.removeListener('removeEntity', handleDispatchDelete)
-      }
-    },
-    [socket, unselect, dispatchDelete]
-  )
+  useEffect(() => {
+    function handleDispatchDelete(entityId) {
+      unselect(entityId)
+      dispatchDelete(entityId)
+    }
+    if (socket) socket.on('removeEntity', handleDispatchDelete)
+    return () => {
+      if (socket) socket.removeListener('removeEntity', handleDispatchDelete)
+    }
+  }, [socket, unselect, dispatchDelete])
 
 
-  useEffect(
-    () => {
-      function handleDispatchMove(entityId, toFolderId) {
-        dispatchMove(entityId, toFolderId)
-      }
-      if (socket) socket.on('reciveEntityMove', handleDispatchMove)
-      return () => {
-        if (socket)
-          socket.removeListener('reciveEntityMove', handleDispatchMove)
-      }
-    },
-    [socket, dispatchMove]
-  )
+  useEffect(() => {
+    function handleDispatchMove(entityId, toFolderId) {
+      dispatchMove(entityId, toFolderId)
+    }
+    if (socket) socket.on('reciveEntityMove', handleDispatchMove)
+    return () => {
+      if (socket) socket.removeListener('reciveEntityMove', handleDispatchMove)
+    }
+  }, [socket, dispatchMove])
 
 
-  useEffect(
-    () => {
-      function handleDispatchCreateFolder(parentFolderId, folder) {
-        dispatchCreateFolder(parentFolderId, folder)
-      }
-      if (socket) socket.on('reciveNewFolder', handleDispatchCreateFolder)
-      return () => {
-        if (socket)
-          socket.removeListener('reciveNewFolder', handleDispatchCreateFolder)
-      }
-    },
-    [socket, dispatchCreateFolder]
-  )
+  useEffect(() => {
+    function handleDispatchCreateFolder(parentFolderId, folder) {
+      dispatchCreateFolder(parentFolderId, folder)
+    }
+    if (socket) socket.on('reciveNewFolder', handleDispatchCreateFolder)
+    return () => {
+      if (socket)
+        socket.removeListener('reciveNewFolder', handleDispatchCreateFolder)
+    }
+  }, [socket, dispatchCreateFolder])
 
 
-  useEffect(
-    () => {
-      function handleDispatchCreateDoc(parentFolderId, doc) {
-        dispatchCreateDoc(parentFolderId, doc)
-      }
-      if (socket) socket.on('reciveNewDoc', handleDispatchCreateDoc)
-      return () => {
-        if (socket)
-          socket.removeListener('reciveNewDoc', handleDispatchCreateDoc)
-      }
-    },
-    [socket, dispatchCreateDoc]
-  )
+  useEffect(() => {
+    function handleDispatchCreateDoc(parentFolderId, doc) {
+      dispatchCreateDoc(parentFolderId, doc)
+    }
+    if (socket) socket.on('reciveNewDoc', handleDispatchCreateDoc)
+    return () => {
+      if (socket) socket.removeListener('reciveNewDoc', handleDispatchCreateDoc)
+    }
+  }, [socket, dispatchCreateDoc])
 
 
-  useEffect(
-    () => {
-      function handleDispatchCreateFile(parentFolderId, file) {
-        dispatchCreateFile(parentFolderId, file)
-      }
-      if (socket) socket.on('reciveNewFile', handleDispatchCreateFile)
-      return () => {
-        if (socket)
-          socket.removeListener('reciveNewFile', handleDispatchCreateFile)
-      }
-    },
-    [socket, dispatchCreateFile]
-  )
+  useEffect(() => {
+    function handleDispatchCreateFile(parentFolderId, file) {
+      dispatchCreateFile(parentFolderId, file)
+    }
+    if (socket) socket.on('reciveNewFile', handleDispatchCreateFile)
+    return () => {
+      if (socket)
+        socket.removeListener('reciveNewFile', handleDispatchCreateFile)
+    }
+  }, [socket, dispatchCreateFile])
 }
 }

+ 11 - 14
services/web/frontend/js/features/outline/components/outline-item.js

@@ -48,20 +48,17 @@ function OutlineItem({ outlineItem, jumpToLine, highlightedLine }) {
     jumpToLine(outlineItem.line, true)
     jumpToLine(outlineItem.line, true)
   }
   }
 
 
-  useEffect(
-    () => {
-      const wasHighlighted = isHighlightedRef.current
-      isHighlightedRef.current = isHighlighted
-
-      if (!wasHighlighted && isHighlighted) {
-        scrollIntoViewIfNeeded(titleElementRef.current, {
-          scrollMode: 'if-needed',
-          block: 'center'
-        })
-      }
-    },
-    [isHighlighted, titleElementRef, isHighlightedRef]
-  )
+  useEffect(() => {
+    const wasHighlighted = isHighlightedRef.current
+    isHighlightedRef.current = isHighlighted
+
+    if (!wasHighlighted && isHighlighted) {
+      scrollIntoViewIfNeeded(titleElementRef.current, {
+        scrollMode: 'if-needed',
+        block: 'center'
+      })
+    }
+  }, [isHighlighted, titleElementRef, isHighlightedRef])
 
 
   // don't set the aria-expanded attribute when there are no children
   // don't set the aria-expanded attribute when there are no children
   const ariaExpandedValue = outlineItem.children ? expanded : undefined
   const ariaExpandedValue = outlineItem.children ? expanded : undefined

+ 4 - 6
services/web/frontend/js/features/outline/components/outline-pane.js

@@ -28,12 +28,10 @@ function OutlinePane({
   })
   })
   const isOpen = isTexFile && expanded
   const isOpen = isTexFile && expanded
 
 
-  useEffect(
-    () => {
-      onToggle(isOpen)
-    },
-    [isOpen]
-  )
+  useEffect(() => {
+    onToggle(isOpen)
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [isOpen])
 
 
   const headerClasses = classNames('outline-pane', {
   const headerClasses = classNames('outline-pane', {
     'outline-pane-disabled': !isTexFile
     'outline-pane-disabled': !isTexFile

+ 9 - 9
services/web/frontend/js/features/preview/components/preview-logs-pane.js

@@ -31,15 +31,15 @@ function PreviewLogsPane({
     <PreviewError key={index} name={name} />
     <PreviewError key={index} name={name} />
   ))
   ))
 
 
-  const validationIssuesUI = Object.keys(validationIssues).map(
-    (name, index) => (
-      <PreviewValidationIssue
-        key={index}
-        name={name}
-        details={validationIssues[name]}
-      />
-    )
-  )
+  const validationIssuesUI = Object.keys(
+    validationIssues
+  ).map((name, index) => (
+    <PreviewValidationIssue
+      key={index}
+      name={name}
+      details={validationIssues[name]}
+    />
+  ))
 
 
   const logEntriesUI = [
   const logEntriesUI = [
     ...compilerErrors,
     ...compilerErrors,

Неке датотеке нису приказане због велике количине промена