validate-website 1.9.0 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Base module ValidateWebsite
2
4
  module ValidateWebsite
3
5
  # Utils class for CSS helpers
@@ -10,6 +12,7 @@ module ValidateWebsite
10
12
  def self.extract_urls_from_css(page)
11
13
  return Set[] unless page
12
14
  return Set[] if page.body.nil?
15
+
13
16
  nodes = Crass::Parser.parse_stylesheet(page.body)
14
17
  extract_urls_from_nodes nodes, page
15
18
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
 
3
5
  require 'nokogiri'
@@ -10,27 +12,25 @@ module ValidateWebsite
10
12
  class Validator
11
13
  extend ValidatorClassMethods
12
14
 
13
- @html5_validator_service_url = 'https://checker.html5.org/'
15
+ @html5_validator_service_url = 'https://validator.nu/'
16
+ XHTML_SCHEMA_PATH = File.expand_path('../../data/schemas', __dir__)
17
+ @mutex = Mutex.new
18
+
14
19
  class << self
15
20
  attr_accessor :html5_validator_service_url
16
- end
17
21
 
18
- XHTML_PATH = File.expand_path('../../data/schemas', __dir__)
19
-
20
- @xsd_schemas ||= {}
21
-
22
- # `Dir.chdir` is needed by `Nokogiri::XML::Schema` to validate with local
23
- # files and cannot use file absolute path.
24
- Dir.glob(File.join(XHTML_PATH, '*.xsd')).each do |schema|
25
- Dir.chdir(XHTML_PATH) do
26
- schema_name = File.basename(schema, '.xsd')
27
- schema_content = File.read(File.basename(schema))
28
- begin
29
- @xsd_schemas[schema_name] = Nokogiri::XML::Schema(schema_content)
30
- rescue Nokogiri::XML::SyntaxError
31
- STDERR.puts "XSD SCHEMA: #{schema} cannot be loaded"
22
+ # http://www.w3.org/TR/xhtml1-schema/
23
+ def schema(namespace)
24
+ @mutex.synchronize do
25
+ Dir.chdir(XHTML_SCHEMA_PATH) do
26
+ if File.exist?("#{namespace}.xsd")
27
+ Nokogiri::XML::Schema(File.read("#{namespace}.xsd"))
28
+ end
29
+ end
32
30
  end
33
31
  end
32
+
33
+ alias xsd schema
34
34
  end
35
35
 
36
36
  attr_reader :original_doc, :body, :dtd, :doc, :namespace, :html5_validator
@@ -65,25 +65,22 @@ module ValidateWebsite
65
65
  @ignore ? @errors.reject { |e| @ignore =~ e } : @errors
66
66
  end
67
67
 
68
- # http://www.w3.org/TR/xhtml1-schema/
69
- def self.xsd(namespace)
70
- return unless namespace
71
- @xsd_schemas[namespace] if @xsd_schemas.key? namespace
72
- end
73
-
74
68
  private
75
69
 
76
70
  # http://www.w3.org/TR/xhtml1/#dtds
77
71
  def find_namespace(dtd)
78
72
  return unless dtd.system_id
73
+
79
74
  dtd_uri = URI.parse(dtd.system_id)
80
75
  return unless dtd_uri.path
76
+
81
77
  @dtd_uri = dtd_uri
82
78
  File.basename(@dtd_uri.path, '.dtd')
83
79
  end
84
80
 
85
81
  def document
86
82
  return @document if @document
83
+
87
84
  @document = if @dtd_uri && @body.match(@dtd_uri.to_s)
88
85
  @body.sub(@dtd_uri.to_s, @namespace + '.dtd')
89
86
  else
@@ -95,11 +92,11 @@ module ValidateWebsite
95
92
  def validate
96
93
  if document =~ /^\<!DOCTYPE html\>/i
97
94
  html5_validate
98
- elsif self.class.xsd(@namespace)
99
- self.class.xsd(@namespace).validate(xhtml_doc)
95
+ elsif self.class.schema(@namespace)
96
+ self.class.schema(@namespace).validate(xhtml_doc)
100
97
  else
101
98
  # dont have xsd fall back to dtd
