gist-compile 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/bin/gist-compile +179 -0
  3. data/lib/json-serializer.rb +115 -0
  4. metadata +125 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f0404315290e1f5a70692d1451eff74a51fc71e9
4
+ data.tar.gz: b09dd574f835081e4976d7b022e52b79624c3dd2
5
+ SHA512:
6
+ metadata.gz: b2f3b8f401acb8ff8726ccaddb1e187c9c0fe6a3298536b764290a5eca1ef4ef3180691a88a82a59f9c1a9c6e40c359d14c5284ec361eaf4ccc3c2fceec88fb5
7
+ data.tar.gz: 07174faeccf7a99f4ec411536e8705de577e143c9a193d05b5289c91d99c34bc1a6b8d30ee1ec4f9022cd746d00933d50e56c42f760c89cfb5386255316f8a38
data/bin/gist-compile ADDED
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ require "uri"
5
+ require "json"
6
+ require "thor"
7
+ require "paint"
8
+ require "rubygems"
9
+ require "nokogiri"
10
+ require "rest-client"
11
+ require_relative "../lib/json-serializer.rb"
12
+
13
+ GIST_BASE_URL = "https://gist.github.com"
14
+ GIST_USERCONTENT_BASE_URL = "https://gist.githubusercontent.com"
15
+ GIST_XPATH_IDENTIFIER = "//*[@id=\"js-flash-container\"]/div/div/div/div/div/span/a[3]"
16
+
17
+ GIST_METADATA_HOOKS = Hash.new
18
+ GIST_METADATA_HOOKS["Title"] = "Title:"
19
+ GIST_METADATA_HOOKS["Authors"] = "Authors:"
20
+ GIST_METADATA_HOOKS["Description"] = "Description:"
21
+ GIST_METADATA_HOOKS["Section"] = "Section:"
22
+ GIST_METADATA_HOOKS["Subsection"] = "Subsection:"
23
+
24
+ class GistCompile < Thor
25
+ no_commands do
26
+ def load_gists(usernames)
27
+ thread_arr = []
28
+ metadata = []
29
+ elements = []
30
+ gists_data = Hash.new
31
+ username_urls = []
32
+
33
+ usernames.each do |u|
34
+ username_urls.push(URI::join(GIST_BASE_URL+'/', u.strip()).to_s)
35
+ end
36
+
37
+ username_urls.each do |username_url|
38
+ page = 1
39
+ while page < 1000
40
+ gist_url_current_page = URI::join(username_url+'/', "?page=#{page}").to_s
41
+ raw_html = Nokogiri::HTML(RestClient.get(gist_url_current_page))
42
+ new_elements = raw_html.css(GIST_XPATH_IDENTIFIER)
43
+ if new_elements.length == 0
44
+ break
45
+ else
46
+ elements.concat(new_elements)
47
+ end
48
+ page = page + 1
49
+ end
50
+ end
51
+
52
+ puts "Processing #{elements.length} gists..."
53
+
54
+ elements.each do |element|
55
+ thread_arr.push(
56
+ Thread.new {
57
+ individual_gist_url = URI::join(GIST_BASE_URL, element['href']+'/').to_s
58
+ individual_gist_url_raw = URI::join(GIST_USERCONTENT_BASE_URL, element['href']+'/', 'raw').to_s
59
+ individual_gist_html = Nokogiri::HTML(RestClient.get(individual_gist_url_raw))
60
+ metadata_for_gist = process_raw_gist(individual_gist_html.xpath("//*/body/p")[0].text)
61
+ if metadata_for_gist != nil && !metadata_for_gist.empty?
62
+ $stdout.write(" • #{individual_gist_url}: " + Paint["[", :yellow] + Paint["OK", :green] + Paint["]",:yellow]+"\r\n")
63
+ $stdout.flush
64
+ GIST_METADATA_HOOKS.each do |key, value|
65
+ if !metadata_for_gist.key? key
66
+ metadata_for_gist[key] = nil
67
+ end
68
+ end
69
+ metadata_for_gist["URL"] = individual_gist_url
70
+ metadata_for_gist["URL_RAW"] = individual_gist_url_raw
71
+ metadata_for_gist["URL_USER"] = /github.com\/[A-Za-z0-9]*/.match(individual_gist_url)
72
+ metadata.push(metadata_for_gist)
73
+ else
74
+ puts " • #{individual_gist_url}: " + Paint["[", :yellow] + Paint["ERR", :red] + Paint["]",:yellow]
75
+ end
76
+ }
77
+ )
78
+ end
79
+
80
+ thread_arr.each{ |t| t.join() }
81
+
82
+ File.open("./prod/gists.json","w") do |f|
83
+ pretty_string = JSON.pretty_generate(metadata.sort_by {|item| item["Title"]})
84
+ f.write(pretty_string)
85
+ f.close()
86
+ end
87
+ end
88
+
89
+ def process_raw_gist (raw_text)
90
+ metadata = Hash.new
91
+
92
+ comment_char = nil
93
+ lines = raw_text.lines()
94
+ last_known_key = nil
95
+
96
+ hooks_remaining = GIST_METADATA_HOOKS.clone
97
+
98
+ for index in 0..lines.length-1
99
+ stripped_line = lines[index].strip()
100
+ if stripped_line != nil && !stripped_line.empty?
101
+ if stripped_line.start_with?("#!")
102
+ next
103
+ end
104
+
105
+ if comment_char == nil
106
+ index = stripped_line.index(GIST_METADATA_HOOKS["Title"])
107
+ if index == nil
108
+ return nil
109
+ else
110
+ comment_char = stripped_line[0..index-1].strip()
111
+ end
112
+ end
113
+ if stripped_line.start_with?(comment_char)
114
+ stripped_line = stripped_line.sub(comment_char,'').strip()
115
+ if stripped_line.empty?
116
+ last_known_key = nil
117
+ break
118
+ end
119
+ hook_data = search_line_for_hooks(hooks_remaining, last_known_key, stripped_line)
120
+ if hook_data == nil
121
+ break
122
+ else
123
+ parsed_key = hook_data[0]
124
+ parsed_value = hook_data[1]
125
+
126
+ last_known_key = parsed_key
127
+ if metadata.key? parsed_key # is the key already in the hash?
128
+ metadata[parsed_key] = metadata[parsed_key] + " #{parsed_value}" # append
129
+ else
130
+ metadata[parsed_key] = parsed_value
131
+ end
132
+ end
133
+ else
134
+ last_known_key = nil
135
+ break
136
+ end
137
+ end
138
+ end
139
+
140
+ return metadata
141
+ end
142
+
143
+ def search_line_for_hooks(hooks_remaining, last_known_key, line)
144
+ hooks_remaining.each do |key, value|
145
+ if line.include? value
146
+ hooks_remaining.delete(key)
147
+ return [key, line.sub(value, '')]
148
+ end
149
+ end
150
+
151
+ if last_known_key != nil
152
+ return [last_known_key, line];
153
+ end
154
+
155
+ return nil
156
+ end
157
+ end
158
+
159
+ desc "start", "Run the gist-compile"
160
+ method_option :username, :aliases => "-u", :desc => "username(s) to run with, seperated by comma: \"claymcleod, othername\""
161
+ method_option :linkauthor, :aliases => "--link-author", :desc => "When serializing in HTML, the authors page will be linked", :default => false
162
+ def start
163
+ usernames = options[:username]
164
+ linkauthor = options[:linkauthor]
165
+
166
+ if usernames == nil
167
+ puts "You must specify a username! (eg. -u \"claymcleod\")"
168
+ return
169
+ end
170
+
171
+ load_gists(usernames.split(","))
172
+ serializer = JSONSerializer.new(File.open("./prod/gists.json","r").read, linkauthor)
173
+ serializer.to_md
174
+ serializer.to_html
175
+ end
176
+ end
177
+
178
+ GistCompile.start(ARGV)
179
+
@@ -0,0 +1,115 @@
1
+ require 'json'
2
+
3
+ class JSONSerializer
4
+ attr_accessor :json
5
+ attr_accessor :linkauthor
6
+
7
+ def initialize(json, linkauthor)
8
+ @json = json
9
+ @linkauthor = linkauthor
10
+ end
11
+
12
+ def compile
13
+ structured_gists = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }
14
+
15
+ entries = JSON.parse(json)
16
+ entries.each do |arr|
17
+ title = arr["Title"] != nil ? arr["Title"].strip() : nil
18
+ authors = arr["Authors"] != nil ? arr["Authors"].strip() : nil
19
+ description = arr["Description"] != nil ? arr["Description"].strip() : nil
20
+ section = arr["Section"] != nil ? arr["Section"].strip() : nil
21
+ subsection = arr["Subsection"] != nil ? arr["Subsection"].strip() : nil
22
+ url = arr["URL"] != nil ? arr["URL"].strip() : nil
23
+ url_user = arr["URL_USER"] != nil ? arr["URL_USER"].strip() : nil
24
+
25
+ if title == nil
26
+ puts "Error: A title must be included for #{url}"
27
+ next
28
+ end
29
+
30
+ if section == nil || subsection == nil
31
+ puts "Error: #{title} must have a section and subsection to be compiled!"
32
+ next
33
+ end
34
+
35
+ structured_gists[section][subsection][title] = {"Authors"=>authors, "Description"=>description,
36
+ "URL"=>url, "URL_USER"=>url_user}
37
+ end
38
+ structured_gists = structured_gists.sort.to_h
39
+ structured_gists.keys.each do |k|
40
+ structured_gists[k] = structured_gists[k].sort.to_h
41
+ structured_gists[k].keys.each do |l|
42
+ structured_gists[k][l] = structured_gists[k][l].sort.to_h
43
+ end
44
+ end
45
+
46
+ return structured_gists
47
+ end
48
+
49
+ def to_md
50
+ structured_gists = compile()
51
+ File.open("./prod/gists.md","w") do |f|
52
+ structured_gists.each do |j, v|
53
+ f.puts("# #{j}\r")
54
+ structured_gists[j].each do |k, v|
55
+ f.puts("### #{k}\r")
56
+ f.puts("\r\n")
57
+ structured_gists[j][k].each do |t, v|
58
+ f.puts("##### #{t}\r")
59
+ structured_gists[j][k][t].each do |l, v|
60
+ if v != nil
61
+ f.puts("* #{l}: #{v}\r")
62
+ end
63
+ end
64
+ f.puts("\r\n")
65
+ end
66
+ end
67
+ end
68
+ f.close()
69
+ end
70
+ end
71
+
72
+ def to_html
73
+ structured_gists = compile()
74
+ File.open("./prod/gists.html","w") do |f|
75
+ f.puts("<!DOCTYPE HTML>")
76
+ f.puts("<html>")
77
+ f.puts(" <head>\n <meta charset=\"UTF-8\">\n </head>");
78
+ f.puts(" <body>")
79
+ f.puts(" Generated by <a href=\"https://github.com/claymcleod/gist-compile\">gist-compile</a> at "+Time.new.strftime("%Y-%m-%d %H:%M:%S"))
80
+ structured_gists.each do |j, v|
81
+ f.puts(" <div class=\"section\">\r")
82
+ f.puts(" <a id=\"#{j}\"></a>")
83
+ f.puts(" <h1>#{j}</h1>\r")
84
+ f.puts(" </div>")
85
+ structured_gists[j].each do |k, v|
86
+ f.puts(" <h2>#{k}</h2>\r")
87
+ f.puts("\r\n")
88
+ structured_gists[j][k].each do |t, v|
89
+ url= structured_gists[j][k][t]["URL"]
90
+ if url == nil
91
+ f.puts(" <h3>#{t}</h3>\r")
92
+ else
93
+ f.puts(" <h3><a href=\'#{url}\'>#{t}</a></h3>")
94
+ end
95
+ f.puts(" <ul>");
96
+ structured_gists[j][k][t].each do |l, v|
97
+ if l != "URL" && l != "URL_USER" && v != nil
98
+ if linkauthor && l == "Authors"
99
+ f.puts(" <li>#{l}: <a href=\"http://#{structured_gists[j][k][t]["URL_USER"]}\">#{v}</a></li>\r")
100
+ else
101
+ f.puts(" <li>#{l}: #{v}</li>\r")
102
+ end
103
+ end
104
+ end
105
+ f.puts("\r\n")
106
+ f.puts(" </ul>\r")
107
+ end
108
+ end
109
+ end
110
+ f.puts(" </body>");
111
+ f.puts("</html>");
112
+ f.close()
113
+ end
114
+ end
115
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gist-compile
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Clay McLeod
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.19.1
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.19.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 0.19.1
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.19.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: paint
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.9.0
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0.9'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: 0.9.0
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0.9'
53
+ - !ruby/object:Gem::Dependency
54
+ name: nokogiri
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: 1.6.6
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 1.6.6
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 1.6.6
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 1.6.6
73
+ - !ruby/object:Gem::Dependency
74
+ name: rest-client
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: 1.7.2
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 1.7.2
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.7.2
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 1.7.2
93
+ description: ''
94
+ email: clay.l.mcleod@gmail.com
95
+ executables: []
96
+ extensions: []
97
+ extra_rdoc_files: []
98
+ files:
99
+ - bin/gist-compile
100
+ - lib/json-serializer.rb
101
+ homepage: http://github.com/claymcleod/gist-compile
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.4.5
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Gist-compile will compile Github gists into an intelligible, book like, form.
125
+ test_files: []