Browse files

Merge branch 'discountlib' (ac689f3)

Conflicts:
	Makefile.in
	VERSION
	configure.inc
	lib/markdown.c
	lib/mkdio.h
	main.c
	markdown.1
	mkd2html.c
	pgm_options.c
	tests/backslash.t
	tests/code.t
	tests/style.t
	tests/tables.t
	theme.1
	theme.c
  • Loading branch information...
2 parents cca92fc + ac689f3 commit 439b9f67c9c389d689ab85d0151c81faf5fa9098 @cataphract committed Dec 17, 2012
Showing with 260 additions and 60 deletions.
  1. +1 −1 config.m4
  2. +1 −1 config.w32
  3. +1 −1 lib/VERSION
  4. +1 −0 lib/flags.c
  5. +29 −20 lib/generate.c
  6. +100 −0 lib/github_flavoured.c
  7. +26 −11 lib/markdown.c
  8. +25 −3 lib/markdown.h
  9. +16 −22 lib/mkdio.c
  10. +6 −0 lib/mkdio.h
  11. +1 −1 lib/version.c
  12. +1 −0 markdowndoc_class.c
  13. +52 −0 tests/compile_variation22.phpt
View
2 config.m4
@@ -9,7 +9,7 @@ discountlib_sources="lib/Csio.c lib/css.c lib/docheader.c \
lib/generate.c lib/html5.c lib/markdown.c \
lib/mkdio.c lib/resource.c lib/tags.c \
lib/toc.c lib/version.c lib/xml.c \
- lib/xmlpage.c lib/setup.c"
+ lib/xmlpage.c lib/setup.c lib/github_flavoured.c"
if test "$PHP_DISCOUNT" != "no"; then
AC_DEFINE(HAVE_DISCOUNT, 1, [Whether you have discount markdown support])
View
2 config.w32
@@ -4,7 +4,7 @@
ARG_ENABLE("discount", "Discount markdown support", "no");
if (PHP_DISCOUNT != "no") {
- EXTENSION("discount", "discount.c markdowndoc_class.c markdowndoc_meth_callbacks.c markdowndoc_meth_document.c markdowndoc_meth_header.c markdowndoc_meth_input.c markdowndoc_meth_misc.c markdowndoc_meth_parts.c ", PHP_DISCOUNT_SHARED, "/D_WSTDIO_DEFINED");
+ EXTENSION("discount", "discount.c markdowndoc_class.c markdowndoc_meth_callbacks.c markdowndoc_meth_document.c markdowndoc_meth_header.c markdowndoc_meth_input.c markdowndoc_meth_misc.c markdowndoc_meth_parts.c github_flavoured.c ", PHP_DISCOUNT_SHARED, "/D_WSTDIO_DEFINED");
ADD_SOURCES(configure_module_dirname + "/lib",
"Csio.c css.c docheader.c \
dumptree.c emmatch.c flags.c \
View
2 lib/VERSION
@@ -1 +1 @@
-2.1.2.1-dev
+2.1.6-dev
View
1 lib/flags.c
@@ -29,6 +29,7 @@ static struct flagnames flagnames[] = {
{ MKD_NOALPHALIST, "!ALPHALIST" },
{ MKD_NODLIST, "!DLIST" },
{ MKD_EXTRA_FOOTNOTE, "FOOTNOTE" },
+ { MKD_NOSTYLE, "!STYLE" },
};
#define NR(x) (sizeof x/sizeof x[0])
View
49 lib/generate.c
@@ -631,7 +631,8 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
{
linkytype *tag;
- if ( image || (ref == 0) )
+
+ if ( image )
tag = &imaget;
else if ( tag = pseudo(ref->link) ) {
if ( f->flags & (MKD_NO_EXT|MKD_SAFELINK) )
@@ -734,8 +735,6 @@ linkylinky(int image, MMIOT *f)
else
status = linkyformat(f, name, image, ref);
}
- else if ( f->flags & IS_LABEL )
- status = linkyformat(f, name, image, 0);
}
}
}
@@ -1088,7 +1087,7 @@ islike(MMIOT *f, char *s)
int len;
int i;
- if ( s[0] == '<' ) {
+ if ( s[0] == '|' ) {
if ( !isthisnonword(f, -1) )
return 0;
++s;
@@ -1097,7 +1096,7 @@ islike(MMIOT *f, char *s)
if ( !(len = strlen(s)) )
return 0;
- if ( s[len-1] == '>' ) {
+ if ( s[len-1] == '|' ) {
if ( !isthisnonword(f,len-1) )
return 0;
len--;
@@ -1116,25 +1115,25 @@ static struct smarties {
char *entity;
int shift;
} smarties[] = {
- { '\'', "'s>", "rsquo", 0 },
- { '\'', "'t>", "rsquo", 0 },
- { '\'', "'re>", "rsquo", 0 },
- { '\'', "'ll>", "rsquo", 0 },
- { '\'', "'ve>", "rsquo", 0 },
- { '\'', "'m>", "rsquo", 0 },
- { '\'', "'d>", "rsquo", 0 },
+ { '\'', "'s|", "rsquo", 0 },
+ { '\'', "'t|", "rsquo", 0 },
+ { '\'', "'re|", "rsquo", 0 },
+ { '\'', "'ll|", "rsquo", 0 },
+ { '\'', "'ve|", "rsquo", 0 },
+ { '\'', "'m|", "rsquo", 0 },
+ { '\'', "'d|", "rsquo", 0 },
{ '-', "---", "mdash", 2 },
{ '-', "--", "ndash", 1 },
{ '.', "...", "hellip", 2 },
{ '.', ". . .", "hellip", 4 },
{ '(', "(c)", "copy", 2 },
{ '(', "(r)", "reg", 2 },
{ '(', "(tm)", "trade", 3 },
- { '3', "<3/4>", "frac34", 2 },
- { '3', "<3/4ths>", "frac34", 2 },
- { '1', "<1/2>", "frac12", 2 },
- { '1', "<1/4>", "frac14", 2 },
- { '1', "<1/4th>", "frac14", 2 },
+ { '3', "|3/4|", "frac34", 2 },
+ { '3', "|3/4ths|", "frac34", 2 },
+ { '1', "|1/2|", "frac12", 2 },
+ { '1', "|1/4|", "frac14", 2 },
+ { '1', "|1/4th|", "frac14", 2 },
{ '&', "&#0;", 0, 3 },
} ;
#define NRSMART ( sizeof smarties / sizeof smarties[0] )
@@ -1338,7 +1337,16 @@ text(MMIOT *f)
case '\\': switch ( c = pull(f) ) {
case '&': Qstring("&amp;", f);
break;
- case '<': Qstring("&lt;", f);
+ case '<': c = peek(f,1);
+ if ( (c == EOF) || isspace(c) )
+ Qstring("&lt;", f);
+ else {
+ /* Markdown.pl does not escape <[nonwhite]
+ * sequences */
+ Qchar('\\', f);
+ shift(f, -1);
+ }
+
break;
case '^': if ( f->flags & (MKD_STRICT|MKD_NOSUPERSCRIPT) ) {
Qchar('\\', f);
@@ -1427,8 +1435,9 @@ printheader(Paragraph *pp, MMIOT *f)
enum e_alignments { a_NONE, a_CENTER, a_LEFT, a_RIGHT };
-static char* alignments[] = { "", " align=\"center\"", " align=\"left\"",
- " align=\"right\"" };
+static char* alignments[] = { "", " style=\"text-align:center;\"",
+ " style=\"text-align:left;\"",
+ " style=\"text-align:right;\"" };
typedef STRING(int) Istring;
View
100 lib/github_flavoured.c
@@ -0,0 +1,100 @@
+
+/*
+ * github_flavoured -- implement the obnoxious "returns are hard newlines"
+ * feature in github flavoured markdown.
+ *
+ * Copyright (C) 2012 David L Parsons.
+ * The redistribution terms are provided in the COPYRIGHT file that must
+ * be distributed with this source code.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "cstring.h"
+#include "markdown.h"
+#include "amalloc.h"
+
+/* build a Document from any old input.
+ */
+typedef int (*getc_func)(void*);
+
+Document *
+gfm_populate(getc_func getc, void* ctx, int flags)
+{
+ Cstring line;
+ Document *a = __mkd_new_Document();
+ int c;
+ int pandoc = 0;
+
+ if ( !a ) return 0;
+
+ a->tabstop = (flags & MKD_TABSTOP) ? 4 : TABSTOP;
+
+ CREATE(line);
+
+ while ( (c = (*getc)(ctx)) != EOF ) {
+ if ( c == '\n' ) {
+ if ( pandoc != EOF && pandoc < 3 ) {
+ if ( S(line) && (T(line)[0] == '%') )
+ pandoc++;
+ else
+ pandoc = EOF;
+ }
+
+ if (pandoc == EOF) {
+ EXPAND(line) = ' ';
+ EXPAND(line) = ' ';
+ }
+ __mkd_enqueue(a, &line);
+ S(line) = 0;
+ }
+ else if ( isprint(c) || isspace(c) || (c & 0x80) )
+ EXPAND(line) = c;
+ }
+
+ if ( S(line) )
+ __mkd_enqueue(a, &line);
+
+ DELETE(line);
+
+ if ( (pandoc == 3) && !(flags & (MKD_NOHEADER|MKD_STRICT)) ) {
+ /* the first three lines started with %, so we have a header.
+ * clip the first three lines out of content and hang them
+ * off header.
+ */
+ Line *headers = T(a->content);
+
+ a->title = headers; __mkd_header_dle(a->title);
+ a->author= headers->next; __mkd_header_dle(a->author);
+ a->date = headers->next->next; __mkd_header_dle(a->date);
+
+ T(a->content) = headers->next->next->next;
+ }
+
+ return a;
+}
+
+
+/* convert a block of text into a linked list
+ */
+Document *
+gfm_string(const char *buf, int len, DWORD flags)
+{
+ struct string_stream about;
+
+ about.data = buf;
+ about.size = len;
+
+ return gfm_populate((getc_func)__mkd_io_strget, &about, flags & INPUT_MASK);
+}
+
+
+/* convert a file into a linked list
+ */
+Document *
+gfm_in(FILE *f, DWORD flags)
+{
+ return gfm_populate((getc_func)fgetc, f, flags & INPUT_MASK);
+}
View
37 lib/markdown.c
@@ -189,7 +189,8 @@ checkline(Line *l)
int eol, i;
int dashes = 0, spaces = 0,
equals = 0, underscores = 0,
- stars = 0, tildes = 0;
+ stars = 0, tildes = 0,
+ backticks = 0;
l->flags |= CHECKED;
l->kind = chk_text;
@@ -211,12 +212,15 @@ checkline(Line *l)
case '=': equals = 1; break;
case '_': underscores = 1; break;
case '*': stars = 1; break;
+#if WITH_FENCED_CODE
case '~': tildes = 1; break;
+ case '`': backticks = 1; break;
+#endif
default: return;
}
}
- if ( dashes + equals + underscores + stars + tildes > 1 )
+ if ( dashes + equals + underscores + stars + tildes + backticks > 1 )
return;
if ( spaces ) {
@@ -227,8 +231,11 @@ checkline(Line *l)
if ( stars || underscores ) { l->kind = chk_hr; }
else if ( dashes ) { l->kind = chk_dash; }
- else if ( tildes ) { l->kind = chk_tilde; }
else if ( equals ) { l->kind = chk_equal; }
+#if WITH_FENCED_CODE
+ else if ( tildes ) { l->kind = chk_tilde; }
+ else if ( backticks ) { l->kind = chk_backtick; }
+#endif
}
@@ -450,8 +457,7 @@ is_extra_dt(Line *t, int *clip)
{
#if USE_EXTRA_DL
- if ( t && t->next && T(t->text)[0] != '='
- && S(t->text) != 0
+ if ( t && t->next && S(t->text) && T(t->text)[0] != '='
&& T(t->text)[S(t->text)-1] != '=') {
Line *x;
@@ -601,12 +607,15 @@ codeblock(Paragraph *p)
#ifdef WITH_FENCED_CODE
static int
-iscodefence(Line *r, int size)
+iscodefence(Line *r, int size, line_type kind)
{
if ( !(r->flags & CHECKED) )
checkline(r);
- return (r->kind == chk_tilde) && (r->count >= size);
+ if ( kind )
+ return (r->kind == kind) && (r->count >= size);
+ else
+ return (r->kind == chk_tilde || r->kind == chk_backtick) && (r->count >= size);
}
static Paragraph *
@@ -619,14 +628,14 @@ fencedcodeblock(ParagraphRoot *d, Line **ptr)
/* don't allow zero-length code fences
*/
- if ( (first->next == 0) || iscodefence(first->next, first->count) )
+ if ( (first->next == 0) || iscodefence(first->next, first->count, 0) )
return 0;
/* find the closing fence, discard the fences,
* return a Paragraph with the contents
*/
for ( r = first; r && r->next; r = r->next )
- if ( iscodefence(r->next, first->count) ) {
+ if ( iscodefence(r->next, first->count, first->kind) ) {
(*ptr) = r->next->next;
ret = Pp(d, first->next, CODE);
___mkd_freeLine(first);
@@ -1087,6 +1096,7 @@ compile_document(Line *ptr, MMIOT *f)
while ( ptr ) {
if ( !(f->flags & MKD_NOHTML) && (tag = isopentag(ptr)) ) {
+ int blocktype;
/* If we encounter a html/style block, compile and save all
* of the cached source BEFORE processing the html/style.
*/
@@ -1096,7 +1106,12 @@ compile_document(Line *ptr, MMIOT *f)
p->down = compile(T(source), 1, f);
T(source) = E(source) = 0;
}
- p = Pp(&d, ptr, strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML);
+
+ if ( f->flags & MKD_NOSTYLE )
+ blocktype = HTML;
+ else
+ blocktype = strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML;
+ p = Pp(&d, ptr, blocktype);
ptr = htmlblock(p, tag, &unclosed);
if ( unclosed ) {
p->typ = SOURCE;
@@ -1214,7 +1229,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
ptr = codeblock(p);
}
#if WITH_FENCED_CODE
- else if ( iscodefence(ptr,3) && (p=fencedcodeblock(&d, &ptr)) )
+ else if ( iscodefence(ptr,3,0) && (p=fencedcodeblock(&d, &ptr)) )
/* yay, it's already done */ ;
#endif
else if ( ishr(ptr) ) {
View
28 lib/markdown.h
@@ -24,6 +24,10 @@ typedef struct footnote {
* that all tabs will be expanded to spaces!], and a pointer to
* the next line.
*/
+typedef enum { chk_text, chk_code,
+ chk_hr, chk_dash,
+ chk_tilde, chk_backtick,
+ chk_equal } line_type;
typedef struct line {
Cstring text;
struct line *next;
@@ -32,9 +36,7 @@ typedef struct line {
#define PIPECHAR 0x01 /* line contains a | */
#define CHECKED 0x02
- enum { chk_text, chk_code,
- chk_hr, chk_dash,
- chk_tilde, chk_equal } kind;
+ line_type kind;
int count;
} Line;
@@ -121,6 +123,7 @@ typedef struct mmiot {
#define MKD_NOALPHALIST 0x00080000
#define MKD_NODLIST 0x00100000
#define MKD_EXTRA_FOOTNOTE 0x00200000
+#define MKD_NOSTYLE 0x00400000
#define IS_LABEL 0x08000000
#define USER_FLAGS 0x0FFFFFFF
#define INPUT_MASK (MKD_NOHEADER|MKD_TABSTOP)
@@ -153,6 +156,16 @@ typedef struct document {
} Document;
+/*
+ * economy FILE-type structure for pulling characters out of a
+ * fixed-length string.
+ */
+struct string_stream {
+ const char *data; /* the unread data */
+ int size; /* and how much is there? */
+} ;
+
+
extern int mkd_firstnonblank(Line *);
extern int mkd_compile(Document *, DWORD);
extern int mkd_document(Document *, char **);
@@ -174,6 +187,9 @@ extern void mkd_string_to_anchor(char*,int, mkd_sta_function_t, void*, int);
extern Document *mkd_in(FILE *, DWORD);
extern Document *mkd_string(const char*,int, DWORD);
+extern Document *gfm_in(FILE *, DWORD);
+extern Document *gfm_string(const char*,int, DWORD);
+
extern void mkd_initialize();
extern void mkd_shlib_destructor();
@@ -194,4 +210,10 @@ extern void ___mkd_reparse(char *, int, int, MMIOT*, char*);
extern void ___mkd_emblock(MMIOT*);
extern void ___mkd_tidy(Cstring *);
+extern Document *__mkd_new_Document();
+extern void __mkd_enqueue(Document*, Cstring *);
+extern void __mkd_header_dle(Line *);
+
+extern int __mkd_io_strget(struct string_stream *);
+
#endif/*_MARKDOWN_D*/
View
38 lib/mkdio.c
@@ -20,8 +20,8 @@ typedef ANCHOR(Line) LineAnchor;
/* create a new blank Document
*/
-static Document*
-new_Document()
+Document*
+__mkd_new_Document()
{
Document *ret = ecalloc(sizeof(Document), 1);
@@ -39,8 +39,8 @@ new_Document()
/* add a line to the markdown input chain, expanding tabs and
* noting the presence of special characters as we go.
*/
-static void
-queue(Document* a, Cstring *line)
+void
+__mkd_enqueue(Document* a, Cstring *line)
{
Line *p = ecalloc(sizeof *p, 1);
unsigned char c;
@@ -77,8 +77,8 @@ queue(Document* a, Cstring *line)
/* trim leading blanks from a header line
*/
-static void
-header_dle(Line *p)
+void
+__mkd_header_dle(Line *p)
{
CLIP(p->text, 0, 1);
p->dle = mkd_firstnonblank(p);
@@ -93,7 +93,7 @@ Document *
populate(getc_func getc, void* ctx, int flags)
{
Cstring line;
- Document *a = new_Document();
+ Document *a = __mkd_new_Document();
int c;
int pandoc = 0;
@@ -111,15 +111,15 @@ populate(getc_func getc, void* ctx, int flags)
else
pandoc = EOF;
}
- queue(a, &line);
+ __mkd_enqueue(a, &line);
S(line) = 0;
}
else if ( isprint(c) || isspace(c) || (c & 0x80) )
EXPAND(line) = c;
}
if ( S(line) )
- queue(a, &line);
+ __mkd_enqueue(a, &line);
DELETE(line);
@@ -130,9 +130,9 @@ populate(getc_func getc, void* ctx, int flags)
*/
Line *headers = T(a->content);
- a->title = headers; header_dle(a->title);
- a->author= headers->next; header_dle(a->author);
- a->date = headers->next->next; header_dle(a->date);
+ a->title = headers; __mkd_header_dle(a->title);
+ a->author= headers->next; __mkd_header_dle(a->author);
+ a->date = headers->next->next; __mkd_header_dle(a->date);
T(a->content) = headers->next->next->next;
}
@@ -152,14 +152,8 @@ mkd_in(FILE *f, DWORD flags)
/* return a single character out of a buffer
*/
-struct string_ctx {
- const char *data; /* the unread data */
- int size; /* and how much is there? */
-} ;
-
-
-static int
-strget(struct string_ctx *in)
+int
+__mkd_io_strget(struct string_stream *in)
{
if ( !in->size ) return EOF;
@@ -174,12 +168,12 @@ strget(struct string_ctx *in)
Document *
mkd_string(const char *buf, int len, DWORD flags)
{
- struct string_ctx about;
+ struct string_stream about;
about.data = buf;
about.size = len;
- return populate((getc_func)strget, &about, flags & INPUT_MASK);
+ return populate((getc_func)__mkd_io_strget, &about, flags & INPUT_MASK);
}
View
6 lib/mkdio.h
@@ -17,6 +17,11 @@ MMIOT *mkd_string(const char*,int,mkd_flag_t); /* assemble input from a buffer *
/*void mkd_basename(MMIOT*,char*);*/
+/* line builder for github flavoured markdown
+ */
+MMIOT *gfm_in(FILE*,mkd_flag_t); /* assemble input from a file */
+MMIOT *gfm_string(const char*,int,mkd_flag_t); /* assemble input from a buffer */
+
void mkd_tags_on_startup(INIT_FUNC_ARGS);
void mkd_tags_on_shutdown(SHUTDOWN_FUNC_ARGS);
@@ -108,6 +113,7 @@ void mkd_ref_prefix(MMIOT*, char*);
#define MKD_NOALPHALIST 0x00080000 /* forbid alphabetic lists */
#define MKD_NODLIST 0x00100000 /* forbid definition lists */
#define MKD_EXTRA_FOOTNOTE 0x00200000 /* enable markdown extra-style footnotes */
+#define MKD_NOSTYLE 0x00400000 /* don't extract <style> blocks */
#define MKD_EMBED MKD_NOLINKS|MKD_NOIMAGE|MKD_TAGTEXT
/* special flags for mkd_in() and mkd_string()
View
2 lib/version.c
@@ -3,7 +3,7 @@
/* on merge: check against version.c.in */
/* on merge: obtain version from VERSION */
-const char markdown_version[] = "2.1.3.1-dev"
+const char markdown_version[] = "2.1.6-dev"
#if TABSTOP != 4
" TAB=" #TABSTOP
#endif
View
1 markdowndoc_class.c
@@ -405,6 +405,7 @@ void markdowndoc_module_start(INIT_FUNC_ARGS)
DISCOUNT_CONST(NODLIST);
DISCOUNT_CONST(EMBED);
DISCOUNT_CONST(EXTRA_FOOTNOTE);
+ DISCOUNT_CONST(NOSTYLE);
#undef DISCOUNT_CONST
}
View
52 tests/compile_variation22.phpt
@@ -0,0 +1,52 @@
+--TEST--
+MarkdownDocument::compile: test NOSTYLE flag
+--SKIPIF--
+<?php
+if (!extension_loaded('discount'))
+ die('SKIP discount extension not loaded');
+--FILE--
+<?php
+$t = <<<EOD
+Style below.
+
+<style>
+p { color: red; }
+</style>
+EOD;
+
+$md = MarkdownDocument::createFromString($t);
+$md->compile();
+echo $md->getCss(), "\n\n";
+echo $md->getHtml(), "\n\n";
+
+echo "=====================\n";
+
+$md = MarkdownDocument::createFromString($t);
+$md->compile(MarkdownDocument::NOSTYLE);
+echo $md->getCss(), "\n\n";
+echo $md->getHtml(), "\n\n";
+
+echo "\nDone.\n";
+--EXPECT--
+<style>
+p { color: red; }
+</style>
+
+
+<p>Style below.</p>
+
+
+
+=====================
+
+
+<p>Style below.</p>
+
+<style>
+p { color: red; }
+</style>
+
+
+
+Done.
+

0 comments on commit 439b9f6

Please sign in to comment.