예제 #1
0
파일: xhtml.c 프로젝트: bnoordhuis/upskirt
static void
rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)
{
	struct xhtml_renderopt *options = opaque;
	size_t i = 0;

	if (ob->size) bufputc(ob, '\n');

	if (!text || !text->size)
		return;

	while (i < text->size && isspace(text->data[i])) i++;

	if (i == text->size)
		return;

	BUFPUTSL(ob, "<p>");
	if (options->flags & XHTML_HARD_WRAP) {
		size_t org;
		while (i < text->size) {
			org = i;
			while (i < text->size && text->data[i] != '\n')
				i++;

			if (i > org)
				bufput(ob, text->data + org, i - org);

			if (i >= text->size)
				break;

			BUFPUTSL(ob, "<br/>\n");
			i++;
		}
	} else {
		bufput(ob, &text->data[i], text->size - i);
	}
	BUFPUTSL(ob, "</p>\n");

	/* Close any open quotes at the end of the paragraph */
	options->quotes.in_squote = 0;
	options->quotes.in_dquote = 0;
}
예제 #2
0
static void
rndr_paragraph(struct buf *ob, const struct buf *text, void *opaque)
{
	struct html_renderopt *options = opaque;
	size_t i = 0;

	if (ob->size) bufputc(ob, '\n');

	if (!text || !text->size)
		return;

	while (i < text->size && isspace(text->data[i])) i++;

	if (i == text->size)
		return;

	BUFPUTSL(ob, "<p>");
	if (options->flags & HTML_HARD_WRAP) {
		size_t org;
		while (i < text->size) {
			org = i;
			while (i < text->size && text->data[i] != '\n')
				i++;

			if (i > org)
				bufput(ob, text->data + org, i - org);

			/*
			 * do not insert a line break if this newline
			 * is the last character on the paragraph
			 */
			if (i >= text->size - 1)
				break;

			rndr_linebreak(ob, opaque);
			i++;
		}
	} else {
		bufput(ob, &text->data[i], text->size - i);
	}
	BUFPUTSL(ob, "</p>\n");
}
예제 #3
0
static void
latex_header(struct buf *ob, struct buf *text, int level, void *opaque) {
	if (ob->size) bufputc(ob, '\n');
	switch(level) {
		case 1:
			BUFPUTSL(ob,"\\section{");
			break;
		case 2:
			BUFPUTSL(ob, "\\subsection{");
			break;
		case 3:
			BUFPUTSL(ob, "\\subsubsection{");
			break;
		default:
			fprintf(stderr, "Warning: ignoring header level %d\n",
                                        level);
	}
	if (text) bufput(ob, text->data, text->size);
	if (level >= 1 && level <= 3) BUFPUTSL(ob, "}\n");
}
예제 #4
0
파일: html.c 프로젝트: beingryu/sundown
static int
rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque)
{
	struct html_renderopt *options = opaque;
	if (!link || !link->size) return 0;

	BUFPUTSL(ob, "<img src=\"");
	escape_href(ob, link->data, link->size);
	BUFPUTSL(ob, "\" alt=\"");

	if (alt && alt->size)
		escape_html(ob, alt->data, alt->size);

	if (title && title->size) {
		BUFPUTSL(ob, "\" title=\"");
		escape_html(ob, title->data, title->size); }

	bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">");
	return 1;
}
예제 #5
0
/********************
 * GENERIC RENDERER *
 ********************/
