codemodels-html 0.1.0-java

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.
@@ -0,0 +1,272 @@
1
+ require 'jars/jericho-html-3.3.jar'
2
+ require 'codemodels'
3
+ require 'codemodels/html/monkey_patching'
4
+
5
+ module CodeModels
6
+ module Html
7
+
8
+ class TextBlock
9
+ attr_accessor :source
10
+ attr_accessor :value
11
+
12
+ def begin_point=(data)
13
+ @source = SourceInfo.new unless @source
14
+ @source.begin_point= data
15
+ end
16
+
17
+ def end_point=(data)
18
+ @source = SourceInfo.new unless @source
19
+ @source.end_point= data
20
+ end
21
+ end
22
+
23
+ class Java::NetHtmlparserJericho::Element
24
+
25
+ def text_blocks(code)
26
+ blocks = []
27
+ break_content(self,code).each do |s,e|
28
+ text = code[s,e-s]
29
+ unless text==nil or text.strip.empty?
30
+ #puts "<<<#{text}>>>"
31
+ block = TextBlock.new
32
+ block.value = text
33
+ block.source = SourceInfo.new
34
+ block.source.position = SourcePosition.from_code_indexes(code,s,e-1)
35
+
36
+ blocks << block
37
+ end
38
+ end
39
+ blocks
40
+ end
41
+
42
+ private
43
+
44
+ def break_content(node,code)
45
+ text_inside = code[(node.begin)...(node.end)]
46
+ #puts "Text inside #{node.name} ^#{text_inside}^ It has child elements #{node.child_elements}"
47
+ i = text_inside.first_index('>')
48
+ raise "No '>' found in node #{node}, text inside: '#{text_inside}'" unless i
49
+ #puts "Index i: #{i}"
50
+ raise "No Fixnum" unless node.begin.is_a?(Fixnum)
51
+ raise "No Fixnum" unless i.is_a?(Fixnum)
52
+ start_index = node.begin+i+1
53
+ li = text_inside.last_index('<')
54
+ #puts "Index li: #{li}"
55
+ end_index = node.begin+li
56
+ #puts "Indexes #{start_index} #{end_index}"
57
+ #puts "Content of #{node.name} ^#{code[start_index,end_index-start_index]}^"
58
+
59
+ # no content
60
+ return [] if start_index==end_index
61
+
62
+ if node.child_elements.count==0
63
+ return [[start_index,end_index]]
64
+ else
65
+ segments = []
66
+ # before the first
67
+ segments << [start_index,node.child_elements.first.begin]
68
+ # between children
69
+ for i in 0...(node.child_elements.count-1)
70
+ s = node.child_elements[i].end
71
+ e = node.child_elements[i+1].begin
72
+ segments << [s,e]
73
+ end
74
+ # after the last
75
+ i_last = node.child_elements.size-1
76
+ last_child = node.child_elements[i_last]
77
+ segments << [last_child.end,end_index]
78
+ end
79
+ segments
80
+ end
81
+
82
+ end
83
+
84
+ class Parser < CodeModels::Parser
85
+
86
+ def initialize
87
+ @embedded_parsers = Hash.new do |h,k|
88
+ h[k] = []
89
+ end
90
+ end
91
+
92
+ def parse_file(path)
93
+ code = IO.read(path)
94
+ parse_artifact(FileArtifact.new(path,code))
95
+ end
96
+
97
+ def raw_node_tree(code)
98
+ Java::net.htmlparser.jericho.Config.IsHTMLEmptyElementTagRecognised = true
99
+ xhtml = Java::net.htmlparser.jericho.Config::CompatibilityMode::XHTML
100
+ Java::net.htmlparser.jericho.Config.CurrentCompatibilityMode = xhtml
101
+ reader = java.io.StringReader.new code
102
+ source = Java::net.htmlparser.jericho.Source.new reader
103
+ source
104
+ end
105
+
106
+ def parse_code(code)
107
+ parse_artifact(FileArtifact.new('<code>',code))
108
+ end
109
+
110
+ def parse_artifact(artifact)
111
+ source = raw_node_tree(artifact.code)
112
+ node_to_model(source,artifact.code,artifact)
113
+ end
114
+
115
+ # It operates on original node, not on the model obtained because
116
+ # it could have less information. For example in parsing scripts I need the
117
+ # raw content
118
+ def register_embedded_parser(node_class,embedded_parser,&selector)
119
+ @embedded_parsers[node_class] << {embedded_parser: embedded_parser, selector: selector}
120
+ end
121
+
122
+ def self.node_content(node,code)
123
+ pos = node_content_pos(node,code)
124
+ code[pos[0]..pos[1]]
125
+ end
126
+
127
+ def self.node_content_pos(node,code)
128
+ text_inside = code[(node.begin)...(node.end)]
129
+ i = text_inside.first_index('>')
130
+ start_index = node.begin+i+1
131
+ li = text_inside.last_index('<')
132
+ end_index = node.begin+li-1
133
+ raise "problem" if start_index>end_index
134
+ #content = code[start_index,end_index-start_index]
135
+ [start_index,end_index]
136
+ end
137
+
138
+ private
139
+
140
+ def add_source_info(node,model,code,artifact)
141
+ return if model==nil
142
+ model.language = LANGUAGE
143
+ model.source = CodeModels::SourceInfo.new
144
+ model.source.artifact = artifact
145
+ model.source.position = SourcePosition.from_code_indexes(code,node.begin,node.end)
146
+ end
147
+
148
+ def analyze_content(model,node,code,artifact)
149
+ node.text_blocks(code).each do |tb|
150
+ raise "GOTCHA #{node.name} TEXT INSIDE '#{code[(node.begin)..(node.end)]}'" if (tb.value=='</head>')
151
+ t = Html::Text.new
152
+ t.value = tb.value
153
+
154
+ t.language = LANGUAGE
155
+ t.source = tb.source
156
+ t.source.artifact = artifact
157
+
158
+ model.addChildren(t)
159
+ end
160
+ end
161
+
162
+ def node_to_model(node,code,artifact)
163
+ if node.is_a? Java::NetHtmlparserJericho::Source
164
+ model = Html::HtmlDocument.new
165
+ translate_many(code,node,model,:children,node.child_elements,artifact)
166
+ model
167
+ elsif node.is_a? Java::NetHtmlparserJericho::Element
168
+ if node.name=='!doctype'
169
+ model = Html::DTD.new
170
+ # I am naughty... and waiting for the Jericho parser to fix
171
+ # how they parse doctypes
172
+ model.name = 'html'
173
+ model
174
+ elsif node.name=='script'
175
+ model = Html::Script.new
176
+ model.name = node.name
177
+ # something is obfuscating the attributes method... damn...
178
+ attributes_method = node.java_method(:getAttributes)
179
+ attributes = attributes_method.call
180
+ raise "Error, Attributes expected, instead it is '#{attributes.class}'. Node class #{node.class}" unless attributes.is_a?(Java::NetHtmlparserJericho::Attributes)
181
+ if attributes.get('type') && attributes.get('type').value=='text/ng-template'
182
+ content_pos = Parser.node_content_pos(node,code)
183
+ #raise "mismatch" unless content==embedded_artifact.code
184
+ embedded_artifact = EmbeddedArtifact.new
185
+ embedded_artifact.host_artifact = artifact
186
+ si = content_pos[0]
187
+ while code[si]==' '||code[si]=="\t"||code[si]=="\r"||code[si]=="\n"
188
+ si+=1
189
+ end
190
+ embedded_artifact.position_in_host = SourcePosition.from_code_indexes(code,si,content_pos[1])
191
+ script_doc = parse_artifact(embedded_artifact)
192
+ model.addForeign_asts script_doc
193
+ end
194
+ else
195
+ model = Html::Node.new
196
+ analyze_content(model,node,code,artifact)
197
+ model.name = node.name
198
+ translate_many(code,node,model,:children,node.child_elements,artifact)
199
+ end
200
+ translate_many(code,node,model,:attributes,artifact)
201
+ model
202
+ elsif node.is_a? Java::NetHtmlparserJericho::Attribute
203
+ model = Html::Attribute.new
204
+ model.name = node.name
205
+ model.value = node.value
206
+ model
207
+ else
208
+ raise "Unknown node class: #{node.class}"
209
+ end
210
+
211
+ add_source_info(node,model,code,artifact)
212
+ check_foreign_parser(node,code,model,artifact)
213
+ model
214
+ end
215
+
216
+ def check_foreign_parser(node,code,model,artifact)
217
+ @embedded_parsers[node.class].each do |ep|
218
+ selector = ep[:selector]
219
+ embedded_parser = ep[:embedded_parser]
220
+ embedded_position = selector.call(node,code)
221
+ if embedded_position
222
+ unless embedded_position.is_a?(Array)
223
+ embedded_position = [embedded_position]
224
+ end
225
+ embedded_position.each do |ep|
226
+ embedded_artifact = EmbeddedArtifact.new
227
+ embedded_artifact.host_artifact = artifact
228
+ embedded_artifact.position_in_host = ep
229
+ #puts "<<<#{embedded_code}>>> #{ep}"
230
+ begin
231
+ embedded_root = embedded_parser.parse_artifact(embedded_artifact)
232
+ rescue Exception => e
233
+ raise "Problem embedded in '#{node}' at #{model.source.position} parsing '#{embedded_artifact.code}', from position #{ep}: #{e.inspect}"
234
+ end
235
+ model.addForeign_asts(embedded_root)
236
+ end
237
+ end
238
+ end
239
+ end
240
+
241
+ def translate_many(code,node,model,dest,node_value=(node.send(dest)),artifact)
242
+ return unless node_value!=nil
243
+ #puts "Considering #{model.class}.#{dest} (#{node_value.class})"
244
+ node_value.each do |el|
245
+ #puts "\t* #{el.class}"
246
+ model_el = node_to_model(el,code,artifact)
247
+ model.send(:"add#{dest.to_s.proper_capitalize}", model_el) if model_el!=nil
248
+ end
249
+ end
250
+
251
+ end # class Parser
252
+
253
+ DefaultParser = Parser.new
254
+
255
+ def self.parse_artifact(artifact)
256
+ DefaultParser.parse_artifact(artifact)
257
+ end
258
+
259
+ def self.parse_code(code)
260
+ parse_file(code,'<code>')
261
+ end
262
+
263
+ def self.parse_file(code,filename)
264
+ parse_artifact(FileArtifact.new(filename,code))
265
+ end
266
+
267
+ def self.raw_node_tree(code)
268
+ DefaultParser.raw_node_tree(code)
269
+ end
270
+
271
+ end
272
+ end
@@ -0,0 +1,5 @@
1
+ module CodeModels
2
+ module Html
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require 'jars/jericho-html-3.3.jar'
2
+
3
+ require "codemodels/html/version"
4
+ require "codemodels/html/metamodel"
5
+ require "codemodels/html/parser"
6
+ require "codemodels/html/model_building"
7
+ require "codemodels/html/language"
8
+ require "codemodels/html/angular_embedding_rules"
Binary file
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>AngularJS puzzle</title>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
6
+ <script type="text/javascript" src="js/lib/angular/angular.js"></script>
7
+ <script type="text/javascript" src="js/puzzle/slidingPuzzle.js"></script>
8
+ <script type="text/javascript" src="js/puzzle/wordSearchPuzzle.js"></script>
9
+ <script type="text/javascript" src="js/app.js"></script>
10
+ <link rel="stylesheet" type="text/css" href="css/styles.css"/>
11
+ </head>
12
+ <body ng-app="puzzleApp">
13
+ <ul id="types">
14
+ <li ng-repeat="t in types" ng-class="{'selected': t.id == type}">
15
+ <a ng-href="#/{{t.id}}">{{t.title}}</a>
16
+ </li>
17
+ </ul>
18
+
19
+ <div ng-include="type"></div>
20
+
21
+ <a id="fork" href="https://github.com/pdanis/angular-puzzle" title="Fork me on GitHub"></a>
22
+ <a id="powered" href="http://angularjs.org" title="powered by AngularJS"><img src="http://www.angularjs.org/img/AngularJS-large.png"/></a>
23
+
24
+ <script type="text/ng-template" id="sliding-puzzle">
25
+ <fieldset id="sliding-simple">
26
+ <legend>Basic</legend>
27
+ <sliding-puzzle size="3x3" src="img/angular.png"></sliding-puzzle>
28
+ </fieldset><br/>
29
+
30
+ <fieldset id="sliding-advanced" ng-controller="slidingAdvancedCtrl">
31
+ <legend>Advanced</legend>
32
+ <div ng-repeat="puzzle in puzzles">
33
+ <h2>{{puzzle.title}}</h2>
34
+ <div class="src">
35
+ <input type="text" ng-model="puzzle.src"/>
36
+ </div>
37
+ <div class="status">
38
+ moves: <strong>{{puzzle.api.moves}}</strong><br/>
39
+ solved: <strong>{{puzzle.api.isSolved()}}</strong>
40
+ </div>
41
+ <div class="size">
42
+ rows: <input type="text" ng-model="puzzle.rows" size="2"/>
43
+ cols: <input type="text" ng-model="puzzle.cols" size="2"/><br/>
44
+ <button ng-click="puzzle.api.shuffle()">shuffle</button>
45
+ <button ng-click="puzzle.api.solve()">solve</button>
46
+ </div>
47
+ <sliding-puzzle api="puzzle.api" size="{{puzzle.rows}}x{{puzzle.cols}}" src="{{puzzle.src}}"></sliding-puzzle>
48
+ </div>
49
+ </fieldset>
50
+ </script>
51
+
52
+ <script type="text/ng-template" id="word-search-puzzle">
53
+ <div id="word-search" ng-controller="wordSearchCtrl">
54
+ <ul class="words">
55
+ <li ng-repeat="word in puzzle.words" ng-class="{'found': word.found}">
56
+ {{word.name}}
57
+ </li>
58
+ </ul>
59
+ <word-search-puzzle matrix="matrix" words="words" api="puzzle"></word-search-puzzle>
60
+ <div class="status">
61
+ <button ng-click="puzzle.solve()" ng-show="!puzzle.solved" class="solve">solve</button>
62
+ <strong ng-show="puzzle.solved" ng-show="puzzle.solved">Solved!</strong>
63
+ </div>
64
+ </div>
65
+ </script>
66
+ </body>
67
+ </html>
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+
3
+ class TestBasicInfo < Test::Unit::TestCase
4
+
5
+ include TestHelper
6
+ include CodeModels
7
+ include CodeModels::Html
8
+
9
+ def test_source_line
10
+ code = %q{<html>
11
+ <body>
12
+ <p>ciao
13
+ come
14
+ stai?</p>
15
+ <p>io bene</p>
16
+ <div><p>
17
+ <span></span>
18
+ </p></div>
19
+ </body>
20
+ </html>}
21
+ r = Html.parse_code(code)
22
+ assert_class HtmlDocument, r
23
+ span = nil
24
+ r.traverse {|n| span = n if n.is_a?(Node) && n.name=='span'}
25
+ assert_not_nil span
26
+ assert_equal 8,span.source.position.begin_point.line
27
+ assert_class Node, span.eContainer
28
+ assert_equal 'p',span.eContainer.name
29
+ assert_equal 7,span.eContainer.source.position.begin_point.line # p
30
+ assert_equal 'div',span.eContainer.eContainer.name
31
+ assert_equal 7,span.eContainer.eContainer.source.position.begin_point.line # div
32
+ assert_equal 'body',span.eContainer.eContainer.eContainer.name
33
+ assert_equal 2,span.eContainer.eContainer.eContainer.source.position.begin_point.line # body
34
+ end
35
+
36
+ def test_source_line_of_text_elements
37
+ code = %q{<html>
38
+ <body>
39
+ <p>ciao
40
+ come
41
+ stai?</p>
42
+ <p>io bene</p>
43
+ <div><p>
44
+ <span></span>
45
+ </p></div>
46
+ </body>
47
+ </html>}
48
+ r = Html.parse_code(code)
49
+ assert_class HtmlDocument, r
50
+ body = nil
51
+ r.traverse {|n| body = n if n.is_a?(Node) && n.name=='body'}
52
+ assert_not_nil body
53
+ first_p = body.all_children[0]
54
+ first_p_text = first_p.all_children[0]
55
+ assert_class Text,first_p_text
56
+ assert_equal 3,first_p_text.source.position.begin_point.line
57
+ assert_equal 5,first_p_text.source.position.end_point.line
58
+ end
59
+
60
+ def test_artifact_final_host_is_set_correctly_for_all
61
+ r = AngularJs.parser_considering_angular_embedded_code.parse_file('test/data/puzzle.html')
62
+ r.traverse(:also_foreign) do |n|
63
+ assert_equal 'test/data/puzzle.html',n.source.artifact.final_host.filename, "Node with wrong final_host: #{n}"
64
+ end
65
+ end
66
+
67
+ end
@@ -0,0 +1,79 @@
1
+ require 'test_helper'
2
+
3
+ class TestBasicParsing < Test::Unit::TestCase
4
+
5
+ include TestHelper
6
+ include CodeModels
7
+ include CodeModels::Html
8
+
9
+ def test_basic_document
10
+ code = "<html></html>"
11
+ r = Html.parse_code(code)
12
+ assert_class HtmlDocument, r
13
+ assert_equal 1, r.children.count
14
+ assert_class Node, r.children[0]
15
+ assert_equal 'html', r.children[0].name
16
+ end
17
+
18
+ def test_basic_attributes
19
+ code = "<html id='ciao'></html>"
20
+ r = Html.parse_code(code)
21
+ html = r.children[0]
22
+ assert_equal 1, html.attributes.count
23
+ assert_equal "id", html.attributes[0].name
24
+ assert_equal "ciao", html.attributes[0].value
25
+ end
26
+
27
+ def test_basic_text
28
+ code = "<html>ciao</html>"
29
+ r = Html.parse_code(code)
30
+ html = r.children[0]
31
+ assert_equal 1, html.children.count
32
+ assert_class Text, html.children[0]
33
+ assert_equal 'ciao', html.children[0].value
34
+ end
35
+
36
+ def test_basic_dtd
37
+ code = "<!DOCTYPE html>"
38
+ r = Html.parse_code(code)
39
+ dtd = r.children[0]
40
+ assert_class DTD, dtd
41
+ assert_equal 'html', dtd.name
42
+ end
43
+
44
+ def test_no_text_blocks
45
+ code = "<head><script type='text/ng-template' id='sliding-puzzle'>\n<a/>\n</script></head>"
46
+ r = Html.raw_node_tree(code)
47
+ assert_equal 0,r.child_elements[0].text_blocks(code).count
48
+ end
49
+
50
+ def test_parse_scripts
51
+ code = "<html><head><script type='text/ng-template' id='sliding-puzzle'>\n<a/>\n</script></head></html>"
52
+ r = Html.parse_code(code)
53
+ script = r.children[0].children[0].children[0]
54
+ assert_class Script, script
55
+ assert_class HtmlDocument, script.foreign_asts[0]
56
+ assert_class Node, script.foreign_asts[0].children[0]
57
+ assert_equal 'a', script.foreign_asts[0].children[0].name
58
+ end
59
+
60
+ def test_node_content
61
+ code = "<html><head><script type='text/ng-template' id='sliding-puzzle'>\n<a/>\n</script></head></html>"
62
+ r = Html.raw_node_tree(code)
63
+ script = r.child_elements[0].child_elements[0].child_elements[0]
64
+ assert_equal "<head><script type='text/ng-template' id='sliding-puzzle'>\n<a/>\n</script></head>",Parser.node_content(r,code)
65
+ assert_equal "\n<a/>\n",Parser.node_content(script,code)
66
+ end
67
+
68
+ def test_text_blocks
69
+ code = "<html><head><div type='text/ng-template' id='sliding-puzzle'>ciao<a/>come</div></head></html>"
70
+ r = Html.raw_node_tree(code)
71
+ assert_equal 0,r.child_elements[0].text_blocks(code).count
72
+ assert_equal 0,r.child_elements[0].child_elements[0].text_blocks(code).count
73
+ div = r.child_elements[0].child_elements[0].child_elements[0]
74
+ assert_equal 2,div.text_blocks(code).count
75
+ assert_equal "ciao",div.text_blocks(code)[0].value
76
+ assert_equal "come",div.text_blocks(code)[1].value
77
+ end
78
+
79
+ end
@@ -0,0 +1,74 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter "/test/"
4
+ end
5
+
6
+ require 'json'
7
+ require 'test/unit'
8
+ require 'codemodels'
9
+ require 'codemodels/html'
10
+
11
+ module TestHelper
12
+
13
+ include CodeModels
14
+
15
+ def assert_metamodel(name,attrs,refs)
16
+ assert Html.const_defined?(name), "Metaclass '#{name}' not found"
17
+ c = Html.const_get name
18
+
19
+ assert_all_attrs attrs, c
20
+ assert_all_refs refs, c
21
+ c
22
+ end
23
+
24
+ def assert_class(expected_class,node)
25
+ assert node.class==expected_class, "Node expected to have class #{expected_class} instead it has class #{node.class}"
26
+ end
27
+
28
+ def relative_path(path)
29
+ File.join(File.dirname(__FILE__),path)
30
+ end
31
+
32
+ def assert_all_attrs(expected,c)
33
+ actual = c.ecore.eAllAttributes
34
+ assert_equal expected.count,actual.count,"Expected #{expected.count} attrs, found #{actual.count}. They are #{actual.name}"
35
+ expected.each do |e|
36
+ assert actual.find {|a| a.name==e}, "Attribute #{e} not found"
37
+ end
38
+ end
39
+
40
+ def assert_all_refs(expected,c)
41
+ actual = c.ecore.eAllReferences
42
+ assert_equal expected.count,actual.count,"Expected #{expected.count} refs, found #{actual.count}. They are #{actual.name}"
43
+ expected.each do |e|
44
+ assert actual.find {|a| a.name==e}, "Reference #{e} not found"
45
+ end
46
+ end
47
+
48
+ def assert_ref(c,name,type,many=false)
49
+ ref = c.ecore.eAllReferences.find {|r| r.name==name}
50
+ assert ref, "Reference '#{name}' not found"
51
+ assert_equal type.ecore.name,ref.eType.name
52
+ assert_equal many, ref.many
53
+ end
54
+
55
+ def assert_attr(c,name,type,many=false)
56
+ att = c.ecore.eAllAttributes.find {|a| a.name==name}
57
+ assert_equal type.name,att.eType.name
58
+ assert_equal many, att.many
59
+ end
60
+
61
+ def assert_map(exp,map)
62
+ assert_equal exp.count,map.count, "Expected to have keys: #{exp.keys}, it has #{map}"
63
+ exp.each do |k,v|
64
+ assert_equal exp[k],map[k], "Expected #{k} to have #{exp[k]} instances, it has #{map[k.to_s]}. Map: #{map}"
65
+ end
66
+ end
67
+
68
+ def assert_code_map_to(code,exp)
69
+ r = Html.parse_code(code)
70
+ map = r.values_map
71
+ assert_map(exp,map)
72
+ end
73
+
74
+ end
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+
3
+ class TestInfoExtraction < Test::Unit::TestCase
4
+
5
+ include TestHelper
6
+ include CodeModels
7
+
8
+ def test_snippet_1
9
+ code = %q{
10
+ <html>
11
+ <body>
12
+ <p>ciao!</p>
13
+ </body>
14
+ </html>
15
+ }
16
+ assert_code_map_to(code, {
17
+ 'html' =>1,
18
+ 'body' =>1,
19
+ 'p' => 1,
20
+ 'ciao!'=> 1
21
+ })
22
+ end
23
+
24
+ def test_no_extraneous_values
25
+ code = IO.read('test/data/puzzle.html')
26
+ r = Html::AngularJs.parser_considering_angular_embedded_code.parse_code(code)
27
+ r.traverse(:also_foreign) do |node|
28
+ node.collect_values_with_count.each do |value,count|
29
+ node_code = node.source.code
30
+ unless node_code.include?(value.to_s)
31
+ fail("Value '#{value}' expected in #{node}. Artifact: #{node.source.artifact}, abspos: #{node.source.position(:absolute)}, code: '#{node_code}'")
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+ require 'codemodels/js'
3
+
4
+ class TestParsingEmbeddedLanguages < Test::Unit::TestCase
5
+
6
+ include TestHelper
7
+ include CodeModels
8
+ include CodeModels::Html
9
+
10
+
11
+ def test_begin_index
12
+ code = "<sliding-puzzle api />"
13
+ assert_equal 0,code.first_index('<')
14
+ assert_equal 1,code.first_index('s')
15
+ assert_equal 8,code.first_index('-')
16
+ assert_equal 20,code.first_index('/')
17
+ assert_equal 21,code.first_index('>')
18
+ end
19
+
20
+ end
@@ -0,0 +1,54 @@
1
+ require 'test_helper'
2
+ require 'codemodels/js'
3
+
4
+ class TestParsingEmbeddedLanguages < Test::Unit::TestCase
5
+
6
+ include TestHelper
7
+ include CodeModels
8
+ include CodeModels::Html
9
+
10
+ def setup
11
+ @p = AngularJs.parser_considering_angular_embedded_code
12
+ end
13
+
14
+ def test_source_line
15
+ code =
16
+ %q{<html>
17
+ <body ng-app="puzzleApp">
18
+ <ul id="types">
19
+ <li ng-repeat="t in types" ng-class="{'selected': t.id == type}">
20
+ <a ng-href="#/{{t.id}}">{{t.title}}</a>
21
+ </li>
22
+ </ul>
23
+ </body>
24
+ </html>}
25
+
26
+ r = @p.parse_code(code)
27
+ li = r.all_children_deep.find {|n| n.is_a?(Node) && n.name=='li'}
28
+ assert_not_nil li
29
+ a = li.attributes.find {|a| a.name=='ng-repeat'}
30
+ assert_not_nil a
31
+ assert_equal 1,a.foreign_asts.count
32
+ assert_class CodeModels::Js::InInfixExpression,a.foreign_asts[0]
33
+ end
34
+
35
+ def test_multiple_angular_expressions_in_attr
36
+ code = %q{<sliding-puzzle api="puzzle.api" size="{{puzzle.rows}}x{{puzzle.cols}}" src="{{puzzle.src}}"></sliding-puzzle>}
37
+
38
+ r = @p.parse_code(code)
39
+ assert_class HtmlDocument,r
40
+ assert_class Node,r.children[0]
41
+ att_size = r.children[0].attributes.find {|a| a.name=='size'}
42
+ att_src = r.children[0].attributes.find {|a| a.name=='src'}
43
+ assert_equal 2,att_size.foreign_asts.count
44
+ assert_equal 1,att_src.foreign_asts.count
45
+ end
46
+
47
+ def test_parsing_empty_attr
48
+ code = %q{<sliding-puzzle api />}
49
+
50
+ r = @p.parse_code(code)
51
+ # it does not crash? It is ok!
52
+ end
53
+
54
+ end