github-markdown-jekyll 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ea4757a81ce3575303fe917cf1382293c8dcc08f
4
+ data.tar.gz: 4036197d950ebe98a4eb6d55b9cc94e7da6f7208
5
+ SHA512:
6
+ metadata.gz: 124463c37cb309e708f226029fab2a1fe7c9d8d161438e720d6b9acb58eaef6ff398c015ac62dae3771d5d4868ac3c84dd8be77f244e9cf2b7005b17b5fe1aba
7
+ data.tar.gz: 5a8e63f08bb85947e6dc22e423e315e0496449b9c6acb383597910b86f27db473d0873b283784a478e563372a231096c5d0c1c21e7c4cb16fca3978631cac65d
@@ -0,0 +1,116 @@
1
+ require 'date'
2
+ require 'rake/clean'
3
+ require 'rake/extensiontask'
4
+ require 'digest/md5'
5
+
6
+ task :default => :test
7
+
8
+ # ==========================================================
9
+ # Ruby Extension
10
+ # ==========================================================
11
+
12
+ Rake::ExtensionTask.new('markdown') do |ext|
13
+ ext.ext_dir = 'ext/markdown'
14
+ ext.lib_dir = 'lib/github'
15
+ end
16
+
17
+ # ==========================================================
18
+ # Helpers
19
+ # ==========================================================
20
+
21
+ def name
22
+ @name ||= "github-markdown-jekyll"
23
+ end
24
+
25
+ def version
26
+ @version ||= File.read("#{name}.gemspec").match(/^\s*s.version\s*=\s*['"](.*)['"]/)[1]
27
+ end
28
+
29
+ def gem_file
30
+ "#{name}-#{version}.gem"
31
+ end
32
+
33
+ # ==========================================================
34
+ # Testing
35
+ # ==========================================================
36
+
37
+ require 'rake/testtask'
38
+ Rake::TestTask.new('test') do |t|
39
+ t.test_files = FileList['test/*_test.rb']
40
+ t.ruby_opts += ['-rubygems'] if defined? Gem
41
+ end
42
+ task 'test' => [:compile]
43
+
44
+ # PACKAGING =================================================================
45
+
46
+ require 'rubygems'
47
+ $spec = eval(File.read('github-markdown-jekyll.gemspec'))
48
+
49
+ def package(ext='')
50
+ "pkg/github-markdown-#{$spec.version}" + ext
51
+ end
52
+
53
+ desc 'Build packages'
54
+ task :package => package('.gem')
55
+
56
+ directory 'pkg/'
57
+
58
+ file package('.gem') => %w[pkg/ github-markdown-jekyll.gemspec] + $spec.files do |f|
59
+ sh "gem build github-markdown-jekyll.gemspec"
60
+ mv File.basename(f.name), f.name
61
+ end
62
+
63
+
64
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
65
+ task :release => :package do
66
+ unless `git branch` =~ /^\* master$/
67
+ puts "You must be on the master branch to release!"
68
+ exit!
69
+ end
70
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
71
+ sh "git tag v#{version}"
72
+ sh "git push origin master"
73
+ sh "git push origin v#{version}"
74
+ sh "gem push pkg/#{name}-#{version}.gem"
75
+ end
76
+
77
+ # GEMSPEC HELPERS ==========================================================
78
+
79
+ task :update_gem do
80
+ # read spec file and split out manifest section
81
+ GEMFILE = 'github-markdown-jekyll.gemspec'
82
+ spec = File.read(GEMFILE)
83
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
84
+ head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
85
+ # determine file list from git ls-files
86
+ files = `git ls-files`.
87
+ split("\n").
88
+ sort.
89
+ reject{ |file| file =~ /^\./ || file =~ /^test\/MarkdownTest/ }.
90
+ map{ |file| " #{file}" }.
91
+ join("\n")
92
+ # piece file back together and write...
93
+ manifest = " s.files = %w[\n#{files}\n ]\n"
94
+ spec = [head,manifest,tail].join(" # = MANIFEST =\n")
95
+ File.open(GEMFILE, 'w') { |io| io.write(spec) }
96
+ puts "updated #{GEMFILE}"
97
+ end
98
+
99
+ desc 'Gather required Sundown sources into extension directory'
100
+ task :gather => 'sundown/src/markdown.h' do |t|
101
+ files =
102
+ FileList[
103
+ 'sundown/src/{markdown,buffer,stack,autolink,html_blocks}.h',
104
+ 'sundown/src/{markdown,buffer,stack,autolink}.c',
105
+ 'sundown/html/{html,houdini_html_e,houdini_href_e}.c',
106
+ 'sundown/html/{html,houdini}.h',
107
+ 'sundown/plaintext/plaintext.{c,h}',
108
+ ]
109
+ cp files, 'ext/markdown/',
110
+ :preserve => true,
111
+ :verbose => true
112
+ end
113
+
114
+ file 'sundown/src/markdown.h' do |t|
115
+ abort "The Sundown submodule is required."
116
+ end
data/bin/gfm ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ HELP = <<-help
4
+ Usage: gfm [--readme | --plaintext] [<file>]
5
+ Convert a GitHub-Flavored Markdown file to HTML and write to standard output.
6
+ With no <file> or when <file> is '-', read Markdown source text from standard input.
7
+ With `--readme`, the files are parsed like README.md files in GitHub.com. By default,
8
+ the files are parsed with all the GFM extensions.
9
+ help
10
+
11
+ if ARGV.include?('--help')
12
+ puts HELP
13
+ exit 0
14
+ end
15
+
16
+ root = File.expand_path('../../', __FILE__)
17
+ $:.unshift File.expand_path('lib', root)
18
+
19
+ require 'github/markdown'
20
+
21
+ mode = :gfm
22
+ mode = :markdown if ARGV.delete('--readme')
23
+ mode = :plaintext if ARGV.delete('--plaintext')
24
+
25
+ STDOUT.write(GitHub::Markdown.to_html(ARGF.read, mode))
@@ -0,0 +1,299 @@
1
+ /*
2
+ * Copyright (c) 2011, Vicent Marti
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+ #include "buffer.h"
18
+ #include "autolink.h"
19
+
20
+ #include <string.h>
21
+ #include <stdlib.h>
22
+ #include <stdio.h>
23
+ #include <ctype.h>
24
+
25
+ #if defined(_WIN32)
26
+ #define strncasecmp _strnicmp
27
+ #endif
28
+
29
+ int
30
+ sd_autolink_issafe(const uint8_t *link, size_t link_len)
31
+ {
32
+ static const size_t valid_uris_count = 5;
33
+ static const char *valid_uris[] = {
34
+ "/", "http://", "https://", "ftp://", "mailto:"
35
+ };
36
+
37
+ size_t i;
38
+
39
+ for (i = 0; i < valid_uris_count; ++i) {
40
+ size_t len = strlen(valid_uris[i]);
41
+
42
+ if (link_len > len &&
43
+ strncasecmp((char *)link, valid_uris[i], len) == 0 &&
44
+ isalnum(link[len]))
45
+ return 1;
46
+ }
47
+
48
+ return 0;
49
+ }
50
+
51
+ static size_t
52
+ autolink_delim(uint8_t *data, size_t link_end, size_t max_rewind, size_t size)
53
+ {
54
+ uint8_t cclose, copen = 0;
55
+ size_t i;
56
+
57
+ for (i = 0; i < link_end; ++i)
58
+ if (data[i] == '<') {
59
+ link_end = i;
60
+ break;
61
+ }
62
+
63
+ while (link_end > 0) {
64
+ if (strchr("?!.,:", data[link_end - 1]) != NULL)
65
+ link_end--;
66
+
67
+ else if (data[link_end - 1] == ';') {
68
+ size_t new_end = link_end - 2;
69
+
70
+ while (new_end > 0 && isalpha(data[new_end]))
71
+ new_end--;
72
+
73
+ if (new_end < link_end - 2 && data[new_end] == '&')
74
+ link_end = new_end;
75
+ else
76
+ link_end--;
77
+ }
78
+ else break;
79
+ }
80
+
81
+ if (link_end == 0)
82
+ return 0;
83
+
84
+ cclose = data[link_end - 1];
85
+
86
+ switch (cclose) {
87
+ case '"': copen = '"'; break;
88
+ case '\'': copen = '\''; break;
89
+ case ')': copen = '('; break;
90
+ case ']': copen = '['; break;
91
+ case '}': copen = '{'; break;
92
+ }
93
+
94
+ if (copen != 0) {
95
+ size_t closing = 0;
96
+ size_t opening = 0;
97
+ size_t i = 0;
98
+
99
+ /* Try to close the final punctuation sign in this same line;
100
+ * if we managed to close it outside of the URL, that means that it's
101
+ * not part of the URL. If it closes inside the URL, that means it
102
+ * is part of the URL.
103
+ *
104
+ * Examples:
105
+ *
106
+ * foo http://www.pokemon.com/Pikachu_(Electric) bar
107
+ * => http://www.pokemon.com/Pikachu_(Electric)
108
+ *
109
+ * foo (http://www.pokemon.com/Pikachu_(Electric)) bar
110
+ * => http://www.pokemon.com/Pikachu_(Electric)
111
+ *
112
+ * foo http://www.pokemon.com/Pikachu_(Electric)) bar
113
+ * => http://www.pokemon.com/Pikachu_(Electric)
114
+ *
115
+ * (foo http://www.pokemon.com/Pikachu_(Electric)) bar
116
+ * => foo http://www.pokemon.com/Pikachu_(Electric)
117
+ */
118
+
119
+ while (i < link_end) {
120
+ if (data[i] == copen)
121
+ opening++;
122
+ else if (data[i] == cclose)
123
+ closing++;
124
+
125
+ i++;
126
+ }
127
+
128
+ if (closing != opening)
129
+ link_end--;
130
+ }
131
+
132
+ return link_end;
133
+ }
134
+
135
+ static size_t
136
+ check_domain(uint8_t *data, size_t size, int allow_short)
137
+ {
138
+ size_t i, np = 0;
139
+
140
+ if (!isalnum(data[0]))
141
+ return 0;
142
+
143
+ for (i = 1; i < size - 1; ++i) {
144
+ if (data[i] == '.') np++;
145
+ else if (!isalnum(data[i]) && data[i] != '-') break;
146
+ }
147
+
148
+ if (allow_short) {
149
+ /* We don't need a valid domain in the strict sense (with
150
+ * least one dot; so just make sure it's composed of valid
151
+ * domain characters and return the length of the the valid
152
+ * sequence. */
153
+ return i;
154
+ } else {
155
+ /* a valid domain needs to have at least a dot.
156
+ * that's as far as we get */
157
+ return np ? i : 0;
158
+ }
159
+ }
160
+
161
+ size_t
162
+ sd_autolink__www(
163
+ size_t *rewind_p,
164
+ struct buf *link,
165
+ uint8_t *data,
166
+ size_t max_rewind,
167
+ size_t size,
168
+ unsigned int flags)
169
+ {
170
+ size_t link_end;
171
+
172
+ if (max_rewind > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
173
+ return 0;
174
+
175
+ if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
176
+ return 0;
177
+
178
+ link_end = check_domain(data, size, 0);
179
+
180
+ if (link_end == 0)
181
+ return 0;
182
+
183
+ while (link_end < size && !isspace(data[link_end]))
184
+ link_end++;
185
+
186
+ link_end = autolink_delim(data, link_end, max_rewind, size);
187
+
188
+ if (link_end == 0)
189
+ return 0;
190
+
191
+ bufput(link, data, link_end);
192
+ *rewind_p = 0;
193
+
194
+ return (int)link_end;
195
+ }
196
+
197
+ size_t
198
+ sd_autolink__email(
199
+ size_t *rewind_p,
200
+ struct buf *link,
201
+ uint8_t *data,
202
+ size_t max_rewind,
203
+ size_t size,
204
+ unsigned int flags)
205
+ {
206
+ size_t link_end, rewind;
207
+ int nb = 0, np = 0, ns = 0;
208
+
209
+ for (rewind = 0; rewind < max_rewind; ++rewind) {
210
+ uint8_t c = data[-rewind - 1];
211
+
212
+ if (isalnum(c))
213
+ continue;
214
+
215
+ if (strchr(".+-_", c) != NULL)
216
+ continue;
217
+
218
+ if (c == '/')
219
+ ns++;
220
+
221
+ break;
222
+ }
223
+
224
+ if (rewind == 0 || ns > 0)
225
+ return 0;
226
+
227
+ for (link_end = 0; link_end < size; ++link_end) {
228
+ uint8_t c = data[link_end];
229
+
230
+ if (isalnum(c))
231
+ continue;
232
+
233
+ if (c == '@')
234
+ nb++;
235
+ else if (c == '.' && link_end < size - 1)
236
+ np++;
237
+ else if (c != '-' && c != '_')
238
+ break;
239
+ }
240
+
241
+ if (link_end < 2 || nb != 1 || np == 0 ||
242
+ (!isalpha(data[link_end - 1]) && data[link_end - 1] != '.'))
243
+ return 0;
244
+
245
+ link_end = autolink_delim(data, link_end, max_rewind, size);
246
+
247
+ if (link_end == 0)
248
+ return 0;
249
+
250
+ bufput(link, data - rewind, link_end + rewind);
251
+ *rewind_p = rewind;
252
+
253
+ return link_end;
254
+ }
255
+
256
+ size_t
257
+ sd_autolink__url(
258
+ size_t *rewind_p,
259
+ struct buf *link,
260
+ uint8_t *data,
261
+ size_t max_rewind,
262
+ size_t size,
263
+ unsigned int flags)
264
+ {
265
+ size_t link_end, rewind = 0, domain_len;
266
+
267
+ if (size < 4 || data[1] != '/' || data[2] != '/')
268
+ return 0;
269
+
270
+ while (rewind < max_rewind && isalpha(data[-rewind - 1]))
271
+ rewind++;
272
+
273
+ if (!sd_autolink_issafe(data - rewind, size + rewind))
274
+ return 0;
275
+
276
+ link_end = strlen("://");
277
+
278
+ domain_len = check_domain(
279
+ data + link_end,
280
+ size - link_end,
281
+ flags & SD_AUTOLINK_SHORT_DOMAINS);
282
+
283
+ if (domain_len == 0)
284
+ return 0;
285
+
286
+ link_end += domain_len;
287
+ while (link_end < size && !isspace(data[link_end]))
288
+ link_end++;
289
+
290
+ link_end = autolink_delim(data, link_end, max_rewind, size);
291
+
292
+ if (link_end == 0)
293
+ return 0;
294
+
295
+ bufput(link, data - rewind, link_end + rewind);
296
+ *rewind_p = rewind;
297
+
298
+ return link_end;
299
+ }