Compare commits
49 Commits
toggle_key
...
production
Author | SHA1 | Date | |
---|---|---|---|
|
32df3370e2 | ||
|
d81195856a | ||
|
6ed427658e | ||
|
08eddc7e80 | ||
|
d040dedc6e | ||
|
5a8697cdd8 | ||
|
091ea973a8 | ||
|
939b7221ab | ||
|
934aaf7f51 | ||
|
930e21ccb7 | ||
|
eb5c8eef6a | ||
|
03dd611a86 | ||
|
f24376b192 | ||
|
eea359d0ec | ||
|
af9a71549b | ||
|
3178676fba | ||
|
3bdfab8219 | ||
|
a3a24d9765 | ||
|
8afb53e77e | ||
|
d6d9cf40f9 | ||
|
1010a142e2 | ||
|
0209375865 | ||
|
00a9d9c312 | ||
|
6835eef468 | ||
|
4626fd9c8d | ||
|
fbb6e63c37 | ||
|
84c909a5db | ||
|
45e19bc7cc | ||
|
233bc6ff16 | ||
|
360b325ced | ||
|
e93f98112b | ||
|
05cb051bc8 | ||
|
031cdd738a | ||
|
c92ab077c0 | ||
|
6c31389327 | ||
|
a8d4f3c300 | ||
|
ab029eae2f | ||
|
447d0aae76 | ||
|
4870158430 | ||
|
0471b059a0 | ||
|
5bbe50b481 | ||
|
bda2749879 | ||
|
028aa96b13 | ||
|
2deda5b68a | ||
|
ee7098457e | ||
|
7a08960414 | ||
|
89909747f1 | ||
|
202e695e07 | ||
|
48e8e79659 |
50
README.md
50
README.md
@@ -20,14 +20,6 @@ to do things like:
|
||||
which will output a URL to share containing the contents of `cat something`'s
|
||||
STDOUT. Check the README there for more details and usages.
|
||||
|
||||
## Support
|
||||
|
||||
Please consider paying what you feel this project is worth:
|
||||
|
||||
<a href="https://www.stripeme.com/pay/1r2f">
|
||||
<img alt="Pay" src="https://www.stripeme.com/pay.jpg" />
|
||||
</a>
|
||||
|
||||
## Tested Browsers
|
||||
|
||||
* Firefox 8
|
||||
@@ -54,6 +46,16 @@ Please consider paying what you feel this project is worth:
|
||||
* `storage` - storage options (see below)
|
||||
* `logging` - logging preferences
|
||||
* `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
|
||||
|
||||
@@ -99,7 +101,8 @@ Where `path` represents where you want the files stored
|
||||
|
||||
### Redis
|
||||
|
||||
To use redis storage you must install the redis package in npm
|
||||
To use redis storage you must install the `redis` package in npm, and have
|
||||
`redis-server` running on the machine.
|
||||
|
||||
`npm install redis`
|
||||
|
||||
@@ -120,6 +123,35 @@ or post.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
Most of the time I want to show you some text, its coming from my current
|
||||
Most of the time I want to show you some text, it's coming from my current
|
||||
console session. We should make it really easy to take code from the console
|
||||
and send it to people.
|
||||
|
||||
@@ -50,7 +50,7 @@ pastes.
|
||||
|
||||
## Open Source
|
||||
|
||||
Haste can easily be installed behind your network, and its all open source!
|
||||
Haste can easily be installed behind your network, and it's all open source!
|
||||
|
||||
* [haste-client](https://github.com/seejohnrun/haste-client)
|
||||
* [haste-server](https://github.com/seejohnrun/haste-server)
|
||||
|
14
config.js
14
config.js
@@ -23,11 +23,17 @@
|
||||
"type": "phonetic"
|
||||
},
|
||||
|
||||
"rateLimits": {
|
||||
"categories": {
|
||||
"normal": {
|
||||
"totalRequests": 500,
|
||||
"every": 60000
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"storage": {
|
||||
"type": "redis",
|
||||
"host": "0.0.0.0",
|
||||
"port": 6379,
|
||||
"db": 2,
|
||||
"type": "postgres",
|
||||
"expire": 2592000
|
||||
},
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
var winston = require('winston');
|
||||
var Busboy = require('busboy');
|
||||
|
||||
// For handling serving stored documents
|
||||
|
||||
@@ -47,15 +48,14 @@ DocumentHandler.prototype.handleRawGet = function(key, response, skipExpire) {
|
||||
};
|
||||
|
||||
// Handle adding a new Document
|
||||
DocumentHandler.prototype.handlePost = function(request, response) {
|
||||
DocumentHandler.prototype.handlePost = function (request, response) {
|
||||
var _this = this;
|
||||
var buffer = '';
|
||||
var cancelled = false;
|
||||
request.on('data', function(data) {
|
||||
if (!buffer) {
|
||||
response.writeHead(200, { 'content-type': 'application/json' });
|
||||
}
|
||||
buffer += data.toString();
|
||||
|
||||
// What to do when done
|
||||
var onSuccess = function () {
|
||||
// Check length
|
||||
if (_this.maxLength && buffer.length > _this.maxLength) {
|
||||
cancelled = true;
|
||||
winston.warn('document >maxLength', { maxLength: _this.maxLength });
|
||||
@@ -63,14 +63,15 @@ DocumentHandler.prototype.handlePost = function(request, response) {
|
||||
response.end(
|
||||
JSON.stringify({ message: 'Document exceeds maximum length.' })
|
||||
);
|
||||
return;
|
||||
}
|
||||
});
|
||||
request.on('end', function(end) {
|
||||
if (cancelled) return;
|
||||
_this.chooseKey(function(key) {
|
||||
_this.store.set(key, buffer, function(res) {
|
||||
// And then save if we should
|
||||
_this.chooseKey(function (key) {
|
||||
_this.store.set(key, buffer, function (res) {
|
||||
if (res) {
|
||||
winston.verbose('added document', { key: key });
|
||||
var ip = request.headers['x-forwarded-for'] || request.ip;
|
||||
winston.verbose('added document', { key: key, ip: ip });
|
||||
response.writeHead(200, { 'content-type': 'application/json' });
|
||||
response.end(JSON.stringify({ key: key }));
|
||||
}
|
||||
else {
|
||||
@@ -80,12 +81,37 @@ 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;
|
||||
}
|
||||
});
|
||||
request.on('error', function(error) {
|
||||
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) {
|
||||
winston.error('connection error: ' + error.message);
|
||||
response.writeHead(500, { 'content-type': 'application/json' });
|
||||
response.end(JSON.stringify({ message: 'Connection error.' }));
|
||||
cancelled = true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Keep choosing keys until one isn't taken
|
||||
|
79
lib/document_stores/postgres.js
Normal file
79
lib/document_stores/postgres.js
Normal file
@@ -0,0 +1,79 @@
|
||||
/*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,11 +25,15 @@ RedisDocumentStore.connect = function(options) {
|
||||
var port = options.port || 6379;
|
||||
var index = options.db || 0;
|
||||
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) {
|
||||
if (err) {
|
||||
winston.error(
|
||||
'error connecting to redis index ' + index,
|
||||
{ error: err.message }
|
||||
{ error: err }
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
@@ -6,13 +6,14 @@ var PhoneticKeyGenerator = function(options) {
|
||||
// Generate a phonetic key
|
||||
PhoneticKeyGenerator.prototype.createKey = function(keyLength) {
|
||||
var text = '';
|
||||
var start = Math.round(Math.random());
|
||||
for (var i = 0; i < keyLength; i++) {
|
||||
text += (i % 2 == 0) ? this.randConsonant() : this.randVowel();
|
||||
text += (i % 2 == start) ? this.randConsonant() : this.randVowel();
|
||||
}
|
||||
return text;
|
||||
};
|
||||
|
||||
PhoneticKeyGenerator.consonants = 'bcdfghjklmnpqrstvwxy';
|
||||
PhoneticKeyGenerator.consonants = 'bcdfghjklmnpqrstvwxyz';
|
||||
PhoneticKeyGenerator.vowels = 'aeiou';
|
||||
|
||||
// Get an random vowel
|
||||
|
14
package.json
14
package.json
@@ -14,11 +14,14 @@
|
||||
},
|
||||
"main": "haste",
|
||||
"dependencies": {
|
||||
"connect-ratelimit": "0.0.7",
|
||||
"connect-route": "0.1.5",
|
||||
"connect": "3.4.1",
|
||||
"st": "1.1.0",
|
||||
"winston": "0.6.2",
|
||||
"connect": "1.9.2",
|
||||
"redis-url": "0.1.0",
|
||||
"redis": "0.8.1",
|
||||
"uglify-js": "1.3.3"
|
||||
"uglify-js": "1.3.3",
|
||||
"busboy": "0.2.4",
|
||||
"pg": "4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "*",
|
||||
@@ -26,8 +29,7 @@
|
||||
},
|
||||
"bundledDependencies": [],
|
||||
"engines": {
|
||||
"node": "0.8.10",
|
||||
"npm": "1.1.49"
|
||||
"node": "0.10.35"
|
||||
},
|
||||
"bin": {
|
||||
"haste-server": "./server.js"
|
||||
|
73
server.js
73
server.js
@@ -4,6 +4,9 @@ var fs = require('fs');
|
||||
|
||||
var winston = require('winston');
|
||||
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');
|
||||
|
||||
@@ -37,7 +40,7 @@ if (!config.storage.type) {
|
||||
|
||||
var Store, preferredStore;
|
||||
|
||||
if (process.env.REDISTOGO_URL) {
|
||||
if (process.env.REDISTOGO_URL && config.storage.type === 'redis') {
|
||||
var redisClient = require('redis-url').connect(process.env.REDISTOGO_URL);
|
||||
Store = require('./lib/document_stores/redis');
|
||||
preferredStore = new Store(config.storage, redisClient);
|
||||
@@ -99,42 +102,58 @@ var documentHandler = new DocumentHandler({
|
||||
keyGenerator: keyGenerator
|
||||
});
|
||||
|
||||
// Set the server up with a static cache
|
||||
connect.createServer(
|
||||
// First look for api calls
|
||||
connect.router(function(app) {
|
||||
var app = connect();
|
||||
|
||||
// Rate limit all requests
|
||||
if (config.rateLimits) {
|
||||
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
|
||||
app.get('/raw/:id', function(request, response, next) {
|
||||
var skipExpire = !!config.documents[request.params.id];
|
||||
router.get('/raw/:id', function(request, response, next) {
|
||||
var key = request.params.id.split('.')[0];
|
||||
var skipExpire = !!config.documents[key];
|
||||
return documentHandler.handleRawGet(key, response, skipExpire);
|
||||
});
|
||||
// add documents
|
||||
app.post('/documents', function(request, response, next) {
|
||||
router.post('/documents', function(request, response, next) {
|
||||
return documentHandler.handlePost(request, response);
|
||||
});
|
||||
// get documents
|
||||
app.get('/documents/:id', function(request, response, next) {
|
||||
var skipExpire = !!config.documents[request.params.id];
|
||||
return documentHandler.handleGet(
|
||||
request.params.id,
|
||||
response,
|
||||
skipExpire
|
||||
);
|
||||
router.get('/documents/:id', function(request, response, next) {
|
||||
var key = request.params.id.split('.')[0];
|
||||
var skipExpire = !!config.documents[key];
|
||||
return documentHandler.handleGet(key, response, skipExpire);
|
||||
});
|
||||
}),
|
||||
// Otherwise, static
|
||||
connect.staticCache(),
|
||||
connect.static(__dirname + '/static', { maxAge: config.staticMaxAge }),
|
||||
// Then we can loop back - and everything else should be a token,
|
||||
// so route it back to /index.html
|
||||
connect.router(function(app) {
|
||||
app.get('/:id', function(request, response, next) {
|
||||
request.url = request.originalUrl = '/index.html';
|
||||
}));
|
||||
|
||||
// Otherwise, try to match static files
|
||||
app.use(connect_st({
|
||||
path: __dirname + '/static',
|
||||
content: { maxAge: config.staticMaxAge },
|
||||
passthrough: true,
|
||||
index: false
|
||||
}));
|
||||
|
||||
// Then we can loop back - and everything else should be a token,
|
||||
// so route it back to /
|
||||
app.use(route(function(router) {
|
||||
router.get('/:id', function(request, response, next) {
|
||||
request.sturl = '/';
|
||||
next();
|
||||
});
|
||||
}),
|
||||
connect.static(__dirname + '/static', { maxAge: config.staticMaxAge })
|
||||
).listen(config.port, config.host);
|
||||
}));
|
||||
|
||||
// And match index
|
||||
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);
|
||||
|
@@ -43,6 +43,7 @@ textarea {
|
||||
outline: none;
|
||||
font-size: 13px;
|
||||
padding-right: 360px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
#box code {
|
||||
@@ -148,6 +149,7 @@ textarea {
|
||||
#box2 .function.twitter { background-position: -153px top; }
|
||||
#box2 .function.enabled.twitter { background-position: -153px center; }
|
||||
#box2 .function.enabled.twitter:hover { background-position: -153px bottom; }
|
||||
#box2 .button-picture{ border-width: 0; font-size: inherit; }
|
||||
|
||||
#messages {
|
||||
position:fixed;
|
||||
@@ -167,3 +169,4 @@ textarea {
|
||||
#messages li.error {
|
||||
background:rgba(102,8,0,0.8);
|
||||
}
|
||||
|
||||
|
@@ -166,9 +166,10 @@ haste.extensionMap = {
|
||||
rb: 'ruby', py: 'python', pl: 'perl', php: 'php', scala: 'scala', go: 'go',
|
||||
xml: 'xml', html: 'xml', htm: 'xml', css: 'css', js: 'javascript', vbs: 'vbscript',
|
||||
lua: 'lua', pas: 'delphi', java: 'java', cpp: 'cpp', cc: 'cpp', m: 'objectivec',
|
||||
vala: 'vala', cs: 'cs', sql: 'sql', sm: 'smalltalk', lisp: 'lisp', ini: 'ini',
|
||||
vala: 'vala', sql: 'sql', sm: 'smalltalk', lisp: 'lisp', ini: 'ini',
|
||||
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
|
||||
|
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>
|
||||
|
||||
<title>hastebin</title>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" type="text/css" href="solarized_dark.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="application.css"/>
|
||||
|
||||
@@ -47,11 +47,11 @@
|
||||
<a href="/about.md" class="logo"></a>
|
||||
</div>
|
||||
<div id="box2">
|
||||
<div class="save function"></div>
|
||||
<div class="new function"></div>
|
||||
<div class="duplicate function"></div>
|
||||
<div class="raw function"></div>
|
||||
<div class="twitter function"></div>
|
||||
<button class="save function button-picture">Save</button>
|
||||
<button class="new function button-picture">New</button>
|
||||
<button class="duplicate function button-picture">Duplicate & Edit</button>
|
||||
<button class="raw function button-picture">Just Text</button>
|
||||
<button class="twitter function button-picture">Twitter</button>
|
||||
</div>
|
||||
<div id="box3" style="display:none;">
|
||||
<div class="label"></div>
|
||||
@@ -60,20 +60,9 @@
|
||||
</div>
|
||||
|
||||
<div id="linenos"></div>
|
||||
<pre id="box" style="display:none;" tabindex="0"><code></code></pre>
|
||||
<pre id="box" style="display:none;" class="hljs" tabindex="0"><code></code></pre>
|
||||
<textarea spellcheck="false" style="display:none;"></textarea>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-27329119-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
@@ -4,97 +4,81 @@ Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull <sourdrums@gmai
|
||||
|
||||
*/
|
||||
|
||||
pre code {
|
||||
display: block; padding: 0.5em;
|
||||
background: #002b36; color: #92a0a0;
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #002b36;
|
||||
color: #839496;
|
||||
}
|
||||
|
||||
pre .comment,
|
||||
pre .template_comment,
|
||||
pre .diff .header,
|
||||
pre .doctype,
|
||||
pre .lisp .string,
|
||||
pre .javadoc {
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #586e75;
|
||||
font-style: italic;
|
||||
display: inline-block;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
pre .keyword,
|
||||
pre .css .rule .keyword,
|
||||
pre .winutils,
|
||||
pre .javascript .title,
|
||||
pre .method,
|
||||
pre .addition,
|
||||
pre .css .tag,
|
||||
pre .lisp .title {
|
||||
/* Solarized Green */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-addition {
|
||||
color: #859900;
|
||||
}
|
||||
|
||||
pre .number,
|
||||
pre .command,
|
||||
pre .string,
|
||||
pre .tag .value,
|
||||
pre .phpdoc,
|
||||
pre .tex .formula,
|
||||
pre .regexp,
|
||||
pre .hexcolor {
|
||||
/* Solarized Cyan */
|
||||
.hljs-number,
|
||||
.hljs-string,
|
||||
.hljs-meta .hljs-meta-string,
|
||||
.hljs-literal,
|
||||
.hljs-doctag,
|
||||
.hljs-regexp {
|
||||
color: #2aa198;
|
||||
}
|
||||
|
||||
pre .title,
|
||||
pre .localvars,
|
||||
pre .function .title,
|
||||
pre .chunk,
|
||||
pre .decorator,
|
||||
pre .builtin,
|
||||
pre .built_in,
|
||||
pre .lisp .title,
|
||||
pre .identifier,
|
||||
pre .title .keymethods,
|
||||
pre .id,
|
||||
pre .header {
|
||||
/* Solarized Blue */
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
pre .tag .title,
|
||||
pre .rules .property,
|
||||
pre .django .tag .keyword {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre .attribute,
|
||||
pre .variable,
|
||||
pre .instancevar,
|
||||
pre .lisp .body,
|
||||
pre .smalltalk .number,
|
||||
pre .constant,
|
||||
pre .class .title,
|
||||
pre .parent,
|
||||
pre .haskell .label {
|
||||
/* Solarized Yellow */
|
||||
.hljs-attribute,
|
||||
.hljs-attr,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-type {
|
||||
color: #b58900;
|
||||
}
|
||||
|
||||
pre .preprocessor,
|
||||
pre .pi,
|
||||
pre .shebang,
|
||||
pre .symbol,
|
||||
pre .diff .change,
|
||||
pre .special,
|
||||
pre .keymethods,
|
||||
pre .attr_selector,
|
||||
pre .important,
|
||||
pre .subst,
|
||||
pre .cdata {
|
||||
/* Solarized Orange */
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-subst,
|
||||
.hljs-meta,
|
||||
.hljs-meta .hljs-keyword,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-link {
|
||||
color: #cb4b16;
|
||||
}
|
||||
|
||||
pre .deletion {
|
||||
/* Solarized Red */
|
||||
.hljs-built_in,
|
||||
.hljs-deletion {
|
||||
color: #dc322f;
|
||||
}
|
||||
|
||||
pre .tex .formula,
|
||||
pre .code {
|
||||
.hljs-formula {
|
||||
background: #073642;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
Reference in New Issue
Block a user