Tables
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam blandit dolor nibh, vitae tempor enim pretium non. Sed in condimentum turpis. Vivamus placerat molestie ullamcorper. Maecenas nec risus nibh. Nullam vel vestibulum sapien. Integer ante erat, aliquam id tellus in, malesuada finibus nunc. Sed porttitor ante orci, eget molestie nibh posuere nec.
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam blandit dolor nibh, vitae tempor enim pretium non. Sed in condimentum turpis. Vivamus placerat molestie ullamcorper. Maecenas nec risus nibh. Nullam vel vestibulum sapien. Integer ante erat, aliquam id tellus in, malesuada finibus nunc. Sed porttitor ante orci, eget molestie nibh posuere nec.
|
||||||
|
|
||||||
#[Link on the right](http://example.com) >>
|
#[Link on the right](http://example.com) >>
|
||||||
(http://example.com)[Example.com]^ <<
|
(http://example.com)[Example.com]# <<
|
||||||
#[Link to nekoweb.org in the middle](https://n0va.nekoweb.org) ^^
|
#[Link to nekoweb.org in the middle](https://n0va.nekoweb.org) ^^
|
||||||
#[https://krzak.org]
|
#[https://krzak.org]
|
||||||
#(https://krzak.org)
|
#(https://krzak.org)
|
||||||
|
|||||||
@@ -76,6 +76,97 @@ print_html :: proc(token: ^Token) {
|
|||||||
}
|
}
|
||||||
fmt.print("</strike>")
|
fmt.print("</strike>")
|
||||||
|
|
||||||
|
case TokenType.Table:
|
||||||
|
fmt.print("<table>\n")
|
||||||
|
for child in token.children {
|
||||||
|
print_html(child)
|
||||||
|
}
|
||||||
|
fmt.print("</table>\n")
|
||||||
|
|
||||||
|
case TokenType.TableHeaderRow:
|
||||||
|
fmt.print("<tr>")
|
||||||
|
for child in token.children {
|
||||||
|
align := ""
|
||||||
|
if len(child.children) > 0 {
|
||||||
|
first_child := child.children[0]
|
||||||
|
if first_child.type == .Left {
|
||||||
|
align = "left"
|
||||||
|
} else if first_child.type == .Right {
|
||||||
|
align = "right"
|
||||||
|
} else if first_child.type == .Middle {
|
||||||
|
align = "center"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if align != "" {
|
||||||
|
fmt.printf("<th align=\"%s\">", align)
|
||||||
|
for grandchild in child.children[0].children {
|
||||||
|
print_html(grandchild)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.print("<th>")
|
||||||
|
for grandchild in child.children {
|
||||||
|
print_html(grandchild)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.print("</th>")
|
||||||
|
}
|
||||||
|
fmt.print("</tr>\n")
|
||||||
|
|
||||||
|
case TokenType.TableRow:
|
||||||
|
fmt.print("<tr>")
|
||||||
|
for child in token.children {
|
||||||
|
print_html(child)
|
||||||
|
}
|
||||||
|
fmt.print("</tr>\n")
|
||||||
|
|
||||||
|
case TokenType.TableCell:
|
||||||
|
align := ""
|
||||||
|
if len(token.children) > 0 {
|
||||||
|
first_child := token.children[0]
|
||||||
|
if first_child.type == .Left {
|
||||||
|
align = "left"
|
||||||
|
} else if first_child.type == .Right {
|
||||||
|
align = "right"
|
||||||
|
} else if first_child.type == .Middle {
|
||||||
|
align = "center"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if align != "" {
|
||||||
|
fmt.printf("<td align=\"%s\">", align)
|
||||||
|
for child in token.children[0].children {
|
||||||
|
print_html(child)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.print("<td>")
|
||||||
|
for child in token.children {
|
||||||
|
print_html(child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.print("</td>")
|
||||||
|
|
||||||
|
case TokenType.TableSeparator:
|
||||||
|
fmt.print("<tr class=\"table-sep\"><td colspan=\"100\"></td></tr>\n")
|
||||||
|
|
||||||
|
case TokenType.Left:
|
||||||
|
fmt.print("<div align=\"left\">")
|
||||||
|
for child in token.children {
|
||||||
|
print_html(child)
|
||||||
|
}
|
||||||
|
fmt.print("</div>")
|
||||||
|
|
||||||
|
case TokenType.Right:
|
||||||
|
fmt.print("<div align=\"right\">")
|
||||||
|
for child in token.children {
|
||||||
|
print_html(child)
|
||||||
|
}
|
||||||
|
fmt.print("</div>")
|
||||||
|
|
||||||
|
case TokenType.Middle:
|
||||||
|
fmt.print("<div align=\"center\">")
|
||||||
|
for child in token.children {
|
||||||
|
print_html(child)
|
||||||
|
}
|
||||||
|
fmt.print("</div>")
|
||||||
|
|
||||||
case TokenType.BreakLine:
|
case TokenType.BreakLine:
|
||||||
fmt.print("<br>\n")
|
fmt.print("<br>\n")
|
||||||
|
|||||||
@@ -39,6 +39,22 @@ print_token :: proc(token: ^Token, depth: int = 0) {
|
|||||||
type_str = "ListItem"
|
type_str = "ListItem"
|
||||||
case TokenType.Strikethrough:
|
case TokenType.Strikethrough:
|
||||||
type_str = "Strikethrough"
|
type_str = "Strikethrough"
|
||||||
|
case TokenType.Table:
|
||||||
|
type_str = "Table"
|
||||||
|
case TokenType.TableRow:
|
||||||
|
type_str = "TableRow"
|
||||||
|
case TokenType.TableHeaderRow:
|
||||||
|
type_str = "TableHeaderRow"
|
||||||
|
case TokenType.TableCell:
|
||||||
|
type_str = "TableCell"
|
||||||
|
case TokenType.TableSeparator:
|
||||||
|
type_str = "TableSeparator"
|
||||||
|
case TokenType.Left:
|
||||||
|
type_str = "Left"
|
||||||
|
case TokenType.Right:
|
||||||
|
type_str = "Right"
|
||||||
|
case TokenType.Middle:
|
||||||
|
type_str = "Middle"
|
||||||
}
|
}
|
||||||
|
|
||||||
value_str := ""
|
value_str := ""
|
||||||
|
|||||||
+132
-10
@@ -16,6 +16,14 @@ TokenType :: enum {
|
|||||||
OrderedList,
|
OrderedList,
|
||||||
ListItem,
|
ListItem,
|
||||||
Strikethrough,
|
Strikethrough,
|
||||||
|
Table,
|
||||||
|
TableRow,
|
||||||
|
TableHeaderRow,
|
||||||
|
TableCell,
|
||||||
|
TableSeparator,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Middle,
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenValue :: union {
|
TokenValue :: union {
|
||||||
@@ -37,6 +45,87 @@ push_token :: proc(parent: ^Token, type: TokenType, value: TokenValue = nil) ->
|
|||||||
return token
|
return token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_table_separator :: proc(line: string) -> bool {
|
||||||
|
inner := line[1:len(line) - 1]
|
||||||
|
cells := strings.split(inner, "|", context.temp_allocator)
|
||||||
|
if len(cells) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for cell in cells {
|
||||||
|
trimmed := strings.trim_space(cell)
|
||||||
|
if len(trimmed) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for ch in trimmed {
|
||||||
|
if ch != '-' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_table_cells :: proc(line: string) -> []string {
|
||||||
|
inner := line[1:len(line) - 1]
|
||||||
|
cells := strings.split(inner, "|", context.temp_allocator)
|
||||||
|
result := make([]string, len(cells), context.temp_allocator)
|
||||||
|
for cell, i in cells {
|
||||||
|
result[i] = strings.trim_space(cell)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
get_alignment_token :: proc(text: string) -> (TokenType, bool) {
|
||||||
|
trimmed := strings.trim_space(text)
|
||||||
|
if len(trimmed) == 0 {
|
||||||
|
return .Text, false
|
||||||
|
}
|
||||||
|
if strings.has_suffix(trimmed, ">>") || strings.has_prefix(trimmed, ">>") {
|
||||||
|
return .Right, true
|
||||||
|
}
|
||||||
|
if strings.has_suffix(trimmed, "<<") || strings.has_prefix(trimmed, "<<") {
|
||||||
|
return .Left, true
|
||||||
|
}
|
||||||
|
if strings.has_suffix(trimmed, "^^") || strings.has_prefix(trimmed, "^^") {
|
||||||
|
return .Middle, true
|
||||||
|
}
|
||||||
|
return .Text, false
|
||||||
|
}
|
||||||
|
|
||||||
|
push_text :: proc(parent: ^Token, text: string) {
|
||||||
|
align_type, has_align := get_alignment_token(text)
|
||||||
|
cleaned := strip_alignment_markers(text)
|
||||||
|
|
||||||
|
target := parent
|
||||||
|
if has_align {
|
||||||
|
target = push_token(parent, align_type, nil)
|
||||||
|
}
|
||||||
|
push_token(target, TokenType.Text, cleaned)
|
||||||
|
}
|
||||||
|
|
||||||
|
strip_alignment_markers :: proc(text: string) -> string {
|
||||||
|
trimmed := strings.trim_space(text)
|
||||||
|
if strings.has_suffix(trimmed, ">>") {
|
||||||
|
return strings.trim_space(trimmed[:len(trimmed) - 2])
|
||||||
|
}
|
||||||
|
if strings.has_prefix(trimmed, ">>") {
|
||||||
|
return strings.trim_space(trimmed[2:])
|
||||||
|
}
|
||||||
|
if strings.has_suffix(trimmed, "<<") {
|
||||||
|
return strings.trim_space(trimmed[:len(trimmed) - 2])
|
||||||
|
}
|
||||||
|
if strings.has_prefix(trimmed, "<<") {
|
||||||
|
return strings.trim_space(trimmed[2:])
|
||||||
|
}
|
||||||
|
if strings.has_suffix(trimmed, "^^") {
|
||||||
|
return strings.trim_space(trimmed[:len(trimmed) - 2])
|
||||||
|
}
|
||||||
|
if strings.has_prefix(trimmed, "^^") {
|
||||||
|
return strings.trim_space(trimmed[2:])
|
||||||
|
}
|
||||||
|
return trimmed
|
||||||
|
}
|
||||||
|
|
||||||
parse_header :: proc(line: string) -> (int, string) {
|
parse_header :: proc(line: string) -> (int, string) {
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
return 0, line
|
return 0, line
|
||||||
@@ -161,9 +250,19 @@ add_breaklines :: proc(token: ^Token) {
|
|||||||
child := token.children[i]
|
child := token.children[i]
|
||||||
add_breaklines(child)
|
add_breaklines(child)
|
||||||
append(&new_children, child)
|
append(&new_children, child)
|
||||||
if child.type == TokenType.Text &&
|
is_child_inline :=
|
||||||
i + 1 < len(token.children) &&
|
child.type == TokenType.Text ||
|
||||||
token.children[i + 1].type == TokenType.Text {
|
child.type == TokenType.Left ||
|
||||||
|
child.type == TokenType.Right ||
|
||||||
|
child.type == TokenType.Middle
|
||||||
|
is_next_inline :=
|
||||||
|
i + 1 < len(token.children) &&
|
||||||
|
(token.children[i + 1].type == TokenType.Text ||
|
||||||
|
token.children[i + 1].type == TokenType.Left ||
|
||||||
|
token.children[i + 1].type == TokenType.Right ||
|
||||||
|
token.children[i + 1].type == TokenType.Middle)
|
||||||
|
|
||||||
|
if is_child_inline && is_next_inline {
|
||||||
br := new(Token)
|
br := new(Token)
|
||||||
br^ = Token{TokenType.BreakLine, nil, nil, token}
|
br^ = Token{TokenType.BreakLine, nil, nil, token}
|
||||||
append(&new_children, br)
|
append(&new_children, br)
|
||||||
@@ -189,7 +288,7 @@ parse :: proc(lines: []string, allocator := context.allocator) -> Token {
|
|||||||
header_level, text := parse_header(line)
|
header_level, text := parse_header(line)
|
||||||
if header_level > 0 {
|
if header_level > 0 {
|
||||||
current_token = push_token(&root, TokenType.Header, header_level)
|
current_token = push_token(&root, TokenType.Header, header_level)
|
||||||
push_token(current_token, TokenType.Text, text)
|
push_text(current_token, text)
|
||||||
current_token = &root
|
current_token = &root
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -200,7 +299,7 @@ parse :: proc(lines: []string, allocator := context.allocator) -> Token {
|
|||||||
push_token(current_token, TokenType.Paragraph, nil)
|
push_token(current_token, TokenType.Paragraph, nil)
|
||||||
}
|
}
|
||||||
last_p := current_token.children[len(current_token.children) - 1]
|
last_p := current_token.children[len(current_token.children) - 1]
|
||||||
push_token(last_p, TokenType.Text, text[2:])
|
push_text(last_p, text[2:])
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +308,7 @@ parse :: proc(lines: []string, allocator := context.allocator) -> Token {
|
|||||||
current_token = push_token(&root, TokenType.UnorderedList, nil)
|
current_token = push_token(&root, TokenType.UnorderedList, nil)
|
||||||
}
|
}
|
||||||
li := push_token(current_token, TokenType.ListItem, nil)
|
li := push_token(current_token, TokenType.ListItem, nil)
|
||||||
push_token(li, TokenType.Text, text[2:])
|
push_text(li, text[2:])
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,24 +327,47 @@ parse :: proc(lines: []string, allocator := context.allocator) -> Token {
|
|||||||
current_token = push_token(&root, TokenType.OrderedList, item)
|
current_token = push_token(&root, TokenType.OrderedList, item)
|
||||||
}
|
}
|
||||||
li := push_token(current_token, TokenType.ListItem, nil)
|
li := push_token(current_token, TokenType.ListItem, nil)
|
||||||
push_token(li, TokenType.Text, text)
|
push_text(li, text)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(text) >= 3 && text[0] == '|' && text[len(text) - 1] == '|' {
|
||||||
|
if current_token.type != TokenType.Table {
|
||||||
|
current_token = push_token(&root, TokenType.Table, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_table_separator(text) {
|
||||||
|
row_count := len(current_token.children)
|
||||||
|
if row_count == 1 {
|
||||||
|
current_token.children[0].type = TokenType.TableHeaderRow
|
||||||
|
} else if row_count > 1 {
|
||||||
|
push_token(current_token, TokenType.TableSeparator, nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
row := push_token(current_token, TokenType.TableRow, nil)
|
||||||
|
cells := parse_table_cells(text)
|
||||||
|
for cell_text in cells {
|
||||||
|
cell := push_token(row, TokenType.TableCell, nil)
|
||||||
|
push_text(cell, cell_text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// LAST-CASE SCENARIO: NORMAL TEXT
|
// LAST-CASE SCENARIO: NORMAL TEXT
|
||||||
|
|
||||||
if current_token.type == .Blockquote {
|
if current_token.type == .Blockquote {
|
||||||
last_p := current_token.children[len(current_token.children) - 1]
|
last_p := current_token.children[len(current_token.children) - 1]
|
||||||
push_token(last_p, TokenType.Text, line)
|
push_text(last_p, line)
|
||||||
} else if current_token.type == .UnorderedList || current_token.type == .OrderedList {
|
} else if current_token.type == .UnorderedList || current_token.type == .OrderedList {
|
||||||
last_li := current_token.children[len(current_token.children) - 1]
|
last_li := current_token.children[len(current_token.children) - 1]
|
||||||
push_token(last_li, TokenType.Text, line)
|
push_text(last_li, line)
|
||||||
} else {
|
} else {
|
||||||
if current_token.type != .Paragraph {
|
if current_token.type != .Paragraph {
|
||||||
current_token = push_token(&root, TokenType.Paragraph, nil)
|
current_token = push_token(&root, TokenType.Paragraph, nil)
|
||||||
}
|
}
|
||||||
push_token(current_token, TokenType.Text, line)
|
push_text(current_token, line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -49,8 +49,13 @@ th,
|
|||||||
td {
|
td {
|
||||||
border: 1px solid #444;
|
border: 1px solid #444;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
text-align: left;
|
|
||||||
}
|
}
|
||||||
th {
|
th {
|
||||||
background: #2a2a2a;
|
background: #2a2a2a;
|
||||||
}
|
}
|
||||||
|
tr.table-sep td {
|
||||||
|
border: none;
|
||||||
|
border-top: 3px solid #ff6b9d;
|
||||||
|
padding: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user