102
- Dir.chdir(XHTML_PATH) do
99
+ Dir.chdir(XHTML_SCHEMA_PATH) do
103
100
  Nokogiri::HTML.parse(document)
104
101
  end.errors
105
102
  end
@@ -138,7 +135,7 @@ module ValidateWebsite
138
135
  end
139
136
 
140
137
  def xhtml_doc
141
- Dir.chdir(XHTML_PATH) do
138
+ Dir.chdir(XHTML_SCHEMA_PATH) do
142
139
  Nokogiri::XML(document) { |cfg| cfg.nonoent.dtdload.dtdvalid.nonet }
143
140
  end
144
141
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tidy_ffi'
2
4
 
3
5
  # Validator Class Methods
@@ -9,6 +11,7 @@ module ValidatorClassMethods
9
11
 
10
12
  def tidy
11
13
  return @tidy if defined?(@tidy)
14
+
12
15
  @lib_tidy = TidyFFI::LibTidy
13
16
  @tidy = TidyFFI::Tidy
14
17
  rescue TidyFFI::LibTidyNotInstalled
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Version file for ValidateWebsite
4
4
  module ValidateWebsite
5
- VERSION = '1.9.0'.freeze
5
+ VERSION = '1.11.0'
6
6
  end
@@ -1,23 +1,32 @@
1
1
  '\" t
2
2
  .\" Title: validate-website-static
3
- .\" Author: [see the "AUTHORS" section]
4
- .\" Generator: Asciidoctor 1.5.6.1
5
- .\" Date: 2018-01-20
3
+ .\" Author: [see the "AUTHOR(S)" section]
4
+ .\" Generator: Asciidoctor 1.5.8
5
+ .\" Date: 2019-01-09
6
6
  .\" Manual: \ \&
7
7
  .\" Source: \ \&
8
8
  .\" Language: English
9
9
  .\"
