codestock 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Rakefile +1 -0
  2. data/VERSION +1 -1
  3. data/bin/cdweb +2 -2
  4. data/codestock.gemspec +56 -10
  5. data/lib/cdstk/cdstk.rb +4 -1
  6. data/lib/codestock/cdweb/app.rb +136 -0
  7. data/lib/codestock/cdweb/cli_cdweb.rb +84 -0
  8. data/lib/codestock/cdweb/config.ru +3 -0
  9. data/lib/codestock/cdweb/lib/coderay_wrapper.rb +94 -0
  10. data/lib/codestock/cdweb/lib/command.rb +67 -0
  11. data/lib/{cdweb → codestock/cdweb/lib}/database.rb +55 -28
  12. data/lib/{cdweb → codestock/cdweb/lib}/grep.rb +24 -8
  13. data/lib/codestock/cdweb/lib/mkurl.rb +56 -0
  14. data/lib/{cdweb → codestock/cdweb/lib}/query.rb +3 -4
  15. data/lib/codestock/cdweb/lib/search_contents.rb +117 -0
  16. data/lib/codestock/cdweb/lib/search_files.rb +88 -0
  17. data/lib/{cdweb → codestock/cdweb}/public/css/gren.css +16 -1
  18. data/lib/codestock/cdweb/public/images/directory.png +0 -0
  19. data/lib/codestock/cdweb/public/images/file.png +0 -0
  20. data/lib/codestock/cdweb/views/filelist.haml +14 -0
  21. data/lib/codestock/cdweb/views/help.haml +16 -0
  22. data/lib/codestock/cdweb/views/index.haml +17 -0
  23. data/lib/codestock/cdweb/views/layout.haml +33 -0
  24. data/lib/codestock/cdweb/views/search.haml +12 -0
  25. data/lib/codestock/cdweb/views/view.haml +16 -0
  26. data/test/file_assert.rb +41 -0
  27. data/test/test_coderay_wrapper.rb +22 -0
  28. data/test/test_coderay_wrapper_data.rb +91 -0
  29. data/test/test_database.rb +54 -0
  30. data/test/test_mkurl.rb +30 -0
  31. data/test/test_query.rb +54 -0
  32. metadata +52 -26
  33. data/lib/cdweb/cli_cdweb.rb +0 -54
  34. data/lib/cdweb/coderay_wrapper.rb +0 -38
  35. data/lib/cdweb/grenweb.ru +0 -35
  36. data/lib/cdweb/help.rb +0 -40
  37. data/lib/cdweb/home.rb +0 -40
  38. data/lib/cdweb/html_renderer.rb +0 -243
  39. data/lib/cdweb/searcher.rb +0 -130
  40. data/lib/cdweb/viewer.rb +0 -52
  41. data/test/test_grenweb_database.rb +0 -36
  42. data/test/test_grenweb_html_renderer.rb +0 -41
  43. data/test/test_grenweb_query.rb +0 -54
  44. data/test/test_grenweb_searcher.rb +0 -35
  45. /data/lib/{cdweb → codestock/cdweb}/public/css/coderay.css +0 -0
  46. /data/lib/{cdweb → codestock/cdweb}/public/images/gren-icon-mini.png +0 -0
  47. /data/lib/{cdweb → codestock/cdweb}/public/images/gren-icon.png +0 -0
@@ -7,31 +7,47 @@
7
7
 
8
8
  module CodeStock
9
9
  class Grep
10
- attr_reader :content
11
-
12
10
  def initialize(content)
13
- @content = content ? content.split("\n") : []
11
+ @content = content
14
12
  end
15
13
 
16
14
  MatchLineResult = Struct.new(:index, :match_datas)
17
15
 
18
- def match_lines_or(patterns)
16
+ def match_lines_and(patterns)
19
17
  result = []
20
- patternRegexps = strs2regs(patterns, true) # @todo ignoreオプションを付ける
18
+ patternRegexps = strs2regs(patterns, true)
19
+ index = 0
21
20
 
22
- @content.each_with_index do |line, index|
21
+ @content.each_line do |line|
23
22
  match_datas = []
24
23
  patternRegexps.each {|v| match_datas << v.match(line)}
25
24
 
26
- if (match_datas.any?)
25
+ if (match_datas.all?)
27
26
  result << MatchLineResult.new(index, match_datas)
28
27
  end
