codnar 0.1.64

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/ChangeLog +165 -0
  2. data/LICENSE +19 -0
  3. data/README.rdoc +32 -0
  4. data/Rakefile +66 -0
  5. data/bin/codnar-split +5 -0
  6. data/bin/codnar-weave +5 -0
  7. data/codnar.html +10945 -0
  8. data/doc/logo.png +0 -0
  9. data/doc/root.html +22 -0
  10. data/doc/story.markdown +180 -0
  11. data/doc/system.markdown +671 -0
  12. data/lib/codnar.rb +41 -0
  13. data/lib/codnar/application.rb +92 -0
  14. data/lib/codnar/cache.rb +61 -0
  15. data/lib/codnar/data/contents.js +113 -0
  16. data/lib/codnar/data/control_chunks.js +44 -0
  17. data/lib/codnar/data/style.css +95 -0
  18. data/lib/codnar/data/sunlight/README.txt +4 -0
  19. data/lib/codnar/data/sunlight/css-min.js +1 -0
  20. data/lib/codnar/data/sunlight/default.css +236 -0
  21. data/lib/codnar/data/sunlight/javascript-min.js +1 -0
  22. data/lib/codnar/data/sunlight/min.js +1 -0
  23. data/lib/codnar/data/sunlight/ruby-min.js +1 -0
  24. data/lib/codnar/data/yui/README.txt +3 -0
  25. data/lib/codnar/data/yui/base.css +132 -0
  26. data/lib/codnar/data/yui/reset.css +142 -0
  27. data/lib/codnar/formatter.rb +180 -0
  28. data/lib/codnar/grouper.rb +28 -0
  29. data/lib/codnar/gvim.rb +132 -0
  30. data/lib/codnar/hash_extensions.rb +41 -0
  31. data/lib/codnar/markdown.rb +47 -0
  32. data/lib/codnar/merger.rb +138 -0
  33. data/lib/codnar/rake.rb +41 -0
  34. data/lib/codnar/rake/split_task.rb +71 -0
  35. data/lib/codnar/rake/weave_task.rb +59 -0
  36. data/lib/codnar/rdoc.rb +9 -0
  37. data/lib/codnar/reader.rb +121 -0
  38. data/lib/codnar/scanner.rb +216 -0
  39. data/lib/codnar/split.rb +58 -0
  40. data/lib/codnar/split_configurations.rb +367 -0
  41. data/lib/codnar/splitter.rb +32 -0
  42. data/lib/codnar/string_extensions.rb +25 -0
  43. data/lib/codnar/sunlight.rb +17 -0
  44. data/lib/codnar/version.rb +8 -0
  45. data/lib/codnar/weave.rb +58 -0
  46. data/lib/codnar/weave_configurations.rb +48 -0
  47. data/lib/codnar/weaver.rb +105 -0
  48. data/lib/codnar/writer.rb +38 -0
  49. data/test/cache_computations.rb +41 -0
  50. data/test/deep_merge.rb +29 -0
  51. data/test/embed_images.rb +12 -0
  52. data/test/expand_markdown.rb +27 -0
  53. data/test/expand_rdoc.rb +20 -0
  54. data/test/format_code_gvim_configurations.rb +55 -0
  55. data/test/format_code_sunlight_configurations.rb +37 -0
  56. data/test/format_comment_configurations.rb +86 -0
  57. data/test/format_lines.rb +72 -0
  58. data/test/group_lines.rb +31 -0
  59. data/test/gvim_highlight_syntax.rb +49 -0
  60. data/test/identify_chunks.rb +32 -0
  61. data/test/lib/test_with_configurations.rb +15 -0
  62. data/test/merge_lines.rb +133 -0
  63. data/test/rake_tasks.rb +38 -0
  64. data/test/read_chunks.rb +110 -0
  65. data/test/run_application.rb +56 -0
  66. data/test/run_split.rb +38 -0
  67. data/test/run_weave.rb +75 -0
  68. data/test/scan_lines.rb +78 -0
  69. data/test/split_chunk_configurations.rb +55 -0
  70. data/test/split_code.rb +109 -0
  71. data/test/split_code_configurations.rb +73 -0
  72. data/test/split_combined_configurations.rb +114 -0
  73. data/test/split_complex_comment_configurations.rb +73 -0
  74. data/test/split_documentation.rb +92 -0
  75. data/test/split_documentation_configurations.rb +97 -0
  76. data/test/split_simple_comment_configurations.rb +50 -0
  77. data/test/sunlight_highlight_syntax.rb +25 -0
  78. data/test/weave_configurations.rb +144 -0
  79. data/test/write_chunks.rb +28 -0
  80. metadata +363 -0
