From 4e7352b91e0dd02b5cf104dea25ee32300a0088b Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Sat, 30 Jun 2018 12:35:16 -0700 Subject: [PATCH] Sync common files and add testing files. --- .travis.yml | 12 +++ Gemfile | 6 ++ Gemfile.lock | 161 +++++++++++++++++++++++++++++++++++++ Rakefile | 11 +++ common/README.rb | 0 common/extract-examples.rb | 160 ++++++++++++++++++++++++++++++++++++ 6 files changed, 350 insertions(+) create mode 100644 .travis.yml create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 Rakefile create mode 100644 common/README.rb create mode 100755 common/extract-examples.rb diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..37cba644 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +jobs: + include: + - stage: common + script: + - git remote add -f b https://github.com/w3c/json-ld-wg.git + - git remote update + - git diff --exit-code remotes/b/master -- common + - stage: examples + language: ruby + rvm: 2.5 + bundler_args: --without debug + script: "rake test" diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..7ba5edbd --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +gem 'nokogiri' +gem 'linkeddata' +gem 'colorize' +gem 'rake' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..ac08f941 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,161 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + bcp47 (0.3.3) + i18n + builder (3.2.3) + colorize (0.8.1) + concurrent-ruby (1.0.5) + connection_pool (2.2.2) + ebnf (1.1.2) + rdf (>= 2.2, < 4.0) + sxp (~> 1.0) + equivalent-xml (0.6.0) + nokogiri (>= 1.4.3) + haml (5.0.4) + temple (>= 0.8.0) + tilt + hamster (3.0.0) + concurrent-ruby (~> 1.0) + htmlentities (4.3.4) + i18n (1.0.1) + concurrent-ruby (~> 1.0) + json-ld (2.2.1) + multi_json (~> 1.12) + rdf (>= 2.2.8, < 4.0) + json-ld-preloaded (2.2.3) + json-ld (>= 2.2, < 4.0) + multi_json (~> 1.12) + rdf (>= 2.2, < 4.0) + ld-patch (0.3.3) + ebnf (~> 1.1) + rdf (>= 2.2, < 4.0) + rdf-xsd (>= 2.2, < 4.0) + sparql (>= 2.2, < 4.0) + sxp (~> 1.0) + link_header (0.0.8) + linkeddata (3.0.1) + equivalent-xml (~> 0.6) + json-ld (>= 2.2.1, < 4.0) + ld-patch (~> 0.3, >= 0.3.3) + nokogiri (~> 1.8) + nokogumbo (~> 1.5) + rdf (~> 3.0) + rdf-aggregate-repo (>= 2.2.1, < 4.0) + rdf-isomorphic (~> 3.0) + rdf-json (>= 2.2, < 4.0) + rdf-microdata (>= 2.2.3, < 4.0) + rdf-n3 (~> 3.0) + rdf-normalize (~> 0.3, >= 0.3.3) + rdf-rdfa (~> 3.0) + rdf-rdfxml (>= 2.2.1, < 4.0) + rdf-reasoner (~> 0.5.0) + rdf-tabular (>= 2.2.1, < 4.0) + rdf-trig (>= 2.2, < 4.0) + rdf-trix (>= 2.2.1, < 4.0) + rdf-turtle (~> 3.0, >= 3.0.1) + rdf-vocab (~> 3.0) + rdf-xsd (~> 3.0) + shex (~> 0.5, >= 0.5.2) + sparql (~> 3.0) + sparql-client (~> 3.0) + mini_portile2 (2.3.0) + multi_json (1.13.1) + net-http-persistent (3.0.0) + connection_pool (~> 2.2) + nokogiri (1.8.2) + mini_portile2 (~> 2.3.0) + nokogumbo (1.5.0) + nokogiri + public_suffix (3.0.2) + rake (12.3.1) + rdf (3.0.2) + hamster (~> 3.0) + link_header (~> 0.0, >= 0.0.8) + rdf-aggregate-repo (2.2.1) + rdf (>= 2.2, < 4.0) + rdf-isomorphic (3.0.0) + rdf (~> 3.0) + rdf-json (2.2.0) + rdf (>= 2.2, < 4.0) + rdf-microdata (2.2.3) + htmlentities (~> 4.3) + nokogiri (~> 1.8) + rdf (>= 2.2.8, < 4.0) + rdf-xsd (>= 2.2, < 4.0) + rdf-n3 (3.0.0) + rdf (~> 3.0) + rdf-normalize (0.3.3) + rdf (>= 2.2, < 4.0) + rdf-rdfa (3.0.1) + haml (~> 5.0) + htmlentities (~> 4.3) + rdf (~> 3.0) + rdf-aggregate-repo (>= 2.2, < 4.0) + rdf-xsd (~> 3.0) + rdf-rdfxml (2.2.1) + htmlentities (~> 4.3) + rdf (>= 2.2, < 4.0) + rdf-rdfa (>= 2.2, < 4.0) + rdf-xsd (>= 2.2, < 4.0) + rdf-reasoner (0.5.1) + rdf (~> 3.0) + rdf-vocab (~> 3.0) + rdf-xsd (~> 3.0) + rdf-tabular (2.2.1) + addressable (~> 2.3) + bcp47 (~> 0.3, >= 0.3.3) + json-ld (>= 2.1, < 4.0) + rdf (>= 2.2, < 4.0) + rdf-vocab (>= 2.2, < 4.0) + rdf-xsd (>= 2.2, < 4.0) + rdf-trig (2.2.0) + ebnf (~> 1.0, >= 1.0.1) + rdf (>= 2.2, < 4.0) + rdf-turtle (>= 2.2, < 4.0) + rdf-trix (2.2.1) + rdf (>= 2.2, < 4.0) + rdf-turtle (3.0.1) + ebnf (~> 1.1) + rdf (~> 3.0) + rdf-vocab (3.0.2) + rdf (~> 3.0) + rdf-xsd (3.0.0) + rdf (~> 3.0) + shex (0.5.2) + ebnf (~> 1.1) + json-ld (>= 2.2, < 4.0) + json-ld-preloaded (>= 2.2, < 4.0) + rdf (>= 2.2, < 4.0) + rdf-xsd (>= 2.2, < 4.0) + sparql (>= 2.2, < 4.0) + sxp (~> 1.0) + sparql (3.0.1) + builder (~> 3.2) + ebnf (~> 1.1) + rdf (~> 3.0) + rdf-aggregate-repo (>= 2.2, < 4.0) + rdf-xsd (~> 3.0) + sparql-client (~> 3.0) + sxp (~> 1.0) + sparql-client (3.0.0) + net-http-persistent (>= 2.9, < 4) + rdf (~> 3.0) + sxp (1.0.1) + rdf (>= 2.2, < 4.0) + temple (0.8.0) + tilt (2.0.8) + +PLATFORMS + ruby + +DEPENDENCIES + colorize + linkeddata + nokogiri + rake + +BUNDLED WITH + 1.16.1 diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..ec17e916 --- /dev/null +++ b/Rakefile @@ -0,0 +1,11 @@ +task default: :test + +desc "Test examples in spec files" +task :test do + sh %(bundle exec common/extract-examples.rb index.html) +end + +desc "Extract Examples" +task :examples do + sh %(bundle exec common/extract-examples.rb --example-dir examples index.html) +end diff --git a/common/README.rb b/common/README.rb new file mode 100644 index 00000000..e69de29b diff --git a/common/extract-examples.rb b/common/extract-examples.rb new file mode 100755 index 00000000..47dbc745 --- /dev/null +++ b/common/extract-examples.rb @@ -0,0 +1,160 @@ +#!/usr/bin/env ruby +# Extracts examples from a ReSpec document, verifies that example titles are unique. Numbering attempts to replicate that used by ReSpec. Examples in script elements, which are not visibile, may be used for describing the results of related examples +require 'getoptlong' +require 'json' +require 'nokogiri' +require 'linkeddata' +require 'fileutils' +require 'colorize' + +example_dir = nil +opts = GetoptLong.new( + ["--example-dir", GetoptLong::REQUIRED_ARGUMENT] +) +opts.each do |opt, arg| + case opt + when '--example-dir' then example_dir = arg + end +end + +num_errors = 0 + +ARGV.each do |input| + $stdout.puts "\ninput: #{input}" + example_number = 0 + examples = {} + errors = [] + warnings = [] + + File.open(input, "r") do |f| + doc = Nokogiri::HTML.parse(f.read) + doc.css(".example").each do |element| + warn = false + example_number += 1 if element.name == "pre" + + if element.attr('data-ignore') || element.name == "table" + $stdout.write "i".colorize(:yellow) + next + end + + if (title = element.attr('title')).to_s.empty? + errors << "Example #{example_number} at line #{element.line} has no title" + $stdout.write "F".colorize(:red) + next + end + + if examples.any? {|n, ex| ex[:title] == title} + warnings << "Example #{example_number} at line #{element.line} uses duplicate title: #{title}" + warn = true + end + + content = element.inner_html. + sub(/^\s*\s*$/m, ''). + gsub('****', ''). + gsub(/####([^#]*)####/, '') + + ext = case element.attr('data-content-type') + when nil, '' then "json" + when 'application/n-quads', 'nq' then 'nq' + when 'text/html', 'html' then 'html' + when 'text/turtle', 'ttl' then 'ttl' + else 'txt' + end + + # Perform example syntactic validation based on extension + case ext + when 'json' + begin + ::JSON.parse(content) + rescue JSON::ParserError => e + errors << "Example #{example_number} at line #{element.line} parse error: #{e.message}" + $stdout.write "F".colorize(:red) + next + end + when 'html' + begin + doc = Nokogiri::HTML.parse(content) {|c| c.strict} + doc.errors.each do |e| + errors << "Example #{example_number} at line #{element.line} parse error: #{e}" + end + unless doc.errors.empty? + $stdout.write "F".colorize(:red) + next + end + rescue Nokogiri::XML::SyntaxError => e + errors << "Example #{example_number} at line #{element.line} parse error: #{e.message}" + $stdout.write "F".colorize(:red) + next + end + when 'ttl' + begin + reader_errors = [] + RDF::Turtle::Reader.new(content, logger: reader_errors) {|r| r.validate!} + rescue + reader_errors.each do |e| + errors << "Example #{example_number} at line #{element.line} parse error: #{e}" + end + $stdout.write "F".colorize(:red) + next + end + when 'nq' + begin + reader_errors = [] + RDF::NQuads::Reader.new(content, logger: reader_errors) {|r| r.validate!} + rescue + reader_errors.each do |e| + errors << "Example #{example_number} at line #{element.line} parse error: #{e}" + end + $stdout.write "F".colorize(:red) + next + end + end + + case element.name + when "pre" + fn = "example-#{"%03d" % example_number}-#{title.gsub(/[^\w]+/, '-')}.#{ext}" + examples[example_number] = { + title: title, + filename: fn, + content: content + } + #puts "example #{example_number}: #{content}" + when "script" + # Validate the previous example appropriately + else + errors << "Example #{example_number} at line #{element.line} has unknown element type #{element.name}" + $stdout.write "F".colorize(:red) + next + end + + if warn + $stdout.write "w".colorize(:yellow) + else + $stdout.write ".".colorize(:green) + end + end + end + + $stdout.puts "\nWarnings:" unless warnings.empty? + warnings.each {|e| $stdout.puts " #{e}".colorize(:yellow)} + $stdout.puts "\nErrors:" unless errors.empty? + errors.each {|e| $stdout.puts " #{e}".colorize(:red)} + num_errors += errors.length + + if example_dir + # Make examples directory + FileUtils::mkdir_p(example_dir) + examples.each do |num, ex| + File.open(File.join(example_dir, ex[:filename]), 'w') {|f| f.write(ex[:content])} + end + end +end + +if num_errors == 0 + $stdout.puts "\nok".colorize(:green) +else + exit(1) +end + +exit(0) \ No newline at end of file