28
+
29
+ index += 1
29
30
  end
30
31
 
31
32
  result
32
33
  end
33
34
 
34
- def context(result, num)
35
+ def one_match_and(patterns)
36
+ patternRegexps = strs2regs(patterns, true)
37
+ index = 0
38
+
39
+ @content.each_line do |line|
40
+ match_datas = []
41
+ patternRegexps.each {|v| match_datas << v.match(line)}
42
+
43
+ if (match_datas.all?)
44
+ return MatchLineResult.new(index, match_datas)
45
+ end
46
+
47
+ index += 1
48
+ end
49
+
50
+ nil
35
51
  end
36
52
 
37
53
  private
@@ -0,0 +1,56 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief
5
+ # @author ongaeshi
6
+ # @date 2011/07/13
7
+
8
+ require 'rubygems'
9
+ require 'rack'
10
+ include Rack::Utils
11
+
12
+ module CodeStock
13
+ class Mkurl
14
+ def initialize(path, params)
15
+ @path = escape_path(path)
16
+ @params = params
17
+ end
18
+
19
+ def inherit_query_shead_offset
20
+ create_url(query_param(true, true, true))
21
+ end
22
+
23
+ def inherit_query_shead
24
+ create_url(query_param(true, true, false))
25
+ end
26
+
27
+ def inherit_shead
28
+ create_url(query_param(false, true, false))
29
+ end
30
+
31
+ private
32
+
33
+ def escape_path(src)
34
+ escape(src).gsub("%2F", '/')
35
+ end
36
+
37
+ def create_url(qp)
38
+ if (qp == "")
39
+ @path
40
+ else
41
+ "#{@path}?#{qp}"
42
+ end
43
+ end
44
+
45
+ def query_param(query_inherit, shead_inherit, offset_inherit)
46
+ qparam = []
47
+ qparam << "query=#{escape(@params[:query])}" if (query_inherit and @params[:query])
48
+ qparam << "shead=#{escape(@params[:shead])}" if (shead_inherit and @params[:shead])
49
+ qparam << "offset=#{escape(@params[:offset])}" if (offset_inherit and @params[:offset])
50
+ qparam.join('&')
51
+ end
52
+ end
53
+ end
54
+
55
+
56
+
@@ -10,17 +10,16 @@ require 'rack'
10
10
 
11
11
  module CodeStock
12
12
  class Query
13
- include Rack::Utils
14
13
  attr_reader :query_string
15
-
14
+
16
15
  OPTIONS = [
17
16
  ['package', 'p'],
18
17
  ['filepath', 'fpath', 'f'],
19
18
  ['suffix', 's'],
20
19
  ]
21
20
 
22
- def initialize(request)
23
- @query_string = unescape(request.path_info.gsub(/\A\/|\/\z/, ''))
21
+ def initialize(str)
22
+ @query_string = str
24
23
  init_hash
25
24
  parse
26
25
  end
