transmuter 0.0.0.1 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -2,3 +2,5 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ *.html
6
+ *.pdf
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ script: "rake spec"
2
+ env: JRUBY_OPTS="--1.9"
3
+ rvm:
4
+ - 1.9.2
5
+ - 1.9.3
6
+ notifications:
7
+ recipients:
8
+ - wael.nasreddine@gmail.com
data/Gemfile CHANGED
@@ -2,3 +2,20 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in transmuter.gemspec
4
4
  gemspec
5
+
6
+ platforms :ruby do
7
+ # Require rbconfig to figure out the target OS
8
+ require 'rbconfig'
9
+
10
+ unless ENV['TRAVIS']
11
+ if RbConfig::CONFIG['target_os'] =~ /darwin/i
12
+ gem 'rb-fsevent', require: false
13
+ gem 'ruby-growl', require: false
14
+ gem 'growl', require: false
15
+ end
16
+ if RbConfig::CONFIG['target_os'] =~ /linux/i
17
+ gem 'rb-inotify', require: false
18
+ gem 'libnotify', require: false
19
+ end
20
+ end
21
+ end
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'bundler' do
5
+ watch('Gemfile')
6
+ watch(/^.+\.gemspec/)
7
+ end
8
+
9
+ guard 'rspec', :version => 2 do
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
12
+ watch('spec/spec_helper.rb') { "spec" }
13
+ end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Transmuter
1
+ # Transmuter [![Build Status](http://travis-ci.org/TechnoGate/transmuter.png)](http://travis-ci.org/TechnoGate/transmuter)
2
2
 
3
3
  Transmuter is a command line tool to convert Markdown files into HTML or PDF
4
4
  files, it can also be used to convert HTML files to PDF, it uses in the
