# Legacy Module

# This file is based upon the work of James Clark "Modularization of XHTML in RELAX NG"
# (see http://www.thaiopensource.com/relaxng/xhtml/ and
# the accompanying jing-copying.html file)
# All changes are marked with relevant comments.
# The following license refers just to those changes.

# Copyright (c) 2005 Petr Nalevka
# Copyright (c) 2007-2008 Mozilla Foundation
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
#    derived from this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

default namespace = "http://www.w3.org/1999/xhtml"
namespace sch = "http://www.ascc.net/xml/schematron"

sch:ns [ prefix = "html" uri = "http://www.w3.org/1999/xhtml" ]
# bugfix - it is already solved in attribs.rng ... strict spec also enables to have backward compatible lang attribute
# <define name="lang.attrib" combine="interleave">
#   <optional>
#     <attribute name="lang">
#       <ref name="language-code.datatype"/>
#     </attribute>
#   </optional>
# </define>
basefont = element basefont { basefont.attlist, empty }
basefont.attlist =
    id.attrib,
    # modified - bugfix - size is required
    attribute size { FontSize.datatype },
    attribute color { Color.datatype }?,
    attribute face { text }?
center = element center { center.attlist, Flow.model }
center.attlist = Common.attrib
font = element font { font.attlist, Inline.model }
font.attlist = Core.attrib, I18n.attrib, Font.attrib
Font.attrib =
    attribute size { FontSize.datatype }?,
    attribute color { Color.datatype }?,
    attribute face { text }?
# added - bugfix - just the reserved names may start without an alphabethic character
FontSize.datatype = xsd:string { pattern = "[1-7]|[\-+][1-6]" }
s = element s { s.attlist, Inline.model }
s.attlist = Common.attrib
strike = element strike { strike.attlist, Inline.model }
strike.attlist = Common.attrib
u = element u { u.attlist, Inline.model }
u.attlist = Common.attrib
dir = element dir { dir.attlist, li.noblock+ }
dir.attlist =
    Common.attrib,
    attribute compact { string "compact" }?
menu = element menu { menu.attlist, li.noblock+ }
menu.attlist =
    Common.attrib,
    attribute compact { string "compact" }?
li.noblock = element li { li.attlist, Inline.model }
isindex = element isindex { isindex.attlist, empty }
isindex.attlist =
    Core.attrib,
    I18n.attrib,
    attribute prompt { text.datatype }?
applet.attlist &=
    attribute align { string "top" | string "middle" | string "bottom" | string "left" | string "right" }?,
    attribute hspace { pixels.datatype }?,
    attribute vspace { pixels.datatype }?
body.attlist &=
    attribute background { uri.datatype }?,
    attribute bgcolor { Color.datatype }?,
    attribute text { Color.datatype }?,
    attribute link { Color.datatype }?,
    attribute vlink { Color.datatype }?,
    attribute alink { Color.datatype }?
br.attlist &= attribute clear { string "left" | string "all" | string "right" | string "none" }?
caption.attlist &= calign.attrib
div.attlist &= align.attrib
# Not in the CR, but surely an edu.petrnalevka.relaxed.error.
dl.attlist &= attribute compact { string "compact" }?
Heading.attrib &= align.attrib
hr.attlist &=
    attribute align { string "left" | string "center" | string "right" }?,
    attribute noshade { string "noshade" }?,
    attribute size { pixels.datatype }?,
    # bugfix - not Pixels but Lenght datatype
    attribute width { length.datatype }?
img.attlist &=
    attribute align { string "top" | string "middle" | string "bottom" | string "left" | string "right" }?,
    attribute border { pixels.datatype }?,
    attribute hspace { pixels.datatype }?,
    attribute vspace { pixels.datatype }?
# modified - bugfix - input has the img align model not the text align
input.attlist &= imgalign.attrib
legend.attlist &=
    attribute align { string "top" | string "bottom" | string "left" | string "right" }?
li.attlist &=
    attribute type {
        (# added - bugfix  - possible values are (1|a|A|i|I) | (desc|square|circle)
         
         # todo implement |
         string "1"
         | string "a"
         | string "A"
         | string "i"
         | string "I")
        | (string "disc" | string "square" | string "circle")
    }?,
    # added - value is a sequece of digits
    attribute value { number.datatype }?
object.attlist &=
    attribute align { string "top" | string "middle" | string "bottom" | string "left" | string "right" }?,
    attribute border { pixels.datatype }?,
    attribute hspace { pixels.datatype }?,
    attribute vspace { pixels.datatype }?
ol.attlist &=
    attribute type {
        # added - bugfix  - possible values are (1|a|A|i|I)
        string "1"
        | string "a"
        | string "A"
        | string "i"
        | string "I"
    }?,
    attribute compact { string "compact" }?,
    # added - needs to be a sequece of digits
    attribute start { number.datatype }?
p.attlist &= align.attrib
pre.attlist &= attribute width { length.datatype }?
script.attlist &= attribute language { string }? # Not MIME -- hsivonen
table.attlist &=
    talign.attrib,
    attribute bgcolor { Color.datatype }?
tr.attlist &= attribute bgcolor { Color.datatype }?
Cell.attrib &=
    attribute nowrap { string "nowrap" }?,
    attribute bgcolor { Color.datatype }?,
    attribute width {
        # bugfix - modified - from Pixels to Length
        length.datatype
    }?,
    attribute height {
        # bugfix - modified - from Pixels to Length
        length.datatype
    }?
