maruku 0.5.3 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
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
+