├── .gitignore ├── .rspec ├── .travis.yml ├── CHANGEDLOG.md ├── Gemfile ├── Gemfile.lock ├── Guardfile ├── LICENSE ├── README.md ├── generators └── highlight_styles_generator │ ├── highlight_styles_generator.rb │ └── templates │ ├── NOTES │ └── highlight.css ├── highlight.gemspec ├── lib └── simplabs │ ├── highlight.rb │ └── highlight │ ├── pygments_wrapper.rb │ └── railtie.rb ├── rails └── init.rb ├── spec ├── boot.rb ├── lib │ ├── highlight_spec.rb │ ├── pygments_wrapper_spec.rb │ └── view_methods_spec.rb └── spec_helper.rb └── uninstall.rb /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | spec/log/spec.log 3 | rdoc 4 | .bundle 5 | *.gem -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format nested 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 1.8.7 4 | - 1.9.2 5 | - 1.9.3 6 | - 2.0.0 7 | - ree 8 | script: "bundle exec rspec" 9 | before_install: 10 | - sudo apt-get install python-pygments -------------------------------------------------------------------------------- /CHANGEDLOG.md: -------------------------------------------------------------------------------- 1 | v2.0.0 2 | ====== 3 | 4 | * don't strip leading/trailing whitespaces, only remove trailing newlines (http://ruby-doc.org/core-2.0/String.html#method-i-chomp) 5 | 6 | v1.1.7 7 | ====== 8 | 9 | * added missing gem license (MIT) 10 | 11 | v1.1.6 12 | ====== 13 | 14 | * added support for CoffeeScript 15 | 16 | v1.1.5 17 | ====== 18 | 19 | * removed activesupport dependency 20 | 21 | v1.1.4 22 | ====== 23 | 24 | * switched to new web API 25 | * cleaned up internals 26 | * fixed Rails 3 generator 27 | 28 | v1.1.3 29 | ====== 30 | 31 | * added new supported language NASM 32 | 33 | v1.1.2 34 | ====== 35 | 36 | * first gem version 37 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | 5 | gem 'rails', '~>3.2.0' 6 | gem 'rspec', '~>2.13.0' 7 | gem 'simplecov', '~>0.7.1' 8 | gem 'excellent', '~>1.6.0' 9 | gem 'bluecloth', '~>2.2.0' 10 | gem 'guard', '~>1.6.2' 11 | gem 'guard-rspec', '~>2.5.1' 12 | gem 'growl', '~>1.0.3' 13 | gem 'rb-fsevent', '~>0.9.3' 14 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | highlight (2.0.0) 5 | 6 | GEM 7 | remote: https://rubygems.org/ 8 | specs: 9 | actionmailer (3.2.13) 10 | actionpack (= 3.2.13) 11 | mail (~> 2.5.3) 12 | actionpack (3.2.13) 13 | activemodel (= 3.2.13) 14 | activesupport (= 3.2.13) 15 | builder (~> 3.0.0) 16 | erubis (~> 2.7.0) 17 | journey (~> 1.0.4) 18 | rack (~> 1.4.5) 19 | rack-cache (~> 1.2) 20 | rack-test (~> 0.6.1) 21 | sprockets (~> 2.2.1) 22 | activemodel (3.2.13) 23 | activesupport (= 3.2.13) 24 | builder (~> 3.0.0) 25 | activerecord (3.2.13) 26 | activemodel (= 3.2.13) 27 | activesupport (= 3.2.13) 28 | arel (~> 3.0.2) 29 | tzinfo (~> 0.3.29) 30 | activeresource (3.2.13) 31 | activemodel (= 3.2.13) 32 | activesupport (= 3.2.13) 33 | activesupport (3.2.13) 34 | i18n (= 0.6.1) 35 | multi_json (~> 1.0) 36 | arel (3.0.2) 37 | bluecloth (2.2.0) 38 | builder (3.0.4) 39 | coderay (1.0.9) 40 | diff-lcs (1.2.1) 41 | erubis (2.7.0) 42 | excellent (1.6.0) 43 | ruby_parser (>= 2.0) 44 | sexp_processor (>= 3.0) 45 | growl (1.0.3) 46 | guard (1.6.2) 47 | listen (>= 0.6.0) 48 | lumberjack (>= 1.0.2) 49 | pry (>= 0.9.10) 50 | terminal-table (>= 1.4.3) 51 | thor (>= 0.14.6) 52 | guard-rspec (2.5.1) 53 | guard (>= 1.1) 54 | rspec (~> 2.11) 55 | hike (1.2.3) 56 | i18n (0.6.1) 57 | journey (1.0.4) 58 | json (1.8.0) 59 | listen (0.7.3) 60 | lumberjack (1.0.3) 61 | mail (2.5.4) 62 | mime-types (~> 1.16) 63 | treetop (~> 1.4.8) 64 | method_source (0.8.1) 65 | mime-types (1.23) 66 | multi_json (1.7.2) 67 | polyglot (0.3.3) 68 | pry (0.9.12) 69 | coderay (~> 1.0.5) 70 | method_source (~> 0.8) 71 | slop (~> 3.4) 72 | rack (1.4.5) 73 | rack-cache (1.2) 74 | rack (>= 0.4) 75 | rack-ssl (1.3.3) 76 | rack 77 | rack-test (0.6.2) 78 | rack (>= 1.0) 79 | rails (3.2.13) 80 | actionmailer (= 3.2.13) 81 | actionpack (= 3.2.13) 82 | activerecord (= 3.2.13) 83 | activeresource (= 3.2.13) 84 | activesupport (= 3.2.13) 85 | bundler (~> 1.0) 86 | railties (= 3.2.13) 87 | railties (3.2.13) 88 | actionpack (= 3.2.13) 89 | activesupport (= 3.2.13) 90 | rack-ssl (~> 1.3.2) 91 | rake (>= 0.8.7) 92 | rdoc (~> 3.4) 93 | thor (>= 0.14.6, < 2.0) 94 | rake (10.1.0) 95 | rb-fsevent (0.9.3) 96 | rdoc (3.12.2) 97 | json (~> 1.4) 98 | rspec (2.13.0) 99 | rspec-core (~> 2.13.0) 100 | rspec-expectations (~> 2.13.0) 101 | rspec-mocks (~> 2.13.0) 102 | rspec-core (2.13.1) 103 | rspec-expectations (2.13.0) 104 | diff-lcs (>= 1.1.3, < 2.0) 105 | rspec-mocks (2.13.0) 106 | ruby_parser (3.1.2) 107 | sexp_processor (~> 4.1) 108 | sexp_processor (4.2.0) 109 | simplecov (0.7.1) 110 | multi_json (~> 1.0) 111 | simplecov-html (~> 0.7.1) 112 | simplecov-html (0.7.1) 113 | slop (3.4.4) 114 | sprockets (2.2.2) 115 | hike (~> 1.2) 116 | multi_json (~> 1.0) 117 | rack (~> 1.0) 118 | tilt (~> 1.1, != 1.3.0) 119 | terminal-table (1.4.5) 120 | thor (0.17.0) 121 | tilt (1.4.1) 122 | treetop (1.4.14) 123 | polyglot 124 | polyglot (>= 0.3.1) 125 | tzinfo (0.3.37) 126 | 127 | PLATFORMS 128 | ruby 129 | 130 | DEPENDENCIES 131 | bluecloth (~> 2.2.0) 132 | excellent (~> 1.6.0) 133 | growl (~> 1.0.3) 134 | guard (~> 1.6.2) 135 | guard-rspec (~> 2.5.1) 136 | highlight! 137 | rails (~> 3.2.0) 138 | rb-fsevent (~> 0.9.3) 139 | rspec (~> 2.13.0) 140 | simplecov (~> 0.7.1) 141 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | notification :growl 2 | 3 | guard :rspec do 4 | watch(%r{^lib/(.+)\.rb$}) { 'spec' } 5 | watch(%r{^generators/(.+)$}) { 'spec' } 6 | watch('spec/spec_helper.rb') { 'spec' } 7 | watch(%r{^spec/.+_spec\.rb$}) 8 | end 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2018 simplabs GmbH and contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Highlight 2 | ========= 3 | 4 | [](https://travis-ci.org/simplabs/highlight) 5 | 6 | Highlight is a simple syntax highlighting gem for Ruby and Rails. It's basically a 7 | wrapper around the popular [http://pygments.org](http://pygments.org) highlighter that's 8 | written in Python and supports an impressive number of languages. 9 | 10 | If pygments is installed on the machine and in the `PATH`, that binary is used, otherwise 11 | the plugin falls back to the web API at [http://pygments.simplabs.com/](http://pygments.simplabs.com/), 12 | created by Trevor Turk. 13 | 14 | See the API docs at [http://rdoc.info/projects/simplabs/highlight](http://rdoc.info/projects/simplabs/highlight). 15 | 16 | Usage 17 | ----- 18 | 19 | Highlight can either be used standalone via 20 | 21 | ```ruby 22 | require 'simplabs/highlight' 23 | Simplabs::Highlight.highlight(:ruby, 'class Test; end') 24 | ``` 25 | 26 | or in Rails where it adds the `highlight_code` helper: 27 | 28 | ```ruby 29 | highlight_code(language, code = nil, &block) 30 | ``` 31 | 32 | `language` may be either a Symbol or a String (see supported languages 33 | below). The code can be passed either as a string or inside a block, e.g.: 34 | 35 | ```ruby 36 | highlight_code(:ruby, 'class Test; end') 37 | ``` 38 | 39 | or 40 | 41 | ```ruby 42 | highlight_code(:ruby) do 43 | klass = 'class' 44 | name = 'Test' 45 | _end = 'end' 46 | "#{klass} #{name}; #{_end}" 47 | end 48 | ``` 49 | 50 | Since highlighting the code takes a while, all highlighted source code 51 | should be cached, e.g.: 52 | 53 | ```ruby 54 | <%- code = 'class Test; end' -%> 55 | <%- cache Digest::SHA1.hexdigest(code) do -%> 56 | <%= highlight_code(:ruby, code) -%> 57 | <%- end -%> 58 | ``` 59 | 60 | 61 | Supported Languages 62 | ------------------- 63 | 64 | The following languages are supported (there are probably more that are supported by `pygments`). 65 | All of the paranthesized identifiers may be used as parameters for highlight to denote the 66 | language the source code to highlight is written in (use either Symbols or Strings). 67 | 68 | * Actionscript (`as`, `as3`, `actionscript`) 69 | * Applescript (`applescript`) 70 | * bash (`bash`, `sh`) 71 | * C (`c`, `h`) 72 | * Clojure (`clojure`) 73 | * C++ (`c++`, `cpp`, `hpp`) 74 | * C# (`c#`, `csharp`, `cs`) 75 | * CSS (`css`) 76 | * diff (`diff`) 77 | * Dylan (`dylan`) 78 | * Erlang (`erlang`, `erl`, `er`) 79 | * HTML (`html`, `htm`) 80 | * Java (`java`) 81 | * JavaScript (`javascript`, `js`, `jscript`) 82 | * JSP (`jsp`) 83 | * Make (`make`, `basemake`, `makefile`) 84 | * Objective-C (`objective-c`) 85 | * OCaml (`ocaml`) 86 | * Perl (`perl`, `pl`) 87 | * PHP (`php`) 88 | * Python (`python`, `py`) 89 | * RHTML (`erb`, `rhtml`) 90 | * Ruby (`ruby`, `rb`) 91 | * Scala (`scala`) 92 | * Scheme (`scheme`) 93 | * Smalltalk (`smalltalk`) 94 | * Smarty (`smarty`) 95 | * SQL (`sql`) 96 | * XML (`xml`, `xsd`) 97 | * XSLT (`xslt`) 98 | * YAML (`yaml`, `yml`) 99 | 100 | 101 | Installation 102 | ------------ 103 | 104 | Installation is as easy as 105 | 106 | ```bash 107 | gem install highlight 108 | ``` 109 | 110 | To use highlight in Rails apps, you have to define the dependency in the Gemfile: 111 | 112 | ```ruby 113 | gem 'highlight', :require => 'simplabs/highlight' 114 | ``` 115 | 116 | Highlight also comes with a default CSS file that defines styles for the highlighted code. This CSS file can be copied to 117 | your application's `public/stylesheets` directory via 118 | 119 | ```bash 120 | ./bin/rails generate highlight_styles 121 | ``` 122 | 123 | If you don't have python and pygments installed, you will need that too. 124 | For instructions on installing pygments, refer to 125 | [http://pygments.org/docs/installation/](http://pygments.org/docs/installation/). 126 | 127 | 128 | Author 129 | ------ 130 | 131 | Copyright (c) 2008-2010 Marco Otte-Witte ([http://simplabs.com](http://simplabs.com)), 132 | released under the MIT license 133 | 134 | 135 | Acknowledgements 136 | ---------------- 137 | 138 | The actual highlighting is done by Pygments ([http://pygments.org](http://pygments.org)). 139 | -------------------------------------------------------------------------------- /generators/highlight_styles_generator/highlight_styles_generator.rb: -------------------------------------------------------------------------------- 1 | if Rails::VERSION::MAJOR >= 3 2 | 3 | class HighlightStylesGenerator < Rails::Generators::Base 4 | 5 | include Rails::Generators::Actions 6 | 7 | source_root File.expand_path('../templates', __FILE__) 8 | 9 | def create_stylesheet_file 10 | empty_directory('public/stylesheets') 11 | copy_file( 12 | 'highlight.css', 13 | 'public/stylesheets/highlight.css' 14 | ) 15 | readme(File.join(File.dirname(__FILE__), 'templates', 'NOTES')) 16 | end 17 | 18 | end 19 | 20 | else 21 | 22 | class HighlightStylesGenerator < Rails::Generator::Base 23 | 24 | def manifest 25 | record do |m| 26 | m.directory('public/stylesheets') 27 | m.file('highlight.css', 'public/stylesheets/highlight.css') 28 | m.readme('NOTES') 29 | end 30 | end 31 | 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /generators/highlight_styles_generator/templates/NOTES: -------------------------------------------------------------------------------- 1 | 2 | ** Don't forget to include highlight.css in your layout's head section. 3 | 4 | -------------------------------------------------------------------------------- /generators/highlight_styles_generator/templates/highlight.css: -------------------------------------------------------------------------------- 1 | .c { color: #408080; font-style: italic } /* Comment */ 2 | .err { border: 1px solid #FF0000 } /* Error */ 3 | .k { color: #008000; font-weight: bold } /* Keyword */ 4 | .o { color: #666666 } /* Operator */ 5 | .cm { color: #408080; font-style: italic } /* Comment.Multiline */ 6 | .cp { color: #BC7A00 } /* Comment.Preproc */ 7 | .c1 { color: #408080; font-style: italic } /* Comment.Single */ 8 | .cs { color: #408080; font-style: italic } /* Comment.Special */ 9 | .gd { color: #A00000 } /* Generic.Deleted */ 10 | .ge { font-style: italic } /* Generic.Emph */ 11 | .gr { color: #FF0000 } /* Generic.Error */ 12 | .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 13 | .gi { color: #00A000 } /* Generic.Inserted */ 14 | .go { color: #808080 } /* Generic.Output */ 15 | .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ 16 | .gs { font-weight: bold } /* Generic.Strong */ 17 | .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 18 | .gt { color: #0040D0 } /* Generic.Traceback */ 19 | .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ 20 | .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ 21 | .kp { color: #008000 } /* Keyword.Pseudo */ 22 | .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ 23 | .kt { color: #B00040 } /* Keyword.Type */ 24 | .m { color: #666666 } /* Literal.Number */ 25 | .s { color: #BA2121 } /* Literal.String */ 26 | .na { color: #7D9029 } /* Name.Attribute */ 27 | .nb { color: #008000 } /* Name.Builtin */ 28 | .nc { color: #0000FF; font-weight: bold } /* Name.Class */ 29 | .no { color: #880000 } /* Name.Constant */ 30 | .nd { color: #AA22FF } /* Name.Decorator */ 31 | .ni { color: #999999; font-weight: bold } /* Name.Entity */ 32 | .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ 33 | .nf { color: #0000FF } /* Name.Function */ 34 | .nl { color: #A0A000 } /* Name.Label */ 35 | .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ 36 | .nt { color: #008000; font-weight: bold } /* Name.Tag */ 37 | .nv { color: #19177C } /* Name.Variable */ 38 | .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ 39 | .w { color: #bbbbbb } /* Text.Whitespace */ 40 | .mf { color: #666666 } /* Literal.Number.Float */ 41 | .mh { color: #666666 } /* Literal.Number.Hex */ 42 | .mi { color: #666666 } /* Literal.Number.Integer */ 43 | .mo { color: #666666 } /* Literal.Number.Oct */ 44 | .sb { color: #BA2121 } /* Literal.String.Backtick */ 45 | .sc { color: #BA2121 } /* Literal.String.Char */ 46 | .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ 47 | .s2 { color: #BA2121 } /* Literal.String.Double */ 48 | .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ 49 | .sh { color: #BA2121 } /* Literal.String.Heredoc */ 50 | .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ 51 | .sx { color: #008000 } /* Literal.String.Other */ 52 | .sr { color: #BB6688 } /* Literal.String.Regex */ 53 | .s1 { color: #BA2121 } /* Literal.String.Single */ 54 | .ss { color: #19177C } /* Literal.String.Symbol */ 55 | .bp { color: #008000 } /* Name.Builtin.Pseudo */ 56 | .vc { color: #19177C } /* Name.Variable.Class */ 57 | .vg { color: #19177C } /* Name.Variable.Global */ 58 | .vi { color: #19177C } /* Name.Variable.Instance */ 59 | .il { color: #666666 } /* Literal.Number.Integer.Long */ 60 | -------------------------------------------------------------------------------- /highlight.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | 3 | pkg_files = [ 4 | 'README.md', 5 | 'HISTORY.md', 6 | 'LICENSE' 7 | ] 8 | pkg_files += Dir['generators/**/*'] 9 | pkg_files += Dir['lib/**/*.rb'] 10 | pkg_files += Dir['rails/**/*.rb'] 11 | pkg_files += Dir['spec/**/*.{rb,yml,opts}'] 12 | 13 | Gem::Specification.new do |s| 14 | 15 | s.name = %q{highlight} 16 | s.version = '2.0.0' 17 | 18 | s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to?(:required_rubygems_version=) 19 | s.authors = ['Marco Otte-Witte'] 20 | s.date = %q{2013-03-23} 21 | s.email = %q{info@simplabs.com} 22 | s.files = pkg_files 23 | s.homepage = %q{http://github.com/simplabs/highlight} 24 | s.license = 'MIT' 25 | s.require_path = 'lib' 26 | s.rubygems_version = %q{1.3.0} 27 | s.has_rdoc = false 28 | s.summary = %q{Syntax Higlighting plugin for Ruby on Rails } 29 | s.description = %q{Highlight highlights code in more than 20 languages. It uses the Pygments syntax highlighter and adds a simple Ruby API over it. It also provides helpers for use in your Ruby on Rails views.} 30 | 31 | if s.respond_to?(:specification_version) then 32 | current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION 33 | s.specification_version = 2 34 | end 35 | 36 | end 37 | -------------------------------------------------------------------------------- /lib/simplabs/highlight.rb: -------------------------------------------------------------------------------- 1 | require 'cgi' 2 | require 'net/http' 3 | require 'uri' 4 | require 'simplabs/highlight/pygments_wrapper' 5 | 6 | module Simplabs 7 | 8 | require 'simplabs/highlight/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3 9 | 10 | # Highlight is a simple syntax highlighting plugin for Ruby on Rails. 11 | # It's basically a wrapper around the popular http://pygments.org 12 | # highlighter that's written in Python and supports an impressive 13 | # number of languages. If pygments is installed on the machine and in 14 | # the +PATH+, that binary is used, otherwise the plugin falls back 15 | # to the web API at (http://pygments.simplabs.com/), created by Trevor 16 | # Turk. 17 | # 18 | # Supported Languages 19 | # 20 | # The following languages are supported. All of the paranthesized 21 | # identifiers may be used as parameters for the +highlight+ method to 22 | # denote the language the source code to highlight is written in (use 23 | # either Symbols or Strings). 24 | # 25 | # * Actionscript (+as+, +as3+, +actionscript+) 26 | # * Applescript (+applescript+) 27 | # * bash (+bash+, +sh+) 28 | # * C (+c+, +h+) 29 | # * Clojure (+clojure+) 30 | # * CoffeeScript (+coffee+) 31 | # * C++ (+c+++, +cpp+, +hpp+) 32 | # * C# (+c#+, +csharp+, +cs+) 33 | # * CSS (+css+) 34 | # * diff (+diff+) 35 | # * Dylan (+dylan+) 36 | # * Erlang (+erlang+, +erl+, +er+) 37 | # * HTML (+html+, +htm+) 38 | # * Java (+java+) 39 | # * JavaScript (+javascript+, +js+, +jscript+) 40 | # * JSP (+jsp+) 41 | # * Make (+make+, +basemake+, +makefile+) 42 | # * NASM (+nasm+, +asm+) 43 | # * Objective-C (+objective-c+) 44 | # * OCaml (+ocaml+) 45 | # * Perl (+perl+, +pl+) 46 | # * PHP (+php+) 47 | # * Python (+python+, +py+) 48 | # * RHTML (+erb+, +rhtml+) 49 | # * Ruby (+ruby+, +rb+) 50 | # * Scala (+scala+) 51 | # * Scheme (+scheme+) 52 | # * Smalltalk (+smalltalk+) 53 | # * Smarty (+smarty+) 54 | # * SQL (+sql+) 55 | # * XML (+xml+, +xsd+) 56 | # * XSLT (+xslt+) 57 | # * YAML (+yaml+, +yml+) 58 | # 59 | module Highlight 60 | 61 | class << self 62 | attr_accessor :use_web_api 63 | end 64 | 65 | SUPPORTED_LANGUAGES = { 66 | :as => ['as', 'as3', 'actionscript'], 67 | :applescript => ['applescript'], 68 | :bash => ['bash', 'sh'], 69 | :c => ['c', 'h'], 70 | :clojure => ['clojure'], 71 | :coffeescript => ['coffeescript', 'coffee'], 72 | :cpp => ['c++', 'cpp', 'hpp'], 73 | :csharp => ['c#', 'csharp', 'cs'], 74 | :css => ['css'], 75 | :diff => ['diff'], 76 | :dylan => ['dylan'], 77 | :erlang => ['erlang'], 78 | :html => ['html', 'htm'], 79 | :java => ['java'], 80 | :js => ['javascript', 'js', 'jscript'], 81 | :jsp => ['jsp'], 82 | :lua => ['lua'], 83 | :make => ['make', 'basemake', 'makefile'], 84 | :nasm => ['nasm', 'asm'], 85 | :'objective-c' => ['objective-c'], 86 | :ocaml => ['ocaml'], 87 | :perl => ['perl', 'pl'], 88 | :php => ['php'], 89 | :python => ['python', 'py'], 90 | :rhtml => ['erb', 'rhtml'], 91 | :ruby => ['ruby', 'rb'], 92 | :scala => ['scala'], 93 | :scheme => ['scheme'], 94 | :smallralk => ['smalltalk'], 95 | :smarty => ['smarty'], 96 | :sql => ['sql', 'mysql'], 97 | :xml => ['xml', 'xsd'], 98 | :xslt => ['xslt'], 99 | :yaml => ['yaml', 'yml'] 100 | } 101 | 102 | WEB_API_URL = 'http://pygments.simplabs.com/' 103 | 104 | # Highlights the passed +code+ with the appropriate rules 105 | # according to the specified +language+. 106 | # 107 | # @param [Symbol, String] language 108 | # the language the +code+ is in 109 | # @param [String] code 110 | # the actual code to highlight 111 | # 112 | # @return [String] 113 | # the highlighted +code+ or simply the HTML-escaped code if +language+ 114 | # is not supported. 115 | # 116 | def self.highlight(language, code) 117 | language = get_language_sym(language) 118 | return CGI.escapeHTML(code) unless language 119 | if Simplabs::Highlight.use_web_api 120 | highlight_with_web_api(language, code) 121 | else 122 | Simplabs::Highlight::PygmentsWrapper.new(code, language).highlight 123 | end 124 | end 125 | 126 | # View Helpers for using {Highlight} in Ruby on Rails templates. 127 | # 128 | module ViewMethods 129 | 130 | # Highlights the passed +code+ with the appropriate rules 131 | # according to the specified +language+. The code can be specified 132 | # either as a string or provided in a block. 133 | # 134 | # @param [Symbol, String] language 135 | # the language the +code+ is in 136 | # @param [String] code 137 | # the actual code to highlight 138 | # @yield 139 | # the +code+ can also be specified as result of a given block. 140 | # 141 | # @return [String] 142 | # the highlighted +code+ or simply the HTML-escaped code if +language+ 143 | # is not supported. 144 | # 145 | # @example Specifying the code to highlight as a String 146 | # 147 | # highlight_code(:ruby, 'class Test; end') 148 | # 149 | # @example Specifying the code to highlight in a block 150 | # 151 | # highlight_code(:ruby) do 152 | # klass = 'class' 153 | # name = 'Test' 154 | # _end = 'end' 155 | # "#{klass} #{name}; #{_end}" 156 | # end 157 | # 158 | # @raise [ArgumentError] if both the +code+ parameter and a block are given 159 | # @raise [ArgumentError] if neither the +code+ parameter or a block are given 160 | # 161 | # @see Simplabs::Highlight.highlight 162 | # 163 | def highlight_code(language, code = nil, &block) 164 | raise ArgumentError.new('Either pass a srting containing the code or a block, not both!') if !code.nil? && block_given? 165 | raise ArgumentError.new('Pass a srting containing the code or a block!') if code.nil? && !block_given? 166 | code ||= yield 167 | Simplabs::Highlight.highlight(language, code) 168 | end 169 | 170 | end 171 | 172 | private 173 | 174 | def self.highlight_with_web_api(language, code) 175 | request = Net::HTTP.post_form(URI.parse(WEB_API_URL), { 176 | 'lang' => language, 177 | 'code' => code 178 | }) 179 | request.body.gsub(/\A\
/, '').gsub(/\n\<\/pre\>\<\/div\>\n/, '')
180 | end
181 |
182 | def self.get_language_sym(name)
183 | SUPPORTED_LANGUAGES.each_pair do |key, value|
184 | return key if value.any? { |lang| lang == name.to_s }
185 | end
186 | return false
187 | end
188 |
189 | end
190 |
191 | end
192 |
--------------------------------------------------------------------------------
/lib/simplabs/highlight/pygments_wrapper.rb:
--------------------------------------------------------------------------------
1 | module Simplabs
2 |
3 | module Highlight
4 |
5 | # Wraps the actual +pygments+ syntax highlighter and
6 | # exposes its functionality to Ruby code.
7 | #
8 | class PygmentsWrapper
9 |
10 | # The code the wrapper highlights
11 | #
12 | attr_reader :code
13 |
14 | # The language the {Simplabs::Highlight::PygmentsWrapper#code} to highlight is in
15 | #
16 | attr_reader :language
17 |
18 | # Initializes a new {Simplabs::Highlight::PygmentsWrapper}.
19 | #
20 | # @param [String] code
21 | # the actual code to highlight
22 | # @param [String, Symbol] language
23 | # the language the +code+ to highlight is in
24 | #
25 | def initialize(code, language)
26 | @code = code
27 | @language = language
28 | end
29 |
30 | # Highlights the {Simplabs::Highlight::PygmentsWrapper#code}.
31 | #
32 | # @return [String]
33 | # the highlighted code or simply the HTML-escaped code
34 | # if the language is not supported.
35 | #
36 | def highlight(options = {})
37 | command = "pygmentize -f html -O nowrap=true -l #{@language}"
38 | IO.popen(command, mode = 'r+') do |pygments|
39 | pygments << @code
40 | pygments.close_write
41 | result = pygments.read.chomp
42 | end
43 | end
44 |
45 | end
46 |
47 | end
48 |
49 | end
50 |
--------------------------------------------------------------------------------
/lib/simplabs/highlight/railtie.rb:
--------------------------------------------------------------------------------
1 | require 'simplabs/highlight'
2 | require 'rails'
3 |
4 | module Simplabs
5 |
6 | module Highlight
7 |
8 | class Railtie < Rails::Railtie
9 |
10 | GEM_ROOT = File.join(File.dirname(__FILE__), '..', '..', '..')
11 |
12 | initializer 'simplabs.highlight.initialization' do
13 | require File.join(GEM_ROOT, 'rails', 'init')
14 | end
15 |
16 | generators do
17 | require File.join(GEM_ROOT, 'generators', 'highlight_styles_generator', 'highlight_styles_generator')
18 | end
19 |
20 | end
21 |
22 | end
23 |
24 | end
25 |
--------------------------------------------------------------------------------
/rails/init.rb:
--------------------------------------------------------------------------------
1 | require 'action_view'
2 | require 'simplabs/highlight'
3 |
4 | if `which pygmentize`.blank?
5 | puts ''
6 | puts " ** [Highlight] pygments cannot be found, falling back to #{Simplabs::Highlight::WEB_API_URL}! **"
7 | puts ' ** If you have pygments installed, make sure it is in your PATH. **'
8 | puts ''
9 | Simplabs::Highlight.use_web_api = true
10 | else
11 | Simplabs::Highlight.use_web_api = false
12 | end
13 |
14 | ActionView::Base.class_eval do
15 | include Simplabs::Highlight::ViewMethods
16 | end
17 |
--------------------------------------------------------------------------------
/spec/boot.rb:
--------------------------------------------------------------------------------
1 | plugin_root = File.join(File.dirname(__FILE__), '..')
2 |
3 | require File.join(File.dirname(__FILE__), '/../rails/init.rb')
4 |
--------------------------------------------------------------------------------
/spec/lib/highlight_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Simplabs::Highlight do
4 |
5 | let(:code) do
6 | <<-EOC
7 | class Test
8 | def method test
9 | end
10 | end
11 | EOC
12 | end
13 |
14 | describe '#highlight' do
15 |
16 | shared_examples 'the highlight method' do
17 |
18 | describe 'when the language is not supported' do
19 |
20 | it 'should only escape HTML in the passed code' do
21 | expect(Simplabs::Highlight.highlight(:unsupported, code)).to eq(CGI.escapeHTML(code))
22 | end
23 |
24 | end
25 |
26 | describe 'when the language is supported' do
27 |
28 | it 'should correctly highlight source code passed as parameter' do
29 | expect(Simplabs::Highlight.highlight(:ruby, code)).to eq(
30 | %Q(class Test\n def method test\n end\nend)
31 | )
32 | end
33 |
34 | end
35 |
36 | end
37 |
38 | describe 'when pygments is used directly' do
39 |
40 | before do
41 | Simplabs::Highlight.use_web_api = false
42 | end
43 |
44 | it_behaves_like 'the highlight method'
45 |
46 | it 'should initialize a Simplabs::PygmentsWrapper.highlight with the language and code' do
47 | wrapper = Simplabs::Highlight::PygmentsWrapper.new(code, :ruby)
48 |
49 | Simplabs::Highlight::PygmentsWrapper.should_receive(:new).once.with(code, :ruby).and_return(wrapper)
50 |
51 | Simplabs::Highlight.highlight(:ruby, code)
52 | end
53 |
54 | end
55 |
56 | describe 'when the web API is used' do
57 |
58 | before do
59 | Simplabs::Highlight.use_web_api = true
60 | end
61 |
62 | it_behaves_like 'the highlight method'
63 |
64 | end
65 |
66 | end
67 |
68 | describe '.get_language_sym' do
69 |
70 | describe 'for an unsupported language' do
71 |
72 | it 'should return false' do
73 | expect(Simplabs::Highlight.send(:get_language_sym, 'unsupported language')).to be_false
74 | end
75 |
76 | end
77 |
78 | describe 'for a supported language' do
79 |
80 | it 'should return the respective symbol when the languages was given as String' do
81 | expect(Simplabs::Highlight.send(:get_language_sym, 'ruby')).to eq(:ruby)
82 | end
83 |
84 | it 'should return the respective symbol when the languages was given as Symbol' do
85 | expect(Simplabs::Highlight.send(:get_language_sym, :rb)).to eq(:ruby)
86 | end
87 |
88 | end
89 |
90 | end
91 |
92 | end
93 |
--------------------------------------------------------------------------------
/spec/lib/pygments_wrapper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Simplabs::Highlight::PygmentsWrapper do
4 |
5 | let(:wrapper) do
6 | code = <<-EOC
7 | class Test
8 | def method test
9 | end
10 | end
11 | EOC
12 | Simplabs::Highlight::PygmentsWrapper.new(code, :ruby)
13 | end
14 |
15 | describe '#highlight' do
16 |
17 | it 'should correctly highlight source code passed as parameter' do
18 | expect(wrapper.highlight).to eq(
19 | %Q(class Test\n def method test\n end\nend)
20 | )
21 | end
22 |
23 | end
24 |
25 | end
26 |
--------------------------------------------------------------------------------
/spec/lib/view_methods_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Simplabs::Highlight::ViewMethods do
4 |
5 | include Simplabs::Highlight::ViewMethods
6 |
7 | let(:code) { 'class Test; end' }
8 |
9 | describe '#highlight_code' do
10 |
11 | describe 'when invoked with a language and a string' do
12 |
13 | it 'should highlight the code' do
14 | Simplabs::Highlight.should_receive(:highlight).once.with(:ruby, code)
15 |
16 | highlight_code(:ruby, code)
17 | end
18 |
19 | end
20 |
21 | describe 'when invoked with a language and a block' do
22 |
23 | it 'should highlight the code' do
24 | Simplabs::Highlight.should_receive(:highlight).once.with(:ruby, code)
25 |
26 | highlight_code(:ruby) do
27 | code
28 | end
29 | end
30 |
31 | end
32 |
33 | describe 'when invoked with both a string and a block' do
34 |
35 | it 'should raise an ArgumentError' do
36 | expect { highlight_code(:ruby, code) { code } }.to raise_error(ArgumentError)
37 | end
38 |
39 | end
40 |
41 | describe 'when invoked with neither a string nor a block' do
42 |
43 | it 'should raise an ArgumentError' do
44 | expect { highlight_code(:ruby) }.to raise_error(ArgumentError)
45 | end
46 |
47 | end
48 |
49 | end
50 |
51 | end
52 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | $:.reject! { |e| e.include? 'TextMate' }
2 |
3 | ENV['RAILS_ENV'] = 'test'
4 |
5 | require 'rubygems'
6 | require 'bundler'
7 | Bundler.setup
8 |
9 | require File.join(File.dirname(__FILE__), 'boot')
10 |
--------------------------------------------------------------------------------
/uninstall.rb:
--------------------------------------------------------------------------------
1 | puts ''
2 | puts " ** Be sure to delete highlight.css from #{RAILS_ROOT}/public/stylesheets/ if you don't need it anymore! **"
3 | puts ''
--------------------------------------------------------------------------------