ul.attlist &=
    attribute type {
        # added - bugfix  - possible values are (disc|square|circle)
        string "disc"
        | string "square"
        | string "circle"
    }?,
    attribute compact { string "compact" }?
align.attrib =
    attribute align {
        # modified - bugfix  - possible values are (left|center|right|justify)
        string "left"
        | string "center"
        | string "right"
        | string "justify"
    }?
# added
talign.attrib = attribute align { string "left" | string "center" | string "right" }?
# added
calign.attrib = attribute align { string "top" | string "left" | string "bottom" | string "right" }?
# added
imgalign.attrib =
    attribute align { string "top" | string "middle" | string "bottom" | string "left" | string "right" }?
# modified - pattern for color names has been added

# can contain widely known color names (e.g. Red, Blue...) or a color patter #R(00-FF)G(00-FF)B(00-FF) example: #13F4B2
Color.datatype =
    xsd:string {
        pattern =
            "[bB][lL][aA][cC][kK]|[gG][rR][eE][eE][nN]|[sS][iI][lL][vV][eE][rR]|[lL][iI][mM][eE]|[gG][rR][aA][yY]|[oO][lL][iI][vV][eE]|[wW][hH][iI][tT][eE]|[yY][eE][lL][lL][oO][wW]|[mM][aA][rR][oO][oO][nN]|[nN][aA][vV][yY]|[rR][eE][dD]|[bB][lL][uU][eE]|[pP][uU][rR][pP][lL][eE]|[tT][eE][aA][lL]|[fF][uU][cC][hH][sS][iI][aA]|[aA][qQ][uU][aA]|#[0-9A-Fa-f]{3}|#[0-9A-Fa-f]{6}"
    }
    # The following Schematron patterns are checking explicitly if the color name is one of the 16 allowed.
    #      There are to patterns. One checks the color attribute and the other the bgcolor attribute.
    #      For schema simplicity reasons, attribute text, link, alink and vlink of the body element is not validated.
    # <sch:pattern name="color.datatype.attr.bgcolor">
    #     <sch:rule context="html:body | html:table | html:tr | html:th | html:td">
    #       <sch:report test="@bgcolor and not(starts-with(@bgcolor,'#'))
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'BLACK'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'SILVER'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'GRAY'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'WHITE'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'MAROON'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'RED'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'PURPLE'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'FUCHSIA'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'GREEN'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'LIME'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'OLIVE'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'YELLOW'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'NAVY'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'BLUE'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'TEAL'
    #       and translate(@bgcolor,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ') != 'AQUA'
    #       ">
    #            There are just 16 recognized color names
    #            for bgcolor attribute:
    #            Black, Green, Silver, Lime, Gray, Olive, White,
    #            Yellow, Maroon, Navy, Red, Blue, Purple, Teal,
    #            Fuchsia and Aqua.
    #       </sch:report>
    #     </sch:rule>
    # </sch:pattern>
    
Inline.class |= font | basefont | s | strike | u
Block.class |=
    center
    | isindex
      #  added - bugfix - in transitional noframes element is part of the block
      # <ref name="noframes"/> moved to frames.rng
      
List.class |= dir | menu
head.content &= isindex?
Block.mix |= text | Inline.class
# added - bugfix -  in transitional froms can contain flow elements ... (thay may not contain other nasted forms - see ../exclude/ form.rng
form |= Inline.class
# moved (from nameident.rng) - bugfix - just transitional form can have name attribute
form.attlist &= nametok.attlist
# moved (from nameident.rng) - bugfix - just transitional img can have name attribute
img.attlist &= nametok.attlist
# added - bugfix - in transitional buttons cannot contain iframe

sch:pattern [
    name = "button.content.trasitional"
    "\x{a}" ~
    "  "
    sch:rule [
        context = "html:button"
        "\x{a}" ~
        "      "
        sch:report [
            test = "html:iframe"
            "\x{a}" ~
            "           Button may not contain iframe elements.\x{a}" ~
            "      "
        ]
        "\x{a}" ~
        "  "
    ]
    "\x{a}"
]
# added - bugfix - for trasitional xhtml pre element cannot
# contain additional elements as applet, map, iframe, big, small, font, basefont, sub and sup element

sch:pattern [
    name = "pre.content.transitional"
    "\x{a}" ~
    "    "
    sch:rule [
        context = "html:pre"
        "\x{a}" ~
        "        "
        sch:report [
            test =
                "html:applet or html:font or html:basefont or html:sub or html:sup or html:small or html:big or html:iframe or html:map"
            "\x{a}" ~
            "             pre element cannot contain applet, map, iframe, big, small, font, basefont, sub and sup element.\x{a}" ~
            "        "
        ]
        "\x{a}" ~
        "    "
    ]
    "\x{a}"
]
# added - bugfix - param's attribute name has to be required in transitional

sch:pattern [
    name = "param.attribute.name.required.transitional"
    "\x{a}" ~
    "    "
    sch:rule [
        context = "html:param"
        "\x{a}" ~
        "        "
        sch:assert [
            test = "html:param/@name"
            "\x{a}" ~
            "             param element has a required name attribute.\x{a}" ~
            "        "
        ]
        "\x{a}" ~
        "    "
    ]
    "\x{a}"
]
# this is the transitional part from frames.rng - moved here to split frameset and trasitional
noframes = element noframes { noframes.attlist, Flow.model }
noframes.attlist = Common.attrib
# added - bugfix - in transitional noframes element is part of the block
Block.class |= noframes