@@ -0,0 +1,117 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief
5
+ # @author ongaeshi
6
+ # @date 2011/07/18
7
+
8
+ require 'codestock/cdweb/lib/query'
9
+ require 'codestock/cdweb/lib/grep'
10
+ require 'codestock/cdweb/lib/mkurl'
11
+
12
+ module CodeStock
13
+ class SearchContents
14
+ attr_reader :total_records
15
+ attr_reader :elapsed
16
+ attr_reader :page
17
+
18
+ DISP_NUM = 20 # 1ページの表示数
19
+ LIMIT_NUM = 50 # 最大検索ファイル数
20
+ NTH = 3 # 表示範囲
21
+
22
+ def initialize(path, params, query)
23
+ @params = params
24
+ @q = query
25
+ @page = params[:page].to_i || 0
26
+ @offset = params[:offset].to_i
27
+ fpaths = @q.fpaths
28
+ fpaths << path unless path == ""
29
+ @records, @total_records, @elapsed = Database.instance.search(@q.keywords, @q.packages, fpaths, @q.suffixs, @offset, LIMIT_NUM)
30
+ grep_contents
31
+ end
32
+
33
+ def query
34
+ @q.query_string
35
+ end
36
+
37
+ def next_offset
38
+ @offset + @next_index
39
+ end
40
+
41
+ def data_range
42
+ @offset..(next_offset - 1)
43
+ end
44
+
45
+ def html_contents
46
+ @match_records.map {|match_record| result_match_record(match_record)}.join
47
+ end
48
+
49
+ def html_pagination
50
+ return "" if @q.empty?
51
+ return "" if next_offset >= @total_records
52
+
53
+ return <<EOF
54
+ <div class='pagination'>
55
+ #{pagination_link(next_offset, "next >>")}
56
+ </div>
57
+ EOF
58
+ end
59
+
60
+ private
61
+
62
+ MatchRecord = Struct.new(:record, :match_line)
63
+
64
+ def grep_contents
65
+ @match_records = []
66
+ @next_index = @records.size
67
+
68
+ @records.each_with_index do |record, index|
69
+ grep = Grep.new(record.content)
70
+ match_line = grep.one_match_and(@q.keywords)
71
+ @match_records << MatchRecord.new(record, match_line) if match_line
72
+
73
+ if @match_records.size > DISP_NUM
74
+ @next_index = index + 1
75
+ break
76
+ end
77
+ end
78
+ end
79
+
80
+ def result_match_record(match_record)
81
+ record = match_record.record
82
+ match_line = match_record.match_line
83
+
84
+ first_index = match_line.index - NTH
85
+ last_index = match_line.index + NTH
86
+
87
+ coderay = CodeRayWrapper.new(record.content, record.shortpath, [match_line])
88
+ coderay.set_range(first_index..last_index)
89
+
90
+ <<EOS
91
+ <dt class='result-record'><a href='#{"/home/" + record_link(record) + "##{coderay.line_number_start}"}'>#{record.shortpath}</a></dt>
92
+ <dd>
93
+ #{coderay.to_html}
94
+ </dd>
95
+ EOS
96
+ end
97
+
98
+ def pagination_link(offset, label)
99
+ tmpp = @params
100
+ tmpp[:offset] = offset.to_s
101
+ href = Mkurl.new("", tmpp).inherit_query_shead_offset
102
+ pagination_span("<a href='#{href}'>#{label}</a>")
103
+ end
104
+
105
+ def pagination_span(content)
106
+ "<span class='pagination-link'>#{content}</span>\n"
107
+ end
108
+
109
+ def record_link(record) #
110
+ Mkurl.new(record.shortpath, @params).inherit_query_shead
111
+ end
112
+
113
+ end
114
+ end
115
+
116
+
117
+
@@ -0,0 +1,88 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief
5
+ # @author ongaeshi
6
+ # @date 2011/07/18
7
+
8
+ require 'codestock/cdweb/lib/query'
9
+ require 'codestock/cdweb/lib/mkurl'
10
+ require 'codestock/cdweb/lib/command'
11
+
12
+ module CodeStock
13
+ class SearchFiles
14
+ attr_reader :total_records
15
+
16
+ DISP_NUM = 100 # 1ページの表示数
17
+
18
+ def initialize(path, params, query)
19
+ @params = params
20
+ @q = query
21
+
22
+ @offset = params[:offset].to_i
23
+
24
+ fpaths = @q.fpaths
25
+ fpaths << path unless path == ""
26
+
27
+ if (fpaths.include?("*"))
28
+ @records, @total_records = Database.instance.selectAll(@offset, DISP_NUM)
29
+ else
30
+ @records, @total_records = Database.instance.search(@q.keywords, @q.packages, fpaths, @q.suffixs, @offset, DISP_NUM)
31
+ end
32
+ end
33
+
34
+ def query
35
+ @q.query_string
36
+ end
37
+
38
+ def next_offset
39
+ @offset + @records.size
40
+ end
41
+
42
+ def data_range
43
+ @offset..(next_offset - 1)
44
+ end
45
+
46
+ def html_contents
47
+ @records.map {|record| result_record(record)}.join
48
+ end
49
+
50
+ def html_pagination
51
+ return "" if @q.empty?
52
+ return "" if next_offset >= @total_records
53
+
54
+ return <<EOF
55
+ <div class='pagination'>
56
+ #{pagination_link(next_offset, "next >>")}
57
+ </div>
58
+ EOF
59
+ end
60
+
61
+ private
62
+
63
+ def pagination_link(offset, label)
64
+ tmpp = @params
65
+ tmpp[:offset] = offset.to_s
66
+ href = Mkurl.new("", tmpp).inherit_query_shead_offset
67
+ pagination_span("<a href='#{href}'>#{label}</a>")
68
+ end
69
+
70
+ def pagination_span(content)
71
+ "<span class='pagination-link'>#{content}</span>\n"
72
+ end
73
+
74
+ def result_record(record)
75
+ <<EOS
76
+ <dt class='result-file'>#{file_or_dirimg(true)}<a href='#{"/home/" + record_link(record)}'>#{record.shortpath}</a></dt>
77
+ EOS
78
+ end
79
+
80
+ def record_link(record)
81
+ Mkurl.new(record.shortpath, @params).inherit_query_shead
82
+ end
83
+
84
+ end
85
+ end
86
+
87
+
88
+
@@ -34,6 +34,10 @@ dt.result-record {
34
34
  font-size: 105%;
35
35
  }
