zenweb 2.18.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.tar.gz.sig +0 -0
- data/History.txt +426 -0
- data/Manifest.txt +54 -0
- data/README.txt +63 -0
- data/Rakefile +22 -0
- data/bin/zenweb +27 -0
- data/bin/zenwebpage +66 -0
- data/bin/zenwebsite +39 -0
- data/design/REQUIREMENTS.txt +52 -0
- data/design/ZENWEB_2.txt +69 -0
- data/design/heirarchy.png +0 -0
- data/design/heirarchy.tgif +311 -0
- data/docs/Customizing +76 -0
- data/docs/FAQ +12 -0
- data/docs/Features +128 -0
- data/docs/Presentation +88 -0
- data/docs/QuickStart +32 -0
- data/docs/Renderers +85 -0
- data/docs/SiteMap +13 -0
- data/docs/YourOwnWebsite +32 -0
- data/docs/index +14 -0
- data/docs/metadata.txt +10 -0
- data/lib/ZenWeb.rb +850 -0
- data/lib/ZenWeb/CalendarRenderer.rb +162 -0
- data/lib/ZenWeb/CompactRenderer.rb +45 -0
- data/lib/ZenWeb/CompositeRenderer.rb +63 -0
- data/lib/ZenWeb/FileAttachmentRenderer.rb +57 -0
- data/lib/ZenWeb/FooterRenderer.rb +38 -0
- data/lib/ZenWeb/GenericRenderer.rb +143 -0
- data/lib/ZenWeb/HeaderRenderer.rb +52 -0
- data/lib/ZenWeb/HtmlRenderer.rb +81 -0
- data/lib/ZenWeb/HtmlTableRenderer.rb +94 -0
- data/lib/ZenWeb/HtmlTemplateRenderer.rb +173 -0
- data/lib/ZenWeb/MetadataRenderer.rb +83 -0
- data/lib/ZenWeb/RelativeRenderer.rb +98 -0
- data/lib/ZenWeb/RubyCodeRenderer.rb +56 -0
- data/lib/ZenWeb/SitemapRenderer.rb +56 -0
- data/lib/ZenWeb/StandardRenderer.rb +40 -0
- data/lib/ZenWeb/StupidRenderer.rb +88 -0
- data/lib/ZenWeb/SubpageRenderer.rb +45 -0
- data/lib/ZenWeb/TextToHtmlRenderer.rb +219 -0
- data/lib/ZenWeb/TocRenderer.rb +61 -0
- data/lib/ZenWeb/XXXRenderer.rb +32 -0
- data/test/SiteMap +14 -0
- data/test/Something +4 -0
- data/test/include.txt +3 -0
- data/test/index +8 -0
- data/test/metadata.txt +10 -0
- data/test/ryand/SiteMap +10 -0
- data/test/ryand/blah +4 -0
- data/test/ryand/blah-blah +4 -0
- data/test/ryand/index +52 -0
- data/test/ryand/metadata.txt +2 -0
- data/test/ryand/stuff/index +4 -0
- data/test/test_zenweb.rb +1624 -0
- metadata +161 -0
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# this is a simple template. Globally replace Calendar with the name of
|
|
2
|
+
# your renderer and then go fill in YYY with the appropriate content.
|
|
3
|
+
|
|
4
|
+
require 'ZenWeb/GenericRenderer'
|
|
5
|
+
require 'date' # which requires rational
|
|
6
|
+
require 'time'
|
|
7
|
+
|
|
8
|
+
# class Integer
|
|
9
|
+
# alias :slowgcd :gcd
|
|
10
|
+
# def gcd(n)
|
|
11
|
+
# m = abs
|
|
12
|
+
# while n != 0
|
|
13
|
+
# m %= n
|
|
14
|
+
# tmp = m; m = n; n = tmp
|
|
15
|
+
# end
|
|
16
|
+
# m.abs
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
|
|
20
|
+
# require 'tally'
|
|
21
|
+
# class Integer
|
|
22
|
+
# tally :gcd, true
|
|
23
|
+
# end
|
|
24
|
+
|
|
25
|
+
=begin
|
|
26
|
+
|
|
27
|
+
= Class CalendarRenderer
|
|
28
|
+
|
|
29
|
+
DOC
|
|
30
|
+
|
|
31
|
+
=== Methods
|
|
32
|
+
|
|
33
|
+
=end
|
|
34
|
+
|
|
35
|
+
class CalendarRenderer < GenericRenderer
|
|
36
|
+
|
|
37
|
+
DAYS_IN_MONTH = [
|
|
38
|
+
[nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
|
|
39
|
+
[nil, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
=begin
|
|
43
|
+
|
|
44
|
+
--- CalendarRenderer#render(content)
|
|
45
|
+
|
|
46
|
+
DOC
|
|
47
|
+
|
|
48
|
+
=end
|
|
49
|
+
|
|
50
|
+
def render(content)
|
|
51
|
+
events = Hash.new { |h,k| h[k] = [] }
|
|
52
|
+
reverse = false
|
|
53
|
+
self.scan_region(content, /<cal/i, /<\/cal>/i) do |line, context|
|
|
54
|
+
case context
|
|
55
|
+
when :START then
|
|
56
|
+
reverse = true if line =~ /<cal\s+reverse\s*>/i
|
|
57
|
+
when :END then
|
|
58
|
+
self.generate_calendars(events, reverse)
|
|
59
|
+
else
|
|
60
|
+
if line =~ /(\d\d\d\d-\d\d-\d\d):\s*(.*)/ then
|
|
61
|
+
description = $2
|
|
62
|
+
time = Time.parse($1) # NOT Date! hellishly slow!
|
|
63
|
+
events[$1] << description
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
return self.result
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def generate_calendar(year, month, events)
|
|
72
|
+
|
|
73
|
+
current_events = []
|
|
74
|
+
|
|
75
|
+
which_year = Date.leap?(year) ? 1 : 0
|
|
76
|
+
date_start = Date.civil(year, month, 1)
|
|
77
|
+
last_day = DAYS_IN_MONTH[which_year][month]
|
|
78
|
+
date_end = Date.civil(year, month, -1)
|
|
79
|
+
|
|
80
|
+
push "<table class=\"calendar\">"
|
|
81
|
+
push "<tr>"
|
|
82
|
+
push "<td valign=\"top\">" # calendar
|
|
83
|
+
|
|
84
|
+
m2 = "%02d" % month
|
|
85
|
+
push "<table class=\"view y#{year} m#{m2}\">\n"
|
|
86
|
+
|
|
87
|
+
long_month_name = Date::MONTHNAMES[month]
|
|
88
|
+
month_name = Date::ABBR_MONTHNAMES[month].downcase
|
|
89
|
+
|
|
90
|
+
push "<tr class=\"title\">\n"
|
|
91
|
+
push "<th colspan=7>#{long_month_name} #{year}</th>\n"
|
|
92
|
+
push "</tr>\n"
|
|
93
|
+
|
|
94
|
+
push "<tr class=\"weektitle\"\n"
|
|
95
|
+
push Date::ABBR_DAYNAMES.map { |d| "<th class=\"#{d.downcase}\">#{d}</th>" }.join("\n")
|
|
96
|
+
push "</tr>\n"
|
|
97
|
+
|
|
98
|
+
dow_start = date_start.wday
|
|
99
|
+
push "<tr class=\"days firstweek\">\n"
|
|
100
|
+
push "<td colspan=#{dow_start}> </td>\n" unless dow_start == 0
|
|
101
|
+
|
|
102
|
+
last_sunday = date_end.day - date_end.wday + 1
|
|
103
|
+
|
|
104
|
+
week = 1
|
|
105
|
+
wday = dow_start
|
|
106
|
+
|
|
107
|
+
day_last = date_end.day
|
|
108
|
+
|
|
109
|
+
1.upto(day_last) do |day|
|
|
110
|
+
|
|
111
|
+
event=""
|
|
112
|
+
cal = Time.local(year, month, day).strftime("%Y-%m-%d")
|
|
113
|
+
if events.has_key? cal then
|
|
114
|
+
current_events << "<li>#{cal}:\n<ul>\n"
|
|
115
|
+
events[cal].each do |description|
|
|
116
|
+
current_events << "<li>#{description}\n"
|
|
117
|
+
end
|
|
118
|
+
current_events << "</ul>\n"
|
|
119
|
+
event=" event"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
dow = Date::ABBR_DAYNAMES[(day + dow_start - 1) % 7].downcase
|
|
123
|
+
d2 = "%02d" % day
|
|
124
|
+
push "<td class=\"d#{d2} #{dow}#{event}\">#{day}</td>\n"
|
|
125
|
+
|
|
126
|
+
if day != day_last and wday == 6 then
|
|
127
|
+
push "</tr>\n"
|
|
128
|
+
unless day == last_sunday then
|
|
129
|
+
push "<tr class=\"days\">\n"
|
|
130
|
+
else
|
|
131
|
+
push "<tr class=\"days lastweek\">\n"
|
|
132
|
+
end
|
|
133
|
+
week += 1
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
wday += 1
|
|
137
|
+
wday = 0 if wday >= 7 # remember 0..6
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
day_count = 7-date_end.wday-1
|
|
141
|
+
push "<td colspan=#{day_count}> </td>\n" unless day_count == 0
|
|
142
|
+
push "</tr>\n"
|
|
143
|
+
push "</table>\n"
|
|
144
|
+
push "</td>\n" # /calendar
|
|
145
|
+
push "<td class=\"eventlist\">\n" # events
|
|
146
|
+
push "<ul>\n"
|
|
147
|
+
push current_events.join('')
|
|
148
|
+
push "</ul>\n"
|
|
149
|
+
push "</td>\n" # /events
|
|
150
|
+
push "</tr>\n"
|
|
151
|
+
push "</table>\n"
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def generate_calendars(events, should_reverse=false)
|
|
155
|
+
active_months = events.keys.map { |d| d[0..6] }.sort.uniq
|
|
156
|
+
active_months = active_months.reverse if should_reverse
|
|
157
|
+
active_months.each do |ym|
|
|
158
|
+
year, month = ym.split(/-/).map { |n| n.to_i }
|
|
159
|
+
self.generate_calendar(year, month, events)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
require 'ZenWeb/GenericRenderer'
|
|
5
|
+
|
|
6
|
+
=begin
|
|
7
|
+
|
|
8
|
+
= Class CompactRenderer
|
|
9
|
+
|
|
10
|
+
CompactRenderer compacts HTML whitespace and comments to minimize how much text gets served.
|
|
11
|
+
|
|
12
|
+
=== Methods
|
|
13
|
+
|
|
14
|
+
=end
|
|
15
|
+
|
|
16
|
+
class CompactRenderer < GenericRenderer
|
|
17
|
+
|
|
18
|
+
=begin
|
|
19
|
+
|
|
20
|
+
--- CompactRenderer#render(content)
|
|
21
|
+
|
|
22
|
+
Compacts HTML blah blah DOC
|
|
23
|
+
|
|
24
|
+
=end
|
|
25
|
+
|
|
26
|
+
def render(content)
|
|
27
|
+
|
|
28
|
+
# protect pre blocks
|
|
29
|
+
content = content.gsub(/(<pre>)([\s\S]*?)(<\/pre>)/i) do
|
|
30
|
+
p1 = $1
|
|
31
|
+
body = $2
|
|
32
|
+
p2 = $3
|
|
33
|
+
body = body.gsub(/\n/, 1.chr).gsub(/ /, 2.chr)
|
|
34
|
+
p1 + body + p2
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
content = content.gsub(/\n\r/, '').gsub(/\s+/, ' ').gsub(/> </, '><').strip
|
|
38
|
+
content = content.gsub(1.chr, "\n").gsub(2.chr, " ")
|
|
39
|
+
|
|
40
|
+
push(content)
|
|
41
|
+
|
|
42
|
+
return self.result
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'ZenWeb/GenericRenderer'
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
|
|
5
|
+
= Class CompositeRenderer
|
|
6
|
+
|
|
7
|
+
Allows multiple renderers to be plugged into a single renderer.
|
|
8
|
+
|
|
9
|
+
=== Methods
|
|
10
|
+
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
class CompositeRenderer < GenericRenderer
|
|
14
|
+
|
|
15
|
+
attr_reader :renderers
|
|
16
|
+
|
|
17
|
+
=begin
|
|
18
|
+
|
|
19
|
+
--- CompositeRenderer#new(document)
|
|
20
|
+
|
|
21
|
+
Creates a new CompositeRenderer.
|
|
22
|
+
|
|
23
|
+
=end
|
|
24
|
+
|
|
25
|
+
def initialize(document)
|
|
26
|
+
super(document)
|
|
27
|
+
@renderers = []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
=begin
|
|
31
|
+
|
|
32
|
+
--- CompositeRenderer#render(content)
|
|
33
|
+
|
|
34
|
+
Renders by running all of the renderers in sequence.
|
|
35
|
+
|
|
36
|
+
=end
|
|
37
|
+
|
|
38
|
+
def render(content)
|
|
39
|
+
@renderers.each { | renderer |
|
|
40
|
+
content = renderer.render(content)
|
|
41
|
+
}
|
|
42
|
+
return content
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
=begin
|
|
46
|
+
|
|
47
|
+
--- CompositeRenderer#addRenderer(renderer)
|
|
48
|
+
|
|
49
|
+
Adds renderer to the list of renderers used by this composite.
|
|
50
|
+
|
|
51
|
+
=end
|
|
52
|
+
|
|
53
|
+
def addRenderer(renderer)
|
|
54
|
+
|
|
55
|
+
if (renderer.nil? or ! renderer.kind_of? GenericRenderer) then
|
|
56
|
+
raise ArgumentError, "You may only add an instance of GenericRenderer"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
@renderers.push(renderer)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# this is a simple template. Globally replace FileAttachment with the name of
|
|
2
|
+
# your renderer and then go fill in YYY with the appropriate content.
|
|
3
|
+
|
|
4
|
+
require 'ZenWeb/GenericRenderer'
|
|
5
|
+
|
|
6
|
+
=begin
|
|
7
|
+
|
|
8
|
+
= Class FileAttachmentRenderer
|
|
9
|
+
|
|
10
|
+
Finds content between <file name="name">...</file> tags. Writes the
|
|
11
|
+
content to a file of the given name and includes a link to the file.
|
|
12
|
+
|
|
13
|
+
=== Methods
|
|
14
|
+
|
|
15
|
+
=end
|
|
16
|
+
|
|
17
|
+
class FileAttachmentRenderer < GenericRenderer
|
|
18
|
+
|
|
19
|
+
=begin
|
|
20
|
+
|
|
21
|
+
--- FileAttachmentRenderer#render(content)
|
|
22
|
+
|
|
23
|
+
YYY
|
|
24
|
+
|
|
25
|
+
=end
|
|
26
|
+
|
|
27
|
+
def render(content)
|
|
28
|
+
|
|
29
|
+
start_re = /<file\s+name\s*=\s*\"([\w\.-]+)\"\s*>/i
|
|
30
|
+
end_re = /<\/file>/i
|
|
31
|
+
|
|
32
|
+
file_content = []
|
|
33
|
+
name = nil
|
|
34
|
+
self.scan_region(content, start_re, end_re) do |line, context|
|
|
35
|
+
case context
|
|
36
|
+
when :START then
|
|
37
|
+
name = $1 if line =~ /name\s*=\s*\"([\w\.-]+)\"/i
|
|
38
|
+
when :END then
|
|
39
|
+
raise "name is undefined, add name= attribute" if name.nil?
|
|
40
|
+
dir = File.dirname @document.htmlpath
|
|
41
|
+
path = File.join(dir, name)
|
|
42
|
+
push "\n"
|
|
43
|
+
push "<A HREF=\"#{name}\">Download #{name}</A>\n"
|
|
44
|
+
File.open(path, "w") do |file|
|
|
45
|
+
file.print file_content.join('')
|
|
46
|
+
end
|
|
47
|
+
file_content = []
|
|
48
|
+
else
|
|
49
|
+
file_content.push line
|
|
50
|
+
push " " + line
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
return self.result.strip
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'ZenWeb/GenericRenderer'
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
|
|
5
|
+
= Class FooterRenderer
|
|
6
|
+
|
|
7
|
+
Inserts a footer based on metadata.
|
|
8
|
+
|
|
9
|
+
=== Methods
|
|
10
|
+
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
class FooterRenderer < GenericRenderer
|
|
14
|
+
|
|
15
|
+
=begin
|
|
16
|
+
|
|
17
|
+
--- FooterRenderer#render(content)
|
|
18
|
+
|
|
19
|
+
Adds a footer if the ((|footer|)) metadata item exists. If the
|
|
20
|
+
document contains a BODY close HTML tag, then the footer
|
|
21
|
+
immediately precedes it, otherwise it is simply at the bottom.
|
|
22
|
+
|
|
23
|
+
=end
|
|
24
|
+
|
|
25
|
+
def render(content)
|
|
26
|
+
|
|
27
|
+
footer = @document['footer'] || nil
|
|
28
|
+
|
|
29
|
+
if footer then
|
|
30
|
+
content.sub!(/(<\/BODY>|\z)/i) {
|
|
31
|
+
footer + $1
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
return content
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
$TESTING = FALSE unless defined? $TESTING
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
|
|
5
|
+
= Class GenericRenderer
|
|
6
|
+
|
|
7
|
+
A GenericRenderer provides an interface for all renderers. It renders
|
|
8
|
+
nothing itself.
|
|
9
|
+
|
|
10
|
+
=== Methods
|
|
11
|
+
|
|
12
|
+
=end
|
|
13
|
+
|
|
14
|
+
class GenericRenderer
|
|
15
|
+
|
|
16
|
+
=begin
|
|
17
|
+
|
|
18
|
+
--- GenericRenderer.new(document)
|
|
19
|
+
|
|
20
|
+
Instantiates a generic renderer with a reference to
|
|
21
|
+
((|document|)), it\'s website and sitemap.
|
|
22
|
+
|
|
23
|
+
=end
|
|
24
|
+
|
|
25
|
+
# REFACTOR: do not take a document at all
|
|
26
|
+
def initialize(document)
|
|
27
|
+
@document = document
|
|
28
|
+
@website = @document.website
|
|
29
|
+
@sitemap = @website.sitemap
|
|
30
|
+
@result = []
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
=begin
|
|
34
|
+
|
|
35
|
+
--- GenericRenderer#push(obj)
|
|
36
|
+
|
|
37
|
+
Pushes a string representation of ((|obj|)) onto the result
|
|
38
|
+
array. If ((|obj|)) is an array, it iterates each item and pushes
|
|
39
|
+
them (recursively). If it is not an array, it pushes (({obj.to_s})).
|
|
40
|
+
|
|
41
|
+
=end
|
|
42
|
+
|
|
43
|
+
def push(obj)
|
|
44
|
+
if obj.is_a?(Array) then
|
|
45
|
+
stuff = obj.flatten
|
|
46
|
+
@result.push(*stuff) unless stuff.empty?
|
|
47
|
+
else
|
|
48
|
+
if false then
|
|
49
|
+
@result.push(obj.to_s)
|
|
50
|
+
else
|
|
51
|
+
@result.push(obj)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
=begin
|
|
57
|
+
|
|
58
|
+
--- GenericRenderer#unshift(obj)
|
|
59
|
+
|
|
60
|
+
Same as ((<GenericRenderer#push>)) but prepends instead of appends.
|
|
61
|
+
|
|
62
|
+
=end
|
|
63
|
+
|
|
64
|
+
def unshift(obj)
|
|
65
|
+
if obj.is_a?(Array) then
|
|
66
|
+
obj.reverse.each { | item |
|
|
67
|
+
self.unshift(item)
|
|
68
|
+
}
|
|
69
|
+
else
|
|
70
|
+
@result.unshift(obj.to_s)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# DOC GenericRenderer#result
|
|
76
|
+
def result(clear=true)
|
|
77
|
+
result = @result.join('')
|
|
78
|
+
@result = [] if clear
|
|
79
|
+
return result
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
=begin
|
|
83
|
+
|
|
84
|
+
--- GenericRenderer#render(content)
|
|
85
|
+
|
|
86
|
+
Renders the content. Does nothing in GenericRenderer, but is
|
|
87
|
+
expected to be overridden by subclasses. ((|content|)) is an array
|
|
88
|
+
of strings and render must return an array of strings.
|
|
89
|
+
|
|
90
|
+
NEW: the argument and result are now a single string!
|
|
91
|
+
|
|
92
|
+
=end
|
|
93
|
+
|
|
94
|
+
# REFACTOR: pass in content and document to render
|
|
95
|
+
def render(content)
|
|
96
|
+
return content
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def each_paragraph(content)
|
|
100
|
+
content.scan(/.+?(?:#{$/}#{$/}+|\Z)/m) do |block|
|
|
101
|
+
$stderr.puts "BLOCK = #{block.inspect}" if $DEBUG
|
|
102
|
+
yield(block)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def each_paragraph_matching(content, pattern)
|
|
107
|
+
$stderr.puts "CONTENT = #{content.inspect}" if $DEBUG
|
|
108
|
+
self.each_paragraph(content) do |block|
|
|
109
|
+
$stderr.puts "PARAGRAPH = #{block.inspect}" if $DEBUG
|
|
110
|
+
if block =~ pattern then
|
|
111
|
+
yield(block)
|
|
112
|
+
else
|
|
113
|
+
push block
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def scan_region(content, region_start, region_end)
|
|
119
|
+
matching = false
|
|
120
|
+
content.scan(/.*#{$/}?/) do |l|
|
|
121
|
+
# TODO: detect region_end w/o start and freak
|
|
122
|
+
# TODO: detect nesting and freak
|
|
123
|
+
if l =~ region_start then
|
|
124
|
+
matching = true
|
|
125
|
+
$stderr.puts :START, l.inspect if $DEBUG
|
|
126
|
+
yield(l, :START)
|
|
127
|
+
matching = false if l =~ region_end
|
|
128
|
+
elsif l =~ region_end then
|
|
129
|
+
matching = false
|
|
130
|
+
$stderr.puts :END, l.inspect if $DEBUG
|
|
131
|
+
yield(l, :END)
|
|
132
|
+
elsif matching then
|
|
133
|
+
$stderr.puts :MIDDLE, l.inspect if $DEBUG
|
|
134
|
+
yield(l, :MIDDLE)
|
|
135
|
+
else
|
|
136
|
+
$stderr.puts :IGNORED, l.inspect if $DEBUG
|
|
137
|
+
push l
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
|