mirror of
https://github.com/hack-chat/main.git
synced 2024-03-22 13:20:33 +08:00
initial commit
This commit is contained in:
commit
fde6895720
82
README.md
Normal file
82
README.md
Normal file
|
@ -0,0 +1,82 @@
|
|||
# Hack.Chat v2
|
||||
|
||||
This is a backwards compatible continuation of the work by Andrew Belt [https://github.com/AndrewBelt/hack.chat](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.
|
||||
|
||||
## Getting Started
|
||||
|
||||
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
What things you need to install the software and how to install them
|
||||
|
||||
```
|
||||
node >= 8.10.0
|
||||
npm >= 5.7.1
|
||||
```
|
||||
|
||||
### Installing
|
||||
|
||||
Clone this git and cd into the directory. These steps will get a development env running:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Or on a Windows machine with Yarn installed:
|
||||
|
||||
```
|
||||
yarn install
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```
|
||||
node main.js
|
||||
```
|
||||
|
||||
The configuration script will execute the initial server setup by requesting input. Follow the steps until it finishes:
|
||||
|
||||
```
|
||||
Note: npm/yarn run config will re-run this utility.
|
||||
|
||||
You will now be asked for the following:
|
||||
- Admin Name, the initial admin username
|
||||
- Admin Pass, the initial admin password
|
||||
- Port, the port for the websocket
|
||||
- Salt, the salt for username trip
|
||||
|
||||
prompt: adminName: admin
|
||||
prompt: adminPass: ****
|
||||
|
||||
prompt: websocketPort: (6060)
|
||||
prompt: tripSalt: ************
|
||||
|
||||
Config generated! You may now start the server normally.
|
||||
```
|
||||
|
||||
You may now begin development or deploy to live system with a node process manager.
|
||||
|
||||
## Deployment
|
||||
|
||||
After configuration, push everything except the node_modules folder to the live server and re-run:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
You can now run start the server software with a process manager like PM2.
|
||||
|
||||
## Authors
|
||||
|
||||
* **Marzavec** - *Initial work* - [https://github.com/marzavec](https://github.com/marzavec)
|
||||
|
||||
See also the list of [contributors](https://github.com/hack-chat/main.git/contributors) who participated in this project.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the WTFPL License - see the [http://www.wtfpl.net/txt/copying/](http://www.wtfpl.net/txt/copying/) file for details
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
* TODO
|
24
client/base16/android.less
Normal file
24
client/base16/android.less
Normal file
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// Base16 Bright
|
||||
// Created by Fredrik Broman (http://frebro.com)
|
||||
// Based on the Android visual guidelines
|
||||
// http://developer.android.com/design/style/color.html
|
||||
//
|
||||
|
||||
@base00: #212121;
|
||||
@base01: #333333;
|
||||
@base02: #626261;
|
||||
@base03: #858585;
|
||||
@base04: #dddddd;
|
||||
@base05: #e0e0e0;
|
||||
@base06: #f2f2f2;
|
||||
@base07: #ffffff;
|
||||
|
||||
@base08: #e94749;
|
||||
@base09: #f18618;
|
||||
@base0A: #fbba37;
|
||||
@base0B: #99C21D;
|
||||
@base0C: #33B5E5;
|
||||
@base0D: #0099CC;
|
||||
@base0E: #9568AA;
|
||||
@base0F: #754595;
|
21
client/base16/atelier-dune.less
Normal file
21
client/base16/atelier-dune.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Atelier Dune
|
||||
// Created by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/)
|
||||
//
|
||||
|
||||
@base00: #20201d;
|
||||
@base01: #292824;
|
||||
@base02: #6e6b5e;
|
||||
@base03: #7d7a68;
|
||||
@base04: #999580;
|
||||
@base05: #a6a28c;
|
||||
@base06: #e8e4cf;
|
||||
@base07: #fefbec;
|
||||
@base08: #d73737;
|
||||
@base09: #b65611;
|
||||
@base0A: #cfb017;
|
||||
@base0B: #60ac39;
|
||||
@base0C: #1fad83;
|
||||
@base0D: #6684e1;
|
||||
@base0E: #b854d4;
|
||||
@base0F: #d43552;
|
21
client/base16/atelier-forest.less
Normal file
21
client/base16/atelier-forest.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Atelier Forest
|
||||
// Created by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/)
|
||||
//
|
||||
|
||||
@base00: #1b1918;
|
||||
@base01: #2c2421;
|
||||
@base02: #68615e;
|
||||
@base03: #766e6b;
|
||||
@base04: #9c9491;
|
||||
@base05: #a8a19f;
|
||||
@base06: #e6e2e0;
|
||||
@base07: #f1efee;
|
||||
@base08: #f22c40;
|
||||
@base09: #df5320;
|
||||
@base0A: #d5911a;
|
||||
@base0B: #5ab738;
|
||||
@base0C: #00ad9c;
|
||||
@base0D: #407ee7;
|
||||
@base0E: #6666ea;
|
||||
@base0F: #c33ff3;
|
21
client/base16/atelier-heath.less
Normal file
21
client/base16/atelier-heath.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Atelier Heath
|
||||
// Created by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/)
|
||||
//
|
||||
|
||||
@base00: #1b181b;
|
||||
@base01: #292329;
|
||||
@base02: #695d69;
|
||||
@base03: #776977;
|
||||
@base04: #9e8f9e;
|
||||
@base05: #ab9bab;
|
||||
@base06: #d8cad8;
|
||||
@base07: #f7f3f7;
|
||||
@base08: #ca402b;
|
||||
@base09: #a65926;
|
||||
@base0A: #bb8a35;
|
||||
@base0B: #379a37;
|
||||
@base0C: #159393;
|
||||
@base0D: #516aec;
|
||||
@base0E: #7b59c0;
|
||||
@base0F: #cc33cc;
|
21
client/base16/atelier-lakeside.less
Normal file
21
client/base16/atelier-lakeside.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Atelier Lakeside
|
||||
// Created by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/)
|
||||
//
|
||||
|
||||
@base00: #161b1d;
|
||||
@base01: #1f292e;
|
||||
@base02: #516d7b;
|
||||
@base03: #5a7b8c;
|
||||
@base04: #7195a8;
|
||||
@base05: #7ea2b4;
|
||||
@base06: #c1e4f6;
|
||||
@base07: #ebf8ff;
|
||||
@base08: #d22d72;
|
||||
@base09: #935c25;
|
||||
@base0A: #8a8a0f;
|
||||
@base0B: #568c3b;
|
||||
@base0C: #2d8f6f;
|
||||
@base0D: #257fad;
|
||||
@base0E: #5d5db1;
|
||||
@base0F: #b72dd2;
|
21
client/base16/atelier-seaside.less
Normal file
21
client/base16/atelier-seaside.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Atelier Seaside
|
||||
// Created by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/)
|
||||
//
|
||||
|
||||
@base00: #131513;
|
||||
@base01: #242924;
|
||||
@base02: #5e6e5e;
|
||||
@base03: #687d68;
|
||||
@base04: #809980;
|
||||
@base05: #8ca68c;
|
||||
@base06: #cfe8cf;
|
||||
@base07: #f0fff0;
|
||||
@base08: #e6193c;
|
||||
@base09: #87711d;
|
||||
@base0A: #c3c322;
|
||||
@base0B: #29a329;
|
||||
@base0C: #1999b3;
|
||||
@base0D: #3d62f5;
|
||||
@base0E: #ad2bee;
|
||||
@base0F: #e619c3;
|
21
client/base16/bright.less
Normal file
21
client/base16/bright.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Bright
|
||||
// Created by Chris Kempson (http://chriskempson.com)
|
||||
//
|
||||
|
||||
@base00: #000000;
|
||||
@base01: #303030;
|
||||
@base02: #505050;
|
||||
@base03: #b0b0b0;
|
||||
@base04: #d0d0d0;
|
||||
@base05: #e0e0e0;
|
||||
@base06: #f5f5f5;
|
||||
@base07: #ffffff;
|
||||
@base08: #fb0120;
|
||||
@base09: #fc6d24;
|
||||
@base0A: #fda331;
|
||||
@base0B: #a1c659;
|
||||
@base0C: #76c7b7;
|
||||
@base0D: #6fb3d2;
|
||||
@base0E: #d381c3;
|
||||
@base0F: #be643c;
|
21
client/base16/chalk.less
Normal file
21
client/base16/chalk.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Chalk
|
||||
// Created by Chris Kempson (http://chriskempson.com)
|
||||
//
|
||||
|
||||
@base00: #151515;
|
||||
@base01: #202020;
|
||||
@base02: #303030;
|
||||
@base03: #505050;
|
||||
@base04: #b0b0b0;
|
||||
@base05: #d0d0d0;
|
||||
@base06: #e0e0e0;
|
||||
@base07: #f5f5f5;
|
||||
@base08: #fb9fb1;
|
||||
@base09: #eda987;
|
||||
@base0A: #ddb26f;
|
||||
@base0B: #acc267;
|
||||
@base0C: #12cfc0;
|
||||
@base0D: #6fc2ef;
|
||||
@base0E: #e1a3ee;
|
||||
@base0F: #deaf8f;
|
21
client/base16/default.less
Normal file
21
client/base16/default.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Default
|
||||
// Created by Chris Kempson (http://chriskempson.com)
|
||||
//
|
||||
|
||||
@base00: #151515;
|
||||
@base01: #202020;
|
||||
@base02: #303030;
|
||||
@base03: #505050;
|
||||
@base04: #b0b0b0;
|
||||
@base05: #d0d0d0;
|
||||
@base06: #e0e0e0;
|
||||
@base07: #f5f5f5;
|
||||
@base08: #ac4142;
|
||||
@base09: #d28445;
|
||||
@base0A: #f4bf75;
|
||||
@base0B: #90a959;
|
||||
@base0C: #75b5aa;
|
||||
@base0D: #6a9fb5;
|
||||
@base0E: #aa759f;
|
||||
@base0F: #8f5536;
|
21
client/base16/eighties.less
Normal file
21
client/base16/eighties.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Eighties
|
||||
// Created by Chris Kempson (http://chriskempson.com)
|
||||
//
|
||||
|
||||
@base00: #2d2d2d;
|
||||
@base01: #393939;
|
||||
@base02: #515151;
|
||||
@base03: #747369;
|
||||
@base04: #a09f93;
|
||||
@base05: #d3d0c8;
|
||||
@base06: #e8e6df;
|
||||
@base07: #f2f0ec;
|
||||
@base08: #f2777a;
|
||||
@base09: #f99157;
|
||||
@base0A: #ffcc66;
|
||||
@base0B: #99cc99;
|
||||
@base0C: #66cccc;
|
||||
@base0D: #6699cc;
|
||||
@base0E: #cc99cc;
|
||||
@base0F: #d27b53;
|
21
client/base16/greenscreen.less
Normal file
21
client/base16/greenscreen.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Greenscreen
|
||||
// Created by Chris Kempson (http://chriskempson.com)
|
||||
//
|
||||
|
||||
@base00: #001100;
|
||||
@base01: #003300;
|
||||
@base02: #005500;
|
||||
@base03: #007700;
|
||||
@base04: #009900;
|
||||
@base05: #00bb00;
|
||||
@base06: #00dd00;
|
||||
@base07: #00ff00;
|
||||
@base08: #007700;
|
||||
@base09: #009900;
|
||||
@base0A: #007700;
|
||||
@base0B: #00bb00;
|
||||
@base0C: #005500;
|
||||
@base0D: #009900;
|
||||
@base0E: #00bb00;
|
||||
@base0F: #005500;
|
21
client/base16/mocha.less
Normal file
21
client/base16/mocha.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Mocha
|
||||
// Created by Chris Kempson (http://chriskempson.com)
|
||||
//
|
||||
|
||||
@base00: #3B3228;
|
||||
@base01: #534636;
|
||||
@base02: #645240;
|
||||
@base03: #7e705a;
|
||||
@base04: #b8afad;
|
||||
@base05: #d0c8c6;
|
||||
@base06: #e9e1dd;
|
||||
@base07: #f5eeeb;
|
||||
@base08: #cb6077;
|
||||
@base09: #d28b71;
|
||||
@base0A: #f4bc87;
|
||||
@base0B: #beb55b;
|
||||
@base0C: #7bbda4;
|
||||
@base0D: #8ab3b5;
|
||||
@base0E: #a89bb9;
|
||||
@base0F: #bb9584;
|
21
client/base16/monokai.less
Normal file
21
client/base16/monokai.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Monokai
|
||||
// Created by Wimer Hazenberg (http://www.monokai.nl)
|
||||
//
|
||||
|
||||
@base00: #272822;
|
||||
@base01: #383830;
|
||||
@base02: #49483e;
|
||||
@base03: #75715e;
|
||||
@base04: #a59f85;
|
||||
@base05: #f8f8f2;
|
||||
@base06: #f5f4f1;
|
||||
@base07: #f9f8f5;
|
||||
@base08: #f92672;
|
||||
@base09: #fd971f;
|
||||
@base0A: #f4bf75;
|
||||
@base0B: #a6e22e;
|
||||
@base0C: #a1efe4;
|
||||
@base0D: #66d9ef;
|
||||
@base0E: #ae81ff;
|
||||
@base0F: #cc6633;
|
26
client/base16/nese.less
Normal file
26
client/base16/nese.less
Normal file
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// Base16 NE.se color system
|
||||
// Created by Fredrik Broman (http://frebro.com)
|
||||
//
|
||||
// Reference on Adobe Kuler:
|
||||
// https://kuler.adobe.com/NESE-Warm-color-theme-2900819/
|
||||
// https://kuler.adobe.com/NESE-Cold-color-theme-2900847/
|
||||
//
|
||||
|
||||
@base00: lighten(black, 1%); // #030303
|
||||
@base01: lighten(black, 5%); // #0c0c0c
|
||||
@base02: lighten(black, 20%); // #262626
|
||||
@base03: lighten(black, 45%); // #5f5f5f
|
||||
@base04: lighten(black, 65%); // #959595
|
||||
@base05: lighten(black, 80%); // #c1c1c1
|
||||
@base06: lighten(black, 95%); // #efefef
|
||||
@base07: lighten(black, 99%); // #fcfcfc
|
||||
|
||||
@base08: #f73e30; // Red
|
||||
@base09: mix(@base08, @base0A, 50%); // Orange = #f97c37
|
||||
@base0A: #faba3d; // Yellow
|
||||
@base0B: #1ab857; // Green
|
||||
@base0C: mix(@base0B, @base0D, 50%); // Cyan = #29a188
|
||||
@base0D: #388bb8; // Blue
|
||||
@base0E: mix(@base0D, @base0F, 50%); // Purple = #9c73a7
|
||||
@base0F: #ff5a96; // Pink
|
21
client/base16/ocean.less
Normal file
21
client/base16/ocean.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Ocean
|
||||
// Created by Chris Kempson (http://chriskempson.com)
|
||||
//
|
||||
|
||||
@base00: #2b303b;
|
||||
@base01: #343d46;
|
||||
@base02: #4f5b66;
|
||||
@base03: #65737e;
|
||||
@base04: #a7adba;
|
||||
@base05: #c0c5ce;
|
||||
@base06: #dfe1e8;
|
||||
@base07: #eff1f5;
|
||||
@base08: #bf616a;
|
||||
@base09: #d08770;
|
||||
@base0A: #ebcb8b;
|
||||
@base0B: #a3be8c;
|
||||
@base0C: #96b5b4;
|
||||
@base0D: #8fa1b3;
|
||||
@base0E: #b48ead;
|
||||
@base0F: #ab7967;
|
21
client/base16/pop.less
Normal file
21
client/base16/pop.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Pop
|
||||
// Created by Chris Kempson (http://chriskempson.com)
|
||||
//
|
||||
|
||||
@base00: #000000;
|
||||
@base01: #202020;
|
||||
@base02: #303030;
|
||||
@base03: #505050;
|
||||
@base04: #b0b0b0;
|
||||
@base05: #d0d0d0;
|
||||
@base06: #e0e0e0;
|
||||
@base07: #ffffff;
|
||||
@base08: #eb008a;
|
||||
@base09: #f29333;
|
||||
@base0A: #f8ca12;
|
||||
@base0B: #37b349;
|
||||
@base0C: #00aabb;
|
||||
@base0D: #0e5a94;
|
||||
@base0E: #b31e8d;
|
||||
@base0F: #7a2d00;
|
21
client/base16/railscasts.less
Normal file
21
client/base16/railscasts.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Railscasts
|
||||
// Created by Ryan Bates (http://railscasts.com)
|
||||
//
|
||||
|
||||
@base00: #2b2b2b;
|
||||
@base01: #272935;
|
||||
@base02: #3a4055;
|
||||
@base03: #5a647e;
|
||||
@base04: #d4cfc9;
|
||||
@base05: #e6e1dc;
|
||||
@base06: #f4f1ed;
|
||||
@base07: #f9f7f3;
|
||||
@base08: #da4939;
|
||||
@base09: #cc7833;
|
||||
@base0A: #ffc66d;
|
||||
@base0B: #a5c261;
|
||||
@base0C: #519f50;
|
||||
@base0D: #6d9cbe;
|
||||
@base0E: #b6b3eb;
|
||||
@base0F: #bc9458;
|
21
client/base16/solarized.less
Normal file
21
client/base16/solarized.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Solarized
|
||||
// Created by Ethan Schoonover (http://ethanschoonover.com/solarized)
|
||||
//
|
||||
|
||||
@base00: #002b36;
|
||||
@base01: #073642;
|
||||
@base02: #586e75;
|
||||
@base03: #657b83;
|
||||
@base04: #839496;
|
||||
@base05: #93a1a1;
|
||||
@base06: #eee8d5;
|
||||
@base07: #fdf6e3;
|
||||
@base08: #dc322f;
|
||||
@base09: #cb4b16;
|
||||
@base0A: #b58900;
|
||||
@base0B: #859900;
|
||||
@base0C: #2aa198;
|
||||
@base0D: #268bd2;
|
||||
@base0E: #6c71c4;
|
||||
@base0F: #d33682;
|
21
client/base16/tomorrow.less
Normal file
21
client/base16/tomorrow.less
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Base16 Tomorrow
|
||||
// Created by Chris Kempson (http://chriskempson.com)
|
||||
//
|
||||
|
||||
@base00: #1d1f21;
|
||||
@base01: #282a2e;
|
||||
@base02: #373b41;
|
||||
@base03: #969896;
|
||||
@base04: #b4b7b4;
|
||||
@base05: #c5c8c6;
|
||||
@base06: #e0e0e0;
|
||||
@base07: #ffffff;
|
||||
@base08: #cc6666;
|
||||
@base09: #de935f;
|
||||
@base0A: #f0c674;
|
||||
@base0B: #b5bd68;
|
||||
@base0C: #8abeb7;
|
||||
@base0D: #81a2be;
|
||||
@base0E: #b294bb;
|
||||
@base0F: #a3685a;
|
534
client/client.js
Normal file
534
client/client.js
Normal file
|
@ -0,0 +1,534 @@
|
|||
var frontpage = [
|
||||
" _ _ _ _ ",
|
||||
" | |_ ___ ___| |_ ___| |_ ___| |_ ",
|
||||
" | |_ || _| '_| | _| |_ || _|",
|
||||
" |_|_|__/|___|_,_|.|___|_|_|__/|_| ",
|
||||
"",
|
||||
"",
|
||||
"Welcome to hack.chat, a minimal, distraction-free chat application.",
|
||||
"Channels are created and joined by going to https://hack.chat/?your-channel. There are no channel lists, so a secret channel name can be used for private discussions.",
|
||||
"",
|
||||
"Here are some pre-made channels you can join:",
|
||||
"?lounge ?meta",
|
||||
"?math ?physics ?chemistry",
|
||||
"?technology ?programming",
|
||||
"?games ?banana",
|
||||
"And here's a random one generated just for you: ?" + Math.random().toString(36).substr(2, 8),
|
||||
"",
|
||||
"Formatting:",
|
||||
"Whitespace is preserved, so source code can be pasted verbatim.",
|
||||
"Surround LaTeX with a dollar sign for inline style $\\zeta(2) = \\pi^2/6$, and two dollars for display. $$\\int_0^1 \\int_0^1 \\frac{1}{1-xy} dx dy = \\frac{\\pi^2}{6}$$",
|
||||
"",
|
||||
"GitHub: https://github.com/AndrewBelt/hack.chat",
|
||||
"Android apps: https://goo.gl/UkbKYy https://goo.gl/qasdSu https://goo.gl/fGQFQN",
|
||||
"",
|
||||
"Server and web client released under the MIT open source license.",
|
||||
"No message history is retained on the hack.chat server.",
|
||||
"",
|
||||
"[03/03/2018] Please note that the server is currently undergoing changes, expect random downtime or disconnections!",
|
||||
"[03/03/2018] Hack.chat is now under new management by the core community; @raf924 @bacon @wwandrew @Rut @_0x17 @M4GNV5 @MinusGix @nanotech",
|
||||
].join("\n")
|
||||
|
||||
function $(query) {return document.querySelector(query)}
|
||||
|
||||
function localStorageGet(key) {
|
||||
try {
|
||||
return window.localStorage[key]
|
||||
}
|
||||
catch(e) {}
|
||||
}
|
||||
|
||||
function localStorageSet(key, val) {
|
||||
try {
|
||||
window.localStorage[key] = val
|
||||
}
|
||||
catch(e) {}
|
||||
}
|
||||
|
||||
|
||||
var ws
|
||||
var myNick = localStorageGet('my-nick')
|
||||
var myChannel = window.location.search.replace(/^\?/, '')
|
||||
var lastSent = [""]
|
||||
var lastSentPos = 0
|
||||
|
||||
|
||||
// Ping server every 50 seconds to retain WebSocket connection
|
||||
window.setInterval(function() {
|
||||
send({cmd: 'ping'})
|
||||
}, 50000)
|
||||
|
||||
|
||||
function join(channel) {
|
||||
|
||||
ws = new WebSocket('ws://127.0.0.1:6060')
|
||||
|
||||
var wasConnected = false
|
||||
|
||||
ws.onopen = function() {
|
||||
if (!wasConnected) {
|
||||
if (location.hash) {
|
||||
myNick = location.hash.substr(1)
|
||||
}
|
||||
else {
|
||||
myNick = prompt('Nickname:', myNick)
|
||||
}
|
||||
}
|
||||
if (myNick) {
|
||||
localStorageSet('my-nick', myNick)
|
||||
send({cmd: 'join', channel: channel, nick: myNick})
|
||||
}
|
||||
wasConnected = true
|
||||
}
|
||||
|
||||
ws.onclose = function() {
|
||||
if (wasConnected) {
|
||||
pushMessage({nick: '!', text: "Server disconnected. Attempting to reconnect..."})
|
||||
}
|
||||
window.setTimeout(function() {
|
||||
join(channel)
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
ws.onmessage = function(message) {
|
||||
var args = JSON.parse(message.data)
|
||||
var cmd = args.cmd
|
||||
var command = COMMANDS[cmd]
|
||||
command.call(null, args)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var COMMANDS = {
|
||||
chat: function(args) {
|
||||
if (ignoredUsers.indexOf(args.nick) >= 0) {
|
||||
return
|
||||
}
|
||||
pushMessage(args)
|
||||
},
|
||||
info: function(args) {
|
||||
args.nick = '*'
|
||||
pushMessage(args)
|
||||
},
|
||||
warn: function(args) {
|
||||
args.nick = '!'
|
||||
pushMessage(args)
|
||||
},
|
||||
onlineSet: function(args) {
|
||||
var nicks = args.nicks
|
||||
usersClear()
|
||||
nicks.forEach(function(nick) {
|
||||
userAdd(nick)
|
||||
})
|
||||
pushMessage({nick: '*', text: "Users online: " + nicks.join(", ")})
|
||||
},
|
||||
onlineAdd: function(args) {
|
||||
var nick = args.nick
|
||||
userAdd(nick)
|
||||
if ($('#joined-left').checked) {
|
||||
pushMessage({nick: '*', text: nick + " joined"})
|
||||
}
|
||||
},
|
||||
onlineRemove: function(args) {
|
||||
var nick = args.nick
|
||||
userRemove(nick)
|
||||
if ($('#joined-left').checked) {
|
||||
pushMessage({nick: '*', text: nick + " left"})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
function pushMessage(args) {
|
||||
// Message container
|
||||
var messageEl = document.createElement('div')
|
||||
messageEl.classList.add('message')
|
||||
|
||||
if (args.nick == myNick) {
|
||||
messageEl.classList.add('me')
|
||||
}
|
||||
else if (args.nick == '!') {
|
||||
messageEl.classList.add('warn')
|
||||
}
|
||||
else if (args.nick == '*') {
|
||||
messageEl.classList.add('info')
|
||||
}
|
||||
else if (args.admin) {
|
||||
messageEl.classList.add('admin')
|
||||
}
|
||||
else if (args.mod) {
|
||||
messageEl.classList.add('mod')
|
||||
}
|
||||
|
||||
// Nickname
|
||||
var nickSpanEl = document.createElement('span')
|
||||
nickSpanEl.classList.add('nick')
|
||||
messageEl.appendChild(nickSpanEl)
|
||||
|
||||
if (args.trip) {
|
||||
var tripEl = document.createElement('span')
|
||||
tripEl.textContent = args.trip + " "
|
||||
tripEl.classList.add('trip')
|
||||
nickSpanEl.appendChild(tripEl)
|
||||
}
|
||||
|
||||
if (args.nick) {
|
||||
var nickLinkEl = document.createElement('a')
|
||||
nickLinkEl.textContent = args.nick
|
||||
nickLinkEl.onclick = function() {
|
||||
insertAtCursor("@" + args.nick + " ")
|
||||
$('#chatinput').focus()
|
||||
}
|
||||
var date = new Date(args.time || Date.now())
|
||||
nickLinkEl.title = date.toLocaleString()
|
||||
nickSpanEl.appendChild(nickLinkEl)
|
||||
}
|
||||
|
||||
// Text
|
||||
var textEl = document.createElement('pre')
|
||||
textEl.classList.add('text')
|
||||
|
||||
textEl.textContent = args.text || ''
|
||||
textEl.innerHTML = textEl.innerHTML.replace(/(\?|https?:\/\/)\S+?(?=[,.!?:)]?\s|$)/g, parseLinks)
|
||||
|
||||
if ($('#parse-latex').checked) {
|
||||
// Temporary hotfix for \rule spamming, see https://github.com/Khan/KaTeX/issues/109
|
||||
textEl.innerHTML = textEl.innerHTML.replace(/\\rule|\\\\\s*\[.*?\]/g, '')
|
||||
try {
|
||||
renderMathInElement(textEl, {delimiters: [
|
||||
{left: "$$", right: "$$", display: true},
|
||||
{left: "$", right: "$", display: false},
|
||||
]})
|
||||
}
|
||||
catch (e) {
|
||||
console.warn(e)
|
||||
}
|
||||
}
|
||||
|
||||
messageEl.appendChild(textEl)
|
||||
|
||||
// Scroll to bottom
|
||||
var atBottom = isAtBottom()
|
||||
$('#messages').appendChild(messageEl)
|
||||
if (atBottom) {
|
||||
window.scrollTo(0, document.body.scrollHeight)
|
||||
}
|
||||
|
||||
unread += 1
|
||||
updateTitle()
|
||||
}
|
||||
|
||||
|
||||
function insertAtCursor(text) {
|
||||
var input = $('#chatinput')
|
||||
var start = input.selectionStart || 0
|
||||
var before = input.value.substr(0, start)
|
||||
var after = input.value.substr(start)
|
||||
before += text
|
||||
input.value = before + after
|
||||
input.selectionStart = input.selectionEnd = before.length
|
||||
updateInputSize()
|
||||
}
|
||||
|
||||
|
||||
function send(data) {
|
||||
if (ws && ws.readyState == ws.OPEN) {
|
||||
ws.send(JSON.stringify(data))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function parseLinks(g0) {
|
||||
var a = document.createElement('a')
|
||||
a.innerHTML = g0
|
||||
var url = a.textContent
|
||||
a.href = url
|
||||
a.target = '_blank'
|
||||
return a.outerHTML
|
||||
}
|
||||
|
||||
|
||||
var windowActive = true
|
||||
var unread = 0
|
||||
|
||||
window.onfocus = function() {
|
||||
windowActive = true
|
||||
updateTitle()
|
||||
}
|
||||
|
||||
window.onblur = function() {
|
||||
windowActive = false
|
||||
}
|
||||
|
||||
window.onscroll = function() {
|
||||
if (isAtBottom()) {
|
||||
updateTitle()
|
||||
}
|
||||
}
|
||||
|
||||
function isAtBottom() {
|
||||
return (window.innerHeight + window.scrollY) >= (document.body.scrollHeight - 1)
|
||||
}
|
||||
|
||||
function updateTitle() {
|
||||
if (windowActive && isAtBottom()) {
|
||||
unread = 0
|
||||
}
|
||||
|
||||
var title
|
||||
if (myChannel) {
|
||||
title = "?" + myChannel
|
||||
}
|
||||
else {
|
||||
title = "hack.chat"
|
||||
}
|
||||
if (unread > 0) {
|
||||
title = '(' + unread + ') ' + title
|
||||
}
|
||||
document.title = title
|
||||
}
|
||||
|
||||
/* footer */
|
||||
|
||||
$('#footer').onclick = function() {
|
||||
$('#chatinput').focus()
|
||||
}
|
||||
|
||||
$('#chatinput').onkeydown = function(e) {
|
||||
if (e.keyCode == 13 /* ENTER */ && !e.shiftKey) {
|
||||
e.preventDefault()
|
||||
// Submit message
|
||||
if (e.target.value != '') {
|
||||
var text = e.target.value
|
||||
e.target.value = ''
|
||||
send({cmd: 'chat', text: text})
|
||||
lastSent[0] = text
|
||||
lastSent.unshift("")
|
||||
lastSentPos = 0
|
||||
updateInputSize()
|
||||
}
|
||||
}
|
||||
else if (e.keyCode == 38 /* UP */) {
|
||||
// Restore previous sent messages
|
||||
if (e.target.selectionStart === 0 && lastSentPos < lastSent.length - 1) {
|
||||
e.preventDefault()
|
||||
if (lastSentPos == 0) {
|
||||
lastSent[0] = e.target.value
|
||||
}
|
||||
lastSentPos += 1
|
||||
e.target.value = lastSent[lastSentPos]
|
||||
e.target.selectionStart = e.target.selectionEnd = e.target.value.length
|
||||
updateInputSize()
|
||||
}
|
||||
}
|
||||
else if (e.keyCode == 40 /* DOWN */) {
|
||||
if (e.target.selectionStart === e.target.value.length && lastSentPos > 0) {
|
||||
e.preventDefault()
|
||||
lastSentPos -= 1
|
||||
e.target.value = lastSent[lastSentPos]
|
||||
e.target.selectionStart = e.target.selectionEnd = 0
|
||||
updateInputSize()
|
||||
}
|
||||
}
|
||||
else if (e.keyCode == 27 /* ESC */) {
|
||||
e.preventDefault()
|
||||
// Clear input field
|
||||
e.target.value = ""
|
||||
lastSentPos = 0
|
||||
lastSent[lastSentPos] = ""
|
||||
updateInputSize()
|
||||
}
|
||||
else if (e.keyCode == 9 /* TAB */) {
|
||||
// Tab complete nicknames starting with @
|
||||
e.preventDefault()
|
||||
var pos = e.target.selectionStart || 0
|
||||
var text = e.target.value
|
||||
var index = text.lastIndexOf('@', pos)
|
||||
if (index >= 0) {
|
||||
var stub = text.substring(index + 1, pos).toLowerCase()
|
||||
// Search for nick beginning with stub
|
||||
var nicks = onlineUsers.filter(function(nick) {
|
||||
return nick.toLowerCase().indexOf(stub) == 0
|
||||
})
|
||||
if (nicks.length == 1) {
|
||||
insertAtCursor(nicks[0].substr(stub.length) + " ")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function updateInputSize() {
|
||||
var atBottom = isAtBottom()
|
||||
|
||||
var input = $('#chatinput')
|
||||
input.style.height = 0
|
||||
input.style.height = input.scrollHeight + 'px'
|
||||
document.body.style.marginBottom = $('#footer').offsetHeight + 'px'
|
||||
|
||||
if (atBottom) {
|
||||
window.scrollTo(0, document.body.scrollHeight)
|
||||
}
|
||||
}
|
||||
|
||||
$('#chatinput').oninput = function() {
|
||||
updateInputSize()
|
||||
}
|
||||
|
||||
updateInputSize()
|
||||
|
||||
|
||||
/* sidebar */
|
||||
|
||||
$('#sidebar').onmouseenter = $('#sidebar').ontouchstart = function(e) {
|
||||
$('#sidebar-content').classList.remove('hidden')
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
$('#sidebar').onmouseleave = document.ontouchstart = function() {
|
||||
if (!$('#pin-sidebar').checked) {
|
||||
$('#sidebar-content').classList.add('hidden')
|
||||
}
|
||||
}
|
||||
|
||||
$('#clear-messages').onclick = function() {
|
||||
// Delete children elements
|
||||
var messages = $('#messages')
|
||||
while (messages.firstChild) {
|
||||
messages.removeChild(messages.firstChild)
|
||||
}
|
||||
}
|
||||
|
||||
// Restore settings from localStorage
|
||||
|
||||
if (localStorageGet('pin-sidebar') == 'true') {
|
||||
$('#pin-sidebar').checked = true
|
||||
$('#sidebar-content').classList.remove('hidden')
|
||||
}
|
||||
if (localStorageGet('joined-left') == 'false') {
|
||||
$('#joined-left').checked = false
|
||||
}
|
||||
if (localStorageGet('parse-latex') == 'false') {
|
||||
$('#parse-latex').checked = false
|
||||
}
|
||||
|
||||
$('#pin-sidebar').onchange = function(e) {
|
||||
localStorageSet('pin-sidebar', !!e.target.checked)
|
||||
}
|
||||
$('#joined-left').onchange = function(e) {
|
||||
localStorageSet('joined-left', !!e.target.checked)
|
||||
}
|
||||
$('#parse-latex').onchange = function(e) {
|
||||
localStorageSet('parse-latex', !!e.target.checked)
|
||||
}
|
||||
|
||||
// User list
|
||||
|
||||
var onlineUsers = []
|
||||
var ignoredUsers = []
|
||||
|
||||
function userAdd(nick) {
|
||||
var user = document.createElement('a')
|
||||
user.textContent = nick
|
||||
user.onclick = function(e) {
|
||||
userInvite(nick)
|
||||
}
|
||||
var userLi = document.createElement('li')
|
||||
userLi.appendChild(user)
|
||||
$('#users').appendChild(userLi)
|
||||
onlineUsers.push(nick)
|
||||
}
|
||||
|
||||
function userRemove(nick) {
|
||||
var users = $('#users')
|
||||
var children = users.children
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var user = children[i]
|
||||
if (user.textContent == nick) {
|
||||
users.removeChild(user)
|
||||
}
|
||||
}
|
||||
var index = onlineUsers.indexOf(nick)
|
||||
if (index >= 0) {
|
||||
onlineUsers.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
function usersClear() {
|
||||
var users = $('#users')
|
||||
while (users.firstChild) {
|
||||
users.removeChild(users.firstChild)
|
||||
}
|
||||
onlineUsers.length = 0
|
||||
}
|
||||
|
||||
function userInvite(nick) {
|
||||
send({cmd: 'invite', nick: nick})
|
||||
}
|
||||
|
||||
function userIgnore(nick) {
|
||||
ignoredUsers.push(nick)
|
||||
}
|
||||
|
||||
/* color scheme switcher */
|
||||
|
||||
var schemes = [
|
||||
'android',
|
||||
'atelier-dune',
|
||||
'atelier-forest',
|
||||
'atelier-heath',
|
||||
'atelier-lakeside',
|
||||
'atelier-seaside',
|
||||
'bright',
|
||||
'chalk',
|
||||
'default',
|
||||
'eighties',
|
||||
'greenscreen',
|
||||
'mocha',
|
||||
'monokai',
|
||||
'nese',
|
||||
'ocean',
|
||||
'pop',
|
||||
'railscasts',
|
||||
'solarized',
|
||||
'tomorrow',
|
||||
]
|
||||
|
||||
var currentScheme = 'atelier-dune'
|
||||
|
||||
function setScheme(scheme) {
|
||||
currentScheme = scheme
|
||||
$('#scheme-link').href = "/schemes/" + scheme + ".css"
|
||||
localStorageSet('scheme', scheme)
|
||||
}
|
||||
|
||||
// Add scheme options to dropdown selector
|
||||
schemes.forEach(function(scheme) {
|
||||
var option = document.createElement('option')
|
||||
option.textContent = scheme
|
||||
option.value = scheme
|
||||
$('#scheme-selector').appendChild(option)
|
||||
})
|
||||
|
||||
$('#scheme-selector').onchange = function(e) {
|
||||
setScheme(e.target.value)
|
||||
}
|
||||
|
||||
// Load sidebar configaration values from local storage if available
|
||||
if (localStorageGet('scheme')) {
|
||||
setScheme(localStorageGet('scheme'))
|
||||
}
|
||||
|
||||
$('#scheme-selector').value = currentScheme
|
||||
|
||||
|
||||
/* main */
|
||||
|
||||
if (myChannel == '') {
|
||||
pushMessage({text: frontpage})
|
||||
$('#footer').classList.add('hidden')
|
||||
$('#sidebar').classList.add('hidden')
|
||||
}
|
||||
else {
|
||||
join(myChannel)
|
||||
}
|
68
client/index.html
Normal file
68
client/index.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
|
||||
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
|
||||
<title>hack.chat</title>
|
||||
|
||||
<meta name="application-name" content="Hack.Chat">
|
||||
<meta name="author" content="Marzavec, admin@marzavec.com">
|
||||
<meta name="description" content="A minimal, accountless, anonymous, distraction-free chat application">
|
||||
<meta name="keywords" content="minimal, accountless, anonymous, distraction-free, chat">
|
||||
<meta name="robots" content="index, follow">
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/favicons/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/favicons/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/favicons/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/favicons/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/favicons/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/favicons/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/favicons/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/favicons/apple-touch-icon-152x152.png">
|
||||
<meta name="apple-mobile-web-app-title" content="Rubix">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-196x196.png" sizes="196x196">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-160x160.png" sizes="160x160">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<meta name="msapplication-TileColor" content="#E76049">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-144x144.png">
|
||||
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="katex/katex.min.css">
|
||||
<link id="scheme-link" rel="stylesheet" href="schemes/atelier-dune.css">
|
||||
<script src="katex/katex.min.js"></script>
|
||||
<script src="katex/contrib/auto-render.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<article class="container">
|
||||
<div id="messages" class="messages"></div>
|
||||
</article>
|
||||
<footer id="footer">
|
||||
<div class="container">
|
||||
<form id="chatform" class="messages"><textarea id="chatinput" type="text" autocomplete="off" autofocus></textarea></form>
|
||||
</div>
|
||||
</footer>
|
||||
<nav id="sidebar">
|
||||
<div id="sidebar-content" class="hidden">
|
||||
<p><input id="pin-sidebar" type="checkbox"><label for="pin-sidebar">Pin sidebar</label></p>
|
||||
<h4>Settings</h4>
|
||||
<p><input id="joined-left" type="checkbox" checked><label for="joined-left">Join/left notify</label></p>
|
||||
<p><input id="parse-latex" type="checkbox" checked><label for="parse-latex">Parse LaTeX</label></p>
|
||||
<p><button id="clear-messages">Clear messages</button></p>
|
||||
<h4>Color scheme</h4><select id="scheme-selector"></select>
|
||||
<h4>Users online</h4>
|
||||
<p>(Click user to invite)</p>
|
||||
<ul id="users"></ul>
|
||||
</div>
|
||||
</nav>
|
||||
<script src="client.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
0
client/katex/.gitkeep
Normal file
0
client/katex/.gitkeep
Normal file
219
client/katex/auto-render.js
Normal file
219
client/katex/auto-render.js
Normal file
|
@ -0,0 +1,219 @@
|
|||
(function(e){if("function"==typeof bootstrap)bootstrap("rendermathinelement",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeRenderMathInElement=e}else"undefined"!=typeof window?window.renderMathInElement=e():global.renderMathInElement=e()})(function(){var define,ses,bootstrap,module,exports;
|
||||
return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
/* global katex */
|
||||
|
||||
var splitAtDelimiters = require("./splitAtDelimiters");
|
||||
|
||||
var splitWithDelimiters = function(text, delimiters) {
|
||||
var data = [{type: "text", data: text}];
|
||||
for (var i = 0; i < delimiters.length; i++) {
|
||||
var delimiter = delimiters[i];
|
||||
data = splitAtDelimiters(
|
||||
data, delimiter.left, delimiter.right,
|
||||
delimiter.display || false);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
var renderMathInText = function(text, delimiters) {
|
||||
var data = splitWithDelimiters(text, delimiters);
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (data[i].type === "text") {
|
||||
fragment.appendChild(document.createTextNode(data[i].data));
|
||||
} else {
|
||||
var span = document.createElement("span");
|
||||
var math = data[i].data;
|
||||
try {
|
||||
katex.render(math, span, {
|
||||
displayMode: data[i].display
|
||||
});
|
||||
} catch (e) {
|
||||
if (!(e instanceof katex.ParseError)) {
|
||||
throw e;
|
||||
}
|
||||
console.error(
|
||||
"KaTeX auto-render: Failed to parse `" + data[i].data +
|
||||
"` with ",
|
||||
e
|
||||
);
|
||||
fragment.appendChild(document.createTextNode(data[i].rawData));
|
||||
continue;
|
||||
}
|
||||
fragment.appendChild(span);
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
var renderElem = function(elem, delimiters, ignoredTags) {
|
||||
for (var i = 0; i < elem.childNodes.length; i++) {
|
||||
var childNode = elem.childNodes[i];
|
||||
if (childNode.nodeType === 3) {
|
||||
// Text node
|
||||
var frag = renderMathInText(childNode.textContent, delimiters);
|
||||
i += frag.childNodes.length - 1;
|
||||
elem.replaceChild(frag, childNode);
|
||||
} else if (childNode.nodeType === 1) {
|
||||
// Element node
|
||||
var shouldRender = ignoredTags.indexOf(
|
||||
childNode.nodeName.toLowerCase()) === -1;
|
||||
|
||||
if (shouldRender) {
|
||||
renderElem(childNode, delimiters, ignoredTags);
|
||||
}
|
||||
}
|
||||
// Otherwise, it's something else, and ignore it.
|
||||
}
|
||||
};
|
||||
|
||||
var defaultOptions = {
|
||||
delimiters: [
|
||||
{left: "$$", right: "$$", display: true},
|
||||
{left: "\\[", right: "\\]", display: true},
|
||||
{left: "\\(", right: "\\)", display: false}
|
||||
// LaTeX uses this, but it ruins the display of normal `$` in text:
|
||||
// {left: "$", right: "$", display: false}
|
||||
],
|
||||
|
||||
ignoredTags: [
|
||||
"script", "noscript", "style", "textarea", "pre", "code"
|
||||
]
|
||||
};
|
||||
|
||||
var extend = function(obj) {
|
||||
// Adapted from underscore.js' `_.extend`. See LICENSE.txt for license.
|
||||
var source, prop;
|
||||
for (var i = 1, length = arguments.length; i < length; i++) {
|
||||
source = arguments[i];
|
||||
for (prop in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, prop)) {
|
||||
obj[prop] = source[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
var renderMathInElement = function(elem, options) {
|
||||
if (!elem) {
|
||||
throw new Error("No element provided to render");
|
||||
}
|
||||
|
||||
options = extend({}, defaultOptions, options);
|
||||
|
||||
renderElem(elem, options.delimiters, options.ignoredTags);
|
||||
};
|
||||
|
||||
module.exports = renderMathInElement;
|
||||
|
||||
},{"./splitAtDelimiters":2}],2:[function(require,module,exports){
|
||||
var findEndOfMath = function(delimiter, text, startIndex) {
|
||||
// Adapted from
|
||||
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
|
||||
var index = startIndex;
|
||||
var braceLevel = 0;
|
||||
|
||||
var delimLength = delimiter.length;
|
||||
|
||||
while (index < text.length) {
|
||||
var character = text[index];
|
||||
|
||||
if (braceLevel <= 0 &&
|
||||
text.slice(index, index + delimLength) === delimiter) {
|
||||
return index;
|
||||
} else if (character === "\\") {
|
||||
index++;
|
||||
} else if (character === "{") {
|
||||
braceLevel++;
|
||||
} else if (character === "}") {
|
||||
braceLevel--;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
var splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
|
||||
var finalData = [];
|
||||
|
||||
for (var i = 0; i < startData.length; i++) {
|
||||
if (startData[i].type === "text") {
|
||||
var text = startData[i].data;
|
||||
|
||||
var lookingForLeft = true;
|
||||
var currIndex = 0;
|
||||
var nextIndex;
|
||||
|
||||
nextIndex = text.indexOf(leftDelim);
|
||||
if (nextIndex !== -1) {
|
||||
currIndex = nextIndex;
|
||||
finalData.push({
|
||||
type: "text",
|
||||
data: text.slice(0, currIndex)
|
||||
});
|
||||
lookingForLeft = false;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (lookingForLeft) {
|
||||
nextIndex = text.indexOf(leftDelim, currIndex);
|
||||
if (nextIndex === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
finalData.push({
|
||||
type: "text",
|
||||
data: text.slice(currIndex, nextIndex)
|
||||
});
|
||||
|
||||
currIndex = nextIndex;
|
||||
} else {
|
||||
nextIndex = findEndOfMath(
|
||||
rightDelim,
|
||||
text,
|
||||
currIndex + leftDelim.length);
|
||||
if (nextIndex === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
finalData.push({
|
||||
type: "math",
|
||||
data: text.slice(
|
||||
currIndex + leftDelim.length,
|
||||
nextIndex),
|
||||
rawData: text.slice(
|
||||
currIndex,
|
||||
nextIndex + rightDelim.length),
|
||||
display: display
|
||||
});
|
||||
|
||||
currIndex = nextIndex + rightDelim.length;
|
||||
}
|
||||
|
||||
lookingForLeft = !lookingForLeft;
|
||||
}
|
||||
|
||||
finalData.push({
|
||||
type: "text",
|
||||
data: text.slice(currIndex)
|
||||
});
|
||||
} else {
|
||||
finalData.push(startData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return finalData;
|
||||
};
|
||||
|
||||
module.exports = splitAtDelimiters;
|
||||
|
||||
},{}]},{},[1])
|
||||
(1)
|
||||
});
|
||||
;
|
1
client/katex/contrib/auto-render.min.js
vendored
Normal file
1
client/katex/contrib/auto-render.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
(function(e){if("function"==typeof bootstrap)bootstrap("rendermathinelement",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeRenderMathInElement=e}else"undefined"!=typeof window?window.renderMathInElement=e():global.renderMathInElement=e()})(function(){var e,t,r,n,a;return function i(e,t,r){function n(o,l){if(!t[o]){if(!e[o]){var f=typeof require=="function"&&require;if(!l&&f)return f(o,!0);if(a)return a(o,!0);throw new Error("Cannot find module '"+o+"'")}var s=t[o]={exports:{}};e[o][0].call(s.exports,function(t){var r=e[o][1][t];return n(r?r:t)},s,s.exports,i,e,t,r)}return t[o].exports}var a=typeof require=="function"&&require;for(var o=0;o<r.length;o++)n(r[o]);return n}({1:[function(e,t,r){var n=e("./splitAtDelimiters");var a=function(e,t){var r=[{type:"text",data:e}];for(var a=0;a<t.length;a++){var i=t[a];r=n(r,i.left,i.right,i.display||false)}return r};var i=function(e,t){var r=a(e,t);var n=document.createDocumentFragment();for(var i=0;i<r.length;i++){if(r[i].type==="text"){n.appendChild(document.createTextNode(r[i].data))}else{var o=document.createElement("span");var l=r[i].data;try{katex.render(l,o,{displayMode:r[i].display})}catch(f){if(!(f instanceof katex.ParseError)){throw f}console.error("KaTeX auto-render: Failed to parse `"+r[i].data+"` with ",f);n.appendChild(document.createTextNode(r[i].rawData));continue}n.appendChild(o)}}return n};var o=function(e,t,r){for(var n=0;n<e.childNodes.length;n++){var a=e.childNodes[n];if(a.nodeType===3){var l=i(a.textContent,t);n+=l.childNodes.length-1;e.replaceChild(l,a)}else if(a.nodeType===1){var f=r.indexOf(a.nodeName.toLowerCase())===-1;if(f){o(a,t,r)}}}};var l={delimiters:[{left:"$$",right:"$$",display:true},{left:"\\[",right:"\\]",display:true},{left:"\\(",right:"\\)",display:false}],ignoredTags:["script","noscript","style","textarea","pre","code"]};var f=function(e){var t,r;for(var n=1,a=arguments.length;n<a;n++){t=arguments[n];for(r in t){if(Object.prototype.hasOwnProperty.call(t,r)){e[r]=t[r]}}}return e};var s=function(e,t){if(!e){throw new Error("No element provided to render")}t=f({},l,t);o(e,t.delimiters,t.ignoredTags)};t.exports=s},{"./splitAtDelimiters":2}],2:[function(e,t,r){var n=function(e,t,r){var n=r;var a=0;var i=e.length;while(n<t.length){var o=t[n];if(a<=0&&t.slice(n,n+i)===e){return n}else if(o==="\\"){n++}else if(o==="{"){a++}else if(o==="}"){a--}n++}return-1};var a=function(e,t,r,a){var i=[];for(var o=0;o<e.length;o++){if(e[o].type==="text"){var l=e[o].data;var f=true;var s=0;var d;d=l.indexOf(t);if(d!==-1){s=d;i.push({type:"text",data:l.slice(0,s)});f=false}while(true){if(f){d=l.indexOf(t,s);if(d===-1){break}i.push({type:"text",data:l.slice(s,d)});s=d}else{d=n(r,l,s+t.length);if(d===-1){break}i.push({type:"math",data:l.slice(s+t.length,d),rawData:l.slice(s,d+r.length),display:a});s=d+r.length}f=!f}i.push({type:"text",data:l.slice(s)})}else{i.push(e[o])}}return i};t.exports=a},{}]},{},[1])(1)});
|
BIN
client/katex/fonts/KaTeX_AMS-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_AMS-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_AMS-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_AMS-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_AMS-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_AMS-Regular.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_AMS-Regular.woff2
Normal file
BIN
client/katex/fonts/KaTeX_AMS-Regular.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Caligraphic-Bold.eot
Normal file
BIN
client/katex/fonts/KaTeX_Caligraphic-Bold.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Caligraphic-Bold.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Caligraphic-Bold.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Caligraphic-Bold.woff
Normal file
BIN
client/katex/fonts/KaTeX_Caligraphic-Bold.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Caligraphic-Bold.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Caligraphic-Bold.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Caligraphic-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_Caligraphic-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Caligraphic-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Caligraphic-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Caligraphic-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_Caligraphic-Regular.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Caligraphic-Regular.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Caligraphic-Regular.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Fraktur-Bold.eot
Normal file
BIN
client/katex/fonts/KaTeX_Fraktur-Bold.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Fraktur-Bold.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Fraktur-Bold.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Fraktur-Bold.woff
Normal file
BIN
client/katex/fonts/KaTeX_Fraktur-Bold.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Fraktur-Bold.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Fraktur-Bold.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Fraktur-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_Fraktur-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Fraktur-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Fraktur-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Fraktur-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_Fraktur-Regular.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Fraktur-Regular.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Fraktur-Regular.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Bold.eot
Normal file
BIN
client/katex/fonts/KaTeX_Main-Bold.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Bold.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Main-Bold.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Bold.woff
Normal file
BIN
client/katex/fonts/KaTeX_Main-Bold.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Bold.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Main-Bold.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Italic.eot
Normal file
BIN
client/katex/fonts/KaTeX_Main-Italic.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Italic.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Main-Italic.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Italic.woff
Normal file
BIN
client/katex/fonts/KaTeX_Main-Italic.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Italic.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Main-Italic.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_Main-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Main-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_Main-Regular.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Main-Regular.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Main-Regular.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-BoldItalic.eot
Normal file
BIN
client/katex/fonts/KaTeX_Math-BoldItalic.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-BoldItalic.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Math-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-BoldItalic.woff
Normal file
BIN
client/katex/fonts/KaTeX_Math-BoldItalic.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-BoldItalic.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Math-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-Italic.eot
Normal file
BIN
client/katex/fonts/KaTeX_Math-Italic.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-Italic.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Math-Italic.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-Italic.woff
Normal file
BIN
client/katex/fonts/KaTeX_Math-Italic.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-Italic.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Math-Italic.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_Math-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Math-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_Math-Regular.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Math-Regular.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Math-Regular.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Bold.eot
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Bold.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Bold.ttf
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Bold.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Bold.woff
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Bold.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Bold.woff2
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Bold.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Italic.eot
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Italic.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Italic.ttf
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Italic.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Italic.woff
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Italic.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Italic.woff2
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Italic.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Regular.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_SansSerif-Regular.woff2
Normal file
BIN
client/katex/fonts/KaTeX_SansSerif-Regular.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Script-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_Script-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Script-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Script-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Script-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_Script-Regular.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Script-Regular.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Script-Regular.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size1-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_Size1-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size1-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Size1-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size1-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_Size1-Regular.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size1-Regular.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Size1-Regular.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size2-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_Size2-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size2-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Size2-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size2-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_Size2-Regular.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size2-Regular.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Size2-Regular.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size3-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_Size3-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size3-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Size3-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size3-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_Size3-Regular.woff
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size3-Regular.woff2
Normal file
BIN
client/katex/fonts/KaTeX_Size3-Regular.woff2
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size4-Regular.eot
Normal file
BIN
client/katex/fonts/KaTeX_Size4-Regular.eot
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size4-Regular.ttf
Normal file
BIN
client/katex/fonts/KaTeX_Size4-Regular.ttf
Normal file
Binary file not shown.
BIN
client/katex/fonts/KaTeX_Size4-Regular.woff
Normal file
BIN
client/katex/fonts/KaTeX_Size4-Regular.woff
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user