validator/engine/htmlparser.js
/**
   * Enter a tag, opening a scope for child tags. Entering a tag can close the
   * previous tag or enter other tags (such as opening a <body> tag when
   * encountering a tag not allowed outside the body.
   * @param {!string} tagName
   * @param {!Array<string>} encounteredAttrs Alternating key/value pairs.
   */
Enter a tag, opening a scope for child tags. Entering a tag can close the
previous tag or enter other tags (such as opening a  tag when
encountering a tag not allowed outside the body.
@param {!string} tagName
@param {!Array} encounteredAttrs Alternating key/value pairs.
Enter a tag opening a scope for child tags . Entering a tag can close the previous tag or enter other tags ( such as opening a tag when encountering a tag not allowed outside the body . @param { !string } tagName @param { !Array } encounteredAttrs Alternating key / value pairs .
startTag(tagName, encounteredAttrs) {
    if (tagName === 'BODY') {
      for (var ii = 0; ii < encounteredAttrs.length; ii++) {
        this.effectiveBodyAttribs_.push(encounteredAttrs[ii]);
      }
    }
    switch (this.region_) {
      case TagRegion.PRE_HEAD:
        if (tagName === 'HEAD') {
          this.region_ = TagRegion.IN_HEAD;
        } else if (tagName === 'BODY') {
          this.region_ = TagRegion.IN_BODY;
        } else if (!HtmlStructureElements.hasOwnProperty(tagName)) {
          if (HeadElements.hasOwnProperty(tagName)) {
            this.startTag('HEAD', []);
          } else {
            if (this.handler_.markManufacturedBody)
              this.handler_.markManufacturedBody();
            this.startTag('BODY', []);
          }
        }
        break;
      case TagRegion.IN_HEAD:
        if (!HeadElements.hasOwnProperty(tagName)) {
          this.endTag('HEAD');
          if (tagName !== 'BODY') {
            if (this.handler_.markManufacturedBody)
              this.handler_.markManufacturedBody();
            this.startTag('BODY', []);
          } else {
            this.region_ = TagRegion.IN_BODY;
          }
        }
        break;
      case TagRegion.PRE_BODY:
        if (tagName !== 'BODY') {
          if (this.handler_.markManufacturedBody)
            this.handler_.markManufacturedBody();
          this.startTag('BODY', []);
        } else {
          this.region_ = TagRegion.IN_BODY;
        }
        break;
      case TagRegion.IN_BODY:
        if (tagName === 'BODY') {
          return;
        }
        if (this.stack_.length > 0) {
          const parentTagName = this.stack_[this.stack_.length - 1];
          if (parentTagName === 'P' &&
              ElementsWhichClosePTag.hasOwnProperty(tagName)) {
            this.endTag('P');
          } else if ((tagName == 'DD' || tagName == 'DT') &&
                     (parentTagName == 'DD' || parentTagName == 'DT')) {
            this.endTag(parentTagName);
          } else if (tagName == 'LI' && parentTagName == 'LI') {
            this.endTag('LI');
          }
        }
        break;
      default:
        break;
    }
    if (this.handler_.startTag) {
      this.handler_.startTag(tagName, encounteredAttrs);
    }
    if (ElementsWithNoEndElements.hasOwnProperty(tagName)) {
      if (this.handler_.endTag) {
        this.handler_.endTag(tagName);
      }
    } else {
      this.stack_.push(tagName);
    }
  }
startTag ( tagName , encounteredAttrs ) { if ( tagName === 'BODY' ) { for ( var ii = 0 ; ii < encounteredAttrs . length ; ii ++ ) { this . effectiveBodyAttribs_ . push ( encounteredAttrs [ ii ] ) ; } } switch ( this . region_ ) { case TagRegion . PRE_HEAD : if ( tagName === 'HEAD' ) { this . region_ = TagRegion . IN_HEAD ; } else if ( tagName === 'BODY' ) { this . region_ = TagRegion . IN_BODY ; } else if ( ! HtmlStructureElements . hasOwnProperty ( tagName ) ) { if ( HeadElements . hasOwnProperty ( tagName ) ) { this . startTag ( 'HEAD' , [ ] ) ; } else { if ( this . handler_ . markManufacturedBody ) this . handler_ . markManufacturedBody ( ) ; this . startTag ( 'BODY' , [ ] ) ; } } break ; case TagRegion . IN_HEAD : if ( ! HeadElements . hasOwnProperty ( tagName ) ) { this . endTag ( 'HEAD' ) ; if ( tagName !== 'BODY' ) { if ( this . handler_ . markManufacturedBody ) this . handler_ . markManufacturedBody ( ) ; this . startTag ( 'BODY' , [ ] ) ; } else { this . region_ = TagRegion . IN_BODY ; } } break ; case TagRegion . PRE_BODY : if ( tagName !== 'BODY' ) { if ( this . handler_ . markManufacturedBody ) this . handler_ . markManufacturedBody ( ) ; this . startTag ( 'BODY' , [ ] ) ; } else { this . region_ = TagRegion . IN_BODY ; } break ; case TagRegion . IN_BODY : if ( tagName === 'BODY' ) { return ; } if ( this . stack_ . length > 0 ) { const parentTagName = this . stack_ [ this . stack_ . length - 1 ] ; if ( parentTagName === 'P' && ElementsWhichClosePTag . hasOwnProperty ( tagName ) ) { this . endTag ( 'P' ) ; } else if ( ( tagName == 'DD' || tagName == 'DT' ) && ( parentTagName == 'DD' || parentTagName == 'DT' ) ) { this . endTag ( parentTagName ) ; } else if ( tagName == 'LI' && parentTagName == 'LI' ) { this . endTag ( 'LI' ) ; } } break ; default : break ; } if ( this . handler_ . startTag ) { this . handler_ . startTag ( tagName , encounteredAttrs ) ; } if ( ElementsWithNoEndElements . hasOwnProperty ( tagName ) ) { if ( this . handler_ . endTag ) { this . handler_ . endTag ( tagName ) ; } } else { this . stack_ . push ( tagName ) ; } }
Enter a tag, opening a scope for child tags.
Enter a tag opening a scope for child tags .
// We only report the first body for each document - either // a manufactured one, or the first one encountered. However, // we collect all attributes in this.effectiveBodyAttribs_. // This section deals with manufacturing <head>, </head>, and <body> tags // if the document has left them out or placed them in the wrong location. // We only report the first body for each document - either // a manufactured one, or the first one encountered. // Check implicit tag closing due to opening tags. // <p> tags can be implicitly closed by certain other start tags. // See https://www.w3.org/TR/html-markup/p.html // <dd> and <dt> tags can be implicitly closed by other <dd> and <dt> // tags. See https://www.w3.org/TR/html-markup/dd.html // <li> tags can be implicitly closed by other <li> tags. // See https://www.w3.org/TR/html-markup/li.html