36
36
 
37
+ dt.result-file {
38
+ font-size: 95%;
39
+ }
40
+
37
41
  div.pagination {
38
42
  background-color:#FEFFF0;
39
43
  text-align: center;
@@ -57,4 +61,15 @@ span.keyword {
57
61
 
58
62
  font.version {
59
63
  font-size: 35%;
60
- }
64
+ }
65
+
66
+ span.highlight-line {
67
+ background-color: #d0ff9c;
68
+ /* background-color: #FFFF55; */
69
+ }
70
+
71
+ a.headmenu {
72
+ font-size: 40%;
73
+ font-weight: normal;
74
+ }
75
+
@@ -0,0 +1,14 @@
1
+ .header
2
+ %h1
3
+ <a href="/"><img src="/images/gren-icon-mini.png" alt="gren-icon" border="0"/></a>
4
+ CodeStock
5
+ = create_headmenu(@path, params)
6
+
7
+ .content
8
+ = create_form(@path, params[:query], params[:shead])
9
+
10
+ .search-summary
11
+ <span class="keyword">#{topic_path(@path, params)}</span> <span class="total-entries">#{@total_records}</span>件(#{@elapsed}秒)
12
+ ~ @record_content
13
+
14
+
@@ -0,0 +1,16 @@
1
+ - @title = 'help'
2
+
3
+ .header
4
+ %h1
5
+ <a href="/"><img src="/images/gren-icon-mini.png" alt="gren-icon" border="0"/></a>
6
+ #{@title} - CodeStock
7
+
8
+ .content
9
+ .sample-code
10
+ %ol
11
+ %li キーワードで検索<br>#{link('def open')}
12
+ %li1フレーズとして検索<br>#{link('"def open"')}
13
+ %li パッケージ名で絞り込み<br>#{link('def open p:gren')}
14
+ %li ファイル名や拡張子で絞り込み<br>#{link('def open f:test s:rb')}
15
+ %li 組み合わせ<br>#{link('p:gren p:tidtools s:rb f:test assert f:cli')}
16
+
@@ -0,0 +1,17 @@
1
+ %div(align="center")
2
+ .header_home
3
+ %h1 <a href="/"><img src="/images/gren-icon.png" alt="gren-icon" border="0" height="100px"/></a> CodeStock <font class="version">#{@version}</font>
4
+
5
+ .content
6
+ %form(method="post" action="home")
7
+ %p
8
+ %input(name="query" type="text" size="60")
9
+ %input(type="submit" value="検索")
10
+
11
+ .footer_home
12
+ <a href="/home">#{@package_num}</a>のパッケージ<br>
13
+ <a href="/home?query=f:*">#{@file_num}</a>のファイル<br>
14
+ <a href="/help">ヘルプ</a> ,
15
+ <a href="http://codestock.ongaeshi.me">codestockについて</a>
16
+
17
+
@@ -0,0 +1,33 @@
1
+ !!!
2
+
3
+ %html(lang='ja')
4
+ %head
5
+ %meta(charset='utf-8')
6
+ %title= [@title, 'CodeStock'].compact.join(' - ')
7
+ %link(rel="stylesheet" href="/css/gren.css" type="text/css" media="all")
8
+ %link(rel="stylesheet" href="/css/coderay.css" type="text/css" media="all")
9
+
10
+ %body
11
+ -# %header
12
+ -# %h1 <a href=".">CodeStock</a>
13
+
14
+ != yield
15
+
16
+ %script{:type=>"text/javascript"}
17
+ var _gaq = _gaq || [];
18
+ _gaq.push(['_setAccount', 'UA-13136329-8']);
19
+ _gaq.push(['_trackPageview']);
20
+
21
+ (function() {
22
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
23
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
24
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
25
+ })();
26
+
27
+ -# %hr
28
+
29
+ -# %footer
30
+ -# %p
31
+ -# ! Develop by <a href="./contact.html">ongaeshi</a>
32
+ -# ! Powered by <a href="http://www.ruby-lang.org/">Ruby</a> #{::RUBY_VERSION},
33
+ -# ! <a href="http://www.sinatrarb.com/">Sinatra</a> #{Sinatra::VERSION}
@@ -0,0 +1,12 @@
1
+ .header
2
+ %h1
3
+ <a href="/"><img src="/images/gren-icon-mini.png" alt="gren-icon" border="0"/></a>
4
+ CodeStock
5
+ = create_headmenu(@path, params)
6
+
7
+ .content
8
+ = create_form(@path, params[:query], params[:shead])
9
+
10
+ .search-summary
11
+ <span class="keyword">#{topic_path(@path, params)}</span> <span class="total-entries">#{@total_records}</span>件中 <span class="display-range">#{@range.first} - #{@range.last}</span>件(#{@elapsed}秒)
12
+ ~ @record_content
@@ -0,0 +1,16 @@
1
+ .header
2
+ %h1
3
+ <a href="/"><img src="/images/gren-icon-mini.png" alt="gren-icon" border="0"/></a>
4
+ CodeStock
5
+ = create_headmenu(@path, params)
6
+
7
+ .content
8
+ = create_form(@path, params[:query], params[:shead])
9
+
10
+ .search-summary
11
+ <span class="keyword">#{topic_path(@path, params)}</span>(#{@elapsed}秒)
12
+ ~ @record_content
13
+
14
+
15
+
16
+
@@ -0,0 +1,41 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief ファイルテスト用アサート関数群
5
+ # @author ongaeshi
6
+ # @date 2011/06/22
7
+ #
8
+ # 以下の関数が使えます
9
+ #
10
+ # assert_diff_files(file1, file2)
11
+ #
12
+ # 二つのファイルが等しい場合はテスト成功
13
+ # 失敗した場合は二つのファイルのdiffを表示します
14
+ #
15
+ # assert_lines(s1, s2)
16
+ #
17
+ # 文字列を行単位で比較します。
18
+ #
19
+
20
+ def assert_diff_files(file1, file2)
21
+ unless (IO.read(file1) == IO.read(file2))
22
+ puts `diff -c #{file1} #{file2}`
23
+ assert_equal true, false
24
+ else
25
+ assert_equal true, true
26
+ end
27
+ end
28
+
29
+ def assert_lines(s1, s2)
30
+ a1 = s1.to_a
31
+ a2 = s2.to_a
32
+
33
+ a1.each_index do |i|
34
+ assert_equal a1[i], a2[i]
35
+ end
36
+
37
+ # s1の行数が長い時にエラーが出てしまう
38
+
39
+ assert_equal a1.size, a2.size
40
+ end
41
+
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief
5
+ # @author ongaeshi
6
+ # @date 2011/07/16
7
+
8
+ require 'test_helper'
9
+ require 'file_assert'
10
+ require 'test_coderay_wrapper_data'
11
+ require 'codestock/cdweb/lib/coderay_wrapper'
12
+
13
+ module CodeStock
14
+ class TestCodeRayWrapper < Test::Unit::TestCase
15
+ def test_basic
16
+ assert_lines JS_SHORT_HTML, CodeRayWrapper.new(JS_SHORT_CODE, "console-dir.js").to_html
17
+ assert_lines JS_HTML , CodeRayWrapper.new(JS_CODE, "console-dir.js").to_html
18
+ end
19
+ end
20
+ end
21
+
22
+
@@ -0,0 +1,91 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief
5
+ # @author ongaeshi
6
+ # @date 2011/07/16
7
+
8
+ module CodeStock
9
+ JS_SHORT_CODE = <<EOF
10
+ console.dir_s = function (object, msg) {
11
+ var disp_properties = function (properties, indent, out) {
12
+ EOF
13
+
14
+ JS_SHORT_HTML = <<EOF
15
+ <table class="CodeRay"><tr>
16
+ <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
17
+ </tt>2<tt>
18
+ </tt></pre></td>
19
+ <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span id="1">console.<span class="fu">dir_s</span> = <span class="kw">function</span> (object, msg) {</span><tt>
20
+ </tt><span id="2"> <span class="kw">var</span> <span class="fu">disp_properties</span> = <span class="kw">function</span> (properties, indent, out) {</span><tt>
21
+ </tt></pre></td>
22
+ </tr></table>
23
+ EOF
24
+
25
+ JS_CODE = <<EOF
26
+ console.dir_s = function (object, msg) {
27
+ var disp_properties = function (properties, indent, out) {
28
+ for (var i = 0; i < properties.length; ++i) {
29
+ var name = properties[i][0], value = properties[i][1];
30
+
31
+ if (typeof value == "string")
32
+ value = '"' + value + '"';
33
+
34
+ out.push(indent + name + ": " + value);
35
+ }
36
+ };
37
+
38
+ var disp_funcs = function (funcs, indent, out) {
39
+ for (var i = 0; i < funcs.length; ++i) {
40
+ var name = funcs[i][0], value = funcs[i][1];
41
+ out.push(indent + name + "()");
42
+ }
43
+ };
44
+ EOF
45
+
46
+ JS_HTML = <<EOF
47
+ <table class="CodeRay"><tr>
48
+ <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
49
+ </tt>2<tt>
50
+ </tt>3<tt>
51
+ </tt>4<tt>
52
+ </tt>5<tt>
53
+ </tt>6<tt>
54
+ </tt>7<tt>
55
+ </tt>8<tt>
56
+ </tt>9<tt>
57
+ </tt>10<tt>
58
+ </tt>11<tt>
59
+ </tt>12<tt>
60
+ </tt>13<tt>
61
+ </tt>14<tt>
62
+ </tt>15<tt>
63
+ </tt>16<tt>
64
+ </tt>17<tt>
65
+ </tt>18<tt>
66
+ </tt></pre></td>
67
+ <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span id="1">console.<span class="fu">dir_s</span> = <span class="kw">function</span> (object, msg) {</span><tt>
68
+ </tt><span id="2"> <span class="kw">var</span> <span class="fu">disp_properties</span> = <span class="kw">function</span> (properties, indent, out) {</span><tt>
69
+ </tt><span id="3"> <span class="kw">for</span> (<span class="kw">var</span> i = <span class="i">0</span>; i &lt; properties.length; ++i) {</span><tt>
70
+ </tt><span id="4"> <span class="kw">var</span> name = properties[i][<span class="i">0</span>], value = properties[i][<span class="i">1</span>];</span><tt>
71
+ </tt><span id="5"></span><tt>
72
+ </tt><span id="6"> <span class="kw">if</span> (<span class="kw">typeof</span> value == <span class="s"><span class="dl">&quot;</span><span class="k">string</span><span class="dl">&quot;</span></span>)</span><tt>
73
+ </tt><span id="7"> value = <span class="s"><span class="dl">'</span><span class="k">&quot;</span><span class="dl">'</span></span> + value + <span class="s"><span class="dl">'</span><span class="k">&quot;</span><span class="dl">'</span></span>;</span><tt>
74
+ </tt><span id="8"></span><tt>
75
+ </tt><span id="9"> out.push(indent + name + <span class="s"><span class="dl">&quot;</span><span class="k">: </span><span class="dl">&quot;</span></span> + value);</span><tt>
76
+ </tt><span id="10"> }</span><tt>
77
+ </tt><span id="11"> };</span><tt>
78
+ </tt><span id="12"> </span><tt>
79
+ </tt><span id="13"> <span class="kw">var</span> <span class="fu">disp_funcs</span> = <span class="kw">function</span> (funcs, indent, out) {</span><tt>
80
+ </tt><span id="14"> <span class="kw">for</span> (<span class="kw">var</span> i = <span class="i">0</span>; i &lt; funcs.length; ++i) {</span><tt>
81
+ </tt><span id="15"> <span class="kw">var</span> name = funcs[i][<span class="i">0</span>], value = funcs[i][<span class="i">1</span>];</span><tt>
82
+ </tt><span id="16"> out.push(indent + name + <span class="s"><span class="dl">&quot;</span><span class="k">()</span><span class="dl">&quot;</span></span>);</span><tt>
83
+ </tt><span id="17"> }</span><tt>
84
+ </tt><span id="18"> };</span><tt>
85
+ </tt></pre></td>
86
+ </tr></table>
87
+ EOF
88
+
89
+ end
90
+
91
+