10
- .TH "VALIDATE\-WEBSITE\-STATIC" "1" "2018-01-20" "\ \&" "\ \&"
10
+ .TH "VALIDATE\-WEBSITE\-STATIC" "1" "2019-01-09" "\ \&" "\ \&"
11
11
  .ie \n(.g .ds Aq \(aq
12
12
  .el .ds Aq '
13
13
  .ss \n[.ss] 0
14
14
  .nh
15
15
  .ad l
16
16
  .de URL
17
- \\$2 \(laURL: \\$1 \(ra\\$3
17
+ \fI\\$2\fP <\\$1>\\$3
18
18
  ..
19
- .if \n[.g] .mso www.tmac
20
- .LINKSTYLE blue R < >
19
+ .als MTO URL
20
+ .if \n[.g] \{\
21
+ . mso www.tmac
22
+ . am URL
23
+ . ad l
24
+ . .
25
+ . am MTO
26
+ . ad l
27
+ . .
28
+ . LINKSTYLE blue R < >
29
+ .\}
21
30
  .SH "NAME"
22
31
  validate\-website\-static \- check the validity of your documents
23
32
  .SH "SYNOPSIS"
@@ -119,5 +128,5 @@ Laurent Arnoud \c
119
128
  .sp
120
129
  The MIT License
121
130
  .sp
122
- Copyright (c) 2009\-2018 \c
131
+ Copyright (c) 2009\-2019 \c
123
132
  .MTO "laurent\(atspkdev.net" "Laurent Arnoud" ""
@@ -1,23 +1,32 @@
1
1
  '\" t
2
2
  .\" Title: validate-website
3
- .\" Author: [see the "AUTHORS" section]
4
- .\" Generator: Asciidoctor 1.5.6.1
5
- .\" Date: 2018-01-20
3
+ .\" Author: [see the "AUTHOR(S)" section]
4
+ .\" Generator: Asciidoctor 1.5.8
5
+ .\" Date: 2019-01-09
6
6
  .\" Manual: \ \&
7
7
  .\" Source: \ \&
8
8
  .\" Language: English
9
9
  .\"
10
- .TH "VALIDATE\-WEBSITE" "1" "2018-01-20" "\ \&" "\ \&"
10
+ .TH "VALIDATE\-WEBSITE" "1" "2019-01-09" "\ \&" "\ \&"
11
11
  .ie \n(.g .ds Aq \(aq
12
12
  .el .ds Aq '
13
13
  .ss \n[.ss] 0
14
14
  .nh
15
15
  .ad l
16
16
  .de URL
17
- \\$2 \(laURL: \\$1 \(ra\\$3
17
+ \fI\\$2\fP <\\$1>\\$3
18
18
  ..
19
- .if \n[.g] .mso www.tmac
20
- .LINKSTYLE blue R < >
19
+ .als MTO URL
20
+ .if \n[.g] \{\
21
+ . mso www.tmac
22
+ . am URL
23
+ . ad l
24
+ . .
25
+ . am MTO
26
+ . ad l
27
+ . .
28
+ . LINKSTYLE blue R < >
29
+ .\}
21
30
  .SH "NAME"
22
31
  validate\-website \- Web crawler for checking the validity of your documents
23
32
  .SH "SYNOPSIS"
@@ -124,5 +133,5 @@ Laurent Arnoud \c
124
133
  .sp
125
134
  The MIT License
126
135
  .sp
127
- Copyright (c) 2009\-2018 \c
136
+ Copyright (c) 2009\-2019 \c
128
137
  .MTO "laurent\(atspkdev.net" "Laurent Arnoud" ""
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('test_helper', __dir__)
2
4
 
3
5
  describe ValidateWebsite::Core do
4
6
  describe 'invalid options' do
5
7
  it 'raise ArgumentError on wrong validation_type' do
6
- proc { ValidateWebsite::Core.new({ color: false }, :fail) }
8
+ _(proc { ValidateWebsite::Core.new({ color: false }, :fail) })
7
9
  .must_raise ArgumentError
8
10
  end
9
11
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('test_helper', __dir__)
2
4
 
3
5
  # rubocop:disable Metrics/BlockLength
@@ -21,7 +23,7 @@ describe ValidateWebsite::Crawl do
21
23
  _out, _err = capture_io do
22
24
  v = ValidateWebsite::Crawl.new(site: TEST_DOMAIN, user_agent: ua)
23
25
  v.crawl
24
- v.crawler.user_agent.must_equal ua
26
+ _(v.crawler.user_agent).must_equal ua
25
27
  end
26
28
  end
27
29
 
@@ -31,7 +33,7 @@ describe ValidateWebsite::Crawl do
31
33
  _out, _err = capture_io do
32
34
  ValidateWebsite::Crawl.new(site: TEST_DOMAIN,
33
35
  html5_validator_service_url: new)
34
- validator.html5_validator_service_url.must_equal new
36
+ _(validator.html5_validator_service_url).must_equal new
35
37
  validator.html5_validator_service_url = original
36
38
  end
37
39
  end
@@ -43,7 +45,8 @@ describe ValidateWebsite::Crawl do
43
45
  _out, _err = capture_io do
44
46
  v = ValidateWebsite::Crawl.new(site: TEST_DOMAIN, cookies: cookies)
45
47
  v.crawl
46
- v.crawler.cookies.cookies_for_host(v.host).must_equal v.default_cookies
48
+ _(v.crawler.cookies.cookies_for_host(v.host))
49
+ .must_equal v.default_cookies
47
50
  end
48
51
  end
49
52
  end
@@ -53,37 +56,53 @@ describe ValidateWebsite::Crawl do
53
56
  name = 'xhtml1-strict'
54
57
  file = File.join('test', 'data', "#{name}.html")
55
58
  page = FakePage.new(name,
56
- body: open(file).read,
59
+ body: File.open(file).read,
57
60
  content_type: 'text/html')
58
61
  @validate_website.site = page.url
59
62
  _out, _err = capture_io do
60
63
  @validate_website.crawl
61
64
  end
62
- @validate_website.history_count.must_equal 5
65
+ _(@validate_website.history_count).must_equal 5
63
66
  end
64
67
 
65
68
  it 'extract link' do
66
69
  name = 'html4-strict'
67
70
  file = File.join('test', 'data', "#{name}.html")
68
71
  page = FakePage.new(name,
69
- body: open(file).read,
72
+ body: File.open(file).read,
70
73
  content_type: 'text/html')
71
74
  @validate_website.site = page.url
72
75
  _out, _err = capture_io do
73
76
  @validate_website.crawl
74
77
  end
75
- @validate_website.history_count.must_equal 98
78
+ _(@validate_website.history_count).must_equal 98
79
+ end
80
+
81
+ it 'can change validator' do
82
+ name = 'html5-fail'
83
+ file = File.join('test', 'data', "#{name}.html")
84
+ page = FakePage.new(name,
85
+ body: File.open(file).read,
86
+ content_type: 'text/html')
87
+ validator_res = File.join('test', 'data', 'validator.nu-failure.json')
88
+ stub_request(:any, /#{validator.html5_validator_service_url}/)
89
+ .to_return(body: File.open(validator_res).read)
90
+ @validate_website.site = page.url
91
+ _out, _err = capture_io do
92
+ @validate_website.crawl(html5_validator: :nu, ignore: /Warning/)
93
+ end
94
+ _(@validate_website.errors_count).must_equal 1
76
95
  end
77
96
 
78
97
  it 'crawl when URLs are not ascii only' do
79
98
  name = 'cozy-community'
80
99
  file = File.join('test', 'data', "#{name}.html")
81
100
  page = FakePage.new(name,
82
- body: open(file).read,
101
+ body: File.open(file).read,
83
102
  content_type: 'text/html')
84
103
  validator_res = File.join('test', 'data', 'validator.nu-failure.json')
85
104
  stub_request(:any, /#{validator.html5_validator_service_url}/)
86
- .to_return(body: open(validator_res).read)
105
+ .to_return(body: File.open(validator_res).read)
87
106
  @validate_website.site = page.url
88
107
  _out, _err = capture_io do
89
108
  @validate_website.crawl
@@ -119,7 +138,7 @@ describe ValidateWebsite::Crawl do
119
138
  _out, _err = capture_io do
120
139
  @validate_website.crawl
121
140
  end
122
- @validate_website.history_count.must_equal 5
141
+ _(@validate_website.history_count).must_equal 5
123
142
  end
124
143
 
125
144
  it 'should extract url with single quote' do
@@ -130,7 +149,7 @@ describe ValidateWebsite::Crawl do
130
149
  _out, _err = capture_io do
131
150
  @validate_website.crawl
132
151
  end
133
- @validate_website.history_count.must_equal 2
152
+ _(@validate_website.history_count).must_equal 2
134
153
  end
135
154
 
136
155
  it 'should extract url with double quote' do
@@ -141,7 +160,7 @@ describe ValidateWebsite::Crawl do
141
160
  _out, _err = capture_io do
142
161
  @validate_website.crawl
143
162
  end
144
- @validate_website.history_count.must_equal 2
163
+ _(@validate_website.history_count).must_equal 2
145
164
  end
146
165
 
147
166
  it 'should extract url with params' do
@@ -152,7 +171,7 @@ describe ValidateWebsite::Crawl do
152
171
  _out, _err = capture_io do
153
172
  @validate_website.crawl
154
173
  end
155
- @validate_website.history_count.must_equal 2
174
+ _(@validate_website.history_count).must_equal 2
156
175
  end
157
176
 
158
177
  it 'should not extract invalid urls' do
@@ -163,7 +182,7 @@ describe ValidateWebsite::Crawl do
163
182
  _out, _err = capture_io do
164
183
  @validate_website.crawl
165
184
  end
166
- @validate_website.history_count.must_equal 1
185
+ _(@validate_website.history_count).must_equal 1
167
186
  end
168
187
  end
169
188
 
@@ -182,7 +201,7 @@ describe ValidateWebsite::Crawl do
182
201
  _out, _err = capture_io do
183
202
  @validate_website.crawl
184
203
  end
185
- @validate_website.errors_count.must_equal 1
204
+ _(@validate_website.errors_count).must_equal 1
186
205
  end
187
206
 
188
207
  it 'should be invalid with syntax error' do
@@ -193,7 +212,7 @@ describe ValidateWebsite::Crawl do
193
212
  _out, _err = capture_io do
194
213
  @validate_website.crawl
195
214
  end
196
- @validate_website.errors_count.must_equal 1
215
+ _(@validate_website.errors_count).must_equal 1
197
216
  end
198
217
  end
199
218
  end
@@ -118,333 +118,6 @@
118
118
  </div>
119
119
  </div>
120
120
 
121
- <script type="text/javascript">
122
- include = function() {
123
-
124
- // save references to save a few bytes
125
- var args = arguments;
126
- var doc = document;
127
-
128
- var toLoad = args.length; // load this many scripts
129
- var lastArgument = args[toLoad - 1];
130
- var hasCallback = lastArgument.call; // is the last arg a callback?
131
- if (hasCallback) {
132
- toLoad--;
133
- }
134
-
135
- function onScriptLoaded() {
136
- var readyState = this.readyState; // we test for "complete" or "loaded" if on IE
137
- if (!readyState || /ded|te/.test(readyState)) {
138
- toLoad--;
139
- if (!toLoad && hasCallback) {
140
- lastArgument();
141
- }
142
- }
143
- }
144
-
145
- for (var i = 0; i < toLoad; i++) {
146
-
147
- var script = doc.createElement('script');
148
- script.src = arguments[i];
149
- script.async = true;
150
- script.onload = script.onerror = script.onreadystatechange = onScriptLoaded;
151
- (
152
- doc.head ||
153
- doc.getElementsByTagName('head')[0]
154
- ).appendChild(script);
155
-
156
- }
157
-
158
- };
159
-
160
-
161
- include("https://cdn.jsdelivr.net/ace/1.1.3/noconflict/ace.js", function () {
162
- include("https://cdn.jsdelivr.net/ace/1.1.3/noconflict/mode-rust.js", function () {
163
- (function () {
164
- "use strict";
165
- // ECMAScript 6 Backwards compatability
166
- if (typeof String.prototype.startsWith !== 'function') {
167
- String.prototype.startsWith = function(str) {
168
- return this.slice(0, str.length) === str;
169
- };
170
- }
171
-
172
- // Regex for finding new lines
173
- var newLineRegex = /(?:\r\n|\r|\n)/g;
174
-
175
- // Fetching DOM items
176
- var activeCode = document.getElementById("active-code");
177
- var editorDiv = document.getElementById("editor");
178
- var staticCode = document.getElementById("static-code");
179
- var runButton = document.getElementById("run-code");
180
- var resultDiv = document.getElementById("result");
181
- var playLink = document.getElementById("playlink");
182
-
183
- // Background colors for program result on success/error
184
- var successColor = "#E2EEF6";
185
- var errorColor = "#F6E2E2";
186
- var warningColor = "#FFFBCB";
187
-
188
- // Message to show when the program is running
189
- var runningMsg = resultDiv.getAttribute("data-msg-running") || "Running...";
190
-
191
- // Error message to return when there's a server failure
192
- var errMsg = "The server encountered an error while running the program.";
193
-
194
- // Stores ACE editor markers (highights) for errors
195
- var markers = [];
196
-
197
- // Status codes, because there are no enums in Javascript
198
- var SUCCESS = 0;
199
- var ERROR = 1;
200
- var WARNING = 2;
201
-
202
- // JS exists, display ACE editor
203
- staticCode.style.display = "none";
204
- activeCode.style.display = "block";
205
-
206
- // Setting up ace editor
207
- var editor = ace.edit("editor");
208
- var Range = ace.require('ace/range').Range;
209
- editor.setTheme("ace/theme/chrome");
210
- editor.getSession().setMode("ace/mode/rust");
211
- editor.setShowPrintMargin(false);
212
- editor.renderer.setShowGutter(false);
213
- editor.setHighlightActiveLine(false);
214
-
215
- // Changes the height of the editor to match its contents
216
- function updateEditorHeight() {
217
- // https://stackoverflow.com/questions/11584061/
218
- var newHeight = editor.getSession().getScreenLength()
219
- * editor.renderer.lineHeight
220
- + editor.renderer.scrollBar.getWidth();
221
-
222
- editorDiv.style.height = Math.ceil(newHeight).toString() + "px";
223
- editor.resize();
224
- }
225
-
226
- // Set initial size to match initial content
227
- updateEditorHeight();
228
-
229
- // Safely remove all content from the result div
230
- function clearResultDiv() {
231
- // Clearing the result div will break our reference to
232
- // the playlink icon, so let's save it if it exists
233
- var newPlayLink = document.getElementById("playlink");
234
- if (newPlayLink) {
235
- playLink = resultDiv.removeChild(newPlayLink);
236
- }
237
- resultDiv.innerHTML = "";
238
- }
239
-
240
- function escapeHTML(unsafe) {
241
- return unsafe
242
- .replace(/&/g, "&amp;")
243
- .replace(/</g, "&lt;")
244
- .replace(/>/g, "&gt;")
245
- .replace(/"/g, "&quot;")
246
- .replace(/'/g, "&#039;")
247
- .replace(newLineRegex, '<br />');
248
- }
249
-
250
- // Dispatches a XMLHttpRequest to the Rust playpen, running the program, and
251
- // issues a callback to `callback` with the result (or null on error)
252
- function runProgram(program, callback) {
253
- var req = new XMLHttpRequest();
254
- var data = JSON.stringify({
255
- version: "beta",
256
- optimize: "0",
257
- code: program
258
- });
259
-
260
- req.timeout = 6000;
261
-
262
- // console.log("Sending", data);
263
- req.open('POST', "https://play.rust-lang.org/evaluate.json", true);
264
- req.onload = function(e) {
265
- var statusCode = false;
266
- var result = null;
267
-
268
- if (req.readyState === 4 && req.status === 200) {
269
- result = JSON.parse(req.response);
270
-
271
- // handle application errors from playpen
272
- if (typeof result['error'] === 'string') {
273
- statusCode = ERROR;
274
- result = 'Playpen Error: ' + result['error'];
275
- } else if (typeof result['result'] === 'string') {
276
- statusCode = SUCCESS;
277
- result = result['result'];
278
-
279
- // handle rustc errors/warnings
280
- // Need server support to get an accurate version of this.
281
- if (result.indexOf("error:") !== -1) {
282
- statusCode = ERROR;
283
- } else if (result.indexOf("warning:") !== -1) {
284
- statusCode = WARNING;
285
- }
286
- }
287
- }
288
-
289
- callback(statusCode, result);
290
- };
291
-
292
- req.onerror = function(e) {
293
- callback(false, null);
294
- };
295
-
296
- req.ontimeout = function(e) {
297
- var statusCode = ERROR;
298
- var result = "play.rust-lang.org not responding, please check back later";
299
-
300
- callback(statusCode, result);
301
- }
302
-
303
- req.setRequestHeader("Content-Type", "application/json");
304
- req.send(data);
305
- }
306
-
307
- // The callback to runProgram
308
- function handleResult(statusCode, message) {
309
- // Dispatch depending on result type
310
- if (result == null) {
311
- clearResultDiv();
312
- resultDiv.style.backgroundColor = errorColor;
313
- resultDiv.innerHTML = errMsg;
314
- } else if (statusCode === SUCCESS) {
315
- handleSuccess(message);
316
- } else if (statusCode === WARNING) {
317
- handleWarning(message);
318
- } else {
319
- handleError(message);
320
- }
321
- }
322
-
323
- // Called on successful program run: display output and playground icon
324
- function handleSuccess(message) {
325
- resultDiv.style.backgroundColor = successColor;
326
- displayOutput(escapeHTML(message), editor.getValue());
327
- }
328
-
329
- // Called when program run results in warning(s)
330
- function handleWarning(message) {
331
- resultDiv.style.backgroundColor = warningColor;
332
- handleProblem(message, "warning");
333
- }
334
-
335
- // Called when program run results in error(s)
336
- function handleError(message) {
337
- resultDiv.style.backgroundColor = errorColor;
338
- handleProblem(message, "error");
339
- }
340
-
341
- // Called on unsuccessful program run. Detects and prints problems (either
342
- // warnings or errors) in program output and highlights relevant lines and text
343
- // in the code.
344
- function handleProblem(message, problem) {
345
- // Getting list of ranges with problems
346
- var lines = message.split(newLineRegex);
347
-
348
- // Cleaning up the message: keeps only relevant problem output.
349
- var cleanMessage = lines.filter(function(line) {
350
- return !line.trim().startsWith("--> <anon>")
351
- && !line.startsWith("playpen:")
352
- && !line.trim().startsWith("error: aborting");
353
- }).map(function(line) {
354
- return escapeHTML(line);
355
- }).filter(function(line) {
356
- return line != "";
357
- }).map(function(line) {
358
- return line.replace(/ /g, '\u00a0\u00a0');
359
- }).join("<br />");
360
-
361
- // Get all of the row:col in the message.
362
- var errorLines = lines.filter(function(line) {
363
- return line.indexOf("--> <anon>") !== -1;
364
- }).map(function(line) {
365
- var lineIndex = line.indexOf(":");
366
- if (lineIndex !== -1) {
367
- return line.slice(lineIndex);
368
- }
369
-
370
- return "";
371
- }).filter(function(line) {
372
- return line != "";
373
- });
374
-
375
- // Setting message
376
- displayOutput(cleanMessage, editor.getValue());
377
-
378
- // Highlighting the lines
379
- var ranges = parseProblems(errorLines);
380
- markers = ranges.map(function(range) {
381
- return editor.getSession().addMarker(range, "ace-" + problem + "-line",
382
- "fullLine", false);
383
- });
384
-
385
- // Highlighting the specific text
386
- markers = markers.concat(ranges.map(function(range) {
387
- return editor.getSession().addMarker(range, "ace-" + problem + "-text",
388
- "text", false);
389
- }));
390
- }
391
-
392
- // Parses a problem message returning a list of ranges (row:col, row:col) where
393
- // problems in the code have occured.
394
- function parseProblems(lines) {
395
- var ranges = [];
396
- for (var i in lines) {
397
- var line = lines[i];
398
- var parts = line.split(/:\s?|\s+/, 5).slice(1, 5);
399
- var ip = parts.map(function(p) { return parseInt(p, 10) - 1; });
400
- console.log("line:", line, parts, ip);
401
- ranges.push(new Range(ip[0], ip[1], ip[2], ip[3]));
402
- }
403
-
404
- return ranges;
405
- }
406
-
407
- // Registering handler for run button click
408
- runButton.addEventListener("click", function(ev) {
409
- resultDiv.style.display = "block";
410
- clearResultDiv();
411
- resultDiv.innerHTML = runningMsg;
412
-
413
- // clear previous markers, if any
414
- markers.map(function(id) { editor.getSession().removeMarker(id); });
415
-
416
- // Get the code, run the program
417
- var program = editor.getValue();
418
- runProgram(program, handleResult);
419
- });
420
-
421
- // Display an output message and a link to the Rust playground
422
- function displayOutput(message, program) {
423
- var programUrl = "https://play.rust-lang.org/?code=" +
424
- encodeURIComponent(program) + "&run=1";
425
- playLink.href = programUrl;
426
-
427
- clearResultDiv(); // clear resultDiv, then add
428
- resultDiv.appendChild(playLink); // playLink icon and message
429
- resultDiv.innerHTML += message;
430
- }
431
-
432
- // Highlight active line when focused
433
- editor.on('focus', function() {
434
- editor.setHighlightActiveLine(true);
435
- });
436
-
437
- // Don't when not
438
- editor.on('blur', function() {
439
- editor.setHighlightActiveLine(false);
440
- });
441
- }());
442
-
443
- });
444
- });
445
- </script>
446
-
447
-
448
121
  <footer>
449
122
  <p>Our site in other languages:
450
123
  <a href="/en-US/">English</a>,
@@ -462,15 +135,5 @@
462
135
  </p>
463
136
  </footer>
464
137
 
465
- <script>
466
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
467
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
468
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
469
- })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
470
-
471
- ga('create', 'UA-58390457-1', 'auto');
472
- ga('send', 'pageview');
473
-
474
- </script>
475
138
  </body>
476
139
  </html>