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,38 @@
1
+ require "codnar/rake"
2
+ require "olag/test"
3
+ require "test/spec"
4
+
5
+ # Test rake tasks.
6
+ class TestRakeTasks < Test::Unit::TestCase
7
+
8
+ include Test::WithFakeFS
9
+ include Test::WithRake
10
+
11
+ def test_default
12
+ run_rake
13
+ test_results
14
+ end
15
+
16
+ protected
17
+
18
+ def run_rake
19
+ File.open("foo", "w") { |file| file.puts("foo") }
20
+ Codnar::Rake::SplitTask.new([ "foo" ], [])
21
+ Codnar::Rake::WeaveTask.new("foo", [])
22
+ @rake["codnar"].invoke
23
+ end
24
+
25
+ def test_results
26
+ chunk_file = Codnar::Rake.chunks_dir + "/foo"
27
+ YAML.load_file(chunk_file).should == [ {
28
+ "html" => "foo",
29
+ "name" => "foo",
30
+ "locations" => [ { "file" => "foo", "line" => 1 } ],
31
+ "containers" => [],
32
+ "contained" => [],
33
+ } ]
34
+ File.read("codnar.html").should == "foo\n"
35
+ Codnar::Rake.chunk_files.should == [ chunk_file ]
36
+ end
37
+
38
+ end
@@ -0,0 +1,110 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+
5
+ # Test reading chunks from files.
6
+ class TestReadChunks < Test::Unit::TestCase
7
+
8
+ include Test::WithErrors
9
+ include Test::WithFakeFS
10
+
11
+ def test_read_chunks
12
+ Codnar::Writer.write("foo.chunks", { "name" => "foo" })
13
+ Codnar::Writer.write("bar.chunks", [ { "name" => "bar" }, { "name" => "baz" } ])
14
+ reader = Codnar::Reader.new(@errors, Dir.glob("./**/*.chunks"))
15
+ check_read_data(reader, "foo" => { "name" => "foo" },
16
+ "bar" => { "name" => "bar" },
17
+ "baz" => { "name" => "baz" })
18
+ @errors.should == []
19
+ end
20
+
21
+ def test_read_invalid_chunks
22
+ file_path = nil
23
+ File.open("foo.chunks", "w") { |file| file_path = File.expand_path(file.path) }
24
+ reader = Codnar::Reader.new(@errors, Dir.glob("./**/*.chunks"))
25
+ @errors.should == [ "#{$0}: Invalid chunks data in file: #{file_path}" ]
26
+ end
27
+
28
+ def test_read_unused_chunks
29
+ Codnar::Writer.write("foo.chunks", { "name" => "foo",
30
+ "locations" => [ { "file" => "a", "line" => 1 } ] })
31
+ Codnar::Writer.write("bar.chunks", { "name" => "bar",
32
+ "locations" => [ { "file" => "b", "line" => 2 } ] })
33
+ reader = Codnar::Reader.new(@errors, Dir.glob("./**/*.chunks"))
34
+ check_read_data(reader, "foo" => { "name" => "foo",
35
+ "locations" => [ { "file" => "a", "line" => 1 } ] })
36
+ @errors.should == [ "#{$0}: Unused chunk: bar in file: b at line: 2" ]
37
+ end
38
+
39
+ def test_read_duplicate_chunks
40
+ Codnar::Writer.write("foo.chunks", { "name" => "foo", "locations" => [ { "file" => "a" } ],
41
+ "contained" => [ "A" ], "containers" => [ "c" ] })
42
+ Codnar::Writer.write("bar.chunks", [
43
+ { "name" => "foo", "locations" => [ { "file" => "b" } ],
44
+ "contained" => [ "a" ], "containers" => [ "d" ] },
45
+ { "name" => "foo", "locations" => [ { "file" => "c" } ],
46
+ "contained" => [ "a" ], "containers" => [] }
47
+ ])
48
+ reader = Codnar::Reader.new(@errors, Dir.glob("./**/*.chunks"))
49
+ check_read_data(reader, "foo" => {
50
+ "name" => "foo",
51
+ "locations" => [ { "file" => "a" }, { "file" => "b" }, { "file" => "c" } ],
52
+ "contained" => [ "a" ],
53
+ "containers" => [ "c", "d" ],
54
+ })
55
+ end
56
+
57
+ def test_read_different_chunks
58
+ Codnar::Writer.write("foo.chunks", [
59
+ { "name" => "foo", "html" => "bar", "locations" => [ { "file" => "foo.chunks", "line" => 1 } ],
60
+ "contained" => [ "a" ], "containers" => [] },
61
+ { "name" => "foo", "html" => "baz", "locations" => [ { "file" => "foo.chunks", "line" => 2 } ],
62
+ "contained" => [ "A" ], "containers" => [] }
63
+ ])
64
+ Codnar::Writer.write("bar.chunks", [ { "name" => "foo", "html" => "bar",
65
+ "locations" => [ { "file" => "bar.chunks", "line" => 1 } ],
66
+ "contained" => [ "a" ], "containers" => [] } ])
67
+ reader = Codnar::Reader.new(@errors, Dir.glob("./**/*.chunks").sort)
68
+ @errors.should == [ "#{$0}: Chunk: foo is different in file: foo.chunks at line: 2, " \
69
+ + "and in file: bar.chunks at line: 1 or in file: foo.chunks at line: 1" ]
70
+ check_read_data(reader, "foo" => {
71
+ "name" => "foo",
72
+ "html" => "bar",
73
+ "locations" => [ { "file" => "bar.chunks", "line" => 1 }, { "file" => "foo.chunks", "line" => 1 } ],
74
+ "contained" => [ "a" ],
75
+ "containers" => [],
76
+ })
77
+ end
78
+
79
+ def test_read_fake_chunk
80
+ reader = Codnar::Reader.new(@errors, [])
81
+ reader["foo"].should == Codnar::Reader.fake_chunk("foo")
82
+ @errors.should == [ "#{$0}: Missing chunk: foo" ]
83
+ end
84
+
85
+ def test_read_equivalent_name_chunks
86
+ Codnar::Writer.write("foo.chunks", [
87
+ { "name" => "Foo?", "locations" => [ { "file" => "foo.chunks", "line" => 1 } ],
88
+ "containers" => [ "1" ], "contained" => [ "c" ] },
89
+ { "name" => "FOO!!", "locations" => [ { "file" => "foo.chunks", "line" => 2 } ],
90
+ "containers" => [ "2" ], "contained" => [ "C" ] }
91
+ ])
92
+ reader = Codnar::Reader.new(@errors, Dir.glob("./**/*.chunks"))
93
+ check_read_data(reader, "foo-" => {
94
+ "name" => "Foo?",
95
+ "locations" => [ { "file" => "foo.chunks", "line" => 1 }, { "file" => "foo.chunks", "line" => 2 } ],
96
+ "containers" => [ "1", "2" ],
97
+ "contained" => [ "c" ],
98
+ })
99
+ end
100
+
101
+ protected
102
+
103
+ def check_read_data(reader, chunks)
104
+ chunks.each do |name, chunk|
105
+ reader[name].should == chunk
106
+ end
107
+ reader.collect_unused_chunk_errors
108
+ end
109
+
110
+ end
@@ -0,0 +1,56 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+
5
+ module Codnar
6
+
7
+ # Test running a Codnar Application.
8
+ class TestRunApplication < Test::Unit::TestCase
9
+
10
+ include Test::WithFakeFS
11
+ include Test::WithTempfile
12
+
13
+ def test_print_version
14
+ Codnar::Application.with_argv(%w(-o nested/stdout -v -h dummy)) { Codnar::Application.new(true).run }.should == 0
15
+ File.read("nested/stdout").should == "#{$0}: Version: #{Codnar::VERSION}\n"
16
+ end
17
+
18
+ def test_print_help
19
+ Codnar::Application.with_argv(%w(-o stdout -h -v dummy)) { Codnar::Application.new(true).run }.should == 0
20
+ File.read("stdout").should.include?("OPTIONS")
21
+ end
22
+
23
+ USER_CONFIGURATION = {
24
+ "formatters" => {
25
+ "doc" => "Formatter.lines_to_pre_html(lines, :class => :pre)",
26
+ }
27
+ }
28
+
29
+ def test_merge_configurations
30
+ File.open("user_configuration.yaml", "w") { |file| file.print(USER_CONFIGURATION.to_yaml) }
31
+ Codnar::Application.with_argv(%w(-o stdout -c split_pre_documentation -c user_configuration.yaml -p)) { Codnar::Application.new(true).run }.should == 0
32
+ YAML.load_file("stdout").should == Codnar::Configuration::SPLIT_PRE_DOCUMENTATION.deep_merge(USER_CONFIGURATION)
33
+ end
34
+
35
+ def test_require_missing_configuration
36
+ status = Application.with_argv(%w(-e stderr -c no-such-configuration)) { Codnar::Application.new(true).run }.should == 1
37
+ File.read("stderr").should \
38
+ == "#{$0}: Configuration: no-such-configuration is neither a disk file nor a known configuration\n"
39
+ end
40
+
41
+ def test_require_module
42
+ FakeFS.deactivate! # The additional_module is read by Ruby and is not affected by FakeFS.
43
+ directory = create_tempdir
44
+ File.open(directory + "/additional_module.rb", "w") { |file| file.puts("puts 'HERE'") }
45
+ Application.with_argv(["-o", stdout = directory + "/stdout", "-I", directory, "-r", "additional_module" ]) { Codnar::Application.new(true).run }.should == 0
46
+ File.read(stdout).should == "HERE\n"
47
+ end
48
+
49
+ def test_require_missing_module
50
+ Application.with_argv(%w(-e stderr -I support -r no_such_module)) { Codnar::Application.new(true).run }.should == 1
51
+ File.read("stderr").should == "#{$0}: no such file to load -- no_such_module\n"
52
+ end
53
+
54
+ end
55
+
56
+ end
@@ -0,0 +1,38 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+
5
+ # Test running the Split Codnar Application.
6
+ class TestRunSplit < Test::Unit::TestCase
7
+
8
+ include Test::WithFakeFS
9
+
10
+ def test_print_help
11
+ Codnar::Application.with_argv(%w(-o stdout -h)) { Codnar::Split.new(true).run }.should == 0
12
+ help = File.read("stdout")
13
+ [ "codnar-split", "OPTIONS", "DESCRIPTION" ].each { |text| help.should.include?(text) }
14
+ end
15
+
16
+ def test_run_split
17
+ File.open("input", "w") { |file| file.puts("<foo>") }
18
+ Codnar::Application.with_argv(%w(-o stdout input)) { Codnar::Split.new(true).run }.should == 0
19
+ YAML.load_file("stdout").should == [ {
20
+ "name" => "input",
21
+ "locations" => [ { "file" => "input", "line" => 1 } ],
22
+ "html" => "<foo>",
23
+ "containers" => [],
24
+ "contained" => [],
25
+ } ]
26
+ end
27
+
28
+ def test_run_split_no_file
29
+ Codnar::Application.with_argv(%w(-e stderr)) { Codnar::Split.new(true).run }.should == 1
30
+ File.read("stderr").should == "#{$0}: No input file to split\n"
31
+ end
32
+
33
+ def test_run_split_many_file
34
+ Codnar::Application.with_argv(%w(-e stderr one two)) { Codnar::Split.new(true).run }.should == 1
35
+ File.read("stderr").should == "#{$0}: Too many input files to split\n"
36
+ end
37
+
38
+ end
@@ -0,0 +1,75 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+
5
+ # Test running the Weave Codnar Application.
6
+ class TestRunWeave < Test::Unit::TestCase
7
+
8
+ include Test::WithFakeFS
9
+
10
+ def test_print_help
11
+ Codnar::Application.with_argv(%w(-o stdout -h)) { Codnar::Weave.new(true).run }.should == 0
12
+ help = File.read("stdout")
13
+ [ "codnar-weave", "OPTIONS", "DESCRIPTION" ].each { |text| help.should.include?(text) }
14
+ end
15
+
16
+ ROOT_CHUNKS = [ {
17
+ "name" => "root",
18
+ "locations" => [ { "file" => "root", "line" => 1 } ],
19
+ "html" => "Root\n<embed src='included' type='x-codnar/include'/>\n"
20
+ } ]
21
+
22
+ INCLUDED_CHUNKS = [ {
23
+ "name" => "included",
24
+ "locations" => [ { "file" => "included", "line" => 1 } ],
25
+ "html" => "Included"
26
+ } ]
27
+
28
+ def test_run_weave
29
+ File.open("root", "w") { |file| file.write(ROOT_CHUNKS.to_yaml) }
30
+ File.open("included", "w") { |file| file.write(INCLUDED_CHUNKS.to_yaml) }
31
+ Codnar::Application.with_argv(%w(-o stdout root included)) { Codnar::Weave.new(true).run }.should == 0
32
+ File.read("stdout").should == "Root\nIncluded\n"
33
+ end
34
+
35
+ def test_run_weave_missing_chunk
36
+ File.open("root", "w") { |file| file.write(ROOT_CHUNKS.to_yaml) }
37
+ Codnar::Application.with_argv(%w(-e stderr -o stdout root)) { Codnar::Weave.new(true).run }.should == 1
38
+ File.read("stderr").should == "#{$0}: Missing chunk: included in file: root\n"
39
+ end
40
+
41
+ def test_run_weave_unused_chunk
42
+ File.open("root", "w") { |file| file.write(ROOT_CHUNKS.to_yaml) }
43
+ File.open("included", "w") { |file| file.write(INCLUDED_CHUNKS.to_yaml) }
44
+ Codnar::Application.with_argv(%w(-e stderr -o stdout included root)) { Codnar::Weave.new(true).run }.should == 1
45
+ File.read("stderr").should == "#{$0}: Unused chunk: root in file: root at line: 1\n"
46
+ end
47
+
48
+ def test_run_weave_no_chunks
49
+ Codnar::Application.with_argv(%w(-e stderr)) { Codnar::Weave.new(true).run }.should == 1
50
+ File.read("stderr").should == "#{$0}: No chunk files to weave\n"
51
+ end
52
+
53
+ FILE_CHUNKS = [ {
54
+ "name" => "root",
55
+ "locations" => [ { "file" => "root", "line" => 1 } ],
56
+ "html" => "Root\n<embed src='included.file' type='x-codnar/file'/>\n"
57
+ } ]
58
+
59
+ def test_run_weave_missing_file
60
+ File.open("root", "w") { |file| file.write(FILE_CHUNKS.to_yaml) }
61
+ Codnar::Application.with_argv(%w(-e stderr -o stdout root)) { Codnar::Weave.new(true).run }.should == 1
62
+ double_message = "No such file or directory - " * 2 # Something weird in Ruby Exception.to_s
63
+ File.read("stdout").should == "Root\nFILE: included.file EXCEPTION: #{double_message}\n"
64
+ File.read("stderr").should \
65
+ == "#{$0}: Reading file: included.file exception: #{double_message} in file: root at line: 1\n"
66
+ end
67
+
68
+ def test_run_weave_existing_file
69
+ File.open("root", "w") { |file| file.write(FILE_CHUNKS.to_yaml) }
70
+ File.open("included.file", "w") { |file| file.write("included file\n") }
71
+ Codnar::Application.with_argv(%w(-e stderr -o stdout root)) { Codnar::Weave.new(true).run }.should == 0
72
+ File.read("stdout").should == "Root\nincluded file\n"
73
+ end
74
+
75
+ end
@@ -0,0 +1,78 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+
5
+ # Test scanning classified lines.
6
+ class TestScanLines < Test::Unit::TestCase
7
+
8
+ include Test::WithErrors
9
+ include Test::WithFakeFS
10
+
11
+ def test_scan_lines
12
+ File.open("comments", "w") { |file| file.write(INPUT) }
13
+ scanner = Codnar::Scanner.new(@errors, SYNTAX)
14
+ scanner.lines("comments").should == LINES
15
+ @errors.should == ERRORS
16
+ end
17
+
18
+ SYNTAX = {
19
+ "start_state" => "comment",
20
+ "patterns" => {
21
+ "shell" => {
22
+ "regexp" => "^(\\s*)#+\\s*(.*)$",
23
+ "groups" => [ "indentation", "payload" ],
24
+ "kind" => "comment",
25
+ },
26
+ "c++" => {
27
+ "regexp" => /^(\s*)\/\/+\s*(.*)$/,
28
+ "groups" => [ "indentation", "payload" ],
29
+ "kind" => "comment",
30
+ },
31
+ "invalid" => { "regexp" => "(" },
32
+ },
33
+ "states" => {
34
+ "comment" => {
35
+ "transitions" => [
36
+ { "pattern" => "shell" },
37
+ { "pattern" => "c++" },
38
+ { "pattern" => "no-such-pattern", "next_state" => "no-such-state" },
39
+ ],
40
+ },
41
+ },
42
+ }
43
+
44
+ INPUT = <<-EOF.unindent.gsub("#!", "#")
45
+ #! foo
46
+ // bar
47
+ baz
48
+ EOF
49
+
50
+ LINES = [ {
51
+ "kind" => "comment",
52
+ "line" => "# foo",
53
+ "indentation" => "",
54
+ "payload" => "foo",
55
+ "number" => 1,
56
+ }, {
57
+ "kind" => "comment",
58
+ "line" => " // bar",
59
+ "indentation" => " ",
60
+ "payload" => "bar",
61
+ "number" => 2,
62
+ }, {
63
+ "kind" => "error",
64
+ "line" => " baz",
65
+ "indentation" => " ",
66
+ "payload" => "baz",
67
+ "state" => "comment",
68
+ "number" => 3,
69
+ } ]
70
+
71
+ ERRORS = [
72
+ "#{$0}: Invalid pattern: invalid regexp: ( error: premature end of regular expression: /(/",
73
+ "#{$0}: Reference to a missing pattern: no-such-pattern",
74
+ "#{$0}: Reference to a missing state: no-such-state",
75
+ "#{$0}: State: comment failed to classify line: baz in file: comments at line: 3"
76
+ ]
77
+
78
+ end
@@ -0,0 +1,55 @@
1
+ require "codnar"
2
+ require "olag/test"
3
+ require "test/spec"
4
+ require "test_with_configurations"
5
+
6
+ # Test built-in split code formatting configurations.
7
+ class TestSplitChunkConfigurations < Test::Unit::TestCase
8
+
9
+ include Test::WithConfigurations
10
+ include Test::WithErrors
11
+ include Test::WithTempfile
12
+
13
+ CODE_TEXT = <<-EOF.unindent.gsub("#!", "#")
14
+ int x;
15
+ #! {{{ chunk
16
+ int y;
17
+ #! }}}
18
+ EOF
19
+
20
+ CODE_HTML = <<-EOF.unindent.chomp
21
+ <pre class='code'>
22
+ int x;
23
+ </pre>
24
+ <pre class='nested chunk'>
25
+ <a class='nested chunk' href='#chunk'>chunk</a>
26
+ </pre>
27
+ EOF
28
+
29
+ CHUNK_HTML = <<-EOF.unindent.chomp
30
+ <pre class='code'>
31
+ int y;
32
+ </pre>
33
+ EOF
34
+
35
+ def test_gvim_chunks
36
+ check_split_file(CODE_TEXT,
37
+ Codnar::Configuration::CLASSIFY_SOURCE_CODE.call("c"),
38
+ Codnar::Configuration::CHUNK_BY_VIM_REGIONS) do |path|
39
+ [ {
40
+ "name"=> path,
41
+ "locations" => [ { "file" => path, "line" => 1 } ],
42
+ "containers" => [],
43
+ "contained" => [ "chunk" ],
44
+ "html"=> CODE_HTML,
45
+ }, {
46
+ "name" => "chunk",
47
+ "locations" => [ { "file" => path, "line" => 2 } ],
48
+ "containers" => [ path ],
49
+ "contained" => [],
50
+ "html" => CHUNK_HTML,
51
+ } ]
52
+ end
53
+ end
54
+
55
+ end