github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/html/doc.go (about)

     1  // Copyright 2010 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  /*
     6  Package html implements an HTML5-compliant tokenizer and parser.
     7  
     8  Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
     9  caller's responsibility to ensure that r provides UTF-8 encoded HTML.
    10  
    11  	z := html.NewTokenizer(r)
    12  
    13  Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(),
    14  which parses the next token and returns its type, or an error:
    15  
    16  	for {
    17  		tt := z.Next()
    18  		if tt == html.ErrorToken {
    19  			// ...
    20  			return ...
    21  		}
    22  		// Process the current token.
    23  	}
    24  
    25  There are two APIs for retrieving the current token. The high-level API is to
    26  call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs
    27  allow optionally calling Raw after Next but before Token, Text, TagName, or
    28  TagAttr. In EBNF notation, the valid call sequence per token is:
    29  
    30  	Next {Raw} [ Token | Text | TagName {TagAttr} ]
    31  
    32  Token returns an independent data structure that completely describes a token.
    33  Entities (such as "<") are unescaped, tag names and attribute keys are
    34  lower-cased, and attributes are collected into a []Attribute. For example:
    35  
    36  	for {
    37  		if z.Next() == html.ErrorToken {
    38  			// Returning io.EOF indicates success.
    39  			return z.Err()
    40  		}
    41  		emitToken(z.Token())
    42  	}
    43  
    44  The low-level API performs fewer allocations and copies, but the contents of
    45  the []byte values returned by Text, TagName and TagAttr may change on the next
    46  call to Next. For example, to extract an HTML page's anchor text:
    47  
    48  	depth := 0
    49  	for {
    50  		tt := z.Next()
    51  		switch tt {
    52  		case html.ErrorToken:
    53  			return z.Err()
    54  		case html.TextToken:
    55  			if depth > 0 {
    56  				// emitBytes should copy the []byte it receives,
    57  				// if it doesn't process it immediately.
    58  				emitBytes(z.Text())
    59  			}
    60  		case html.StartTagToken, html.EndTagToken:
    61  			tn, _ := z.TagName()
    62  			if len(tn) == 1 && tn[0] == 'a' {
    63  				if tt == html.StartTagToken {
    64  					depth++
    65  				} else {
    66  					depth--
    67  				}
    68  			}
    69  		}
    70  	}
    71  
    72  Parsing is done by calling Parse with an io.Reader, which returns the root of
    73  the parse tree (the document element) as a *Node. It is the caller's
    74  responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
    75  example, to process each anchor node in depth-first order:
    76  
    77  	doc, err := html.Parse(r)
    78  	if err != nil {
    79  		// ...
    80  	}
    81  	var f func(*html.Node)
    82  	f = func(n *html.Node) {
    83  		if n.Type == html.ElementNode && n.Data == "a" {
    84  			// Do something with n...
    85  		}
    86  		for c := n.FirstChild; c != nil; c = c.NextSibling {
    87  			f(c)
    88  		}
    89  	}
    90  	f(doc)
    91  
    92  The relevant specifications include:
    93  https://html.spec.whatwg.org/multipage/syntax.html and
    94  https://html.spec.whatwg.org/multipage/syntax.html#tokenization
    95  */
    96  package html // import "github.com/hxx258456/ccgo/net/html"
    97  
    98  // The tokenization algorithm implemented by this package is not a line-by-line
    99  // transliteration of the relatively verbose state-machine in the WHATWG
   100  // specification. A more direct approach is used instead, where the program
   101  // counter implies the state, such as whether it is tokenizing a tag or a text
   102  // node. Specification compliance is verified by checking expected and actual
   103  // outputs over a test suite rather than aiming for algorithmic fidelity.
   104  
   105  // TODO(nigeltao): Does a DOM API belong in this package or a separate one?
   106  // TODO(nigeltao): How does parsing interact with a JavaScript engine?