static int
rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque)
{
	struct html_renderopt *options = opaque;

	if (!link || !link->size)
		return 0;

	if ((options->flags & HTML_SAFELINK) != 0 &&
		!sd_autolink_issafe(link->data, link->size) &&
		type != MKDA_EMAIL)
		return 0;

	BUFPUTSL(ob, "<a href=\"");
	if (type == MKDA_EMAIL)
		BUFPUTSL(ob, "mailto:");
	escape_href(ob, link->data, link->size);

	if (options->link_attributes) {
		bufputc(ob, '\"');
		options->link_attributes(ob, link, opaque);
		bufputc(ob, '>');
	} else {
		BUFPUTSL(ob, "\">");
	}

	/*
	 * Pretty printing: if we get an email address as
	 * an actual URI, e.g. `mailto:[email protected]`, we don't
	 * want to print the `mailto:` prefix
	 */
	if (bufprefix(link, "mailto:") == 0) {
		escape_html(ob, link->data + 7, link->size - 7);
	} else {
		escape_html(ob, link->data, link->size);
	}

	BUFPUTSL(ob, "</a>");

	return 1;
}
예제 #6
0
static void
snudown_link_attr(struct buf *ob, const struct buf *link, void *opaque)
{
	struct snudown_renderopt *options = opaque;
	
	if (options->nofollow)
		BUFPUTSL(ob, " rel=\"nofollow\"");
	
	/* If we have an option, if it is "_blank" which means to open a 
	   new tab, then we should check to make sure the item is not
	   on the lightnet domain before outputting the target. We don't
	   want to open new windows for links within the lightnet.is domain. */
	if (options->target != NULL &&
		(strcmp(options->target, "_blank") != 0 ||
		strstr((const char*) link->data, options->domain) == 0) ) {
	
		BUFPUTSL(ob, " target=\"");
		bufputs(ob, options->target);
		bufputc(ob, '\"');
	}
}
예제 #7
0
파일: html.c 프로젝트: beingryu/sundown
static void
toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
{
	struct html_renderopt *options = opaque;

	/* set the level offset if this is the first header
	 * we're parsing for the document */
	if (options->toc_data.current_level == 0) {
		options->toc_data.level_offset = level - 1;
	}
	level -= options->toc_data.level_offset;

	if (level > options->toc_data.current_level) {
		while (level > options->toc_data.current_level) {
			BUFPUTSL(ob, "<ul>\n<li>\n");
			options->toc_data.current_level++;
		}
	} else if (level < options->toc_data.current_level) {
		BUFPUTSL(ob, "</li>\n");
		while (level < options->toc_data.current_level) {
			BUFPUTSL(ob, "</ul>\n</li>\n");
			options->toc_data.current_level--;
		}
		BUFPUTSL(ob,"<li>\n");
	} else {
		BUFPUTSL(ob,"</li>\n<li>\n");
	}

	bufprintf(ob, "<a href=\"#toc_%d\">", options->toc_data.header_count++);
	if (text)
		escape_html(ob, text->data, text->size);
	BUFPUTSL(ob, "</a>\n");
}
예제 #8
0
파일: html.c 프로젝트: sanilrocks/snudown
static void
toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
{
	struct html_renderopt *options = opaque;

	if (level > options->toc_data.current_level) {
		while (level > options->toc_data.current_level) {
			BUFPUTSL(ob, "<ul>\n<li>\n");
			options->toc_data.current_level++;
		}
	} else if (level < options->toc_data.current_level) {
		BUFPUTSL(ob, "</li>\n");
		while (level < options->toc_data.current_level) {
			BUFPUTSL(ob, "</ul>\n</li>\n");
			options->toc_data.current_level--;
		}
		BUFPUTSL(ob,"<li>\n");
	} else {
		BUFPUTSL(ob,"</li>\n<li>\n");
	}

	bufprintf(ob, "<a href=\"#toc_%d\">", options->toc_data.header_count++);
	if (text)
		bufput(ob, text->data, text->size);
	BUFPUTSL(ob, "</a>\n");
}
예제 #9
0
static size_t
smartypants_cb__dash(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
	if (size >= 3 && text[1] == '-' && text[2] == '-') {
		BUFPUTSL(ob, "&mdash;");
		return 2;
	}

	if (size >= 2 && text[1] == '-') {
		if(size >= 4 && (previous_char == '>' || previous_char == '\n') && text[2] == ' ' && text[3] == '<') {
			// A hack to avoid '-- ' being converted to an ndash.
		}
		else
		{
			BUFPUTSL(ob, "&ndash;");
			return 1;
		}
	}

	bufputc(ob, text[0]);
	return 0;
}
예제 #10
0
static void
nat_paragraph(struct buf *ob, struct buf *text, void *opaque) {
	size_t i = 0;
	if (ob->size) bufputc(ob, '\n');
	BUFPUTSL(ob, "<p");
	if (text && text->size && text->data[0] == '(') {
		i = 1;
		while (i < text->size && (text->data[i] == ' '
			/* this seems to be a bit more restrictive than */
			/* what is allowed for class names */
			 || (text->data[i] >= 'a' && text->data[i] <= 'z')
			 || (text->data[i] >= 'A' && text->data[i] <= 'Z')
			 || (text->data[i] >= '0' && text->data[i] <= '0')))
			i += 1;
		if (i < text->size && text->data[i] == ')') {
			bufprintf(ob, " class=\"%.*s\"",
						(int)(i - 1), text->data + 1);
			i += 1; }
		else i = 0; }
	bufputc(ob, '>');
	if (text) bufput(ob, text->data + i, text->size - i);
	BUFPUTSL(ob, "</p>\n"); }
