How to use Options method of html Package

Best K6 code snippet using html.Options

html.go

Source:html.go Github

copy

Full Screen

1//2// Blackfriday Markdown Processor3// Available at http://github.com/russross/blackfriday4//5// Copyright © 2011 Russ Ross <russ@russross.com>.6// Distributed under the Simplified BSD License.7// See README.md for details.8//9//10//11// HTML rendering backend12//13//14package blackfriday15import (16 "bytes"17 "fmt"18 "regexp"19 "strconv"20 "strings"21)22// Html renderer configuration options.23const (24 HTML_SKIP_HTML = 1 << iota // skip preformatted HTML blocks25 HTML_SKIP_STYLE // skip embedded <style> elements26 HTML_SKIP_IMAGES // skip embedded images27 HTML_SKIP_LINKS // skip all links28 HTML_SAFELINK // only link to trusted protocols29 HTML_NOFOLLOW_LINKS // only link with rel="nofollow"30 HTML_NOREFERRER_LINKS // only link with rel="noreferrer"31 HTML_HREF_TARGET_BLANK // add a blank target32 HTML_TOC // generate a table of contents33 HTML_OMIT_CONTENTS // skip the main contents (for a standalone table of contents)34 HTML_COMPLETE_PAGE // generate a complete HTML page35 HTML_USE_XHTML // generate XHTML output instead of HTML36 HTML_USE_SMARTYPANTS // enable smart punctuation substitutions37 HTML_SMARTYPANTS_FRACTIONS // enable smart fractions (with HTML_USE_SMARTYPANTS)38 HTML_SMARTYPANTS_DASHES // enable smart dashes (with HTML_USE_SMARTYPANTS)39 HTML_SMARTYPANTS_LATEX_DASHES // enable LaTeX-style dashes (with HTML_USE_SMARTYPANTS and HTML_SMARTYPANTS_DASHES)40 HTML_SMARTYPANTS_ANGLED_QUOTES // enable angled double quotes (with HTML_USE_SMARTYPANTS) for double quotes rendering41 HTML_SMARTYPANTS_QUOTES_NBSP // enable "French guillemets" (with HTML_USE_SMARTYPANTS)42 HTML_FOOTNOTE_RETURN_LINKS // generate a link at the end of a footnote to return to the source43)44var (45 alignments = []string{46 "left",47 "right",48 "center",49 }50 // TODO: improve this regexp to catch all possible entities:51 htmlEntity = regexp.MustCompile(`&[a-z]{2,5};`)52)53type HtmlRendererParameters struct {54 // Prepend this text to each relative URL.55 AbsolutePrefix string56 // Add this text to each footnote anchor, to ensure uniqueness.57 FootnoteAnchorPrefix string58 // Show this text inside the <a> tag for a footnote return link, if the59 // HTML_FOOTNOTE_RETURN_LINKS flag is enabled. If blank, the string60 // <sup>[return]</sup> is used.61 FootnoteReturnLinkContents string62 // If set, add this text to the front of each Header ID, to ensure63 // uniqueness.64 HeaderIDPrefix string65 // If set, add this text to the back of each Header ID, to ensure uniqueness.66 HeaderIDSuffix string67}68// Html is a type that implements the Renderer interface for HTML output.69//70// Do not create this directly, instead use the HtmlRenderer function.71type Html struct {72 flags int // HTML_* options73 closeTag string // how to end singleton tags: either " />" or ">"74 title string // document title75 css string // optional css file url (used with HTML_COMPLETE_PAGE)76 parameters HtmlRendererParameters77 // table of contents data78 tocMarker int79 headerCount int80 currentLevel int81 toc *bytes.Buffer82 // Track header IDs to prevent ID collision in a single generation.83 headerIDs map[string]int84 smartypants *smartypantsRenderer85}86const (87 xhtmlClose = " />"88 htmlClose = ">"89)90// HtmlRenderer creates and configures an Html object, which91// satisfies the Renderer interface.92//93// flags is a set of HTML_* options ORed together.94// title is the title of the document, and css is a URL for the document's95// stylesheet.96// title and css are only used when HTML_COMPLETE_PAGE is selected.97func HtmlRenderer(flags int, title string, css string) Renderer {98 return HtmlRendererWithParameters(flags, title, css, HtmlRendererParameters{})99}100func HtmlRendererWithParameters(flags int, title string,101 css string, renderParameters HtmlRendererParameters) Renderer {102 // configure the rendering engine103 closeTag := htmlClose104 if flags&HTML_USE_XHTML != 0 {105 closeTag = xhtmlClose106 }107 if renderParameters.FootnoteReturnLinkContents == "" {108 renderParameters.FootnoteReturnLinkContents = `<sup>[return]</sup>`109 }110 return &Html{111 flags: flags,112 closeTag: closeTag,113 title: title,114 css: css,115 parameters: renderParameters,116 headerCount: 0,117 currentLevel: 0,118 toc: new(bytes.Buffer),119 headerIDs: make(map[string]int),120 smartypants: smartypants(flags),121 }122}123// Using if statements is a bit faster than a switch statement. As the compiler124// improves, this should be unnecessary this is only worthwhile because125// attrEscape is the single largest CPU user in normal use.126// Also tried using map, but that gave a ~3x slowdown.127func escapeSingleChar(char byte) (string, bool) {128 if char == '"' {129 return "&quot;", true130 }131 if char == '&' {132 return "&amp;", true133 }134 if char == '<' {135 return "&lt;", true136 }137 if char == '>' {138 return "&gt;", true139 }140 return "", false141}142func attrEscape(out *bytes.Buffer, src []byte) {143 org := 0144 for i, ch := range src {145 if entity, ok := escapeSingleChar(ch); ok {146 if i > org {147 // copy all the normal characters since the last escape148 out.Write(src[org:i])149 }150 org = i + 1151 out.WriteString(entity)152 }153 }154 if org < len(src) {155 out.Write(src[org:])156 }157}158func entityEscapeWithSkip(out *bytes.Buffer, src []byte, skipRanges [][]int) {159 end := 0160 for _, rang := range skipRanges {161 attrEscape(out, src[end:rang[0]])162 out.Write(src[rang[0]:rang[1]])163 end = rang[1]164 }165 attrEscape(out, src[end:])166}167func (options *Html) GetFlags() int {168 return options.flags169}170func (options *Html) TitleBlock(out *bytes.Buffer, text []byte) {171 text = bytes.TrimPrefix(text, []byte("% "))172 text = bytes.Replace(text, []byte("\n% "), []byte("\n"), -1)173 out.WriteString("<h1 class=\"title\">")174 out.Write(text)175 out.WriteString("\n</h1>")176}177func (options *Html) Header(out *bytes.Buffer, text func() bool, level int, id string) {178 marker := out.Len()179 doubleSpace(out)180 if id == "" && options.flags&HTML_TOC != 0 {181 id = fmt.Sprintf("toc_%d", options.headerCount)182 }183 if id != "" {184 id = options.ensureUniqueHeaderID(id)185 if options.parameters.HeaderIDPrefix != "" {186 id = options.parameters.HeaderIDPrefix + id187 }188 if options.parameters.HeaderIDSuffix != "" {189 id = id + options.parameters.HeaderIDSuffix190 }191 out.WriteString(fmt.Sprintf("<h%d id=\"%s\">", level, id))192 } else {193 out.WriteString(fmt.Sprintf("<h%d>", level))194 }195 tocMarker := out.Len()196 if !text() {197 out.Truncate(marker)198 return199 }200 // are we building a table of contents?201 if options.flags&HTML_TOC != 0 {202 options.TocHeaderWithAnchor(out.Bytes()[tocMarker:], level, id)203 }204 out.WriteString(fmt.Sprintf("</h%d>\n", level))205}206func (options *Html) BlockHtml(out *bytes.Buffer, text []byte) {207 if options.flags&HTML_SKIP_HTML != 0 {208 return209 }210 doubleSpace(out)211 out.Write(text)212 out.WriteByte('\n')213}214func (options *Html) HRule(out *bytes.Buffer) {215 doubleSpace(out)216 out.WriteString("<hr")217 out.WriteString(options.closeTag)218 out.WriteByte('\n')219}220func (options *Html) BlockCode(out *bytes.Buffer, text []byte, info string) {221 doubleSpace(out)222 endOfLang := strings.IndexAny(info, "\t ")223 if endOfLang < 0 {224 endOfLang = len(info)225 }226 lang := info[:endOfLang]227 if len(lang) == 0 || lang == "." {228 out.WriteString("<pre><code>")229 } else {230 out.WriteString("<pre><code class=\"language-")231 attrEscape(out, []byte(lang))232 out.WriteString("\">")233 }234 attrEscape(out, text)235 out.WriteString("</code></pre>\n")236}237func (options *Html) BlockQuote(out *bytes.Buffer, text []byte) {238 doubleSpace(out)239 out.WriteString("<blockquote>\n")240 out.Write(text)241 out.WriteString("</blockquote>\n")242}243func (options *Html) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) {244 doubleSpace(out)245 out.WriteString("<table>\n<thead>\n")246 out.Write(header)247 out.WriteString("</thead>\n\n<tbody>\n")248 out.Write(body)249 out.WriteString("</tbody>\n</table>\n")250}251func (options *Html) TableRow(out *bytes.Buffer, text []byte) {252 doubleSpace(out)253 out.WriteString("<tr>\n")254 out.Write(text)255 out.WriteString("\n</tr>\n")256}257func (options *Html) TableHeaderCell(out *bytes.Buffer, text []byte, align int) {258 doubleSpace(out)259 switch align {260 case TABLE_ALIGNMENT_LEFT:261 out.WriteString("<th align=\"left\">")262 case TABLE_ALIGNMENT_RIGHT:263 out.WriteString("<th align=\"right\">")264 case TABLE_ALIGNMENT_CENTER:265 out.WriteString("<th align=\"center\">")266 default:267 out.WriteString("<th>")268 }269 out.Write(text)270 out.WriteString("</th>")271}272func (options *Html) TableCell(out *bytes.Buffer, text []byte, align int) {273 doubleSpace(out)274 switch align {275 case TABLE_ALIGNMENT_LEFT:276 out.WriteString("<td align=\"left\">")277 case TABLE_ALIGNMENT_RIGHT:278 out.WriteString("<td align=\"right\">")279 case TABLE_ALIGNMENT_CENTER:280 out.WriteString("<td align=\"center\">")281 default:282 out.WriteString("<td>")283 }284 out.Write(text)285 out.WriteString("</td>")286}287func (options *Html) Footnotes(out *bytes.Buffer, text func() bool) {288 out.WriteString("<div class=\"footnotes\">\n")289 options.HRule(out)290 options.List(out, text, LIST_TYPE_ORDERED)291 out.WriteString("</div>\n")292}293func (options *Html) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) {294 if flags&LIST_ITEM_CONTAINS_BLOCK != 0 || flags&LIST_ITEM_BEGINNING_OF_LIST != 0 {295 doubleSpace(out)296 }297 slug := slugify(name)298 out.WriteString(`<li id="`)299 out.WriteString(`fn:`)300 out.WriteString(options.parameters.FootnoteAnchorPrefix)301 out.Write(slug)302 out.WriteString(`">`)303 out.Write(text)304 if options.flags&HTML_FOOTNOTE_RETURN_LINKS != 0 {305 out.WriteString(` <a class="footnote-return" href="#`)306 out.WriteString(`fnref:`)307 out.WriteString(options.parameters.FootnoteAnchorPrefix)308 out.Write(slug)309 out.WriteString(`">`)310 out.WriteString(options.parameters.FootnoteReturnLinkContents)311 out.WriteString(`</a>`)312 }313 out.WriteString("</li>\n")314}315func (options *Html) List(out *bytes.Buffer, text func() bool, flags int) {316 marker := out.Len()317 doubleSpace(out)318 if flags&LIST_TYPE_DEFINITION != 0 {319 out.WriteString("<dl>")320 } else if flags&LIST_TYPE_ORDERED != 0 {321 out.WriteString("<ol>")322 } else {323 out.WriteString("<ul>")324 }325 if !text() {326 out.Truncate(marker)327 return328 }329 if flags&LIST_TYPE_DEFINITION != 0 {330 out.WriteString("</dl>\n")331 } else if flags&LIST_TYPE_ORDERED != 0 {332 out.WriteString("</ol>\n")333 } else {334 out.WriteString("</ul>\n")335 }336}337func (options *Html) ListItem(out *bytes.Buffer, text []byte, flags int) {338 if (flags&LIST_ITEM_CONTAINS_BLOCK != 0 && flags&LIST_TYPE_DEFINITION == 0) ||339 flags&LIST_ITEM_BEGINNING_OF_LIST != 0 {340 doubleSpace(out)341 }342 if flags&LIST_TYPE_TERM != 0 {343 out.WriteString("<dt>")344 } else if flags&LIST_TYPE_DEFINITION != 0 {345 out.WriteString("<dd>")346 } else {347 out.WriteString("<li>")348 }349 out.Write(text)350 if flags&LIST_TYPE_TERM != 0 {351 out.WriteString("</dt>\n")352 } else if flags&LIST_TYPE_DEFINITION != 0 {353 out.WriteString("</dd>\n")354 } else {355 out.WriteString("</li>\n")356 }357}358func (options *Html) Paragraph(out *bytes.Buffer, text func() bool) {359 marker := out.Len()360 doubleSpace(out)361 out.WriteString("<p>")362 if !text() {363 out.Truncate(marker)364 return365 }366 out.WriteString("</p>\n")367}368func (options *Html) AutoLink(out *bytes.Buffer, link []byte, kind int) {369 skipRanges := htmlEntity.FindAllIndex(link, -1)370 if options.flags&HTML_SAFELINK != 0 && !isSafeLink(link) && kind != LINK_TYPE_EMAIL {371 // mark it but don't link it if it is not a safe link: no smartypants372 out.WriteString("<tt>")373 entityEscapeWithSkip(out, link, skipRanges)374 out.WriteString("</tt>")375 return376 }377 out.WriteString("<a href=\"")378 if kind == LINK_TYPE_EMAIL {379 out.WriteString("mailto:")380 } else {381 options.maybeWriteAbsolutePrefix(out, link)382 }383 entityEscapeWithSkip(out, link, skipRanges)384 var relAttrs []string385 if options.flags&HTML_NOFOLLOW_LINKS != 0 && !isRelativeLink(link) {386 relAttrs = append(relAttrs, "nofollow")387 }388 if options.flags&HTML_NOREFERRER_LINKS != 0 && !isRelativeLink(link) {389 relAttrs = append(relAttrs, "noreferrer")390 }391 if len(relAttrs) > 0 {392 out.WriteString(fmt.Sprintf("\" rel=\"%s", strings.Join(relAttrs, " ")))393 }394 // blank target only add to external link395 if options.flags&HTML_HREF_TARGET_BLANK != 0 && !isRelativeLink(link) {396 out.WriteString("\" target=\"_blank")397 }398 out.WriteString("\">")399 // Pretty print: if we get an email address as400 // an actual URI, e.g. `mailto:foo@bar.com`, we don't401 // want to print the `mailto:` prefix402 switch {403 case bytes.HasPrefix(link, []byte("mailto://")):404 attrEscape(out, link[len("mailto://"):])405 case bytes.HasPrefix(link, []byte("mailto:")):406 attrEscape(out, link[len("mailto:"):])407 default:408 entityEscapeWithSkip(out, link, skipRanges)409 }410 out.WriteString("</a>")411}412func (options *Html) CodeSpan(out *bytes.Buffer, text []byte) {413 out.WriteString("<code>")414 attrEscape(out, text)415 out.WriteString("</code>")416}417func (options *Html) DoubleEmphasis(out *bytes.Buffer, text []byte) {418 out.WriteString("<strong>")419 out.Write(text)420 out.WriteString("</strong>")421}422func (options *Html) Emphasis(out *bytes.Buffer, text []byte) {423 if len(text) == 0 {424 return425 }426 out.WriteString("<em>")427 out.Write(text)428 out.WriteString("</em>")429}430func (options *Html) maybeWriteAbsolutePrefix(out *bytes.Buffer, link []byte) {431 if options.parameters.AbsolutePrefix != "" && isRelativeLink(link) && link[0] != '.' {432 out.WriteString(options.parameters.AbsolutePrefix)433 if link[0] != '/' {434 out.WriteByte('/')435 }436 }437}438func (options *Html) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {439 if options.flags&HTML_SKIP_IMAGES != 0 {440 return441 }442 out.WriteString("<img src=\"")443 options.maybeWriteAbsolutePrefix(out, link)444 attrEscape(out, link)445 out.WriteString("\" alt=\"")446 if len(alt) > 0 {447 attrEscape(out, alt)448 }449 if len(title) > 0 {450 out.WriteString("\" title=\"")451 attrEscape(out, title)452 }453 out.WriteByte('"')454 out.WriteString(options.closeTag)455}456func (options *Html) LineBreak(out *bytes.Buffer) {457 out.WriteString("<br")458 out.WriteString(options.closeTag)459 out.WriteByte('\n')460}461func (options *Html) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {462 if options.flags&HTML_SKIP_LINKS != 0 {463 // write the link text out but don't link it, just mark it with typewriter font464 out.WriteString("<tt>")465 attrEscape(out, content)466 out.WriteString("</tt>")467 return468 }469 if options.flags&HTML_SAFELINK != 0 && !isSafeLink(link) {470 // write the link text out but don't link it, just mark it with typewriter font471 out.WriteString("<tt>")472 attrEscape(out, content)473 out.WriteString("</tt>")474 return475 }476 out.WriteString("<a href=\"")477 options.maybeWriteAbsolutePrefix(out, link)478 attrEscape(out, link)479 if len(title) > 0 {480 out.WriteString("\" title=\"")481 attrEscape(out, title)482 }483 var relAttrs []string484 if options.flags&HTML_NOFOLLOW_LINKS != 0 && !isRelativeLink(link) {485 relAttrs = append(relAttrs, "nofollow")486 }487 if options.flags&HTML_NOREFERRER_LINKS != 0 && !isRelativeLink(link) {488 relAttrs = append(relAttrs, "noreferrer")489 }490 if len(relAttrs) > 0 {491 out.WriteString(fmt.Sprintf("\" rel=\"%s", strings.Join(relAttrs, " ")))492 }493 // blank target only add to external link494 if options.flags&HTML_HREF_TARGET_BLANK != 0 && !isRelativeLink(link) {495 out.WriteString("\" target=\"_blank")496 }497 out.WriteString("\">")498 out.Write(content)499 out.WriteString("</a>")500 return501}502func (options *Html) RawHtmlTag(out *bytes.Buffer, text []byte) {503 if options.flags&HTML_SKIP_HTML != 0 {504 return505 }506 if options.flags&HTML_SKIP_STYLE != 0 && isHtmlTag(text, "style") {507 return508 }509 if options.flags&HTML_SKIP_LINKS != 0 && isHtmlTag(text, "a") {510 return511 }512 if options.flags&HTML_SKIP_IMAGES != 0 && isHtmlTag(text, "img") {513 return514 }515 out.Write(text)516}517func (options *Html) TripleEmphasis(out *bytes.Buffer, text []byte) {518 out.WriteString("<strong><em>")519 out.Write(text)520 out.WriteString("</em></strong>")521}522func (options *Html) StrikeThrough(out *bytes.Buffer, text []byte) {523 out.WriteString("<del>")524 out.Write(text)525 out.WriteString("</del>")526}527func (options *Html) FootnoteRef(out *bytes.Buffer, ref []byte, id int) {528 slug := slugify(ref)529 out.WriteString(`<sup class="footnote-ref" id="`)530 out.WriteString(`fnref:`)531 out.WriteString(options.parameters.FootnoteAnchorPrefix)532 out.Write(slug)533 out.WriteString(`"><a href="#`)534 out.WriteString(`fn:`)535 out.WriteString(options.parameters.FootnoteAnchorPrefix)536 out.Write(slug)537 out.WriteString(`">`)538 out.WriteString(strconv.Itoa(id))539 out.WriteString(`</a></sup>`)540}541func (options *Html) Entity(out *bytes.Buffer, entity []byte) {542 out.Write(entity)543}544func (options *Html) NormalText(out *bytes.Buffer, text []byte) {545 if options.flags&HTML_USE_SMARTYPANTS != 0 {546 options.Smartypants(out, text)547 } else {548 attrEscape(out, text)549 }550}551func (options *Html) Smartypants(out *bytes.Buffer, text []byte) {552 smrt := smartypantsData{false, false}553 // first do normal entity escaping554 var escaped bytes.Buffer555 attrEscape(&escaped, text)556 text = escaped.Bytes()557 mark := 0558 for i := 0; i < len(text); i++ {559 if action := options.smartypants[text[i]]; action != nil {560 if i > mark {561 out.Write(text[mark:i])562 }563 previousChar := byte(0)564 if i > 0 {565 previousChar = text[i-1]566 }567 i += action(out, &smrt, previousChar, text[i:])568 mark = i + 1569 }570 }571 if mark < len(text) {572 out.Write(text[mark:])573 }574}575func (options *Html) DocumentHeader(out *bytes.Buffer) {576 if options.flags&HTML_COMPLETE_PAGE == 0 {577 return578 }579 ending := ""580 if options.flags&HTML_USE_XHTML != 0 {581 out.WriteString("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" ")582 out.WriteString("\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n")583 out.WriteString("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n")584 ending = " /"585 } else {586 out.WriteString("<!DOCTYPE html>\n")587 out.WriteString("<html>\n")588 }589 out.WriteString("<head>\n")590 out.WriteString(" <title>")591 options.NormalText(out, []byte(options.title))592 out.WriteString("</title>\n")593 out.WriteString(" <meta name=\"GENERATOR\" content=\"Blackfriday Markdown Processor v")594 out.WriteString(VERSION)595 out.WriteString("\"")596 out.WriteString(ending)597 out.WriteString(">\n")598 out.WriteString(" <meta charset=\"utf-8\"")599 out.WriteString(ending)600 out.WriteString(">\n")601 if options.css != "" {602 out.WriteString(" <link rel=\"stylesheet\" type=\"text/css\" href=\"")603 attrEscape(out, []byte(options.css))604 out.WriteString("\"")605 out.WriteString(ending)606 out.WriteString(">\n")607 }608 out.WriteString("</head>\n")609 out.WriteString("<body>\n")610 options.tocMarker = out.Len()611}612func (options *Html) DocumentFooter(out *bytes.Buffer) {613 // finalize and insert the table of contents614 if options.flags&HTML_TOC != 0 {615 options.TocFinalize()616 // now we have to insert the table of contents into the document617 var temp bytes.Buffer618 // start by making a copy of everything after the document header619 temp.Write(out.Bytes()[options.tocMarker:])620 // now clear the copied material from the main output buffer621 out.Truncate(options.tocMarker)622 // corner case spacing issue623 if options.flags&HTML_COMPLETE_PAGE != 0 {624 out.WriteByte('\n')625 }626 // insert the table of contents627 out.WriteString("<nav>\n")628 out.Write(options.toc.Bytes())629 out.WriteString("</nav>\n")630 // corner case spacing issue631 if options.flags&HTML_COMPLETE_PAGE == 0 && options.flags&HTML_OMIT_CONTENTS == 0 {632 out.WriteByte('\n')633 }634 // write out everything that came after it635 if options.flags&HTML_OMIT_CONTENTS == 0 {636 out.Write(temp.Bytes())637 }638 }639 if options.flags&HTML_COMPLETE_PAGE != 0 {640 out.WriteString("\n</body>\n")641 out.WriteString("</html>\n")642 }643}644func (options *Html) TocHeaderWithAnchor(text []byte, level int, anchor string) {645 for level > options.currentLevel {646 switch {647 case bytes.HasSuffix(options.toc.Bytes(), []byte("</li>\n")):648 // this sublist can nest underneath a header649 size := options.toc.Len()650 options.toc.Truncate(size - len("</li>\n"))651 case options.currentLevel > 0:652 options.toc.WriteString("<li>")653 }654 if options.toc.Len() > 0 {655 options.toc.WriteByte('\n')656 }657 options.toc.WriteString("<ul>\n")658 options.currentLevel++659 }660 for level < options.currentLevel {661 options.toc.WriteString("</ul>")662 if options.currentLevel > 1 {663 options.toc.WriteString("</li>\n")664 }665 options.currentLevel--666 }667 options.toc.WriteString("<li><a href=\"#")668 if anchor != "" {669 options.toc.WriteString(anchor)670 } else {671 options.toc.WriteString("toc_")672 options.toc.WriteString(strconv.Itoa(options.headerCount))673 }674 options.toc.WriteString("\">")675 options.headerCount++676 options.toc.Write(text)677 options.toc.WriteString("</a></li>\n")678}679func (options *Html) TocHeader(text []byte, level int) {680 options.TocHeaderWithAnchor(text, level, "")681}682func (options *Html) TocFinalize() {683 for options.currentLevel > 1 {684 options.toc.WriteString("</ul></li>\n")685 options.currentLevel--686 }687 if options.currentLevel > 0 {688 options.toc.WriteString("</ul>\n")689 }690}691func isHtmlTag(tag []byte, tagname string) bool {692 found, _ := findHtmlTagPos(tag, tagname)693 return found694}695// Look for a character, but ignore it when it's in any kind of quotes, it696// might be JavaScript697func skipUntilCharIgnoreQuotes(html []byte, start int, char byte) int {698 inSingleQuote := false699 inDoubleQuote := false700 inGraveQuote := false701 i := start702 for i < len(html) {703 switch {704 case html[i] == char && !inSingleQuote && !inDoubleQuote && !inGraveQuote:705 return i706 case html[i] == '\'':707 inSingleQuote = !inSingleQuote708 case html[i] == '"':709 inDoubleQuote = !inDoubleQuote710 case html[i] == '`':711 inGraveQuote = !inGraveQuote712 }713 i++714 }715 return start716}717func findHtmlTagPos(tag []byte, tagname string) (bool, int) {718 i := 0719 if i < len(tag) && tag[0] != '<' {720 return false, -1721 }722 i++723 i = skipSpace(tag, i)724 if i < len(tag) && tag[i] == '/' {725 i++726 }727 i = skipSpace(tag, i)728 j := 0729 for ; i < len(tag); i, j = i+1, j+1 {730 if j >= len(tagname) {731 break732 }733 if strings.ToLower(string(tag[i]))[0] != tagname[j] {734 return false, -1735 }736 }737 if i == len(tag) {738 return false, -1739 }740 rightAngle := skipUntilCharIgnoreQuotes(tag, i, '>')741 if rightAngle > i {742 return true, rightAngle743 }744 return false, -1745}746func skipUntilChar(text []byte, start int, char byte) int {747 i := start748 for i < len(text) && text[i] != char {749 i++750 }751 return i752}753func skipSpace(tag []byte, i int) int {754 for i < len(tag) && isspace(tag[i]) {755 i++756 }757 return i758}759func skipChar(data []byte, start int, char byte) int {760 i := start761 for i < len(data) && data[i] == char {762 i++763 }764 return i765}766func doubleSpace(out *bytes.Buffer) {767 if out.Len() > 0 {768 out.WriteByte('\n')769 }770}771func isRelativeLink(link []byte) (yes bool) {772 // a tag begin with '#'773 if link[0] == '#' {774 return true775 }776 // link begin with '/' but not '//', the second maybe a protocol relative link777 if len(link) >= 2 && link[0] == '/' && link[1] != '/' {778 return true779 }780 // only the root '/'781 if len(link) == 1 && link[0] == '/' {782 return true783 }784 // current directory : begin with "./"785 if bytes.HasPrefix(link, []byte("./")) {786 return true787 }788 // parent directory : begin with "../"789 if bytes.HasPrefix(link, []byte("../")) {790 return true791 }792 return false793}794func (options *Html) ensureUniqueHeaderID(id string) string {795 for count, found := options.headerIDs[id]; found; count, found = options.headerIDs[id] {796 tmp := fmt.Sprintf("%s-%d", id, count+1)797 if _, tmpFound := options.headerIDs[tmp]; !tmpFound {798 options.headerIDs[id] = count + 1799 id = tmp800 } else {801 id = id + "-1"802 }803 }804 if _, found := options.headerIDs[id]; !found {805 options.headerIDs[id] = 0806 }807 return id808}...

