zenweb 2.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +426 -0
  3. data/Manifest.txt +54 -0
  4. data/README.txt +63 -0
  5. data/Rakefile +22 -0
  6. data/bin/zenweb +27 -0
  7. data/bin/zenwebpage +66 -0
  8. data/bin/zenwebsite +39 -0
  9. data/design/REQUIREMENTS.txt +52 -0
  10. data/design/ZENWEB_2.txt +69 -0
  11. data/design/heirarchy.png +0 -0
  12. data/design/heirarchy.tgif +311 -0
  13. data/docs/Customizing +76 -0
  14. data/docs/FAQ +12 -0
  15. data/docs/Features +128 -0
  16. data/docs/Presentation +88 -0
  17. data/docs/QuickStart +32 -0
  18. data/docs/Renderers +85 -0
  19. data/docs/SiteMap +13 -0
  20. data/docs/YourOwnWebsite +32 -0
  21. data/docs/index +14 -0
  22. data/docs/metadata.txt +10 -0
  23. data/lib/ZenWeb.rb +850 -0
  24. data/lib/ZenWeb/CalendarRenderer.rb +162 -0
  25. data/lib/ZenWeb/CompactRenderer.rb +45 -0
  26. data/lib/ZenWeb/CompositeRenderer.rb +63 -0
  27. data/lib/ZenWeb/FileAttachmentRenderer.rb +57 -0
  28. data/lib/ZenWeb/FooterRenderer.rb +38 -0
  29. data/lib/ZenWeb/GenericRenderer.rb +143 -0
  30. data/lib/ZenWeb/HeaderRenderer.rb +52 -0
  31. data/lib/ZenWeb/HtmlRenderer.rb +81 -0
  32. data/lib/ZenWeb/HtmlTableRenderer.rb +94 -0
  33. data/lib/ZenWeb/HtmlTemplateRenderer.rb +173 -0
  34. data/lib/ZenWeb/MetadataRenderer.rb +83 -0
  35. data/lib/ZenWeb/RelativeRenderer.rb +98 -0
  36. data/lib/ZenWeb/RubyCodeRenderer.rb +56 -0
  37. data/lib/ZenWeb/SitemapRenderer.rb +56 -0
  38. data/lib/ZenWeb/StandardRenderer.rb +40 -0
  39. data/lib/ZenWeb/StupidRenderer.rb +88 -0
  40. data/lib/ZenWeb/SubpageRenderer.rb +45 -0
  41. data/lib/ZenWeb/TextToHtmlRenderer.rb +219 -0
  42. data/lib/ZenWeb/TocRenderer.rb +61 -0
  43. data/lib/ZenWeb/XXXRenderer.rb +32 -0
  44. data/test/SiteMap +14 -0
  45. data/test/Something +4 -0
  46. data/test/include.txt +3 -0
  47. data/test/index +8 -0
  48. data/test/metadata.txt +10 -0
  49. data/test/ryand/SiteMap +10 -0
  50. data/test/ryand/blah +4 -0
  51. data/test/ryand/blah-blah +4 -0
  52. data/test/ryand/index +52 -0
  53. data/test/ryand/metadata.txt +2 -0
  54. data/test/ryand/stuff/index +4 -0
  55. data/test/test_zenweb.rb +1624 -0
  56. metadata +161 -0
  57. metadata.gz.sig +0 -0
