jim 0.2.3 → 0.3.0.pre

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 (66) hide show
  1. data/Gemfile +2 -1
  2. data/Gemfile.lock +2 -0
  3. data/HISTORY +13 -0
  4. data/README.md +148 -0
  5. data/Rakefile +6 -3
  6. data/bin/jim +1 -2
  7. data/default +0 -0
  8. data/jim.gemspec +142 -105
  9. data/lib/jim.rb +1 -1
  10. data/lib/jim/bundler.rb +168 -73
  11. data/lib/jim/cli.rb +200 -151
  12. data/lib/jim/index.rb +20 -9
  13. data/lib/jim/installer.rb +46 -46
  14. data/lib/jim/rack.rb +57 -20
  15. data/lib/jim/templates/jimfile +11 -5
  16. data/lib/jim/version_parser.rb +3 -3
  17. data/test/fixtures/infoincomments.js +1 -1
  18. data/test/fixtures/jimfile +14 -7
  19. data/test/fixtures/jquery-1.4.1.js +3 -6057
  20. data/test/fixtures/jquery.color.js +1 -1
  21. data/test/fixtures/localfile.js +1 -1
  22. data/test/fixtures/mustache.js/package.json +1 -1
  23. data/test/fixtures/noversion.js +1 -1
  24. data/test/fixtures/old_jimfile +7 -0
  25. data/test/fixtures/sammy-0.5.0/examples/backend/app.rb +4 -4
  26. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js +18 -18
  27. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js +1 -1
  28. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js +1 -1
  29. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js +161 -161
  30. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb +1 -1
  31. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb +1 -1
  32. data/test/fixtures/sammy-0.5.0/examples/backend/views/app.sass +6 -6
  33. data/test/fixtures/sammy-0.5.0/examples/backend/views/index.haml +5 -5
  34. data/test/fixtures/sammy-0.5.0/examples/form_handling/index.html +16 -16
  35. data/test/fixtures/sammy-0.5.0/examples/hello_world/index.html +13 -13
  36. data/test/fixtures/sammy-0.5.0/examples/location_override/data.html +28 -28
  37. data/test/fixtures/sammy-0.5.0/examples/location_override/index.html +18 -18
  38. data/test/fixtures/sammy-0.5.0/examples/location_override/test.html +36 -36
  39. data/test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js +1 -1
  40. data/test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js +1 -1
  41. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js +13 -13
  42. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js +2 -2
  43. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js +15 -15
  44. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js +46 -46
  45. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js +29 -29
  46. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js +54 -54
  47. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js +17 -17
  48. data/test/fixtures/sammy-0.5.0/lib/sammy.js +220 -220
  49. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.html +1 -1
  50. data/test/fixtures/sammy-0.5.0/test/index.html +26 -26
  51. data/test/fixtures/sammy-0.5.0/test/test_sammy_application.js +60 -60
  52. data/test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js +21 -21
  53. data/test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js +3 -3
  54. data/test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js +17 -17
  55. data/test/fixtures/sammy-0.5.0/test/test_sammy_storage.js +4 -4
  56. data/test/helper.rb +15 -0
  57. data/test/test_jim_bundler.rb +114 -74
  58. data/test/test_jim_cli.rb +34 -18
  59. data/test/test_jim_index.rb +19 -19
  60. data/test/test_jim_installer.rb +13 -13
  61. data/test/test_jim_rack.rb +41 -0
  62. data/test/test_jim_version_parser.rb +4 -4
  63. metadata +204 -41
  64. data/.gitignore +0 -24
  65. data/README.rdoc +0 -105
  66. data/lib/jim/templates/commands +0 -58
@@ -1,4 +1,4 @@
1
1
  <li class="task <%= (task.attr('completed') ? 'completed' : '') %>" id="<%= task.attr('id') %>">
2
2
  <input type="checkbox" <%= (task.attr('completed') ? 'checked="checked"' : '') %>" />
