glyph 0.2.0 → 0.3.0

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