diff options
Diffstat (limited to 'content.go')
-rw-r--r-- | content.go | 104 |
1 files changed, 70 insertions, 34 deletions
@@ -18,9 +18,18 @@ type Block interface { // Args returns the block arguments. Args() []string + WriteIndent(w io.Writer, n int) error } +// ContainerBlock represents a content block that contains only other blocks. +type ContainerBlock interface { + Block + + // Children returns the child blocks. + Children() []Block +} + // ContentBlock represents a block that holds other content blocks. type ContentBlock struct { name string @@ -190,8 +199,7 @@ func parseTextFormat(p *Parser, block *TokenBlock, format string) (TextContents, if parser := GetTextContentParser(format); parser != nil { return parser(p, block) } - r, err := parseContentRaw(p, block) - return TextPreContents{r.Contents}, err + return parseTextRaw(p, block) } // TextContents represents the textual contents of a text block. @@ -327,13 +335,60 @@ func parseTextPre(p *Parser, block *TokenBlock) (TextContents, error) { return TextPreContents{strings.Join(lines, "\n")}, err } +// TextRawContents represents raw (unesacped) contents of a text or raw block. +type TextRawContents struct { + // Text is the raw content. + Text string +} + +// WriteIndent writes the raw content indented by n tabs. +func (t TextRawContents) WriteIndent(w io.Writer, n int) error { + ss := strings.Split(t.Text, "\n") + for _, s := range ss { + if err := writeIndent(w, s, n); err != nil { + return err + } + } + + return nil +} + +func parseTextRaw(p *Parser, block *TokenBlock) (TextContents, error) { + var lines []string + var ls []string + var err error + for err == nil { + if !p.Empty() && p.Indent() <= block.Indent() { + break + } + token := p.RawText() + if text, ok := token.(*TokenRawText); ok { + if len(ls) > 0 { + lines = append(lines, ls...) + ls = ls[:0] + } + lines = append(lines, text.Text) + } else if _, ok := token.(*TokenEmptyLine); ok && len(lines) > 0 { + ls = append(ls, "") + } + err = p.Next() + } + + return TextRawContents{strings.Join(lines, "\n")}, err +} + // RawBlock represents a "raw" content block. type RawBlock struct { // Syntax is the syntax of the block contents (first word of block argument) Syntax string // Contents is the raw content. - Contents string + Contents TextRawContents +} + +// NewRawBlock creates a new RawBlock. +func NewRawBlock(syntax, contents string) *RawBlock { + return &RawBlock{syntax, TextRawContents{contents}} } // Name returns the block name "raw". @@ -356,14 +411,7 @@ func (r *RawBlock) WriteIndent(w io.Writer, n int) error { if err := writeIndent(w, s, n); err != nil { return err } - if r.Contents != "" { - ss := strings.Split(r.Contents, "\n") - for _, s := range ss { - if err := writeIndent(w, s, n+1); err != nil { - return err - } - } - } + r.Contents.WriteIndent(w, n+1) return nil } @@ -372,33 +420,16 @@ func parseContentRaw(p *Parser, block *TokenBlock) (*RawBlock, error) { if len(block.Args) > 0 { arg = block.Args[0] } - rb := &RawBlock{arg, ""} + rb := &RawBlock{arg, TextRawContents{}} if err := p.Next(); err != nil { return rb, err } - var lines []string - var ls []string - var err error - for err == nil { - if !p.Empty() && p.Indent() <= block.Indent() { - break - } - - token := p.RawText() - if text, ok := token.(*TokenRawText); ok { - if len(ls) > 0 { - lines = append(lines, ls...) - ls = ls[:0] - } - lines = append(lines, text.Text) - } else if _, ok := token.(*TokenEmptyLine); ok && len(lines) > 0 { - ls = append(ls, "") - } - err = p.Next() + tc, err := parseTextRaw(p, block) + if tc != nil { + rb.Contents = tc.(TextRawContents) } - rb.Contents = strings.Join(lines, "\n") return rb, err } @@ -467,8 +498,8 @@ func (t *TableBlock) WriteIndent(w io.Writer, n int) error { return nil } -// Rows returns the table's rows. -func (t *TableBlock) Rows() []Block { +// Children returns the table's rows. +func (t *TableBlock) Children() []Block { return t.rows } @@ -560,6 +591,11 @@ type EmbedBlock struct { Description string } +// NewEmbedBlock creates a new EmbedBlock. +func NewEmbedBlock(typ, url, desc string) *EmbedBlock { + return &EmbedBlock{typ, url, desc} +} + // Name returns the block name "embed". func (e *EmbedBlock) Name() string { return "embed" } |