3
3
  <a href="#/tasks/<%= task.attr('id') %>" class="entry"><%= task.attr('entry') %></a>
4
- </li>
4
+ </li>
@@ -1,4 +1,4 @@
1
1
  <%= console.log('template task', task) %>
2
2
  <div id="task_<%= task.__id__ %>">
3
3
  <h3><%= task.entry %></h3>
4
- </div>
4
+ </div>
@@ -5,17 +5,17 @@ body
5
5
  :color #333
6
6
  :margin 0px
7
7
  :background #F3F3F3
8
-
8
+
9
9
 
10
10
  a:link, a:visited
11
11
  :text-decoration none
12
12
  :color #5588CA
13
- a:hover
13
+ a:hover
14
14
  :color #333
15
15
  :background #E8E8E8
16
16
  :-moz-border-radius 2px
17
17
 
18
- h1
18
+ h1
19
19
  :color #000
20
20
  :margin 0px
21
21
  :font-weight normal
@@ -25,7 +25,7 @@ h1
25
25
  a:hover
26
26
  :color #5588CA
27
27
  :background none
28
-
28
+
29
29
  #header
30
30
  :padding 5px 20px
31
31
  :background #D7D7D7
@@ -46,7 +46,7 @@ h1
46
46
  &.completed a
47
47
  :text-decoration line-through
48
48
  :color #999
49
-
49
+
50
50
  #task_entry
51
51
  input[type=text]
52
52
  :width 100%
@@ -60,4 +60,4 @@ h1
60
60
  :padding 4px 20px
61
61
  :color #333
62
62
  :background #ECECEC
63
- :border 1px solid #CCC
63
+ :border 1px solid #CCC
@@ -2,17 +2,17 @@
2
2
  %head
3
3
  %meta{'http-equiv' => "Content-Type", 'content' => "text/html; charset=utf-8"}
4
4
  %title Backended
5
-
5
+
6
6
  %link{:rel => 'stylesheet', :href => '/stylesheets/app.css', :media => 'screen'}
7
-
7
+
8
8
  - ['jquery', 'jquery.cloudkit', 'sammy', 'app'].each do |js|
9
9
  %script{:src => "/javascripts/#{js}.js", :type => 'text/javascript', :charset => 'utf-8'}
10
10
  %body
11
11
  #container
12
12
  #header
13
- %h1
13
+ %h1
14
14
  %a{:href => '#/', :title => 'Home'} Sammy Todo
15
15
  #error{:style => 'display:none'}
16
16
  %span.close x
17
- #main
18
- #debug
17
+ #main
18
+ #debug
@@ -1,38 +1,38 @@
1
1
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
3
 
4
4
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
5
  <head>
6
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
+
8
+ <title>Form Handling</title>
7
9
 
8
- <title>Form Handling</title>
9
-
10
10
  <style type="text/css" media="screen">
11
-
11
+
12
12
  </style>
13
-
14
- <script src="../../vendor/jquery-1.4.1.min.js" type="text/javascript" charset="utf-8"></script>
15
- <script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
13
+
14
+ <script src="../../vendor/jquery-1.4.1.min.js" type="text/javascript" charset="utf-8"></script>
15
+ <script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
16
16
  <script type="text/javascript" charset="utf-8">
17
17
  // ;(function($) {
18
18
  var app = new Sammy.Application(function() { with(this) {
19
19
  debug = true;
20
20
  element_selector = '#main';
21
21
  form_fields = null;
22
-
22
+
23
23
  get('#/', function() { with(this) {
24
24
  $element().text('Click form!');
25
25
  }});
26
-
26
+
27
27
  get('#/form', function() { with(this) {
28
28
  partial('files/form.html');
29
29
  }});
30
-
30
+
31
31
  post('#/pretend/post/url', function() { with(this) {
32
32
  form_fields = params;
33
33
  redirect('#/display');
34
34
  }});
35
-
35
+
36
36
  get('#/display', function() { with(this) {
37
37
  if (form_fields) {
38
38
  $element().html(form_fields.toHTML());
@@ -40,16 +40,16 @@
40
40
  redirect('#/form')
41
41
  }
42
42
  }});
43
-
43
+
44
44
  }});