@@ -0,0 +1,52 @@
1
+ require 'ZenWeb/GenericRenderer'
2
+
3
+ =begin
4
+
5
+ = Class HeaderRenderer
6
+
7
+ Inserts a header based on metadata.
8
+
9
+ === Methods
10
+
11
+ =end
12
+
13
+ class HeaderRenderer < GenericRenderer
14
+
15
+ =begin
16
+
17
+ --- HeaderRenderer#render(content)
18
+
19
+ Adds a header if the ((|header|)) metadata item exists. If the
20
+ document contains a BODY HTML tag, then the header immediately
21
+ follows it, otherwise it is simply at the top.
22
+
23
+ =end
24
+
25
+ def render(content)
26
+
27
+ header = @document['header'] || nil
28
+
29
+ if header then
30
+ placed = false
31
+
32
+ content.each { | line |
33
+
34
+ push(line)
35
+
36
+ if (line =~ /<BODY/i) then
37
+ push(header)
38
+ placed = true
39
+ end
40
+ }
41
+
42
+ unless placed then
43
+ unshift(header) unless placed
44
+ end
45
+ else
46
+ push(content)
47
+ end
48
+
49
+ return self.result
50
+ end
51
+ end
52
+
@@ -0,0 +1,81 @@
1
+ require 'ZenWeb/GenericRenderer'
2
+
3
+ =begin
4
+
5
+ = Class HtmlRenderer
6
+
7
+ Abstract superclass that provides common functionality for those
8
+ renderers that produce HTML.
9
+
10
+ === Methods
11
+
12
+ =end
13
+
14
+ class HtmlRenderer < GenericRenderer
15
+
16
+ =begin
17
+
18
+ --- HtmlRenderer#render(content)
19
+
20
+ Raises an exception. This is subclass responsibility as this is an
21
+ abstract class.
22
+
23
+ =end
24
+
25
+ def render(content)
26
+ raise "Subclass Responsibility"
27
+ end
28
+
29
+ =begin
30
+
31
+ --- HtmlRenderer#array2html
32
+
33
+ Converts an array (of arrays, potentially) into an unordered list.
34
+
35
+ =end
36
+
37
+ def array2html(list, ordered=false, indent=0)
38
+ result = []
39
+
40
+ indent1 = " " * indent
41
+ indent2 = " " * (indent + 1)
42
+
43
+ tag = ordered ? "OL" : "UL"
44
+
45
+ result << "#{indent1}<#{tag}>\n"
46
+ list.each { | l |
47
+ if (l.is_a?(Array)) then
48
+ x = result.pop
49
+ result.push "\n"
50
+ result.push self.array2html(l, ordered, indent+2)
51
+ result.push indent2 unless x =~ /^\s+/
52
+ result.push x
53
+ else
54
+ result.push(indent2, "<LI>", l.to_s, "</LI>\n")
55
+ end
56
+ }
57
+ result << "#{indent1}</#{tag}>\n"
58
+
59
+ return result.join
60
+ end
61
+
62
+ def hash2html(hash, order)
63
+ result = ""
64
+
65
+ if (hash) then
66
+ result += "<DL>\n"
67
+ order.each { | key |
68
+ val = hash[key] or raise "Key '#{key}' is missing!"
69
+ result += " <DT>#{key}</DT>\n"
70
+ result += " <DD>#{val}</DD>\n\n"
71
+ }
72
+ result += "</DL>\n"
73
+ else
74
+ result = "not a hash"
75
+ end
76
+
77
+ return result
78
+ end
79
+
80
+ end
81
+
@@ -0,0 +1,94 @@
1
+ require 'ZenWeb/GenericRenderer'
2
+
3
+ class Hash
4
+ def %(style)
5
+ style.gsub(/%([-\d]*)\(([^\)]+)\)/) do |match|
6
+ result = ''
7
+ key = $2.intern
8
+ if self.has_key?(key) then
9
+ result = $1 ? sprintf("%*s", $1.to_i, self[key]) : self[key]
10
+ else
11
+ $stderr.puts " WARNING: missing data for '#{key}' in #{self.inspect}" unless $TESTING
12
+ end
13
+ result
14
+ end
15
+ end
16
+ end
17
+
18
+ =begin
19
+
20
+ = Class HtmlTableRenderer
21
+
22
+ Converts tab delimited data (tagged with <tabs>) into HTML tables
23
+
24
+ === Methods
25
+
26
+ =end
27
+
28
+ class HtmlTableRenderer < GenericRenderer
29
+
30
+ =begin
31
+
32
+ --- HtmlTableRenderer#render(content)
33
+
34
+ Converts tab delimited data (tagged with <tabs>) into HTML tables
35
+
36
+ =end
37
+
38
+ def render(content)
39
+
40
+ first=true
41
+ pre_style = post_style = head_style = body_style = column_titles = nil
42
+
43
+ self.scan_region(content, /^<tabs/i, /^<\/tabs>/i) do |line, context|
44
+ line.chomp!
45
+ case context
46
+ when :START then
47
+ first = true
48
+ if line =~ /style\s*=\s*\"?([\w\.-]+)\"?/i then
49
+ pre_style = @document["style_#{$1}_pre"] || ''
50
+ post_style = @document["style_#{$1}_post"] || ''
51
+ head_style = @document["style_#{$1}_head"] || ''
52
+ body_style = @document["style_#{$1}"] or
53
+ raise "You must specify a metadata entry for 'style_#{$1}'"
54
+ else
55
+ pre_style = "<table border=\"0\">\n"
56
+ post_style = "</table>\n"
57
+ head_style = nil
58
+ body_style = nil
59
+ column_titles = nil
60
+ end
61
+ line = pre_style
62
+ when :END then
63
+ line = post_style
64
+ else
65
+ columns = line.split(/\t+/)
66
+
67
+ if body_style then
68
+ if first then
69
+ line = head_style
70
+ # map the first row of data to column title positions
71
+ column_titles = columns.map {|x| x.intern}
72
+ else
73
+ data = {}
74
+ # use the column title positions to extract the data from the table
75
+ column_titles.each_with_index do |title, index|
76
+ data[title] = columns[index]
77
+ end
78
+
79
+ # use our extension to hash (see above) to format the data
80
+ line = data % body_style
81
+ end
82
+ else
83
+ type = first ? "th" : "td"
84
+ line = "<tr><#{type}>#{columns.join "</#{type}><#{type}>"}</#{type}></tr>\n"
85
+ end
86
+ first = false if first
87
+ end
88
+ push line
89
+ end
90
+
91
+ return self.result
92
+ end
93
+
94
+ end
@@ -0,0 +1,173 @@
1
+ require 'ZenWeb/HtmlRenderer'
2
+
3
+ =begin
4
+
5
+ = Class HtmlTemplateRenderer
6
+
7
+ Generates a consistant HTML page header and footer, including a
8
+ navigation bar, title, subtitle, and appropriate META tags.
9
+
10
+ === Methods
11
+
12
+ =end
13
+
14
+ class HtmlTemplateRenderer < HtmlRenderer
15
+
16
+ =begin
17
+
18
+ --- HtmlTemplateRenderer#render(content)
19
+
20
+ Renders a standardized HTML header and footer. This currently also
21
+ includes a navigation bar and a list of subpages, which will
22
+ probably be broken out to their own renderers soon.
23
+
24
+ Metadata variables used:
25
+
26
+ + author
27
+ + banner - graphic at the top of the page, usually a logo
28
+ + bgcolor - defaults to not being defined
29
+ + copyright
30
+ + description
31
+ + dtd (default: 'DTD HTML 4.0')
32
+ + email - used in a mailto in metadata
33
+ + keywords
34
+ + rating (default: 'general')
35
+ + stylesheet - reference to a CSS file
36
+ + style - CSS code directly (for smaller snippets)
37
+ + subtitle
38
+ + title (default: 'Unknown Title')
39
+ + icbm - longitude and latitude for geourl.org
40
+ + icbm_title - defaults to the page title
41
+
42
+ =end
43
+
44
+ def render(content)
45
+ author = @document['author']
46
+ banner = @document['banner']
47
+ bgcolor = @document['bgcolor']
48
+ dtd = @document['dtd'] || 'DTD HTML 4.0'
49
+ copyright = @document['copyright']
50
+ description = @document['description']
51
+ email = @document['email']
52
+ keywords = @document['keywords']
53
+ rating = @document['rating'] || 'general'
54
+ stylesheet = @document['stylesheet']
55
+ subtitle = @document['subtitle']
56
+ title = @document['title'] || 'Unknown Title'
57
+ icbm = @document['icbm']
58
+ icbm_title = @document['icbm_title'] || @document['title']
59
+ charset = @document['charset']
60
+ style = @document['style']
61
+ naked_page = @document['naked_page']
62
+ head_extra = @document['head_extra'] || []
63
+
64
+ titletext = @document.fulltitle
65
+
66
+ # TODO: iterate over a list of metas and add them in one nicely organized block
67
+
68
+ if bgcolor then
69
+ style ||= ""
70
+ style = "body { background-color: #{bgcolor} }\n" + style
71
+ end
72
+
73
+ # header
74
+ push([
75
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//#{dtd}//EN\">\n",
76
+ "<HTML>\n",
77
+ "<HEAD>\n",
78
+ "<TITLE>#{titletext}</TITLE>\n",
79
+ email ? "<LINK REV=\"MADE\" HREF=\"#{email}\">\n" : [],
80
+ stylesheet ? "<LINK REL=\"STYLESHEET\" HREF=\"#{stylesheet}\" TYPE=\"text/css\" title=\"#{stylesheet}\">\n" : [],
81
+ "<META NAME=\"rating\" CONTENT=\"#{rating}\">\n",
82
+ "<META NAME=\"GENERATOR\" CONTENT=\"#{ZenWebsite.banner}\">\n",
83
+ style ? "<STYLE TYPE=\"text/css\">\n#{style}\n</STYLE>" : [],
84
+ author ? "<META NAME=\"author\" CONTENT=\"#{author}\">\n" : [],
85
+ copyright ? "<META NAME=\"copyright\" CONTENT=\"#{copyright}\">\n" : [],
86
+ keywords ? "<META NAME=\"keywords\" CONTENT=\"#{keywords}\">\n" : [],
87
+ description ? "<META NAME=\"description\" CONTENT=\"#{description}\">\n" : [],
88
+ charset ? "<META HTTP-EQUIV=\"content-type\" CONTENT=\"text/html; charset=#{charset}\">" : [],
89
+ icbm ? "<meta name=\"ICBM\" content=\"#{icbm}\">\n<meta name=\"DC.title\" content=\"#{icbm_title}\">" : [],
90
+
91
+ "<link rel=\"up\" href=\"#{@document.parentURL}\" title=\"#{@document.parent.title}\">\n",
92
+ "<link rel=\"contents\" href=\"#{@sitemap.url}\" title=\"#{@sitemap.title}\">\n",
93
+ "<link rel=\"top\" href=\"#{@website.top.url}\" title=\"#{@website.top.title}\">\n",
94
+
95
+ head_extra.join("\n"),
96
+
97
+ "</HEAD>\n",
98
+ "<BODY>\n",
99
+ ])
100
+
101
+ unless naked_page then
102
+ self.navbar
103
+
104
+ if banner then
105
+ push("<H1><IMG SRC=\"#{banner}\" ALT=\"#{File.basename banner}\"></H1>\n")
106
+ unless (subtitle) then
107
+ push("<H2>#{title}</H2>\n")
108
+ end
109
+ else
110
+ push("<H1>#{title}</H1>\n")
111
+ end
112
+
113
+ push([
114
+ subtitle ? "<H2>#{subtitle}</H2>\n" : [],
115
+ "<HR CLASS=\"thick\">\n\n",
116
+ ])
117
+ end
118
+
119
+ push content
120
+
121
+ unless naked_page then
122
+ push([
123
+ "<HR CLASS=\"thick\">\n\n",
124
+ ])
125
+
126
+ self.navbar
127
+ end
128
+
129
+ push("\n</BODY>\n</HTML>\n")
130
+
131
+ return self.result
132
+ end
133
+
134
+ =begin
135
+
136
+ --- HtmlTemplateRenderer#navbar
137
+
138
+ Generates a navbar that contains a link to the sitemap, search
139
+ page (if any), and a fake "breadcrumbs" trail which is really just
140
+ a list of all of the parent titles up the chain to the top.
141
+
142
+ =end
143
+
144
+ def navbar
145
+
146
+ sep = " / "
147
+ search = @website["/Search.html"]
148
+
149
+ push([
150
+ "<P class=\"navbar\">\n",
151
+ "<A HREF=\"#{@sitemap.url}\">Sitemap</A>",
152
+ search ? " | <A HREF=\"#{search.url}\"><EM>Search</EM></A>" : [],
153
+ " || ",
154
+ ])
155
+
156
+ path = []
157
+ current = @document
158
+ while current and current != current.parent do
159
+ current = current.parent
160
+ path.unshift(current) if current
161
+ end
162
+
163
+ push([
164
+ path.map{|doc| ["<A HREF=\"#{doc.url}\">#{doc['title']}</A>\n", sep]},
165
+ @document['title'],
166
+ "</P>\n",
167
+ ])
168
+
169
+ return []
170
+ end
171
+
172
+ end
173
+
@@ -0,0 +1,83 @@
1
+ require 'ZenWeb/GenericRenderer'
2
+
3
+ =begin
4
+
5
+ = Class MetadataRenderer
6
+
7
+ Converts all metadata references into their values.
8
+
9
+ === Methods
10
+
11
+ =end
12
+
13
+ class MetadataRenderer < GenericRenderer
14
+
15
+ @@cache = {}
16
+
17
+ =begin
18
+
19
+ --- MetadataRenderer#render(content)
20
+
21
+ Converts all metadata references into their values.
22
+
23
+ =end
24
+
25
+ def render(content)
26
+
27
+ content = content.gsub(/\#\{([^\}]+)\}/) {
28
+ key = $1
29
+
30
+ # check to see if this is a metadata entry
31
+ val = @document[key] || nil
32
+
33
+ # otherwise try to eval it. If that fails, just give text.
34
+ unless (val) then
35
+ begin
36
+ # this allows evals that fail (expensive) to be cached,
37
+ # and good code to be eval'd every time.
38
+ # I think this is a good balance.
39
+ if @@cache[key] then
40
+ val = @@cache[key]
41
+ else
42
+ val = eval(key)
43
+ end
44
+ rescue NameError => err
45
+ val = key
46
+ @@cache[key] = key
47
+ rescue Exception => err
48
+ $stderr.puts "eval failed in MetadataRenderer for #{@document.datapath}: #{err}. Code = '#{key}'"
49
+ val = key
50
+ @@cache[key] = key
51
+ end
52
+ end
53
+
54
+ val
55
+ }
56
+
57
+ return content
58
+ end
59
+
60
+ @@paths = {}
61
+
62
+ def include(path, remove_metadata=false, escape=false)
63
+ unless @@paths.include? path then
64
+ full_path = File.expand_path(File.join(File.dirname(@document.datapath), path))
65
+ @@paths[path] = full_path
66
+ else
67
+ full_path = @@paths[path]
68
+ end
69
+
70
+ content = File.new(full_path).readlines
71
+
72
+ if remove_metadata then
73
+ content = content.reject { |line| line =~ /^\s*\#/ }
74
+ end
75
+
76
+ content = self.render(content.join(''))
77
+ content.gsub!(/([<>&])/) { |x| '\\' + x } if escape
78
+
79
+ content
80
+ end
81
+
82
+ end
83
+