maruku 0.5.3 → 0.5.4

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 (51) hide show
  1. data/bin/maruku +14 -6
  2. data/bin/marutest +19 -10
  3. data/docs/changelog.html +49 -8
  4. data/docs/changelog.md +26 -1
  5. data/docs/entity_test.html +1 -1
  6. data/docs/exd.html +43 -24
  7. data/docs/index.html +4 -6
  8. data/docs/markdown_syntax.html +81 -170
  9. data/docs/maruku.html +4 -6
  10. data/docs/maruku.md +1 -1
  11. data/docs/proposal.html +21 -41
  12. data/lib/maruku.rb +5 -0
  13. data/lib/maruku/attributes.rb +3 -2
  14. data/lib/maruku/defaults.rb +3 -1
  15. data/lib/maruku/ext/math.rb +30 -0
  16. data/lib/maruku/ext/math/elements.rb +3 -2
  17. data/lib/maruku/ext/math/parsing.rb +81 -58
  18. data/lib/maruku/ext/math/to_html.rb +5 -5
  19. data/lib/maruku/helpers.rb +2 -0
  20. data/lib/maruku/input/charsource.rb +1 -1
  21. data/lib/maruku/input/extensions.rb +6 -5
  22. data/lib/maruku/input/parse_block.rb +7 -8
  23. data/lib/maruku/input/parse_doc.rb +1 -1
  24. data/lib/maruku/input/parse_span_better.rb +4 -4
  25. data/lib/maruku/input_textile2/t2_parser.rb +163 -0
  26. data/lib/maruku/maruku.rb +1 -1
  27. data/lib/maruku/output/s5/fancy.rb +756 -0
  28. data/lib/maruku/output/s5/to_s5.rb +104 -0
  29. data/lib/maruku/output/to_html.rb +103 -49
  30. data/lib/maruku/string_utils.rb +1 -1
  31. data/lib/maruku/textile2.rb +1 -0
  32. data/lib/maruku/version.rb +3 -1
  33. data/maruku_gem.rb +33 -0
  34. data/tests/s5/s5profiling.md +48 -0
  35. data/tests/unittest/blanks_in_code.md +6 -12
  36. data/tests/unittest/code3.md +3 -5
  37. data/tests/unittest/data_loss.md +53 -0
  38. data/tests/unittest/email.md +2 -2
  39. data/tests/unittest/entities.md +3 -5
  40. data/tests/unittest/footnotes.md +5 -5
  41. data/tests/unittest/ie.md +1 -1
  42. data/tests/unittest/images.md +2 -2
  43. data/tests/unittest/inline_html.md +6 -10
  44. data/tests/unittest/links.md +1 -1
  45. data/tests/unittest/list2.md +5 -5
  46. data/tests/unittest/lists.md +13 -13
  47. data/tests/unittest/lists_ol.md +13 -13
  48. data/tests/unittest/math/math2.md +84 -0
  49. data/tests/unittest/math/notmath.md +48 -0
  50. data/tests/unittest/syntax_hl.md +3 -5
  51. metadata +11 -2
@@ -95,8 +95,8 @@ module MaRuKu; module Out; module HTML
95
95
  end
96
96
 
97
97
  def to_html_inline_math
98
- mathml = render_mathml(:inline, self.math)
99
- png = render_png(:inline, self.math)
98
+ mathml = get_setting(:html_math_output_mathml) && render_mathml(:inline, self.math)
99
+ png = get_setting(:html_math_output_png) && render_png(:inline, self.math)
100
100
 
101
101
  span = create_html_element 'span'
102
102
  add_class_to(span, 'maruku-inline')
@@ -116,12 +116,12 @@ module MaRuKu; module Out; module HTML
116
116
  end
117
117
 
118
118
  def to_html_equation
119
- mathml = render_mathml(:equation, self.math)
120
- png = render_png(:equation, self.math)
119
+ mathml = get_setting(:html_math_output_mathml) && render_mathml(:equation, self.math)
120
+ png = get_setting(:html_math_output_png) && render_png(:equation, self.math)
121
121
 
122
122
  div = create_html_element 'div'
123
123
  add_class_to(div, 'maruku-equation')
124
- if self.label # then numerate
124
+ if self.label # then numerate
125
125
  span = Element.new 'span'
126
126
  span.attributes['class'] = 'maruku-eq-number'
127
127
  num = self.num
@@ -92,6 +92,8 @@ module Helpers
92
92
  e.instance_variable_set :@parsed_html,
93
93
  REXML::Document.new(raw_html)
94
94
  rescue
95
+ e.instance_variable_set :@parsed_html, nil
96
+
95
97
  # tell_user "Malformed block of HTML:\n"+
96
98
  # add_tabs(raw_html,1,'|')
97
99
  # " #{raw_html.inspect}\n\n"+ex.inspect
@@ -262,7 +262,7 @@ class CharSourceStrscan
262
262
  end
263
263
 
264
264
  def consume_whitespace
265
- @s.scan /\s+/
265
+ @s.scan(/\s+/)
266
266
  nil
267
267
  end
268
268
 
@@ -29,19 +29,19 @@ module MaRuKu; module In; module Markdown
29
29
  return false # not special
30
30
  end
31
31
 
32
- def self.register_span_extension(args, &block)
32
+ def self.register_span_extension(args)
33
33
  e = SpanExtension.new
34
34
  e.chars = [*args[:chars]]
35
35
  e.regexp = args[:regexp]