45
-
45
+
46
46
  $(function() {
47
47
  app.run('#/');
48
48
  });
49
-
49
+
50
50
  // })(jQuery);
51
51
  </script>
52
-
52
+
53
53
  </head>
54
54
 
55
55
  <body>
@@ -1,40 +1,40 @@
1
1
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
3
 
4
4
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
5
  <head>
6
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
+
8
+ <title>Hello World</title>
7
9
 
8
- <title>Hello World</title>
9
-
10
10
  <style type="text/css" media="screen">
11
-
11
+
12
12
  </style>
13
-
14
- <script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
15
- <script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
13
+
14
+ <script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
15
+ <script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
16
16
  <script type="text/javascript" charset="utf-8">
17
17
  ;(function($) {
18
18
  var app = new Sammy.Application(function() {
19
19
  with(this) {
20
-
20
+
21
21
  get('#/', function() { with(this) {
22
22
  $('#main').text('');
23
23
  }});
24
-
24
+
25
25
  get('#/test', function() { with(this) {
26
26
  $('#main').text('Hello World');
27
27
  }});
28
-
28
+
29
29
  }
30
30
  });
31
-
31
+
32
32
  $(function() {
33
33
  app.run()
34
34
  });
35
35
  })(jQuery);
36
36
  </script>
37
-
37
+
38
38
  </head>
39
39
 
40
40
  <body>
@@ -1,23 +1,23 @@
1
1
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
3
 
4
4
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
5
  <head>
6
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
- <title>Location Demo</title>
8
- <style type="text/css" media="screen">
9
- #main { background-color: #CCCCCC; }
10
- </style>
11
-
12
- <script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
13
- <script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
14
-
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
+ <title>Location Demo</title>
8
+ <style type="text/css" media="screen">
9
+ #main { background-color: #CCCCCC; }
10
+ </style>
11
+
12
+ <script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
13
+ <script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
14
+
15
15
  <script type="text/javascript" charset="utf-8">
16
16
  ;(function($) {
17
17
  var app = new Sammy.Application(function() { with(this) {
18
18
  debug = true;
19
19
  element_selector = '#main';
20
-
20
+
21
21
  // overide getLocation
22
22
  this.getLocation = function() {
23
23
  if (this.$element().data('location') == undefined) {
@@ -25,25 +25,25 @@
25
25
  };
26
26
  return this.$element().data('location');
27
27
  };
28
-
28
+
29
29
  // overide setLocation
30
30
  this.setLocation = function(new_location) {
31
31
  return this.$element().data('location', new_location);
32
32
  };
33
-
33
+
34
34
  get('#/', function() { with(this) {
35
35
  $("#output").text("matched: #/");
36
36
  }});
37
-
37
+
38
38
  get('#/link/:id', function() { with(this) {
39
39
  $("#output").text("matched: #/link/:" + params['id']);
40
40
  }});
41
-
41
+
42
42
  post('#/form', function() { with(this) {
43
43
  $("#output").text("post matched: #/form - params[field] = " + params['field']);
44
44
  return false;
45
45
  }});
46
-
46
+
47
47
  put('#/form', function() { with(this) {
48
48
  $("#output").text("put matched: #/form - params[field] = " + params['field']);
49
49
  return false;
@@ -64,47 +64,47 @@
64
64
  return true;
65
65
  }
66
66
  });
67
-
67
+
68
68
  }});
69
-
69
+
70
70
  }});
71
-
71
+
72
72
  $(function() {
73
73
  app.run('#/');
74
74
  });
75
-
75
+
76
76
  })(jQuery);
77
77
  </script>
78
-
78
+
79
79
  </head>
