literate_md 1.0.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.
- data/bin/literate_md +107 -0
- metadata +106 -0
data/bin/literate_md
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
#!/usr/bin/ruby -rubygems
|
2
|
+
|
3
|
+
require 'coderay'
|
4
|
+
require 'redcarpet'
|
5
|
+
require 'trollop'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
opts = Trollop::options do
|
9
|
+
opt :weave, "Produce documentation", :short => 'w'
|
10
|
+
opt :tangle, "Produce code", :short => 't'
|
11
|
+
opt :outputdir, "Directory to write files to", :default => Dir.pwd, :short => 'o'
|
12
|
+
opt :lang, "Default language of code", :default => "ruby", :short => 'l'
|
13
|
+
opt :files, "Files to process", :type => :string, :short => 'f', :required => true
|
14
|
+
end
|
15
|
+
|
16
|
+
$allowed = '(\w| )*|((.*:)?\*)'
|
17
|
+
html_opts = {
|
18
|
+
:fenced_code_blocks => true,
|
19
|
+
:superscript => true,
|
20
|
+
:tables => true,
|
21
|
+
:lax_html_blocks => true,
|
22
|
+
:strikethrough => true
|
23
|
+
}
|
24
|
+
$ext_for_lang = {
|
25
|
+
:ruby => 'rb',
|
26
|
+
:c => 'c',
|
27
|
+
}
|
28
|
+
|
29
|
+
class Weave < Redcarpet::Render::XHTML
|
30
|
+
attr_accessor :default_lang, :original_text
|
31
|
+
def block_code(code, lang)
|
32
|
+
l_ang, r_ang, equiv = "__lang__", "__rang__", "__equiv__"
|
33
|
+
line_num = @original_text[0,@original_text.index(code)].count("\n")+1
|
34
|
+
code = code.
|
35
|
+
gsub(/@(#{$allowed})@\s*\+=/,"#{l_ang}\\1#{r_ang}+#{equiv}").
|
36
|
+
gsub(/@(#{$allowed})@/,"#{l_ang}\\1#{r_ang}")
|
37
|
+
code = CodeRay.
|
38
|
+
scan(code, lang.nil? ? @default_lang : lang.to_sym).
|
39
|
+
html(
|
40
|
+
:wrap => :div,
|
41
|
+
:css => :style,
|
42
|
+
:line_numbers => :table,
|
43
|
+
:line_number_start => line_num)
|
44
|
+
code.
|
45
|
+
gsub(/#{l_ang}(#{$allowed})#{r_ang}(\s*)\+#{equiv}/,'⟨\\1⟩+≡').
|
46
|
+
gsub(/#{l_ang}(#{$allowed})#{r_ang}/,'⟨\\1⟩')
|
47
|
+
end
|
48
|
+
def codespan(code); block_code(code,nil) end
|
49
|
+
end
|
50
|
+
|
51
|
+
def write_to path, data
|
52
|
+
FileUtils.mkdir_p(File.dirname(path))
|
53
|
+
File.open(path, 'w') {|f| f.write(data)}
|
54
|
+
end
|
55
|
+
|
56
|
+
if opts.weave
|
57
|
+
r = Redcarpet::Markdown.new(Weave, html_opts)
|
58
|
+
r.renderer.default_lang = opts.lang.to_sym
|
59
|
+
opts.files.split(',').each{|file|
|
60
|
+
code = File.open(file, 'r'){|f|f.read}
|
61
|
+
r.renderer.original_text = code
|
62
|
+
html = r.render(code)
|
63
|
+
write_to("#{opts.outputdir}/#{file}.html", html)
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
class Tangle < Redcarpet::Render::Base
|
68
|
+
attr_accessor :default_lang, :links, :file_no_ext
|
69
|
+
def block_code(code, lang)
|
70
|
+
chunks =
|
71
|
+
[{:start => 0, :anchor => '*', :anchor_len => 0}] +
|
72
|
+
code.scan(/(@(#{$allowed})@\s*\+=)/).map{|x|
|
73
|
+
{:start => code.index(x[0]), :anchor => x[1], :anchor_len => x[0].length}
|
74
|
+
} +
|
75
|
+
[{:start => code.length}]
|
76
|
+
(1..chunks.length-1).each{|index|
|
77
|
+
last, this = chunks[index-1], chunks[index]
|
78
|
+
@links[normalise(last[:anchor],lang)] << code[last[:start] + last[:anchor_len], this[:start]]
|
79
|
+
}
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
def normalise(link_name, lang)
|
83
|
+
if link_name == '*'
|
84
|
+
"#{@file_no_ext}.#{$ext_for_lang[lang.nil? ? @default_lang : lang.to_sym]}:*"
|
85
|
+
else
|
86
|
+
link_name
|
87
|
+
end
|
88
|
+
end
|
89
|
+
def codespan(code); block_code(code,nil) end
|
90
|
+
end
|
91
|
+
|
92
|
+
if opts.tangle
|
93
|
+
links = Hash.new{|h,k|h[k]=[]}
|
94
|
+
r = Redcarpet::Markdown.new(Tangle, html_opts)
|
95
|
+
r.renderer.default_lang, r.renderer.links = opts.lang.to_sym, links
|
96
|
+
opts.files.split(',').each{|file|
|
97
|
+
r.renderer.file_no_ext = file[0,file.rindex('.')]
|
98
|
+
r.render(File.open(file, 'r'){|f|f.read})
|
99
|
+
}
|
100
|
+
resolve = lambda{|parts| parts.join('').gsub(/@(#{$allowed})@/) {|match|resolve.call(links[match[1..-2]])} }
|
101
|
+
links.keys.reject{|k|!k.end_with? ':*'}.each{|root|
|
102
|
+
write_to(
|
103
|
+
"#{opts.outputdir}/#{root[0..-3]}",
|
104
|
+
resolve.call(links[root]))
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: literate_md
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- remis
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-03-08 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: redcarpet
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: coderay
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: trollop
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
62
|
+
description: A simple hello world gem
|
63
|
+
email:
|
64
|
+
executables:
|
65
|
+
- literate_md
|
66
|
+
extensions: []
|
67
|
+
|
68
|
+
extra_rdoc_files: []
|
69
|
+
|
70
|
+
files:
|
71
|
+
- bin/literate_md
|
72
|
+
homepage: http://remis-thoughts.blogspot.com
|
73
|
+
licenses: []
|
74
|
+
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
requirements: []
|
99
|
+
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 1.8.5
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: Convert markdown documents into code or html
|
105
|
+
test_files: []
|
106
|
+
|