glyph 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. data/AUTHORS.textile +1 -1
  2. data/CHANGELOG.textile +119 -222
  3. data/LICENSE.textile +1 -1
  4. data/README.textile +42 -23
  5. data/Rakefile +1 -3
  6. data/VERSION +1 -1
  7. data/benchmark.rb +72 -0
  8. data/book/config.yml +4 -4
  9. data/book/document.glyph +90 -57
  10. data/book/images/document_generation.png +0 -0
  11. data/book/lib/macros/reference.rb +75 -22
  12. data/book/output/html/glyph.html +3183 -2121
  13. data/book/output/html/images/document_generation.png +0 -0
  14. data/book/output/pdf/glyph.pdf +7370 -4913
  15. data/book/resources/document_generation.txt +34 -0
  16. data/book/snippets.yml +6 -0
  17. data/book/text/changelog.glyph +45 -34
  18. data/book/text/compiling/compiling.glyph +23 -0
  19. data/book/text/compiling/lite_mode.glyph +23 -0
  20. data/book/text/compiling/programmatic_usage.glyph +77 -0
  21. data/book/text/extending/bookmarks_headers.glyph +21 -0
  22. data/book/text/extending/further_reading.glyph +13 -0
  23. data/book/text/extending/internals.glyph +79 -0
  24. data/book/text/extending/interpreting.glyph +51 -0
  25. data/book/text/extending/macro_def.glyph +64 -0
  26. data/book/text/extending/params_attrs.glyph +70 -0
  27. data/book/text/extending/placeholders.glyph +34 -0
  28. data/book/text/extending/validators.glyph +16 -0
  29. data/book/text/getting_started/configuration.glyph +49 -0
  30. data/book/text/getting_started/create_project.glyph +41 -0
  31. data/book/text/getting_started/structure.glyph +55 -0
  32. data/book/text/introduction.glyph +49 -26
  33. data/book/text/license.glyph +1 -1
  34. data/book/text/macros/macros_block.glyph +99 -0
  35. data/book/text/macros/macros_core.glyph +208 -0
  36. data/book/text/macros/macros_filters.glyph +40 -0
  37. data/book/text/macros/macros_inline.glyph +50 -0
  38. data/book/text/macros/macros_structure.glyph +100 -0
  39. data/book/text/ref_commands.glyph +94 -73
  40. data/book/text/ref_config.glyph +34 -42
  41. data/book/text/ref_macros.glyph +1 -373
  42. data/book/text/text_editing/code.glyph +51 -0
  43. data/book/text/text_editing/conditionals.glyph +49 -0
  44. data/book/text/text_editing/evaluation.glyph +13 -0
  45. data/book/text/text_editing/glyph_files.glyph +7 -0
  46. data/book/text/text_editing/images.glyph +29 -0
  47. data/book/text/text_editing/inclusions.glyph +44 -0
  48. data/book/text/text_editing/links.glyph +53 -0
  49. data/book/text/text_editing/macro_intro.glyph +111 -0
  50. data/book/text/text_editing/raw_html.glyph +112 -0
  51. data/book/text/text_editing/sections.glyph +63 -0
  52. data/book/text/text_editing/stylesheets.glyph +36 -0
  53. data/book/text/troubleshooting/errors_command.glyph +39 -0
  54. data/book/text/troubleshooting/errors_generic.glyph +29 -0
  55. data/book/text/troubleshooting/errors_intro.glyph +3 -0
  56. data/book/text/troubleshooting/errors_macro.glyph +98 -0
  57. data/book/text/troubleshooting/errors_parser.glyph +29 -0
  58. data/config.yml +77 -58
  59. data/document.glyph +25 -25
  60. data/glyph.gemspec +57 -22
  61. data/lib/glyph.rb +54 -13
  62. data/lib/glyph/commands.rb +84 -17
  63. data/lib/glyph/config.rb +3 -3
  64. data/lib/glyph/document.rb +14 -8
  65. data/lib/glyph/interpreter.rb +18 -58
  66. data/lib/glyph/macro.rb +160 -55
  67. data/lib/glyph/macro_validators.rb +104 -12
  68. data/lib/glyph/node.rb +24 -0
  69. data/lib/glyph/parser.rb +278 -0
  70. data/lib/glyph/syntax_node.rb +225 -0
  71. data/macros/core.rb +212 -0
  72. data/macros/filters.rb +66 -15
  73. data/macros/html/block.rb +43 -105
  74. data/macros/html/inline.rb +11 -12
  75. data/macros/html/structure.rb +123 -58
  76. data/macros/xml.rb +33 -0
  77. data/spec/files/container.textile +2 -2
  78. data/spec/files/document.glyph +2 -2
  79. data/spec/files/document_with_toc.glyph +3 -3
  80. data/spec/files/included.textile +1 -1
  81. data/spec/files/ligature.jpg +0 -0
  82. data/spec/files/markdown.markdown +2 -1
  83. data/spec/lib/commands_spec.rb +46 -3
  84. data/spec/lib/document_spec.rb +4 -4
  85. data/spec/lib/glyph_spec.rb +17 -46
  86. data/spec/lib/interpreter_spec.rb +6 -25
  87. data/spec/lib/macro_spec.rb +141 -43
  88. data/spec/lib/macro_validators_spec.rb +27 -5
  89. data/spec/lib/node_spec.rb +26 -1
  90. data/spec/lib/parser_spec.rb +246 -0
  91. data/spec/lib/syntax_node_spec.rb +111 -0
  92. data/spec/macros/core_spec.rb +195 -0
  93. data/spec/macros/filters_spec.rb +38 -4
  94. data/spec/macros/macros_spec.rb +20 -176
  95. data/spec/macros/textile_spec.rb +13 -71
  96. data/spec/macros/xml_spec.rb +77 -0
  97. data/spec/spec_helper.rb +50 -10
  98. data/spec/tasks/load_spec.rb +13 -2
  99. data/styles/default.css +18 -6
  100. data/styles/pagination.css +1 -19
  101. data/tasks/generate.rake +2 -2
  102. data/tasks/load.rake +27 -17
  103. data/tasks/project.rake +1 -1
  104. metadata +75 -62
  105. data/book/script/compile.rb +0 -8
  106. data/book/script/prof +0 -1
  107. data/book/script/prof_results.htm +0 -21079
  108. data/book/text/authoring.glyph +0 -548
  109. data/book/text/extending.glyph +0 -224
  110. data/book/text/getting_started.glyph +0 -158
  111. data/book/text/troubleshooting.glyph +0 -179
  112. data/lib/glyph/glyph_language.rb +0 -538
  113. data/lib/glyph/glyph_language.treetop +0 -27
  114. data/macros/common.rb +0 -160
