diff --git a/README.adoc b/README.adoc index 20f8205..fa471fd 100644 --- a/README.adoc +++ b/README.adoc @@ -641,6 +641,40 @@ You need to augment the layout to include resources typically present in a stand ---- +=== Stylesheet for Code Highlighting + +Asciidoctor integrates with Pygments to provide code highlighting of source blocks in AsciiDoc content. +This integration is separate from the Pygments integration in Jekyll. +As part of this integration, Asciidoctor generates a custom stylesheet tailored specially to work with the HTML that Asciidocotor produces. +Since this stylesheet is backed by the Pygments API, it provides access to all the themes in Pygments + +This plugin will automatically generate a stylesheet for Pygments into the source directory if the AsciiDoc attributes in your site's {path-config} are configured as follows: + +* `source-highlighter` has the value `pygments` +* `pygments-css` has the value `class` or is not set +* `pygments-stylesheet` is not unset (if set, it can have any value) + +By default, the stylesheet is written to `stylesdir` + `pygments-stylesheet`. +If the `pygments-stylesheet` attribute is not specified, the value defaults to `asciidoc-pygments.css`. +You can customize this value to your liking. + +The Pygments theme is selected by the value of the `pygments-style` attribute. +If this attribute is not set, it defaults to `vs`. + +The stylesheet file will be created if it does not yet exist or the theme has been changed. +Jekyll will handle copying the file to the output directory. + +You'll need to add a line to your template to link to this stylesheet, such as: + +[source,html] +---- + +---- + +To disable this feature, either set the `pygments-css` to `style` (to enable inline styles) or unset the `pygments-stylesheet` attribute in your site's {path-config}. + +NOTE: It may still be necessary to make some tweaks to your site's stylesheet to accomodate this integration. + === Font-based Admonition and Inline Icons To enable font-based admonition and inline icons, you first need to add Font Awesome to [path]_{empty}_includes/head.html_ file under the asciidoc.css declaration: diff --git a/jekyll-asciidoc.gemspec b/jekyll-asciidoc.gemspec index 235e499..dc4b653 100644 --- a/jekyll-asciidoc.gemspec +++ b/jekyll-asciidoc.gemspec @@ -24,4 +24,5 @@ Gem::Specification.new do |s| s.add_development_dependency 'rake' s.add_development_dependency 'rspec', '~> 3.0' + s.add_development_dependency 'pygments.rb', '~> 0.6.3' unless RUBY_ENGINE == 'jruby' end diff --git a/lib/jekyll-asciidoc/integrator.rb b/lib/jekyll-asciidoc/integrator.rb index ae4abbc..df24050 100644 --- a/lib/jekyll-asciidoc/integrator.rb +++ b/lib/jekyll-asciidoc/integrator.rb @@ -42,6 +42,12 @@ def generate site (converter.matches doc.extname) ? (integrate doc, name) : true end end + + if (attrs = site.config['asciidoctor'][:attributes]) && + ((attrs['source-highlighter'] || '').chomp '@') == 'pygments' && + ((attrs['pygments-css'] || '').chomp '@') != 'style' && attrs.fetch('pygments-stylesheet', '') + generate_pygments_stylesheet site, attrs + end end # Integrate the page-related attributes from the AsciiDoc document header @@ -86,6 +92,28 @@ def integrate document, collection_name = nil document.extend NoLiquid unless document.data['liquid'] document.data.fetch 'published', true end + + def generate_pygments_stylesheet site, attrs + css_base = site.source + unless (css_dir = (attrs['stylesdir'] || '').chomp '@').empty? || (css_dir.start_with? '/') + css_dir = %(/#{css_dir}) + end + if (css_name = attrs['pygments-stylesheet']).nil_or_empty? + css_name = 'asciidoc-pygments.css' + end + css_file = ::File.join css_base, css_dir, css_name + css_style = (attrs['pygments-style'] || 'vs').chomp '@' + css = ::Asciidoctor::Stylesheets.instance.pygments_stylesheet_data css_style + # NOTE apply stronger CSS rule for general text color + css = css.sub('.listingblock .pygments {', '.listingblock .pygments, .listingblock .pygments code {') + if site.static_files.any? {|f| f.path == css_file } + ::IO.write css_file, css unless css == (::IO.read css_file) + else + ::Asciidoctor::Helpers.mkdir_p(::File.dirname css_file) + ::IO.write css_file, css + site.static_files << (::Jekyll::StaticFile.new site, css_base, css_dir, css_name) + end + end end end end diff --git a/spec/fixtures/pygments_code_highlighting/_config.yml b/spec/fixtures/pygments_code_highlighting/_config.yml new file mode 100644 index 0000000..645a23b --- /dev/null +++ b/spec/fixtures/pygments_code_highlighting/_config.yml @@ -0,0 +1,6 @@ +gems: + - jekyll-asciidoc +asciidoctor: + attributes: + - stylesdir=/css + - source-highlighter=pygments@ diff --git a/spec/fixtures/pygments_code_highlighting/_layouts/page.html b/spec/fixtures/pygments_code_highlighting/_layouts/page.html new file mode 100644 index 0000000..a09117a --- /dev/null +++ b/spec/fixtures/pygments_code_highlighting/_layouts/page.html @@ -0,0 +1,13 @@ + + + + +{{ page.title }} + + + +
+{{ content }} +
+ + diff --git a/spec/fixtures/pygments_code_highlighting/page-with-code.adoc b/spec/fixtures/pygments_code_highlighting/page-with-code.adoc new file mode 100644 index 0000000..63761ca --- /dev/null +++ b/spec/fixtures/pygments_code_highlighting/page-with-code.adoc @@ -0,0 +1,16 @@ += Code + +```ruby +class NilClass + alias :nil_or_empty? :nil? +end + +class String + def nil_or_empty? + alias :nil_or_empty? :empty? + end +end + +v = nil +puts v.nil_or_empty? +``` diff --git a/spec/jekyll-asciidoc_spec.rb b/spec/jekyll-asciidoc_spec.rb index c40dd2a..c95ca73 100644 --- a/spec/jekyll-asciidoc_spec.rb +++ b/spec/jekyll-asciidoc_spec.rb @@ -765,6 +765,55 @@ end if ::Jekyll::MIN_VERSION_3 end + describe 'pygments code highlighting' do + let :name do + 'pygments_code_highlighting' + end + + before :each do + site.process + end + + it 'should write the pygments stylesheet to the stylesdir' do + src_file = source_file 'css/asciidoc-pygments.css' + out_file = output_file 'css/asciidoc-pygments.css' + begin + expect(::File).to exist(src_file) + expect(::File).to exist(out_file) + src_content = ::File.read src_file + out_content = ::File.read out_file + expect(src_content).to eql(out_content) + ensure + if ::File.exist? src_file + ::File.delete src_file + ::Dir.rmdir(::File.dirname src_file) + end + end + end + + it 'should overwrite pygments stylesheet if style has changed' do + src_file = source_file 'css/asciidoc-pygments.css' + out_file = output_file 'css/asciidoc-pygments.css' + begin + src_content = ::File.read src_file + out_content = ::File.read src_file + attrs = site.config['asciidoctor'][:attributes] + attrs['pygments-style'] = 'monokai' + integrator = site.generators.find {|g| ::Jekyll::AsciiDoc::Integrator === g } + integrator.generate_pygments_stylesheet site, attrs + expect(::File.read src_file).not_to eql(src_content) + ::Jekyll::StaticFile.reset_cache + site.process + expect(::File.read out_file).not_to eql(out_content) + ensure + if ::File.exist? src_file + ::File.delete src_file + ::Dir.rmdir(::File.dirname src_file) + end + end + end + end unless RUBY_ENGINE == 'jruby' + describe 'xhtml syntax' do let :name do 'xhtml_syntax'