Compare commits
1 Commits
production
...
jsonp
Author | SHA1 | Date | |
---|---|---|---|
|
467f9a53b2 |
42
README.md
42
README.md
@@ -46,16 +46,6 @@ STDOUT. Check the README there for more details and usages.
|
|||||||
* `storage` - storage options (see below)
|
* `storage` - storage options (see below)
|
||||||
* `logging` - logging preferences
|
* `logging` - logging preferences
|
||||||
* `keyGenerator` - key generator options (see below)
|
* `keyGenerator` - key generator options (see below)
|
||||||
* `rateLimits` - settings for rate limiting (see below)
|
|
||||||
|
|
||||||
## Rate Limiting
|
|
||||||
|
|
||||||
When present, the `rateLimits` option enables built-in rate limiting courtesy
|
|
||||||
of `connect-ratelimit`. Any of the options supported by that library can be
|
|
||||||
used and set in `config.json`.
|
|
||||||
|
|
||||||
See the README for [connect-ratelimit](https://github.com/dharmafly/connect-ratelimit)
|
|
||||||
for more information!
|
|
||||||
|
|
||||||
## Key Generation
|
## Key Generation
|
||||||
|
|
||||||
@@ -101,8 +91,7 @@ Where `path` represents where you want the files stored
|
|||||||
|
|
||||||
### Redis
|
### Redis
|
||||||
|
|
||||||
To use redis storage you must install the `redis` package in npm, and have
|
To use redis storage you must install the redis package in npm
|
||||||
`redis-server` running on the machine.
|
|
||||||
|
|
||||||
`npm install redis`
|
`npm install redis`
|
||||||
|
|
||||||
@@ -123,35 +112,6 @@ or post.
|
|||||||
|
|
||||||
All of which are optional except `type` with very logical default values.
|
All of which are optional except `type` with very logical default values.
|
||||||
|
|
||||||
If your Redis server is configured for password authentification, use the `password` field.
|
|
||||||
|
|
||||||
### Postgres
|
|
||||||
|
|
||||||
To use postgres storage you must install the `pg` package in npm
|
|
||||||
|
|
||||||
`npm install pg`
|
|
||||||
|
|
||||||
Once you've done that, your config section should look like:
|
|
||||||
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"type": "postgres",
|
|
||||||
"connectionUrl": "postgres://user:password@host:5432/database"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also just set the environment variable for `DATABASE_URL` to your database connection url.
|
|
||||||
|
|
||||||
You will have to manually add a table to your postgres database:
|
|
||||||
|
|
||||||
`create table entries (id serial primary key, key varchar(255) not null, value text not null, expiration int, unique(key));`
|
|
||||||
|
|
||||||
You can also set an `expire` option to the number of seconds to expire keys in.
|
|
||||||
This is off by default, but will constantly kick back expirations on each view
|
|
||||||
or post.
|
|
||||||
|
|
||||||
All of which are optional except `type` with very logical default values.
|
|
||||||
|
|
||||||
### Memcached
|
### Memcached
|
||||||
|
|
||||||
To use memcached storage you must install the `memcache` package via npm
|
To use memcached storage you must install the `memcache` package via npm
|
||||||
|
4
about.md
4
about.md
@@ -15,7 +15,7 @@ To make a new entry, click "New" (or type 'control + n')
|
|||||||
|
|
||||||
## From the Console
|
## From the Console
|
||||||
|
|
||||||
Most of the time I want to show you some text, it's coming from my current
|
Most of the time I want to show you some text, its coming from my current
|
||||||
console session. We should make it really easy to take code from the console
|
console session. We should make it really easy to take code from the console
|
||||||
and send it to people.
|
and send it to people.
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ pastes.
|
|||||||
|
|
||||||
## Open Source
|
## Open Source
|
||||||
|
|
||||||
Haste can easily be installed behind your network, and it's all open source!
|
Haste can easily be installed behind your network, and its all open source!
|
||||||
|
|
||||||
* [haste-client](https://github.com/seejohnrun/haste-client)
|
* [haste-client](https://github.com/seejohnrun/haste-client)
|
||||||
* [haste-server](https://github.com/seejohnrun/haste-server)
|
* [haste-server](https://github.com/seejohnrun/haste-server)
|
||||||
|
14
config.js
14
config.js
@@ -23,17 +23,11 @@
|
|||||||
"type": "phonetic"
|
"type": "phonetic"
|
||||||
},
|
},
|
||||||
|
|
||||||
"rateLimits": {
|
|
||||||
"categories": {
|
|
||||||
"normal": {
|
|
||||||
"totalRequests": 500,
|
|
||||||
"every": 60000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"storage": {
|
"storage": {
|
||||||
"type": "postgres",
|
"type": "redis",
|
||||||
|
"host": "0.0.0.0",
|
||||||
|
"port": 6379,
|
||||||
|
"db": 2,
|
||||||
"expire": 2592000
|
"expire": 2592000
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
var winston = require('winston');
|
var winston = require('winston');
|
||||||
var Busboy = require('busboy');
|
|
||||||
|
|
||||||
// For handling serving stored documents
|
// For handling serving stored documents
|
||||||
|
|
||||||
@@ -16,12 +15,23 @@ var DocumentHandler = function(options) {
|
|||||||
DocumentHandler.defaultKeyLength = 10;
|
DocumentHandler.defaultKeyLength = 10;
|
||||||
|
|
||||||
// Handle retrieving a document
|
// Handle retrieving a document
|
||||||
DocumentHandler.prototype.handleGet = function(key, response, skipExpire) {
|
DocumentHandler.prototype.handleGet = function(key, callback, response, skipExpire) {
|
||||||
this.store.get(key, function(ret) {
|
this.store.get(key, function(ret) {
|
||||||
if (ret) {
|
if (ret) {
|
||||||
winston.verbose('retrieved document', { key: key });
|
winston.verbose('retrieved document', { key: key });
|
||||||
|
var responseData = JSON.stringify({ data: ret, key: key });
|
||||||
|
if (callback) {
|
||||||
|
if (callback.match(/^[a-z0-9]+$/i)) {
|
||||||
|
response.writeHead(200, { 'content-type': 'application/javascript' });
|
||||||
|
response.end(callback + '(' + responseData + ');');
|
||||||
|
} else {
|
||||||
|
response.writeHead(400, { 'content-type': 'application/json' });
|
||||||
|
response.end(JSON.stringify({ message: 'invalid callback function name' }));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
response.writeHead(200, { 'content-type': 'application/json' });
|
response.writeHead(200, { 'content-type': 'application/json' });
|
||||||
response.end(JSON.stringify({ data: ret, key: key }));
|
response.end(responseData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
winston.warn('document not found', { key: key });
|
winston.warn('document not found', { key: key });
|
||||||
@@ -52,10 +62,11 @@ DocumentHandler.prototype.handlePost = function (request, response) {
|
|||||||
var _this = this;
|
var _this = this;
|
||||||
var buffer = '';
|
var buffer = '';
|
||||||
var cancelled = false;
|
var cancelled = false;
|
||||||
|
request.on('data', function(data) {
|
||||||
// What to do when done
|
if (!buffer) {
|
||||||
var onSuccess = function () {
|
response.writeHead(200, { 'content-type': 'application/json' });
|
||||||
// Check length
|
}
|
||||||
|
buffer += data.toString();
|
||||||
if (_this.maxLength && buffer.length > _this.maxLength) {
|
if (_this.maxLength && buffer.length > _this.maxLength) {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
winston.warn('document >maxLength', { maxLength: _this.maxLength });
|
winston.warn('document >maxLength', { maxLength: _this.maxLength });
|
||||||
@@ -63,15 +74,14 @@ DocumentHandler.prototype.handlePost = function (request, response) {
|
|||||||
response.end(
|
response.end(
|
||||||
JSON.stringify({ message: 'Document exceeds maximum length.' })
|
JSON.stringify({ message: 'Document exceeds maximum length.' })
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// And then save if we should
|
});
|
||||||
|
request.on('end', function(end) {
|
||||||
|
if (cancelled) return;
|
||||||
_this.chooseKey(function(key) {
|
_this.chooseKey(function(key) {
|
||||||
_this.store.set(key, buffer, function(res) {
|
_this.store.set(key, buffer, function(res) {
|
||||||
if (res) {
|
if (res) {
|
||||||
var ip = request.headers['x-forwarded-for'] || request.ip;
|
winston.verbose('added document', { key: key });
|
||||||
winston.verbose('added document', { key: key, ip: ip });
|
|
||||||
response.writeHead(200, { 'content-type': 'application/json' });
|
|
||||||
response.end(JSON.stringify({ key: key }));
|
response.end(JSON.stringify({ key: key }));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -81,37 +91,12 @@ DocumentHandler.prototype.handlePost = function (request, response) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
// If we should, parse a form to grab the data
|
|
||||||
var ct = request.headers['content-type'];
|
|
||||||
if (ct && ct.split(';')[0] === 'multipart/form-data') {
|
|
||||||
var busboy = new Busboy({ headers: request.headers });
|
|
||||||
busboy.on('field', function (fieldname, val) {
|
|
||||||
if (fieldname === 'data') {
|
|
||||||
buffer = val;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
busboy.on('finish', function () {
|
|
||||||
onSuccess();
|
|
||||||
});
|
|
||||||
request.pipe(busboy);
|
|
||||||
// Otherwise, use our own and just grab flat data from POST body
|
|
||||||
} else {
|
|
||||||
request.on('data', function (data) {
|
|
||||||
buffer += data.toString();
|
|
||||||
});
|
|
||||||
request.on('end', function () {
|
|
||||||
if (cancelled) { return; }
|
|
||||||
onSuccess();
|
|
||||||
});
|
});
|
||||||
request.on('error', function(error) {
|
request.on('error', function(error) {
|
||||||
winston.error('connection error: ' + error.message);
|
winston.error('connection error: ' + error.message);
|
||||||
response.writeHead(500, { 'content-type': 'application/json' });
|
response.writeHead(500, { 'content-type': 'application/json' });
|
||||||
response.end(JSON.stringify({ message: 'Connection error.' }));
|
response.end(JSON.stringify({ message: 'Connection error.' }));
|
||||||
cancelled = true;
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Keep choosing keys until one isn't taken
|
// Keep choosing keys until one isn't taken
|
||||||
|
@@ -1,79 +0,0 @@
|
|||||||
/*global require,module,process*/
|
|
||||||
|
|
||||||
var postgres = require('pg');
|
|
||||||
var winston = require('winston');
|
|
||||||
|
|
||||||
// create table entries (id serial primary key, key varchar(255) not null, value text not null, expiration int, unique(key));
|
|
||||||
|
|
||||||
// A postgres document store
|
|
||||||
var PostgresDocumentStore = function (options) {
|
|
||||||
this.expireJS = options.expire;
|
|
||||||
this.connectionUrl = process.env.DATABASE_URL || options.connectionUrl;
|
|
||||||
};
|
|
||||||
|
|
||||||
PostgresDocumentStore.prototype = {
|
|
||||||
|
|
||||||
// Set a given key
|
|
||||||
set: function (key, data, callback, skipExpire) {
|
|
||||||
var now = Math.floor(new Date().getTime() / 1000);
|
|
||||||
var that = this;
|
|
||||||
this.safeConnect(function (err, client, done) {
|
|
||||||
if (err) { return callback(false); }
|
|
||||||
client.query('INSERT INTO entries (key, value, expiration) VALUES ($1, $2, $3)', [
|
|
||||||
key,
|
|
||||||
data,
|
|
||||||
that.expireJS && !skipExpire ? that.expireJS + now : null
|
|
||||||
], function (err, result) {
|
|
||||||
if (err) {
|
|
||||||
winston.error('error persisting value to postgres', { error: err });
|
|
||||||
return callback(false);
|
|
||||||
}
|
|
||||||
callback(true);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Get a given key's data
|
|
||||||
get: function (key, callback, skipExpire) {
|
|
||||||
var now = Math.floor(new Date().getTime() / 1000);
|
|
||||||
var that = this;
|
|
||||||
this.safeConnect(function (err, client, done) {
|
|
||||||
if (err) { return callback(false); }
|
|
||||||
client.query('SELECT id,value,expiration from entries where KEY = $1 and (expiration IS NULL or expiration > $2)', [key, now], function (err, result) {
|
|
||||||
if (err) {
|
|
||||||
winston.error('error retrieving value from postgres', { error: err });
|
|
||||||
return callback(false);
|
|
||||||
}
|
|
||||||
callback(result.rows.length ? result.rows[0].value : false);
|
|
||||||
if (result.rows.length && that.expireJS && !skipExpire) {
|
|
||||||
client.query('UPDATE entries SET expiration = $1 WHERE ID = $2', [
|
|
||||||
that.expireJS + now,
|
|
||||||
result.rows[0].id
|
|
||||||
], function (err, result) {
|
|
||||||
if (!err) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// A connection wrapper
|
|
||||||
safeConnect: function (callback) {
|
|
||||||
postgres.connect(this.connectionUrl, function (err, client, done) {
|
|
||||||
if (err) {
|
|
||||||
winston.error('error connecting to postgres', { error: err });
|
|
||||||
callback(err);
|
|
||||||
} else {
|
|
||||||
callback(undefined, client, done);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = PostgresDocumentStore;
|
|
@@ -25,10 +25,6 @@ RedisDocumentStore.connect = function(options) {
|
|||||||
var port = options.port || 6379;
|
var port = options.port || 6379;
|
||||||
var index = options.db || 0;
|
var index = options.db || 0;
|
||||||
RedisDocumentStore.client = redis.createClient(port, host);
|
RedisDocumentStore.client = redis.createClient(port, host);
|
||||||
// authenticate if password is provided
|
|
||||||
if (options.password) {
|
|
||||||
RedisDocumentStore.client.auth(options.password);
|
|
||||||
}
|
|
||||||
RedisDocumentStore.client.select(index, function(err, reply) {
|
RedisDocumentStore.client.select(index, function(err, reply) {
|
||||||
if (err) {
|
if (err) {
|
||||||
winston.error(
|
winston.error(
|
||||||
|
@@ -6,14 +6,13 @@ var PhoneticKeyGenerator = function(options) {
|
|||||||
// Generate a phonetic key
|
// Generate a phonetic key
|
||||||
PhoneticKeyGenerator.prototype.createKey = function(keyLength) {
|
PhoneticKeyGenerator.prototype.createKey = function(keyLength) {
|
||||||
var text = '';
|
var text = '';
|
||||||
var start = Math.round(Math.random());
|
|
||||||
for (var i = 0; i < keyLength; i++) {
|
for (var i = 0; i < keyLength; i++) {
|
||||||
text += (i % 2 == start) ? this.randConsonant() : this.randVowel();
|
text += (i % 2 == 0) ? this.randConsonant() : this.randVowel();
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
PhoneticKeyGenerator.consonants = 'bcdfghjklmnpqrstvwxyz';
|
PhoneticKeyGenerator.consonants = 'bcdfghjklmnpqrstvwxy';
|
||||||
PhoneticKeyGenerator.vowels = 'aeiou';
|
PhoneticKeyGenerator.vowels = 'aeiou';
|
||||||
|
|
||||||
// Get an random vowel
|
// Get an random vowel
|
||||||
|
14
package.json
14
package.json
@@ -14,14 +14,11 @@
|
|||||||
},
|
},
|
||||||
"main": "haste",
|
"main": "haste",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"connect-ratelimit": "0.0.7",
|
|
||||||
"connect-route": "0.1.5",
|
|
||||||
"connect": "3.4.1",
|
|
||||||
"st": "1.1.0",
|
|
||||||
"winston": "0.6.2",
|
"winston": "0.6.2",
|
||||||
"uglify-js": "1.3.3",
|
"connect": "1.9.2",
|
||||||
"busboy": "0.2.4",
|
"redis-url": "0.1.0",
|
||||||
"pg": "4.1.1"
|
"redis": "0.8.1",
|
||||||
|
"uglify-js": "1.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "*",
|
"mocha": "*",
|
||||||
@@ -29,7 +26,8 @@
|
|||||||
},
|
},
|
||||||
"bundledDependencies": [],
|
"bundledDependencies": [],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "0.10.35"
|
"node": "0.8.10",
|
||||||
|
"npm": "1.1.49"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"haste-server": "./server.js"
|
"haste-server": "./server.js"
|
||||||
|
73
server.js
73
server.js
@@ -4,9 +4,6 @@ var fs = require('fs');
|
|||||||
|
|
||||||
var winston = require('winston');
|
var winston = require('winston');
|
||||||
var connect = require('connect');
|
var connect = require('connect');
|
||||||
var route = require('connect-route');
|
|
||||||
var connect_st = require('st');
|
|
||||||
var connect_rate_limit = require('connect-ratelimit');
|
|
||||||
|
|
||||||
var DocumentHandler = require('./lib/document_handler');
|
var DocumentHandler = require('./lib/document_handler');
|
||||||
|
|
||||||
@@ -40,7 +37,7 @@ if (!config.storage.type) {
|
|||||||
|
|
||||||
var Store, preferredStore;
|
var Store, preferredStore;
|
||||||
|
|
||||||
if (process.env.REDISTOGO_URL && config.storage.type === 'redis') {
|
if (process.env.REDISTOGO_URL) {
|
||||||
var redisClient = require('redis-url').connect(process.env.REDISTOGO_URL);
|
var redisClient = require('redis-url').connect(process.env.REDISTOGO_URL);
|
||||||
Store = require('./lib/document_stores/redis');
|
Store = require('./lib/document_stores/redis');
|
||||||
preferredStore = new Store(config.storage, redisClient);
|
preferredStore = new Store(config.storage, redisClient);
|
||||||
@@ -102,58 +99,44 @@ var documentHandler = new DocumentHandler({
|
|||||||
keyGenerator: keyGenerator
|
keyGenerator: keyGenerator
|
||||||
});
|
});
|
||||||
|
|
||||||
var app = connect();
|
// Set the server up with a static cache
|
||||||
|
connect.createServer(
|
||||||
// Rate limit all requests
|
// First look for api calls
|
||||||
if (config.rateLimits) {
|
connect.router(function(app) {
|
||||||
config.rateLimits.end = true;
|
|
||||||
app.use(connect_rate_limit(config.rateLimits));
|
|
||||||
}
|
|
||||||
|
|
||||||
// first look at API calls
|
|
||||||
app.use(route(function(router) {
|
|
||||||
// get raw documents - support getting with extension
|
// get raw documents - support getting with extension
|
||||||
router.get('/raw/:id', function(request, response, next) {
|
app.get('/raw/:id', function(request, response, next) {
|
||||||
|
var skipExpire = !!config.documents[request.params.id];
|
||||||
var key = request.params.id.split('.')[0];
|
var key = request.params.id.split('.')[0];
|
||||||
var skipExpire = !!config.documents[key];
|
|
||||||
return documentHandler.handleRawGet(key, response, skipExpire);
|
return documentHandler.handleRawGet(key, response, skipExpire);
|
||||||
});
|
});
|
||||||
// add documents
|
// add documents
|
||||||
router.post('/documents', function(request, response, next) {
|
app.post('/documents', function(request, response, next) {
|
||||||
return documentHandler.handlePost(request, response);
|
return documentHandler.handlePost(request, response);
|
||||||
});
|
});
|
||||||
// get documents
|
// get documents
|
||||||
router.get('/documents/:id', function(request, response, next) {
|
app.get('/documents/:id', function(request, response, next) {
|
||||||
var key = request.params.id.split('.')[0];
|
var skipExpire = !!config.documents[request.params.id];
|
||||||
var skipExpire = !!config.documents[key];
|
var parsedUrl = url.parse(request.url, true);
|
||||||
return documentHandler.handleGet(key, response, skipExpire);
|
return documentHandler.handleGet(
|
||||||
|
request.params.id,
|
||||||
|
parsedUrl.query.callback,
|
||||||
|
response,
|
||||||
|
skipExpire
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}));
|
}),
|
||||||
|
// Otherwise, static
|
||||||
// Otherwise, try to match static files
|
connect.staticCache(),
|
||||||
app.use(connect_st({
|
connect.static(__dirname + '/static', { maxAge: config.staticMaxAge }),
|
||||||
path: __dirname + '/static',
|
|
||||||
content: { maxAge: config.staticMaxAge },
|
|
||||||
passthrough: true,
|
|
||||||
index: false
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Then we can loop back - and everything else should be a token,
|
// Then we can loop back - and everything else should be a token,
|
||||||
// so route it back to /
|
// so route it back to /index.html
|
||||||
app.use(route(function(router) {
|
connect.router(function(app) {
|
||||||
router.get('/:id', function(request, response, next) {
|
app.get('/:id', function(request, response, next) {
|
||||||
request.sturl = '/';
|
request.url = request.originalUrl = '/index.html';
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}));
|
}),
|
||||||
|
connect.static(__dirname + '/static', { maxAge: config.staticMaxAge })
|
||||||
// And match index
|
).listen(config.port, config.host);
|
||||||
app.use(connect_st({
|
|
||||||
path: __dirname + '/static',
|
|
||||||
content: { maxAge: config.staticMaxAge },
|
|
||||||
index: 'index.html'
|
|
||||||
}));
|
|
||||||
|
|
||||||
http.createServer(app).listen(config.port, config.host);
|
|
||||||
|
|
||||||
winston.info('listening on ' + config.host + ':' + config.port);
|
winston.info('listening on ' + config.host + ':' + config.port);
|
||||||
|
@@ -43,7 +43,6 @@ textarea {
|
|||||||
outline: none;
|
outline: none;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
padding-right: 360px;
|
padding-right: 360px;
|
||||||
overflow: inherit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#box code {
|
#box code {
|
||||||
@@ -149,7 +148,6 @@ textarea {
|
|||||||
#box2 .function.twitter { background-position: -153px top; }
|
#box2 .function.twitter { background-position: -153px top; }
|
||||||
#box2 .function.enabled.twitter { background-position: -153px center; }
|
#box2 .function.enabled.twitter { background-position: -153px center; }
|
||||||
#box2 .function.enabled.twitter:hover { background-position: -153px bottom; }
|
#box2 .function.enabled.twitter:hover { background-position: -153px bottom; }
|
||||||
#box2 .button-picture{ border-width: 0; font-size: inherit; }
|
|
||||||
|
|
||||||
#messages {
|
#messages {
|
||||||
position:fixed;
|
position:fixed;
|
||||||
@@ -169,4 +167,3 @@ textarea {
|
|||||||
#messages li.error {
|
#messages li.error {
|
||||||
background:rgba(102,8,0,0.8);
|
background:rgba(102,8,0,0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -166,10 +166,9 @@ haste.extensionMap = {
|
|||||||
rb: 'ruby', py: 'python', pl: 'perl', php: 'php', scala: 'scala', go: 'go',
|
rb: 'ruby', py: 'python', pl: 'perl', php: 'php', scala: 'scala', go: 'go',
|
||||||
xml: 'xml', html: 'xml', htm: 'xml', css: 'css', js: 'javascript', vbs: 'vbscript',
|
xml: 'xml', html: 'xml', htm: 'xml', css: 'css', js: 'javascript', vbs: 'vbscript',
|
||||||
lua: 'lua', pas: 'delphi', java: 'java', cpp: 'cpp', cc: 'cpp', m: 'objectivec',
|
lua: 'lua', pas: 'delphi', java: 'java', cpp: 'cpp', cc: 'cpp', m: 'objectivec',
|
||||||
vala: 'vala', sql: 'sql', sm: 'smalltalk', lisp: 'lisp', ini: 'ini',
|
vala: 'vala', cs: 'cs', sql: 'sql', sm: 'smalltalk', lisp: 'lisp', ini: 'ini',
|
||||||
diff: 'diff', bash: 'bash', sh: 'bash', tex: 'tex', erl: 'erlang', hs: 'haskell',
|
diff: 'diff', bash: 'bash', sh: 'bash', tex: 'tex', erl: 'erlang', hs: 'haskell',
|
||||||
md: 'markdown', txt: '', coffee: 'coffee', json: 'javascript',
|
md: 'markdown', txt: '', coffee: 'coffee', json: 'javascript'
|
||||||
swift: 'swift'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Look up the extension preferred for a type
|
// Look up the extension preferred for a type
|
||||||
|
2
static/application.min.js
vendored
2
static/application.min.js
vendored
File diff suppressed because one or more lines are too long
3
static/highlight.min.js
vendored
3
static/highlight.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
|
|
||||||
<title>hastebin</title>
|
<title>hastebin</title>
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="solarized_dark.css"/>
|
<link rel="stylesheet" type="text/css" href="solarized_dark.css"/>
|
||||||
<link rel="stylesheet" type="text/css" href="application.css"/>
|
<link rel="stylesheet" type="text/css" href="application.css"/>
|
||||||
|
|
||||||
@@ -47,11 +47,11 @@
|
|||||||
<a href="/about.md" class="logo"></a>
|
<a href="/about.md" class="logo"></a>
|
||||||
</div>
|
</div>
|
||||||
<div id="box2">
|
<div id="box2">
|
||||||
<button class="save function button-picture">Save</button>
|
<div class="save function"></div>
|
||||||
<button class="new function button-picture">New</button>
|
<div class="new function"></div>
|
||||||
<button class="duplicate function button-picture">Duplicate & Edit</button>
|
<div class="duplicate function"></div>
|
||||||
<button class="raw function button-picture">Just Text</button>
|
<div class="raw function"></div>
|
||||||
<button class="twitter function button-picture">Twitter</button>
|
<div class="twitter function"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="box3" style="display:none;">
|
<div id="box3" style="display:none;">
|
||||||
<div class="label"></div>
|
<div class="label"></div>
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="linenos"></div>
|
<div id="linenos"></div>
|
||||||
<pre id="box" style="display:none;" class="hljs" tabindex="0"><code></code></pre>
|
<pre id="box" style="display:none;" tabindex="0"><code></code></pre>
|
||||||
<textarea spellcheck="false" style="display:none;"></textarea>
|
<textarea spellcheck="false" style="display:none;"></textarea>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
@@ -4,81 +4,97 @@ Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull <sourdrums@gmai
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.hljs {
|
pre code {
|
||||||
display: block;
|
display: block; padding: 0.5em;
|
||||||
overflow-x: auto;
|
background: #002b36; color: #92a0a0;
|
||||||
padding: 0.5em;
|
|
||||||
background: #002b36;
|
|
||||||
color: #839496;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-comment,
|
pre .comment,
|
||||||
.hljs-quote {
|
pre .template_comment,
|
||||||
|
pre .diff .header,
|
||||||
|
pre .doctype,
|
||||||
|
pre .lisp .string,
|
||||||
|
pre .javadoc {
|
||||||
color: #586e75;
|
color: #586e75;
|
||||||
|
font-style: italic;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Solarized Green */
|
pre .keyword,
|
||||||
.hljs-keyword,
|
pre .css .rule .keyword,
|
||||||
.hljs-selector-tag,
|
pre .winutils,
|
||||||
.hljs-addition {
|
pre .javascript .title,
|
||||||
|
pre .method,
|
||||||
|
pre .addition,
|
||||||
|
pre .css .tag,
|
||||||
|
pre .lisp .title {
|
||||||
color: #859900;
|
color: #859900;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Solarized Cyan */
|
pre .number,
|
||||||
.hljs-number,
|
pre .command,
|
||||||
.hljs-string,
|
pre .string,
|
||||||
.hljs-meta .hljs-meta-string,
|
pre .tag .value,
|
||||||
.hljs-literal,
|
pre .phpdoc,
|
||||||
.hljs-doctag,
|
pre .tex .formula,
|
||||||
.hljs-regexp {
|
pre .regexp,
|
||||||
|
pre .hexcolor {
|
||||||
color: #2aa198;
|
color: #2aa198;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Solarized Blue */
|
pre .title,
|
||||||
.hljs-title,
|
pre .localvars,
|
||||||
.hljs-section,
|
pre .function .title,
|
||||||
.hljs-name,
|
pre .chunk,
|
||||||
.hljs-selector-id,
|
pre .decorator,
|
||||||
.hljs-selector-class {
|
pre .builtin,
|
||||||
|
pre .built_in,
|
||||||
|
pre .lisp .title,
|
||||||
|
pre .identifier,
|
||||||
|
pre .title .keymethods,
|
||||||
|
pre .id,
|
||||||
|
pre .header {
|
||||||
color: #268bd2;
|
color: #268bd2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Solarized Yellow */
|
pre .tag .title,
|
||||||
.hljs-attribute,
|
pre .rules .property,
|
||||||
.hljs-attr,
|
pre .django .tag .keyword {
|
||||||
.hljs-variable,
|
font-weight: bold;
|
||||||
.hljs-template-variable,
|
}
|
||||||
.hljs-class .hljs-title,
|
|
||||||
.hljs-type {
|
pre .attribute,
|
||||||
|
pre .variable,
|
||||||
|
pre .instancevar,
|
||||||
|
pre .lisp .body,
|
||||||
|
pre .smalltalk .number,
|
||||||
|
pre .constant,
|
||||||
|
pre .class .title,
|
||||||
|
pre .parent,
|
||||||
|
pre .haskell .label {
|
||||||
color: #b58900;
|
color: #b58900;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Solarized Orange */
|
pre .preprocessor,
|
||||||
.hljs-symbol,
|
pre .pi,
|
||||||
.hljs-bullet,
|
pre .shebang,
|
||||||
.hljs-subst,
|
pre .symbol,
|
||||||
.hljs-meta,
|
pre .diff .change,
|
||||||
.hljs-meta .hljs-keyword,
|
pre .special,
|
||||||
.hljs-selector-attr,
|
pre .keymethods,
|
||||||
.hljs-selector-pseudo,
|
pre .attr_selector,
|
||||||
.hljs-link {
|
pre .important,
|
||||||
|
pre .subst,
|
||||||
|
pre .cdata {
|
||||||
color: #cb4b16;
|
color: #cb4b16;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Solarized Red */
|
pre .deletion {
|
||||||
.hljs-built_in,
|
|
||||||
.hljs-deletion {
|
|
||||||
color: #dc322f;
|
color: #dc322f;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-formula {
|
pre .tex .formula,
|
||||||
|
pre .code {
|
||||||
background: #073642;
|
background: #073642;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-emphasis {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-strong {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user