zenweb 2.18.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,98 @@
|
|
1
|
+
require 'ZenWeb/GenericRenderer'
|
2
|
+
|
3
|
+
$Uri_Implemented = true
|
4
|
+
if RUBY_VERSION =~ /1.6.(\d+)/ then
|
5
|
+
$Uri_Implemented = $1.to_i >= 7
|
6
|
+
end
|
7
|
+
|
8
|
+
if $Uri_Implemented then
|
9
|
+
require 'uri'
|
10
|
+
else
|
11
|
+
if $TESTING then
|
12
|
+
$stderr.puts "WARNING: RelativeRenderer can not be implemented in ruby versions < 1.6.7."
|
13
|
+
$stderr.puts "Some unit tests will fail as a result"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
=begin
|
18
|
+
|
19
|
+
= Class RelativeRenderer
|
20
|
+
|
21
|
+
Converts urls to relative urls if possible...
|
22
|
+
|
23
|
+
=== Methods
|
24
|
+
|
25
|
+
=end
|
26
|
+
|
27
|
+
class RelativeRenderer < GenericRenderer
|
28
|
+
|
29
|
+
=begin
|
30
|
+
|
31
|
+
--- RelativeRenderer.new(document)
|
32
|
+
|
33
|
+
Instantiates RelativeRenderer.
|
34
|
+
|
35
|
+
=end
|
36
|
+
|
37
|
+
def initialize(document)
|
38
|
+
super(document)
|
39
|
+
|
40
|
+
if $Uri_Implemented then
|
41
|
+
# fake, since we don't know the domain (or care), but necessary for URI#-
|
42
|
+
# it bombs otherwise... fun.
|
43
|
+
@base = URI.parse("http://www.domain.com/")
|
44
|
+
|
45
|
+
# @base + url will == url if url is not relative...
|
46
|
+
@docurl = @base + URI.parse(@document.url)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
=begin
|
51
|
+
|
52
|
+
--- RelativeRenderer#render(content)
|
53
|
+
|
54
|
+
Converts urls that look like they can be made relative to be so...
|
55
|
+
|
56
|
+
=end
|
57
|
+
|
58
|
+
def render(content)
|
59
|
+
if $Uri_Implemented then
|
60
|
+
content.each { | line |
|
61
|
+
|
62
|
+
line.gsub!(%r%(href=\")([^\"]+)(\")%i) { |url|
|
63
|
+
front = $1
|
64
|
+
oldurl = $2
|
65
|
+
back = $3
|
66
|
+
newurl = convert(oldurl)
|
67
|
+
|
68
|
+
front + newurl + back
|
69
|
+
}
|
70
|
+
|
71
|
+
push(line)
|
72
|
+
}
|
73
|
+
|
74
|
+
return self.result
|
75
|
+
else
|
76
|
+
return content
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def convert(u)
|
81
|
+
|
82
|
+
if $Uri_Implemented and (u[0].chr != '#') then
|
83
|
+
oldurl = URI.parse(u)
|
84
|
+
|
85
|
+
if oldurl.relative? then
|
86
|
+
oldurl = @base + oldurl
|
87
|
+
scheme = oldurl.scheme
|
88
|
+
newurl = oldurl - @docurl
|
89
|
+
else
|
90
|
+
newurl = u
|
91
|
+
end
|
92
|
+
return newurl.to_s
|
93
|
+
else
|
94
|
+
return u
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'ZenWeb/GenericRenderer'
|
2
|
+
|
3
|
+
=begin
|
4
|
+
|
5
|
+
= Class RubyCodeRenderer
|
6
|
+
|
7
|
+
Finds paragraphs prefixed with "!" and evaluates them with xmp
|
8
|
+
|
9
|
+
=== Methods
|
10
|
+
|
11
|
+
=end
|
12
|
+
|
13
|
+
class RubyCodeRenderer < GenericRenderer
|
14
|
+
|
15
|
+
=begin
|
16
|
+
|
17
|
+
--- RubyCodeRenderer#render(content)
|
18
|
+
|
19
|
+
Finds paragraphs prefixed with "!" and evaluates them with xmp
|
20
|
+
|
21
|
+
=end
|
22
|
+
|
23
|
+
def render(content)
|
24
|
+
|
25
|
+
text = content.split($PARAGRAPH_RE)
|
26
|
+
|
27
|
+
text.each do | p |
|
28
|
+
|
29
|
+
if p =~ /^\s*\!/m then
|
30
|
+
p.gsub!(/^\s*\!\s*/, '')
|
31
|
+
|
32
|
+
begin
|
33
|
+
cmd = "irb --prompt xmp --noreadline 2>/dev/null"
|
34
|
+
puts "Running irb for code:\n#{p}" unless $TESTING
|
35
|
+
IO.popen(cmd, "r+") do |xmp|
|
36
|
+
xmp.puts(p + "\nexit")
|
37
|
+
result = xmp.read
|
38
|
+
result.gsub!(/\s+>> exit\s*\Z/, '')
|
39
|
+
result.gsub!(/=>(.*)\Z/m, '=><EM>\1</EM>')
|
40
|
+
push result
|
41
|
+
end
|
42
|
+
rescue Exception => something
|
43
|
+
$stderr.puts "xmp: #{something}\nTrace =\n" + $@.join("\n") + "\n"
|
44
|
+
end
|
45
|
+
else
|
46
|
+
push p
|
47
|
+
end
|
48
|
+
push ''
|
49
|
+
end
|
50
|
+
|
51
|
+
# put it back into line-by-line format
|
52
|
+
@result = @result.join("\n").scan(/^.*[\n\r]+/)
|
53
|
+
|
54
|
+
return self.result
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'ZenWeb/GenericRenderer'
|
2
|
+
|
3
|
+
=begin
|
4
|
+
|
5
|
+
= Class SitemapRenderer
|
6
|
+
|
7
|
+
Converts a sitemap file into output suitable for
|
8
|
+
((<Class TextToHtmlRenderer>)).
|
9
|
+
|
10
|
+
=== Methods
|
11
|
+
|
12
|
+
=end
|
13
|
+
|
14
|
+
class SitemapRenderer < GenericRenderer
|
15
|
+
|
16
|
+
=begin
|
17
|
+
|
18
|
+
--- SitemapRenderer#render(content)
|
19
|
+
|
20
|
+
Converts a sitemap file into output suitable for ((<Class TextToHtmlRenderer>)).
|
21
|
+
|
22
|
+
=end
|
23
|
+
|
24
|
+
def render(content)
|
25
|
+
|
26
|
+
# used for /~user/blah.html pages
|
27
|
+
# basically, we need to strip off whatever the base of the sitemap is to
|
28
|
+
# make sure we indent everything to the right level.
|
29
|
+
base = @sitemap.url
|
30
|
+
base = base.sub(%r%/[^/]*$%, '/')
|
31
|
+
|
32
|
+
urls = @sitemap.doc_order.clone
|
33
|
+
|
34
|
+
@document['subtitle'] ||= "There are #{urls.size} pages in this website."
|
35
|
+
urls.each { | url |
|
36
|
+
|
37
|
+
indent = url.sub(/\.html$/, "")
|
38
|
+
indent.sub!(/#{base}/, "")
|
39
|
+
indent.sub!(/\/index$/, "")
|
40
|
+
indent.sub!(/^\//, "")
|
41
|
+
indent.gsub!(/[^\/]+\//, "\t")
|
42
|
+
|
43
|
+
if indent =~ /^(\t*).*/ then
|
44
|
+
indent = $1
|
45
|
+
end
|
46
|
+
|
47
|
+
doc = @website[url]
|
48
|
+
title = doc.fulltitle
|
49
|
+
|
50
|
+
push("#{indent}+ <A HREF=\"#{url}\">#{title}</A>\n")
|
51
|
+
}
|
52
|
+
|
53
|
+
return self.result
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'ZenWeb/CompositeRenderer'
|
2
|
+
require 'ZenWeb/SubpageRenderer'
|
3
|
+
require 'ZenWeb/MetadataRenderer'
|
4
|
+
require 'ZenWeb/TextToHtmlRenderer'
|
5
|
+
require 'ZenWeb/HtmlTemplateRenderer'
|
6
|
+
require 'ZenWeb/FooterRenderer'
|
7
|
+
|
8
|
+
=begin
|
9
|
+
|
10
|
+
= Class StandardRenderer
|
11
|
+
|
12
|
+
Creates a fairly standard webpage using several different renderers.
|
13
|
+
|
14
|
+
=== Methods
|
15
|
+
|
16
|
+
=end
|
17
|
+
|
18
|
+
class StandardRenderer < CompositeRenderer
|
19
|
+
|
20
|
+
=begin
|
21
|
+
|
22
|
+
--- StandardRenderer#new(document)
|
23
|
+
|
24
|
+
Creates a new StandardRenderer.
|
25
|
+
|
26
|
+
=end
|
27
|
+
|
28
|
+
def initialize(document)
|
29
|
+
super(document)
|
30
|
+
|
31
|
+
# TODO: make this a metadata variable
|
32
|
+
self.addRenderer(SubpageRenderer.new(document))
|
33
|
+
self.addRenderer(MetadataRenderer.new(document))
|
34
|
+
self.addRenderer(TextToHtmlRenderer.new(document))
|
35
|
+
self.addRenderer(HtmlTemplateRenderer.new(document))
|
36
|
+
self.addRenderer(FooterRenderer.new(document))
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# this is a simple template. Globally replace Stupid 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 StupidRenderer
|
9
|
+
|
10
|
+
Maniplates the text as a whole, in really stupid ways. Currently, as
|
11
|
+
a fun demo of metadata, we have it using the variable 'stupidmethod'
|
12
|
+
to determine what it does. There are two actions possible:
|
13
|
+
|
14
|
+
+ strip - strips vowels from the text. Good compression! :)
|
15
|
+
+ leet - does a horrid job of making the text 7337. Scary.
|
16
|
+
|
17
|
+
=== Methods
|
18
|
+
|
19
|
+
=end
|
20
|
+
|
21
|
+
$Transcode = {
|
22
|
+
'a' => '4', 'b' => '|3', 'c' => '<', 'd' => '|)', 'e' => '3',
|
23
|
+
'f' => 'F', 'g' => 'G', 'h' => ']-[', 'i' => '|', 'j' => 'J',
|
24
|
+
'k' => ']<', 'l' => 'L', 'm' => '/\/\\', 'n' => '/\/', 'o' => '0',
|
25
|
+
'p' => 'P', 'q' => 'Q', 'r' => '/~', 's' => '$', 't' => '+',
|
26
|
+
'u' => '|_|', 'v' => '\/', 'w' => '\/\/', 'x' => '><', 'y' => '`/',
|
27
|
+
'z' => 'Z',
|
28
|
+
}
|
29
|
+
|
30
|
+
class StupidRenderer < GenericRenderer
|
31
|
+
|
32
|
+
=begin
|
33
|
+
|
34
|
+
--- StupidRenderer#render(content)
|
35
|
+
|
36
|
+
Strips vowells
|
37
|
+
|
38
|
+
=end
|
39
|
+
|
40
|
+
def render(content)
|
41
|
+
|
42
|
+
methodname = @document['stupidmethod'] || nil
|
43
|
+
if methodname then
|
44
|
+
method = self.method(methodname)
|
45
|
+
|
46
|
+
content.each { |line|
|
47
|
+
line = method.call(line)
|
48
|
+
push(line)
|
49
|
+
}
|
50
|
+
else
|
51
|
+
@result = content.to_a
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
return self.result
|
56
|
+
end
|
57
|
+
|
58
|
+
def strip(s)
|
59
|
+
s = s.gsub(/[aeiou]/i, '')
|
60
|
+
return s
|
61
|
+
end
|
62
|
+
|
63
|
+
def leet(s)
|
64
|
+
|
65
|
+
# this is a lot more complicated than it needs to be. Basically,
|
66
|
+
# we didn't want variable interpolation chunks (eg #{blah}) to
|
67
|
+
# become 7337, so we split on #{}s, work on the other parts, and
|
68
|
+
# then fit it all back together. This should probably be moved up
|
69
|
+
# to render.
|
70
|
+
|
71
|
+
result = []
|
72
|
+
new_s = s.clone
|
73
|
+
re = /(\#\{[^\}]+\})/
|
74
|
+
new_s.split(re).each { |chunk|
|
75
|
+
if (chunk =~ re) then
|
76
|
+
result.push(chunk)
|
77
|
+
else
|
78
|
+
chunk.gsub!(/./) { |char|
|
79
|
+
$Transcode[char.downcase] || char
|
80
|
+
}
|
81
|
+
result.push(chunk)
|
82
|
+
end
|
83
|
+
}
|
84
|
+
|
85
|
+
return result.join('')
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'ZenWeb/GenericRenderer'
|
2
|
+
|
3
|
+
=begin
|
4
|
+
|
5
|
+
= Class SubpageRenderer
|
6
|
+
|
7
|
+
Generates a list of known subpages in a format compatible with
|
8
|
+
TextToHtmlRenderer.
|
9
|
+
|
10
|
+
=== Methods
|
11
|
+
|
12
|
+
=end
|
13
|
+
|
14
|
+
class SubpageRenderer < GenericRenderer
|
15
|
+
|
16
|
+
=begin
|
17
|
+
|
18
|
+
--- SubpageRenderer#render(content)
|
19
|
+
|
20
|
+
Renders a list of known subpages in a format compatible with
|
21
|
+
TextToHtmlRenderer. Adds the list to the end of the content.
|
22
|
+
|
23
|
+
=end
|
24
|
+
|
25
|
+
def render(content)
|
26
|
+
skip = @document['skipsubpages'] || (@document['includesubpages'] || '') =~ /false/
|
27
|
+
|
28
|
+
subpages = @document.subpages.clone
|
29
|
+
if (not skip and subpages.length > 0) then
|
30
|
+
push("\n\n")
|
31
|
+
push("** Subpages:\n\n")
|
32
|
+
subpages.each_index { | index |
|
33
|
+
url = subpages[index]
|
34
|
+
doc = @website[url]
|
35
|
+
title = doc.fulltitle
|
36
|
+
|
37
|
+
push("+ <A HREF=\"#{url}\">#{title}</A>\n")
|
38
|
+
}
|
39
|
+
push("\n")
|
40
|
+
end
|
41
|
+
|
42
|
+
return content + self.result
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,219 @@
|
|
1
|
+
require 'ZenWeb/HtmlRenderer'
|
2
|
+
|
3
|
+
=begin
|
4
|
+
|
5
|
+
= Class TextToHtmlRenderer
|
6
|
+
|
7
|
+
Converts a fairly plain text format into styled HTML.
|
8
|
+
|
9
|
+
=== Methods
|
10
|
+
|
11
|
+
=end
|
12
|
+
|
13
|
+
class TextToHtmlRenderer < HtmlRenderer
|
14
|
+
|
15
|
+
=begin
|
16
|
+
|
17
|
+
--- TextToHtmlRenderer#render(content)
|
18
|
+
|
19
|
+
Converts a simple plaintext format into formatted HTML. Includes
|
20
|
+
paragraphing, embedded variables, lists, rules, preformatted
|
21
|
+
blocks, and embedded HTML. See the demo pages for a complete
|
22
|
+
description on how to use this.
|
23
|
+
|
24
|
+
=end
|
25
|
+
|
26
|
+
def render(content)
|
27
|
+
|
28
|
+
text = content.split($PARAGRAPH_RE)
|
29
|
+
|
30
|
+
table = div = false
|
31
|
+
|
32
|
+
text.each { | p |
|
33
|
+
|
34
|
+
# massage a little
|
35
|
+
p = p.sub($PARAGRAPH_END_RE, '')
|
36
|
+
p.chomp!
|
37
|
+
|
38
|
+
p.gsub!(/\\&/, "&")
|
39
|
+
p.gsub!(/\\</, "<")
|
40
|
+
p.gsub!(/\\>/, ">")
|
41
|
+
p.gsub!(/\\\"/, """)
|
42
|
+
|
43
|
+
p.gsub!(/\\\{/, "{")
|
44
|
+
p.gsub!(/\\:/, ":")
|
45
|
+
|
46
|
+
# WARN Not sure if I want to do this or not... thinking about it.
|
47
|
+
# p.gsub!(/\\(.)/) { | c | sprintf("&#%04X#;", $1[0]) }
|
48
|
+
|
49
|
+
# url substitutions
|
50
|
+
p.gsub!(/([^=\"])((http|ftp|mailto):(\S+))/) {
|
51
|
+
pre = $1
|
52
|
+
url = $2
|
53
|
+
txt = $4
|
54
|
+
|
55
|
+
txt.gsub!(/\//, " ")
|
56
|
+
txt.strip!
|
57
|
+
txt.gsub!(/ /, " /")
|
58
|
+
|
59
|
+
"#{pre}<A HREF=\"#{url}\">#{txt}</A>"
|
60
|
+
}
|
61
|
+
|
62
|
+
case p
|
63
|
+
when /^(\*\*+)\s*(.*)$/ then
|
64
|
+
level = $1.length
|
65
|
+
push("<H#{level}>#{$2}</H#{level}>\n\n")
|
66
|
+
when /^---+$/ then
|
67
|
+
push("<HR>\n\n")
|
68
|
+
when /^===+$/ then
|
69
|
+
push("<HR CLASS=\"thick\">\n\n")
|
70
|
+
when /^%%%\s*(.*)/ then # TODO: I'm not fond of this
|
71
|
+
rest = $1
|
72
|
+
close = (rest.empty? or (rest.downcase == "end"))
|
73
|
+
push "</div></div>\n" if div
|
74
|
+
push "\n" if div unless table
|
75
|
+
push "</td><td>\n" if table and div
|
76
|
+
|
77
|
+
push "<div #{rest}><div>\n\n" unless close
|
78
|
+
div = ! close
|
79
|
+
when /^%%\s*$/ then
|
80
|
+
if div then
|
81
|
+
push "</div></div>\n"
|
82
|
+
div = false
|
83
|
+
end
|
84
|
+
if table then
|
85
|
+
push "</td></tr></table>\n\n"
|
86
|
+
else
|
87
|
+
push "<table><tr><td>\n\n"
|
88
|
+
end
|
89
|
+
table = ! table
|
90
|
+
when /^%[=-]/ then
|
91
|
+
hash, order = self.createHash(p)
|
92
|
+
push(self.hash2html(hash, order) + "\n") if hash
|
93
|
+
when /^\t*([\+=])/ then
|
94
|
+
ordered = $1 == "="
|
95
|
+
list = self.createList(p)
|
96
|
+
push(self.array2html(list, ordered)) if list
|
97
|
+
when /^\ \ / then # and p !~ /^[^\ ]/ then
|
98
|
+
p.gsub!(/^\ \ /, '')
|
99
|
+
push("<PRE>" + p + "</PRE>\n\n")
|
100
|
+
when /^\s*<\//, /^\s*<(?:DIV|FORM|P|TABLE|BLOCKQUOTE|H[1-7])\b/i then
|
101
|
+
push p
|
102
|
+
push "\n\n"
|
103
|
+
else
|
104
|
+
push("<P>" + p + "</P>")
|
105
|
+
push "\n\n"
|
106
|
+
end
|
107
|
+
}
|
108
|
+
|
109
|
+
# TODO: need to extend: ordered lists
|
110
|
+
|
111
|
+
# FIX: xmp makes this slow
|
112
|
+
# put it back into line-by-line format
|
113
|
+
# I use scan instead of split so I can keep the EOLs.
|
114
|
+
# @result = @result.join("\n").scan(/^.*[\n\r]+/)
|
115
|
+
|
116
|
+
return self.result
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
=begin
|
121
|
+
|
122
|
+
--- ZenDocument#createList
|
123
|
+
|
124
|
+
Convert a string composed of lines prefixed by plus signs into an
|
125
|
+
array of those strings, sans plus signs. If a line is indented
|
126
|
+
with tabs, then the lines at that indention level will become an
|
127
|
+
array of their own, to be added to the encompassing array.
|
128
|
+
|
129
|
+
=end
|
130
|
+
|
131
|
+
def createList(data)
|
132
|
+
|
133
|
+
if (data.is_a?(String)) then
|
134
|
+
# TODO: at some time we'll want to support different types of lists
|
135
|
+
data = data.gsub(/^(\t*)([\+=])\s*(.*)$/) { type=$2; $1 + $3 }
|
136
|
+
data = data.split($/)
|
137
|
+
end
|
138
|
+
|
139
|
+
min = -1
|
140
|
+
i = 0
|
141
|
+
len = data.size
|
142
|
+
|
143
|
+
while (i < len)
|
144
|
+
if (min == -1) then
|
145
|
+
|
146
|
+
# looking for initial match:
|
147
|
+
if (data[i] =~ /^\t(\t*.*)/) then
|
148
|
+
|
149
|
+
# replace w/ one less tab, and record that we have a match
|
150
|
+
data[i] = $1
|
151
|
+
min = i
|
152
|
+
end
|
153
|
+
else
|
154
|
+
|
155
|
+
# found match, looking for mismatch
|
156
|
+
if (data[i] !~ /^\t(\t*.*)/ or i == len) then
|
157
|
+
|
158
|
+
# found mismatch, replacing w/ sublist
|
159
|
+
data[min..i-1] = [ createList(data[min..i-1]) ]
|
160
|
+
# resetting appropriate values
|
161
|
+
len = data.size
|
162
|
+
i = min
|
163
|
+
min = -1
|
164
|
+
else
|
165
|
+
data[i] = $1
|
166
|
+
end
|
167
|
+
end
|
168
|
+
i += 1
|
169
|
+
end
|
170
|
+
|
171
|
+
if (i >= len - 1 and min != -1) then
|
172
|
+
data[min..i-1] = [ createList(data[min..i-1]) ]
|
173
|
+
end
|
174
|
+
|
175
|
+
return data
|
176
|
+
end
|
177
|
+
|
178
|
+
=begin
|
179
|
+
|
180
|
+
--- ZenDocument#createHash
|
181
|
+
|
182
|
+
Convert a string composed of lines prefixed one of two delimiters
|
183
|
+
into a hash. If the delimiter is "%-", then that string is used
|
184
|
+
as the key to the hash. If the delimiter is "%=", then that
|
185
|
+
string is used as the value to the hash.
|
186
|
+
|
187
|
+
=end
|
188
|
+
|
189
|
+
def createHash(data)
|
190
|
+
|
191
|
+
result = {}
|
192
|
+
order = []
|
193
|
+
|
194
|
+
if (data.is_a?(String)) then
|
195
|
+
data = data.split($/)
|
196
|
+
end
|
197
|
+
|
198
|
+
key = nil
|
199
|
+
data.each { |line|
|
200
|
+
if (line =~ /^\s*%-\s*(.*)/) then
|
201
|
+
key = $1
|
202
|
+
elsif (line =~ /^\s*%=\s*(.*)/) then
|
203
|
+
val = $1
|
204
|
+
|
205
|
+
if (key) then
|
206
|
+
# WARN: maybe do something if already defined?
|
207
|
+
result[key] = val
|
208
|
+
order << key
|
209
|
+
end
|
210
|
+
|
211
|
+
else
|
212
|
+
# nothing
|
213
|
+
end
|
214
|
+
}
|
215
|
+
|
216
|
+
return result, order
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|