Full Screen

Full Screen

Options

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 c := colly.NewCollector()4 c.OnHTML("a[href]", func(e *colly.HTMLElement) {5 link := e.Attr("href")6 fmt.Printf("Link found: %q -> %s\n", e.Text, link)7 })8 c.OnRequest(func(r *colly.Request) {9 fmt.Println("Visiting", r.URL)10 })11 c.OnError(func(_ *colly.Response, err error) {12 fmt.Println("Something went wrong:", err)13 })

Full Screen

Full Screen

Options

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 if err != nil {4 fmt.Println(err)5 }6 defer resp.Body.Close()7 doc, err := html.Parse(resp.Body)8 if err != nil {9 fmt.Println(err)10 }11 options := html.NewTokenizerOptions(doc)12 token := options.Token()13 fmt.Println(token.Data)14 fmt.Println(token.Text())15 fmt.Println(token.String())16 fmt.Println(token.Type)17 fmt.Println(token.DataAtom)18 fmt.Println(token.Attr)19 fmt.Println(token.HasAttr)20 fmt.Println(token.AttrVal)21 fmt.Println(token.Line)22 fmt.Println(token.Column)23 fmt.Println(token.IsEmptyElement)24 fmt.Println(token.HasChildNodes)25 fmt.Println(token.FirstChild)26 fmt.Println(token.LastChild)27 fmt.Println(token.NextSibling)28 fmt.Println(token.PrevSibling)29 fmt.Println(token.Parent)30 fmt.Println(token.AppendChild)31 fmt.Println(token.InsertBefore)32 fmt.Println(token.RemoveChild)33 fmt.Println(token.ReplaceChild)34 fmt.Println(token.CloneNode)35 fmt.Println(token.SetUserData)36 fmt.Println(token.UserData)37 fmt.Println(token.GetAttribute

Full Screen

Full Screen

Options

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 f, err := os.Open("1.html")4 if err != nil {5 fmt.Println(err)6 }7 defer f.Close()8 doc, err := html.Parse(f)9 if err != nil {10 fmt.Println(err)11 }12 fmt.Println("title:", html.Title(doc))13 fmt.Println("body:", html.Body(doc))14 fmt.Println("head:", html.Head(doc))15 fmt.Println("doctype:", html.Doctype(doc))16 fmt.Println("first child:", html.FirstChild(doc))17 fmt.Println("last child:", html.LastChild(doc))18 fmt.Println("next sibling:", html.NextSibling(doc))19 fmt.Println("prev sibling:", html.PrevSibling(doc))20 fmt.Println("parent:", html.Parent(doc))21 fmt.Println("root node:", html.RootNode(doc))22 fmt.Println("text:", html.Text(doc))23 fmt.Println("type:", html.Type(doc))24 fmt.Println("has child:", html.HasChildNodes(doc))25 fmt.Println("has attr:", html.HasAttributes(doc))26 fmt.Println("attr:", html.Attribute([]html.Attribute{}, "attr"))27 fmt.Println("attr value:", html.AttributeValue([]html.Attribute{}, "attr"))28 fmt.Println("attr key:", html.AttributeKey([]html.Attribute{}, "attr"))29 fmt.Println("attr namespace:", html.AttributeNamespace([]html.Attribute{}, "attr"))30 fmt.Println("node name:", html.NodeName(doc))31 fmt.Println("node data:", html.NodeData(doc))32 fmt.Println("node type:", html.NodeType(doc))33 fmt.Println("node namespace:", html.NodeNamespace(doc))34 fmt.Println("node attr:", html.NodeAttr(doc))35 fmt.Println("node first child:", html.NodeFirstChild(doc))36 fmt.Println("node last child:", html.NodeLastChild(doc))37 fmt.Println("node next sibling:", html.NodeNextSibling(doc))38 fmt.Println("node prev sibling:", html.NodePrevSibling(doc))39 fmt.Println("node parent:", html.NodeParent(doc))40 fmt.Println("node root node:", html.NodeRootNode(doc))41 fmt.Println("node text:", html.NodeText(doc))42 fmt.Println("node has child:", html.NodeHasChildNodes(doc))43 fmt.Println("node has attr:", html.NodeHasAttributes(doc))44 fmt.Println("node attr:", html.NodeAttribute(doc, "attr"))45 fmt.Println("node attr value:", html.NodeAttributeValue(doc, "attr"))46 fmt.Println("node attr key:", html.NodeAttributeKey(doc, "attr"))

Full Screen

Full Screen

Options

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 if err != nil {4 panic(err)5 }6 defer resp.Body.Close()7 node, err := htmlquery.Parse(resp.Body)8 if err != nil {9 panic(err)10 }11 fmt.Println("No. of options are", len(options))12}

Full Screen

Full Screen

Options

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 if err != nil {4 log.Fatal(err)5 }6 req.Header.Add("Accept", "text/html")7 client := new(http.Client)8 resp, err := client.Do(req)9 if err != nil {10 log.Fatal(err)11 }12 defer resp.Body.Close()13 doc, err := html.Parse(resp.Body)14 if err != nil {15 log.Fatal(err)16 }17 options, err := html.Options(doc)18 if err != nil {19 log.Fatal(err)20 }21 for k, v := range options {22 fmt.Println(k, v)23 }24}

Full Screen

Full Screen

Options

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 driver := agouti.ChromeDriver()4 err := driver.Start()5 if err != nil {6 fmt.Println(err)7 }8 page, err := driver.NewPage()9 if err != nil {10 fmt.Println(err)11 }12 if err != nil {13 fmt.Println(err)14 }15 err = page.FindByID("dropdown").Select("option2")16 if err != nil {17 fmt.Println(err)18 }19 err = driver.Stop()20 if err != nil {21 fmt.Println(err)22 }23}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run K6 automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful