PreviousUpNext

15.4.805  src/lib/html/check-html-g.pkg

## check-html-g.pkg

# Compiled by:
#     src/lib/html/html.lib

# This implements a tree walk over an HTML file to check for
# errors, such as violations of exclusions.


generic package check_html_g (err:  Html_Error )                # Html_Error    is from   src/lib/html/html-error.api
: (weak)
api {
    Context = { file:  Null_Or( String ), line:  Int };

    check:  Context -> html::Html -> Void;

}
{
    Context = err::Context;

    fun check context (html::HTML { body=>html::BODY { content, ... }, ... } )
        =
        check_body_content { in_form=>FALSE } content
        where
            fun error (element, ctx)
                =
                err::syntax_error context
                    (sfprintf::sprintf' "unexpected %s element in %s" [
                        sfprintf::STRING element, sfprintf::STRING ctx
                      ]);

            fun content_error ctx
                =
                err::syntax_error context
                    (sfprintf::sprintf' "unexpected element in %s" [sfprintf::STRING ctx]);

            fun form_error element
                =
                err::syntax_error context
                    (sfprintf::sprintf' "unexpected %s element not in FORM" [
                        sfprintf::STRING element
                      ]);

            fun attribute_error attribute
                =
                err::missing_attribute context attribute;


            fun check_body_content { in_form } b
                =
                case b
                     html::HN { n, align, content }
                         =>
                         check_text { in_anchor=>FALSE, in_form, in_pre=>FALSE, in_applet=>FALSE } content;

                     html::ADDRESS block
                         =>
                         check_address { in_form } block;

                     html::BLOCK_LIST bl
                         =>
                         list::apply (check_body_content { in_form } ) bl;

                     block =>
                         check_block { in_form } block;
                esac


            also
            fun check_address { in_form } blk
                =
                case blk
                  
                    html::BLOCK_LIST bl
                        =>
                        list::apply (check_address { in_form } ) bl;

                    html::TEXTABLOCK txt
                        =>
                        check_text { in_anchor=>FALSE, in_form, in_pre=>FALSE, in_applet => FALSE } txt;

                    html::PP { content, ... }
                        =>
                        check_text { in_anchor=>FALSE, in_form, in_pre=>FALSE, in_applet => FALSE } content;

                    _   =>
                        content_error "ADDRESS";
                esac

            also
            fun check_block { in_form } blk
                 =
                 case blk

                     html::BLOCK_LIST bl
                         =>
                         list::apply (check_block { in_form } ) bl;

                     html::TEXTABLOCK txt
                         =>
                         check_text { in_anchor=>FALSE, in_form, in_pre=>FALSE, in_applet => FALSE } txt;

                     html::PP { content, ... }
                         =>
                         check_text { in_anchor=>FALSE, in_form, in_pre=>FALSE, in_applet => FALSE } content;

                     html::UL { content, ... }
                         =>
                         check_items { in_form, in_dir_or_menu=>FALSE } content;

                     html::OL { content, ... }
                         =>
                         check_items { in_form, in_dir_or_menu=>FALSE } content;

                     html::DIR { content, ... }
                         =>
                         check_items { in_form, in_dir_or_menu=>TRUE } content;

                     html::MENU { content, ... }
                         =>
                         check_items { in_form, in_dir_or_menu=>TRUE } content;

                     html::DL { content, ... }
                         =>
                         check_dlitems { in_form } content;

                     html::PRE { content, ... }
                         =>
                         check_text { in_anchor=>FALSE, in_form, in_pre=>TRUE, in_applet => FALSE } content;

                     html::DIV { content, ... }
                         =>
                         check_body_content { in_form } content;

                     html::CENTER content
                         =>
                         check_body_content { in_form } content;

                     html::BLOCKQUOTE content
                         =>
                         check_body_content { in_form } content;

                     html::FORM { content, ... }
                         =>
                         {   if  in_form    error("FORM", "FORM");  fi;
                             check_body_content { in_form=>TRUE } content;
                         };

                     html::ISINDEX _ => ();
                     html::HR _      => ();

                     html::TABLE { caption=>THE (html::CAPTION { content=>caption, ... } ), content, ... }
                         =>
                         {   check_text {
                                 in_anchor=>FALSE, in_form, in_pre=>FALSE,
                                 in_applet => FALSE
                               } caption;

                             check_rows { in_form } content;
                         };

                     html::TABLE { content, ... }
                         =>
                         check_rows { in_form } content;

                     html::HN      _ =>  error ("HN",      "block");
                     html::ADDRESS _ =>  error ("ADDRESS", "block");
                  esac

            also
            fun check_items { in_form, in_dir_or_menu } items
                =
                list::apply check items
                where
                    fun check_blk (html::BLOCK_LIST bl)   =>  list::apply check_blk bl;
                        check_blk (html::TEXTABLOCK txt) =>  ();
                        check_blk (html::PP _)            =>  ();
                        check_blk _                       =>  error ("block", "DIR/MENU");
                    end;

                    check
                        =
                        if   in_dir_or_menu

                             fn (html::LI { content, ... } )
                                 =
                                 {   check_blk content;
                                     check_block { in_form } content;
                                 };
                        else
                             fn (html::LI { content, ... } )
                                 =
                                 check_block { in_form } content;
                        fi;
                end

            also
            fun check_dlitems { in_form } items
                =
                list::apply check items
                where
                    fun check { dt, dd }
                        =
                        {
                            list::apply
                              (check_text {
                                in_anchor=>FALSE, in_form, in_pre=>FALSE, in_applet=>FALSE
                              } )
                                dt;

                            check_block { in_form } dd;
                        };
                end

            also
            fun check_rows { in_form } rows
                =
                list::apply check_row rows
                where

                    fun check_cell (html::TH { content, ... } )
                            =>
                            check_body_content { in_form } content;

                        check_cell (html::TD { content, ... } )
                            =>
                            check_body_content { in_form } content;
                    end;


                    fun check_row (html::TR { content, ... } )
                        =
                        list::apply check_cell content;

                end

            also
            fun check_text { in_anchor, in_form, in_pre, in_applet }
                =
                check
                where
                    fun check txt
                        =
                        case txt
                          
                            html::TEXT_LIST tl => list::apply check tl;
                            html::PCDATA _ => ();

                            html::TT     txt => check txt;
                            html::IX     txt => check txt;
                            html::BX     txt => check txt;
                            html::UX     txt => check txt;
                            html::STRIKE txt => check txt;
                            html::EM     txt => check txt;
                            html::STRONG txt => check txt;
                            html::DFN    txt => check txt;
                            html::CODE   txt => check txt;
                            html::SAMP   txt => check txt;
                            html::KBD    txt => check txt;
                            html::VAR    txt => check txt;
                            html::CITE   txt => check txt;

                            html::BIG   txt => { if in_pre  error("BIG",   "PRE"); fi; check txt; };
                            html::SMALL txt => { if in_pre  error("SMALL", "PRE"); fi; check txt; };
                            html::SUB   txt => { if in_pre  error("SUB",   "PRE"); fi; check txt; };
                            html::SUP   txt => { if in_pre  error("SUP",   "PRE"); fi; check txt; };

                            html::AX { content, ... }
                               =>
                               {   if in_anchor  error("anchor", "anchor"); fi;

                                   check_text {
                                       in_anchor=>TRUE, in_form, in_pre,
                                       in_applet
                                     } content;
                               };

                            html::IMG _ =>
                               if in_pre  error("IMG", "PRE"); fi;

                            html::APPLET { content, ... }  => check_text {
                                 in_anchor=>FALSE, in_form, in_pre,
                                 in_applet=>TRUE
                               } content;

                            html::PARAM _                    => if in_applet  error ("parameter", "applet"); fi;
                            html::FONT {     content, ... }  => if in_pre     error("FONT",       "PRE"   ); fi;
                            html::BASEFONT { content, ... }  => if in_pre     error("BASEFONT",   "PRE"   ); fi;

                            html::BR _ => ();
                            html::MAP _ => ();

                            html::INPUT { type, name, value, ... } 
                                =>
                                {
                                    if (not in_form)  form_error "INPUT"; fi;

                                    if ((name == NULL)
                                    and (type != THE html::input_type::submit)
                                    and (type != THE html::input_type::reset))
                                          attribute_error "NAME";
                                    fi;

                                    if ((value == NULL)
                                    and ((type == THE html::input_type::radio)
                                    or (type == THE html::input_type::checkbox)))
                                         attribute_error "VALUE";
                                    fi;
                                };

                            html::SELECT   _ =>  if (not in_form)  form_error "SELECT";   fi;
                            html::TEXTAREA _ =>  if (not in_form)  form_error "TEXTAREA"; fi;

                            html::SCRIPT _   => ();
                        esac;
                end;                    # fun check_text
        end;                            # fun check
};


## COPYRIGHT (c) 1996 AT&T Research.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2013,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext