markover 0.6.0

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.
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
+