hayde 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,12 @@
1
+ # .document is used by rdoc and yard to know how to generate documentation
2
+ # for example, it can be used to control how rdoc gets built when you do `gem install foo`
3
+
4
+ README.rdoc
5
+ lib/**/*.rb
6
+ bin/*
7
+
8
+ # Files below the line with - are treated as 'extra files', and aren't parsed for ruby code
9
+ -
10
+ README.markdown
11
+ features/**/*.feature
12
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ doc
19
+ rdoc
20
+ pkg
21
+ .yardoc
22
+ .bundle
23
+
24
+ ## PROJECT::SPECIFIC
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'http://gemcutter.org'
2
+ source 'http://gems.github.com'
3
+
4
+ group :runtime do
5
+ gem 'RedCloth', '>= 4.1.1'
6
+ gem 'actionpack', '= 3.0.0.beta3'
7
+ end
8
+
9
+ group :development do
10
+ gem 'rake'
11
+ gem 'jeweler'
12
+ gem 'shoulda'
13
+ gem 'yard'
14
+ gem 'rcov'
15
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Roman Zaharenkov
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.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = hayde
2
+
3
+ Hayde is a helper for generating guides articles from textile source. Extracted from railties-3.0.0.beta3 project.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Roman Zaharenkov. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,65 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require "bundler"
4
+ Bundler.setup
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "hayde"
10
+ gem.summary = %Q{Textile guides generator like rails-guides.}
11
+ gem.description = %Q{Helper for generating guides articles from textile source. Extracted from railties-3.0.0.beta3 project. }
12
+ gem.email = "ZaharenkovRoman@gmail.com"
13
+ gem.homepage = "http://github.com/Romantic/hayde"
14
+ gem.authors = ["Roman Zaharenkov"]
15
+ gem.add_dependency('RedCloth', '>= 4.1.1')
16
+ gem.add_dependency('actionpack', '>= 2.9')
17
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
18
+
19
+ gem.files.include %w(lib/hayde/**/*)
20
+
21
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
22
+ end
23
+ Jeweler::GemcutterTasks.new
24
+ rescue LoadError
25
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
26
+ end
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ begin
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |test|
38
+ test.libs << 'test'
39
+ test.pattern = 'test/**/test_*.rb'
40
+ test.verbose = true
41
+ end
42
+ rescue LoadError
43
+ task :rcov do
44
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
45
+ end
46
+ end
47
+
48
+ task :test => :check_dependencies
49
+
50
+ task :default => :test
51
+
52
+ require 'yard'
53
+ YARD::Rake::YardocTask.new(:yardoc) do |t|
54
+ t.files = FileList['lib/**/*.rb'].exclude('lib/hayde/templates/**/*.rb')
55
+ end
56
+
57
+ require 'rake/rdoctask'
58
+ Rake::RDocTask.new do |rdoc|
59
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
60
+
61
+ rdoc.rdoc_dir = 'rdoc'
62
+ rdoc.title = "hayde #{version}"
63
+ rdoc.rdoc_files.include('README*')
64
+ rdoc.rdoc_files.include('lib/**/*.rb')
65
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/hayde.gemspec ADDED
@@ -0,0 +1,66 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{hayde}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Roman Zaharenkov"]
12
+ s.date = %q{2010-05-14}
13
+ s.description = %q{Helper for generating guides articles from textile source. Extracted from railties-3.0.0.beta3 project. }
14
+ s.email = %q{ZaharenkovRoman@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "Gemfile",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "hayde.gemspec",
28
+ "lib/hayde.rb",
29
+ "lib/hayde/generator.rb",
30
+ "lib/hayde/helpers.rb",
31
+ "lib/hayde/indexer.rb",
32
+ "lib/hayde/levenshtein.rb",
33
+ "lib/hayde/textile_extensions.rb",
34
+ "test/helper.rb",
35
+ "test/test_hayde.rb"
36
+ ]
37
+ s.homepage = %q{http://github.com/Romantic/hayde}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.7}
41
+ s.summary = %q{Textile guides generator like rails-guides.}
42
+ s.test_files = [
43
+ "test/helper.rb",
44
+ "test/test_hayde.rb"
45
+ ]
46
+
47
+ if s.respond_to? :specification_version then
48
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
+ s.add_runtime_dependency(%q<RedCloth>, [">= 4.1.1"])
53
+ s.add_runtime_dependency(%q<actionpack>, [">= 2.9"])
54
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
55
+ else
56
+ s.add_dependency(%q<RedCloth>, [">= 4.1.1"])
57
+ s.add_dependency(%q<actionpack>, [">= 2.9"])
58
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
59
+ end
60
+ else
61
+ s.add_dependency(%q<RedCloth>, [">= 4.1.1"])
62
+ s.add_dependency(%q<actionpack>, [">= 2.9"])
63
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
64
+ end
65
+ end
66
+
@@ -0,0 +1,244 @@
1
+ # ---------------------------------------------------------------------------
2
+ #
3
+ # This script generates the guides. It can be invoked either directly or via the
4
+ # generate_guides rake task within the railties directory.
5
+ #
6
+ # Guides are taken from the source directory, and the resulting HTML goes into the
7
+ # output directory. Assets are stored under files, and copied to output/files as
8
+ # part of the generation process.
9
+ #
10
+ # Options:
11
+ #
12
+ # :warnings
13
+ # If you are writing a guide, please work always with :warnings = true.
14
+ # Users can generate the guides, and thus this flag is off by default.
15
+ #
16
+ # Internal links (anchors) are checked. If a reference is broken levenshtein
17
+ # distance is used to suggest an existing one. This is useful since IDs are
18
+ # generated by Textile from headers and thus edits alter them.
19
+ #
20
+ # Also detects duplicated IDs. They happen if there are headers with the same
21
+ # text. Please do resolve them, if any, so guides are valid XHTML.
22
+ #
23
+ # :force
24
+ # Set to true to force the generation of all guides.
25
+ #
26
+ # :edge
27
+ # Set to true to indicate generated guides should be marked as edge. This
28
+ # inserts a badge and changes the preamble of the home page.
29
+ #
30
+ # :layout
31
+ # Use to customize layout. Layout must be placed to the same directory with guides sources.
32
+ #
33
+ # ---------------------------------------------------------------------------
34
+
35
+ require 'set'
36
+ require 'fileutils'
37
+
38
+ require 'active_support/core_ext/string/output_safety'
39
+ require 'active_support/core_ext/object/blank'
40
+ require 'action_controller'
41
+ require 'action_view'
42
+
43
+ require 'hayde/indexer'
44
+ require 'hayde/helpers'
45
+ require 'hayde/levenshtein'
46
+ require 'hayde/utils'
47
+
48
+ module Hayde
49
+ class Generator
50
+ # TODO: Move method to utils mudule.
51
+ def self.filelist_attribute(*names)
52
+ names.each do |name|
53
+ define_method "#{name}" do
54
+ files = instance_variable_get("@#{name}_files")
55
+ if !files
56
+ files = FileList.new()
57
+ instance_variable_set("@#{name}_files", files)
58
+ end
59
+ files
60
+ end
61
+
62
+ define_method "#{name}=" do |files|
63
+ instance_variable_set("@#{name}_files", FileList[files])
64
+ if files && files.class != FileList
65
+ files = FileList.new(files)
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ attr_accessor :output_dir, :assets_dir, :warnings, :edge, :force, :layout
72
+ filelist_attribute :sources
73
+
74
+ GUIDES_RE = /\.(?:textile|html\.erb)$/
75
+
76
+ def initialize(output = nil)
77
+ initialize_output_dir(output)
78
+ yield self if block_given?
79
+ end
80
+
81
+ def generate
82
+ generate_guides
83
+ copy_assets
84
+ end
85
+
86
+ private
87
+
88
+ def initialize_output_dir(output)
89
+ @output_dir = output || File.join(File.dirname(__FILE__), "docs", "guides")
90
+ FileUtils.mkdir_p(@output_dir)
91
+ end
92
+
93
+ def generate_guides
94
+ sources.each do |source|
95
+ output = output_file_for(source)
96
+ generate_guide(source, output) if generate?(source, output)
97
+ end
98
+ end
99
+
100
+ def copy_assets
101
+ FileUtils.cp_r(Dir.glob("#{assets_dir}/*"), output_dir)
102
+ end
103
+
104
+ def output_file_for(source)
105
+ output = File.basename(source).sub(GUIDES_RE, '.html')
106
+ File.join(output_dir, output)
107
+ end
108
+
109
+ def generate?(source, output)
110
+ force || !File.exists?(output) || File.mtime(output) < File.mtime(source)
111
+ end
112
+
113
+ def generate_guide(source, output)
114
+ puts "Generating #{output}"
115
+ File.open(output, 'w') do |f|
116
+ view = ActionView::Base.new(File.dirname(source), :edge => edge)
117
+ view.extend(Helpers)
118
+
119
+ if source =~ /\.html\.erb$/
120
+ # Generate the special pages like the home.
121
+ result = view.render(:layout => 'layout', :file => source)
122
+ else
123
+ body = File.read(source)
124
+ body = set_header_section(body, view)
125
+ body = set_index(body, view)
126
+
127
+ result = view.render(:layout => 'layout', :text => textile(body))
128
+
129
+ warn_about_broken_links(result) if warnings
130
+ end
131
+
132
+ f.write result
133
+ end
134
+ end
135
+
136
+ def set_header_section(body, view)
137
+ new_body = body.gsub(/(.*?)endprologue\./m, '').strip
138
+ header = $1
139
+
140
+ header =~ /h2\.(.*)/
141
+ page_title = "Framework Guides: #{$1.strip}"
142
+
143
+ header = textile(header)
144
+
145
+ view.content_for(:page_title) { page_title.html_safe }
146
+ view.content_for(:header_section) { header.html_safe }
147
+ new_body
148
+ end
149
+
150
+ def set_index(body, view)
151
+ index = <<-INDEX
152
+ <div id="subCol">
153
+ <h3 class="chapter"><img src="images/chapters_icon.gif" alt="" />Chapters</h3>
154
+ <ol class="chapters">
155
+ INDEX
156
+
157
+ i = Indexer.new(body, warnings)
158
+ i.index
159
+
160
+ # Set index for 2 levels
161
+ i.level_hash.each do |key, value|
162
+ link = view.content_tag(:a, :href => key[:id]) { textile(key[:title], true).html_safe }
163
+
164
+ children = value.keys.map do |k|
165
+ view.content_tag(:li,
166
+ view.content_tag(:a, :href => k[:id]) { textile(k[:title], true).html_safe })
167
+ end
168
+
169
+ children_ul = children.empty? ? "" : view.content_tag(:ul, children.join(" ").html_safe)
170
+
171
+ index << view.content_tag(:li, link.html_safe + children_ul.html_safe)
172
+ end
173
+
174
+ index << '</ol>'
175
+ index << '</div>'
176
+
177
+ view.content_for(:index_section) { index.html_safe }
178
+
179
+ i.result
180
+ end
181
+
182
+ def textile(body, lite_mode=false)
183
+ # If the issue with notextile is fixed just remove the wrapper.
184
+ with_workaround_for_notextile(body) do |body|
185
+ t = RedCloth.new(body)
186
+ t.hard_breaks = false
187
+ t.lite_mode = lite_mode
188
+ t.to_html(:notestuff, :plusplus, :code, :tip)
189
+ end
190
+ end
191
+
192
+ # For some reason the notextile tag does not always turn off textile. See
193
+ # LH ticket of the security guide (#7). As a temporary workaround we deal
194
+ # with code blocks by hand.
195
+ def with_workaround_for_notextile(body)
196
+ code_blocks = []
197
+ body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain)>(.*?)</\1>}m) do |m|
198
+ es = ERB::Util.h($2)
199
+ css_class = ['erb', 'shell'].include?($1) ? 'html' : $1
200
+ code_blocks << %{<div class="code_container"><code class="#{css_class}">#{es}</code></div>}
201
+ "\ndirty_workaround_for_notextile_#{code_blocks.size - 1}\n"
202
+ end
203
+
204
+ body = yield body
205
+
206
+ body.gsub(%r{<p>dirty_workaround_for_notextile_(\d+)</p>}) do |_|
207
+ code_blocks[$1.to_i]
208
+ end
209
+ end
210
+
211
+ def warn_about_broken_links(html)
212
+ anchors = extract_anchors(html)
213
+ check_fragment_identifiers(html, anchors)
214
+ end
215
+
216
+ def extract_anchors(html)
217
+ # Textile generates headers with IDs computed from titles.
218
+ anchors = Set.new
219
+ html.scan(/<h\d\s+id="([^"]+)/).flatten.each do |anchor|
220
+ if anchors.member?(anchor)
221
+ puts "*** DUPLICATE ID: #{anchor}, please put and explicit ID, e.g. h4(#explicit-id), or consider rewording"
222
+ else
223
+ anchors << anchor
224
+ end
225
+ end
226
+
227
+ # Also, footnotes are rendered as paragraphs this way.
228
+ anchors += Set.new(html.scan(/<p\s+class="footnote"\s+id="([^"]+)/).flatten)
229
+ return anchors
230
+ end
231
+
232
+ def check_fragment_identifiers(html, anchors)
233
+ html.scan(/<a\s+href="#([^"]+)/).flatten.each do |fragment_identifier|
234
+ next if fragment_identifier == 'mainCol' # in layout, jumps to some DIV
235
+ unless anchors.member?(fragment_identifier)
236
+ guess = anchors.min { |a, b|
237
+ Levenshtein.distance(fragment_identifier, a) <=> Levenshtein.distance(fragment_identifier, b)
238
+ }
239
+ puts "*** BROKEN LINK: ##{fragment_identifier}, perhaps you meant ##{guess}."
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,34 @@
1
+ module Hayde
2
+ module Helpers
3
+ def guide(name, url, options = {}, &block)
4
+ link = content_tag(:a, :href => url) { name }
5
+ result = content_tag(:dt, link)
6
+
7
+ if ticket = options[:ticket]
8
+ result << content_tag(:dd, lh(ticket), :class => 'ticket')
9
+ end
10
+
11
+ result << content_tag(:dd, capture(&block))
12
+ result
13
+ end
14
+
15
+ def lh(id, label = "Lighthouse Ticket")
16
+ url = "http://rails.lighthouseapp.com/projects/16213/tickets/#{id}"
17
+ content_tag(:a, label, :href => url)
18
+ end
19
+
20
+ def author(name, nick, image = 'credits_pic_blank.gif', &block)
21
+ image = "images/#{image}"
22
+
23
+ result = content_tag(:img, nil, :src => image, :class => 'left pic', :alt => name)
24
+ result << content_tag(:h3, name)
25
+ result << content_tag(:p, capture(&block))
26
+ content_tag(:div, result, :class => 'clearfix', :id => nick)
27
+ end
28
+
29
+ def code(&block)
30
+ c = capture(&block)
31
+ content_tag(:code, c)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,68 @@
1
+ require 'active_support/core_ext/object/blank'
2
+ require 'active_support/ordered_hash'
3
+
4
+ module Hayde
5
+ class Indexer
6
+ attr_reader :body, :result, :warnings, :level_hash
7
+
8
+ def initialize(body, warnings)
9
+ @body = body
10
+ @result = @body.dup
11
+ @warnings = warnings
12
+ end
13
+
14
+ def index
15
+ @level_hash = process(body)
16
+ end
17
+
18
+ private
19
+
20
+ def process(string, current_level=3, counters=[1])
21
+ s = StringScanner.new(string)
22
+
23
+ level_hash = ActiveSupport::OrderedHash.new
24
+
25
+ while !s.eos?
26
+ re = %r{^h(\d)(?:\((#.*?)\))?\s*\.\s*(.*)$}
27
+ s.match?(re)
28
+ if matched = s.matched
29
+ matched =~ re
30
+ level, idx, title = $1.to_i, $2, $3.strip
31
+
32
+ if level < current_level
33
+ # This is needed. Go figure.
34
+ return level_hash
35
+ elsif level == current_level
36
+ index = counters.join(".")
37
+ idx ||= '#' + title_to_idx(title)
38
+
39
+ raise "Parsing Fail" unless @result.sub!(matched, "h#{level}(#{idx}). #{index} #{title}")
40
+
41
+ key = {
42
+ :title => title,
43
+ :id => idx
44
+ }
45
+ # Recurse
46
+ counters << 1
47
+ level_hash[key] = process(s.post_match, current_level + 1, counters)
48
+ counters.pop
49
+
50
+ # Increment the current level
51
+ last = counters.pop
52
+ counters << last + 1
53
+ end
54
+ end
55
+ s.getch
56
+ end
57
+ level_hash
58
+ end
59
+
60
+ def title_to_idx(title)
61
+ idx = title.strip.downcase.gsub(/\s+|_/, '-').delete('^a-z0-9-').sub(/^[^a-z]*/, '')
62
+ if warnings && idx.blank?
63
+ puts "BLANK ID: please put an explicit ID for section #{title}, as in h5(#my-id)"
64
+ end
65
+ idx
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,31 @@
1
+ module Hayde
2
+ module Levenshtein
3
+ # Based on the pseudocode in http://en.wikipedia.org/wiki/Levenshtein_distance.
4
+ def self.distance(s1, s2)
5
+ s = s1.unpack('U*')
6
+ t = s2.unpack('U*')
7
+ m = s.length
8
+ n = t.length
9
+
10
+ # matrix initialization
11
+ d = []
12
+ 0.upto(m) { |i| d << [i] }
13
+ 0.upto(n) { |j| d[0][j] = j }
14
+
15
+ # distance computation
16
+ 1.upto(m) do |i|
17
+ 1.upto(n) do |j|
18
+ cost = s[i] == t[j] ? 0 : 1
19
+ d[i][j] = [
20
+ d[i-1][j] + 1, # deletion
21
+ d[i][j-1] + 1, # insertion
22
+ d[i-1][j-1] + cost, # substitution
23
+ ].min
24
+ end
25
+ end
26
+
27
+ # all done
28
+ return d[m][n]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ module Hayde
2
+ module TextileExtensions
3
+ def notestuff(body)
4
+ body.gsub!(/^(IMPORTANT|CAUTION|WARNING|NOTE|INFO)[.:](.*)$/) do |m|
5
+ css_class = $1.downcase
6
+ css_class = 'warning' if ['caution', 'important'].include?(css_class)
7
+
8
+ result = "<div class='#{css_class}'><p>"
9
+ result << $2.strip
10
+ result << '</p></div>'
11
+ result
12
+ end
13
+ end
14
+
15
+ def tip(body)
16
+ body.gsub!(/^TIP[.:](.*)$/) do |m|
17
+ result = "<div class='info'><p>"
18
+ result << $1.strip
19
+ result << '</p></div>'
20
+ result
21
+ end
22
+ end
23
+
24
+ def plusplus(body)
25
+ body.gsub!(/\+(.*?)\+/) do |m|
26
+ "<notextile><tt>#{$1}</tt></notextile>"
27
+ end
28
+
29
+ # The real plus sign
30
+ body.gsub!('<plus>', '+')
31
+ end
32
+
33
+ def code(body)
34
+ body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain)>(.*?)</\1>}m) do |m|
35
+ es = ERB::Util.h($2)
36
+ css_class = ['erb', 'shell'].include?($1) ? 'html' : $1
37
+ %{<notextile><div class="code_container"><code class="#{css_class}">#{es}</code></div></notextile>}
38
+ end
39
+ end
40
+ end
41
+ end
data/lib/hayde.rb ADDED
@@ -0,0 +1,33 @@
1
+ pwd = File.dirname(__FILE__)
2
+ $:.unshift pwd
3
+
4
+ # Loading Action Pack requires rack and erubis.
5
+ require 'rubygems'
6
+
7
+ begin
8
+ # Guides generation in the Rails repo.
9
+ as_lib = File.join(pwd, "../../activesupport/lib")
10
+ ap_lib = File.join(pwd, "../../actionpack/lib")
11
+
12
+ $:.unshift as_lib if File.directory?(as_lib)
13
+ $:.unshift ap_lib if File.directory?(ap_lib)
14
+ rescue LoadError
15
+ # Guides generation from gems.
16
+ gem "actionpack", '>= 3.0'
17
+ end
18
+
19
+ begin
20
+ gem 'RedCloth', '>= 4.1.1'
21
+ require 'redcloth'
22
+ rescue Gem::LoadError
23
+ $stderr.puts %(Generating Guides requires RedCloth 4.1.1+)
24
+ exit 1
25
+ end
26
+
27
+ module Hayde
28
+ require 'hayde/textile_extensions'
29
+ require 'hayde/generator'
30
+
31
+ RedCloth.send(:include, Hayde::TextileExtensions)
32
+ #Hayde::Generator.new.generate
33
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'hayde'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestHayde < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hayde
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Roman Zaharenkov
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-14 00:00:00 +03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :runtime
23
+ prerelease: false
24
+ name: RedCloth
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 57
31
+ segments:
32
+ - 4
33
+ - 1
34
+ - 1
35
+ version: 4.1.1
36
+ requirement: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ type: :runtime
39
+ prerelease: false
40
+ name: actionpack
41
+ version_requirements: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ hash: 17
47
+ segments:
48
+ - 2
49
+ - 9
50
+ version: "2.9"
51
+ requirement: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ type: :development
54
+ prerelease: false
55
+ name: thoughtbot-shoulda
56
+ version_requirements: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirement: *id003
66
+ description: "Helper for generating guides articles from textile source. Extracted from railties-3.0.0.beta3 project. "
67
+ email: ZaharenkovRoman@gmail.com
68
+ executables: []
69
+
70
+ extensions: []
71
+
72
+ extra_rdoc_files:
73
+ - LICENSE
74
+ - README.rdoc
75
+ files:
76
+ - .document
77
+ - .gitignore
78
+ - Gemfile
79
+ - LICENSE
80
+ - README.rdoc
81
+ - Rakefile
82
+ - VERSION
83
+ - hayde.gemspec
84
+ - lib/hayde.rb
85
+ - lib/hayde/generator.rb
86
+ - lib/hayde/helpers.rb
87
+ - lib/hayde/indexer.rb
88
+ - lib/hayde/levenshtein.rb
89
+ - lib/hayde/textile_extensions.rb
90
+ - test/helper.rb
91
+ - test/test_hayde.rb
92
+ has_rdoc: true
93
+ homepage: http://github.com/Romantic/hayde
94
+ licenses: []
95
+
96
+ post_install_message:
97
+ rdoc_options:
98
+ - --charset=UTF-8
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 3
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ requirements: []
120
+
121
+ rubyforge_project:
122
+ rubygems_version: 1.3.7
123
+ signing_key:
124
+ specification_version: 3
125
+ summary: Textile guides generator like rails-guides.
126
+ test_files:
127
+ - test/helper.rb
128
+ - test/test_hayde.rb