@@ -0,0 +1,109 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+
5
+ # Test splitting code files.
6
+ class TestSplitCode < Test::Unit::TestCase
7
+
8
+ include Test::WithErrors
9
+ include Test::WithTempfile
10
+
11
+ def test_split_ruby
12
+ splitter = Codnar::Splitter.new(@errors, RUBY_CONFIGURATION)
13
+ path = write_tempfile("ruby.rb", RUBY_FILE)
14
+ chunks = splitter.chunks(path)
15
+ @errors.should == []
16
+ chunks.should == ruby_chunks(path)
17
+ end
18
+
19
+ protected
20
+
21
+ def ruby_chunks(path)
22
+ RUBY_CHUNKS[0].name = path
23
+ RUBY_CHUNKS[1].containers[0] = path
24
+ RUBY_CHUNKS.each { |chunk| chunk.locations[0].file = path }
25
+ return RUBY_CHUNKS
26
+ end
27
+
28
+ RUBY_FILE = <<-EOF.unindent.gsub("#!", "#")
29
+ #! This is *rdoc*.
30
+ #! {{{ assignment
31
+ local = $global
32
+ indented
33
+ #! }}}
34
+ EOF
35
+
36
+ RUBY_CONFIGURATION = {
37
+ "formatters" => {
38
+ "code" => "Formatter.cast_lines(lines, 'ruby')",
39
+ "comment" => "Formatter.cast_lines(lines, 'rdoc')",
40
+ "ruby" => "GVim.lines_to_html(lines, 'ruby')",
41
+ "rdoc" => "Formatter.markup_lines_to_html(lines, 'RDoc')",
42
+ "begin_chunk" => "[]",
43
+ "end_chunk" => "[]",
44
+ "nested_chunk" => "Formatter.nested_chunk_lines_to_html(lines)",
45
+ "unindented_html" => "Formatter.unindented_lines_to_html(lines)",
46
+ },
47
+ "syntax" => {
48
+ "start_state" => "ruby",
49
+ "patterns" => {
50
+ "comment" => { "regexp" => "^(\\s*)#\\s*(.*)$" },
51
+ "code" => { "regexp" => "^(\\s*)(.*)$" },
52
+ "begin_chunk" => { "regexp" => "^(\\s*)\\W*\\{\\{\\{\\s*(.*?)\\s*$" },
53
+ "end_chunk" => { "regexp" => "^(\\s*)\\W*\\}\\}\\}\\s*(.*?)\\s*$" },
54
+ },
55
+ "states" => {
56
+ "ruby" => {
57
+ "transitions" => [
58
+ { "pattern" => "begin_chunk" },
59
+ { "pattern" => "end_chunk" },
60
+ { "pattern" => "comment" },
61
+ { "pattern" => "code" },
62
+ ],
63
+ },
64
+ },
65
+ },
66
+ }
67
+
68
+ RUBY_CHUNKS = [ {
69
+ "name" => "PATH",
70
+ "locations" => [ "file" => "PATH", "line" => 1 ],
71
+ "containers" => [],
72
+ "contained" => [ "assignment" ],
73
+ "html" => <<-EOF.unindent.chomp, #! ((( html
74
+ <table class='layout'>
75
+ <tr>
76
+ <td class='indentation'>
77
+ <pre></pre>
78
+ </td>
79
+ <td class='html'>
80
+ <div class='rdoc rdoc markup'>
81
+ <p>
82
+ This is <b>rdoc</b>.
83
+ </p>
84
+ </div>
85
+ </td>
86
+ </tr>
87
+ </table>
88
+ <pre class='nested chunk'>
89
+ <a class='nested chunk' href='#assignment'>assignment</a>
90
+ </pre>
91
+ EOF
92
+ #! ))) html
93
+ }, {
94
+ "name" => "assignment",
95
+ "containers" => [ "PATH" ],
96
+ "contained" => [],
97
+ "locations" => [ "file" => "PATH", "line" => 2 ],
98
+ "html" => <<-EOF.unindent.chomp, #! ((( html
99
+ <div class='ruby code syntax' bgcolor="#ffffff" text="#000000">
100
+ <font face="monospace">
101
+ local =&nbsp;<font color="#00ffff">$global</font><br />
102
+ &nbsp;&nbsp;indented<br />
103
+ </font>
104
+ </div>
105
+ EOF
106
+ #! ))) html
107
+ } ]
108
+
109
+ end
@@ -0,0 +1,73 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+ require "test_with_configurations"
5
+
6
+ # Test combinations of the built-in split code configurations.
7
+ class TestSplitCodeConfigurations < Test::Unit::TestCase
8
+
9
+ include Test::WithConfigurations
10
+ include Test::WithErrors
11
+ include Test::WithTempfile
12
+
13
+ SOURCE_CODE = <<-EOF.unindent
14
+ a = b
15
+ b = 1
16
+ EOF
17
+
18
+ def test_source_code
19
+ check_split_file(SOURCE_CODE, Codnar::Configuration::CLASSIFY_SOURCE_CODE.call("ruby")) do |path|
20
+ [ {
21
+ "name" => path,
22
+ "locations" => [ { "file" => path, "line" => 1 } ],
23
+ "containers" => [],
24
+ "contained" => [],
25
+ "html" => "<pre class='code'>\n#{SOURCE_CODE}</pre>"
26
+ } ]
27
+ end
28
+ end
29
+
30
+ ISLAND_CODE = <<-EOF.unindent
31
+ a = b
32
+ b = 1
33
+ HTML = <<-EOH.unindent # ((( html
34
+ <p>
35
+ HTML
36
+ </p>
37
+ EOH
38
+ # ))) html
39
+ EOF
40
+
41
+ ISLAND_HTML = <<-EOF.unindent.chomp
42
+ <pre class='ruby code syntax'>
43
+ a = b
44
+ b = <span class="Constant">1</span>
45
+ <span class="Type">HTML</span> = &lt;&lt;-<span class="Special">EOH</span>.unindent <span class="Comment"># ((( html</span>
46
+ </pre>
47
+ <pre class='html code syntax'>
48
+ <span class="Identifier">&lt;</span><span class="Statement">p</span><span class="Identifier">&gt;</span>
49
+ HTML
50
+ <span class="Identifier">&lt;/</span><span class="Statement">p</span><span class="Identifier">&gt;</span>
51
+ EOH
52
+ </pre>
53
+ <pre class='ruby code syntax'>
54
+ <span class="Comment"># ))) html</span>
55
+ </pre>
56
+ EOF
57
+
58
+ def test_island_code
59
+ check_split_file(ISLAND_CODE, Codnar::Configuration::CLASSIFY_SOURCE_CODE.call("ruby"),
60
+ Codnar::Configuration::FORMAT_CODE_GVIM_CSS.call("ruby"),
61
+ Codnar::Configuration::CLASSIFY_NESTED_CODE.call("ruby", "html"),
62
+ Codnar::Configuration::FORMAT_CODE_GVIM_CSS.call("html")) do |path|
63
+ [ {
64
+ "name" => path,
65
+ "locations" => [ { "file" => path, "line" => 1 } ],
66
+ "containers" => [],
67
+ "contained" => [],
68
+ "html" => ISLAND_HTML
69
+ } ]
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,114 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+ require "test_with_configurations"
5
+
6
+ # Test combination of many built-in configurations.
7
+ class TestSplitCombinedConfigurations < Test::Unit::TestCase
8
+
9
+ include Test::WithConfigurations
10
+ include Test::WithErrors
11
+ include Test::WithTempfile
12
+
13
+ CODE_TEXT = <<-EOF.unindent.gsub("#!", "#")
14
+ #!!/usr/bin/ruby -w
15
+
16
+ #! {{{ HTML snippet
17
+
18
+ HELLO_WORLD_IN_HTML = <<-EOH.unindent.chomp #! ((( html
19
+ <p>
20
+ Hello, world!
21
+ </p>
22
+ EOH
23
+ #! ))) html
24
+
25
+ #! }}}
26
+
27
+ #! {{{ Ruby code
28
+
29
+ #! Hello, *world*!
30
+ puts HELLO_WORLD_IN_HTML
31
+
32
+ #! }}}
33
+ EOF
34
+
35
+ FILE_HTML = <<-EOF.unindent.chomp
36
+ <pre class='ruby code syntax'>
37
+ <span class="PreProc">#!/usr/bin/ruby -w</span>
38
+
39
+ </pre>
40
+ <pre class='nested chunk'>
41
+ <a class='nested chunk' href='#html-snippet'>HTML snippet</a>
42
+ </pre>
43
+ <pre class='ruby code syntax'>
44
+
45
+ </pre>
46
+ <pre class='nested chunk'>
47
+ <a class='nested chunk' href='#ruby-code'>Ruby code</a>
48
+ </pre>
49
+ EOF
50
+
51
+ HTML_CHUNK = <<-EOF.unindent.chomp
52
+ <pre class='ruby code syntax'>
53
+
54
+ <span class="Type">HELLO_WORLD_IN_HTML</span> = &lt;&lt;-<span class="Special">EOH</span>.unindent.chomp <span class="Comment"># ((( html</span>
55
+ </pre>
56
+ <pre class='html code syntax'>
57
+ <span class="Identifier">&lt;</span><span class="Statement">p</span><span class="Identifier">&gt;</span>
58
+ Hello, world!
59
+ <span class="Identifier">&lt;/</span><span class="Statement">p</span><span class="Identifier">&gt;</span>
60
+ EOH
61
+ </pre>
62
+ <pre class='ruby code syntax'>
63
+ <span class="Comment"># ))) html</span>
64
+
65
+ </pre>
66
+ EOF
67
+
68
+ RUBY_CHUNK = <<-EOF.unindent.chomp
69
+ <pre class='ruby code syntax'>
70
+
71
+ </pre>
72
+ <table class='layout'>
73
+ <tr>
74
+ <td class='indentation'>
75
+ <pre></pre>
76
+ </td>
77
+ <td class='html'>
78
+ <div class='rdoc comment markup'>
79
+ <p>
80
+ Hello, <b>world</b>!
81
+ </p>
82
+ </div>
83
+ </td>
84
+ </tr>
85
+ </table>
86
+ <pre class='ruby code syntax'>
87
+ puts <span class="Type">HELLO_WORLD_IN_HTML</span>
88
+
89
+ </pre>
90
+ EOF
91
+
92
+ def test_gvim_chunks
93
+ check_split_file(CODE_TEXT,
94
+ Codnar::Configuration::CLASSIFY_SOURCE_CODE.call("ruby"),
95
+ Codnar::Configuration::FORMAT_CODE_GVIM_CSS.call("ruby"),
96
+ Codnar::Configuration::CLASSIFY_NESTED_CODE.call("ruby", "html"),
97
+ Codnar::Configuration::FORMAT_CODE_GVIM_CSS.call("html"),
98
+ Codnar::Configuration::CLASSIFY_SHELL_COMMENTS.call,
99
+ Codnar::Configuration::FORMAT_RDOC_COMMENTS,
100
+ Codnar::Configuration::CHUNK_BY_VIM_REGIONS) do |path|
101
+ [ {
102
+ "name" => path, "html" => FILE_HTML,
103
+ "locations" => [ { "line" => 1, "file" => path } ], "containers" => [], "contained" => [ "HTML snippet", "Ruby code" ],
104
+ }, {
105
+ "name" => "HTML snippet", "html" => HTML_CHUNK,
106
+ "locations" => [ { "line" => 3, "file" => path } ], "containers" => [ path ], "contained" => [],
107
+ }, {
108
+ "name" => "Ruby code", "html" => RUBY_CHUNK,
109
+ "locations" => [ { "line" => 14, "file" => path } ], "containers" => [ path ], "contained" => [],
110
+ } ]
111
+ end
112
+ end
113
+
114
+ end
@@ -0,0 +1,73 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+ require "test_with_configurations"
5
+
6
+ # Test built-in split complex comment configurations.
7
+ class TestSplitComplexCommentsConfigurations < Test::Unit::TestCase
8
+
9
+ include Test::WithConfigurations
10
+ include Test::WithErrors
11
+ include Test::WithTempfile
12
+
13
+ def test_custom_comments
14
+ # Since the prefix/inner/suffix passed to the configuration are regexps,
15
+ # we need to escape special characters such as "{" and "|".
16
+ check_any_comment([ "@{", " |", " }@" ], Codnar::Configuration::CLASSIFY_COMPLEX_COMMENTS.call("@\\{", " \\|", " \\}@"))
17
+ end
18
+
19
+ def test_c_comments
20
+ check_any_comment([ "/*", " *", " */" ], Codnar::Configuration::CLASSIFY_C_COMMENTS.call)
21
+ end
22
+
23
+ def test_html_comments
24
+ check_any_comment([ "<!--", " -", "-->" ], Codnar::Configuration::CLASSIFY_HTML_COMMENTS.call)
25
+ end
26
+
27
+ protected
28
+
29
+ # The "<<<" will be replaced by the complex comment prefix,
30
+ # the "<>" will be replaced by the inner line comment prefix,
31
+ # and the ">>>" will be replaced by the complex comment suffix.
32
+ ANY_COMMENT_CODE = <<-EOF.unindent
33
+ /-- One-line comment --/
34
+ Code
35
+ /--
36
+ - Multi-line
37
+ - comment.
38
+ --/
39
+ EOF
40
+
41
+ ANY_COMMENT_HTML = <<-EOF.unindent.chomp # ((( html
42
+ <pre class='comment'>
43
+ One-line comment
44
+ </pre>
45
+ <pre class='code'>
46
+ Code
47
+ </pre>
48
+ <pre class='comment'>
49
+
50
+ Multi-line
51
+ comment.
52
+
53
+ </pre>
54
+ EOF
55
+ # )))
56
+
57
+ def check_any_comment(patterns, configuration)
58
+ prefix, inner, suffix = patterns
59
+ check_split_file(ANY_COMMENT_CODE.gsub("/--", prefix).gsub("--/", suffix).gsub(" -", inner),
60
+ Codnar::Configuration::CLASSIFY_SOURCE_CODE.call("any"),
61
+ Codnar::Configuration::FORMAT_PRE_COMMENTS,
62
+ configuration) do |path|
63
+ [ {
64
+ "name" => path,
65
+ "locations" => [ { "file" => path, "line" => 1 } ],
66
+ "containers" => [],
67
+ "contained" => [],
68
+ "html" => ANY_COMMENT_HTML.gsub("/--", prefix).gsub("--/", suffix).gsub(" -", inner),
69
+ } ]
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,92 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+
5
+ # Test "splitting" documentation files.
6
+ class TestSplitDocumentation < Test::Unit::TestCase
7
+
8
+ include Test::WithErrors
9
+ include Test::WithFakeFS
10
+
11
+ def test_split_raw
12
+ File.open("raw.html", "w") { |file| file.write("<foo>\nbar\n</foo>\n") }
13
+ splitter = Codnar::Splitter.new(@errors, configuration("html"))
14
+ chunks = splitter.chunks("raw.html")
15
+ @errors.should == []
16
+ chunks.should == [ {
17
+ "name" => "raw.html",
18
+ "containers" => [],
19
+ "contained" => [],
20
+ "locations" => [ { "file" => "raw.html", "line" => 1 } ],
21
+ "html" => "<foo>\nbar\n</foo>"
22
+ } ]
23
+ end
24
+
25
+ def test_split_markdown
26
+ File.open("markdown.md", "w") { |file| file.write("*foo*\nbar\n") }
27
+ splitter = Codnar::Splitter.new(@errors, configuration("markdown"))
28
+ chunks = splitter.chunks("markdown.md")
29
+ @errors.should == []
30
+ chunks.should == [ {
31
+ "name" => "markdown.md",
32
+ "containers" => [],
33
+ "contained" => [],
34
+ "locations" => [ { "file" => "markdown.md", "line" => 1 } ],
35
+ "html" => "<div class='markdown markdown markup'>\n<p>\n<em>foo</em>\nbar\n</p>\n</div>"
36
+ } ]
37
+ end
38
+
39
+ def test_split_rdoc
40
+ File.open("rdoc.rdoc", "w") { |file| file.write("*foo*\nbar\n") }
41
+ splitter = Codnar::Splitter.new(@errors, configuration("rdoc"))
42
+ chunks = splitter.chunks("rdoc.rdoc")
43
+ @errors.should == []
44
+ chunks.should == [ {
45
+ "name" => "rdoc.rdoc",
46
+ "containers" => [],
47
+ "contained" => [],
48
+ "locations" => [ { "file" => "rdoc.rdoc", "line" => 1 } ],
49
+ "html" => "<div class='rdoc rdoc markup'>\n<p>\n<b>foo</b> bar\n</p>\n</div>"
50
+ } ]
51
+ end
52
+
53
+ def test_split_unknown_kind
54
+ File.open("unknown.kind", "w") { |file| file.write("foo\nbar\n") }
55
+ splitter = Codnar::Splitter.new(@errors, configuration("unknown-kind"))
56
+ chunks = splitter.chunks("unknown.kind")
57
+ @errors.should == [ "#{$0}: No formatter specified for lines of kind: unknown-kind" ]
58
+ chunks.should == [ {
59
+ "name" => "unknown.kind",
60
+ "containers" => [],
61
+ "contained" => [],
62
+ "locations" => [ { "file" => "unknown.kind", "line" => 1 } ],
63
+ "html" => "<pre class='missing formatter error'>\nfoo\nbar\n</pre>"
64
+ } ]
65
+ end
66
+
67
+ protected
68
+
69
+ def configuration(kind)
70
+ return {
71
+ "formatters" => {
72
+ "markdown" => "Formatter.markup_lines_to_html(lines, 'Markdown')",
73
+ "unindented_html" => "Formatter.unindented_lines_to_html(lines)",
74
+ "rdoc" => "Formatter.markup_lines_to_html(lines, 'RDoc')",
75
+ },
76
+ "syntax" => {
77
+ "start_state" => kind,
78
+ "patterns" => {
79
+ kind => { "regexp" => "^(.*)$", "groups" => [ "payload" ] },
80
+ },
81
+ "states" => {
82
+ kind => {
83
+ "transitions" => [
84
+ { "pattern" => kind }
85
+ ]
86
+ }
87
+ }
88
+ }
89
+ }
90
+ end
91
+
92
+ end