Example #1
0
// header creates a HeaderNode out of hn.
// It returns nil if header content is empty.
// A non-empty header will always reset ds.env to nil.
//
// Given that headers do not belong to any block, the returned node's B
// field is always nil.
func header(ds *docState) types.Node {
	ds.push(nil, ds.flags|fSkipBlock|fSkipHeader|fSkipList)
	nodes := parseSubtree(ds)
	ds.pop()
	if len(nodes) == 0 {
		return nil
	}
	n := types.NewHeaderNode(headerLevel[ds.cur.DataAtom], nodes...)
	switch strings.ToLower(stringifyNode(ds.cur, true)) {
	case headerLearn, headerCover:
		n.MutateType(types.NodeHeaderCheck)
	case headerFAQ:
		n.MutateType(types.NodeHeaderFAQ)
	}
	ds.env = nil
	return n
}
Example #2
0
func TestParseDoc(t *testing.T) {
	const markup = `
	<html><head><style>
		.meta { color: #b7b7b7 }
		.code { font-family: "Courier New" }
		.term { font-family: "Consolas" }
		.btn { background-color: #6aa84f }
		.bold { font-weight: bold }
		.ita { font-style: italic }
		.nibox { background-color: #fce5cd }
		.survey { background-color: #cfe2f3 }
	</style></head>
	<body>
		<p class="title"><a name="a1"></a><span>Test Codelab</span></p>
		<h1><a name="a2"></a><span>Overview</span></h1>
		<p><span class="meta">Duration: 1:00</span></p>

		<img src="https://host/image.png">
		<p><img src="https://host/small.png" style="height: 10px; width: 25.5px"> icon.</p>

		<h3><a name="a3"></a><span>What you&rsquo;ll learn</span></h3>
		<ul class="start">
		<li><span>First </span><span>One</span><sup><a href="#cmnt1" name="cmnt_ref1" target="_blank">[a]</a></sup></li>
		<li><span>Two </span><span><a href="https://google.com/url?q=http%3A%2F%2Fexample.com">Link</a></span></li>
		</ul>
		<ul><li><span>Three</span></li></ul>

		<p>This is<span class="code"> code</span>.</p>
		<p>Just <span>a</span> paragraph.</p>
		<p><a href="url">one</a><a href="url"> url</a></p>
		<p><span class="btn"><a href="http://example.com">Download Zip</a></span></p>
		<p>
			<span class="bold">Bo</span><span>&nbsp;</span><span class="bold">ld</span>
			<span class="ita"> italic</span> text <span class="bold ita">or both.</span></p>

		<h3><a href="http://host/file.java">a file</a></h3>
		<table cellpadding="0" cellspacing="0"><tbody><tr>
		<td colspan="1" rowspan="1">
			<p><span class="code">start func() {<br>}</span></p>
			<p><span class="code"></span></p>
			<p><span class="code">func2() {<br>}</span><span class="code">&nbsp;// comment</span></p>
		</td>
		</tr></tbody></table>

		<table cellpadding="0" cellspacing="0"><tbody><tr>
		<td colspan="1" rowspan="1">
			<p><span class="term">adb shell am start -a VIEW \</span></p>
			<p><span class="term">-d &quot;http://host&quot; app</span></p>
		</td>
		</tr></tbody></table>

		<table cellpadding="0" cellspacing="0"><tbody><tr>
		<td class="nibox" colspan="1" rowspan="1">
			<p><span class="bold">warning</span></p>
			<p><span>negative box.</span></p>
		</td>
		</tr></tbody></table>

		<table cellpadding="0" cellspacing="0"><tbody><tr>
		<td class="survey" colspan="1" rowspan="1">
		<h4><a name="x"></a><span class="code">How</span><span class="ita">&nbsp;will you use it?</span></h4>
		<ul><li class="bold"><span class="c5">Read it</span></li></ul>
		<ul><li class="c23 c47"><span class="c5">Read and complete</span></li></ul>
		<p class="c23 c44"><span class="c5"></span></p>
		<h4><a name="asd"></a><span>How</span><span>&nbsp;would you rate?</span></h4>
		<ul>
			<li class="c19 c47"><span class="c5">Novice</span></li>
			<li class="c19 c47"><span class="c5">Intermediate</span></li>
			<li class="c19 c47"><span class="c5">Proficient</span></li>
		</ul>
		<p class="c23 c44"><span class="c5"></span></p>
		</td>
		</tr></tbody></table>
		<div><p><a href="#cmnt_ref1" name="cmnt1">[a]</a><span class="c16 c8">Test comment.</span></p></div>
	</body>
	</html>
	`
	c, err := Parse(markupReader(markup))
	if err != nil {
		t.Fatal(err)
	}
	if c.Meta.Title != "Test Codelab" {
		t.Errorf("c.Meta.Title = %q; want Test Codelab", c.Meta.Title)
	}
	if c.Meta.ID != "test-codelab" {
		t.Errorf("c.ID = %q; want test-codelab", c.Meta.ID)
	}
	if len(c.Steps) == 0 {
		t.Fatalf("len(c.Steps) = 0")
	}
	step := c.Steps[0]
	if step.Title != "Overview" {
		t.Errorf("step.Title = %q; want Overview", step.Title)
	}

	content := types.NewListNode()

	img := types.NewImageNode("https://host/image.png")
	para := types.NewListNode(img)
	para.MutateBlock(true)
	content.Append(para)

	img = types.NewImageNode("https://host/small.png")
	img.MaxWidth = 25.5
	para = types.NewListNode(img, types.NewTextNode(" icon."))
	para.MutateBlock(true)
	content.Append(para)

	h := types.NewHeaderNode(3, types.NewTextNode("What you'll learn"))
	h.MutateType(types.NodeHeaderCheck)
	content.Append(h)
	list := types.NewItemsListNode("", 0)
	list.MutateType(types.NodeItemsCheck)
	list.NewItem().Append(types.NewTextNode("First One"))
	item := list.NewItem()
	item.Append(types.NewTextNode("Two "))
	item.Append(types.NewURLNode("http://example.com", types.NewTextNode("Link")))
	list.NewItem().Append(types.NewTextNode("Three"))
	content.Append(list)

	para = types.NewListNode()
	para.MutateBlock(true)
	para.Append(types.NewTextNode("This is "))
	txt := types.NewTextNode("code")
	txt.Code = true
	para.Append(txt)
	para.Append(types.NewTextNode("."))
	content.Append(para)

	para = types.NewListNode()
	para.MutateBlock(true)
	para.Append(types.NewTextNode("Just a paragraph."))
	content.Append(para)

	u := types.NewURLNode("url", types.NewTextNode("one url"))
	para = types.NewListNode(u)
	para.MutateBlock(true)
	content.Append(para)

	btn := types.NewButtonNode(true, true, true, types.NewTextNode("Download Zip"))
	dl := types.NewURLNode("http://example.com", btn)
	para = types.NewListNode(dl)
	para.MutateBlock(true)
	content.Append(para)

	b := types.NewTextNode("Bo ld")
	b.Bold = true
	i := types.NewTextNode(" italic")
	i.Italic = true
	bi := types.NewTextNode("or both.")
	bi.Bold = true
	bi.Italic = true
	para = types.NewListNode(b, i, types.NewTextNode(" text "), bi)
	para.MutateBlock(true)
	content.Append(para)

	h = types.NewHeaderNode(3, types.NewURLNode(
		"http://host/file.java", types.NewTextNode("a file")))
	content.Append(h)

	code := "start func() {\n}\n\nfunc2() {\n} // comment"
	cn := types.NewCodeNode(code, false)
	cn.MutateBlock(1)
	content.Append(cn)

	term := "adb shell am start -a VIEW \\\n-d \"http://host\" app"
	tn := types.NewCodeNode(term, true)
	tn.MutateBlock(2)
	content.Append(tn)

	b = types.NewTextNode("warning")
	b.Bold = true
	n1 := types.NewListNode(b)
	n1.MutateBlock(true)
	n2 := types.NewListNode(types.NewTextNode("negative box."))
	n2.MutateBlock(true)
	box := types.NewInfoboxNode(types.InfoboxNegative, n1, n2)
	content.Append(box)

	sv := types.NewSurveyNode("test-codelab-1")
	sv.Groups = append(sv.Groups, &types.SurveyGroup{
		Name:    "How will you use it?",
		Options: []string{"Read it", "Read and complete"},
	})
	sv.Groups = append(sv.Groups, &types.SurveyGroup{
		Name:    "How would you rate?",
		Options: []string{"Novice", "Intermediate", "Proficient"},
	})
	content.Append(sv)

	html1, _ := render.HTML("", step.Content)
	html2, _ := render.HTML("", content)
	if html1 != html2 {
		t.Errorf("step.Content:\n\n%s\nwant:\n\n%s", html1, html2)
	}
}