hayde 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.
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