예제 #11
0
static int
rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque)
{
	struct html_renderopt *options = opaque;

	if (link != NULL && (options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size))
		return 0;

	BUFPUTSL(ob, "<img src=\"");
	escape_href(ob, link->data, link->size);
	BUFPUTSL(ob, "\" alt=\"");

	if (alt && alt->size)
		escape_html(ob, alt->data, alt->size);

	if (title && title->size) {
		BUFPUTSL(ob, "\" title=\"");
		escape_html(ob, title->data, title->size); }

	bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">");
	return 1;
}
예제 #12
0
static void
rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)
{
	struct html_renderopt *options = opaque;
	size_t i = 0;

	if (ob->size) bufputc(ob, '\n');

	if (!text || !text->size)
		return;

	while (i < text->size && isspace(text->data[i])) i++;

	if (i == text->size)
		return;

	BUFPUTSL(ob, "<p>");
	if (options->flags & HTML_HARD_WRAP) {
		size_t org;
		while (i < text->size) {
			org = i;
			while (i < text->size && text->data[i] != '\n')
				i++;

			if (i > org)
				bufput(ob, text->data + org, i - org);

			if (i >= text->size)
				break;

			BUFPUTSL(ob, "<br");
			bufputs(ob, options->close_tag);
			i++;
		}
	} else {
		bufput(ob, &text->data[i], text->size - i);
	}
	BUFPUTSL(ob, "</p>\n");
}
예제 #13
0
파일: xhtml.c 프로젝트: bnoordhuis/upskirt
static void
toc_header(struct buf *ob, struct buf *text, int level, void *opaque)
{
	struct xhtml_renderopt *options = opaque;

	if (level > options->toc_data.current_level) {
		if (level > 1)
			BUFPUTSL(ob, "<li>");
		BUFPUTSL(ob, "<ul>\n");
	}
	
	if (level < options->toc_data.current_level) {
		BUFPUTSL(ob, "</ul>");
		if (options->toc_data.current_level > 1)
			BUFPUTSL(ob, "</li>\n");
	}

	options->toc_data.current_level = level;

	bufprintf(ob, "<li><a href=\"#toc_%d\">", options->toc_data.header_count++);
	if (text)
		bufput(ob, text->data, text->size);
	BUFPUTSL(ob, "</a></li>\n");
}
예제 #14
0
static size_t
smartypants_cb__squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
{
	if (size >= 2) {
		uint8_t t1 = tolower(text[1]);

		if (t1 == '\'') {
			if (smartypants_quotes(ob, previous_char, size >= 3 ? text[2] : 0, 'd', &smrt->in_dquote))
				return 1;
		}

		if ((t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') &&
			(size == 3 || word_boundary(text[2]))) {
			BUFPUTSL(ob, "&rsquo;");
			return 0;
		}

		if (size >= 3) {
			uint8_t t2 = tolower(text[2]);

			if (((t1 == 'r' && t2 == 'e') ||
				(t1 == 'l' && t2 == 'l') ||
				(t1 == 'v' && t2 == 'e')) &&
				(size == 4 || word_boundary(text[3]))) {
				BUFPUTSL(ob, "&rsquo;");
				return 0;
			}
		}
	}

	if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
		return 0;

	bufputc(ob, text[0]);
	return 0;
}
예제 #15
0
static int
print_link_wxh(struct buf *ob, struct buf *link) {
	size_t eq, ex, end;
	eq = link->size - 1;
	while (eq > 0 && (link->data[eq - 1] != ' ' || link->data[eq] != '='))
		eq -= 1;
	if (eq <= 0) return 0;
	ex = eq + 1;
	while (ex < link->size
	&& link->data[ex] >= '0' && link->data[ex] <= '9')
		ex += 1;
	if (ex >= link->size || ex == eq + 1 || link->data[ex] != 'x') return 0;
	end = ex + 1;
	while (end < link->size
	&& link->data[end] >= '0' && link->data[end] <= '9')
		end += 1;
	if (end == ex + 1) return 0;
	/* everything is fine, proceeding to actual printing */
	lus_attr_escape(ob, link->data, eq - 1);
	BUFPUTSL(ob, "\" width=");
	bufput(ob, link->data + eq + 1, ex - eq - 1);
	BUFPUTSL(ob, " height=");
	bufput(ob, link->data + ex + 1, end - ex - 1);
	return 1; }
예제 #16
0
static void
rndr_header(struct buf *ob, const struct buf *text, int level, void *opaque)
{
	struct html_renderopt *options = opaque;

	if (ob->size)
		bufputc(ob, '\n');

	if ((options->flags & HTML_TOC) && (level <= options->toc_data.nesting_level)) {
		bufprintf(ob, "<h%d id=\"", level);
		rndr_header_anchor(ob, text);
		BUFPUTSL(ob, "\">");
	}
	else
		bufprintf(ob, "<h%d>", level);

	if (text) bufput(ob, text->data, text->size);
	bufprintf(ob, "</h%d>\n", level);
}
예제 #17
0
파일: rinku.c 프로젝트: Arkham/rinku
/*
 * Rinku assumes valid HTML encoding for all input, but there's still
 * the case where a link can contain a double quote `"` that allows XSS.
 *
 * We need to properly escape the character we use for the `href` attribute
 * declaration
 */
static void print_link(struct buf *ob, const char *link, size_t size)
{
	size_t i = 0, org;

	while (i < size) {
		org = i;

		while (i < size && link[i] != '"')
			i++;

		if (i > org)
			bufput(ob, link + org, i - org);

		if (i >= size)
			break;

		BUFPUTSL(ob, "&quot;");
		i++;
	}
}
예제 #18
0
static void
toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
{
	struct html_renderopt *options = opaque;

	if (level <= options->toc_data.nesting_level) {
		/* set the level offset if this is the first header
		 * we're parsing for the document */
		if (options->toc_data.current_level == 0)
			options->toc_data.level_offset = level - 1;

		level -= options->toc_data.level_offset;

		if (level > options->toc_data.current_level) {
			while (level > options->toc_data.current_level) {
				BUFPUTSL(ob, "<ul>\n<li>\n");
				options->toc_data.current_level++;
			}
		} else if (level < options->toc_data.current_level) {
			BUFPUTSL(ob, "</li>\n");
			while (level < options->toc_data.current_level) {
				BUFPUTSL(ob, "</ul>\n</li>\n");
				options->toc_data.current_level--;
			}
			BUFPUTSL(ob,"<li>\n");
		} else {
			BUFPUTSL(ob,"</li>\n<li>\n");
		}

		bufprintf(ob, "<a href=\"#");
		rndr_header_anchor(ob, text);
		BUFPUTSL(ob, "\">");

		if (text) {
			if (options->flags & HTML_ESCAPE)
				escape_html(ob, text->data, text->size);
			else
				bufput(ob, text->data, text->size);
		}

		BUFPUTSL(ob, "</a>\n");
	}
}
예제 #19
0
static void
rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque)
{
	struct html_renderopt *options = opaque;

	if (ob->size) bufputc(ob, '\n');

	if (lang && lang->size) {
		size_t i, cls;
		if (options->flags & HTML_PRETTIFY) {
			BUFPUTSL(ob, "<pre><code class=\"prettyprint lang-");
			cls++;
		} else {
			BUFPUTSL(ob, "<pre><code class=\"");
		}

		for (i = 0, cls = 0; i < lang->size; ++i, ++cls) {
			while (i < lang->size && isspace(lang->data[i]))
				i++;

			if (i < lang->size) {
				size_t org = i;
				while (i < lang->size && !isspace(lang->data[i]))
					i++;

				if (lang->data[org] == '.')
					org++;

				if (cls) bufputc(ob, ' ');
				escape_html(ob, lang->data + org, i - org);
			}
		}

		BUFPUTSL(ob, "\">");
	} else if (options->flags & HTML_PRETTIFY) {
		BUFPUTSL(ob, "<pre><code class=\"prettyprint\">");
	} else {
		BUFPUTSL(ob, "<pre><code>");
	}

	if (text)
		escape_html(ob, text->data, text->size);

	BUFPUTSL(ob, "</code></pre>\n");
}
예제 #20
0
static void
discount_table_cell(struct buf *ob, struct buf *text, int flags, void *opaque){
	if (flags & MKD_CELL_HEAD)
		BUFPUTSL(ob, "    <th");
	else
		BUFPUTSL(ob, "    <td");
	switch (flags & MKD_CELL_ALIGN_MASK) {
		case MKD_CELL_ALIGN_LEFT:
			BUFPUTSL(ob, " align=\"left\"");
			break;
		case MKD_CELL_ALIGN_RIGHT:
			BUFPUTSL(ob, " align=\"right\"");
			break;
		case MKD_CELL_ALIGN_CENTER:
			BUFPUTSL(ob, " align=\"center\"");
			break; }
	bufputc(ob, '>');
	if (text) bufput(ob, text->data, text->size);
	if (flags & MKD_CELL_HEAD)
		BUFPUTSL(ob, "</th>\n");
	else
		BUFPUTSL(ob, "</td>\n"); }
