From cdd1faa6b97de023ef7129399483e841fb4a9b16 Mon Sep 17 00:00:00 2001 From: Shulhan Date: Sun, 10 Dec 2023 02:38:42 +0700 Subject: all: fix custom IDs on first section got replaced Any custom ID on the first section always replaced with the subsection because, first, when detecting preamble we did not check for line with kind ID "[[...]]" an short ID "[#...]". Second, when parsing preamble we did not stop when we found line kind ID and short ID. This preamble thing is kind of annoying. We need to revisit again how to detect preamble, maybe not calling separate block parser, but making it linear as the default first child of parent element. --- asciidoctor_test.go | 20 ++++--------- document_parser.go | 31 +++++++++++++++----- parser.go | 2 +- testdata/custom_ids_test.txt | 70 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 24 deletions(-) create mode 100644 testdata/custom_ids_test.txt diff --git a/asciidoctor_test.go b/asciidoctor_test.go index 8944165..886e84c 100644 --- a/asciidoctor_test.go +++ b/asciidoctor_test.go @@ -20,11 +20,13 @@ func TestData(t *testing.T) { var ( listTData []*test.Data tdata *test.Data - inputCall string + bbuf bytes.Buffer outputCall string inputName string subtestName string inputContent []byte + exp []byte + got []byte err error ) @@ -34,28 +36,15 @@ func TestData(t *testing.T) { } for _, tdata = range listTData { - inputCall = tdata.Flag[`input_call`] outputCall = tdata.Flag[`output_call`] for inputName, inputContent = range tdata.Input { subtestName = tdata.Name + `/` + inputName t.Run(subtestName, func(t *testing.T) { - var ( - doc *Document - bbuf bytes.Buffer - exp []byte - got []byte - ) - - exp = tdata.Output[inputName] - bbuf.Reset() - switch inputCall { - default: - doc = Parse(inputContent) - } + var doc = Parse(inputContent) switch outputCall { case outputCallHTMLWriteHeader: @@ -73,6 +62,7 @@ func TestData(t *testing.T) { got = bbuf.Bytes() } + exp = tdata.Output[inputName] test.Assert(t, subtestName, string(exp), string(got)) }) } diff --git a/document_parser.go b/document_parser.go index d165ff9..27f92be 100644 --- a/document_parser.go +++ b/document_parser.go @@ -61,6 +61,8 @@ func parseSub(parentDoc *Document, content []byte) (subdoc *Document) { return subdoc } +// consumeLinesUntil given an element el, consume all lines until we found +// a line with kind match with term or match with one in terms. func (docp *documentParser) consumeLinesUntil(el *element, term int, terms []int) (line []byte) { var ( logp = `consumeLinesUntil` @@ -148,7 +150,9 @@ func (docp *documentParser) hasPreamble() bool { kind, _, _ = whatKindOfLine(line) if kind == elKindSectionL1 || kind == elKindSectionL2 || kind == elKindSectionL3 || kind == elKindSectionL4 || - kind == elKindSectionL5 { + kind == elKindSectionL5 || + kind == lineKindID || + kind == lineKindIDShort { return notEmtpy > 0 } notEmtpy++ @@ -276,9 +280,7 @@ func (docp *documentParser) parseMultiline(out io.Writer) { func (docp *documentParser) parseBlock(parent *element, term int) { var ( logp = `parseBlock` - el = &element{ - kind: elKindUnknown, - } + el = &element{} line []byte isTerm bool @@ -314,13 +316,19 @@ func (docp *documentParser) parseBlock(parent *element, term int) { continue case lineKindID: + if parent.kind == elKindPreamble { + docp.kind = lineKindEmpty + docp.prevKind = lineKindEmpty + docp.lineNum-- + isTerm = true + continue + } var ( idLabel = line[2 : len(line)-2] id, label = parseIDLabel(idLabel) ) if len(id) > 0 { - el.ID = docp.doc.registerAnchor( - string(id), string(label)) + el.ID = docp.doc.registerAnchor(string(id), string(label)) line = nil continue } @@ -330,6 +338,14 @@ func (docp *documentParser) parseBlock(parent *element, term int) { continue case lineKindIDShort: + if parent.kind == elKindPreamble { + docp.kind = lineKindEmpty + docp.prevKind = lineKindEmpty + docp.lineNum-- + isTerm = true + continue + } + var ( id = line[2 : len(line)-1] label []byte @@ -338,8 +354,7 @@ func (docp *documentParser) parseBlock(parent *element, term int) { id, label = parseIDLabel(id) if len(id) > 0 { - el.ID = docp.doc.registerAnchor( - string(id), string(label)) + el.ID = docp.doc.registerAnchor(string(id), string(label)) line = nil continue } diff --git a/parser.go b/parser.go index a748bde..6d47d1d 100644 --- a/parser.go +++ b/parser.go @@ -665,7 +665,7 @@ func parseClosedBracket(input []byte, openb, closedb byte) (out []byte, idx int) return nil, -1 } -// parseIDLabel parse the string "ID (,LABEL)" into ID and label. +// parseIDLabel parse the string "ID (,LABEL)" into id and label. // It will return empty id and label if ID is not valid. func parseIDLabel(s []byte) (id, label []byte) { var idLabel = bytes.Split(s, []byte(`,`)) diff --git a/testdata/custom_ids_test.txt b/testdata/custom_ids_test.txt new file mode 100644 index 0000000..917a492 --- /dev/null +++ b/testdata/custom_ids_test.txt @@ -0,0 +1,70 @@ +output_call: ToHTMLBody + +>>> without_preamble += Without preamble + +[#foo_v1_1_0] +== foo v1.1.0 (2023-02-01) + +[#foo_v1_0_0] +== foo v1.0.0 (2023-01-01) + +<<< without_preamble + +
+
+

foo v1.1.0 (2023-02-01)

+
+
+
+
+

foo v1.0.0 (2023-01-01)

+
+
+
+
+ + +>>> with_preamble += With preamble + +This is a preamble. + +[#foo_v1_1_0] +== foo v1.1.0 (2023-02-01) + +[#foo_v1_0_0] +== foo v1.0.0 (2023-01-01) + +<<< with_preamble + +
+
+
+
+

This is a preamble.

+
+
+
+
+

foo v1.1.0 (2023-02-01)

+
+
+
+
+

foo v1.0.0 (2023-01-01)

+
+
+
+
+ -- cgit v1.3