aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2024-10-15 12:36:20 +0700
committerShulhan <ms@kilabit.info>2024-10-15 12:37:13 +0700
commit2ea376671b1975392252bc6f70497c54d4bbab16 (patch)
treee2f88ef4203c82e21d0b27e593dca92f18bfdf92
parentc8eb463345633a1816f97cc967d104127cc4c5f4 (diff)
downloadasciidoctor-go-2ea376671b1975392252bc6f70497c54d4bbab16.tar.xz
all: group all image related method and functions into single file
This is to make it easy to see how it parsed and how it written to HTML, make the code more searchable. While at it, add test for block image.
-rw-r--r--_doc/SPECS.adoc12
-rw-r--r--element.go94
-rw-r--r--element_image.go163
-rw-r--r--element_image_test.go38
-rw-r--r--html_backend.go41
-rw-r--r--inline_parser.go30
-rw-r--r--testdata/element_image_test.txt35
7 files changed, 246 insertions, 167 deletions
diff --git a/_doc/SPECS.adoc b/_doc/SPECS.adoc
index 20567ee..55e2615 100644
--- a/_doc/SPECS.adoc
+++ b/_doc/SPECS.adoc
@@ -346,12 +346,13 @@ ABSOLUTE_PATH = "/" WORD *( "/" WORD )
RELATIVE_PATH = ( "." / ".." ) "/" WORD * ( "/" WORD )
----
+
== Images
-=== Inline image
+=== Block image
----
-IMAGE_INLINE = "image:" URL "[" (IMAGE_ATTRS) "]"
+BLOCK_IMAGE = "image::" URL "[" IMAGE_ATTRS "]"
IMAGE_ATTRS = TEXT ("," IMAGE_WIDTH ("," IMAGE_HEIGHT)) *("," IMAGE_OPTS)
@@ -360,6 +361,13 @@ IMAGE_OPTS = IMAGE_OPT_KEY "=" 1*VCHAR
IMAGE_OPT_KEY = "title" / "float" / "align" / "role" / "link"
----
+=== Inline image
+
+----
+IMAGE_INLINE = "image:" URL "[" (IMAGE_ATTRS) "]"
+----
+
+
== Video
----
diff --git a/element.go b/element.go
index 498524c..9f77633 100644
--- a/element.go
+++ b/element.go
@@ -301,100 +301,6 @@ func (el *element) parseBlockAudio(doc *Document, line []byte) bool {
return true
}
-// parseBlockImage parse the image block or line.
-// The line parameter must not have "image::" block or "image:" macro prefix.
-func (el *element) parseBlockImage(doc *Document, line []byte) bool {
- var (
- attrBegin = bytes.IndexByte(line, '[')
-
- attr string
- key string
- val string
- kv []string
-
- attrs [][]byte
- src []byte
- battr []byte
- alt []byte
-
- attrEnd int
- dot int
- x int
- )
-
- if attrBegin < 0 {
- return false
- }
- attrEnd = bytes.IndexByte(line, ']')
- if attrEnd < 0 {
- return false
- }
-
- src = bytes.TrimRight(line[:attrBegin], " \t")
-
- if el.Attrs == nil {
- el.Attrs = make(map[string]string)
- }
- src = applySubstitutions(doc, src)
- el.Attrs[attrNameSrc] = string(src)
-
- attrs = bytes.Split(line[attrBegin+1:attrEnd], []byte(`,`))
- if el.Attrs == nil {
- el.Attrs = make(map[string]string)
- }
- var hasWidth bool
- for x, battr = range attrs {
- attr = string(battr)
- if x == 0 {
- alt = bytes.TrimSpace(attrs[0])
- if len(alt) == 0 {
- dot = bytes.IndexByte(src, '.')
- if dot > 0 {
- alt = src[:dot]
- }
- }
- el.Attrs[attrNameAlt] = string(alt)
- continue
- }
- if x == 1 {
- if ascii.IsDigits(attrs[1]) {
- el.Attrs[attrNameWidth] = string(attrs[1])
- hasWidth = true
- continue
- }
- }
- if hasWidth && x == 2 {
- if ascii.IsDigits(attrs[2]) {
- el.Attrs[attrNameHeight] = string(attrs[2])
- }
- }
- kv = strings.SplitN(attr, `=`, 2)
- if len(kv) != 2 {
- continue
- }
- key = strings.TrimSpace(kv[0])
- val = strings.Trim(kv[1], `"`)
- switch key {
- case attrNameFloat, attrNameAlign, attrNameRole:
- if val == `center` {
- val = `text-center`
- }
- el.addRole(val)
- default:
- el.Attrs[key] = val
- }
- }
-
- for key, val = range el.Attrs {
- if key == attrNameLink {
- val = string(applySubstitutions(doc, []byte(val)))
- el.Attrs[key] = val
- }
- }
-
- return true
-}
-
func (el *element) parseInlineMarkup(doc *Document, kind int) {
if len(el.raw) == 0 {
return
diff --git a/element_image.go b/element_image.go
new file mode 100644
index 0000000..d98bb61
--- /dev/null
+++ b/element_image.go
@@ -0,0 +1,163 @@
+// SPDX-FileCopyrightText: 2024 M. Shulhan <ms@kilabit.info>
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package asciidoctor
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "strings"
+
+ "git.sr.ht/~shulhan/pakakeh.go/lib/ascii"
+)
+
+// parseBlockImage parse the image block or line.
+// The line parameter must not contains the "image::" block or "image:"
+// macro prefix.
+func (el *element) parseBlockImage(doc *Document, line []byte) bool {
+ var attrBegin = bytes.IndexByte(line, '[')
+ if attrBegin < 0 {
+ return false
+ }
+ var attrEnd = bytes.IndexByte(line, ']')
+ if attrEnd < 0 {
+ return false
+ }
+
+ var link = bytes.TrimRight(line[:attrBegin], " \t")
+ link = applySubstitutions(doc, link)
+
+ if el.Attrs == nil {
+ el.Attrs = make(map[string]string)
+ }
+ el.Attrs[attrNameSrc] = string(link)
+
+ var listAttribute = bytes.Split(line[attrBegin+1:attrEnd], []byte(`,`))
+ if el.Attrs == nil {
+ el.Attrs = make(map[string]string)
+ }
+
+ var (
+ x int
+ battr []byte
+ hasWidth bool
+ )
+ for x, battr = range listAttribute {
+ if x == 0 {
+ var alt = bytes.TrimSpace(listAttribute[0])
+ if len(alt) == 0 {
+ var dot = bytes.IndexByte(link, '.')
+ if dot > 0 {
+ alt = link[:dot]
+ }
+ }
+ el.Attrs[attrNameAlt] = string(alt)
+ continue
+ }
+ if x == 1 {
+ if ascii.IsDigits(listAttribute[1]) {
+ el.Attrs[attrNameWidth] = string(listAttribute[1])
+ hasWidth = true
+ continue
+ }
+ }
+ if hasWidth && x == 2 {
+ if ascii.IsDigits(listAttribute[2]) {
+ el.Attrs[attrNameHeight] = string(listAttribute[2])
+ }
+ }
+
+ var attr = string(battr)
+ var kv = strings.SplitN(attr, `=`, 2)
+ if len(kv) != 2 {
+ continue
+ }
+ var key = strings.TrimSpace(kv[0])
+ var val = strings.Trim(kv[1], `"`)
+
+ switch key {
+ case attrNameFloat, attrNameAlign, attrNameRole:
+ if val == `center` {
+ val = `text-center`
+ }
+ el.addRole(val)
+
+ case attrNameLink:
+ val = string(applySubstitutions(doc, []byte(val)))
+ el.Attrs[key] = val
+
+ default:
+ el.Attrs[key] = val
+ }
+ }
+ return true
+}
+
+func parseInlineImage(doc *Document, content []byte) (el *element, n int) {
+ // If the next character is ':' (as in block "image::") mark it as
+ // invalid inline image, since this is block image that has been
+ // parsed but invalid (probably missing '[]').
+ if content[0] == ':' {
+ return nil, 0
+ }
+
+ _, n = indexByteUnescape(content, ']')
+ if n < 0 {
+ return nil, 0
+ }
+
+ var lineImage = content[:n+1]
+ el = &element{
+ elementAttribute: elementAttribute{
+ Attrs: make(map[string]string),
+ },
+ kind: elKindInlineImage,
+ }
+ if el.parseBlockImage(doc, lineImage) {
+ return el, n + 2
+ }
+ return nil, 0
+}
+
+func htmlWriteInlineImage(el *element, out io.Writer) {
+ var (
+ classes = strings.TrimSpace(`image ` + el.htmlClasses())
+
+ link string
+ withLink bool
+ )
+
+ fmt.Fprintf(out, `<span class=%q>`, classes)
+ link, withLink = el.Attrs[attrNameLink]
+ if withLink {
+ fmt.Fprintf(out, `<a class=%q href=%q>`, attrValueImage, link)
+ }
+
+ var (
+ src = el.Attrs[attrNameSrc]
+ alt = el.Attrs[attrNameAlt]
+
+ width string
+ height string
+ ok bool
+ )
+
+ width, ok = el.Attrs[attrNameWidth]
+ if ok {
+ width = fmt.Sprintf(` width="%s"`, width)
+ }
+ height, ok = el.Attrs[attrNameHeight]
+ if ok {
+ height = fmt.Sprintf(` height="%s"`, height)
+ }
+
+ fmt.Fprintf(out, `<img src=%q alt=%q%s%s>`, src, alt, width, height)
+
+ if withLink {
+ fmt.Fprint(out, `</a>`)
+ }
+
+ fmt.Fprint(out, `</span>`)
+}
diff --git a/element_image_test.go b/element_image_test.go
new file mode 100644
index 0000000..a548501
--- /dev/null
+++ b/element_image_test.go
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: 2024 M. Shulhan <ms@kilabit.info>
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package asciidoctor
+
+import (
+ "bytes"
+ "testing"
+
+ "git.sr.ht/~shulhan/pakakeh.go/lib/test"
+)
+
+func TestElementParseBlockImage(t *testing.T) {
+ var (
+ tdata *test.Data
+ err error
+ )
+ tdata, err = test.LoadData(`testdata/element_image_test.txt`)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var (
+ caseName string
+ input []byte
+ got bytes.Buffer
+ )
+ for caseName, input = range tdata.Input {
+ var doc = Parse(input)
+
+ got.Reset()
+ doc.ToHTMLEmbedded(&got)
+
+ var exp = string(tdata.Output[caseName])
+ test.Assert(t, caseName, exp, got.String())
+ }
+}
diff --git a/html_backend.go b/html_backend.go
index b404ba7..14137e5 100644
--- a/html_backend.go
+++ b/html_backend.go
@@ -1063,47 +1063,6 @@ func htmlWriteHeader(doc *Document, out io.Writer) {
fmt.Fprint(out, "\n</div>")
}
-func htmlWriteInlineImage(el *element, out io.Writer) {
- var (
- classes = strings.TrimSpace(`image ` + el.htmlClasses())
-
- link string
- withLink bool
- )
-
- fmt.Fprintf(out, `<span class=%q>`, classes)
- link, withLink = el.Attrs[attrNameLink]
- if withLink {
- fmt.Fprintf(out, `<a class=%q href=%q>`, attrValueImage, link)
- }
-
- var (
- src = el.Attrs[attrNameSrc]
- alt = el.Attrs[attrNameAlt]
-
- width string
- height string
- ok bool
- )
-
- width, ok = el.Attrs[attrNameWidth]
- if ok {
- width = fmt.Sprintf(` width="%s"`, width)
- }
- height, ok = el.Attrs[attrNameHeight]
- if ok {
- height = fmt.Sprintf(` height="%s"`, height)
- }
-
- fmt.Fprintf(out, `<img src=%q alt=%q%s%s>`, src, alt, width, height)
-
- if withLink {
- fmt.Fprint(out, `</a>`)
- }
-
- fmt.Fprint(out, `</span>`)
-}
-
func htmlWriteInlinePass(doc *Document, el *element, out io.Writer) {
var text = htmlSubs(doc, el)
diff --git a/inline_parser.go b/inline_parser.go
index 2f18aaf..561cab7 100644
--- a/inline_parser.go
+++ b/inline_parser.go
@@ -694,36 +694,6 @@ func (pi *inlineParser) parseFormatUnconstrained(
return false
}
-func parseInlineImage(doc *Document, content []byte) (elImage *element, n int) {
- var (
- lineImage []byte
- )
-
- // If the next character is ':' (as in block "image::") mark it as
- // invalid inline image, since this is block image that has been
- // parsed but invalid (probably missing '[]').
- if content[0] == ':' {
- return nil, 0
- }
-
- _, n = indexByteUnescape(content, ']')
- if n < 0 {
- return nil, 0
- }
-
- lineImage = content[:n+1]
- elImage = &element{
- elementAttribute: elementAttribute{
- Attrs: make(map[string]string),
- },
- kind: elKindInlineImage,
- }
- if elImage.parseBlockImage(doc, lineImage) {
- return elImage, n + 2
- }
- return nil, 0
-}
-
func (pi *inlineParser) parseMacro() bool {
var (
el *element
diff --git a/testdata/element_image_test.txt b/testdata/element_image_test.txt
new file mode 100644
index 0000000..ae15cbb
--- /dev/null
+++ b/testdata/element_image_test.txt
@@ -0,0 +1,35 @@
+>>> empty_block_image
+
+image::[]
+
+<<< empty_block_image
+
+<div class="imageblock">
+<div class="content">
+<img src="" alt="">
+</div>
+</div>
+
+>>> with_absolute_path
+
+image::/absolute/path.png[Image alt text]
+
+<<< with_absolute_path
+
+<div class="imageblock">
+<div class="content">
+<img src="/absolute/path.png" alt="Image alt text">
+</div>
+</div>
+
+>>> with_attr_link
+
+image::/image/path.png[Image alt text,link="{dummy}/link"]
+
+<<< with_attr_link
+
+<div class="imageblock">
+<div class="content">
+<img src="/image/path.png" alt="Image alt text">
+</div>
+</div>