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,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
|