80
80
 
81
81
  <body>
82
82
  <div id="container">
83
-
83
+
84
84
  <div id="main">
85
85
  <ul>
86
86
  <li><a href="data.html">reset</a></li>
87
87
  <li><a href="#/">#/</a></li>
88
88
  <li><a href="#/link/id">#/link/id</a></li>
89
89
  </ul>
90
-
90
+
91
91
  <form action="#/form" method="put">
92
92
  <p><input type="text" name="field" value="WAS PUT" id="field"/></p>
93
93
  <p><input type="submit" value="Continue &rarr;"/></p>
94
94
  </form>
95
-
95
+
96
96
  <form action="#/form" method="post">
97
97
  <p><input type="text" name="field" value="WAS POSTED" id="field"/></p>
98
98
  <p><input type="submit" value="Continue &rarr;"/></p>
99
99
  </form>
100
100
  </div>
101
-
101
+
102
102
  <h1>Results</h1>
103
-
103
+
104
104
  <div id="output">
105
105
  </div>
106
-
106
+
107
107
  </div>
108
-
108
+
109
109
  </body>
110
110
  </html>
@@ -1,46 +1,46 @@
1
1
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
3
 
4
4
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
5
  <head>
6
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
+
8
+ <title>Form Handling</title>
7
9
 
8
- <title>Form Handling</title>
9
-
10
10
  <style type="text/css" media="screen">
11
-
11
+
12
12
  </style>
13
-
14
- <script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
15
- <script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
13
+
14
+ <script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
15
+ <script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
16
16
  <script type="text/javascript" charset="utf-8">
17
17
  ;(function($) {
18
18
  var app = new Sammy.Application(function() { with(this) {
19
19
  debug = true;
20
20
  element_selector = '#main';
21
21
  // form_fields = null;
22
-
22
+
23
23
  this.getLocation = function() {
24
24
  return $('#location').val().toString();
25
25
  };
26
-
26
+
27
27
  this.setLocation = function(new_location) {
28
28
  return $('#location').val(new_location);
29
29
  }
30
-
30
+
31
31
  get('/', function() { with(this) {
32
32
  $element().html('Enter a URL in the field above! Try /user/...');
33
33
  }});
34
-
34
+
35
35
  get('/user/:name', function() { with(this) {
36
36
  $element().html('Youre at ' + params['name'] + "'s page. <a href='/' class='back'>Go Back</a>.");
37
37
  }});
38
-
38
+
39
39
  bind('back', function() { with(this) {
40
40
  log('back!');
41
41
  redirect('/');
42
42
  }});
43
-
43
+
44
44
  bind('run', function() {
45
45
  var context = this;
46
46
  $('a').live('click', function() {
@@ -53,16 +53,16 @@
53
53
  }
54
54
  });
55
55
  });
56
-
56
+
57
57
  }});
58
-
58
+
59
59
  $(function() {
60
60
  app.run('/');
61
61
  });
62
-
62
+
63
63
  })(jQuery);
64
64
  </script>
65
-
65
+
66
66
  </head>
67
67
 
68
68
  <body>
@@ -1,21 +1,21 @@
1
1
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
3
 
4
4
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
5
  <head>
6
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
- <title>Location Demo</title>
8
- <style type="text/css" media="screen">
9
- #main { background-color: #CCCCCC; }
10
- #output { background-color: #FF6666; }
11
- </style>
12
-
13
- <script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
14
- <script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
15
-
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
+ <title>Location Demo</title>
8
+ <style type="text/css" media="screen">
9
+ #main { background-color: #CCCCCC; }
10
+ #output { background-color: #FF6666; }
11
+ </style>
12
+
13
+ <script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
14
+ <script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
15
+
16
16
  <script type="text/javascript" charset="utf-8">
