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