data/macros/xml.rb ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ macro "|xml|" do
4
+ begin
5
+ valid_xml_element
6
+ max_parameters 1
7
+ rescue Exception => e
8
+ if @node[:fallback] then
9
+ macro_error "Unknown macro '#{@node[:element]}'"
10
+ else
11
+ raise
12
+ end
13
+ end
14
+ name = @node[:element]
15
+ if name.to_s.in? Glyph['language.options.xml_blacklist'] then
16
+ ""
17
+ else
18
+ attributes # evaluate attributes
19
+ xml_attributes = @node.children.select{|node| node.is_a?(Glyph::AttributeNode)}.
20
+ map do |e|
21
+ if valid_xml_attribute(e[:name]) then
22
+ %|#{e[:name]}="#{e[:value]}"|
23
+ else
24
+ nil
25
+ end
26
+ end.compact.join(" ")
27
+ xml_attributes = " "+xml_attributes unless xml_attributes.blank?
28
+ end_first_tag = param(0) ? ">" : ""
29
+ end_tag = param(0) ? "</#{name}>" : " />"
30
+ contents = (@node.param(0)&0) && (@node.param(0)&0)[:element] ? "\n#{param(0)}\n" : param(0)
31
+ %{<#{name}#{xml_attributes}#{end_first_tag}#{contents}#{end_tag}}
32
+ end
33
+ end
@@ -1,5 +1,5 @@
1
1
  section[
2
- header[Container section]
2
+ @title[Container section]
3
3
  This is a test.
4
- @[included.textile]
4
+ include[a/b/c/included.textile]
5
5
  ]
@@ -1,2 +1,2 @@
1
- @[container.textile]
2
- @[markdown.markdown]
1
+ include[container.textile]
2
+ include[a/b/c/markdown.markdown]
@@ -1,3 +1,3 @@
1
- toc[]
2
- @[container.textile]
3
- @[markdown.markdown]
1
+ toc[1]
2
+ include[container.textile]
3
+ include[a/b/c/markdown.markdown]
@@ -1,4 +1,4 @@
1
1
  section[
2
- header[Test Section]
2
+ @title[Test Section]
3
3
  ...
4
4
  ]
Binary file
@@ -1,5 +1,6 @@
1
1
  section[
2
- header[Markdown|md]
2
+ @title[Markdown]
3
+ @id[md]
3
4
  This contains markdown text.
4
5
 
5
6
  - item 1
@@ -9,7 +9,7 @@ describe "glyph" do
9
9
  end
10
10
 
11
11
  after do
12
- Glyph.lite_mode = false
12
+ reset_quiet
13
13
  delete_project
14
14
  end
15
15
 
@@ -45,6 +45,13 @@ describe "glyph" do
45
45
  (Glyph::SPEC_DIR/'.glyphrc').unlink
46
46
  end
47
47
 
48
+ it "[config] should not overwrite system settings" do
49
+ create_project
50
+ Glyph['system.test_setting'] = false
51
+ run_command(["config", "system.test_setting", true]).match(/warning.+\(system use only\)/m).should_not == nil
52
+ Glyph['system.test_setting'].should == false
53
+ end
54
+
48
55
  it "[add] should create a new text file" do
49
56
  create_project
50
57
  run_command_successfully(["add", "test.textile"]).should == true
@@ -60,7 +67,7 @@ describe "glyph" do
60
67
  it "[compile] should support a custom source file" do
61
68
  create_project
62
69
  file_copy Glyph::PROJECT/'document.glyph', Glyph::PROJECT/'custom.glyph'
63
- run_command(["compile", "-s", "custom.glyph"]).match(/custom\.glyph/m).should_not == nil
70
+ run_command(["-d", "compile", "-s", "custom.glyph"]).match(/custom\.glyph/m).should_not == nil
64
71
  (Glyph::PROJECT/'output/html/test_project.html').exist?.should == true
65
72
  end
66
73
 
@@ -160,7 +167,7 @@ describe "glyph" do
160
167
 
161
168
  it "[compile] should finalize the document in case of errors in included files" do
162
169
  create_project
163
- file_write Glyph::PROJECT/'document.glyph', "section[header[Test]\n@[errors.glyph]\n@[syntax_error.glyph]]"
170
+ file_write Glyph::PROJECT/'document.glyph', "section[@title[Test]\ninclude[errors.glyph]\ninclude[syntax_error.glyph]]"
164
171
  file_write Glyph::PROJECT/'text/errors.glyph', "not[a|b]"
165
172
  file_write Glyph::PROJECT/'text/syntax_error.glyph', "$[a"
166
173
  err = "Document cannot be finalized due to previous errors"
@@ -175,4 +182,40 @@ describe "glyph" do
175
182
  res.match("error: #{err}").should == nil
176
183
  end
177
184
 
185
+ it "[outline] should display the document outline" do
186
+ create_project
187
+ start = %{=====================================
188
+ test_project - Outline
189
+ =====================================}
190
+ c_file = "=== container.textile"
191
+ i_file = "=== a/b/c/included.textile"
192
+ m_file = "=== a/b/c/markdown.markdown"
193
+ c_title = "- Container section "
194
+ i_title = "- Test Section "
195
+ m_title = "- Markdown "
196
+ c_id = "[#h_1]"
197
+ i_id = "[#h_2]"
198
+ m_id = "[#md]"
199
+ file_write Glyph::PROJECT/'document.glyph', "document[#{file_load(Glyph::PROJECT/'document.glyph')}]"
200
+ run_command(["outline"]).should == %{#{start}
201
+ #{c_title}
202
+ #{i_title}
203
+ #{m_title}
204
+ }
205
+ reset_quiet
206
+ run_command(["outline", "-l", "1"]).should == %{#{start}
207
+ #{c_title}
208
+ #{m_title}
209
+ }
210
+ reset_quiet
211
+ run_command(["outline", "-ift"]).should == %{#{start}
212
+ #{c_file}
213
+ #{c_title}#{c_id}
214
+ #{i_file}
215
+ #{i_title}#{i_id}
216
+ #{m_file}
217
+ #{m_title}#{m_id}
218
+ }
219
+ end
220
+
178
221
  end
@@ -7,7 +7,7 @@ describe Glyph::Document do
7
7
 
8
8
  before do
9
9
  Glyph.macro :test do |node|
10
- "Test: #{node[:value]}"
10
+ "Test: #{value}"
11
11
  end
12
12
  create_tree = lambda {|text| }
13
13
  create_doc = lambda {|tree| }
@@ -72,7 +72,7 @@ describe Glyph::Document do
72
72
  n = placeholder do |document|
73
73
  count = 0
74
74
  document.structure.descend do |node, level|
75
- count +=1 if node[:macro] == :test
75
+ count +=1 if node[:name] == :test
76
76
  end
77
77
  count
78
78
  end
@@ -99,10 +99,10 @@ describe Glyph::Document do
99
99
  it "should substitute escaped pipes only when finalizing the document" do
100
100
  define_em_macro
101
101
  define_ref_macro
102
- text = %{em[ref[link with ref[fake \\| parameter]]]}
102
+ text = %{em[ref[link with ref[fake \\| parameter|.]|.]]}
103
103
  # Nevermind the absurdity. It's just to test that the escaped pipes
104
104
  # are handled properly.
105
- result = %{<em><a href="link with <a href="fake | parameter"></a>"></a></em>}
105
+ result = %{<em><a href="link with <a href="fake | parameter">.</a>">.</a></em>}
106
106
  tree = create_tree text
107
107
  doc = create_doc tree
108
108
  doc.analyze
@@ -7,6 +7,10 @@ describe Glyph do
7
7
  Glyph.enable 'project:create'
8
8
  end
9
9
 
10
+ after do
11
+ delete_project
12
+ end
13
+
10
14
  it "should initialize a rake app and tasks" do
11
15
  Rake.application.tasks.length.should > 0
12
16
  end
@@ -31,66 +35,22 @@ describe Glyph do
31
35
 
32
36
  it "should support macro aliases" do
33
37
  define_ref_macro
38
+ define_em_macro
34
39
  lambda { Glyph.macro_alias("->" => :ref)}.should_not raise_error
35
40
  Glyph::MACROS[:"->"].should == Glyph::MACROS[:ref]
36
41
  Glyph.macro_alias :em => :ref
37
42
  Glyph::MACROS[:em].should_not == Glyph::MACROS[:ref]
38
43
  end
39
44
 
40
- it "should provide a set of default macros and aliases" do
41
- delete_project
42
- create_project
43
- Glyph.run! 'load:macros'
44
- macros = [:anchor, :link, :codeph, :fmi, :note, :box, :code, :title, :subtitle,
45
- :img, :fig, :author, :pubdate, :table, :td, :tr, :th, :comment, :todo, :snippet, "snippet:",
46
- :include, :config, "config:", :ruby, :escape, :textile, :markdown, :div, :header, :document, :body,
47
- :head, :style, :toc, :section, :condition, :eq, :and, :or, :not, :match, :highlight, "macro:",
48
- :encode, :decode, :draftcomment]
49
- aliases = [
50
- [[:bookmark, "#"], :anchor],
51
- [["=>"], :link],
52
- [[:important, :caution, :tip], :note],
53
- [["@"], :include],
54
- [["&"], :snippet],
55
- [["&:"], "snippet:"],
56
- [["%:"], "macro:"],
57
- [["?"], "condition"],
58
- [["$"], :config],
59
- [["$:"], "config:"],
60
- [["%"], :ruby],
61
- [["."], :escape],
62
- [["--"], :comment],
63
- [[:dc], :draftcomment],
64
- [["!"], :todo],
65
- [["*"], :encode],
66
- [["**"], :decode],
67
- [[:md], :markdown],
68
- [[:frontcover, :titlepage, :halftitlepage, :frontmatter, :bodymatter, :backmatter, :backcover], :div]]
69
- total = 0
70
- macros.each { |v| total+=1; Glyph::MACROS[v.to_sym].should_not == nil }
71
- check_aliases = lambda do |arr, target|
72
- arr.each {|v| total += 1; Glyph::MACROS[v.to_sym].should == Glyph::MACROS[target.to_sym]}
73
- end
74
- aliases.each { |v| check_aliases.call v[0], v[1] }
75
- check_aliases.call Glyph['structure.frontmatter'], :div
76
- check_aliases.call Glyph['structure.bodymatter'], :div
77
- check_aliases.call Glyph['structure.backmatter'], :div
78
- Glyph['structure.frontmatter'].length.should == 8
79
- Glyph['structure.bodymatter'].length.should == 4
80
- Glyph['structure.backmatter'].length.should == 13
81
- #puts Glyph::MACROS.keys.map{|i| i.to_s}.sort.to_yaml
82
- total.should == Glyph::MACROS.length
83
- end
84
-
85
45
  it "should provide a filter method to convert raw text into HTML" do
86
46
  Glyph['document.title'] = "Test"
87
47
  Glyph.filter("title[]").gsub(/\n|\t/, '').should == "<h1>Test</h1>"
88
48
  end
89
49
 
90
50
  it "should provide a compile method to compile files in lite mode" do
51
+ reset_quiet
91
52
  file_copy Glyph::PROJECT/'../files/article.glyph', Glyph::PROJECT/'article.glyph'
92
53
  lambda { Glyph.compile Glyph::PROJECT/'article.glyph' }.should_not raise_error
93
- reset_quiet
94
54
  (Glyph::PROJECT/'article.html').exist?.should == true
95
55
  end
96
56
 
@@ -102,4 +62,15 @@ describe Glyph do
102
62
  Glyph['test_setting'].should == nil
103
63
  end
104
64
 
65
+ it "should not allow certain macros to be expanded in safe mode" do
66
+ create_project
67
+ Glyph.run! "load:all"
68
+ Glyph.safe_mode = true
69
+ lambda { output_for("include[test.glyph]")}.should raise_error Glyph::MacroError
70
+ lambda {output_for("config:[test|true]")}.should raise_error Glyph::MacroError
71
+ lambda { output_for("ruby[Time.now]")}.should raise_error Glyph::MacroError
72
+ lambda { output_for("rw:[a|section[{{0}}]]")}.should raise_error Glyph::MacroError
73
+ Glyph.safe_mode = false
74
+ end
75
+
105
76
  end
@@ -11,17 +11,16 @@ describe Glyph::Interpreter do
11
11
 
12
12
 
13
13
  after do
14
+ reset_quiet
14
15
  delete_project
15
16
  end
16
17
 
17
18
  it "should process text and run simple macros" do
18
19
  define_em_macro
19
20
  text = "This is a em[test]. It em[should] work."
20
- interpret text
21
- @p.document.output.should == "This is a <em>test</em>. It <em>should</em> work."
21
+ output_for(text).should == "This is a <em>test</em>. It <em>should</em> work."
22
22
  text2 = "This is pointless, but valid: em[]. This em[will] though."
23
- interpret text2
24
- @p.document.output.should == "This is pointless, but valid: <em></em>. This <em>will</em> though."
23
+ output_for(text2).should == "This is pointless, but valid: <em></em>. This <em>will</em> though."
25
24
  end
26
25
 
27
26
  it "should process and run complex macros" do
@@ -62,35 +61,17 @@ describe Glyph::Interpreter do
62
61
  it "should store syntax node information in context" do
63
62
  define_em_macro
64
63
  define_ref_macro
65
- count = 0
66
64
  Glyph.macro :test_node do |node|
67
- node.ascend do |n|
68
- count+=1
69
- end
70
- node.parent[:macro]
65
+ node.parent_macro[:name]
71
66
  end
72
67
  text = %{Test em[test_node[em[test_node[---]]]].}
73
68
  interpret text
74
69
  @p.document.output.should == "Test <em>em</em>."
75
- count.should == 8
76
70
  end
77
71
 
78
- it "should process document.glyph" do
79
- interpret file_load(Glyph::PROJECT/'document.glyph')
80
- macros = []
81
- @p.document.structure.descend do |n, level|
82
- macros << {n[:macro] => level} if n[:macro]
83
- end
84
- macros.should == [{:"@" => 1},{:textile => 2},{:section => 3}, {:header => 4},
85
- {:"@" => 4}, {:textile => 5}, {:section => 6}, {:header => 7},
86
- {:"@" => 1}, {:markdown => 2},{:section => 3}, {:header => 4}]
87
- end
88
-
89
-
90
72
  it "should provide diagnostic information on errors" do
91
- failure = "Incorrect macro syntax\n -> -- [Line 1, Column 13]"
92
- # This is probably the only type of error recognized which can occur at parser level
93
- lambda { interpret "section[em[]" }.should raise_error(Glyph::SyntaxError, failure)
73
+ failure = "-- [1, 12] Macro 'section' not closed"
74
+ lambda { interpret("section[em[]").document }.should raise_error(Glyph::SyntaxError, failure)
94
75
  end
95
76
 
96
77
  end
@@ -5,14 +5,16 @@ describe Glyph::Macro do
5
5
 
6
6
  before do
7
7
  Glyph.macro :test do
8
- "Test: #{@value}"
8
+ "Test: #{value}"
9
9
  end
10
10
  create_tree = lambda {|text| }
11
11
  create_doc = lambda {|tree| }
12
12
  @text = "test[section[header[Test!|test]]]"
13
13
  @tree = create_tree @text
14
14
  @doc = create_doc @tree
15
- @node = {:macro => :test, :value => "Testing...", :source => "--", :document => @doc}.to_node
15
+ @node = Glyph::MacroNode.new.from({:name => :test, :source => {:name => "--"}, :document => @doc})
16
+ @node << Glyph::ParameterNode.new.from({:name => :"0"})
17
+ (@node&0) << Glyph::TextNode.new.from({:value => "Testing..."})
16
18
  @macro = Glyph::Macro.new @node
17
19
  end
18
20
 
@@ -26,10 +28,10 @@ describe Glyph::Macro do
26
28
 
27
29
  it "should not interpret escaped macros" do
28
30
  Glyph.macro :int_1 do
29
- "->#{interpret(@value)}<-"
31
+ "->#{interpret(value)}<-"
30
32
  end
31
33
  Glyph.macro :int_2 do
32
- "=>#{interpret(@value)}<="
34
+ "=>#{interpret(value)}<="
33
35
  end
34
36
  text1 = "int_1[int_2[Test]]"
35
37
  text2 = "int_1[=int_2[Test]=]"
@@ -60,49 +62,145 @@ describe Glyph::Macro do
60
62
  @doc.placeholders.length.should == 1
61
63
  end
62
64
 
63
- it "should execute" do
64
- @macro.execute.should == "Test: Testing..."
65
+ it "should expand" do
66
+ @macro.expand.should == "Test: Testing..."
65
67
  end
66
68
 
67
- it "should detect mutual inclusion" do
68
- delete_project
69
- create_project
70
- Glyph.run! 'load:macros'
71
- Glyph::SNIPPETS[:inc] = "Test &[inc]"
72
- lambda {interpret("&[inc] test").document}.should raise_error(Glyph::MutualInclusionError)
69
+ it "should support rewriting" do
70
+ test = 0
71
+ Glyph.macro :test do
72
+ interpret "#{@node.value}-#{test+=1}"
73
+ end
74
+ Glyph.macro :release do
75
+ interpret "Release\n#{@node.value}"
76
+ end
77
+ Glyph.macro :features do
78
+ interpret "\n\ntest[Features: \n#{@node.value}]"
79
+ end
80
+ Glyph.macro :feature do
81
+ interpret "test[#{@node.value}]\n"
82
+ end
83
+ text = %{
84
+ release[
85
+ features[
86
+ feature[a]
87
+ feature[b]
88
+ feature[c]
89
+ ]
90
+ ]
91
+ }
92
+ output_for(text).gsub(/\n|\t/, '').should ==
93
+ "ReleaseFeatures: a-2b-3c-4-1"
94
+ test = 0
95
+ Glyph.macro :test do
96
+ interpret "#{value}-#{test+=1}"
97
+ end
98
+ Glyph.macro :release do
99
+ interpret "Release\n#{value}"
100
+ end
101
+ Glyph.macro :features do
102
+ interpret "\n\ntest[Features: \n#{value}]"
103
+ end
104
+ Glyph.macro :feature do
105
+ interpret "test[#{value}]\n"
106
+ end
107
+ output_for(text).gsub(/\n|\t/, '').should ==
108
+ "ReleaseFeatures: a-1b-2c-3-4"
109
+ end
110
+
111
+ it "should support access to parameters and attributes" do
112
+ Glyph.macro :test do
113
+ "test: #{value}"
114
+ end
115
+ Glyph.macro :test1 do
116
+ "test1: #{value}"
117
+ end
118
+ node = Glyph::Parser.new("test[@a[test1[...]]test1[...]|test1[---]]").parse
119
+ m = Glyph::Macro.new(node&0)
120
+ m.parameters.should == ["test1: ...", "test1: ---"]
121
+ m.attributes.should == {:a => "test1: ..."}
122
+ m.parameter(0).should == "test1: ..."
123
+ m.parameter(1).should == "test1: ---"
124
+ m.parameter(2).should == nil
125
+ m.attribute(:a).should == "test1: ..."
126
+ m.attribute(:b).should == nil
127
+ end
128
+
129
+ it "should not evaluate attributes unless specifically requested" do
130
+ define_em_macro
131
+ node = Glyph::Parser.new("par0[em[...]|em[---]]").parse
132
+ m = Glyph::Macro.new(node&0)
133
+ syntaxnode = lambda do |hash|
134
+ Glyph::SyntaxNode.new.from hash
135
+ end
136
+ p0 = p_node 0
137
+ p0 << macro_node(:em, :escape => false)
138
+ p00 = p_node 0
139
+ (p0&0) << p00
140
+ p00 << text_node("...")
141
+ p1 = p_node 1
142
+ p1 << macro_node(:em, :escape => false)
143
+ p10 = p_node 0
144
+ (p1&0) << p10
145
+ p10 << text_node("---")
146
+ m.node.parameters.should == [p0, p1]
147
+ m.node.parameters[0][:value].should == nil
148
+ m.node.parameters[1][:value].should == nil
149
+ m.parameter(0).should == "<em>...</em>"
150
+ m.node.parameters[0][:value].should == "<em>...</em>"
151
+ m.node.parameters[1][:value].should == nil
73
152
  end
74
153
 
75
- it "should encode and decode text" do
76
- Glyph.run! "load:all"
77
- Glyph.macro :sec_1 do
78
- res = decode "section[header[Test1]\n#{@value}]"
79
- interpret res
80
- end
81
- Glyph.macro :sec_2 do
82
- encode "section[section[header[Test2]\n#@value]]"
83
- end
84
- text1 = %{sec_1[sec_2[Test]]}
85
- interpret text1
86
- res1 = @p.document.output.gsub(/\t/, '')
87
- text2 = %{section[header[Test1]
88
- section[section[header[Test2]
89
- Test]]]}
90
- interpret text2
91
- res2 = @p.document.output.gsub(/\t/, '')
92
- result = "<div class=\"section\">
93
- <h2 id=\"h_1\">Test1</h2>
94
- <div class=\"section\">
95
- <div class=\"section\">
96
- <h4 id=\"h_2\">Test2</h4>
97
- Test
98
-
99
- </div>
100
-
101
- </div>
102
-
103
- </div>".gsub(/\t/, '')
104
- res1.should == result
105
- res2.should == result
154
+ it "should not evaluate parameters unless specifically requested" do
155
+ define_em_macro
156
+ node = Glyph::Parser.new("par0[@a[em[...]]@b[em[---]]]").parse
157
+ m = Glyph::Macro.new(node&0)
158
+ syntaxnode = lambda do |hash|
159
+ Glyph::SyntaxNode.new.from hash
160
+ end
161
+ p0 = a_node :a, :escape => false
162
+ p0 << macro_node(:em, :escape => false)
163
+ p00 = p_node 0
164
+ (p0&0) << p00
165
+ p00 << text_node("...")
166
+ p1 = a_node :b, :escape => false
167
+ p1 << macro_node(:em, :escape => false)
168
+ p10 = p_node 0
169
+ (p1&0) << p10
170
+ p10 << text_node("---")
171
+ m.node.attributes.should == [p0, p1]
172
+ m.node.attribute(:a)[:value].should == nil
173
+ m.node.attribute(:b)[:value].should == nil
174
+ m.attribute(:a).should == "<em>...</em>"
175
+ m.node.attribute(:a)[:value].should == "<em>...</em>"
176
+ m.node.attribute(:b)[:value].should == nil
177
+ end
178
+
179
+ it "should expose a path method to determine its location" do
180
+ tree = Glyph::Parser.new(%{
181
+ test1[
182
+ a[...]|
183
+ b[
184
+ test2[@a[x[]]]
185
+ ]
186
+ ]}).parse
187
+ node = tree&1&1&1&0&1&0&0
188
+ m = Glyph::Macro.new(node)
189
+ m.path.should == "test1/1/b/test2/@a/x"
190
+ end
191
+
192
+ it "should substitute bracket escapes properly" do
193
+ define_em_macro
194
+ Glyph.macro :test_int do
195
+ interpret "- #{value} -"
196
+ end
197
+ text1 = %{em[test\\\\\.\\[...\\\\\.\\]]} # test\\\.\[\\\.\]
198
+ text2 = %{em[=test\\\\\\.[...\\\\\\.]=]} # test\\\.[\\\.]
199
+ text3 = %{test_int[em[=test\\\\\.[...\\\\\.]=]]}
200
+ out = "<em>test\\[...\\]</em>"
201
+ output_for(text1).should == out
202
+ output_for(text2).should == out
203
+ output_for(text3).should == "- #{out} -"
106
204
  end
107
205
 
108
206
  end