@@ -6,6 +6,8 @@ backgound [Redcarper](https://github.com/tanoku/redcarpet),
6
6
  [Albino](https://github.com/github/albino) and
7
7
  [PDFkit](https://github.com/jdpace/PDFKit).
8
8
 
9
+ <a href='http://www.pledgie.com/campaigns/16086'><img alt='Click here to lend your support to: Transmuter and make a donation at www.pledgie.com !' src='http://www.pledgie.com/campaigns/16086.png?skin_name=chrome' border='0' /></a>
10
+
9
11
  # Installation
10
12
 
11
13
  To install Transmuter use the command
@@ -35,3 +37,35 @@ $ sudo easy_install pygments
35
37
  2. Try using the wkhtmltopdf-binary gem (mac + linux i386)
36
38
 
37
39
  gem install wkhtmltopdf-binary
40
+
41
+ # Usage
42
+
43
+ You should check the help
44
+
45
+ ```bash
46
+ $ transmute --help
47
+ ```
48
+
49
+ To Generate a PDF from a markdown file with the default CSS:
50
+
51
+ ```bash
52
+ $ transmute file.md
53
+ ```
54
+
55
+ To Generate an HTML from a markdown file with the default CSS:
56
+
57
+ ```bash
58
+ $ transmute file.md -t html
59
+ ```
60
+
61
+ To Generate an HTML from a markdown file with custom CSS:
62
+
63
+ ```bash
64
+ $ transmute file.md -t html -s custom.css
65
+ ```
66
+
67
+ Custom CSS files can be be multiple path separated by a space, for example:
68
+
69
+ ```bash
70
+ $ transmute file.md -t html -s custom1.css custom2.css
71
+ ```
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ # Require RSpec tasks
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ # The default task is tests
8
+ task :default => :spec
data/bin/transmute ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ $:.push File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+
6
+ require 'transmuter'
7
+ Transmuter::CLI::Runner.start
@@ -0,0 +1,99 @@
1
+ require 'thor'
2
+ require 'thor/group'
3
+
4
+ module Transmuter
5
+ module CLI
6
+ module Thor
7
+
8
+ def self.included(base)
9
+ base.send :include, InstanceMethods
10
+ end
11
+
12
+ module InstanceMethods
13
+ def self.included(base)
14
+ base.class_eval <<-END, __FILE__, __LINE__ + 1
15
+ desc "Transmute one file format into another."
16
+
17
+ class_option :input_format,
18
+ type: :string,
19
+ required: false,
20
+ aliases: "-f",
21
+ desc: "The input format."
22
+
23
+ class_option :output_format,
24
+ type: :string,
25
+ required: false,
26
+ aliases: "-t",
27
+ default: "pdf",
28
+ desc: "The output format."
29
+
30
+ class_option :stylesheets,
31
+ type: :array,
32
+ required: false,
33
+ aliases: "-s",
34
+ default: [DEFAULT_THEME],
35
+ desc: "The stylesheets."
36
+
37
+ argument :input,
38
+ type: :string,
39
+ required: true,
40
+ aliases: "-i",
41
+ desc: "The input file name."
42
+
43
+ argument :output,
44
+ type: :string,
45
+ required: false,
46
+ aliases: "-o",
47
+ desc: "The output file name."
48
+
49
+ def set_input_filename
50
+ @input_filename = input
51
+ end
52
+
53
+ def set_input_fileformat
54
+ @input_fileformat = options[:input_format] || input_format
55
+ end
56
+
57
+ def set_output_fileformat
58
+ @output_fileformat = options[:output_format]
59
+ end
60
+
61
+ def set_output_filename
62
+ if output.blank? && options[:output_format].blank?
63
+ raise ArgumentError, "Either output or output_format should be given,"
64
+ end
65
+
66
+ @output_filename = output || output_file
67
+ end
68
+
69
+ def set_stylesheets
70
+ @stylesheets = options[:stylesheets]
71
+ end
72
+
73
+ def transmute_input_to_output
74
+ transmute!
75
+ end
76
+
77
+ protected
78
+
79
+ def input_format
80
+ case @input.split('.').last
81
+ when /^(md|markdown)$/
82
+ "markdown"
83
+ when /^(html|htm)/
84
+ "html"
85
+ else
86
+ raise ArgumentError, "No format was given and format could not be parsed from the file name"
87
+ end
88
+ end
89
+
90
+ def output_file
91
+ output = @input_filename.dup
92
+ output.gsub(/^(.+)\\.[^.]*$/, "\\\\1.\#{@output_fileformat}")
93
+ end
94
+ END
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,67 @@
1
+ module Transmuter
2
+ module CLI
3
+ module Transmute
4
+ def self.included(base)
5
+ base.send :include, InstanceMethods
6
+ end
7
+
8
+ module InstanceMethods
9
+ def transmute!
10
+ set_klasses!
11
+ set_methods
12
+ verify_klasses!
13
+
14
+ source_klass_instance = @source_klass.new(read_input_file, parse_transmute_options)
15
+ output = source_klass_instance.send(@source_transform_method)
16
+
17
+ write_output_file(output)
18
+ end
19
+
20
+ def transmute
21
+ transmute!
22
+ rescue Exception => e
23
+ handle_error(e)
24
+ end
25
+
26
+ protected
27
+ def handle_error(exception)
28
+ # TODO: Handle error properly
29
+ end
30
+
31
+ def set_klasses!
32
+ @source_klass ||= "::Transmuter::Format::#{@input_fileformat.to_s.camelcase}".constantize
33
+ @destination_klass ||= "::Transmuter::Format::#{@output_fileformat.to_s.camelcase}".constantize
34
+ end
35
+
36
+ def set_methods
37
+ @source_transform_method ||= "to_#{@output_fileformat.to_s.downcase}".to_sym
38
+ @destination_process_method ||= :process
39
+ end
40
+
41
+ def verify_klasses!
42
+
43
+ raise NotImplementedError,
44
+ "#{@source_klass} does not respond to #{@source_transform_method}" unless
45
+ @source_klass.public_instance_methods.include?(@source_transform_method)
46
+
47
+ raise NotImplementedError,
48
+ "#{@destination_klass} does not respond to #{@destination_process_method}" unless
49
+ @destination_klass.public_instance_methods.include?(@destination_process_method)
50
+ end
51
+
52
+ def read_input_file
53
+ @input_file_contents ||= File.read(@input_filename)
54
+ end
55
+
56
+ def write_output_file(contents)
57
+ File.open(@output_filename, 'w') { |f| f.write(contents) }
58
+ end
59
+
60
+ def parse_transmute_options
61
+ { stylesheets: @stylesheets }
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,13 @@
1
+ require 'transmuter/cli/thor'
2
+ require 'transmuter/cli/transmute'
3
+
4
+ module Transmuter
5
+ module CLI
6
+ class Runner < ::Thor::Group
7
+ DEFAULT_THEME = File.expand_path(File.join(ROOT_PATH, 'stylesheets', 'default.css'))
8
+
9
+ include Transmute
10
+ include Thor
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ require 'active_support/core_ext'
2
+ require 'active_support/dependencies/autoload'
3
+
4
+ Dir["#{File.dirname(__FILE__)}/core_ext/**/*.rb"].each { |f| require f }
@@ -0,0 +1,81 @@
1
+ require 'albino'
2
+ require 'nokogiri'
3
+
4
+ module Transmuter
5
+ module Format
6
+ class Html
7
+
8
+ def initialize(html, options = {})
9
+ parse_options(options)
10
+ @html = html
11
+ end
12
+
13
+ def to_pdf
14
+ html = process
15
+ pdf = Pdf.new(html, get_options)
16
+ pdf.process
17
+ end
18
+
19
+ def process
20
+ include_inline_stylesheets(syntax_highlighter)
21
+ end
22
+
23
+ protected
24
+ def get_options
25
+ options = @options.dup
26
+ options.delete(:redcarpet_options)
27
+ options
28
+ end
29
+
30
+ def parse_options(options)
31
+ @options = options.dup
32
+ end
33
+
34
+ def read_stylesheet_files
35
+ case @options[:stylesheets]
36
+ when Array
37
+ @options[:stylesheets].collect do |f|
38
+ File.read(f)
39
+ end.join("\n")
40
+ when String
41
+ File.read @options[:stylesheets]
42
+ when NilClass
43
+ # Apparently no stylesheets has been requested
44
+ end
45
+ end
46
+
47
+ def include_inline_stylesheets(html)
48
+ if @options[:stylesheets].present?
49
+ stylesheet_contents = read_stylesheet_files
50
+
51
+ doc = Nokogiri::HTML(html)
52
+ head = doc.xpath('/html/head').first
53
+
54
+ style = Nokogiri::XML::Node.new "style", doc
55
+ style['type'] = "text/css"
56
+ style.content = stylesheet_contents
57
+
58
+ unless head.present?
59
+ head = Nokogiri::XML::Node.new "head", doc
60
+ body = doc.xpath('/html/body').first
61
+ body.add_previous_sibling head
62
+ end
63
+
64
+ style.parent = head
65
+
66
+ html = doc.to_s
67
+ end
68
+
69
+ html
70
+ end
71
+
72
+ def syntax_highlighter
73
+ doc = Nokogiri::HTML(@html)
74
+ doc.search("//pre[@lang]").each do |pre|
75
+ pre.replace Albino.colorize(pre.text.rstrip, pre[:lang].downcase.to_sym)
76
+ end
77
+ doc.to_s
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,45 @@
1
+ require 'redcarpet'
2
+
3
+ module Transmuter
4
+ module Format
5
+ class Markdown
6
+ REDCARPET_OPTIONS = [:autolink, :no_intraemphasis, :fenced_code, :gh_blockcode]
7
+
8
+ def initialize(markdown, options = {})
9
+ parse_options(options)
10
+ @markdown = markdown
11
+ end
12
+
13
+ def to_pdf
14
+ html = to_html
15
+ pdf = Pdf.new(html, get_options)
16
+ pdf.process
17
+ end
18
+
19
+ def to_html
20
+ html = Html.new(parse_markdown, get_options)
21
+ html.process
22
+ end
23
+
24
+ protected
25
+ def get_options
26
+ options = @options.dup
27
+ options.delete(:redcarpet_options)
28
+ options
29
+ end
30
+
31
+ def parse_options(options)
32
+ options = options.dup
33
+ @options = options.merge!(:redcarpet_options => REDCARPET_OPTIONS)
34
+ end
35
+
36
+ def create_markdown
37
+ Redcarpet.new(@markdown, *@options[:redcarpet_options])
38
+ end
39
+
40
+ def parse_markdown
41
+ create_markdown.to_html
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ require 'pdfkit'
2
+
3
+ module Transmuter
4
+ module Format
5
+ class Pdf
6
+
7
+ def initialize(html, options = {})
8
+ parse_options(options)
9
+ @html = html
10
+ end
11
+
12
+ def process
13
+ kit = PDFKit.new(@html, :page_size => @options[:page_size])
14
+
15
+ kit.to_pdf
16
+ end
17
+
18
+ protected
19
+ def parse_options(options)
20
+ options = options.dup
21
+ @options = options.merge!(:page_size => 'Letter')
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ module Transmuter
2
+ module Format
3
+ extend ::ActiveSupport::Autoload
4
+
5
+ autoload :Markdown
6
+ autoload :Html
7
+ autoload :Pdf
8
+ end
9
+ end
@@ -1,8 +1,7 @@
1
1
  module Transmuter
2
2
  MAJOR = 0
3
3
  MINOR = 0
4
- BUILD = 0
5
- REVISION = 1
4
+ PATCH = 1
6
5
 
7
- VERSION = [MAJOR, MINOR, BUILD, REVISION].join('.')
8
- end
6
+ VERSION = [MAJOR, MINOR, PATCH].join('.')
7
+ end
data/lib/transmuter.rb CHANGED
@@ -1,5 +1,6 @@
1
- require "transmuter/version"
1
+ ROOT_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..'))
2
2
 
3
- module Transmuter
4
- # Your code goes here...
5
- end
3
+ require "transmuter/version"
4
+ require "transmuter/core_ext"
5
+ require "transmuter/format"
6
+ require "transmuter/cli"
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ ROOT_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+ $:.push File.expand_path("#{ROOT_PATH}/lib")
4
+
5
+ require 'rubygems'
6
+ require 'rspec'
7
+
8
+ # Require the library
9
+ require 'transmuter'
10
+
11
+ include Transmuter
12
+
13
+ # Require support files
14
+ Dir[ROOT_PATH + "/spec/support/**/*.rb"].each {|f| require f}
15
+
16
+ RSpec.configure do |config|
17
+ # == Mock Framework
18
+ #
19
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
20
+ #
21
+ config.mock_with :mocha
22
+ # config.mock_with :flexmock
23
+ # config.mock_with :rr
24
+ # config.mock_with :rspec
25
+ end