예제 #21
0
파일: escape.c 프로젝트: doo/hoedown
void
hoedown_escape_href(struct hoedown_buffer *ob, const uint8_t *src, size_t size)
{
	static const char hex_chars[] = "0123456789ABCDEF";
	size_t  i = 0, org;
	char hex_str[3];

	hex_str[0] = '%';

	while (i < size) {
		org = i;
		while (i < size && HREF_SAFE[src[i]] != 0)
			i++;

		if (i > org) {
			if (org == 0) {
				if (i >= size) {
					hoedown_buffer_put(ob, src, size);
					return;
				}

				hoedown_buffer_grow(ob, ESCAPE_GROW_FACTOR(size));
			}

			hoedown_buffer_put(ob, src + org, i - org);
		}

		/* escaping */
		if (i >= size)
			break;

		switch (src[i]) {
		/* amp appears all the time in URLs, but needs
		 * HTML-entity escaping to be inside an href */
		case '&': 
			BUFPUTSL(ob, "&amp;");
			break;

		/* the single quote is a valid URL character
		 * according to the standard; it needs HTML
		 * entity escaping too */
		case '\'':
			BUFPUTSL(ob, "&#x27;");
			break;
		
		/* the space can be escaped to %20 or a plus
		 * sign. we're going with the generic escape
		 * for now. the plus thing is more commonly seen
		 * when building GET strings */
#if 0
		case ' ':
			hoedown_buffer_putc(ob, '+');
			break;
#endif

		/* every other character goes with a %XX escaping */
		default:
			hex_str[1] = hex_chars[(src[i] >> 4) & 0xF];
			hex_str[2] = hex_chars[src[i] & 0xF];
			hoedown_buffer_put(ob, hex_str, 3);
		}

		i++;
	}
}
예제 #22
0
static void
rndr_blockquote(struct buf *ob, struct buf *text, void *opaque) {
	if (ob->size) bufputc(ob, '\n');
	BUFPUTSL(ob, "<blockquote>\n");
	if (text) bufput(ob, text->data, text->size);
	BUFPUTSL(ob, "</blockquote>\n"); }
