lib/github/markup.rb (view raw)
1begin
2 require 'open3_detach'
3rescue LoadError
4 require 'open3'
5end
6
7module GitHub
8 module Markup
9 extend self
10 @@markups = {}
11 @@deferred_markups = []
12
13 def preload!
14 @@deferred_markups.each do |loader|
15 loader.call
16 end
17 @@deferred_markups = []
18 end
19
20 def render(filename, content = nil)
21 content ||= File.read(filename)
22
23 if proc = renderer(filename)
24 proc[content]
25 else
26 content
27 end
28 end
29
30 def markup(file, pattern, opts = {}, &block)
31 loader = proc do
32 begin
33 require file.to_s
34 add_markup(pattern, &block)
35 true
36 rescue LoadError
37 false
38 end
39 end
40
41 if opts[:eager]
42 loader.call
43 else
44 @@deferred_markups << loader
45 add_markup pattern do |*args|
46 @@deferred_markups.delete(loader)
47 loader.call
48 block.call(*args)
49 end
50 true
51 end
52 end
53
54 def command(command, regexp, &block)
55 command = command.to_s
56
57 if File.exists?(file = File.dirname(__FILE__) + "/commands/#{command}")
58 command = file
59 end
60
61 add_markup(regexp) do |content|
62 rendered = execute(command, content)
63 rendered = rendered.to_s.empty? ? content : rendered
64
65 if block && block.arity == 2
66 # If the block takes two arguments, pass new content and old
67 # content.
68 block.call(rendered, content)
69 elsif block
70 # One argument is just the new content.
71 block.call(rendered)
72 else
73 # No block? No problem!
74 rendered
75 end
76 end
77 end
78
79 def add_markup(regexp, &block)
80 @@markups[regexp] = block
81 end
82
83 def can_render?(filename)
84 !!renderer(filename)
85 end
86
87 def renderer(filename)
88 @@markups.each do |key, value|
89 if Regexp.compile("\\.(#{key})$") =~ filename
90 return value
91 end
92 end
93 nil
94 end
95
96 def renderer_name(filename)
97 @@markups.each do |key, value|
98 if Regexp.compile("\\.(#{key})$") =~ filename
99 return key
100 end
101 end
102 nil
103 end
104
105 def execute(command, target)
106 out = ''
107 Open3.popen3(command) do |stdin, stdout, _|
108 stdin.puts target
109 stdin.close
110 out = stdout.read
111 end
112 out.gsub("\r", '')
113 rescue Errno::EPIPE
114 ""
115 rescue Errno::ENOENT
116 ""
117 end
118
119 # Define markups
120 markups_rb = File.dirname(__FILE__) + '/markups.rb'
121 instance_eval File.read(markups_rb), markups_rb
122 end
123end