markover 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +102 -0
  4. data/bin/markover +31 -0
  5. data/config/style.css +174 -0
  6. data/ext/github_markup.rb +11 -0
  7. data/lib/markover.rb +31 -0
  8. data/lib/markover/config.rb +28 -0
  9. data/lib/markover/converter.rb +120 -0
  10. data/lib/markover/markup.rb +28 -0
  11. data/lib/markover/markup/code.rb +40 -0
  12. data/lib/markover/markup/code_block.rb +30 -0
  13. data/lib/markover/markup/renderer.rb +67 -0
  14. data/lib/markover/markup/yaml_frontmatter_remover.rb +17 -0
  15. data/lib/markover/markupfile.rb +67 -0
  16. data/lib/markover/optionparser.rb +93 -0
  17. data/lib/markover/path.rb +29 -0
  18. data/lib/markover/version.rb +6 -0
  19. data/lib/markover/wkhtmltopdf.rb +39 -0
  20. data/spec/fixtures/autolink_url.md +3 -0
  21. data/spec/fixtures/code_block.textile +8 -0
  22. data/spec/fixtures/code_block_with_utf8.textile +7 -0
  23. data/spec/fixtures/code_with_utf8.textile +6 -0
  24. data/spec/fixtures/integration/markdown.md +60 -0
  25. data/spec/fixtures/integration/style.css +3 -0
  26. data/spec/fixtures/integration/textile.textile +47 -0
  27. data/spec/fixtures/long_code_block.md +5 -0
  28. data/spec/fixtures/recursion/level1.textile +1 -0
  29. data/spec/fixtures/recursion/level2/level2.markdown +1 -0
  30. data/spec/fixtures/table.md +7 -0
  31. data/spec/fixtures/yaml_front_matter.textile +7 -0
  32. data/spec/integration_spec.rb +41 -0
  33. data/spec/markover/converter_spec.rb +124 -0
  34. data/spec/markover/markup/code_block_spec.rb +21 -0
  35. data/spec/markover/markup/code_spec.rb +45 -0
  36. data/spec/markover/markup/renderer_spec.rb +18 -0
  37. data/spec/markover/markup/yaml_frontmatter_remover_spec.rb +21 -0
  38. data/spec/markover/markup_file_spec.rb +45 -0
  39. data/spec/markover/path_spec.rb +32 -0
  40. data/spec/markover/wkhtmltopdf_spec.rb +35 -0
  41. data/spec/spec_helper.rb +11 -0
  42. metadata +228 -0
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ # This file is based on the markup class in gollum - https://github.com/github/gollum
4
+ # (The MIT License)
5
+ #
6
+ # Copyright (c) Tom Preston-Werner, Rick Olson
7
+
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the 'Software'), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+
15
+ require 'digest/sha1'
16
+
17
+ require 'github/markup'
18
+ require 'nokogiri'
19
+
20
+ require 'markover/markup/yaml_frontmatter_remover'
21
+ require 'markover/markup/code'
22
+ require 'markover/markup/code_block'
23
+ require 'markover/markup/renderer'
24
+
25
+ module Markover
26
+ module Markup
27
+ end
28
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ module Markover
4
+
5
+ module Markup
6
+
7
+ # Class that knows how to extract code blocks and render them with syntax highlightning
8
+ class Code
9
+
10
+ def initialize
11
+ @code_blocks = []
12
+ end
13
+
14
+ # Extract all code blocks into the codemap and replace with placeholders.
15
+ #
16
+ # @return [String] Returns the placeholder'd String data.
17
+ def extract(data)
18
+ data.gsub!(/^``` ?([^\r\n]+)?\r?\n(.+?)\r?\n```\r?$/m) do
19
+ id = Digest::SHA1.hexdigest($2)
20
+ @code_blocks << CodeBlock.new(id, $1, $2)
21
+ id
22
+ end
23
+ data
24
+ end
25
+
26
+ # Process all code from the codemap and replace the placeholders with the
27
+ # final HTML.
28
+ #
29
+ # @return [String] Returns the marked up String data.
30
+ def process(data)
31
+ return data if data.nil? || data.size.zero? || @code_blocks.size.zero?
32
+ @code_blocks.each do |block|
33
+ data.gsub!(block.id, block.highlighted)
34
+ end
35
+ data
36
+ end
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ require 'coderay'
4
+
5
+ module Markover
6
+
7
+ module Markup
8
+
9
+ # Class that contains data for a code block
10
+ class CodeBlock
11
+ attr_reader :id, :language, :code
12
+
13
+ def initialize(id, language, code)
14
+ @id, @language, @code = id, language, code
15
+ end
16
+
17
+ # Returns the code with syntax highlightning
18
+ # @return [String]
19
+ def highlighted
20
+ if @language
21
+ CodeRay.scan(@code, @language).html(:line_numbers => :table)
22
+ else
23
+ CodeRay.scan(@code, :text).div
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ module Markover
4
+
5
+ module Markup
6
+
7
+ # Contains functionality to render html from a markup file
8
+ class Renderer
9
+ # Initialize a new Markup object.
10
+ #
11
+ # @param [Markover::File] file The Markover::File to process
12
+ # @param [Boolean] do_remove_yaml_front_matter Should we remove the front matter?
13
+ # @return [Markover::Markup]
14
+ def initialize(file, do_remove_yaml_front_matter = false)
15
+ @file = file
16
+ @do_remove_yaml_front_matter = do_remove_yaml_front_matter
17
+
18
+ @data = file.data
19
+ @code = Code.new
20
+ @yaml_frontmatter_remover = YamlFrontmatterRemover.new
21
+ end
22
+
23
+ # Render the content with Gollum wiki syntax on top of the file's own
24
+ # markup language.
25
+ #
26
+ # @return [String] The formatted data
27
+ def render
28
+ prepare_data
29
+ render_data
30
+ post_process_data
31
+
32
+ return @data
33
+ end
34
+
35
+ private
36
+
37
+ # Prepare data for rendering
38
+ def prepare_data
39
+ @data = @yaml_frontmatter_remover.process(@data) if @do_remove_yaml_front_matter
40
+ @data = @code.extract(@data)
41
+ end
42
+
43
+ # Do the markup to html rendering
44
+ def render_data
45
+ begin
46
+ @data = @data.force_encoding('utf-8') if @data.respond_to? :force_encoding
47
+ @data = GitHub::Markup.render(@file.filename, @data)
48
+ if @data.nil?
49
+ raise "There was an error converting #{@file.name} to HTML."
50
+ end
51
+ rescue Object => e
52
+ @data = %{<p class="markover-error">#{e.message}</p>}
53
+ end
54
+ end
55
+
56
+ # Do post processing on data
57
+ def post_process_data
58
+ @data = @code.process(@data)
59
+ doc = Nokogiri::HTML::DocumentFragment.parse(@data, 'UTF-8')
60
+ @data = doc.to_xhtml(:save_with => Nokogiri::XML::Node::SaveOptions::AS_XHTML, :encoding => 'UTF-8')
61
+ @data.gsub!(/<p><\/p>/, '')
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ module Markover
4
+
5
+ module Markup
6
+
7
+ # Class that knows how to remove yaml front matter
8
+ class YamlFrontmatterRemover
9
+
10
+ # Removes YAML Front Matter
11
+ # Useful if you want to PDF your Jekyll site.
12
+ def process(data)
13
+ data.gsub /^(---\s*\n.*?\n?)^(---\s*$\n?)/m, ''
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ module Markover
4
+
5
+ # Class used to load files and determine if they are valid
6
+ class MarkupFile
7
+ attr_reader :filename, :name, :data, :format
8
+
9
+ # Accepted formats
10
+ FORMATS = [:markdown, :textile, :rdoc, :org, :creole, :rest, :asciidoc, :pod, :roff, :mediawiki]
11
+
12
+ # Initializes the file object. Only reads contents if it's a valid file
13
+ def initialize(filename)
14
+ @filename = filename
15
+ extension = ::File.extname(@filename)
16
+ @format = load_format(extension)
17
+ @name = ::File.basename(@filename, extension)
18
+ @data = ::File.open(@filename, 'rb') { |f| f.read } if valid? && ::File.exists?(@filename)
19
+ end
20
+
21
+ # Is the file valid
22
+ # @return [Boolean]
23
+ def valid?
24
+ valid_format? @format
25
+ end
26
+
27
+ # Converts the format to a symbol if it's a valid format nil otherwise
28
+ # @param [String] format
29
+ # @return [Symbol|nil]
30
+ def load_format(format)
31
+ case format.to_s
32
+ when /(md|mkdn?|mdown|markdown)$/i
33
+ :markdown
34
+ when /(textile)$/i
35
+ :textile
36
+ when /(rdoc)$/i
37
+ :rdoc
38
+ when /(org)$/i
39
+ :org
40
+ when /(creole)$/i
41
+ :creole
42
+ when /(re?st(\.txt)?)$/i
43
+ :rest
44
+ when /(asciidoc)$/i
45
+ :asciidoc
46
+ when /(pod)$/i
47
+ :pod
48
+ when /(\d)$/i
49
+ :roff
50
+ when /(media)?wiki$/i
51
+ :mediawiki
52
+ else
53
+ nil
54
+ end
55
+ end
56
+
57
+ # Checks if the format is a valid one
58
+ # @param [String] format
59
+ # @return [Boolean]
60
+ def valid_format?(format)
61
+ return false if format.nil?
62
+
63
+ FORMATS.include? format.to_sym
64
+ end
65
+ end
66
+ end
67
+
@@ -0,0 +1,93 @@
1
+ require 'optparse'
2
+ require 'markover/version'
3
+
4
+ module Markover
5
+ class Parser
6
+ def self.parse!(args)
7
+ new.parse!(args)
8
+ end
9
+
10
+ def parse!(args)
11
+ return {} if args.empty?
12
+ options = {
13
+ outputdir: nil,
14
+ stylesheet: nil,
15
+ recursive: false,
16
+ merge: false,
17
+ filename: nil,
18
+ debug: false,
19
+ wkhtmltopdfparameters: '',
20
+ removefrontmatter: false,
21
+ table_of_contents: false
22
+ }
23
+ parser(options).parse!(args)
24
+ options
25
+ end
26
+
27
+ def parser(options)
28
+ OptionParser.new do |parser|
29
+ parser.banner = 'Usage: markover [options] [files or directories]'
30
+ parser.separator ''
31
+ parser.separator 'Options'
32
+
33
+ parser.on('-o', '--output-dir', '=OUTDIR',
34
+ 'Save parsed files to OUTDIR. Defaults to working directory.') do |value|
35
+
36
+ options[:outputdir] = value
37
+ end
38
+
39
+ parser.on('-s', '--stylesheet', '=SHEET',
40
+ 'Override standard stylesheet with SHEET') do |value|
41
+
42
+ options[:stylesheet] = value
43
+ end
44
+
45
+ parser.on('-r', '--recursive',
46
+ 'Recurse current or target directory and convert all valid markup files') do
47
+
48
+ options[:recursive] = true
49
+ end
50
+
51
+ parser.on('-m', '--merge', '=FILENAME',
52
+ 'Merge any and all passed markup files into single file of the specified name') do |value|
53
+
54
+ options[:merge] = true
55
+ options[:filename] = value
56
+ end
57
+
58
+ parser.on('-d', '--debug', 'Dumps HTML output to stdout') do |value|
59
+ options[:debug] = true
60
+ end
61
+
62
+ parser.on('-w', '--wkhtmltopdf-params', '=PARAMS',
63
+ 'Parameters to be passed on to wkhtmltopdf. Use "" if more than one parameter. See wkhtmltopdf usage for possible parameters.') do |value|
64
+ options[:wkhtmltopdfparameters] = value
65
+ end
66
+
67
+ parser.on('-o', '--remove-front-matter', 'Remove yaml frontmatter from your files.') do
68
+ options[:removefrontmatter] = true
69
+ end
70
+
71
+ parser.on('-n', '--output-filename', '=FILENAME',
72
+ 'Sets the name of the output file. Only used with single file and in merge mode.') do |value|
73
+
74
+ options[:filename] = value
75
+ end
76
+
77
+ parser.on('-t', '--toc', 'Generate a table of contents') do
78
+ options[:table_of_contents] = true
79
+ end
80
+
81
+ parser.on('-v', '--version', 'Show version information and quit') do
82
+ puts Markover::Version
83
+ exit
84
+ end
85
+
86
+ parser.on('-?', '-h', '--help', 'Show this message') do
87
+ puts parser
88
+ exit
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ module Markover
4
+
5
+ # Class used to interact with directory structure
6
+ class Path
7
+
8
+ # Return an array of paths to valid markup file matching the passed pattern
9
+ # @param [String] target
10
+ # @param [Bool] recursive
11
+ # @return [Array] an array of valid files
12
+ def self.list_valid(target, recursive = false)
13
+ if recursive
14
+ target ||= Dir.pwd
15
+ if File.directory?(target)
16
+ target = File.join(target, '**', '*')
17
+ end
18
+ else
19
+ target ||= Dir.pwd
20
+ if File.directory?(target)
21
+ target = File.join(target, '*')
22
+ end
23
+ end
24
+
25
+ # Use select to support ruby 1.8
26
+ Dir.glob(target).select { |file| MarkupFile.new(file).valid? }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ module Markover
4
+ VERSION = "0.6.0"
5
+ end
6
+
@@ -0,0 +1,39 @@
1
+ module Markover
2
+
3
+ # The class that communicates with wkhtmltopdf
4
+ class Wkhtmltopdf
5
+
6
+ # Set up options for wkhtmltopdf
7
+ # @param [String] parameters
8
+ def initialize(parameters = nil)
9
+ @parameters = parameters
10
+ end
11
+
12
+ # Convert the html to pdf and write it to file
13
+ # @param [String] html the html input
14
+ # @param [String] filename the name of the output file
15
+ def output_pdf(html, filename)
16
+ args = command(filename)
17
+ invoke = args.join(' ')
18
+
19
+ IO.popen(invoke, "wb+") do |pdf|
20
+ pdf.puts(html)
21
+ pdf.close_write
22
+ pdf.gets(nil)
23
+ end
24
+ end
25
+
26
+ # Assemble the command to run
27
+ # @param [String] filename the outputed pdf's filename
28
+ # @return [Array] a list of strings that make out the call to wkhtmltopdf
29
+ def command(filename)
30
+ [bin, @parameters, '--quiet', '-', "\"#{filename}\""].compact
31
+ end
32
+
33
+ # Find the wkhtmltopdf binary
34
+ # @return [String] the path to the binary
35
+ def bin
36
+ @bin ||= "\"#{(`which wkhtmltopdf`).chomp}\""
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ # Autolink url
2
+
3
+ Autolink this https://github.com url.
@@ -0,0 +1,8 @@
1
+ a
2
+
3
+ ```ruby
4
+ x = 1
5
+ ```
6
+
7
+ b
8
+
@@ -0,0 +1,7 @@
1
+ Abcåäö
2
+
3
+ ```html
4
+ <h1>Abcåäö</h1>
5
+ <img src="åäö.png" alt="ÅÄÖ" />
6
+ ```
7
+