mirror of
https://github.com/michaelrsweet/mxml.git
synced 2024-11-24 11:25:30 +00:00
Update Mini-Markdown code.
This commit is contained in:
parent
0035a02432
commit
501dcfe6b6
@ -1,4 +1,4 @@
|
||||
.TH mxml 3 "Mini-XML API" "09/09/18" "Mini-XML API"
|
||||
.TH mxml 3 "Mini-XML API" "09/29/18" "Mini-XML API"
|
||||
.SH NAME
|
||||
mxml \- Mini-XML API
|
||||
.SH INCLUDE FILE
|
||||
|
247
mmd.c
247
mmd.c
@ -3,28 +3,10 @@
|
||||
*
|
||||
* https://github.com/michaelrsweet/mmd
|
||||
*
|
||||
* Copyright 2017 by Michael R Sweet.
|
||||
* Copyright © 2017-2018 by Michael R Sweet.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
* Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
* information.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -35,6 +17,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
# define snprintf _snprintf
|
||||
#endif /* WIN32 */
|
||||
|
||||
|
||||
/*
|
||||
@ -67,6 +52,92 @@ static char *mmd_parse_link(char *lineptr, char **text, char **url);
|
||||
static void mmd_remove(mmd_t *node);
|
||||
|
||||
|
||||
/*
|
||||
* 'mmdCopyAllText()' - Make a copy of all the text under a given node.
|
||||
*
|
||||
* The returned string must be freed using free().
|
||||
*/
|
||||
|
||||
char * /* O - Copied string */
|
||||
mmdCopyAllText(mmd_t *node) /* I - Parent node */
|
||||
{
|
||||
char *all = NULL, /* String buffer */
|
||||
*allptr = NULL, /* Pointer into string buffer */
|
||||
*temp; /* Temporary pointer */
|
||||
size_t allsize = 0, /* Size of "all" buffer */
|
||||
textlen; /* Length of "text" string */
|
||||
mmd_t *current, /* Current node */
|
||||
*next; /* Next node */
|
||||
|
||||
|
||||
current = mmdGetFirstChild(node);
|
||||
|
||||
while (current != node)
|
||||
{
|
||||
if (current->text)
|
||||
{
|
||||
/*
|
||||
* Append this node's text to the string...
|
||||
*/
|
||||
|
||||
textlen = strlen(current->text);
|
||||
|
||||
if (allsize == 0)
|
||||
{
|
||||
allsize = textlen + (size_t)current->whitespace + 1;
|
||||
all = malloc(allsize);
|
||||
allptr = all;
|
||||
|
||||
if (!all)
|
||||
return (NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
allsize += textlen + (size_t)current->whitespace;
|
||||
temp = realloc(all, allsize);
|
||||
|
||||
if (!temp)
|
||||
{
|
||||
free(all);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
allptr = temp + (allptr - all);
|
||||
all = temp;
|
||||
}
|
||||
|
||||
if (current->whitespace)
|
||||
*allptr++ = ' ';
|
||||
|
||||
memcpy(allptr, current->text, textlen);
|
||||
allptr += textlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the next logical node...
|
||||
*/
|
||||
|
||||
if ((next = mmdGetNextSibling(current)) == NULL)
|
||||
{
|
||||
next = mmdGetParent(current);
|
||||
|
||||
while (next && next != node && mmdGetNextSibling(next) == NULL)
|
||||
next = mmdGetParent(next);
|
||||
|
||||
if (next != node)
|
||||
next = mmdGetNextSibling(next);
|
||||
}
|
||||
|
||||
current = next;
|
||||
}
|
||||
|
||||
if (allptr)
|
||||
*allptr = '\0';
|
||||
|
||||
return (all);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mmdFree()' - Free a markdown tree.
|
||||
*/
|
||||
@ -309,6 +380,9 @@ mmdLoadFile(FILE *fp) /* I - File to load */
|
||||
*lineptr, /* Pointer into line */
|
||||
*lineend; /* End of line */
|
||||
int blank_code = 0; /* Saved indented blank code line */
|
||||
mmd_type_t columns[256]; /* Alignment of table columns */
|
||||
int num_columns = 0, /* Number of columns in table */
|
||||
rows = 0; /* Number of rows in table */
|
||||
|
||||
|
||||
/*
|
||||
@ -426,7 +500,11 @@ mmdLoadFile(FILE *fp) /* I - File to load */
|
||||
* quote...
|
||||
*/
|
||||
|
||||
if (current == doc || current->type != MMD_TYPE_BLOCK_QUOTE)
|
||||
mmd_t *node; /* Current node */
|
||||
|
||||
for (node = current; node != doc && node->type != MMD_TYPE_BLOCK_QUOTE; node = node->parent);
|
||||
|
||||
if (node == doc || node->type != MMD_TYPE_BLOCK_QUOTE)
|
||||
current = mmd_add(doc, MMD_TYPE_BLOCK_QUOTE, 0, NULL, NULL);
|
||||
|
||||
/*
|
||||
@ -446,7 +524,130 @@ mmdLoadFile(FILE *fp) /* I - File to load */
|
||||
block = NULL;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(lineptr, "+"))
|
||||
else if (strchr(lineptr, '|'))
|
||||
{
|
||||
/*
|
||||
* Table...
|
||||
*/
|
||||
|
||||
int col; /* Current column */
|
||||
char *start, /* Start of column/cell */
|
||||
*end; /* End of column/cell */
|
||||
mmd_t *row = NULL, /* Current row */
|
||||
*cell; /* Current cell */
|
||||
|
||||
// fprintf(stderr, "TABLE current=%p (%d), rows=%d\n", current, current->type, rows);
|
||||
|
||||
if (current->type != MMD_TYPE_TABLE)
|
||||
{
|
||||
if (current != doc && current->type != MMD_TYPE_BLOCK_QUOTE)
|
||||
current = current->parent;
|
||||
|
||||
// fprintf(stderr, "ADDING NEW TABLE to %p (%d)\n", current, current->type);
|
||||
|
||||
current = mmd_add(current, MMD_TYPE_TABLE, 0, NULL, NULL);
|
||||
block = mmd_add(current, MMD_TYPE_TABLE_HEADER, 0, NULL, NULL);
|
||||
|
||||
for (col = 0; col < (int)(sizeof(columns) / sizeof(columns[0])); col ++)
|
||||
columns[col] = MMD_TYPE_TABLE_BODY_CELL_LEFT;
|
||||
|
||||
num_columns = 0;
|
||||
rows = -1;
|
||||
}
|
||||
else if (rows > 0)
|
||||
{
|
||||
if (rows == 1)
|
||||
block = mmd_add(current, MMD_TYPE_TABLE_BODY, 0, NULL, NULL);
|
||||
}
|
||||
else
|
||||
block = NULL;
|
||||
|
||||
if (block)
|
||||
row = mmd_add(block, MMD_TYPE_TABLE_ROW, 0, NULL, NULL);
|
||||
|
||||
if (*lineptr == '|')
|
||||
lineptr ++; /* Skip leading pipe */
|
||||
|
||||
if ((end = lineptr + strlen(lineptr) - 1) > lineptr)
|
||||
{
|
||||
while ((*end == '\n' || *end == 'r') && end > lineptr)
|
||||
end --;
|
||||
|
||||
if (end > lineptr && *end == '|')
|
||||
*end = '\0'; /* Truncate trailing pipe */
|
||||
}
|
||||
|
||||
for (col = 0; lineptr && *lineptr && col < (int)(sizeof(columns) / sizeof(columns[0])); col ++)
|
||||
{
|
||||
/*
|
||||
* Get the bounds of the current cell...
|
||||
*/
|
||||
|
||||
start = lineptr;
|
||||
if ((lineptr = strchr(lineptr + 1, '|')) != NULL)
|
||||
*lineptr++ = '\0';
|
||||
|
||||
if (block)
|
||||
{
|
||||
/*
|
||||
* Add a cell to this row...
|
||||
*/
|
||||
|
||||
if (block->type == MMD_TYPE_TABLE_HEADER)
|
||||
cell = mmd_add(row, MMD_TYPE_TABLE_HEADER_CELL, 0, NULL, NULL);
|
||||
else
|
||||
cell = mmd_add(row, columns[col], 0, NULL, NULL);
|
||||
|
||||
mmd_parse_inline(cell, start);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Process separator row for alignment...
|
||||
*/
|
||||
|
||||
while (isspace(*start & 255))
|
||||
start ++;
|
||||
|
||||
for (end = start + strlen(start) - 1; end > start && isspace(*end & 255); end --);
|
||||
|
||||
if (*start == ':' && *end == ':')
|
||||
columns[col] = MMD_TYPE_TABLE_BODY_CELL_CENTER;
|
||||
else if (*end == ':')
|
||||
columns[col] = MMD_TYPE_TABLE_BODY_CELL_RIGHT;
|
||||
|
||||
// fprintf(stderr, "COLUMN %d SEPARATOR=\"%s\", TYPE=%d\n", col, start, columns[col]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the table is balanced...
|
||||
*/
|
||||
|
||||
if (col > num_columns)
|
||||
{
|
||||
num_columns = col;
|
||||
}
|
||||
else if (block && block->type != MMD_TYPE_TABLE_HEADER)
|
||||
{
|
||||
while (col < num_columns)
|
||||
{
|
||||
mmd_add(row, columns[col], 0, NULL, NULL);
|
||||
col ++;
|
||||
}
|
||||
}
|
||||
|
||||
rows ++;
|
||||
continue;
|
||||
}
|
||||
else if (current->type == MMD_TYPE_TABLE)
|
||||
{
|
||||
// fputs("END TABLE\n", stderr);
|
||||
current = current->parent;
|
||||
block = NULL;
|
||||
}
|
||||
|
||||
if (!strcmp(lineptr, "+"))
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
|
33
mmd.h
33
mmd.h
@ -3,28 +3,10 @@
|
||||
*
|
||||
* https://github.com/michaelrsweet/mmd
|
||||
*
|
||||
* Copyright 2017 by Michael R Sweet.
|
||||
* Copyright © 2017-2018 by Michael R Sweet.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
* Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
* information.
|
||||
*/
|
||||
|
||||
#ifndef MMD_H
|
||||
@ -50,6 +32,10 @@ typedef enum mmd_type_e
|
||||
MMD_TYPE_ORDERED_LIST,
|
||||
MMD_TYPE_UNORDERED_LIST,
|
||||
MMD_TYPE_LIST_ITEM,
|
||||
MMD_TYPE_TABLE,
|
||||
MMD_TYPE_TABLE_HEADER,
|
||||
MMD_TYPE_TABLE_BODY,
|
||||
MMD_TYPE_TABLE_ROW,
|
||||
MMD_TYPE_HEADING_1 = 10,
|
||||
MMD_TYPE_HEADING_2,
|
||||
MMD_TYPE_HEADING_3,
|
||||
@ -59,6 +45,10 @@ typedef enum mmd_type_e
|
||||
MMD_TYPE_PARAGRAPH,
|
||||
MMD_TYPE_CODE_BLOCK,
|
||||
MMD_TYPE_THEMATIC_BREAK,
|
||||
MMD_TYPE_TABLE_HEADER_CELL,
|
||||
MMD_TYPE_TABLE_BODY_CELL_LEFT,
|
||||
MMD_TYPE_TABLE_BODY_CELL_CENTER,
|
||||
MMD_TYPE_TABLE_BODY_CELL_RIGHT,
|
||||
MMD_TYPE_NORMAL_TEXT = 100,
|
||||
MMD_TYPE_EMPHASIZED_TEXT,
|
||||
MMD_TYPE_STRONG_TEXT,
|
||||
@ -87,6 +77,7 @@ typedef struct _mmd_s mmd_t;
|
||||
extern "C" {
|
||||
# endif /* __cplusplus */
|
||||
|
||||
extern char *mmdCopyAllText(mmd_t *node);
|
||||
extern void mmdFree(mmd_t *node);
|
||||
extern mmd_t *mmdGetFirstChild(mmd_t *node);
|
||||
extern mmd_t *mmdGetLastChild(mmd_t *node);
|
||||
|
Loading…
Reference in New Issue
Block a user