codnar 0.1.64

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 (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