36
- e.block = block
36
+ e.block = args[:handler] || raise("No blocks passed")
37
37
  e.chars.each do |c|
38
38
  (SpanExtensionsTrigger[c] ||= []).push e
39
39
  end
40
40
  end
41
41
 
42
- def self.register_block_extension(args, &block)
42
+ def self.register_block_extension(args)
43
43
  regexp = args[:regexp]
44
- BlockExtensions[regexp] = block
44
+ BlockExtensions[regexp] = (args[:handler] || raise("No blocks passed"))
45
45
  end
46
46
 
47
47
  # Hash Regexp -> Block
@@ -51,7 +51,8 @@ module MaRuKu; module In; module Markdown
51
51
  BlockExtensions.each do |reg, block|
52
52
  if m = reg.match(line)
53
53
  block = BlockExtensions[reg]
54
- return true if block.call(doc, src, con)
54
+ accepted = block.call(doc, src, con)
55
+ return true if accepted
55
56
  end
56
57
  end
57
58
  return false # not special
@@ -215,7 +215,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
215
215
  if result.kind_of? String
216
216
  raise "Not expected"
217
217
  else
218
- output.push *result
218
+ output.push(*result)
219
219
  end
220
220
  end
221
221
  else
@@ -242,7 +242,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
242
242
  end
243
243
 
244
244
  def read_paragraph(src)
245
- lines = []
245
+ lines = [src.shift_line]
246
246
  while src.cur_line
247
247
  # :olist does not break
248
248
  case t = src.cur_line.md_type
@@ -253,7 +253,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
253
253
  end
254
254
  break if src.cur_line.strip.size == 0
255
255
  break if [:header1,:header2].include? src.next_line.md_type
256
- break if any_matching_block_extension?(src.cur_line)
256
+ break if any_matching_block_extension?(src.cur_line)
257
257
 
258
258
  lines << src.shift_line
259
259
  end
@@ -491,12 +491,11 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
491
491
  out.push md_ref_def(id, url, meta={:title=>title})
492
492
  end
493
493
 
494
+ def split_cells(s)
495
+ s.strip.split('|').select{|x|x.strip.size>0}.map{|x|x.strip}
496
+ end
497
+
494
498
  def read_table(src)
495
-
496
- def split_cells(s)
497
- s.strip.split('|').select{|x|x.strip.size>0}.map{|x|x.strip}
498
- end
499
-
500
499
  head = split_cells(src.shift_line).map{|s| md_el(:head_cell, parse_lines_as_span([s])) }
501
500
 
502
501
  separator=split_cells(src.shift_line)
@@ -25,7 +25,7 @@ require 'iconv'
25
25
  module MaRuKu; module In; module Markdown; module BlockLevelParser
26
26
 
27
27
  def parse_doc(s)
28
-
28
+ # FIXME \r\n => \n
29
29
  meta2 = parse_email_headers(s)
30
30
  data = meta2[:data]
31
31
  meta2.delete :data
@@ -196,10 +196,10 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
196
196
  interpret_extension(src, con, [?}])
197
197
  src.ignore_char # }
198
198
  when nil
199
- maruku_error ("Unclosed span (waiting for %s"+
199
+ maruku_error( ("Unclosed span (waiting for %s"+
200
200
  "#{exit_on_strings.inspect})") % [
201
201
  exit_on_chars ? "#{exit_on_chars.inspect} or" : ""],
202
- src,con
202
+ src,con)
203
203
  break
204
204
  else # normal text
205
205
  con.push_char src.shift_char
@@ -618,8 +618,8 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
618
618
  src.consume_whitespace
619
619
  closing = src.shift_char # closing )
620
620
  if closing != ?)
621
- error ("Unclosed link: '"<<closing<<"'")+
622
- " Read url=#{url.inspect} title=#{title.inspect}",src,con
621
+ error( ("Unclosed link: '"<<closing<<"'")+
622
+ " Read url=#{url.inspect} title=#{title.inspect}",src,con)
623
623
  end
624
624
  con.push_element md_im_image(alt_text, url, title)
