From df032862666a5041afdba1869dbc4a823896f39a Mon Sep 17 00:00:00 2001 From: Gregory Eremin Date: Wed, 10 Jul 2013 19:02:19 +0700 Subject: [PATCH] Syntax highlighting support --- app/assets/javascripts/pastemaster.coffee | 2 +- app/assets/stylesheets/pastemaster.styl | 12 +++- app/paste.rb | 21 +++++-- pastemaster.rb | 4 +- public/pygments_solarized_modified.css | 69 +++++++++++++++++++++++ views/default.slim | 1 + views/form.slim | 2 +- views/show.slim | 2 +- 8 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 public/pygments_solarized_modified.css diff --git a/app/assets/javascripts/pastemaster.coffee b/app/assets/javascripts/pastemaster.coffee index a024730..f3ebfd2 100644 --- a/app/assets/javascripts/pastemaster.coffee +++ b/app/assets/javascripts/pastemaster.coffee @@ -10,6 +10,6 @@ $ -> $contents.focus() # Binding submit event to new button - $button.on 'click', -> + $button.on 'mouseup', -> $form.submit() false diff --git a/app/assets/stylesheets/pastemaster.styl b/app/assets/stylesheets/pastemaster.styl index f0bc18f..a98fd80 100644 --- a/app/assets/stylesheets/pastemaster.styl +++ b/app/assets/stylesheets/pastemaster.styl @@ -2,11 +2,11 @@ body, input, select { font-family: Helvetica, Arial, sans-serif; - font-size: 1.2em; + font-size: 1em; } textarea, pre { font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif; - font-size: 1.2em; + font-size: 1em; } html, body, form { height: 100%; @@ -27,6 +27,14 @@ h1 { text-transform: uppercase; color: #ccc; } +.linenos { + padding-right: .5em; + color: #ccc; + border-right: #eee 1px solid; +} +.code { + padding-left: .5em; +} .container { width: 100%; diff --git a/app/paste.rb b/app/paste.rb index 8a82182..2f3475a 100644 --- a/app/paste.rb +++ b/app/paste.rb @@ -1,20 +1,21 @@ class Paste - attr_reader :contents + attr_reader :contents, :type class << self def find(id) record = DB[:pastes].where(id: id).first - record ? new(record[:contents]) : nil + record ? new(record[:contents], record[:type]) : nil end end - def initialize(contents) + def initialize(contents, type = nil) @contents = contents + @type = type end def save encrypt! - DB[:pastes].insert(contents: contents) + DB[:pastes].insert(contents: contents, type: type) end def decrypt(key) @@ -34,4 +35,16 @@ class Paste def decrypt! @contents = Encryptor.decrypt(value: Base64.decode64(contents), key: key) end + + def highlighted + Pygments.highlight(@contents, lexer: 'ruby', options: { linenos: 'table' }) + end + + def paragraph + "
#{@contents}
" + end + + def html + type ? highlighted : paragraph + end end diff --git a/pastemaster.rb b/pastemaster.rb index c3642a6..7f35b98 100644 --- a/pastemaster.rb +++ b/pastemaster.rb @@ -11,6 +11,7 @@ require 'slim' require 'coffee_script' require 'stylus' require 'stylus/tilt' +require 'pygments' require 'lib/error_pages' require 'lib/assets' @@ -46,8 +47,9 @@ class Pastemaster < Sinatra::Application begin @paste.decrypt(params[:key]) + slim :show, layout: :default - rescue => Error + rescue OpenSSL::Cipher::CipherError forbidden end end diff --git a/public/pygments_solarized_modified.css b/public/pygments_solarized_modified.css new file mode 100644 index 0000000..6821dbe --- /dev/null +++ b/public/pygments_solarized_modified.css @@ -0,0 +1,69 @@ +/* .highlight { background-color: #ffffcc } */ +.highlight .c { color: #586E75 } /* Comment */ +.highlight .err { color: #538181 } /* Error */ +.highlight .g { color: #538181 } /* Generic */ +.highlight .k { color: #859900 } /* Keyword */ +.highlight .l { color: #538181 } /* Literal */ +.highlight .n { color: #538181 } /* Name */ +.highlight .o { color: #859900 } /* Operator */ +.highlight .x { color: #CB4B16 } /* Other */ +.highlight .p { color: #538181 } /* Punctuation */ +.highlight .cm { color: #586E75 } /* Comment.Multiline */ +.highlight .cp { color: #859900 } /* Comment.Preproc */ +.highlight .c1 { color: #586E75 } /* Comment.Single */ +.highlight .cs { color: #859900 } /* Comment.Special */ +.highlight .gd { color: #2AA198 } /* Generic.Deleted */ +.highlight .ge { color: #538181; font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #DC322F } /* Generic.Error */ +.highlight .gh { color: #CB4B16 } /* Generic.Heading */ +.highlight .gi { color: #859900 } /* Generic.Inserted */ +.highlight .go { color: #538181 } /* Generic.Output */ +.highlight .gp { color: #538181 } /* Generic.Prompt */ +.highlight .gs { color: #538181; font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #CB4B16 } /* Generic.Subheading */ +.highlight .gt { color: #538181 } /* Generic.Traceback */ +.highlight .kc { color: #CB4B16 } /* Keyword.Constant */ +.highlight .kd { color: #268BD2 } /* Keyword.Declaration */ +.highlight .kn { color: #859900 } /* Keyword.Namespace */ +.highlight .kp { color: #859900 } /* Keyword.Pseudo */ +.highlight .kr { color: #268BD2 } /* Keyword.Reserved */ +.highlight .kt { color: #DC322F } /* Keyword.Type */ +.highlight .ld { color: #538181 } /* Literal.Date */ +.highlight .m { color: #2AA198 } /* Literal.Number */ +.highlight .s { color: #2AA198 } /* Literal.String */ +.highlight .na { color: #538181 } /* Name.Attribute */ +.highlight .nb { color: #B58900 } /* Name.Builtin */ +.highlight .nc { color: #268BD2 } /* Name.Class */ +.highlight .no { color: #CB4B16 } /* Name.Constant */ +.highlight .nd { color: #268BD2 } /* Name.Decorator */ +.highlight .ni { color: #CB4B16 } /* Name.Entity */ +.highlight .ne { color: #CB4B16 } /* Name.Exception */ +.highlight .nf { color: #268BD2 } /* Name.Function */ +.highlight .nl { color: #538181 } /* Name.Label */ +.highlight .nn { color: #538181 } /* Name.Namespace */ +.highlight .nx { color: #538181 } /* Name.Other */ +.highlight .py { color: #538181 } /* Name.Property */ +.highlight .nt { color: #268BD2 } /* Name.Tag */ +.highlight .nv { color: #268BD2 } /* Name.Variable */ +.highlight .ow { color: #859900 } /* Operator.Word */ +.highlight .w { color: #538181 } /* Text.Whitespace */ +.highlight .mf { color: #2AA198 } /* Literal.Number.Float */ +.highlight .mh { color: #2AA198 } /* Literal.Number.Hex */ +.highlight .mi { color: #2AA198 } /* Literal.Number.Integer */ +.highlight .mo { color: #2AA198 } /* Literal.Number.Oct */ +.highlight .sb { color: #586E75 } /* Literal.String.Backtick */ +.highlight .sc { color: #2AA198 } /* Literal.String.Char */ +.highlight .sd { color: #538181 } /* Literal.String.Doc */ +.highlight .s2 { color: #2AA198 } /* Literal.String.Double */ +.highlight .se { color: #CB4B16 } /* Literal.String.Escape */ +.highlight .sh { color: #538181 } /* Literal.String.Heredoc */ +.highlight .si { color: #2AA198 } /* Literal.String.Interpol */ +.highlight .sx { color: #2AA198 } /* Literal.String.Other */ +.highlight .sr { color: #DC322F } /* Literal.String.Regex */ +.highlight .s1 { color: #2AA198 } /* Literal.String.Single */ +.highlight .ss { color: #2AA198 } /* Literal.String.Symbol */ +.highlight .bp { color: #268BD2 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #268BD2 } /* Name.Variable.Class */ +.highlight .vg { color: #268BD2 } /* Name.Variable.Global */ +.highlight .vi { color: #268BD2 } /* Name.Variable.Instance */ +.highlight .il { color: #2AA198 } /* Literal.Number.Integer.Long */ diff --git a/views/default.slim b/views/default.slim index 122a5a7..f98db94 100644 --- a/views/default.slim +++ b/views/default.slim @@ -4,6 +4,7 @@ html title Pastemaster link rel="stylesheet" href="/normalize.css?v2.1.2" link rel="stylesheet" href="/assets/pastemaster.css?r1" + link rel="stylesheet" href="/pygments_solarized_modified.css?r1" body h1 strong Paste diff --git a/views/form.slim b/views/form.slim index ac4533f..7362bed 100644 --- a/views/form.slim +++ b/views/form.slim @@ -1,4 +1,4 @@ form#pasteform action="/" method="post" accept-charset="UTF-8" textarea#contents name="contents" input#submitbtn type="submit" value="Save" - a#submitlnk href="" role="submit" Save + a#submitlnk href="#" role="submit" Save diff --git a/views/show.slim b/views/show.slim index 5705505..59c106a 100644 --- a/views/show.slim +++ b/views/show.slim @@ -1 +1 @@ -pre= @paste.contents +== @paste.html