github_markup 0.1.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.
@@ -0,0 +1 @@
1
+ *.pyc
data/.kick ADDED
@@ -0,0 +1,26 @@
1
+ # take control of the growl notifications
2
+ module GrowlHacks
3
+ def growl(type, subject, body, *args, &block)
4
+ case type
5
+ when Kicker::GROWL_NOTIFICATIONS[:succeeded]
6
+ puts subject = "Success"
7
+ body = body.split("\n").last
8
+ when Kicker::GROWL_NOTIFICATIONS[:failed]
9
+ subject = "Failure"
10
+ puts body
11
+ body = body.split("\n").last
12
+ else
13
+ return nil
14
+ end
15
+ super(type, subject, body, *args, &block)
16
+ end
17
+ end
18
+
19
+ Kicker.send :extend, GrowlHacks
20
+
21
+ # no logging
22
+ Kicker::Utils.module_eval do
23
+ def log(message)
24
+ nil
25
+ end
26
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 GitHub
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,82 @@
1
+ GitHub Markup
2
+ =============
3
+
4
+ We use this library on GitHub when rendering your README or any other
5
+ rich text file.
6
+
7
+ Want to contribute? Great! There are two ways to add markups.
8
+
9
+
10
+ ### Commands
11
+
12
+ If your markup is in a language other than Ruby, drop a translator
13
+ script in `lib/github/commands` which accepts input on STDIN and
14
+ returns HTML on STDOUT. See [rest2html][r2h] for an example.
15
+
16
+ Once your script is in place, edit `lib/github/markups.rb` and tell
17
+ GitHub Markup about it. Again we look to [rest2html][r2hc] for
18
+ guidance:
19
+
20
+ command(:rest2html, /rest|rst/)
21
+
22
+ Here we're telling GitHub Markup of the existence of a `rest2html`
23
+ command which should be used for any file ending in `rest` or
24
+ `rst`. Any regular expression will do.
25
+
26
+ Finally add your tests. Create a `README.extension` in `test/markups`
27
+ along with a `README.extension.html`. As you may imagine, the
28
+ `README.extension` should be your known input and the
29
+ `README.extension.html` should be the desired output.
30
+
31
+ Now run the tests: `rake`
32
+
33
+ If nothing complains, congratulations!
34
+
35
+
36
+ ### Classes
37
+
38
+ If your markup can be translated using a Ruby library, that's
39
+ great. Check out Check `lib/github/markups.rb` for some
40
+ examples. Let's look at Markdown:
41
+
42
+ markup(:markdown, /md|mkdn?|markdown/) do |content|
43
+ Markdown.new(content).to_html
44
+ end
45
+
46
+ We give the `markup` method three bits of information: the name of the
47
+ file to `require`, a regular expression for extensions to match, and a
48
+ block to run with unformatted markup which should return HTML.
49
+
50
+ If you need to monkeypatch a RubyGem or something, check out the
51
+ included RDoc example.
52
+
53
+ Tests should be added in the same manner as described under the
54
+ `Commands` section.
55
+
56
+
57
+ Usage
58
+ -----
59
+
60
+ require 'github/markup'
61
+ GitHub::Markup.render('README.markdown', "* One\n* Two")
62
+
63
+ Or, more realistically:
64
+
65
+ require 'github/markup'
66
+ GitHub::Markup.render(file, File.read(file))
67
+
68
+
69
+ Contributing
70
+ ------------
71
+
72
+ 1. Fork it.
73
+ 2. Create a branch
74
+ 3. Commit your changes
75
+ 4. Push to the branch
76
+ 5. Create an [Issue][1] with a link to your branch
77
+ 6. Enjoy a refreshing Diet Coke and wait
78
+
79
+
80
+ [r2h]: http://github.com/defunkt/github_markup/tree/master/lib/github/commands/rest2html
81
+ [r2hc]: http://github.com/defunkt/github_markup/tree/master/lib/github/markups.rb#L13
82
+ [1]: http://github.com/defunkt/github_markup/issues
@@ -0,0 +1,45 @@
1
+ task :default => :test
2
+
3
+ desc "Run tests"
4
+ task :test do
5
+ Dir['test/**/*_test.rb'].each { |file| require file }
6
+ end
7
+
8
+ desc "Kick it"
9
+ task :kick do
10
+ exec "kicker -e rake test lib"
11
+ end
12
+
13
+ begin
14
+ require 'jeweler'
15
+ $LOAD_PATH.unshift 'lib'
16
+ require 'github/markup/version'
17
+ Jeweler::Tasks.new do |gemspec|
18
+ gemspec.name = "github_markup"
19
+ gemspec.summary = "The code we use to render README.your_favorite_markup"
20
+ gemspec.description = "The code we use to render README.your_favorite_markup"
21
+ gemspec.email = "chris@ozmm.org"
22
+ gemspec.homepage = "http://github.com/defunkt/github_markup"
23
+ gemspec.authors = ["Chris Wanstrath"]
24
+ gemspec.version = GitHub::Markup::Version
25
+ end
26
+ rescue LoadError
27
+ puts "Jeweler not available."
28
+ puts "Install it with: gem install jeweler"
29
+ end
30
+
31
+ begin
32
+ require 'sdoc_helpers'
33
+ rescue LoadError
34
+ puts "sdoc support not enabled. Please gem install sdoc-helpers."
35
+ end
36
+
37
+ desc "Push a new version to Gemcutter"
38
+ task :publish => [ :test, :gemspec, :build ] do
39
+ system "git tag v#{GitHub::Markup::Version}"
40
+ system "git push origin v#{GitHub::Markup::Version}"
41
+ system "git push origin master"
42
+ system "gem push pkg/github_markup-#{GitHub::Markup::Version}.gem"
43
+ system "git clean -fd"
44
+ #exec "rake pages"
45
+ end
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env python
2
+
3
+ """A small wrapper file for parsing AsciiDoc files at Github."""
4
+
5
+ __author__ = "Devin Weaver"
6
+ __copyright__ = "Copyright (C) 2009 Devin Weaver"
7
+ __license__ = "Public Domain"
8
+ __version__ = "0.1"
9
+
10
+ """
11
+ github_asciidoc.py
12
+ ------------------
13
+
14
+ This is a wrapper file for parsing AsciiDoc files at github. It wraps the
15
+ current AsciiDoc API.
16
+
17
+ AsciiDoc specifications suggest using the file extension of `.txt` however this
18
+ causes conflict because there is no way to determine if a text file is an
19
+ AsciiDoc or not without pre-processing the file. This gives us two simple
20
+ options:
21
+
22
+ 1. **Parse all text files**. We could have all files ending in `.txt` or
23
+ ``README.txt`` be parsed through AsciiDoc. It will print pretty text fine
24
+ even if it isn't formatted as such. However this could be *not what the user
25
+ expects*.
26
+ 2. **Pick a unique extension**. We could pick a unique extension (i.e.
27
+ `.asciidoc`) to prevent clashing. Although not directly suggested by the
28
+ author of AsciiDoc there is no standard or practice to the contrary.
29
+
30
+ Option two is recommended by myself.
31
+
32
+ Requirements
33
+ ~~~~~~~~~~~~
34
+
35
+ The AsciiDoc API comes in two parts. The first is the system installation of
36
+ AsciiDoc which has a simple install_. The second part is the API script. You
37
+ can either copy this to the current directory or the application's lib folder.
38
+ There is more information on the `API page`_
39
+
40
+ The `re` package is imported here for the purpose to accomplish E-Mail address
41
+ cloaking. AsciiDoc does not offer it's own cloaking algorithm like docutils
42
+ does. So I made a simple one here to do the same. **If the expense of regex's
43
+ is too high it can be easily commented out.**
44
+
45
+ .. tip::
46
+ AsciiDoc by default runs in *safe mode* which means it will not include
47
+ external files that are **not** in the same directory as the `infile`.
48
+ However since we use a StringIO through the API it should be based on the
49
+ current working directory.
50
+
51
+ .. _install: http://www.methods.co.nz/asciidoc/userguide.html
52
+ .. _API page: http://www.methods.co.nz/asciidoc/asciidocapi.html
53
+ """
54
+
55
+ try:
56
+ import locale
57
+ locale.setlocale(locale.LC_ALL, '')
58
+ except:
59
+ pass
60
+
61
+ import sys
62
+ import cStringIO # faster then StringIO
63
+ from asciidocapi import AsciiDocAPI
64
+ from asciidocapi import AsciiDocError
65
+ import re # only needed to simulate cloak_email_addresses
66
+
67
+ def main():
68
+ """
69
+ Parses the given AsciiDoc file or the redirected string input and returns
70
+ the HTML body.
71
+
72
+ Usage: asciidoc2html < README.rst
73
+ asciidoc2html README.rst
74
+ """
75
+ try:
76
+ text = open(sys.argv[1], 'r').read()
77
+ except IOError: # given filename could not be found
78
+ return ''
79
+ except IndexError: # no filename given
80
+ text = sys.stdin.read()
81
+
82
+ infile = cStringIO.StringIO(text)
83
+ outfile = cStringIO.StringIO()
84
+ asciidoc = AsciiDocAPI()
85
+ asciidoc.options('-s')
86
+
87
+ try:
88
+ asciidoc.execute(infile, outfile, 'xhtml11')
89
+ except AsciiDocError, strerror:
90
+ str = "%s" % (strerror)
91
+ str = str.replace("&", "&amp;") # Must be done first
92
+ str = str.replace("<", "%lt;")
93
+ str = str.replace(">", "%gt;")
94
+ outfile.write ("<blockquote><strong>AsciiDoc ERROR: %s</strong></blockquote>" % (str))
95
+
96
+ """
97
+ Cloak email addresses
98
+
99
+ AsciiDoc API does not have a `cloak_email_addresses` option. We can do the
100
+ same with a set of regex but that can be expensive. Keep section commented
101
+ to disable. So ``abc@mail.example.com`` becomes:
102
+
103
+ -----------
104
+ <a class="reference" href="mailto:abc&#37;&#52;&#48;mail&#46;example&#46;org">
105
+ abc<span>&#64;</span>mail<span>&#46;</span>example<span>&#46;</span>org</a>
106
+ -----------
107
+ """
108
+ def mangleEmail(matches):
109
+ email1 = "%s&#37;&#52;&#48;%s" % (matches.group(1), matches.group(2))
110
+ email1 = email1.replace(".", "&#46;")
111
+ email2 = "%s<span>&#64;</span>%s" % (matches.group(1), matches.group(2))
112
+ email2 = email2.replace(".", "<span>&#46;</span>")
113
+ return "<a class=\"reference\" href=\"mailto:%s\">%s</a>" % (email1, email2)
114
+
115
+ return re.sub(r'<a href="mailto:([^@]+)@([^@]+)">([^@]+)@([^@]+)</a>', mangleEmail, outfile.getvalue())
116
+ #return outfile.getvalue()
117
+
118
+ if __name__ == '__main__':
119
+ print main()
@@ -0,0 +1,240 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ asciidocapi - AsciiDoc API wrapper class.
4
+
5
+ The AsciiDocAPI class provides an API for executing asciidoc. Minimal example
6
+ compiles `mydoc.txt` to `mydoc.html`:
7
+
8
+ import asciidocapi
9
+ asciidoc = asciidocapi.AsciiDocAPI()
10
+ asciidoc.execute('mydoc.txt')
11
+
12
+ - Full documentation in asciidocapi.txt.
13
+ - See the doctests below for more examples.
14
+
15
+ Doctests:
16
+
17
+ 1. Check execution:
18
+
19
+ >>> import StringIO
20
+ >>> infile = StringIO.StringIO('Hello *{author}*')
21
+ >>> outfile = StringIO.StringIO()
22
+ >>> asciidoc = AsciiDocAPI()
23
+ >>> asciidoc.options('--no-header-footer')
24
+ >>> asciidoc.attributes['author'] = 'Joe Bloggs'
25
+ >>> asciidoc.execute(infile, outfile, backend='html4')
26
+ >>> print outfile.getvalue()
27
+ <p>Hello <strong>Joe Bloggs</strong></p>
28
+
29
+ >>> asciidoc.attributes['author'] = 'Bill Smith'
30
+ >>> infile = StringIO.StringIO('Hello _{author}_')
31
+ >>> outfile = StringIO.StringIO()
32
+ >>> asciidoc.execute(infile, outfile, backend='docbook')
33
+ >>> print outfile.getvalue()
34
+ <simpara>Hello <emphasis>Bill Smith</emphasis></simpara>
35
+
36
+ 2. Check error handling:
37
+
38
+ >>> import StringIO
39
+ >>> asciidoc = AsciiDocAPI()
40
+ >>> infile = StringIO.StringIO('---------')
41
+ >>> outfile = StringIO.StringIO()
42
+ >>> asciidoc.execute(infile, outfile)
43
+ Traceback (most recent call last):
44
+ File "<stdin>", line 1, in <module>
45
+ File "asciidocapi.py", line 189, in execute
46
+ raise AsciiDocError(self.messages[-1])
47
+ AsciiDocError: ERROR: <stdin>: line 1: [blockdef-listing] missing closing delimiter
48
+
49
+
50
+ Copyright (C) 2009 Stuart Rackham. Free use of this software is granted
51
+ under the terms of the GNU General Public License (GPL).
52
+
53
+ """
54
+
55
+ import sys,os,re
56
+
57
+ API_VERSION = '0.1.1'
58
+ MIN_ASCIIDOC_VERSION = '8.4.1' # Minimum acceptable AsciiDoc version.
59
+
60
+
61
+ def find_in_path(fname, path=None):
62
+ """
63
+ Find file fname in paths. Return None if not found.
64
+ """
65
+ if path is None:
66
+ path = os.environ.get('PATH', '')
67
+ for dir in path.split(os.pathsep):
68
+ fpath = os.path.join(dir, fname)
69
+ if os.path.isfile(fpath):
70
+ return fpath
71
+ else:
72
+ return None
73
+
74
+
75
+ class AsciiDocError(Exception):
76
+ pass
77
+
78
+
79
+ class Options(object):
80
+ """
81
+ Stores asciidoc(1) command options.
82
+ """
83
+ def __init__(self, values=[]):
84
+ self.values = values[:]
85
+ def __call__(self, name, value=None):
86
+ """Shortcut for append method."""
87
+ self.append(name, value)
88
+ def append(self, name, value=None):
89
+ if type(value) in (int,float):
90
+ value = str(value)
91
+ self.values.append((name,value))
92
+
93
+
94
+ class Version(object):
95
+ """
96
+ Parse and compare AsciiDoc version numbers. Instance attributes:
97
+
98
+ string: String version number '<major>.<minor>[.<micro>][suffix]'.
99
+ major: Integer major version number.
100
+ minor: Integer minor version number.
101
+ micro: Integer micro version number.
102
+ suffix: Suffix (begins with non-numeric character) is ignored when
103
+ comparing.
104
+
105
+ Doctest examples:
106
+
107
+ >>> Version('8.2.5') < Version('8.3 beta 1')
108
+ True
109
+ >>> Version('8.3.0') == Version('8.3. beta 1')
110
+ True
111
+ >>> Version('8.2.0') < Version('8.20')
112
+ True
113
+ >>> Version('8.20').major
114
+ 8
115
+ >>> Version('8.20').minor
116
+ 20
117
+ >>> Version('8.20').micro
118
+ 0
119
+ >>> Version('8.20').suffix
120
+ ''
121
+ >>> Version('8.20 beta 1').suffix
122
+ 'beta 1'
123
+
124
+ """
125
+ def __init__(self, version):
126
+ self.string = version
127
+ reo = re.match(r'^(\d+)\.(\d+)(\.(\d+))?\s*(.*?)\s*$', self.string)
128
+ if not reo:
129
+ raise ValueError('invalid version number: %s' % self.string)
130
+ groups = reo.groups()
131
+ self.major = int(groups[0])
132
+ self.minor = int(groups[1])
133
+ self.micro = int(groups[3] or '0')
134
+ self.suffix = groups[4] or ''
135
+ def __cmp__(self, other):
136
+ result = cmp(self.major, other.major)
137
+ if result == 0:
138
+ result = cmp(self.minor, other.minor)
139
+ if result == 0:
140
+ result = cmp(self.micro, other.micro)
141
+ return result
142
+
143
+
144
+ class AsciiDocAPI(object):
145
+ """
146
+ AsciiDoc API class.
147
+ """
148
+ def __init__(self, asciidoc_py=None):
149
+ """
150
+ Locate and import asciidoc.py.
151
+ Initialize instance attributes.
152
+ """
153
+ self.options = Options()
154
+ self.attributes = {}
155
+ self.messages = []
156
+ # Search for the asciidoc command file.
157
+ # Try ASCIIDOC_PY environment variable first.
158
+ cmd = os.environ.get('ASCIIDOC_PY')
159
+ if cmd:
160
+ if not os.path.isfile(cmd):
161
+ raise AsciiDocError('missing ASCIIDOC_PY file: %s' % cmd)
162
+ elif asciidoc_py:
163
+ # Next try path specified by caller.
164
+ cmd = asciidoc_py
165
+ if not os.path.isfile(cmd):
166
+ raise AsciiDocError('missing file: %s' % cmd)
167
+ else:
168
+ # Try shell search paths.
169
+ for fname in ['asciidoc.py','asciidoc.pyc','asciidoc']:
170
+ cmd = find_in_path(fname)
171
+ if cmd: break
172
+ else:
173
+ # Finally try current working directory.
174
+ for cmd in ['asciidoc.py','asciidoc.pyc','asciidoc']:
175
+ if os.path.isfile(cmd): break
176
+ else:
177
+ raise AsciiDocError('failed to locate asciidoc.py[c]')
178
+ cmd = os.path.realpath(cmd)
179
+ if os.path.splitext(cmd)[1] not in ['.py','.pyc']:
180
+ raise AsciiDocError('invalid Python module name: %s' % cmd)
181
+ sys.path.insert(0, os.path.dirname(cmd))
182
+ try:
183
+ try:
184
+ import asciidoc
185
+ except ImportError:
186
+ raise AsciiDocError('failed to import asciidoc')
187
+ finally:
188
+ del sys.path[0]
189
+ if Version(asciidoc.VERSION) < Version(MIN_ASCIIDOC_VERSION):
190
+ raise AsciiDocError(
191
+ 'asciidocapi %s requires asciidoc %s or better'
192
+ % (API_VERSION, MIN_ASCIIDOC_VERSION))
193
+ self.asciidoc = asciidoc
194
+ self.cmd = cmd
195
+
196
+ def execute(self, infile, outfile=None, backend=None):
197
+ """
198
+ Compile infile to outfile using backend format.
199
+ infile can outfile can be file path strings or file like objects.
200
+ """
201
+ self.messages = []
202
+ opts = Options(self.options.values)
203
+ if outfile is not None:
204
+ opts('--out-file', outfile)
205
+ if backend is not None:
206
+ opts('--backend', backend)
207
+ for k,v in self.attributes.items():
208
+ if v == '' or k[-1] in '!@':
209
+ s = k
210
+ elif v is None: # A None value undefines the attribute.
211
+ s = k + '!'
212
+ else:
213
+ s = '%s=%s' % (k,v)
214
+ opts('--attribute', s)
215
+ args = [infile]
216
+ sys.path.insert(0, os.path.dirname(self.cmd))
217
+ try:
218
+ # The AsciiDoc command was designed to process source text then
219
+ # exit, there are globals and statics in asciidoc.py that have
220
+ # to be reinitialized before each run -- hence the reload.
221
+ reload(self.asciidoc)
222
+ finally:
223
+ del sys.path[0]
224
+ try:
225
+ try:
226
+ self.asciidoc.execute(self.cmd, opts.values, args)
227
+ finally:
228
+ self.messages = self.asciidoc.messages[:]
229
+ except SystemExit, e:
230
+ if e.code:
231
+ raise AsciiDocError(self.messages[-1])
232
+
233
+
234
+ if __name__ == "__main__":
235
+ """
236
+ Run module doctests.
237
+ """
238
+ import doctest
239
+ options = doctest.NORMALIZE_WHITESPACE + doctest.ELLIPSIS
240
+ doctest.testmod(optionflags=options)
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env python
2
+
3
+ """A small wrapper file for parsing ReST files at GitHub."""
4
+
5
+ __author__ = "Jannis Leidel"
6
+ __copyright__ = "Copyright (C) 2008 Jannis Leidel"
7
+ __license__ = "Public Domain"
8
+ __version__ = "0.1"
9
+
10
+ try:
11
+ import locale
12
+ locale.setlocale(locale.LC_ALL, '')
13
+ except:
14
+ pass
15
+
16
+ import sys
17
+ from docutils.core import publish_parts
18
+ from docutils.writers.html4css1 import Writer
19
+
20
+ SETTINGS = {
21
+ 'cloak_email_addresses': True,
22
+ 'file_insertion_enabled': False,
23
+ 'raw_enabled': False,
24
+ 'strip_comments': True,
25
+ }
26
+
27
+ def main():
28
+ """
29
+ Parses the given ReST file or the redirected string input and returns the
30
+ HTML body.
31
+
32
+ Usage: rest2html < README.rst
33
+ rest2html README.rst
34
+ """
35
+ try:
36
+ text = open(sys.argv[1], 'r').read()
37
+ except IOError: # given filename could not be found
38
+ return ''
39
+ except IndexError: # no filename given
40
+ text = sys.stdin.read()
41
+
42
+ parts = publish_parts(text, writer=Writer(), settings_overrides=SETTINGS)
43
+ if 'html_body' in parts:
44
+ return parts['html_body']
45
+ return ''
46
+
47
+ if __name__ == '__main__':
48
+ print main()
@@ -0,0 +1,60 @@
1
+ begin
2
+ require 'open3_detach'
3
+ rescue LoadError
4
+ require 'open3'
5
+ end
6
+
7
+ module GitHub
8
+ module Markup
9
+ extend self
10
+ @@markups = {}
11
+
12
+ def render(filename, content)
13
+ renderer(filename)[content] || content
14
+ end
15
+
16
+ def markup(file, pattern, &block)
17
+ require file.to_s
18
+ add_markup(pattern, &block)
19
+ rescue LoadError
20
+ nil
21
+ end
22
+
23
+ def command(command, regexp, &block)
24
+ command = command.to_s
25
+ if !File.exists?(command) && !command.include?('/')
26
+ command = File.dirname(__FILE__) + '/commands/' + command.to_s
27
+ end
28
+
29
+ add_markup(regexp) do |content|
30
+ rendered = execute(command, content)
31
+ block ? block.call(rendered) : rendered
32
+ end
33
+ end
34
+
35
+ def add_markup(regexp, &block)
36
+ @@markups[regexp] = block
37
+ end
38
+
39
+ def renderer(filename)
40
+ @@markups.each do |key, value|
41
+ if Regexp.compile("(#{key})$") =~ filename
42
+ return value
43
+ end
44
+ end
45
+ end
46
+
47
+ def execute(command, target)
48
+ out = ''
49
+ Open3.popen3(command) do |stdin, stdout, _|
50
+ stdin.puts target
51
+ stdin.close
52
+ out = stdout.read
53
+ end
54
+ out.gsub("\r", '')
55
+ end
56
+
57
+ # Define markups
58
+ instance_eval File.read(File.dirname(__FILE__) + '/markups.rb')
59
+ end
60
+ end
@@ -0,0 +1,20 @@
1
+ require 'rdoc/generators/html_generator'
2
+ require 'ostruct'
3
+
4
+ module GitHub
5
+ module Markup
6
+ class RDoc
7
+ def initialize(content)
8
+ @content = content
9
+ end
10
+
11
+ def to_html
12
+ simple_markup = SM::SimpleMarkup.new
13
+ generator = Generators::HyperlinkHtml.new(nil, OpenStruct.new)
14
+ simple_markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
15
+ simple_markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK)
16
+ simple_markup.convert(@content, generator)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module GitHub
2
+ module Markup
3
+ Version = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ markup(:markdown, /md|mkdn?|markdown/) do |content|
2
+ Markdown.new(content).to_html
3
+ end
4
+
5
+ markup(:redcloth, /textile/) do |content|
6
+ RedCloth.new(content).to_html
7
+ end
8
+
9
+ markup('github/markup/rdoc', /rdoc/) do |content|
10
+ GitHub::Markup::RDoc.new(content).to_html
11
+ end
12
+
13
+ command(:rest2html, /rest|rst/)
14
+
15
+ command(:asciidoc2html, /asciidoc/)
16
+
17
+ # pod2html is nice enough to generate a full-on HTML document for us,
18
+ # so we return the favor by ripping out the good parts.
19
+ #
20
+ # Any block passed to `command` will be handed the command's STDOUT for
21
+ # post processing.
22
+ command("/usr/bin/env pod2html", /pod/) do |rendered|
23
+ if rendered =~ /<!-- INDEX BEGIN -->\s*(.+)\s*<!-- INDEX END -->/mi
24
+ `rm pod2htmd.tmp` if File.exists?('pod2htmd.tmp') rescue nil
25
+ `rm pod2htmi.tmp` if File.exists?('pod2htmi.tmp') rescue nil
26
+ $1
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
2
+
3
+ require 'github/markup'
4
+
5
+ def test_markup
6
+ passed = true
7
+ Dir['test/markups/README.*'].each do |readme|
8
+ next if readme =~ /html$/
9
+ markup = readme.split('.').last
10
+
11
+ expected = File.read("#{readme}.html")
12
+ actual = GitHub::Markup.render(readme, File.read(readme))
13
+
14
+ if expected == actual
15
+ puts "- #{markup}: OK"
16
+ else
17
+ passed = false
18
+ puts "- #{markup}: FAIL"
19
+ puts "#{markup} expected:", expected
20
+ puts "#{markup} actual:", actual
21
+ end
22
+ end
23
+ passed
24
+ end
25
+
26
+ at_exit do
27
+ exit test_markup ? 0 : 1
28
+ end
@@ -0,0 +1,2 @@
1
+ * One
2
+ * Two
@@ -0,0 +1,13 @@
1
+ <div class="ulist"><ul>
2
+ <li>
3
+ <p>
4
+ One
5
+ </p>
6
+ </li>
7
+ <li>
8
+ <p>
9
+ Two
10
+ </p>
11
+ </li>
12
+ </ul></div>
13
+
@@ -0,0 +1,2 @@
1
+ * One
2
+ * Two
@@ -0,0 +1,5 @@
1
+ <ul>
2
+ <li>One</li>
3
+ <li>Two</li>
4
+ </ul>
5
+
@@ -0,0 +1,2 @@
1
+ * One
2
+ * Two
@@ -0,0 +1,2 @@
1
+ * One
2
+ * Two
@@ -0,0 +1,7 @@
1
+ =head1 NAME
2
+
3
+ podsample - A sample pod document
4
+
5
+ =item * This is a bulleted list.
6
+
7
+ =item * Here's another item.
@@ -0,0 +1,10 @@
1
+ <div name="index">
2
+ <p><a name="__index__"></a></p>
3
+
4
+ <ul>
5
+
6
+ <li><a href="#name">NAME</a></li>
7
+ </ul>
8
+
9
+ <hr name="index" />
10
+ </div>
@@ -0,0 +1,2 @@
1
+ * One
2
+ * Two
@@ -0,0 +1,8 @@
1
+ <ul>
2
+ <li>One
3
+
4
+ </li>
5
+ <li>Two
6
+
7
+ </li>
8
+ </ul>
@@ -0,0 +1,3 @@
1
+ 1. Blah blah ``code`` blah
2
+
3
+ 2. More ``code``, hooray
@@ -0,0 +1,7 @@
1
+ <div class="document">
2
+ <ol class="arabic simple">
3
+ <li>Blah blah <tt class="docutils literal">code</tt> blah</li>
4
+ <li>More <tt class="docutils literal">code</tt>, hooray</li>
5
+ </ol>
6
+ </div>
7
+
@@ -0,0 +1,2 @@
1
+ * One
2
+ * Two
@@ -0,0 +1,4 @@
1
+ <ul>
2
+ <li>One</li>
3
+ <li>Two</li>
4
+ </ul>
@@ -0,0 +1,2 @@
1
+ * One
2
+ * Two
@@ -0,0 +1,2 @@
1
+ * One
2
+ * Two
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: github_markup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Wanstrath
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-02 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: The code we use to render README.your_favorite_markup
17
+ email: chris@ozmm.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.md
25
+ files:
26
+ - .gitignore
27
+ - .kick
28
+ - LICENSE
29
+ - README.md
30
+ - Rakefile
31
+ - lib/github/commands/asciidoc2html
32
+ - lib/github/commands/asciidocapi.py
33
+ - lib/github/commands/rest2html
34
+ - lib/github/markup.rb
35
+ - lib/github/markup/rdoc.rb
36
+ - lib/github/markup/version.rb
37
+ - lib/github/markups.rb
38
+ - test/markup_test.rb
39
+ - test/markups/README.asciidoc
40
+ - test/markups/README.asciidoc.html
41
+ - test/markups/README.markdown
42
+ - test/markups/README.markdown.html
43
+ - test/markups/README.noformat
44
+ - test/markups/README.noformat.html
45
+ - test/markups/README.pod
46
+ - test/markups/README.pod.html
47
+ - test/markups/README.rdoc
48
+ - test/markups/README.rdoc.html
49
+ - test/markups/README.rst
50
+ - test/markups/README.rst.html
51
+ - test/markups/README.textile
52
+ - test/markups/README.textile.html
53
+ - test/markups/README.txt
54
+ - test/markups/README.txt.html
55
+ has_rdoc: true
56
+ homepage: http://github.com/defunkt/github_markup
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --charset=UTF-8
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.5
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: The code we use to render README.your_favorite_markup
83
+ test_files:
84
+ - test/markup_test.rb