validate-website 1.9.0 → 1.11.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.
@@ -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>