예제 #23
0
static void
rndr_blockcode(struct buf *ob, struct buf *text, void *opaque) {
	if (ob->size) bufputc(ob, '\n');
	BUFPUTSL(ob, "<pre><code>");
	if (text) lus_body_escape(ob, text->data, text->size);
	BUFPUTSL(ob, "</code></pre>\n"); }
예제 #24
0
파일: rinku.c 프로젝트: vmg/rinku
int
rinku_autolink(
	struct buf *ob,
	const uint8_t *text,
	size_t size,
	autolink_mode mode,
	unsigned int flags,
	const char *link_attr,
	const char **skip_tags,
	void (*link_text_cb)(struct buf *, const uint8_t *, size_t, void *),
	void *payload)
{
	size_t i, end;
	char active_chars[256] = {0};
	int link_count = 0;

	if (!text || size == 0)
		return 0;

	active_chars['<'] = AUTOLINK_ACTION_SKIP_TAG;

	if (mode & AUTOLINK_EMAILS)
		active_chars['@'] = AUTOLINK_ACTION_EMAIL;

	if (mode & AUTOLINK_URLS) {
		active_chars['w'] = AUTOLINK_ACTION_WWW;
		active_chars['W'] = AUTOLINK_ACTION_WWW;
		active_chars[':'] = AUTOLINK_ACTION_URL;
	}

	if (link_attr != NULL) {
		while (rinku_isspace(*link_attr))
			link_attr++;
	}

	bufgrow(ob, size);

	i = end = 0;

	while (i < size) {
		struct autolink_pos link;
		bool link_found;
		char action = 0;

		while (end < size && (action = active_chars[text[end]]) == 0)
			end++;

		if (end == size) {
			if (link_count > 0)
				bufput(ob, text + i, end - i);
			break;
		}

		if (action == AUTOLINK_ACTION_SKIP_TAG) {
			end += autolink__skip_tag(ob,
				text + end, size - end, skip_tags);
			continue;
		}

		link_found = g_callbacks[(int)action](
			&link, text, end, size, flags);

		if (link_found && link.start >= i) {
			const uint8_t *link_str = text + link.start;
			const size_t link_len = link.end - link.start;

			bufput(ob, text + i, link.start - i);
			bufputs(ob, g_hrefs[(int)action]);
			print_link(ob, link_str, link_len);

			if (link_attr) {
				BUFPUTSL(ob, "\" ");
				bufputs(ob, link_attr);
				bufputc(ob, '>');
			} else {
				BUFPUTSL(ob, "\">");
			}

			if (link_text_cb) {
				link_text_cb(ob, link_str, link_len, payload);
			} else {
				bufput(ob, link_str, link_len);
			}

			BUFPUTSL(ob, "</a>");

			link_count++;
			end = i = link.end;
		} else {
			end = end + 1;
		}
	}

	return link_count;
}
예제 #25
0
static void
discount_table_row(struct buf *ob, struct buf *cells, int flags, void *opaque){
	(void)flags;
	BUFPUTSL(ob, "  <tr>\n");
	if (cells) bufput(ob, cells->data, cells->size);
	BUFPUTSL(ob, "  </tr>\n"); }
