@@ -6,16 +6,14 @@ package api
66import (
77 "bufio"
88 "encoding/json"
9+ "encoding/xml"
910 "fmt"
1011 "html"
1112 "io"
1213 "log"
1314 "os"
1415 "regexp"
1516 "strings"
16-
17- xhtml "golang.org/x/net/html"
18- "golang.org/x/net/html/atom"
1917)
2018
2119type apiDocumentation struct {
@@ -225,12 +223,17 @@ func getLeadingWhitespace(v string) string {
225223
226224// generateDoc will generate the proper doc string for html encoded or plain text doc entries.
227225func generateDoc (htmlSrc string ) string {
228- tokenizer := xhtml .NewTokenizer (strings .NewReader (htmlSrc ))
226+ tokenizer := xml .NewDecoder (strings .NewReader (htmlSrc ))
227+ tokenizer .Strict = false
228+ tokenizer .AutoClose = xml .HTMLAutoClose
229+ tokenizer .Entity = xml .HTMLEntity
230+
231+ // Some service docstrings are hopelessly malformed. Rather than throwing
232+ // up our hands, the converter will map over as much as it can. If it
233+ // returns an error, we stop there and go with whatever it was able to
234+ // produce.
229235 var builder strings.Builder
230- if err := encodeHTMLToText (& builder , tokenizer ); err != nil {
231- panic (fmt .Sprintf ("failed to generated docs, %v" , err ))
232- }
233-
236+ encodeHTMLToText (& builder , tokenizer )
234237 return wrap (strings .Trim (builder .String (), "\n " ), 72 )
235238}
236239
@@ -241,31 +244,30 @@ type stringWriter interface {
241244 WriteString (string ) (int , error )
242245}
243246
244- func encodeHTMLToText (w stringWriter , z * xhtml. Tokenizer ) error {
247+ func encodeHTMLToText (w stringWriter , z * xml. Decoder ) error {
245248 encoder := newHTMLTokenEncoder (w )
246249 defer encoder .Flush ()
247250
248251 for {
249- tt := z .Next ()
250- if tt == xhtml .ErrorToken {
251- if err := z .Err (); err == io .EOF {
252- return nil
253- } else if err != nil {
254- return err
255- }
252+ tt , err := z .Token ()
253+ if err == io .EOF {
254+ return nil
255+ }
256+ if err != nil {
257+ return err
256258 }
257259
258- if err := encoder .Encode (z . Token () ); err != nil {
260+ if err := encoder .Encode (tt ); err != nil {
259261 return err
260262 }
261263 }
262264}
263265
264266type htmlTokenHandler interface {
265- OnStartTagToken (xhtml. Token ) htmlTokenHandler
266- OnEndTagToken (xhtml .Token , bool )
267- OnSelfClosingTagToken (xhtml .Token )
268- OnTextTagToken (xhtml. Token )
267+ OnStartTagToken (xml. StartElement ) htmlTokenHandler
268+ OnEndTagToken (xml .Token , bool )
269+ OnSelfClosingTagToken (xml .Token )
270+ OnTextTagToken (xml. CharData )
269271}
270272
271273type htmlTokenEncoder struct {
@@ -293,29 +295,29 @@ func newHTMLTokenEncoder(w stringWriter) *htmlTokenEncoder {
293295}
294296
295297func (e * htmlTokenEncoder ) Flush () error {
296- e .baseHandler .handler .OnEndTagToken (xhtml. Token { Type : xhtml . TextToken } , true )
298+ e .baseHandler .handler .OnEndTagToken (xml . CharData ([] byte {}) , true )
297299 return nil
298300}
299301
300- func (e * htmlTokenEncoder ) Encode (token xhtml .Token ) error {
302+ func (e * htmlTokenEncoder ) Encode (token xml .Token ) error {
301303 h := e .baseHandler
302304 if len (e .handlers ) != 0 {
303305 h = e .handlers [len (e .handlers )- 1 ]
304306 }
305307
306- switch token .Type {
307- case xhtml . StartTagToken :
308+ switch v := token .( type ) {
309+ case xml. StartElement :
308310 e .depth ++
309311
310- next := h .handler .OnStartTagToken (token )
312+ next := h .handler .OnStartTagToken (v )
311313 if next != nil {
312314 e .handlers = append (e .handlers , tokenHandlerItem {
313315 handler : next ,
314316 depth : e .depth ,
315317 })
316318 }
317319
318- case xhtml . EndTagToken :
320+ case xml. EndElement :
319321 handlerBlockClosing := e .depth == h .depth
320322
321323 h .handler .OnEndTagToken (token , handlerBlockClosing )
@@ -330,11 +332,8 @@ func (e *htmlTokenEncoder) Encode(token xhtml.Token) error {
330332 e .depth = 0
331333 }
332334
333- case xhtml .SelfClosingTagToken :
334- h .handler .OnSelfClosingTagToken (token )
335-
336- case xhtml .TextToken :
337- h .handler .OnTextTagToken (token )
335+ case xml.CharData :
336+ h .handler .OnTextTagToken (v )
338337 }
339338
340339 return nil
@@ -344,11 +343,11 @@ type baseTokenHandler struct {
344343 w stringWriter
345344}
346345
347- func (e * baseTokenHandler ) OnStartTagToken (token xhtml. Token ) htmlTokenHandler { return nil }
348- func (e * baseTokenHandler ) OnEndTagToken (token xhtml .Token , blockClosing bool ) {}
349- func (e * baseTokenHandler ) OnSelfClosingTagToken (token xhtml .Token ) {}
350- func (e * baseTokenHandler ) OnTextTagToken (token xhtml. Token ) {
351- e .w .WriteString (token . Data )
346+ func (e * baseTokenHandler ) OnStartTagToken (token xml. StartElement ) htmlTokenHandler { return nil }
347+ func (e * baseTokenHandler ) OnEndTagToken (token xml .Token , blockClosing bool ) {}
348+ func (e * baseTokenHandler ) OnSelfClosingTagToken (token xml .Token ) {}
349+ func (e * baseTokenHandler ) OnTextTagToken (token xml. CharData ) {
350+ e .w .WriteString (string ( token ) )
352351}
353352
354353type blockTokenHandler struct {
@@ -372,27 +371,27 @@ func newBlockTokenHandler(w stringWriter) *blockTokenHandler {
372371 },
373372 }
374373}
375- func (e * blockTokenHandler ) OnStartTagToken (token xhtml. Token ) htmlTokenHandler {
374+ func (e * blockTokenHandler ) OnStartTagToken (token xml. StartElement ) htmlTokenHandler {
376375 e .started = true
377376 if e .newlineBeforeNextBlock {
378377 e .w .WriteString ("\n " )
379378 e .newlineBeforeNextBlock = false
380379 }
381380
382- switch token .DataAtom {
383- case atom . A :
381+ switch token .Name . Local {
382+ case "a" :
384383 return newLinkTokenHandler (e .w , token )
385- case atom . Ul :
384+ case "ul" :
386385 e .w .WriteString ("\n " )
387386 e .newlineBeforeNextBlock = true
388387 return newListTokenHandler (e .w )
389388
390- case atom . Div , atom . Dt , atom . P , atom . H1 , atom . H2 , atom . H3 , atom . H4 , atom . H5 , atom . H6 :
389+ case "div" , "dt" , "p" , "h1" , "h2" , "h3" , "h4" , "h5" , "h6" :
391390 e .w .WriteString ("\n " )
392391 e .newlineBeforeNextBlock = true
393392 return newBlockTokenHandler (e .w )
394393
395- case atom . Pre , atom . Code :
394+ case "pre" , "code" :
396395 if e .rootBlock {
397396 e .w .WriteString ("\n " )
398397 e .w .WriteString (indent )
@@ -403,7 +402,7 @@ func (e *blockTokenHandler) OnStartTagToken(token xhtml.Token) htmlTokenHandler
403402
404403 return nil
405404}
406- func (e * blockTokenHandler ) OnEndTagToken (token xhtml .Token , blockClosing bool ) {
405+ func (e * blockTokenHandler ) OnEndTagToken (token xml .Token , blockClosing bool ) {
407406 if ! blockClosing {
408407 return
409408 }
@@ -417,34 +416,34 @@ func (e *blockTokenHandler) OnEndTagToken(token xhtml.Token, blockClosing bool)
417416 e .strBuilder .Reset ()
418417}
419418
420- func (e * blockTokenHandler ) OnTextTagToken (token xhtml. Token ) {
419+ func (e * blockTokenHandler ) OnTextTagToken (token xml. CharData ) {
421420 if e .newlineBeforeNextBlock {
422421 e .w .WriteString ("\n " )
423422 e .newlineBeforeNextBlock = false
424423 }
425424 if ! e .started {
426- token . Data = strings .TrimLeft (token . Data , " \t \n " )
425+ token = xml . CharData ( strings .TrimLeft (string ( token ) , " \t \n " ) )
427426 }
428- if len (token . Data ) != 0 {
427+ if len (token ) != 0 {
429428 e .started = true
430429 }
431430 e .baseTokenHandler .OnTextTagToken (token )
432431}
433432
434433type linkTokenHandler struct {
435434 baseTokenHandler
436- linkToken xhtml. Token
435+ linkToken xml. StartElement
437436}
438437
439- func newLinkTokenHandler (w stringWriter , token xhtml. Token ) * linkTokenHandler {
438+ func newLinkTokenHandler (w stringWriter , token xml. StartElement ) * linkTokenHandler {
440439 return & linkTokenHandler {
441440 baseTokenHandler : baseTokenHandler {
442441 w : w ,
443442 },
444443 linkToken : token ,
445444 }
446445}
447- func (e * linkTokenHandler ) OnEndTagToken (token xhtml .Token , blockClosing bool ) {
446+ func (e * linkTokenHandler ) OnEndTagToken (token xml .Token , blockClosing bool ) {
448447 if ! blockClosing {
449448 return
450449 }
@@ -467,9 +466,9 @@ func newListTokenHandler(w stringWriter) *listTokenHandler {
467466 },
468467 }
469468}
470- func (e * listTokenHandler ) OnStartTagToken (token xhtml. Token ) htmlTokenHandler {
471- switch token .DataAtom {
472- case atom . Li :
469+ func (e * listTokenHandler ) OnStartTagToken (token xml. StartElement ) htmlTokenHandler {
470+ switch token .Name . Local {
471+ case "li" :
473472 if e .items >= 1 {
474473 e .w .WriteString ("\n \n " )
475474 }
@@ -479,7 +478,7 @@ func (e *listTokenHandler) OnStartTagToken(token xhtml.Token) htmlTokenHandler {
479478 return nil
480479}
481480
482- func (e * listTokenHandler ) OnTextTagToken (token xhtml. Token ) {
481+ func (e * listTokenHandler ) OnTextTagToken (token xml. CharData ) {
483482 // Squash whitespace between list and items
484483}
485484
@@ -500,14 +499,14 @@ func newListItemTokenHandler(w stringWriter) *listItemTokenHandler {
500499 },
501500 }
502501}
503- func (e * listItemTokenHandler ) OnStartTagToken (token xhtml. Token ) htmlTokenHandler {
504- switch token .DataAtom {
505- case atom . P :
502+ func (e * listItemTokenHandler ) OnStartTagToken (token xml. StartElement ) htmlTokenHandler {
503+ switch token .Name . Local {
504+ case "p" :
506505 return newBlockTokenHandler (e .w )
507506 }
508507 return nil
509508}
510- func (e * listItemTokenHandler ) OnEndTagToken (token xhtml .Token , blockClosing bool ) {
509+ func (e * listItemTokenHandler ) OnEndTagToken (token xml .Token , blockClosing bool ) {
511510 if ! blockClosing {
512511 return
513512 }
@@ -533,18 +532,18 @@ func newTrimSpaceTokenHandler(w stringWriter) *trimSpaceTokenHandler {
533532 },
534533 }
535534}
536- func (e * trimSpaceTokenHandler ) OnEndTagToken (token xhtml .Token , blockClosing bool ) {
535+ func (e * trimSpaceTokenHandler ) OnEndTagToken (token xml .Token , blockClosing bool ) {
537536 if ! blockClosing {
538537 return
539538 }
540539
541540 e .origWriter .WriteString (strings .TrimSpace (e .strBuilder .String ()))
542541}
543542
544- func getHTMLTokenAttr (attr []xhtml. Attribute , name string ) (string , bool ) {
543+ func getHTMLTokenAttr (attr []xml. Attr , name string ) (string , bool ) {
545544 for _ , a := range attr {
546- if strings .EqualFold (a .Key , name ) {
547- return a .Val , true
545+ if strings .EqualFold (a .Name . Local , name ) {
546+ return a .Value , true
548547 }
549548 }
550549 return "" , false
0 commit comments