17
17
  ;(function($) {
18
-
18
+
19
19
  // ----------------------------------------------------------------
20
20
 
21
21
  Sammy.Application.prototype.getLocation = function() {
@@ -24,27 +24,27 @@
24
24
  };
25
25
  return this.$element().data('appState');
26
26
  };
27
-
27
+
28
28
  Sammy.Application.prototype.setLocation = function(newState) {
29
29
  console.log('setLocation called with:', newState);
30
30
  return this.$element().data('appState', newState);
31
31
  };
32
-
32
+
33
33
  // ----------------------------------------------------------------
34
-
34
+
35
35
  var app = new Sammy.Application(function() { with(this) {
36
36
  element_selector = '#main';
37
-
37
+
38
38
  get('#/link', function() { with(this) {
39
39
  $("#output").text("matched: #/link");
40
40
  redirect('#/test_route');
41
41
  }});
42
-
42
+
43
43
  post('#/form', function() { with(this) {
44
44
  $("#output").text("post matched: #/form (REDIRECT UNSUCCESSFUL)");
45
45
  redirect('#/test_route');
46
46
  }});
47
-
47
+
48
48
  get('#/test_route', function() { with(this) {
49
49
  $("#output").text("matched: #/test_route (REDIRECT SUCCESSFUL)");
50
50
  }});
@@ -64,58 +64,58 @@
64
64
  return true;
65
65
  }
66
66
  });
67
-
67
+
68
68
  }});
69
69
  }});
70
-
70
+
71
71
  // ----------------------------------------------------------------
72
-
72
+
73
73
  $(function() {
74
74
  app.run();
75
75
  });
76
-
76
+
77
77
  })(jQuery);
78
78
  </script>
79
-
79
+
80
80
  </head>
81
81
 
82
82
  <body>
83
83
  <div id="container">
84
-
84
+
85
85
  <h2>Using <strong>redirects</strong> with the new location storage.</h2>
86
-
86
+
87
87
  <p>This example defines 2 routes, <strong>#/link</strong> and <strong>#/form</strong> ... both of which execute a redirect to <strong>#/test_route</strong></p>
88
-
88
+
89
89
  <p><u>When #/link route triggers the redirect</u>, the behavior is as expected every time. And when I look in console I can see setLocation being called <strong>twice</strong> as I'd expect.</p>
90
90
 
91
91
  <p><u>When #/form route triggers the redirect</u>, the behavior seems inconsistent.</p>
92
-
92
+
93
93
  <p>The first form submit is successful, the redirect occurs and the body of the #/test_route executes. BUT! looking in console, we see setLocation only being called <strong>once</strong> for the #/test_route/ and not at all for the #/form route preceeding it.</p>
94
-
94
+
95
95
  <p>Because #/test_route was the last location set, and because the #/form route never did a setLocation anyway, repeated clicks to submit the form will not be heard.</p>
96
-
96
+
97
97
  <p>I kind of expect that when a form submission is caught it will trigger a Setlocation ... but looking in _checkFormSubmission, i see that the form routes are manually run here via runRoute, bypassing setLocation entirely!</p>
98
-
98
+
99
99
  <p>Any thoughts on this? I know that recording app state via data attributes isn't a core feature of sammy, but I'm curious to hear if you think caught form submits should still bypass setLocation etc.</p>
100
-
100
+
101
101
  <div id="main">
102
102
  <ul>
103
103
  <li><a href="quirkey.html">reset</a></li>
104
104
  <li><a href="#/link">#/link</a></li>
105
105
  </ul>
106
-
106
+
107
107
  <form action="#/form" method="post">
108
108
  <p><input type="text" name="field" value="WAS POSTED" id="field"/></p>
109
109
  <p><input type="submit" value="Continue &rarr;"/></p>
110
110
  </form>
111
111
  </div>
112
-
112
+
113
113
  <h1>Results</h1>
114
-
114
+
115
115
  <div id="output">
116
116
  </div>
117
-
117
+
118
118
  </div>
119
-
119
+
120
120
  </body>
121
121
  </html>