kui-md 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *~
19
+ .rbenv-version
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in md.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Keiichiro Ui
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ kui-md
2
+ ====================================
3
+
4
+ 自分向けの markdown 変換器。Graphviz によるグラフ作成や、Pygments.rb による
5
+ コードのシンタックスハイライトもできる。
6
+
7
+
8
+ インストール
9
+ ----------------------------------
10
+
11
+ 下記のコマンドを実行する。
12
+
13
+ ~~~~~~~~~~~~~~~~~sh
14
+ $ gem install kui-md
15
+ ~~~~~~~~~~~~~~~~~
16
+
17
+
18
+ 使い方
19
+ ----------------------------------
20
+
21
+ こんな感じで markdown の変換ができる。
22
+
23
+ ~~~~~~~~~~~~~~~~~sh
24
+ $ md -h
25
+ $ md foo.markdown
26
+ $ md foo.markdown output.html
27
+ ~~~~~~~~~~~~~~~~~
28
+
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ # -*- coding:utf-8-unix; mode:ruby; -*-
3
+
4
+ require "bundler/gem_tasks"
5
+ require "rspec/core"
6
+ require "rspec/core/rake_task"
7
+
8
+ desc "Run all specs in spec/*_spec.rb"
9
+ RSpec::Core::RakeTask.new :spec
10
+
11
+ task :build => :spec
12
+ task :default => :spec
data/bin/md ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding:utf-8-unix; mode:ruby; -*-
3
+
4
+ require 'rubygems'
5
+ require 'md'
6
+
7
+ Md::CLI::run *ARGV
@@ -0,0 +1,26 @@
1
+ # -*- coding:utf-8; mode:ruby; -*-
2
+
3
+ title_format "%s - メモ"
4
+
5
+ # see https://github.com/tanoku/redcarpet
6
+ enable_markdown_opts :fenced_code_blocks, :tables, :no_intra_emphasis, :autolink,
7
+ :strikethrough, :space_after_headers, :superscript
8
+ enable_html_opts
9
+
10
+ # see `pygmentize -H formatter html`
11
+ pygments_opts({
12
+ :cssclass => 'hll',
13
+ :classprefix => 'pyg',
14
+ #:linenos => 'table',
15
+ #:linenos => 'inline',
16
+ :linenos => nil,
17
+ :style => 'native',
18
+ })
19
+
20
+ css <<EOS
21
+ h1, h2, h3, h4, h5, h6, p, ul, ol, pre, div {
22
+ color: #333;
23
+ }
24
+ EOS
25
+
26
+ script "// foo"
@@ -0,0 +1,12 @@
1
+ # -*- coding:utf-8-unix; mode:ruby; -*-
2
+
3
+ require 'md/version'
4
+ require 'md/configure'
5
+ require 'md/renderer'
6
+ require 'md/cli'
7
+
8
+ module Md
9
+ USAGE = <<EOS
10
+ Usage: #{$0} SOURCE_FILE [ DEST_FILE ]
11
+ EOS
12
+ end
@@ -0,0 +1,110 @@
1
+ # -*- coding:utf-8-unix; mode:ruby; -*-
2
+
3
+ require 'optparse'
4
+
5
+ module Md
6
+
7
+ # a command line interface
8
+ class CLI
9
+
10
+ DEFAULT_CONFIG_NAME = ".md/config.rb"
11
+ DEFAULT_CONFIG_PATH = File.join ENV['HOME'], DEFAULT_CONFIG_NAME
12
+
13
+ def self.run *args
14
+ new.run *args
15
+ end
16
+
17
+ # a configure file path
18
+ attr_reader :config_file
19
+
20
+ # a render options
21
+ attr_reader :opts
22
+
23
+ # a command which will be executed
24
+ attr_reader :cmd
25
+
26
+ # a usage message
27
+ attr_reader :usage
28
+
29
+ def initialize
30
+ @config_file = DEFAULT_CONFIG_PATH
31
+ @cmd = :render
32
+ @usage = USAGE
33
+ @opts = {}
34
+ end
35
+
36
+ def run *args
37
+ load_config
38
+ parse_opts args
39
+ begin
40
+ method(@cmd).call(args[0], args[1])
41
+ rescue Exception => e
42
+ if $DEBUG
43
+ raise e
44
+ else
45
+ err 1, "ERROR: #{e.message}"
46
+ end
47
+ end
48
+ end
49
+
50
+ def parse_opts args
51
+ opt = OptionParser.new USAGE
52
+
53
+ opt.on('-c VAL', '--config VAL',
54
+ "specify a configure file. (default: '#{DEFAULT_CONFIG_PATH}')") do |v|
55
+ @config_file = v
56
+ end
57
+
58
+ opt.on('--with-wrapping-html',
59
+ 'wrap the converted html with html and body elements') do
60
+ @opts[:wrapping_html] = true
61
+ end
62
+ opt.on('--without-wrapping-html',
63
+ 'do not wrap the converted html with html and body elements') do
64
+ @opts[:wrapping_html] = false
65
+ end
66
+
67
+ opt.parse! args
68
+ @usage = opt.help
69
+ end
70
+
71
+ def err code = 1, msg = nil
72
+ puts msg if msg
73
+ puts @usage
74
+ exit code
75
+ end
76
+
77
+ def load_config
78
+ if not File.exists? @config_file
79
+ require 'fileutils'
80
+ FileUtils.mkdir_p File.dirname @config_file
81
+ FileUtils.touch @config_file
82
+ end
83
+ config = Configure.new(@config_file)
84
+ @opts.merge! config[:html]
85
+
86
+ [:markdown, :pygments, :css, :script, :wrapping_html, :title_format].each do |s|
87
+ @opts[s] = config[s] if config[s]
88
+ end
89
+ end
90
+
91
+ # a default command
92
+ def render src, dest
93
+ if not src
94
+ raise ArgumentError, "expect to specify a src file"
95
+ end
96
+
97
+ renderer = Md::Renderer.new @opts
98
+ open src do |f|
99
+ result = Redcarpet::Markdown.new(renderer, @opts[:markdown]).render f.read
100
+ if dest
101
+ open dest, 'w' do |w|
102
+ w.write result
103
+ end
104
+ else
105
+ print result
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,143 @@
1
+ # -*- coding:utf-8-unix; mode:ruby; -*-
2
+
3
+ require 'forwardable'
4
+
5
+ module Md
6
+
7
+ # a config DSL parser
8
+ class Configure
9
+
10
+ # options for Redcarpet::Render::HTML
11
+ KNOWN_HTML_OPTS = [
12
+ :filter_html,
13
+ :no_images,
14
+ :no_links,
15
+ :no_styles,
16
+ :safe_links_only,
17
+ :with_toc_data,
18
+ :hard_wrap,
19
+ :xhtml,
20
+ ]
21
+
22
+ # options for Redcarpet::Markdown
23
+ KNOWN_MARKDOWN_OPTS = [
24
+ :no_intra_emphasis,
25
+ :tables,
26
+ :fenced_code_blocks,
27
+ :autolink,
28
+ :strikethrough,
29
+ :lax_html_blocks,
30
+ :space_after_headers ,
31
+ :superscript,
32
+ ]
33
+
34
+ KNOWN_PYGMENTS_OPTS = [
35
+ # specify a formatter
36
+ # see `pygmentize -L formatters`
37
+ #:formatter,
38
+
39
+ # options for HtmlFormatter
40
+ # see `pygmentize -H formatter html`
41
+ :nowrap,
42
+ :full,
43
+ :title,
44
+ :style,
45
+ :noclasses,
46
+ :classprefix,
47
+ :cssclass,
48
+ :cssstyles,
49
+ :prestyles,
50
+ :cssfile,
51
+ :noclobber_cssfile,
52
+ :linenos,
53
+ :hl_lines,
54
+ :linenostart,
55
+ :linenostep,
56
+ :linenospecial,
57
+ :nobackground,
58
+ :lineseparator,
59
+ :lineanchors,
60
+ :anchorlinenos,
61
+ ]
62
+
63
+ extend Forwardable
64
+ def_delegators :@map, :[]
65
+
66
+ def initialize file_path = nil
67
+ @map = {}
68
+ @map[:html] = Hash[*KNOWN_HTML_OPTS.map{|o|[o,false]}.flatten]
69
+ @map[:markdown] = Hash[*KNOWN_MARKDOWN_OPTS.map{|o|[o,false]}.flatten]
70
+ @map[:pygments] = {}
71
+ @map[:css] = []
72
+ @map[:script] = []
73
+ @renderer = nil
74
+ include file_path if file_path
75
+ end
76
+
77
+ def include file_path
78
+ open file_path do |f|
79
+ eval f.read
80
+ end
81
+ end
82
+
83
+ def wrapping_html bool
84
+ @map[:wrapping_html] = bool
85
+ end
86
+
87
+ def css style
88
+ raise "expect a String" if not style.kind_of? String
89
+ @map[:css].push style
90
+ end
91
+
92
+ def script src
93
+ raise "expect a String" if not src.kind_of? String
94
+ @map[:script].push src
95
+ end
96
+
97
+ def title_format format
98
+ if not format.kind_of? String
99
+ raise "expect a String"
100
+ end
101
+ @map[:title_format] = format
102
+ end
103
+
104
+ def enable_html_opts *opts
105
+ opts.each {|o| html_opt o, true }
106
+ end
107
+
108
+ def disable_html_opts *opts
109
+ opts.each {|o| html_opt o, false }
110
+ end
111
+
112
+ def enable_markdown_opts *opts
113
+ opts.each {|o| markdown_opt o, true}
114
+ end
115
+
116
+ def disable_markdown_opts *opts
117
+ opts.each {|o| markdown_opt o, false}
118
+ end
119
+
120
+ def pygments_opts *args
121
+ if args.first.kind_of? Hash
122
+ @map[:pygments].merge! args.first
123
+ else
124
+ if args.length != 2
125
+ raise 'expect a hash or a pair with an option name and a value'
126
+ end
127
+ o, v = args
128
+ raise "unknown pygments option (#{o})" if not KNOWN_PYGMENTS_OPTS.include? o
129
+ @map[:pygments][o] = v
130
+ end
131
+ end
132
+
133
+ def html_opt o, v
134
+ raise "unknown html option (#{o})" if not KNOWN_HTML_OPTS.include? o
135
+ @map[:html][o] = v
136
+ end
137
+
138
+ def markdown_opt o, v
139
+ raise "unknown markdown option (#{o})" if not KNOWN_MARKDOWN_OPTS.include? o
140
+ @map[:markdown][o] = v
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,114 @@
1
+ # -*- coding:utf-8; mode:ruby; -*-
2
+
3
+ require 'redcarpet'
4
+ require 'pygments'
5
+ require 'graphviz'
6
+
7
+ module Md
8
+ class Renderer < Redcarpet::Render::HTML
9
+
10
+ attr_accessor :opts
11
+
12
+ def initialize opts = {}
13
+ super
14
+ @opts = opts
15
+ @opts[:pygments] ||= {}
16
+ @opts[:graphviz] ||= {
17
+ :format => :svg
18
+ }
19
+ @opts[:graphviz][:format] ||= :svg
20
+ @opts[:wrapping_html] = true if not @opts.key? :wrapping_html
21
+ @opts[:css] ||= []
22
+ @opts[:script] ||= []
23
+ @opts[:title_format] ||= "%s"
24
+
25
+ @opts[:css].push Pygments.css @opts[:pygments]
26
+ end
27
+
28
+ def block_code code, lang
29
+ if lang.casecmp('graphviz') == 0
30
+ block_code_graphviz code
31
+ elsif lang.casecmp('graph') == 0
32
+ block_code_graph code
33
+ elsif lang.casecmp('digraph') == 0
34
+ block_code_digraph code
35
+ else
36
+ block_code_default code, lang
37
+ end
38
+ end
39
+
40
+ def block_code_default code, lang
41
+ @opts[:pygments][:full] = false
42
+ opts = {:lexer => lang, :options => @opts[:pygments]}
43
+ return Pygments.highlight code, opts
44
+ end
45
+
46
+ def block_code_digraph code
47
+ block_code_digraph "digraph g { #{code} }"
48
+ end
49
+
50
+ def block_code_graph code
51
+ block_code_graphviz "graph g { #{code} }"
52
+ end
53
+
54
+ def block_code_graphviz code
55
+ opts = {:svg => String}
56
+ block_code_svg GraphViz.parse_string(code).output(opts)
57
+ end
58
+
59
+ def block_code_svg code
60
+ remove_doctype_declaration remove_xml_declaration code
61
+ end
62
+
63
+ def remove_doctype_declaration code
64
+ code.sub(/<!DOCTYPE .+?>/im,'')
65
+ end
66
+
67
+ def remove_xml_declaration code
68
+ code.sub(/<\?xml .+?\?>/im,'')
69
+ end
70
+
71
+ def postprocess html
72
+ html = wrapp_with_html html if @opts[:wrapping_html]
73
+ return html
74
+ end
75
+
76
+ def wrapp_with_html html
77
+ return "<!DOCTYPE html>\n" +
78
+ "<html><head>\n" +
79
+ head_element_content(html) +
80
+ "</head>\n"+
81
+ "<body>#{html}</body></html>\n"
82
+ end
83
+
84
+ def head_element_content html
85
+ content = ""
86
+
87
+ content << %{<meta charset="utf-8" />\n}
88
+
89
+ title = scrape_title html
90
+ content << "<title>#{@opts[:title_format]}</title>\n" % title if title
91
+
92
+ @opts[:css].each do |style|
93
+ content << "<style>#{minify_css style}</style>\n"
94
+ end if @opts[:css]
95
+
96
+ @opts[:script].each do |src|
97
+ content << "<script>\n#{src}\n</script>\n"
98
+ end if @opts[:script]
99
+
100
+ return content
101
+ end
102
+
103
+ # get first h1, h2 or h3 element content
104
+ def scrape_title html
105
+ m = html.match(/<h[1-3][^>]*>(.+?)<\/h[1-3]>/)
106
+ return (m and m[1])
107
+ end
108
+
109
+ # remove space and new line code
110
+ def minify_css text
111
+ text.gsub(%r{/\*.+?\*/}, '').gsub(/\s+/,'')
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,3 @@
1
+ module Md
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ # -*- coding:utf-8-unix; mode:ruby; -*-
2
+
3
+ require File.expand_path('../lib/md/version', __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.authors = ["Keiichiro Ui"]
7
+ gem.email = ["keiichiro.ui@gmail.com"]
8
+ gem.summary = "a markdown engine which makes you to describe a graph with Graphviz and highlight codes"
9
+ gem.description = nil
10
+ gem.homepage = "http://k-ui.jp/"
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "kui-md"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = Md::VERSION
18
+
19
+ gem.add_runtime_dependency 'redcarpet', '>= 2'
20
+ gem.add_runtime_dependency 'pygments.rb'
21
+ gem.add_runtime_dependency 'ruby-graphviz'
22
+ gem.add_development_dependency 'rake'
23
+ gem.add_development_dependency 'rspec'
24
+ gem.add_development_dependency 'bundler'
25
+ end
@@ -0,0 +1,20 @@
1
+ # -*- coding:utf-8-unix; mode:ruby; -*-
2
+
3
+ require 'md'
4
+
5
+ include Md
6
+
7
+ describe CLI do
8
+
9
+ before do
10
+ @src_file_path = 'foo'
11
+ @src_file_content = 'foo content'
12
+ @src_file = mock File
13
+
14
+ @renderer = mock Renderer
15
+ Renderer.stub(:new){ @renderer }
16
+
17
+ @cli = CLI.new
18
+ end
19
+
20
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kui-md
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Keiichiro Ui
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redcarpet
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '2'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '2'
30
+ - !ruby/object:Gem::Dependency
31
+ name: pygments.rb
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: ruby-graphviz
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: bundler
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: ''
111
+ email:
112
+ - keiichiro.ui@gmail.com
113
+ executables:
114
+ - md
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - Gemfile
120
+ - LICENSE
121
+ - README.md
122
+ - Rakefile
123
+ - bin/md
124
+ - example/config.rb
125
+ - lib/md.rb
126
+ - lib/md/cli.rb
127
+ - lib/md/configure.rb
128
+ - lib/md/renderer.rb
129
+ - lib/md/version.rb
130
+ - md.gemspec
131
+ - spec/cli_spec.rb
132
+ homepage: http://k-ui.jp/
133
+ licenses: []
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 1.8.23
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: a markdown engine which makes you to describe a graph with Graphviz and highlight
156
+ codes
157
+ test_files:
158
+ - spec/cli_spec.rb