Skip to content

Commit

Permalink
feat(parser/renderer): support for literal blocks (bytesparadise#29)
Browse files Browse the repository at this point in the history
support for literal blocks in the form of:
- [x] a paragraph starting with one or more spaces
- [x] a paragraph surrounded with the `....` delimiter
- [x] a parapgrah with the `[literal]` attribute

Signed-off-by: Xavier Coulon <[email protected]>
  • Loading branch information
xcoulon committed Oct 10, 2017
1 parent b69fe01 commit 51f4897
Show file tree
Hide file tree
Showing 15 changed files with 1,479 additions and 831 deletions.
2 changes: 1 addition & 1 deletion glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 49 additions & 14 deletions parser/asciidoc-grammar.peg
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import "github.com/bytesparadise/libasciidoc/types"

}

// ------------------------------------------
// Document
// ------------------------------------------

Document <- frontmatter:(FrontMatter?) blocks:(DocumentBlock*) EOF {
if frontmatter != nil {
return types.NewDocument(frontmatter.(*types.FrontMatter), blocks.([]interface{}))
Expand All @@ -20,7 +24,7 @@ DocumentBlock <- content:(Section / StandaloneBlock) {
return content.(types.DocElement), nil
}

StandaloneBlock <- DocumentAttributeDeclaration / DocumentAttributeReset / List / BlockImage / DelimitedBlock / Paragraph / ElementAttribute / BlankLine //TODO: should Paragraph be the last type ?
StandaloneBlock <- DocumentAttributeDeclaration / DocumentAttributeReset / List / BlockImage / LiteralBlock / DelimitedBlock / Paragraph / ElementAttribute / BlankLine //TODO: should Paragraph be the last type ?

// ------------------------------------------
// Front Matter
Expand Down Expand Up @@ -175,7 +179,7 @@ Paragraph <- attributes:(ElementAttribute)* lines:(InlineContent)+ {

// an inline content element may start with and end with spaces,
// but it must contain at least an inline element (image, quoted text, external link, document attribute substitution, word, etc.)
InlineContent <- elements:(WS* InlineElement WS*)+ EOL {
InlineContent <- !FencedBlockDelimiter elements:(WS* InlineElement WS*)+ EOL {
return types.NewInlineContent(c.text, elements.([]interface{}))
}

Expand Down Expand Up @@ -236,22 +240,52 @@ InlineImageMacro <- "image:" !":" path:(URL) '[' attributes:(URL_TEXT?) ']' {
return types.NewImageMacro(c.text, path.(string), attributes)
}

// ------------------------------------------
// Delimited Blocks
// ------------------------------------------
// ------------------------------------------------------------------------------------
// Delimited Blocks (http://asciidoctor.org/docs/user-manual/#built-in-blocks-summary)
// ------------------------------------------------------------------------------------
DelimitedBlock <- FencedBlock

FencedBlock <- FencedBlockDelimiter WS* NEWLINE content:(FencedBlockContent) FencedBlockDelimiter WS* EOL {
return types.NewDelimitedBlock(types.FencedBlock, content.([]interface{}))
}

FencedBlockDelimiter <- "```"

DelimitedBlock <- SourceBlock
FencedBlockContent <- content:(!FencedBlockDelimiter .)*

SourceBlock <- SourceBlockDelimiter NEWLINE content:(SourceBlockLine)* SourceBlockDelimiter {
return types.NewDelimitedBlock(types.SourceBlock, content.([]interface{}))
// -------------------------------------------------------------------------------------
// Literal Blocks (see http://asciidoctor.org/docs/user-manual/#literal-text-and-blocks)
// -------------------------------------------------------------------------------------
LiteralBlock <- ParagraphWithSpaces / ParagraphWithLiteralBlockDelimiter / ParagraphWithLiteralAttribute

// paragraph indented with one or more spaces on the first line
ParagraphWithSpaces <- spaces:(WS+) !NEWLINE content:(LiteralBlockContent) EndOfLiteralBlock {
// fmt.Printf("matching LiteralBlock with raw content=`%v`\n", content)
return types.NewLiteralBlock(spaces.([]interface{}), content.([]interface{}))
}

// no NEWLINE allowed between the first spaces and the content of the block
LiteralBlockContent <- content:(!(NEWLINE BlankLine) .)+ {
return content, nil
}

SourceBlockDelimiter <- "```"
// a literal block ends with a blank line (or EOF)
EndOfLiteralBlock <- NEWLINE BlankLine / NEWLINE / EOF

SourceBlockLine <- (!EOL .)* NEWLINE
// paragraph with the literal block delimiter (`....`)
ParagraphWithLiteralBlockDelimiter <- LiteralBlockDelimiter WS* NEWLINE content:(!LiteralBlockDelimiter .)* LiteralBlockDelimiter WS* EOL {
return types.NewLiteralBlock([]interface{}{}, content.([]interface{}))
}

LiteralBlockDelimiter <- "...."

// paragraph with the literal attribute (`[literal]`)
ParagraphWithLiteralAttribute <- "[literal]" WS* NEWLINE content:(LiteralBlockContent) EndOfLiteralBlock {
return types.NewLiteralBlock([]interface{}{}, content.([]interface{}))
}

// ------------------------------------------
// Meta Elements
// Element Attributes
// ------------------------------------------
ElementAttribute <- meta:(ElementLink / ElementID / ElementTitle)

Expand All @@ -265,8 +299,9 @@ ElementID <- "[" WS* '#' id:(ID) WS* "]" EOL {
return types.NewElementID(id.(string))
}

// a title attached to an element, such as a BlockImage
ElementTitle <- "." !WS title:(!NEWLINE .)+ EOL {
// a title attached to an element, such as a BlockImage (
// a title starts with a single '.' followed by the value, without space in-between
ElementTitle <- "." !"." !WS title:(!NEWLINE .)+ EOL {
return types.NewElementTitle(title.([]interface{}))
}

Expand Down Expand Up @@ -297,7 +332,7 @@ URL_SCHEME <- "http://" / "https://" / "ftp://" / "irc://" / "mailto:"

DIGIT <- [0-9]

NEWLINE <- "\r\n" / '\r' / '\n'
NEWLINE <- "\r\n" / "\r" / "\n"

WS <- ' ' / '\t' {
return string(c.text), nil
Expand Down
Loading

0 comments on commit 51f4897

Please sign in to comment.