diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9d08a1a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..ebc367f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +/test/*.js +/client/* +/documentation/* diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..24182a1 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,33 @@ +module.exports = { + env: { + es2021: true, + node: true, + }, + extends: [ + 'airbnb-base', + ], + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + }, + rules: { + "no-console": 0, + "no-param-reassign": [ + "error", + { + "props": false, + } + ], + "import/extensions": [ + "error", + "ignorePackages", + { + js: "always", + jsx: "always", + ts: "always", + tsx: "always", + mjs: "always", + } + ] + }, +}; diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c917234 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,107 @@ +# From https://github.com/Danimoth/gitattributes/blob/master/Web.gitattributes + +# Handle line endings automatically for files detected as text +# and leave all files detected as binary untouched. +* text=auto + +# +# The above will handle all files NOT found below +# + +# +## These files are text and should be normalized (Convert crlf => lf) +# + +# source code +*.php text +*.css text +*.sass text +*.scss text +*.less text +*.styl text +*.js text eol=lf +*.coffee text +*.json text +*.htm text +*.html text +*.xml text +*.svg text +*.txt text +*.ini text +*.inc text +*.pl text +*.rb text +*.py text +*.scm text +*.sql text +*.sh text +*.bat text + +# templates +*.ejs text +*.hbt text +*.jade text +*.haml text +*.hbs text +*.dot text +*.tmpl text +*.phtml text + +# server config +.htaccess text +.nginx.conf text + +# git config +.gitattributes text +.gitignore text +.gitconfig text + +# code analysis config +.jshintrc text +.jscsrc text +.jshintignore text +.csslintrc text + +# misc config +*.yaml text +*.yml text +.editorconfig text + +# build config +*.npmignore text +*.bowerrc text + +# Heroku +Procfile text +.slugignore text + +# Documentation +*.md text +LICENSE text +AUTHORS text + + +# +## These files are binary and should be left untouched +# + +# (binary is a macro for -text -diff) +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.mov binary +*.mp4 binary +*.mp3 binary +*.flv binary +*.fla binary +*.swf binary +*.gz binary +*.zip binary +*.7z binary +*.ttf binary +*.eot binary +*.woff binary +*.pyc binary +*.pdf binary diff --git a/.gitignore b/.gitignore index 4bf93f7..a93c6d0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,11 @@ logs npm-debug.log* yarn-debug.log* yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Runtime data pids @@ -15,12 +20,13 @@ pids lib-cov # Coverage directory used by tools like istanbul -coverage +.coverage +*.lcov # nyc test coverage .nyc_output -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) @@ -36,8 +42,11 @@ build/Release node_modules/ jspm_packages/ -# Typescript v1 declaration files -typings/ +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo # Optional npm cache directory .npm @@ -45,6 +54,15 @@ typings/ # Optional eslint cache .eslintcache +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + # Optional REPL history .node_repl_history @@ -54,10 +72,63 @@ typings/ # Yarn Integrity file .yarn-integrity -# dotenv environment variables file +# dotenv environment variable files .env +.env.development.local +.env.test.local +.env.production.local +.env.local -# next.js build output +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output .next +out -server/config/ \ No newline at end of file +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +session.key +salt.key +config.json diff --git a/.hcserver.json b/.hcserver.json new file mode 100644 index 0000000..eb59264 --- /dev/null +++ b/.hcserver.json @@ -0,0 +1 @@ +{"modulesPath":"./commands","websocketPort":"6060","rateLimit":{"halflife":"30000","threshold":"25"},"pulseSpeed":"16000"} diff --git a/.nycrc b/.nycrc new file mode 100644 index 0000000..9328f12 --- /dev/null +++ b/.nycrc @@ -0,0 +1,29 @@ +{ + "check-coverage": true, + "per-file": true, + "lines": 80, + "statements": 80, + "functions": 80, + "branches": 80, + "include": [ + "commands/**/*.js" + ], + "exclude": [ + "commands/**/*.spec.js" + ], + "ignore-class-method": "methodToIgnore", + "reporter": [ + "html", + "lcov", + "text", + "text-summary" + ], + "require": [ + "dotenv/config" + ], + "extension": [], + "cache": true, + "all": true, + "temp-dir": "", + "report-dir": "./.coverage" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index f52afd7..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,147 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -## [Unreleased] - -## [2.1.93 pre 2.2] - 2020-03-12 -### Added -- (Source) `./pm2.config.js` PM2 ecosystem config handling both http-server and the websocket -- (Source) NPM new commands: -- "start": Starts or reloads the dev environment -- "stop": Stops and clears the dev environment -- "logs": Show / watch http & websocket logs for errors and events -- "clear": Clear all logged data -- "status": Show status of http and websocket -- "refresh": Clears logged data and stops http and websocket -- (Server) Numeric user levels / UAC, related to issue #86 -- (Server) `join` module password property, related to V2 protocol update -- (Server) `users` array to `onlineSet` structure, related to V2 protocol update -- (Server) `session` module, related to V2 protocol update -- (Server) `/move` chat hook to `move` module - -### Removed -- (Source) `./clientSource/` directory - -### Changed -- (Server) Minor bug fixes -- (Server) Increased module abstraction to remove duplicate code (thanks @MinusGix) - -## [2.1.92 pre 2.2] - 2019-11-06 -### Added -- (Server) `./server/src/utility/` directory -- (Server) `Constants.js` class in `utility` -- (Server) `esm` module to transpile ES6 - -### Changed -- (Server) Changed ES5 styling to ES6 -- (Server) And improved source comments -- (Server) Minor code format changes -- (Server) Updated all dependencies (be sure to update your local copy with the new packages) - -## [2.1.91 pre 2.2] - 2019-08-17 -### Added -- (Client) Markdown engine -- (Client) Imgur based image posting (through markdown) - -### Changed -- (Client) Removed cloudflare references making hack.chat self-hosted again -- (Client) The way messages are pushed, closing an xss vuln in PRs 985dd6f and 9fcb235 -- (Client) Side bar layout -- (Client) Fixed some options not storing -- (Client) Fixed firefox drop down menu bug -- (Client) Updated Katex lib - -### Stretched -- The term "minimal" - -## [2.1.9 pre 2.2] - 2019-03-18 -### Changed -- Configuration script setup, making it more portable/sane -- Refactored naming scheme and entry point - -### Removed -- Configuration setup from `./serverLib/ConfigManager` -- Unused feature allowing command modules to add to the configuration/setup process -- `deasync` dependency - -## [2.1.9] - 2019-02-21 -### Added -- `./server/src/commands/core/emote.js` module to provide action text -- `./server/src/core/server.js` priorities to command hooking -- Priority levels to all command modules -- `./server/src/commands/core/chat.js` Unknown '/' commands will now return a warning -- `./server/src/commands/internal/legacylayer.js` to provide compatibility to legacy connections - -### Changed -- Updated all libraries to latest -- `./server/src/core/server.js` Removed unneeded function bindings -- `./server/src/core/server.js` Hook function layout -- `./server/src/managers/config.js` Documentation wording - -## [2.1.0] - 2018-09-29 -### Added -- Module hook framework, isolating modules and making them truly drop-to-install -- `./server/src/commands/core/whisper.js` module to send in-channel private messages, `/whisper` hook -- `muzzle` and `mute` aliases to `./server/src/commands/mod/dumb.js` -- `unmuzzle` and `unmute` aliases to `./server/src/commands/mod/speak.js` -- `./server/src/commands/admin/removemod.js` module to remove mods -- `./server/src/commands/mod/unbanall.js` module to clear all bans and ratelimiting - -### Changed -- Further code cleanup on all modules -- Adjusted `ipSalt` entropy -- `./server/src/commands/core/help.js` output is now helpful, added `/help` hook -- `./server/src/commands/core/chat.js` added `/myhash` and `/me` hooks -- `./server/src/commands/core/morestats.js` added `/stats` hook - -## [2.0.3] - 2018-06-03 -### Added -- `./server/src/commands/mod/dumb.js` module for server-wide shadow muting -- `./server/src/commands/mod/speak.js` module unmuting -- `./server/src/commands/internal/socketreply.js` module to route warning to clients -- `./server/src/commands/core/ping.js` module to prevent `didYouMean` errors on legacy sources - -### Changed -- Moved `disconnect.js` into servers internal modules directory -- Restructured `server.js` and `commands.js`, removing hardcoded protocol use - -## [2.0.2] - 2018-05-19 -### Added -- `./documentation/DOCUMENTATION.md` document which gives overview of the applications protocol -- `./documentation/DEPLOY.md` document which gives overview of deploying the server live -- `./LICENSE` License file -- Code highlighting, triggered with # - -### Changed -- `README.md` wording and layout - -### Removed -- Unneeded `use strict` - -## [2.0.1] - 2018-04-18 -### Added -- `users-kicked` tracking to `morestats` command -- Server-side ping interval -- `move` command to change channels without reconnecting -- `disconnect` command module to free core server from protocol dependency -- `changenick` command to change client nick without reconnecting - -### Changed -- Filter object of the `findSockets` function now accepts more complex parameters, including functions and arrays -- `kick` command now accepts an array as the `nick` argument allowing multiple simultaneous kicks -- `join` command now takes advantage of the new filter object -- Core server disconnect handler now calls the `disconnect` module instead of broadcasting hard coded `onlineRemove` - -### Removed -- Client-side ping interval - -## [2.0.0] - 2018-04-12 -### Added -- CHANGELOG.md -- `index.html` files to `katex` directories - -### Changed -- Updated client html KaTeX libraries to v0.9.0 - -### Removed -- Uneeded files under `katex` directories diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 5c93f45..0000000 --- a/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2004 Sam Hocevar - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/README.md b/README.md index 2208ea6..d3a2cb4 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ A list of software developed for the hack.chat framework can be found at the [3rd party software list](https://github.com/hack-chat/3rd-party-software-list) repository. This includes bots, clients, docker containers, etc. -This is a backwards compatible continuation of the [work by Andrew Belt](https://github.com/AndrewBelt/hack.chat). The server code has been updated to ES6 along with several new features including new commands and hot-reload of the commands/protocol. There is also [documentation](documentation/DOCUMENTATION.md) and a [changelog](CHANGELOG.md). +This is a backwards compatible continuation of the [work by Andrew Belt](https://github.com/AndrewBelt/hack.chat). The server code has been updated to ES6 along with several new features including new commands and hot-reload of the commands/protocol. There is also [documentation](documentation/index.html). # Installation ## Prerequisites -- [node.js 8.10.0](https://nodejs.org/en/download/package-manager/#windows) or higher -- [npm 5.7.1](https://nodejs.org/en/download/package-manager/#windows) or higher +- [node.js v16.14.0](https://nodejs.org/) or higher +- [npm 8.5.4](https://nodejs.org/) or higher ## Developer Installation @@ -20,19 +20,14 @@ This is a backwards compatible continuation of the [work by Andrew Belt](https:/ 1. Install the dependencies: `npm install` 1. Launch: `npm start` - If you change the `websocketPort` option during the config setup then these changes will need to be reflected on [line 60 of client.js](https://github.com/hack-chat/main/blob/master/client/client.js#L60). - ## Live Deployment Installation See [DEPLOY.md](documentation/DEPLOY.md) # Contributing -- If you are modifying commands, make sure it is backwards compatible with the legacy client and you update the documentation accordingly. -- Use [the template](documentation/templateCommand.js) to learn how to create new commands. - Use two space indents. - Name files in camelCase. -- Scripts that do not default to strict mode (such as modules) must use the `'use strict'` directive. # Credits @@ -41,10 +36,10 @@ See [DEPLOY.md](documentation/DEPLOY.md) * [**Neel Kamath**](https://github.com/neelkamath) - *Base Documentation* * [**Carlos Villavicencio**](https://github.com/po5i) - *Syntax Highlighting Integration* * [**OpSimple**](https://github.com/OpSimple) - *Modules Added: dumb.js & speak.js* -* Andrew Belt, https://github.com/AndrewBelt, for original base work -* [wwandrew](https://github.com/wwandrew), for finding server flaws (including attack vectors) and submitting ~~___incredibly detailed___~~ bug reports -* [Everyone else](https://github.com/hack-chat/main/graphs/contributors) who participated in this project. +* [**Andrew Belt**](https://github.com/AndrewBelt), for original base work +* [**wwandrew**](https://github.com/wwandrew), for finding server flaws (including attack vectors) and submitting ~~___incredibly detailed___~~ bug reports +* [**Everyone else**](https://github.com/hack-chat/main/graphs/contributors) who participated in this project. # License -This project is licensed under the [WTFPL License](LICENSE). +This project is licensed under the [MIT License](LICENSE). diff --git a/client/client.js b/client/client.js index 097e926..944a644 100644 --- a/client/client.js +++ b/client/client.js @@ -23,7 +23,7 @@ var markdownOptions = { langPrefix: '', linkify: true, linkTarget: '_blank" rel="noreferrer', - typographer: true, + typographer: true, quotes: `""''`, doHighlight: true, @@ -33,12 +33,12 @@ var markdownOptions = { if (lang && hljs.getLanguage(lang)) { try { return hljs.highlight(lang, str).value; - } catch (__) {} + } catch (__) { } } try { return hljs.highlightAuto(str).value; - } catch (__) {} + } catch (__) { } return ''; } @@ -75,20 +75,20 @@ md.renderer.rules.image = function (tokens, idx, options) { return ''; } - return '' + Remarkable.utils.escapeHtml(Remarkable.utils.replaceEntities(src)) + ''; + return '' + Remarkable.utils.escapeHtml(Remarkable.utils.replaceEntities(src)) + ''; }; md.renderer.rules.link_open = function (tokens, idx, options) { var title = tokens[idx].title ? (' title="' + Remarkable.utils.escapeHtml(Remarkable.utils.replaceEntities(tokens[idx].title)) + '"') : ''; - var target = options.linkTarget ? (' target="' + options.linkTarget + '"') : ''; - return ''; + var target = options.linkTarget ? (' target="' + options.linkTarget + '"') : ''; + return ''; }; -md.renderer.rules.text = function(tokens, idx) { +md.renderer.rules.text = function (tokens, idx) { tokens[idx].content = Remarkable.utils.escapeHtml(tokens[idx].content); if (tokens[idx].content.indexOf('?') !== -1) { - tokens[idx].content = tokens[idx].content.replace(/(^|\s)(\?)\S+?(?=[,.!?:)]?\s|$)/gm, function(match) { + tokens[idx].content = tokens[idx].content.replace(/(^|\s)(\?)\S+?(?=[,.!?:)]?\s|$)/gm, function (match) { var channelLink = Remarkable.utils.escapeHtml(Remarkable.utils.replaceEntities(match.trim())); var whiteSpace = ''; if (match[0] !== '?') { @@ -98,7 +98,7 @@ md.renderer.rules.text = function(tokens, idx) { }); } - return tokens[idx].content; + return tokens[idx].content; }; md.use(remarkableKatex); @@ -172,12 +172,40 @@ var myChannel = window.location.search.replace(/^\?/, ''); var lastSent = [""]; var lastSentPos = 0; +/** + * Stores active messages + * These are messages that can be edited. + * @type {{ customId: string, userid: number, sent: number, text: string, elem: HTMLElement }[]} + */ +var activeMessages = []; + +setInterval(function () { + var editTimeout = 6 * 60 * 1000; + var now = Date.now(); + for (var i = 0; i < activeMessages.length; i++) { + if (now - activeMessages[i].sent > editTimeout) { + activeMessages.splice(i, 1); + i--; + } + } +}, 30 * 1000); + +function addActiveMessage(customId, userid, text, elem) { + activeMessages.push({ + customId, + userid, + sent: Date.now(), + text, + elem, + }); +} + /** Notification switch and local storage behavior **/ var notifySwitch = document.getElementById("notify-switch") var notifySetting = localStorageGet("notify-api") var notifyPermissionExplained = 0; // 1 = granted msg shown, -1 = denied message shown -// Inital request for notifications permission +// Initial request for notifications permission function RequestNotifyPermission() { try { var notifyPromise = Notification.requestPermission(); @@ -361,7 +389,9 @@ function join(channel) { var args = JSON.parse(message.data); var cmd = args.cmd; var command = COMMANDS[cmd]; - command.call(null, args); + if (command) { + command.call(null, args); + } } } @@ -370,7 +400,63 @@ var COMMANDS = { if (ignoredUsers.indexOf(args.nick) >= 0) { return; } - pushMessage(args); + + var elem = pushMessage(args); + + if (typeof (args.customId) === 'string') { + addActiveMessage(args.customId, args.userid, args.text, elem); + } + }, + + updateMessage: function (args) { + var customId = args.customId; + var mode = args.mode; + + if (!mode) { + return; + } + + var message; + for (var i = 0; i < activeMessages.length; i++) { + var msg = activeMessages[i]; + if (msg.userid === args.userid && msg.customId === customId) { + if (mode === 'complete') { + activeMessages.splice(i, 1); + return; + } + message = msg; + break; + } + } + + if (!message) { + return; + } + + var textElem = message.elem.querySelector('.text'); + if (!textElem) { + return; + } + + var newText = message.text; + if (mode === 'overwrite') { + newText = args.text; + } else if (mode === 'append') { + newText += args.text; + } else if (mode === 'prepend') { + newText = args.text + newText; + } + + message.text = newText; + + // Scroll to bottom if necessary + var atBottom = isAtBottom(); + + textElem.innerHTML = md.render(newText); + + if (atBottom) { + window.scrollTo(0, document.body.scrollHeight); + } }, info: function (args) { @@ -378,6 +464,11 @@ var COMMANDS = { pushMessage(args); }, + emote: function (args) { + args.nick = '*'; + pushMessage(args); + }, + warn: function (args) { args.nick = '!'; pushMessage(args); @@ -413,6 +504,30 @@ var COMMANDS = { if ($('#joined-left').checked) { pushMessage({ nick: '*', text: nick + " left" }); } + }, + + captcha: function (args) { + var messageEl = document.createElement('div'); + messageEl.classList.add('info'); + + + var nickSpanEl = document.createElement('span'); + nickSpanEl.classList.add('nick'); + messageEl.appendChild(nickSpanEl); + + var nickLinkEl = document.createElement('a'); + nickLinkEl.textContent = '#'; + nickSpanEl.appendChild(nickLinkEl); + + var textEl = document.createElement('pre'); + textEl.style.fontSize = '4px'; + textEl.classList.add('text'); + textEl.innerHTML = args.text; + + messageEl.appendChild(textEl); + $('#messages').appendChild(messageEl); + + window.scrollTo(0, document.body.scrollHeight); } } @@ -450,7 +565,13 @@ function pushMessage(args) { if (args.trip) { var tripEl = document.createElement('span'); - tripEl.textContent = args.trip + " "; + + if (args.mod) { + tripEl.textContent = String.fromCodePoint(11088) + " " + args.trip + " "; + } else { + tripEl.textContent = args.trip + " "; + } + tripEl.classList.add('trip'); nickSpanEl.appendChild(tripEl); } @@ -459,6 +580,10 @@ function pushMessage(args) { var nickLinkEl = document.createElement('a'); nickLinkEl.textContent = args.nick; + if (args.color && /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i.test(args.color)) { + nickLinkEl.setAttribute('style', 'color:#' + args.color + ' !important'); + } + nickLinkEl.onclick = function () { insertAtCursor("@" + args.nick + " "); $('#chatinput').focus(); @@ -485,6 +610,8 @@ function pushMessage(args) { unread += 1; updateTitle(); + + return messageEl; } function insertAtCursor(text) { @@ -641,12 +768,23 @@ $('#chatinput').onkeydown = function (e) { } } +// from https://stackoverflow.com/questions/11381673/detecting-a-mobile-browser +function checkIsMobileOrTablet() { + let check = false; + (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); + return check; +}; + +var isMobileOrTablet = checkIsMobileOrTablet(); + function updateInputSize() { var atBottom = isAtBottom(); + if (!isMobileOrTablet) { + var input = $('#chatinput'); + input.style.height = 0; + input.style.height = input.scrollHeight + 'px'; + } - var input = $('#chatinput'); - input.style.height = 0; - input.style.height = input.scrollHeight + 'px'; document.body.style.marginBottom = $('#footer').offsetHeight + 'px'; if (atBottom) { @@ -672,8 +810,8 @@ $('#sidebar').onmouseleave = document.ontouchstart = function (event) { var e = event.toElement || event.relatedTarget; try { if (e.parentNode == this || e == this) { - return; - } + return; + } } catch (e) { return; } if (!$('#pin-sidebar').checked) { @@ -701,8 +839,8 @@ if (localStorageGet('joined-left') == 'false') { if (localStorageGet('parse-latex') == 'false') { $('#parse-latex').checked = false; - md.inline.ruler.disable([ 'katex' ]); - md.block.ruler.disable([ 'katex' ]); + md.inline.ruler.disable(['katex']); + md.block.ruler.disable(['katex']); } $('#pin-sidebar').onchange = function (e) { @@ -717,11 +855,11 @@ $('#parse-latex').onchange = function (e) { var enabled = !!e.target.checked; localStorageSet('parse-latex', enabled); if (enabled) { - md.inline.ruler.enable([ 'katex' ]); - md.block.ruler.enable([ 'katex' ]); + md.inline.ruler.enable(['katex']); + md.block.ruler.enable(['katex']); } else { - md.inline.ruler.disable([ 'katex' ]); - md.block.ruler.disable([ 'katex' ]); + md.inline.ruler.disable(['katex']); + md.block.ruler.disable(['katex']); } } @@ -830,15 +968,16 @@ var schemes = [ 'pop', 'railscasts', 'solarized', - 'tk-night', 'tomorrow', + 'tk-night', 'carrot', 'lax', 'Ubuntu', 'gruvbox-light', 'fried-egg', 'rainbow', - 'amoled' + 'amoled', + 'retro' ]; var highlights = [ @@ -892,7 +1031,7 @@ $('#highlight-selector').onchange = function (e) { setHighlight(e.target.value); } -// Load sidebar configaration values from local storage if available +// Load sidebar configuration values from local storage if available if (localStorageGet('scheme')) { setScheme(localStorageGet('scheme')); } diff --git a/client/index.html b/client/index.html index ca623ec..86658d9 100644 --- a/client/index.html +++ b/client/index.html @@ -24,7 +24,7 @@
-
+