Cleanup
This commit is contained in:
parent
6e8816c467
commit
82a498a4ff
97
README.md
97
README.md
|
@ -5,25 +5,25 @@
|
|||
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.md)
|
||||
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/753ef40cec1747c2b5025f834635375b)](https://www.codacy.com/gh/Hexagon/cryptalk/dashboard?utm_source=github.com&utm_medium=referral&utm_content=Hexagon/cryptalk&utm_campaign=Badge_Grade)
|
||||
|
||||
# Cryptalk
|
||||
|
||||
Cyptalk is a HTML5/Node.js based, client side (E2EE) encrypted instant chat
|
||||
|
||||
## Features
|
||||
|
||||
Features
|
||||
========
|
||||
* Client side AES-256-CBC encryption/decryption (the server is just a messenger)
|
||||
* 256 bit key derived from your passphrase using PBKDF2
|
||||
* Messages torched after a configurable delay, default is 600s.
|
||||
* Simple setup using npm, Docker or Heroku
|
||||
* Notification sounds (mutable)
|
||||
* Native popup notifications
|
||||
* Configurable page title
|
||||
* Nicknames, optional.
|
||||
* Quick-links using http://server/#Room:Passphrase, optional and insecure
|
||||
|
||||
* Client side AES-256-CBC encryption/decryption (the server is just a messenger)
|
||||
* 256 bit key derived from your passphrase using PBKDF2
|
||||
* Messages torched after a configurable delay, default is 600s.
|
||||
* Simple setup using npm, Docker or Heroku
|
||||
* Notification sounds (mutable)
|
||||
* Native popup notifications
|
||||
* Configurable page title
|
||||
* Nicknames, optional.
|
||||
* Quick-links using http://server/#Room:Passphrase, optional and insecure
|
||||
## Installing
|
||||
|
||||
|
||||
Docker setup
|
||||
========
|
||||
### Docker setup
|
||||
|
||||
To run latest cryptalk with docker, exposed on host port 80, simply run the following command to pull it from docker hub
|
||||
|
||||
|
@ -31,18 +31,13 @@ To run latest cryptalk with docker, exposed on host port 80, simply run the foll
|
|||
sudo docker run -d --restart=always -p 80:8080 hexagon/cryptalk
|
||||
```
|
||||
|
||||
|
||||
Heroku setup
|
||||
========
|
||||
### Heroku setup
|
||||
|
||||
Click the button below
|
||||
|
||||
[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy?template=https://github.com/hexagon/cryptalk)
|
||||
|
||||
|
||||
|
||||
Docker setup without using docker hub
|
||||
========
|
||||
### Docker setup without using docker hub
|
||||
|
||||
Clone this repo, enter the new directory.
|
||||
|
||||
|
@ -60,10 +55,7 @@ Browse to ```http://<ip-of-server>/```
|
|||
|
||||
Done!
|
||||
|
||||
|
||||
|
||||
npm setup
|
||||
========
|
||||
### npm setup
|
||||
|
||||
Install node.js, exact procedure is dependant on platform and distribution.
|
||||
|
||||
|
@ -82,36 +74,7 @@ Browse to ```http://localhost:8080```
|
|||
|
||||
Done!
|
||||
|
||||
|
||||
|
||||
Developer setup
|
||||
========
|
||||
|
||||
Install node.js (development require >=12.0), exact procedure is dependant on platform and distribution.
|
||||
|
||||
Clone this repo
|
||||
```bash
|
||||
git clone https://github.com/Hexagon/cryptalk.git
|
||||
cd cryptalk
|
||||
```
|
||||
|
||||
Pull dependencies from npm
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
Start server
|
||||
```bash
|
||||
npn run start
|
||||
```
|
||||
|
||||
Browse to ```http://localhost:8080```
|
||||
|
||||
To work on the JavaScript, edit the code in ```client/source/```. To test the changes, first run ```npm run build``` to lint, build and minify the code. Then restart the server.
|
||||
|
||||
|
||||
Usage
|
||||
========
|
||||
## Usage
|
||||
|
||||
```
|
||||
|
||||
|
@ -148,3 +111,27 @@ to prevent browsers from keeping history or cache.
|
|||
|
||||
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
Install node.js (development require >=12.0), exact procedure is dependant on platform and distribution.
|
||||
|
||||
Clone this repo
|
||||
```bash
|
||||
git clone https://github.com/Hexagon/cryptalk.git
|
||||
cd cryptalk
|
||||
```
|
||||
|
||||
Pull dependencies from npm
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
Start server
|
||||
```bash
|
||||
npn run start
|
||||
```
|
||||
|
||||
Browse to ```http://localhost:8080```
|
||||
|
||||
To work on the JavaScript, edit the code in ```client/source/```. To test the changes, first run ```npm run build``` to lint, build and minify the code. Then restart the server.
|
||||
|
|
|
@ -1,32 +1,31 @@
|
|||
/*------------------------------------*\
|
||||
GENERIC
|
||||
\*------------------------------------*/
|
||||
html {
|
||||
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
||||
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
||||
box-sizing: border-box; /* Opera/IE 8+ */
|
||||
}
|
||||
|
||||
*, *:before, *:after {
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
|
||||
font-family: monospace, 'Courier New';
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
body, html {
|
||||
body,
|
||||
html {
|
||||
min-height: 100%;
|
||||
min-width: 600px;
|
||||
background-color: #181A1D;
|
||||
background-color: #181a1d;
|
||||
overflow: hidden;
|
||||
padding: 0px;
|
||||
margin:0px;
|
||||
color: #00DD00;
|
||||
margin: 0px;
|
||||
color: #00dd00;
|
||||
}
|
||||
|
||||
.good { color: #99FF99; }
|
||||
.good { color: #99ff99; }
|
||||
.bad { color: #ff7777; }
|
||||
.info { color: #99FFFF; }
|
||||
.info { color: #99ffff; }
|
||||
.neutral { color: #eeeeee; }
|
||||
|
||||
/*------------------------------------*\
|
||||
|
@ -38,8 +37,8 @@ body, html {
|
|||
bottom: 40px;
|
||||
position: absolute;
|
||||
list-style-type: none;
|
||||
padding:0;
|
||||
margin:0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Messages */
|
||||
|
@ -50,7 +49,7 @@ body, html {
|
|||
}
|
||||
|
||||
#chat li .timestamp {
|
||||
color: #A0A00A;
|
||||
color: #a0a00a;
|
||||
}
|
||||
|
||||
/* Message types */
|
||||
|
@ -58,24 +57,27 @@ body, html {
|
|||
#chat i {
|
||||
font-style: normal;
|
||||
}
|
||||
#chat i.motd { color: #99FF99; display:inline-block; line-height: 12px !important; }
|
||||
#chat i.motd {
|
||||
color: #99ff99;
|
||||
display:inline-block;
|
||||
line-height: 12px !important;
|
||||
}
|
||||
#chat i.info { color: #999999; }
|
||||
#chat i.server { color: #99FFFF; }
|
||||
#chat i.server { color: #99ffff; }
|
||||
#chat i.error { color: #ff7777; }
|
||||
#chat i.message { color: #eeeeee; }
|
||||
#chat i.nick { color: #99FF99; }
|
||||
#chat i.nick { color: #99ff99; }
|
||||
#chat i.fatal { color: #ff7777; }
|
||||
|
||||
/*------------------------------------*\
|
||||
INPUT & LOADER
|
||||
\*------------------------------------*/
|
||||
#input_wrapper {
|
||||
right:0;
|
||||
bottom:0;
|
||||
left:0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
|
||||
height:30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#input,
|
||||
|
@ -90,26 +92,35 @@ body, html {
|
|||
|
||||
padding: 5px 5px 5px 15px;
|
||||
|
||||
color: #FFFFFF;
|
||||
background-color:#272A2E;
|
||||
color: #ffffff;
|
||||
background-color:#272a2e;
|
||||
height:30px;
|
||||
|
||||
border-top: 2px solid #153315;
|
||||
}
|
||||
|
||||
#input { z-index: 1; }
|
||||
#loader { z-index: 0; line-height: 20px; font-size: 14px; font-weight: 100; font-family: tahoma;}
|
||||
#input {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#loader {
|
||||
z-index: 0;
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 100;
|
||||
font-family: tahoma;
|
||||
}
|
||||
|
||||
.loading #loader {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/*------------------------------------*\
|
||||
SPINNER
|
||||
\*------------------------------------*/
|
||||
.loading #loader { z-index: 2; }
|
||||
.loading #loader span {
|
||||
margin-left:-2px;
|
||||
-webkit-animation: rotation 1s infinite linear;
|
||||
}
|
||||
|
||||
@-webkit-keyframes rotation {
|
||||
from {-webkit-transform: rotate(0deg);}
|
||||
to {-webkit-transform: rotate(359deg);}
|
||||
from { -webkit-transform: rotate(0deg); }
|
||||
to { -webkit-transform: rotate(359deg); }
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -9,8 +9,7 @@ for(var k in proto) ElementArray.prototype[k] = proto[k];
|
|||
// Create to actual dollar function
|
||||
function Dollar (selector) {
|
||||
|
||||
var match,
|
||||
matches = new ElementArray();
|
||||
let matches = new ElementArray();
|
||||
|
||||
if (selector !== undefined) {
|
||||
if (selector === document) {
|
||||
|
@ -18,7 +17,8 @@ function Dollar (selector) {
|
|||
} else if (selector === window) {
|
||||
matches.push(window);
|
||||
} else {
|
||||
if ((match = document.querySelectorAll(selector))) {
|
||||
let match = document.querySelectorAll(selector);
|
||||
if (match) {
|
||||
for( var i=0; i < match.length; i++) {
|
||||
matches.push(match[i]);
|
||||
}
|
||||
|
|
|
@ -142,7 +142,8 @@ export default function(mediator,settings,templates, sounds) {
|
|||
// If the active element is not the input, focus on it and exit the function.
|
||||
// Ignore this when ctrl and/or alt is pressed!
|
||||
if (!e.ctrlKey && !e.altKey && components.input[0] !== $.activeElement()) {
|
||||
return components.input.focus();
|
||||
components.input.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Return immediatly if the buffer is empty or if the hit key was not <enter>
|
||||
|
@ -162,7 +163,8 @@ export default function(mediator,settings,templates, sounds) {
|
|||
payload,
|
||||
function(retvals, recipients) {
|
||||
if(!recipients) {
|
||||
return commands.post('error', $.template(templates.messages.unrecognized_command, { commandName: command }));
|
||||
commands.post('error', $.template(templates.messages.unrecognized_command, { commandName: command }));
|
||||
return;
|
||||
} else {
|
||||
commands.clearInput();
|
||||
}
|
||||
|
|
|
@ -155,9 +155,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz",
|
||||
"integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w=="
|
||||
"version": "16.11.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz",
|
||||
"integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw=="
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.17.1",
|
||||
|
@ -756,9 +756,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-visitor-keys": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz",
|
||||
"integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz",
|
||||
"integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -954,9 +954,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/flatted": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz",
|
||||
"integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==",
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz",
|
||||
"integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
|
@ -1282,19 +1282,19 @@
|
|||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.50.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz",
|
||||
"integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==",
|
||||
"version": "1.51.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
|
||||
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.33",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz",
|
||||
"integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==",
|
||||
"version": "2.1.34",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
|
||||
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.50.0"
|
||||
"mime-db": "1.51.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
|
@ -1776,9 +1776,9 @@
|
|||
"integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ=="
|
||||
},
|
||||
"node_modules/socket.io": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.3.1.tgz",
|
||||
"integrity": "sha512-HC5w5Olv2XZ0XJ4gOLGzzHEuOCfj3G0SmoW3jLHYYh34EVsIr3EkW9h6kgfW+K3TFEcmYy8JcPWe//KUkBp5jA==",
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.3.2.tgz",
|
||||
"integrity": "sha512-6S5tV4jcY6dbZ/lLzD6EkvNWI3s81JO6ABP/EpvOlK1NPOcIj3AS4khi6xXw6JlZCASq82HQV4SapfmVMMl2dg==",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
|
@ -2138,9 +2138,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz",
|
||||
"integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w=="
|
||||
"version": "16.11.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz",
|
||||
"integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw=="
|
||||
},
|
||||
"@types/resolve": {
|
||||
"version": "1.17.1",
|
||||
|
@ -2580,9 +2580,9 @@
|
|||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz",
|
||||
"integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz",
|
||||
"integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==",
|
||||
"dev": true
|
||||
},
|
||||
"espree": {
|
||||
|
@ -2735,9 +2735,9 @@
|
|||
}
|
||||
},
|
||||
"flatted": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz",
|
||||
"integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==",
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz",
|
||||
"integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
|
||||
"dev": true
|
||||
},
|
||||
"fs.realpath": {
|
||||
|
@ -2984,16 +2984,16 @@
|
|||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.50.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz",
|
||||
"integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A=="
|
||||
"version": "1.51.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
|
||||
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.33",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz",
|
||||
"integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==",
|
||||
"version": "2.1.34",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
|
||||
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
|
||||
"requires": {
|
||||
"mime-db": "1.50.0"
|
||||
"mime-db": "1.51.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
|
@ -3363,9 +3363,9 @@
|
|||
"integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ=="
|
||||
},
|
||||
"socket.io": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.3.1.tgz",
|
||||
"integrity": "sha512-HC5w5Olv2XZ0XJ4gOLGzzHEuOCfj3G0SmoW3jLHYYh34EVsIr3EkW9h6kgfW+K3TFEcmYy8JcPWe//KUkBp5jA==",
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.3.2.tgz",
|
||||
"integrity": "sha512-6S5tV4jcY6dbZ/lLzD6EkvNWI3s81JO6ABP/EpvOlK1NPOcIj3AS4khi6xXw6JlZCASq82HQV4SapfmVMMl2dg==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
|
|
Loading…
Reference in New Issue