summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/conformance-checkers/tools
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /testing/web-platform/tests/conformance-checkers/tools
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/web-platform/tests/conformance-checkers/tools')
-rw-r--r--testing/web-platform/tests/conformance-checkers/tools/build-svg-tests.py252
-rw-r--r--testing/web-platform/tests/conformance-checkers/tools/ins-del-datetime.py176
-rw-r--r--testing/web-platform/tests/conformance-checkers/tools/picture.py364
-rw-r--r--testing/web-platform/tests/conformance-checkers/tools/url.py454
4 files changed, 1246 insertions, 0 deletions
diff --git a/testing/web-platform/tests/conformance-checkers/tools/build-svg-tests.py b/testing/web-platform/tests/conformance-checkers/tools/build-svg-tests.py
new file mode 100644
index 000000000..3986a8dca
--- /dev/null
+++ b/testing/web-platform/tests/conformance-checkers/tools/build-svg-tests.py
@@ -0,0 +1,252 @@
+#!/usr/bin/env python2.7
+
+# Copyright (c) 2016 PowerMapper Software
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+"""build_svg_tests.py.
+
+This script builds a set of SVG-in-HTML test files for the Nu Html Checker
+based on the SVG 1.1 Second Edition Test Suite
+http://www.w3.org/Graphics/SVG/Test/20110816/archives/W3C_SVG_11_TestSuite.tar.gz
+
+"""
+
+import logging
+import os
+import sys, getopt
+import urllib2
+
+# some files in the SVG 1.1 test suite don't validate against the SVG 1.1 DTD
+# but are valid against the HTML 5 spec
+
+valid_svg_files = dict([
+ # these entries manually added after cross checking behaviour with spec
+
+ # VNU warns about text not in Unicode Normalization Form C, but it's not an error
+ ('struct-cond-02-t-manual.svg', 'Source text is not in Unicode Normalization Form C'),
+ # FiLl, fill and FILL are all valid in case-insensitive HTML (but SVG DTD is case-sensitive)
+ ('styling-css-10-f-manual.svg', 'Attribute FiLl not allowed on SVG element circle at this point')
+])
+
+# some files in the SVG 1.1 test suite don't validate against the SVG 1.1 DTD
+# and some files are marked as version='SVG 1.2'.
+# this is used to toggle between -isvalid.html and -novalid.html output
+
+invalid_svg_files = dict([
+ # 'DTD Invalid' entries are produced by calling validate_svg_dtd (see below)
+ ('animate-elem-24-t-manual.svg', 'DTD Invalid'),
+ ('animate-elem-77-t-manual.svg', 'DTD Invalid'),
+ ('animate-pservers-grad-01-b-manual.svg', 'DTD Invalid'),
+ ('conform-viewers-03-f-manual.svg', 'DTD Invalid'),
+ ('coords-dom-01-f-manual.svg', 'DTD Invalid'),
+ ('coords-dom-02-f-manual.svg', 'DTD Invalid'),
+ ('extend-namespace-01-f-manual.svg', 'DTD Invalid'),
+ ('filters-color-02-b-manual.svg', 'DTD Invalid'),
+ ('filters-conv-02-f-manual.svg', 'DTD Invalid'),
+ ('filters-conv-04-f-manual.svg', 'DTD Invalid'),
+ ('filters-conv-05-f-manual.svg', 'DTD Invalid'),
+ ('filters-light-05-f-manual.svg', 'DTD Invalid'),
+ ('fonts-glyph-04-t-manual.svg', 'DTD Invalid'),
+ ('interact-pointer-02-t-manual.svg', 'DTD Invalid'),
+ ('linking-a-09-b-manual.svg', 'DTD Invalid'),
+ ('linking-a-10-f-manual.svg', 'DTD Invalid'),
+ ('masking-filter-01-f-manual.svg', 'DTD Invalid'),
+ ('masking-intro-01-f-manual.svg', 'DTD Invalid'),
+ ('painting-marker-04-f-manual.svg', 'DTD Invalid'),
+ ('paths-data-18-f-manual.svg', 'DTD Invalid'),
+ ('paths-data-20-f-manual.svg', 'DTD Invalid'),
+ ('pservers-grad-23-f-manual.svg', 'DTD Invalid'),
+ ('render-elems-03-t-manual.svg', 'DTD Invalid'),
+ ('shapes-rect-03-t-manual.svg', 'DTD Invalid'),
+ ('struct-cond-02-t-manual.svg', 'DTD Invalid'),
+ ('struct-dom-17-f-manual.svg', 'DTD Invalid'),
+ ('struct-dom-19-f-manual.svg', 'DTD Invalid'),
+ ('struct-frag-05-t-manual.svg', 'DTD Invalid'),
+ ('struct-image-12-b-manual.svg', 'DTD Invalid'),
+ ('struct-use-11-f-manual.svg', 'DTD Invalid'),
+ ('struct-use-12-f-manual.svg', 'DTD Invalid'),
+ ('styling-css-10-f-manual.svg', 'DTD Invalid'),
+ ('styling-pres-02-f-manual.svg', 'DTD Invalid'),
+ ('svgdom-over-01-f-manual.svg', 'DTD Invalid'),
+ ('text-dom-03-f-manual.svg', 'DTD Invalid'),
+ ('text-fonts-03-t-manual.svg', 'DTD Invalid'),
+ ('text-fonts-05-f-manual.svg', 'DTD Invalid'),
+ ('text-tref-02-b-manual.svg', 'DTD Invalid'),
+ ('types-dom-04-b-manual.svg', 'DTD Invalid'),
+
+ # these entries manually added after cross checking behaviour with spec
+ # note there are some confusing differences between w:iri-ref (used in HTML for img/@src)
+ # and xsd:anyURI (used in SVG for image/@xlink:href)
+ ('conform-viewers-02-f-manual.svg', 'Newlines in data: URI - not allowed by URL Standard or RFC 2397.'),
+ ('coords-transformattr-01-f-manual.svg', 'Numeric character reference expanded to carriage return - not allowed in HTML5 - see 8.1.4'),
+ ('fonts-overview-201-t-manual.svg', 'Unsupported SVG version specified - specifies SVG 1.2'),
+ ('script-specify-01-f-manual.svg', 'Attribute contentscripttype not allowed on element svg at this point - not allowed in HTML5 - see 4.8.18 SVG'),
+ ('types-dom-04-b-manual.svg', 'Attribute externalresourcesrequired not allowed on element svg at this point - not allowed in HTML5 - see 4.8.18 SVG'),
+ ('metadata-example-01-t-manual.svg', 'Element rdf:rdf not allowed as child of element metadata in this context - namespaced XML not allowed in HTML5')
+])
+
+# TODO Github Issue #216 MathML and SVG uses xsd:anyURI, HTML URLs use URL Standard
+# TODO Github Issue #217 NU has script/@type optional for HTML, but not SVG-in-HTML
+
+def build_html_testfiles(svgdirectory,htmldirectory):
+ """Builds HTML test files from SVG test suite folder."""
+
+ logging.debug('build_html_testfiles: IN')
+
+ testfiles = []
+
+ for filename in os.listdir(svgdirectory):
+ #logging.debug(filename)
+ if filename.endswith(".svg"):
+ htmlpathname = build_html_test_file(filename, svgdirectory, htmldirectory)
+ if htmlpathname:
+ testfiles.append(htmlpathname)
+ pass
+ pass
+
+
+def build_html_test_file(filename, svgdirectory, htmldirectory):
+ """Builds HTML test file by wrapping input SVG in boilerplate HTML."""
+
+ svgpathname = svgdirectory + "/" + filename
+
+ # valid_svg_file overrides invalid_svg_files (may invalid in case-sensitive XML but valid in case-insensitive HTML)
+ if invalid_svg_files.has_key(filename) and not valid_svg_files.has_key(filename):
+ htmlpathname = htmldirectory + "/" + filename.replace( "-manual.svg", "-novalid.html")
+ else:
+ htmlpathname = htmldirectory + "/" + filename.replace( "-manual.svg", "-isvalid.html")
+
+ logging.debug(svgpathname)
+ logging.debug(htmlpathname)
+
+ # read SVG data
+ svgfile = open(svgpathname, "rU")
+ svg = svgfile.read()
+ svgfile.close()
+
+ # but remove <d:SVGTestCase> from file (not valid in HTML or SVG DTD)
+ svg = svg.replace('<?xml version="1.0" encoding="UTF-8"?>', '')
+ svgbefore = svg.split("<d:SVGTestCase")[0];
+ svgafter = svg.split("</d:SVGTestCase>")[1];
+ svg = svgbefore + svgafter
+
+ # ignore files with SVG DOCTYPE and !ENTITY declarations (unsupported in HTML)
+ if svg.find( "<!DOCTYPE" ) != -1:
+ return
+
+ # uncomment these 2 lines to generate 'DTD Invalid' entries for invalid_svg_files dict above
+ # very slow operation - only needs done if the SVG test suite ever changes
+ # when uncommented expect to see AttributeError: 'NoneType' object has no attribute 'find'
+ #validate_svg_dtd(filename, svg)
+ #return
+
+ htmlfile = open(htmlpathname, "w")
+
+ htmlfile.write("<!DOCTYPE html>\n")
+ htmlfile.write("<html lang='en'>\n")
+
+ htmlfile.write("<head>\n")
+ htmlfile.write(" <title>%s</title>\n" % os.path.basename(svgpathname) )
+ htmlfile.write(" <meta charset='utf-8'>\n")
+ htmlfile.write("</head>\n")
+
+ htmlfile.write("<body>\n")
+ htmlfile.write(" <h1>Source SVG: %s</h1>\n" % os.path.basename(svgpathname) )
+
+ # insert SVG without any XML processing to avoid unexpected transformations on
+ # encoding and entity refs, but remove <d:SVGTestCase> from file (not valid in HTML)
+ htmlfile.write(svgbefore)
+ htmlfile.write(svgafter)
+
+ htmlfile.write("</body>\n")
+
+ htmlfile.write("</html>\n")
+ htmlfile.close()
+
+ return htmlpathname
+
+def create_dir_if_missing(directory):
+ """Create the given directory if it doesn't exist"""
+
+ d = os.path.dirname(directory)
+ if not os.path.exists(directory):
+ os.makedirs(directory)
+
+
+def validate_svg_dtd(filename,svg):
+ """Prints legacy DTD markup validation status to stdout in a format suitable for pasting into invalid_svg_files dict above."""
+
+ # setup multipart/form-data POST body
+ body = ''
+ body = body + '--AaB03x\r\n'
+ body = body + 'Content-Disposition: form-data; name="fieldname"\r\n'
+ body = body + '\r\n'
+ body = body + 'value\r\n'
+ body = body + '--AaB03x\r\n'
+ body = body + 'Content-Disposition: form-data; name="uploaded_file"; filename="test.svg"\r\n'
+ body = body + 'Content-Type: image/svg+xml\r\n'
+ body = body + '\r\n'
+ body = body + svg
+ body = body + '\r\n'
+ body = body + '--AaB03x--\r\n'
+
+ # send request to W3 DTD validator for SVG 1.1 validation
+ headers = { "Content-type" : "multipart/form-data; boundary=AaB03x", "Content-length" : len(body) }
+ request = urllib2.Request("http://validator.w3.org/check?charset=utf-8&doctype=SVG+1.1&output=json", data=body, headers=headers)
+ response = urllib2.urlopen(request, timeout=60)
+
+ status = response.info().getheader('X-W3C-Validator-Status')
+ logging.debug(status)
+
+ if status == "Valid":
+ return True
+
+ print " ('%s', 'DTD %s')," % (filename, status)
+ return False
+
+
+def main():
+
+ #logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
+ logging.debug('main: IN')
+
+ ccdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+ svgdirectory = os.path.join(os.path.dirname(ccdir), "svg", "import")
+ htmldirectory = os.path.join(ccdir, "html-svg")
+
+ try:
+ opts, args = getopt.getopt(sys.argv[1:],"",["svgdir=","outdir="])
+ except getopt.GetoptError:
+ print 'build-svg-tests.py --svgdir <indir> --outdir <outdir>'
+ sys.exit(2)
+
+ for opt, arg in opts:
+ print opt, arg
+ if opt in ("-s", "--svgdir"):
+ svgdirectory = arg
+ elif opt in ("-o", "--outdir"):
+ htmldirectory = arg
+
+
+ create_dir_if_missing(htmldirectory)
+ build_html_testfiles(svgdirectory, htmldirectory)
+
+
+main()
diff --git a/testing/web-platform/tests/conformance-checkers/tools/ins-del-datetime.py b/testing/web-platform/tests/conformance-checkers/tools/ins-del-datetime.py
new file mode 100644
index 000000000..3767a7d70
--- /dev/null
+++ b/testing/web-platform/tests/conformance-checkers/tools/ins-del-datetime.py
@@ -0,0 +1,176 @@
+# -*- coding: utf-8 -*-
+import os
+ccdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+template = """<!DOCTYPE html>
+<meta charset=utf-8>
+"""
+errors = {
+ "date-year-0000": "0000-12-09",
+ "date-month-00": "2002-00-15",
+ "date-month-13": "2002-13-15",
+ "date-0005-02-29": "0005-02-29",
+ "date-1969-02-29": "1969-02-29",
+ "date-1900-02-29": "1900-02-29",
+ "date-2100-02-29": "2100-02-29",
+ "date-2200-02-29": "2200-02-29",
+ "date-2014-02-29": "2014-02-29",
+ "date-day-04-31": "2002-04-31",
+ "date-day-06-31": "2002-06-31",
+ "date-day-09-31": "2002-09-31",
+ "date-day-11-31": "2002-11-31",
+ "date-day-01-32": "2002-01-32",
+ "date-day-03-32": "2002-03-32",
+ "date-day-05-32": "2002-05-32",
+ "date-day-07-32": "2002-07-32",
+ "date-day-08-32": "2002-08-32",
+ "date-day-10-32": "2002-10-32",
+ "date-day-12-32": "2002-12-32",
+ "date-iso8601-YYYYMMDD-no-hyphen": "20020929",
+ "date-leading-whitespace": " 2002-09-29",
+ "date-trailing-whitespace": "2002-09-29 ",
+ "date-month-one-digit": "2002-9-29",
+ "date-month-three-digits": "2002-011-29",
+ "date-year-three-digits": "782-09-29",
+ "date-day-one-digit": "2002-09-9",
+ "date-day-three-digits": "2002-11-009",
+ "date-day-missing-separator": "2014-0220",
+ "date-month-missing-separator": "201402-20",
+ "date-non-ascii-digit": "2002-09-29",
+ "date-trailing-U+0000": "2002-09-29&#x0000;",
+ "date-trailing-pile-of-poo": "2002-09-29💩",
+ "date-wrong-day-separator": "2014-02:20",
+ "date-wrong-month-separator": "2014:02-20",
+ "date-year-negative": "-2002-09-29",
+ "date-leading-bom": "2002-09-29",
+ "global-date-and-time-60-minutes": "2011-11-12T00:60:00+08:00",
+ "global-date-and-time-60-seconds": "2011-11-12T00:00:60+08:00",
+ "global-date-and-time-2400": "2011-11-12T24:00:00+08:00",
+ "global-date-and-time-space-before-timezone": "2011-11-12T06:54:39 08:00",
+ "global-date-and-time-hour-one-digit": "2011-11-12T6:54:39-08:00",
+ "global-date-and-time-hour-three-digits": "2011-11-12T016:54:39-08:00",
+ "global-date-and-time-minutes-one-digit": "2011-11-12T16:4:39-08:00",
+ "global-date-and-time-minutes-three-digits": "2011-11-12T16:354:39-08:00",
+ "global-date-and-time-seconds-one-digit": "2011-11-12T16:54:9-08:00",
+ "global-date-and-time-seconds-three-digits": "2011-11-12T16:54:039-08:00",
+ "global-date-and-time-timezone-with-seconds": "2011-11-12T06:54:39-08:00:00",
+ "global-date-and-time-timezone-60-minutes": "2011-11-12T06:54:39-08:60",
+ "global-date-and-time-timezone-one-digit-hour": "2011-11-12T06:54:39-5:00",
+ "global-date-and-time-timezone-one-digit-minute": "2011-11-12T06:54:39-05:0",
+ "global-date-and-time-timezone-three-digit-hour": "2011-11-12T06:54:39-005:00",
+ "global-date-and-time-timezone-three-digit-minute": "2011-11-12T06:54:39-05:000",
+ "global-date-and-time-nbsp": "2011-11-12 14:54Z",
+ "global-date-and-time-missing-minutes-separator": "2011-11-12T1454Z",
+ "global-date-and-time-missing-seconds-separator": "2011-11-12T14:5439Z",
+ "global-date-and-time-wrong-minutes-separator": "2011-11-12T14-54Z",
+ "global-date-and-time-wrong-seconds-separator": "2011-11-12T14:54-39Z",
+ "global-date-and-time-lowercase-z": "2011-11-12T14:54z",
+ "global-date-and-time-with-both-T-and-space": "2011-11-12T 14:54Z",
+ "global-date-and-time-zero-digit-fraction": "2011-11-12T06:54:39.-08:00",
+ "global-date-and-time-four-digit-fraction": "2011-11-12T06:54:39.9291-08:00",
+ "global-date-and-time-bad-fraction-separator": "2011-11-12T14:54:39,929+0000",
+ "global-date-and-time-timezone-non-T-character": "2011-11-12+14:54Z",
+ "global-date-and-time-timezone-lowercase-t": "2011-11-12t14:54Z",
+ "global-date-and-time-timezone-multiple-spaces": "2011-11-12 14:54Z",
+ "global-date-and-time-timezone-offset-space-start": "2011-11-12T06:54:39.929 08:00",
+ "global-date-and-time-timezone-offset-colon-start": "2011-11-12T06:54:39.929:08:00",
+ "global-date-and-time-timezone-plus-2400": "2011-11-12T06:54:39-24:00",
+ "global-date-and-time-timezone-minus-2400": "2011-11-12T06:54:39-24:00",
+ "global-date-and-time-timezone-iso8601-two-digit": "2011-11-12T06:54:39-08",
+ "global-date-and-time-iso8601-hhmmss-no-colon": "2011-11-12T145439Z",
+ "global-date-and-time-iso8601-hhmm-no-colon": "2011-11-12T1454Z",
+ "global-date-and-time-iso8601-hh": "2011-11-12T14Z",
+ "year": "2006",
+ "yearless-date": "07-15",
+ "month": "2011-11",
+ "week": "2011-W46",
+ "time": "14:54:39",
+ "local-date-and-time": "2011-11-12T14:54",
+ "duration-P-form": "PT4H18M3S",
+ "duration-time-component": "4h 18m 3s",
+}
+
+warnings = {
+ "global-date-and-time-timezone-plus-1500": "2011-11-12T00:00:00+1500",
+ "global-date-and-time-timezone-minus-1300": "2011-11-12T00:00:00-1300",
+ "global-date-and-time-timezone-minutes-15": "2011-11-12T00:00:00+08:15",
+ "date-0214-09-29": "0214-09-29",
+ "date-20014-09-29": "20014-09-29",
+ "date-0004-02-29": "0004-02-29",
+ "date-year-five-digits": "12014-09-29",
+}
+
+non_errors = {
+ "date": "2002-09-29",
+ "date-2000-02-29": "2000-02-29",
+ "date-2400-02-29": "2400-02-29",
+ "date-1968-02-29": "1968-02-29",
+ "date-1900-02-28": "1900-02-28",
+ "date-2100-02-28": "2100-02-28",
+ "date-2100-02-28": "2100-02-28",
+ "date-2200-02-28": "2200-02-28",
+ "date-2014-02-28": "2014-02-28",
+ "date-day-01-31": "2002-01-31",
+ "date-day-03-31": "2002-03-31",
+ "date-day-05-31": "2002-05-31",
+ "date-day-07-31": "2002-07-31",
+ "date-day-08-31": "2002-08-31",
+ "date-day-10-31": "2002-10-31",
+ "date-day-12-31": "2002-12-31",
+ "date-day-04-30": "2002-04-30",
+ "date-day-06-30": "2002-06-30",
+ "date-day-09-30": "2002-09-30",
+ "date-day-11-30": "2002-11-30",
+ "global-date-and-time-no-seconds": "2011-11-12T14:54Z",
+ "global-date-and-time-with-seconds": "2011-11-12T14:54:39+0000",
+ "global-date-and-time-with-one-digit-fraction": "2011-11-12T06:54:39.9-08:00",
+ "global-date-and-time-with-two-digit-fraction": "2011-11-12T06:54:39.92+07:00",
+ "global-date-and-time-with-three-digit-fraction": "2011-11-12T06:54:39.929-06:00",
+ "global-date-and-time-space": "2011-11-12 14:54Z",
+ "global-date-and-time-timezone": "2011-11-12T06:54:39+0900",
+ "global-date-and-time-timezone-30": "2011-11-12T06:54:39-0830",
+ "global-date-and-time-timezone-45": "2011-11-12T06:54:39-0845",
+ "global-date-and-time-timezone-with-colon": "2011-11-12T06:54:39-08:00",
+ "global-date-and-time-timezone-without-colon": "2011-11-12T06:54:39-0800",
+}
+
+for key in errors.keys():
+ error = errors[key]
+ template_ins = template
+ template_del = template
+ template_ins += '<title>%s</title>\n' % key
+ template_del += '<title>%s</title>\n' % key
+ template_ins += '<ins datetime="%s"></ins>' % errors[key]
+ template_del += '<del datetime="%s"></del>' % errors[key]
+ ins_file = open(os.path.join(ccdir, "html/elements/ins/%s-novalid.html" % key), 'wb')
+ ins_file.write(template_ins)
+ ins_file.close()
+ del_file = open(os.path.join(ccdir, "html/elements/del/%s-novalid.html" % key), 'wb')
+ del_file.write(template_del)
+ del_file.close()
+
+for key in warnings.keys():
+ non_error = warnings[key]
+ template_ins = template
+ template_del = template
+ template_ins += '<title>%s</title>\n' % key
+ template_del += '<title>%s</title>\n' % key
+ template_ins += '<ins datetime="%s"></ins>' % warnings[key]
+ template_del += '<del datetime="%s"></del>' % warnings[key]
+ ins_file = open(os.path.join(ccdir, "html/elements/ins/%s-haswarn.html" % key), 'wb')
+ ins_file.write(template_ins)
+ ins_file.close()
+ del_file = open(os.path.join(ccdir, "html/elements/del/%s-haswarn.html" % key), 'wb')
+ del_file.write(template_del)
+ del_file.close()
+
+ins_file = open(os.path.join(ccdir, "html/elements/ins/datetime-isvalid.html"), 'wb')
+del_file = open(os.path.join(ccdir, "html/elements/del/datetime-isvalid.html"), 'wb')
+ins_file.write(template + '<title>valid datetime</title>\n')
+del_file.write(template + '<title>valid datetime</title>\n')
+for key in non_errors.keys():
+ non_error = non_errors[key]
+ ins_file.write('<ins datetime="%s"></ins> <!-- %s -->\n' % (non_errors[key], key))
+ del_file.write('<del datetime="%s"></del> <!-- %s -->\n' % (non_errors[key], key))
+ins_file.close()
+del_file.close()
+# vim: ts=4:sw=4
diff --git a/testing/web-platform/tests/conformance-checkers/tools/picture.py b/testing/web-platform/tests/conformance-checkers/tools/picture.py
new file mode 100644
index 000000000..5b03f67ac
--- /dev/null
+++ b/testing/web-platform/tests/conformance-checkers/tools/picture.py
@@ -0,0 +1,364 @@
+# -*- coding: utf-8 -*-
+import os
+ccdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+template = """<!DOCTYPE html>
+<meta charset=utf-8>
+"""
+
+errors = {
+ # missing src on img
+ "img-no-src": "<img alt>",
+ "img-no-src-with-srcset": "<img srcset=x alt>",
+ "img-no-src-with-picture": "<picture><img alt></picture>",
+ "img-no-src-with-srcset-and-picture": "<picture><img srcset=x alt></picture>",
+ "img-no-src-with-source": "<picture><source srcset=x><img alt></picture>",
+ # junk content in picture
+ "junk-text-before-img": "<picture>x<img src=x alt></picture>",
+ "junk-text-after-img": "<picture><img src=x alt>x</picture>",
+ "junk-text-before-source": "<picture>x<source srcset=x><img src=x alt></picture>",
+ "junk-text-after-source": "<picture><source srcset=x>x<img src=x alt></picture>",
+ "junk-br-before-img": "<picture><br><img src=x alt></picture>",
+ "junk-br-after-img": "<picture><img src=x alt><br></picture>",
+ "junk-br-before-source": "<picture><br><source srcset=x><img src=x alt></picture>",
+ "junk-br-after-source": "<picture><source srcset=x><br><img src=x alt></picture>",
+ "junk-video-before": "<picture><video></video><source srcset=x><img src=x alt></picture>",
+ "junk-video-no-img": "<picture><video></video></picture>",
+ "junk-p-before": "<picture><p></p><source srcset=x><img src=x alt></picture>",
+ "junk-p-after": "<picture><source srcset=x><img src=x alt><p></p></picture>",
+ "junk-p-wrapping": "<picture><p><source srcset=x><img src=x alt></p></picture>",
+ "junk-span-before": "<picture><span></span><source srcset=x><img src=x alt></picture>",
+ "junk-span-after": "<picture><source srcset=x><img src=x alt><span></span></picture>",
+ "junk-span-wrapping": "<picture><span><source srcset=x><img src=x alt></span></picture>",
+ "junk-picture-before": "<picture><picture><img src=x alt></picture><img src=x alt></picture>",
+ "junk-picture-wrapping": "<picture><picture><img src=x alt></picture></picture>",
+ "junk-figure-wrapping": "<picture><figure><img src=x alt></figure></picture>",
+ "junk-input-type-hidden": "<picture><input type=hidden name=x value=x><img src=x alt></picture>",
+ "junk-style-scroped": "<picture><style scroped></style><img src=x alt></picture>",
+ "junk-noscript": "<picture><img src=x alt><noscript></noscript></picture>",
+ "junk-noscript-after-source-no-img": "<picture><source srcset=x><noscript><img src=x alt></noscript></picture>",
+ "junk-svg": "<picture><img src=x alt><svg></svg></picture>",
+ "junk-svg-no-img": "<picture><svg></svg></picture>",
+ "junk-math-nog-img": "<picture><math></math></picture>",
+ # parents
+ "parent-ul": "<ul><picture><img src=x alt></picture></ul>",
+ "parent-dl": "<dl><picture><img src=x alt></picture></dl>",
+ "parent-hgroup": "<hgroup><h1>x</h1><picture><img src=x alt></picture></hgroup>",
+ "parent-noscript-in-head": "<noscript><picture><img src=x alt></picture></noscript>",
+ # invalid html syntax
+ "html-syntax-source-end-tag": "<picture><source srcset=x></source><img src=x alt></picture>",
+ "html-syntax-img-end-tag": "<picture><img src=x alt></img></picture>",
+ "html-syntax-picture-no-end-tag": "<picture><img src=x alt>",
+ "html-syntax-picture-slash": "<picture/><img src=x alt></picture>",
+ "html-syntax-picture-slash-no-end-tag": "<picture/><img src=x alt>",
+ # missing img in picture
+ "missing-img-empty-picture": "<picture></picture>",
+ "missing-img-only-source": "<picture><source srcset=x></picture>",
+ "missing-img-only-script": "<picture><script></script></picture>",
+ "missing-img-script-and-source": "<picture><script></script><source srcset=x></picture>",
+ "missing-img-source-and-script": "<picture><source srcset=x><script></script></picture>",
+ # multiple img in picture
+ "multiple-img": "<picture><img src=x alt><img src=x alt></picture>",
+ "multiple-img-with-script": "<picture><img src=x alt><script></script><img src=x alt></picture>",
+ "multiple-img-with-source": "<picture><source srcset=x><img src=x alt><img src=x alt></picture>",
+ "multiple-img-with-source-and-script": "<picture><source srcset=x><img src=x alt><script></script><img src=x alt></picture>",
+ # source after img
+ "source-after-img": "<picture><img src=x alt><source srcset=x></picture>",
+ "source-before-and-after-img": "<picture><source srcset=x><img src=x alt><source srcset=x></picture>",
+ # source with following sibling source element or img element with a srcset attribute
+ "always-matching-source-with-following-img-srcset": "<picture><source srcset=x><img src=x srcset=x alt></picture>",
+ "always-matching-source-with-following-source-srcset": "<picture><source srcset=x><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-with-following-source-media": "<picture><source srcset=x><source srcset=x media=screen><img src=x alt></picture>",
+ "always-matching-source-with-following-source-type": "<picture><source srcset=x><source srcset=x type=image/gif><img src=x alt></picture>",
+ "always-matching-source-media-empty-with-following-source-srcset": "<picture><source srcset=x media><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-media-spaces-with-following-source-srcset": "<picture><source srcset=x media=' \n\t'><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-media-all-with-following-source-srcset": "<picture><source srcset=x media=all><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-media-uppercase-with-following-source-srcset": "<picture><source srcset=x media=ALL><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-media-all-spaces-with-following-source-srcset": "<picture><source srcset=x media=' all '><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-sizes-with-following-source-srcset": "<picture><source srcset='x 100w' sizes=50vw><source srcset=x><img src=x alt></picture>",
+ # sizes present
+ "img-srcset-no-descriptor-with-sizes": "<img src=x srcset='x' sizes=50vw alt>",
+ "img-srcset-w-and-x-width-sizes": "<img src=x srcset='x 100w, y 2x' sizes=50vw alt>",
+ "source-srcset-x-with-sizes": "<picture><source srcset='x 1x, y 2x' sizes=50vw><img src=x alt></picture>",
+ "source-srcset-h-with-sizes": "<picture><source srcset='x 100h, y 200h' sizes=50vw><img src=x alt></picture>",
+ "source-srcset-w-and-x-with-sizes": "<picture><source srcset='x 100w, y 2x' sizes=50vw><img src=x alt></picture>",
+ "img-with-sizes-no-srcset": "<img sizes=50vw src=foo alt>",
+ # width descriptor without sizes
+ "img-srcset-w-no-sizes": "<img srcset='x 100w, y 200w' src=x alt>",
+ "source-srcset-w-no-sizes": "<picture><source srcset='x 100w, y 200w'><img src=x alt></picture>",
+ "source-type-srcset-w": "<picture><source srcset='x 100w, y 200w' type=image/gif><img src=x alt></picture>",
+ # invalid attributes on source
+ "source-src": "<picture><source src=x><img src=x alt></picture>",
+ "source-src-srcset": "<picture><source src=x srcset=x><img src=x alt></picture>",
+ "source-alt": "<picture><source srcset=x alt><img src=x alt></picture>",
+ "source-width": "<picture><source srcset=x width=100><img src=x alt></picture>",
+ "source-height": "<picture><source srcset=x height=100><img src=x alt></picture>",
+ "source-usemap": "<picture><source srcset=x usemap><img src=x alt></picture>",
+ "source-ismap": "<picture><source srcset=x ismap><img src=x alt></picture>",
+ "source-crossorigin": "<picture><source srcset=x crossorigin><img src=x alt></picture>",
+ "source-name": "<picture><source srcset=x crossorigin><img src=x alt></picture>",
+ "source-align": "<picture><source srcset=x align=left><img src=x alt></picture>",
+ "source-hspace": "<picture><source srcset=x hspace=1><img src=x alt></picture>",
+ "source-vspace": "<picture><source srcset=x vspace=1><img src=x alt></picture>",
+ "source-longdesc": "<picture><source srcset=x longdesc=x><img src=x alt></picture>",
+ "source-border": "<picture><source srcset=x border=1><img src=x alt></picture>",
+ # missing srcset on source
+ "source-no-srcset": "<picture><source><img src=x alt></picture>",
+ "source-no-srcset-with-sizes": "<picture><source sizes=50vw><img src=x alt></picture>",
+ "source-no-srcset-with-media": "<picture><source media=screen><img src=x alt></picture>",
+ "source-no-srcset-with-type": "<picture><source type='image/webp'><img src=x alt></picture>",
+ # invalid attributes on picture
+ "picture-src": "<picture src=x><img src=x alt></picture>",
+ "picture-srcset": "<picture srcset=x><img src=x alt></picture>",
+ "picture-media": "<picture media=screen><img src=x alt></picture>",
+ "picture-sizes": "<picture sizes=50vw><img src=x alt></picture>",
+ "picture-alt": "<picture alt><img src=x alt></picture>",
+ "picture-width": "<picture width=100><img src=x alt></picture>",
+ "picture-height": "<picture height=100><img src=x alt></picture>",
+ "picture-usemap": "<picture usemap><img src=x alt></picture>",
+ "picture-ismap": "<picture ismap><img src=x alt></picture>",
+ "picture-crossorigin": "<picture crossorigin><img src=x alt></picture>",
+ "picture-name": "<picture name=x><img src=x alt></picture>",
+ "picture-lowsrc": "<picture lowsrc=x><img src=x alt></picture>",
+ "picture-align": "<picture align=left><img src=x alt></picture>",
+ "picture-hspace": "<picture hspace=1><img src=x alt></picture>",
+ "picture-vspace": "<picture vspace=1><img src=x alt></picture>",
+ "picture-longdesc": "<picture longdesc=x><img src=x alt></picture>",
+ "picture-border": "<picture border=1><img src=x alt></picture>",
+ # invalid attributes on source in video
+ "video-source-srcset": "<video><source srcset=x></video>",
+ "video-source-srcset-src": "<video><source srcset=x src=x></video>",
+ "video-source-sizes-srcset": "<video><source sizes=50vw srcset='x 100w'></video>",
+ "video-source-media-src": "<video><source media=screen src=x></video>",
+ # srcset on other elements
+ "link-rel-icon-srcset": "<link rel=icon srcset=x href=x>",
+ "input-type-image-srcset": "<input type=image src=x srcset=x alt=x>",
+ "object-srcset": "<object data=x srcset=x></object>",
+ "video-srcset": "<video src=x srcset=x></video>",
+ "audio-srcset": "<audio src=x srcset=x></audio>",
+ "track-srcset": "<video src=x><track src=x srcset=x></video>",
+ "svg-image-srcset": "<svg><image xlink:href=x srcset=x width=1 height=1 /></svg>",
+ # invalid attributes on img
+ "img-type": "<img src=x type=image/gif alt>",
+ "img-type-with-picture": "<picture><img src=x type=image/gif alt></picture>",
+ # sizes microsyntax
+ "sizes-microsyntax-media-all": "<img sizes='all 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-media-all-and-min-width": "<img sizes='all and (min-width:500px) 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-media-min-width-no-parenthesis": "<img sizes='min-width:500px 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-media-general-enclosed-junk": "<img sizes='(123) 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-media-bad-junk": "<img sizes='(}) 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-two-defaults": "<img sizes='500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-default-first": "<img sizes='100vw, (min-width:500px) 500px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-trailing-comma": "<img sizes='(min-width:500px) 500px, 100vw,' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-trailing-junk": "<img sizes='(min-width:500px) 500px, 100vw, foo bar' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-junk-in-default": "<img sizes='(min-width:500px) 500px, 100vw foo bar' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-junk-in-source-size": "<img sizes='(min-width:500px) 500px foo bar, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-percent-in-source-size-value": "<img sizes='(min-width:500px) 50%, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-no-unit-in-source-size-value": "<img sizes='(min-width:500px) 50, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-deg-source-size-value": "<img sizes='1deg' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-grad-source-size-value": "<img sizes='1grad' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-rad-source-size-value": "<img sizes='1rad' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-turn-source-size-value": "<img sizes='1turn' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-s-source-size-value": "<img sizes='1s' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-ms-source-size-value": "<img sizes='1ms' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-hz-source-size-value": "<img sizes='1Hz' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-khz-source-size-value": "<img sizes='1kHz' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-dpi-source-size-value": "<img sizes='1dpi' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-dpcm-source-size-value": "<img sizes='1dpcm' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-dppx-source-size-value": "<img sizes='1dppx' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-auto-source-size-value": "<img sizes='auto' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-inherit-source-size-value": "<img sizes='inherit' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-initial-source-size-value": "<img sizes='initial' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-default-source-size-value": "<img sizes='default' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-foo-bar-source-size-value": "<img sizes='foo-bar' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-negative-source-size-value": "<img sizes='-1px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-empty": "<img sizes='' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-comma": "<img sizes=',' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-css-comment-after-plus": "<img sizes='+/**/50vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-css-comment-before-unit": "<img sizes='50/**/vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientific-notation-negative": "<img sizes='-1e+0px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientific-notation-non-integer-in-exponent": "<img sizes='1e+1.5px' srcset='x 100w, y 200w' src=x alt>",
+ # srcset microsyntax
+ "srcset-microsyntax-leading-comma": "<img srcset=',x' src=x alt>",
+ "srcset-microsyntax-leading-comma-multiple": "<img srcset=',,,x' src=x alt>",
+ "srcset-microsyntax-trailing-comma": "<img srcset='x,' src=x alt>",
+ "srcset-microsyntax-trailing-comma-multiple": "<img srcset='x,,,' src=x alt>",
+ "srcset-microsyntax-broken-url": "<img srcset='http: 1x' src=x alt>",
+ "srcset-microsyntax-non-integer-w": "<img srcset='x 1.5w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-uppercase-w": "<img srcset='x 1W' sizes=100vw src=x alt>",
+ "srcset-microsyntax-plus-w": "<img srcset='x +1w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-scientific-notation-w": "<img srcset='x 1e0w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-zero-w": "<img srcset='x 0w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-negative-zero-w": "<img srcset='x -0w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-negative-w": "<img srcset='x -1w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-plus-x": "<img srcset='x +1x' src=x alt>",
+ "srcset-microsyntax-negative-x": "<img srcset='x -1x' src=x alt>",
+ "srcset-microsyntax-zero-x": "<img srcset='x 0x' src=x alt>",
+ "srcset-microsyntax-negative-zero-x": "<img srcset='x -0x' src=x alt>",
+ "srcset-microsyntax-leading-dot-x": "<img srcset='x .5x' src=x alt>",
+ "srcset-microsyntax-nan-x": "<img srcset='x NaNx' src=x alt>",
+ "srcset-microsyntax-infinity-x": "<img srcset='x Infinityx' src=x alt>",
+ "srcset-microsyntax-x-and-w": "<img srcset='x 1x 1w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-x-and-h": "<img srcset='x 1x 1h' sizes=100vw src=x alt>",
+ "srcset-microsyntax-w-and-h": "<img srcset='x 1w 1h' sizes=100vw src=x alt>",
+ "srcset-microsyntax-h": "<img srcset='x 1h' sizes=100vw src=x alt>",
+ "srcset-microsyntax-function": "<img srcset='x foobar(baz quux, lol), y 1x' src=x alt>",
+ "srcset-microsyntax-parenthesis-junk": "<img srcset='x ><(((((o)>, y 1x' src=x alt>",
+ "srcset-microsyntax-square-bracket-junk": "<img srcset='x [, y 1x' src=x alt>",
+ "srcset-microsyntax-curly-bracket-junk": "<img srcset='x {, y 1x' src=x alt>",
+ "srcset-microsyntax-pipe-junk": "<img srcset='x ||, y 1x' src=x alt>",
+ "srcset-microsyntax-w-and-no-descriptor": "<img srcset='x 1w, y' sizes=100vw src=x alt>",
+ "srcset-microsyntax-unique-descriptors-1x-and-omitted": "<img srcset='x 1x, y' src=x alt>",
+ "srcset-microsyntax-unique-descriptors-2x": "<img srcset='x 2x, y 2x' src=x alt>",
+ "srcset-microsyntax-unique-descriptors-integer-and-decimals-x": "<img srcset='x 1x, y 1.0x' src=x alt>",
+ "srcset-microsyntax-unique-descriptors-w": "<img srcset='x 1w, y 1w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-empty": "<img srcset='' src=x alt>",
+ "srcset-microsyntax-comma": "<img srcset=',' src=x alt>",
+ "srcset-microsyntax-css-comment-after-descriptor": "<img srcset='x 2x/**/' src=x alt>",
+ # aria
+ "picture-aria-role-img": "<picture role=img><img src=x alt></picture>",
+ "picture-aria-role-button": "<picture role=button><img src=x alt></picture>",
+ "picture-aria-role-region": "<picture role=region><img src=x alt></picture>",
+ "picture-aria-role-application": "<picture role=application><img src=x alt></picture>",
+ "source-aria-role-img": "<picture><source role=img srcset=x><img src=x alt></picture>",
+ "picture-aria-role-presentation": "<picture role=presentation><img src=x alt></picture>",
+ "source-aria-role-presentation": "<picture><source role=presentation srcset=x><img src=x alt></picture>",
+}
+
+non_errors_in_head = {
+ "parent-template-in-head": "<template><picture><img src=x alt></picture></template>",
+}
+
+non_errors = {
+ # basic
+ "basic-img-src": "<img src=x alt>",
+ "basic-picture-img-src": "<picture><img src=x alt></picture>",
+ "basic-picture-source": "<picture><source srcset=x><img src=x alt></picture>",
+ # inter-element whitespace
+ "inter-element-whitespace": "<picture> <!--x--> <source srcset=x> <!--x--> <img src=x alt> <!--x--> </picture>",
+ # parents
+ "parent-p": "<p><picture><img src=x alt></picture></p>",
+ "parent-h1": "<h1><picture><img src=x alt=x></picture></h1>",
+ "parent-noscript-in-body": "<noscript><picture><img src=x alt></picture></noscript>",
+ "parent-object": "<object data=x><picture><img src=x alt></picture></object>",
+ "parent-video": "<video src=x><picture><img src=x alt></picture></video>",
+ "parent-section": "<section><h2>x</h2><picture><img src=x alt></picture></section>",
+ "parent-main": "<main><picture><img src=x alt></picture></main>",
+ "parent-canvas": "<canvas><picture><img src=x alt></picture></canvas>",
+ "parent-template-in-body": "<template><picture><img src=x alt></picture></template>",
+ "parent-ruby": "<ruby><picture><img src=x alt></picture><rt>x</rt></ruby>",
+ "parent-rt": "<ruby>x<rt><picture><img src=x alt></picture></rt></ruby>",
+ "parent-rp": "<ruby>x<rp><picture><img src=x alt></picture></rp><rt>x</rt><rp>x</rp></ruby>",
+ "parent-a": "<a href=x><picture><img src=x alt></picture></a>",
+ "parent-button": "<button><picture><img src=x alt></picture></button>",
+ "parent-td": "<table><tr><td><picture><img src=x alt></picture></table>",
+ # script-supporting elements
+ "script-first": "<picture><script></script><source srcset=x><img src=x alt></picture>",
+ "template-first": "<picture><template></template><source srcset=x><img src=x alt></picture>",
+ "script-between": "<picture><source srcset=x><script></script><img src=x alt></picture>",
+ "script-after": "<picture><source srcset=x><img src=x alt><script></script></picture>",
+ "script-before-after": "<picture><script></script><source srcset=x><img src=x alt><script></script></picture>",
+ "script-before-between-after": "<picture><script></script><source srcset=x><script></script><img src=x alt><script></script></picture>",
+ "script-and-template": "<picture><template></template><source srcset=x><script></script><img src=x alt><template></template></picture>",
+ # source with following sibling source element or img element with a srcset attribute
+ "source-with-media-img-with-srcset": "<picture><source srcset=x media=screen><img src=x srcset=x alt></picture>",
+ "source-with-media-uppercase-img-with-srcset": "<picture><source srcset=x media=SCREEN><img src=x srcset=x alt></picture>",
+ "source-with-media-spaces-img-with-srcset": "<picture><source srcset=x media=' \n\tscreen \n\t'><img src=x srcset=x alt></picture>",
+ "source-with-media-source-with-srcset": "<picture><source srcset=x media=screen><source srcset=x><img src=x alt></picture>",
+ "source-with-type-img-with-srcset": "<picture><source srcset=x type=image/gif><img src=x srcset=x alt></picture>",
+ "source-with-type-source-with-srcset": "<picture><source srcset=x type=image/gif><source srcset=x><img src=x alt></picture>",
+ # sizes present
+ "img-with-sizes": "<img srcset='x 100w, y 200w' sizes=50vw src=x alt>",
+ "source-with-sizes": "<picture><source srcset='x 100w, y 200w' sizes=50vw><img src=x alt></picture>",
+ # embed allows any attributes
+ "embed-srcset-empty": "<embed srcset>",
+ "embed-srcset-junk": "<embed srcset='foo bar'>",
+ "embed-sizes-empty": "<embed sizes>",
+ "embed-sizes-junk": "<embed sizes='foo bar'>",
+ # img src also in srcset
+ "img-src-also-in-srcset-1x": "<img src=x srcset='x 1x, y 2x' alt>",
+ "img-src-also-in-srcset-2x": "<img src=x srcset='y 1x, x 2x' alt>",
+ "img-src-also-in-srcset-w": "<img src=x srcset='x 100w, y 200w' sizes=100vw alt>",
+ # img src not in srcset
+ "img-src-not-in-srcset-x": "<img src=x srcset='y 1x, z 2x' alt>",
+ "img-src-not-in-srcset-w": "<img src=x srcset='y 100w, z 200w' sizes=100vw alt>",
+ # source type
+ "source-type": "<picture><source srcset=x type=image/gif><img src=x alt></picture>",
+ "source-type-srcset-x": "<picture><source srcset='x 1x, y 2x' type=image/gif><img src=x alt></picture>",
+ "source-type-srcset-w-sizes": "<picture><source srcset='x 100w, y 200w' type=image/gif sizes=50vw><img src=x alt></picture>",
+ # sizes microsyntax
+ "sizes-microsyntax-media-min-width": "<img sizes='(min-width:500px) 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-multiple-source-sizes": "<img sizes='(min-width:1500px) 500px, (min-width:1000px) 33vw, (min-width:500px) 50vw, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-no-default": "<img sizes='(min-width:500px) 500px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-media-not-and": "<img sizes='not (width:500px) and (width:500px) 500px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-only-default": "<img sizes='500px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-calc-in-default": "<img sizes='calc(500px)' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-calc-in-source-size-value": "<img sizes='(min-width:500px) calc(500px)' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-calc-in-media": "<img sizes='(min-width:calc(500px)) 500px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-zero": "<img sizes='0' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-minus-zero": "<img sizes='-0' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-em-in-source-size-value": "<img sizes='1em' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-ex-in-source-size-value": "<img sizes='1ex' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-ch-in-source-size-value": "<img sizes='1ch' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-rem-in-source-size-value": "<img sizes='1rem' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-vw-in-source-size-value": "<img sizes='1vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-vh-in-source-size-value": "<img sizes='1vh' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-vmin-in-source-size-value": "<img sizes='1vmin' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-vmax-in-source-size-value": "<img sizes='1vmax' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-cm-in-source-size-value": "<img sizes='1cm' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-mm-in-source-size-value": "<img sizes='1mm' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-q-in-source-size-value": "<img sizes='1q' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-in-in-source-size-value": "<img sizes='1in' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-pc-in-source-size-value": "<img sizes='1pc' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-pt-in-source-size-value": "<img sizes='1pt' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-px-in-source-size-value": "<img sizes='1px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-non-integer-px-in-source-size-value": "<img sizes='0.2px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-leading-css-comment": "<img sizes='/**/50vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-trailing-css-comment": "<img sizes='50vw/**/' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-plus": "<img sizes='+50vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-non-integer-omitted-zero": "<img sizes='.2px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientifi-notation-0": "<img sizes='-0e-0px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientifi-notation-1": "<img sizes='+11.11e+11px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientifi-notation-2": "<img sizes='2.2e2px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientifi-notation-3": "<img sizes='33E33px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientifi-notation-4": "<img sizes='.4E4px' srcset='x 100w, y 200w' src=x alt>",
+ # srcset microsyntax
+ "srcset-microsyntax-comma-in-url": "<img srcset='x,x' src=x alt>",
+ "srcset-microsyntax-percent-escaped-leading-comma-in-url": "<img srcset='%2Cx' src=x alt>",
+ "srcset-microsyntax-percent-escaped-trailing-comma-in-url": "<img srcset='x%2C' src=x alt>",
+ "srcset-microsyntax-percent-escaped-space-in-url": "<img srcset='%20' src=x alt>",
+ "srcset-microsyntax-w": "<img srcset='x 1w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-x": "<img srcset='x 1x' src=x alt>",
+ "srcset-microsyntax-non-integer-x": "<img srcset='x 1.5x' src=x alt>",
+ "srcset-microsyntax-scientific-notation-x": "<img srcset='x 1e0x' src=x alt>",
+ "srcset-microsyntax-scientific-notation-decimals-x": "<img srcset='x 1.5e0x' src=x alt>",
+ "srcset-microsyntax-scientific-notation-e-plus-x": "<img srcset='x 1e+0x' src=x alt>",
+ "srcset-microsyntax-scientific-notation-e-minus-x": "<img srcset='x 1e-0x' src=x alt>",
+ "srcset-microsyntax-scientific-notation-e-uppercase-x": "<img srcset='x 1E0x' src=x alt>",
+ "srcset-microsyntax-no-space-between-candidates": "<img srcset='x 1x,y 2x' src=x alt>",
+ # valid attributes on img in picture
+ "img-crossorigin-with-picture": "<picture><img crossorigin src=x alt></picture>",
+ "img-usemap-with-picture": "<picture><img usemap=#x src=x alt></picture><map name=x></map>",
+ "img-ismap-with-picture": "<a href=x><picture><img ismap src=x alt></picture></a>",
+ "img-width-height-with-picture": "<picture><img src=x alt width=1 height=1></picture>",
+ "img-width-height-zero-with-picture": "<picture><img src=x alt width=0 height=0></picture>",
+ # global attributes on picture
+ "picture-global-attributes": "<picture title=x class=x dir=ltr hidden id=asdf tabindex=0><img src=x alt></picture>",
+}
+
+for key in errors.keys():
+ template_error = template
+ template_error += '<title>invalid %s</title>\n' % key
+ template_error += errors[key]
+ file = open(os.path.join(ccdir, "html/elements/picture/%s-novalid.html" % key), 'wb')
+ file.write(template_error)
+ file.close()
+
+file = open(os.path.join(ccdir, "html/elements/picture/picture-isvalid.html"), 'wb')
+file.write(template + '<title>valid picture</title>\n')
+for key in non_errors_in_head.keys():
+ file.write('%s <!-- %s -->\n' % (non_errors_in_head[key], key))
+file.write('<body>\n')
+for key in non_errors.keys():
+ file.write('%s <!-- %s -->\n' % (non_errors[key], key))
+file.close()
+# vim: ts=4:sw=4
diff --git a/testing/web-platform/tests/conformance-checkers/tools/url.py b/testing/web-platform/tests/conformance-checkers/tools/url.py
new file mode 100644
index 000000000..f97d428ab
--- /dev/null
+++ b/testing/web-platform/tests/conformance-checkers/tools/url.py
@@ -0,0 +1,454 @@
+# -*- coding: utf-8 -*-
+import os
+ccdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+# based on https://github.com/w3c/web-platform-tests/blob/275544eab54a0d0c7f74ccc2baae9711293d8908/url/urltestdata.txt
+invalid = {
+ "scheme-trailing-tab": "a:\tfoo.com",
+ "scheme-trailing-newline": "a:\nfoo.com",
+ "scheme-trailing-cr": "a:\rfoo.com",
+ "scheme-trailing-space": "a: foo.com",
+ "scheme-trailing-tab": "a:\tfoo.com",
+ "scheme-trailing-newline": "a:\nfoo.com",
+ "scheme-trailing-cr": "a:\rfoo.com",
+ "scheme-http-no-slash": "http:foo.com",
+ "scheme-http-no-slash-colon": "http::@c:29",
+ "scheme-http-no-slash-square-bracket": "http:[61:27]/:foo",
+ "scheme-http-backslash": "http:\\\\foo.com\\",
+ "scheme-http-single-slash": "http:/example.com/",
+ "scheme-ftp-single-slash": "ftp:/example.com/",
+ "scheme-https-single-slash": "https:/example.com/",
+ "scheme-data-single-slash": "data:/example.com/",
+ "scheme-ftp-no-slash": "ftp:example.com/",
+ "scheme-https-no-slash": "https:example.com/",
+ "scheme-javascript-no-slash-malformed": "javascript:example.com/",
+ "userinfo-password-bad-chars": "http://&a:foo(b]c@d:2/",
+ "userinfo-username-contains-at-sign": "http://::@c@d:2",
+ "userinfo-backslash": "http://a\\b:c\\d@foo.com",
+ "host-space": "http://example .org",
+ "host-tab": "http://example\t.org",
+ "host-newline": "http://example.\norg",
+ "host-cr": "http://example.\rorg",
+ "host-square-brackets-port-contains-colon": "http://[1::2]:3:4",
+ "port-999999": "http://f:999999/c",
+ "port-single-letter": "http://f:b/c",
+ "port-multiple-letters": "http://f:fifty-two/c",
+ "port-leading-colon": "http://2001::1",
+ "port-leading-colon-bracket-colon": "http://2001::1]:80",
+ "path-leading-backslash-at-sign": "http://foo.com/\\@",
+ "path-leading-colon-backslash": ":\\",
+ "path-leading-colon-chars-backslash": ":foo.com\\",
+ "path-relative-square-brackets": "[61:24:74]:98",
+ "fragment-contains-hash": "http://foo/path#f#g",
+ "path-percent-encoded-malformed": "http://example.com/foo/%2e%2",
+ "path-bare-percent-sign": "http://example.com/foo%",
+ "path-u0091": u"http://example.com/foo\u0091".encode('utf-8'),
+ "userinfo-username-contains-pile-of-poo": "http://💩:foo@example.com",
+ "userinfo-password-contains-pile-of-poo": "http://foo:💩@example.com",
+ "host-hostname-in-brackets": "http://[www.google.com]/",
+ "host-empty": "http://",
+ "host-empty-with-userinfo": "http://user:pass@/",
+ "port-leading-dash": "http://foo:-80/",
+ "host-empty-userinfo-empty": "http://@/www.example.com",
+ "host-invalid-unicode": u"http://\ufdd0zyx.com".encode('utf-8'),
+ "host-invalid-unicode-percent-encoded": "http://%ef%b7%90zyx.com",
+ "host-double-percent-encoded": u"http://\uff05\uff14\uff11.com".encode('utf-8'),
+ "host-double-percent-encoded-percent-encoded": "http://%ef%bc%85%ef%bc%94%ef%bc%91.com",
+ "host-u0000-percent-encoded": u"http://\uff05\uff10\uff10.com".encode('utf-8'),
+ "host-u0000-percent-encoded-percent-encoded": "http://%ef%bc%85%ef%bc%90%ef%bc%90.com",
+}
+invalid_absolute = invalid.copy()
+
+invalid_url_code_points = {
+ "fragment-backslash": "#\\",
+ "fragment-leading-space": "http://f:21/b# e",
+ "path-contains-space": "/a/ /c",
+ "path-leading-space": "http://f:21/ b",
+ "path-tab": "http://example.com/foo\tbar",
+ "path-trailing-space": "http://f:21/b ?",
+ "port-cr": "http://f:\r/c",
+ "port-newline": "http://f:\n/c",
+ "port-space": "http://f: /c",
+ "port-tab": "http://f:\t/c",
+ "query-leading-space": "http://f:21/b? d",
+ "query-trailing-space": "http://f:21/b?d #",
+}
+invalid.update(invalid_url_code_points)
+invalid_absolute.update(invalid_url_code_points)
+
+valid_absolute = {
+ "scheme-private": "a:foo.com",
+ "scheme-private-slash": "foo:/",
+ "scheme-private-slash-slash": "foo://",
+ "scheme-private-path": "foo:/bar.com/",
+ "scheme-private-path-leading-slashes-only": "foo://///////",
+ "scheme-private-path-leading-slashes-chars": "foo://///////bar.com/",
+ "scheme-private-path-leading-slashes-colon-slashes": "foo:////://///",
+ "scheme-private-single-letter": "c:/foo",
+ "scheme-private-single-slash": "madeupscheme:/example.com/",
+ "scheme-file-single-slash": "file:/example.com/",
+ "scheme-ftps-single-slash": "ftps:/example.com/",
+ "scheme-gopher-single-slash": "gopher:/example.com/",
+ "scheme-ws-single-slash": "ws:/example.com/",
+ "scheme-wss-single-slash": "wss:/example.com/",
+ "scheme-javascript-single-slash": "javascript:/example.com/",
+ "scheme-mailto-single-slash": "mailto:/example.com/",
+ "scheme-private-no-slash": "madeupscheme:example.com/",
+ "scheme-ftps-no-slash": "ftps:example.com/",
+ "scheme-gopher-no-slash": "gopher:example.com/",
+ "scheme-wss-no-slash": "wss:example.com/",
+ "scheme-mailto-no-slash": "mailto:example.com/",
+ "scheme-data-no-slash": "data:text/plain,foo",
+ "userinfo": "http://user:pass@foo:21/bar;par?b#c",
+ "host-ipv6": "http://[2001::1]",
+ "host-ipv6-port": "http://[2001::1]:80",
+ "port-none-but-colon": "http://f:/c",
+ "port-0": "http://f:0/c",
+ "port-00000000000000": "http://f:00000000000000/c",
+ "port-00000000000000000000080": "http://f:00000000000000000000080/c",
+ "port-00000000000000000000080": "http://f:00000000000000000000080/c",
+ "userinfo-host-port-path": "http://a:b@c:29/d",
+ "userinfo-username-non-alpha": "http://foo.com:b@d/",
+ "query-contains-question-mark": "http://foo/abcd?efgh?ijkl",
+ "fragment-contains-question-mark": "http://foo/abcd#foo?bar",
+ "path-percent-encoded-dot": "http://example.com/foo/%2e",
+ "path-percent-encoded-space": "http://example.com/%20foo",
+ "path-non-ascii": u"http://example.com/\u00C2\u00A9zbar".encode('utf-8'),
+ "path-percent-encoded-multiple": "http://example.com/foo%41%7a",
+ "path-percent-encoded-u0091": "http://example.com/foo%91",
+ "path-percent-encoded-u0000": "http://example.com/foo%00",
+ "path-percent-encoded-mixed-case": "http://example.com/%3A%3a%3C%3c",
+ "path-unicode-han": u"http://example.com/\u4F60\u597D\u4F60\u597D".encode('utf-8'),
+ "path-uFEFF": u"http://example.com/\uFEFF/foo".encode('utf-8'),
+ "path-u202E-u202D": u"http://example.com/\u202E/foo/\u202D/bar".encode('utf-8'),
+ "host-is-pile-of-poo": "http://💩",
+ "path-contains-pile-of-poo": "http://example.com/foo/💩",
+ "query-contains-pile-of-poo": "http://example.com/foo?💩",
+ "fragment-contains-pile-of-poo": "http://example.com/foo#💩",
+ "host-192.0x00A80001": "http://192.0x00A80001",
+ "userinfo-username-contains-percent-encoded": "http://%25DOMAIN:foobar@foodomain.com",
+ "userinfo-empty": "http://@www.example.com",
+ "userinfo-user-empty": "http://:b@www.example.com",
+ "userinfo-password-empty": "http://a:@www.example.com",
+ "host-exotic-whitespace": u"http://GOO\u200b\u2060\ufeffgoo.com".encode('utf-8'),
+ "host-exotic-dot": u"http://www.foo\u3002bar.com".encode('utf-8'),
+ "host-fullwidth": u"http://\uff27\uff4f.com".encode('utf-8'),
+ "host-idn-unicode-han": u"http://\u4f60\u597d\u4f60\u597d".encode('utf-8'),
+ "host-IP-address-broken": "http://192.168.0.257/",
+}
+valid = valid_absolute.copy()
+
+valid_relative = {
+ "scheme-schemeless-relative": "//foo/bar",
+ "path-slash-only-relative": "/",
+ "path-simple-relative": "/a/b/c",
+ "path-percent-encoded-slash-relative": "/a%2fc",
+ "path-percent-encoded-slash-plus-slashes-relative": "/a/%2f/c",
+ "query-empty-no-path-relative": "?",
+ "fragment-empty-hash-only-no-path-relative": "#",
+ "fragment-slash-relative": "#/",
+ "fragment-semicolon-question-mark-relative": "#;?",
+ "fragment-non-ascii-relative": u"#\u03B2".encode('utf-8'),
+}
+valid.update(valid_relative)
+invalid_absolute.update(valid_relative)
+
+valid_relative_colon_dot = {
+ "scheme-none-relative": "foo.com",
+ "path-colon-relative": ":",
+ "path-leading-colon-letter-relative": ":a",
+ "path-leading-colon-chars-relative": ":foo.com",
+ "path-leading-colon-slash-relative": ":/",
+ "path-leading-colon-hash-relative": ":#",
+ "path-leading-colon-number-relative": ":23",
+ "path-slash-colon-number-relative": "/:23",
+ "path-leading-colon-colon-relative": "::",
+ "path-colon-colon-number-relative": "::23",
+ "path-starts-with-pile-of-poo": "💩http://foo",
+ "path-contains-pile-of-poo": "http💩//:foo",
+}
+valid.update(valid_relative_colon_dot)
+
+invalid_file = {
+ "scheme-file-backslash": "file:c:\\foo\\bar.html",
+ "scheme-file-single-slash-c-bar": "file:/C|/foo/bar",
+ "scheme-file-triple-slash-c-bar": "file:///C|/foo/bar",
+}
+invalid.update(invalid_file)
+
+valid_file = {
+ "scheme-file-uppercase": "File://foo/bar.html",
+ "scheme-file-slash-slash-c-bar": "file://C|/foo/bar",
+ "scheme-file-slash-slash-abc-bar": "file://abc|/foo/bar",
+ "scheme-file-host-included": "file://server/foo/bar",
+ "scheme-file-host-empty": "file:///foo/bar.txt",
+ "scheme-file-scheme-only": "file:",
+ "scheme-file-slash-only": "file:/",
+ "scheme-file-slash-slash-only": "file://",
+ "scheme-file-slash-slash-slash-only": "file:///",
+ "scheme-file-no-slash": "file:test",
+}
+valid.update(valid_file)
+valid_absolute.update(valid_file)
+
+warnings = {
+ "scheme-data-contains-fragment": "data:text/html,test#test",
+}
+
+element_attribute_pairs = [
+ "a href",
+ # "a ping", space-separated list of URLs; tested elsewhere
+ "area href",
+ # "area ping", space-separated list of URLs; tested elsewhere
+ "audio src",
+ "base href",
+ "blockquote cite",
+ "button formaction",
+ "del cite",
+ "embed src",
+ "form action",
+ "html manifest",
+ "iframe src",
+ "img src", # srcset is tested elsewhere
+ "input formaction", # type=submit, type=image
+ "input src", # type=image
+ "input value", # type=url
+ "ins cite",
+ "link href",
+ #"menuitem icon", # skip until parser is updated
+ "object data",
+ "q cite",
+ "script src",
+ "source src",
+ "track src",
+ "video poster",
+ "video src",
+]
+
+template = "<!DOCTYPE html>\n<meta charset=utf-8>\n"
+
+def write_novalid_files():
+ for el, attr in (pair.split() for pair in element_attribute_pairs):
+ for desc, url in invalid.items():
+ if ("area" == el):
+ f = open(os.path.join(ccdir, "html/elements/area/href/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid href: %s</title>\n' % desc)
+ f.write('<map name=foo><%s %s="%s" alt></map>\n' % (el, attr, url))
+ f.close()
+ elif ("base" == el or "embed" == el):
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-novalid.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>invalid %s: %s</title>\n' % (attr, desc))
+ f.write('<%s %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("html" == el):
+ f = open(os.path.join(ccdir, "html/elements/html/manifest/%s-novalid.html" % desc), 'wb')
+ f.write('<!DOCTYPE html>\n')
+ f.write('<html manifest="%s">\n' % url)
+ f.write('<meta charset=utf-8>\n')
+ f.write('<title>invalid manifest: %s</title>\n' % desc)
+ f.write('</html>\n')
+ f.close()
+ elif ("img" == el):
+ f = open(os.path.join(ccdir, "html/elements/img/src/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid src: %s</title>\n' % desc)
+ f.write('<img src="%s" alt>\n' % url)
+ f.close()
+ elif ("input" == el and "src" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-image-src/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid src: %s</title>\n' % desc)
+ f.write('<%s type=image alt="foo" %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("input" == el and "formaction" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-submit-formaction/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid formaction: %s</title>\n' % desc)
+ f.write('<%s type=submit %s="%s">\n' % (el, attr, url))
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/input/type-image-formaction/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid formaction: %s</title>\n' % desc)
+ f.write('<%s type=image alt="foo" %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("input" == el and "value" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-url-value/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid value attribute: %s</title>\n' % desc)
+ f.write('<%s type=url %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("link" == el):
+ f = open(os.path.join(ccdir, "html/elements/link/href/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid href: %s</title>\n' % desc)
+ f.write('<link href="%s" rel=help>\n' % url)
+ f.close()
+ elif ("source" == el or "track" == el):
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-novalid.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>invalid %s: %s</title>\n' % (attr, desc))
+ f.write('<video><%s %s="%s"></video>\n' % (el, attr, url))
+ f.close()
+ else:
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-novalid.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>invalid %s: %s</title>\n' % (attr, desc))
+ f.write('<%s %s="%s"></%s>\n' % (el, attr, url, el))
+ f.close()
+ for desc, url in invalid.items():
+ f = open(os.path.join(ccdir, "html/microdata/itemid/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid itemid: %s</title>\n' % desc)
+ f.write('<div itemid="%s" itemtype="http://foo" itemscope></div>\n' % url)
+ f.close()
+ for desc, url in invalid_absolute.items():
+ f = open(os.path.join(ccdir, "html/microdata/itemtype/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid itemtype: %s</title>\n' % desc)
+ f.write('<div itemtype="%s" itemscope></div>\n' % url)
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/input/type-url-value/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid value attribute: %s</title>\n' %desc)
+ f.write('<input type=url value="%s">\n' % url)
+ f.close()
+
+def write_haswarn_files():
+ for el, attr in (pair.split() for pair in element_attribute_pairs):
+ for desc, url in warnings.items():
+ if ("area" == el):
+ f = open(os.path.join(ccdir, "html/elements/area/href/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<map name=foo><%s %s="%s" alt></map>\n' % (el, attr, url))
+ f.close()
+ elif ("base" == el or "embed" == el):
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-haswarn.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("html" == el):
+ f = open(os.path.join(ccdir, "html/elements/html/manifest/%s-haswarn.html" % desc), 'wb')
+ f.write('<!DOCTYPE html>\n')
+ f.write('<html manifest="%s">\n' % url)
+ f.write('<meta charset=utf-8>\n')
+ f.write('<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('</html>\n')
+ f.close()
+ elif ("img" == el):
+ f = open(os.path.join(ccdir, "html/elements/img/src/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s %s="%s" alt>\n' % (el, attr, url))
+ f.close()
+ elif ("input" == el and "src" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-image-src/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s type=image alt="foo" %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("input" == el and "formaction" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-submit-formaction/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s type=submit %s="%s">\n' % (el, attr, url))
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/input/type-image-formaction/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s type=image alt="foo" %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("input" == el and "value" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-url-value/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s type=url %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("link" == el):
+ f = open(os.path.join(ccdir, "html/elements/link/href/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s %s="%s" rel=help>\n' % (el, attr, url))
+ f.close()
+ elif ("source" == el or "track" == el):
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-haswarn.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<video><%s %s="%s"></video>\n' % (el, attr, url))
+ f.close()
+ else:
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-haswarn.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (url, desc))
+ f.write('<%s %s="%s"></%s>\n' % (el, attr, url, el))
+ f.close()
+ for desc, url in warnings.items():
+ f = open(os.path.join(ccdir, "html/microdata/itemtype-%s-haswarn.html" % desc ), 'wb')
+ f.write(template + '<title>warning: %s</title>\n' % desc)
+ f.write('<div itemtype="%s" itemscope></div>\n' % url)
+ f.close()
+ f = open(os.path.join(ccdir, "html/microdata/itemid-%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>warning: %s</title>\n' % desc)
+ f.write('<div itemid="%s" itemtype="http://foo" itemscope></div>\n' % url)
+ f.close()
+
+def write_isvalid_files():
+ for el, attr in (pair.split() for pair in element_attribute_pairs):
+ if ("base" == el):
+ continue
+ if ("html" == el):
+ continue
+ elif ("input" == el and "value" == attr):
+ continue
+ elif ("input" == el and "formaction" == attr):
+ fs = open(os.path.join(ccdir, "html/elements/input/type-submit-formaction-isvalid.html"), 'wb')
+ fs.write(template + '<title>valid formaction</title>\n')
+ fi = open(os.path.join(ccdir, "html/elements/input/type-image-formaction-isvalid.html"), 'wb')
+ fi.write(template + '<title>valid formaction</title>\n')
+ elif ("input" == el and "src" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-image-src-isvalid.html"), 'wb')
+ f.write(template + '<title>valid src</title>\n')
+ else:
+ f = open(os.path.join(ccdir, "html/elements/%s/%s-isvalid.html" % (el, attr)), 'wb')
+ f.write(template + '<title>valid %s</title>\n' % attr)
+ for desc, url in valid.items():
+ if ("area" == el):
+ f.write('<map name=foo><%s %s="%s" alt></map><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("embed" == el):
+ f.write('<%s %s="%s"><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("img" == el):
+ f.write('<%s %s="%s" alt><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("input" == el and "src" == attr):
+ f.write('<%s type=image alt="foo" %s="%s"><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("input" == el and "formaction" == attr):
+ fs.write('<%s type=submit %s="%s"><!-- %s -->\n' % (el, attr, url, desc))
+ fi.write('<%s type=image alt="foo" %s="%s"><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("link" == el):
+ f.write('<%s %s="%s" rel=help><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("source" == el or "track" == el):
+ f.write('<video><%s %s="%s"></video><!-- %s -->\n' % (el, attr, url, desc))
+ else:
+ f.write('<%s %s="%s"></%s><!-- %s -->\n' % (el, attr, url, el, desc))
+ if ("input" == el and "formaction" == attr):
+ fs.close()
+ fi.close()
+ else:
+ if ("a" == el and "href" == attr):
+ f.write('<a href=""></a><!-- empty-href -->\n')
+ f.close()
+ for desc, url in valid.items():
+ f = open(os.path.join(ccdir, "html/elements/base/href/%s-isvalid.html" % desc), 'wb')
+ f.write(template + '<title>valid href: %s</title>\n' % desc)
+ f.write('<base href="%s">\n' % url)
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/html/manifest/%s-isvalid.html" % desc), 'wb')
+ f.write('<!DOCTYPE html>\n')
+ f.write('<html manifest="%s">\n' % url)
+ f.write('<meta charset=utf-8>\n')
+ f.write('<title>valid manifest: %s</title>\n' % desc)
+ f.write('</html>\n')
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/meta/refresh-isvalid.html"), 'wb')
+ f.write(template + '<title>valid meta refresh</title>\n')
+ for desc, url in valid.items():
+ f.write('<meta http-equiv=refresh content="0; URL=%s"><!-- %s -->\n' % (url, desc))
+ f.close()
+ f = open(os.path.join(ccdir, "html/microdata/itemid-isvalid.html"), 'wb')
+ f.write(template + '<title>valid itemid</title>\n')
+ for desc, url in valid.items():
+ f.write('<div itemid="%s" itemtype="http://foo" itemscope></div><!-- %s -->\n' % (url, desc))
+ f.close()
+ f = open(os.path.join(ccdir, "html/microdata/itemtype-isvalid.html"), 'wb')
+ f.write(template + '<title>valid itemtype</title>\n')
+ for desc, url in valid_absolute.items():
+ f.write('<div itemtype="%s" itemscope></div><!-- %s -->\n' % (url, desc))
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/input/type-url-value-isvalid.html"), 'wb')
+ f.write(template + '<title>valid value attribute</title>\n')
+ for desc, url in valid_absolute.items():
+ f.write('<input type=url value="%s"><!-- %s -->\n' % (url, desc))
+ f.close()
+
+write_novalid_files()
+write_haswarn_files()
+write_isvalid_files()
+# vim: ts=4:sw=4