diff --git a/commands.js b/commands.js index 8f2450e..1661a25 100644 --- a/commands.js +++ b/commands.js @@ -86,7 +86,7 @@ const ban = { usage: "[nick]", description: "Ban a user from the channel, or display the current ban list", execute: (app, args) => { - if (args.length == 0) { + if (args.length === 0) { let activeChannel = getActiveChannel(app); getActiveClient(app).send({ command: "MODE", @@ -142,7 +142,7 @@ export default { description: "Close the current buffer", execute: (app, args) => { let activeBuffer = app.state.buffers.get(app.state.activeBuffer); - if (!activeBuffer || activeBuffer.type == BufferType.SERVER) { + if (!activeBuffer || activeBuffer.type === BufferType.SERVER) { throw new Error("Not in a user or channel buffer"); } app.close(activeBuffer.id); @@ -297,7 +297,7 @@ export default { usage: "[nick]", description: "Quiet a user in the channel, or display the current quiet list", execute: (app, args) => { - if (args.length == 0) { + if (args.length === 0) { getActiveClient(app).send({ command: "MODE", params: [getActiveChannel(app), "+q"], diff --git a/components/app.js b/components/app.js index 1e4120b..cc4eef7 100644 --- a/components/app.js +++ b/components/app.js @@ -94,7 +94,7 @@ function splitHostPort(str) { function fillConnectParams(params) { let host = window.location.host || "localhost:8080"; let proto = "wss:"; - if (window.location.protocol != "https:") { + if (window.location.protocol !== "https:") { proto = "ws:"; } let path = window.location.pathname || "/"; @@ -687,7 +687,7 @@ export default class App extends Component { } let msgUnread = Unread.NONE; - if ((msg.command == "PRIVMSG" || msg.command == "NOTICE") && !isRead) { + if ((msg.command === "PRIVMSG" || msg.command === "NOTICE") && !isRead) { let target = msg.params[0]; let text = msg.params[1]; @@ -702,7 +702,7 @@ export default class App extends Component { msgUnread = Unread.MESSAGE; } - if (msgUnread == Unread.HIGHLIGHT && !isDelivered && !irc.parseCTCP(msg)) { + if (msgUnread === Unread.HIGHLIGHT && !isDelivered && !irc.parseCTCP(msg)) { let title = "New " + kind + " from " + msg.prefix.name; if (client.isChannel(bufName)) { title += " in " + bufName; @@ -760,7 +760,7 @@ export default class App extends Component { // Open a new buffer if the message doesn't come from me or is a // self-message - if ((!client.isMyNick(msg.prefix.name) || client.isMyNick(bufName)) && (msg.command != "PART" && msg.comand != "QUIT" && msg.command != irc.RPL_MONONLINE && msg.command != irc.RPL_MONOFFLINE)) { + if ((!client.isMyNick(msg.prefix.name) || client.isMyNick(bufName)) && (msg.command !== "PART" && msg.comand !== "QUIT" && msg.command !== irc.RPL_MONONLINE && msg.command !== irc.RPL_MONOFFLINE)) { this.createBuffer(serverID, bufName); } @@ -978,7 +978,7 @@ export default class App extends Component { affectedBuffers.push(chatHistoryBatch.params[0]); } else { this.state.buffers.forEach((buf) => { - if (buf.server != serverID) { + if (buf.server !== serverID) { return; } if (!buf.members.has(msg.prefix.name)) { @@ -996,7 +996,7 @@ export default class App extends Component { affectedBuffers.push(chatHistoryBatch.params[0]); } else { this.state.buffers.forEach((buf) => { - if (buf.server != serverID) { + if (buf.server !== serverID) { return; } if (!buf.members.has(msg.prefix.name)) { @@ -1149,7 +1149,7 @@ export default class App extends Component { if (client.isMyNick(msg.prefix.name)) { this.syncBufferUnread(serverID, channel); } - if (channel == this.switchToChannel) { + if (channel === this.switchToChannel) { this.switchBuffer({ server: serverID, name: channel }); this.switchToChannel = null; } @@ -1279,7 +1279,7 @@ export default class App extends Component { }); break; default: - if (irc.isError(msg.command) && msg.command != irc.ERR_NOMOTD) { + if (irc.isError(msg.command) && msg.command !== irc.ERR_NOMOTD) { let description = msg.params[msg.params.length - 1]; this.showError(description); } @@ -1527,7 +1527,7 @@ export default class App extends Component { servers.delete(buf.server); let connectForm = state.connectForm; - if (servers.size == 0) { + if (servers.size === 0) { connectForm = true; } @@ -1598,7 +1598,7 @@ export default class App extends Component { } privmsg(target, text) { - if (target == SERVER_BUFFER) { + if (target === SERVER_BUFFER) { this.showError("Cannot send message in server buffer"); return; } @@ -1743,7 +1743,7 @@ export default class App extends Component { async handleBufferScrollTop() { let buf = this.state.buffers.get(this.state.activeBuffer); - if (!buf || buf.type == BufferType.SERVER) { + if (!buf || buf.type === BufferType.SERVER) { return; } @@ -1922,7 +1922,7 @@ export default class App extends Component { this.dismissDialog(); if (this.state.dialogData && this.state.dialogData.id) { - if (Object.keys(attrs).length == 0) { + if (Object.keys(attrs).length === 0) { return; } @@ -2062,7 +2062,7 @@ export default class App extends Component { let bufferHeader = null; if (activeBuffer) { let activeUser = null; - if (activeBuffer.type == BufferType.NICK) { + if (activeBuffer.type === BufferType.NICK) { activeUser = activeServer.users.get(activeBuffer.name); } @@ -2086,7 +2086,7 @@ export default class App extends Component { } let memberList = null; - if (activeBuffer && activeBuffer.type == BufferType.CHANNEL) { + if (activeBuffer && activeBuffer.type === BufferType.CHANNEL) { memberList = html`
props.onBufferClick(buf)} onClose=${() => props.onBufferClose(buf)} - active=${props.activeBuffer == buf.id} + active=${props.activeBuffer === buf.id} /> `; }); diff --git a/components/buffer.js b/components/buffer.js index 4ee80a7..7e159b3 100644 --- a/components/buffer.js +++ b/components/buffer.js @@ -134,7 +134,7 @@ class LogLine extends Component { let ctcp = irc.parseCTCP(msg); if (ctcp) { - if (ctcp.command == "ACTION") { + if (ctcp.command === "ACTION") { lineClass = "me-tell"; content = html`* ${createNick(msg.prefix.name)} ${linkify(stripANSI(ctcp.param), onChannelClick)}`; } else { @@ -145,7 +145,7 @@ class LogLine extends Component { } else { lineClass = "talk"; let prefix = "<", suffix = ">"; - if (msg.command == "NOTICE") { + if (msg.command === "NOTICE") { prefix = suffix = "-"; } content = html`${prefix}${createNick(msg.prefix.name)}${suffix} ${linkify(stripANSI(text), onChannelClick)}`; @@ -200,7 +200,7 @@ class LogLine extends Component { let user = html`${createNick(msg.prefix.name)}`; // TODO: use irc.forEachChannelModeUpdate() - if (buf.type == BufferType.CHANNEL && modeStr.length === 2 && server.cm(buf.name) === server.cm(target)) { + if (buf.type === BufferType.CHANNEL && modeStr.length === 2 && server.cm(buf.name) === server.cm(target)) { let plusMinus = modeStr[0]; let mode = modeStr[1]; let arg = msg.params[2]; @@ -357,7 +357,7 @@ class LogLine extends Component { content = html`${createNick(buf.name)} is offline`; break; default: - if (irc.isError(msg.command) && msg.command != irc.ERR_NOMOTD) { + if (irc.isError(msg.command) && msg.command !== irc.ERR_NOMOTD) { lineClass = "error"; } content = html`${msg.command} ${linkify(msg.params.join(" "))}`; @@ -676,13 +676,13 @@ export default class Buffer extends Component { let serverName = server.name; let children = []; - if (buf.type == BufferType.SERVER) { + if (buf.type === BufferType.SERVER) { children.push(html`<${NotificationNagger}/>`); } - if (buf.type == BufferType.SERVER && server.isBouncer && !server.bouncerNetID) { + if (buf.type === BufferType.SERVER && server.isBouncer && !server.bouncerNetID) { children.push(html`<${ProtocolHandlerNagger} bouncerName=${serverName}/>`); } - if (buf.type == BufferType.SERVER && server.status == ServerStatus.REGISTERED && server.supportsSASLPlain && !server.account) { + if (buf.type === BufferType.SERVER && server.status === ServerStatus.REGISTERED && server.supportsSASLPlain && !server.account) { children.push(html` <${AccountNagger} server=${server} @@ -752,7 +752,7 @@ export default class Buffer extends Component { keep[partIndexes.get(msg.prefix.name)] = false; partIndexes.delete(msg.prefix.name); keep.push(false); - } else if (msg.command === "NICK" && msg.prefix.name == msg.params[0]) { + } else if (msg.command === "NICK" && msg.prefix.name === msg.params[0]) { keep.push(false); } else { keep.push(true); @@ -795,7 +795,7 @@ export default class Buffer extends Component { } } - if (!hasUnreadSeparator && buf.type != BufferType.SERVER && !isMessageBeforeReceipt(msg, buf.prevReadReceipt)) { + if (!hasUnreadSeparator && buf.type !== BufferType.SERVER && !isMessageBeforeReceipt(msg, buf.prevReadReceipt)) { sep.push(html`<${UnreadSeparator} key="unread"/>`); hasUnreadSeparator = true; } diff --git a/components/connect-form.js b/components/connect-form.js index 6eab2df..ae8a59e 100644 --- a/components/connect-form.js +++ b/components/connect-form.js @@ -34,7 +34,7 @@ export default class ConnectForm extends Component { handleInput(event) { let target = event.target; - let value = target.type == "checkbox" ? target.checked : target.value; + let value = target.type === "checkbox" ? target.checked : target.value; this.setState({ [target.name]: value }); } diff --git a/components/dialog.js b/components/dialog.js index 28eff1d..7748765 100644 --- a/components/dialog.js +++ b/components/dialog.js @@ -21,13 +21,13 @@ export default class Dialog extends Component { } handleBackdropClick(event) { - if (event.target.className == "dialog") { + if (event.target.className === "dialog") { this.dismiss(); } } handleKeyDown(event) { - if (event.key == "Escape") { + if (event.key === "Escape") { this.dismiss(); } } diff --git a/components/join-form.js b/components/join-form.js index 3676891..41c2277 100644 --- a/components/join-form.js +++ b/components/join-form.js @@ -18,7 +18,7 @@ export default class JoinForm extends Component { handleInput(event) { let target = event.target; - let value = target.type == "checkbox" ? target.checked : target.value; + let value = target.type === "checkbox" ? target.checked : target.value; this.setState({ [target.name]: value }); } diff --git a/components/network-form.js b/components/network-form.js index 1610040..b49e951 100644 --- a/components/network-form.js +++ b/components/network-form.js @@ -37,7 +37,7 @@ export default class NetworkForm extends Component { handleInput(event) { let target = event.target; - let value = target.type == "checkbox" ? target.checked : target.value; + let value = target.type === "checkbox" ? target.checked : target.value; this.setState({ [target.name]: value }); } @@ -46,10 +46,10 @@ export default class NetworkForm extends Component { let params = {}; Object.keys(defaultParams).forEach((k) => { - if (!this.props.isNew && this.prevParams[k] == this.state[k]) { + if (!this.props.isNew && this.prevParams[k] === this.state[k]) { return; } - if (this.props.isNew && defaultParams[k] == this.state[k]) { + if (this.props.isNew && defaultParams[k] === this.state[k]) { return; } params[k] = this.state[k]; diff --git a/components/register-form.js b/components/register-form.js index e8537a6..0e4be5d 100644 --- a/components/register-form.js +++ b/components/register-form.js @@ -15,7 +15,7 @@ export default class RegisterForm extends Component { handleInput(event) { let target = event.target; - let value = target.type == "checkbox" ? target.checked : target.value; + let value = target.type === "checkbox" ? target.checked : target.value; this.setState({ [target.name]: value }); } diff --git a/components/scroll-manager.js b/components/scroll-manager.js index fe253fa..c5fad76 100644 --- a/components/scroll-manager.js +++ b/components/scroll-manager.js @@ -48,13 +48,13 @@ export default class ScrollManager extends Component { } } - if (target.scrollTop == 0) { + if (target.scrollTop === 0) { this.props.onScrollTop(); } } handleScroll() { - if (this.props.target.current.scrollTop == 0) { + if (this.props.target.current.scrollTop === 0) { this.props.onScrollTop(); } } diff --git a/components/settings-form.js b/components/settings-form.js index 31e045e..5b5f917 100644 --- a/components/settings-form.js +++ b/components/settings-form.js @@ -15,7 +15,7 @@ export default class SettingsForm extends Component { handleInput(event) { let target = event.target; - let value = target.type == "checkbox" ? target.checked : target.value; + let value = target.type === "checkbox" ? target.checked : target.value; this.setState({ [target.name]: value }, () => { this.props.onChange(this.state); }); diff --git a/components/verify-form.js b/components/verify-form.js index 6f2603e..2e2a0bb 100644 --- a/components/verify-form.js +++ b/components/verify-form.js @@ -15,7 +15,7 @@ export default class RegisterForm extends Component { handleInput(event) { let target = event.target; - let value = target.type == "checkbox" ? target.checked : target.value; + let value = target.type === "checkbox" ? target.checked : target.value; this.setState({ [target.name]: value }); } diff --git a/eslint.config.js b/eslint.config.js index a3bbd22..ab23d08 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -23,6 +23,7 @@ export default [ destructuredArrayIgnorePattern: "^_", }], "no-var": "error", + "eqeqeq": "error", "@stylistic/js/indent": ["warn", "tab"], "@stylistic/js/quotes": ["warn", "double"], "@stylistic/js/semi": "warn", diff --git a/keybindings.js b/keybindings.js index a030d7f..a7ed6c1 100644 --- a/keybindings.js +++ b/keybindings.js @@ -121,9 +121,9 @@ export function setup(app) { return; } candidates = candidates.filter((binding) => { - return !!binding.altKey == event.altKey && !!binding.ctrlKey == event.ctrlKey; + return !!binding.altKey === event.altKey && !!binding.ctrlKey === event.ctrlKey; }); - if (candidates.length != 1) { + if (candidates.length !== 1) { return; } event.preventDefault(); diff --git a/lib/ansi.js b/lib/ansi.js index 86cbbb7..4c4bed8 100644 --- a/lib/ansi.js +++ b/lib/ansi.js @@ -51,7 +51,7 @@ export function strip(text) { if (isDigit(text[i + 1])) { i++; } - if (text[i + 1] == "," && isDigit(text[i + 2])) { + if (text[i + 1] === "," && isDigit(text[i + 2])) { i += 2; if (isDigit(text[i + 1])) { i++; @@ -63,7 +63,7 @@ export function strip(text) { break; } i += HEX_COLOR_LENGTH; - if (text[i + 1] == "," && isHexColor(text.slice(i + 2))) { + if (text[i + 1] === "," && isHexColor(text.slice(i + 2))) { i += 1 + HEX_COLOR_LENGTH; } break; diff --git a/lib/base64.js b/lib/base64.js index 3aba7ad..c128708 100644 --- a/lib/base64.js +++ b/lib/base64.js @@ -25,12 +25,12 @@ export function encode(data) { out += alphabet[u24 & 0x3F]; } - if (trailing == 1) { + if (trailing === 1) { let u8 = bytes[bytes.length - 1]; out += alphabet[u8 >> 2]; out += alphabet[(u8 << 4) & 0x3F]; out += "=="; - } else if (trailing == 2) { + } else if (trailing === 2) { let u16 = (bytes[bytes.length - 2] << 8) + bytes[bytes.length - 1]; out += alphabet[u16 >> 10]; out += alphabet[(u16 >> 4) & 0x3F]; diff --git a/lib/client.js b/lib/client.js index 90c25ba..4f78484 100644 --- a/lib/client.js +++ b/lib/client.js @@ -354,7 +354,7 @@ export default class Client extends EventTarget { case "AUTHENTICATE": // Both PLAIN and EXTERNAL expect an empty challenge let challengeStr = msg.params[0]; - if (challengeStr != "+") { + if (challengeStr !== "+") { this.dispatchError(new Error("Expected an empty challenge, got: " + challengeStr)); this.send({ command: "AUTHENTICATE", params: ["*"] }); } @@ -425,7 +425,7 @@ export default class Client extends EventTarget { case irc.ERR_NOPERMFORHOST: case irc.ERR_YOUREBANNEDCREEP: this.dispatchError(new IRCError(msg)); - if (this.status != Client.Status.REGISTERED) { + if (this.status !== Client.Status.REGISTERED) { this.disconnect(); } break; @@ -656,7 +656,7 @@ export default class Client extends EventTarget { switch (subCmd) { case "LS": this.supportsCap = true; - if (args[0] == "*") { + if (args[0] === "*") { break; } @@ -728,7 +728,7 @@ export default class Client extends EventTarget { } isMyNick(nick) { - return this.cm(nick) == this.cm(this.nick); + return this.cm(nick) === this.cm(this.nick); } isChannel(name) { @@ -775,7 +775,7 @@ export default class Client extends EventTarget { let msg = event.detail.message; let msgLabel = irc.getMessageLabel(msg); - if (msgLabel && msgLabel != label) { + if (msgLabel && msgLabel !== label) { return; } diff --git a/lib/irc.js b/lib/irc.js index d370294..df30c15 100644 --- a/lib/irc.js +++ b/lib/irc.js @@ -120,7 +120,7 @@ export function parseTags(s) { let parts = s.split("=", 2); let k = parts[0]; let v = null; - if (parts.length == 2) { + if (parts.length === 2) { v = unescapeTag(parts[1]); if (v.endsWith("\\")) { v = v.slice(0, v.length - 1); @@ -315,13 +315,13 @@ function isURIPrefix(text) { } export function isHighlight(msg, nick, cm) { - if (msg.command != "PRIVMSG" && msg.command != "NOTICE") { + if (msg.command !== "PRIVMSG" && msg.command !== "NOTICE") { return false; } nick = cm(nick); - if (msg.prefix && cm(msg.prefix.name) == nick) { + if (msg.prefix && cm(msg.prefix.name) === nick) { return false; // Our own messages aren't highlights } @@ -349,7 +349,7 @@ export function isHighlight(msg, nick, cm) { } export function isServerBroadcast(msg) { - if (msg.command != "PRIVMSG" && msg.command != "NOTICE") { + if (msg.command !== "PRIVMSG" && msg.command !== "NOTICE") { return false; } return msg.params[0].startsWith("$"); @@ -387,7 +387,7 @@ export function formatDate(date) { } export function parseCTCP(msg) { - if (msg.command != "PRIVMSG" && msg.command != "NOTICE") { + if (msg.command !== "PRIVMSG" && msg.command !== "NOTICE") { return null; } @@ -507,7 +507,7 @@ export class Isupport { return stdChanModes; } let chanModes = this.raw.get("CHANMODES").split(","); - if (chanModes.length != 4) { + if (chanModes.length !== 4) { console.error("Invalid CHANMODES: ", this.raw.get("CHANMODES")); return stdChanModes; } @@ -572,13 +572,13 @@ export const CaseMapping = { let ch = str[i]; if ("A" <= ch && ch <= "Z") { ch = ch.toLowerCase(); - } else if (ch == "{") { + } else if (ch === "{") { ch = "["; - } else if (ch == "}") { + } else if (ch === "}") { ch = "]"; - } else if (ch == "\\") { + } else if (ch === "\\") { ch = "|"; - } else if (ch == "~") { + } else if (ch === "~") { ch = "^"; } out += ch; @@ -592,11 +592,11 @@ export const CaseMapping = { let ch = str[i]; if ("A" <= ch && ch <= "Z") { ch = ch.toLowerCase(); - } else if (ch == "{") { + } else if (ch === "{") { ch = "["; - } else if (ch == "}") { + } else if (ch === "}") { ch = "]"; - } else if (ch == "\\") { + } else if (ch === "\\") { ch = "|"; } out += ch; diff --git a/state.js b/state.js index 8047dc7..f96c75f 100644 --- a/state.js +++ b/state.js @@ -136,19 +136,19 @@ function updateState(state, updater) { } function isServerBuffer(buf) { - return buf.type == BufferType.SERVER; + return buf.type === BufferType.SERVER; } /* Returns 1 if a should appear after b, -1 if a should appear before b, or * 0 otherwise. */ function compareBuffers(a, b) { - if (a.server != b.server) { + if (a.server !== b.server) { return a.server > b.server ? 1 : -1; } - if (isServerBuffer(a) != isServerBuffer(b)) { + if (isServerBuffer(a) !== isServerBuffer(b)) { return isServerBuffer(b) ? 1 : -1; } - if (a.name != b.name) { + if (a.name !== b.name) { return a.name.localeCompare(b.name); } return 0; @@ -178,7 +178,7 @@ function updateMembership(membership, letter, add, client) { /* Insert a message in an immutable list of sorted messages. */ function insertMessage(list, msg) { - if (list.length == 0) { + if (list.length === 0) { return [msg]; } else if (!irc.findBatchByType(msg, "chathistory") || list[list.length - 1].tags.time <= msg.tags.time) { return list.concat(msg); @@ -318,7 +318,7 @@ export const State = { let id = lastBufferID; let type; - if (name == SERVER_BUFFER) { + if (name === SERVER_BUFFER) { type = BufferType.SERVER; } else if (client.isChannel(name)) { type = BufferType.CHANNEL; @@ -394,7 +394,7 @@ export const State = { case irc.RPL_ISUPPORT: buffers = new Map(state.buffers); state.buffers.forEach((buf) => { - if (buf.server != serverID) { + if (buf.server !== serverID) { return; } let members = new irc.CaseMapMap(buf.members, client.cm); @@ -454,7 +454,7 @@ export const State = { }); case irc.RPL_ENDOFWHO: target = msg.params[1]; - if (msg.list.length == 0 && !client.isChannel(target) && target.indexOf("*") < 0) { + if (msg.list.length === 0 && !client.isChannel(target) && target.indexOf("*") < 0) { // Not a channel nor a mask, likely a nick return updateUser(target, (user) => { return { offline: true }; @@ -544,7 +544,7 @@ export const State = { case "QUIT": buffers = new Map(state.buffers); state.buffers.forEach((buf) => { - if (buf.server != serverID) { + if (buf.server !== serverID) { return; } if (!buf.members.has(msg.prefix.name)) { @@ -570,7 +570,7 @@ export const State = { buffers = new Map(state.buffers); state.buffers.forEach((buf) => { - if (buf.server != serverID) { + if (buf.server !== serverID) { return; } if (!buf.members.has(msg.prefix.name)) { @@ -648,7 +648,7 @@ export const State = { for (let target of targets) { let prefix = irc.parsePrefix(target); - let update = updateUser(prefix.name, { offline: msg.command == irc.RPL_MONOFFLINE }); + let update = updateUser(prefix.name, { offline: msg.command === irc.RPL_MONOFFLINE }); state = { ...state, ...update }; }