Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ESLint to the build #1390

Merged
merged 14 commits into from
May 15, 2023
21 changes: 21 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = {
env: {
node: true,
browser: true,
es2022: true,
},
parserOptions: {
sourceType: "module",
},
plugins: ["html"],
extends: ["eslint:recommended"],
rules: {
// This will produce an error for console.log or console.warn in production
// and a warning in development.
"no-console": [
process.env.NODE_ENV === "production" ? "error" : "warn",
{ allow: ["error", "debug"] },
],
},
ignorePatterns: ["app/static/third-party", "playwright-report", "venv"],
};
10 changes: 8 additions & 2 deletions app/static/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ import {
} from "./keycodes.js";
import { KeyboardState } from "./keyboardstate.js";
import { sendKeystroke } from "./keystrokes.js";
import { isPasteOverlayShowing, showPasteOverlay } from "./paste.js";
import * as settings from "./settings.js";
import { OverlayTracker } from "./overlays.js";

// Suppress ESLint warnings about undefined variables.
// `io` is defined by the Socket.IO library, which is globally available on the
// page.
/* global io */

const socket = io();
let connectedToServer = false;

Expand Down Expand Up @@ -73,7 +79,7 @@ function processKeystroke(keystroke) {
// sends dummy keydown events with a keycode of 229. Ignore these events, as
// there's no way to map it to a real key.
if (keystroke.keyCode === 229) {
resolve({});
return;
}
const keystrokeHistoryEvent = keystrokeHistory.push(keystroke.key);
const result = sendKeystroke(socket, keystroke);
Expand Down Expand Up @@ -409,7 +415,7 @@ document
document.getElementById("app").focus();
});
const shutdownDialog = document.getElementById("shutdown-dialog");
shutdownDialog.addEventListener("shutdown-started", (evt) => {
shutdownDialog.addEventListener("shutdown-started", () => {
// Hide the interactive elements of the page during shutdown.
for (const elementId of ["remote-screen", "on-screen-keyboard"]) {
document.getElementById(elementId).style.display = "none";
Expand Down
7 changes: 7 additions & 0 deletions app/static/js/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export async function getLatestRelease() {
.then(processJsonResponse)
.then((updateInfo) => {
["version", "kind", "data"].forEach((field) => {
// eslint-disable-next-line no-prototype-builtins
if (!updateInfo.hasOwnProperty(field)) {
throw new ControllerError(`Missing expected ${field} field`);
}
Expand All @@ -88,6 +89,7 @@ export async function getVersion() {
})
.then(processJsonResponse)
.then((versionResponse) => {
// eslint-disable-next-line no-prototype-builtins
if (!versionResponse.hasOwnProperty("version")) {
throw new ControllerError("Missing expected version field");
}
Expand Down Expand Up @@ -151,9 +153,11 @@ export async function getUpdateStatus() {
})
.then(processJsonResponse)
.then((data) => {
// eslint-disable-next-line no-prototype-builtins
if (!data.hasOwnProperty("status")) {
throw new ControllerError("Missing expected status field");
}
// eslint-disable-next-line no-prototype-builtins
if (!data.hasOwnProperty("updateError")) {
throw new ControllerError("Missing expected updateError field");
}
Expand All @@ -171,6 +175,7 @@ export async function determineHostname() {
})
.then(processJsonResponse)
.then((hostnameResponse) => {
// eslint-disable-next-line no-prototype-builtins
if (!hostnameResponse.hasOwnProperty("hostname")) {
throw new ControllerError("Missing expected hostname field");
}
Expand Down Expand Up @@ -234,6 +239,7 @@ export async function textToShareableUrl(text) {
})
.then(processJsonResponse)
.then((data) => {
// eslint-disable-next-line no-prototype-builtins
if (!data.hasOwnProperty("id")) {
throw new ControllerError("Missing expected id field");
}
Expand All @@ -260,6 +266,7 @@ export async function getVideoSettings() {
"h264Bitrate",
"defaultH264Bitrate",
].forEach((field) => {
// eslint-disable-next-line no-prototype-builtins
if (!data.hasOwnProperty(field)) {
throw new ControllerError(`Missing expected ${field} field`);
}
Expand Down
2 changes: 1 addition & 1 deletion app/static/js/keycodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export function findKeyCode(character, browserLanguage) {

// Returns true if the text character requires a shift key.
export function requiresShiftKey(character) {
const shiftedPattern = /^[A-Z¬!"£$%^&\*()_\+{}|<>\?:@~#]/;
const shiftedPattern = /^[A-Z¬!"£$%^&*()_+{}|<>?:@~#]/;
return shiftedPattern.test(character);
}

Expand Down
6 changes: 3 additions & 3 deletions app/static/js/paste.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
pasteOverlay = document.getElementById("paste-overlay");
const pasteOverlay = document.getElementById("paste-overlay");
pasteOverlay.addEventListener("keydown", onPasteOverlayKeyDown);
pasteOverlay.addEventListener("paste", onPaste);
pasteOverlay.addEventListener("click", () => {
hidePasteOverlay();
});

// TODO(jotaen) Migrate this to use `OverlayTracker`
function isPasteOverlayShowing() {
export function isPasteOverlayShowing() {
return pasteOverlay.getAttribute("show") === "true";
}

function showPasteOverlay() {
export function showPasteOverlay() {
pasteOverlay.setAttribute("show", "true");
placeCaretInPasteOverlay();
}
Expand Down
4 changes: 3 additions & 1 deletion app/static/js/settings.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
let settings = {};
try {
settings = JSON.parse(localStorage.getItem("settings"));
} catch {}
} catch {
// Ignore errors.
}

const defaults = {
isKeyHistoryEnabled: true,
Expand Down
5 changes: 5 additions & 0 deletions app/static/js/updatelogs.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// Suppress ESLint warnings about undefined variables.
// `io` is defined by the Socket.IO library, which is globally available on the
// page.
/* global io */

/**
* Streams the TinyPilot update logs via a SocketIO connection.
* @requires socketio
Expand Down
5 changes: 5 additions & 0 deletions app/static/js/webrtc-video.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
* https://github.com/tiny-pilot/ustreamer/blob/master/docs/h264.md
*/

// Suppress ESLint warnings about undefined variables.
// Janus is defined by the Janus library, which is globally available on the
// page.
/* global Janus */

// Parameters for the setup.
const config = {
// Set to `true` to turn on all internal Janus logging. Make sure to set the
Expand Down
1 change: 0 additions & 1 deletion app/templates/custom-elements/about-dialog.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ <h3>About TinyPilot</h3>

(function () {
const template = document.querySelector("#about-dialog-template");
const creditBoxTemplate = document.querySelector("#credit-box-template");

customElements.define(
"about-dialog",
Expand Down
2 changes: 1 addition & 1 deletion app/templates/custom-elements/key.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
constructor() {
super();

this.addEventListener("click", (evt) => {
this.addEventListener("click", () => {
this.togglePressedState();

// Don't send event if click removed "pressed" state
Expand Down
12 changes: 1 addition & 11 deletions app/templates/custom-elements/remote-screen.html
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,7 @@
const mobileKeyboard = this.shadowRoot.getElementById(
"mobile-keyboard-input"
);
mobileKeyboard.addEventListener("input", (evt) => {
// Handle insertCompositionText, which mean typing in autocomplete
// mode. The global keydown event handler processes all other key
// input events.
if (
evt.inputType === "insertText" ||
evt.inputType === "insertCompositionText"
) {
sendTextInput(evt.data);
}

mobileKeyboard.addEventListener("input", () => {
// Force the autocomplete sequence to restart.
mobileKeyboard.blur();
mobileKeyboard.value = "";
Expand Down
1 change: 0 additions & 1 deletion app/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
</div>
{% include "components/paste-overlay.html" %}
<script src="/third-party/socket.io/3.1.3/socket.io.min.js"></script>
<script src="/js/paste.js"></script>
<script type="module" src="/js/app.js"></script>

{% if use_webrtc_remote_screen %}
Expand Down
2 changes: 2 additions & 0 deletions dev-scripts/build-javascript
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ set -u
# Location of app source files.
SOURCE_DIR="app"

./dev-scripts/lint-frontend

# Run unit tests.
./node_modules/.bin/mocha \
--recursive \
Expand Down
14 changes: 14 additions & 0 deletions dev-scripts/lint-frontend
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

# Checks for JavaScript anti-patterns.

# Exit on first failure.
set -e

# Echo commands before executing them, by default to stderr.
set -x

# Exit on unset variable.
set -u

./node_modules/.bin/eslint "./**/*.js" "./**/*.html"
Loading