625
625
  when ?[ # link ref
@@ -0,0 +1,163 @@
1
+ class String
2
+ Textile2_EmptyLine = /^\s*$/
3
+ Textile2_Signature = /^(\S+\.?)\.\s(.*)/
4
+
5
+ def t2_empty?
6
+ self =~ Textile2_EmptyLine
7
+ end
8
+
9
+ def t2_contains_signature?
10
+ self =~ Textile2_Signature
11
+ end
12
+
13
+ # sig, rest = t2_get_signature
14
+ def t2_get_signature
15
+ self =~ Textile2_Signature
16
+ return Textile2Signature.new($1), $2
17
+ end
18
+ end
19
+
20
+ class Textile2Signature
21
+ Reg = %r{
22
+ ^
23
+ # block name is 1
24
+ ([A-Za-z0-9]+)?
25
+ # style is 2
26
+ (
27
+ \{ # open bracket
28
+ ([^\}]+) # style spec is 3
29
+ \} # close bracket
30
+ )?
31
+ # language is 4
32
+ (\[(\w+)\])? # value is 5
33
+ # class and id
34
+ (?:
35
+ \( # open par
36
+ (\w+)? # optional class specification is 6
37
+ (?:\#(\w+))? # optional id is 7
38
+ \) # close par
39
+ )?
40
+ # alignment is 8
41
+ (\<|\>|\<\>|\=)?
42
+ # padding
43
+ (\(+)? # left is 9
44
+ (\)+)? # right is 10
45
+ # filters is 11
46
+ (\|
47
+ (?:(?:\w+)\|)+
48
+ )?
49
+ # optional final dot is 12
50
+ (\.)?
51
+ $
52
+ }x
53
+
54
+
55
+ def initialize(s)
56
+ if m = Reg.match(s)
57
+ self.block_name = m[1]
58
+ self.style = m[3]
59
+ self.lang = m[4]
60
+ self.css_class = m[6]
61
+ self.css_id = m[7]
62
+ self.text_align = {nil=>nil,'>'=>'right','<'=>'left',
63
+ '<>'=>'center','='=>'justified'}[m[8]]
64
+ self.num_left_pad = m[9] && m[9].size
65
+ self.num_right_pad = m[10] && m[10].size
66
+ self.filters = m[11] && m[11].split('|')
67
+ self.double_dot = m[12] && true
68
+ end
69
+ end
70
+
71
+
72
+ attr_accessor :block_name # or nil
73
+ attr_accessor :style # or nil
74
+ attr_accessor :lang # or nil
75
+ attr_accessor :css_class # or nil
76
+ attr_accessor :css_id # or nil
77
+ attr_accessor :text_align # {nil, 'left', 'right', 'center', 'justified'}
78
+ attr_accessor :num_left_pad # nil or 1..
79
+ attr_accessor :num_right_pad # nil or 1..
80
+ attr_accessor :filters # nil [], array of strings
81
+ attr_accessor :double_dot # nil or true
82
+
83
+
84
+ end
85
+
86
+ module MaRuKu
87
+
88
+ def self.textile2(source, params)
89
+ m = Maruku.new
90
+ m.t2_parse(source, params)
91
+ end
92
+
93
+
94
+ class MDDocument
95
+ def t2_parse(source, params)
96
+ src = LineSource.new(source)
97
+ output = BlockContext.new
98
+ t2_parse_blocks(src, output)
99
+ self.children = output.elements
100
+ end
101
+
102
+ Handling = Struct.new(:method, :parse_lines)
103
+ T2_Handling = {
104
+ nil => Handling.new(:t2_block_paragraph, true),
105
+ 'p' => Handling.new(:t2_block_paragraph, true)
106
+ }
107
+
108
+ # Input is a LineSource
109
+ def t2_parse_blocks(src, output)
110
+ while src.cur_line
111
+
112
+ # ignore empty line
113
+ if l.t2_empty? then
114
+ src.shift_line
115
+ next
116
+ end
117
+
118
+ l = src.shift_line
119
+ # TODO: lists
120
+ # TODO: xml
121
+ # TODO: `==`
122
+
123
+ signature, l =
124
+ if l.t2_contains_signature?
125
+ l.t2_get_signature
126
+ else
127
+ [Textile2Signature.new, l]
128
+ end
129
+
130
+ if handling = T2_Handling.has_key?(signature.block_name)
131
+ if self.responds_to? handling.method
132
+ # read as many non-empty lines that you can
133
+ lines = [l]
134
+ if handling.parse_lines
135
+ while not src.cur_line.t2_empty?
136
+ lines.push src.shift_line
137
+ end
138
+ end
139
+
140
+ self.send(handling.method, src, output, signature, lines)
141
+ else
142
+ maruku_error("We don't know about method #{handling.method.inspect}")
143
+ next
144
+ end
145
+ end
146
+
147
+
148
+ end
149
+ end
150
+
151
+ def t2_block_paragraph(src, output, signature, lines)
152
+ paragraph = lines.join("\n")
153
+ src2 = CharSource.new(paragraph, src)
154
+ # output =
155
+ end
156
+
157
+ def t2_parse_span(src, output)
158
+
159
+ end
160
+
161
+ end # MDDocument
162
+
163
+ end
data/lib/maruku/maruku.rb CHANGED
@@ -20,9 +20,9 @@
20
20
 
21
21
 
22
22
  # The Maruku class is the public interface
23
+ #
23
24
 
24
25
  class Maruku
25
-
26
26
  def initialize(s=nil, meta={})
27
27
  super(nil)
28
28
  self.attributes.merge! meta
@@ -0,0 +1,756 @@
1
+ module MaRuKu
2
+ S5_external =<<EOF
3
+
4
+ <meta name="defaultView" content="slideshow" />
5
+ <meta name="controlVis" content="hidden" />
6
+ <link rel="stylesheet" href="ui/default/slides.css" type="text/css" media="projection" id="slideProj" />
7
+ <link rel="stylesheet" href="ui/default/outline.css" type="text/css" media="screen" id="outlineStyle" />
8
+ <link rel="stylesheet" href="ui/default/print.css" type="text/css" media="print" id="slidePrint" />
9
+ <link rel="stylesheet" href="ui/default/opera.css" type="text/css" media="projection" id="operaFix" />
10
+ <script src="ui/default/slides.js" type="text/javascript"> </script>
11
+ EOF
12
+
13
+
14
+ S5_Fancy =<<EOF
15
+
16
+ <meta name="defaultView" content="slideshow" />
17
+ <meta name="controlVis" content="hidden" />
18
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
19
+ <style type="text/css" media="projection" id="slideProj">
20
+ /* Do not edit or override these styles! The system will likely break if you do. */
21
+
22
+ div#header, div#footer, div#controls, .slide {position: absolute;}
23
+ html>body div#header, html>body div#footer,
24
+ html>body div#controls, html>body .slide {position: fixed;}
25
+ .handout {display: none;}
26
+ .layout {display: block;}
27
+ .slide, .hideme, .incremental {visibility: hidden;}
28
+ #slide0 {visibility: visible;}
29
+
30
+ /* The following styles size, place, and layer the slide components.
31
+ Edit these if you want to change the overall slide layout.
32
+ The commented lines can be uncommented (and modified, if necessary)
33
+ to help you with the rearrangement process. */
34
+
35
+ /* target = 1024x768 */
36
+
37
+ div#header, div#footer, .slide {width: 100%; top: 0; left: 0;}
38
+ div#header {top: 0; height: 3em; z-index: 1;}
39
+ div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;}
40
+ .slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;}
41
+ div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}
42
+ div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
43
+ margin: 0;}
44
+ #currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;}
45
+ html>body #currentSlide {position: fixed;}
46
+
47
+ /*
48
+ div#header {background: #FCC;}
49
+ div#footer {background: #CCF;}
50
+ div#controls {background: #BBD;}
51
+ div#currentSlide {background: #FFC;}
52
+ */
53
+
54
+ /* Following are the presentation styles -- edit away! */
55
+
56
+ body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2em;}
57
+ :link, :visited {text-decoration: none; color: #00C;}
58
+ #controls :active {color: #88A !important;}
59
+ #controls :focus {outline: 1px dotted #227;}
60
+ h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}
61
+ ul, pre {margin: 0; line-height: 1em;}
62
+ html, body {margin: 0; padding: 0;}
63
+
64
+ blockquote, q {font-style: italic;}
65
+ blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;}
66
+ blockquote p {margin: 0;}
67
+ blockquote i {font-style: normal;}
68
+ blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;}
69
+ blockquote b i {font-style: italic;}
70
+
71
+ kbd {font-weight: bold; font-size: 1em;}
72
+ sup {font-size: smaller; line-height: 1px;}
73
+
74
+ .slide code {padding: 2px 0.25em; font-weight: bold; color: #533;}
75
+ .slide code.bad, code del {color: red;}
76
+ .slide code.old {color: silver;}
77
+ .slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;}
78
+ .slide pre code {display: block;}
79
+ .slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;}
80
+ .slide li {margin-top: 0.75em; margin-right: 0;}
81
+ .slide ul ul {line-height: 1;}
82
+ .slide ul ul li {margin: .2em; font-size: 85%; list-style: square;}
83
+ .slide img.leader {display: block; margin: 0 auto;}
84
+
85
+ div#header, div#footer {background: #005; color: #AAB;
86
+ font-family: Verdana, Helvetica, sans-serif;}
87
+ div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat;
88
+ line-height: 1px;}
89
+ div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;}
90
+ #footer h1, #footer h2 {display: block; padding: 0 1em;}
91
+ #footer h2 {font-style: italic;}
92
+
93
+ div.long {font-size: 0.75em;}
94
+ .slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1;
95
+ margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap;
96
+ font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize;
97
+ color: #DDE; background: #005;}
98
+ .slide h3 {font-size: 130%;}
99
+ h1 abbr {font-variant: small-caps;}
100
+
101
+ div#controls {position: absolute; left: 50%; bottom: 0;
102
+ width: 50%;
103
+ text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;}
104
+ html>body div#controls {position: fixed; padding: 0 0 1em 0;
105
+ top: auto;}
106
+ div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
107
+ margin: 0; padding: 0;}
108
+ #controls #navLinks a {padding: 0; margin: 0 0.5em;
109
+ background: #005; border: none; color: #779;
110
+ cursor: pointer;}
111
+ #controls #navList {height: 1em;}
112
+ #controls #navList #jumplist {position: absolute; bottom: 0; right: 0; background: #DDD; color: #227;}
113
+
114
+ #currentSlide {text-align: center; font-size: 0.5em; color: #449;}
115
+
116
+ #slide0 {padding-top: 3.5em; font-size: 90%;}
117
+ #slide0 h1 {position: static; margin: 1em 0 0; padding: 0;
118
+ font: bold 2em Helvetica, sans-serif; white-space: normal;
119
+ color: #000; background: transparent;}
120
+ #slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;}
121
+ #slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}
122
+ #slide0 h4 {margin-top: 0; font-size: 1em;}
123
+
124
+ ul.urls {list-style: none; display: inline; margin: 0;}
125
+ .urls li {display: inline; margin: 0;}
126
+ .note {display: none;}
127
+ .external {border-bottom: 1px dotted gray;}
128
+ html>body .external {border-bottom: none;}
129
+ .external:after {content: " \274F"; font-size: smaller; color: #77B;}
130
+
131
+ .incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;}
132
+ img.incremental {visibility: hidden;}
133
+ .slide .current {color: #B02;}
134
+
135
+
136
+ /* diagnostics
137
+
138
+ li:after {content: " [" attr(class) "]"; color: #F88;}
139
+ */
140
+ </style>
141
+ <style type="text/css" media="projection" id="operaFix">
142
+ /* DO NOT CHANGE THESE unless you really want to break Opera Show */
143
+ .slide {
144
+ visibility: visible !important;
145
+ position: static !important;
146
+ page-break-before: always;
147
+ }
148
+ #slide0 {page-break-before: avoid;}
149
+
150
+ </style>
151
+ <style type="text/css" media="screen" id="outlineStyle">
152
+ /* don't change this unless you want the layout stuff to show up in the outline view! */
153
+
154
+ .layout div, #footer *, #controlForm * {display: none;}
155
+ #footer, #controls, #controlForm, #navLinks, #toggle {
156
+ display: block; visibility: visible; margin: 0; padding: 0;}
157
+ #toggle {float: right; padding: 0.5em;}
158
+ html>body #toggle {position: fixed; top: 0; right: 0;}
159
+
160
+ /* making the outline look pretty-ish */
161
+
162
+ #slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;}
163
+ #slide0 h1 {padding-top: 1.5em;}
164
+ .slide h1 {margin: 1.5em 0 0; padding-top: 0.25em;
165
+ border-top: 1px solid #888; border-bottom: 1px solid #AAA;}
166
+ #toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;}
167
+
168
+ </style>
169
+ <style type="text/css" media="print" id="slidePrint">
170
+ /* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */
171
+ .slide, ul {page-break-inside: avoid; visibility: visible !important;}
172
+ h1 {page-break-after: avoid;}
173
+
174
+ body {font-size: 12pt; background: white;}
175
+ * {color: black;}
176
+
177
+ #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}
178
+ #slide0 h3 {margin: 0; padding: 0;}
179
+ #slide0 h4 {margin: 0 0 0.5em; padding: 0;}
180
+ #slide0 {margin-bottom: 3em;}
181
+
182
+ h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}
183
+ .extra {background: transparent !important;}
184
+ div.extra, pre.extra, .example {font-size: 10pt; color: #333;}
185
+ ul.extra a {font-weight: bold;}
186
+ p.example {display: none;}
187
+
188
+ #header {display: none;}
189
+ #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}
190
+ #footer h2, #controls {display: none;}
191
+
192
+ /* The following rule keeps the layout stuff out of print. Remove at your own risk! */
193
+ .layout, .layout * {display: none !important;}
194
+
195
+ </style>
196
+ <script type="text/javascript">
197
+ <![CDATA[
198
+ // S5 v1.1 slides.js -- released into the Public Domain
199
+ //
200
+ // Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information
201
+ // about all the wonderful and talented contributors to this code!
202
+
203
+ var undef;
204
+ var slideCSS = '';
205
+ var snum = 0;
206
+ var smax = 1;
207
+ var incpos = 0;
208
+ var number = undef;
209
+ var s5mode = true;
210
+ var defaultView = 'slideshow';
211
+ var controlVis = 'visible';
212
+
213
+ var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0;
214
+ var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0;
215
+ var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0;
216
+
217
+ function hasClass(object, className) {
218
+ if (!object.className) return false;
219
+ return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1);
220
+ }
221
+
222
+ function hasValue(object, value) {
223
+ if (!object) return false;
224
+ return (object.search('(^|\\s)' + value + '(\\s|$)') != -1);
225
+ }
226
+
227
+ function removeClass(object,className) {
228
+ if (!object) return;
229
+ object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2);
230
+ }
231
+
232
+ function addClass(object,className) {
233
+ if (!object || hasClass(object, className)) return;
234
+ if (object.className) {
235
+ object.className += ' '+className;
236
+ } else {
237
+ object.className = className;
238
+ }
239
+ }
240
+
241
+ function GetElementsWithClassName(elementName,className) {
242
+ var allElements = document.getElementsByTagName(elementName);
243
+ var elemColl = new Array();
244
+ for (var i = 0; i< allElements.length; i++) {
245
+ if (hasClass(allElements[i], className)) {
246
+ elemColl[elemColl.length] = allElements[i];
247
+ }
248
+ }
249
+ return elemColl;
250
+ }
251
+
252
+ function isParentOrSelf(element, id) {
253
+ if (element == null || element.nodeName=='BODY') return false;
254
+ else if (element.id == id) return true;
255
+ else return isParentOrSelf(element.parentNode, id);
256
+ }
257
+
258
+ function nodeValue(node) {
259
+ var result = "";
260
+ if (node.nodeType == 1) {
261
+ var children = node.childNodes;
262
+ for (var i = 0; i < children.length; ++i) {
263
+ result += nodeValue(children[i]);
264
+ }
265
+ }
266
+ else if (node.nodeType == 3) {
267
+ result = node.nodeValue;
268
+ }
269
+ return(result);
270
+ }
271
+
272
+ function slideLabel() {
273
+ var slideColl = GetElementsWithClassName('*','slide');
274
+ var list = document.getElementById('jumplist');
275
+ smax = slideColl.length;
276
+ for (var n = 0; n < smax; n++) {
277
+ var obj = slideColl[n];
278
+
279
+ var did = 'slide' + n.toString();
280
+ obj.setAttribute('id',did);
281
+ if (isOp) continue;
282
+
283
+ var otext = '';
284
+ var menu = obj.firstChild;
285
+ if (!menu) continue; // to cope with empty slides
286
+ while (menu && menu.nodeType == 3) {
287
+ menu = menu.nextSibling;
288
+ }
289
+ if (!menu) continue; // to cope with slides with only text nodes
290
+
291
+ var menunodes = menu.childNodes;
292
+ for (var o = 0; o < menunodes.length; o++) {
293
+ otext += nodeValue(menunodes[o]);
294
+ }
295
+ list.options[list.length] = new Option(n + ' : ' + otext, n);
296
+ }
297
+ }
298
+
299
+ function currentSlide() {
300
+ var cs;
301
+ if (document.getElementById) {
302
+ cs = document.getElementById('currentSlide');
303
+ } else {
304
+ cs = document.currentSlide;
305
+ }
306
+ cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' +
307
+ '<span id="csSep">\/<\/span> ' +
308
+ '<span id="csTotal">' + (smax-1) + '<\/span>';
309
+ if (snum == 0) {
310
+ cs.style.visibility = 'hidden';
311
+ } else {
312
+ cs.style.visibility = 'visible';
313
+ }
314
+ }
315
+
316
+ function go(step) {
317
+ if (document.getElementById('slideProj').disabled || step == 0) return;
318
+ var jl = document.getElementById('jumplist');
319
+ var cid = 'slide' + snum;
320
+ var ce = document.getElementById(cid);
321
+ if (incrementals[snum].length > 0) {
322
+ for (var i = 0; i < incrementals[snum].length; i++) {
323
+ removeClass(incrementals[snum][i], 'current');
324
+ removeClass(incrementals[snum][i], 'incremental');
325
+ }
326
+ }
327
+ if (step != 'j') {
328
+ snum += step;
329
+ lmax = smax - 1;
330
+ if (snum > lmax) snum = lmax;
331
+ if (snum < 0) snum = 0;
332
+ } else
333
+ snum = parseInt(jl.value);
334
+ var nid = 'slide' + snum;
335
+ var ne = document.getElementById(nid);
336
+ if (!ne) {
337
+ ne = document.getElementById('slide0');
338
+ snum = 0;
339
+ }
340
+ if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;}
341
+ if (incrementals[snum].length > 0 && incpos == 0) {
342
+ for (var i = 0; i < incrementals[snum].length; i++) {
343
+ if (hasClass(incrementals[snum][i], 'current'))
344
+ incpos = i + 1;
345
+ else
346
+ addClass(incrementals[snum][i], 'incremental');
347
+ }
348
+ }
349
+ if (incrementals[snum].length > 0 && incpos > 0)
350
+ addClass(incrementals[snum][incpos - 1], 'current');
351
+ ce.style.visibility = 'hidden';
352
+ ne.style.visibility = 'visible';
353
+ jl.selectedIndex = snum;
354
+ currentSlide();
355
+ number = 0;
356
+ }
357
+
358
+ function goTo(target) {
359
+ if (target >= smax || target == snum) return;
360
+ go(target - snum);
361
+ }
362
+
363
+ function subgo(step) {
364
+ if (step > 0) {
365
+ removeClass(incrementals[snum][incpos - 1],'current');
366
+ removeClass(incrementals[snum][incpos], 'incremental');
367
+ addClass(incrementals[snum][incpos],'current');
368
+ incpos++;
369
+ } else {
370
+ incpos--;
371
+ removeClass(incrementals[snum][incpos],'current');
372
+ addClass(incrementals[snum][incpos], 'incremental');
373
+ addClass(incrementals[snum][incpos - 1],'current');
374
+ }
375
+ }
376
+
377
+ function toggle() {
378
+ var slideColl = GetElementsWithClassName('*','slide');
379
+ var slides = document.getElementById('slideProj');
380
+ var outline = document.getElementById('outlineStyle');
381
+ if (!slides.disabled) {
382
+ slides.disabled = true;
383
+ outline.disabled = false;
384
+ s5mode = false;
385
+ fontSize('1em');
386
+ for (var n = 0; n < smax; n++) {
387
+ var slide = slideColl[n];
388
+ slide.style.visibility = 'visible';
389
+ }
390
+ } else {
391
+ slides.disabled = false;
392
+ outline.disabled = true;
393
+ s5mode = true;
394
+ fontScale();
395
+ for (var n = 0; n < smax; n++) {
396
+ var slide = slideColl[n];
397
+ slide.style.visibility = 'hidden';
398
+ }
399
+ slideColl[snum].style.visibility = 'visible';
400
+ }
401
+ }
402
+
403
+ function showHide(action) {
404
+ var obj = GetElementsWithClassName('*','hideme')[0];
405
+ switch (action) {
406
+ case 's': obj.style.visibility = 'visible'; break;
407
+ case 'h': obj.style.visibility = 'hidden'; break;
408
+ case 'k':
409
+ if (obj.style.visibility != 'visible') {
410
+ obj.style.visibility = 'visible';
411
+ } else {
412
+ obj.style.visibility = 'hidden';
413
+ }
414
+ break;
415
+ }
416
+ }
417
+
418
+ // 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/)
419
+ function keys(key) {
420
+ if (!key) {
421
+ key = event;
422
+ key.which = key.keyCode;
423
+ }
424
+ if (key.which == 84) {
425
+ toggle();
426
+ return;
427
+ }
428
+ if (s5mode) {
429
+ switch (key.which) {
430
+ case 10: // return
431
+ case 13: // enter
432
+ if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;
433
+ if (key.target && isParentOrSelf(key.target, 'controls')) return;
434
+ if(number != undef) {
435
+ goTo(number);
436
+ break;
437
+ }
438
+ case 32: // spacebar
439
+ case 34: // page down
440
+ case 39: // rightkey
441
+ case 40: // downkey
442
+ if(number != undef) {
443
+ go(number);
444
+ } else if (!incrementals[snum] || incpos >= incrementals[snum].length) {
445
+ go(1);
446
+ } else {
447
+ subgo(1);
448
+ }
449
+ break;
450
+ case 33: // page up
451
+ case 37: // leftkey
452
+ case 38: // upkey
453
+ if(number != undef) {
454
+ go(-1 * number);
455
+ } else if (!incrementals[snum] || incpos <= 0) {
456
+ go(-1);
457
+ } else {
458
+ subgo(-1);
459
+ }
460
+ break;
461
+ case 36: // home
462
+ goTo(0);
463
+ break;
464
+ case 35: // end
465
+ goTo(smax-1);
466
+ break;
467
+ case 67: // c
468
+ showHide('k');
469
+ break;
470
+ }
471
+ if (key.which < 48 || key.which > 57) {
472
+ number = undef;
473
+ } else {
474
+ if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;
475
+ if (key.target && isParentOrSelf(key.target, 'controls')) return;
476
+ number = (((number != undef) ? number : 0) * 10) + (key.which - 48);
477
+ }
478
+ }
479
+ return false;
480
+ }
481
+
482
+ function clicker(e) {
483
+ number = undef;
484
+ var target;
485
+ if (window.event) {
486
+ target = window.event.srcElement;
487
+ e = window.event;
488
+ } else target = e.target;
489
+ if (target.getAttribute('href') != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true;
490
+ if (!e.which || e.which == 1) {
491
+ if (!incrementals[snum] || incpos >= incrementals[snum].length) {
492
+ go(1);
493
+ } else {
494
+ subgo(1);
495
+ }
496
+ }
497
+ }
498
+
499
+ function findSlide(hash) {
500
+ var target = null;
501
+ var slides = GetElementsWithClassName('*','slide');
502
+ for (var i = 0; i < slides.length; i++) {
503
+ var targetSlide = slides[i];
504
+ if ( (targetSlide.name && targetSlide.name == hash)
505
+ || (targetSlide.id && targetSlide.id == hash) ) {
506
+ target = targetSlide;
507
+ break;
508
+ }
509
+ }
510
+ while(target != null && target.nodeName != 'BODY') {
511
+ if (hasClass(target, 'slide')) {
512
+ return parseInt(target.id.slice(5));
513
+ }
514
+ target = target.parentNode;
515
+ }
516
+ return null;
517
+ }
518
+
519
+ function slideJump() {
520
+ if (window.location.hash == null) return;
521
+ var sregex = /^#slide(\d+)$/;
522
+ var matches = sregex.exec(window.location.hash);
523
+ var dest = null;
524
+ if (matches != null) {
525
+ dest = parseInt(matches[1]);
526
+ } else {
527
+ dest = findSlide(window.location.hash.slice(1));
528
+ }
529
+ if (dest != null)
530
+ go(dest - snum);
531
+ }
532
+
533
+ function fixLinks() {
534
+ var thisUri = window.location.href;
535
+ thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length);
536
+ var aelements = document.getElementsByTagName('A');
537
+ for (var i = 0; i < aelements.length; i++) {
538
+ var a = aelements[i].href;
539
+ var slideID = a.match('\#slide[0-9]{1,2}');
540
+ if ((slideID) && (slideID[0].slice(0,1) == '#')) {
541
+ var dest = findSlide(slideID[0].slice(1));
542
+ if (dest != null) {
543
+ if (aelements[i].addEventListener) {
544
+ aelements[i].addEventListener("click", new Function("e",
545
+ "if (document.getElementById('slideProj').disabled) return;" +
546
+ "go("+dest+" - snum); " +
547
+ "if (e.preventDefault) e.preventDefault();"), true);
548
+ } else if (aelements[i].attachEvent) {
549
+ aelements[i].attachEvent("onclick", new Function("",
550
+ "if (document.getElementById('slideProj').disabled) return;" +
551
+ "go("+dest+" - snum); " +
552
+ "event.returnValue = false;"));
553
+ }
554
+ }
555
+ }
556
+ }
557
+ }
558
+
559
+ function externalLinks() {
560
+ if (!document.getElementsByTagName) return;
561
+ var anchors = document.getElementsByTagName('a');
562
+ for (var i=0; i<anchors.length; i++) {
563
+ var anchor = anchors[i];
564
+ if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) {
565
+ anchor.target = '_blank';
566
+ addClass(anchor,'external');
567
+ }
568
+ }
569
+ }
570
+
571
+ function createControls() {
572
+ var controlsDiv = document.getElementById("controls");
573
+ if (!controlsDiv) return;
574
+ var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"';
575
+ var hideDiv, hideList = '';
576
+ if (controlVis == 'hidden') {
577
+ hideDiv = hider;
578
+ } else {
579
+ hideList = hider;
580
+ }
581
+ controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' +
582
+ '<div id="navLinks">' +
583
+ '<a accesskey="t" id="toggle" href="javascript:toggle();">&#216;<\/a>' +
584
+ '<a accesskey="z" id="prev" href="javascript:go(-1);">&laquo;<\/a>' +
585
+ '<a accesskey="x" id="next" href="javascript:go(1);">&raquo;<\/a>' +
586
+ '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' +
587
+ '<\/div><\/form>';
588
+ if (controlVis == 'hidden') {
589
+ var hidden = document.getElementById('navLinks');
590
+ } else {
591
+ var hidden = document.getElementById('jumplist');
592
+ }
593
+ addClass(hidden,'hideme');
594
+ }
595
+
596
+ function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers
597
+ if (!s5mode) return false;
598
+ var vScale = 22; // both yield 32 (after rounding) at 1024x768
599
+ var hScale = 32; // perhaps should auto-calculate based on theme's declared value?
600
+ if (window.innerHeight) {
601
+ var vSize = window.innerHeight;
602
+ var hSize = window.innerWidth;
603
+ } else if (document.documentElement.clientHeight) {
604
+ var vSize = document.documentElement.clientHeight;
605
+ var hSize = document.documentElement.clientWidth;
606
+ } else if (document.body.clientHeight) {
607
+ var vSize = document.body.clientHeight;
608
+ var hSize = document.body.clientWidth;
609
+ } else {
610
+ var vSize = 700; // assuming 1024x768, minus chrome and such
611
+ var hSize = 1024; // these do not account for kiosk mode or Opera Show
612
+ }
613
+ var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale));
614
+ fontSize(newSize + 'px');
615
+ if (isGe) { // hack to counter incremental reflow bugs
616
+ var obj = document.getElementsByTagName('body')[0];
617
+ obj.style.display = 'none';
618
+ obj.style.display = 'block';
619
+ }
620
+ }
621
+
622
+ function fontSize(value) {
623
+ if (!(s5ss = document.getElementById('s5ss'))) {
624
+ if (!isIE) {
625
+ document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style'));
626
+ s5ss.setAttribute('media','screen, projection');
627
+ s5ss.setAttribute('id','s5ss');
628
+ } else {
629
+ document.createStyleSheet();
630
+ document.s5ss = document.styleSheets[document.styleSheets.length - 1];
631
+ }
632
+ }
633
+ if (!isIE) {
634
+ while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild);
635
+ s5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}'));
636
+ } else {
637
+ document.s5ss.addRule('body','font-size: ' + value + ' !important;');
638
+ }
639
+ }
640
+
641
+ function notOperaFix() {
642
+ slideCSS = document.getElementById('slideProj').href;
643
+ var slides = document.getElementById('slideProj');
644
+ var outline = document.getElementById('outlineStyle');
645
+ slides.setAttribute('media','screen');
646
+ outline.disabled = true;
647
+ if (isGe) {
648
+ slides.setAttribute('href','null'); // Gecko fix
649
+ slides.setAttribute('href',slideCSS); // Gecko fix
650
+ }
651
+ if (isIE && document.styleSheets && document.styleSheets[0]) {
652
+ document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)');
653
+ document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)');
654
+ document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)');
655
+ }
656
+ }
657
+
658
+ function getIncrementals(obj) {
659
+ var incrementals = new Array();
660
+ if (!obj)
661
+ return incrementals;
662
+ var children = obj.childNodes;
663
+ for (var i = 0; i < children.length; i++) {
664
+ var child = children[i];
665
+ if (hasClass(child, 'incremental')) {
666
+ if (child.nodeName == 'OL' || child.nodeName == 'UL') {
667
+ removeClass(child, 'incremental');
668
+ for (var j = 0; j < child.childNodes.length; j++) {
669
+ if (child.childNodes[j].nodeType == 1) {
670
+ addClass(child.childNodes[j], 'incremental');
671
+ }
672
+ }
673
+ } else {
674
+ incrementals[incrementals.length] = child;
675
+ removeClass(child,'incremental');
676
+ }
677
+ }
678
+ if (hasClass(child, 'show-first')) {
679
+ if (child.nodeName == 'OL' || child.nodeName == 'UL') {
680
+ removeClass(child, 'show-first');
681
+ if (child.childNodes[isGe].nodeType == 1) {
682
+ removeClass(child.childNodes[isGe], 'incremental');
683
+ }
684
+ } else {
685
+ incrementals[incrementals.length] = child;
686
+ }
687
+ }
688
+ incrementals = incrementals.concat(getIncrementals(child));
689
+ }
690
+ return incrementals;
691
+ }
692
+
693
+ function createIncrementals() {
694
+ var incrementals = new Array();
695
+ for (var i = 0; i < smax; i++) {
696
+ incrementals[i] = getIncrementals(document.getElementById('slide'+i));
697
+ }
698
+ return incrementals;
699
+ }
700
+
701
+ function defaultCheck() {
702
+ var allMetas = document.getElementsByTagName('meta');
703
+ for (var i = 0; i< allMetas.length; i++) {
704
+ if (allMetas[i].name == 'defaultView') {
705
+ defaultView = allMetas[i].content;
706
+ }
707
+ if (allMetas[i].name == 'controlVis') {
708
+ controlVis = allMetas[i].content;
709
+ }
710
+ }
711
+ }
712
+
713
+ // Key trap fix, new function body for trap()
714
+ function trap(e) {
715
+ if (!e) {
716
+ e = event;
717
+ e.which = e.keyCode;
718
+ }
719
+ try {
720
+ modifierKey = e.ctrlKey || e.altKey || e.metaKey;
721
+ }
722
+ catch(e) {
723
+ modifierKey = false;
724
+ }
725
+ return modifierKey || e.which == 0;
726
+ }
727
+
728
+ function startup() {
729
+ defaultCheck();
730
+ if (!isOp)
731
+ createControls();
732
+ slideLabel();
733
+ fixLinks();
734
+ externalLinks();
735
+ fontScale();
736
+ if (!isOp) {
737
+ notOperaFix();
738
+ incrementals = createIncrementals();
739
+ slideJump();
740
+ if (defaultView == 'outline') {
741
+ toggle();
742
+ }
743
+ document.onkeyup = keys;
744
+ document.onkeypress = trap;
745
+ document.onclick = clicker;
746
+ }
747
+ }
748
+
749
+ window.onload = startup;
750
+ window.onresize = function(){setTimeout('fontScale()', 50);}
751
+ ]]></script>
752
+
753
+ EOF
754
+
755
+ end
756
+