예제 #26
0
static int
xhtml_linebreak(struct buf *ob, void *opaque) {
	BUFPUTSL(ob, "<br />\n");
	return 1; }
예제 #27
0
static void
xhtml_hrule(struct buf *ob, void *opaque) {
	if (ob->size) bufputc(ob, '\n');
	BUFPUTSL(ob, "<hr />\n"); }
예제 #28
0
static void
rndr_paragraph(struct buf *ob, struct buf *text, void *opaque) {
	if (ob->size) bufputc(ob, '\n');
	BUFPUTSL(ob, "<p>");
	if (text) bufput(ob, text->data, text->size);
	BUFPUTSL(ob, "</p>\n"); }
예제 #29
0
static int
rndr_codespan(struct buf *ob, struct buf *text, void *opaque) {
	BUFPUTSL(ob, "<code>");
	if (text) lus_body_escape(ob, text->data, text->size);
	BUFPUTSL(ob, "</code>");
	return 1; }
예제 #30
0
파일: rinku.c 프로젝트: Arkham/rinku
int
rinku_autolink(
	struct buf *ob,
	const uint8_t *text,
	size_t size,
	autolink_mode mode,
	unsigned int flags,
	const char *link_attr,
	const char **skip_tags,
	void (*link_text_cb)(struct buf *ob, const struct buf *link, void *payload),
	void *payload)
{
	size_t i, end, last_link_found = 0;
	struct buf *link = bufnew(16);
	char active_chars[256];
	void (*link_url_cb)(struct buf *, const struct buf *, void *);
	int link_count = 0;

	if (!text || size == 0)
		return 0;

	memset(active_chars, 0x0, sizeof(active_chars));

	active_chars['<'] = AUTOLINK_ACTION_SKIP_TAG;

	if (mode & AUTOLINK_EMAILS)
		active_chars['@'] = AUTOLINK_ACTION_EMAIL;

	if (mode & AUTOLINK_URLS) {
		active_chars['w'] = AUTOLINK_ACTION_WWW;
		active_chars['W'] = AUTOLINK_ACTION_WWW;
		active_chars[':'] = AUTOLINK_ACTION_URL;
	}

	if (link_text_cb == NULL)
		link_text_cb = &autolink__print;

	if (link_attr != NULL) {
		while (isspace(*link_attr))
			link_attr++;
	}

	bufgrow(ob, size);

	i = end = 0;

	while (i < size) {
		size_t rewind, link_end;
		char action = 0;

		while (end < size && (action = active_chars[text[end]]) == 0)
			end++;

		if (end == size) {
			if (link_count > 0)
				bufput(ob, text + i, end - i);
			break;
		}

		if (action == AUTOLINK_ACTION_SKIP_TAG) {
			end += autolink__skip_tag(ob,
				text + end, size - end, skip_tags);

			continue;
		}

		link->size = 0;

		link_end = g_callbacks[(int)action](
			&rewind, link, (uint8_t *)text + end,
			end - last_link_found,
			size - end, flags);

		/* print the link */
		if (link_end > 0) {
			bufput(ob, text + i, end - i - rewind);

			bufputs(ob, g_hrefs[(int)action]);
			print_link(ob, link->data, link->size);

			if (link_attr) {
				BUFPUTSL(ob, "\" ");
				bufputs(ob, link_attr);
				bufputc(ob, '>');
			} else {
				BUFPUTSL(ob, "\">");
			}

			link_text_cb(ob, link, payload);
			BUFPUTSL(ob, "</a>");

			link_count++;
			i = end + link_end;
			last_link_found = end = i;
		} else {
			end = end + 1;
		}
	}

	bufrelease(link);
	return link_count;
}